comisai 1.0.24 → 1.0.25
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/node_modules/@comis/agent/package.json +1 -1
- package/node_modules/@comis/channels/package.json +1 -1
- package/node_modules/@comis/cli/package.json +1 -1
- package/node_modules/@comis/core/dist/bootstrap.js +5 -0
- package/node_modules/@comis/core/dist/config/env-layer.d.ts +31 -0
- package/node_modules/@comis/core/dist/config/env-layer.js +41 -0
- package/node_modules/@comis/core/dist/config/layered.d.ts +9 -0
- package/node_modules/@comis/core/dist/config/layered.js +11 -0
- package/node_modules/@comis/core/package.json +1 -1
- package/node_modules/@comis/daemon/dist/daemon.js +3 -0
- package/node_modules/@comis/daemon/package.json +1 -1
- package/node_modules/@comis/gateway/package.json +1 -1
- package/node_modules/@comis/infra/package.json +1 -1
- package/node_modules/@comis/memory/package.json +1 -1
- package/node_modules/@comis/scheduler/package.json +1 -1
- package/node_modules/@comis/shared/package.json +1 -1
- package/node_modules/@comis/skills/package.json +1 -1
- package/node_modules/@comis/web/dist/assets/{agent-detail-BG9MGWWj.js → agent-detail-ru-AhppM.js} +270 -270
- package/node_modules/@comis/web/dist/assets/agent-editor-hjwRuFVp.js +2173 -0
- package/node_modules/@comis/web/dist/assets/{agent-list-LHCJ4rw2.js → agent-list-6Uotjatr.js} +170 -170
- package/node_modules/@comis/web/dist/assets/{approvals-q9VH_IKr.js → approvals-C-K6hN2U.js} +13 -13
- package/node_modules/@comis/web/dist/assets/billing-view-CxysXH0p.js +375 -0
- package/node_modules/@comis/web/dist/assets/{channel-detail-CaInesJM.js → channel-detail-BBCKtmne.js} +265 -265
- package/node_modules/@comis/web/dist/assets/channel-list-FkfeOLBQ.js +323 -0
- package/node_modules/@comis/web/dist/assets/{chat-console-CNmzl0JW.js → chat-console-BumBaIgO.js} +243 -246
- package/node_modules/@comis/web/dist/assets/{config-editor-DX4ITw6y.js → config-editor-C9BSwHGy.js} +477 -477
- package/node_modules/@comis/web/dist/assets/{context-dag-browser-BwiaF5tf.js → context-dag-browser-BHm00mJD.js} +105 -105
- package/node_modules/@comis/web/dist/assets/{context-engine-BZ5Am6hA.js → context-engine-BENY3pWE.js} +136 -136
- package/node_modules/@comis/web/dist/assets/decorate-BvWYovGE.js +38 -0
- package/node_modules/@comis/web/dist/assets/{delivery-view-OfBZof-m.js → delivery-view-BCnkPsAp.js} +134 -134
- package/node_modules/@comis/web/dist/assets/{diagnostics-view-YFwCxgr2.js → diagnostics-view-C_jQFG2H.js} +82 -82
- package/node_modules/@comis/web/dist/assets/directive-BOYXJ-K-.js +1 -0
- package/node_modules/@comis/web/dist/assets/{extract-variables-BM5qyK-s.js → extract-variables-B7-Doo7l.js} +39 -39
- package/node_modules/@comis/web/dist/assets/{ic-array-editor-B7m6x7-S.js → ic-array-editor-BLoEyeLS.js} +29 -29
- package/node_modules/@comis/web/dist/assets/{ic-breadcrumb-CUMpp3BL.js → ic-breadcrumb-DqN6G3gc.js} +16 -16
- package/node_modules/@comis/web/dist/assets/{ic-budget-segment-bar-BtJ6x5mN.js → ic-budget-segment-bar-zLsMzjDO.js} +20 -20
- package/node_modules/@comis/web/dist/assets/ic-chat-message-FdQcZsSQ.js +352 -0
- package/node_modules/@comis/web/dist/assets/{ic-confirm-dialog-CCDbB04e.js → ic-confirm-dialog-DGlPbV1T.js} +26 -26
- package/node_modules/@comis/web/dist/assets/{ic-connection-dot-CnT1b8xr.js → ic-connection-dot-BgYiK2N4.js} +13 -13
- package/node_modules/@comis/web/dist/assets/ic-data-table-CKIvr-ag.js +277 -0
- package/node_modules/@comis/web/dist/assets/ic-delivery-row-B3YwjjuM.js +67 -0
- package/node_modules/@comis/web/dist/assets/{ic-detail-panel-BF83r-if.js → ic-detail-panel-DiCe4hLr.js} +27 -27
- package/node_modules/@comis/web/dist/assets/{ic-empty-state-60l2ePhd.js → ic-empty-state-CM3Wbj2f.js} +19 -19
- package/node_modules/@comis/web/dist/assets/ic-graph-canvas-ByRjij68.js +359 -0
- package/node_modules/@comis/web/dist/assets/ic-icon-BGNCCPpZ.js +33 -0
- package/node_modules/@comis/web/dist/assets/{ic-layer-waterfall-COvEYMg5.js → ic-layer-waterfall-WkaFyu-l.js} +18 -18
- package/node_modules/@comis/web/dist/assets/ic-relative-time-B3UAnTqg.js +12 -0
- package/node_modules/@comis/web/dist/assets/{ic-search-input-CSOxY9g7.js → ic-search-input-B02AGw1i.js} +22 -22
- package/node_modules/@comis/web/dist/assets/{ic-select-Ce-Raudx.js → ic-select-BqfZISjw.js} +29 -29
- package/node_modules/@comis/web/dist/assets/ic-tabs-yBjkWKJH.js +95 -0
- package/node_modules/@comis/web/dist/assets/ic-tag-CvMVQFRR.js +33 -0
- package/node_modules/@comis/web/dist/assets/{ic-time-range-picker-CypCT68y.js → ic-time-range-picker-DXbYeBmY.js} +31 -31
- package/node_modules/@comis/web/dist/assets/{ic-tool-call-7MaXSsCW.js → ic-tool-call-DMPHsLyx.js} +51 -51
- package/node_modules/@comis/web/dist/assets/index-CVEaS9aY.css +2 -0
- package/node_modules/@comis/web/dist/assets/index-FLPhHz8p.js +2792 -0
- package/node_modules/@comis/web/dist/assets/{mcp-management-BNZPnpDn.js → mcp-management-5jyScQis.js} +209 -209
- package/node_modules/@comis/web/dist/assets/{media-config-BBvTYxOX.js → media-config-J9oT9PPs.js} +154 -154
- package/node_modules/@comis/web/dist/assets/{media-test-BkK3RCRK.js → media-test-DGTCtM8-.js} +259 -259
- package/node_modules/@comis/web/dist/assets/{memory-inspector-1hDGCGat.js → memory-inspector-D5Re9ptG.js} +450 -450
- package/node_modules/@comis/web/dist/assets/{message-center-CXefwsUu.js → message-center-cRLK6ZmG.js} +290 -290
- package/node_modules/@comis/web/dist/assets/{models-C1qcU_j3.js → models-D5vu07MR.js} +371 -371
- package/node_modules/@comis/web/dist/assets/observability-types-D0tkwElU.js +1 -0
- package/node_modules/@comis/web/dist/assets/{observe-view-C0VBhX4C.js → observe-view-CalNNEmd.js} +399 -399
- package/node_modules/@comis/web/dist/assets/pipeline-builder-DUYDGwZf.js +1495 -0
- package/node_modules/@comis/web/dist/assets/{pipeline-history-DkfOQ6SW.js → pipeline-history-BAO8brOe.js} +124 -124
- package/node_modules/@comis/web/dist/assets/{pipeline-history-detail-hyHgD0ai.js → pipeline-history-detail-DectIoQt.js} +65 -65
- package/node_modules/@comis/web/dist/assets/{pipeline-list-BPW8hV-q.js → pipeline-list-BHlaBKww.js} +227 -227
- package/node_modules/@comis/web/dist/assets/{pipeline-monitor-Bip16T7e.js → pipeline-monitor-BhtpNEHf.js} +298 -298
- package/node_modules/@comis/web/dist/assets/{scheduler-BGgwKd06.js → scheduler-VafN_8xi.js} +486 -486
- package/node_modules/@comis/web/dist/assets/{security-D15st4xx.js → security-QQXMRTlo.js} +389 -389
- package/node_modules/@comis/web/dist/assets/{session-detail-SGEYNJ0M.js → session-detail-BpZ_8Yih.js} +294 -294
- package/node_modules/@comis/web/dist/assets/session-key-parser-Dkqcj2Ss.js +1 -0
- package/node_modules/@comis/web/dist/assets/session-list-DfCm8Cec.js +231 -0
- package/node_modules/@comis/web/dist/assets/{setup-wizard-nT0tz9QP.js → setup-wizard-C-z477CG.js} +486 -494
- package/node_modules/@comis/web/dist/assets/{skills-D8yVfSUy.js → skills-BCOGPf6s.js} +329 -329
- package/node_modules/@comis/web/dist/assets/{subagents-HHXMeHYo.js → subagents-l-auUraL.js} +74 -74
- package/node_modules/@comis/web/dist/assets/{workspace-manager-BQlr10iH.js → workspace-manager-DlvBixiq.js} +236 -236
- package/node_modules/@comis/web/dist/index.html +3 -2
- package/node_modules/@comis/web/package.json +1 -1
- package/package.json +15 -15
- package/node_modules/@comis/web/dist/assets/agent-editor-C26Q_xCs.js +0 -2173
- package/node_modules/@comis/web/dist/assets/billing-view-CtYvBqTE.js +0 -375
- package/node_modules/@comis/web/dist/assets/channel-list-B8dj3O9a.js +0 -323
- package/node_modules/@comis/web/dist/assets/directive-DoeGSK_T.js +0 -1
- package/node_modules/@comis/web/dist/assets/ic-chat-message-CFyDJd0z.js +0 -352
- package/node_modules/@comis/web/dist/assets/ic-data-table-CKUNTxHw.js +0 -277
- package/node_modules/@comis/web/dist/assets/ic-delivery-row-GP5Fkygs.js +0 -67
- package/node_modules/@comis/web/dist/assets/ic-graph-canvas-C8FuSMe1.js +0 -359
- package/node_modules/@comis/web/dist/assets/ic-icon-xeGTVhVG.js +0 -33
- package/node_modules/@comis/web/dist/assets/ic-relative-time-3FqpjeAI.js +0 -12
- package/node_modules/@comis/web/dist/assets/ic-tabs-B7QtM_v8.js +0 -95
- package/node_modules/@comis/web/dist/assets/ic-tag-CPPUnDLF.js +0 -33
- package/node_modules/@comis/web/dist/assets/index-CEcM1R_C.js +0 -2830
- package/node_modules/@comis/web/dist/assets/index-CIJFuItj.css +0 -1
- package/node_modules/@comis/web/dist/assets/observability-types-D7jUtSde.js +0 -1
- package/node_modules/@comis/web/dist/assets/pipeline-builder-DcUUIrm0.js +0 -1496
- package/node_modules/@comis/web/dist/assets/session-key-parser-DPORMVyU.js +0 -1
- package/node_modules/@comis/web/dist/assets/session-list-6ybUTxbY.js +0 -231
|
@@ -1,24 +1,4 @@
|
|
|
1
|
-
import{
|
|
2
|
-
<div class="field-wrapper">
|
|
3
|
-
${this.label?s`<label>${this.label}</label>`:p}
|
|
4
|
-
<div class="input-row">
|
|
5
|
-
<input
|
|
6
|
-
type=${this._visible?"text":"password"}
|
|
7
|
-
.value=${this.value}
|
|
8
|
-
placeholder=${this.placeholder}
|
|
9
|
-
?disabled=${this.disabled}
|
|
10
|
-
@input=${this._onInput}
|
|
11
|
-
/>
|
|
12
|
-
<button
|
|
13
|
-
class="toggle-btn"
|
|
14
|
-
type="button"
|
|
15
|
-
aria-label=${this._visible?"Hide value":"Show value"}
|
|
16
|
-
@click=${this._toggleVisibility}
|
|
17
|
-
>${this._visible?"🙈":"👁"}</button>
|
|
18
|
-
</div>
|
|
19
|
-
<span class="hint">Format: env:VAR_NAME or file:/path/to/secret</span>
|
|
20
|
-
</div>
|
|
21
|
-
`}};g.styles=[_,S,w`
|
|
1
|
+
import{c as e,f as t,h as n,l as r,n as i,o as a,r as o,s,t as c,u as l}from"./decorate-BvWYovGE.js";import{a as u,i as d}from"./index-FLPhHz8p.js";import"./ic-tag-CvMVQFRR.js";import"./ic-relative-time-B3UAnTqg.js";import"./ic-array-editor-BLoEyeLS.js";import"./ic-empty-state-CM3Wbj2f.js";import"./ic-tabs-yBjkWKJH.js";import"./ic-connection-dot-BgYiK2N4.js";import"./ic-select-BqfZISjw.js";var f=class extends r{constructor(...e){super(...e),this.label=``,this.value=``,this.placeholder=`env:SECRET_NAME or file:/path`,this.disabled=!1,this._visible=!1}static{this.styles=[o,i,n`
|
|
22
2
|
:host {
|
|
23
3
|
display: block;
|
|
24
4
|
}
|
|
@@ -88,71 +68,27 @@ import{s as _,f as S,i as w,n as d,r as l,a as x,A as p,b as s,t as $,I as n,S a
|
|
|
88
68
|
color: var(--ic-text-dim);
|
|
89
69
|
font-style: italic;
|
|
90
70
|
}
|
|
91
|
-
`]
|
|
92
|
-
<div class="
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
</div>
|
|
109
|
-
|
|
110
|
-
${this._newSecretDisplay?s`
|
|
111
|
-
<div class="new-secret-banner">
|
|
112
|
-
<div class="secret-label">New Token Secret</div>
|
|
113
|
-
<div class="secret-value">${this._newSecretDisplay}</div>
|
|
114
|
-
<div class="secret-warning">Copy this secret now. It will not be shown again.</div>
|
|
115
|
-
</div>
|
|
116
|
-
`:p}
|
|
117
|
-
|
|
118
|
-
<div class="create-form">
|
|
119
|
-
<div class="create-form-title">Create Token</div>
|
|
120
|
-
<div class="form-field">
|
|
121
|
-
<label class="form-label">Scopes</label>
|
|
122
|
-
<div class="checkbox-row">
|
|
123
|
-
<input type="checkbox" id="scope-rpc"
|
|
124
|
-
.checked=${this._newTokenScopes.includes("rpc")}
|
|
125
|
-
@change=${e=>this._onScopeToggle("rpc",e.target.checked)}
|
|
126
|
-
/><label for="scope-rpc">rpc</label>
|
|
127
|
-
</div>
|
|
128
|
-
<div class="checkbox-row">
|
|
129
|
-
<input type="checkbox" id="scope-ws"
|
|
130
|
-
.checked=${this._newTokenScopes.includes("ws")}
|
|
131
|
-
@change=${e=>this._onScopeToggle("ws",e.target.checked)}
|
|
132
|
-
/><label for="scope-ws">ws</label>
|
|
133
|
-
</div>
|
|
134
|
-
<div class="checkbox-row">
|
|
135
|
-
<input type="checkbox" id="scope-admin"
|
|
136
|
-
.checked=${this._newTokenScopes.includes("admin")}
|
|
137
|
-
@change=${e=>this._onScopeToggle("admin",e.target.checked)}
|
|
138
|
-
/><label for="scope-admin">admin</label>
|
|
139
|
-
</div>
|
|
140
|
-
<div class="checkbox-row">
|
|
141
|
-
<input type="checkbox" id="scope-api"
|
|
142
|
-
.checked=${this._newTokenScopes.includes("api")}
|
|
143
|
-
@change=${e=>this._onScopeToggle("api",e.target.checked)}
|
|
144
|
-
/><label for="scope-api">api</label>
|
|
145
|
-
</div>
|
|
146
|
-
<div class="checkbox-row">
|
|
147
|
-
<input type="checkbox" id="scope-all"
|
|
148
|
-
.checked=${this._newTokenScopes.includes("*")}
|
|
149
|
-
@change=${e=>this._onScopeToggle("*",e.target.checked)}
|
|
150
|
-
/><label for="scope-all">* (all)</label>
|
|
151
|
-
</div>
|
|
71
|
+
`]}_onInput(e){let t=e.target.value;this.dispatchEvent(new CustomEvent(`change`,{detail:t,bubbles:!0,composed:!0}))}_toggleVisibility(){this._visible=!this._visible}render(){return t`
|
|
72
|
+
<div class="field-wrapper">
|
|
73
|
+
${this.label?t`<label>${this.label}</label>`:l}
|
|
74
|
+
<div class="input-row">
|
|
75
|
+
<input
|
|
76
|
+
type=${this._visible?`text`:`password`}
|
|
77
|
+
.value=${this.value}
|
|
78
|
+
placeholder=${this.placeholder}
|
|
79
|
+
?disabled=${this.disabled}
|
|
80
|
+
@input=${this._onInput}
|
|
81
|
+
/>
|
|
82
|
+
<button
|
|
83
|
+
class="toggle-btn"
|
|
84
|
+
type="button"
|
|
85
|
+
aria-label=${this._visible?`Hide value`:`Show value`}
|
|
86
|
+
@click=${this._toggleVisibility}
|
|
87
|
+
>${this._visible?`🙈`:`👁`}</button>
|
|
152
88
|
</div>
|
|
153
|
-
<
|
|
89
|
+
<span class="hint">Format: env:VAR_NAME or file:/path/to/secret</span>
|
|
154
90
|
</div>
|
|
155
|
-
`}};
|
|
91
|
+
`}};c([s()],f.prototype,`label`,void 0),c([s()],f.prototype,`value`,void 0),c([s()],f.prototype,`placeholder`,void 0),c([s({type:Boolean})],f.prototype,`disabled`,void 0),c([a()],f.prototype,`_visible`,void 0),f=c([e(`ic-secret-input`)],f);var p=class extends r{constructor(...e){super(...e),this._tokens=[],this._newTokenScopes=[],this._newSecretDisplay=null}static{this.styles=[o,i,n`
|
|
156
92
|
:host {
|
|
157
93
|
display: block;
|
|
158
94
|
}
|
|
@@ -317,41 +253,71 @@ import{s as _,f as S,i as w,n as d,r as l,a as x,A as p,b as s,t as $,I as n,S a
|
|
|
317
253
|
color: var(--ic-text-dim);
|
|
318
254
|
margin-top: var(--ic-space-xs);
|
|
319
255
|
}
|
|
320
|
-
`]
|
|
321
|
-
<div
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
<
|
|
329
|
-
<span class="action-name">${e.action}</span>
|
|
330
|
-
<ic-tag variant=${t}>${e.classification}</ic-tag>
|
|
331
|
-
</div>
|
|
332
|
-
<div class="timestamp">
|
|
333
|
-
<ic-relative-time .timestamp=${e.requestedAt}></ic-relative-time>
|
|
256
|
+
`]}connectedCallback(){super.connectedCallback()}updated(e){e.has(`rpc`)&&this.rpc&&this._loadTokens()}async _loadTokens(){if(this.rpc)try{let e=await this.rpc.call(`tokens.list`);this._tokens=e.tokens??[]}catch{}}async _revokeToken(e){if(this.rpc)try{await this.rpc.call(`tokens.revoke`,{id:e}),this._tokens=this._tokens.filter(t=>t.id!==e),u.show(`Token "${e}" revoked`,`success`),this.dispatchEvent(new CustomEvent(`tokens-changed`,{bubbles:!0,composed:!0}))}catch(e){let t=e instanceof Error?e.message:`Failed to revoke token`;u.show(t,`error`)}}async _rotateToken(e){if(this.rpc)try{let t=await this.rpc.call(`tokens.rotate`,{id:e});this._newSecretDisplay=t.secret,u.show(`Token "${e}" rotated -- new secret shown below`,`success`),this.dispatchEvent(new CustomEvent(`tokens-changed`,{bubbles:!0,composed:!0}))}catch(e){let t=e instanceof Error?e.message:`Failed to rotate token`;u.show(t,`error`)}}_onScopeToggle(e,t){t?this._newTokenScopes=[...this._newTokenScopes,e]:this._newTokenScopes=this._newTokenScopes.filter(t=>t!==e)}async _generateToken(){if(this.rpc)try{let e=await this.rpc.call(`tokens.create`,{scopes:[...this._newTokenScopes]});this._tokens=[...this._tokens,{id:e.id,scopes:e.scopes}],this._newSecretDisplay=e.secret,this._newTokenScopes=[],u.show(`Token created -- secret shown below`,`success`),this.dispatchEvent(new CustomEvent(`tokens-changed`,{bubbles:!0,composed:!0}))}catch(e){let t=e instanceof Error?e.message:`Failed to create token`;u.show(t,`error`)}}_renderTokenRow(e){return t`
|
|
257
|
+
<div class="data-cell" role="cell">${e.id}</div>
|
|
258
|
+
<div class="data-cell scopes-cell" role="cell">
|
|
259
|
+
${e.scopes.map(e=>t`<ic-tag variant="info">${e}</ic-tag>`)}
|
|
260
|
+
</div>
|
|
261
|
+
<div class="data-cell" role="cell">
|
|
262
|
+
<div class="token-actions">
|
|
263
|
+
<button class="rotate-btn" @click=${()=>this._rotateToken(e.id)}>Rotate</button>
|
|
264
|
+
<button class="revoke-btn" @click=${()=>this._revokeToken(e.id)}>Revoke</button>
|
|
334
265
|
</div>
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
266
|
+
</div>
|
|
267
|
+
`}render(){return t`
|
|
268
|
+
<div class="grid-table grid-table--tokens" role="table" aria-label="API tokens">
|
|
269
|
+
<div class="header-cell" role="columnheader">Token ID</div>
|
|
270
|
+
<div class="header-cell" role="columnheader">Scopes</div>
|
|
271
|
+
<div class="header-cell" role="columnheader">Actions</div>
|
|
272
|
+
${this._tokens.map(e=>this._renderTokenRow(e))}
|
|
273
|
+
</div>
|
|
274
|
+
|
|
275
|
+
${this._newSecretDisplay?t`
|
|
276
|
+
<div class="new-secret-banner">
|
|
277
|
+
<div class="secret-label">New Token Secret</div>
|
|
278
|
+
<div class="secret-value">${this._newSecretDisplay}</div>
|
|
279
|
+
<div class="secret-warning">Copy this secret now. It will not be shown again.</div>
|
|
280
|
+
</div>
|
|
281
|
+
`:l}
|
|
282
|
+
|
|
283
|
+
<div class="create-form">
|
|
284
|
+
<div class="create-form-title">Create Token</div>
|
|
285
|
+
<div class="form-field">
|
|
286
|
+
<label class="form-label">Scopes</label>
|
|
287
|
+
<div class="checkbox-row">
|
|
288
|
+
<input type="checkbox" id="scope-rpc"
|
|
289
|
+
.checked=${this._newTokenScopes.includes(`rpc`)}
|
|
290
|
+
@change=${e=>this._onScopeToggle(`rpc`,e.target.checked)}
|
|
291
|
+
/><label for="scope-rpc">rpc</label>
|
|
292
|
+
</div>
|
|
293
|
+
<div class="checkbox-row">
|
|
294
|
+
<input type="checkbox" id="scope-ws"
|
|
295
|
+
.checked=${this._newTokenScopes.includes(`ws`)}
|
|
296
|
+
@change=${e=>this._onScopeToggle(`ws`,e.target.checked)}
|
|
297
|
+
/><label for="scope-ws">ws</label>
|
|
298
|
+
</div>
|
|
299
|
+
<div class="checkbox-row">
|
|
300
|
+
<input type="checkbox" id="scope-admin"
|
|
301
|
+
.checked=${this._newTokenScopes.includes(`admin`)}
|
|
302
|
+
@change=${e=>this._onScopeToggle(`admin`,e.target.checked)}
|
|
303
|
+
/><label for="scope-admin">admin</label>
|
|
304
|
+
</div>
|
|
305
|
+
<div class="checkbox-row">
|
|
306
|
+
<input type="checkbox" id="scope-api"
|
|
307
|
+
.checked=${this._newTokenScopes.includes(`api`)}
|
|
308
|
+
@change=${e=>this._onScopeToggle(`api`,e.target.checked)}
|
|
309
|
+
/><label for="scope-api">api</label>
|
|
310
|
+
</div>
|
|
311
|
+
<div class="checkbox-row">
|
|
312
|
+
<input type="checkbox" id="scope-all"
|
|
313
|
+
.checked=${this._newTokenScopes.includes(`*`)}
|
|
314
|
+
@change=${e=>this._onScopeToggle(`*`,e.target.checked)}
|
|
315
|
+
/><label for="scope-all">* (all)</label>
|
|
316
|
+
</div>
|
|
352
317
|
</div>
|
|
318
|
+
<button class="generate-btn" @click=${()=>this._generateToken()}>Generate</button>
|
|
353
319
|
</div>
|
|
354
|
-
`}};
|
|
320
|
+
`}};c([s({attribute:!1})],p.prototype,`rpc`,void 0),c([a()],p.prototype,`_tokens`,void 0),c([a()],p.prototype,`_newTokenScopes`,void 0),c([a()],p.prototype,`_newSecretDisplay`,void 0),p=c([e(`ic-token-manager`)],p);var m={low:`success`,medium:`warning`,high:`error`,critical:`error`},h={low:`var(--ic-success)`,medium:`var(--ic-warning)`,high:`var(--ic-error)`,critical:`var(--ic-error)`},g=class extends r{constructor(...e){super(...e),this.approval=null,this._reason=``,this._expanded=!1}static{this.styles=[o,i,n`
|
|
355
321
|
:host {
|
|
356
322
|
display: block;
|
|
357
323
|
width: 100%;
|
|
@@ -483,119 +449,41 @@ import{s as _,f as S,i as w,n as d,r as l,a as x,A as p,b as s,t as $,I as n,S a
|
|
|
483
449
|
.deny-btn:hover {
|
|
484
450
|
background: color-mix(in srgb, var(--ic-error) 25%, transparent);
|
|
485
451
|
}
|
|
486
|
-
`]
|
|
487
|
-
<div
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
<ic-toggle label="Require for destructive actions"
|
|
498
|
-
.checked=${e.requireForDestructive??!0}
|
|
499
|
-
@change=${r=>this._onActionConfirmationChange("requireForDestructive",r.detail)}
|
|
500
|
-
></ic-toggle>
|
|
501
|
-
<div style="margin-top: var(--ic-space-sm);">
|
|
502
|
-
<ic-toggle label="Require for sensitive actions"
|
|
503
|
-
.checked=${e.requireForSensitive??!1}
|
|
504
|
-
@change=${r=>this._onActionConfirmationChange("requireForSensitive",r.detail)}
|
|
505
|
-
></ic-toggle>
|
|
506
|
-
</div>
|
|
507
|
-
<div style="margin-top: var(--ic-space-md);">
|
|
508
|
-
<ic-array-editor label="Auto-approve list" .items=${e.autoApprove??[]} placeholder="Action name to auto-approve"
|
|
509
|
-
@change=${r=>this._onActionConfirmationChange("autoApprove",r.detail)}
|
|
510
|
-
></ic-array-editor>
|
|
511
|
-
</div>
|
|
512
|
-
</div>
|
|
513
|
-
|
|
514
|
-
<div class="policy-section">
|
|
515
|
-
<div class="section-header">Agent-to-Agent Policy</div>
|
|
516
|
-
<ic-toggle label="Enable cross-agent messaging"
|
|
517
|
-
.checked=${t.enabled??!0}
|
|
518
|
-
@change=${r=>this._onAgentToAgentEnabledChange(r.detail)}
|
|
519
|
-
></ic-toggle>
|
|
520
|
-
<div style="margin-top: var(--ic-space-md);">
|
|
521
|
-
<ic-array-editor label="Allowed agents" .items=${t.allowAgents??[]} placeholder="Agent ID"
|
|
522
|
-
@change=${r=>this._onAgentToAgentAllowChange(r.detail)}
|
|
523
|
-
></ic-array-editor>
|
|
524
|
-
</div>
|
|
525
|
-
</div>
|
|
526
|
-
|
|
527
|
-
<div class="policy-section">
|
|
528
|
-
<div class="section-header">Permissions</div>
|
|
529
|
-
<ic-toggle label="Enable Node.js permission model"
|
|
530
|
-
.checked=${i.enableNodePermissions??!1}
|
|
531
|
-
@change=${r=>this._onPermissionToggleChange(r.detail)}
|
|
532
|
-
></ic-toggle>
|
|
533
|
-
<div style="margin-top: var(--ic-space-md);">
|
|
534
|
-
<ic-array-editor label="Allowed filesystem paths" .items=${i.allowedFsPaths??[]} placeholder="/path/to/allow"
|
|
535
|
-
@change=${r=>this._onPermissionPathsChange("allowedFsPaths",r.detail)}
|
|
536
|
-
></ic-array-editor>
|
|
452
|
+
`]}_onApprove(){this.approval&&this.dispatchEvent(new CustomEvent(`approve`,{detail:{id:this.approval.id,reason:this._reason},bubbles:!0,composed:!0}))}_onDeny(){this.approval&&this.dispatchEvent(new CustomEvent(`deny`,{detail:{id:this.approval.id,reason:this._reason},bubbles:!0,composed:!0}))}render(){if(!this.approval)return l;let e=this.approval,n=m[e.classification]??`default`,r=h[e.classification]??`var(--ic-border)`;return t`
|
|
453
|
+
<div
|
|
454
|
+
class="card"
|
|
455
|
+
role="article"
|
|
456
|
+
aria-label="${e.agentId} ${e.action} approval request"
|
|
457
|
+
style="border-left-color: ${r};"
|
|
458
|
+
>
|
|
459
|
+
<div class="card-header">
|
|
460
|
+
<span class="agent-id">${e.agentId}</span>
|
|
461
|
+
<span class="action-name">${e.action}</span>
|
|
462
|
+
<ic-tag variant=${n}>${e.classification}</ic-tag>
|
|
537
463
|
</div>
|
|
538
|
-
<div
|
|
539
|
-
<ic-
|
|
540
|
-
@change=${r=>this._onPermissionPathsChange("allowedNetHosts",r.detail)}
|
|
541
|
-
></ic-array-editor>
|
|
464
|
+
<div class="timestamp">
|
|
465
|
+
<ic-relative-time .timestamp=${e.requestedAt}></ic-relative-time>
|
|
542
466
|
</div>
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
</
|
|
559
|
-
<button class="
|
|
467
|
+
${e.user?t`<div class="user-row"><span class="user-label">Requested by:</span> ${e.user}</div>`:l}
|
|
468
|
+
<button
|
|
469
|
+
class="context-toggle"
|
|
470
|
+
@click=${()=>{this._expanded=!this._expanded}}
|
|
471
|
+
>${this._expanded?`Hide details`:`Show details`}</button>
|
|
472
|
+
${this._expanded?t`<div class="context-details">${e.context}</div>`:l}
|
|
473
|
+
<input
|
|
474
|
+
class="reason-input"
|
|
475
|
+
type="text"
|
|
476
|
+
placeholder="Reason (optional)"
|
|
477
|
+
aria-label="Decision reason"
|
|
478
|
+
.value=${this._reason}
|
|
479
|
+
@input=${e=>{this._reason=e.target.value}}
|
|
480
|
+
/>
|
|
481
|
+
<div class="action-buttons">
|
|
482
|
+
<button class="approve-btn" @click=${()=>this._onApprove()}>Approve</button>
|
|
483
|
+
<button class="deny-btn" @click=${()=>this._onDeny()}>Deny</button>
|
|
560
484
|
</div>
|
|
561
485
|
</div>
|
|
562
|
-
`}
|
|
563
|
-
<div class="queue-header">
|
|
564
|
-
<span>Pending</span>
|
|
565
|
-
<span class="queue-count">${this._pendingApprovals.length}</span>
|
|
566
|
-
</div>
|
|
567
|
-
<div class="bulk-actions">
|
|
568
|
-
<button class="action-btn action-btn--success" ?disabled=${this._pendingApprovals.length===0}
|
|
569
|
-
@click=${()=>this._handleResolveAll(!0)}>Approve All (${this._pendingApprovals.length})</button>
|
|
570
|
-
<button class="action-btn action-btn--danger" ?disabled=${this._pendingApprovals.length===0}
|
|
571
|
-
@click=${()=>this._handleResolveAll(!1)}>Deny All (${this._pendingApprovals.length})</button>
|
|
572
|
-
<button class="action-btn" @click=${()=>this._handleClearDenialCache()}>Clear Denial Cache</button>
|
|
573
|
-
</div>
|
|
574
|
-
${e.length===0?s`<ic-empty-state icon="security" message="No pending approvals" description="Approval requests will appear here as they arrive."></ic-empty-state>`:s`
|
|
575
|
-
<div class="queue-list">
|
|
576
|
-
${e.map(t=>s`
|
|
577
|
-
<ic-approval-card .approval=${t}
|
|
578
|
-
@approve=${i=>this._handleApprove(i)}
|
|
579
|
-
@deny=${i=>this._handleDeny(i)}
|
|
580
|
-
></ic-approval-card>
|
|
581
|
-
`)}
|
|
582
|
-
</div>
|
|
583
|
-
`}
|
|
584
|
-
|
|
585
|
-
<div class="history-divider">Recent History</div>
|
|
586
|
-
${this._resolvedApprovals.length===0?s`<p style="font-size: var(--ic-text-sm); color: var(--ic-text-dim); font-style: italic;">No resolved approvals in the last 7 days.</p>`:s`
|
|
587
|
-
<div class="history-grid" role="table" aria-label="Resolved approvals">
|
|
588
|
-
<div class="header-cell" role="columnheader">Agent</div>
|
|
589
|
-
<div class="header-cell" role="columnheader">Action</div>
|
|
590
|
-
<div class="header-cell" role="columnheader">Risk</div>
|
|
591
|
-
<div class="header-cell" role="columnheader">Outcome</div>
|
|
592
|
-
<div class="header-cell" role="columnheader">Reason</div>
|
|
593
|
-
<div class="header-cell" role="columnheader">Resolved At</div>
|
|
594
|
-
<div class="header-cell" role="columnheader">Resolved By</div>
|
|
595
|
-
${this._resolvedApprovals.map(t=>this._renderHistoryRow(t))}
|
|
596
|
-
</div>
|
|
597
|
-
`}
|
|
598
|
-
`}render(){return this.activeSubTab==="rules"?this._renderRulesContent():this._renderPendingContent()}};m.styles=[_,S,w`
|
|
486
|
+
`}};c([s({type:Object})],g.prototype,`approval`,void 0),c([a()],g.prototype,`_reason`,void 0),c([a()],g.prototype,`_expanded`,void 0),g=c([e(`ic-approval-card`)],g);function _(e){return{id:e.requestId,agentId:e.agentId,action:e.action||e.toolName,classification:e.trustLevel===`admin`?`low`:e.trustLevel===`user`?`medium`:`high`,context:JSON.stringify(e.params,null,2),requestedAt:e.createdAt}}var v=`ic:approval-history`,y=10080*60*1e3;function b(){try{let e=localStorage.getItem(v);if(!e)return[];let t=JSON.parse(e),n=Date.now()-y;return t.filter(e=>e.resolvedAt>n)}catch{return[]}}function x(e){try{let t=Date.now()-y,n=e.filter(e=>e.resolvedAt>t);localStorage.setItem(v,JSON.stringify(n))}catch{}}var S=class extends r{constructor(...e){super(...e),this.securityConfig={},this.activeSubTab=`pending`,this._pendingApprovals=[],this._resolvedApprovals=[],this._approvalRules={defaultMode:`manual`,timeoutMs:0}}static{this.styles=[o,i,n`
|
|
599
487
|
:host {
|
|
600
488
|
display: block;
|
|
601
489
|
}
|
|
@@ -772,24 +660,119 @@ import{s as _,f as S,i as w,n as d,r as l,a as x,A as p,b as s,t as $,I as n,S a
|
|
|
772
660
|
opacity: 0.5;
|
|
773
661
|
cursor: not-allowed;
|
|
774
662
|
}
|
|
775
|
-
`]
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
<div class="cell cell--muted" role="cell">
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
663
|
+
`]}connectedCallback(){super.connectedCallback(),this._resolvedApprovals=b()}updated(e){e.has(`rpc`)&&this.rpc&&this._loadApprovals(),e.has(`securityConfig`)&&(this._approvalRules=this.securityConfig.approvalRules??{defaultMode:`manual`,timeoutMs:0})}async _loadApprovals(){if(this.rpc)try{let e=await this.rpc.call(`admin.approval.pending`);this._pendingApprovals=(e.requests??[]).map(_)}catch{}}onApprovalPending(e){let t=e;t?.requestId&&(this._pendingApprovals=[_(t),...this._pendingApprovals])}onApprovalResolved(e){let t=e,n=t?.requestId;if(!n)return;this._pendingApprovals=this._pendingApprovals.filter(e=>e.id!==n);let r={..._(t),outcome:t.approved?`approved`:`denied`,reason:t.reason??``,resolvedAt:t.resolvedAt??Date.now(),resolvedBy:t.approvedBy??`system`};this._resolvedApprovals=[r,...this._resolvedApprovals],x(this._resolvedApprovals)}async _handleApprove(e){if(!this.rpc)return;let{id:t,reason:n}=e.detail;try{await this.rpc.call(`admin.approval.resolve`,{requestId:t,approved:!0,approvedBy:`operator`,reason:n});let e=this._pendingApprovals.find(e=>e.id===t);if(this._pendingApprovals=this._pendingApprovals.filter(e=>e.id!==t),e){let t={...e,outcome:`approved`,reason:n,resolvedAt:Date.now(),resolvedBy:`operator`};this._resolvedApprovals=[t,...this._resolvedApprovals],x(this._resolvedApprovals)}u.show(`Approval granted`,`success`),this.dispatchEvent(new CustomEvent(`approvals-changed`,{bubbles:!0,composed:!0}))}catch(e){u.show(e instanceof Error?e.message:`Failed to approve request`,`error`)}}async _handleDeny(e){if(!this.rpc)return;let{id:t,reason:n}=e.detail;try{await this.rpc.call(`admin.approval.resolve`,{requestId:t,approved:!1,approvedBy:`operator`,reason:n});let e=this._pendingApprovals.find(e=>e.id===t);if(this._pendingApprovals=this._pendingApprovals.filter(e=>e.id!==t),e){let t={...e,outcome:`denied`,reason:n,resolvedAt:Date.now(),resolvedBy:`operator`};this._resolvedApprovals=[t,...this._resolvedApprovals],x(this._resolvedApprovals)}u.show(`Approval denied`,`success`),this.dispatchEvent(new CustomEvent(`approvals-changed`,{bubbles:!0,composed:!0}))}catch(e){u.show(e instanceof Error?e.message:`Failed to deny request`,`error`)}}async _handleResolveAll(e){if(!(!this.rpc||this._pendingApprovals.length===0))try{let t=await this.rpc.call(`admin.approval.resolveAll`,{approved:e,approvedBy:`operator`,reason:e?`Bulk approved by operator`:`Bulk denied by operator`});for(let t of this._pendingApprovals){let n={...t,outcome:e?`approved`:`denied`,reason:e?`Bulk approved by operator`:`Bulk denied by operator`,resolvedAt:Date.now(),resolvedBy:`operator`};this._resolvedApprovals=[n,...this._resolvedApprovals]}this._pendingApprovals=[],x(this._resolvedApprovals),u.show(`${t.resolved} approval(s) ${e?`approved`:`denied`}`,`success`),this.dispatchEvent(new CustomEvent(`approvals-changed`,{bubbles:!0,composed:!0}))}catch(e){u.show(e instanceof Error?e.message:`Bulk operation failed`,`error`)}}async _handleClearDenialCache(){if(this.rpc)try{await this.rpc.call(`admin.approval.clearDenialCache`,{}),u.show(`Denial cache cleared`,`success`)}catch(e){u.show(e instanceof Error?e.message:`Failed to clear denial cache`,`error`)}}async _patchConfig(e,t){if(!this.rpc)return!1;try{let n=e.indexOf(`.`),r=n>0?e.slice(0,n):e,i=n>0?e.slice(n+1):void 0;return await this.rpc.call(`config.patch`,{section:r,key:i,value:t}),u.show(`Configuration updated`,`success`),!0}catch(e){return u.show(e instanceof Error?e.message:`Failed to update configuration`,`error`),!1}}async _onActionConfirmationChange(e,t){let n={...this.securityConfig.actionConfirmation,[e]:t};await this._patchConfig(`security.actionConfirmation`,n)}async _onAgentToAgentEnabledChange(e){let t={...this.securityConfig.agentToAgent,enabled:e};await this._patchConfig(`security.agentToAgent`,t)}async _onAgentToAgentAllowChange(e){let t={...this.securityConfig.agentToAgent,allowAgents:e};await this._patchConfig(`security.agentToAgent`,t)}async _onPermissionToggleChange(e){let t={...this.securityConfig.permission,enableNodePermissions:e};await this._patchConfig(`security.permission`,t)}async _onPermissionPathsChange(e,t){let n={...this.securityConfig.permission,[e]:t};await this._patchConfig(`security.permission`,n)}async _saveApprovalRules(){if(this.rpc)try{await this.rpc.call(`config.patch`,{section:`security`,key:`approvalRules`,value:this._approvalRules}),u.show(`Approval rules updated`,`success`)}catch(e){u.show(e instanceof Error?e.message:`Failed to update approval rules`,`error`)}}_renderHistoryRow(e){let n=e.outcome===`approved`?`success`:`error`,r={low:`success`,medium:`warning`,high:`error`,critical:`error`}[e.classification]??`default`;return t`
|
|
664
|
+
<div class="data-cell" role="cell">${e.agentId}</div>
|
|
665
|
+
<div class="data-cell" role="cell">${e.action}</div>
|
|
666
|
+
<div class="data-cell" role="cell"><ic-tag variant=${r}>${e.classification}</ic-tag></div>
|
|
667
|
+
<div class="data-cell" role="cell"><ic-tag variant=${n}>${e.outcome}</ic-tag></div>
|
|
668
|
+
<div class="data-cell data-cell--muted" role="cell">${e.reason||`---`}</div>
|
|
669
|
+
<div class="data-cell data-cell--muted" role="cell"><ic-relative-time .timestamp=${e.resolvedAt}></ic-relative-time></div>
|
|
670
|
+
<div class="data-cell data-cell--muted" role="cell">${e.resolvedBy}</div>
|
|
671
|
+
`}_renderRulesContent(){let e=this.securityConfig.actionConfirmation??{},n=this.securityConfig.agentToAgent??{},r=this.securityConfig.permission??{};return t`
|
|
672
|
+
<div class="policy-section">
|
|
673
|
+
<div class="section-header">Action Confirmation</div>
|
|
674
|
+
<ic-toggle label="Require for destructive actions"
|
|
675
|
+
.checked=${e.requireForDestructive??!0}
|
|
676
|
+
@change=${e=>this._onActionConfirmationChange(`requireForDestructive`,e.detail)}
|
|
677
|
+
></ic-toggle>
|
|
678
|
+
<div style="margin-top: var(--ic-space-sm);">
|
|
679
|
+
<ic-toggle label="Require for sensitive actions"
|
|
680
|
+
.checked=${e.requireForSensitive??!1}
|
|
681
|
+
@change=${e=>this._onActionConfirmationChange(`requireForSensitive`,e.detail)}
|
|
682
|
+
></ic-toggle>
|
|
683
|
+
</div>
|
|
684
|
+
<div style="margin-top: var(--ic-space-md);">
|
|
685
|
+
<ic-array-editor label="Auto-approve list" .items=${e.autoApprove??[]} placeholder="Action name to auto-approve"
|
|
686
|
+
@change=${e=>this._onActionConfirmationChange(`autoApprove`,e.detail)}
|
|
687
|
+
></ic-array-editor>
|
|
688
|
+
</div>
|
|
689
|
+
</div>
|
|
690
|
+
|
|
691
|
+
<div class="policy-section">
|
|
692
|
+
<div class="section-header">Agent-to-Agent Policy</div>
|
|
693
|
+
<ic-toggle label="Enable cross-agent messaging"
|
|
694
|
+
.checked=${n.enabled??!0}
|
|
695
|
+
@change=${e=>this._onAgentToAgentEnabledChange(e.detail)}
|
|
696
|
+
></ic-toggle>
|
|
697
|
+
<div style="margin-top: var(--ic-space-md);">
|
|
698
|
+
<ic-array-editor label="Allowed agents" .items=${n.allowAgents??[]} placeholder="Agent ID"
|
|
699
|
+
@change=${e=>this._onAgentToAgentAllowChange(e.detail)}
|
|
700
|
+
></ic-array-editor>
|
|
701
|
+
</div>
|
|
702
|
+
</div>
|
|
703
|
+
|
|
704
|
+
<div class="policy-section">
|
|
705
|
+
<div class="section-header">Permissions</div>
|
|
706
|
+
<ic-toggle label="Enable Node.js permission model"
|
|
707
|
+
.checked=${r.enableNodePermissions??!1}
|
|
708
|
+
@change=${e=>this._onPermissionToggleChange(e.detail)}
|
|
709
|
+
></ic-toggle>
|
|
710
|
+
<div style="margin-top: var(--ic-space-md);">
|
|
711
|
+
<ic-array-editor label="Allowed filesystem paths" .items=${r.allowedFsPaths??[]} placeholder="/path/to/allow"
|
|
712
|
+
@change=${e=>this._onPermissionPathsChange(`allowedFsPaths`,e.detail)}
|
|
713
|
+
></ic-array-editor>
|
|
714
|
+
</div>
|
|
715
|
+
<div style="margin-top: var(--ic-space-md);">
|
|
716
|
+
<ic-array-editor label="Allowed network hosts" .items=${r.allowedNetHosts??[]} placeholder="hostname or IP"
|
|
717
|
+
@change=${e=>this._onPermissionPathsChange(`allowedNetHosts`,e.detail)}
|
|
718
|
+
></ic-array-editor>
|
|
719
|
+
</div>
|
|
720
|
+
</div>
|
|
721
|
+
|
|
722
|
+
<div class="policy-section">
|
|
723
|
+
<div class="section-header">Approval Mode</div>
|
|
724
|
+
<div class="rules-form">
|
|
725
|
+
<ic-select label="Default Mode" .value=${this._approvalRules.defaultMode} .options=${[{value:`manual`,label:`Manual (all require approval)`},{value:`auto-low`,label:`Auto-approve low risk`},{value:`auto-medium`,label:`Auto-approve low + medium risk`},{value:`auto-all`,label:`Auto-approve all (no approvals)`}]}
|
|
726
|
+
@change=${e=>{this._approvalRules={...this._approvalRules,defaultMode:e.detail}}}
|
|
727
|
+
></ic-select>
|
|
728
|
+
<div class="form-field">
|
|
729
|
+
<label class="form-label">Timeout (seconds)</label>
|
|
730
|
+
<input class="number-input" type="number" min="0"
|
|
731
|
+
.value=${String(Math.round(this._approvalRules.timeoutMs/1e3))}
|
|
732
|
+
@change=${e=>{let t=parseInt(e.target.value,10);!isNaN(t)&&t>=0&&(this._approvalRules={...this._approvalRules,timeoutMs:t*1e3})}}
|
|
733
|
+
/>
|
|
734
|
+
<span class="form-hint">0 = no timeout (request waits indefinitely)</span>
|
|
735
|
+
</div>
|
|
736
|
+
<button class="save-btn" @click=${()=>this._saveApprovalRules()}>Save Rules</button>
|
|
737
|
+
</div>
|
|
789
738
|
</div>
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
739
|
+
`}_renderPendingContent(){let e=[...this._pendingApprovals].sort((e,t)=>t.requestedAt-e.requestedAt);return t`
|
|
740
|
+
<div class="queue-header">
|
|
741
|
+
<span>Pending</span>
|
|
742
|
+
<span class="queue-count">${this._pendingApprovals.length}</span>
|
|
743
|
+
</div>
|
|
744
|
+
<div class="bulk-actions">
|
|
745
|
+
<button class="action-btn action-btn--success" ?disabled=${this._pendingApprovals.length===0}
|
|
746
|
+
@click=${()=>this._handleResolveAll(!0)}>Approve All (${this._pendingApprovals.length})</button>
|
|
747
|
+
<button class="action-btn action-btn--danger" ?disabled=${this._pendingApprovals.length===0}
|
|
748
|
+
@click=${()=>this._handleResolveAll(!1)}>Deny All (${this._pendingApprovals.length})</button>
|
|
749
|
+
<button class="action-btn" @click=${()=>this._handleClearDenialCache()}>Clear Denial Cache</button>
|
|
750
|
+
</div>
|
|
751
|
+
${e.length===0?t`<ic-empty-state icon="security" message="No pending approvals" description="Approval requests will appear here as they arrive."></ic-empty-state>`:t`
|
|
752
|
+
<div class="queue-list">
|
|
753
|
+
${e.map(e=>t`
|
|
754
|
+
<ic-approval-card .approval=${e}
|
|
755
|
+
@approve=${e=>this._handleApprove(e)}
|
|
756
|
+
@deny=${e=>this._handleDeny(e)}
|
|
757
|
+
></ic-approval-card>
|
|
758
|
+
`)}
|
|
759
|
+
</div>
|
|
760
|
+
`}
|
|
761
|
+
|
|
762
|
+
<div class="history-divider">Recent History</div>
|
|
763
|
+
${this._resolvedApprovals.length===0?t`<p style="font-size: var(--ic-text-sm); color: var(--ic-text-dim); font-style: italic;">No resolved approvals in the last 7 days.</p>`:t`
|
|
764
|
+
<div class="history-grid" role="table" aria-label="Resolved approvals">
|
|
765
|
+
<div class="header-cell" role="columnheader">Agent</div>
|
|
766
|
+
<div class="header-cell" role="columnheader">Action</div>
|
|
767
|
+
<div class="header-cell" role="columnheader">Risk</div>
|
|
768
|
+
<div class="header-cell" role="columnheader">Outcome</div>
|
|
769
|
+
<div class="header-cell" role="columnheader">Reason</div>
|
|
770
|
+
<div class="header-cell" role="columnheader">Resolved At</div>
|
|
771
|
+
<div class="header-cell" role="columnheader">Resolved By</div>
|
|
772
|
+
${this._resolvedApprovals.map(e=>this._renderHistoryRow(e))}
|
|
773
|
+
</div>
|
|
774
|
+
`}
|
|
775
|
+
`}render(){return this.activeSubTab===`rules`?this._renderRulesContent():this._renderPendingContent()}};c([s({attribute:!1})],S.prototype,`rpc`,void 0),c([s({attribute:!1})],S.prototype,`securityConfig`,void 0),c([s({type:String})],S.prototype,`activeSubTab`,void 0),c([a()],S.prototype,`_pendingApprovals`,void 0),c([a()],S.prototype,`_resolvedApprovals`,void 0),c([a()],S.prototype,`_approvalRules`,void 0),S=c([e(`ic-approval-queue`)],S);var C={low:`success`,medium:`warning`,high:`error`,critical:`error`},w=class extends r{constructor(...e){super(...e),this.event=null}static{this.styles=[o,n`
|
|
793
776
|
:host {
|
|
794
777
|
display: contents;
|
|
795
778
|
}
|
|
@@ -812,47 +795,24 @@ import{s as _,f as S,i as w,n as d,r as l,a as x,A as p,b as s,t as $,I as n,S a
|
|
|
812
795
|
color: var(--ic-text-dim);
|
|
813
796
|
font-size: var(--ic-text-xs);
|
|
814
797
|
}
|
|
815
|
-
`]
|
|
816
|
-
|
|
817
|
-
<
|
|
818
|
-
<
|
|
819
|
-
|
|
798
|
+
`]}render(){if(!this.event)return t`
|
|
799
|
+
<div class="cell cell--muted" role="cell">---</div>
|
|
800
|
+
<div class="cell cell--muted" role="cell">---</div>
|
|
801
|
+
<div class="cell cell--muted" role="cell">---</div>
|
|
802
|
+
<div class="cell cell--muted" role="cell">---</div>
|
|
803
|
+
<div class="cell cell--muted" role="cell">---</div>
|
|
804
|
+
`;let e=this.event,n=C[e.classification]??`default`;return t`
|
|
805
|
+
<div class="cell cell--muted" role="cell">
|
|
806
|
+
<ic-relative-time .timestamp=${e.timestamp}></ic-relative-time>
|
|
820
807
|
</div>
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
<ic-tag variant=${this._severityVariant(e.severity)}>${e.severity}</ic-tag>
|
|
826
|
-
<ic-tag variant="default">${e.type}</ic-tag>
|
|
827
|
-
<span class="event-message">${e.message}</span>
|
|
828
|
-
${e.agentId?s`<ic-tag variant="info">${e.agentId}</ic-tag>`:p}
|
|
829
|
-
<ic-relative-time .timestamp=${e.timestamp}></ic-relative-time>
|
|
830
|
-
<button class="event-details-toggle"
|
|
831
|
-
@click=${()=>this._toggleEventDetails(e.id)}
|
|
832
|
-
>${this._expandedEvents.has(e.id)?"hide":"details"}</button>
|
|
833
|
-
</div>
|
|
834
|
-
${this._expandedEvents.has(e.id)?s`<pre class="event-details">${JSON.stringify(e.details,null,2)}</pre>`:p}
|
|
835
|
-
`)}
|
|
836
|
-
</div>
|
|
837
|
-
`}
|
|
838
|
-
`}_renderAuditContent(){return s`
|
|
839
|
-
<div class="audit-controls">
|
|
840
|
-
<button class="pause-btn" ?data-active=${this._paused}
|
|
841
|
-
@click=${()=>this._togglePause()}
|
|
842
|
-
>${this._paused?"Resume":"Pause"}</button>
|
|
843
|
-
${this._paused?s`<span style="font-size: var(--ic-text-xs); color: var(--ic-text-dim);">${this._pauseBuffer.length} buffered</span>`:p}
|
|
808
|
+
<div class="cell" role="cell">${e.agentId||`---`}</div>
|
|
809
|
+
<div class="cell" role="cell">${e.action||`---`}</div>
|
|
810
|
+
<div class="cell" role="cell">
|
|
811
|
+
<ic-tag variant=${n}>${e.classification||`unknown`}</ic-tag>
|
|
844
812
|
</div>
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
<div class="header-cell" role="columnheader">Agent</div>
|
|
849
|
-
<div class="header-cell" role="columnheader">Action</div>
|
|
850
|
-
<div class="header-cell" role="columnheader">Risk</div>
|
|
851
|
-
<div class="header-cell" role="columnheader">User</div>
|
|
852
|
-
${this._auditEntries.map(e=>s`<ic-audit-row .event=${e} role="row"></ic-audit-row>`)}
|
|
853
|
-
</div>
|
|
854
|
-
`}
|
|
855
|
-
`}render(){return this.activeSubTab==="audit"?this._renderAuditContent():this._renderEventsContent()}};f.styles=[_,S,w`
|
|
813
|
+
<div class="cell cell--muted" role="cell">${e.user||`---`}</div>
|
|
814
|
+
${e.details?t`<div class="cell cell--details" role="cell" style="grid-column: 1 / -1;">${e.details}</div>`:l}
|
|
815
|
+
`}};c([s({type:Object})],w.prototype,`event`,void 0),w=c([e(`ic-audit-row`)],w);var T=200,E=class extends r{constructor(...e){super(...e),this.activeSubTab=`events`,this.securityEvents=[],this.inputGuardSummary={blockedAttempts:0,patternsTriggered:[],period:`session`},this._auditEntries=[],this._paused=!1,this._pauseBuffer=[],this._expandedEvents=new Set}static{this.styles=[o,i,n`
|
|
856
816
|
:host {
|
|
857
817
|
display: block;
|
|
858
818
|
}
|
|
@@ -951,120 +911,47 @@ import{s as _,f as S,i as w,n as d,r as l,a as x,A as p,b as s,t as $,I as n,S a
|
|
|
951
911
|
top: 0;
|
|
952
912
|
z-index: 1;
|
|
953
913
|
}
|
|
954
|
-
`]
|
|
955
|
-
<div class="
|
|
956
|
-
<
|
|
957
|
-
<ic-
|
|
958
|
-
|
|
959
|
-
.checked=${e.enabled??!1}
|
|
960
|
-
@change=${t=>this._onSecretsEnabledChange(t.detail)}
|
|
961
|
-
></ic-toggle>
|
|
962
|
-
<div style="margin-top: var(--ic-space-md);">
|
|
963
|
-
<div class="tls-row">
|
|
964
|
-
<span class="tls-label">DB Path</span>
|
|
965
|
-
<span class="tls-value">${e.dbPath??"secrets.db"}</span>
|
|
966
|
-
</div>
|
|
967
|
-
</div>
|
|
914
|
+
`]}onAuditEvent(e){let t=e;if(t){if(this._paused){this._pauseBuffer=[...this._pauseBuffer.slice(-(T-1)),t];return}this._auditEntries=[...this._auditEntries.slice(-(T-1)),t]}}get auditEntries(){return this._auditEntries}get paused(){return this._paused}get pauseBuffer(){return this._pauseBuffer}_severityVariant(e){switch(e){case`critical`:case`high`:return`error`;case`medium`:return`warning`;default:return`info`}}_toggleEventDetails(e){this._expandedEvents.has(e)?this._expandedEvents.delete(e):this._expandedEvents.add(e),this.requestUpdate()}_togglePause(){if(this._paused){let e=[...this._auditEntries,...this._pauseBuffer].slice(-T);this._auditEntries=e,this._pauseBuffer=[]}this._paused=!this._paused}_renderEventsContent(){return t`
|
|
915
|
+
<div class="guard-summary">
|
|
916
|
+
<span style="font-size: var(--ic-text-sm); font-weight: 500; color: var(--ic-text-muted);">Input Guard</span>
|
|
917
|
+
<ic-tag variant="error">${this.inputGuardSummary.blockedAttempts} blocked</ic-tag>
|
|
918
|
+
${this.inputGuardSummary.patternsTriggered.length>0?t`<ic-tag variant="warning">${this.inputGuardSummary.patternsTriggered.join(`, `)}</ic-tag>`:l}
|
|
968
919
|
</div>
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
<
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
</div>
|
|
982
|
-
<ic-progress-bar
|
|
983
|
-
.value=${Math.round(i.cacheHitRate*100)}
|
|
984
|
-
label="Cache Hit Rate"
|
|
985
|
-
.thresholds=${{green:101,yellow:102}}
|
|
986
|
-
></ic-progress-bar>
|
|
987
|
-
<div class="health-card-stat">
|
|
988
|
-
Failovers: ${i.failoverCount}
|
|
989
|
-
${i.lastFailover?s` — last <ic-relative-time .timestamp=${i.lastFailover}></ic-relative-time>`:p}
|
|
990
|
-
</div>
|
|
991
|
-
${i.authCooldownUntil&&i.authCooldownUntil>e?s`
|
|
992
|
-
<div class="health-card-stat">
|
|
993
|
-
<ic-tag variant="warning">Auth cooldown</ic-tag>
|
|
994
|
-
${Math.ceil((i.authCooldownUntil-e)/1e3)}s remaining
|
|
995
|
-
</div>
|
|
996
|
-
`:p}
|
|
997
|
-
</div>
|
|
998
|
-
`)}
|
|
999
|
-
</div>
|
|
1000
|
-
`}
|
|
1001
|
-
|
|
1002
|
-
<div class="section-header" style="margin-top: var(--ic-space-xl);">Failover Event Log</div>
|
|
1003
|
-
${this._failoverLog.length===0?s`<p style="font-size: var(--ic-text-sm); color: var(--ic-text-dim); font-style: italic;">No failover events recorded</p>`:s`
|
|
1004
|
-
<div class="failover-log">
|
|
1005
|
-
${this._failoverLog.map(i=>s`
|
|
1006
|
-
<div class="failover-entry">
|
|
1007
|
-
<ic-relative-time .timestamp=${i.timestamp}></ic-relative-time>
|
|
1008
|
-
${i.exhausted?s`
|
|
1009
|
-
<span>${i.provider??"unknown"} exhausted after ${i.totalAttempts??"?"} attempts</span>
|
|
1010
|
-
<ic-tag variant="error">EXHAUSTED</ic-tag>
|
|
1011
|
-
`:s`
|
|
1012
|
-
<span>${i.fromProvider??"?"}/${i.fromModel??"?"} → ${i.toProvider??"?"}/${i.toModel??"?"}</span>
|
|
1013
|
-
${i.attemptNumber!=null?s`<ic-tag variant="info">#${i.attemptNumber}</ic-tag>`:p}
|
|
1014
|
-
${i.error?s`<span style="color: var(--ic-text-dim);">${i.error}</span>`:p}
|
|
1015
|
-
`}
|
|
920
|
+
${this.securityEvents.length===0?t`<ic-empty-state icon="security" message="No security events" description="Security events will appear here in real-time as they are detected."></ic-empty-state>`:t`
|
|
921
|
+
<div role="list" aria-label="Security events">
|
|
922
|
+
${this.securityEvents.map(e=>t`
|
|
923
|
+
<div class="event-row" role="listitem">
|
|
924
|
+
<ic-tag variant=${this._severityVariant(e.severity)}>${e.severity}</ic-tag>
|
|
925
|
+
<ic-tag variant="default">${e.type}</ic-tag>
|
|
926
|
+
<span class="event-message">${e.message}</span>
|
|
927
|
+
${e.agentId?t`<ic-tag variant="info">${e.agentId}</ic-tag>`:l}
|
|
928
|
+
<ic-relative-time .timestamp=${e.timestamp}></ic-relative-time>
|
|
929
|
+
<button class="event-details-toggle"
|
|
930
|
+
@click=${()=>this._toggleEventDetails(e.id)}
|
|
931
|
+
>${this._expandedEvents.has(e.id)?`hide`:`details`}</button>
|
|
1016
932
|
</div>
|
|
933
|
+
${this._expandedEvents.has(e.id)?t`<pre class="event-details">${JSON.stringify(e.details,null,2)}</pre>`:l}
|
|
1017
934
|
`)}
|
|
1018
935
|
</div>
|
|
1019
936
|
`}
|
|
1020
|
-
|
|
1021
|
-
<div class="
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
937
|
+
`}_renderAuditContent(){return t`
|
|
938
|
+
<div class="audit-controls">
|
|
939
|
+
<button class="pause-btn" ?data-active=${this._paused}
|
|
940
|
+
@click=${()=>this._togglePause()}
|
|
941
|
+
>${this._paused?`Resume`:`Pause`}</button>
|
|
942
|
+
${this._paused?t`<span style="font-size: var(--ic-text-xs); color: var(--ic-text-dim);">${this._pauseBuffer.length} buffered</span>`:l}
|
|
943
|
+
</div>
|
|
944
|
+
${this._auditEntries.length===0?t`<ic-empty-state icon="security" message="No audit events" description="Events will appear here as they occur."></ic-empty-state>`:t`
|
|
945
|
+
<div class="audit-grid" role="table" aria-label="Audit log">
|
|
946
|
+
<div class="header-cell" role="columnheader">Time</div>
|
|
947
|
+
<div class="header-cell" role="columnheader">Agent</div>
|
|
948
|
+
<div class="header-cell" role="columnheader">Action</div>
|
|
949
|
+
<div class="header-cell" role="columnheader">Risk</div>
|
|
950
|
+
<div class="header-cell" role="columnheader">User</div>
|
|
951
|
+
${this._auditEntries.map(e=>t`<ic-audit-row .event=${e} role="row"></ic-audit-row>`)}
|
|
1032
952
|
</div>
|
|
1033
953
|
`}
|
|
1034
|
-
`}
|
|
1035
|
-
activeSubTab="events"
|
|
1036
|
-
.securityEvents=${this._securityEvents}
|
|
1037
|
-
.inputGuardSummary=${this._inputGuardSummary}
|
|
1038
|
-
></ic-security-event-feed>`;case"audit":return s`<ic-security-event-feed
|
|
1039
|
-
activeSubTab="audit"
|
|
1040
|
-
.securityEvents=${this._securityEvents}
|
|
1041
|
-
.inputGuardSummary=${this._inputGuardSummary}
|
|
1042
|
-
></ic-security-event-feed>`;case"tokens":return s`<ic-token-manager .rpc=${this.rpcClient}></ic-token-manager>`;case"secrets":return this._renderSecretsTab();case"rules":return s`<ic-approval-queue
|
|
1043
|
-
activeSubTab="rules"
|
|
1044
|
-
.rpc=${this.rpcClient}
|
|
1045
|
-
.securityConfig=${this._securityConfig}
|
|
1046
|
-
></ic-approval-queue>`;case"pending":return s`<ic-approval-queue
|
|
1047
|
-
activeSubTab="pending"
|
|
1048
|
-
.rpc=${this.rpcClient}
|
|
1049
|
-
.securityConfig=${this._securityConfig}
|
|
1050
|
-
></ic-approval-queue>`;case"health":return this._renderHealthTab();default:return p}}render(){return this._loadState==="loading"?s`<ic-skeleton-view variant="list"></ic-skeleton-view>`:this._loadState==="error"?s`
|
|
1051
|
-
<div class="error-container">
|
|
1052
|
-
<span class="error-message">${this._error}</span>
|
|
1053
|
-
<button class="retry-btn" @click=${()=>this._loadData()}>Retry</button>
|
|
1054
|
-
</div>
|
|
1055
|
-
`:s`
|
|
1056
|
-
<div class="view-header">
|
|
1057
|
-
<div class="view-title">Security</div>
|
|
1058
|
-
</div>
|
|
1059
|
-
<ic-tabs
|
|
1060
|
-
.tabs=${se}
|
|
1061
|
-
.activeTab=${this._activeTab}
|
|
1062
|
-
@tab-change=${e=>{this._activeTab=e.detail}}
|
|
1063
|
-
></ic-tabs>
|
|
1064
|
-
<div class="tab-content">
|
|
1065
|
-
${this._renderTabContent()}
|
|
1066
|
-
</div>
|
|
1067
|
-
`}};v.styles=[_,S,w`
|
|
954
|
+
`}render(){return this.activeSubTab===`audit`?this._renderAuditContent():this._renderEventsContent()}};c([s({type:String})],E.prototype,`activeSubTab`,void 0),c([s({attribute:!1})],E.prototype,`securityEvents`,void 0),c([s({attribute:!1})],E.prototype,`inputGuardSummary`,void 0),c([a()],E.prototype,`_auditEntries`,void 0),c([a()],E.prototype,`_paused`,void 0),E=c([e(`ic-security-event-feed`)],E);var D=200,O=100,k=[{id:`events`,label:`Security Events`},{id:`audit`,label:`Audit Log`},{id:`tokens`,label:`API Tokens`},{id:`secrets`,label:`Secrets`},{id:`rules`,label:`Approval Rules`},{id:`pending`,label:`Pending Approvals`},{id:`health`,label:`Provider Health`}],A=class extends r{constructor(...e){super(...e),this.rpcClient=null,this.apiClient=null,this.eventDispatcher=null,this._sse=null,this._loadState=`loading`,this._error=``,this._activeTab=`events`,this._securityEvents=[],this._inputGuardSummary={blockedAttempts:0,patternsTriggered:[],period:`session`},this._securityConfig={},this._providerHealth=[],this._failoverLog=[],this._authCooldowns=[],this._healthReloadDebounce=null}static{this.styles=[o,i,n`
|
|
1068
955
|
:host {
|
|
1069
956
|
display: block;
|
|
1070
957
|
}
|
|
@@ -1221,4 +1108,117 @@ import{s as _,f as S,i as w,n as d,r as l,a as x,A as p,b as s,t as $,I as n,S a
|
|
|
1221
1108
|
align-items: center;
|
|
1222
1109
|
font-size: var(--ic-text-sm);
|
|
1223
1110
|
}
|
|
1224
|
-
`]
|
|
1111
|
+
`]}_scheduleHealthReload(e=300){this._healthReloadDebounce!==null&&clearTimeout(this._healthReloadDebounce),this._healthReloadDebounce=setTimeout(()=>{this._healthReloadDebounce=null,this._loadProviderHealth()},e)}connectedCallback(){super.connectedCallback(),this._initSse()}disconnectedCallback(){super.disconnectedCallback(),this._healthReloadDebounce!==null&&(clearTimeout(this._healthReloadDebounce),this._healthReloadDebounce=null)}updated(e){e.has(`rpcClient`)&&this.rpcClient&&this._loadData(),e.has(`eventDispatcher`)&&this.eventDispatcher&&!this._sse&&this._initSse()}get _eventFeed(){return this.shadowRoot?.querySelector(`ic-security-event-feed`)??null}get _approvalQueue(){return this.shadowRoot?.querySelector(`ic-approval-queue`)??null}_initSse(){!this.eventDispatcher||this._sse||(this._sse=new d(this,this.eventDispatcher,{"audit:event":e=>{this._eventFeed?.onAuditEvent(e);let t=e;if(t.actionType===`output_guard`){let e=t.metadata??{},n=e.action,r=n===`redacted`?`high`:`medium`,i=e.findingCount??0,a={id:`sec-${Date.now()}-${Math.random().toString(36).slice(2,6)}`,type:`output_guard`,severity:r,message:`Output guard ${n??`scan`}: ${i} finding(s)`,details:{findingTypes:e.findingTypes,severities:e.severities,action:e.action,context:e.context},timestamp:t.timestamp??Date.now(),agentId:t.agentId};this._securityEvents=[a,...this._securityEvents].slice(0,D)}},"approval:requested":e=>{this._approvalQueue?.onApprovalPending(e)},"approval:resolved":e=>{this._approvalQueue?.onApprovalResolved(e)},"security:injection_detected":e=>{let t=e,n={high:`high`,medium:`medium`,low:`low`}[t.riskLevel??`medium`]??`medium`,r=t.source??`unknown`,i=t.patterns??[],a={id:`sec-${Date.now()}-${Math.random().toString(36).slice(2,6)}`,type:`injection`,severity:n,message:`Injection detected from ${r}`,details:{patterns:i,source:r,sessionKey:t.sessionKey},timestamp:Date.now(),agentId:t.agentId};this._securityEvents=[a,...this._securityEvents].slice(0,D);let o=[...new Set([...this._inputGuardSummary.patternsTriggered,...i])];this._inputGuardSummary={...this._inputGuardSummary,blockedAttempts:this._inputGuardSummary.blockedAttempts+1,patternsTriggered:o}},"security:injection_rate_exceeded":e=>{let t=e,n=t.count??0,r=t.threshold??0,i=t.action??`block`,a={id:`sec-${Date.now()}-${Math.random().toString(36).slice(2,6)}`,type:`input_guard`,severity:`critical`,message:`Rate limit exceeded: ${n}/${r} (action: ${i})`,details:{sessionKey:t.sessionKey,count:n,threshold:r,action:i},timestamp:Date.now()};this._securityEvents=[a,...this._securityEvents].slice(0,D)},"security:memory_tainted":e=>{let t=e,n=t.blocked??!1,r=t.originalTrustLevel??`unknown`,i=t.adjustedTrustLevel??`unknown`,a={id:`sec-${Date.now()}-${Math.random().toString(36).slice(2,6)}`,type:`memory_tainted`,severity:n?`high`:`medium`,message:`Memory tainted for ${t.agentId??`unknown`}: ${r} -> ${i}`,details:{patterns:t.patterns,blocked:n,originalTrustLevel:r,adjustedTrustLevel:i},timestamp:Date.now(),agentId:t.agentId};this._securityEvents=[a,...this._securityEvents].slice(0,D)},"security:warn":e=>{let t=e,n={id:`sec-${Date.now()}-${Math.random().toString(36).slice(2,6)}`,type:`warn`,severity:`medium`,message:t.message??`Security warning`,details:{category:t.category},timestamp:Date.now(),agentId:t.agentId};this._securityEvents=[n,...this._securityEvents].slice(0,D)},"secret:accessed":e=>{let t=e,n=t.outcome??`unknown`,r={denied:`high`,not_found:`medium`,success:`low`}[n]??`medium`,i=t.secretName??`unknown`,a={id:`sec-${Date.now()}-${Math.random().toString(36).slice(2,6)}`,type:`secret_access`,severity:r,message:`Secret '${i}' ${n} by ${t.agentId??`unknown`}`,details:{secretName:i,outcome:n},timestamp:Date.now(),agentId:t.agentId};this._securityEvents=[a,...this._securityEvents].slice(0,D)},"secret:modified":e=>{let t=e,n=t.secretName??`unknown`,r=t.action??`modified`,i={id:`sec-${Date.now()}-${Math.random().toString(36).slice(2,6)}`,type:`secret_access`,severity:`medium`,message:`Secret '${n}' ${r}`,details:{secretName:n,action:r},timestamp:Date.now()};this._securityEvents=[i,...this._securityEvents].slice(0,D)},"provider:degraded":e=>{let t=e.provider??``;this._providerHealth=this._providerHealth.map(e=>e.providerId===t?{...e,status:`degraded`}:e),this._scheduleHealthReload()},"provider:recovered":e=>{let t=e.provider??``;this._providerHealth=this._providerHealth.map(e=>e.providerId===t?{...e,status:`healthy`}:e),this._scheduleHealthReload()},"model:auth_cooldown":e=>{let t=e,n={keyName:t.keyName,provider:t.provider,cooldownMs:t.cooldownMs,failureCount:t.failureCount,timestamp:t.timestamp};this._authCooldowns=[n,...this._authCooldowns].slice(0,50),this._scheduleHealthReload(500)},"model:fallback_attempt":e=>{let t=e,n={fromProvider:t.fromProvider,fromModel:t.fromModel,toProvider:t.toProvider,toModel:t.toModel,error:t.error,attemptNumber:t.attemptNumber,timestamp:t.timestamp};this._failoverLog=[n,...this._failoverLog].slice(0,O),this._scheduleHealthReload()},"model:fallback_exhausted":e=>{let t=e,n={provider:t.provider,model:t.model,totalAttempts:t.totalAttempts,timestamp:t.timestamp,exhausted:!0};this._failoverLog=[n,...this._failoverLog].slice(0,O),this._scheduleHealthReload()},"observability:token_usage":()=>{this._scheduleHealthReload(500)}}))}async _loadProviderHealth(){if(this.rpcClient)try{let e=await this.rpcClient.call(`agent.cacheStats`),t=Date.now(),n=t-300*1e3,r=(e.providers??[]).map(e=>{let r=this._failoverLog.filter(t=>t.fromProvider===e.provider||t.provider===e.provider),i=r.length>0?Math.max(...r.map(e=>e.timestamp)):void 0,a=`healthy`,o=this._authCooldowns.find(n=>n.provider===e.provider&&n.timestamp+n.cooldownMs>t);return o&&(a=`degraded`),this._failoverLog.find(t=>t.exhausted===!0&&t.provider===e.provider&&t.timestamp>n)&&(a=`down`),{providerId:e.provider,name:e.provider,status:a,cacheHitRate:e.cacheHitRate,failoverCount:r.length,lastFailover:i,authCooldownUntil:o?o.timestamp+o.cooldownMs:void 0}});this._providerHealth=r}catch{}}async _loadData(){if(this.rpcClient){this._loadState=`loading`,this._error=``;try{let e=await this.rpcClient.call(`config.read`);this._securityConfig=e.config.security??{},this._loadState=`loaded`,this._loadProviderHealth()}catch(e){this._error=e instanceof Error?e.message:`Failed to load security configuration`,this._loadState=`error`}}}async _patchConfig(e,t){if(!this.rpcClient)return!1;try{let n=e.indexOf(`.`),r=n>0?e.slice(0,n):e,i=n>0?e.slice(n+1):void 0;return await this.rpcClient.call(`config.patch`,{section:r,key:i,value:t}),u.show(`Configuration updated`,`success`),!0}catch(e){let t=e instanceof Error?e.message:`Failed to update configuration`;return u.show(t,`error`),!1}}async _onSecretsEnabledChange(e){let t={...this._securityConfig.secrets,enabled:e};await this._patchConfig(`security.secrets`,t)&&(this._securityConfig={...this._securityConfig,secrets:t})}_renderSecretsTab(){let e=this._securityConfig.secrets??{};return t`
|
|
1112
|
+
<div class="policy-section">
|
|
1113
|
+
<div class="section-header">Encrypted Secrets Store</div>
|
|
1114
|
+
<ic-toggle
|
|
1115
|
+
label="Enabled"
|
|
1116
|
+
.checked=${e.enabled??!1}
|
|
1117
|
+
@change=${e=>this._onSecretsEnabledChange(e.detail)}
|
|
1118
|
+
></ic-toggle>
|
|
1119
|
+
<div style="margin-top: var(--ic-space-md);">
|
|
1120
|
+
<div class="tls-row">
|
|
1121
|
+
<span class="tls-label">DB Path</span>
|
|
1122
|
+
<span class="tls-value">${e.dbPath??`secrets.db`}</span>
|
|
1123
|
+
</div>
|
|
1124
|
+
</div>
|
|
1125
|
+
</div>
|
|
1126
|
+
`}_statusToDotStatus(e){switch(e){case`healthy`:return`connected`;case`degraded`:return`reconnecting`;case`down`:return`disconnected`;default:return`disconnected`}}_renderHealthTab(){let e=Date.now(),n=this._authCooldowns.filter(t=>t.timestamp+t.cooldownMs>e);return t`
|
|
1127
|
+
<div class="section-header">Provider Status</div>
|
|
1128
|
+
${this._providerHealth.length===0?t`<ic-empty-state icon="cloud" message="No provider data" description="Provider health data will appear after LLM calls are made."></ic-empty-state>`:t`
|
|
1129
|
+
<div class="health-grid">
|
|
1130
|
+
${this._providerHealth.map(n=>t`
|
|
1131
|
+
<div class="health-card">
|
|
1132
|
+
<div class="health-card-header">
|
|
1133
|
+
<strong>${n.name}</strong>
|
|
1134
|
+
<ic-connection-dot
|
|
1135
|
+
status=${this._statusToDotStatus(n.status)}
|
|
1136
|
+
size="8px"
|
|
1137
|
+
></ic-connection-dot>
|
|
1138
|
+
</div>
|
|
1139
|
+
<ic-progress-bar
|
|
1140
|
+
.value=${Math.round(n.cacheHitRate*100)}
|
|
1141
|
+
label="Cache Hit Rate"
|
|
1142
|
+
.thresholds=${{green:101,yellow:102}}
|
|
1143
|
+
></ic-progress-bar>
|
|
1144
|
+
<div class="health-card-stat">
|
|
1145
|
+
Failovers: ${n.failoverCount}
|
|
1146
|
+
${n.lastFailover?t` — last <ic-relative-time .timestamp=${n.lastFailover}></ic-relative-time>`:l}
|
|
1147
|
+
</div>
|
|
1148
|
+
${n.authCooldownUntil&&n.authCooldownUntil>e?t`
|
|
1149
|
+
<div class="health-card-stat">
|
|
1150
|
+
<ic-tag variant="warning">Auth cooldown</ic-tag>
|
|
1151
|
+
${Math.ceil((n.authCooldownUntil-e)/1e3)}s remaining
|
|
1152
|
+
</div>
|
|
1153
|
+
`:l}
|
|
1154
|
+
</div>
|
|
1155
|
+
`)}
|
|
1156
|
+
</div>
|
|
1157
|
+
`}
|
|
1158
|
+
|
|
1159
|
+
<div class="section-header" style="margin-top: var(--ic-space-xl);">Failover Event Log</div>
|
|
1160
|
+
${this._failoverLog.length===0?t`<p style="font-size: var(--ic-text-sm); color: var(--ic-text-dim); font-style: italic;">No failover events recorded</p>`:t`
|
|
1161
|
+
<div class="failover-log">
|
|
1162
|
+
${this._failoverLog.map(e=>t`
|
|
1163
|
+
<div class="failover-entry">
|
|
1164
|
+
<ic-relative-time .timestamp=${e.timestamp}></ic-relative-time>
|
|
1165
|
+
${e.exhausted?t`
|
|
1166
|
+
<span>${e.provider??`unknown`} exhausted after ${e.totalAttempts??`?`} attempts</span>
|
|
1167
|
+
<ic-tag variant="error">EXHAUSTED</ic-tag>
|
|
1168
|
+
`:t`
|
|
1169
|
+
<span>${e.fromProvider??`?`}/${e.fromModel??`?`} → ${e.toProvider??`?`}/${e.toModel??`?`}</span>
|
|
1170
|
+
${e.attemptNumber==null?l:t`<ic-tag variant="info">#${e.attemptNumber}</ic-tag>`}
|
|
1171
|
+
${e.error?t`<span style="color: var(--ic-text-dim);">${e.error}</span>`:l}
|
|
1172
|
+
`}
|
|
1173
|
+
</div>
|
|
1174
|
+
`)}
|
|
1175
|
+
</div>
|
|
1176
|
+
`}
|
|
1177
|
+
|
|
1178
|
+
<div class="section-header" style="margin-top: var(--ic-space-xl);">Auth Cooldowns</div>
|
|
1179
|
+
${n.length===0?t`<p style="font-size: var(--ic-text-sm); color: var(--ic-text-dim); font-style: italic;">No active cooldowns</p>`:t`
|
|
1180
|
+
<div class="cooldown-list">
|
|
1181
|
+
${n.map(n=>t`
|
|
1182
|
+
<div class="cooldown-entry">
|
|
1183
|
+
<ic-tag variant="warning">${n.provider}</ic-tag>
|
|
1184
|
+
<span>${n.keyName}</span>
|
|
1185
|
+
<span style="color: var(--ic-text-dim);">${n.failureCount} failures</span>
|
|
1186
|
+
<span>${Math.ceil((n.timestamp+n.cooldownMs-e)/1e3)}s remaining</span>
|
|
1187
|
+
</div>
|
|
1188
|
+
`)}
|
|
1189
|
+
</div>
|
|
1190
|
+
`}
|
|
1191
|
+
`}_renderTabContent(){switch(this._activeTab){case`events`:return t`<ic-security-event-feed
|
|
1192
|
+
activeSubTab="events"
|
|
1193
|
+
.securityEvents=${this._securityEvents}
|
|
1194
|
+
.inputGuardSummary=${this._inputGuardSummary}
|
|
1195
|
+
></ic-security-event-feed>`;case`audit`:return t`<ic-security-event-feed
|
|
1196
|
+
activeSubTab="audit"
|
|
1197
|
+
.securityEvents=${this._securityEvents}
|
|
1198
|
+
.inputGuardSummary=${this._inputGuardSummary}
|
|
1199
|
+
></ic-security-event-feed>`;case`tokens`:return t`<ic-token-manager .rpc=${this.rpcClient}></ic-token-manager>`;case`secrets`:return this._renderSecretsTab();case`rules`:return t`<ic-approval-queue
|
|
1200
|
+
activeSubTab="rules"
|
|
1201
|
+
.rpc=${this.rpcClient}
|
|
1202
|
+
.securityConfig=${this._securityConfig}
|
|
1203
|
+
></ic-approval-queue>`;case`pending`:return t`<ic-approval-queue
|
|
1204
|
+
activeSubTab="pending"
|
|
1205
|
+
.rpc=${this.rpcClient}
|
|
1206
|
+
.securityConfig=${this._securityConfig}
|
|
1207
|
+
></ic-approval-queue>`;case`health`:return this._renderHealthTab();default:return l}}render(){return this._loadState===`loading`?t`<ic-skeleton-view variant="list"></ic-skeleton-view>`:this._loadState===`error`?t`
|
|
1208
|
+
<div class="error-container">
|
|
1209
|
+
<span class="error-message">${this._error}</span>
|
|
1210
|
+
<button class="retry-btn" @click=${()=>this._loadData()}>Retry</button>
|
|
1211
|
+
</div>
|
|
1212
|
+
`:t`
|
|
1213
|
+
<div class="view-header">
|
|
1214
|
+
<div class="view-title">Security</div>
|
|
1215
|
+
</div>
|
|
1216
|
+
<ic-tabs
|
|
1217
|
+
.tabs=${k}
|
|
1218
|
+
.activeTab=${this._activeTab}
|
|
1219
|
+
@tab-change=${e=>{this._activeTab=e.detail}}
|
|
1220
|
+
></ic-tabs>
|
|
1221
|
+
<div class="tab-content">
|
|
1222
|
+
${this._renderTabContent()}
|
|
1223
|
+
</div>
|
|
1224
|
+
`}};c([s({attribute:!1})],A.prototype,`rpcClient`,void 0),c([s({attribute:!1})],A.prototype,`apiClient`,void 0),c([s({attribute:!1})],A.prototype,`eventDispatcher`,void 0),c([a()],A.prototype,`_loadState`,void 0),c([a()],A.prototype,`_error`,void 0),c([a()],A.prototype,`_activeTab`,void 0),c([a()],A.prototype,`_securityEvents`,void 0),c([a()],A.prototype,`_inputGuardSummary`,void 0),c([a()],A.prototype,`_securityConfig`,void 0),c([a()],A.prototype,`_providerHealth`,void 0),c([a()],A.prototype,`_failoverLog`,void 0),c([a()],A.prototype,`_authCooldowns`,void 0),A=c([e(`ic-security-view`)],A);export{A as IcSecurityView};
|