shieldcortex 2.18.0 → 2.19.1

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 (129) hide show
  1. package/README.md +42 -12
  2. package/dashboard/.next/standalone/dashboard/.next/BUILD_ID +1 -1
  3. package/dashboard/.next/standalone/dashboard/.next/build-manifest.json +2 -2
  4. package/dashboard/.next/standalone/dashboard/.next/prerender-manifest.json +3 -3
  5. package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.html +2 -2
  6. package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.rsc +1 -1
  7. package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  8. package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  9. package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  10. package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  11. package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  12. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  13. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.html +1 -1
  14. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.rsc +2 -2
  15. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
  16. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  17. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
  18. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  19. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  20. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  21. package/dashboard/.next/standalone/dashboard/.next/server/app/index.html +1 -1
  22. package/dashboard/.next/standalone/dashboard/.next/server/app/index.rsc +3 -3
  23. package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  24. package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/_full.segment.rsc +3 -3
  25. package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/_head.segment.rsc +1 -1
  26. package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/_index.segment.rsc +2 -2
  27. package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  28. package/dashboard/.next/standalone/dashboard/.next/server/app/page_client-reference-manifest.js +1 -1
  29. package/dashboard/.next/standalone/dashboard/.next/server/chunks/ssr/dashboard_25b1b286._.js +1 -1
  30. package/dashboard/.next/standalone/dashboard/.next/server/pages/404.html +1 -1
  31. package/dashboard/.next/standalone/dashboard/.next/server/pages/500.html +2 -2
  32. package/dashboard/.next/standalone/dashboard/.next/server/server-reference-manifest.js +1 -1
  33. package/dashboard/.next/standalone/dashboard/.next/server/server-reference-manifest.json +1 -1
  34. package/dashboard/.next/standalone/dashboard/.next/static/chunks/1a71c9a52f0c9b16.css +3 -0
  35. package/dashboard/.next/standalone/dashboard/.next/static/chunks/6bf7d89d34068ecb.js +9 -0
  36. package/dashboard/.next/standalone/dashboard/.next/static/chunks/d0dcb5e0e04ae015.js +1 -0
  37. package/dashboard/.next/standalone/dashboard/package.json +1 -1
  38. package/dist/api/visualization-server.d.ts.map +1 -1
  39. package/dist/api/visualization-server.js +306 -0
  40. package/dist/api/visualization-server.js.map +1 -1
  41. package/dist/cloud/config.d.ts +13 -1
  42. package/dist/cloud/config.d.ts.map +1 -1
  43. package/dist/cloud/config.js +28 -3
  44. package/dist/cloud/config.js.map +1 -1
  45. package/dist/database/init.d.ts.map +1 -1
  46. package/dist/database/init.js +77 -0
  47. package/dist/database/init.js.map +1 -1
  48. package/dist/defence/__tests__/tool-response-scanner.test.d.ts +8 -0
  49. package/dist/defence/__tests__/tool-response-scanner.test.d.ts.map +1 -0
  50. package/dist/defence/__tests__/tool-response-scanner.test.js +106 -0
  51. package/dist/defence/__tests__/tool-response-scanner.test.js.map +1 -0
  52. package/dist/defence/audit/export.d.ts +6 -0
  53. package/dist/defence/audit/export.d.ts.map +1 -0
  54. package/dist/defence/audit/export.js +43 -0
  55. package/dist/defence/audit/export.js.map +1 -0
  56. package/dist/defence/custom-patterns/store.d.ts +52 -0
  57. package/dist/defence/custom-patterns/store.d.ts.map +1 -0
  58. package/dist/defence/custom-patterns/store.js +108 -0
  59. package/dist/defence/custom-patterns/store.js.map +1 -0
  60. package/dist/defence/custom-rules/store.d.ts +36 -0
  61. package/dist/defence/custom-rules/store.d.ts.map +1 -0
  62. package/dist/defence/custom-rules/store.js +57 -0
  63. package/dist/defence/custom-rules/store.js.map +1 -0
  64. package/dist/defence/iron-dome/custom-policies.d.ts +31 -0
  65. package/dist/defence/iron-dome/custom-policies.d.ts.map +1 -0
  66. package/dist/defence/iron-dome/custom-policies.js +79 -0
  67. package/dist/defence/iron-dome/custom-policies.js.map +1 -0
  68. package/dist/defence/iron-dome/index.d.ts +5 -5
  69. package/dist/defence/iron-dome/index.d.ts.map +1 -1
  70. package/dist/defence/iron-dome/index.js +51 -7
  71. package/dist/defence/iron-dome/index.js.map +1 -1
  72. package/dist/defence/pipeline.d.ts.map +1 -1
  73. package/dist/defence/pipeline.js +73 -0
  74. package/dist/defence/pipeline.js.map +1 -1
  75. package/dist/defence/skill-scanner/deep-scan.d.ts +30 -0
  76. package/dist/defence/skill-scanner/deep-scan.d.ts.map +1 -0
  77. package/dist/defence/skill-scanner/deep-scan.js +112 -0
  78. package/dist/defence/skill-scanner/deep-scan.js.map +1 -0
  79. package/dist/defence/tool-response-scanner.d.ts +23 -0
  80. package/dist/defence/tool-response-scanner.d.ts.map +1 -0
  81. package/dist/defence/tool-response-scanner.js +157 -0
  82. package/dist/defence/tool-response-scanner.js.map +1 -0
  83. package/dist/defence/trust/source-scorer.d.ts.map +1 -1
  84. package/dist/defence/trust/source-scorer.js +2 -1
  85. package/dist/defence/trust/source-scorer.js.map +1 -1
  86. package/dist/defence/types.d.ts +13 -2
  87. package/dist/defence/types.d.ts.map +1 -1
  88. package/dist/defence/types.js.map +1 -1
  89. package/dist/lib.d.ts +2 -0
  90. package/dist/lib.d.ts.map +1 -1
  91. package/dist/lib.js +2 -0
  92. package/dist/lib.js.map +1 -1
  93. package/dist/license/__tests__/feature-gating.test.d.ts +10 -0
  94. package/dist/license/__tests__/feature-gating.test.d.ts.map +1 -0
  95. package/dist/license/__tests__/feature-gating.test.js +188 -0
  96. package/dist/license/__tests__/feature-gating.test.js.map +1 -0
  97. package/dist/license/index.d.ts +1 -0
  98. package/dist/license/index.d.ts.map +1 -1
  99. package/dist/license/index.js.map +1 -1
  100. package/dist/license/types.d.ts +16 -0
  101. package/dist/license/types.d.ts.map +1 -0
  102. package/dist/license/types.js +6 -0
  103. package/dist/license/types.js.map +1 -0
  104. package/dist/server.d.ts.map +1 -1
  105. package/dist/server.js +99 -16
  106. package/dist/server.js.map +1 -1
  107. package/dist/tools/context.d.ts +5 -5
  108. package/dist/tools/context.js +1 -1
  109. package/dist/tools/context.js.map +1 -1
  110. package/dist/tools/forget.d.ts +5 -5
  111. package/dist/tools/forget.js +1 -1
  112. package/dist/tools/forget.js.map +1 -1
  113. package/dist/tools/recall.d.ts +10 -10
  114. package/dist/tools/recall.js +1 -1
  115. package/dist/tools/recall.js.map +1 -1
  116. package/dist/tools/remember.d.ts +7 -7
  117. package/dist/tools/remember.js +1 -1
  118. package/dist/tools/remember.js.map +1 -1
  119. package/hooks/openclaw/cortex-memory/HOOK.md +7 -7
  120. package/hooks/openclaw/cortex-memory/handler.ts +1 -1
  121. package/package.json +2 -1
  122. package/plugins/openclaw/README.md +8 -8
  123. package/plugins/openclaw/index.ts +1 -1
  124. package/dashboard/.next/standalone/dashboard/.next/static/chunks/42d01b77019fd208.js +0 -1
  125. package/dashboard/.next/standalone/dashboard/.next/static/chunks/8a1c0cc0ae709e3d.js +0 -9
  126. package/dashboard/.next/standalone/dashboard/.next/static/chunks/c252c4de65df6d09.css +0 -3
  127. /package/dashboard/.next/standalone/dashboard/.next/static/{h890EBq1H-89xzeQf-gx5 → vxPliVFK4FIBIPl1JPL0U}/_buildManifest.js +0 -0
  128. /package/dashboard/.next/standalone/dashboard/.next/static/{h890EBq1H-89xzeQf-gx5 → vxPliVFK4FIBIPl1JPL0U}/_clientMiddlewareManifest.json +0 -0
  129. /package/dashboard/.next/standalone/dashboard/.next/static/{h890EBq1H-89xzeQf-gx5 → vxPliVFK4FIBIPl1JPL0U}/_ssgManifest.js +0 -0
