@evomap/evolver 1.91.0 → 1.91.2

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 (72) hide show
  1. package/index.js +1 -1
  2. package/package.json +1 -1
  3. package/src/atp/hubClient.js +13 -1
  4. package/src/evolve/guards.js +1 -1
  5. package/src/evolve/pipeline/collect.js +1 -1
  6. package/src/evolve/pipeline/dispatch.js +1 -1
  7. package/src/evolve/pipeline/enrich.js +1 -1
  8. package/src/evolve/pipeline/hub.js +1 -1
  9. package/src/evolve/pipeline/select.js +1 -1
  10. package/src/evolve/pipeline/signals.js +1 -1
  11. package/src/evolve/utils.js +1 -1
  12. package/src/evolve.js +1 -1
  13. package/src/gep/a2aProtocol.js +5175 -1
  14. package/src/gep/antiAbuseTelemetry.js +233 -1
  15. package/src/gep/assetStore.js +3 -2
  16. package/src/gep/autoDistillConv.js +205 -1
  17. package/src/gep/autoDistillLlm.js +315 -1
  18. package/src/gep/candidateEval.js +92 -1
  19. package/src/gep/candidates.js +1 -1
  20. package/src/gep/contentHash.js +30 -1
  21. package/src/gep/conversationDistiller.js +270 -1
  22. package/src/gep/conversationSniffer.js +266 -1
  23. package/src/gep/crypto.js +93 -1
  24. package/src/gep/curriculum.js +1 -1
  25. package/src/gep/deviceId.js +218 -1
  26. package/src/gep/envFingerprint.js +118 -1
  27. package/src/gep/epigenetics.js +31 -1
  28. package/src/gep/execBridge.js +712 -1
  29. package/src/gep/explore.js +289 -1
  30. package/src/gep/hash.js +15 -1
  31. package/src/gep/hubFetch.js +672 -1
  32. package/src/gep/hubReview.js +212 -1
  33. package/src/gep/hubSearch.js +544 -1
  34. package/src/gep/hubVerify.js +306 -1
  35. package/src/gep/learningSignals.js +1 -1
  36. package/src/gep/memoryGraph.js +1449 -1
  37. package/src/gep/memoryGraphAdapter.js +203 -1
  38. package/src/gep/mutation.js +1 -1
  39. package/src/gep/narrativeMemory.js +1 -1
  40. package/src/gep/openPRRegistry.js +205 -1
  41. package/src/gep/personality.js +1 -1
  42. package/src/gep/policyCheck.js +599 -1
  43. package/src/gep/prompt.js +1 -1
  44. package/src/gep/recallInject.js +409 -1
  45. package/src/gep/recallVerifier.js +318 -1
  46. package/src/gep/reflection.js +1 -1
  47. package/src/gep/savingsCore.js +1 -1
  48. package/src/gep/selector.js +1 -1
  49. package/src/gep/skillDistiller.js +1294 -1
  50. package/src/gep/solidify.js +1 -1
  51. package/src/gep/strategy.js +136 -1
  52. package/src/gep/tokenSavings.js +1 -1
  53. package/src/gep/trajectoryExport.js +3841 -1
  54. package/src/gep/workspaceKeychain.js +174 -1
  55. package/src/proxy/extensions/sessionHandler.js +123 -53
  56. package/src/proxy/extensions/traceControl.js +123 -1
  57. package/src/proxy/index.js +57 -2
  58. package/src/proxy/inject.js +52 -1
  59. package/src/proxy/router/messages_route.js +6 -0
  60. package/src/proxy/server/routes.js +40 -62
  61. package/src/proxy/trace/extractor.js +2355 -1
  62. package/src/proxy/trace/usage.js +105 -1
  63. package/src/webui/client/clientJs/bootstrap.js +6 -0
  64. package/src/webui/client/clientJs/github.js +225 -0
  65. package/src/webui/client/clientJs/i18n.js +14 -0
  66. package/src/webui/client/clientJs/index.js +3 -0
  67. package/src/webui/client/clientJs/pipelines.js +3 -1
  68. package/src/webui/client/indexHtml.js +10 -0
  69. package/src/webui/client/stylesCss.js +61 -0
  70. package/src/webui/observer/github.js +340 -0
  71. package/src/webui/observer/index.js +4 -0
  72. package/src/webui/server/routes.js +11 -0
