@suveren/gateway 0.9.0 → 0.10.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.
- package/README.md +33 -1
- package/bin/suveren-gateway.js +203 -5
- package/content/integrations/erp.json +184 -0
- package/content/integrations/index.json +2 -1
- package/dist/control-plane/index.mjs +653 -179
- package/dist/mcp-server/http.mjs +466 -259
- package/dist/ui/assets/{index-CIiOCgjJ.js → index-B1qNl7zo.js} +1 -1
- package/dist/ui/index.html +1 -1
- package/lib/as-pairing.mjs +77 -0
- package/lib/config.mjs +48 -0
- package/node_modules/undici/LICENSE +21 -0
- package/node_modules/undici/README.md +741 -0
- package/node_modules/undici/docs/docs/api/Agent.md +84 -0
- package/node_modules/undici/docs/docs/api/BalancedPool.md +99 -0
- package/node_modules/undici/docs/docs/api/CacheStorage.md +30 -0
- package/node_modules/undici/docs/docs/api/CacheStore.md +164 -0
- package/node_modules/undici/docs/docs/api/Client.md +288 -0
- package/node_modules/undici/docs/docs/api/ClientStats.md +27 -0
- package/node_modules/undici/docs/docs/api/Connector.md +115 -0
- package/node_modules/undici/docs/docs/api/ContentType.md +57 -0
- package/node_modules/undici/docs/docs/api/Cookies.md +128 -0
- package/node_modules/undici/docs/docs/api/Debug.md +62 -0
- package/node_modules/undici/docs/docs/api/DiagnosticsChannel.md +317 -0
- package/node_modules/undici/docs/docs/api/Dispatcher.md +1393 -0
- package/node_modules/undici/docs/docs/api/EnvHttpProxyAgent.md +159 -0
- package/node_modules/undici/docs/docs/api/Errors.md +49 -0
- package/node_modules/undici/docs/docs/api/EventSource.md +45 -0
- package/node_modules/undici/docs/docs/api/Fetch.md +60 -0
- package/node_modules/undici/docs/docs/api/GlobalInstallation.md +139 -0
- package/node_modules/undici/docs/docs/api/H2CClient.md +263 -0
- package/node_modules/undici/docs/docs/api/MockAgent.md +603 -0
- package/node_modules/undici/docs/docs/api/MockCallHistory.md +197 -0
- package/node_modules/undici/docs/docs/api/MockCallHistoryLog.md +43 -0
- package/node_modules/undici/docs/docs/api/MockClient.md +81 -0
- package/node_modules/undici/docs/docs/api/MockErrors.md +12 -0
- package/node_modules/undici/docs/docs/api/MockPool.md +555 -0
- package/node_modules/undici/docs/docs/api/Pool.md +84 -0
- package/node_modules/undici/docs/docs/api/PoolStats.md +35 -0
- package/node_modules/undici/docs/docs/api/ProxyAgent.md +229 -0
- package/node_modules/undici/docs/docs/api/RedirectHandler.md +93 -0
- package/node_modules/undici/docs/docs/api/RetryAgent.md +50 -0
- package/node_modules/undici/docs/docs/api/RetryHandler.md +118 -0
- package/node_modules/undici/docs/docs/api/RoundRobinPool.md +145 -0
- package/node_modules/undici/docs/docs/api/SnapshotAgent.md +616 -0
- package/node_modules/undici/docs/docs/api/Socks5ProxyAgent.md +275 -0
- package/node_modules/undici/docs/docs/api/Util.md +25 -0
- package/node_modules/undici/docs/docs/api/WebSocket.md +141 -0
- package/node_modules/undici/docs/docs/api/api-lifecycle.md +91 -0
- package/node_modules/undici/docs/docs/best-practices/client-certificate.md +64 -0
- package/node_modules/undici/docs/docs/best-practices/crawling.md +58 -0
- package/node_modules/undici/docs/docs/best-practices/mocking-request.md +190 -0
- package/node_modules/undici/docs/docs/best-practices/proxy.md +127 -0
- package/node_modules/undici/docs/docs/best-practices/undici-vs-builtin-fetch.md +224 -0
- package/node_modules/undici/docs/docs/best-practices/writing-tests.md +63 -0
- package/node_modules/undici/index-fetch.js +65 -0
- package/node_modules/undici/index.d.ts +3 -0
- package/node_modules/undici/index.js +234 -0
- package/node_modules/undici/lib/api/abort-signal.js +59 -0
- package/node_modules/undici/lib/api/api-connect.js +110 -0
- package/node_modules/undici/lib/api/api-pipeline.js +252 -0
- package/node_modules/undici/lib/api/api-request.js +214 -0
- package/node_modules/undici/lib/api/api-stream.js +209 -0
- package/node_modules/undici/lib/api/api-upgrade.js +111 -0
- package/node_modules/undici/lib/api/index.js +7 -0
- package/node_modules/undici/lib/api/readable.js +580 -0
- package/node_modules/undici/lib/cache/memory-cache-store.js +279 -0
- package/node_modules/undici/lib/cache/sqlite-cache-store.js +467 -0
- package/node_modules/undici/lib/core/connect.js +153 -0
- package/node_modules/undici/lib/core/constants.js +143 -0
- package/node_modules/undici/lib/core/diagnostics.js +227 -0
- package/node_modules/undici/lib/core/errors.js +477 -0
- package/node_modules/undici/lib/core/request.js +485 -0
- package/node_modules/undici/lib/core/socks5-client.js +422 -0
- package/node_modules/undici/lib/core/socks5-utils.js +212 -0
- package/node_modules/undici/lib/core/symbols.js +75 -0
- package/node_modules/undici/lib/core/tree.js +160 -0
- package/node_modules/undici/lib/core/util.js +992 -0
- package/node_modules/undici/lib/dispatcher/agent.js +158 -0
- package/node_modules/undici/lib/dispatcher/balanced-pool.js +221 -0
- package/node_modules/undici/lib/dispatcher/client-h1.js +1746 -0
- package/node_modules/undici/lib/dispatcher/client-h2.js +1060 -0
- package/node_modules/undici/lib/dispatcher/client.js +668 -0
- package/node_modules/undici/lib/dispatcher/dispatcher-base.js +184 -0
- package/node_modules/undici/lib/dispatcher/dispatcher.js +48 -0
- package/node_modules/undici/lib/dispatcher/env-http-proxy-agent.js +146 -0
- package/node_modules/undici/lib/dispatcher/fixed-queue.js +135 -0
- package/node_modules/undici/lib/dispatcher/h2c-client.js +51 -0
- package/node_modules/undici/lib/dispatcher/pool-base.js +214 -0
- package/node_modules/undici/lib/dispatcher/pool.js +118 -0
- package/node_modules/undici/lib/dispatcher/proxy-agent.js +319 -0
- package/node_modules/undici/lib/dispatcher/retry-agent.js +35 -0
- package/node_modules/undici/lib/dispatcher/round-robin-pool.js +137 -0
- package/node_modules/undici/lib/dispatcher/socks5-proxy-agent.js +260 -0
- package/node_modules/undici/lib/encoding/index.js +33 -0
- package/node_modules/undici/lib/global.js +59 -0
- package/node_modules/undici/lib/handler/cache-handler.js +776 -0
- package/node_modules/undici/lib/handler/cache-revalidation-handler.js +124 -0
- package/node_modules/undici/lib/handler/decorator-handler.js +67 -0
- package/node_modules/undici/lib/handler/deduplication-handler.js +460 -0
- package/node_modules/undici/lib/handler/redirect-handler.js +238 -0
- package/node_modules/undici/lib/handler/retry-handler.js +504 -0
- package/node_modules/undici/lib/handler/unwrap-handler.js +106 -0
- package/node_modules/undici/lib/handler/wrap-handler.js +105 -0
- package/node_modules/undici/lib/interceptor/cache.js +621 -0
- package/node_modules/undici/lib/interceptor/decompress.js +551 -0
- package/node_modules/undici/lib/interceptor/deduplicate.js +117 -0
- package/node_modules/undici/lib/interceptor/dns.js +571 -0
- package/node_modules/undici/lib/interceptor/dump.js +99 -0
- package/node_modules/undici/lib/interceptor/redirect.js +21 -0
- package/node_modules/undici/lib/interceptor/response-error.js +95 -0
- package/node_modules/undici/lib/interceptor/retry.js +19 -0
- package/node_modules/undici/lib/llhttp/.gitkeep +0 -0
- package/node_modules/undici/lib/llhttp/constants.d.ts +195 -0
- package/node_modules/undici/lib/llhttp/constants.js +531 -0
- package/node_modules/undici/lib/llhttp/llhttp-wasm.js +15 -0
- package/node_modules/undici/lib/llhttp/llhttp_simd-wasm.js +15 -0
- package/node_modules/undici/lib/llhttp/utils.d.ts +2 -0
- package/node_modules/undici/lib/llhttp/utils.js +12 -0
- package/node_modules/undici/lib/mock/mock-agent.js +232 -0
- package/node_modules/undici/lib/mock/mock-call-history.js +248 -0
- package/node_modules/undici/lib/mock/mock-client.js +68 -0
- package/node_modules/undici/lib/mock/mock-errors.js +29 -0
- package/node_modules/undici/lib/mock/mock-interceptor.js +209 -0
- package/node_modules/undici/lib/mock/mock-pool.js +68 -0
- package/node_modules/undici/lib/mock/mock-symbols.js +32 -0
- package/node_modules/undici/lib/mock/mock-utils.js +486 -0
- package/node_modules/undici/lib/mock/pending-interceptors-formatter.js +43 -0
- package/node_modules/undici/lib/mock/snapshot-agent.js +353 -0
- package/node_modules/undici/lib/mock/snapshot-recorder.js +588 -0
- package/node_modules/undici/lib/mock/snapshot-utils.js +158 -0
- package/node_modules/undici/lib/util/cache.js +676 -0
- package/node_modules/undici/lib/util/date.js +670 -0
- package/node_modules/undici/lib/util/promise.js +28 -0
- package/node_modules/undici/lib/util/runtime-features.js +124 -0
- package/node_modules/undici/lib/util/stats.js +32 -0
- package/node_modules/undici/lib/util/timers.js +425 -0
- package/node_modules/undici/lib/web/cache/cache.js +864 -0
- package/node_modules/undici/lib/web/cache/cachestorage.js +152 -0
- package/node_modules/undici/lib/web/cache/util.js +45 -0
- package/node_modules/undici/lib/web/cookies/constants.js +12 -0
- package/node_modules/undici/lib/web/cookies/index.js +199 -0
- package/node_modules/undici/lib/web/cookies/parse.js +314 -0
- package/node_modules/undici/lib/web/cookies/util.js +352 -0
- package/node_modules/undici/lib/web/eventsource/eventsource-stream.js +494 -0
- package/node_modules/undici/lib/web/eventsource/eventsource.js +501 -0
- package/node_modules/undici/lib/web/eventsource/util.js +29 -0
- package/node_modules/undici/lib/web/fetch/LICENSE +21 -0
- package/node_modules/undici/lib/web/fetch/body.js +509 -0
- package/node_modules/undici/lib/web/fetch/constants.js +131 -0
- package/node_modules/undici/lib/web/fetch/data-url.js +596 -0
- package/node_modules/undici/lib/web/fetch/formdata-parser.js +586 -0
- package/node_modules/undici/lib/web/fetch/formdata.js +259 -0
- package/node_modules/undici/lib/web/fetch/global.js +40 -0
- package/node_modules/undici/lib/web/fetch/headers.js +719 -0
- package/node_modules/undici/lib/web/fetch/index.js +2413 -0
- package/node_modules/undici/lib/web/fetch/request.js +1115 -0
- package/node_modules/undici/lib/web/fetch/response.js +641 -0
- package/node_modules/undici/lib/web/fetch/util.js +1522 -0
- package/node_modules/undici/lib/web/infra/index.js +229 -0
- package/node_modules/undici/lib/web/subresource-integrity/Readme.md +9 -0
- package/node_modules/undici/lib/web/subresource-integrity/subresource-integrity.js +307 -0
- package/node_modules/undici/lib/web/webidl/index.js +1006 -0
- package/node_modules/undici/lib/web/websocket/connection.js +339 -0
- package/node_modules/undici/lib/web/websocket/constants.js +126 -0
- package/node_modules/undici/lib/web/websocket/events.js +331 -0
- package/node_modules/undici/lib/web/websocket/frame.js +133 -0
- package/node_modules/undici/lib/web/websocket/permessage-deflate.js +105 -0
- package/node_modules/undici/lib/web/websocket/receiver.js +507 -0
- package/node_modules/undici/lib/web/websocket/sender.js +109 -0
- package/node_modules/undici/lib/web/websocket/stream/websocketerror.js +104 -0
- package/node_modules/undici/lib/web/websocket/stream/websocketstream.js +496 -0
- package/node_modules/undici/lib/web/websocket/util.js +347 -0
- package/node_modules/undici/lib/web/websocket/websocket.js +758 -0
- package/node_modules/undici/package.json +152 -0
- package/node_modules/undici/scripts/strip-comments.js +10 -0
- package/node_modules/undici/types/README.md +6 -0
- package/node_modules/undici/types/agent.d.ts +32 -0
- package/node_modules/undici/types/api.d.ts +43 -0
- package/node_modules/undici/types/balanced-pool.d.ts +30 -0
- package/node_modules/undici/types/cache-interceptor.d.ts +179 -0
- package/node_modules/undici/types/cache.d.ts +36 -0
- package/node_modules/undici/types/client-stats.d.ts +15 -0
- package/node_modules/undici/types/client.d.ts +139 -0
- package/node_modules/undici/types/connector.d.ts +36 -0
- package/node_modules/undici/types/content-type.d.ts +21 -0
- package/node_modules/undici/types/cookies.d.ts +30 -0
- package/node_modules/undici/types/diagnostics-channel.d.ts +74 -0
- package/node_modules/undici/types/dispatcher.d.ts +275 -0
- package/node_modules/undici/types/env-http-proxy-agent.d.ts +22 -0
- package/node_modules/undici/types/errors.d.ts +177 -0
- package/node_modules/undici/types/eventsource.d.ts +66 -0
- package/node_modules/undici/types/fetch.d.ts +231 -0
- package/node_modules/undici/types/formdata.d.ts +114 -0
- package/node_modules/undici/types/global-dispatcher.d.ts +9 -0
- package/node_modules/undici/types/global-origin.d.ts +7 -0
- package/node_modules/undici/types/h2c-client.d.ts +73 -0
- package/node_modules/undici/types/handlers.d.ts +14 -0
- package/node_modules/undici/types/header.d.ts +160 -0
- package/node_modules/undici/types/index.d.ts +91 -0
- package/node_modules/undici/types/interceptors.d.ts +82 -0
- package/node_modules/undici/types/mock-agent.d.ts +68 -0
- package/node_modules/undici/types/mock-call-history.d.ts +111 -0
- package/node_modules/undici/types/mock-client.d.ts +27 -0
- package/node_modules/undici/types/mock-errors.d.ts +12 -0
- package/node_modules/undici/types/mock-interceptor.d.ts +94 -0
- package/node_modules/undici/types/mock-pool.d.ts +27 -0
- package/node_modules/undici/types/patch.d.ts +29 -0
- package/node_modules/undici/types/pool-stats.d.ts +19 -0
- package/node_modules/undici/types/pool.d.ts +41 -0
- package/node_modules/undici/types/proxy-agent.d.ts +29 -0
- package/node_modules/undici/types/readable.d.ts +68 -0
- package/node_modules/undici/types/retry-agent.d.ts +8 -0
- package/node_modules/undici/types/retry-handler.d.ts +125 -0
- package/node_modules/undici/types/round-robin-pool.d.ts +41 -0
- package/node_modules/undici/types/snapshot-agent.d.ts +109 -0
- package/node_modules/undici/types/socks5-proxy-agent.d.ts +25 -0
- package/node_modules/undici/types/util.d.ts +18 -0
- package/node_modules/undici/types/utility.d.ts +7 -0
- package/node_modules/undici/types/webidl.d.ts +347 -0
- package/node_modules/undici/types/websocket.d.ts +188 -0
- package/package.json +4 -2
|
@@ -71,7 +71,7 @@ Watch out — What should the agent avoid or be careful about?`;function qy(e,t,
|
|
|
71
71
|
.profile-grid .card { display: flex; flex-direction: column; height: 100%; margin-top: 0 !important; }
|
|
72
72
|
@media (max-width: 900px) { .profile-grid { grid-template-columns: repeat(2, 1fr); } }
|
|
73
73
|
@media (max-width: 560px) { .profile-grid { grid-template-columns: 1fr; } }
|
|
74
|
-
`}),p?s.jsx("p",{style:{color:"var(--text-tertiary)",fontSize:"0.9rem"},children:"Loading..."}):v.length===0?s.jsxs("div",{className:"card",style:{padding:"2rem",textAlign:"center"},children:[s.jsx("p",{style:{color:"var(--text-secondary)",fontSize:"0.9rem",marginBottom:"1rem"},children:"No integrations set up yet. Connect a service first."}),s.jsx(Je,{to:"/integrations",className:"btn btn-primary btn-sm",onClick:()=>e==null?void 0:e(),children:"Go to Integrations"})]}):s.jsx("div",{className:"profile-grid",children:v.map(({manifest:C,profile:R,integration:E})=>{const L=S(R.id),D=(E==null?void 0:E.running)===!0;return s.jsxs("div",{className:"card",style:D?void 0:{opacity:.7},children:[s.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"0.5rem",marginBottom:"0.125rem"},children:[s.jsx("h3",{className:"card-title",style:{margin:0},children:C.name}),L?s.jsx("span",{style:{fontSize:"0.6rem",padding:"0.1rem 0.35rem",borderRadius:"0.2rem",background:"var(--accent-subtle)",color:"var(--accent)",fontWeight:600},children:"Team"}):s.jsx("span",{style:{fontSize:"0.6rem",padding:"0.1rem 0.35rem",borderRadius:"0.2rem",background:"var(--bg-main)",color:"var(--text-tertiary)",fontWeight:600,border:"1px solid var(--border)"},children:"Personal"})]}),s.jsx("p",{style:{fontSize:"0.8rem",color:"var(--text-tertiary)",marginBottom:"1rem",flex:1},children:C.description||R.description}),D?s.jsx("button",{className:"btn btn-primary btn-sm",onClick:()=>N(R.id),children:"Give a mandate"}):s.jsxs(Je,{to:`/integrations?setup=${(C==null?void 0:C.id)??""}`,className:"btn btn-secondary btn-sm",style:{textDecoration:"none",textAlign:"center"},onClick:()=>e==null?void 0:e(),children:["Set up ",(C==null?void 0:C.name)??"integration"]})]},C.id)})})]})}const hx={active:"Active",pending:"Pending",expired:"Expired",revoked:"Revoked"};function gx({status:e,label:t}){return s.jsx("span",{className:`status-badge status-${e}`,children:t||hx[e]})}function vx({domain:e,attested:t}){const n=t===!0?"domain-attested":t===!1?"domain-missing":"";return s.jsx("span",{className:`domain-badge ${n}`,style:{fontSize:"0.75rem"},children:e})}const Tn=86400,Lr=3600,Ds=60,yx=30*Tn;function xx(e){if(e<=0)return"Expired";if(e>90*Tn){const t=Math.floor(e/yx);return`${t} ${t===1?"month":"months"} remaining`}if(e>7*Tn){const t=Math.floor(e/Tn);return`${t} ${t===1?"day":"days"} remaining`}if(e>=2*Tn){const t=Math.floor(e/Tn),n=Math.floor(e%Tn/Lr);return`${t} ${t===1?"day":"days"} ${n}h remaining`}if(e>=2*Lr){const t=Math.floor(e/Lr),n=Math.floor(e%Lr/Ds);return`${t}h ${String(n).padStart(2,"0")}m remaining`}if(e>=Ds){const t=Math.floor(e/Ds),n=Math.floor(e%Ds);return`${t}m ${String(n).padStart(2,"0")}s remaining`}return`${Math.floor(e)}s remaining`}function wx({expiresAt:e}){const[t,n]=u.useState(()=>e-Date.now()/1e3),r=t<2*Lr;u.useEffect(()=>{const o=setInterval(()=>n(e-Date.now()/1e3),r?1e3:6e4);return()=>clearInterval(o)},[e,r]);const a=t<300;return s.jsx("span",{className:`ttl-badge ${a?"ttl-warn":"ttl-ok"}`,children:xx(t)})}function vm({icon:e,title:t,text:n,children:r}){return s.jsxs("div",{className:"empty-state",children:[e&&s.jsx("div",{className:"empty-state-icon",children:e}),s.jsx("div",{className:"empty-state-title",children:t}),n&&s.jsx("div",{className:"empty-state-text",children:n}),r]})}function Sx(e){const t=Math.floor(e/86400);if(t>=1)return`${t} day${t===1?"":"s"}`;const n=Math.floor(e/3600);if(n>=1)return`${n} hour${n===1?"":"s"}`;const r=Math.ceil(e/60);return`${r} minute${r===1?"":"s"}`}const jx=[{label:"30m",seconds:1800},{label:"1h",seconds:3600},{label:"2h",seconds:7200},{label:"4h",seconds:14400},{label:"8h",seconds:28800},{label:"24h",seconds:86400},{label:"7d",seconds:604800},{label:"30d",seconds:2592e3},{label:"1y",seconds:31536e3}];function kx({item:e,onClose:t,onSuccess:n}){var v;const{user:r,activeDomain:a,groupId:o}=Oe(),[i,l]=u.useState(null);u.useEffect(()=>{let S=!1;return T.getProfile(e.profile_id).then(b=>{var N;S||l(((N=b==null?void 0:b.ttl)==null?void 0:N.max)??null)}).catch(()=>{}),()=>{S=!0}},[e.profile_id]);const c=e.remaining_seconds??0,d=jx.filter(S=>S.seconds>c&&(i===null||S.seconds<=i)),f=((v=d[0])==null?void 0:v.seconds)??2592e3,[p,m]=u.useState(f);u.useEffect(()=>{var S;if(i!==null&&p>i){const b=(S=d[d.length-1])==null?void 0:S.seconds;b&&m(b)}},[i]);const[w,y]=u.useState(!1),[x,j]=u.useState(""),g=Object.entries(e.frame).filter(([S])=>S!=="profile"&&S!=="path"),h=async()=>{var S;if(r){y(!0),j("");try{const b=e.authorization_id,N=await T.getGateContent(b);if(!N)throw new Error("Gate content not found locally. The MCP server may have restarted. Please re-authorize through the full wizard instead.");const C=await T.getProfile(e.profile_id),R=e.frame,E=N.context??{},L=e.attested_domains[0]||a||"owner",D=await ra(R,C),V=await pm(E,C),[J,U]=await Promise.all([Pa(N.gateContent.intent),Pa(JSON.stringify({profile:e.profile_id,path:e.path,domain:L}))]);if(!o)throw new Error("No active group; cannot extend mandate.");const P=(((S=e.deferred_commitment_domains)==null?void 0:S.length)??0)>0?"review":"automatic",ee=await T.attest({authorization_id:e.authorization_id,renew:!0,profile_id:e.profile_id,bounds:R,bounds_hash:D,context_hash:V,domain:L,did:r.did,gate_content_hashes:{intent:J},execution_context_hash:U,group_id:o,commitment_mode:P,ttl:p});await T.pushGateContent(hm(ee,{boundsHash:D,contextHash:V,context:E,path:e.path,gateContent:N.gateContent})),n()}catch(b){j(b instanceof Error?b.message:"Extension failed")}finally{y(!1)}}};return s.jsx("div",{className:"modal-backdrop",onClick:S=>S.target===S.currentTarget&&t(),children:s.jsxs("div",{className:"modal",children:[s.jsxs("div",{className:"modal-header",children:[s.jsx("h3",{className:"modal-title",children:"Extend mandate"}),s.jsx("button",{className:"modal-close",onClick:t,children:"×"})]}),s.jsxs("div",{className:"modal-body",children:[s.jsxs("div",{style:{marginBottom:"1rem"},children:[s.jsxs("div",{style:{fontWeight:600,marginBottom:"0.25rem"},children:[Le(e.profile_id)," / ",e.path]}),g.length>0&&s.jsx("div",{style:{fontSize:"0.8rem",color:"var(--text-tertiary)"},children:g.map(([S,b])=>`${S}=${b}`).join(" · ")})]}),s.jsxs("div",{style:{marginBottom:"1rem"},children:[s.jsx("div",{style:{fontSize:"0.75rem",fontWeight:600,color:"var(--text-tertiary)",textTransform:"uppercase",letterSpacing:"0.04em",marginBottom:"0.5rem"},children:"New duration"}),c>0&&s.jsxs("div",{style:{fontSize:"0.75rem",color:"var(--text-tertiary)",marginBottom:"0.5rem"},children:["Currently valid for ",Sx(c),". Only longer durations are shown."]}),s.jsx("div",{style:{display:"flex",gap:"0.5rem",flexWrap:"wrap"},children:d.length===0?s.jsx("div",{style:{fontSize:"0.8rem",color:"var(--text-tertiary)"},children:"This mandate is already on the longest available duration. Nothing to extend."}):d.map(S=>s.jsx("button",{className:`btn ${p===S.seconds?"btn-primary":"btn-secondary"}`,onClick:()=>m(S.seconds),style:{minWidth:"3.5rem"},children:S.label},S.seconds))})]}),s.jsx("div",{style:{fontSize:"0.8rem",color:"var(--text-tertiary)",marginBottom:"0.5rem"},children:"Same bounds, scope, and gate content will be re-signed with a new TTL (measured from now)."}),x&&s.jsx("div",{className:"error-message",children:x})]}),s.jsxs("div",{className:"modal-footer",children:[s.jsx("button",{className:"btn btn-secondary",onClick:t,disabled:w,children:"Cancel"}),s.jsx("button",{className:"btn btn-primary",onClick:h,disabled:w,children:w?"Extending...":"Extend"})]})]})})}function bx(e,t,n){return[...e].sort((r,a)=>{if(n){if(r.authorization_id===n&&a.authorization_id!==n)return-1;if(a.authorization_id===n&&r.authorization_id!==n)return 1}const o=Ra(r,t),i=Ra(a,t),l={active:0,pending:1,expired:2,revoked:3,archived:4};return l[o]!==l[i]?l[o]-l[i]:new Date(a.created_at).getTime()-new Date(r.created_at).getTime()})}function Cx({item:e,newerProfile:t,revokedSet:n,expandedHash:r,gateCache:a,gateLoading:o,copiedHash:i,revokingHash:l,copyingHash:c,profileConfigCache:d,mode:f,ownerLabel:p,isAdmin:m,onExpand:w,onCopyHash:y,onCopy:x,onRevoke:j,onExtend:g,archivedSet:h,archivingHash:v,onArchive:S,highlightHash:b}){var me;const N=Ll(e,{revokedSet:n}),C=em(e,{revokedSet:n,archivedSet:h}),R=!p&&!!S&&Zf(N),E=r===e.authorization_id,L=a[e.authorization_id],D=N==="active"||N==="pending"||N==="expired",V=Object.entries(e.frame).filter(([te])=>te!=="profile"&&te!=="path"),J=d.get(e.profile_id)??null,U=(((me=J==null?void 0:J.approvers)==null?void 0:me.length)??0)>0,P=new Map;if(J!=null&&J.caps&&f==="team")for(const[te,oe]of V){const se=J.caps[te];se!==void 0&&Number(oe)>se&&P.set(te,{authorized:Number(oe),cap:se})}const ee=P.size>0,F=e.approvers_frozen??[],$=(J==null?void 0:J.approvers)??[],z=f==="team"&&F.length>0&&$.length>0&&(F.length!==$.length||F.some(te=>!$.includes(te))||$.some(te=>!F.includes(te))),W=Array.from(P.entries()).map(([te,oe])=>`${te}: ${oe.authorized} (cap ${oe.cap})`).join(", "),I=Array.from(P.entries()).map(([te,oe])=>`${te}: ${oe.authorized} → ${oe.cap}`).join(", "),B=ee?U?P.size===1?`Above team cap: ${W} — actions require approval`:`Above team cap (${P.size}): ${W} — actions require approval`:P.size===1?`Reduced by hard cap: ${I}`:`Reduced by hard cap (${P.size}): ${I}`:"",Q=ee?U?"Above-cap actions under this mandate require per-action approval from the profile's approvers. Bounds remain authorized at their original values.":"No approvers are configured for this profile, so the team cap is a hard ceiling. Bounds above the cap are effectively reduced to the cap. Ask the admin to raise the cap or add approvers, or copy this mandate to reissue within the cap.":void 0,q=Le(e.profile_id),re=t?s.jsxs("div",{style:{fontSize:"0.75rem",color:"var(--text-tertiary)",marginBottom:"0.5rem",padding:"0.4rem 0.6rem",border:"1px solid var(--border)",borderRadius:6},children:[s.jsxs("strong",{style:{color:"var(--text-secondary)"},children:[q,"@",t.version," available"]}),t.whatsNew?s.jsxs(s.Fragment,{children:[" — ",t.whatsNew]}):null,s.jsx("br",{}),s.jsxs("span",{children:["This mandate stays on ",e.profile_id.split("@")[1]??"its pinned version","; authorize again to move it."]})]}):null,ce=b!=null&&e.authorization_id===b;return s.jsxs("div",{className:`card${ce?" card-highlight":""}`,style:{marginBottom:0},children:[re,p&&s.jsxs("div",{style:{fontSize:"0.75rem",color:"var(--text-tertiary)",marginBottom:"0.375rem"},children:["Owner: ",s.jsx("span",{style:{color:"var(--text-secondary)",fontWeight:500},children:p})]}),s.jsxs("div",{className:"auth-card-header",children:[s.jsx("span",{style:{fontWeight:700,fontSize:"1rem",color:"var(--text-primary)",letterSpacing:"0.01em"},children:q}),e.title&&s.jsx("span",{style:{fontWeight:500,fontSize:"0.85rem",color:"var(--text-secondary)"},children:e.title}),s.jsx(gx,{status:N}),N==="active"&&e.earliest_expiry&&s.jsx(wx,{expiresAt:new Date(e.earliest_expiry).getTime()/1e3}),N==="expired"&&(()=>{const te=Lv(e,N);return te?s.jsx("span",{style:{fontSize:"0.75rem",color:"var(--text-tertiary)"},title:`Expired ${new Date(te.iso).toLocaleString()}`,children:new Date(te.iso).toLocaleDateString(void 0,{month:"short",day:"numeric"})}):null})()]}),s.jsxs("div",{style:{display:"flex",gap:"0.5rem",flexWrap:"wrap",marginBottom:"0.5rem",alignItems:"center"},children:[e.required_domains.map(te=>s.jsx(vx,{domain:te,attested:e.attested_domains.includes(te)},te)),e.deferred_commitment_domains.length>0&&s.jsx("span",{style:{fontSize:"0.65rem",padding:"0.15rem 0.4rem",borderRadius:"0.25rem",background:"var(--accent-subtle)",color:"var(--accent)",fontWeight:600},children:"Review Mode"}),ee&&s.jsx("span",{title:Q,style:{fontSize:"0.65rem",padding:"0.15rem 0.4rem",borderRadius:"0.25rem",background:U?"var(--accent-subtle)":"var(--danger-subtle)",color:U?"var(--accent)":"var(--danger)",fontWeight:600,cursor:"help"},children:B}),z&&s.jsx("button",{className:"btn btn-ghost btn-sm",style:{fontSize:"0.65rem",padding:"0.15rem 0.5rem",borderRadius:"0.25rem",background:"var(--warning-subtle, rgba(234,179,8,0.12))",color:"var(--warning, #ca8a04)",fontWeight:600,border:"1px solid var(--warning-border, rgba(234,179,8,0.3))",cursor:"pointer",lineHeight:1.4},onClick:()=>x(e),disabled:c===e.authorization_id,title:"The approver list for this profile has changed since this mandate was created. Copy to reissue with the current approvers.",children:c===e.authorization_id?"Copying...":"Approver list updated · Copy with new approvers"})]}),V.length>0&&s.jsx("div",{style:{fontSize:"0.8rem",color:"var(--text-tertiary)"},children:V.map(([te,oe],se)=>{const _=P.get(te);return s.jsxs("span",{children:[se>0&&" · ",_?U?s.jsxs("span",{title:`Team cap on ${te} is ${_.cap}. Actions exceeding the cap require per-action approval. Bound remains authorized at ${_.authorized}.`,children:[s.jsxs("span",{style:{color:"var(--text-tertiary)"},children:[te,"=",String(oe)]}),s.jsxs("span",{style:{color:"var(--accent)",marginLeft:"0.25rem",fontWeight:600},children:["↑ approval at ",_.cap]})]}):s.jsxs("span",{title:`Team cap on ${te} is ${_.cap} with no approvers configured (hard cap). Authorized for ${_.authorized}; effective ${_.cap}.`,children:[s.jsxs("span",{style:{textDecoration:"line-through",color:"var(--text-tertiary)"},children:[te,"=",String(oe)]}),s.jsxs("span",{style:{color:"var(--danger)",marginLeft:"0.25rem",fontWeight:600},children:["→"," ",_.cap]})]}):s.jsxs("span",{children:[te,"=",String(oe)]})]},te)})}),s.jsxs("div",{style:{display:"flex",justifyContent:"flex-end",gap:"0.5rem",marginTop:"0.5rem"},children:[R&&s.jsx("button",{className:"btn btn-secondary btn-sm",onClick:()=>S(e.authorization_id,!C),disabled:v===e.authorization_id,title:C?"Move back to the Expired or Revoked list":"Hide from the list and the nav badge. Nothing is deleted: the mandate and its tickets stay stored and verifiable.",children:v===e.authorization_id?C?"Unarchiving…":"Archiving…":C?"↩ Unarchive":"⊟ Archive"}),s.jsx("button",{className:"btn btn-ghost btn-sm",onClick:()=>w(e),children:E?"▲ Hide Details":"▼ Details"})]}),E&&s.jsxs("div",{style:{borderTop:"1px solid var(--border)",marginTop:"0.75rem",paddingTop:"0.75rem"},children:[V.length>0&&s.jsxs(s.Fragment,{children:[s.jsx("div",{style:{fontSize:"0.75rem",fontWeight:600,color:"var(--text-tertiary)",textTransform:"uppercase",letterSpacing:"0.04em",marginBottom:"0.25rem"},children:"Bounds"}),s.jsx("dl",{className:"review-grid",children:V.map(([te,oe])=>s.jsxs("span",{style:{display:"contents"},children:[s.jsx("dt",{children:te}),s.jsx("dd",{children:String(oe)})]},te))})]}),(L==null?void 0:L.context)&&Object.keys(L.context).length>0&&s.jsxs(s.Fragment,{children:[s.jsx("div",{style:{fontSize:"0.75rem",fontWeight:600,color:"var(--text-tertiary)",textTransform:"uppercase",letterSpacing:"0.04em",marginTop:"1rem",marginBottom:"0.25rem"},children:"Scope"}),s.jsx("dl",{className:"review-grid",children:Object.entries(L.context).map(([te,oe])=>s.jsxs("span",{style:{display:"contents"},children:[s.jsx("dt",{children:te}),s.jsx("dd",{title:String(oe),children:gm(te,oe,L.contextLabels)})]},te))})]}),s.jsx("div",{style:{fontSize:"0.75rem",fontWeight:600,color:"var(--text-tertiary)",textTransform:"uppercase",letterSpacing:"0.04em",marginTop:"1rem",marginBottom:"0.25rem"},children:"Intent"}),o===e.authorization_id?s.jsx("p",{style:{fontSize:"0.8rem",color:"var(--text-tertiary)"},children:"Loading gate content..."}):L?s.jsx("div",{className:"gate-content-block",children:s.jsx("div",{className:"gate-content-item",children:s.jsx("div",{className:"gate-content-text",children:L.gateContent.intent})})}):s.jsx("p",{style:{fontSize:"0.8rem",color:"var(--text-tertiary)"},children:"Gate content not available."}),s.jsxs("div",{style:{fontSize:"0.75rem",color:"var(--text-tertiary)",marginTop:"1rem"},children:["Created: ",new Date(e.created_at).toLocaleString(),e.earliest_expiry&&` · Expires: ${new Date(e.earliest_expiry).toLocaleString()}`]}),s.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"0.5rem",marginTop:"0.25rem"},children:[s.jsx("span",{style:{fontSize:"0.7rem",color:"var(--text-tertiary)",fontFamily:"'SF Mono', Monaco, monospace",wordBreak:"break-all"},children:e.authorization_id}),s.jsx("button",{className:"btn btn-ghost btn-sm",style:{fontSize:"0.7rem",padding:"0.125rem 0.375rem"},onClick:()=>y(e.authorization_id),children:i===e.authorization_id?"copied":"copy"})]}),s.jsxs("div",{style:{display:"flex",justifyContent:"flex-end",gap:"0.5rem",marginTop:"0.75rem"},children:[!p&&s.jsx("button",{className:"btn btn-secondary btn-sm",onClick:()=>x(e),disabled:c===e.authorization_id,title:"Start a new mandate pre-filled with these bounds, scope, and intent",children:c===e.authorization_id?"Copying…":"⧉ Copy"}),!p&&(N==="active"||N==="pending")&&s.jsx("button",{className:"btn btn-secondary btn-sm",onClick:()=>x(e,{asEdit:!0}),disabled:c===e.authorization_id,title:"Adjust intent, bounds, or scope: opens the ceremony pre-filled; signing the new mandate revokes this one",children:"✎ Edit"}),!p&&D&&s.jsx("button",{className:"btn btn-secondary btn-sm",onClick:()=>g(e),children:"↻ Extend"}),p&&m&&N!=="revoked"?s.jsx("button",{className:"btn btn-danger btn-sm",onClick:()=>j(e.authorization_id,p,q),disabled:l===e.authorization_id,children:l===e.authorization_id?"Revoking…":"Revoke"}):!p&&(N==="active"||N==="pending")?s.jsx("button",{className:"btn btn-danger btn-sm",onClick:()=>j(e.authorization_id),disabled:l===e.authorization_id,children:l===e.authorization_id?"Revoking…":"Revoke"}):null]})]})]},e.authorization_id)}function Nx(){const[e,t]=u.useState([]),[n,r]=u.useState(!0),[a,o]=u.useState([]),[i,l]=u.useState(!1),[c,d]=u.useState(new Map),[f,p]=u.useState("mine"),[m,w]=u.useState("active"),[y,x]=u.useState(null),[j,g]=u.useState(null),[h,v]=Yf(),[S,b]=u.useState(()=>h.get("new")==="1"),[N,C]=u.useState(()=>h.get("highlight")),[R,E]=u.useState(null),[L,D]=u.useState({}),[V,J]=u.useState(null),[U,P]=u.useState(null),[ee,F]=u.useState(null),[$,z]=u.useState(new Set),[W,I]=u.useState(null),[B,Q]=u.useState(new Set),[q,re]=u.useState(null),[ce,me]=u.useState(null),te=tn(),{group:oe,groupId:se,domain:_,mode:X,activeTeam:ae}=Oe(),ge=(ae==null?void 0:ae.isAdmin)===!0,[he,_e]=u.useState(()=>new Map),it=u.useCallback(()=>{r(!0),T.getMyAttestations().then(t).catch(()=>{}).finally(()=>r(!1))},[]),Ae=u.useCallback(()=>{T.getArchivedMandates().then(H=>Q(new Set(H))).catch(()=>{})},[]);u.useEffect(()=>{Ae()},[Ae]);const yt=async(H,Z)=>{re(H);try{const K=await T.setMandateArchived(H,Z);Q(new Set(K)),window.dispatchEvent(new Event("suveren:archived-changed"))}catch(K){alert(K instanceof Error?K.message:"Failed to update archive")}finally{re(null)}},Ke=u.useCallback(()=>{se&&(l(!0),T.listTeamAuthorizations(se).then(o).catch(()=>{}).finally(()=>l(!1)))},[se]);fe("attestation-changed",()=>{it(),ge&&se&&Ke()}),u.useEffect(()=>{if(!N)return;h.get("highlight")&&(h.delete("highlight"),v(h,{replace:!0}));const H=window.setTimeout(()=>C(null),3e3);return()=>window.clearTimeout(H)},[]),Pt(it,3e5),u.useEffect(()=>{f==="team"&&ge&&se&&a.length===0&&!i&&Ke()},[f,ge,se,a.length,i,Ke]),u.useEffect(()=>{let H=!1;return T.listProfiles().then(Z=>{if(H)return;const K=ct=>ct.replace(/@.*$/,"").split("/").pop()??ct,de=ct=>ct.split("@")[1]??"",ye=new Map;for(const ct of Z){const Ut=K(ct.id),ys=ye.get(Ut);(!ys||de(ct.id).localeCompare(de(ys.id),void 0,{numeric:!0})>0)&&ye.set(Ut,ct)}d(ye)}).catch(()=>{}),()=>{H=!0}},[]);const et=u.useCallback(H=>{const Z=Ut=>Ut.replace(/@.*$/,"").split("/").pop()??Ut,K=Ut=>Ut.split("@")[1]??"",de=c.get(Z(H));if(!de)return;const ye=K(H),ct=K(de.id);if(!(!ye||!ct))return ct.localeCompare(ye,void 0,{numeric:!0})>0?de:void 0},[c]);u.useEffect(()=>{if(X!=="team"||!se)return;const H=f==="mine"?e:a;if(H.length===0)return;const Z=[...new Set(H.map(K=>K.profile_id))].filter(K=>!he.has(K));if(Z.length!==0){_e(K=>{const de=new Map(K);for(const ye of Z)de.set(ye,null);return de});for(const K of Z)T.getTeamProfileConfig(se,K).then(de=>{_e(ye=>new Map(ye).set(K,de))}).catch(()=>{})}},[e,a,f,se,X,he]);const le=async H=>{if(R===H.authorization_id){E(null);return}E(H.authorization_id);const Z=H.authorization_id;if(!(Z in L)){J(H.authorization_id);try{const K=await T.getGateContent(Z);D(de=>({...de,[Z]:K}))}catch{D(K=>({...K,[Z]:null}))}finally{J(null)}}},Ye=H=>{navigator.clipboard.writeText(H).then(()=>{F(H),setTimeout(()=>F(null),2e3)})},G=async(H,Z)=>{var K;if(!se){alert("No active group; cannot copy mandate.");return}me(H.authorization_id);try{const de=H.authorization_id;let ye=L[de]??null;de in L||(ye=await T.getGateContent(de),D(xs=>({...xs,[de]:ye})));const ct=Object.fromEntries(Object.entries(H.frame).filter(([xs])=>xs!=="profile"&&xs!=="path")),Ut=(ye==null?void 0:ye.context)??{},ys=((K=ye==null?void 0:ye.gateContent)==null?void 0:K.intent)??"",wm=H.deferred_commitment_domains.length>0?"review":"automatic",Sm=H.attested_domains[0]||_||"owner",Xa=Date.parse(H.created_at),qa=H.earliest_expiry?Date.parse(H.earliest_expiry):NaN,jm=Number.isFinite(Xa)&&Number.isFinite(qa)&&qa>Xa?Math.round((qa-Xa)/1e3):void 0;sessionStorage.setItem("agentAuth",JSON.stringify({profileId:H.profile_id,groupId:se,groupName:(oe==null?void 0:oe.name)??null,domain:Sm,isPersonal:!!(oe!=null&&oe.isPersonal)})),sessionStorage.setItem("agentGate",JSON.stringify({bounds:ct,context:Ut,gateContent:{intent:ys},templateMode:wm,templateTtl:jm})),Z!=null&&Z.asEdit?sessionStorage.setItem("agentEditReplaces",H.authorization_id):sessionStorage.removeItem("agentEditReplaces"),te("/mandates/new/intent")}catch(de){alert(de instanceof Error?de.message:"Failed to copy mandate")}finally{me(null)}},k=async(H,Z,K)=>{const de=Z&&K?`Revoke ${Z}'s ${K} mandate? This cannot be undone.`:"Revoke this mandate? The agent will no longer be able to execute actions under it.";if(confirm(de)){I(H);try{await T.revokeAttestation(H),z(ye=>new Set(ye).add(H)),T.resyncGates().catch(()=>{}),Z&&se&&Ke()}catch(ye){alert(ye instanceof Error?ye.message:"Failed to revoke mandate")}finally{I(null)}}},A=f==="mine"?e:a,M=f==="mine"?n:i,ne=f==="mine"?{revokedSet:$,archivedSet:B}:{revokedSet:$},ve=H=>Ra(H,ne),kn={active:0,pending:0,expired:0,revoked:0,archived:0};for(const H of A)kn[ve(H)]+=1;const bn=f==="mine"?["active","pending","expired","revoked","archived"]:["active","pending","expired","revoked"],Ie=(()=>{const H=new Map;for(const Z of A){if(ve(Z)!==m)continue;const K=H.get(Z.profile_id)??{count:0,review:!1};K.count+=1,Z.deferred_commitment_domains.length>0&&(K.review=!0),H.set(Z.profile_id,K)}return Array.from(H.entries()).map(([Z,K])=>({profileId:Z,...K})).sort((Z,K)=>Le(Z.profileId).localeCompare(Le(K.profileId)))})(),lt=bx(A.filter(H=>{if(ve(H)!==m||y!==null&&H.profile_id!==y)return!1;if(j!==null){const Z=H.deferred_commitment_domains.length>0;if(j==="review"&&!Z||j==="auto"&&Z)return!1}return!0}),ne,N),xt={revokedSet:$,expandedHash:R,gateCache:L,gateLoading:V,copiedHash:ee,revokingHash:W,copyingHash:ce,profileConfigCache:he,mode:X,activeDomain:_,group:oe,groupId:se,onExpand:le,onCopyHash:Ye,onCopy:G,onRevoke:k,onExtend:P,highlightHash:N},tt={...xt,archivedSet:B,archivingHash:q,onArchive:yt};return s.jsxs(s.Fragment,{children:[s.jsxs("div",{className:"page-header",style:{display:"flex",justifyContent:"space-between",alignItems:"flex-start",gap:"1rem",flexWrap:"wrap"},children:[s.jsxs("div",{children:[s.jsx("h1",{className:"page-title",children:"Mandates"}),s.jsx("p",{className:"page-subtitle",children:"Active, pending, expired, and archived agent mandates."})]}),s.jsx("button",{className:"btn btn-primary",onClick:()=>b(!0),children:"+ New mandate"})]}),S&&s.jsx("div",{className:"modal-backdrop",onClick:()=>{b(!1),h.get("new")&&(h.delete("new"),v(h,{replace:!0}))},children:s.jsxs("div",{className:"modal",onClick:H=>H.stopPropagation(),style:{maxWidth:"960px",width:"90vw"},children:[s.jsxs("div",{className:"modal-header",children:[s.jsx("h2",{className:"modal-title",children:"New mandate"}),s.jsx("button",{className:"modal-close",onClick:()=>{b(!1),h.get("new")&&(h.delete("new"),v(h,{replace:!0}))},children:"×"})]}),s.jsxs("div",{className:"modal-body",children:[s.jsx("p",{style:{color:"var(--text-tertiary)",fontSize:"0.9rem",marginTop:0,marginBottom:"1rem"},children:"What should your agent be able to do? Pick a profile, set limits, then authorize."}),s.jsx(px,{onDismiss:()=>b(!1)})]})]})}),ge&&s.jsxs("div",{className:"nav-tabs",style:{marginBottom:"0.5rem"},children:[s.jsx("button",{className:`nav-tab${f==="mine"?" active":""}`,onClick:()=>{p("mine"),w("active"),x(null),g(null),E(null)},children:"Mine"}),s.jsx("button",{className:`nav-tab${f==="team"?" active":""}`,onClick:()=>{p("team"),w("active"),x(null),g(null),E(null)},children:"Team"})]}),s.jsx("div",{className:"nav-tabs",children:bn.map(H=>s.jsxs("button",{className:`nav-tab${m===H?" active":""}`,onClick:()=>{w(H),x(null),g(null)},children:[H.charAt(0).toUpperCase()+H.slice(1)," (",kn[H],")"]},H))}),Ie.length>0&&s.jsxs("div",{style:{display:"flex",gap:"0.5rem",flexWrap:"wrap",alignItems:"center",marginTop:"-0.25rem",marginBottom:"1rem"},children:[Ie.map(H=>{const Z=y===H.profileId;return s.jsx("button",{className:`btn btn-sm ${Z?"btn-primary":"btn-secondary"}`,onClick:()=>x(Z?null:H.profileId),children:Le(H.profileId)},H.profileId)}),s.jsx("span",{"aria-hidden":"true",style:{color:"var(--border)",fontSize:"1.1rem",padding:"0 0.25rem",userSelect:"none"},children:"|"}),["auto","review"].map(H=>{const Z=j===H;return s.jsx("button",{className:`btn btn-sm ${Z?"btn-primary":"btn-secondary"}`,onClick:()=>g(Z?null:H),children:H==="auto"?"Auto":"Review"},H)})]}),M&&A.length===0?s.jsx("p",{style:{color:"var(--text-tertiary)"},children:"Loading..."}):lt.length===0?s.jsx(vm,{icon:"☰",title:"No mandates",text:m==="archived"?"Nothing archived. Archive an expired or revoked mandate to move it here.":`No ${m} mandates found.`}):s.jsx("div",{style:{display:"flex",flexDirection:"column",gap:"0.75rem"},children:lt.map(H=>{const Z=f==="team"?H:null,K=Z!=null&&Z.owner?Z.owner.name??Z.owner.email??Z.owner.userId:void 0;return s.jsx(Cx,{item:H,newerProfile:et(H.profile_id),ownerLabel:K,isAdmin:ge,...f==="mine"?tt:xt},H.authorization_id)})}),U&&s.jsx(kx,{item:U,onClose:()=>P(null),onSuccess:()=>{P(null),it()}})]})}function Ex(e){const t=e.indexOf("__");return t<0?{integrationId:"",toolName:e}:{integrationId:e.slice(0,t),toolName:e.slice(t+2)}}function Tx(e,t){var c,d,f;const{integrationId:n,toolName:r}=Ex(e.action),a=t.find(p=>p.id===n),o=(d=(c=a==null?void 0:a.toolGating)==null?void 0:c.overrides)==null?void 0:d[r];if(o!=null&&o.actionLabel)return o.actionLabel;const i=Le(e.profileId),l=(f=e.executionContext)==null?void 0:f.action_type;return typeof l=="string"&&l?`${i} · ${l}`:`${i} · ${r}`}function Rx(e){const t=[];for(const[n,r]of Object.entries(e.executionContext??{})){if(!n.startsWith("allowed_"))continue;const a=String(r??"").trim();a&&t.push(a.split(",").map(o=>o.trim()).filter(Boolean).join(", "))}return t.join(" · ")}function Ix(e){if(!e)return"";const t=[];for(const[n,r]of Object.entries(e)){if(n==="action_type")continue;const a=String(r??"").trim();if(!a)continue;const o=n.replace(/^allowed_/,"").replace(/_/g," ");t.push(`${o} ${a.split(",").map(i=>i.trim()).filter(Boolean).join(", ")}`)}return t.join(" · ")}function Px(e,t){var o,i;const n=[{window:"daily",label:"today"},{window:"monthly",label:"this month"}],r=e.actionType??(typeof((o=e.executionContext)==null?void 0:o.action_type)=="string"?e.executionContext.action_type:void 0),a=[];for(const{window:l,label:c}of n){const d=(i=e.cumulativeState)==null?void 0:i[l];if(!d)continue;const f=`_${l}_max`,p=Object.keys(t??{}).filter(j=>j.endsWith(f)),m=(r&&p.find(j=>j.startsWith(`${r}_`)))??(p.length===1?p[0]:void 0),y=(m?/^(amount|spend)_/.test(m):!1)?d.amount:d.count,x=m?Number(t==null?void 0:t[m]):NaN;m&&Number.isFinite(x)?a.push(`${y} of ${x} ${c}`):a.push(`${d.count} ${d.count===1?"call":"calls"} ${c}`)}return a.join(" · ")}function _x(e){return typeof e.proposalId=="string"&&e.proposalId.length>0}function Ax(e){const t=Le(e),n=e.split("@")[1];return n?`${t}@${n}`:t}function Pr({label:e,children:t}){return s.jsxs(s.Fragment,{children:[s.jsx("dt",{className:"receipt-row-label",children:e}),s.jsx("dd",{className:"receipt-row-value",children:t})]})}function zx({receipt:e,manifests:t,localAuth:n,localUnavailable:r,signature:a,grantTitle:o,ownerLabel:i,spUrl:l,formatDate:c,onOpenComplete:d}){var y;const f=Rx(e),p=Ix(n==null?void 0:n.context),m=Px(e,(n==null?void 0:n.bounds)??e.limits),w=n==null?void 0:n.intent;return s.jsxs("div",{className:"card",style:{marginBottom:0},children:[s.jsxs("div",{className:"receipt-head",children:[s.jsx("span",{className:"receipt-what",children:Tx(e,t)}),s.jsx("span",{className:"receipt-tag",children:_x(e)?"review":"automatic"}),e.contentHash&&s.jsx("span",{className:"receipt-tag receipt-tag-bound",title:(y=e.contentBinding)!=null&&y.fields?`The ticket binds: ${e.contentBinding.fields.join(", ")}`:"This exact content was authorized",children:"content bound"}),s.jsx("span",{className:"auth-card-time",children:c(e.timestamp)})]}),f&&s.jsx("div",{className:"receipt-scope",children:f}),s.jsxs("dl",{className:"receipt-rows",children:[s.jsx(Pr,{label:"mandate",children:s.jsx("strong",{children:o||Ax(e.profileId)})}),i&&s.jsx(Pr,{label:"owner",children:i}),p&&s.jsx(Pr,{label:"allowed",children:p}),m&&s.jsx(Pr,{label:"used",children:s.jsx("span",{className:"receipt-num",children:m})}),s.jsx(Pr,{label:"intent",children:w?s.jsx("span",{className:"receipt-intent",children:w}):s.jsx("span",{className:"receipt-absent",children:r?"local store unreachable — sign in to the gateway to read it":"not on this device — the Authority Server stores only its hash"})})]}),s.jsxs("div",{className:"receipt-foot",children:[a==="valid"&&s.jsx("span",{className:"receipt-verified",title:"Ed25519 signature checked on this device against the issuer key archived when the ticket was issued — no Authority Server involved.",children:"✓ Verified on this device"}),a==="invalid"&&s.jsx("span",{className:"receipt-tamper",title:"The stored ticket does not match what was signed.",children:"⚠ Signature check FAILED"}),s.jsx("button",{type:"button",className:"receipt-evidence-link",onClick:d,children:"Complete ticket"}),l&&s.jsxs("span",{className:"receipt-public",children:["redacted, shareable:"," ",s.jsx("a",{className:"receipt-link",href:`${l}/r/${e.id}`,target:"_blank",rel:"noreferrer",children:"public link ↗"})]})]}),s.jsxs("details",{className:"receipt-more",children:[s.jsx("summary",{children:"Raw"}),s.jsxs("div",{className:"receipt-kv",children:[s.jsxs("div",{children:["ticket · ",e.id]}),s.jsxs("div",{children:["action · ",e.action]}),s.jsxs("div",{children:["profile · ",e.profileId]}),e.authorizationId&&s.jsxs("div",{children:["mandate · ",e.authorizationId]}),Object.keys(e.executionContext??{}).length>0&&s.jsxs("div",{children:["scope ·"," ",Object.entries(e.executionContext).map(([x,j])=>`${x}=${j}`).join(" · ")]}),(n==null?void 0:n.boundsHash)&&s.jsxs("div",{children:["bounds hash · ",n.boundsHash]}),(n==null?void 0:n.contextHash)&&s.jsxs("div",{children:["scope hash · ",n.contextHash]}),e.contentHash&&s.jsxs("div",{children:["content · ",e.contentHash]}),e.proposalId&&s.jsxs("div",{children:["proposal · ",e.proposalId]}),s.jsxs("div",{children:["signature · ",e.signature]})]})]})]})}function $x({receipt:e,onClose:t}){const[n,r]=u.useState(null),[a,o]=u.useState(null),[i,l]=u.useState(null),[c,d]=u.useState(!0),[f,p]=u.useState(!1);u.useEffect(()=>{let j=!1;return d(!0),T.getArchivedReceipt(e.id).then(g=>{j||(r(g),o(g?"local":"authority-server"),l((g==null?void 0:g.signature)??null))}).catch(()=>{j||o("authority-server")}).finally(()=>{j||d(!1)}),()=>{j=!0}},[e.id]);const m=n?n.entry:{receipt:e},w=JSON.stringify(m,null,2);function y(){const j=URL.createObjectURL(new Blob([w],{type:"application/json"})),g=document.createElement("a");g.href=j,g.download=`suveren-ticket-${e.id.slice(0,8)}.json`,g.click(),URL.revokeObjectURL(j)}async function x(){try{await navigator.clipboard.writeText(w),p(!0),setTimeout(()=>p(!1),2e3)}catch{p(!1)}}return s.jsx("div",{className:"modal-backdrop",onClick:j=>j.target===j.currentTarget&&t(),children:s.jsxs("div",{className:"modal",style:{maxWidth:"44rem"},children:[s.jsxs("div",{className:"modal-header",children:[s.jsx("h3",{className:"modal-title",children:"Complete ticket"}),s.jsx("button",{className:"modal-close",onClick:t,"aria-label":"Close",children:"×"})]}),s.jsxs("div",{className:"modal-body",children:[i==="valid"&&s.jsx("p",{className:"receipt-verified",style:{margin:"0 0 0.5rem",fontSize:"0.8rem"},children:"✓ Ed25519 signature verified on this device, against the issuer key archived when this ticket was issued."}),i==="invalid"&&s.jsx("p",{className:"receipt-tamper",style:{margin:"0 0 0.5rem",fontSize:"0.8rem"},children:"⚠ Signature check FAILED — the stored ticket does not match what was signed."}),s.jsx("p",{style:{fontSize:"0.8rem",color:"var(--text-muted)",margin:"0 0 0.75rem"},children:c?"Loading…":a==="local"?"Held on this device — the signed ticket, the mandate it ran under, and the issuer key. Anyone with this file and that key can verify it offline, without Suveren.":"No local copy of this ticket (it predates local archiving, or ran on another device). Shown from the Authority Server — complete and signed, but it needs the server to retrieve."}),s.jsx("pre",{style:{fontFamily:"'SF Mono', Monaco, monospace",fontSize:"0.68rem",lineHeight:1.65,margin:0,background:"var(--accent-subtle)",border:"1px solid var(--border)",borderRadius:"6px",padding:"0.75rem 0.85rem",overflowX:"auto",maxHeight:"22rem",overflowY:"auto"},children:w})]}),s.jsxs("div",{className:"modal-footer",children:[s.jsx("button",{className:"btn btn-primary btn-sm",onClick:y,children:"Download"}),s.jsx("button",{className:"btn btn-secondary btn-sm",onClick:x,children:f?"Copied":"Copy"})]})]})})}function Lx(e){return new Date(e*1e3).toLocaleString()}function Mx(e,t){if(t==="all")return!0;const n=t==="1d"?1:t==="7d"?7:30,r=Math.floor(Date.now()/1e3)-n*86400;return e.timestamp>=r}function Fx(e,t){if(!t)return!0;const n=t.toLowerCase();return e.profileId.toLowerCase().includes(n)||Le(e.profileId).toLowerCase().includes(n)||e.path.toLowerCase().includes(n)||e.action.toLowerCase().includes(n)||e.attestationHash.toLowerCase().includes(n)||e.id.toLowerCase().includes(n)||JSON.stringify(e.executionContext).toLowerCase().includes(n)}function fu(e,t){const n=new Map(e.map(r=>[r.id,r]));for(const r of t)n.set(r.id,r);return[...n.values()].sort((r,a)=>a.timestamp-r.timestamp)}function Ox(){const{activeTeam:e,groupId:t}=Oe(),n=(e==null?void 0:e.isAdmin)===!0,[r,a]=u.useState("mine"),[o,i]=u.useState([]),[l,c]=u.useState([]),[d,f]=u.useState(""),[p,m]=u.useState(!0),[w,y]=u.useState({}),[x,j]=u.useState(new Set),[g,h]=u.useState(""),[v,S]=u.useState(new Set),[b,N]=u.useState(new Set),[C,R]=u.useState("all"),[E,L]=u.useState(!1),[D,V]=u.useState(!1),[J,U]=u.useState(null),[P,ee]=u.useState({}),[F,$]=u.useState(!1),[z,W]=u.useState({}),[I,B]=u.useState({}),[Q,q]=u.useState(null),[re,ce]=u.useState(null),[me,te]=u.useState(!1),[oe,se]=u.useState(!1),_=u.useRef(""),X=u.useCallback(k=>r==="team"&&n&&t?T.listTeamReceiptsPage(t,{before:k,limit:200}):T.getMyReceiptsPage({before:k,limit:200}),[r,n,t]),ae=u.useCallback(()=>{const k=r==="team"?`team:${t}`:"mine",A=_.current!==k;_.current=k,m(!0),se(!1),X().then(M=>{i(ne=>A?M.receipts:fu(ne,M.receipts)),ce(ne=>A?M.nextBefore:ne??M.nextBefore)}).catch(()=>{A&&i([]),se(!0)}).finally(()=>m(!1))},[X,r,t]),ge=u.useCallback(()=>{!re||me||(te(!0),se(!1),X(re).then(k=>{i(A=>fu(A,k.receipts)),ce(k.nextBefore)}).catch(()=>se(!0)).finally(()=>te(!1)))},[re,me,X]);Pt(ae,12e4),u.useEffect(()=>{T.getIntegrationManifests().then(({manifests:k})=>c(k)).catch(()=>{}),fetch("/health").then(k=>k.json()).then(k=>{typeof k.spUrl=="string"&&f(k.spUrl.replace(/\/$/,""))}).catch(()=>{})},[]),u.useEffect(()=>{T.getLocalAuthorizations().then(({authorizations:k,signatures:A})=>{ee(k),W(A),$(!1)}).catch(()=>{ee({}),W({}),$(!0)}),T.getMyAttestations().then(k=>{const A={};for(const M of k)M.authorization_id&&M.title&&(A[M.authorization_id]=M.title);B(A)}).catch(()=>{})},[]),u.useEffect(()=>{r!=="team"||Object.keys(w).length>0||T.listUsers().then(k=>{const A={};for(const M of k)A[M.id]={name:M.name,email:M.email};y(A)}).catch(()=>{})},[r,w]);const he=u.useMemo(()=>{const k=new Set;for(const A of o)k.add(Le(A.profileId));return[...k].sort()},[o]),_e=u.useMemo(()=>{const k=new Set;for(const A of o)k.add(A.action);return[...k].sort()},[o]),it=u.useMemo(()=>{if(r!=="team")return[];const k=new Set;for(const A of o)A.userId&&k.add(A.userId);return[...k].map(A=>{var M;return{id:A,label:(M=w[A])!=null&&M.name?`${w[A].name} (${w[A].email})`:A}}).sort((A,M)=>A.label.localeCompare(M.label))},[r,o,w]),Ae=u.useMemo(()=>o.filter(k=>!(!Fx(k,g)||v.size>0&&!v.has(Le(k.profileId))||b.size>0&&!b.has(k.action)||x.size>0&&k.userId&&!x.has(k.userId)||!Mx(k,C))),[o,g,v,b,x,C]),yt=v.size>0||b.size>0||x.size>0||C!=="all";function Ke(k){S(A=>{const M=new Set(A);return M.has(k)?M.delete(k):M.add(k),M})}function et(k){N(A=>{const M=new Set(A);return M.has(k)?M.delete(k):M.add(k),M})}function le(k){j(A=>{const M=new Set(A);return M.has(k)?M.delete(k):M.add(k),M})}function Ye(){S(new Set),N(new Set),j(new Set),R("all"),h("")}async function G(){V(!0),U(null);try{const{bundle:k,filename:A}=await T.fetchEvidenceBundle(),M=URL.createObjectURL(new Blob([JSON.stringify(k,null,2)],{type:"application/json"})),ne=document.createElement("a");ne.href=M,ne.download=A,ne.click(),URL.revokeObjectURL(M);const ve=k.sources??{};ve.authorityServer?ve.local||U(`Downloaded Authority Server history only — ${ve.localError??"local archive unavailable."}`):U(`Downloaded local evidence only — ${ve.asError??"Authority Server export unavailable."}`)}catch(k){U(`Export failed: ${k instanceof Error?k.message:String(k)}`)}finally{V(!1)}}return s.jsxs(s.Fragment,{children:[s.jsxs("div",{className:"page-header",style:{display:"flex",justifyContent:"space-between",alignItems:"flex-start",gap:"1rem",flexWrap:"wrap"},children:[s.jsxs("div",{children:[s.jsx("h1",{className:"page-title",children:"Tickets"}),s.jsx("p",{className:"page-subtitle",children:"Execution history for agent actions."})]}),s.jsx("button",{className:"btn btn-secondary",onClick:G,disabled:D,children:D?"Preparing…":"Download evidence"})]}),J&&s.jsx("div",{style:{marginBottom:"1rem",color:"var(--text-tertiary)",fontSize:"0.875rem"},children:J}),n&&s.jsx("div",{style:{display:"flex",gap:"0.5rem",marginBottom:"1rem",borderBottom:"1px solid var(--border)"},children:["mine","team"].map(k=>s.jsx("button",{onClick:()=>a(k),className:"btn btn-ghost",style:{borderRadius:0,padding:"0.5rem 0.875rem",borderBottom:r===k?"2px solid var(--accent)":"2px solid transparent",color:r===k?"var(--text-primary)":"var(--text-tertiary)",fontWeight:r===k?600:500},children:k==="mine"?"Mine":"Team"},k))}),s.jsxs("div",{className:"search-filter-bar",children:[s.jsxs("div",{className:"search-input-wrap",children:[s.jsx("span",{className:"search-icon",children:"⌕"}),s.jsx("input",{type:"text",className:"form-input search-input",placeholder:"Search by profile, action, path, or hash\\u2026",value:g,onChange:k=>h(k.target.value)}),g&&s.jsx("button",{className:"search-clear",onClick:()=>h(""),children:"×"})]}),s.jsxs("button",{className:`btn btn-sm btn-secondary${E?" active":""}`,onClick:()=>L(!E),children:["Filters",yt?` (${v.size+b.size+(C!=="all"?1:0)})`:""]})]}),E&&s.jsxs("div",{className:"filter-panel",children:[he.length>1&&s.jsxs("div",{className:"filter-section",children:[s.jsx("div",{className:"filter-label",children:"Profile"}),s.jsx("div",{className:"filter-chips",children:he.map(k=>s.jsx("button",{className:`filter-chip${v.has(k)?" selected":""}`,onClick:()=>Ke(k),children:k},k))})]}),_e.length>1&&s.jsxs("div",{className:"filter-section",children:[s.jsx("div",{className:"filter-label",children:"Action"}),s.jsx("div",{className:"filter-chips",children:_e.map(k=>s.jsx("button",{className:`filter-chip${b.has(k)?" selected":""}`,onClick:()=>et(k),children:k},k))})]}),r==="team"&&it.length>1&&s.jsxs("div",{className:"filter-section",children:[s.jsx("div",{className:"filter-label",children:"Owner"}),s.jsx("div",{className:"filter-chips",children:it.map(k=>s.jsx("button",{className:`filter-chip${x.has(k.id)?" selected":""}`,onClick:()=>le(k.id),children:k.label},k.id))})]}),s.jsxs("div",{className:"filter-section",children:[s.jsx("div",{className:"filter-label",children:"Time range"}),s.jsx("div",{className:"filter-chips",children:[["1d","Today"],["7d","7 days"],["30d","30 days"],["all","All time"]].map(([k,A])=>s.jsx("button",{className:`filter-chip${C===k?" selected":""}`,onClick:()=>R(k),children:A},k))})]})]}),yt&&s.jsxs("div",{className:"active-filters",children:[[...v].map(k=>s.jsxs("span",{className:"active-chip",onClick:()=>Ke(k),children:[k," ",s.jsx("span",{className:"chip-remove",children:"×"})]},k)),[...b].map(k=>s.jsxs("span",{className:"active-chip",onClick:()=>et(k),children:[k," ",s.jsx("span",{className:"chip-remove",children:"×"})]},k)),[...x].map(k=>{const A=w[k],M=A?A.name:k;return s.jsxs("span",{className:"active-chip",onClick:()=>le(k),children:[M," ",s.jsx("span",{className:"chip-remove",children:"×"})]},k)}),C!=="all"&&s.jsxs("span",{className:"active-chip",onClick:()=>R("all"),children:[C==="1d"?"Today":C==="7d"?"7 days":"30 days"," ",s.jsx("span",{className:"chip-remove",children:"×"})]}),s.jsx("button",{className:"clear-filters",onClick:Ye,children:"Clear all"})]}),oe&&s.jsx("div",{className:"card",style:{borderColor:"var(--danger, #c0392b)",marginBottom:"0.75rem"},children:s.jsx("span",{style:{color:"var(--danger, #c0392b)",fontSize:"0.85rem"},children:"Couldn’t load tickets — your session may have expired. Try signing out and back in."})}),p&&o.length===0?s.jsx("p",{style:{color:"var(--text-tertiary)"},children:"Loading..."}):Ae.length===0?s.jsx(vm,{icon:"⌕",title:o.length===0?"No tickets in the last 30 days":"No matching tickets",text:o.length===0?"Tickets appear here after an agent uses an authorized tool. Older tickets can be loaded below.":"Try adjusting your search or filters."}):s.jsxs(s.Fragment,{children:[s.jsx("div",{style:{fontSize:"0.8rem",color:"var(--text-tertiary)",marginBottom:"0.75rem"},children:Ae.length===o.length?`${o.length} ticket${o.length!==1?"s":""}`:`${Ae.length} of ${o.length} tickets`}),s.jsx("div",{className:"timeline",children:Ae.map(k=>{const A=k.userId?w[k.userId]:void 0;return s.jsx("div",{className:"timeline-event",children:s.jsx(zx,{receipt:k,manifests:l,localAuth:k.authorizationId?P[k.authorizationId]:void 0,localUnavailable:F,signature:z[k.id],grantTitle:k.authorizationId?I[k.authorizationId]:null,ownerLabel:r==="team"&&k.userId?A?`${A.name} (${A.email})`:k.userId:null,spUrl:d,formatDate:Lx,onOpenComplete:()=>q(k)})},k.id)})})]}),Q&&s.jsx($x,{receipt:Q,onClose:()=>q(null)}),re&&s.jsx("div",{style:{textAlign:"center",marginTop:"1rem"},children:s.jsx("button",{className:"btn btn-secondary btn-sm",onClick:ge,disabled:me,children:me?"Loading…":"Load older"})})]})}const Bx={darwin:"a macOS login item",win32:"a Windows scheduled task",linux:"a systemd user service"};function Dx(){const[e,t]=u.useState(null),[n,r]=u.useState(!1),[a,o]=u.useState(null),i=u.useCallback(async()=>{try{t(await T.getAutostart())}catch(d){o(d instanceof Error?d.message:"Could not read autostart state")}},[]);u.useEffect(()=>{i()},[i]);const l=u.useCallback(async()=>{if(!(!(e!=null&&e.supported)||n)){r(!0),o(null);try{await T.setAutostart(!e.installed)}catch(d){o(d instanceof Error?d.message:"Failed")}finally{try{t(await T.getAutostart()),o(null)}catch(d){o(d instanceof Error?d.message:"Could not re-read state")}r(!1)}}},[e,n,i]);if(!e)return s.jsxs("div",{className:"card",style:{padding:"1.5rem",marginTop:"2rem"},children:[s.jsx("h2",{style:{fontSize:"1rem",fontWeight:700,margin:0},children:"Keep Suveren running"}),s.jsx("p",{role:a?"alert":void 0,style:{margin:"0.5rem 0 0",fontSize:"0.9rem",color:"var(--text-secondary)"},children:a?`Could not read autostart state: ${a}`:"Checking…"})]});const c=Bx[e.platform]??"a login service";return s.jsxs("div",{className:"card",style:{padding:"1.5rem",marginTop:"2rem"},children:[s.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"flex-start",gap:"1rem"},children:[s.jsxs("div",{children:[s.jsx("h2",{style:{fontSize:"1rem",fontWeight:700,margin:0},children:"Keep Suveren running"}),s.jsx("p",{style:{color:"var(--text-secondary)",margin:"0.5rem 0 0",fontSize:"0.9rem"},children:e.supported?s.jsxs(s.Fragment,{children:["Starts automatically when you log in, and restarts if it crashes. Uses ",c," — no admin rights needed."]}):e.reason})]}),e.supported&&s.jsx("button",{type:"button",onClick:()=>void l(),disabled:n,"aria-pressed":e.installed,className:e.installed?"btn btn-secondary":"btn btn-primary",style:{whiteSpace:"nowrap"},children:n?"Working…":e.installed?"Turn off":"Turn on"})]}),e.supported&&s.jsxs("p",{style:{margin:"1rem 0 0",fontSize:"0.85rem",color:"var(--text-tertiary)"},children:["Status: ",s.jsx("strong",{children:e.installed?"On — starts from your next login":"Off"})]}),e.supported&&s.jsxs("p",{style:{margin:"0.5rem 0 0",fontSize:"0.85rem",color:"var(--text-tertiary)"},children:["Turning this on doesn't interrupt the gateway you're using — it takes effect at your next login. After any restart Suveren comes back ",s.jsx("strong",{children:"locked"}),": you enter your API key once to unlock it, because nothing stored on this machine can unlock it for you."]}),a&&s.jsx("p",{role:"alert",style:{margin:"0.75rem 0 0",fontSize:"0.85rem",color:"var(--danger, #c00)"},children:a})]})}function Ux(){const[e,t]=u.useState(null),[n,r]=u.useState(!1),[a,o]=u.useState(null),i=u.useCallback(async()=>{try{const c=await T.getGatewaySettings();t(c.desktopNotifications),o(null)}catch(c){o(c instanceof Error?c.message:"Could not read notification setting")}},[]);u.useEffect(()=>{i()},[i]);const l=u.useCallback(async()=>{if(!(e===null||n)){r(!0),o(null);try{const c=await T.setGatewaySettings({desktopNotifications:!e});t(c.desktopNotifications)}catch(c){o(c instanceof Error?c.message:"Failed to save"),await i()}finally{r(!1)}}},[e,n,i]);return e===null?s.jsxs("div",{className:"card",style:{padding:"1.5rem",marginTop:"2rem"},children:[s.jsx("h2",{style:{fontSize:"1rem",fontWeight:700,margin:0},children:"Desktop notifications"}),s.jsx("p",{role:a?"alert":void 0,style:{margin:"0.5rem 0 0",fontSize:"0.9rem",color:"var(--text-secondary)"},children:a?`Could not read the setting: ${a}`:"Checking…"})]}):s.jsxs("div",{className:"card",style:{padding:"1.5rem",marginTop:"2rem"},children:[s.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"flex-start",gap:"1rem"},children:[s.jsxs("div",{children:[s.jsx("h2",{style:{fontSize:"1rem",fontWeight:700,margin:0},children:"Desktop notifications"}),s.jsx("p",{style:{color:"var(--text-secondary)",margin:"0.5rem 0 0",fontSize:"0.9rem"},children:"Tells you something is waiting for review — never what it is, and never with an approve button. Open Suveren to see and decide. At most one notification a minute; the browser tab always shows the count."})]}),s.jsx("button",{type:"button",onClick:()=>void l(),disabled:n,"aria-pressed":e,className:e?"btn btn-secondary":"btn btn-primary",style:{whiteSpace:"nowrap"},children:n?"Saving…":e?"Turn off":"Turn on"})]}),a&&s.jsx("p",{role:"alert",style:{margin:"0.75rem 0 0",fontSize:"0.85rem",color:"var(--danger)"},children:a})]})}const Wx={npm:"Checking npm for new releases",docker:"Checking the container registry for new images",dev:"Git checkout — comparing against origin/main, not npm releases"};function Hx(){const{version:e,latestVersion:t,updateAvailable:n,installMethod:r}=zl();return e?s.jsxs("div",{className:"card",style:{padding:"1.5rem",marginTop:"2rem"},children:[s.jsx("h2",{style:{fontSize:"1rem",fontWeight:700,margin:0},children:"Version"}),s.jsxs("p",{style:{margin:"0.5rem 0 0",fontSize:"0.9rem",color:"var(--text-secondary)"},children:["Running ",s.jsx("strong",{children:e}),n&&t?s.jsxs(s.Fragment,{children:[" — ",s.jsx("strong",{children:t})," is available"]}):null]}),s.jsxs("p",{style:{margin:"0.5rem 0 0",fontSize:"0.85rem",color:"var(--text-tertiary)"},children:[Wx[r]??"Update checking is unavailable",r==="dev"&&s.jsx(s.Fragment,{children:" — a development checkout is not told about published releases."})]})]}):null}function Vx(){const[e,t]=u.useState(null),[n,r]=u.useState(null);return u.useEffect(()=>{let a=!1;return T.getAsPairing().then(o=>{a||t(o)}).catch(o=>{a||r(o instanceof Error?o.message:"Could not read Authority Server info")}),()=>{a=!0}},[]),s.jsxs("div",{className:"card",style:{padding:"1.5rem",marginTop:"2rem"},children:[s.jsx("h2",{style:{fontSize:"1rem",fontWeight:700,margin:0},children:"Authority Server"}),!e&&!n&&s.jsx("p",{style:{margin:"0.5rem 0 0",fontSize:"0.9rem",color:"var(--text-secondary)"},children:"Checking…"}),n&&s.jsx("p",{role:"alert",style:{margin:"0.5rem 0 0",fontSize:"0.9rem",color:"var(--danger, #c00)"},children:n}),e&&s.jsxs(s.Fragment,{children:[s.jsxs("p",{style:{margin:"0.5rem 0 0",fontSize:"0.9rem",color:"var(--text-secondary)"},children:[s.jsx("strong",{children:"URL:"})," ",s.jsx("code",{children:e.asUrl})]}),e.paired&&e.fingerprint?s.jsxs("p",{style:{margin:"0.5rem 0 0",fontSize:"0.9rem",color:"var(--text-secondary)"},children:[s.jsx("strong",{children:"Key fingerprint:"})," ",s.jsx("code",{children:e.fingerprint}),s.jsx("br",{}),s.jsx("span",{style:{fontSize:"0.8rem",color:"var(--text-tertiary)"},children:"Compare this with the fingerprint on the Authority Server's own admin page over a second channel (phone, video call) to confirm this gateway is talking to the right server."})]}):s.jsx("p",{style:{margin:"0.5rem 0 0",fontSize:"0.85rem",color:"var(--text-tertiary)"},children:"Not yet paired — sign in once to pin this server's key."}),s.jsxs("p",{style:{margin:"0.75rem 0 0",fontSize:"0.8rem",color:"var(--text-tertiary)"},children:["To point this gateway at a different Authority Server:"," ",s.jsx("code",{children:"suveren-gateway config set as-url <url>"}),", then restart. Changing it ends the current sign-in and clears cached mandates — you sign in again against the new server."]})]})]})}const Gx={ollama:{provider:"ollama",endpoint:"http://localhost:11434",models:["gemma4:e4b","gemma4:e2b","gemma4:26b","gemma4:31b","llama3.2","llama3.1","mistral","qwen2.5"]},openrouter:{provider:"openai-compatible",endpoint:"https://openrouter.ai/api/v1",models:["google/gemma-4-31b-it","qwen/qwen3.6-plus:free","stepfun/step-3.5-flash:free","google/gemini-2.5-flash","openai/gpt-4o-mini","anthropic/claude-haiku-4"]},openai:{provider:"openai-compatible",endpoint:"https://api.openai.com/v1",models:["gpt-4o-mini","gpt-4o","o3-mini"]},groq:{provider:"openai-compatible",endpoint:"https://api.groq.com/openai/v1",models:["llama-3.1-8b-instant","llama-3.3-70b-versatile","gemma2-9b-it"]},together:{provider:"openai-compatible",endpoint:"https://api.together.xyz/v1",models:["meta-llama/Llama-3-8b-chat-hf","meta-llama/Llama-3-70b-chat-hf"]}};function Kx(){const[e,t]=u.useState(""),[n,r]=u.useState("openrouter"),[a,o]=u.useState("openai-compatible"),[i,l]=u.useState("https://openrouter.ai/api/v1"),[c,d]=u.useState("google/gemma-4-31b-it"),[f,p]=u.useState(""),[m,w]=u.useState(!1),[y,x]=u.useState(!1),[j,g]=u.useState(!1),[h,v]=u.useState(null),[S,b]=u.useState([]),[N,C]=u.useState(!1),[R,E]=u.useState(null),[L,D]=u.useState(""),V=u.useCallback(z=>{t(z),setTimeout(()=>t(""),3e3)},[]),J=u.useCallback(async(z,W,I)=>{C(!0),E(null);try{const B=await T.aiModels({provider:z,endpoint:W,...I?{apiKey:I}:{}});B.ok&&B.models.length>0?(b(B.models),E(`${B.models.length} models available`)):(b([]),E(B.message||"No models returned — using defaults"))}catch(B){b([]),E(B instanceof Error?B.message:"Failed to load models")}finally{C(!1)}},[]),U=u.useCallback(async()=>{try{const z=await T.getCredential("ai-config");if(w(z.configured),z.configured&&z.fields){const W=z.fields.provider||"openai-compatible",I=z.fields.endpoint||"";z.fields.provider&&o(W),z.fields.endpoint&&l(I),z.fields.model&&d(z.fields.model),I.includes("openai.com")?r("openai"):I.includes("groq.com")?r("groq"):I.includes("together.xyz")?r("together"):I.includes("openrouter.ai")?r("openrouter"):r("ollama"),I&&J(W,I)}}catch{}},[J]);u.useEffect(()=>{U()},[U]);const P=z=>{r(z),b([]),E(null),D("");const W=Gx[z];W&&(o(W.provider),l(W.endpoint),d(""),J(W.provider,W.endpoint,f||void 0))},ee=()=>J(a,i,f||void 0),F=async()=>{x(!0);try{await T.setCredential("ai-config",{provider:a,endpoint:i,model:c,...f?{apiKey:f}:{}}),w(!0),V("AI configuration saved!")}catch{V("Failed to save AI config")}finally{x(!1)}},$=async()=>{g(!0),v(null);try{const z=await T.aiTest({provider:a,endpoint:i,model:c,...f?{apiKey:f}:{}});v(z.ok?`OK: ${z.message}`:`Failed: ${z.message}`)}catch(z){v(`Error: ${z instanceof Error?z.message:"Unknown"}`)}finally{g(!1)}};return s.jsxs(s.Fragment,{children:[s.jsxs("div",{className:"page-header",children:[s.jsx("h1",{className:"page-title",children:"AI Assistant"}),s.jsx("p",{className:"page-subtitle",children:"Advisory AI to help you think through intent when giving mandates."})]}),e&&s.jsx("div",{className:"alert alert-success",children:e}),s.jsxs("div",{className:"card",children:[s.jsx("h3",{className:"card-title",children:"Configuration"}),s.jsx("p",{style:{fontSize:"0.85rem",color:"var(--text-secondary)",marginBottom:"1rem"},children:"Connect a trusted AI model that has access to your intent — problem, objective, and tradeoffs — to help you think through mandates. Keys are encrypted in your vault."}),m&&s.jsxs("div",{className:"status-banner status-banner-success",style:{marginBottom:"1rem",fontSize:"0.8rem"},children:[s.jsx("span",{className:"status-banner-icon",children:"✓"}),s.jsx("span",{className:"status-banner-text",children:"AI configured"})]}),s.jsxs("div",{className:"form-group",style:{marginBottom:"0.75rem"},children:[s.jsx("label",{className:"form-label",children:"Provider Preset"}),s.jsxs("select",{className:"form-input",value:n,onChange:z=>P(z.target.value),children:[s.jsx("option",{value:"openrouter",children:"OpenRouter (recommended)"}),s.jsx("option",{value:"ollama",children:"Ollama (local)"}),s.jsx("option",{value:"openai",children:"OpenAI"}),s.jsx("option",{value:"groq",children:"Groq"}),s.jsx("option",{value:"together",children:"Together"})]})]}),s.jsxs("div",{className:"form-group",style:{marginBottom:"0.75rem"},children:[s.jsxs("label",{className:"form-label",children:["API Key ",a==="ollama"?"(not needed for Ollama)":"(required to load models)"]}),s.jsx("input",{className:"form-input",type:"password",name:"ai-provider-api-key-credential-top",autoComplete:"new-password",value:f,onChange:z=>p(z.target.value),onBlur:()=>{f.trim()&&J(a,i,f.trim())},placeholder:m?"••••••••••••••••":"sk-... (not needed for Ollama)"}),s.jsx("p",{style:{fontSize:"0.75rem",color:"var(--text-secondary)",margin:"0.375rem 0 0"},children:"Each provider uses its own key — paste it and the model list loads automatically."})]}),s.jsxs("div",{className:"form-group",style:{marginBottom:"0.75rem"},children:[s.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center"},children:[s.jsx("label",{className:"form-label",children:"Model"}),s.jsx("button",{type:"button",className:"btn btn-ghost",style:{fontSize:"0.75rem",padding:"0.125rem 0.5rem"},onClick:ee,disabled:N,title:"Re-fetch the model list from the provider",children:N?"Loading…":"↻ Refresh"})]}),S.length===0?s.jsx("div",{className:"form-input",style:{display:"flex",alignItems:"center",minHeight:"2.5rem",color:"var(--text-secondary)",fontSize:"0.85rem"},children:N?"Loading models…":a==="ollama"?"Start Ollama locally, then ↻ Refresh to load models.":"Enter a valid API key above to load available models."}):(()=>{const z=S,W=z.includes(c),I=z.length>12,B=L.trim().toLowerCase();let Q=B?z.filter(q=>q.toLowerCase().includes(B)):z;return W&&!Q.includes(c)&&(Q=[c,...Q]),s.jsxs(s.Fragment,{children:[I&&s.jsx("input",{className:"form-input",value:L,onChange:q=>D(q.target.value),placeholder:"Filter models… (e.g. kimi)",style:{marginBottom:"0.375rem"}}),s.jsxs("select",{className:"form-input",value:W?c:"__unset__",onChange:q=>d(q.target.value==="__unset__"?"":q.target.value),children:[s.jsx("option",{value:"__unset__",disabled:!0,children:"Select a model…"}),Q.map(q=>s.jsx("option",{value:q,children:q},q)),B&&Q.length===0&&s.jsxs("option",{value:"__unset__",disabled:!0,children:["No models match “",L,"”"]})]})]})})(),R&&s.jsx("p",{style:{fontSize:"0.75rem",color:"var(--text-secondary)",margin:"0.375rem 0 0"},children:R})]}),s.jsxs("div",{style:{display:"flex",gap:"0.5rem",alignItems:"center"},children:[s.jsx("button",{className:"btn btn-primary",onClick:F,disabled:y||!c.trim(),title:c.trim()?void 0:"Select a model first",children:y?"Saving...":"Save & Encrypt"}),m&&s.jsx("button",{className:"btn btn-ghost",onClick:$,disabled:j,children:j?"Testing...":"Test Connection"})]}),h&&s.jsx("div",{className:`alert ${h.startsWith("OK")?"alert-success":"alert-error"}`,style:{marginTop:"0.75rem"},children:h})]}),s.jsx(Yx,{}),s.jsx(Dx,{}),s.jsx(Ux,{}),s.jsx(Vx,{}),s.jsx(Hx,{}),s.jsxs("div",{className:"card",style:{padding:"1.5rem",marginTop:"2rem"},children:[s.jsx("h2",{style:{fontSize:"1rem",fontWeight:700,marginBottom:"1rem"},children:"Security"}),s.jsxs("div",{style:{fontSize:"0.85rem",color:"var(--text-secondary)",lineHeight:1.7},children:[s.jsxs("div",{style:{marginBottom:"1rem"},children:[s.jsx("div",{style:{fontWeight:600,color:"var(--text-primary)",marginBottom:"0.375rem"},children:"What the gateway protects"}),s.jsxs("ul",{style:{margin:0,paddingLeft:"1.25rem"},children:[s.jsx("li",{children:"Every tool call verified against your mandate bounds"}),s.jsx("li",{children:"Credentials never exposed to agents through MCP"}),s.jsx("li",{children:"Every action produces a signed ticket"})]})]}),s.jsxs("div",{children:[s.jsx("div",{style:{fontWeight:600,color:"var(--text-primary)",marginBottom:"0.375rem"},children:"Your responsibility"}),s.jsxs("ul",{style:{margin:0,paddingLeft:"1.25rem"},children:[s.jsx("li",{children:"If your AI agent has full access to your computer, it could bypass the gateway"}),s.jsx("li",{children:"For best security, run agents in sandboxed environments"}),s.jsx("li",{children:"The gateway secures what agents do through tools — not what they do on your machine"})]})]})]})]})]})}function Yx(){const[e,t]=u.useState(null),[n,r]=u.useState({intent:"",context:""}),[a,o]=u.useState(null),[i,l]=u.useState(null),[c,d]=u.useState(null),[f,p]=u.useState(!1),m=u.useCallback(async()=>{if(!f)try{const x=await T.getAIPrompts();t(x),r({intent:x.intent.current,context:x.context.current}),p(!0)}catch(x){l(x instanceof Error?x.message:"Failed to load prompts")}},[f]),w=async x=>{if(e){o(x),l(null);try{const j=n[x],g=j.trim()===e[x].default.trim()?"":j;await T.setAIPrompt(x,g);const h=await T.getAIPrompts();t(h),r({intent:h.intent.current,context:h.context.current}),d(x),setTimeout(()=>d(null),2e3)}catch(j){l(j instanceof Error?j.message:"Save failed")}finally{o(null)}}},y=async x=>{if(confirm(`Revert ${x} prompt to the built-in default?`)){o(x),l(null);try{await T.setAIPrompt(x,"");const j=await T.getAIPrompts();t(j),r({intent:j.intent.current,context:j.context.current})}catch(j){l(j instanceof Error?j.message:"Revert failed")}finally{o(null)}}};return s.jsxs("details",{className:"card",style:{padding:"1.5rem",marginTop:"1rem"},onToggle:x=>{x.currentTarget.open&&m()},children:[s.jsx("summary",{style:{fontSize:"1rem",fontWeight:700,cursor:"pointer",listStyle:"revert",userSelect:"none"},children:"Advanced — AI assistant prompts"}),s.jsx("p",{style:{fontSize:"0.85rem",color:"var(--text-secondary)",margin:"0.75rem 0 1rem 0",lineHeight:1.55},children:"These are the system prompts the AI assistant sees when helping you write Intent (per-mandate) or Context (your standing-orders brief). Edit with care — changes apply on the next chat turn."}),i&&s.jsx("div",{className:"alert alert-error",style:{marginBottom:"0.75rem"},children:i}),!f&&!i&&s.jsx("p",{style:{color:"var(--text-muted)",fontSize:"0.85rem"},children:"Loading prompts…"}),e&&s.jsxs(s.Fragment,{children:[s.jsx(mu,{kind:"intent",label:"Intent — per-mandate",description:"Used on the Intent gate when creating a new mandate.",state:e.intent,draft:n.intent,onChange:x=>r(j=>({...j,intent:x})),onSave:()=>w("intent"),onRevert:()=>y("intent"),saving:a==="intent",justSaved:c==="intent"}),s.jsx(mu,{kind:"context",label:"Context — standing-orders brief",description:"Used on the Brief page when refining your context.md.",state:e.context,draft:n.context,onChange:x=>r(j=>({...j,context:x})),onSave:()=>w("context"),onRevert:()=>y("context"),saving:a==="context",justSaved:c==="context"})]})]})}function mu({kind:e,label:t,description:n,state:r,draft:a,onChange:o,onSave:i,onRevert:l,saving:c,justSaved:d}){const f=a!==r.current;return s.jsxs("section",{style:{marginBottom:"1.5rem"},children:[s.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"baseline",marginBottom:"0.25rem",gap:"1rem",flexWrap:"wrap"},children:[s.jsxs("div",{children:[s.jsx("div",{style:{fontWeight:600,fontSize:"0.9rem"},children:t}),s.jsx("div",{style:{fontSize:"0.78rem",color:"var(--text-secondary)"},children:n})]}),r.overridden&&s.jsx("span",{style:{fontSize:"0.7rem",color:"var(--accent)",fontWeight:600,textTransform:"uppercase",letterSpacing:"0.05em"},children:"Custom"})]}),s.jsx("textarea",{className:"form-textarea",value:a,onChange:p=>o(p.target.value),rows:12,spellCheck:!1,style:{width:"100%",fontFamily:"'SF Mono', Monaco, 'Cascadia Code', monospace",fontSize:"0.82rem",lineHeight:1.55,resize:"vertical",minHeight:"14rem",marginTop:"0.5rem"},"aria-label":`${t} system prompt`}),s.jsxs("div",{style:{display:"flex",gap:"0.5rem",alignItems:"center",marginTop:"0.5rem",flexWrap:"wrap"},children:[s.jsx("button",{type:"button",className:"btn btn-primary btn-sm",onClick:i,disabled:c||!f,children:c?"Saving…":"Save"}),r.overridden&&s.jsx("button",{type:"button",className:"btn btn-ghost btn-sm",onClick:l,disabled:c,title:"Discard the override and use the built-in default",children:"Revert to default"}),d&&s.jsx("span",{style:{fontSize:"0.78rem",color:"var(--success)"},children:"Saved"}),f&&!c&&!d&&s.jsx("span",{style:{fontSize:"0.78rem",color:"var(--text-muted)"},children:"Unsaved changes"})]}),s.jsxs("details",{style:{marginTop:"0.5rem"},children:[s.jsx("summary",{style:{fontSize:"0.78rem",color:"var(--text-muted)",cursor:"pointer"},children:"Show built-in default"}),s.jsx("pre",{style:{marginTop:"0.5rem",padding:"0.75rem 1rem",background:"var(--bg-main)",border:"1px solid var(--border)",borderRadius:"0.5rem",fontSize:"0.78rem",lineHeight:1.55,whiteSpace:"pre-wrap",maxHeight:"20rem",overflowY:"auto"},children:r.default})]}),s.jsx("span",{style:{display:"none"},children:e})]})}function Qx(e){return e.proposalId?"review":"automatic"}function pu(e,t,n={}){const r=n.status??"pending",a=n.includeAutonomous??!1,o=[];for(const i of e)r==="pending"&&i.status!=="pending"||n.profile&&i.profileId!==n.profile||o.push({kind:"proposal",id:i.id,sortTimestamp:i.createdAt,commitmentMode:"review",profileId:i.profileId,proposal:i});if(r==="all")for(const i of t){const l=Qx(i);!a&&l==="automatic"||n.profile&&i.profileId!==n.profile||o.push({kind:"receipt",id:i.id,sortTimestamp:i.timestamp,commitmentMode:l,profileId:i.profileId,receipt:i})}return o.sort((i,l)=>l.sortTimestamp-i.sortTimestamp),typeof n.limit=="number"&&n.limit>0?o.slice(0,n.limit):o}const Jx=["https://","http://"];function ym(e,t){return e!=null&&e.length?e.flatMap(n=>{const r=n.template.replace(/\{(\w+)\}/g,(a,o)=>{const i=t[o];return typeof i=="string"||typeof i=="number"?String(i):"\0"});return r.includes("\0")||/\{|\}/.test(r)?[]:Jx.some(a=>r.toLowerCase().startsWith(a))?[{label:n.label,href:r,description:n.description}]:[]}):[]}function Xx({profileId:e}){return s.jsx("span",{className:"profile-badge",children:Le(e)})}function xm(e,t){const n=e-Math.floor(t/1e3);if(n<=0)return{label:"expired",urgent:!1,expired:!0};const r=Math.floor(n/86400),a=Math.floor(n%86400/3600),o=Math.floor(n%3600/60);let i;return r>0?i=`expires in ${r}d ${a}h`:a>0?i=`expires in ${a}h ${o}m`:i=`expires in ${Math.max(1,o)}m`,{label:i,urgent:n<2*3600,expired:!1}}const qx={pending:"Pending",committed:"Approved",executed:"Executed",rejected:"Rejected",expired:"Expired"},Zx={pending:"status-pending",committed:"status-active",executed:"status-active",rejected:"status-revoked",expired:"status-expired"};function e0(e){const t=Date.now()-e*1e3,n=t/36e5;return n<48?n<1?`${Math.max(1,Math.round(t/6e4))}m ago`:`${Math.round(n)}h ago`:new Date(e*1e3).toLocaleString(void 0,{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit"})}function t0(e){return e.split("__").pop()??e}function n0(e){const t=e.toLowerCase();return t.includes("delete")||t.includes("refund")||t.includes("cancel")||t.includes("revoke")}const r0=new Set(["apiKey","api_key","accessToken","access_token","password","secret","signature","_imagePreview"]),s0=/^(image|img|photo|picture|thumbnail)(_?url)?$/i;function a0(e,t){return typeof t!="string"?!1:/^data:image\//i.test(t)?!0:s0.test(e)?/^https?:\/\//.test(t):/^https?:\/\/.+\.(jpe?g|png|gif|webp|svg|avif)(\?|$)/i.test(t)}function Pi(e){if(e==null)return"—";if(typeof e=="string")return e;if(typeof e=="number"||typeof e=="boolean")return String(e);if(Array.isArray(e))return e.map(t=>Pi(t)).join(", ");try{return JSON.stringify(e,null,2)}catch{return String(e)}}function hu({item:e,onApprove:t,onReject:n,resolving:r,proposalLinks:a}){const o=e.kind==="proposal",i=o?e.proposal.status:"executed",l=o?e.proposal.tool:e.receipt.action,c=t0(l),d=n0(l),f=o?e.proposal.toolArgs:null,p=o?e.proposal.executionContext:e.receipt.executionContext,m=o?null:e.receipt.cumulativeState,w=o?ym(a,e.proposal.toolArgs):[],y=f?Object.entries(f).filter(([j])=>!r0.has(j)):[],x=Object.entries(p??{});return s.jsxs("div",{className:"card",children:[s.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"0.5rem",marginBottom:"0.75rem",flexWrap:"wrap"},children:[s.jsx(Xx,{profileId:e.profileId}),s.jsx("code",{style:{fontSize:"0.85rem"},children:c}),e.commitmentMode==="automatic"&&s.jsx("span",{style:{fontSize:"0.7rem",color:"var(--text-tertiary)",textTransform:"uppercase",letterSpacing:"0.04em"},children:"autonomous"}),s.jsxs("span",{style:{marginLeft:"auto",display:"flex",alignItems:"center",gap:"0.5rem"},children:[o&&i==="pending"&&(()=>{const j=xm(e.proposal.expiresAt,Date.now());return s.jsx("span",{style:{fontSize:"0.72rem",color:j.urgent?"var(--warning)":"var(--text-tertiary)",fontWeight:j.urgent?600:400,whiteSpace:"nowrap"},children:j.label})})(),s.jsx("span",{className:`status-badge ${Zx[i]}`,children:qx[i]}),s.jsx("span",{style:{fontSize:"0.75rem",color:"var(--text-tertiary)"},children:e0(e.sortTimestamp)})]})]}),d&&s.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"0.4rem",fontSize:"0.8rem",color:"var(--warning)",background:"var(--bg-main)",border:"1px solid var(--border)",borderRadius:"0.375rem",padding:"0.4rem 0.6rem",marginBottom:"0.75rem"},children:[s.jsx("span",{children:"⚠"}),s.jsx("span",{children:"Irreversible action"})]}),o&&typeof(f==null?void 0:f._imagePreview)=="string"&&s.jsxs("div",{style:{marginBottom:"0.75rem"},children:[s.jsx("div",{style:{fontSize:"0.7rem",fontWeight:600,color:"var(--text-tertiary)",textTransform:"uppercase",letterSpacing:"0.04em",marginBottom:"0.35rem"},children:"Preview"}),s.jsx("img",{src:f._imagePreview,alt:typeof(f==null?void 0:f.altText)=="string"?f.altText:"local image preview",style:{display:"block",maxWidth:"100%",maxHeight:"240px",borderRadius:"0.375rem",border:"1px solid var(--border)"}})]}),w.length>0&&s.jsx("div",{style:{marginBottom:"0.75rem",display:"flex",gap:"0.5rem",flexWrap:"wrap"},children:w.map(j=>s.jsxs("a",{href:j.href,target:"_blank",rel:"noopener noreferrer",className:"btn btn-secondary btn-sm",style:{textDecoration:"none"},title:j.description??j.href,children:[j.label," ↗"]},j.label))}),o&&y.length>0&&s.jsxs("div",{style:{marginBottom:"0.75rem"},children:[s.jsx("div",{style:{fontSize:"0.7rem",fontWeight:600,color:"var(--text-tertiary)",textTransform:"uppercase",letterSpacing:"0.04em",marginBottom:"0.35rem"},children:"Arguments"}),s.jsx("dl",{style:{display:"grid",gridTemplateColumns:"max-content 1fr",gap:"0.2rem 0.75rem",fontSize:"0.85rem",margin:0},children:y.map(([j,g])=>s.jsxs(u.Fragment,{children:[s.jsx("dt",{style:{color:"var(--text-tertiary)",whiteSpace:"nowrap",alignSelf:"start"},children:j}),s.jsx("dd",{style:{color:"var(--text-primary)",margin:0,wordBreak:"break-word",whiteSpace:"pre-wrap"},children:a0(j,g)?s.jsx("img",{src:g,alt:typeof(f==null?void 0:f.altText)=="string"?f.altText:j,style:{display:"block",maxWidth:"100%",maxHeight:"240px",borderRadius:"0.375rem",border:"1px solid var(--border)"},onError:h=>{const v=h.currentTarget,S=v.parentElement;if(!S)return;v.style.display="none";const b=document.createElement("span");b.textContent=g,b.style.color="var(--text-tertiary)",S.appendChild(b)}}):Pi(g)})]},j))})]}),x.length>0&&s.jsx("div",{style:{marginBottom:"0.75rem",fontSize:"0.8rem",color:"var(--text-secondary)"},children:x.map(([j,g])=>`${j}=${Pi(g)}`).join(" · ")}),m&&s.jsxs("div",{style:{fontSize:"0.75rem",color:"var(--text-tertiary)",marginBottom:"0.5rem"},children:["After this action · today: ",m.daily.count," action",m.daily.count===1?"":"s",m.daily.amount>0?`, ${m.daily.amount}`:""," · ","this month: ",m.monthly.count,m.monthly.amount>0?`, ${m.monthly.amount}`:""]}),o&&i==="pending"&&s.jsxs("div",{style:{display:"flex",gap:"0.5rem"},children:[s.jsx("button",{className:"btn btn-primary",onClick:()=>t==null?void 0:t(e.id),disabled:r,children:r?"Approving…":"Approve"}),s.jsx("button",{className:"btn btn-ghost",style:{color:"var(--danger)"},onClick:()=>n==null?void 0:n(e.id),disabled:r,children:"Reject"})]}),s.jsxs("div",{style:{marginTop:"0.5rem",fontSize:"0.7rem",color:"var(--text-tertiary)"},children:[o?"Proposal":"Ticket",": ",e.id]})]})}const o0=new Set(["apiKey","api_key","accessToken","access_token","password","secret","signature","_imagePreview"]);function _i(e){if(e==null)return"—";if(typeof e=="string")return e;if(typeof e=="number"||typeof e=="boolean")return String(e);if(Array.isArray(e))return e.map(t=>_i(t)).join(", ");try{return JSON.stringify(e,null,2)}catch{return String(e)}}function i0(e){const t=Date.now()-e*1e3,n=Math.floor(t/6e4);if(n<60)return`${Math.max(1,n)}m ago`;const r=Math.floor(t/36e5);return r<48?`${r}h ago`:`${Math.floor(r/24)}d ago`}function l0({proposal:e,currentUserId:t,onAction:n,onMessage:r,proposalLinks:a}){const[o,i]=u.useState(!1),[l,c]=u.useState(!1),[d,f]=u.useState(null),[p,m]=u.useState(!1),[w,y]=u.useState(null),[x,j]=u.useState(!1),g=e.tool.split("__").pop()??e.tool,h=Object.entries(e.toolArgs).filter(([P])=>!o0.has(P)),v=Object.entries(e.executionContext),S=ym(a,e.toolArgs),b=e.pendingApprovers??[],N=e.approvedBy??{},C=Object.keys(N).length,R=b.filter(P=>!(P in N)).length,E=t in N,L=async()=>{if(d===null){m(!0),y(null);try{const P=await T.getAttestationIntent(e.authorizationId);if(!P){y("Intent not available or you are not an authorized approver.");return}const ee=await T.decryptIntent({intentCiphertext:P.intentCiphertext,encryptedKey:P.encryptedKey,approverId:t});f(ee)}catch(P){y(P instanceof Error?P.message:"Failed to decrypt intent")}finally{m(!1)}}},D=async()=>{x?j(!1):(j(!0),await L())},V=async()=>{i(!0),r("");try{await T.approveProposal(e.id);try{if(d===null){const P=await T.getAttestationIntent(e.authorizationId);if(P){const ee=await T.decryptIntent({intentCiphertext:P.intentCiphertext,encryptedKey:P.encryptedKey,approverId:t});f(ee),await T.storeApprovedIntent(e.authorizationId,ee)}}else await T.storeApprovedIntent(e.authorizationId,d)}catch{}r(`Approved. ${R-1>0?`${R-1} more approver(s) still needed.`:"All approvers signed off — action is ready to execute."}`),n()}catch(P){r(P instanceof Error?P.message:"Approval failed")}finally{i(!1)}},J=async()=>{const P=prompt("Rejection reason (optional):");if(P!==null){c(!0),r("");try{await T.rejectProposal(e.id,P||void 0),r("Action rejected."),n()}catch(ee){r(ee instanceof Error?ee.message:"Rejection failed")}finally{c(!1)}}},U=o||l;return s.jsxs("div",{className:"card",children:[s.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"0.5rem",marginBottom:"0.5rem",flexWrap:"wrap"},children:[s.jsx("span",{style:{fontWeight:600,fontSize:"0.9rem"},children:Le(e.profileId)}),s.jsx("span",{style:{fontSize:"0.65rem",padding:"0.15rem 0.4rem",borderRadius:"0.25rem",background:"var(--accent-subtle)",color:"var(--accent)",fontWeight:600},children:"Above cap"}),s.jsxs("span",{style:{marginLeft:"auto",display:"flex",alignItems:"center",gap:"0.5rem"},children:[(()=>{const P=xm(e.expiresAt,Date.now());return s.jsx("span",{style:{fontSize:"0.72rem",color:P.urgent?"var(--warning)":"var(--text-tertiary)",fontWeight:P.urgent?600:400,whiteSpace:"nowrap"},children:P.label})})(),s.jsx("span",{style:{fontSize:"0.75rem",color:"var(--text-tertiary)"},children:i0(e.createdAt)})]})]}),s.jsxs("div",{style:{fontSize:"0.8rem",color:"var(--text-tertiary)",marginBottom:"0.5rem"},children:[C," of ",b.length," approver",b.length===1?"":"s"," signed off",b.map(P=>{const ee=P in N;return s.jsxs("span",{style:{marginLeft:"0.5rem",color:ee?"var(--success, green)":"var(--text-tertiary)"},children:[ee?"✓":"○"," ",P===t?"You":P]},P)})]}),s.jsxs("div",{style:{marginBottom:"0.5rem"},children:[s.jsx("div",{style:{fontSize:"0.7rem",fontWeight:600,color:"var(--text-tertiary)",textTransform:"uppercase",letterSpacing:"0.04em",marginBottom:"0.25rem"},children:"Proposed action"}),s.jsx("code",{style:{fontSize:"0.85rem"},children:g})]}),S.length>0&&s.jsx("div",{style:{marginBottom:"0.75rem",display:"flex",gap:"0.5rem",flexWrap:"wrap"},children:S.map(P=>s.jsxs("a",{href:P.href,target:"_blank",rel:"noopener noreferrer",className:"btn btn-secondary btn-sm",style:{textDecoration:"none"},title:P.description??P.href,children:[P.label," ↗"]},P.label))}),h.length>0&&s.jsxs("div",{style:{marginBottom:"0.75rem"},children:[s.jsx("div",{style:{fontSize:"0.7rem",fontWeight:600,color:"var(--text-tertiary)",textTransform:"uppercase",letterSpacing:"0.04em",marginBottom:"0.25rem"},children:"Arguments"}),s.jsx("dl",{style:{display:"grid",gridTemplateColumns:"max-content 1fr",gap:"0.2rem 0.75rem",fontSize:"0.85rem",margin:0},children:h.map(([P,ee])=>s.jsxs(u.Fragment,{children:[s.jsx("dt",{style:{color:"var(--text-tertiary)",whiteSpace:"nowrap",alignSelf:"start"},children:P}),s.jsx("dd",{style:{color:"var(--text-primary)",margin:0,wordBreak:"break-word",whiteSpace:"pre-wrap"},children:_i(ee)})]},P))})]}),v.length>0&&s.jsx("div",{style:{fontSize:"0.8rem",color:"var(--text-secondary)",marginBottom:"0.5rem"},children:v.map(([P,ee])=>`${P}=${_i(ee)}`).join(" · ")}),s.jsxs("div",{style:{marginBottom:"0.75rem"},children:[s.jsxs("button",{className:"btn btn-ghost btn-sm",style:{padding:"0.2rem 0",fontSize:"0.75rem"},onClick:D,disabled:p,children:[x?"▲ Hide intent":"▼ Show intent",p&&" (decrypting...)"]}),x&&s.jsx("div",{style:{marginTop:"0.5rem",padding:"0.75rem",background:"var(--bg-main)",borderRadius:"0.375rem",border:"1px solid var(--border)"},children:w?s.jsx("p",{style:{color:"var(--danger)",fontSize:"0.8rem",margin:0},children:w}):d!==null?s.jsx("p",{style:{fontSize:"0.85rem",margin:0,whiteSpace:"pre-wrap",color:"var(--text-primary)"},children:d}):s.jsx("p",{style:{color:"var(--text-tertiary)",fontSize:"0.8rem",margin:0},children:"No intent available for this mandate."})})]}),!E&&s.jsxs("div",{style:{display:"flex",gap:"0.5rem",marginTop:"0.25rem"},children:[s.jsx("button",{className:"btn btn-primary",onClick:V,disabled:U,children:o?"Approving...":"Approve"}),s.jsx("button",{className:"btn btn-ghost",style:{color:"var(--danger)"},onClick:J,disabled:U,children:l?"Rejecting...":"Reject"})]}),E&&s.jsx("p",{style:{fontSize:"0.8rem",color:"var(--text-tertiary)",marginTop:"0.25rem"},children:"You approved this action. Waiting on other approvers."}),s.jsxs("div",{style:{marginTop:"0.5rem",fontSize:"0.7rem",color:"var(--text-tertiary)"},children:["Proposal: ",e.id]})]})}function c0(){const{domain:e,user:t}=Oe(),n=(t==null?void 0:t.id)??"",[r,a]=u.useState("awaiting-me"),[o,i]=u.useState([]),[l,c]=u.useState([]),[d,f]=u.useState(!0),[p,m]=u.useState(""),w=u.useCallback(async()=>{try{const _=await T.getProposalsForApprover();i(_)}catch{}finally{f(!1)}},[]);fe("proposal-added",w),fe("proposal-approved",w),fe("proposal-rejected",w),fe("proposal-resolved",w),Pt(w,3e4);const[y,x]=u.useState([]),j=u.useCallback(async()=>{try{const _=await T.getProposals(e||"owner");x(_)}catch{}},[e]);fe("proposal-added",j),fe("proposal-approved",j),fe("proposal-rejected",j),fe("proposal-resolved",j),Pt(j,3e4,e);const g=u.useMemo(()=>y.filter(_=>{var X;return _.status==="pending"&&(((X=_.pendingApprovers)==null?void 0:X.length)??0)===0}),[y]),h=u.useMemo(()=>pu(g,[],{status:"pending"}),[g]),[v,S]=u.useState([]),b=u.useCallback(async()=>{if(n)try{const X=(await T.getProposals(e||"owner")).filter(ae=>ae.status==="pending"&&ae.pendingApprovers&&ae.pendingApprovers.includes(n)&&ae.approvedBy&&n in ae.approvedBy);S(X)}catch{}},[n,e]);fe("proposal-approved",b),fe("proposal-rejected",b),Pt(b,3e4,`${n}:${e}`),u.useEffect(()=>{T.getIntegrationManifests().then(_=>c(_.manifests??[])).catch(()=>{})},[]);const N=_=>{var X;return(X=l.find(ae=>ae.id===_.split("__")[0]))==null?void 0:X.proposalLinks};u.useEffect(()=>{w(),j(),b()},[]);const[C,R]=u.useState([]),[E,L]=u.useState([]),[D,V]=u.useState(!0),[J,U]=u.useState(null),[P,ee]=u.useState(""),[F,$]=u.useState("pending"),[z,W]=u.useState(null),[I,B]=u.useState(!1),Q=u.useCallback(async()=>{try{const{proposals:_,receipts:X}=await T.getThread({domain:e,status:F,sinceDays:7});R(_),L(X)}catch{}finally{V(!1)}},[e,F]);Pt(Q,3e4,`${e}:${F}`);const q=async(_,X)=>{U(_),ee("");try{const ae=e||"owner",ge=await T.resolveProposal(_,X,ae);ee(X==="commit"?`Action approved. Status: ${ge.status}`:"Action rejected."),await Promise.all([Q(),j()])}catch(ae){ee(ae instanceof Error?ae.message:"Failed")}finally{U(null)}},re=u.useMemo(()=>{const _=new Set;for(const X of C)_.add(X.profileId);for(const X of E)_.add(X.profileId);return Array.from(_).sort()},[C,E]),ce=u.useMemo(()=>pu(C,E,{status:F,profile:z??void 0,includeAutonomous:I}),[C,E,F,z,I]),me=u.useCallback(()=>{w(),b()},[w,b]),te=u.useMemo(()=>{const _=new Set,X=[];for(const ae of v)_.has(ae.id)||(_.add(ae.id),X.push(ae));return X.sort((ae,ge)=>ge.createdAt-ae.createdAt)},[v]),oe=o.length+h.length,se=te.length;return s.jsxs(s.Fragment,{children:[s.jsxs("div",{className:"page-header",children:[s.jsx("h1",{className:"page-title",children:"Pending Approvals"}),s.jsx("p",{className:"page-subtitle",children:"Actions awaiting approval, plus recent activity from the last 7 days."})]}),s.jsxs("div",{className:"nav-tabs",style:{marginBottom:"1rem"},children:[s.jsxs("button",{className:`nav-tab${r==="awaiting-me"?" active":""}`,onClick:()=>a("awaiting-me"),children:["Awaiting me ",oe>0&&s.jsx("span",{style:{marginLeft:"0.4rem",background:"var(--warning)",color:"var(--bg-elevated)",borderRadius:"0.625rem",padding:"0 0.375rem",fontSize:"0.7rem",fontWeight:600},children:oe})]}),s.jsxs("button",{className:`nav-tab${r==="awaiting-others"?" active":""}`,onClick:()=>a("awaiting-others"),children:["Awaiting others ",se>0&&s.jsx("span",{style:{marginLeft:"0.4rem",background:"var(--border)",color:"var(--text-secondary)",borderRadius:"0.625rem",padding:"0 0.375rem",fontSize:"0.7rem",fontWeight:600},children:se})]}),s.jsx("button",{className:`nav-tab${r==="all"?" active":""}`,onClick:()=>{a("all"),Q()},children:"All"})]}),r==="awaiting-me"&&s.jsx(s.Fragment,{children:d&&oe===0?s.jsx("p",{style:{color:"var(--text-tertiary)"},children:"Loading..."}):oe===0?s.jsxs("div",{className:"card",style:{textAlign:"center",padding:"2rem"},children:[s.jsx("p",{style:{color:"var(--text-tertiary)",marginBottom:"0.5rem"},children:"No actions awaiting your approval."}),s.jsx("p",{style:{fontSize:"0.8rem",color:"var(--text-tertiary)"},children:"Review-mode actions and above-cap actions you must approve will appear here."})]}):s.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:"1rem"},children:[(p||P)&&s.jsx("div",{className:"alert alert-success",children:p||P}),h.map(_=>s.jsx(hu,{proposalLinks:_.kind==="proposal"?N(_.proposal.tool):void 0,item:_,onApprove:X=>q(X,"commit"),onReject:X=>q(X,"reject"),resolving:J===_.id},_.id)),o.map(_=>s.jsx(l0,{proposal:_,currentUserId:n,onAction:me,onMessage:m,proposalLinks:N(_.tool)},_.id))]})}),r==="awaiting-others"&&s.jsx(s.Fragment,{children:te.length===0?s.jsxs("div",{className:"card",style:{textAlign:"center",padding:"2rem"},children:[s.jsx("p",{style:{color:"var(--text-tertiary)",marginBottom:"0.5rem"},children:"No actions waiting on others."}),s.jsx("p",{style:{fontSize:"0.8rem",color:"var(--text-tertiary)"},children:"Actions you proposed or approved that are pending other approvers will appear here."})]}):s.jsx("div",{style:{display:"flex",flexDirection:"column",gap:"1rem"},children:te.map(_=>s.jsx(d0,{proposal:_,currentUserId:n,onCancel:async()=>{try{await T.rejectProposal(_.id,"cancelled by creator"),b(),j()}catch(X){alert(X instanceof Error?X.message:"Cancel failed")}}},_.id))})}),r==="all"&&s.jsxs(s.Fragment,{children:[P&&s.jsx("div",{className:"alert alert-success",style:{marginBottom:"1rem"},children:P}),s.jsxs("div",{className:"filter-chips",style:{marginBottom:"1rem"},children:[s.jsx("button",{className:`filter-chip ${F==="pending"?"selected":""}`,onClick:()=>$("pending"),children:"Pending"}),s.jsx("button",{className:`filter-chip ${F==="all"?"selected":""}`,onClick:()=>$("all"),children:"All"}),re.length>0&&s.jsx("span",{style:{width:1,background:"var(--border)",alignSelf:"stretch",margin:"0 0.25rem"}}),re.map(_=>s.jsx("button",{className:`filter-chip ${z===_?"selected":""}`,onClick:()=>W(z===_?null:_),children:Le(_)},_)),F==="all"&&s.jsxs(s.Fragment,{children:[s.jsx("span",{style:{width:1,background:"var(--border)",alignSelf:"stretch",margin:"0 0.25rem"}}),s.jsxs("button",{className:`filter-chip ${I?"selected":""}`,onClick:()=>B(!I),title:"Include actions executed without human review (automatic commitment mode)",children:[I?"✓ ":"","Autonomous actions"]})]})]}),D&&ce.length===0?s.jsx("p",{style:{color:"var(--text-tertiary)"},children:"Loading..."}):ce.length===0?s.jsxs("div",{className:"card",style:{textAlign:"center",padding:"2rem"},children:[s.jsx("p",{style:{color:"var(--text-tertiary)",marginBottom:"0.5rem"},children:F==="pending"?"No actions awaiting your approval.":"Nothing here yet."}),s.jsx("p",{style:{fontSize:"0.8rem",color:"var(--text-tertiary)"},children:F==="pending"?"Your agents are operating within their mandates. Switch to All to see recent activity.":"When an agent calls a gated tool, activity will appear here."})]}):s.jsx("div",{style:{display:"flex",flexDirection:"column",gap:"1rem"},children:ce.map(_=>s.jsx(hu,{proposalLinks:_.kind==="proposal"?N(_.proposal.tool):void 0,item:_,onApprove:X=>q(X,"commit"),onReject:X=>q(X,"reject"),resolving:J===_.id},_.id))})]})]})}function u0(e){const t=Date.now()-e*1e3,n=Math.floor(t/6e4);if(n<60)return`${Math.max(1,n)}m ago`;const r=Math.floor(t/36e5);return r<48?`${r}h ago`:`${Math.floor(r/24)}d ago`}function d0({proposal:e,currentUserId:t,onCancel:n}){var d;const[r,a]=u.useState(!1),o=Object.keys(e.approvedBy??{}),i=(e.pendingApprovers??[]).filter(f=>!(f in(e.approvedBy??{}))),l=(((d=e.pendingApprovers)==null?void 0:d.length)??0)>0,c=async()=>{if(confirm("Cancel this action? All approvers will be notified.")){a(!0);try{await n()}finally{a(!1)}}};return s.jsxs("div",{className:"card",children:[s.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"0.5rem",marginBottom:"0.5rem",flexWrap:"wrap"},children:[s.jsx("span",{style:{fontWeight:600,fontSize:"0.9rem"},children:Le(e.profileId)}),l&&s.jsx("span",{style:{fontSize:"0.65rem",padding:"0.15rem 0.4rem",borderRadius:"0.25rem",background:"var(--accent-subtle)",color:"var(--accent)",fontWeight:600},children:"Above cap"}),s.jsx("span",{style:{marginLeft:"auto",fontSize:"0.75rem",color:"var(--text-tertiary)"},children:u0(e.createdAt)})]}),s.jsx("div",{style:{fontSize:"0.85rem",color:"var(--text-secondary)",marginBottom:"0.5rem"},children:s.jsx("code",{children:e.tool.split("__").pop()??e.tool})}),l&&s.jsxs("div",{style:{fontSize:"0.8rem",color:"var(--text-tertiary)",marginBottom:"0.5rem"},children:[o.map(f=>s.jsx("span",{style:{marginRight:"0.75rem",color:"var(--success, green)"},children:f===t?"You approved":`${f} approved`},f)),i.map(f=>s.jsxs("span",{style:{marginRight:"0.75rem",color:"var(--text-tertiary)"},children:["Waiting on ",f===t?"you":f]},f))]}),s.jsx("div",{style:{display:"flex",justifyContent:"flex-end",gap:"0.5rem",marginTop:"0.5rem"},children:s.jsx("button",{className:"btn btn-ghost btn-sm",style:{color:"var(--danger)"},onClick:c,disabled:r,children:r?"Cancelling...":"Cancel"})})]})}const f0=`# Agent Brief
|
|
74
|
+
`}),p?s.jsx("p",{style:{color:"var(--text-tertiary)",fontSize:"0.9rem"},children:"Loading..."}):v.length===0?s.jsxs("div",{className:"card",style:{padding:"2rem",textAlign:"center"},children:[s.jsx("p",{style:{color:"var(--text-secondary)",fontSize:"0.9rem",marginBottom:"1rem"},children:"No integrations set up yet. Connect a service first."}),s.jsx(Je,{to:"/integrations",className:"btn btn-primary btn-sm",onClick:()=>e==null?void 0:e(),children:"Go to Integrations"})]}):s.jsx("div",{className:"profile-grid",children:v.map(({manifest:C,profile:R,integration:E})=>{const L=S(R.id),D=(E==null?void 0:E.running)===!0;return s.jsxs("div",{className:"card",style:D?void 0:{opacity:.7},children:[s.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"0.5rem",marginBottom:"0.125rem"},children:[s.jsx("h3",{className:"card-title",style:{margin:0},children:C.name}),L?s.jsx("span",{style:{fontSize:"0.6rem",padding:"0.1rem 0.35rem",borderRadius:"0.2rem",background:"var(--accent-subtle)",color:"var(--accent)",fontWeight:600},children:"Team"}):s.jsx("span",{style:{fontSize:"0.6rem",padding:"0.1rem 0.35rem",borderRadius:"0.2rem",background:"var(--bg-main)",color:"var(--text-tertiary)",fontWeight:600,border:"1px solid var(--border)"},children:"Personal"})]}),s.jsx("p",{style:{fontSize:"0.8rem",color:"var(--text-tertiary)",marginBottom:"1rem",flex:1},children:C.description||R.description}),D?s.jsx("button",{className:"btn btn-primary btn-sm",onClick:()=>N(R.id),children:"Give a mandate"}):s.jsxs(Je,{to:`/integrations?setup=${(C==null?void 0:C.id)??""}`,className:"btn btn-secondary btn-sm",style:{textDecoration:"none",textAlign:"center"},onClick:()=>e==null?void 0:e(),children:["Set up ",(C==null?void 0:C.name)??"integration"]})]},C.id)})})]})}const hx={active:"Active",pending:"Pending",expired:"Expired",revoked:"Revoked"};function gx({status:e,label:t}){return s.jsx("span",{className:`status-badge status-${e}`,children:t||hx[e]})}function vx({domain:e,attested:t}){const n=t===!0?"domain-attested":t===!1?"domain-missing":"";return s.jsx("span",{className:`domain-badge ${n}`,style:{fontSize:"0.75rem"},children:e})}const Tn=86400,Lr=3600,Ds=60,yx=30*Tn;function xx(e){if(e<=0)return"Expired";if(e>90*Tn){const t=Math.floor(e/yx);return`${t} ${t===1?"month":"months"} remaining`}if(e>7*Tn){const t=Math.floor(e/Tn);return`${t} ${t===1?"day":"days"} remaining`}if(e>=2*Tn){const t=Math.floor(e/Tn),n=Math.floor(e%Tn/Lr);return`${t} ${t===1?"day":"days"} ${n}h remaining`}if(e>=2*Lr){const t=Math.floor(e/Lr),n=Math.floor(e%Lr/Ds);return`${t}h ${String(n).padStart(2,"0")}m remaining`}if(e>=Ds){const t=Math.floor(e/Ds),n=Math.floor(e%Ds);return`${t}m ${String(n).padStart(2,"0")}s remaining`}return`${Math.floor(e)}s remaining`}function wx({expiresAt:e}){const[t,n]=u.useState(()=>e-Date.now()/1e3),r=t<2*Lr;u.useEffect(()=>{const o=setInterval(()=>n(e-Date.now()/1e3),r?1e3:6e4);return()=>clearInterval(o)},[e,r]);const a=t<300;return s.jsx("span",{className:`ttl-badge ${a?"ttl-warn":"ttl-ok"}`,children:xx(t)})}function vm({icon:e,title:t,text:n,children:r}){return s.jsxs("div",{className:"empty-state",children:[e&&s.jsx("div",{className:"empty-state-icon",children:e}),s.jsx("div",{className:"empty-state-title",children:t}),n&&s.jsx("div",{className:"empty-state-text",children:n}),r]})}function Sx(e){const t=Math.floor(e/86400);if(t>=1)return`${t} day${t===1?"":"s"}`;const n=Math.floor(e/3600);if(n>=1)return`${n} hour${n===1?"":"s"}`;const r=Math.ceil(e/60);return`${r} minute${r===1?"":"s"}`}const jx=[{label:"30m",seconds:1800},{label:"1h",seconds:3600},{label:"2h",seconds:7200},{label:"4h",seconds:14400},{label:"8h",seconds:28800},{label:"24h",seconds:86400},{label:"7d",seconds:604800},{label:"30d",seconds:2592e3},{label:"1y",seconds:31536e3}];function kx({item:e,onClose:t,onSuccess:n}){var v;const{user:r,activeDomain:a,groupId:o}=Oe(),[i,l]=u.useState(null);u.useEffect(()=>{let S=!1;return T.getProfile(e.profile_id).then(b=>{var N;S||l(((N=b==null?void 0:b.ttl)==null?void 0:N.max)??null)}).catch(()=>{}),()=>{S=!0}},[e.profile_id]);const c=e.remaining_seconds??0,d=jx.filter(S=>S.seconds>c&&(i===null||S.seconds<=i)),f=((v=d[0])==null?void 0:v.seconds)??2592e3,[p,m]=u.useState(f);u.useEffect(()=>{var S;if(i!==null&&p>i){const b=(S=d[d.length-1])==null?void 0:S.seconds;b&&m(b)}},[i]);const[w,y]=u.useState(!1),[x,j]=u.useState(""),g=Object.entries(e.frame).filter(([S])=>S!=="profile"&&S!=="path"),h=async()=>{var S;if(r){y(!0),j("");try{const b=e.authorization_id,N=await T.getGateContent(b);if(!N)throw new Error("Gate content not found locally. The MCP server may have restarted. Please re-authorize through the full wizard instead.");const C=await T.getProfile(e.profile_id),R=e.frame,E=N.context??{},L=e.attested_domains[0]||a||"owner",D=await ra(R,C),V=await pm(E,C),[J,U]=await Promise.all([Pa(N.gateContent.intent),Pa(JSON.stringify({profile:e.profile_id,path:e.path,domain:L}))]);if(!o)throw new Error("No active group; cannot extend mandate.");const P=(((S=e.deferred_commitment_domains)==null?void 0:S.length)??0)>0?"review":"automatic",ee=await T.attest({authorization_id:e.authorization_id,renew:!0,profile_id:e.profile_id,bounds:R,bounds_hash:D,context_hash:V,domain:L,did:r.did,gate_content_hashes:{intent:J},execution_context_hash:U,group_id:o,commitment_mode:P,ttl:p});await T.pushGateContent(hm(ee,{boundsHash:D,contextHash:V,context:E,path:e.path,gateContent:N.gateContent})),n()}catch(b){j(b instanceof Error?b.message:"Extension failed")}finally{y(!1)}}};return s.jsx("div",{className:"modal-backdrop",onClick:S=>S.target===S.currentTarget&&t(),children:s.jsxs("div",{className:"modal",children:[s.jsxs("div",{className:"modal-header",children:[s.jsx("h3",{className:"modal-title",children:"Extend mandate"}),s.jsx("button",{className:"modal-close",onClick:t,children:"×"})]}),s.jsxs("div",{className:"modal-body",children:[s.jsxs("div",{style:{marginBottom:"1rem"},children:[s.jsxs("div",{style:{fontWeight:600,marginBottom:"0.25rem"},children:[Le(e.profile_id)," / ",e.path]}),g.length>0&&s.jsx("div",{style:{fontSize:"0.8rem",color:"var(--text-tertiary)"},children:g.map(([S,b])=>`${S}=${b}`).join(" · ")})]}),s.jsxs("div",{style:{marginBottom:"1rem"},children:[s.jsx("div",{style:{fontSize:"0.75rem",fontWeight:600,color:"var(--text-tertiary)",textTransform:"uppercase",letterSpacing:"0.04em",marginBottom:"0.5rem"},children:"New duration"}),c>0&&s.jsxs("div",{style:{fontSize:"0.75rem",color:"var(--text-tertiary)",marginBottom:"0.5rem"},children:["Currently valid for ",Sx(c),". Only longer durations are shown."]}),s.jsx("div",{style:{display:"flex",gap:"0.5rem",flexWrap:"wrap"},children:d.length===0?s.jsx("div",{style:{fontSize:"0.8rem",color:"var(--text-tertiary)"},children:"This mandate is already on the longest available duration. Nothing to extend."}):d.map(S=>s.jsx("button",{className:`btn ${p===S.seconds?"btn-primary":"btn-secondary"}`,onClick:()=>m(S.seconds),style:{minWidth:"3.5rem"},children:S.label},S.seconds))})]}),s.jsx("div",{style:{fontSize:"0.8rem",color:"var(--text-tertiary)",marginBottom:"0.5rem"},children:"Same bounds, scope, and gate content will be re-signed with a new TTL (measured from now)."}),x&&s.jsx("div",{className:"error-message",children:x})]}),s.jsxs("div",{className:"modal-footer",children:[s.jsx("button",{className:"btn btn-secondary",onClick:t,disabled:w,children:"Cancel"}),s.jsx("button",{className:"btn btn-primary",onClick:h,disabled:w,children:w?"Extending...":"Extend"})]})]})})}function bx(e,t,n){return[...e].sort((r,a)=>{if(n){if(r.authorization_id===n&&a.authorization_id!==n)return-1;if(a.authorization_id===n&&r.authorization_id!==n)return 1}const o=Ra(r,t),i=Ra(a,t),l={active:0,pending:1,expired:2,revoked:3,archived:4};return l[o]!==l[i]?l[o]-l[i]:new Date(a.created_at).getTime()-new Date(r.created_at).getTime()})}function Cx({item:e,newerProfile:t,revokedSet:n,expandedHash:r,gateCache:a,gateLoading:o,copiedHash:i,revokingHash:l,copyingHash:c,profileConfigCache:d,mode:f,ownerLabel:p,isAdmin:m,onExpand:w,onCopyHash:y,onCopy:x,onRevoke:j,onExtend:g,archivedSet:h,archivingHash:v,onArchive:S,highlightHash:b}){var me;const N=Ll(e,{revokedSet:n}),C=em(e,{revokedSet:n,archivedSet:h}),R=!p&&!!S&&Zf(N),E=r===e.authorization_id,L=a[e.authorization_id],D=N==="active"||N==="pending"||N==="expired",V=Object.entries(e.frame).filter(([te])=>te!=="profile"&&te!=="path"),J=d.get(e.profile_id)??null,U=(((me=J==null?void 0:J.approvers)==null?void 0:me.length)??0)>0,P=new Map;if(J!=null&&J.caps&&f==="team")for(const[te,oe]of V){const se=J.caps[te];se!==void 0&&Number(oe)>se&&P.set(te,{authorized:Number(oe),cap:se})}const ee=P.size>0,F=e.approvers_frozen??[],$=(J==null?void 0:J.approvers)??[],z=f==="team"&&F.length>0&&$.length>0&&(F.length!==$.length||F.some(te=>!$.includes(te))||$.some(te=>!F.includes(te))),W=Array.from(P.entries()).map(([te,oe])=>`${te}: ${oe.authorized} (cap ${oe.cap})`).join(", "),I=Array.from(P.entries()).map(([te,oe])=>`${te}: ${oe.authorized} → ${oe.cap}`).join(", "),B=ee?U?P.size===1?`Above team cap: ${W} — actions require approval`:`Above team cap (${P.size}): ${W} — actions require approval`:P.size===1?`Reduced by hard cap: ${I}`:`Reduced by hard cap (${P.size}): ${I}`:"",Q=ee?U?"Above-cap actions under this mandate require per-action approval from the profile's approvers. Bounds remain authorized at their original values.":"No approvers are configured for this profile, so the team cap is a hard ceiling. Bounds above the cap are effectively reduced to the cap. Ask the admin to raise the cap or add approvers, or copy this mandate to reissue within the cap.":void 0,q=Le(e.profile_id),re=t?s.jsxs("div",{style:{fontSize:"0.75rem",color:"var(--text-tertiary)",marginBottom:"0.5rem",padding:"0.4rem 0.6rem",border:"1px solid var(--border)",borderRadius:6},children:[s.jsxs("strong",{style:{color:"var(--text-secondary)"},children:[q,"@",t.version," available"]}),t.whatsNew?s.jsxs(s.Fragment,{children:[" — ",t.whatsNew]}):null,s.jsx("br",{}),s.jsxs("span",{children:["This mandate stays on ",e.profile_id.split("@")[1]??"its pinned version","; authorize again to move it."]})]}):null,ce=b!=null&&e.authorization_id===b;return s.jsxs("div",{className:`card${ce?" card-highlight":""}`,style:{marginBottom:0},children:[re,p&&s.jsxs("div",{style:{fontSize:"0.75rem",color:"var(--text-tertiary)",marginBottom:"0.375rem"},children:["Owner: ",s.jsx("span",{style:{color:"var(--text-secondary)",fontWeight:500},children:p})]}),s.jsxs("div",{className:"auth-card-header",children:[s.jsx("span",{style:{fontWeight:700,fontSize:"1rem",color:"var(--text-primary)",letterSpacing:"0.01em"},children:q}),e.title&&s.jsx("span",{style:{fontWeight:500,fontSize:"0.85rem",color:"var(--text-secondary)"},children:e.title}),s.jsx(gx,{status:N}),N==="active"&&e.earliest_expiry&&s.jsx(wx,{expiresAt:new Date(e.earliest_expiry).getTime()/1e3}),N==="expired"&&(()=>{const te=Lv(e,N);return te?s.jsx("span",{style:{fontSize:"0.75rem",color:"var(--text-tertiary)"},title:`Expired ${new Date(te.iso).toLocaleString()}`,children:new Date(te.iso).toLocaleDateString(void 0,{month:"short",day:"numeric"})}):null})()]}),s.jsxs("div",{style:{display:"flex",gap:"0.5rem",flexWrap:"wrap",marginBottom:"0.5rem",alignItems:"center"},children:[e.required_domains.map(te=>s.jsx(vx,{domain:te,attested:e.attested_domains.includes(te)},te)),e.deferred_commitment_domains.length>0&&s.jsx("span",{style:{fontSize:"0.65rem",padding:"0.15rem 0.4rem",borderRadius:"0.25rem",background:"var(--accent-subtle)",color:"var(--accent)",fontWeight:600},children:"Review Mode"}),ee&&s.jsx("span",{title:Q,style:{fontSize:"0.65rem",padding:"0.15rem 0.4rem",borderRadius:"0.25rem",background:U?"var(--accent-subtle)":"var(--danger-subtle)",color:U?"var(--accent)":"var(--danger)",fontWeight:600,cursor:"help"},children:B}),z&&s.jsx("button",{className:"btn btn-ghost btn-sm",style:{fontSize:"0.65rem",padding:"0.15rem 0.5rem",borderRadius:"0.25rem",background:"var(--warning-subtle, rgba(234,179,8,0.12))",color:"var(--warning, #ca8a04)",fontWeight:600,border:"1px solid var(--warning-border, rgba(234,179,8,0.3))",cursor:"pointer",lineHeight:1.4},onClick:()=>x(e),disabled:c===e.authorization_id,title:"The approver list for this profile has changed since this mandate was created. Copy to reissue with the current approvers.",children:c===e.authorization_id?"Copying...":"Approver list updated · Copy with new approvers"})]}),V.length>0&&s.jsx("div",{style:{fontSize:"0.8rem",color:"var(--text-tertiary)"},children:V.map(([te,oe],se)=>{const _=P.get(te);return s.jsxs("span",{children:[se>0&&" · ",_?U?s.jsxs("span",{title:`Team cap on ${te} is ${_.cap}. Actions exceeding the cap require per-action approval. Bound remains authorized at ${_.authorized}.`,children:[s.jsxs("span",{style:{color:"var(--text-tertiary)"},children:[te,"=",String(oe)]}),s.jsxs("span",{style:{color:"var(--accent)",marginLeft:"0.25rem",fontWeight:600},children:["↑ approval at ",_.cap]})]}):s.jsxs("span",{title:`Team cap on ${te} is ${_.cap} with no approvers configured (hard cap). Authorized for ${_.authorized}; effective ${_.cap}.`,children:[s.jsxs("span",{style:{textDecoration:"line-through",color:"var(--text-tertiary)"},children:[te,"=",String(oe)]}),s.jsxs("span",{style:{color:"var(--danger)",marginLeft:"0.25rem",fontWeight:600},children:["→"," ",_.cap]})]}):s.jsxs("span",{children:[te,"=",String(oe)]})]},te)})}),s.jsxs("div",{style:{display:"flex",justifyContent:"flex-end",gap:"0.5rem",marginTop:"0.5rem"},children:[R&&s.jsx("button",{className:"btn btn-secondary btn-sm",onClick:()=>S(e.authorization_id,!C),disabled:v===e.authorization_id,title:C?"Move back to the Expired or Revoked list":"Hide from the list and the nav badge. Nothing is deleted: the mandate and its tickets stay stored and verifiable.",children:v===e.authorization_id?C?"Unarchiving…":"Archiving…":C?"↩ Unarchive":"⊟ Archive"}),s.jsx("button",{className:"btn btn-ghost btn-sm",onClick:()=>w(e),children:E?"▲ Hide Details":"▼ Details"})]}),E&&s.jsxs("div",{style:{borderTop:"1px solid var(--border)",marginTop:"0.75rem",paddingTop:"0.75rem"},children:[V.length>0&&s.jsxs(s.Fragment,{children:[s.jsx("div",{style:{fontSize:"0.75rem",fontWeight:600,color:"var(--text-tertiary)",textTransform:"uppercase",letterSpacing:"0.04em",marginBottom:"0.25rem"},children:"Bounds"}),s.jsx("dl",{className:"review-grid",children:V.map(([te,oe])=>s.jsxs("span",{style:{display:"contents"},children:[s.jsx("dt",{children:te}),s.jsx("dd",{children:String(oe)})]},te))})]}),(L==null?void 0:L.context)&&Object.keys(L.context).length>0&&s.jsxs(s.Fragment,{children:[s.jsx("div",{style:{fontSize:"0.75rem",fontWeight:600,color:"var(--text-tertiary)",textTransform:"uppercase",letterSpacing:"0.04em",marginTop:"1rem",marginBottom:"0.25rem"},children:"Scope"}),s.jsx("dl",{className:"review-grid",children:Object.entries(L.context).map(([te,oe])=>s.jsxs("span",{style:{display:"contents"},children:[s.jsx("dt",{children:te}),s.jsx("dd",{title:String(oe),children:gm(te,oe,L.contextLabels)})]},te))})]}),s.jsx("div",{style:{fontSize:"0.75rem",fontWeight:600,color:"var(--text-tertiary)",textTransform:"uppercase",letterSpacing:"0.04em",marginTop:"1rem",marginBottom:"0.25rem"},children:"Intent"}),o===e.authorization_id?s.jsx("p",{style:{fontSize:"0.8rem",color:"var(--text-tertiary)"},children:"Loading gate content..."}):L?s.jsx("div",{className:"gate-content-block",children:s.jsx("div",{className:"gate-content-item",children:s.jsx("div",{className:"gate-content-text",children:L.gateContent.intent})})}):s.jsx("p",{style:{fontSize:"0.8rem",color:"var(--text-tertiary)"},children:"Gate content not available."}),s.jsxs("div",{style:{fontSize:"0.75rem",color:"var(--text-tertiary)",marginTop:"1rem"},children:["Created: ",new Date(e.created_at).toLocaleString(),e.earliest_expiry&&` · Expires: ${new Date(e.earliest_expiry).toLocaleString()}`]}),s.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"0.5rem",marginTop:"0.25rem"},children:[s.jsx("span",{style:{fontSize:"0.7rem",color:"var(--text-tertiary)",fontFamily:"'SF Mono', Monaco, monospace",wordBreak:"break-all"},children:e.authorization_id}),s.jsx("button",{className:"btn btn-ghost btn-sm",style:{fontSize:"0.7rem",padding:"0.125rem 0.375rem"},onClick:()=>y(e.authorization_id),children:i===e.authorization_id?"copied":"copy"})]}),s.jsxs("div",{style:{display:"flex",justifyContent:"flex-end",gap:"0.5rem",marginTop:"0.75rem"},children:[!p&&s.jsx("button",{className:"btn btn-secondary btn-sm",onClick:()=>x(e),disabled:c===e.authorization_id,title:"Start a new mandate pre-filled with these bounds, scope, and intent",children:c===e.authorization_id?"Copying…":"⧉ Copy"}),!p&&(N==="active"||N==="pending")&&s.jsx("button",{className:"btn btn-secondary btn-sm",onClick:()=>x(e,{asEdit:!0}),disabled:c===e.authorization_id,title:"Adjust intent, bounds, or scope: opens the ceremony pre-filled; signing the new mandate revokes this one",children:"✎ Edit"}),!p&&D&&s.jsx("button",{className:"btn btn-secondary btn-sm",onClick:()=>g(e),children:"↻ Extend"}),p&&m&&N!=="revoked"?s.jsx("button",{className:"btn btn-danger btn-sm",onClick:()=>j(e.authorization_id,p,q),disabled:l===e.authorization_id,children:l===e.authorization_id?"Revoking…":"Revoke"}):!p&&(N==="active"||N==="pending")?s.jsx("button",{className:"btn btn-danger btn-sm",onClick:()=>j(e.authorization_id),disabled:l===e.authorization_id,children:l===e.authorization_id?"Revoking…":"Revoke"}):null]})]})]},e.authorization_id)}function Nx(){const[e,t]=u.useState([]),[n,r]=u.useState(!0),[a,o]=u.useState([]),[i,l]=u.useState(!1),[c,d]=u.useState(new Map),[f,p]=u.useState("mine"),[m,w]=u.useState("active"),[y,x]=u.useState(null),[j,g]=u.useState(null),[h,v]=Yf(),[S,b]=u.useState(()=>h.get("new")==="1"),[N,C]=u.useState(()=>h.get("highlight")),[R,E]=u.useState(null),[L,D]=u.useState({}),[V,J]=u.useState(null),[U,P]=u.useState(null),[ee,F]=u.useState(null),[$,z]=u.useState(new Set),[W,I]=u.useState(null),[B,Q]=u.useState(new Set),[q,re]=u.useState(null),[ce,me]=u.useState(null),te=tn(),{group:oe,groupId:se,domain:_,mode:X,activeTeam:ae}=Oe(),ge=(ae==null?void 0:ae.isAdmin)===!0,[he,_e]=u.useState(()=>new Map),it=u.useCallback(()=>{r(!0),T.getMyAttestations().then(t).catch(()=>{}).finally(()=>r(!1))},[]),Ae=u.useCallback(()=>{T.getArchivedMandates().then(H=>Q(new Set(H))).catch(()=>{})},[]);u.useEffect(()=>{Ae()},[Ae]);const yt=async(H,Z)=>{re(H);try{const K=await T.setMandateArchived(H,Z);Q(new Set(K)),window.dispatchEvent(new Event("suveren:archived-changed"))}catch(K){alert(K instanceof Error?K.message:"Failed to update archive")}finally{re(null)}},Ke=u.useCallback(()=>{se&&(l(!0),T.listTeamAuthorizations(se).then(o).catch(()=>{}).finally(()=>l(!1)))},[se]);fe("attestation-changed",()=>{it(),ge&&se&&Ke()}),u.useEffect(()=>{if(!N)return;h.get("highlight")&&(h.delete("highlight"),v(h,{replace:!0}));const H=window.setTimeout(()=>C(null),3e3);return()=>window.clearTimeout(H)},[]),Pt(it,3e5),u.useEffect(()=>{f==="team"&&ge&&se&&a.length===0&&!i&&Ke()},[f,ge,se,a.length,i,Ke]),u.useEffect(()=>{let H=!1;return T.listProfiles().then(Z=>{if(H)return;const K=ct=>ct.replace(/@.*$/,"").split("/").pop()??ct,de=ct=>ct.split("@")[1]??"",ye=new Map;for(const ct of Z){const Ut=K(ct.id),ys=ye.get(Ut);(!ys||de(ct.id).localeCompare(de(ys.id),void 0,{numeric:!0})>0)&&ye.set(Ut,ct)}d(ye)}).catch(()=>{}),()=>{H=!0}},[]);const et=u.useCallback(H=>{const Z=Ut=>Ut.replace(/@.*$/,"").split("/").pop()??Ut,K=Ut=>Ut.split("@")[1]??"",de=c.get(Z(H));if(!de)return;const ye=K(H),ct=K(de.id);if(!(!ye||!ct))return ct.localeCompare(ye,void 0,{numeric:!0})>0?de:void 0},[c]);u.useEffect(()=>{if(X!=="team"||!se)return;const H=f==="mine"?e:a;if(H.length===0)return;const Z=[...new Set(H.map(K=>K.profile_id))].filter(K=>!he.has(K));if(Z.length!==0){_e(K=>{const de=new Map(K);for(const ye of Z)de.set(ye,null);return de});for(const K of Z)T.getTeamProfileConfig(se,K).then(de=>{_e(ye=>new Map(ye).set(K,de))}).catch(()=>{})}},[e,a,f,se,X,he]);const le=async H=>{if(R===H.authorization_id){E(null);return}E(H.authorization_id);const Z=H.authorization_id;if(!(Z in L)){J(H.authorization_id);try{const K=await T.getGateContent(Z);D(de=>({...de,[Z]:K}))}catch{D(K=>({...K,[Z]:null}))}finally{J(null)}}},Ye=H=>{navigator.clipboard.writeText(H).then(()=>{F(H),setTimeout(()=>F(null),2e3)})},G=async(H,Z)=>{var K;if(!se){alert("No active group; cannot copy mandate.");return}me(H.authorization_id);try{const de=H.authorization_id;let ye=L[de]??null;de in L||(ye=await T.getGateContent(de),D(xs=>({...xs,[de]:ye})));const ct=Object.fromEntries(Object.entries(H.frame).filter(([xs])=>xs!=="profile"&&xs!=="path")),Ut=(ye==null?void 0:ye.context)??{},ys=((K=ye==null?void 0:ye.gateContent)==null?void 0:K.intent)??"",wm=H.deferred_commitment_domains.length>0?"review":"automatic",Sm=H.attested_domains[0]||_||"owner",Xa=Date.parse(H.created_at),qa=H.earliest_expiry?Date.parse(H.earliest_expiry):NaN,jm=Number.isFinite(Xa)&&Number.isFinite(qa)&&qa>Xa?Math.round((qa-Xa)/1e3):void 0;sessionStorage.setItem("agentAuth",JSON.stringify({profileId:H.profile_id,groupId:se,groupName:(oe==null?void 0:oe.name)??null,domain:Sm,isPersonal:!!(oe!=null&&oe.isPersonal)})),sessionStorage.setItem("agentGate",JSON.stringify({bounds:ct,context:Ut,gateContent:{intent:ys},templateMode:wm,templateTtl:jm})),Z!=null&&Z.asEdit?sessionStorage.setItem("agentEditReplaces",H.authorization_id):sessionStorage.removeItem("agentEditReplaces"),te("/mandates/new/intent")}catch(de){alert(de instanceof Error?de.message:"Failed to copy mandate")}finally{me(null)}},k=async(H,Z,K)=>{const de=Z&&K?`Revoke ${Z}'s ${K} mandate? This cannot be undone.`:"Revoke this mandate? The agent will no longer be able to execute actions under it.";if(confirm(de)){I(H);try{await T.revokeAttestation(H),z(ye=>new Set(ye).add(H)),T.resyncGates().catch(()=>{}),Z&&se&&Ke()}catch(ye){alert(ye instanceof Error?ye.message:"Failed to revoke mandate")}finally{I(null)}}},A=f==="mine"?e:a,M=f==="mine"?n:i,ne=f==="mine"?{revokedSet:$,archivedSet:B}:{revokedSet:$},ve=H=>Ra(H,ne),kn={active:0,pending:0,expired:0,revoked:0,archived:0};for(const H of A)kn[ve(H)]+=1;const bn=f==="mine"?["active","pending","expired","revoked","archived"]:["active","pending","expired","revoked"],Ie=(()=>{const H=new Map;for(const Z of A){if(ve(Z)!==m)continue;const K=H.get(Z.profile_id)??{count:0,review:!1};K.count+=1,Z.deferred_commitment_domains.length>0&&(K.review=!0),H.set(Z.profile_id,K)}return Array.from(H.entries()).map(([Z,K])=>({profileId:Z,...K})).sort((Z,K)=>Le(Z.profileId).localeCompare(Le(K.profileId)))})(),lt=bx(A.filter(H=>{if(ve(H)!==m||y!==null&&H.profile_id!==y)return!1;if(j!==null){const Z=H.deferred_commitment_domains.length>0;if(j==="review"&&!Z||j==="auto"&&Z)return!1}return!0}),ne,N),xt={revokedSet:$,expandedHash:R,gateCache:L,gateLoading:V,copiedHash:ee,revokingHash:W,copyingHash:ce,profileConfigCache:he,mode:X,activeDomain:_,group:oe,groupId:se,onExpand:le,onCopyHash:Ye,onCopy:G,onRevoke:k,onExtend:P,highlightHash:N},tt={...xt,archivedSet:B,archivingHash:q,onArchive:yt};return s.jsxs(s.Fragment,{children:[s.jsxs("div",{className:"page-header",style:{display:"flex",justifyContent:"space-between",alignItems:"flex-start",gap:"1rem",flexWrap:"wrap"},children:[s.jsxs("div",{children:[s.jsx("h1",{className:"page-title",children:"Mandates"}),s.jsx("p",{className:"page-subtitle",children:"Active, pending, expired, and archived agent mandates."})]}),s.jsx("button",{className:"btn btn-primary",onClick:()=>b(!0),children:"+ New mandate"})]}),S&&s.jsx("div",{className:"modal-backdrop",onClick:()=>{b(!1),h.get("new")&&(h.delete("new"),v(h,{replace:!0}))},children:s.jsxs("div",{className:"modal",onClick:H=>H.stopPropagation(),style:{maxWidth:"960px",width:"90vw"},children:[s.jsxs("div",{className:"modal-header",children:[s.jsx("h2",{className:"modal-title",children:"New mandate"}),s.jsx("button",{className:"modal-close",onClick:()=>{b(!1),h.get("new")&&(h.delete("new"),v(h,{replace:!0}))},children:"×"})]}),s.jsxs("div",{className:"modal-body",children:[s.jsx("p",{style:{color:"var(--text-tertiary)",fontSize:"0.9rem",marginTop:0,marginBottom:"1rem"},children:"What should your agent be able to do? Pick a profile, set limits, then authorize."}),s.jsx(px,{onDismiss:()=>b(!1)})]})]})}),ge&&s.jsxs("div",{className:"nav-tabs",style:{marginBottom:"0.5rem"},children:[s.jsx("button",{className:`nav-tab${f==="mine"?" active":""}`,onClick:()=>{p("mine"),w("active"),x(null),g(null),E(null)},children:"Mine"}),s.jsx("button",{className:`nav-tab${f==="team"?" active":""}`,onClick:()=>{p("team"),w("active"),x(null),g(null),E(null)},children:"Team"})]}),s.jsx("div",{className:"nav-tabs",children:bn.map(H=>s.jsxs("button",{className:`nav-tab${m===H?" active":""}`,onClick:()=>{w(H),x(null),g(null)},children:[H.charAt(0).toUpperCase()+H.slice(1)," (",kn[H],")"]},H))}),Ie.length>0&&s.jsxs("div",{style:{display:"flex",gap:"0.5rem",flexWrap:"wrap",alignItems:"center",marginTop:"-0.25rem",marginBottom:"1rem"},children:[Ie.map(H=>{const Z=y===H.profileId;return s.jsx("button",{className:`btn btn-sm ${Z?"btn-primary":"btn-secondary"}`,onClick:()=>x(Z?null:H.profileId),children:Le(H.profileId)},H.profileId)}),s.jsx("span",{"aria-hidden":"true",style:{color:"var(--border)",fontSize:"1.1rem",padding:"0 0.25rem",userSelect:"none"},children:"|"}),["auto","review"].map(H=>{const Z=j===H;return s.jsx("button",{className:`btn btn-sm ${Z?"btn-primary":"btn-secondary"}`,onClick:()=>g(Z?null:H),children:H==="auto"?"Auto":"Review"},H)})]}),M&&A.length===0?s.jsx("p",{style:{color:"var(--text-tertiary)"},children:"Loading..."}):lt.length===0?s.jsx(vm,{icon:"☰",title:"No mandates",text:m==="archived"?"Nothing archived. Archive an expired or revoked mandate to move it here.":`No ${m} mandates found.`}):s.jsx("div",{style:{display:"flex",flexDirection:"column",gap:"0.75rem"},children:lt.map(H=>{const Z=f==="team"?H:null,K=Z!=null&&Z.owner?Z.owner.name??Z.owner.email??Z.owner.userId:void 0;return s.jsx(Cx,{item:H,newerProfile:et(H.profile_id),ownerLabel:K,isAdmin:ge,...f==="mine"?tt:xt},H.authorization_id)})}),U&&s.jsx(kx,{item:U,onClose:()=>P(null),onSuccess:()=>{P(null),it()}})]})}function Ex(e){const t=e.indexOf("__");return t<0?{integrationId:"",toolName:e}:{integrationId:e.slice(0,t),toolName:e.slice(t+2)}}function Tx(e,t){var c,d,f;const{integrationId:n,toolName:r}=Ex(e.action),a=t.find(p=>p.id===n),o=(d=(c=a==null?void 0:a.toolGating)==null?void 0:c.overrides)==null?void 0:d[r];if(o!=null&&o.actionLabel)return o.actionLabel;const i=Le(e.profileId),l=(f=e.executionContext)==null?void 0:f.action_type;return typeof l=="string"&&l?`${i} · ${l}`:`${i} · ${r}`}function Rx(e){const t=[];for(const[n,r]of Object.entries(e.executionContext??{})){if(!n.startsWith("allowed_"))continue;const a=String(r??"").trim();a&&t.push(a.split(",").map(o=>o.trim()).filter(Boolean).join(", "))}return t.join(" · ")}function Ix(e){if(!e)return"";const t=[];for(const[n,r]of Object.entries(e)){if(n==="action_type")continue;const a=String(r??"").trim();if(!a)continue;const o=n.replace(/^allowed_/,"").replace(/_/g," ");t.push(`${o} ${a.split(",").map(i=>i.trim()).filter(Boolean).join(", ")}`)}return t.join(" · ")}function Px(e,t){var o,i;const n=[{window:"daily",label:"today"},{window:"monthly",label:"this month"}],r=e.actionType??(typeof((o=e.executionContext)==null?void 0:o.action_type)=="string"?e.executionContext.action_type:void 0),a=[];for(const{window:l,label:c}of n){const d=(i=e.cumulativeState)==null?void 0:i[l];if(!d)continue;const f=`_${l}_max`,p=Object.keys(t??{}).filter(j=>j.endsWith(f)),m=(r&&p.find(j=>j.startsWith(`${r}_`)))??(p.length===1?p[0]:void 0),y=(m?/^(amount|spend)_/.test(m):!1)?d.amount:d.count,x=m?Number(t==null?void 0:t[m]):NaN;m&&Number.isFinite(x)?a.push(`${y} of ${x} ${c}`):a.push(`${d.count} ${d.count===1?"call":"calls"} ${c}`)}return a.join(" · ")}function _x(e){return typeof e.proposalId=="string"&&e.proposalId.length>0}function Ax(e){const t=Le(e),n=e.split("@")[1];return n?`${t}@${n}`:t}function Pr({label:e,children:t}){return s.jsxs(s.Fragment,{children:[s.jsx("dt",{className:"receipt-row-label",children:e}),s.jsx("dd",{className:"receipt-row-value",children:t})]})}function zx({receipt:e,manifests:t,localAuth:n,localUnavailable:r,signature:a,grantTitle:o,ownerLabel:i,spUrl:l,formatDate:c,onOpenComplete:d}){var y;const f=Rx(e),p=Ix(n==null?void 0:n.context),m=Px(e,(n==null?void 0:n.bounds)??e.limits),w=n==null?void 0:n.intent;return s.jsxs("div",{className:"card",style:{marginBottom:0},children:[s.jsxs("div",{className:"receipt-head",children:[s.jsx("span",{className:"receipt-what",children:Tx(e,t)}),s.jsx("span",{className:"receipt-tag",children:_x(e)?"review":"automatic"}),e.contentHash&&s.jsx("span",{className:"receipt-tag receipt-tag-bound",title:(y=e.contentBinding)!=null&&y.fields?`The ticket binds: ${e.contentBinding.fields.join(", ")}`:"This exact content was authorized",children:"content bound"}),s.jsx("span",{className:"auth-card-time",children:c(e.timestamp)})]}),f&&s.jsx("div",{className:"receipt-scope",children:f}),s.jsxs("dl",{className:"receipt-rows",children:[s.jsx(Pr,{label:"mandate",children:s.jsx("strong",{children:o||Ax(e.profileId)})}),i&&s.jsx(Pr,{label:"owner",children:i}),p&&s.jsx(Pr,{label:"allowed",children:p}),m&&s.jsx(Pr,{label:"used",children:s.jsx("span",{className:"receipt-num",children:m})}),s.jsx(Pr,{label:"intent",children:w?s.jsx("span",{className:"receipt-intent",children:w}):s.jsx("span",{className:"receipt-absent",children:r?"local store unreachable — sign in to the gateway to read it":"not on this device — the Authority Server stores only its hash"})})]}),s.jsxs("div",{className:"receipt-foot",children:[a==="valid"&&s.jsx("span",{className:"receipt-verified",title:"Ed25519 signature checked on this device against the issuer key archived when the ticket was issued — no Authority Server involved.",children:"✓ Verified on this device"}),a==="invalid"&&s.jsx("span",{className:"receipt-tamper",title:"The stored ticket does not match what was signed.",children:"⚠ Signature check FAILED"}),s.jsx("button",{type:"button",className:"receipt-evidence-link",onClick:d,children:"Complete ticket"}),l&&s.jsxs("span",{className:"receipt-public",children:["redacted, shareable:"," ",s.jsx("a",{className:"receipt-link",href:`${l}/r/${e.id}`,target:"_blank",rel:"noreferrer",children:"public link ↗"})]})]}),s.jsxs("details",{className:"receipt-more",children:[s.jsx("summary",{children:"Raw"}),s.jsxs("div",{className:"receipt-kv",children:[s.jsxs("div",{children:["ticket · ",e.id]}),s.jsxs("div",{children:["action · ",e.action]}),s.jsxs("div",{children:["profile · ",e.profileId]}),e.authorizationId&&s.jsxs("div",{children:["mandate · ",e.authorizationId]}),Object.keys(e.executionContext??{}).length>0&&s.jsxs("div",{children:["scope ·"," ",Object.entries(e.executionContext).map(([x,j])=>`${x}=${j}`).join(" · ")]}),(n==null?void 0:n.boundsHash)&&s.jsxs("div",{children:["bounds hash · ",n.boundsHash]}),(n==null?void 0:n.contextHash)&&s.jsxs("div",{children:["scope hash · ",n.contextHash]}),e.contentHash&&s.jsxs("div",{children:["content · ",e.contentHash]}),e.proposalId&&s.jsxs("div",{children:["proposal · ",e.proposalId]}),s.jsxs("div",{children:["signature · ",e.signature]})]})]})]})}function $x({receipt:e,onClose:t}){const[n,r]=u.useState(null),[a,o]=u.useState(null),[i,l]=u.useState(null),[c,d]=u.useState(!0),[f,p]=u.useState(!1);u.useEffect(()=>{let j=!1;return d(!0),T.getArchivedReceipt(e.id).then(g=>{j||(r(g),o(g?"local":"authority-server"),l((g==null?void 0:g.signature)??null))}).catch(()=>{j||o("authority-server")}).finally(()=>{j||d(!1)}),()=>{j=!0}},[e.id]);const m=n?n.entry:{receipt:e},w=JSON.stringify(m,null,2);function y(){const j=URL.createObjectURL(new Blob([w],{type:"application/json"})),g=document.createElement("a");g.href=j,g.download=`suveren-ticket-${e.id.slice(0,8)}.json`,g.click(),URL.revokeObjectURL(j)}async function x(){try{await navigator.clipboard.writeText(w),p(!0),setTimeout(()=>p(!1),2e3)}catch{p(!1)}}return s.jsx("div",{className:"modal-backdrop",onClick:j=>j.target===j.currentTarget&&t(),children:s.jsxs("div",{className:"modal",style:{maxWidth:"44rem"},children:[s.jsxs("div",{className:"modal-header",children:[s.jsx("h3",{className:"modal-title",children:"Complete ticket"}),s.jsx("button",{className:"modal-close",onClick:t,"aria-label":"Close",children:"×"})]}),s.jsxs("div",{className:"modal-body",children:[i==="valid"&&s.jsx("p",{className:"receipt-verified",style:{margin:"0 0 0.5rem",fontSize:"0.8rem"},children:"✓ Ed25519 signature verified on this device, against the issuer key archived when this ticket was issued."}),i==="invalid"&&s.jsx("p",{className:"receipt-tamper",style:{margin:"0 0 0.5rem",fontSize:"0.8rem"},children:"⚠ Signature check FAILED — the stored ticket does not match what was signed."}),s.jsx("p",{style:{fontSize:"0.8rem",color:"var(--text-muted)",margin:"0 0 0.75rem"},children:c?"Loading…":a==="local"?"Held on this device — the signed ticket, the mandate it ran under, and the issuer key. Anyone with this file and that key can verify it offline, without Suveren.":"No local copy of this ticket (it predates local archiving, or ran on another device). Shown from the Authority Server — complete and signed, but it needs the server to retrieve."}),s.jsx("pre",{style:{fontFamily:"'SF Mono', Monaco, monospace",fontSize:"0.68rem",lineHeight:1.65,margin:0,background:"var(--accent-subtle)",border:"1px solid var(--border)",borderRadius:"6px",padding:"0.75rem 0.85rem",overflowX:"auto",maxHeight:"22rem",overflowY:"auto"},children:w})]}),s.jsxs("div",{className:"modal-footer",children:[s.jsx("button",{className:"btn btn-primary btn-sm",onClick:y,children:"Download"}),s.jsx("button",{className:"btn btn-secondary btn-sm",onClick:x,children:f?"Copied":"Copy"})]})]})})}function Lx(e){return new Date(e*1e3).toLocaleString()}function Mx(e,t){if(t==="all")return!0;const n=t==="1d"?1:t==="7d"?7:30,r=Math.floor(Date.now()/1e3)-n*86400;return e.timestamp>=r}function Fx(e,t){if(!t)return!0;const n=t.toLowerCase();return e.profileId.toLowerCase().includes(n)||Le(e.profileId).toLowerCase().includes(n)||e.path.toLowerCase().includes(n)||e.action.toLowerCase().includes(n)||e.attestationHash.toLowerCase().includes(n)||e.id.toLowerCase().includes(n)||JSON.stringify(e.executionContext).toLowerCase().includes(n)}function fu(e,t){const n=new Map(e.map(r=>[r.id,r]));for(const r of t)n.set(r.id,r);return[...n.values()].sort((r,a)=>a.timestamp-r.timestamp)}function Ox(){const{activeTeam:e,groupId:t}=Oe(),n=(e==null?void 0:e.isAdmin)===!0,[r,a]=u.useState("mine"),[o,i]=u.useState([]),[l,c]=u.useState([]),[d,f]=u.useState(""),[p,m]=u.useState(!0),[w,y]=u.useState({}),[x,j]=u.useState(new Set),[g,h]=u.useState(""),[v,S]=u.useState(new Set),[b,N]=u.useState(new Set),[C,R]=u.useState("all"),[E,L]=u.useState(!1),[D,V]=u.useState(!1),[J,U]=u.useState(null),[P,ee]=u.useState({}),[F,$]=u.useState(!1),[z,W]=u.useState({}),[I,B]=u.useState({}),[Q,q]=u.useState(null),[re,ce]=u.useState(null),[me,te]=u.useState(!1),[oe,se]=u.useState(!1),_=u.useRef(""),X=u.useCallback(k=>r==="team"&&n&&t?T.listTeamReceiptsPage(t,{before:k,limit:200}):T.getMyReceiptsPage({before:k,limit:200}),[r,n,t]),ae=u.useCallback(()=>{const k=r==="team"?`team:${t}`:"mine",A=_.current!==k;_.current=k,m(!0),se(!1),X().then(M=>{i(ne=>A?M.receipts:fu(ne,M.receipts)),ce(ne=>A?M.nextBefore:ne??M.nextBefore)}).catch(()=>{A&&i([]),se(!0)}).finally(()=>m(!1))},[X,r,t]),ge=u.useCallback(()=>{!re||me||(te(!0),se(!1),X(re).then(k=>{i(A=>fu(A,k.receipts)),ce(k.nextBefore)}).catch(()=>se(!0)).finally(()=>te(!1)))},[re,me,X]);Pt(ae,12e4),u.useEffect(()=>{T.getIntegrationManifests().then(({manifests:k})=>c(k)).catch(()=>{}),fetch("/health").then(k=>k.json()).then(k=>{typeof k.spUrl=="string"&&f(k.spUrl.replace(/\/$/,""))}).catch(()=>{})},[]),u.useEffect(()=>{T.getLocalAuthorizations().then(({authorizations:k,signatures:A})=>{ee(k),W(A),$(!1)}).catch(()=>{ee({}),W({}),$(!0)}),T.getMyAttestations().then(k=>{const A={};for(const M of k)M.authorization_id&&M.title&&(A[M.authorization_id]=M.title);B(A)}).catch(()=>{})},[]),u.useEffect(()=>{r!=="team"||Object.keys(w).length>0||T.listUsers().then(k=>{const A={};for(const M of k)A[M.id]={name:M.name,email:M.email};y(A)}).catch(()=>{})},[r,w]);const he=u.useMemo(()=>{const k=new Set;for(const A of o)k.add(Le(A.profileId));return[...k].sort()},[o]),_e=u.useMemo(()=>{const k=new Set;for(const A of o)k.add(A.action);return[...k].sort()},[o]),it=u.useMemo(()=>{if(r!=="team")return[];const k=new Set;for(const A of o)A.userId&&k.add(A.userId);return[...k].map(A=>{var M;return{id:A,label:(M=w[A])!=null&&M.name?`${w[A].name} (${w[A].email})`:A}}).sort((A,M)=>A.label.localeCompare(M.label))},[r,o,w]),Ae=u.useMemo(()=>o.filter(k=>!(!Fx(k,g)||v.size>0&&!v.has(Le(k.profileId))||b.size>0&&!b.has(k.action)||x.size>0&&k.userId&&!x.has(k.userId)||!Mx(k,C))),[o,g,v,b,x,C]),yt=v.size>0||b.size>0||x.size>0||C!=="all";function Ke(k){S(A=>{const M=new Set(A);return M.has(k)?M.delete(k):M.add(k),M})}function et(k){N(A=>{const M=new Set(A);return M.has(k)?M.delete(k):M.add(k),M})}function le(k){j(A=>{const M=new Set(A);return M.has(k)?M.delete(k):M.add(k),M})}function Ye(){S(new Set),N(new Set),j(new Set),R("all"),h("")}async function G(){V(!0),U(null);try{const{bundle:k,filename:A}=await T.fetchEvidenceBundle(),M=URL.createObjectURL(new Blob([JSON.stringify(k,null,2)],{type:"application/json"})),ne=document.createElement("a");ne.href=M,ne.download=A,ne.click(),URL.revokeObjectURL(M);const ve=k.sources??{};ve.authorityServer?ve.local||U(`Downloaded Authority Server history only — ${ve.localError??"local archive unavailable."}`):U(`Downloaded local evidence only — ${ve.asError??"Authority Server export unavailable."}`)}catch(k){U(`Export failed: ${k instanceof Error?k.message:String(k)}`)}finally{V(!1)}}return s.jsxs(s.Fragment,{children:[s.jsxs("div",{className:"page-header",style:{display:"flex",justifyContent:"space-between",alignItems:"flex-start",gap:"1rem",flexWrap:"wrap"},children:[s.jsxs("div",{children:[s.jsx("h1",{className:"page-title",children:"Tickets"}),s.jsx("p",{className:"page-subtitle",children:"Execution history for agent actions."})]}),s.jsx("button",{className:"btn btn-secondary",onClick:G,disabled:D,children:D?"Preparing…":"Download evidence"})]}),J&&s.jsx("div",{style:{marginBottom:"1rem",color:"var(--text-tertiary)",fontSize:"0.875rem"},children:J}),n&&s.jsx("div",{style:{display:"flex",gap:"0.5rem",marginBottom:"1rem",borderBottom:"1px solid var(--border)"},children:["mine","team"].map(k=>s.jsx("button",{onClick:()=>a(k),className:"btn btn-ghost",style:{borderRadius:0,padding:"0.5rem 0.875rem",borderBottom:r===k?"2px solid var(--accent)":"2px solid transparent",color:r===k?"var(--text-primary)":"var(--text-tertiary)",fontWeight:r===k?600:500},children:k==="mine"?"Mine":"Team"},k))}),s.jsxs("div",{className:"search-filter-bar",children:[s.jsxs("div",{className:"search-input-wrap",children:[s.jsx("span",{className:"search-icon",children:"⌕"}),s.jsx("input",{type:"text",className:"form-input search-input",placeholder:"Search by profile, action, path, or hash\\u2026",value:g,onChange:k=>h(k.target.value)}),g&&s.jsx("button",{className:"search-clear",onClick:()=>h(""),children:"×"})]}),s.jsxs("button",{className:`btn btn-sm btn-secondary${E?" active":""}`,onClick:()=>L(!E),children:["Filters",yt?` (${v.size+b.size+(C!=="all"?1:0)})`:""]})]}),E&&s.jsxs("div",{className:"filter-panel",children:[he.length>1&&s.jsxs("div",{className:"filter-section",children:[s.jsx("div",{className:"filter-label",children:"Profile"}),s.jsx("div",{className:"filter-chips",children:he.map(k=>s.jsx("button",{className:`filter-chip${v.has(k)?" selected":""}`,onClick:()=>Ke(k),children:k},k))})]}),_e.length>1&&s.jsxs("div",{className:"filter-section",children:[s.jsx("div",{className:"filter-label",children:"Action"}),s.jsx("div",{className:"filter-chips",children:_e.map(k=>s.jsx("button",{className:`filter-chip${b.has(k)?" selected":""}`,onClick:()=>et(k),children:k},k))})]}),r==="team"&&it.length>1&&s.jsxs("div",{className:"filter-section",children:[s.jsx("div",{className:"filter-label",children:"Owner"}),s.jsx("div",{className:"filter-chips",children:it.map(k=>s.jsx("button",{className:`filter-chip${x.has(k.id)?" selected":""}`,onClick:()=>le(k.id),children:k.label},k.id))})]}),s.jsxs("div",{className:"filter-section",children:[s.jsx("div",{className:"filter-label",children:"Time range"}),s.jsx("div",{className:"filter-chips",children:[["1d","Today"],["7d","7 days"],["30d","30 days"],["all","All time"]].map(([k,A])=>s.jsx("button",{className:`filter-chip${C===k?" selected":""}`,onClick:()=>R(k),children:A},k))})]})]}),yt&&s.jsxs("div",{className:"active-filters",children:[[...v].map(k=>s.jsxs("span",{className:"active-chip",onClick:()=>Ke(k),children:[k," ",s.jsx("span",{className:"chip-remove",children:"×"})]},k)),[...b].map(k=>s.jsxs("span",{className:"active-chip",onClick:()=>et(k),children:[k," ",s.jsx("span",{className:"chip-remove",children:"×"})]},k)),[...x].map(k=>{const A=w[k],M=A?A.name:k;return s.jsxs("span",{className:"active-chip",onClick:()=>le(k),children:[M," ",s.jsx("span",{className:"chip-remove",children:"×"})]},k)}),C!=="all"&&s.jsxs("span",{className:"active-chip",onClick:()=>R("all"),children:[C==="1d"?"Today":C==="7d"?"7 days":"30 days"," ",s.jsx("span",{className:"chip-remove",children:"×"})]}),s.jsx("button",{className:"clear-filters",onClick:Ye,children:"Clear all"})]}),oe&&s.jsx("div",{className:"card",style:{borderColor:"var(--danger, #c0392b)",marginBottom:"0.75rem"},children:s.jsx("span",{style:{color:"var(--danger, #c0392b)",fontSize:"0.85rem"},children:"Couldn’t load tickets — your session may have expired. Try signing out and back in."})}),p&&o.length===0?s.jsx("p",{style:{color:"var(--text-tertiary)"},children:"Loading..."}):Ae.length===0?s.jsx(vm,{icon:"⌕",title:o.length===0?"No tickets in the last 30 days":"No matching tickets",text:o.length===0?"Tickets appear here after an agent uses an authorized tool. Older tickets can be loaded below.":"Try adjusting your search or filters."}):s.jsxs(s.Fragment,{children:[s.jsx("div",{style:{fontSize:"0.8rem",color:"var(--text-tertiary)",marginBottom:"0.75rem"},children:Ae.length===o.length?`${o.length} ticket${o.length!==1?"s":""}`:`${Ae.length} of ${o.length} tickets`}),s.jsx("div",{className:"timeline",children:Ae.map(k=>{const A=k.userId?w[k.userId]:void 0;return s.jsx("div",{className:"timeline-event",children:s.jsx(zx,{receipt:k,manifests:l,localAuth:k.authorizationId?P[k.authorizationId]:void 0,localUnavailable:F,signature:z[k.id],grantTitle:k.authorizationId?I[k.authorizationId]:null,ownerLabel:r==="team"&&k.userId?A?`${A.name} (${A.email})`:k.userId:null,spUrl:d,formatDate:Lx,onOpenComplete:()=>q(k)})},k.id)})})]}),Q&&s.jsx($x,{receipt:Q,onClose:()=>q(null)}),re&&s.jsx("div",{style:{textAlign:"center",marginTop:"1rem"},children:s.jsx("button",{className:"btn btn-secondary btn-sm",onClick:ge,disabled:me,children:me?"Loading…":"Load older"})})]})}const Bx={darwin:"a macOS login item",win32:"a Windows scheduled task",linux:"a systemd user service"};function Dx(){const[e,t]=u.useState(null),[n,r]=u.useState(!1),[a,o]=u.useState(null),i=u.useCallback(async()=>{try{t(await T.getAutostart())}catch(d){o(d instanceof Error?d.message:"Could not read autostart state")}},[]);u.useEffect(()=>{i()},[i]);const l=u.useCallback(async()=>{if(!(!(e!=null&&e.supported)||n)){r(!0),o(null);try{await T.setAutostart(!e.installed)}catch(d){o(d instanceof Error?d.message:"Failed")}finally{try{t(await T.getAutostart()),o(null)}catch(d){o(d instanceof Error?d.message:"Could not re-read state")}r(!1)}}},[e,n,i]);if(!e)return s.jsxs("div",{className:"card",style:{padding:"1.5rem",marginTop:"2rem"},children:[s.jsx("h2",{style:{fontSize:"1rem",fontWeight:700,margin:0},children:"Keep Suveren running"}),s.jsx("p",{role:a?"alert":void 0,style:{margin:"0.5rem 0 0",fontSize:"0.9rem",color:"var(--text-secondary)"},children:a?`Could not read autostart state: ${a}`:"Checking…"})]});const c=Bx[e.platform]??"a login service";return s.jsxs("div",{className:"card",style:{padding:"1.5rem",marginTop:"2rem"},children:[s.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"flex-start",gap:"1rem"},children:[s.jsxs("div",{children:[s.jsx("h2",{style:{fontSize:"1rem",fontWeight:700,margin:0},children:"Keep Suveren running"}),s.jsx("p",{style:{color:"var(--text-secondary)",margin:"0.5rem 0 0",fontSize:"0.9rem"},children:e.supported?s.jsxs(s.Fragment,{children:["Starts automatically when you log in, and restarts if it crashes. Uses ",c," — no admin rights needed."]}):e.reason})]}),e.supported&&s.jsx("button",{type:"button",onClick:()=>void l(),disabled:n,"aria-pressed":e.installed,className:e.installed?"btn btn-secondary":"btn btn-primary",style:{whiteSpace:"nowrap"},children:n?"Working…":e.installed?"Turn off":"Turn on"})]}),e.supported&&s.jsxs("p",{style:{margin:"1rem 0 0",fontSize:"0.85rem",color:"var(--text-tertiary)"},children:["Status: ",s.jsx("strong",{children:e.installed?"On — starts from your next login":"Off"})]}),e.supported&&s.jsxs("p",{style:{margin:"0.5rem 0 0",fontSize:"0.85rem",color:"var(--text-tertiary)"},children:["Turning this on doesn't interrupt the gateway you're using — it takes effect at your next login. After any restart Suveren comes back ",s.jsx("strong",{children:"locked"}),": you enter your API key once to unlock it, because nothing stored on this machine can unlock it for you."]}),a&&s.jsx("p",{role:"alert",style:{margin:"0.75rem 0 0",fontSize:"0.85rem",color:"var(--danger, #c00)"},children:a})]})}function Ux(){const[e,t]=u.useState(null),[n,r]=u.useState(!1),[a,o]=u.useState(null),i=u.useCallback(async()=>{try{const c=await T.getGatewaySettings();t(c.desktopNotifications),o(null)}catch(c){o(c instanceof Error?c.message:"Could not read notification setting")}},[]);u.useEffect(()=>{i()},[i]);const l=u.useCallback(async()=>{if(!(e===null||n)){r(!0),o(null);try{const c=await T.setGatewaySettings({desktopNotifications:!e});t(c.desktopNotifications)}catch(c){o(c instanceof Error?c.message:"Failed to save"),await i()}finally{r(!1)}}},[e,n,i]);return e===null?s.jsxs("div",{className:"card",style:{padding:"1.5rem",marginTop:"2rem"},children:[s.jsx("h2",{style:{fontSize:"1rem",fontWeight:700,margin:0},children:"Desktop notifications"}),s.jsx("p",{role:a?"alert":void 0,style:{margin:"0.5rem 0 0",fontSize:"0.9rem",color:"var(--text-secondary)"},children:a?`Could not read the setting: ${a}`:"Checking…"})]}):s.jsxs("div",{className:"card",style:{padding:"1.5rem",marginTop:"2rem"},children:[s.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"flex-start",gap:"1rem"},children:[s.jsxs("div",{children:[s.jsx("h2",{style:{fontSize:"1rem",fontWeight:700,margin:0},children:"Desktop notifications"}),s.jsx("p",{style:{color:"var(--text-secondary)",margin:"0.5rem 0 0",fontSize:"0.9rem"},children:"Tells you something is waiting for review — never what it is, and never with an approve button. Open Suveren to see and decide. At most one notification a minute; the browser tab always shows the count."})]}),s.jsx("button",{type:"button",onClick:()=>void l(),disabled:n,"aria-pressed":e,className:e?"btn btn-secondary":"btn btn-primary",style:{whiteSpace:"nowrap"},children:n?"Saving…":e?"Turn off":"Turn on"})]}),a&&s.jsx("p",{role:"alert",style:{margin:"0.75rem 0 0",fontSize:"0.85rem",color:"var(--danger)"},children:a})]})}const Wx={npm:"Checking npm for new releases",docker:"Checking the container registry for new images",dev:"Git checkout — comparing against origin/main, not npm releases"};function Hx(){const{version:e,latestVersion:t,updateAvailable:n,installMethod:r}=zl();return e?s.jsxs("div",{className:"card",style:{padding:"1.5rem",marginTop:"2rem"},children:[s.jsx("h2",{style:{fontSize:"1rem",fontWeight:700,margin:0},children:"Version"}),s.jsxs("p",{style:{margin:"0.5rem 0 0",fontSize:"0.9rem",color:"var(--text-secondary)"},children:["Running ",s.jsx("strong",{children:e}),n&&t?s.jsxs(s.Fragment,{children:[" — ",s.jsx("strong",{children:t})," is available"]}):null]}),s.jsxs("p",{style:{margin:"0.5rem 0 0",fontSize:"0.85rem",color:"var(--text-tertiary)"},children:[Wx[r]??"Update checking is unavailable",r==="dev"&&s.jsx(s.Fragment,{children:" — a development checkout is not told about published releases."})]})]}):null}function Vx(){const[e,t]=u.useState(null),[n,r]=u.useState(null);return u.useEffect(()=>{let a=!1;return T.getAsPairing().then(o=>{a||t(o)}).catch(o=>{a||r(o instanceof Error?o.message:"Could not read Authority Server info")}),()=>{a=!0}},[]),s.jsxs("div",{className:"card",style:{padding:"1.5rem",marginTop:"2rem"},children:[s.jsx("h2",{style:{fontSize:"1rem",fontWeight:700,margin:0},children:"Authority Server"}),!e&&!n&&s.jsx("p",{style:{margin:"0.5rem 0 0",fontSize:"0.9rem",color:"var(--text-secondary)"},children:"Checking…"}),n&&s.jsx("p",{role:"alert",style:{margin:"0.5rem 0 0",fontSize:"0.9rem",color:"var(--danger, #c00)"},children:n}),e&&s.jsxs(s.Fragment,{children:[s.jsxs("p",{style:{margin:"0.5rem 0 0",fontSize:"0.9rem",color:"var(--text-secondary)"},children:[s.jsx("strong",{children:"URL:"})," ",s.jsx("code",{children:e.asUrl})]}),e.paired&&e.fingerprint?s.jsxs("p",{style:{margin:"0.5rem 0 0",fontSize:"0.9rem",color:"var(--text-secondary)"},children:[s.jsx("strong",{children:"Key fingerprint:"})," ",s.jsx("code",{children:e.fingerprint}),s.jsx("br",{}),s.jsx("span",{style:{fontSize:"0.8rem",color:"var(--text-tertiary)"},children:"Compare this with the fingerprint on the Authority Server's own admin page over a second channel (phone, video call) to confirm this gateway is talking to the right server."})]}):s.jsx("p",{style:{margin:"0.5rem 0 0",fontSize:"0.85rem",color:"var(--text-tertiary)"},children:"Not yet paired — sign in once to pin this server's key."}),(e.tlsPinFingerprint||e.pinTlsEnabled)&&s.jsxs("p",{style:{margin:"0.5rem 0 0",fontSize:"0.9rem",color:"var(--text-secondary)"},children:[s.jsx("strong",{children:"TLS certificate pin:"})," ",e.tlsPinFingerprint?s.jsx("code",{children:e.tlsPinFingerprint}):s.jsxs("span",{style:{color:"var(--text-tertiary)"},children:["not yet captured — this URL has no recorded pairing over TLS",e.pinTlsEnabled?"; sign in to establish one (re-pairing required)":""]}),s.jsx("br",{}),s.jsxs("span",{style:{fontSize:"0.8rem",color:"var(--text-tertiary)"},children:[e.pinTlsEnabled?s.jsxs(s.Fragment,{children:["TLS pinning is ON (",s.jsx("code",{children:"config set pin-tls on"}),"). Every connection to the Authority Server must present this certificate's public key, or the gateway refuses it and locks."]}):s.jsxs(s.Fragment,{children:["Captured at sign-in; not currently enforced (",s.jsx("code",{children:"config set pin-tls on"})," ","to require it on every connection)."]})," ","A certificate renewal with the SAME key keeps this pin; a NEW key needs re-pairing."]})]}),s.jsxs("p",{style:{margin:"0.75rem 0 0",fontSize:"0.8rem",color:"var(--text-tertiary)"},children:["To point this gateway at a different Authority Server:"," ",s.jsx("code",{children:"suveren-gateway config set as-url <url>"}),", then restart. Changing it ends the current sign-in and clears cached mandates — you sign in again against the new server."]})]})]})}const Gx={ollama:{provider:"ollama",endpoint:"http://localhost:11434",models:["gemma4:e4b","gemma4:e2b","gemma4:26b","gemma4:31b","llama3.2","llama3.1","mistral","qwen2.5"]},openrouter:{provider:"openai-compatible",endpoint:"https://openrouter.ai/api/v1",models:["google/gemma-4-31b-it","qwen/qwen3.6-plus:free","stepfun/step-3.5-flash:free","google/gemini-2.5-flash","openai/gpt-4o-mini","anthropic/claude-haiku-4"]},openai:{provider:"openai-compatible",endpoint:"https://api.openai.com/v1",models:["gpt-4o-mini","gpt-4o","o3-mini"]},groq:{provider:"openai-compatible",endpoint:"https://api.groq.com/openai/v1",models:["llama-3.1-8b-instant","llama-3.3-70b-versatile","gemma2-9b-it"]},together:{provider:"openai-compatible",endpoint:"https://api.together.xyz/v1",models:["meta-llama/Llama-3-8b-chat-hf","meta-llama/Llama-3-70b-chat-hf"]}};function Kx(){const[e,t]=u.useState(""),[n,r]=u.useState("openrouter"),[a,o]=u.useState("openai-compatible"),[i,l]=u.useState("https://openrouter.ai/api/v1"),[c,d]=u.useState("google/gemma-4-31b-it"),[f,p]=u.useState(""),[m,w]=u.useState(!1),[y,x]=u.useState(!1),[j,g]=u.useState(!1),[h,v]=u.useState(null),[S,b]=u.useState([]),[N,C]=u.useState(!1),[R,E]=u.useState(null),[L,D]=u.useState(""),V=u.useCallback(z=>{t(z),setTimeout(()=>t(""),3e3)},[]),J=u.useCallback(async(z,W,I)=>{C(!0),E(null);try{const B=await T.aiModels({provider:z,endpoint:W,...I?{apiKey:I}:{}});B.ok&&B.models.length>0?(b(B.models),E(`${B.models.length} models available`)):(b([]),E(B.message||"No models returned — using defaults"))}catch(B){b([]),E(B instanceof Error?B.message:"Failed to load models")}finally{C(!1)}},[]),U=u.useCallback(async()=>{try{const z=await T.getCredential("ai-config");if(w(z.configured),z.configured&&z.fields){const W=z.fields.provider||"openai-compatible",I=z.fields.endpoint||"";z.fields.provider&&o(W),z.fields.endpoint&&l(I),z.fields.model&&d(z.fields.model),I.includes("openai.com")?r("openai"):I.includes("groq.com")?r("groq"):I.includes("together.xyz")?r("together"):I.includes("openrouter.ai")?r("openrouter"):r("ollama"),I&&J(W,I)}}catch{}},[J]);u.useEffect(()=>{U()},[U]);const P=z=>{r(z),b([]),E(null),D("");const W=Gx[z];W&&(o(W.provider),l(W.endpoint),d(""),J(W.provider,W.endpoint,f||void 0))},ee=()=>J(a,i,f||void 0),F=async()=>{x(!0);try{await T.setCredential("ai-config",{provider:a,endpoint:i,model:c,...f?{apiKey:f}:{}}),w(!0),V("AI configuration saved!")}catch{V("Failed to save AI config")}finally{x(!1)}},$=async()=>{g(!0),v(null);try{const z=await T.aiTest({provider:a,endpoint:i,model:c,...f?{apiKey:f}:{}});v(z.ok?`OK: ${z.message}`:`Failed: ${z.message}`)}catch(z){v(`Error: ${z instanceof Error?z.message:"Unknown"}`)}finally{g(!1)}};return s.jsxs(s.Fragment,{children:[s.jsxs("div",{className:"page-header",children:[s.jsx("h1",{className:"page-title",children:"AI Assistant"}),s.jsx("p",{className:"page-subtitle",children:"Advisory AI to help you think through intent when giving mandates."})]}),e&&s.jsx("div",{className:"alert alert-success",children:e}),s.jsxs("div",{className:"card",children:[s.jsx("h3",{className:"card-title",children:"Configuration"}),s.jsx("p",{style:{fontSize:"0.85rem",color:"var(--text-secondary)",marginBottom:"1rem"},children:"Connect a trusted AI model that has access to your intent — problem, objective, and tradeoffs — to help you think through mandates. Keys are encrypted in your vault."}),m&&s.jsxs("div",{className:"status-banner status-banner-success",style:{marginBottom:"1rem",fontSize:"0.8rem"},children:[s.jsx("span",{className:"status-banner-icon",children:"✓"}),s.jsx("span",{className:"status-banner-text",children:"AI configured"})]}),s.jsxs("div",{className:"form-group",style:{marginBottom:"0.75rem"},children:[s.jsx("label",{className:"form-label",children:"Provider Preset"}),s.jsxs("select",{className:"form-input",value:n,onChange:z=>P(z.target.value),children:[s.jsx("option",{value:"openrouter",children:"OpenRouter (recommended)"}),s.jsx("option",{value:"ollama",children:"Ollama (local)"}),s.jsx("option",{value:"openai",children:"OpenAI"}),s.jsx("option",{value:"groq",children:"Groq"}),s.jsx("option",{value:"together",children:"Together"})]})]}),s.jsxs("div",{className:"form-group",style:{marginBottom:"0.75rem"},children:[s.jsxs("label",{className:"form-label",children:["API Key ",a==="ollama"?"(not needed for Ollama)":"(required to load models)"]}),s.jsx("input",{className:"form-input",type:"password",name:"ai-provider-api-key-credential-top",autoComplete:"new-password",value:f,onChange:z=>p(z.target.value),onBlur:()=>{f.trim()&&J(a,i,f.trim())},placeholder:m?"••••••••••••••••":"sk-... (not needed for Ollama)"}),s.jsx("p",{style:{fontSize:"0.75rem",color:"var(--text-secondary)",margin:"0.375rem 0 0"},children:"Each provider uses its own key — paste it and the model list loads automatically."})]}),s.jsxs("div",{className:"form-group",style:{marginBottom:"0.75rem"},children:[s.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center"},children:[s.jsx("label",{className:"form-label",children:"Model"}),s.jsx("button",{type:"button",className:"btn btn-ghost",style:{fontSize:"0.75rem",padding:"0.125rem 0.5rem"},onClick:ee,disabled:N,title:"Re-fetch the model list from the provider",children:N?"Loading…":"↻ Refresh"})]}),S.length===0?s.jsx("div",{className:"form-input",style:{display:"flex",alignItems:"center",minHeight:"2.5rem",color:"var(--text-secondary)",fontSize:"0.85rem"},children:N?"Loading models…":a==="ollama"?"Start Ollama locally, then ↻ Refresh to load models.":"Enter a valid API key above to load available models."}):(()=>{const z=S,W=z.includes(c),I=z.length>12,B=L.trim().toLowerCase();let Q=B?z.filter(q=>q.toLowerCase().includes(B)):z;return W&&!Q.includes(c)&&(Q=[c,...Q]),s.jsxs(s.Fragment,{children:[I&&s.jsx("input",{className:"form-input",value:L,onChange:q=>D(q.target.value),placeholder:"Filter models… (e.g. kimi)",style:{marginBottom:"0.375rem"}}),s.jsxs("select",{className:"form-input",value:W?c:"__unset__",onChange:q=>d(q.target.value==="__unset__"?"":q.target.value),children:[s.jsx("option",{value:"__unset__",disabled:!0,children:"Select a model…"}),Q.map(q=>s.jsx("option",{value:q,children:q},q)),B&&Q.length===0&&s.jsxs("option",{value:"__unset__",disabled:!0,children:["No models match “",L,"”"]})]})]})})(),R&&s.jsx("p",{style:{fontSize:"0.75rem",color:"var(--text-secondary)",margin:"0.375rem 0 0"},children:R})]}),s.jsxs("div",{style:{display:"flex",gap:"0.5rem",alignItems:"center"},children:[s.jsx("button",{className:"btn btn-primary",onClick:F,disabled:y||!c.trim(),title:c.trim()?void 0:"Select a model first",children:y?"Saving...":"Save & Encrypt"}),m&&s.jsx("button",{className:"btn btn-ghost",onClick:$,disabled:j,children:j?"Testing...":"Test Connection"})]}),h&&s.jsx("div",{className:`alert ${h.startsWith("OK")?"alert-success":"alert-error"}`,style:{marginTop:"0.75rem"},children:h})]}),s.jsx(Yx,{}),s.jsx(Dx,{}),s.jsx(Ux,{}),s.jsx(Vx,{}),s.jsx(Hx,{}),s.jsxs("div",{className:"card",style:{padding:"1.5rem",marginTop:"2rem"},children:[s.jsx("h2",{style:{fontSize:"1rem",fontWeight:700,marginBottom:"1rem"},children:"Security"}),s.jsxs("div",{style:{fontSize:"0.85rem",color:"var(--text-secondary)",lineHeight:1.7},children:[s.jsxs("div",{style:{marginBottom:"1rem"},children:[s.jsx("div",{style:{fontWeight:600,color:"var(--text-primary)",marginBottom:"0.375rem"},children:"What the gateway protects"}),s.jsxs("ul",{style:{margin:0,paddingLeft:"1.25rem"},children:[s.jsx("li",{children:"Every tool call verified against your mandate bounds"}),s.jsx("li",{children:"Credentials never exposed to agents through MCP"}),s.jsx("li",{children:"Every action produces a signed ticket"})]})]}),s.jsxs("div",{children:[s.jsx("div",{style:{fontWeight:600,color:"var(--text-primary)",marginBottom:"0.375rem"},children:"Your responsibility"}),s.jsxs("ul",{style:{margin:0,paddingLeft:"1.25rem"},children:[s.jsx("li",{children:"If your AI agent has full access to your computer, it could bypass the gateway"}),s.jsx("li",{children:"For best security, run agents in sandboxed environments"}),s.jsx("li",{children:"The gateway secures what agents do through tools — not what they do on your machine"})]})]})]})]})]})}function Yx(){const[e,t]=u.useState(null),[n,r]=u.useState({intent:"",context:""}),[a,o]=u.useState(null),[i,l]=u.useState(null),[c,d]=u.useState(null),[f,p]=u.useState(!1),m=u.useCallback(async()=>{if(!f)try{const x=await T.getAIPrompts();t(x),r({intent:x.intent.current,context:x.context.current}),p(!0)}catch(x){l(x instanceof Error?x.message:"Failed to load prompts")}},[f]),w=async x=>{if(e){o(x),l(null);try{const j=n[x],g=j.trim()===e[x].default.trim()?"":j;await T.setAIPrompt(x,g);const h=await T.getAIPrompts();t(h),r({intent:h.intent.current,context:h.context.current}),d(x),setTimeout(()=>d(null),2e3)}catch(j){l(j instanceof Error?j.message:"Save failed")}finally{o(null)}}},y=async x=>{if(confirm(`Revert ${x} prompt to the built-in default?`)){o(x),l(null);try{await T.setAIPrompt(x,"");const j=await T.getAIPrompts();t(j),r({intent:j.intent.current,context:j.context.current})}catch(j){l(j instanceof Error?j.message:"Revert failed")}finally{o(null)}}};return s.jsxs("details",{className:"card",style:{padding:"1.5rem",marginTop:"1rem"},onToggle:x=>{x.currentTarget.open&&m()},children:[s.jsx("summary",{style:{fontSize:"1rem",fontWeight:700,cursor:"pointer",listStyle:"revert",userSelect:"none"},children:"Advanced — AI assistant prompts"}),s.jsx("p",{style:{fontSize:"0.85rem",color:"var(--text-secondary)",margin:"0.75rem 0 1rem 0",lineHeight:1.55},children:"These are the system prompts the AI assistant sees when helping you write Intent (per-mandate) or Context (your standing-orders brief). Edit with care — changes apply on the next chat turn."}),i&&s.jsx("div",{className:"alert alert-error",style:{marginBottom:"0.75rem"},children:i}),!f&&!i&&s.jsx("p",{style:{color:"var(--text-muted)",fontSize:"0.85rem"},children:"Loading prompts…"}),e&&s.jsxs(s.Fragment,{children:[s.jsx(mu,{kind:"intent",label:"Intent — per-mandate",description:"Used on the Intent gate when creating a new mandate.",state:e.intent,draft:n.intent,onChange:x=>r(j=>({...j,intent:x})),onSave:()=>w("intent"),onRevert:()=>y("intent"),saving:a==="intent",justSaved:c==="intent"}),s.jsx(mu,{kind:"context",label:"Context — standing-orders brief",description:"Used on the Brief page when refining your context.md.",state:e.context,draft:n.context,onChange:x=>r(j=>({...j,context:x})),onSave:()=>w("context"),onRevert:()=>y("context"),saving:a==="context",justSaved:c==="context"})]})]})}function mu({kind:e,label:t,description:n,state:r,draft:a,onChange:o,onSave:i,onRevert:l,saving:c,justSaved:d}){const f=a!==r.current;return s.jsxs("section",{style:{marginBottom:"1.5rem"},children:[s.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"baseline",marginBottom:"0.25rem",gap:"1rem",flexWrap:"wrap"},children:[s.jsxs("div",{children:[s.jsx("div",{style:{fontWeight:600,fontSize:"0.9rem"},children:t}),s.jsx("div",{style:{fontSize:"0.78rem",color:"var(--text-secondary)"},children:n})]}),r.overridden&&s.jsx("span",{style:{fontSize:"0.7rem",color:"var(--accent)",fontWeight:600,textTransform:"uppercase",letterSpacing:"0.05em"},children:"Custom"})]}),s.jsx("textarea",{className:"form-textarea",value:a,onChange:p=>o(p.target.value),rows:12,spellCheck:!1,style:{width:"100%",fontFamily:"'SF Mono', Monaco, 'Cascadia Code', monospace",fontSize:"0.82rem",lineHeight:1.55,resize:"vertical",minHeight:"14rem",marginTop:"0.5rem"},"aria-label":`${t} system prompt`}),s.jsxs("div",{style:{display:"flex",gap:"0.5rem",alignItems:"center",marginTop:"0.5rem",flexWrap:"wrap"},children:[s.jsx("button",{type:"button",className:"btn btn-primary btn-sm",onClick:i,disabled:c||!f,children:c?"Saving…":"Save"}),r.overridden&&s.jsx("button",{type:"button",className:"btn btn-ghost btn-sm",onClick:l,disabled:c,title:"Discard the override and use the built-in default",children:"Revert to default"}),d&&s.jsx("span",{style:{fontSize:"0.78rem",color:"var(--success)"},children:"Saved"}),f&&!c&&!d&&s.jsx("span",{style:{fontSize:"0.78rem",color:"var(--text-muted)"},children:"Unsaved changes"})]}),s.jsxs("details",{style:{marginTop:"0.5rem"},children:[s.jsx("summary",{style:{fontSize:"0.78rem",color:"var(--text-muted)",cursor:"pointer"},children:"Show built-in default"}),s.jsx("pre",{style:{marginTop:"0.5rem",padding:"0.75rem 1rem",background:"var(--bg-main)",border:"1px solid var(--border)",borderRadius:"0.5rem",fontSize:"0.78rem",lineHeight:1.55,whiteSpace:"pre-wrap",maxHeight:"20rem",overflowY:"auto"},children:r.default})]}),s.jsx("span",{style:{display:"none"},children:e})]})}function Qx(e){return e.proposalId?"review":"automatic"}function pu(e,t,n={}){const r=n.status??"pending",a=n.includeAutonomous??!1,o=[];for(const i of e)r==="pending"&&i.status!=="pending"||n.profile&&i.profileId!==n.profile||o.push({kind:"proposal",id:i.id,sortTimestamp:i.createdAt,commitmentMode:"review",profileId:i.profileId,proposal:i});if(r==="all")for(const i of t){const l=Qx(i);!a&&l==="automatic"||n.profile&&i.profileId!==n.profile||o.push({kind:"receipt",id:i.id,sortTimestamp:i.timestamp,commitmentMode:l,profileId:i.profileId,receipt:i})}return o.sort((i,l)=>l.sortTimestamp-i.sortTimestamp),typeof n.limit=="number"&&n.limit>0?o.slice(0,n.limit):o}const Jx=["https://","http://"];function ym(e,t){return e!=null&&e.length?e.flatMap(n=>{const r=n.template.replace(/\{(\w+)\}/g,(a,o)=>{const i=t[o];return typeof i=="string"||typeof i=="number"?String(i):"\0"});return r.includes("\0")||/\{|\}/.test(r)?[]:Jx.some(a=>r.toLowerCase().startsWith(a))?[{label:n.label,href:r,description:n.description}]:[]}):[]}function Xx({profileId:e}){return s.jsx("span",{className:"profile-badge",children:Le(e)})}function xm(e,t){const n=e-Math.floor(t/1e3);if(n<=0)return{label:"expired",urgent:!1,expired:!0};const r=Math.floor(n/86400),a=Math.floor(n%86400/3600),o=Math.floor(n%3600/60);let i;return r>0?i=`expires in ${r}d ${a}h`:a>0?i=`expires in ${a}h ${o}m`:i=`expires in ${Math.max(1,o)}m`,{label:i,urgent:n<2*3600,expired:!1}}const qx={pending:"Pending",committed:"Approved",executed:"Executed",rejected:"Rejected",expired:"Expired"},Zx={pending:"status-pending",committed:"status-active",executed:"status-active",rejected:"status-revoked",expired:"status-expired"};function e0(e){const t=Date.now()-e*1e3,n=t/36e5;return n<48?n<1?`${Math.max(1,Math.round(t/6e4))}m ago`:`${Math.round(n)}h ago`:new Date(e*1e3).toLocaleString(void 0,{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit"})}function t0(e){return e.split("__").pop()??e}function n0(e){const t=e.toLowerCase();return t.includes("delete")||t.includes("refund")||t.includes("cancel")||t.includes("revoke")}const r0=new Set(["apiKey","api_key","accessToken","access_token","password","secret","signature","_imagePreview"]),s0=/^(image|img|photo|picture|thumbnail)(_?url)?$/i;function a0(e,t){return typeof t!="string"?!1:/^data:image\//i.test(t)?!0:s0.test(e)?/^https?:\/\//.test(t):/^https?:\/\/.+\.(jpe?g|png|gif|webp|svg|avif)(\?|$)/i.test(t)}function Pi(e){if(e==null)return"—";if(typeof e=="string")return e;if(typeof e=="number"||typeof e=="boolean")return String(e);if(Array.isArray(e))return e.map(t=>Pi(t)).join(", ");try{return JSON.stringify(e,null,2)}catch{return String(e)}}function hu({item:e,onApprove:t,onReject:n,resolving:r,proposalLinks:a}){const o=e.kind==="proposal",i=o?e.proposal.status:"executed",l=o?e.proposal.tool:e.receipt.action,c=t0(l),d=n0(l),f=o?e.proposal.toolArgs:null,p=o?e.proposal.executionContext:e.receipt.executionContext,m=o?null:e.receipt.cumulativeState,w=o?ym(a,e.proposal.toolArgs):[],y=f?Object.entries(f).filter(([j])=>!r0.has(j)):[],x=Object.entries(p??{});return s.jsxs("div",{className:"card",children:[s.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"0.5rem",marginBottom:"0.75rem",flexWrap:"wrap"},children:[s.jsx(Xx,{profileId:e.profileId}),s.jsx("code",{style:{fontSize:"0.85rem"},children:c}),e.commitmentMode==="automatic"&&s.jsx("span",{style:{fontSize:"0.7rem",color:"var(--text-tertiary)",textTransform:"uppercase",letterSpacing:"0.04em"},children:"autonomous"}),s.jsxs("span",{style:{marginLeft:"auto",display:"flex",alignItems:"center",gap:"0.5rem"},children:[o&&i==="pending"&&(()=>{const j=xm(e.proposal.expiresAt,Date.now());return s.jsx("span",{style:{fontSize:"0.72rem",color:j.urgent?"var(--warning)":"var(--text-tertiary)",fontWeight:j.urgent?600:400,whiteSpace:"nowrap"},children:j.label})})(),s.jsx("span",{className:`status-badge ${Zx[i]}`,children:qx[i]}),s.jsx("span",{style:{fontSize:"0.75rem",color:"var(--text-tertiary)"},children:e0(e.sortTimestamp)})]})]}),d&&s.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"0.4rem",fontSize:"0.8rem",color:"var(--warning)",background:"var(--bg-main)",border:"1px solid var(--border)",borderRadius:"0.375rem",padding:"0.4rem 0.6rem",marginBottom:"0.75rem"},children:[s.jsx("span",{children:"⚠"}),s.jsx("span",{children:"Irreversible action"})]}),o&&typeof(f==null?void 0:f._imagePreview)=="string"&&s.jsxs("div",{style:{marginBottom:"0.75rem"},children:[s.jsx("div",{style:{fontSize:"0.7rem",fontWeight:600,color:"var(--text-tertiary)",textTransform:"uppercase",letterSpacing:"0.04em",marginBottom:"0.35rem"},children:"Preview"}),s.jsx("img",{src:f._imagePreview,alt:typeof(f==null?void 0:f.altText)=="string"?f.altText:"local image preview",style:{display:"block",maxWidth:"100%",maxHeight:"240px",borderRadius:"0.375rem",border:"1px solid var(--border)"}})]}),w.length>0&&s.jsx("div",{style:{marginBottom:"0.75rem",display:"flex",gap:"0.5rem",flexWrap:"wrap"},children:w.map(j=>s.jsxs("a",{href:j.href,target:"_blank",rel:"noopener noreferrer",className:"btn btn-secondary btn-sm",style:{textDecoration:"none"},title:j.description??j.href,children:[j.label," ↗"]},j.label))}),o&&y.length>0&&s.jsxs("div",{style:{marginBottom:"0.75rem"},children:[s.jsx("div",{style:{fontSize:"0.7rem",fontWeight:600,color:"var(--text-tertiary)",textTransform:"uppercase",letterSpacing:"0.04em",marginBottom:"0.35rem"},children:"Arguments"}),s.jsx("dl",{style:{display:"grid",gridTemplateColumns:"max-content 1fr",gap:"0.2rem 0.75rem",fontSize:"0.85rem",margin:0},children:y.map(([j,g])=>s.jsxs(u.Fragment,{children:[s.jsx("dt",{style:{color:"var(--text-tertiary)",whiteSpace:"nowrap",alignSelf:"start"},children:j}),s.jsx("dd",{style:{color:"var(--text-primary)",margin:0,wordBreak:"break-word",whiteSpace:"pre-wrap"},children:a0(j,g)?s.jsx("img",{src:g,alt:typeof(f==null?void 0:f.altText)=="string"?f.altText:j,style:{display:"block",maxWidth:"100%",maxHeight:"240px",borderRadius:"0.375rem",border:"1px solid var(--border)"},onError:h=>{const v=h.currentTarget,S=v.parentElement;if(!S)return;v.style.display="none";const b=document.createElement("span");b.textContent=g,b.style.color="var(--text-tertiary)",S.appendChild(b)}}):Pi(g)})]},j))})]}),x.length>0&&s.jsx("div",{style:{marginBottom:"0.75rem",fontSize:"0.8rem",color:"var(--text-secondary)"},children:x.map(([j,g])=>`${j}=${Pi(g)}`).join(" · ")}),m&&s.jsxs("div",{style:{fontSize:"0.75rem",color:"var(--text-tertiary)",marginBottom:"0.5rem"},children:["After this action · today: ",m.daily.count," action",m.daily.count===1?"":"s",m.daily.amount>0?`, ${m.daily.amount}`:""," · ","this month: ",m.monthly.count,m.monthly.amount>0?`, ${m.monthly.amount}`:""]}),o&&i==="pending"&&s.jsxs("div",{style:{display:"flex",gap:"0.5rem"},children:[s.jsx("button",{className:"btn btn-primary",onClick:()=>t==null?void 0:t(e.id),disabled:r,children:r?"Approving…":"Approve"}),s.jsx("button",{className:"btn btn-ghost",style:{color:"var(--danger)"},onClick:()=>n==null?void 0:n(e.id),disabled:r,children:"Reject"})]}),s.jsxs("div",{style:{marginTop:"0.5rem",fontSize:"0.7rem",color:"var(--text-tertiary)"},children:[o?"Proposal":"Ticket",": ",e.id]})]})}const o0=new Set(["apiKey","api_key","accessToken","access_token","password","secret","signature","_imagePreview"]);function _i(e){if(e==null)return"—";if(typeof e=="string")return e;if(typeof e=="number"||typeof e=="boolean")return String(e);if(Array.isArray(e))return e.map(t=>_i(t)).join(", ");try{return JSON.stringify(e,null,2)}catch{return String(e)}}function i0(e){const t=Date.now()-e*1e3,n=Math.floor(t/6e4);if(n<60)return`${Math.max(1,n)}m ago`;const r=Math.floor(t/36e5);return r<48?`${r}h ago`:`${Math.floor(r/24)}d ago`}function l0({proposal:e,currentUserId:t,onAction:n,onMessage:r,proposalLinks:a}){const[o,i]=u.useState(!1),[l,c]=u.useState(!1),[d,f]=u.useState(null),[p,m]=u.useState(!1),[w,y]=u.useState(null),[x,j]=u.useState(!1),g=e.tool.split("__").pop()??e.tool,h=Object.entries(e.toolArgs).filter(([P])=>!o0.has(P)),v=Object.entries(e.executionContext),S=ym(a,e.toolArgs),b=e.pendingApprovers??[],N=e.approvedBy??{},C=Object.keys(N).length,R=b.filter(P=>!(P in N)).length,E=t in N,L=async()=>{if(d===null){m(!0),y(null);try{const P=await T.getAttestationIntent(e.authorizationId);if(!P){y("Intent not available or you are not an authorized approver.");return}const ee=await T.decryptIntent({intentCiphertext:P.intentCiphertext,encryptedKey:P.encryptedKey,approverId:t});f(ee)}catch(P){y(P instanceof Error?P.message:"Failed to decrypt intent")}finally{m(!1)}}},D=async()=>{x?j(!1):(j(!0),await L())},V=async()=>{i(!0),r("");try{await T.approveProposal(e.id);try{if(d===null){const P=await T.getAttestationIntent(e.authorizationId);if(P){const ee=await T.decryptIntent({intentCiphertext:P.intentCiphertext,encryptedKey:P.encryptedKey,approverId:t});f(ee),await T.storeApprovedIntent(e.authorizationId,ee)}}else await T.storeApprovedIntent(e.authorizationId,d)}catch{}r(`Approved. ${R-1>0?`${R-1} more approver(s) still needed.`:"All approvers signed off — action is ready to execute."}`),n()}catch(P){r(P instanceof Error?P.message:"Approval failed")}finally{i(!1)}},J=async()=>{const P=prompt("Rejection reason (optional):");if(P!==null){c(!0),r("");try{await T.rejectProposal(e.id,P||void 0),r("Action rejected."),n()}catch(ee){r(ee instanceof Error?ee.message:"Rejection failed")}finally{c(!1)}}},U=o||l;return s.jsxs("div",{className:"card",children:[s.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"0.5rem",marginBottom:"0.5rem",flexWrap:"wrap"},children:[s.jsx("span",{style:{fontWeight:600,fontSize:"0.9rem"},children:Le(e.profileId)}),s.jsx("span",{style:{fontSize:"0.65rem",padding:"0.15rem 0.4rem",borderRadius:"0.25rem",background:"var(--accent-subtle)",color:"var(--accent)",fontWeight:600},children:"Above cap"}),s.jsxs("span",{style:{marginLeft:"auto",display:"flex",alignItems:"center",gap:"0.5rem"},children:[(()=>{const P=xm(e.expiresAt,Date.now());return s.jsx("span",{style:{fontSize:"0.72rem",color:P.urgent?"var(--warning)":"var(--text-tertiary)",fontWeight:P.urgent?600:400,whiteSpace:"nowrap"},children:P.label})})(),s.jsx("span",{style:{fontSize:"0.75rem",color:"var(--text-tertiary)"},children:i0(e.createdAt)})]})]}),s.jsxs("div",{style:{fontSize:"0.8rem",color:"var(--text-tertiary)",marginBottom:"0.5rem"},children:[C," of ",b.length," approver",b.length===1?"":"s"," signed off",b.map(P=>{const ee=P in N;return s.jsxs("span",{style:{marginLeft:"0.5rem",color:ee?"var(--success, green)":"var(--text-tertiary)"},children:[ee?"✓":"○"," ",P===t?"You":P]},P)})]}),s.jsxs("div",{style:{marginBottom:"0.5rem"},children:[s.jsx("div",{style:{fontSize:"0.7rem",fontWeight:600,color:"var(--text-tertiary)",textTransform:"uppercase",letterSpacing:"0.04em",marginBottom:"0.25rem"},children:"Proposed action"}),s.jsx("code",{style:{fontSize:"0.85rem"},children:g})]}),S.length>0&&s.jsx("div",{style:{marginBottom:"0.75rem",display:"flex",gap:"0.5rem",flexWrap:"wrap"},children:S.map(P=>s.jsxs("a",{href:P.href,target:"_blank",rel:"noopener noreferrer",className:"btn btn-secondary btn-sm",style:{textDecoration:"none"},title:P.description??P.href,children:[P.label," ↗"]},P.label))}),h.length>0&&s.jsxs("div",{style:{marginBottom:"0.75rem"},children:[s.jsx("div",{style:{fontSize:"0.7rem",fontWeight:600,color:"var(--text-tertiary)",textTransform:"uppercase",letterSpacing:"0.04em",marginBottom:"0.25rem"},children:"Arguments"}),s.jsx("dl",{style:{display:"grid",gridTemplateColumns:"max-content 1fr",gap:"0.2rem 0.75rem",fontSize:"0.85rem",margin:0},children:h.map(([P,ee])=>s.jsxs(u.Fragment,{children:[s.jsx("dt",{style:{color:"var(--text-tertiary)",whiteSpace:"nowrap",alignSelf:"start"},children:P}),s.jsx("dd",{style:{color:"var(--text-primary)",margin:0,wordBreak:"break-word",whiteSpace:"pre-wrap"},children:_i(ee)})]},P))})]}),v.length>0&&s.jsx("div",{style:{fontSize:"0.8rem",color:"var(--text-secondary)",marginBottom:"0.5rem"},children:v.map(([P,ee])=>`${P}=${_i(ee)}`).join(" · ")}),s.jsxs("div",{style:{marginBottom:"0.75rem"},children:[s.jsxs("button",{className:"btn btn-ghost btn-sm",style:{padding:"0.2rem 0",fontSize:"0.75rem"},onClick:D,disabled:p,children:[x?"▲ Hide intent":"▼ Show intent",p&&" (decrypting...)"]}),x&&s.jsx("div",{style:{marginTop:"0.5rem",padding:"0.75rem",background:"var(--bg-main)",borderRadius:"0.375rem",border:"1px solid var(--border)"},children:w?s.jsx("p",{style:{color:"var(--danger)",fontSize:"0.8rem",margin:0},children:w}):d!==null?s.jsx("p",{style:{fontSize:"0.85rem",margin:0,whiteSpace:"pre-wrap",color:"var(--text-primary)"},children:d}):s.jsx("p",{style:{color:"var(--text-tertiary)",fontSize:"0.8rem",margin:0},children:"No intent available for this mandate."})})]}),!E&&s.jsxs("div",{style:{display:"flex",gap:"0.5rem",marginTop:"0.25rem"},children:[s.jsx("button",{className:"btn btn-primary",onClick:V,disabled:U,children:o?"Approving...":"Approve"}),s.jsx("button",{className:"btn btn-ghost",style:{color:"var(--danger)"},onClick:J,disabled:U,children:l?"Rejecting...":"Reject"})]}),E&&s.jsx("p",{style:{fontSize:"0.8rem",color:"var(--text-tertiary)",marginTop:"0.25rem"},children:"You approved this action. Waiting on other approvers."}),s.jsxs("div",{style:{marginTop:"0.5rem",fontSize:"0.7rem",color:"var(--text-tertiary)"},children:["Proposal: ",e.id]})]})}function c0(){const{domain:e,user:t}=Oe(),n=(t==null?void 0:t.id)??"",[r,a]=u.useState("awaiting-me"),[o,i]=u.useState([]),[l,c]=u.useState([]),[d,f]=u.useState(!0),[p,m]=u.useState(""),w=u.useCallback(async()=>{try{const _=await T.getProposalsForApprover();i(_)}catch{}finally{f(!1)}},[]);fe("proposal-added",w),fe("proposal-approved",w),fe("proposal-rejected",w),fe("proposal-resolved",w),Pt(w,3e4);const[y,x]=u.useState([]),j=u.useCallback(async()=>{try{const _=await T.getProposals(e||"owner");x(_)}catch{}},[e]);fe("proposal-added",j),fe("proposal-approved",j),fe("proposal-rejected",j),fe("proposal-resolved",j),Pt(j,3e4,e);const g=u.useMemo(()=>y.filter(_=>{var X;return _.status==="pending"&&(((X=_.pendingApprovers)==null?void 0:X.length)??0)===0}),[y]),h=u.useMemo(()=>pu(g,[],{status:"pending"}),[g]),[v,S]=u.useState([]),b=u.useCallback(async()=>{if(n)try{const X=(await T.getProposals(e||"owner")).filter(ae=>ae.status==="pending"&&ae.pendingApprovers&&ae.pendingApprovers.includes(n)&&ae.approvedBy&&n in ae.approvedBy);S(X)}catch{}},[n,e]);fe("proposal-approved",b),fe("proposal-rejected",b),Pt(b,3e4,`${n}:${e}`),u.useEffect(()=>{T.getIntegrationManifests().then(_=>c(_.manifests??[])).catch(()=>{})},[]);const N=_=>{var X;return(X=l.find(ae=>ae.id===_.split("__")[0]))==null?void 0:X.proposalLinks};u.useEffect(()=>{w(),j(),b()},[]);const[C,R]=u.useState([]),[E,L]=u.useState([]),[D,V]=u.useState(!0),[J,U]=u.useState(null),[P,ee]=u.useState(""),[F,$]=u.useState("pending"),[z,W]=u.useState(null),[I,B]=u.useState(!1),Q=u.useCallback(async()=>{try{const{proposals:_,receipts:X}=await T.getThread({domain:e,status:F,sinceDays:7});R(_),L(X)}catch{}finally{V(!1)}},[e,F]);Pt(Q,3e4,`${e}:${F}`);const q=async(_,X)=>{U(_),ee("");try{const ae=e||"owner",ge=await T.resolveProposal(_,X,ae);ee(X==="commit"?`Action approved. Status: ${ge.status}`:"Action rejected."),await Promise.all([Q(),j()])}catch(ae){ee(ae instanceof Error?ae.message:"Failed")}finally{U(null)}},re=u.useMemo(()=>{const _=new Set;for(const X of C)_.add(X.profileId);for(const X of E)_.add(X.profileId);return Array.from(_).sort()},[C,E]),ce=u.useMemo(()=>pu(C,E,{status:F,profile:z??void 0,includeAutonomous:I}),[C,E,F,z,I]),me=u.useCallback(()=>{w(),b()},[w,b]),te=u.useMemo(()=>{const _=new Set,X=[];for(const ae of v)_.has(ae.id)||(_.add(ae.id),X.push(ae));return X.sort((ae,ge)=>ge.createdAt-ae.createdAt)},[v]),oe=o.length+h.length,se=te.length;return s.jsxs(s.Fragment,{children:[s.jsxs("div",{className:"page-header",children:[s.jsx("h1",{className:"page-title",children:"Pending Approvals"}),s.jsx("p",{className:"page-subtitle",children:"Actions awaiting approval, plus recent activity from the last 7 days."})]}),s.jsxs("div",{className:"nav-tabs",style:{marginBottom:"1rem"},children:[s.jsxs("button",{className:`nav-tab${r==="awaiting-me"?" active":""}`,onClick:()=>a("awaiting-me"),children:["Awaiting me ",oe>0&&s.jsx("span",{style:{marginLeft:"0.4rem",background:"var(--warning)",color:"var(--bg-elevated)",borderRadius:"0.625rem",padding:"0 0.375rem",fontSize:"0.7rem",fontWeight:600},children:oe})]}),s.jsxs("button",{className:`nav-tab${r==="awaiting-others"?" active":""}`,onClick:()=>a("awaiting-others"),children:["Awaiting others ",se>0&&s.jsx("span",{style:{marginLeft:"0.4rem",background:"var(--border)",color:"var(--text-secondary)",borderRadius:"0.625rem",padding:"0 0.375rem",fontSize:"0.7rem",fontWeight:600},children:se})]}),s.jsx("button",{className:`nav-tab${r==="all"?" active":""}`,onClick:()=>{a("all"),Q()},children:"All"})]}),r==="awaiting-me"&&s.jsx(s.Fragment,{children:d&&oe===0?s.jsx("p",{style:{color:"var(--text-tertiary)"},children:"Loading..."}):oe===0?s.jsxs("div",{className:"card",style:{textAlign:"center",padding:"2rem"},children:[s.jsx("p",{style:{color:"var(--text-tertiary)",marginBottom:"0.5rem"},children:"No actions awaiting your approval."}),s.jsx("p",{style:{fontSize:"0.8rem",color:"var(--text-tertiary)"},children:"Review-mode actions and above-cap actions you must approve will appear here."})]}):s.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:"1rem"},children:[(p||P)&&s.jsx("div",{className:"alert alert-success",children:p||P}),h.map(_=>s.jsx(hu,{proposalLinks:_.kind==="proposal"?N(_.proposal.tool):void 0,item:_,onApprove:X=>q(X,"commit"),onReject:X=>q(X,"reject"),resolving:J===_.id},_.id)),o.map(_=>s.jsx(l0,{proposal:_,currentUserId:n,onAction:me,onMessage:m,proposalLinks:N(_.tool)},_.id))]})}),r==="awaiting-others"&&s.jsx(s.Fragment,{children:te.length===0?s.jsxs("div",{className:"card",style:{textAlign:"center",padding:"2rem"},children:[s.jsx("p",{style:{color:"var(--text-tertiary)",marginBottom:"0.5rem"},children:"No actions waiting on others."}),s.jsx("p",{style:{fontSize:"0.8rem",color:"var(--text-tertiary)"},children:"Actions you proposed or approved that are pending other approvers will appear here."})]}):s.jsx("div",{style:{display:"flex",flexDirection:"column",gap:"1rem"},children:te.map(_=>s.jsx(d0,{proposal:_,currentUserId:n,onCancel:async()=>{try{await T.rejectProposal(_.id,"cancelled by creator"),b(),j()}catch(X){alert(X instanceof Error?X.message:"Cancel failed")}}},_.id))})}),r==="all"&&s.jsxs(s.Fragment,{children:[P&&s.jsx("div",{className:"alert alert-success",style:{marginBottom:"1rem"},children:P}),s.jsxs("div",{className:"filter-chips",style:{marginBottom:"1rem"},children:[s.jsx("button",{className:`filter-chip ${F==="pending"?"selected":""}`,onClick:()=>$("pending"),children:"Pending"}),s.jsx("button",{className:`filter-chip ${F==="all"?"selected":""}`,onClick:()=>$("all"),children:"All"}),re.length>0&&s.jsx("span",{style:{width:1,background:"var(--border)",alignSelf:"stretch",margin:"0 0.25rem"}}),re.map(_=>s.jsx("button",{className:`filter-chip ${z===_?"selected":""}`,onClick:()=>W(z===_?null:_),children:Le(_)},_)),F==="all"&&s.jsxs(s.Fragment,{children:[s.jsx("span",{style:{width:1,background:"var(--border)",alignSelf:"stretch",margin:"0 0.25rem"}}),s.jsxs("button",{className:`filter-chip ${I?"selected":""}`,onClick:()=>B(!I),title:"Include actions executed without human review (automatic commitment mode)",children:[I?"✓ ":"","Autonomous actions"]})]})]}),D&&ce.length===0?s.jsx("p",{style:{color:"var(--text-tertiary)"},children:"Loading..."}):ce.length===0?s.jsxs("div",{className:"card",style:{textAlign:"center",padding:"2rem"},children:[s.jsx("p",{style:{color:"var(--text-tertiary)",marginBottom:"0.5rem"},children:F==="pending"?"No actions awaiting your approval.":"Nothing here yet."}),s.jsx("p",{style:{fontSize:"0.8rem",color:"var(--text-tertiary)"},children:F==="pending"?"Your agents are operating within their mandates. Switch to All to see recent activity.":"When an agent calls a gated tool, activity will appear here."})]}):s.jsx("div",{style:{display:"flex",flexDirection:"column",gap:"1rem"},children:ce.map(_=>s.jsx(hu,{proposalLinks:_.kind==="proposal"?N(_.proposal.tool):void 0,item:_,onApprove:X=>q(X,"commit"),onReject:X=>q(X,"reject"),resolving:J===_.id},_.id))})]})]})}function u0(e){const t=Date.now()-e*1e3,n=Math.floor(t/6e4);if(n<60)return`${Math.max(1,n)}m ago`;const r=Math.floor(t/36e5);return r<48?`${r}h ago`:`${Math.floor(r/24)}d ago`}function d0({proposal:e,currentUserId:t,onCancel:n}){var d;const[r,a]=u.useState(!1),o=Object.keys(e.approvedBy??{}),i=(e.pendingApprovers??[]).filter(f=>!(f in(e.approvedBy??{}))),l=(((d=e.pendingApprovers)==null?void 0:d.length)??0)>0,c=async()=>{if(confirm("Cancel this action? All approvers will be notified.")){a(!0);try{await n()}finally{a(!1)}}};return s.jsxs("div",{className:"card",children:[s.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"0.5rem",marginBottom:"0.5rem",flexWrap:"wrap"},children:[s.jsx("span",{style:{fontWeight:600,fontSize:"0.9rem"},children:Le(e.profileId)}),l&&s.jsx("span",{style:{fontSize:"0.65rem",padding:"0.15rem 0.4rem",borderRadius:"0.25rem",background:"var(--accent-subtle)",color:"var(--accent)",fontWeight:600},children:"Above cap"}),s.jsx("span",{style:{marginLeft:"auto",fontSize:"0.75rem",color:"var(--text-tertiary)"},children:u0(e.createdAt)})]}),s.jsx("div",{style:{fontSize:"0.85rem",color:"var(--text-secondary)",marginBottom:"0.5rem"},children:s.jsx("code",{children:e.tool.split("__").pop()??e.tool})}),l&&s.jsxs("div",{style:{fontSize:"0.8rem",color:"var(--text-tertiary)",marginBottom:"0.5rem"},children:[o.map(f=>s.jsx("span",{style:{marginRight:"0.75rem",color:"var(--success, green)"},children:f===t?"You approved":`${f} approved`},f)),i.map(f=>s.jsxs("span",{style:{marginRight:"0.75rem",color:"var(--text-tertiary)"},children:["Waiting on ",f===t?"you":f]},f))]}),s.jsx("div",{style:{display:"flex",justifyContent:"flex-end",gap:"0.5rem",marginTop:"0.5rem"},children:s.jsx("button",{className:"btn btn-ghost btn-sm",style:{color:"var(--danger)"},onClick:c,disabled:r,children:r?"Cancelling...":"Cancel"})})]})}const f0=`# Agent Brief
|
|
75
75
|
|
|
76
76
|
You act on my behalf through Suveren — the gateway that gates every
|
|
77
77
|
privileged tool call you make. Suveren implements the bounded-authority
|
package/dist/ui/index.html
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
<meta name="apple-mobile-web-app-title" content="Suveren" />
|
|
15
15
|
<meta name="theme-color" content="#111111" />
|
|
16
16
|
<title>Suveren</title>
|
|
17
|
-
<script type="module" crossorigin src="/assets/index-
|
|
17
|
+
<script type="module" crossorigin src="/assets/index-B1qNl7zo.js"></script>
|
|
18
18
|
<link rel="stylesheet" crossorigin href="/assets/index-BJqF5rmx.css">
|
|
19
19
|
</head>
|
|
20
20
|
<body>
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal reader/writer for `<dataDir>/as-pairing.json` — the CLI's copy.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors `apps/control-plane/src/lib/as-pairing.ts` (same file shape, same
|
|
5
|
+
* rules) but written in plain JS, same reason as `config.mjs`: this runs as
|
|
6
|
+
* `bundle/bin/suveren-gateway.js`, hand-authored ESM shipped as-is. Only
|
|
7
|
+
* what the CLI's `config set pin-tls on --expect-fingerprint` /
|
|
8
|
+
* `start --pin-tls --expect-fingerprint` need is implemented here —
|
|
9
|
+
* `readPairing` and `recordTlsPin`. Keep in step with the TS version if the
|
|
10
|
+
* file shape changes.
|
|
11
|
+
*/
|
|
12
|
+
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
13
|
+
import { join } from 'node:path';
|
|
14
|
+
|
|
15
|
+
function pairingPath(dataDir) {
|
|
16
|
+
return join(dataDir, 'as-pairing.json');
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function readPairing(dataDir) {
|
|
20
|
+
const path = pairingPath(dataDir);
|
|
21
|
+
if (!existsSync(path)) return null;
|
|
22
|
+
try {
|
|
23
|
+
const data = JSON.parse(readFileSync(path, 'utf8'));
|
|
24
|
+
if (typeof data.asUrl !== 'string' || typeof data.publicKeyHex !== 'string') return null;
|
|
25
|
+
return {
|
|
26
|
+
asUrl: data.asUrl,
|
|
27
|
+
publicKeyHex: data.publicKeyHex,
|
|
28
|
+
pairedAt: data.pairedAt ?? '',
|
|
29
|
+
...(typeof data.tlsSpkiPinHex === 'string' ? { tlsSpkiPinHex: data.tlsSpkiPinHex } : {}),
|
|
30
|
+
};
|
|
31
|
+
} catch {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** Attach/overwrite the TLS SPKI pin on the EXISTING pairing record for
|
|
37
|
+
* `asUrl`. Returns false (no-op) when there is no existing pairing for
|
|
38
|
+
* this URL to attach to — the CLI falls back to the config.json
|
|
39
|
+
* `pinTlsExpectedFingerprint` staging field in that case (see
|
|
40
|
+
* suveren-gateway.js), since a pairing record requires a `publicKeyHex`
|
|
41
|
+
* this command never has. */
|
|
42
|
+
export function recordTlsPin(dataDir, asUrl, tlsSpkiPinHex) {
|
|
43
|
+
const existing = readPairing(dataDir);
|
|
44
|
+
if (!existing || existing.asUrl !== asUrl) return false;
|
|
45
|
+
const path = pairingPath(dataDir);
|
|
46
|
+
writeFileSync(
|
|
47
|
+
path,
|
|
48
|
+
JSON.stringify({ ...existing, tlsSpkiPinHex }, null, 2),
|
|
49
|
+
{ encoding: 'utf8', mode: 0o600 },
|
|
50
|
+
);
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** Group a hex digest into colon-separated uppercase quads — the
|
|
55
|
+
* human-readable, compare-over-the-phone form. Same convention as
|
|
56
|
+
* as-pairing.ts's `fingerprintOf` / as-tls-pin.ts's `formatPinFingerprint`,
|
|
57
|
+
* applied here to an already-computed digest (never re-hashes anything). */
|
|
58
|
+
export function formatFingerprint(hex) {
|
|
59
|
+
const upper = hex.toUpperCase();
|
|
60
|
+
return upper.match(/.{1,4}/g)?.join(':') ?? upper;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Validate + normalize a candidate SHA-256 fingerprint: accepts with or
|
|
65
|
+
* without colons/spaces/grouping, case-insensitive. Returns
|
|
66
|
+
* `{ ok: true, hex }` (lowercase, no separators) or `{ ok: false, error }`.
|
|
67
|
+
*/
|
|
68
|
+
export function normalizeFingerprint(raw) {
|
|
69
|
+
const hex = (raw ?? '').replace(/[^0-9a-fA-F]/g, '').toLowerCase();
|
|
70
|
+
if (!/^[0-9a-f]{64}$/.test(hex)) {
|
|
71
|
+
return {
|
|
72
|
+
ok: false,
|
|
73
|
+
error: 'must be a 64-character SHA-256 hex digest (colons/spacing are fine), e.g. the output of `openssl dgst -sha256`.',
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
return { ok: true, hex };
|
|
77
|
+
}
|