@@ -0,0 +1 @@
1
+ (globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,88069,45688,71921,88969,94156,e=>{"use strict";let t;var r=e.i(22534),s=e.i(11919),i=e.i(79736),n=e.i(96099),a=e.i(70207),o=e.i(32446),u=e.i(60904),c=e.i(62422),l=class extends a.Subscribable{constructor(e,t){super(),this.options=t,this.#e=e,this.#t=null,this.#r=(0,o.pendingThenable)(),this.bindMethods(),this.setOptions(t)}#e;#s=void 0;#i=void 0;#n=void 0;#a;#o;#r;#t;#u;#c;#l;#h;#d;#y;#f=new Set;bindMethods(){this.refetch=this.refetch.bind(this)}onSubscribe(){1===this.listeners.size&&(this.#s.addObserver(this),h(this.#s,this.options)?this.#p():this.updateResult(),this.#m())}onUnsubscribe(){this.hasListeners()||this.destroy()}shouldFetchOnReconnect(){return d(this.#s,this.options,this.options.refetchOnReconnect)}shouldFetchOnWindowFocus(){return d(this.#s,this.options,this.options.refetchOnWindowFocus)}destroy(){this.listeners=new Set,this.#v(),this.#b(),this.#s.removeObserver(this)}setOptions(e){let t=this.options,r=this.#s;if(this.options=this.#e.defaultQueryOptions(e),void 0!==this.options.enabled&&"boolean"!=typeof this.options.enabled&&"function"!=typeof this.options.enabled&&"boolean"!=typeof(0,u.resolveEnabled)(this.options.enabled,this.#s))throw Error("Expected enabled to be a boolean or a callback that returns a boolean");this.#S(),this.#s.setOptions(this.options),t._defaulted&&!(0,u.shallowEqualObjects)(this.options,t)&&this.#e.getQueryCache().notify({type:"observerOptionsUpdated",query:this.#s,observer:this});let s=this.hasListeners();s&&y(this.#s,r,this.options,t)&&this.#p(),this.updateResult(),s&&(this.#s!==r||(0,u.resolveEnabled)(this.options.enabled,this.#s)!==(0,u.resolveEnabled)(t.enabled,this.#s)||(0,u.resolveStaleTime)(this.options.staleTime,this.#s)!==(0,u.resolveStaleTime)(t.staleTime,this.#s))&&this.#R();let i=this.#g();s&&(this.#s!==r||(0,u.resolveEnabled)(this.options.enabled,this.#s)!==(0,u.resolveEnabled)(t.enabled,this.#s)||i!==this.#y)&&this.#w(i)}getOptimisticResult(e){var t,r;let s=this.#e.getQueryCache().build(this.#e,e),i=this.createResult(s,e);return t=this,r=i,(0,u.shallowEqualObjects)(t.getCurrentResult(),r)||(this.#n=i,this.#o=this.options,this.#a=this.#s.state),i}getCurrentResult(){return this.#n}trackResult(e,t){return new Proxy(e,{get:(e,r)=>(this.trackProp(r),t?.(r),"promise"===r&&(this.trackProp("data"),this.options.experimental_prefetchInRender||"pending"!==this.#r.status||this.#r.reject(Error("experimental_prefetchInRender feature flag is not enabled"))),Reflect.get(e,r))})}trackProp(e){this.#f.add(e)}getCurrentQuery(){return this.#s}refetch({...e}={}){return this.fetch({...e})}fetchOptimistic(e){let t=this.#e.defaultQueryOptions(e),r=this.#e.getQueryCache().build(this.#e,t);return r.fetch().then(()=>this.createResult(r,t))}fetch(e){return this.#p({...e,cancelRefetch:e.cancelRefetch??!0}).then(()=>(this.updateResult(),this.#n))}#p(e){this.#S();let t=this.#s.fetch(this.options,e);return e?.throwOnError||(t=t.catch(u.noop)),t}#R(){this.#v();let e=(0,u.resolveStaleTime)(this.options.staleTime,this.#s);if(u.isServer||this.#n.isStale||!(0,u.isValidTimeout)(e))return;let t=(0,u.timeUntilStale)(this.#n.dataUpdatedAt,e);this.#h=c.timeoutManager.setTimeout(()=>{this.#n.isStale||this.updateResult()},t+1)}#g(){return("function"==typeof this.options.refetchInterval?this.options.refetchInterval(this.#s):this.options.refetchInterval)??!1}#w(e){this.#b(),this.#y=e,!u.isServer&&!1!==(0,u.resolveEnabled)(this.options.enabled,this.#s)&&(0,u.isValidTimeout)(this.#y)&&0!==this.#y&&(this.#d=c.timeoutManager.setInterval(()=>{(this.options.refetchIntervalInBackground||s.focusManager.isFocused())&&this.#p()},this.#y))}#m(){this.#R(),this.#w(this.#g())}#v(){this.#h&&(c.timeoutManager.clearTimeout(this.#h),this.#h=void 0)}#b(){this.#d&&(c.timeoutManager.clearInterval(this.#d),this.#d=void 0)}createResult(e,t){let r,s=this.#s,i=this.options,a=this.#n,c=this.#a,l=this.#o,d=e!==s?e.state:this.#i,{state:p}=e,m={...p},v=!1;if(t._optimisticResults){let r=this.hasListeners(),a=!r&&h(e,t),o=r&&y(e,s,t,i);(a||o)&&(m={...m,...(0,n.fetchState)(p.data,e.options)}),"isRestoring"===t._optimisticResults&&(m.fetchStatus="idle")}let{error:b,errorUpdatedAt:S,status:R}=m;r=m.data;let g=!1;if(void 0!==t.placeholderData&&void 0===r&&"pending"===R){let e;a?.isPlaceholderData&&t.placeholderData===l?.placeholderData?(e=a.data,g=!0):e="function"==typeof t.placeholderData?t.placeholderData(this.#l?.state.data,this.#l):t.placeholderData,void 0!==e&&(R="success",r=(0,u.replaceData)(a?.data,e,t),v=!0)}if(t.select&&void 0!==r&&!g)if(a&&r===c?.data&&t.select===this.#u)r=this.#c;else try{this.#u=t.select,r=t.select(r),r=(0,u.replaceData)(a?.data,r,t),this.#c=r,this.#t=null}catch(e){this.#t=e}this.#t&&(b=this.#t,r=this.#c,S=Date.now(),R="error");let w="fetching"===m.fetchStatus,Q="pending"===R,E="error"===R,F=Q&&w,T=void 0!==r,q={status:R,fetchStatus:m.fetchStatus,isPending:Q,isSuccess:"success"===R,isError:E,isInitialLoading:F,isLoading:F,data:r,dataUpdatedAt:m.dataUpdatedAt,error:b,errorUpdatedAt:S,failureCount:m.fetchFailureCount,failureReason:m.fetchFailureReason,errorUpdateCount:m.errorUpdateCount,isFetched:m.dataUpdateCount>0||m.errorUpdateCount>0,isFetchedAfterMount:m.dataUpdateCount>d.dataUpdateCount||m.errorUpdateCount>d.errorUpdateCount,isFetching:w,isRefetching:w&&!Q,isLoadingError:E&&!T,isPaused:"paused"===m.fetchStatus,isPlaceholderData:v,isRefetchError:E&&T,isStale:f(e,t),refetch:this.refetch,promise:this.#r,isEnabled:!1!==(0,u.resolveEnabled)(t.enabled,e)};if(this.options.experimental_prefetchInRender){let t=void 0!==q.data,r="error"===q.status&&!t,i=e=>{r?e.reject(q.error):t&&e.resolve(q.data)},n=()=>{i(this.#r=q.promise=(0,o.pendingThenable)())},a=this.#r;switch(a.status){case"pending":e.queryHash===s.queryHash&&i(a);break;case"fulfilled":(r||q.data!==a.value)&&n();break;case"rejected":r&&q.error===a.reason||n()}}return q}updateResult(){let e=this.#n,t=this.createResult(this.#s,this.options);if(this.#a=this.#s.state,this.#o=this.options,void 0!==this.#a.data&&(this.#l=this.#s),(0,u.shallowEqualObjects)(t,e))return;this.#n=t;let r=()=>{if(!e)return!0;let{notifyOnChangeProps:t}=this.options,r="function"==typeof t?t():t;if("all"===r||!r&&!this.#f.size)return!0;let s=new Set(r??this.#f);return this.options.throwOnError&&s.add("error"),Object.keys(this.#n).some(t=>this.#n[t]!==e[t]&&s.has(t))};this.#Q({listeners:r()})}#S(){let e=this.#e.getQueryCache().build(this.#e,this.options);if(e===this.#s)return;let t=this.#s;this.#s=e,this.#i=e.state,this.hasListeners()&&(t?.removeObserver(this),e.addObserver(this))}onQueryUpdate(){this.updateResult(),this.hasListeners()&&this.#m()}#Q(e){i.notifyManager.batch(()=>{e.listeners&&this.listeners.forEach(e=>{e(this.#n)}),this.#e.getQueryCache().notify({query:this.#s,type:"observerResultsUpdated"})})}};function h(e,t){return!1!==(0,u.resolveEnabled)(t.enabled,e)&&void 0===e.state.data&&("error"!==e.state.status||!1!==t.retryOnMount)||void 0!==e.state.data&&d(e,t,t.refetchOnMount)}function d(e,t,r){if(!1!==(0,u.resolveEnabled)(t.enabled,e)&&"static"!==(0,u.resolveStaleTime)(t.staleTime,e)){let s="function"==typeof r?r(e):r;return"always"===s||!1!==s&&f(e,t)}return!1}function y(e,t,r,s){return(e!==t||!1===(0,u.resolveEnabled)(s.enabled,e))&&(!r.suspense||"error"!==e.state.status)&&f(e,r)}function f(e,t){return!1!==(0,u.resolveEnabled)(t.enabled,e)&&e.isStaleByTime((0,u.resolveStaleTime)(t.staleTime,e))}var p=e.i(4),m=e.i(1235);e.i(27493);var v=p.createContext((t=!1,{clearReset:()=>{t=!1},reset:()=>{t=!0},isReset:()=>t})),b=p.createContext(!1);b.Provider;var S=(e,t,r)=>t.fetchOptimistic(e).catch(()=>{r.clearReset()});function R(e,t){return function(e,t,r){let s,n=p.useContext(b),a=p.useContext(v),o=(0,m.useQueryClient)(r),c=o.defaultQueryOptions(e);o.getDefaultOptions().queries?._experimental_beforeQuery?.(c);let l=o.getQueryCache().get(c.queryHash);if(c._optimisticResults=n?"isRestoring":"optimistic",c.suspense){let e=e=>"static"===e?e:Math.max(e??1e3,1e3),t=c.staleTime;c.staleTime="function"==typeof t?(...r)=>e(t(...r)):e(t),"number"==typeof c.gcTime&&(c.gcTime=Math.max(c.gcTime,1e3))}s=l?.state.error&&"function"==typeof c.throwOnError?(0,u.shouldThrowError)(c.throwOnError,[l.state.error,l]):c.throwOnError,(c.suspense||c.experimental_prefetchInRender||s)&&!a.isReset()&&(c.retryOnMount=!1),p.useEffect(()=>{a.clearReset()},[a]);let h=!o.getQueryCache().get(c.queryHash),[d]=p.useState(()=>new t(o,c)),y=d.getOptimisticResult(c),f=!n&&!1!==e.subscribed;if(p.useSyncExternalStore(p.useCallback(e=>{let t=f?d.subscribe(i.notifyManager.batchCalls(e)):u.noop;return d.updateResult(),t},[d,f]),()=>d.getCurrentResult(),()=>d.getCurrentResult()),p.useEffect(()=>{d.setOptions(c)},[c,d]),c?.suspense&&y.isPending)throw S(c,d,a);if((({result:e,errorResetBoundary:t,throwOnError:r,query:s,suspense:i})=>e.isError&&!t.isReset()&&!e.isFetching&&s&&(i&&void 0===e.data||(0,u.shouldThrowError)(r,[e.error,s])))({result:y,errorResetBoundary:a,throwOnError:c.throwOnError,query:l,suspense:c.suspense}))throw y.error;if(o.getDefaultOptions().queries?._experimental_afterQuery?.(c,y),c.experimental_prefetchInRender&&!u.isServer&&y.isLoading&&y.isFetching&&!n){let e=h?S(c,d,a):l?.promise;e?.catch(u.noop).finally(()=>{d.updateResult()})}return c.notifyOnChangeProps?y:d.trackResult(y)}(e,l,t)}e.s(["useQuery",()=>R],45688);var g=e.i(21230),w=a,Q=class extends w.Subscribable{#e;#n=void 0;#E;#F;constructor(e,t){super(),this.#e=e,this.setOptions(t),this.bindMethods(),this.#T()}bindMethods(){this.mutate=this.mutate.bind(this),this.reset=this.reset.bind(this)}setOptions(e){let t=this.options;this.options=this.#e.defaultMutationOptions(e),(0,u.shallowEqualObjects)(this.options,t)||this.#e.getMutationCache().notify({type:"observerOptionsUpdated",mutation:this.#E,observer:this}),t?.mutationKey&&this.options.mutationKey&&(0,u.hashKey)(t.mutationKey)!==(0,u.hashKey)(this.options.mutationKey)?this.reset():this.#E?.state.status==="pending"&&this.#E.setOptions(this.options)}onUnsubscribe(){this.hasListeners()||this.#E?.removeObserver(this)}onMutationUpdate(e){this.#T(),this.#Q(e)}getCurrentResult(){return this.#n}reset(){this.#E?.removeObserver(this),this.#E=void 0,this.#T(),this.#Q()}mutate(e,t){return this.#F=t,this.#E?.removeObserver(this),this.#E=this.#e.getMutationCache().build(this.#e,this.options),this.#E.addObserver(this),this.#E.execute(e)}#T(){let e=this.#E?.state??(0,g.getDefaultState)();this.#n={...e,isPending:"pending"===e.status,isSuccess:"success"===e.status,isError:"error"===e.status,isIdle:"idle"===e.status,mutate:this.mutate,reset:this.reset}}#Q(e){i.notifyManager.batch(()=>{if(this.#F&&this.hasListeners()){let t=this.#n.variables,r=this.#n.context,s={client:this.#e,meta:this.options.meta,mutationKey:this.options.mutationKey};if(e?.type==="success"){try{this.#F.onSuccess?.(e.data,t,r,s)}catch(e){Promise.reject(e)}try{this.#F.onSettled?.(e.data,null,t,r,s)}catch(e){Promise.reject(e)}}else if(e?.type==="error"){try{this.#F.onError?.(e.error,t,r,s)}catch(e){Promise.reject(e)}try{this.#F.onSettled?.(void 0,e.error,t,r,s)}catch(e){Promise.reject(e)}}}this.listeners.forEach(e=>{e(this.#n)})})}};function E(e,t){let r=(0,m.useQueryClient)(t),[s]=p.useState(()=>new Q(r,e));p.useEffect(()=>{s.setOptions(e)},[s,e]);let n=p.useSyncExternalStore(p.useCallback(e=>s.subscribe(i.notifyManager.batchCalls(e)),[s]),()=>s.getCurrentResult(),()=>s.getCurrentResult()),a=p.useCallback((e,t)=>{s.mutate(e,t).catch(u.noop)},[s]);if(n.error&&(0,u.shouldThrowError)(s.options.throwOnError,[n.error]))throw n.error;return{...n,mutate:a,mutateAsync:n.mutate}}e.s(["useMutation",()=>E],71921);let F=r.default.env.NEXT_PUBLIC_API_URL||"http://localhost:3001",T=null,q=null;async function k(){if(T)return T;if(q)return q;q=(async()=>{let e=await fetch(`${F}/api/auth/session-token`);if(!e.ok)throw Error((await e.json().catch(()=>({}))).error||"Failed to fetch session token");let{token:t}=await e.json();return T=t,t})();try{return await q}finally{q=null}}async function O(e,t){let r=await k(),s=new Headers(t?.headers);return s.set("Authorization",`Bearer ${r}`),fetch(e,{...t,headers:s})}class C extends Error{feature;requiredTier;constructor(e,t){super(`Feature locked: ${e}`),this.name="FeatureLockedError",this.feature=e,this.requiredTier=t}}async function M(e,t){let r=await O(e,t);if(403===r.status){let e=await r.json().catch(()=>({}));if("FEATURE_GATED"===e.code)throw new C(e.feature,e.requiredTier)}return r}e.s(["FeatureLockedError",()=>C,"authFetch",()=>O,"gatedFetch",()=>M,"getApiToken",()=>k],88969);let j=r.default.env.NEXT_PUBLIC_WS_URL||"ws://localhost:3001/ws/events";function I(e={}){let{enabled:t=!0,onMessage:r}=e,s=(0,m.useQueryClient)(),i=(0,p.useRef)(null),n=(0,p.useRef)(null),a=(0,p.useRef)(0),o=(0,p.useRef)(1e3),u=(0,p.useRef)(()=>{}),[c,l]=(0,p.useState)(!1),[h,d]=(0,p.useState)(null),y=(0,p.useRef)(r);(0,p.useEffect)(()=>{y.current=r},[r]);let f=(0,p.useCallback)(async()=>{if(t&&i.current?.readyState!==WebSocket.OPEN){n.current&&(clearTimeout(n.current),n.current=null);try{let e=await k(),r=`${j}?token=${encodeURIComponent(e)}`,c=new WebSocket(r);i.current=c,c.onopen=()=>{l(!0),a.current=0,o.current=1e3,console.log("[WebSocket] Connected to memory server")},c.onmessage=e=>{try{let t=JSON.parse(e.data);switch(d({type:t.type,data:t.data,timestamp:t.timestamp||new Date().toISOString()}),y.current?.(t),t.type){case"initial_state":case"consolidation_complete":case"predictive_consolidation":s.invalidateQueries({queryKey:["memories"]}),s.invalidateQueries({queryKey:["stats"]}),s.invalidateQueries({queryKey:["links"]});break;case"memory_created":case"memory_updated":case"memory_deleted":s.invalidateQueries({queryKey:["memories"]}),s.invalidateQueries({queryKey:["stats"]});break;case"decay_tick":case"worker_light_tick":case"worker_medium_tick":break;case"link_discovered":s.invalidateQueries({queryKey:["links"]});break;case"defence_event":s.invalidateQueries({queryKey:["agents"]}),s.invalidateQueries({queryKey:["agent-timeline"]}),s.invalidateQueries({queryKey:["audit-logs"]}),s.invalidateQueries({queryKey:["audit-stats"]});break;case"update_started":case"update_complete":case"update_failed":"update_complete"===t.type&&(s.invalidateQueries({queryKey:["version"]}),s.invalidateQueries({queryKey:["version-check"]}));break;case"server_restarting":console.log("[WebSocket] Server restarting, will reconnect shortly...")}}catch(e){console.error("[WebSocket] Failed to parse message:",e)}},c.onerror=()=>{console.warn("[WebSocket] Connection failed - is the API server running?")},c.onclose=()=>{if(l(!1),console.log("[WebSocket] Disconnected"),t&&a.current<10){let e=o.current;a.current++,o.current=Math.min(2*o.current,3e4),console.log(`[WebSocket] Reconnecting in ${e}ms (attempt ${a.current}/10)...`),n.current=setTimeout(()=>{u.current()},e)}else a.current>=10&&console.error("[WebSocket] Max reconnection attempts reached. Use reconnect() to try again.")}}catch(e){console.error("[WebSocket] Failed to connect:",e)}}},[t,s]);return(0,p.useEffect)(()=>{u.current=f}),(0,p.useEffect)(()=>(t&&f(),()=>{n.current&&clearTimeout(n.current),i.current&&(i.current.close(),i.current=null)}),[t,f]),{isConnected:c,lastEvent:h,reconnect:(0,p.useCallback)(()=>{a.current=0,o.current=1e3,f()},[f])}}e.s(["useMemoryWebSocket",()=>I],94156);let P=r.default.env.NEXT_PUBLIC_API_URL||"http://localhost:3001";async function K(e){let t=new URLSearchParams;e?.project&&t.set("project",e.project),e?.type&&t.set("type",e.type),e?.category&&t.set("category",e.category),e?.limit&&t.set("limit",e.limit.toString()),e?.offset&&t.set("offset",e.offset.toString()),e?.mode&&t.set("mode",e.mode),e?.query&&t.set("query",e.query);let r=await O(`${P}/api/memories?${t}`);if(!r.ok)throw Error("Failed to fetch memories");return r.json()}async function $(e){let t=e?`?project=${e}`:"",r=await O(`${P}/api/stats${t}`);if(!r.ok)throw Error("Failed to fetch stats");return r.json()}async function _(e){let t=e?`?project=${e}`:"",r=await O(`${P}/api/links${t}`);if(!r.ok)throw Error("Failed to fetch links");return r.json()}async function x(){let e=await O(`${P}/api/projects`);if(!e.ok)throw Error("Failed to fetch projects");return e.json()}async function U(e){let t=await O(`${P}/api/memories/${e}/access`,{method:"POST"});if(!t.ok)throw Error("Failed to access memory");return t.json()}async function D(){let e=await O(`${P}/api/consolidate`,{method:"POST"});if(!e.ok)throw Error("Failed to consolidate");return e.json()}function L(e){return R({queryKey:["stats",e],queryFn:()=>$(e),refetchInterval:3e4})}function A(e){return R({queryKey:["links",e],queryFn:()=>_(e),refetchInterval:6e4})}function W(){return R({queryKey:["projects"],queryFn:x,refetchInterval:6e4})}function z(e){let t,r=I();return{...{...t=R({queryKey:["memories",e],queryFn:()=>K(e),refetchInterval:3e4}),data:t.data?.memories,pagination:t.data?.pagination},isConnected:r.isConnected,lastEvent:r.lastEvent}}function B(){let e=(0,m.useQueryClient)();return E({mutationFn:U,onSuccess:()=>{e.invalidateQueries({queryKey:["memories"]}),e.invalidateQueries({queryKey:["stats"]})}})}function N(){let e=(0,m.useQueryClient)();return E({mutationFn:D,onSuccess:()=>{e.invalidateQueries({queryKey:["memories"]}),e.invalidateQueries({queryKey:["stats"]})}})}async function H(){let e=await O(`${P}/api/control/status`);if(!e.ok)throw Error("Failed to fetch control status");return e.json()}async function J(){let e=await O(`${P}/api/control/pause`,{method:"POST"});if(!e.ok)throw Error("Failed to pause");return e.json()}async function V(){let e=await O(`${P}/api/control/resume`,{method:"POST"});if(!e.ok)throw Error("Failed to resume");return e.json()}function X(){return R({queryKey:["control-status"],queryFn:H,refetchInterval:1e4})}function G(){let e=(0,m.useQueryClient)();return E({mutationFn:J,onSuccess:()=>{e.invalidateQueries({queryKey:["control-status"]})}})}function Y(){let e=(0,m.useQueryClient)();return E({mutationFn:V,onSuccess:()=>{e.invalidateQueries({queryKey:["control-status"]})}})}async function Z(){let e=await O(`${P}/api/version`);if(!e.ok)throw Error("Failed to fetch version");return e.json()}function ee(){return R({queryKey:["version"],queryFn:Z,refetchInterval:6e4,staleTime:3e4})}async function et(e){let t=e?`?project=${e}`:"",r=await O(`${P}/api/contradictions${t}`);if(!r.ok)throw Error("Failed to fetch contradictions");return r.json()}function er(e){return R({queryKey:["contradictions",e],queryFn:()=>et(e),staleTime:3e5})}async function es(e){let t=await O(`${P}/api/memories/${e}/boost`,{method:"POST"});if(!t.ok)throw Error("Failed to boost memory");return t.json()}async function ei(e){let t=await O(`${P}/api/memories/${e}/demote`,{method:"POST"});if(!t.ok)throw Error("Failed to demote memory");return t.json()}async function en(e){let t=await O(`${P}/api/memories/${e}/promote`,{method:"POST"});if(!t.ok)throw Error("Failed to promote memory");return t.json()}async function ea(e,t){let r=await O(`${P}/api/memories/${e}`,{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)});if(!r.ok)throw Error("Failed to edit memory");return r.json()}async function eo(e){let t=await O(`${P}/api/memories/${e}`,{method:"DELETE"});if(!t.ok)throw Error("Failed to delete memory");return t.json()}async function eu(e,t){let r=await O(`${P}/api/memories/${e}/quarantine`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({reason:t})});if(!r.ok)throw Error("Failed to quarantine memory");return r.json()}async function ec(){let e=await O(`${P}/api/worker/status`);if(!e.ok)throw Error("Failed to fetch worker status");return e.json()}function el(){let e=(0,m.useQueryClient)();return E({mutationFn:es,onSuccess:()=>{e.invalidateQueries({queryKey:["memories"]}),e.invalidateQueries({queryKey:["stats"]})}})}function eh(){let e=(0,m.useQueryClient)();return E({mutationFn:ei,onSuccess:()=>{e.invalidateQueries({queryKey:["memories"]}),e.invalidateQueries({queryKey:["stats"]})}})}function ed(){let e=(0,m.useQueryClient)();return E({mutationFn:en,onSuccess:()=>{e.invalidateQueries({queryKey:["memories"]}),e.invalidateQueries({queryKey:["stats"]})}})}function ey(){let e=(0,m.useQueryClient)();return E({mutationFn:({id:e,updates:t})=>ea(e,t),onSuccess:()=>{e.invalidateQueries({queryKey:["memories"]}),e.invalidateQueries({queryKey:["stats"]})}})}function ef(){let e=(0,m.useQueryClient)();return E({mutationFn:eo,onSuccess:()=>{e.invalidateQueries({queryKey:["memories"]}),e.invalidateQueries({queryKey:["stats"]}),e.invalidateQueries({queryKey:["links"]})}})}function ep(){let e=(0,m.useQueryClient)();return E({mutationFn:({id:e,reason:t})=>eu(e,t),onSuccess:()=>{e.invalidateQueries({queryKey:["memories"]}),e.invalidateQueries({queryKey:["stats"]})}})}function em(){return R({queryKey:["worker-status"],queryFn:ec,refetchInterval:15e3})}e.s(["useAccessMemory",()=>B,"useBoostMemory",()=>el,"useConsolidate",()=>N,"useContradictions",()=>er,"useControlStatus",()=>X,"useDeleteMemory",()=>ef,"useDemoteMemory",()=>eh,"useEditMemory",()=>ey,"useMemoriesWithRealtime",()=>z,"useMemoryLinks",()=>A,"usePauseMemory",()=>G,"useProjects",()=>W,"usePromoteMemory",()=>ed,"useQuarantineMemory",()=>ep,"useResumeMemory",()=>Y,"useStats",()=>L,"useVersion",()=>ee,"useWorkerStatus",()=>em],88069)},42098,92618,e=>{"use strict";let t;var r=e.i(4);let s=e=>{let t,r=new Set,s=(e,s)=>{let i="function"==typeof e?e(t):e;if(!Object.is(i,t)){let e=t;t=(null!=s?s:"object"!=typeof i||null===i)?i:Object.assign({},t,i),r.forEach(r=>r(t,e))}},i=()=>t,n={setState:s,getState:i,getInitialState:()=>a,subscribe:e=>(r.add(e),()=>r.delete(e))},a=t=e(s,i,n);return n},i=e=>e?s(e):s;e.s(["createStore",()=>i],92618);let n=e=>{let t=i(e),s=e=>(function(e,t=e=>e){let s=r.default.useSyncExternalStore(e.subscribe,r.default.useCallback(()=>t(e.getState()),[e,t]),r.default.useCallback(()=>t(e.getInitialState()),[e,t]));return r.default.useDebugValue(s),s})(t,e);return Object.assign(s,t),s},a=(t=e=>({selectedMemory:null,setSelectedMemory:t=>e({selectedMemory:t}),selectedAuditEntry:null,setSelectedAuditEntry:t=>e({selectedAuditEntry:t}),viewMode:"shield",setViewMode:t=>e({viewMode:t}),typeFilter:null,categoryFilter:null,projectFilter:null,setTypeFilter:t=>e({typeFilter:t}),setCategoryFilter:t=>e({categoryFilter:t}),setProjectFilter:t=>e({projectFilter:t}),recentEvents:[],addEvent:t=>e(e=>({recentEvents:[t,...e.recentEvents].slice(0,50)})),clearEvents:()=>e({recentEvents:[]}),cameraPosition:[0,0,12],setCameraPosition:t=>e({cameraPosition:t}),showLeftSidebar:!0,showRightSidebar:!0,toggleLeftSidebar:()=>e(e=>({showLeftSidebar:!e.showLeftSidebar})),toggleRightSidebar:()=>e(e=>({showRightSidebar:!e.showRightSidebar})),searchQuery:"",setSearchQuery:t=>e({searchQuery:t})}))?n(t):n;e.s(["useDashboardStore",0,a],42098)},33368,e=>{"use strict";let t={architecture:{basePosition:{x:0,y:1.2,z:2.2},spread:1},pattern:{basePosition:{x:0,y:.3,z:-2.2},spread:.9},preference:{basePosition:{x:1.6,y:-.3,z:0},spread:.7},error:{basePosition:{x:-1.6,y:-.3,z:.3},spread:.8},context:{basePosition:{x:0,y:1.8,z:0},spread:1.2},learning:{basePosition:{x:0,y:-.3,z:0},spread:.8},todo:{basePosition:{x:.6,y:.8,z:1.8},spread:.7},note:{basePosition:{x:1.8,y:0,z:-.3},spread:1},relationship:{basePosition:{x:-1.8,y:.3,z:-.3},spread:.9},custom:{basePosition:{x:0,y:0,z:0},spread:1.5}},r={short_term:.6,episodic:0,long_term:-.4};function s(e){let t=43758.5453*Math.sin(12.9898*e);return t-Math.floor(t)}function i(e){let i=t[e.category]||t.custom,n=r[e.type]||0,a=s(e.id),o=s(e.id+1e3),u=s(e.id+2e3),c=i.spread,l=a*Math.PI*2,h=(o-.5)*Math.PI,d=u*c*.7+.3*c,y=d*Math.cos(h)*Math.cos(l),f=d*Math.sin(h)*.6,p=d*Math.cos(h)*Math.sin(l),m=i.basePosition.x+y,v=i.basePosition.y+f,b=i.basePosition.z+p+n,S=.4*e.salience,R=Math.sqrt(m*m+v*v+b*b);if(R>.1){let e=(R+S)/R;m*=e,v*=e,b*=e}let g=Math.sqrt((m/3.2)**2+(v/2.5)**2+(b/3.5)**2);if(g>.95){let e=.95/g;m*=e,v*=e,b*=e}return{x:m,y:v,z:b}}function n(e){if(!e.lastAccessed)return 1;let t=Date.now(),r=new Date(e.lastAccessed).getTime();return Math.pow({short_term:.995,long_term:.9995,episodic:.998}[e.type]||.995,(t-r)/36e5)}e.s(["calculateDecayFactor",()=>n,"calculateMemoryPosition",()=>i])},87353,e=>{"use strict";var t=e.i(22534),r=e.i(45688),s=e.i(71921),i=e.i(1235),n=e.i(88969);let a=t.default.env.NEXT_PUBLIC_API_URL||"http://localhost:3001";async function o(e){let t=new URLSearchParams;e?.startTime&&t.set("startTime",e.startTime),e?.endTime&&t.set("endTime",e.endTime),e?.source&&t.set("source",e.source),e?.firewallResult&&t.set("firewallResult",e.firewallResult),e?.project&&t.set("project",e.project),e?.limit&&t.set("limit",e.limit.toString());let r=await (0,n.authFetch)(`${a}/api/v1/audit?${t}`);if(!r.ok)throw Error("Failed to fetch audit logs");return r.json()}async function u(e,t){let r=new URLSearchParams({timeRange:e});t&&r.set("project",t);let s=await (0,n.authFetch)(`${a}/api/v1/audit/stats?${r}`);if(!s.ok)throw Error("Failed to fetch audit stats");return s.json()}async function c(e="pending",t=50,r){let s=new URLSearchParams({status:e,limit:t.toString()});r&&s.set("project",r);let i=await (0,n.authFetch)(`${a}/api/v1/quarantine?${s}`);if(!i.ok)throw Error("Failed to fetch quarantine");return i.json()}async function l(e){let t=await (0,n.authFetch)(`${a}/api/v1/quarantine/${e}/approve`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({reviewedBy:"dashboard"})});if(!t.ok)throw Error("Failed to approve");return t.json()}async function h(e,t){let r=await (0,n.authFetch)(`${a}/api/v1/quarantine/${e}/reject`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({reviewedBy:"dashboard",notes:t})});if(!r.ok)throw Error("Failed to reject");return r.json()}function d(e){return(0,r.useQuery)({queryKey:["audit-logs",e],queryFn:()=>o(e),refetchInterval:3e4,retry:2})}function y(e="24h",t){return(0,r.useQuery)({queryKey:["audit-stats",e,t],queryFn:()=>u(e,t),refetchInterval:3e4,retry:2})}function f(e="pending",t=50,s){return(0,r.useQuery)({queryKey:["quarantine",e,t,s],queryFn:()=>c(e,t,s),refetchInterval:3e4,retry:2})}function p(){let e=(0,i.useQueryClient)();return(0,s.useMutation)({mutationFn:l,onSuccess:()=>{e.invalidateQueries({queryKey:["quarantine"]}),e.invalidateQueries({queryKey:["audit-stats"]})}})}function m(){let e=(0,i.useQueryClient)();return(0,s.useMutation)({mutationFn:({id:e,notes:t})=>h(e,t),onSuccess:()=>{e.invalidateQueries({queryKey:["quarantine"]}),e.invalidateQueries({queryKey:["audit-stats"]})}})}function v(){return(0,r.useQuery)({queryKey:["defence-config"],queryFn:()=>(0,n.authFetch)(`${a}/api/defence/config`).then(e=>e.json())})}function b(){let e=(0,i.useQueryClient)();return(0,s.useMutation)({mutationFn:e=>(0,n.authFetch)(`${a}/api/defence/config`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({mode:e})}).then(e=>e.json()),onSuccess:()=>{e.invalidateQueries({queryKey:["defence-config"]})}})}e.s(["useApproveQuarantine",()=>p,"useAuditLogs",()=>d,"useAuditStats",()=>y,"useDefenceConfig",()=>v,"useQuarantine",()=>f,"useRejectQuarantine",()=>m,"useSetDefenceMode",()=>b])}]);
@@ -5,7 +5,7 @@
5
5
  "scripts": {
6
6
  "predev": "node scripts/ensure-api.mjs",
7
7
  "dev": "next dev -p 3030",
8
- "build": "next build",
8
+ "build": "next build && node scripts/copy-static.mjs",
9
9
  "start": "next start -p 3030",
10
10
  "lint": "eslint"
11
11
  },
@@ -1 +1 @@
1
- {"version":3,"file":"visualization-server.d.ts","sourceRoot":"","sources":["../../src/api/visualization-server.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AA+DH;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CA+lE9D"}
1
+ {"version":3,"file":"visualization-server.d.ts","sourceRoot":"","sources":["../../src/api/visualization-server.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAqGH;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CA62E9D"}
@@ -31,7 +31,42 @@ import { getCloudConfig, setCloudConfig, readRawConfig, getTrustedSkills, addTru
31
31
  import { getQueueStats } from '../cloud/sync-queue.js';
32
32
  import { scanSkill, scanSkillContent, discoverSkillFiles } from '../defence/skill-scanner/index.js';
33
33
  import { getIronDomeStatus, activateIronDome, deactivateIronDome, scanForInjection } from '../defence/iron-dome/index.js';
34
+ import { getLicense, activateLicense, deactivateLicense } from '../license/store.js';
35
+ import { listFeatures, requireFeature, FeatureGatedError } from '../license/gate.js';
36
+ import { validateOnceNow } from '../license/validate.js';
34
37
  const PORT = process.env.PORT || 3001;
38
+ /**
39
+ * In-memory counters for FEATURE_GATED (403) responses per feature.
40
+ * Lightweight telemetry to detect noisy free-tier clients hammering gated endpoints.
41
+ */
42
+ const gatedCounters = {};
43
+ /**
44
+ * Express middleware that gates an endpoint behind a Pro/Team licence feature.
45
+ * Wraps requireFeature() — one source of truth for tier checks.
46
+ * Returns a structured 403 (FeatureGatedResponse) if the feature isn't enabled.
47
+ */
48
+ function requireProFeature(feature) {
49
+ return (_req, res, next) => {
50
+ try {
51
+ requireFeature(feature);
52
+ next();
53
+ }
54
+ catch (err) {
55
+ if (err instanceof FeatureGatedError) {
56
+ gatedCounters[err.feature] = (gatedCounters[err.feature] || 0) + 1;
57
+ const body = {
58
+ error: 'Feature requires upgrade',
59
+ code: 'FEATURE_GATED',
60
+ feature: err.feature,
61
+ requiredTier: err.requiredTier,
62
+ upgradeUrl: 'https://shieldcortex.ai/pricing',
63
+ };
64
+ return res.status(403).json(body);
65
+ }
66
+ next(err);
67
+ }
68
+ };
69
+ }
35
70
  // Track connected WebSocket clients
36
71
  const clients = new Set();
37
72
  /**
@@ -101,6 +136,11 @@ export function startVisualizationServer(dbPath) {
101
136
  const version = getRunningVersion();
102
137
  res.json({ status: 'ok', timestamp: new Date().toISOString(), version });
103
138
  });
139
+ // Feature-gated response counters (detect noisy free-tier clients)
140
+ app.get('/api/gated-stats', (_req, res) => {
141
+ const total = Object.values(gatedCounters).reduce((sum, n) => sum + n, 0);
142
+ res.json({ total, byFeature: { ...gatedCounters } });
143
+ });
104
144
  // Get all memories with filters and pagination
105
145
  app.get('/api/memories', async (req, res) => {
106
146
  try {
@@ -1740,6 +1780,272 @@ export function startVisualizationServer(dbPath) {
1740
1780
  }
1741
1781
  });
1742
1782
  // ============================================
1783
+ // LICENSE
1784
+ // ============================================
1785
+ app.get('/api/license/status', (_req, res) => {
1786
+ try {
1787
+ const info = getLicense();
1788
+ const features = listFeatures();
1789
+ res.json({
1790
+ tier: info.tier,
1791
+ valid: info.valid,
1792
+ email: info.email,
1793
+ expiresAt: info.expiresAt?.toISOString() ?? null,
1794
+ daysUntilExpiry: info.daysUntilExpiry,
1795
+ teamId: info.teamId,
1796
+ features,
1797
+ });
1798
+ }
1799
+ catch (error) {
1800
+ res.status(500).json({ error: error.message });
1801
+ }
1802
+ });
1803
+ app.post('/api/license/activate', async (req, res) => {
1804
+ try {
1805
+ const { key } = req.body;
1806
+ if (!key || typeof key !== 'string') {
1807
+ return res.status(400).json({ error: 'License key is required' });
1808
+ }
1809
+ const info = activateLicense(key.trim());
1810
+ // Fire online validation (non-blocking but wait briefly for immediate feedback)
1811
+ const validationStatus = await validateOnceNow();
1812
+ const features = listFeatures();
1813
+ res.json({
1814
+ success: true,
1815
+ tier: info.tier,
1816
+ valid: info.valid,
1817
+ email: info.email,
1818
+ expiresAt: info.expiresAt?.toISOString() ?? null,
1819
+ daysUntilExpiry: info.daysUntilExpiry,
1820
+ validationStatus,
1821
+ features,
1822
+ });
1823
+ }
1824
+ catch (error) {
1825
+ res.status(400).json({ error: error.message });
1826
+ }
1827
+ });
1828
+ app.post('/api/license/deactivate', (_req, res) => {
1829
+ try {
1830
+ deactivateLicense();
1831
+ const features = listFeatures();
1832
+ res.json({
1833
+ success: true,
1834
+ tier: 'free',
1835
+ features,
1836
+ });
1837
+ }
1838
+ catch (error) {
1839
+ res.status(500).json({ error: error.message });
1840
+ }
1841
+ });
1842
+ // ============================================
1843
+ // PRO FEATURE ENDPOINTS
1844
+ // ============================================
1845
+ // ── Custom Firewall Rules ────────────────────
1846
+ app.get('/api/firewall-rules', requireProFeature('custom_firewall_rules'), (_req, res) => {
1847
+ try {
1848
+ const { listFirewallRules } = require('../defence/custom-rules/store.js');
1849
+ const rules = listFirewallRules();
1850
+ res.json({ rules, total: rules.length });
1851
+ }
1852
+ catch (error) {
1853
+ res.status(500).json({ error: error.message });
1854
+ }
1855
+ });
1856
+ app.post('/api/firewall-rules', requireProFeature('custom_firewall_rules'), (req, res) => {
1857
+ try {
1858
+ const { createFirewallRule } = require('../defence/custom-rules/store.js');
1859
+ const { name, priority, condition_type, condition_value, action } = req.body;
1860
+ if (!name || !condition_type || !condition_value || !action) {
1861
+ return res.status(400).json({ error: 'name, condition_type, condition_value, and action are required' });
1862
+ }
1863
+ const rule = createFirewallRule({ name, priority: priority ?? 100, condition_type, condition_value, action });
1864
+ res.status(201).json(rule);
1865
+ }
1866
+ catch (error) {
1867
+ const msg = error.message;
1868
+ const status = msg.includes('Maximum') ? 400 : 500;
1869
+ res.status(status).json({ error: msg });
1870
+ }
1871
+ });
1872
+ app.patch('/api/firewall-rules/:id', requireProFeature('custom_firewall_rules'), (req, res) => {
1873
+ try {
1874
+ const { updateFirewallRule } = require('../defence/custom-rules/store.js');
1875
+ const rule = updateFirewallRule(Number(req.params.id), req.body);
1876
+ if (!rule)
1877
+ return res.status(404).json({ error: 'Rule not found' });
1878
+ res.json(rule);
1879
+ }
1880
+ catch (error) {
1881
+ res.status(500).json({ error: error.message });
1882
+ }
1883
+ });
1884
+ app.delete('/api/firewall-rules/:id', requireProFeature('custom_firewall_rules'), (req, res) => {
1885
+ try {
1886
+ const { deleteFirewallRule } = require('../defence/custom-rules/store.js');
1887
+ const deleted = deleteFirewallRule(Number(req.params.id));
1888
+ if (!deleted)
1889
+ return res.status(404).json({ error: 'Rule not found' });
1890
+ res.json({ success: true, id: Number(req.params.id) });
1891
+ }
1892
+ catch (error) {
1893
+ res.status(500).json({ error: error.message });
1894
+ }
1895
+ });
1896
+ // ── Custom Injection Patterns ────────────────
1897
+ app.get('/api/patterns', requireProFeature('custom_injection_patterns'), (_req, res) => {
1898
+ try {
1899
+ const { listCustomPatterns } = require('../defence/custom-patterns/store.js');
1900
+ const patterns = listCustomPatterns();
1901
+ res.json({ patterns, total: patterns.length });
1902
+ }
1903
+ catch (error) {
1904
+ res.status(500).json({ error: error.message });
1905
+ }
1906
+ });
1907
+ app.post('/api/patterns', requireProFeature('custom_injection_patterns'), (req, res) => {
1908
+ try {
1909
+ const { createCustomPattern, validateRegex } = require('../defence/custom-patterns/store.js');
1910
+ const { name, category, severity, regex, description } = req.body;
1911
+ if (!name || !regex) {
1912
+ return res.status(400).json({ error: 'name and regex are required' });
1913
+ }
1914
+ // Validate regex safety before creating
1915
+ const validation = validateRegex(regex);
1916
+ if (!validation.valid) {
1917
+ return res.status(400).json({ error: validation.error });
1918
+ }
1919
+ const pattern = createCustomPattern({
1920
+ name,
1921
+ category: category || 'custom',
1922
+ severity: severity || 'medium',
1923
+ regex,
1924
+ description,
1925
+ });
1926
+ res.status(201).json(pattern);
1927
+ }
1928
+ catch (error) {
1929
+ const msg = error.message;
1930
+ const status = msg.includes('Maximum') || msg.includes('Invalid') || msg.includes('rejected') ? 400 : 500;
1931
+ res.status(status).json({ error: msg });
1932
+ }
1933
+ });
1934
+ app.delete('/api/patterns/:id', requireProFeature('custom_injection_patterns'), (req, res) => {
1935
+ try {
1936
+ const { deleteCustomPattern } = require('../defence/custom-patterns/store.js');
1937
+ const deleted = deleteCustomPattern(Number(req.params.id));
1938
+ if (!deleted)
1939
+ return res.status(404).json({ error: 'Pattern not found' });
1940
+ res.json({ success: true, id: Number(req.params.id) });
1941
+ }
1942
+ catch (error) {
1943
+ res.status(500).json({ error: error.message });
1944
+ }
1945
+ });
1946
+ app.post('/api/patterns/:id/test', requireProFeature('custom_injection_patterns'), (req, res) => {
1947
+ try {
1948
+ const { testPattern } = require('../defence/custom-patterns/store.js');
1949
+ const { text } = req.body;
1950
+ if (!text)
1951
+ return res.status(400).json({ error: 'text is required' });
1952
+ const result = testPattern(Number(req.params.id), text);
1953
+ res.json(result);
1954
+ }
1955
+ catch (error) {
1956
+ res.status(500).json({ error: error.message });
1957
+ }
1958
+ });
1959
+ // ── Custom Iron Dome Policies ────────────────
1960
+ app.get('/api/iron-dome/policies', requireProFeature('custom_iron_dome_policies'), (_req, res) => {
1961
+ try {
1962
+ const { listIronDomePolicies } = require('../defence/iron-dome/custom-policies.js');
1963
+ const policies = listIronDomePolicies();
1964
+ res.json({ policies, total: policies.length });
1965
+ }
1966
+ catch (error) {
1967
+ res.status(500).json({ error: error.message });
1968
+ }
1969
+ });
1970
+ app.post('/api/iron-dome/policies', requireProFeature('custom_iron_dome_policies'), (req, res) => {
1971
+ try {
1972
+ const { createIronDomePolicy } = require('../defence/iron-dome/custom-policies.js');
1973
+ const { name, description, config } = req.body;
1974
+ if (!name)
1975
+ return res.status(400).json({ error: 'name is required' });
1976
+ const policy = createIronDomePolicy({ name, description, config: config || {} });
1977
+ res.status(201).json(policy);
1978
+ }
1979
+ catch (error) {
1980
+ const msg = error.message;
1981
+ const status = msg.includes('Maximum') ? 400 : 500;
1982
+ res.status(status).json({ error: msg });
1983
+ }
1984
+ });
1985
+ app.delete('/api/iron-dome/policies/:id', requireProFeature('custom_iron_dome_policies'), (req, res) => {
1986
+ try {
1987
+ const { deleteIronDomePolicy } = require('../defence/iron-dome/custom-policies.js');
1988
+ const deleted = deleteIronDomePolicy(Number(req.params.id));
1989
+ if (!deleted)
1990
+ return res.status(404).json({ error: 'Policy not found' });
1991
+ res.json({ success: true, id: Number(req.params.id) });
1992
+ }
1993
+ catch (error) {
1994
+ res.status(500).json({ error: error.message });
1995
+ }
1996
+ });
1997
+ app.put('/api/iron-dome/policies/:id/activate', requireProFeature('custom_iron_dome_policies'), (req, res) => {
1998
+ try {
1999
+ const { activateIronDomePolicy } = require('../defence/iron-dome/custom-policies.js');
2000
+ const policy = activateIronDomePolicy(Number(req.params.id));
2001
+ if (!policy)
2002
+ return res.status(404).json({ error: 'Policy not found' });
2003
+ res.json(policy);
2004
+ }
2005
+ catch (error) {
2006
+ res.status(500).json({ error: error.message });
2007
+ }
2008
+ });
2009
+ // ── Audit Export ─────────────────────────────
2010
+ app.get('/api/audit/export', requireProFeature('audit_export'), (req, res) => {
2011
+ try {
2012
+ const { exportAuditJSON, exportAuditCSV } = require('../defence/audit/export.js');
2013
+ const format = req.query.format || 'json';
2014
+ const startTime = req.query.startTime;
2015
+ const endTime = req.query.endTime;
2016
+ if (format === 'csv') {
2017
+ const csv = exportAuditCSV(startTime, endTime);
2018
+ res.setHeader('Content-Type', 'text/csv');
2019
+ res.setHeader('Content-Disposition', `attachment; filename="shieldcortex-audit-${Date.now()}.csv"`);
2020
+ res.send(csv);
2021
+ }
2022
+ else {
2023
+ const json = exportAuditJSON(startTime, endTime);
2024
+ res.setHeader('Content-Type', 'application/json');
2025
+ res.setHeader('Content-Disposition', `attachment; filename="shieldcortex-audit-${Date.now()}.json"`);
2026
+ res.send(json);
2027
+ }
2028
+ }
2029
+ catch (error) {
2030
+ res.status(500).json({ error: error.message });
2031
+ }
2032
+ });
2033
+ // ── Deep Skill Scanner ───────────────────────
2034
+ app.post('/api/skills/deep-scan', requireProFeature('skill_scanner_deep'), async (req, res) => {
2035
+ try {
2036
+ const { runDeepScan } = require('../defence/skill-scanner/deep-scan.js');
2037
+ const { files } = req.body;
2038
+ if (!files || !Array.isArray(files) || files.length === 0) {
2039
+ return res.status(400).json({ error: 'files array is required (each with name and content)' });
2040
+ }
2041
+ const result = await runDeepScan(files);
2042
+ res.json(result);
2043
+ }
2044
+ catch (error) {
2045
+ res.status(500).json({ error: error.message });
2046
+ }
2047
+ });
2048
+ // ============================================
1743
2049
  // WEBSOCKET SERVER
1744
2050
  // ============================================
1745
2051
  const wss = new WebSocketServer({ server, path: '/ws/events' });