@@ -1 +1,174 @@
1
- const _0x1f0dbb=_0x2fcd;(function(_0x2ea48b,_0x297346){const _0x4f7603=_0x2fcd,_0x98cf88=_0x2ea48b();while(!![]){try{const _0x1bcb5d=parseInt(_0x4f7603(0x226,'\x44\x69\x34\x31'))/(0x288*-0xc+-0x229f+0x4100)*(parseInt(_0x4f7603(0x1c2,'\x4e\x59\x29\x78'))/(0xde8+0x121*-0x13+0x78d))+parseInt(_0x4f7603(0x1e9,'\x4c\x5e\x54\x5d'))/(-0x1c1+0x22f7+-0x2133)*(parseInt(_0x4f7603(0x216,'\x76\x28\x4d\x33'))/(-0x16*0xa6+-0x2188+0x2fd0))+parseInt(_0x4f7603(0x214,'\x5b\x50\x49\x2a'))/(-0x967*-0x1+0xf9*-0xb+0x151)+-parseInt(_0x4f7603(0x1f2,'\x76\x4b\x37\x56'))/(-0x261f+-0x1*0x11b+0x2740)+parseInt(_0x4f7603(0x20c,'\x78\x50\x59\x70'))/(-0x289*0xe+0x1*-0x2675+0x49fa)+parseInt(_0x4f7603(0x21c,'\x21\x78\x61\x72'))/(0x3c7+-0x647*0x4+0x155d)*(-parseInt(_0x4f7603(0x1b6,'\x57\x47\x4c\x61'))/(-0x17ae*-0x1+0x90c+-0x1*0x20b1))+parseInt(_0x4f7603(0x220,'\x65\x7a\x6e\x23'))/(-0x1*0x18d3+0x1911+-0x34)*(-parseInt(_0x4f7603(0x1f1,'\x44\x37\x76\x50'))/(-0x442*0x6+0x6bb+0x11c*0x11));if(_0x1bcb5d===_0x297346)break;else _0x98cf88['push'](_0x98cf88['shift']());}catch(_0x3eb120){_0x98cf88['push'](_0x98cf88['shift']());}}}(_0x1de9,-0xb338f+0x2ba*-0x513+0x1e7af*0x11));const _0x1fcafc=(function(){let _0x213e77=!![];return function(_0x278a4b,_0x4d2894){const _0x44edb2=_0x213e77?function(){const _0x3f77ab=_0x2fcd;if(_0x4d2894){const _0x430757=_0x4d2894[_0x3f77ab(0x1e7,'\x4e\x6a\x77\x66')](_0x278a4b,arguments);return _0x4d2894=null,_0x430757;}}:function(){};return _0x213e77=![],_0x44edb2;};}()),_0x28e666=_0x1fcafc(this,function(){const _0x2ea0ee=_0x2fcd,_0x2df733={};_0x2df733['\x78\x48\x62\x79\x42']=_0x2ea0ee(0x20a,'\x37\x36\x75\x21')+_0x2ea0ee(0x1c9,'\x5b\x47\x4c\x6f');const _0x3dd5d3=_0x2df733;return _0x28e666[_0x2ea0ee(0x224,'\x21\x50\x6f\x21')]()[_0x2ea0ee(0x1e1,'\x61\x31\x6e\x75')](_0x3dd5d3['\x78\x48\x62\x79\x42'])[_0x2ea0ee(0x1e3,'\x24\x42\x5e\x21')]()[_0x2ea0ee(0x1b7,'\x47\x6f\x5d\x41')+_0x2ea0ee(0x1ce,'\x4e\x6a\x77\x66')](_0x28e666)[_0x2ea0ee(0x1e1,'\x61\x31\x6e\x75')](_0x3dd5d3[_0x2ea0ee(0x202,'\x6b\x56\x50\x5d')]);});function _0x1de9(){const _0x3f1ab1=['\x76\x4c\x5a\x64\x4a\x73\x7a\x31\x79\x58\x39\x75\x57\x35\x30\x6f\x64\x43\x6b\x35\x57\x34\x75','\x41\x64\x44\x6e\x73\x33\x54\x49\x57\x52\x65','\x57\x50\x38\x65\x57\x50\x37\x63\x4c\x68\x43','\x57\x52\x76\x64\x57\x4f\x4e\x63\x4b\x43\x6b\x57','\x57\x50\x76\x64\x57\x36\x58\x37\x57\x50\x52\x64\x4f\x38\x6f\x53\x57\x50\x47\x44\x57\x50\x4a\x64\x55\x38\x6b\x6e\x57\x36\x30','\x57\x36\x46\x64\x56\x53\x6f\x54\x57\x4f\x33\x63\x50\x47','\x6e\x6d\x6b\x56\x57\x52\x78\x64\x49\x66\x4f\x70\x57\x52\x6d\x78','\x57\x37\x37\x63\x51\x43\x6b\x35\x57\x36\x6e\x53\x57\x51\x39\x79\x67\x61','\x43\x43\x6f\x30\x57\x35\x46\x63\x4a\x62\x4c\x78\x57\x36\x30\x39\x57\x36\x54\x38\x57\x52\x66\x75\x78\x71','\x46\x43\x6b\x37\x57\x34\x52\x64\x52\x78\x44\x49\x57\x36\x46\x63\x47\x49\x43\x43\x77\x75\x75\x6b','\x57\x52\x4e\x64\x4c\x4c\x69\x75\x57\x50\x70\x63\x49\x38\x6f\x53\x57\x4f\x30','\x57\x4f\x78\x63\x4b\x59\x4f\x30\x57\x37\x6d\x4e\x57\x50\x4f\x6a','\x57\x52\x54\x36\x57\x34\x47\x66\x61\x47','\x41\x71\x58\x6f\x70\x6d\x6f\x79','\x73\x71\x64\x63\x4e\x71','\x57\x51\x6e\x65\x57\x4f\x64\x63\x4f\x43\x6b\x74','\x6f\x76\x4a\x64\x51\x53\x6b\x5a\x57\x35\x37\x64\x51\x38\x6f\x2f','\x44\x77\x33\x64\x54\x43\x6b\x66\x57\x36\x52\x64\x48\x38\x6f\x45\x57\x50\x6d','\x57\x50\x68\x63\x49\x53\x6b\x50\x57\x4f\x68\x63\x4c\x61','\x57\x34\x52\x64\x4d\x6d\x6f\x52\x57\x52\x68\x63\x51\x43\x6b\x36\x57\x50\x62\x4b','\x57\x52\x37\x63\x47\x53\x6b\x36\x57\x50\x46\x63\x53\x43\x6f\x5a\x57\x50\x44\x37\x57\x37\x43','\x44\x38\x6f\x58\x57\x35\x68\x63\x49\x62\x30\x6a\x57\x52\x65\x43\x57\x34\x44\x39\x57\x52\x61','\x41\x47\x68\x64\x51\x61','\x57\x52\x35\x45\x57\x51\x78\x63\x56\x53\x6b\x48','\x57\x51\x47\x70\x57\x35\x75\x45\x61\x6d\x6b\x68\x64\x63\x79','\x57\x35\x74\x63\x55\x53\x6b\x48\x57\x36\x4c\x4f\x57\x51\x39\x74\x67\x47','\x42\x68\x53\x5a\x57\x37\x37\x64\x4f\x6d\x6b\x2f\x76\x43\x6f\x6c\x79\x43\x6f\x44\x57\x35\x4b','\x57\x52\x6c\x63\x4b\x53\x6f\x2b\x7a\x4a\x6a\x46\x68\x33\x53','\x57\x37\x4e\x64\x4b\x38\x6f\x52\x57\x52\x70\x63\x4f\x38\x6f\x2f','\x69\x43\x6b\x31\x57\x50\x6c\x64\x4b\x57','\x6c\x76\x34\x52\x69\x43\x6f\x48\x7a\x53\x6f\x65\x57\x50\x56\x64\x4a\x47','\x57\x50\x46\x63\x49\x49\x79\x34','\x57\x34\x2f\x64\x4d\x6d\x6f\x2b\x57\x52\x70\x63\x55\x71','\x57\x52\x6a\x66\x57\x52\x68\x63\x4f\x6d\x6b\x38\x57\x51\x68\x63\x52\x53\x6b\x78','\x77\x43\x6f\x7a\x79\x66\x5a\x63\x55\x57','\x57\x52\x56\x64\x56\x75\x37\x63\x51\x4e\x79','\x6e\x78\x38\x71\x57\x36\x74\x63\x54\x57','\x7a\x6d\x6f\x45\x69\x43\x6f\x34\x57\x35\x6a\x55\x71\x4b\x4b\x51\x43\x6d\x6f\x4d\x44\x38\x6b\x41','\x63\x6d\x6f\x70\x64\x38\x6f\x41\x57\x52\x6e\x32\x57\x35\x39\x51','\x57\x36\x33\x63\x4c\x48\x46\x63\x50\x4e\x42\x63\x52\x53\x6f\x4a\x46\x47','\x57\x50\x34\x6e\x57\x34\x6d\x4e\x62\x47','\x57\x37\x54\x46\x57\x36\x50\x46','\x6d\x6d\x6b\x76\x57\x4f\x70\x64\x4c\x43\x6b\x76','\x57\x35\x69\x4e\x57\x51\x76\x6c','\x57\x52\x61\x43\x57\x50\x70\x63\x4e\x78\x71','\x57\x50\x5a\x63\x52\x53\x6f\x65\x74\x72\x54\x33\x6f\x61','\x73\x6d\x6b\x71\x6d\x47','\x7a\x57\x46\x64\x47\x77\x53\x36','\x63\x61\x42\x63\x4d\x68\x6d\x64\x70\x30\x39\x6a','\x66\x43\x6f\x4b\x57\x50\x79\x37\x57\x4f\x69\x63\x46\x43\x6f\x7a','\x75\x38\x6b\x35\x57\x50\x79\x52','\x66\x63\x44\x62\x57\x52\x37\x63\x56\x47','\x44\x53\x6f\x54\x75\x31\x5a\x63\x50\x71','\x67\x6d\x6b\x57\x57\x50\x75','\x57\x37\x4f\x79\x57\x35\x47','\x57\x50\x42\x63\x53\x43\x6f\x62','\x57\x51\x48\x34\x57\x4f\x50\x72','\x57\x35\x38\x47\x6f\x76\x6c\x64\x51\x57','\x57\x37\x74\x63\x4b\x53\x6b\x6d\x57\x35\x54\x4f','\x57\x4f\x30\x70\x57\x52\x4a\x63\x55\x65\x4a\x63\x48\x61\x4a\x63\x55\x61','\x57\x35\x48\x44\x57\x51\x79\x67\x70\x6d\x6b\x66\x57\x51\x78\x63\x4c\x71','\x57\x37\x50\x69\x64\x47','\x45\x53\x6f\x32\x57\x52\x37\x63\x47\x38\x6b\x6d','\x6c\x6d\x6f\x47\x57\x50\x74\x63\x52\x64\x79\x4e\x57\x51\x78\x63\x4b\x47','\x70\x43\x6b\x64\x57\x4f\x42\x64\x4d\x38\x6b\x41','\x7a\x38\x6b\x33\x6a\x53\x6b\x78\x6b\x61','\x57\x4f\x72\x51\x79\x30\x53\x68\x7a\x53\x6b\x51\x57\x34\x47','\x57\x50\x54\x36\x57\x34\x6d\x4d\x6c\x71','\x79\x61\x35\x74\x70\x38\x6f\x30','\x69\x53\x6f\x62\x65\x73\x54\x69\x65\x76\x79\x54','\x57\x51\x42\x64\x4b\x4a\x76\x69\x57\x34\x61','\x44\x57\x6e\x4b\x78\x75\x53','\x45\x6d\x6b\x41\x57\x51\x52\x64\x56\x4d\x34\x4a\x57\x50\x69','\x73\x57\x6c\x63\x4e\x67\x34\x57\x6d\x4b\x76\x62','\x66\x66\x57\x45\x57\x35\x46\x63\x55\x4c\x78\x63\x4f\x61\x71','\x57\x36\x6d\x56\x57\x52\x57\x72\x57\x34\x75','\x6f\x64\x58\x54\x57\x51\x74\x63\x53\x6d\x6b\x64\x6e\x6d\x6f\x33','\x57\x52\x54\x67\x57\x50\x70\x63\x50\x38\x6b\x36','\x57\x52\x57\x69\x57\x52\x6c\x63\x50\x75\x34','\x70\x43\x6f\x51\x57\x50\x56\x63\x55\x57\x71\x4e\x57\x52\x2f\x63\x4e\x61','\x57\x35\x31\x78\x57\x51\x53\x63\x6f\x53\x6b\x46','\x57\x50\x39\x38\x57\x36\x65\x46\x6d\x61','\x69\x53\x6b\x76\x57\x51\x6c\x64\x47\x53\x6b\x63\x6c\x38\x6f\x42\x7a\x57','\x62\x31\x79\x4d\x57\x36\x4a\x63\x52\x65\x70\x63\x4f\x74\x61','\x65\x43\x6f\x53\x57\x4f\x4b\x4d\x57\x4f\x4b\x6e\x46\x6d\x6f\x56','\x57\x52\x5a\x63\x55\x43\x6f\x74\x76\x57\x6d','\x57\x36\x39\x78\x64\x68\x42\x63\x4b\x57','\x57\x50\x58\x32\x57\x37\x34\x61\x6b\x72\x6c\x63\x4a\x57','\x45\x72\x46\x63\x4f\x53\x6b\x6e\x57\x37\x70\x64\x47\x75\x37\x63\x4c\x53\x6f\x71\x68\x47\x30','\x46\x62\x70\x63\x4f\x43\x6b\x69\x57\x37\x68\x63\x4c\x48\x42\x63\x49\x6d\x6f\x30\x6e\x72\x5a\x63\x48\x6d\x6b\x45','\x57\x50\x78\x64\x47\x4b\x61\x31\x57\x4f\x79','\x6c\x53\x6f\x35\x57\x50\x56\x63\x54\x49\x34\x30\x57\x52\x6c\x63\x4e\x71','\x57\x36\x52\x63\x4d\x38\x6b\x37\x57\x36\x66\x50','\x57\x4f\x56\x63\x47\x53\x6b\x7a\x57\x52\x74\x63\x48\x61','\x6d\x53\x6b\x53\x57\x4f\x76\x4c\x61\x57','\x57\x50\x42\x63\x4e\x61\x34\x56\x57\x36\x30\x50\x57\x4f\x4f','\x57\x51\x42\x64\x51\x38\x6f\x50\x57\x52\x4b\x34\x57\x4f\x72\x53\x68\x59\x50\x6a\x6b\x61','\x6b\x31\x53\x52\x74\x38\x6b\x4e\x6e\x6d\x6f\x5a\x57\x50\x42\x64\x4c\x30\x6a\x75\x57\x36\x43','\x57\x35\x7a\x4c\x57\x36\x53\x77\x6b\x71\x2f\x63\x4b\x53\x6f\x58','\x57\x37\x57\x6f\x57\x34\x4b\x36\x61\x43\x6b\x74\x57\x51\x71','\x68\x43\x6f\x6d\x57\x52\x74\x64\x4e\x71','\x57\x50\x7a\x63\x57\x4f\x64\x63\x56\x6d\x6b\x6e','\x64\x43\x6f\x76\x64\x38\x6f\x6b\x57\x52\x6e\x54\x57\x34\x76\x4e','\x62\x53\x6f\x6d\x57\x52\x42\x64\x47\x38\x6b\x65\x44\x78\x66\x36','\x68\x6d\x6f\x4b\x6e\x72\x62\x59\x6f\x78\x43\x65','\x6e\x33\x4e\x64\x49\x58\x4e\x64\x50\x57','\x57\x4f\x62\x51\x57\x34\x79\x4e\x70\x57','\x57\x51\x65\x35\x57\x52\x30\x61\x57\x51\x69','\x42\x72\x48\x59\x67\x47','\x57\x36\x57\x4a\x57\x34\x75','\x57\x52\x70\x63\x4f\x43\x6b\x59\x57\x50\x33\x63\x4e\x61','\x57\x51\x56\x64\x4e\x61\x33\x63\x52\x57','\x57\x34\x5a\x64\x53\x6d\x6f\x57\x57\x51\x6c\x63\x52\x61','\x65\x43\x6f\x32\x57\x52\x2f\x64\x49\x43\x6b\x32','\x71\x57\x37\x63\x47\x75\x6c\x63\x56\x6d\x6f\x58\x6c\x53\x6f\x50\x67\x6d\x6b\x2f\x57\x50\x56\x63\x52\x47','\x57\x34\x56\x64\x47\x53\x6f\x56\x57\x35\x56\x64\x4a\x38\x6f\x6a\x57\x37\x70\x64\x48\x43\x6f\x71\x73\x6d\x6f\x44','\x68\x6d\x6f\x45\x61\x57\x58\x6c\x6e\x76\x4f\x31','\x6e\x43\x6f\x4c\x57\x50\x64\x63\x4e\x61\x57','\x62\x43\x6f\x6c\x43\x43\x6f\x52\x57\x34\x64\x63\x49\x67\x58\x67\x72\x38\x6b\x30\x57\x35\x69','\x57\x4f\x64\x63\x50\x6d\x6f\x49\x79\x71\x30','\x57\x51\x33\x64\x56\x5a\x37\x63\x50\x33\x71','\x57\x35\x38\x4e\x70\x5a\x76\x6e\x70\x6d\x6f\x59\x57\x50\x79','\x57\x51\x6c\x63\x4e\x53\x6b\x49\x57\x36\x2f\x64\x51\x38\x6b\x2b\x57\x34\x4b\x2b'];_0x1de9=function(){return _0x3f1ab1;};return _0x1de9();}_0x28e666();const _0x35ac6a=_0x1f0dbb(0x1dd,'\x44\x69\x34\x31')+_0x1f0dbb(0x1cd,'\x61\x31\x6e\x75')+_0x1f0dbb(0x1f8,'\x6b\x56\x50\x5d')+_0x1f0dbb(0x21a,'\x78\x50\x59\x70'),_0x1e18d5=/^[a-f0-9]{32,}$/i;let _0x42efc2=undefined;function _0x2527ea(){const _0x391a46=_0x1f0dbb,_0x59a96d={'\x65\x79\x4f\x58\x5a':function(_0x10ebc0,_0x492ffc){return _0x10ebc0!==_0x492ffc;},'\x62\x74\x4d\x49\x76':function(_0x3c4fe9,_0x4cd4b6){return _0x3c4fe9(_0x4cd4b6);},'\x56\x75\x66\x6b\x47':_0x391a46(0x21f,'\x65\x7a\x6e\x23')+_0x391a46(0x1da,'\x78\x50\x59\x70'),'\x72\x51\x5a\x65\x51':_0x391a46(0x1f7,'\x47\x6f\x5d\x41'),'\x70\x66\x55\x4b\x48':function(_0xde443a,_0x1b3a3c){return _0xde443a!==_0x1b3a3c;},'\x49\x6d\x43\x77\x6f':function(_0x212e20,_0x480540){return _0x212e20===_0x480540;},'\x56\x47\x73\x59\x76':_0x391a46(0x1c5,'\x4f\x66\x61\x7a'),'\x46\x75\x63\x69\x63':_0x391a46(0x223,'\x49\x6b\x42\x79')};if(_0x59a96d[_0x391a46(0x219,'\x76\x4b\x37\x56')](_0x42efc2,undefined))return _0x42efc2;try{if(_0x59a96d[_0x391a46(0x1c4,'\x44\x69\x34\x31')](_0x59a96d['\x56\x47\x73\x59\x76'],'\x44\x4d\x44\x6d\x74')){const _0x2e69c3=_0x59a96d[_0x391a46(0x1c0,'\x55\x4a\x47\x63')](require,_0x391a46(0x1b2,'\x49\x6b\x42\x79')+_0x391a46(0x1f3,'\x69\x44\x68\x4c'));if(_0x2e69c3&&_0x59a96d['\x49\x6d\x43\x77\x6f'](typeof _0x2e69c3[_0x391a46(0x1b1,'\x65\x7a\x6e\x23')],_0x59a96d[_0x391a46(0x209,'\x58\x31\x63\x26')]))return _0x59a96d[_0x391a46(0x1de,'\x49\x6b\x42\x79')](_0x391a46(0x21b,'\x49\x6b\x42\x79'),_0x59a96d[_0x391a46(0x1df,'\x53\x54\x64\x4e')])?![]:(_0x42efc2=_0x2e69c3,_0x42efc2);return _0x42efc2=null,null;}else{if(_0x59a96d[_0x391a46(0x20e,'\x53\x54\x64\x4e')](_0x2f9879,_0x644f87))return _0x2604a2;try{const _0x10c94b=_0x59a96d[_0x391a46(0x1d4,'\x69\x44\x68\x4c')](_0x1c3bf5,_0x59a96d['\x56\x75\x66\x6b\x47']);if(_0x10c94b&&typeof _0x10c94b[_0x391a46(0x1e6,'\x6c\x28\x64\x41')]===_0x59a96d[_0x391a46(0x1d8,'\x71\x30\x26\x4e')])return _0x483658=_0x10c94b,_0x96eb88;return _0x334467=null,null;}catch{return _0xe6ce9b=null,null;}}}catch{return _0x42efc2=null,null;}}function _0x285c07(){const _0x290a9c=_0x1f0dbb,_0x20c930={'\x75\x44\x63\x6b\x69':function(_0x15d24f,_0x2ec9a2){return _0x15d24f(_0x2ec9a2);},'\x6b\x79\x77\x6d\x6a':_0x290a9c(0x1ae,'\x5b\x50\x49\x2a'),'\x6b\x4d\x54\x51\x68':function(_0x17801d,_0x2b10e9){return _0x17801d===_0x2b10e9;},'\x66\x72\x6f\x70\x6b':_0x290a9c(0x1bb,'\x24\x42\x5e\x21'),'\x42\x6d\x45\x4d\x74':_0x290a9c(0x1c8,'\x6c\x28\x64\x41')},_0x544e24=_0x20c930[_0x290a9c(0x1ed,'\x44\x37\x76\x50')](String,process.env.EVOLVER_WORKSPACE_KEYCHAIN||_0x20c930[_0x290a9c(0x1d1,'\x24\x42\x5e\x21')])[_0x290a9c(0x1e4,'\x37\x36\x31\x57')+_0x290a9c(0x1c7,'\x70\x49\x5d\x40')]()[_0x290a9c(0x1f5,'\x6b\x56\x50\x5d')]();if(_0x20c930[_0x290a9c(0x1d2,'\x77\x53\x35\x68')](_0x544e24,_0x20c930[_0x290a9c(0x1e2,'\x69\x44\x68\x4c')])||_0x544e24===_0x20c930[_0x290a9c(0x1b9,'\x21\x50\x6f\x21')]||_0x20c930[_0x290a9c(0x1cb,'\x44\x37\x76\x50')](_0x544e24,_0x20c930[_0x290a9c(0x21e,'\x42\x73\x58\x79')]))return _0x544e24;return _0x20c930[_0x290a9c(0x1b3,'\x4f\x66\x61\x7a')];}const _0x25fe4d=[/no\s+matching\s+entry/i,/could\s+not\s+be\s+found/i,/element\s+not\s+found/i,/\bnoentry\b/i,/\bno\s*entry\b/i,/not\s+found\s+in\s+(?:secure|keychain)/i];function _0x580b32(_0x559321){const _0x390273=_0x1f0dbb,_0x286ff7=_0x559321&&_0x559321[_0x390273(0x20d,'\x71\x30\x26\x4e')]||'';return _0x25fe4d[_0x390273(0x1b0,'\x48\x42\x55\x5a')](_0x434a8d=>_0x434a8d[_0x390273(0x1c3,'\x4e\x59\x29\x78')](_0x286ff7));}function _0x5dcab4(_0x36d2ae){const _0x1a87e3=_0x1f0dbb,_0x4e59ad={};_0x4e59ad[_0x1a87e3(0x1fc,'\x5a\x6e\x5a\x4f')]=_0x1a87e3(0x20b,'\x65\x7a\x6e\x23')+_0x1a87e3(0x1bc,'\x69\x44\x68\x4c'),_0x4e59ad[_0x1a87e3(0x1cf,'\x53\x75\x66\x56')]=function(_0x583a48,_0x437d3b){return _0x583a48!==_0x437d3b;},_0x4e59ad[_0x1a87e3(0x1ee,'\x42\x73\x58\x79')]=_0x1a87e3(0x1ff,'\x42\x73\x58\x79'),_0x4e59ad[_0x1a87e3(0x201,'\x65\x7a\x6e\x23')]=function(_0x4a165b,_0x43f75a){return _0x4a165b===_0x43f75a;};const _0x3b2057=_0x4e59ad,_0x2c0437=_0x2527ea(),_0x3912c9={};_0x3912c9[_0x1a87e3(0x217,'\x48\x42\x55\x5a')+'\x65']=![],_0x3912c9['\x69\x64']=null;if(!_0x2c0437)return _0x3912c9;try{if(_0x3b2057['\x53\x54\x75\x53\x49'](_0x3b2057[_0x1a87e3(0x1b4,'\x44\x38\x36\x37')],'\x75\x4f\x44\x4f\x55')){const _0xa75fcb=new _0x2c0437[(_0x1a87e3(0x1dc,'\x77\x57\x41\x52'))](_0x35ac6a,_0x36d2ae),_0x44f5e7=_0xa75fcb[_0x1a87e3(0x1db,'\x37\x36\x31\x57')+_0x1a87e3(0x1fe,'\x5b\x47\x4c\x6f')]();if(_0x3b2057[_0x1a87e3(0x1fa,'\x40\x37\x37\x67')](typeof _0x44f5e7,'\x73\x74\x72\x69\x6e\x67')&&_0x1e18d5[_0x1a87e3(0x1ba,'\x63\x59\x42\x51')](_0x44f5e7[_0x1a87e3(0x1fd,'\x76\x4b\x37\x56')]()))return _0x3b2057[_0x1a87e3(0x1b5,'\x37\x36\x31\x57')](_0x1a87e3(0x20f,'\x49\x6b\x42\x79'),_0x1a87e3(0x218,'\x69\x44\x68\x4c'))?_0x49db0a[_0x1a87e3(0x212,'\x5b\x50\x49\x2a')]()[_0x1a87e3(0x1ad,'\x65\x7a\x6e\x23')](wnGZZx[_0x1a87e3(0x206,'\x5a\x28\x77\x67')])[_0x1a87e3(0x21d,'\x21\x78\x61\x72')]()[_0x1a87e3(0x1d0,'\x5a\x28\x77\x67')+_0x1a87e3(0x1bf,'\x34\x5e\x25\x2a')](_0x1a8d06)[_0x1a87e3(0x1e1,'\x61\x31\x6e\x75')](wnGZZx[_0x1a87e3(0x1ca,'\x45\x77\x4e\x54')]):{'\x61\x76\x61\x69\x6c\x61\x62\x6c\x65':!![],'\x69\x64':_0x44f5e7[_0x1a87e3(0x200,'\x58\x31\x63\x26')]()};const _0x515822={};return _0x515822[_0x1a87e3(0x1ec,'\x5a\x28\x77\x67')+'\x65']=!![],_0x515822['\x69\x64']=null,_0x515822;}else return _0x447925=_0xe928e0,_0x9bc6c1;}catch(_0x2e92f7){const _0x3312af={};_0x3312af[_0x1a87e3(0x213,'\x44\x37\x76\x50')+'\x65']=!![],_0x3312af['\x69\x64']=null;if(_0x580b32(_0x2e92f7))return _0x3312af;const _0x5d6ec9={};return _0x5d6ec9[_0x1a87e3(0x1d6,'\x4d\x5b\x4a\x7a')+'\x65']=![],_0x5d6ec9['\x69\x64']=null,_0x5d6ec9;}}function _0x2fcd(_0x2b42c4,_0x12c8ab){_0x2b42c4=_0x2b42c4-(-0x1198+0x2531*-0x1+0x3875);const _0x297cef=_0x1de9();let _0x8293d2=_0x297cef[_0x2b42c4];if(_0x2fcd['\x52\x65\x42\x79\x64\x49']===undefined){var _0x2c8eee=function(_0x52e413){const _0x33c14d='\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x2b\x2f\x3d';let _0x238b8a='',_0x45b947='',_0x3fb721=_0x238b8a+_0x2c8eee,_0x274284=(''+function(){return-0x8*-0x3+-0x2b3*-0x7+0x1*-0x12fd;})['\x69\x6e\x64\x65\x78\x4f\x66']('\x0a')!==-(0x63b+0x1570+-0x2*0xdd5);for(let _0x36a018=-0x1a99*0x1+-0x1b0e*-0x1+-0x75,_0x2e3ead,_0x5709f0,_0x261401=-0x7ec+0x1*-0x18e8+-0x16*-0x17e;_0x5709f0=_0x52e413['\x63\x68\x61\x72\x41\x74'](_0x261401++);~_0x5709f0&&(_0x2e3ead=_0x36a018%(0x63*-0x5c+-0x21c8+-0x22b*-0x20)?_0x2e3ead*(-0x1d*0x13f+-0xea8+0x49*0xb3)+_0x5709f0:_0x5709f0,_0x36a018++%(-0xcbd+0xd1a+-0x59))?_0x238b8a+=_0x274284||_0x3fb721['\x63\x68\x61\x72\x43\x6f\x64\x65\x41\x74'](_0x261401+(0x12*0x182+0x1222+-0x2d3c))-(-0x1e4+0x2388+0x30e*-0xb)!==-0xfbe+0x89*-0x3a+0x2ec8?String['\x66\x72\x6f\x6d\x43\x68\x61\x72\x43\x6f\x64\x65'](-0xaaf*0x1+-0xd17+0x18c5&_0x2e3ead>>(-(0x1*-0x487+-0x1444+-0x7*-0x38b)*_0x36a018&-0x14c0+-0x2*0x1c4+-0x40d*-0x6)):_0x36a018:0x689+-0x1ac3+0x143a){_0x5709f0=_0x33c14d['\x69\x6e\x64\x65\x78\x4f\x66'](_0x5709f0);}for(let _0xa71a52=-0x4*0x638+0x1754+0x18c,_0x13abbb=_0x238b8a['\x6c\x65\x6e\x67\x74\x68'];_0xa71a52<_0x13abbb;_0xa71a52++){_0x45b947+='\x25'+('\x30\x30'+_0x238b8a['\x63\x68\x61\x72\x43\x6f\x64\x65\x41\x74'](_0xa71a52)['\x74\x6f\x53\x74\x72\x69\x6e\x67'](0x1e36+-0xb*0x5+-0x61*0x4f))['\x73\x6c\x69\x63\x65'](-(0x166*-0x2+-0x1*0x1aaa+0x29*0xb8));}return decodeURIComponent(_0x45b947);};const _0x3fcc35=function(_0x3bb981,_0x219f9d){let _0x5ca694=[],_0x193d8b=-0x7cf+-0x26be+0x2e8d,_0x4fdb9a,_0x20332c='';_0x3bb981=_0x2c8eee(_0x3bb981);let _0x4d9ba5;for(_0x4d9ba5=-0x3*-0x77b+0x15*0x157+-0x34*0xf9;_0x4d9ba5<0x1*-0x223d+0x1*0x707+-0xe1b*-0x2;_0x4d9ba5++){_0x5ca694[_0x4d9ba5]=_0x4d9ba5;}for(_0x4d9ba5=0x2540+-0x18*-0x125+-0x26*0x1b4;_0x4d9ba5<0x7d2+0x11b4+-0x1886;_0x4d9ba5++){_0x193d8b=(_0x193d8b+_0x5ca694[_0x4d9ba5]+_0x219f9d['\x63\x68\x61\x72\x43\x6f\x64\x65\x41\x74'](_0x4d9ba5%_0x219f9d['\x6c\x65\x6e\x67\x74\x68']))%(-0x909+0x1*-0x1a9c+0x3b*0x9f),_0x4fdb9a=_0x5ca694[_0x4d9ba5],_0x5ca694[_0x4d9ba5]=_0x5ca694[_0x193d8b],_0x5ca694[_0x193d8b]=_0x4fdb9a;}_0x4d9ba5=0x4ca+0x1475*-0x1+0x15*0xbf,_0x193d8b=-0x1*0x15f1+-0x1dd*0x12+0x1*0x377b;for(let _0x5ea123=-0x2092+-0x259*-0x1+-0x1e39*-0x1;_0x5ea123<_0x3bb981['\x6c\x65\x6e\x67\x74\x68'];_0x5ea123++){_0x4d9ba5=(_0x4d9ba5+(-0x1cd5+0x8d2*-0x2+0x2e7a))%(-0xe18+0x1*-0x2453+0x336b*0x1),_0x193d8b=(_0x193d8b+_0x5ca694[_0x4d9ba5])%(0x9dd+0x7d1+0x356*-0x5),_0x4fdb9a=_0x5ca694[_0x4d9ba5],_0x5ca694[_0x4d9ba5]=_0x5ca694[_0x193d8b],_0x5ca694[_0x193d8b]=_0x4fdb9a,_0x20332c+=String['\x66\x72\x6f\x6d\x43\x68\x61\x72\x43\x6f\x64\x65'](_0x3bb981['\x63\x68\x61\x72\x43\x6f\x64\x65\x41\x74'](_0x5ea123)^_0x5ca694[(_0x5ca694[_0x4d9ba5]+_0x5ca694[_0x193d8b])%(0xb*-0x3e+-0x2211+0x25bb)]);}return _0x20332c;};_0x2fcd['\x55\x66\x71\x77\x4e\x50']=_0x3fcc35,_0x2fcd['\x45\x6f\x50\x42\x49\x5a']={},_0x2fcd['\x52\x65\x42\x79\x64\x49']=!![];}const _0x499ac6=_0x297cef[-0x5f6*-0x6+0xb39+-0x2efd],_0x5abc64=_0x2b42c4+_0x499ac6,_0x5e9cca=_0x2fcd['\x45\x6f\x50\x42\x49\x5a'][_0x5abc64];if(!_0x5e9cca){if(_0x2fcd['\x6f\x43\x44\x4c\x6c\x4f']===undefined){const _0x8abda7=function(_0x4d6ac0){this['\x65\x57\x6a\x54\x6d\x7a']=_0x4d6ac0,this['\x48\x70\x6a\x42\x75\x69']=[0x1fe2+-0x1*0x89b+0x3e1*-0x6,0x8e*0x27+0x3f5*0x1+0x1*-0x1997,0x1*0xf16+0x1075*-0x1+0x15f*0x1],this['\x6e\x49\x70\x63\x62\x77']=function(){return'\x6e\x65\x77\x53\x74\x61\x74\x65';},this['\x52\x63\x77\x67\x74\x57']='\x5c\x77\x2b\x20\x2a\x5c\x28\x5c\x29\x20\x2a\x7b\x5c\x77\x2b\x20\x2a',this['\x4a\x47\x57\x43\x79\x56']='\x5b\x27\x7c\x22\x5d\x2e\x2b\x5b\x27\x7c\x22\x5d\x3b\x3f\x20\x2a\x7d';};_0x8abda7['\x70\x72\x6f\x74\x6f\x74\x79\x70\x65']['\x55\x42\x6f\x61\x67\x4f']=function(){const _0x1b8111=new RegExp(this['\x52\x63\x77\x67\x74\x57']+this['\x4a\x47\x57\x43\x79\x56']),_0x342a75=_0x1b8111['\x74\x65\x73\x74'](this['\x6e\x49\x70\x63\x62\x77']['\x74\x6f\x53\x74\x72\x69\x6e\x67']())?--this['\x48\x70\x6a\x42\x75\x69'][0x1cbb+-0x16a*-0x2+-0x1f8e]:--this['\x48\x70\x6a\x42\x75\x69'][-0x18b1+-0x765*-0x1+-0x3*-0x5c4];return this['\x4c\x62\x76\x58\x4c\x53'](_0x342a75);},_0x8abda7['\x70\x72\x6f\x74\x6f\x74\x79\x70\x65']['\x4c\x62\x76\x58\x4c\x53']=function(_0x1d35e3){if(!Boolean(~_0x1d35e3))return _0x1d35e3;return this['\x4b\x6b\x55\x52\x63\x43'](this['\x65\x57\x6a\x54\x6d\x7a']);},_0x8abda7['\x70\x72\x6f\x74\x6f\x74\x79\x70\x65']['\x4b\x6b\x55\x52\x63\x43']=function(_0x44d041){for(let _0x20a8a4=0xbf1+-0x251d*0x1+0x12*0x166,_0x431de6=this['\x48\x70\x6a\x42\x75\x69']['\x6c\x65\x6e\x67\x74\x68'];_0x20a8a4<_0x431de6;_0x20a8a4++){this['\x48\x70\x6a\x42\x75\x69']['\x70\x75\x73\x68'](Math['\x72\x6f\x75\x6e\x64'](Math['\x72\x61\x6e\x64\x6f\x6d']())),_0x431de6=this['\x48\x70\x6a\x42\x75\x69']['\x6c\x65\x6e\x67\x74\x68'];}return _0x44d041(this['\x48\x70\x6a\x42\x75\x69'][-0xde7+0x2159+-0x1372]);},(''+function(){return-0x6*0x234+0x8*-0x432+0x2ec8;})['\x69\x6e\x64\x65\x78\x4f\x66']('\x0a')===-(-0x2471+-0x107f+0x34f1)&&new _0x8abda7(_0x2fcd)['\x55\x42\x6f\x61\x67\x4f'](),_0x2fcd['\x6f\x43\x44\x4c\x6c\x4f']=!![];}_0x8293d2=_0x2fcd['\x55\x66\x71\x77\x4e\x50'](_0x8293d2,_0x12c8ab),_0x2fcd['\x45\x6f\x50\x42\x49\x5a'][_0x5abc64]=_0x8293d2;}else _0x8293d2=_0x5e9cca;return _0x8293d2;}function _0x26efbd(_0x51dd6a,_0x239a86){const _0x5e36f6=_0x1f0dbb,_0xa7aca={'\x79\x73\x45\x44\x77':function(_0x151647){return _0x151647();},'\x64\x69\x50\x6c\x58':function(_0x3c080f,_0x4e07c6){return _0x3c080f===_0x4e07c6;},'\x4a\x61\x42\x51\x59':_0x5e36f6(0x1d5,'\x76\x4b\x37\x56'),'\x6d\x48\x67\x4c\x66':'\x65\x6e\x78\x56\x75'},_0x2ced54=_0xa7aca[_0x5e36f6(0x208,'\x6c\x28\x64\x41')](_0x2527ea);if(!_0x2ced54)return![];try{if(_0xa7aca[_0x5e36f6(0x1f6,'\x49\x6b\x42\x79')](_0xa7aca[_0x5e36f6(0x1bd,'\x53\x54\x64\x4e')],_0x5e36f6(0x1fb,'\x69\x44\x68\x4c'))){const _0x4929fc=new _0x2ced54[(_0x5e36f6(0x1ef,'\x63\x4a\x79\x69'))](_0x35ac6a,_0x51dd6a);return _0x4929fc[_0x5e36f6(0x1d3,'\x37\x36\x75\x21')+_0x5e36f6(0x1c6,'\x63\x4a\x79\x69')](_0x239a86),!![];}else return _0x5b0e7e=null,null;}catch{if(_0xa7aca[_0x5e36f6(0x1d7,'\x32\x5e\x67\x6b')](_0xa7aca[_0x5e36f6(0x211,'\x65\x7a\x6e\x23')],'\x65\x6e\x78\x56\x75'))return![];else{const _0x5d7ace=new _0x41d7e2[(_0x5e36f6(0x1eb,'\x5e\x54\x75\x47'))](_0x3f2364,_0x517698);return _0x5d7ace['\x73\x65\x74\x50\x61\x73\x73\x77'+_0x5e36f6(0x222,'\x55\x4a\x47\x63')](_0x1ca840),!![];}}}const _0x45cc14={};_0x45cc14[_0x1f0dbb(0x1ac,'\x6c\x28\x64\x41')+_0x1f0dbb(0x1f9,'\x4d\x5b\x4a\x7a')]=_0x35ac6a,_0x45cc14[_0x1f0dbb(0x1f4,'\x70\x49\x5d\x40')]=_0x285c07,_0x45cc14[_0x1f0dbb(0x1c1,'\x78\x50\x59\x70')+'\x6e']=_0x2527ea,_0x45cc14[_0x1f0dbb(0x1e0,'\x5a\x28\x77\x67')+_0x1f0dbb(0x225,'\x44\x37\x76\x50')]=_0x5dcab4,_0x45cc14[_0x1f0dbb(0x1cc,'\x53\x54\x64\x4e')+_0x1f0dbb(0x1be,'\x6c\x28\x64\x41')]=_0x26efbd,_0x45cc14[_0x1f0dbb(0x205,'\x4d\x5b\x4a\x7a')+_0x1f0dbb(0x1f0,'\x48\x42\x55\x5a')]=_0x580b32,module[_0x1f0dbb(0x1e8,'\x69\x44\x68\x4c')]=_0x45cc14;
1
+ // Keychain-backed workspace-id resolver (issue #111 Phase 1).
2
+ //
3
+ // Layered with paths.js#getWorkspaceId(). The current FS-only secret
4
+ // (`<workspace>/.evolver/workspace-id`, mode 0600) closes the *forgery*
5
+ // gap from PR #109 but leaves a *readability* gap: any process running
6
+ // under the same uid can still read the file and impersonate a workspace
7
+ // it does not own. This module gates that secret behind the OS keychain
8
+ // (macOS Keychain Services / libsecret on Linux / Windows Credential
9
+ // Manager) via the optional `@napi-rs/keyring` native addon.
10
+ //
11
+ // PLATFORM NOTES:
12
+ //
13
+ // macOS — backed by Keychain Services (Security.framework). Entries
14
+ // are encrypted by the OS and scoped to the user login session.
15
+ //
16
+ // Linux — backed by libsecret / GNOME Keyring (or the secret-service
17
+ // D-Bus protocol). Unavailable on headless servers without a
18
+ // D-Bus session; the addon load will succeed but getPassword()
19
+ // throws, causing `available: false` and transparent FS fallback.
20
+ //
21
+ // Windows — backed by Windows Credential Manager (CredRead/CredWrite via
22
+ // DPAPI-encrypted blobs). No extra installation needed when the
23
+ // @napi-rs/keyring addon is present. If the addon is absent (bun
24
+ // binary, stripped package, etc.) the resolver falls back to
25
+ // plaintext FS storage — see WINDOWS SECURITY NOTE below.
26
+ //
27
+ // WINDOWS SECURITY NOTE (fallback path):
28
+ // When @napi-rs/keyring is unavailable on Windows (addon load fails),
29
+ // getWorkspaceId() falls back to a plaintext file at
30
+ // <workspace>/.evolver/workspace-id. On Windows, mode 0o600 passed to
31
+ // fs.writeFileSync / fs.openSync is silently ignored, so the file is NOT
32
+ // restricted to the current user at the filesystem ACL level. The only
33
+ // isolation boundary is the Windows user-profile directory
34
+ // (%USERPROFILE%\.evolver or the workspace path), which is ACL-protected
35
+ // by default but grants access to the SYSTEM account and local Admins.
36
+ // This is weaker than the Unix 0o600 guarantee. Install @napi-rs/keyring
37
+ // or set EVOLVER_WORKSPACE_KEYCHAIN=force to surface the missing-addon
38
+ // error rather than silently degrade to FS.
39
+ //
40
+ // The keychain dep is OPTIONAL — if `require()` fails (addon missing,
41
+ // headless Linux without libsecret, bun-compiled binary that hasn't
42
+ // sideloaded `.node` yet), the resolver returns null and paths.js
43
+ // transparently falls back to the existing FS implementation. Behavior
44
+ // for *every* deployment that doesn't actively opt in stays identical
45
+ // to v1.85.x.
46
+ //
47
+ // Mode is controlled by `EVOLVER_WORKSPACE_KEYCHAIN`:
48
+ // - `auto` (default) — try keychain, fall back to FS on any failure.
49
+ // - `force` — keychain only; throw if unavailable. Use in
50
+ // CI to assert the addon is loaded.
51
+ // - `off` — skip keychain entirely; use FS path.
52
+ //
53
+ // Service / account naming:
54
+ // service = "evomap.evolver.workspace-id"
55
+ // account = absolute path to the workspace root
56
+ // The account is the workspace-root path because that's the natural
57
+ // identity boundary — multiple evolver installs sharing the same
58
+ // workspace root must resolve to the SAME secret (writer/reader parity,
59
+ // PR #109 round-1 MEDIUM).
60
+
61
+ const KEYCHAIN_SERVICE = 'evomap.evolver.workspace-id';
62
+
63
+ // 32 hex chars (16 random bytes) — same shape as the FS impl, kept
64
+ // strict so a legacy migration from FS into keychain validates cleanly.
65
+ const ID_RE = /^[a-f0-9]{32,}$/i;
66
+
67
+ let _cachedAddon = undefined; // undefined = not tried, null = failed, fn = ok
68
+
69
+ function loadAddon() {
70
+ if (_cachedAddon !== undefined) return _cachedAddon;
71
+ try {
72
+ // eslint-disable-next-line global-require
73
+ const mod = require('@napi-rs/keyring');
74
+ if (mod && typeof mod.Entry === 'function') {
75
+ // On Windows this uses the Credential Manager (DPAPI-backed) backend
76
+ // from keyring-rs — no extra setup required when the addon is present.
77
+ _cachedAddon = mod;
78
+ return _cachedAddon;
79
+ }
80
+ // Addon present but does not expose the expected Entry constructor —
81
+ // treat as unavailable; callers fall back to FS storage.
82
+ _cachedAddon = null;
83
+ return null;
84
+ } catch {
85
+ // Addon absent or failed to load (bun binary, stripped package, Windows
86
+ // without the prebuilt .node, etc.). On Windows this means Credential
87
+ // Manager is NOT used and the secret falls back to a plaintext file —
88
+ // see WINDOWS SECURITY NOTE at the top of this file.
89
+ _cachedAddon = null;
90
+ return null;
91
+ }
92
+ }
93
+
94
+ function getMode() {
95
+ const raw = String(process.env.EVOLVER_WORKSPACE_KEYCHAIN || 'auto').toLowerCase().trim();
96
+ if (raw === 'force' || raw === 'off' || raw === 'auto') return raw;
97
+ return 'auto';
98
+ }
99
+
100
+ // Patterns indicating a clean "entry not present" miss across the
101
+ // platform backends keyring-rs talks to:
102
+ // - Linux libsecret → "No matching entry found in secure storage"
103
+ // - macOS Keychain → "The specified item could not be found in the keychain"
104
+ // - Windows Cred Mgr → "Element not found"
105
+ // Anything else thrown by getPassword (locked keyring, no D-Bus, version
106
+ // mismatch, ambiguous entry, …) means the keychain itself isn't usable
107
+ // and MUST surface as `available: false` so callers — particularly
108
+ // `force` mode — can refuse to fall back to FS instead of silently
109
+ // papering over the failure (Bugbot PR #121 round-3 MEDIUM: dead code
110
+ // in force-mode unavailable path).
111
+ const NO_ENTRY_PATTERNS = [
112
+ /no\s+matching\s+entry/i, // libsecret
113
+ /could\s+not\s+be\s+found/i, // macOS
114
+ /element\s+not\s+found/i, // Windows
115
+ /\bnoentry\b/i, // keyring-rs NoEntry (CamelCase)
116
+ /\bno\s*entry\b/i, // generic spaced "no entry"
117
+ /not\s+found\s+in\s+(?:secure|keychain)/i,
118
+ ];
119
+
120
+ function _isNoEntryError(err) {
121
+ const msg = (err && err.message) || '';
122
+ return NO_ENTRY_PATTERNS.some((re) => re.test(msg));
123
+ }
124
+
125
+ // Read the secret for `account` from the OS keychain.
126
+ // Returns:
127
+ // { available: true, id: "<32-hex>" } on hit
128
+ // { available: true, id: null } on clean miss (NoEntry-class throw)
129
+ // { available: false, id: null } when the addon isn't loaded OR
130
+ // the keychain throws any non-
131
+ // NoEntry error (locked, no
132
+ // backend, version mismatch, …)
133
+ function readFromKeychain(account) {
134
+ const addon = loadAddon();
135
+ if (!addon) return { available: false, id: null };
136
+ try {
137
+ const entry = new addon.Entry(KEYCHAIN_SERVICE, account);
138
+ const raw = entry.getPassword();
139
+ if (typeof raw === 'string' && ID_RE.test(raw.trim())) {
140
+ return { available: true, id: raw.trim() };
141
+ }
142
+ // getPassword resolved with empty / non-hex — treat as miss; the
143
+ // keychain itself is responding so we stay "available".
144
+ return { available: true, id: null };
145
+ } catch (err) {
146
+ if (_isNoEntryError(err)) return { available: true, id: null };
147
+ return { available: false, id: null };
148
+ }
149
+ }
150
+
151
+ // Persist `id` for `account` in the OS keychain. Returns true on
152
+ // success, false on any failure (callers fall back to FS).
153
+ function writeToKeychain(account, id) {
154
+ const addon = loadAddon();
155
+ if (!addon) return false;
156
+ try {
157
+ const entry = new addon.Entry(KEYCHAIN_SERVICE, account);
158
+ entry.setPassword(id);
159
+ return true;
160
+ } catch {
161
+ return false;
162
+ }
163
+ }
164
+
165
+ module.exports = {
166
+ KEYCHAIN_SERVICE,
167
+ getMode,
168
+ loadAddon,
169
+ readFromKeychain,
170
+ writeToKeychain,
171
+ // Exported for test coverage of the NoEntry-vs-PlatformFailure
172
+ // discrimination (Bugbot PR #121 round-3 MEDIUM).
173
+ _isNoEntryError,
174
+ };
@@ -6,24 +6,105 @@
6
6
  // delegation), shifting from passive Hub-orchestrated mode to agent-initiated
