@i4ctime/q-ring 0.11.7 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,630 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ PACKAGE_VERSION,
4
+ checkDecay,
5
+ collapseEnvironment,
6
+ detectAnomalies,
7
+ getPolicySummary,
8
+ listApprovals,
9
+ listEntanglements,
10
+ listHooks,
11
+ listMemory,
12
+ listSecrets,
13
+ queryAudit,
14
+ readProjectConfig,
15
+ tunnelList
16
+ } from "./chunk-YWDKAZWS.js";
17
+
18
+ // src/core/dashboard.ts
19
+ import { createServer } from "http";
20
+ import { randomBytes, timingSafeEqual } from "crypto";
21
+
22
+ // src/core/dashboard-client.ts
23
+ var DASHBOARD_CLIENT = '"use strict";(()=>{var G,g,we,et,N,ge,Ce,Se,se,W,L,Me,le,ae,oe,tt,O={},Y=[],nt=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i,Q=Array.isArray;function R(t,e){for(var n in e)t[n]=e[n];return t}function re(t){t&&t.parentNode&&t.parentNode.removeChild(t)}function ce(t,e,n){var s,o,a,l={};for(a in e)a=="key"?s=e[a]:a=="ref"?o=e[a]:l[a]=e[a];if(arguments.length>2&&(l.children=arguments.length>3?G.call(arguments,2):n),typeof t=="function"&&t.defaultProps!=null)for(a in t.defaultProps)l[a]===void 0&&(l[a]=t.defaultProps[a]);return z(t,l,s,o,null)}function z(t,e,n,s,o){var a={type:t,props:e,key:n,ref:s,__k:null,__:null,__b:0,__e:null,__c:null,constructor:void 0,__v:o==null?++we:o,__i:-1,__u:0};return o==null&&g.vnode!=null&&g.vnode(a),a}function X(t){return t.children}function K(t,e){this.props=t,this.context=e}function D(t,e){if(e==null)return t.__?D(t.__,t.__i+1):null;for(var n;e<t.__k.length;e++)if((n=t.__k[e])!=null&&n.__e!=null)return n.__e;return typeof t.type=="function"?D(t):null}function st(t){if(t.__P&&t.__d){var e=t.__v,n=e.__e,s=[],o=[],a=R({},e);a.__v=e.__v+1,g.vnode&&g.vnode(a),de(t.__P,a,e,t.__n,t.__P.namespaceURI,32&e.__u?[n]:null,s,n==null?D(e):n,!!(32&e.__u),o),a.__v=e.__v,a.__.__k[a.__i]=a,Re(s,a,o),e.__e=e.__=null,a.__e!=n&&Ae(a)}}function Ae(t){if((t=t.__)!=null&&t.__c!=null)return t.__e=t.__c.base=null,t.__k.some(function(e){if(e!=null&&e.__e!=null)return t.__e=t.__c.base=e.__e}),Ae(t)}function ke(t){(!t.__d&&(t.__d=!0)&&N.push(t)&&!J.__r++||ge!=g.debounceRendering)&&((ge=g.debounceRendering)||Ce)(J)}function J(){try{for(var t,e=1;N.length;)N.length>e&&N.sort(Se),t=N.shift(),e=N.length,st(t)}finally{N.length=J.__r=0}}function Ee(t,e,n,s,o,a,l,d,_,c,i){var r,p,v,f,C,k,y,h=s&&s.__k||Y,$=e.length;for(_=at(n,e,h,_,$),r=0;r<$;r++)(v=n.__k[r])!=null&&(p=v.__i!=-1&&h[v.__i]||O,v.__i=r,k=de(t,v,p,o,a,l,d,_,c,i),f=v.__e,v.ref&&p.ref!=v.ref&&(p.ref&&ue(p.ref,null,v),i.push(v.ref,v.__c||f,v)),C==null&&f!=null&&(C=f),(y=!!(4&v.__u))||p.__k===v.__k?(_=Pe(v,_,t,y),y&&p.__e&&(p.__e=null)):typeof v.type=="function"&&k!==void 0?_=k:f&&(_=f.nextSibling),v.__u&=-7);return n.__e=C,_}function at(t,e,n,s,o){var a,l,d,_,c,i=n.length,r=i,p=0;for(t.__k=new Array(o),a=0;a<o;a++)(l=e[a])!=null&&typeof l!="boolean"&&typeof l!="function"?(typeof l=="string"||typeof l=="number"||typeof l=="bigint"||l.constructor==String?l=t.__k[a]=z(null,l,null,null,null):Q(l)?l=t.__k[a]=z(X,{children:l},null,null,null):l.constructor===void 0&&l.__b>0?l=t.__k[a]=z(l.type,l.props,l.key,l.ref?l.ref:null,l.__v):t.__k[a]=l,_=a+p,l.__=t,l.__b=t.__b+1,d=null,(c=l.__i=ot(l,n,_,r))!=-1&&(r--,(d=n[c])&&(d.__u|=2)),d==null||d.__v==null?(c==-1&&(o>i?p--:o<i&&p++),typeof l.type!="function"&&(l.__u|=4)):c!=_&&(c==_-1?p--:c==_+1?p++:(c>_?p--:p++,l.__u|=4))):t.__k[a]=null;if(r)for(a=0;a<i;a++)(d=n[a])!=null&&(2&d.__u)==0&&(d.__e==s&&(s=D(d)),Ne(d,d));return s}function Pe(t,e,n,s){var o,a;if(typeof t.type=="function"){for(o=t.__k,a=0;o&&a<o.length;a++)o[a]&&(o[a].__=t,e=Pe(o[a],e,n,s));return e}t.__e!=e&&(s&&(e&&t.type&&!e.parentNode&&(e=D(t)),n.insertBefore(t.__e,e||null)),e=t.__e);do e=e&&e.nextSibling;while(e!=null&&e.nodeType==8);return e}function ot(t,e,n,s){var o,a,l,d=t.key,_=t.type,c=e[n],i=c!=null&&(2&c.__u)==0;if(c===null&&d==null||i&&d==c.key&&_==c.type)return n;if(s>(i?1:0)){for(o=n-1,a=n+1;o>=0||a<e.length;)if((c=e[l=o>=0?o--:a++])!=null&&(2&c.__u)==0&&d==c.key&&_==c.type)return l}return-1}function be(t,e,n){e[0]=="-"?t.setProperty(e,n==null?"":n):t[e]=n==null?"":typeof n!="number"||nt.test(e)?n:n+"px"}function V(t,e,n,s,o){var a,l;e:if(e=="style")if(typeof n=="string")t.style.cssText=n;else{if(typeof s=="string"&&(t.style.cssText=s=""),s)for(e in s)n&&e in n||be(t.style,e,"");if(n)for(e in n)s&&n[e]==s[e]||be(t.style,e,n[e])}else if(e[0]=="o"&&e[1]=="n")a=e!=(e=e.replace(Me,"$1")),l=e.toLowerCase(),e=l in t||e=="onFocusOut"||e=="onFocusIn"?l.slice(2):e.slice(2),t.l||(t.l={}),t.l[e+a]=n,n?s?n[L]=s[L]:(n[L]=le,t.addEventListener(e,a?oe:ae,a)):t.removeEventListener(e,a?oe:ae,a);else{if(o=="http://www.w3.org/2000/svg")e=e.replace(/xlink(H|:h)/,"h").replace(/sName$/,"s");else if(e!="width"&&e!="height"&&e!="href"&&e!="list"&&e!="form"&&e!="tabIndex"&&e!="download"&&e!="rowSpan"&&e!="colSpan"&&e!="role"&&e!="popover"&&e in t)try{t[e]=n==null?"":n;break e}catch{}typeof n=="function"||(n==null||n===!1&&e[4]!="-"?t.removeAttribute(e):t.setAttribute(e,e=="popover"&&n==1?"":n))}}function xe(t){return function(e){if(this.l){var n=this.l[e.type+t];if(e[W]==null)e[W]=le++;else if(e[W]<n[L])return;return n(g.event?g.event(e):e)}}}function de(t,e,n,s,o,a,l,d,_,c){var i,r,p,v,f,C,k,y,h,$,b,T,F,B,ne,P=e.type;if(e.constructor!==void 0)return null;128&n.__u&&(_=!!(32&n.__u),a=[d=e.__e=n.__e]),(i=g.__b)&&i(e);e:if(typeof P=="function")try{if(y=e.props,h=P.prototype&&P.prototype.render,$=(i=P.contextType)&&s[i.__c],b=i?$?$.props.value:i.__:s,n.__c?k=(r=e.__c=n.__c).__=r.__E:(h?e.__c=r=new P(y,b):(e.__c=r=new K(y,b),r.constructor=P,r.render=lt),$&&$.sub(r),r.state||(r.state={}),r.__n=s,p=r.__d=!0,r.__h=[],r._sb=[]),h&&r.__s==null&&(r.__s=r.state),h&&P.getDerivedStateFromProps!=null&&(r.__s==r.state&&(r.__s=R({},r.__s)),R(r.__s,P.getDerivedStateFromProps(y,r.__s))),v=r.props,f=r.state,r.__v=e,p)h&&P.getDerivedStateFromProps==null&&r.componentWillMount!=null&&r.componentWillMount(),h&&r.componentDidMount!=null&&r.__h.push(r.componentDidMount);else{if(h&&P.getDerivedStateFromProps==null&&y!==v&&r.componentWillReceiveProps!=null&&r.componentWillReceiveProps(y,b),e.__v==n.__v||!r.__e&&r.shouldComponentUpdate!=null&&r.shouldComponentUpdate(y,r.__s,b)===!1){e.__v!=n.__v&&(r.props=y,r.state=r.__s,r.__d=!1),e.__e=n.__e,e.__k=n.__k,e.__k.some(function(H){H&&(H.__=e)}),Y.push.apply(r.__h,r._sb),r._sb=[],r.__h.length&&l.push(r);break e}r.componentWillUpdate!=null&&r.componentWillUpdate(y,r.__s,b),h&&r.componentDidUpdate!=null&&r.__h.push(function(){r.componentDidUpdate(v,f,C)})}if(r.context=b,r.props=y,r.__P=t,r.__e=!1,T=g.__r,F=0,h)r.state=r.__s,r.__d=!1,T&&T(e),i=r.render(r.props,r.state,r.context),Y.push.apply(r.__h,r._sb),r._sb=[];else do r.__d=!1,T&&T(e),i=r.render(r.props,r.state,r.context),r.state=r.__s;while(r.__d&&++F<25);r.state=r.__s,r.getChildContext!=null&&(s=R(R({},s),r.getChildContext())),h&&!p&&r.getSnapshotBeforeUpdate!=null&&(C=r.getSnapshotBeforeUpdate(v,f)),B=i!=null&&i.type===X&&i.key==null?Te(i.props.children):i,d=Ee(t,Q(B)?B:[B],e,n,s,o,a,l,d,_,c),r.base=e.__e,e.__u&=-161,r.__h.length&&l.push(r),k&&(r.__E=r.__=null)}catch(H){if(e.__v=null,_||a!=null)if(H.then){for(e.__u|=_?160:128;d&&d.nodeType==8&&d.nextSibling;)d=d.nextSibling;a[a.indexOf(d)]=null,e.__e=d}else{for(ne=a.length;ne--;)re(a[ne]);ie(e)}else e.__e=n.__e,e.__k=n.__k,H.then||ie(e);g.__e(H,e,n)}else a==null&&e.__v==n.__v?(e.__k=n.__k,e.__e=n.__e):d=e.__e=it(n.__e,e,n,s,o,a,l,_,c);return(i=g.diffed)&&i(e),128&e.__u?void 0:d}function ie(t){t&&(t.__c&&(t.__c.__e=!0),t.__k&&t.__k.some(ie))}function Re(t,e,n){for(var s=0;s<n.length;s++)ue(n[s],n[++s],n[++s]);g.__c&&g.__c(e,t),t.some(function(o){try{t=o.__h,o.__h=[],t.some(function(a){a.call(o)})}catch(a){g.__e(a,o.__v)}})}function Te(t){return typeof t!="object"||t==null||t.__b>0?t:Q(t)?t.map(Te):t.constructor!==void 0?null:R({},t)}function it(t,e,n,s,o,a,l,d,_){var c,i,r,p,v,f,C,k=n.props||O,y=e.props,h=e.type;if(h=="svg"?o="http://www.w3.org/2000/svg":h=="math"?o="http://www.w3.org/1998/Math/MathML":o||(o="http://www.w3.org/1999/xhtml"),a!=null){for(c=0;c<a.length;c++)if((v=a[c])&&"setAttribute"in v==!!h&&(h?v.localName==h:v.nodeType==3)){t=v,a[c]=null;break}}if(t==null){if(h==null)return document.createTextNode(y);t=document.createElementNS(o,h,y.is&&y),d&&(g.__m&&g.__m(e,a),d=!1),a=null}if(h==null)k===y||d&&t.data==y||(t.data=y);else{if(a=h=="textarea"&&y.defaultValue!=null?null:a&&G.call(t.childNodes),!d&&a!=null)for(k={},c=0;c<t.attributes.length;c++)k[(v=t.attributes[c]).name]=v.value;for(c in k)v=k[c],c=="dangerouslySetInnerHTML"?r=v:c=="children"||c in y||c=="value"&&"defaultValue"in y||c=="checked"&&"defaultChecked"in y||V(t,c,null,v,o);for(c in y)v=y[c],c=="children"?p=v:c=="dangerouslySetInnerHTML"?i=v:c=="value"?f=v:c=="checked"?C=v:d&&typeof v!="function"||k[c]===v||V(t,c,v,k[c],o);if(i)d||r&&(i.__html==r.__html||i.__html==t.innerHTML)||(t.innerHTML=i.__html),e.__k=[];else if(r&&(t.innerHTML=""),Ee(e.type=="template"?t.content:t,Q(p)?p:[p],e,n,s,h=="foreignObject"?"http://www.w3.org/1999/xhtml":o,a,l,a?a[0]:n.__k&&D(n,0),d,_),a!=null)for(c=a.length;c--;)re(a[c]);d&&h!="textarea"||(c="value",h=="progress"&&f==null?t.removeAttribute("value"):f!=null&&(f!==t[c]||h=="progress"&&!f||h=="option"&&f!=k[c])&&V(t,c,f,k[c],o),c="checked",C!=null&&C!=t[c]&&V(t,c,C,k[c],o))}return t}function ue(t,e,n){try{if(typeof t=="function"){var s=typeof t.__u=="function";s&&t.__u(),s&&e==null||(t.__u=t(e))}else t.current=e}catch(o){g.__e(o,n)}}function Ne(t,e,n){var s,o;if(g.unmount&&g.unmount(t),(s=t.ref)&&(s.current&&s.current!=t.__e||ue(s,null,e)),(s=t.__c)!=null){if(s.componentWillUnmount)try{s.componentWillUnmount()}catch(a){g.__e(a,e)}s.base=s.__P=null}if(s=t.__k)for(o=0;o<s.length;o++)s[o]&&Ne(s[o],e,n||typeof t.type!="function");n||re(t.__e),t.__c=t.__=t.__e=void 0}function lt(t,e,n){return this.constructor(t,n)}function qe(t,e,n){var s,o,a,l;e==document&&(e=document.documentElement),g.__&&g.__(t,e),o=(s=typeof n=="function")?null:n&&n.__k||e.__k,a=[],l=[],de(e,t=(!s&&n||e).__k=ce(X,null,[t]),o||O,O,e.namespaceURI,!s&&n?[n]:o?null:e.firstChild?G.call(e.childNodes):null,a,!s&&n?n:o?o.__e:e.firstChild,s,l),Re(a,t,l)}G=Y.slice,g={__e:function(t,e,n,s){for(var o,a,l;e=e.__;)if((o=e.__c)&&!o.__)try{if((a=o.constructor)&&a.getDerivedStateFromError!=null&&(o.setState(a.getDerivedStateFromError(t)),l=o.__d),o.componentDidCatch!=null&&(o.componentDidCatch(t,s||{}),l=o.__d),l)return o.__E=o}catch(d){t=d}throw t}},we=0,et=function(t){return t!=null&&t.constructor===void 0},K.prototype.setState=function(t,e){var n;n=this.__s!=null&&this.__s!=this.state?this.__s:this.__s=R({},this.state),typeof t=="function"&&(t=t(R({},n),this.props)),t&&R(n,t),t!=null&&this.__v&&(e&&this._sb.push(e),ke(this))},K.prototype.forceUpdate=function(t){this.__v&&(this.__e=!0,t&&this.__h.push(t),ke(this))},K.prototype.render=X,N=[],Ce=typeof Promise=="function"?Promise.prototype.then.bind(Promise.resolve()):setTimeout,Se=function(t,e){return t.__v.__b-e.__v.__b},J.__r=0,se=Math.random().toString(8),W="__d"+se,L="__a"+se,Me=/(PointerCapture)$|Capture$/i,le=0,ae=xe(!1),oe=xe(!0),tt=0;var U,x,_e,He,I=0,Ve=[],w=g,De=w.__b,je=w.__r,Le=w.diffed,Ue=w.__c,Ie=w.unmount,Fe=w.__;function ve(t,e){w.__h&&w.__h(x,t,I||e),I=0;var n=x.__H||(x.__H={__:[],__h:[]});return t>=n.__.length&&n.__.push({}),n.__[t]}function q(t){return I=1,rt(ze,t)}function rt(t,e,n){var s=ve(U++,2);if(s.t=t,!s.__c&&(s.__=[n?n(e):ze(void 0,e),function(d){var _=s.__N?s.__N[0]:s.__[0],c=s.t(_,d);_!==c&&(s.__N=[c,s.__[1]],s.__c.setState({}))}],s.__c=x,!x.__f)){var o=function(d,_,c){if(!s.__c.__H)return!0;var i=s.__c.__H.__.filter(function(p){return p.__c});if(i.every(function(p){return!p.__N}))return!a||a.call(this,d,_,c);var r=s.__c.props!==d;return i.some(function(p){if(p.__N){var v=p.__[0];p.__=p.__N,p.__N=void 0,v!==p.__[0]&&(r=!0)}}),a&&a.call(this,d,_,c)||r};x.__f=!0;var a=x.shouldComponentUpdate,l=x.componentWillUpdate;x.componentWillUpdate=function(d,_,c){if(this.__e){var i=a;a=void 0,o(d,_,c),a=i}l&&l.call(this,d,_,c)},x.shouldComponentUpdate=o}return s.__N||s.__}function ee(t,e){var n=ve(U++,3);!w.__s&&We(n.__H,e)&&(n.__=t,n.u=e,x.__H.__h.push(n))}function fe(t){return I=5,te(function(){return{current:t}},[])}function te(t,e){var n=ve(U++,7);return We(n.__H,e)&&(n.__=t(),n.__H=e,n.__h=t),n.__}function ye(t,e){return I=8,te(function(){return t},e)}function ct(){for(var t;t=Ve.shift();){var e=t.__H;if(t.__P&&e)try{e.__h.some(Z),e.__h.some(pe),e.__h=[]}catch(n){e.__h=[],w.__e(n,t.__v)}}}w.__b=function(t){x=null,De&&De(t)},w.__=function(t,e){t&&e.__k&&e.__k.__m&&(t.__m=e.__k.__m),Fe&&Fe(t,e)},w.__r=function(t){je&&je(t),U=0;var e=(x=t.__c).__H;e&&(_e===x?(e.__h=[],x.__h=[],e.__.some(function(n){n.__N&&(n.__=n.__N),n.u=n.__N=void 0})):(e.__h.some(Z),e.__h.some(pe),e.__h=[],U=0)),_e=x},w.diffed=function(t){Le&&Le(t);var e=t.__c;e&&e.__H&&(e.__H.__h.length&&(Ve.push(e)!==1&&He===w.requestAnimationFrame||((He=w.requestAnimationFrame)||dt)(ct)),e.__H.__.some(function(n){n.u&&(n.__H=n.u),n.u=void 0})),_e=x=null},w.__c=function(t,e){e.some(function(n){try{n.__h.some(Z),n.__h=n.__h.filter(function(s){return!s.__||pe(s)})}catch(s){e.some(function(o){o.__h&&(o.__h=[])}),e=[],w.__e(s,n.__v)}}),Ue&&Ue(t,e)},w.unmount=function(t){Ie&&Ie(t);var e,n=t.__c;n&&n.__H&&(n.__H.__.some(function(s){try{Z(s)}catch(o){e=o}}),n.__H=void 0,e&&w.__e(e,n.__v))};var Be=typeof requestAnimationFrame=="function";function dt(t){var e,n=function(){clearTimeout(s),Be&&cancelAnimationFrame(e),setTimeout(t)},s=setTimeout(n,35);Be&&(e=requestAnimationFrame(n))}function Z(t){var e=x,n=t.__c;typeof n=="function"&&(t.__c=void 0,n()),x=e}function pe(t){var e=x;t.__c=t.__(),x=e}function We(t,e){return!t||t.length!==e.length||e.some(function(n,s){return n!==t[s]})}function ze(t,e){return typeof e=="function"?e(t):e}var Oe=function(t,e,n,s){var o;e[0]=0;for(var a=1;a<e.length;a++){var l=e[a++],d=e[a]?(e[0]|=l?1:2,n[e[a++]]):e[++a];l===3?s[0]=d:l===4?s[1]=Object.assign(s[1]||{},d):l===5?(s[1]=s[1]||{})[e[++a]]=d:l===6?s[1][e[++a]]+=d+"":l?(o=t.apply(d,Oe(t,d,n,["",null])),s.push(o),d[0]?e[0]|=2:(e[a-2]=0,e[a]=o)):s.push(d)}return s},Ke=new Map;function Ye(t){var e=Ke.get(this);return e||(e=new Map,Ke.set(this,e)),(e=Oe(this,e.get(t)||(e.set(t,e=(function(n){for(var s,o,a=1,l="",d="",_=[0],c=function(p){a===1&&(p||(l=l.replace(/^\\s*\\n\\s*|\\s*\\n\\s*$/g,"")))?_.push(0,p,l):a===3&&(p||l)?(_.push(3,p,l),a=2):a===2&&l==="..."&&p?_.push(4,p,0):a===2&&l&&!p?_.push(5,0,!0,l):a>=5&&((l||!p&&a===5)&&(_.push(a,0,l,o),a=6),p&&(_.push(a,p,0,o),a=6)),l=""},i=0;i<n.length;i++){i&&(a===1&&c(),c(i));for(var r=0;r<n[i].length;r++)s=n[i][r],a===1?s==="<"?(c(),_=[_],a=3):l+=s:a===4?l==="--"&&s===">"?(a=1,l=""):l=s+l[0]:d?s===d?d="":l+=s:s===\'"\'||s==="\'"?d=s:s===">"?(c(),a=1):a&&(s==="="?(a=5,o=l,l=""):s==="/"&&(a<5||n[i][r+1]===">")?(c(),a===3&&(_=_[0]),a=_,(_=_[0]).push(2,0,a),a=0):s===" "||s===" "||s===`\n`||s==="\\r"?(c(),a=2):l+=s),a===3&&l==="!--"&&(a=4,_=_[0])}return c(),_})(t)),e),arguments,[])).length>1?e:e[0]}var u=Ye.bind(ce),Je=window.__QRING__&&window.__QRING__.token||"",he=Je?"?token="+encodeURIComponent(Je):"",A=t=>\'<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="url(#neon-grad)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">\'+t+"</svg>",m={health:A(\'<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/>\'),environment:A(\'<polyline points="22 12 18 12 15 21 9 3 6 12 2 12"/>\'),decay:A(\'<path d="M5 22h14"/><path d="M5 2h14"/><path d="M17 22v-4.172a2 2 0 0 0-.586-1.414L12 12l-4.414 4.414A2 2 0 0 0 7 17.828V22"/><path d="M7 2v4.172a2 2 0 0 0 .586 1.414L12 12l4.414-4.414A2 2 0 0 0 17 6.172V2"/>\'),superposition:A(\'<polygon points="12 2 2 7 12 12 22 7 12 2"/><polyline points="2 17 12 22 22 17"/><polyline points="2 12 12 17 22 12"/>\'),entangle:A(\'<path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/>\'),tunnel:A(\'<path d="M9 10h.01"/><path d="M15 10h.01"/><path d="M12 2a8 8 0 0 0-8 8v12l3-3 2.5 2.5L12 19l2.5 2.5L17 19l3 3V10a8 8 0 0 0-8-8z"/>\'),anomaly:A(\'<path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/>\'),audit:A(\'<circle cx="12" cy="12" r="10"/><circle cx="12" cy="12" r="6"/><circle cx="12" cy="12" r="2"/>\'),key:A(\'<path d="M21 2l-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.778 7.778 5.5 5.5 0 0 1 7.777-7.777zm0 0L15.5 7.5m0 0l3 3L22 7l-3-3m-3.5 3.5L19 4"/>\'),hook:A(\'<path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/>\'),approve:A(\'<path d="M9 11l3 3L22 4"/><path d="M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11"/>\'),manifest:A(\'<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/>\'),policy:A(\'<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/><path d="M9 12l2 2 4-4"/>\'),memory:A(\'<rect x="4" y="4" width="16" height="16" rx="2"/><rect x="9" y="9" width="6" height="6"/><line x1="9" y1="2" x2="9" y2="4"/><line x1="15" y1="2" x2="15" y2="4"/><line x1="9" y1="20" x2="9" y2="22"/><line x1="15" y1="20" x2="15" y2="22"/><line x1="20" y1="9" x2="22" y2="9"/><line x1="20" y1="14" x2="22" y2="14"/><line x1="2" y1="9" x2="4" y2="9"/><line x1="2" y1="14" x2="4" y2="14"/>\'),folder:\'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/></svg>\',search:\'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>\',lock:\'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="11" width="18" height="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg>\'};function me(t){if(!t)return"env-default";let e=t.toLowerCase();return e==="prod"||e==="production"?"env-prod":e==="staging"||e==="stage"?"env-staging":e==="dev"||e==="development"?"env-dev":e==="test"||e==="testing"?"env-test":"env-default"}function Qe(t,e){return e||t>=90?"var(--danger)":t>=75?"var(--warning)":"var(--accent)"}function Xe(t){let e=new Date(t);return String(e.getHours()).padStart(2,"0")+":"+String(e.getMinutes()).padStart(2,"0")+":"+String(e.getSeconds()).padStart(2,"0")}function Ze(t){if(!t)return"\\u2014";let e=Math.floor((Date.now()-new Date(t).getTime())/1e3);return isNaN(e)?"\\u2014":e<5?"just now":e<60?e+"s ago":e<3600?Math.floor(e/60)+"m ago":e<86400?Math.floor(e/3600)+"h ago":Math.floor(e/86400)+"d ago"}function $e(t){return t==null?"\\u2014":t<0?"expired":t<60?t+"s":t<3600?Math.floor(t/60)+"m":t<86400?Math.floor(t/3600)+"h":Math.floor(t/86400)+"d"}var j=({svg:t})=>u`<span style="display:contents" dangerouslySetInnerHTML=${{__html:t}} />`;function S({icon:t,title:e,aside:n,asideStyle:s}){return u`<div class="card-title">\n <${j} svg=${t} />${e}\n ${n!=null?u`<span class="title-aside" style=${s||""}>${n}</span>`:null}\n </div>`}function M({delay:t=0,wide:e=!1,style:n="",children:s}){let o="card"+(e?" grid-wide":""),a="animation-delay:"+t+"ms"+(n?";"+n:"");return u`<div class=${o} style=${a}>${s}</div>`}function E({children:t,cta:e}){return u`<div class="empty">${t}${e?u`<span class="empty-cta">${e}</span>`:null}</div>`}function Ge({snap:t,paused:e,connState:n,onPause:s,onRefresh:o,lastUpdate:a}){let l=e?"paused":n==="live"?"live":n==="reconnecting"?"reconnecting\\u2026":"connecting\\u2026",d="status-dot"+(e?" paused":n==="reconnecting"?" disconnected":"");return u`\n <header class="header">\n <div class="header-left">\n <h1>\n <span class="q-icon"><svg width="26" height="26" viewBox="0 0 24 24" fill="none" stroke="url(#neon-grad)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><circle cx="12" cy="12" r="10"/><circle cx="12" cy="12" r="6"/><circle cx="12" cy="12" r="2"/></svg></span>\n <span class="brand">q-ring</span>\n <span class="sub">quantum status</span>\n </h1>\n <span class="meta-chip" title="q-ring version">\n <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg>\n ${" v"+(t?t.version:"")}\n </span>\n <span class="meta-chip" title="Project working directory">\n <${j} svg=${m.folder} /> ${t?t.projectPath:""}\n </span>\n </div>\n <div class="header-right">\n <span class="conn-label" title="Last update from the live stream"><span>${a}</span></span>\n <button class="btn" type="button" title="Pause / resume the live stream (P)" onClick=${s}>\n ${e?u`<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="5 3 19 12 5 21 5 3"/></svg>`:u`<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="6" y="4" width="4" height="16" rx="1"/><rect x="14" y="4" width="4" height="16" rx="1"/></svg>`}\n <span>${e?"Resume":"Pause"}</span>\n </button>\n <button class="btn" type="button" title="Force-refresh now (R)" onClick=${o}>\n <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 1 1-3.5-7.1"/><polyline points="21 3 21 9 15 9"/></svg>\n Refresh\n </button>\n <a class="btn" href=${"/api/status"+he} target="_blank" rel="noopener" title="Open the raw JSON snapshot in a new tab">\n <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="16 18 22 12 16 6"/><polyline points="8 6 2 12 8 18"/></svg>\n JSON\n </a>\n <span class="conn-label"><span class=${d}></span><span>${l}</span></span>\n </div>\n </header>\n `}function ut({snap:t}){let e=t,n=e.auditMetrics||{total:0,byAction:{},topRead:[]},s=n.byAction.read||0,o=(n.byAction.write||0)+(n.byAction.delete||0)+(n.byAction.rotate||0),a=n.byAction.policy_deny||0,l=(e.hooks||[]).filter(i=>i.enabled).length,d=(e.approvals||[]).filter(i=>i.valid).length,_=(e.anomalies||[]).length,c=[{label:"Secrets",icon:m.key,value:e.health.total,sub:e.health.healthy+" healthy \\xB7 "+e.health.stale+" stale \\xB7 "+e.health.expired+" expired",cls:""},{label:"Environment",icon:m.environment,value:e.environment?e.environment.env:"none",sub:e.environment?"via "+e.environment.source:"no env detected",cls:e.environment?"":"dim"},{label:"Protected",icon:m.lock,value:e.protectedCount,sub:"require approval",cls:e.protectedCount>0?"warning":"dim"},{label:"Approvals",icon:m.approve,value:d,sub:"active grants",cls:d>0?"green":"dim"},{label:"Hooks",icon:m.hook,value:l,sub:"enabled / "+(e.hooks||[]).length+" total",cls:l>0?"":"dim"},{label:"Reads (24h)",icon:m.audit,value:s,sub:o+" writes \\xB7 "+a+" denied",cls:""},{label:"Anomalies",icon:m.anomaly,value:_,sub:_?"investigate now":"all clear",cls:_?"danger":"green"}];return u`<section class="kpi-strip">\n ${c.map(i=>u`<div class="kpi" key=${i.label}>\n <div class="kpi-label"><${j} svg=${i.icon} />${i.label}</div>\n <div class="kpi-value ${i.cls}">${i.value}</div>\n <div class="kpi-sub">${i.sub}</div>\n </div>`)}\n </section>`}function _t({snap:t,delay:e}){let n=t.health,s=n.total||1,o=42,a=2*Math.PI*o,l=[{v:n.healthy,c:"var(--accent)"},{v:n.stale,c:"var(--warning)"},{v:n.expired,c:"var(--danger)"},{v:n.noDecay,c:"var(--text-dim)"}],d=0,_=l.map((i,r)=>{let p=i.v/s*a,v=u`<circle key=${r} cx="50" cy="50" r=${o} fill="none" stroke=${i.c} stroke-width="12" stroke-dasharray=${p+" "+(a-p)} stroke-dashoffset=${-d} stroke-linecap="round" opacity="0.85" />`;return d+=p,v}),c=t.scopes||{global:0,project:0,team:0,org:0};return u`<${M} delay=${e}>\n <${S} icon=${m.health} title="Health Summary" aside=${n.healthy+"/"+n.total+" healthy"} />\n <div class="health-row">\n <div class="donut-wrap">\n <svg viewBox="0 0 100 100" width="100" height="100">${_}</svg>\n <div class="donut-label">${n.total}<small>secrets</small></div>\n </div>\n <div class="health-legend">\n <div class="legend-item"><span class="legend-dot" style="background:var(--accent)"></span>Healthy ${n.healthy}</div>\n <div class="legend-item"><span class="legend-dot" style="background:var(--warning)"></span>Stale ${n.stale}</div>\n <div class="legend-item"><span class="legend-dot" style="background:var(--danger)"></span>Expired ${n.expired}</div>\n <div class="legend-item"><span class="legend-dot" style="background:var(--text-dim)"></span>No decay ${n.noDecay}</div>\n </div>\n </div>\n <div class="scope-row">\n ${["global","project","team","org"].filter(i=>c[i]).map(i=>u`<span class="scope-pill" key=${i}><strong>${c[i]}</strong>${i}</span>`)}\n </div>\n <//>`}function pt({snap:t,delay:e}){let n=t.environment;return u`<${M} delay=${e}>\n <${S} icon=${m.environment} title="Environment" />\n ${n?u`<div class="env-status"><span class="env-big env-pill ${me(n.env)}">${n.env}</span><span class="env-source">detected via ${n.source}</span></div>`:u`<${E} cta="$ qring env --project-path .">No environment detected.<//>`}\n <//>`}function vt({snap:t,delay:e}){let n=t.manifest;if(!n)return u`<${M} delay=${e}>\n <${S} icon=${m.manifest} title="Manifest" />\n <${E} cta=${u`$ qring wizard <name>`}>No <code>.q-ring.json</code> manifest in this project.<//>\n <//>`;let s=n.required-n.missing.length-n.expired.length-n.stale.length,o=n.required?Math.max(0,Math.round(s/n.required*100)):100,a=n.missing.length?"var(--danger)":n.expired.length||n.stale.length?"var(--warning)":"var(--green)",l=(_,c,i)=>u`<div class="label">${_} (${c.length})</div><div>${c.map(r=>u`<span class="key-pill ${i}" key=${r}>${r}</span>`)}</div>`,d=n.missing.length||n.expired.length||n.stale.length;return u`<${M} delay=${e}>\n <${S} icon=${m.manifest} title="Manifest" aside=${n.required+" required / "+n.declared+" declared"} />\n <div class="manifest-bars">\n <div class="manifest-row"><span style="min-width:54px">healthy</span><div class="manifest-bar"><div class="manifest-fill" style=${"width:"+o+"%;background:"+a}></div></div><span>${o}%</span></div>\n </div>\n <div class="manifest-list">\n ${n.missing.length?l("Missing required",n.missing,"miss"):null}\n ${n.expired.length?l("Expired",n.expired,"exp"):null}\n ${n.stale.length?l("Stale",n.stale,"exp"):null}\n ${d?null:u`<div class="label">All required keys present and healthy.</div>`}\n </div>\n <//>`}function ft({snap:t,delay:e}){let n=t.policy||{counts:{}},s=n.counts||{};if(!(n.hasMcpPolicy||n.hasExecPolicy||n.hasSecretPolicy))return u`<${M} delay=${e}>\n <${S} icon=${m.policy} title="Policy" />\n <${E} cta=${u`add <code>policy</code> to <code>.q-ring.json</code>`}>No governance policy declared.<//>\n <//>`;let a=({label:d,value:_})=>u`<div class="policy-row"><span class="policy-label">${d}</span><span class="policy-value ${_?"":"zero"}">${_||"\\u2014"}</span></div>`,l=[n.hasMcpPolicy?"mcp":"",n.hasExecPolicy?"exec":"",n.hasSecretPolicy?"secrets":""].filter(Boolean).join(" \\xB7 ")||"none";return u`<${M} delay=${e}>\n <${S} icon=${m.policy} title="Policy" aside=${l} />\n <div class="policy-rows">\n <${a} label="MCP allow tools" value=${s.allowTools} />\n <${a} label="MCP deny tools" value=${s.denyTools} />\n <${a} label="Denied keys" value=${s.deniedKeys} />\n <${a} label="Denied tags" value=${s.deniedTags} />\n <${a} label="Exec allow" value=${s.allowCommands} />\n <${a} label="Exec deny" value=${s.denyCommands} />\n <${a} label="Tag \u2192 approval" value=${s.requireApprovalForTags} />\n <${a} label="Tag \u2192 rotation" value=${s.requireRotationFormatForTags} />\n ${n.maxTtlSeconds?u`<${a} label="Max TTL" value=${$e(n.maxTtlSeconds)} />`:null}\n ${n.maxRuntimeSeconds?u`<${a} label="Max exec runtime" value=${$e(n.maxRuntimeSeconds)} />`:null}\n </div>\n <//>`}function yt({snap:t,delay:e}){let n=(t.secrets||[]).filter(s=>s.decay&&s.decay.timeRemaining).sort((s,o)=>(s.decay.secondsRemaining||0)-(o.decay.secondsRemaining||0));return u`<${M} delay=${e}>\n <${S} icon=${m.decay} title="Decay Timers" aside=${n.length+" tracked"} />\n ${n.length?u`<div class="decay-list">${n.slice(0,12).map(s=>{let o=Math.min(s.decay.lifetimePercent,100),a=Qe(o,s.decay.isExpired),l=s.decay.isExpired?"expired":s.decay.timeRemaining||"";return u`<div class="decay-item" key=${s.scope+":"+s.key}>\n <span class="decay-key" title=${s.key}>${s.key}</span>\n <div class="decay-bar"><div class="decay-fill" style=${"width:"+o+"%;background:"+a}></div></div>\n <span class="decay-time" style=${"color:"+a}>${l}</span>\n </div>`})}</div>`:u`<${E} cta="$ qring set KEY --ttl 86400">No secrets with decay configured.<//>`}\n <//>`}function ht({snap:t,delay:e}){let n=(t.secrets||[]).filter(s=>s.type==="superposition"&&s.environments&&s.environments.length);return u`<${M} delay=${e}>\n <${S} icon=${m.superposition} title="Superposition" aside=${n.length+" multi-env"} />\n ${n.length?u`<div class="super-list">${n.slice(0,14).map(s=>u`<div class="super-item" key=${s.scope+":"+s.key}>\n <span class="super-key">${s.key}</span>\n ${(s.environments||[]).map(o=>u`<span class="env-pill ${me(o)}" key=${o}>${o}${o===s.defaultEnv?" \\u2713":""}</span>`)}\n </div>`)}</div>`:u`<${E} cta="$ qring set KEY --env prod">No secrets in superposition.<//>`}\n <//>`}function $t({snap:t,delay:e}){let n=t.entanglements||[],s=new Set,o=n.filter(a=>{let l=[a.source.service,a.source.key,a.target.service,a.target.key].sort().join("|");return s.has(l)?!1:(s.add(l),!0)});return u`<${M} delay=${e}>\n <${S} icon=${m.entangle} title="Entanglement" aside=${o.length+" pair"+(o.length===1?"":"s")} />\n ${o.length?u`<div class="entangle-list">${o.slice(0,12).map((a,l)=>u`<div class="entangle-pair" key=${l}>\n <span>${a.source.key}</span><span class="entangle-arrow">\u2194</span><span>${a.target.key}</span>\n </div>`)}</div>`:u`<${E} cta="$ qring entangle KEY_A KEY_B">No entangled secrets.<//>`}\n <//>`}function mt({snap:t,delay:e}){let n=t.tunnels||[];return u`<${M} delay=${e}>\n <${S} icon=${m.tunnel} title="Quantum Tunnels" aside=${n.length+" live"} />\n ${n.length?u`<div class="tunnel-list">${n.map(s=>{let o=s.expiresAt?Math.max(0,Math.floor((s.expiresAt-Date.now())/1e3)):null;return u`<div class="tunnel-card" key=${s.id}>${s.id}<div class="tunnel-meta">\n <span>reads: ${s.accessCount}${s.maxReads?"/"+s.maxReads:""}</span>\n ${o!==null?u`<span>expires: ${o}s</span>`:u`<span>no expiry</span>`}\n </div></div>`})}</div>`:u`<${E} cta=${u`$ qring tunnel create <value>`}>No active tunnels.<//>`}\n <//>`}function gt({snap:t,delay:e}){let n=t.approvals||[];return u`<${M} delay=${e}>\n <${S} icon=${m.approve} title="Approvals" aside=${n.filter(s=>s.valid).length+" valid"} />\n ${n.length?u`<div class="approval-list">${n.slice(0,8).map(s=>{let o=s.tampered?"tampered":s.secondsRemaining<300?"expiring":"";return u`<div class="approval-card ${o}" key=${s.id}>\n <div class="approval-head"><span>${s.key}${s.tampered?" \\u26A0 TAMPERED":""}</span><span>${$e(s.secondsRemaining)} left</span></div>\n <div class="approval-reason">${s.reason||"(no reason)"}</div>\n <div class="approval-meta"><span>scope:${s.scope}</span><span>by:${s.grantedBy}</span></div>\n </div>`})}</div>`:u`<${E} cta=${\'$ qring approve KEY --for 1800 --reason "..."\'}>No active approvals.<//>`}\n <//>`}function kt({snap:t,delay:e}){let n=t.hooks||[];return u`<${M} delay=${e}>\n <${S} icon=${m.hook} title="Hooks" aside=${n.filter(s=>s.enabled).length+" enabled / "+n.length} />\n ${n.length?u`<div class="hooks-list">${n.slice(0,8).map(s=>u`<div class="hook-row ${s.enabled?"":"disabled"}" key=${s.id}>\n <span class="hook-type ${s.type}">${s.type}</span>\n <span class="hook-summary" title=${s.matchSummary}>${s.description||s.matchSummary}</span>\n <span class="hook-id">${s.id}</span>\n </div>`)}</div>`:u`<${E} cta=${\'$ qring hook add --tag payments --action rotate --exec "..."\'}>No hooks registered.<//>`}\n <//>`}function bt({snap:t,delay:e}){return u`<${M} delay=${e}>\n <${S} icon=${m.memory} title="Agent Memory" />\n <div class="empty" style="display:flex;align-items:baseline;gap:8px;font-style:normal">\n <span style="font-size:1.6rem;font-weight:700;color:var(--text-primary);font-family:var(--font-display)">${t.memoryKeys||0}</span>\n <span>memory key${t.memoryKeys===1?"":"s"} encrypted at <code>~/.config/q-ring/agent-memory.enc</code></span>\n </div>\n <//>`}function xt({snap:t,delay:e}){let n=t.anomalies||[];if(!n.length)return u`<${M} delay=${e} wide=${!0}>\n <${S} icon=${m.anomaly} title="Anomaly Alerts" aside="all clear" asideStyle="color:var(--green)" />\n <${E}>No anomalies detected \u2014 quantum field is stable.<//>\n <//>`;let s=o=>o==="tampered"?"$ qring audit:verify":o==="burst"?"$ qring audit --key \\u2026 --action read":o==="unusual-hour"?\'$ qring audit --action read --since "1am"\':"$ qring audit --limit 100";return u`<${M} delay=${e} wide=${!0}>\n <${S} icon=${m.anomaly} title="Anomaly Alerts" aside=${n.length+" active"} asideStyle="color:var(--danger)" />\n <div class="anomaly-list">${n.map((o,a)=>u`<div class="anomaly-card" key=${a}>\n <div class="anomaly-type">${o.type}</div>\n <div class="anomaly-desc">${o.description}</div>\n <div class="anomaly-hint">${s(o.type)}</div>\n </div>`)}</div>\n <//>`}function wt(t,e){let n=e.trim().toLowerCase();return n?n==="expired"?t.filter(s=>s.decay&&s.decay.isExpired):n==="stale"?t.filter(s=>s.decay&&s.decay.isStale&&!s.decay.isExpired):n==="protected"?t.filter(s=>s.requiresApproval):t.filter(s=>[s.key,s.scope,s.type,s.provider||"",s.defaultEnv||"",(s.environments||[]).join(" "),(s.tags||[]).join(" ")].join(" ").toLowerCase().indexOf(n)!==-1):t.slice()}function Ct(t,e){let n=e.dir==="asc"?1:-1;return t.sort((s,o)=>{let a,l;switch(e.col){case"key":a=s.key,l=o.key;break;case"scope":a=s.scope,l=o.scope;break;case"env":a=s.defaultEnv||(s.environments||[])[0]||"",l=o.defaultEnv||(o.environments||[])[0]||"";break;case"type":a=s.type,l=o.type;break;case"decay":a=s.decay&&s.decay.secondsRemaining!=null?s.decay.secondsRemaining:1/0,l=o.decay&&o.decay.secondsRemaining!=null?o.decay.secondsRemaining:1/0;break;case"tags":a=(s.tags||[]).join(","),l=(o.tags||[]).join(",");break;default:a=s.lastAccessedAt?new Date(s.lastAccessedAt).getTime():0,l=o.lastAccessedAt?new Date(o.lastAccessedAt).getTime():0}return a<l?-1*n:a>l?1*n:0})}function St({snap:t,query:e,setQuery:n,sort:s,setSort:o,searchRef:a}){let l=t.secrets||[],d=te(()=>Ct(wt(l,e),s),[l,e,s]),_=[{id:"key",label:"Key"},{id:"scope",label:"Scope"},{id:"env",label:"Env"},{id:"type",label:"Type"},{id:"decay",label:"Decay"},{id:"tags",label:"Tags"},{id:"lastAccessedAt",label:"Last read"}],c=i=>{s.col===i?o({col:i,dir:s.dir==="asc"?"desc":"asc"}):o({col:i,dir:i==="key"?"asc":"desc"})};return u`<section><${M} wide=${!0} style="margin-bottom:16px">\n <${S} icon=${m.key} title="Secrets" aside=${d.length+" of "+l.length} />\n <div class="secrets-toolbar">\n <label class="search"><${j} svg=${m.search} /><input ref=${a} id="secretsSearch" type="search" placeholder="Filter by key, scope, env, tag, provider\u2026" autocomplete="off" value=${e} onInput=${i=>n(i.target.value)} /></label>\n <button class="btn" type="button" onClick=${()=>n("expired")}>${t.health.expired||0} expired</button>\n <button class="btn" type="button" onClick=${()=>n("stale")}>${t.health.stale||0} stale</button>\n <button class="btn" type="button" onClick=${()=>n("protected")}>${t.protectedCount||0} protected</button>\n <button class="btn" type="button" onClick=${()=>n("")}>clear</button>\n </div>\n <div class="secrets-table-wrap">\n ${d.length?u`<table class="secrets-table">\n <thead><tr>${_.map(i=>u`<th key=${i.id} class=${s.col===i.id?"sorted":""} onClick=${()=>c(i.id)}>${i.label}<span class="sort-arrow">${s.dir==="asc"?"\\u25B2":"\\u25BC"}</span></th>`)}</tr></thead>\n <tbody>${d.map(i=>{let r=i.type==="superposition"?(i.environments||[]).map(f=>u`<span class="env-pill ${me(f)}" style="margin-right:3px" key=${f}>${f}${f===i.defaultEnv?" \\u2713":""}</span>`):u`<span class="env-pill env-default">\u2014</span>`,p=i.decay&&i.decay.timeRemaining?(()=>{let f=Math.min(i.decay.lifetimePercent,100),C=Qe(f,i.decay.isExpired);return u`<span class="mini-decay"><span class="mini-decay-bar"><span class="mini-decay-fill" style=${"width:"+f+"%;background:"+C}></span></span><span class="mini-decay-time" style=${"color:"+C}>${i.decay.isExpired?"expired":i.decay.timeRemaining}</span></span>`})():u`<span class="mini-decay-time">\u2014</span>`,v=i.tags||[];return u`<tr key=${i.scope+":"+i.key}>\n <td class="col-key" title=${i.key}>${i.key}${i.requiresApproval?u`<span class="protected-icon" title="requires approval for MCP read"><${j} svg=${m.lock} /></span>`:null}</td>\n <td><span class="scope-tag ${i.scope}">${i.scope}</span></td>\n <td>${r}</td>\n <td><span class="type-tag ${i.type}">${i.type}</span></td>\n <td class="col-decay">${p}</td>\n <td class="col-tags">${v.slice(0,3).map(f=>u`<span class="tag-pill" key=${f}>${f}</span>`)}${v.length>3?"+"+(v.length-3):""}</td>\n <td>${Ze(i.lastAccessedAt)}</td>\n </tr>`})}</tbody>\n </table>`:u`<div class="empty" style="padding:18px;text-align:center">No secrets match the filter.</div>`}\n </div>\n <//></section>`}function Mt({snap:t,delay:e,filter:n,setFilter:s}){let o=t.audit||[],a=t.auditMetrics||{byAction:{},bySource:{}},l=o.filter(i=>{if(n.action&&i.action!==n.action||n.source&&i.source!==n.source)return!1;let r=n.text.trim().toLowerCase();return!(r&&[i.key||"",i.action,i.source,i.detail||"",i.scope||"",i.env||""].join(" ").toLowerCase().indexOf(r)===-1)}),d=["read","write","delete","rotate","generate","entangle","tunnel","teleport","approve","revoke","policy_deny","collapse","export"],_=["cli","mcp","agent","ci","hook","api"],c=(i,r)=>s({...n,[i]:n[i]===r?"":r});return u`<${M} delay=${e} wide=${!0}>\n <${S} icon=${m.audit} title="Audit Log (24h)" aside=${l.length+" of "+o.length+" shown \\xB7 window "+(a.windowSeconds||86400)/3600+"h"} />\n <div class="audit-actions-strip">\n ${d.filter(i=>a.byAction[i]).length?d.filter(i=>a.byAction[i]).map(i=>u`<span class="audit-chip ${n.action===i?"active":""}" key=${i} onClick=${()=>c("action",i)}>${i}<strong>${a.byAction[i]}</strong></span>`):u`<span class="empty" style="padding:0">no actions</span>`}\n </div>\n ${_.filter(i=>a.bySource[i]).length?u`<div class="audit-actions-strip">${_.filter(i=>a.bySource[i]).map(i=>u`<span class="audit-chip ${n.source===i?"active":""}" key=${i} onClick=${()=>c("source",i)}>${i}<strong>${a.bySource[i]}</strong></span>`)}</div>`:null}\n <div class="audit-toolbar">\n <label class="search"><${j} svg=${m.search} /><input id="auditSearch" type="search" placeholder="Filter by key, detail, scope\u2026" autocomplete="off" value=${n.text} onInput=${i=>s({...n,text:i.target.value})} /></label>\n <button class="btn" type="button" onClick=${()=>s({action:"",source:"",text:""})}>clear</button>\n </div>\n ${l.length?u`<div class="audit-feed">${l.slice(0,80).map((i,r)=>u`<div class="audit-row" key=${r}>\n <span class="audit-ts" title=${i.timestamp}>${Xe(i.timestamp)}</span>\n <span class="audit-action ${i.action}">${i.action}</span>\n <span class="audit-source">${i.source}</span>\n <span><span class="audit-key">${i.key||"\\u2014"}</span> <span class="audit-detail">${i.detail||""}</span></span>\n </div>`)}</div>`:u`<${E}>No audit events match the filter.<//>`}\n <//>`}function At(){let[t,e]=q(null),[n,s]=q(!1),[o,a]=q("connecting"),[l,d]=q(""),[_,c]=q({col:"lastAccessedAt",dir:"desc"}),[i,r]=q({action:"",source:"",text:""}),[,p]=q(0),v=fe(n);v.current=n;let f=fe(null),C=ye($=>{try{e(typeof $=="string"?JSON.parse($):$)}catch{}},[]),k=ye(()=>{fetch("/api/status"+he,{cache:"no-store"}).then($=>$.json()).then(C).catch(()=>{})},[C]);ee(()=>{let $=new EventSource("/events"+he);return $.onopen=()=>a("live"),$.onmessage=b=>{v.current||C(b.data)},$.onerror=()=>a("reconnecting"),()=>$.close()},[C]),ee(()=>{let $=setInterval(()=>p(b=>b+1),5e3);return()=>clearInterval($)},[]),ee(()=>{let $=b=>{let T=b.target&&b.target.tagName;if(T==="INPUT"||T==="TEXTAREA"){b.key==="Escape"&&b.target.blur();return}b.key==="/"?(b.preventDefault(),f.current&&f.current.focus()):b.key==="p"||b.key==="P"?s(F=>!F):(b.key==="r"||b.key==="R")&&k()};return document.addEventListener("keydown",$),()=>document.removeEventListener("keydown",$)},[k]);let y=t?"updated "+Ze(t.timestamp):"\\u2014";if(!t)return u`<div class="container">\n <${Ge} snap=${null} paused=${n} connState=${o} onPause=${()=>s($=>!$)} onRefresh=${k} lastUpdate=${y} />\n <p class="foot"><span>Connecting to the live quantum stream\u2026</span></p>\n </div>`;let h=t.auditMetrics||{total:0};return u`<div class="container">\n <${Ge} snap=${t} paused=${n} connState=${o} onPause=${()=>s($=>!$)} onRefresh=${k} lastUpdate=${y} />\n <${ut} snap=${t} />\n <section class="grid">\n <${_t} snap=${t} delay=${0} />\n <${pt} snap=${t} delay=${60} />\n <${vt} snap=${t} delay=${120} />\n <${ft} snap=${t} delay=${180} />\n </section>\n <${St} snap=${t} query=${l} setQuery=${d} sort=${_} setSort=${c} searchRef=${f} />\n <section class="grid">\n <${yt} snap=${t} delay=${0} />\n <${ht} snap=${t} delay=${60} />\n <${$t} snap=${t} delay=${120} />\n <${mt} snap=${t} delay=${180} />\n </section>\n <section class="grid">\n <${gt} snap=${t} delay=${0} />\n <${kt} snap=${t} delay=${60} />\n <${bt} snap=${t} delay=${120} />\n </section>\n <section class="grid">\n <${xt} snap=${t} delay=${0} />\n <${Mt} snap=${t} delay=${60} filter=${i} setFilter=${r} />\n </section>\n <p class="foot">\n <span>${"q-ring v"+t.version+" \\xB7 snapshot "+Xe(t.timestamp)+" \\xB7 "+(h.total||0)+" audit events in last 24h"}</span>\n \xB7 keyboard: <span class="kbd">/</span> search \xB7 <span class="kbd">P</span> pause \xB7 <span class="kbd">R</span> refresh\n </p>\n </div>`}qe(u`<${At} />`,document.getElementById("app"));})();';
24
+
25
+ // src/core/dashboard-html.ts
26
+ function jsString(value) {
27
+ return JSON.stringify(value).replace(/</g, "\\u003c");
28
+ }
29
+ function getDashboardHtml(token) {
30
+ return `<!DOCTYPE html>
31
+ <html lang="en">
32
+ <head>
33
+ <meta charset="utf-8"/>
34
+ <meta name="viewport" content="width=device-width, initial-scale=1"/>
35
+ <title>q-ring \u2014 quantum status</title>
36
+ <style>
37
+ *,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
38
+ :root{
39
+ --bg-deep:#04080f;
40
+ --bg-section:#080e18;
41
+ --bg-card:#0f1a2e;
42
+ --bg-card-hover:#142240;
43
+ --border:#1a2d4a;
44
+ --border-glow:#0ea5e9;
45
+
46
+ --text-primary:#f8f8ff;
47
+ --text-secondary:#c8cfe0;
48
+ --text-dim:#8899b4;
49
+
50
+ --accent:#0ea5e9;
51
+ --accent-bright:#38bdf8;
52
+ --accent-dim:rgba(14,165,233,0.15);
53
+ --accent-glow:rgba(14,165,233,0.4);
54
+
55
+ --danger:#ff5e5b;
56
+ --warning:#fbbf24;
57
+ --green:#22c55e;
58
+ --violet:#a855f7;
59
+ --pink:#ff0055;
60
+
61
+ --font-display:system-ui,-apple-system,'Segoe UI',Roboto,sans-serif;
62
+ --font-mono:'SF Mono','Cascadia Code','Fira Code',Consolas,'Liberation Mono',monospace;
63
+
64
+ --radius:12px;
65
+ --radius-sm:8px;
66
+ --radius-lg:20px;
67
+
68
+ --glass-bg:rgba(15,26,46,0.65);
69
+ --glass-border:rgba(26,45,74,0.8);
70
+ --shadow-card:0 4px 24px -1px rgba(0,0,0,0.4),0 0 1px rgba(255,255,255,0.04);
71
+ --shadow-glow:0 0 20px rgba(14,165,233,0.12),0 0 40px rgba(168,85,247,0.08);
72
+ }
73
+ html{background:var(--bg-deep);color:var(--text-primary);font-family:var(--font-display);font-size:16px;line-height:1.5}
74
+ body{min-height:100vh;overflow-x:hidden;position:relative}
75
+
76
+ /* Hidden SVG defs for gradient icons */
77
+ .svg-defs{position:absolute;width:0;height:0;overflow:hidden}
78
+
79
+ /* Mesh blobs */
80
+ .blob{position:fixed;border-radius:50%;filter:blur(100px);opacity:.12;pointer-events:none;z-index:0}
81
+ .blob-1{width:600px;height:600px;top:-120px;left:-100px;background:radial-gradient(circle,var(--accent),transparent 70%);animation:drift1 22s ease-in-out infinite}
82
+ .blob-2{width:500px;height:500px;bottom:-80px;right:-60px;background:radial-gradient(circle,var(--violet),transparent 70%);animation:drift2 26s ease-in-out infinite}
83
+ .blob-3{width:350px;height:350px;top:40%;left:50%;background:radial-gradient(circle,var(--green),transparent 70%);animation:drift3 30s ease-in-out infinite;opacity:.06}
84
+ @keyframes drift1{0%,100%{transform:translate(0,0) scale(1)}33%{transform:translate(60px,-40px) scale(1.08)}66%{transform:translate(-30px,50px) scale(.95)}}
85
+ @keyframes drift2{0%,100%{transform:translate(0,0) scale(1)}33%{transform:translate(-50px,30px) scale(1.05)}66%{transform:translate(40px,-60px) scale(.92)}}
86
+ @keyframes drift3{0%,100%{transform:translate(-50%,-50%) scale(1)}50%{transform:translate(-40%,-60%) scale(1.1)}}
87
+
88
+ .container{position:relative;z-index:1;max-width:1320px;margin:0 auto;padding:20px 20px 48px}
89
+
90
+ /* Header */
91
+ .header{position:sticky;top:0;z-index:5;display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:14px;margin-bottom:20px;padding:14px 18px;background:rgba(4,8,15,0.85);backdrop-filter:blur(16px) saturate(1.2);-webkit-backdrop-filter:blur(16px) saturate(1.2);border:1px solid var(--border);border-radius:var(--radius)}
92
+ .header-left{display:flex;align-items:center;gap:14px;flex-wrap:wrap;min-width:0}
93
+ .header h1{font-family:var(--font-display);font-size:1.45rem;font-weight:700;letter-spacing:-.02em;display:flex;align-items:center;gap:10px}
94
+ .header h1 .q-icon{display:flex;filter:drop-shadow(0 0 6px rgba(14,165,233,0.6))}
95
+ .header h1 .brand{background:linear-gradient(135deg,#00D1FF,var(--violet));-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent}
96
+ .header h1 .sub{color:var(--text-dim);font-weight:400;font-size:1rem;-webkit-text-fill-color:var(--text-dim)}
97
+ .meta-chip{font-family:var(--font-mono);font-size:.72rem;color:var(--text-dim);background:rgba(255,255,255,.04);border:1px solid var(--border);padding:3px 8px;border-radius:99px;display:inline-flex;align-items:center;gap:6px;max-width:340px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
98
+ .meta-chip svg{width:11px;height:11px;flex-shrink:0;opacity:.7}
99
+ .header-right{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
100
+ .status-dot{width:8px;height:8px;border-radius:50%;background:var(--green);box-shadow:0 0 8px var(--green);display:inline-block;animation:pulse 2s ease-in-out infinite}
101
+ .status-dot.disconnected{background:var(--danger);box-shadow:0 0 8px var(--danger);animation:none}
102
+ .status-dot.paused{background:var(--warning);box-shadow:0 0 8px var(--warning);animation:none}
103
+ @keyframes pulse{0%,100%{opacity:1}50%{opacity:.4}}
104
+ .conn-label{font-size:.78rem;color:var(--text-dim);display:flex;align-items:center;gap:6px;font-family:var(--font-mono)}
105
+ .btn{font-family:var(--font-display);font-size:.78rem;font-weight:500;color:var(--text-secondary);background:rgba(255,255,255,.04);border:1px solid var(--border);padding:5px 11px;border-radius:var(--radius-sm);cursor:pointer;display:inline-flex;align-items:center;gap:5px;transition:background .2s,border-color .2s,color .2s}
106
+ .btn:hover{background:rgba(14,165,233,.08);border-color:var(--accent);color:var(--text-primary)}
107
+ .btn svg{width:13px;height:13px}
108
+ .btn.active{background:var(--accent-dim);color:var(--accent-bright);border-color:rgba(14,165,233,.4)}
109
+ .kbd{font-family:var(--font-mono);font-size:.65rem;color:var(--text-dim);background:rgba(255,255,255,.06);border:1px solid var(--border);border-bottom-width:2px;padding:1px 5px;border-radius:4px;margin-left:4px}
110
+
111
+ /* KPI strip */
112
+ .kpi-strip{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:10px;margin-bottom:20px}
113
+ .kpi{background:var(--glass-bg);backdrop-filter:blur(20px);-webkit-backdrop-filter:blur(20px);border:1px solid var(--glass-border);border-radius:var(--radius);padding:12px 14px;display:flex;flex-direction:column;gap:2px;transition:border-color .25s,transform .25s}
114
+ .kpi:hover{border-color:var(--border-glow);transform:translateY(-2px)}
115
+ .kpi-label{font-size:.66rem;text-transform:uppercase;letter-spacing:.1em;color:var(--text-dim);font-weight:600;display:flex;align-items:center;gap:6px}
116
+ .kpi-label svg{width:12px;height:12px;flex-shrink:0}
117
+ .kpi-value{font-family:var(--font-display);font-size:1.5rem;font-weight:700;line-height:1.1;color:var(--text-primary)}
118
+ .kpi-value.warning{color:var(--warning)}
119
+ .kpi-value.danger{color:var(--danger)}
120
+ .kpi-value.green{color:var(--green)}
121
+ .kpi-value.dim{color:var(--text-dim)}
122
+ .kpi-sub{font-size:.7rem;color:var(--text-dim);font-family:var(--font-mono)}
123
+
124
+ /* Grid */
125
+ .grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(360px,1fr));gap:16px;margin-bottom:16px}
126
+ .grid-wide{grid-column:1/-1}
127
+
128
+ /* Cards \u2014 reveal animation */
129
+ .card{background:var(--glass-bg);backdrop-filter:blur(20px);-webkit-backdrop-filter:blur(20px);border:1px solid var(--glass-border);border-radius:var(--radius);padding:18px 20px;box-shadow:var(--shadow-card);transition:border-color .3s,box-shadow .3s,transform .3s;opacity:0;transform:translateY(16px);animation:cardReveal .5s cubic-bezier(0.16,1,0.3,1) forwards}
130
+ .card:hover{border-color:var(--border-glow);box-shadow:var(--shadow-card),var(--shadow-glow)}
131
+ @keyframes cardReveal{to{opacity:1;transform:translateY(0)}}
132
+
133
+ .card-title{font-family:var(--font-display);font-size:.78rem;text-transform:uppercase;letter-spacing:.1em;color:var(--text-dim);margin-bottom:14px;display:flex;align-items:center;gap:8px;font-weight:600}
134
+ .card-title svg{width:16px;height:16px;flex-shrink:0;filter:drop-shadow(0 0 4px rgba(14,165,233,0.4))}
135
+ .card-title .title-aside{margin-left:auto;font-size:.7rem;color:var(--text-dim);font-weight:400;letter-spacing:.04em;text-transform:none;display:flex;align-items:center;gap:6px}
136
+
137
+ /* Health donut */
138
+ .health-row{display:flex;align-items:center;gap:24px}
139
+ .donut-wrap{position:relative;width:100px;height:100px;flex-shrink:0}
140
+ .donut-wrap svg{transform:rotate(-90deg)}
141
+ .donut-wrap .donut-label{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;flex-direction:column;font-size:1.5rem;font-weight:700;line-height:1;font-family:var(--font-display)}
142
+ .donut-wrap .donut-label small{font-size:.7rem;color:var(--text-dim);font-weight:400;margin-top:2px;letter-spacing:.04em}
143
+ .health-legend{display:flex;flex-direction:column;gap:6px;font-family:var(--font-mono)}
144
+ .legend-item{display:flex;align-items:center;gap:8px;font-size:.82rem}
145
+ .legend-dot{width:8px;height:8px;border-radius:50%;flex-shrink:0}
146
+ .scope-row{display:flex;gap:6px;margin-top:14px;flex-wrap:wrap;font-family:var(--font-mono);font-size:.72rem;color:var(--text-dim)}
147
+ .scope-pill{padding:2px 8px;border-radius:99px;background:rgba(255,255,255,.04);border:1px solid var(--border)}
148
+ .scope-pill strong{color:var(--text-primary);margin-right:4px;font-weight:600}
149
+
150
+ /* Decay bars */
151
+ .decay-list{display:flex;flex-direction:column;gap:8px;max-height:280px;overflow-y:auto}
152
+ .decay-item{display:flex;align-items:center;gap:10px}
153
+ .decay-key{font-family:var(--font-mono);font-size:.85rem;min-width:120px;max-width:180px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
154
+ .decay-bar{flex:1;height:6px;border-radius:3px;background:rgba(255,255,255,0.06);overflow:hidden;position:relative}
155
+ .decay-fill{height:100%;border-radius:3px;transition:width .6s ease}
156
+ .decay-time{font-size:.8rem;color:var(--text-dim);min-width:60px;text-align:right;font-family:var(--font-mono)}
157
+
158
+ /* Superposition pills */
159
+ .super-list{display:flex;flex-direction:column;gap:8px;max-height:280px;overflow-y:auto}
160
+ .super-item{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
161
+ .super-key{font-family:var(--font-mono);font-size:.85rem;min-width:100px}
162
+ .env-pill{font-size:.72rem;padding:2px 8px;border-radius:99px;font-weight:600;letter-spacing:.03em;font-family:var(--font-mono)}
163
+ .env-prod{background:rgba(255,0,85,0.2);color:var(--pink);border:1px solid rgba(255,0,85,0.3)}
164
+ .env-staging{background:rgba(251,191,36,0.15);color:var(--warning);border:1px solid rgba(251,191,36,0.25)}
165
+ .env-dev{background:rgba(34,197,94,0.15);color:var(--green);border:1px solid rgba(34,197,94,0.25)}
166
+ .env-default{background:rgba(168,85,247,0.15);color:var(--violet);border:1px solid rgba(168,85,247,0.25)}
167
+ .env-test{background:rgba(14,165,233,0.15);color:var(--accent-bright);border:1px solid rgba(14,165,233,0.25)}
168
+
169
+ /* Entanglement */
170
+ .entangle-list{display:flex;flex-direction:column;gap:6px;max-height:240px;overflow-y:auto}
171
+ .entangle-pair{display:flex;align-items:center;gap:8px;font-family:var(--font-mono);font-size:.83rem}
172
+ .entangle-arrow{color:var(--accent-bright)}
173
+
174
+ /* Tunnels */
175
+ .tunnel-list{display:flex;flex-direction:column;gap:8px;max-height:240px;overflow-y:auto}
176
+ .tunnel-card{background:rgba(168,85,247,0.06);border:1px solid rgba(168,85,247,0.15);border-radius:var(--radius-sm);padding:10px 12px;font-size:.83rem;font-family:var(--font-mono)}
177
+ .tunnel-meta{display:flex;gap:12px;margin-top:4px;font-size:.78rem;color:var(--text-dim)}
178
+
179
+ /* Audit feed */
180
+ .audit-toolbar{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:10px;align-items:center}
181
+ .audit-actions-strip{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:10px}
182
+ .audit-chip{font-family:var(--font-mono);font-size:.7rem;padding:2px 9px;border-radius:99px;background:rgba(255,255,255,.04);border:1px solid var(--border);color:var(--text-secondary);cursor:pointer;transition:all .2s}
183
+ .audit-chip:hover{border-color:var(--accent);color:var(--text-primary)}
184
+ .audit-chip.active{background:var(--accent-dim);color:var(--accent-bright);border-color:rgba(14,165,233,.4)}
185
+ .audit-chip strong{color:var(--text-primary);margin-left:5px;font-weight:600}
186
+ .audit-feed{display:flex;flex-direction:column;gap:2px;max-height:340px;overflow-y:auto;font-size:.82rem;font-family:var(--font-mono)}
187
+ .audit-row{display:grid;grid-template-columns:78px 76px 56px 1fr;gap:8px;padding:4px 0;border-bottom:1px solid rgba(255,255,255,0.03);align-items:baseline}
188
+ .audit-ts{color:var(--text-dim)}
189
+ .audit-action{font-weight:600}
190
+ .audit-action.read{color:var(--accent)}.audit-action.write{color:var(--green)}.audit-action.delete{color:var(--danger)}
191
+ .audit-action.entangle{color:var(--violet)}.audit-action.tunnel{color:var(--violet)}.audit-action.teleport{color:var(--warning)}
192
+ .audit-action.generate{color:var(--warning)}.audit-action.list{color:var(--text-dim)}.audit-action.export{color:var(--text-dim)}
193
+ .audit-action.collapse{color:var(--accent)}.audit-action.approve{color:var(--green)}.audit-action.revoke{color:var(--danger)}
194
+ .audit-action.policy_deny{color:var(--danger)}.audit-action.rotate{color:var(--violet)}
195
+ .audit-source{color:var(--text-dim);font-size:.72rem;text-transform:uppercase;letter-spacing:.04em}
196
+ .audit-detail{color:var(--text-dim);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
197
+ .audit-key{color:var(--text-secondary)}
198
+
199
+ /* Anomalies */
200
+ .anomaly-list{display:flex;flex-direction:column;gap:8px}
201
+ .anomaly-card{background:rgba(255,94,91,0.06);border:1px solid rgba(255,94,91,0.15);border-radius:var(--radius-sm);padding:10px 14px;animation:anomaly-pulse 3s ease-in-out infinite}
202
+ @keyframes anomaly-pulse{0%,100%{border-color:rgba(255,94,91,0.15)}50%{border-color:rgba(255,94,91,0.4)}}
203
+ .anomaly-type{font-size:.7rem;text-transform:uppercase;letter-spacing:.06em;color:var(--danger);font-weight:700;margin-bottom:2px;font-family:var(--font-display)}
204
+ .anomaly-desc{font-size:.86rem;color:var(--text-primary)}
205
+ .anomaly-hint{font-size:.74rem;color:var(--text-dim);margin-top:4px;font-family:var(--font-mono)}
206
+
207
+ /* Environment badge */
208
+ .env-status{display:flex;align-items:center;gap:12px;flex-wrap:wrap}
209
+ .env-big{font-size:1rem;font-weight:700;padding:4px 14px;border-radius:var(--radius-sm)}
210
+ .env-source{font-size:.78rem;color:var(--text-dim);font-family:var(--font-mono)}
211
+
212
+ /* Manifest */
213
+ .manifest-bars{display:flex;flex-direction:column;gap:8px}
214
+ .manifest-row{display:flex;align-items:center;gap:8px;font-family:var(--font-mono);font-size:.78rem}
215
+ .manifest-bar{flex:1;height:6px;border-radius:3px;background:rgba(255,255,255,.06);overflow:hidden}
216
+ .manifest-fill{height:100%;border-radius:3px}
217
+ .manifest-list{margin-top:10px;display:flex;flex-direction:column;gap:3px;font-family:var(--font-mono);font-size:.78rem;color:var(--text-secondary)}
218
+ .manifest-list .label{color:var(--text-dim);text-transform:uppercase;font-size:.66rem;letter-spacing:.08em;margin-top:6px}
219
+ .manifest-list .key-pill{display:inline-block;padding:1px 6px;background:rgba(255,255,255,.04);border:1px solid var(--border);border-radius:4px;margin:1px 3px 1px 0;font-size:.74rem}
220
+ .manifest-list .key-pill.miss{color:var(--danger);border-color:rgba(255,94,91,.3)}
221
+ .manifest-list .key-pill.exp{color:var(--warning);border-color:rgba(251,191,36,.3)}
222
+
223
+ /* Policy */
224
+ .policy-rows{display:flex;flex-direction:column;gap:6px;font-family:var(--font-mono);font-size:.78rem;color:var(--text-secondary)}
225
+ .policy-row{display:flex;justify-content:space-between;padding:2px 0;border-bottom:1px solid rgba(255,255,255,.04)}
226
+ .policy-label{color:var(--text-dim)}
227
+ .policy-value{color:var(--text-primary)}
228
+ .policy-value.zero{color:var(--text-dim)}
229
+
230
+ /* Approvals */
231
+ .approval-list{display:flex;flex-direction:column;gap:8px;max-height:240px;overflow-y:auto}
232
+ .approval-card{background:rgba(34,197,94,.05);border:1px solid rgba(34,197,94,.2);border-radius:var(--radius-sm);padding:10px 12px;font-size:.82rem}
233
+ .approval-card.tampered{background:rgba(255,94,91,.06);border-color:rgba(255,94,91,.4)}
234
+ .approval-card.expiring{background:rgba(251,191,36,.06);border-color:rgba(251,191,36,.3)}
235
+ .approval-head{display:flex;justify-content:space-between;gap:8px;font-family:var(--font-mono);font-weight:600}
236
+ .approval-reason{color:var(--text-dim);font-size:.76rem;margin-top:3px}
237
+ .approval-meta{display:flex;gap:12px;margin-top:4px;font-size:.72rem;color:var(--text-dim);font-family:var(--font-mono)}
238
+
239
+ /* Hooks */
240
+ .hooks-list{display:flex;flex-direction:column;gap:6px;max-height:240px;overflow-y:auto}
241
+ .hook-row{display:flex;align-items:center;gap:8px;font-family:var(--font-mono);font-size:.8rem;padding:6px 10px;background:rgba(255,255,255,.03);border:1px solid var(--border);border-radius:var(--radius-sm)}
242
+ .hook-row.disabled{opacity:.5}
243
+ .hook-type{font-size:.7rem;text-transform:uppercase;font-weight:600;padding:1px 6px;border-radius:99px;letter-spacing:.04em}
244
+ .hook-type.shell{background:rgba(168,85,247,.15);color:var(--violet)}
245
+ .hook-type.http{background:rgba(14,165,233,.15);color:var(--accent-bright)}
246
+ .hook-type.signal{background:rgba(251,191,36,.15);color:var(--warning)}
247
+ .hook-summary{flex:1;color:var(--text-secondary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
248
+ .hook-id{color:var(--text-dim);font-size:.72rem}
249
+
250
+ /* Secrets table */
251
+ .secrets-toolbar{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:10px;align-items:center}
252
+ .search{flex:1;min-width:180px;display:flex;align-items:center;gap:6px;background:rgba(255,255,255,.04);border:1px solid var(--border);border-radius:var(--radius-sm);padding:5px 10px;transition:border-color .2s}
253
+ .search:focus-within{border-color:var(--accent);box-shadow:0 0 0 3px rgba(14,165,233,.12)}
254
+ .search svg{width:13px;height:13px;color:var(--text-dim);flex-shrink:0}
255
+ .search input{flex:1;background:transparent;border:none;outline:none;color:var(--text-primary);font-family:var(--font-mono);font-size:.82rem}
256
+ .search input::placeholder{color:var(--text-dim)}
257
+ .secrets-table-wrap{max-height:380px;overflow:auto;border:1px solid var(--border);border-radius:var(--radius-sm);background:rgba(4,8,15,.4)}
258
+ .secrets-table{width:100%;border-collapse:collapse;font-family:var(--font-mono);font-size:.78rem}
259
+ .secrets-table thead th{position:sticky;top:0;background:rgba(8,14,24,.95);backdrop-filter:blur(8px);text-align:left;padding:8px 10px;color:var(--text-dim);font-weight:600;font-size:.7rem;text-transform:uppercase;letter-spacing:.05em;border-bottom:1px solid var(--border);cursor:pointer;user-select:none;white-space:nowrap}
260
+ .secrets-table thead th:hover{color:var(--text-primary)}
261
+ .secrets-table thead th .sort-arrow{display:inline-block;margin-left:4px;color:var(--accent-bright);opacity:0;font-size:.7rem}
262
+ .secrets-table thead th.sorted .sort-arrow{opacity:1}
263
+ .secrets-table tbody td{padding:6px 10px;border-bottom:1px solid rgba(255,255,255,.03);color:var(--text-secondary);vertical-align:middle}
264
+ .secrets-table tbody tr:hover td{background:rgba(14,165,233,.05);color:var(--text-primary)}
265
+ .secrets-table .col-key{color:var(--text-primary);font-weight:500;max-width:240px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
266
+ .secrets-table .col-decay{min-width:90px}
267
+ .secrets-table .col-tags{max-width:200px;overflow:hidden}
268
+ .tag-pill{display:inline-block;font-size:.68rem;padding:1px 6px;background:rgba(168,85,247,.1);color:var(--violet);border:1px solid rgba(168,85,247,.2);border-radius:99px;margin-right:3px;font-family:var(--font-mono)}
269
+ .scope-tag{display:inline-block;font-size:.68rem;padding:1px 6px;border-radius:4px;letter-spacing:.04em;font-weight:600;text-transform:uppercase}
270
+ .scope-tag.global{background:rgba(14,165,233,.15);color:var(--accent-bright)}
271
+ .scope-tag.project{background:rgba(34,197,94,.15);color:var(--green)}
272
+ .scope-tag.team{background:rgba(168,85,247,.15);color:var(--violet)}
273
+ .scope-tag.org{background:rgba(251,191,36,.15);color:var(--warning)}
274
+ .type-tag{display:inline-block;font-size:.68rem;padding:1px 6px;border-radius:4px;letter-spacing:.04em;text-transform:uppercase;background:rgba(255,255,255,.05);color:var(--text-dim)}
275
+ .type-tag.superposition{background:rgba(168,85,247,.12);color:var(--violet)}
276
+ .protected-icon{color:var(--warning);margin-left:4px;display:inline-flex;vertical-align:middle}
277
+ .mini-decay{display:inline-flex;align-items:center;gap:6px;width:100%}
278
+ .mini-decay-bar{flex:1;height:4px;border-radius:2px;background:rgba(255,255,255,.06);overflow:hidden;min-width:30px}
279
+ .mini-decay-fill{height:100%;border-radius:2px}
280
+ .mini-decay-time{color:var(--text-dim);font-size:.7rem;min-width:38px;text-align:right}
281
+
282
+ /* Empty states */
283
+ .empty{color:var(--text-dim);font-size:.86rem;font-style:italic;padding:8px 0}
284
+ .empty-cta{margin-top:6px;display:block;font-style:normal;font-family:var(--font-mono);font-size:.78rem;color:var(--accent-bright)}
285
+
286
+ /* Footer */
287
+ .foot{margin-top:24px;text-align:center;color:var(--text-dim);font-size:.72rem;font-family:var(--font-mono)}
288
+ .foot a{color:var(--accent-bright);text-decoration:none}
289
+ .foot a:hover{text-decoration:underline}
290
+
291
+ /* Scrollbar */
292
+ ::-webkit-scrollbar{width:6px;height:6px}
293
+ ::-webkit-scrollbar-track{background:transparent}
294
+ ::-webkit-scrollbar-thumb{background:rgba(255,255,255,0.08);border-radius:3px}
295
+ ::-webkit-scrollbar-thumb:hover{background:rgba(255,255,255,0.15)}
296
+
297
+ /* Print */
298
+ @media print{
299
+ .blob,.header-right{display:none}
300
+ .header{position:static}
301
+ body{background:#fff;color:#000}
302
+ }
303
+ </style>
304
+ </head>
305
+ <body>
306
+
307
+ <!-- Shared SVG gradient definition (referenced by the neon icons) -->
308
+ <svg class="svg-defs" aria-hidden="true" focusable="false">
309
+ <defs>
310
+ <linearGradient id="neon-grad" x1="0%" y1="0%" x2="100%" y2="100%">
311
+ <stop offset="0%" stop-color="#00D1FF"/>
312
+ <stop offset="100%" stop-color="#a855f7"/>
313
+ </linearGradient>
314
+ </defs>
315
+ </svg>
316
+
317
+ <div class="blob blob-1"></div>
318
+ <div class="blob blob-2"></div>
319
+ <div class="blob blob-3"></div>
320
+
321
+ <!-- Preact mounts the entire UI here; see src/dashboard-client/main.js -->
322
+ <div id="app"></div>
323
+
324
+ <script>window.__QRING__=Object.freeze({token:${jsString(token)}});</script>
325
+ <script>${DASHBOARD_CLIENT}</script>
326
+ </body>
327
+ </html>`;
328
+ }
329
+
330
+ // src/core/dashboard.ts
331
+ var AUDIT_WINDOW_SECONDS = 24 * 60 * 60;
332
+ function toSecretSnapshot(entry) {
333
+ const envelope = entry.envelope;
334
+ const decay = envelope ? checkDecay(envelope) : {
335
+ isExpired: false,
336
+ isStale: false,
337
+ lifetimePercent: 0,
338
+ secondsRemaining: null,
339
+ timeRemaining: null
340
+ };
341
+ return {
342
+ key: entry.key,
343
+ scope: entry.scope,
344
+ type: envelope?.states ? "superposition" : "collapsed",
345
+ environments: envelope?.states ? Object.keys(envelope.states) : void 0,
346
+ defaultEnv: envelope?.defaultEnv,
347
+ decay,
348
+ accessCount: envelope?.meta.accessCount ?? 0,
349
+ lastAccessedAt: envelope?.meta.lastAccessedAt,
350
+ createdAt: envelope?.meta.createdAt ?? "",
351
+ updatedAt: envelope?.meta.updatedAt ?? "",
352
+ description: envelope?.meta.description,
353
+ tags: envelope?.meta.tags,
354
+ entangled: envelope?.meta.entangled,
355
+ provider: envelope?.meta.provider,
356
+ requiresApproval: envelope?.meta.requiresApproval,
357
+ jitProvider: envelope?.meta.jitProvider,
358
+ hasRotationFormat: !!envelope?.meta.rotationFormat
359
+ };
360
+ }
361
+ function summariseHookMatch(match) {
362
+ const parts = [];
363
+ if (match.key) parts.push(`key=${match.key}`);
364
+ if (match.keyPattern) parts.push(`pattern=${match.keyPattern}`);
365
+ if (match.tag) parts.push(`tag=${match.tag}`);
366
+ if (match.scope) parts.push(`scope=${match.scope}`);
367
+ if (match.action?.length) parts.push(`on=${match.action.join("|")}`);
368
+ return parts.length ? parts.join(" \xB7 ") : "any change";
369
+ }
370
+ function buildManifest(projectPath, secrets) {
371
+ const config = readProjectConfig(projectPath);
372
+ if (!config?.secrets) return null;
373
+ const declared = Object.keys(config.secrets);
374
+ const projectSecrets = new Map(
375
+ secrets.filter((s) => s.scope === "project").map((s) => [s.key, s])
376
+ );
377
+ const required = [];
378
+ const missing = [];
379
+ const expired = [];
380
+ const stale = [];
381
+ for (const key of declared) {
382
+ const entry = config.secrets[key];
383
+ if (entry.required) required.push(key);
384
+ const present = projectSecrets.get(key);
385
+ if (!present) {
386
+ if (entry.required) missing.push(key);
387
+ continue;
388
+ }
389
+ if (present.decay.isExpired) expired.push(key);
390
+ else if (present.decay.isStale) stale.push(key);
391
+ }
392
+ return {
393
+ declared: declared.length,
394
+ required: required.length,
395
+ missing,
396
+ expired,
397
+ stale
398
+ };
399
+ }
400
+ function buildPolicySnapshot(projectPath) {
401
+ const summary = getPolicySummary(projectPath);
402
+ const mcp = summary.details.mcp ?? {};
403
+ const exec = summary.details.exec ?? {};
404
+ const sec = summary.details.secrets ?? {};
405
+ return {
406
+ hasMcpPolicy: summary.hasMcpPolicy,
407
+ hasExecPolicy: summary.hasExecPolicy,
408
+ hasSecretPolicy: summary.hasSecretPolicy,
409
+ counts: {
410
+ allowTools: mcp.allowTools?.length ?? 0,
411
+ denyTools: mcp.denyTools?.length ?? 0,
412
+ deniedKeys: mcp.deniedKeys?.length ?? 0,
413
+ deniedTags: mcp.deniedTags?.length ?? 0,
414
+ allowCommands: exec.allowCommands?.length ?? 0,
415
+ denyCommands: exec.denyCommands?.length ?? 0,
416
+ requireApprovalForTags: sec.requireApprovalForTags?.length ?? 0,
417
+ requireRotationFormatForTags: sec.requireRotationFormatForTags?.length ?? 0
418
+ },
419
+ maxTtlSeconds: sec.maxTtlSeconds,
420
+ maxRuntimeSeconds: exec.maxRuntimeSeconds
421
+ };
422
+ }
423
+ function buildAuditMetrics(events) {
424
+ const byAction = {};
425
+ const bySource = {};
426
+ const readCounts = /* @__PURE__ */ new Map();
427
+ for (const e of events) {
428
+ byAction[e.action] = (byAction[e.action] ?? 0) + 1;
429
+ bySource[e.source] = (bySource[e.source] ?? 0) + 1;
430
+ if (e.action === "read" && e.key) {
431
+ readCounts.set(e.key, (readCounts.get(e.key) ?? 0) + 1);
432
+ }
433
+ }
434
+ const topRead = [...readCounts.entries()].map(([key, reads]) => ({ key, reads })).sort((a, b) => b.reads - a.reads).slice(0, 10);
435
+ return {
436
+ byAction,
437
+ bySource,
438
+ topRead,
439
+ total: events.length,
440
+ windowSeconds: AUDIT_WINDOW_SECONDS
441
+ };
442
+ }
443
+ function collectSnapshot() {
444
+ const projectPath = process.cwd();
445
+ const entries = listSecrets({ source: "api", silent: true, projectPath });
446
+ const secrets = entries.map(toSecretSnapshot);
447
+ let healthy = 0;
448
+ let stale = 0;
449
+ let expired = 0;
450
+ let noDecay = 0;
451
+ let protectedCount = 0;
452
+ const scopes = { global: 0, project: 0, team: 0, org: 0 };
453
+ for (const s of secrets) {
454
+ if (!s.decay.timeRemaining) noDecay++;
455
+ else if (s.decay.isExpired) expired++;
456
+ else if (s.decay.isStale) stale++;
457
+ else healthy++;
458
+ if (s.requiresApproval) protectedCount++;
459
+ if (s.scope === "global") scopes.global++;
460
+ else if (s.scope === "project") scopes.project++;
461
+ else if (s.scope === "team") scopes.team++;
462
+ else if (s.scope === "org") scopes.org++;
463
+ }
464
+ const auditWindow = queryAudit({
465
+ since: new Date(Date.now() - AUDIT_WINDOW_SECONDS * 1e3).toISOString()
466
+ }).filter((e) => e.action !== "list");
467
+ const recent = auditWindow.slice(0, 80);
468
+ const approvals = listApprovals().map((a) => ({
469
+ id: a.id,
470
+ key: a.key,
471
+ scope: a.scope,
472
+ reason: a.reason,
473
+ grantedBy: a.grantedBy,
474
+ grantedAt: a.grantedAt,
475
+ expiresAt: a.expiresAt,
476
+ secondsRemaining: Math.floor(
477
+ (new Date(a.expiresAt).getTime() - Date.now()) / 1e3
478
+ ),
479
+ valid: a.valid && !a.tampered,
480
+ tampered: a.tampered
481
+ }));
482
+ const hookEntries = listHooks().map((h) => ({
483
+ id: h.id,
484
+ type: h.type,
485
+ description: h.description,
486
+ enabled: h.enabled,
487
+ match: h.match,
488
+ matchSummary: summariseHookMatch(h.match)
489
+ }));
490
+ return {
491
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
492
+ version: PACKAGE_VERSION,
493
+ projectPath,
494
+ secrets,
495
+ health: { healthy, stale, expired, noDecay, total: secrets.length },
496
+ scopes,
497
+ protectedCount,
498
+ entanglements: listEntanglements(),
499
+ tunnels: tunnelList(),
500
+ audit: recent,
501
+ auditMetrics: buildAuditMetrics(auditWindow),
502
+ anomalies: detectAnomalies(),
503
+ environment: collapseEnvironment({ projectPath }),
504
+ manifest: buildManifest(projectPath, secrets),
505
+ policy: buildPolicySnapshot(projectPath),
506
+ approvals,
507
+ hooks: hookEntries,
508
+ memoryKeys: listMemory().length
509
+ };
510
+ }
511
+ function timingSafeStringEqual(a, b) {
512
+ const ab = Buffer.from(a, "utf8");
513
+ const bb = Buffer.from(b, "utf8");
514
+ if (ab.length !== bb.length) return false;
515
+ return timingSafeEqual(ab, bb);
516
+ }
517
+ function startDashboardServer(options = {}) {
518
+ const port = options.port ?? 9876;
519
+ const clients = /* @__PURE__ */ new Set();
520
+ let intervalHandle = null;
521
+ const token = randomBytes(24).toString("base64url");
522
+ const html = getDashboardHtml(token);
523
+ function broadcast() {
524
+ const snapshot = collectSnapshot();
525
+ const data = `data: ${JSON.stringify(snapshot)}
526
+
527
+ `;
528
+ for (const res of clients) {
529
+ if (res.writableEnded || res.destroyed) {
530
+ clients.delete(res);
531
+ continue;
532
+ }
533
+ try {
534
+ const ok = res.write(data);
535
+ if (!ok) {
536
+ clients.delete(res);
537
+ try {
538
+ res.end();
539
+ } catch {
540
+ try {
541
+ res.destroy();
542
+ } catch {
543
+ }
544
+ }
545
+ }
546
+ } catch {
547
+ clients.delete(res);
548
+ try {
549
+ res.end();
550
+ } catch {
551
+ try {
552
+ res.destroy();
553
+ } catch {
554
+ }
555
+ }
556
+ }
557
+ }
558
+ }
559
+ const server = createServer((req, res) => {
560
+ let pathname;
561
+ let query;
562
+ try {
563
+ const parsed = new URL(req.url ?? "/", "http://127.0.0.1");
564
+ pathname = parsed.pathname;
565
+ query = parsed.searchParams;
566
+ } catch {
567
+ res.writeHead(400, { "Content-Type": "text/plain; charset=utf-8" });
568
+ res.end("Bad Request: invalid URL");
569
+ return;
570
+ }
571
+ const provided = query.get("token") ?? "";
572
+ if (!timingSafeStringEqual(provided, token)) {
573
+ res.writeHead(403, { "Content-Type": "text/plain; charset=utf-8" });
574
+ res.end("Forbidden: missing or invalid token");
575
+ return;
576
+ }
577
+ if (pathname === "/events") {
578
+ res.writeHead(200, {
579
+ "Content-Type": "text/event-stream",
580
+ "Cache-Control": "no-cache",
581
+ Connection: "keep-alive"
582
+ });
583
+ const snapshot = collectSnapshot();
584
+ res.write(`data: ${JSON.stringify(snapshot)}
585
+
586
+ `);
587
+ clients.add(res);
588
+ req.on("close", () => clients.delete(res));
589
+ return;
590
+ }
591
+ if (pathname === "/api/status") {
592
+ const snapshot = collectSnapshot();
593
+ res.writeHead(200, {
594
+ "Content-Type": "application/json"
595
+ });
596
+ res.end(JSON.stringify(snapshot, null, 2));
597
+ return;
598
+ }
599
+ res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
600
+ res.end(html);
601
+ });
602
+ server.listen(port, "127.0.0.1", () => {
603
+ intervalHandle = setInterval(broadcast, 5e3);
604
+ if (intervalHandle && typeof intervalHandle === "object" && "unref" in intervalHandle) {
605
+ intervalHandle.unref();
606
+ }
607
+ });
608
+ return {
609
+ port,
610
+ token,
611
+ url: `http://127.0.0.1:${port}/?token=${token}`,
612
+ close: () => {
613
+ if (intervalHandle) clearInterval(intervalHandle);
614
+ for (const res of clients) {
615
+ try {
616
+ res.end();
617
+ } catch {
618
+ }
619
+ }
620
+ clients.clear();
621
+ server.close();
622
+ },
623
+ server
624
+ };
625
+ }
626
+ export {
627
+ collectSnapshot,
628
+ startDashboardServer
629
+ };
630
+ //# sourceMappingURL=dashboard-HHJY73JX.js.map