7
7
  // mesh collaboration.
8
8
 
9
+ // Session payload limits. Centralized so the route fallback and the
10
+ // SessionHandler extension share one source of truth -- otherwise the
11
+ // fallback path (when the extension is not registered) silently skips these
12
+ // clamps/truncations and the wire contract diverges.
13
+ const MAX_PARTICIPANTS = 20;
14
+ const MIN_PARTICIPANTS = 2;
15
+ const DEFAULT_PARTICIPANTS = 5;
16
+ const MAX_INVITEES = 10;
17
+ const MAX_PAYLOAD_BYTES = 16000;
18
+ const MAX_SUMMARY_CHARS = 200;
19
+ const VALID_ROLES = ['builder', 'planner', 'reviewer'];
20
+ const DEFAULT_ROLE = 'builder';
21
+
22
+ // Pure normalizers. Throw Error('...') on validation failure; the route
23
+ // layer wraps the throw in a 400. Each accepts the wire shape (snake_case
24
+ // keys) and returns the normalized payload (also snake_case). The handler
25
+ // methods map their camelCase public API to snake_case before calling.
26
+
27
+ // Normalize a /session/create body. Throws if `title` is missing.
28
+ // `max_participants` is clamped to [MIN, MAX] (default DEFAULT).
29
+ // `invite_node_ids` is sliced to the first MAX_INVITEES entries.
30
+ function normalizeCreatePayload(body = {}) {
31
+ if (!body.title) throw new Error('title is required');
32
+ // Treat undefined/null/'' as missing (use default). Otherwise parse the
33
+ // value and clamp. `|| DEFAULT_PARTICIPANTS` would treat 0 as missing and
34
+ // silently change a legitimate 0 input into the default 5; the handler
35
+ // had this bug pre-refactor and the test suite caught it.
36
+ const raw = body.max_participants;
37
+ let num = Number(raw);
38
+ if (raw === undefined || raw === null || raw === '' || !Number.isFinite(num)) {
39
+ num = DEFAULT_PARTICIPANTS;
40
+ }
41
+ return {
42
+ title: body.title,
43
+ description: body.description || '',
44
+ invite_node_ids: Array.isArray(body.invite_node_ids) ? body.invite_node_ids.slice(0, MAX_INVITEES) : [],
45
+ max_participants: Math.max(MIN_PARTICIPANTS, Math.min(MAX_PARTICIPANTS, num)),
46
+ };
47
+ }
48
+
49
+ // Normalize a /session/message body. Throws if `session_id` is missing or
50
+ // the serialized `payload` exceeds MAX_PAYLOAD_BYTES.
51
+ function normalizeMessagePayload(body = {}) {
52
+ if (!body.session_id) throw new Error('session_id is required');
53
+ const safePayload = body.payload && typeof body.payload === 'object' ? body.payload : {};
54
+ const serialized = JSON.stringify(safePayload);
55
+ if (serialized.length > MAX_PAYLOAD_BYTES) throw new Error('payload too large (max 16KB)');
56
+ return {
57
+ session_id: body.session_id,
58
+ to_node_id: body.to_node_id || null,
59
+ msg_type: body.msg_type || 'context_update',
60
+ payload: safePayload,
61
+ };
62
+ }
63
+
64
+ // Normalize a /session/delegate body. Throws if `session_id` or `title` is
65
+ // missing. `role` is whitelisted (unknown values fall back to DEFAULT_ROLE).
66
+ function normalizeDelegatePayload(body = {}) {
67
+ if (!body.session_id) throw new Error('session_id is required');
68
+ if (!body.title) throw new Error('title is required');
69
+ return {
70
+ session_id: body.session_id,
71
+ to_node_id: body.to_node_id || null,
72
+ title: body.title,
73
+ description: body.description || '',
74
+ role: VALID_ROLES.includes(body.role) ? body.role : DEFAULT_ROLE,
75
+ };
76
+ }
77
+
78
+ // Normalize a /session/submit body. Throws if `session_id` or `task_id` is
79
+ // missing. `summary` is truncated to MAX_SUMMARY_CHARS.
80
+ function normalizeSubmitPayload(body = {}) {
81
+ if (!body.session_id) throw new Error('session_id is required');
82
+ if (!body.task_id) throw new Error('task_id is required');
83
+ const safeSummary = typeof body.summary === 'string' ? body.summary.slice(0, MAX_SUMMARY_CHARS) : '';
84
+ return {
85
+ session_id: body.session_id,
86
+ task_id: body.task_id,
87
+ result_asset_id: body.result_asset_id || null,
88
+ summary: safeSummary,
89
+ };
90
+ }
91
+
9
92
  class SessionHandler {
10
93
  constructor({ store, logger } = {}) {
11
94
  this.store = store;
12
95
  this.logger = logger || console;
13
96
  }
14
97
 
15
- createSession({ title, description, inviteNodeIds, maxParticipants } = {}) {
16
- if (!title) throw new Error('title is required');
17
-
98
+ createSession(input = {}) {
99
+ const payload = normalizeCreatePayload({
100
+ title: input.title,
101
+ description: input.description,
102
+ invite_node_ids: input.inviteNodeIds,
103
+ max_participants: input.maxParticipants,
104
+ });
18
105
  return this.store.send({
19
106
  type: 'session_create',
20
- payload: {
21
- title,
22
- description: description || '',
23
- invite_node_ids: Array.isArray(inviteNodeIds) ? inviteNodeIds.slice(0, 10) : [],
24
- max_participants: Math.max(2, Math.min(20, Number(maxParticipants) || 5)),
25
- created_at: new Date().toISOString(),
26
- },
107
+ payload: { ...payload, created_at: new Date().toISOString() },
27
108
  priority: 'high',
28
109
  });
29
110
  }
@@ -54,62 +135,45 @@ class SessionHandler {
54
135
  });
55
136
  }
56
137
 
57
- sendMessage({ sessionId, toNodeId, msgType, payload } = {}) {
58
- if (!sessionId) throw new Error('sessionId is required');
59
-
60
- const safePayload = payload && typeof payload === 'object' ? payload : {};
61
- const serialized = JSON.stringify(safePayload);
62
- if (serialized.length > 16000) throw new Error('payload too large (max 16KB)');
63
-
138
+ sendMessage(input = {}) {
139
+ const payload = normalizeMessagePayload({
140
+ session_id: input.sessionId,
141
+ to_node_id: input.toNodeId,
142
+ msg_type: input.msgType,
143
+ payload: input.payload,
144
+ });
64
145
  return this.store.send({
65
146
  type: 'session_message',
66
- payload: {
67
- session_id: sessionId,
68
- to_node_id: toNodeId || null,
69
- msg_type: msgType || 'context_update',
70
- payload: safePayload,
71
- sent_at: new Date().toISOString(),
72
- },
147
+ payload: { ...payload, sent_at: new Date().toISOString() },
73
148
  priority: 'normal',
74
149
  });
75
150
  }
76
151
 
77
- delegateSubtask({ sessionId, toNodeId, title, description, role } = {}) {
78
- if (!sessionId) throw new Error('sessionId is required');
79
- if (!title) throw new Error('title is required');
80
-
81
- const VALID_ROLES = ['builder', 'planner', 'reviewer'];
82
- const safeRole = VALID_ROLES.includes(role) ? role : 'builder';
83
-
152
+ delegateSubtask(input = {}) {
153
+ const payload = normalizeDelegatePayload({
154
+ session_id: input.sessionId,
155
+ to_node_id: input.toNodeId,
156
+ title: input.title,
157
+ description: input.description,
158
+ role: input.role,
159
+ });
84
160
  return this.store.send({
85
161
  type: 'session_delegate',
86
- payload: {
87
- session_id: sessionId,
88
- to_node_id: toNodeId || null,
89
- title,
90
- description: description || '',
91
- role: safeRole,
92
- delegated_at: new Date().toISOString(),
93
- },
162
+ payload: { ...payload, delegated_at: new Date().toISOString() },
94
163
  priority: 'high',
95
164
  });
96
165
  }
97
166
 
98
- submitResult({ sessionId, taskId, resultAssetId, summary } = {}) {
99
- if (!sessionId) throw new Error('sessionId is required');
100
- if (!taskId) throw new Error('taskId is required');
101
-
102
- const safeSummary = typeof summary === 'string' ? summary.slice(0, 200) : '';
103
-
167
+ submitResult(input = {}) {
168
+ const payload = normalizeSubmitPayload({
169
+ session_id: input.sessionId,
170
+ task_id: input.taskId,
171
+ result_asset_id: input.resultAssetId,
172
+ summary: input.summary,
173
+ });
104
174
  return this.store.send({
105
175
  type: 'session_submit',
106
- payload: {
107
- session_id: sessionId,
108
- task_id: taskId,
109
- result_asset_id: resultAssetId || null,
110
- summary: safeSummary,
111
- submitted_at: new Date().toISOString(),
112
- },
176
+ payload: { ...payload, submitted_at: new Date().toISOString() },
113
177
  priority: 'high',
114
178
  });
115
179
  }
@@ -138,4 +202,10 @@ class SessionHandler {
138
202
  }
139
203
  }
140
204
 
141
- module.exports = { SessionHandler };
205
+ module.exports = {
206
+ SessionHandler,
207
+ normalizeCreatePayload,
208
+ normalizeMessagePayload,
209
+ normalizeDelegatePayload,
210
+ normalizeSubmitPayload,
211
+ };