okengine 0.14.1 → 0.16.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/package.json +3 -4
- package/site/content/docs/elements/ai.mdx +2 -1
- package/site/content/docs/elements/channel.mdx +1 -0
- package/site/content/docs/elements/clock.mdx +3 -0
- package/site/content/docs/elements/flow.mdx +9 -0
- package/site/content/docs/elements/gate.mdx +80 -22
- package/site/content/docs/elements/signal.mdx +4 -4
- package/site/content/docs/elements/store.mdx +84 -27
- package/site/content/docs/elements/vault.mdx +4 -0
- package/site/content/docs/get-started/basic-usage.mdx +22 -13
- package/site/content/docs/get-started/index.mdx +5 -0
- package/site/content/docs/get-started/introduction.mdx +11 -3
- package/site/content/docs/get-started/meta.json +1 -1
- package/site/content/docs/get-started/project-structure.mdx +932 -0
- package/site/content/docs/reference/cli.md +13 -10
- package/site/content/docs/reference/client.mdx +28 -21
- package/site/content/docs/reference/fx.mdx +29 -18
- package/site/content/docs/reference/security.md +2 -2
- package/src/auth/api-key-sql.test.ts +47 -0
- package/src/auth/api-key-sql.ts +254 -0
- package/src/auth/api-keys.ts +273 -14
- package/src/auth/auth.test.ts +56 -0
- package/src/auth/bindings.ts +14 -5
- package/src/auth/config.ts +5 -5
- package/src/auth/cross-plane.ts +10 -3
- package/src/auth/index.ts +25 -1
- package/src/auth/schema.ts +8 -0
- package/src/cli/ai-setup/ai-setup.test.ts +62 -0
- package/src/cli/ai-setup/apply.ts +32 -1
- package/src/cli/attach-host-console.test.ts +40 -2
- package/src/cli/attach-host-console.ts +9 -0
- package/src/cli/build.test.ts +4 -2
- package/src/cli/db-seed.ts +48 -15
- package/src/cli/db.test.ts +104 -0
- package/src/cli/db.ts +122 -10
- package/src/cli/dev-controls.test.ts +20 -0
- package/src/cli/dev-controls.ts +13 -0
- package/src/cli/dev.test.ts +15 -4
- package/src/cli/dev.ts +102 -29
- package/src/cli/ensure-drizzle-config.ts +2 -1
- package/src/cli/tui/DevLive.tsx +12 -2
- package/src/cli/tui/keys.test.ts +2 -1
- package/src/cli/tui/keys.ts +3 -2
- package/src/compiler/aot.test.ts +1 -1
- package/src/compiler/effects-infer.ts +17 -2
- package/src/compiler/extract.test.ts +409 -33
- package/src/compiler/extract.ts +318 -67
- package/src/compiler/flow-path.test.ts +96 -0
- package/src/compiler/flow-path.ts +173 -0
- package/src/compiler/generate-adopt.test.ts +112 -3
- package/src/compiler/generate-adopt.ts +280 -26
- package/src/compiler/schema-from-ast.ts +609 -0
- package/src/console/server/access.test.ts +116 -8
- package/src/console/server/access.ts +70 -23
- package/src/console/server/app.ts +1 -0
- package/src/console/server/bind.ts +2 -2
- package/src/console/server/console.test.ts +3 -0
- package/src/console/server/dev-identities.test.ts +127 -0
- package/src/console/server/dev-identities.ts +229 -0
- package/src/console/server/flows-invoke.test.ts +21 -4
- package/src/console/server/flows.ts +233 -98
- package/src/console/server/gates.test.ts +24 -0
- package/src/console/server/gates.ts +8 -21
- package/src/console/server/index.ts +1 -0
- package/src/console/server/invoke-user-flow.test.ts +3 -1
- package/src/console/server/invoke-user-flow.ts +17 -2
- package/src/console/server/iso-at.test.ts +9 -0
- package/src/console/server/iso-at.ts +11 -0
- package/src/console/server/live.test.ts +26 -1
- package/src/console/server/live.ts +4 -2
- package/src/console/server/operator-db.ts +2 -0
- package/src/console/server/security-headers.ts +6 -3
- package/src/console/server/spa-proxy.test.ts +1 -0
- package/src/console/server/sql-catalog.ts +147 -7
- package/src/console/server/sql-rls.test.ts +16 -0
- package/src/console/server/state.ts +37 -55
- package/src/console/server/store.test.ts +7 -4
- package/src/console/server/store.ts +142 -58
- package/src/console/ui-next/dist/assets/access-page-CAGHrA9H.js +4 -0
- package/src/console/ui-next/dist/assets/agent-disclosure-BP0Y0Sux.js +1 -0
- package/src/console/ui-next/dist/assets/cache-glyph-B5X-NM0-.js +1 -0
- package/src/console/ui-next/dist/assets/call-pii-button-ChAUiLo9.js +1 -0
- package/src/console/ui-next/dist/assets/collapsible-DGnOM2ph.js +1 -0
- package/src/console/ui-next/dist/assets/copy-inline-button-DBHhgHKP.js +1 -0
- package/src/console/ui-next/dist/assets/detail-header-DhHM1iaZ.js +1 -0
- package/src/console/ui-next/dist/assets/dropdown-menu-_NjTEo5_.js +1 -0
- package/src/console/ui-next/dist/assets/{duration-tone-oiRxPVsZ.js → duration-tone-sC3lGABz.js} +1 -1
- package/src/console/ui-next/dist/assets/element-icons-BVXtRyd3.js +1 -0
- package/src/console/ui-next/dist/assets/explorer-empty-2uIhBu0_.js +1 -0
- package/src/console/ui-next/dist/assets/flows-page-B-OUtiAu.js +1 -0
- package/src/console/ui-next/dist/assets/{highlighted-json-CvDPvveV.js → highlighted-json-Awq7gYdu.js} +1 -1
- package/src/console/ui-next/dist/assets/http-method-_UHM2ODJ.js +1 -0
- package/src/console/ui-next/dist/assets/index-CGoZkILK.js +66 -0
- package/src/console/ui-next/dist/assets/index-Ck88Jmv8.css +2 -0
- package/src/console/ui-next/dist/assets/link-BX6Vqztd.js +1 -0
- package/src/console/ui-next/dist/assets/observability-page-BDyXalNR.js +4 -0
- package/src/console/ui-next/dist/assets/react-D8E3mtu1.js +1 -0
- package/src/console/ui-next/dist/assets/replica-lag-DKRrbvdo.js +18 -0
- package/src/console/ui-next/dist/assets/request-meta-DV0ywz7t.js +1 -0
- package/src/console/ui-next/dist/assets/shortcut-JQIZlWfm.js +1 -0
- package/src/console/ui-next/dist/assets/shortcut-keys-DKxNTe_m.js +1 -0
- package/src/console/ui-next/dist/assets/{skeleton-CL_X0GCj.js → skeleton-D-czQJT6.js} +1 -1
- package/src/console/ui-next/dist/assets/store-page-Xh8Kn3rx.js +41 -0
- package/src/console/ui-next/dist/assets/trace-detail-sheet-B09O8rA6.js +2 -0
- package/src/console/ui-next/dist/assets/tree-expand-toggle-DkOXA12R.js +54 -0
- package/src/console/ui-next/dist/assets/units-page-Dpk40kOQ.js +1 -0
- package/src/console/ui-next/dist/assets/{use-vault-list-Cl79j_ku.js → use-vault-list-uk4WVboC.js} +1 -1
- package/src/console/ui-next/dist/assets/useMutation-B8EO02Ej.js +1 -0
- package/src/console/ui-next/dist/assets/useRender-BE2A9BWC.js +1 -0
- package/src/console/ui-next/dist/assets/vault-page-B1dB9Ft0.js +2 -0
- package/src/console/ui-next/dist/index.html +12 -10
- package/src/console/ui-next/index.html +3 -3
- package/src/console/ui-next/src/client.ts +202 -7
- package/src/console/ui-next/src/components/motion/table/index.tsx +16 -0
- package/src/console/ui-next/src/components/motion/table/types.ts +4 -0
- package/src/console/ui-next/src/components/shell/app-sidebar.tsx +2 -0
- package/src/console/ui-next/src/components/shell/command-items.test.ts +1 -0
- package/src/console/ui-next/src/components/shell/command-items.ts +8 -0
- package/src/console/ui-next/src/components/shell/shell-layout.tsx +2 -1
- package/src/console/ui-next/src/components/ui/kbd.tsx +2 -2
- package/src/console/ui-next/src/components/ui/sheet-form.tsx +8 -3
- package/src/console/ui-next/src/features/access/access-page.tsx +347 -0
- package/src/console/ui-next/src/features/access/data/use-access.ts +23 -0
- package/src/console/ui-next/src/features/access/detail/access-detail.tsx +552 -0
- package/src/console/ui-next/src/features/access/explorer/access-list.tsx +125 -0
- package/src/console/ui-next/src/features/access/lib/format-when.test.ts +139 -0
- package/src/console/ui-next/src/features/access/lib/format-when.ts +296 -0
- package/src/console/ui-next/src/features/access/lib/scope-groups.test.ts +34 -0
- package/src/console/ui-next/src/features/access/lib/scope-groups.ts +40 -0
- package/src/console/ui-next/src/features/access/sheets/access-allow-fields.tsx +236 -0
- package/src/console/ui-next/src/features/access/sheets/access-create-sheet.tsx +316 -0
- package/src/console/ui-next/src/features/access/sheets/access-edit-sheet.tsx +240 -0
- package/src/console/ui-next/src/features/access/sheets/access-expiry-fields.tsx +66 -0
- package/src/console/ui-next/src/features/access/sheets/access-refresh-sheet.tsx +104 -0
- package/src/console/ui-next/src/features/access/sheets/access-scope-field.tsx +115 -0
- package/src/console/ui-next/src/features/access/sheets/access-secret-sheet.tsx +89 -0
- package/src/console/ui-next/src/features/access/sheets/access-sheet-search.tsx +49 -0
- package/src/console/ui-next/src/features/access/state/access-selection.ts +84 -0
- package/src/console/ui-next/src/features/auth/auth-redirect.test.ts +5 -0
- package/src/console/ui-next/src/features/auth/auth-redirect.ts +18 -2
- package/src/console/ui-next/src/features/flows/traces/http-method.ts +19 -0
- package/src/console/ui-next/src/features/flows/traces/trace-detail.test.ts +19 -1
- package/src/console/ui-next/src/features/flows/traces/traces-pane.tsx +10 -3
- package/src/console/ui-next/src/features/not-found/not-found-page.tsx +1 -1
- package/src/console/ui-next/src/features/store/detail/browse-section.tsx +45 -1
- package/src/console/ui-next/src/features/store/detail/resource-panel.tsx +78 -16
- package/src/console/ui-next/src/features/store/detail/store-row-detail-sheet.tsx +155 -14
- package/src/console/ui-next/src/features/store/explorer/store-tree.tsx +33 -133
- package/src/console/ui-next/src/features/store/files/file-preview.tsx +4 -1
- package/src/console/ui-next/src/features/store/grid/rls-policy-sheet.tsx +326 -165
- package/src/console/ui-next/src/features/store/grid/sql-insert-sheet.tsx +6 -0
- package/src/console/ui-next/src/features/store/grid/store-data-grid.tsx +50 -3
- package/src/console/ui-next/src/features/store/lib/files-meta.test.ts +3 -0
- package/src/console/ui-next/src/features/store/lib/files-meta.ts +12 -0
- package/src/console/ui-next/src/features/store/lib/query-defaults.test.ts +25 -0
- package/src/console/ui-next/src/features/store/lib/query-defaults.ts +85 -3
- package/src/console/ui-next/src/features/store/lib/query-gate.ts +30 -4
- package/src/console/ui-next/src/features/store/lib/rls-policy.test.ts +139 -0
- package/src/console/ui-next/src/features/store/lib/rls-policy.ts +223 -21
- package/src/console/ui-next/src/features/store/lib/schema-graph.ts +4 -0
- package/src/console/ui-next/src/features/store/lib/sql-catalog.test.ts +24 -0
- package/src/console/ui-next/src/features/store/lib/sql-catalog.ts +19 -0
- package/src/console/ui-next/src/features/store/lib/store-tree.test.ts +6 -0
- package/src/console/ui-next/src/features/store/lib/store-tree.ts +13 -0
- package/src/console/ui-next/src/features/store/query/query-console.tsx +48 -14
- package/src/console/ui-next/src/features/store/query/query-gate-menu.tsx +19 -20
- package/src/console/ui-next/src/features/store/query/query-gate-parts.tsx +2 -1
- package/src/console/ui-next/src/features/store/query/query-results.tsx +110 -83
- package/src/console/ui-next/src/features/store/schema/schema-table-node.tsx +17 -0
- package/src/console/ui-next/src/features/units/call/call-api-panel.tsx +112 -72
- package/src/console/ui-next/src/features/units/lib/contract-input.test.ts +206 -1
- package/src/console/ui-next/src/features/units/lib/contract-input.ts +55 -0
- package/src/console/ui-next/src/features/vault/lib/types.ts +1 -1
- package/src/console/ui-next/src/lib/document-meta.test.ts +1 -0
- package/src/console/ui-next/src/lib/document-meta.ts +2 -1
- package/src/console/ui-next/src/lib/last-module-search.test.ts +1 -0
- package/src/console/ui-next/src/lib/last-module-search.ts +2 -1
- package/src/console/ui-next/src/lib/shortcut.test.ts +2 -0
- package/src/console/ui-next/src/lib/shortcut.ts +3 -0
- package/src/console/ui-next/src/router.tsx +10 -1
- package/src/console/ui-next/ui-next-seed-app-schema.ts +88 -37
- package/src/console/ui-next/ui-next-seed-store.ts +43 -15
- package/src/console/xss.gate.test.ts +1 -0
- package/src/docker/compose-health.test.ts +27 -0
- package/src/docker/compose-health.ts +19 -3
- package/src/docker/docker.test.ts +3 -0
- package/src/docker/recipes/pgdog.ts +2 -0
- package/src/drivers/clock-postgres.ts +13 -9
- package/src/drivers/instances-postgres.ts +4 -6
- package/src/drivers/journal-postgres.ts +13 -9
- package/src/drivers/pg-rls.test.ts +87 -0
- package/src/drivers/pg-rls.ts +233 -7
- package/src/drivers/pglite.ts +26 -3
- package/src/drivers/postgres.test.ts +23 -0
- package/src/drivers/postgres.ts +133 -9
- package/src/drivers/types.ts +10 -0
- package/src/elements/clock/declare.ts +26 -1
- package/src/elements/gate/boot.ts +5 -5
- package/src/elements/gate/declare.ts +38 -4
- package/src/elements/gate/flatten.ts +1 -1
- package/src/elements/gate/runtime.ts +1 -1
- package/src/elements/store/cache.ts +1 -1
- package/src/elements/store/declare.ts +9 -6
- package/src/elements/store/emit-drizzle.ts +44 -8
- package/src/elements/store/resource.test.ts +1 -1
- package/src/elements/store/rls-identity.test.ts +95 -0
- package/src/elements/store/rls-identity.ts +116 -0
- package/src/elements/store/runtime.ts +18 -0
- package/src/elements/store/schema-decl.test.ts +37 -0
- package/src/elements/store/schema-decl.ts +260 -41
- package/src/elements/store/seed.ts +1 -1
- package/src/elements/store/sql-condition.test.ts +12 -0
- package/src/elements/store/sql-condition.ts +26 -2
- package/src/elements/store/sql-rls-isolation.test.ts +165 -0
- package/src/elements/store/sql-rls-stamp.test.ts +117 -0
- package/src/elements/store/sql-select.types.test.ts +71 -0
- package/src/elements/store/sql-session.ts +135 -35
- package/src/elements/store/upsert-app.test.ts +1 -1
- package/src/elements/store.ts +17 -0
- package/src/http.ts +20 -3
- package/src/index.ts +11 -1
- package/src/kernel/adopt-barrel-fresh.test.ts +1 -1
- package/src/kernel/adopt-routes.ts +30 -2
- package/src/kernel/api-key-host-persist.test.ts +143 -0
- package/src/kernel/app.ts +145 -16
- package/src/kernel/auth-resolve.ts +10 -5
- package/src/kernel/auto-cache.test.ts +8 -8
- package/src/kernel/auto-registry.test.ts +49 -9
- package/src/kernel/boot.test.ts +5 -5
- package/src/kernel/boot.ts +2 -2
- package/src/kernel/effects-stamping.test.ts +3 -3
- package/src/kernel/element-registries.ts +12 -5
- package/src/kernel/errors.ts +24 -0
- package/src/kernel/flow-units.ts +64 -0
- package/src/kernel/flow.ts +29 -17
- package/src/kernel/fx-auth-keys.test.ts +88 -0
- package/src/kernel/fx-auth-keys.ts +198 -0
- package/src/kernel/fx.test.ts +17 -1
- package/src/kernel/fx.ts +59 -18
- package/src/kernel/horizontal-child.ts +4 -4
- package/src/kernel/http-path-pending.ts +20 -0
- package/src/kernel/http-resource.ts +4 -0
- package/src/kernel/http-stream.test.ts +4 -4
- package/src/kernel/pipeline-api-key.test.ts +192 -7
- package/src/kernel/pipeline.test.ts +2 -2
- package/src/kernel/pipeline.ts +4 -2
- package/src/kernel/plugin-elements.test.ts +1 -1
- package/src/kernel/plugin-needs.test.ts +1 -1
- package/src/kernel/ready.test.ts +2 -2
- package/src/kernel/resource-mount.test.ts +14 -0
- package/src/kernel/run-duration.test.ts +2 -2
- package/src/kernel/stamp-http.test.ts +79 -0
- package/src/kernel/stamp-http.ts +75 -0
- package/src/kernel/triggers.ts +52 -27
- package/src/manifest/types.ts +22 -3
- package/src/release/build-lib.ts +1 -0
- package/src/release/measure.ts +2 -2
- package/src/runtime/json-code-block.test.ts +2 -2
- package/src/runtime/serve.test.ts +4 -4
- package/src/term.test.ts +52 -4
- package/src/term.ts +125 -17
- package/src/test/reset-element-registries.ts +8 -3
- package/src/cli/ask-seed.test.ts +0 -96
- package/src/cli/ask-seed.ts +0 -82
- package/src/console/ui-next/dist/assets/cache-glyph-BanhLsEY.js +0 -1
- package/src/console/ui-next/dist/assets/call-pii-button-bqkxMrJH.js +0 -1
- package/src/console/ui-next/dist/assets/collapsible-DYb0xU8C.js +0 -1
- package/src/console/ui-next/dist/assets/confirm-sheet-DDCRmG62.js +0 -1
- package/src/console/ui-next/dist/assets/explorer-empty-HjTnVQoR.js +0 -1
- package/src/console/ui-next/dist/assets/flows-page-DxDsOd4f.js +0 -1
- package/src/console/ui-next/dist/assets/http-method-CJCBYL2j.js +0 -1
- package/src/console/ui-next/dist/assets/index-Ce6WKWKM.js +0 -66
- package/src/console/ui-next/dist/assets/index-D4Ldtj79.css +0 -2
- package/src/console/ui-next/dist/assets/link-DF7SZ9Ek.js +0 -1
- package/src/console/ui-next/dist/assets/observability-page-BEZDzyYh.js +0 -4
- package/src/console/ui-next/dist/assets/query-gate-parts-1m8m1iNp.js +0 -2
- package/src/console/ui-next/dist/assets/react-B1ML8gxg.js +0 -1
- package/src/console/ui-next/dist/assets/replica-lag-C8_BRt2x.js +0 -18
- package/src/console/ui-next/dist/assets/sheet-form-D-ata7jy.js +0 -1
- package/src/console/ui-next/dist/assets/shortcut-Cgzuv4k1.js +0 -1
- package/src/console/ui-next/dist/assets/shortcut-keys-DO4IsVqv.js +0 -1
- package/src/console/ui-next/dist/assets/store-page-v3LXdYpr.js +0 -45
- package/src/console/ui-next/dist/assets/trace-detail-sheet-DFLFfUUX.js +0 -2
- package/src/console/ui-next/dist/assets/units-page-C0gW6Kdo.js +0 -1
- package/src/console/ui-next/dist/assets/vault-page-DuKzqwzW.js +0 -2
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{r as e}from"./rolldown-runtime-hePW80VL.js";import{$n as t,Bi as n,Cr as r,E as i,Fi as a,Fo as o,Jr as s,Mr as c,Qi as l,Qn as u,Sr as d,Ta as f,Wi as p,Wr as m,Zn as h,_ as g,_r as _,ao as v,ar as y,b,br as ee,c as x,co as te,cr as ne,d as re,dr as S,er as C,gr as ie,h as ae,hr as w,i as T,ia as oe,ii as se,io as ce,kr as le,l as E,la as ue,lo as de,mr as D,na as fe,nr as pe,o as O,oi as me,or as k,p as A,s as j,so as he,sr as M,tr as N,u as P,ur as F,vr as ge,wr as I,x as L,xi as _e,xr as ve,y as ye}from"./shortcut-keys-DKxNTe_m.js";import{t as be}from"./useMutation-B8EO02Ej.js";import{r as xe}from"./react-dom-Bph1y7z7.js";import{A as Se}from"./xyflow-D7n4g6go.js";import{t as R}from"./link-BX6Vqztd.js";import{a as z,d as Ce,i as we,l as Te,r as Ee,t as De}from"./dropdown-menu-_NjTEo5_.js";import{r as Oe}from"./index-CGoZkILK.js";import{a as ke,c as Ae,i as je,n as Me,o as Ne,r as Pe,s as B,t as V}from"./element-icons-BVXtRyd3.js";import{t as Fe}from"./explorer-empty-2uIhBu0_.js";import{a as H,c as U,l as W,n as G,o as Ie,s as Le,t as Re}from"./detail-header-DhHM1iaZ.js";import{n as ze,t as Be}from"./copy-inline-button-DBHhgHKP.js";import{i as Ve,n as He,r as Ue,t as We}from"./collapsible-DGnOM2ph.js";import{a as Ge,i as Ke,n as qe,o as Je,r as Ye,s as Xe,t as Ze}from"./use-vault-list-uk4WVboC.js";var K=e(xe(),1);function Qe(e){if(e.count===0)return{summary:`No in-flight durable runs hold this secret`,detail:null,warn:!1};let t=e.longestOutstandingMs==null?null:$e(e.longestOutstandingMs);return{summary:`${e.count} in-flight durable run(s) will wake holding a new key`,detail:t?`Longest outstanding wake in ${t}`:e.longestWakeAt==null?null:`Longest wake at ${new Date(e.longestWakeAt).toISOString()}`,warn:!0}}function $e(e){if(e<1e3)return`${e}ms`;let t=Math.floor(e/1e3);if(t<60)return`${t}s`;let n=Math.floor(t/60);if(n<60)return`${n}m`;let r=Math.floor(n/60);return r<48?`${r}h`:`${Math.floor(r/24)}d`}function et(e){return`await fx.vault.get(${e})`}function tt(e){return`oke vault set ${e}`}function nt(e){return`oke vault rotate ${e}`}function rt(e){return`${e}=`}function it(e,t,n){switch(e){case`process.env`:return{source:e,label:`env`,command:`export ${t}=`,hint:`Process environment for this Console process`};case`.env.local`:return{source:e,label:`local`,command:rt(t),hint:`Write to .env.local (gitignored)`};case`driver`:return{source:e,label:Je(n),command:tt(t),hint:Ke(n)};case`dev-fallback`:return{source:e,label:`fallback`,command:`dev: "…"`,hint:`Local-only option on the contract — never used in prod`}}}function at(e){return{name:e.name,kind:e.kind,sensitive:e.sensitive,description:e.description??null,rotate:e.rotate??null,fingerprints:{...e.fingerprints},fingerprint:e.fingerprint,cleartext:e.sensitive?null:e.cleartext,winner:e.winner,resolution:e.resolution.map(e=>({...e})),readers:[...e.readers],blastRadius:{count:e.blastRadius.count,longestWakeAt:e.blastRadius.longestWakeAt,longestOutstandingMs:e.blastRadius.longestOutstandingMs,runIds:[...e.blastRadius.runIds]},lastReadAt:e.lastReadAt,sharedFingerprintEnvs:[...e.sharedFingerprintEnvs]}}function ot(e){return JSON.stringify(e.map(e=>at(e)),null,2)}var st=[{id:`blast`,label:`Blast`,token:`blast`,tone:`danger`},{id:`unset`,label:`Unset`,token:`unset`,tone:`warn`},{id:`overdue`,label:`Overdue`,token:`overdue`,tone:`warn`},{id:`shared`,label:`Shared`,token:`shared`,tone:`warn`},{id:`dormant`,label:`Dormant`,token:`dormant`,tone:`neutral`}],ct=[`blast`,`unset`,`overdue`,`shared`,`dormant`];function lt(e){if(!e)return 0;let t=/^(\d+)(ms|s|m|h|d)$/.exec(e.trim());if(!t)return 0;let n=Number(t[1]);switch(t[2]){case`ms`:return n;case`s`:return n*1e3;case`m`:return n*6e4;case`h`:return n*36e5;case`d`:return n*864e5;default:return 0}}var ut=new Set([`never`,`none`,`off`]);function q(e){return lt(e)>0}function dt(e){if(q(e))return e.trim();let t=e?.trim().toLowerCase()??``;return t.length===0||ut.has(t)?`no rotate`:e.trim()}function ft(e){return e.sensitive?e.fingerprint!=null&&e.fingerprint.length>0:e.cleartext!=null&&e.cleartext.length>0}function pt(e,t){let n=ft(e),r=!n,i=e.blastRadius.count>0,a=e.sharedFingerprintEnvs.length>0,o=e.lastReadAt==null,s=e.kind===`secret`&&(o||e.lastReadAt!=null&&t-e.lastReadAt>=7776e6),c=lt(e.rotate),l=e.kind===`secret`&&n&&c>0&&(o||e.lastReadAt!=null&&t-e.lastReadAt>=c),u=[];return i&&u.push(`blast`),r&&u.push(`unset`),l&&u.push(`overdue`),a&&u.push(`shared`),s&&u.push(`dormant`),{unset:r,set:n,blast:i,shared:a,dormant:s,overdue:l,unread:o,healthy:n&&!i&&!a&&!s&&!l,risks:u,primary:e.kind===`config`&&!r&&!i&&!a?`config`:ct.find(e=>u.includes(e))??`healthy`}}function mt(e,t){let n=0,r=0,i=0,a=0,o=0,s=0,c=0,l=0;for(let u of e){u.kind===`secret`?n+=1:r+=1;let e=pt(u,t);e.unset&&(i+=1),e.blast&&(a+=1),e.shared&&(o+=1),e.dormant&&(s+=1),e.overdue&&(c+=1),e.healthy&&(l+=1)}return{total:e.length,secrets:n,config:r,unset:i,blast:a,shared:o,dormant:s,overdue:c,healthy:l}}function ht(e,t){let n=Math.max(0,t-e);if(n<6e4)return`just now`;if(n<36e5)return`${Math.floor(n/6e4)}m ago`;if(n<864e5)return`${Math.floor(n/36e5)}h ago`;let r=Math.floor(n/864e5);return r<14?`${r}d ago`:r<60?`${Math.floor(r/7)}w ago`:`${Math.floor(r/30)}mo ago`}function gt(e){switch(e){case`blast`:return`blast`;case`unset`:return`unset`;case`overdue`:return`overdue`;case`shared`:return`shared`;case`dormant`:return`dormant`;case`config`:return`config`;case`healthy`:return`set`}}function _t(e,t){switch(e){case`blast`:return`In-flight durable runs hold this secret`;case`unset`:return`No value in this environment`;case`overdue`:return t?`Last read older than rotate ${t} — never-read counts`:`Last read older than the rotate hint — never-read counts`;case`shared`:return`Fingerprint matches another environment`;case`dormant`:return`Unread for 90 days, or never`;case`config`:return`vault.config — shown in the clear`;case`healthy`:return`Set, no blast, no shared, not dormant`}}var J=`#94A3B8`,Y=Se(),vt={driver:`driver`,"process.env":`env`,".env.local":`local`,"dev-fallback":`fallback`},yt={driver:_e,"process.env":l,".env.local":se,"dev-fallback":oe},bt=`text-emerald-700 dark:text-emerald-400`,xt=[`driver`,`process.env`,`.env.local`,`dev-fallback`];function St(e){let t=e.resolution.length>0?e.resolution:xt.map(t=>({source:t,present:!1,won:e.winner===t})),n=new Map(t.map(e=>[e.source,e]));return xt.map(t=>n.get(t)??{source:t,present:!1,won:e.winner===t})}function Ct(e){return e.find(e=>e.won)?.source??e.find(e=>!e.present)?.source??e[0].source}function wt(e,t,n){return e.won?`won`:n>=0&&t>n?e.present?`shadowed`:`skipped`:e.present?`shadowed`:`missed`}function Tt({row:e,env:t,now:n,backend:r=null,onSet:i,onRotate:a,onQueryChange:o,leading:s}){let c=Qe(e.blastRadius),l=pt(e,n),u=e.description??e.name,d=jt(e,t),f=St(e),p=f.find(e=>e.won)??null,[m,h]=(0,K.useState)(()=>Ct(f)),g=l.unset,_=l.overdue&&q(e.rotate)&&!c.warn&&!l.unset;(0,K.useEffect)(()=>{h(Ct(St(e)))},[e.name]);let v=f.find(e=>e.source===m)??f[0],y=it(v.source,e.name,r);return(0,Y.jsxs)(`div`,{className:`flex h-full min-h-0 flex-col overflow-y-auto`,"data-slot":`vault-detail`,"aria-label":`Vault detail`,"aria-live":`polite`,children:[(0,Y.jsx)(Re,{dataSlot:`vault-detail-header`,leading:s,icon:(0,Y.jsx)(I,{icon:V.vault.icon,className:`size-4`}),wellStyle:{color:J},title:u,badge:(0,Y.jsxs)(Y.Fragment,{children:[(0,Y.jsx)(`span`,{className:`font-mono text-[10px] font-medium tracking-[0.08em] text-muted-foreground uppercase`,children:e.kind}),e.kind===`secret`?(0,Y.jsx)(`span`,{className:`font-mono text-[10px] text-muted-foreground`,children:dt(e.rotate)}):null,e.origin===`console`?(0,Y.jsx)(`span`,{className:`font-mono text-[10px] text-muted-foreground`,children:`console`}):null,(0,Y.jsx)(`span`,{className:`font-mono text-[10px] text-muted-foreground`,children:Ge(r)})]}),subtitle:(0,Y.jsxs)(Y.Fragment,{children:[(0,Y.jsx)(`code`,{className:`min-w-0 truncate font-mono text-[11px] leading-none text-foreground/80`,children:e.name}),(0,Y.jsx)(Be,{value:e.name,label:`Copy ${e.name}`})]}),actions:(0,Y.jsxs)(Y.Fragment,{children:[(0,Y.jsx)(Et,{row:e}),g?null:(0,Y.jsx)(B,{label:e.kind===`config`?`Updates this vault.config value. Console shows it in the clear.`:`Write-only. The new value is never shown again.`,className:`flex self-stretch`,children:(0,Y.jsx)(L,{type:`button`,variant:`ghost`,size:`sm`,className:`h-full rounded-none`,onClick:i,children:`Set`})}),g||_?null:(0,Y.jsx)(B,{label:c.warn?c.summary:`Re-encrypt with a new value. Review the fingerprint before it writes.`,className:`flex self-stretch`,children:(0,Y.jsx)(L,{type:`button`,variant:`destructive`,size:`sm`,className:`h-full rounded-none`,disabled:c.warn,onClick:a,children:`Rotate`})})]})}),(0,Y.jsx)(Dt,{row:e,env:t,postureUnset:l.unset,blastWarn:c.warn,blastSummary:c.summary,blastDetail:c.detail,overdue:l.overdue,onSet:i,onRotate:a}),(0,Y.jsxs)(`div`,{className:w,"data-slot":`vault-briefing`,role:`group`,"aria-label":`Posture`,children:[(0,Y.jsx)(X,{label:`from`,value:e.winner?vt[e.winner]:`none`,hint:p?e.winner===`driver`?Xe(r):`First layer that had a value`:`No layer provided a value`,warn:!e.winner,won:!!e.winner,onClick:o?()=>o(e.winner?`from:${e.winner}`:`is:unset`):void 0}),(0,Y.jsx)(X,{label:`read`,value:e.lastReadAt==null?`never`:ht(e.lastReadAt,n),hint:e.lastReadAt==null?`Possible dead secret`:new Date(e.lastReadAt).toISOString(),warn:e.lastReadAt==null&&e.kind===`secret`,onClick:o?()=>o(`is:dormant`):void 0}),(0,Y.jsx)(X,{label:`readers`,value:String(e.readers.length),hint:e.readers.length===0?`No Flow declares a read`:e.readers.join(`, `),onClick:o&&e.readers[0]?()=>o(`reader:${e.readers[0]}`):void 0}),(0,Y.jsx)(X,{label:`blast`,value:e.blastRadius.count===0?`clear`:`${e.blastRadius.count} run${e.blastRadius.count===1?``:`s`}`,hint:c.detail??(e.blastRadius.longestOutstandingMs==null?c.summary:$e(e.blastRadius.longestOutstandingMs)),warn:c.warn,onClick:o?()=>o(`is:blast`):void 0}),e.sharedFingerprintEnvs.length>0?(0,Y.jsx)(X,{label:`shared`,value:e.sharedFingerprintEnvs.join(`, `),hint:`Same fingerprint in another environment`,warn:!0,onClick:o?()=>o(`is:shared`):void 0}):null]}),(0,Y.jsx)(kt,{steps:f,selected:v,fill:y,backend:r,onSelect:h}),(0,Y.jsxs)(`section`,{className:`shrink-0 border-b border-border/60`,"aria-label":`Fingerprints by environment`,children:[(0,Y.jsx)(Ot,{title:e.sensitive?`Fingerprints`:`Value`,meta:e.sensitive?`${d.length} env`:t}),e.sensitive?(0,Y.jsx)(At,{slots:d,env:t}):(0,Y.jsx)(`p`,{className:`px-2 py-1.5 font-mono text-[12px]`,role:`status`,children:e.cleartext??`unset`})]}),(0,Y.jsx)(Mt,{readers:e.readers,name:e.name,onFilterReader:o?e=>o(`reader:${e}`):void 0})]})}function Et({row:e}){let t=[{id:`fx`,label:`Flow read`,value:et(e.name)},{id:`set`,label:`oke vault set`,value:tt(e.name)},{id:`rotate`,label:`oke vault rotate`,value:nt(e.name)},{id:`env`,label:`.env assignment`,value:rt(e.name)},{id:`json`,label:`Export fingerprints`,value:JSON.stringify(at(e),null,2)}];return(0,Y.jsxs)(De,{children:[(0,Y.jsx)(B,{label:`Copy snippets (no secret values)`,className:`flex self-stretch`,children:(0,Y.jsx)(Ce,{render:e=>(0,Y.jsx)(`button`,{...e,type:`button`,"aria-label":`Copy`,className:y,children:(0,Y.jsx)(I,{icon:a,className:`size-3.5`})})})}),(0,Y.jsxs)(Ee,{align:`end`,className:`min-w-52`,children:[(0,Y.jsx)(we,{children:t.slice(0,4).map(e=>(0,Y.jsx)(z,{onClick:()=>{navigator.clipboard?.writeText(e.value)},children:e.label},e.id))}),(0,Y.jsx)(Te,{}),(0,Y.jsx)(z,{onClick:()=>{navigator.clipboard?.writeText(t[4].value)},children:`Export fingerprints`})]})]})}function Dt({row:e,env:t,postureUnset:n,blastWarn:i,blastSummary:a,blastDetail:o,overdue:s,onSet:c,onRotate:l}){return i?(0,Y.jsxs)(`section`,{className:`shrink-0 border-b border-destructive/25 bg-destructive/5`,"aria-label":`Rotation blast radius`,role:`alert`,children:[(0,Y.jsx)(`div`,{className:r(w,`border-b-0`),children:(0,Y.jsxs)(`p`,{className:`flex min-w-0 flex-1 items-center px-2 text-[12px] text-destructive`,children:[a,o?(0,Y.jsxs)(`span`,{className:`text-muted-foreground`,children:[` · `,o]}):null]})}),e.blastRadius.runIds.length>0?(0,Y.jsx)(`ul`,{children:e.blastRadius.runIds.map(e=>(0,Y.jsx)(`li`,{children:(0,Y.jsx)(R,{to:`/overview`,search:{run:e},className:r(S,`text-destructive`),children:(0,Y.jsx)(`span`,{className:`min-w-0 truncate font-mono text-[11px]`,children:e})})},e))}):null]}):n?(0,Y.jsxs)(`section`,{className:r(w,`border-amber-500/25 bg-amber-500/5`),"aria-label":`Unset contract`,role:`status`,children:[(0,Y.jsxs)(`p`,{className:`flex min-w-0 flex-1 items-center px-2 text-[12px] text-amber-900 dark:text-amber-300`,children:[`No value in `,t,e.readers[0]?(0,Y.jsxs)(`span`,{className:`text-muted-foreground`,children:[` `,`· `,(0,Y.jsx)(`span`,{className:`font-mono`,children:e.readers[0]}),` will fail boot`]}):(0,Y.jsx)(`span`,{className:`text-muted-foreground`,children:` · boot gap until a layer provides one`})]}),(0,Y.jsx)(L,{type:`button`,size:`sm`,onClick:c,className:`h-full shrink-0 rounded-none`,children:`Set`})]}):s&&q(e.rotate)?(0,Y.jsxs)(`section`,{className:r(w,`border-amber-500/25 bg-amber-500/5`),"aria-label":`Rotation overdue`,role:`status`,children:[(0,Y.jsxs)(`p`,{className:`flex min-w-0 flex-1 items-center px-2 text-[12px] text-amber-900 dark:text-amber-300`,children:[`Past rotate `,e.rotate,(0,Y.jsx)(`span`,{className:`text-muted-foreground`,children:` · blast is clear`})]}),(0,Y.jsx)(L,{type:`button`,variant:`destructive`,size:`sm`,onClick:l,className:`h-full shrink-0 rounded-none`,children:`Rotate`})]}):null}function Ot({title:e,meta:t,children:n}){return(0,Y.jsxs)(`header`,{className:r(w,`items-center gap-2 px-2`),children:[(0,Y.jsx)(`h3`,{className:r(ve,`shrink-0 leading-none`),children:e}),n,t?(0,Y.jsx)(`span`,{className:`ml-auto shrink-0 font-mono text-[10px] leading-none tabular-nums text-muted-foreground`,children:t}):null]})}function X({label:e,value:t,hint:n,warn:i=!1,won:a=!1,onClick:o}){let s=r(_,ge,`gap-1.5`),c=(0,Y.jsxs)(Y.Fragment,{children:[(0,Y.jsx)(`span`,{className:`tracking-[0.08em] uppercase`,children:e}),(0,Y.jsx)(`span`,{className:r(`font-mono tabular-nums text-foreground`,i&&`text-amber-800 dark:text-amber-400`,a&&bt),children:t})]});return o?(0,Y.jsx)(`button`,{type:`button`,title:n,onClick:o,className:s,children:c}):(0,Y.jsx)(`span`,{title:n,className:s,children:c})}function kt({steps:e,selected:t,fill:n,backend:i,onSelect:a}){let o=e.findIndex(e=>e.won);return(0,Y.jsxs)(`section`,{className:`shrink-0 border-b border-border/60`,"aria-label":`Resolution chain`,children:[(0,Y.jsx)(Ot,{title:`Resolution`,meta:`first hit wins`}),(0,Y.jsxs)(`ol`,{className:`relative`,"data-slot":`vault-lock-path`,children:[(0,Y.jsx)(`span`,{className:`pointer-events-none absolute top-3 bottom-3 left-[15px] w-px bg-border/60`,"aria-hidden":!0}),e.map((e,s)=>{let c=e.source===t.source,l=wt(e,s,o);return(0,Y.jsxs)(`li`,{children:[(0,Y.jsxs)(`button`,{type:`button`,"aria-pressed":c,onClick:()=>a(e.source),className:r(S,c&&`bg-muted/70 text-foreground`,o>=0&&s>o&&!c&&`opacity-50`),children:[(0,Y.jsx)(`span`,{className:r(F,c&&`bg-sky-500`),"aria-hidden":!0}),(0,Y.jsx)(`span`,{className:r(`relative z-10 size-2 shrink-0 rounded-full border`,l===`won`&&`border-emerald-500 bg-emerald-500`,l===`shadowed`&&`border-muted-foreground/50 bg-muted-foreground/40`,l===`missed`&&`border-muted-foreground/50 bg-transparent`,l===`skipped`&&`border-border bg-transparent`),"aria-hidden":!0}),(0,Y.jsx)(I,{icon:yt[e.source],className:r(k,l===`won`?bt:`text-muted-foreground`),"aria-hidden":!0}),(0,Y.jsxs)(`span`,{className:r(`min-w-0 flex-1 truncate font-mono`,l===`won`?bt:`text-foreground`),children:[vt[e.source],e.source===`driver`?(0,Y.jsx)(`span`,{className:`ml-1.5 font-sans text-[10px] text-muted-foreground`,children:Ge(i)}):null]}),(0,Y.jsx)(`span`,{className:r(`shrink-0 text-[10px]`,l===`won`?bt:`text-muted-foreground`),children:l})]}),c?(0,Y.jsxs)(`div`,{className:`flex items-center gap-2 border-b border-border/60 py-1.5 pr-2 pl-8`,children:[(0,Y.jsx)(`p`,{className:`min-w-0 flex-1 truncate font-mono text-[11px] text-muted-foreground`,children:n.command}),(0,Y.jsx)(`span`,{className:`hidden min-w-0 truncate text-[10px] text-muted-foreground sm:inline`,children:n.hint}),(0,Y.jsx)(Be,{value:n.command,label:`Copy ${e.source} fill`})]}):null]},e.source)})]}),(0,Y.jsxs)(`p`,{className:`sr-only`,children:[`Winner: `,e.find(e=>e.won)?.source??`none`,`. `,n.hint]})]})}function At({slots:e,env:t}){return(0,Y.jsx)(`ul`,{"data-slot":`vault-fingerprints`,children:e.map(e=>(0,Y.jsxs)(`li`,{className:S,children:[(0,Y.jsxs)(`span`,{className:`shrink-0 font-mono text-[11px] text-muted-foreground`,children:[e.env,e.env===t?(0,Y.jsx)(`span`,{className:`ml-1 text-[10px] text-muted-foreground`,children:`this`}):null]}),e.fp?(0,Y.jsx)(`span`,{className:`min-w-0 flex-1 truncate font-mono text-[11px]`,children:e.fp}):(0,Y.jsx)(`span`,{className:`min-w-0 flex-1 text-[11px] text-muted-foreground`,children:`—`}),e.shared?(0,Y.jsxs)(`span`,{role:`status`,className:`shrink-0 text-[10px] text-amber-800 dark:text-amber-400`,children:[`matches `,t]}):null,e.fp?(0,Y.jsx)(Be,{value:e.fp,label:`Copy ${e.env} fingerprint`}):null]},e.env))})}function jt(e,t){let n=new Set,r=[],i=(t,i)=>{n.has(t)||(n.add(t),r.push({env:t,fp:i,shared:i!=null&&e.sharedFingerprintEnvs.includes(t)}))};i(t,e.fingerprint);for(let[t,n]of Object.entries(e.fingerprints))i(t,n);return r}function Mt({readers:e,name:t,onFilterReader:n}){return(0,Y.jsxs)(`section`,{className:`shrink-0 border-b border-border/60`,"aria-label":`Readers`,children:[(0,Y.jsx)(Ot,{title:`Readers`,meta:String(e.length),children:(0,Y.jsx)(`code`,{className:`min-w-0 truncate font-mono text-[10px] leading-none text-muted-foreground`,children:et(t)})}),e.length===0?(0,Y.jsx)(`p`,{className:`px-2 py-1.5 text-[11px] text-muted-foreground`,children:`None declared.`}):(0,Y.jsx)(`ul`,{children:e.map(e=>(0,Y.jsx)(`li`,{children:(0,Y.jsxs)(`div`,{className:r(S,`group/reader`),children:[(0,Y.jsx)(I,{icon:V.flow.icon,className:r(k,`text-sky-500`),"aria-hidden":!0}),(0,Y.jsx)(`span`,{className:`min-w-0 flex-1 truncate font-mono text-xs`,children:e}),(0,Y.jsxs)(`div`,{className:r(h,`group-hover/reader:opacity-100 group-focus-within/reader:opacity-100`),children:[n?(0,Y.jsx)(`button`,{type:`button`,className:`shrink-0 text-[10px] text-muted-foreground hover:text-foreground`,onClick:()=>n(e),children:`filter`}):null,(0,Y.jsx)(R,{to:`/flows`,search:{flow:e},className:`shrink-0 text-[10px] text-muted-foreground hover:text-foreground`,children:`Flows`}),(0,Y.jsx)(R,{to:`/overview`,search:{flow:e},className:`shrink-0 text-[10px] text-muted-foreground hover:text-foreground`,children:`Graph`})]})]})},e))})]})}function Nt({loading:e=!1,hasContracts:t,query:n,onClearQuery:r,leading:i}){return e?(0,Y.jsx)(`div`,{"data-slot":`vault-overview`,className:`h-full`,children:(0,Y.jsx)(Fe,{icon:V.vault.icon,iconClassName:`border-border/70`,title:`Loading vault…`,description:`Reading contracts and posture.`,leading:i})}):(0,Y.jsx)(`div`,{"data-slot":`vault-overview`,className:`h-full`,children:(0,Y.jsx)(Fe,{icon:V.vault.icon,iconClassName:`border-border/70`,title:t?`No contracts match`:`No contracts`,leading:i,description:t?(0,Y.jsxs)(Y.Fragment,{children:[`Nothing matches `,(0,Y.jsx)(`span`,{className:`font-mono`,children:n}),`.`,` `,(0,Y.jsx)(`button`,{type:`button`,className:`underline underline-offset-2 hover:text-foreground`,onClick:r,children:`Clear search`})]}):`Declare vault.secret (fingerprinted) or vault.config (shown in the Config band) in the Manifest.`})})}var Pt={secret:`border-indigo-500/40 bg-indigo-500/12 text-indigo-600 dark:text-indigo-300`,config:`border-emerald-500/40 bg-emerald-500/10 text-emerald-700 dark:text-emerald-400`},Ft={secret:V.vault.icon,config:l},It={secret:`fingerprints only`,config:`vault.config · shown in clear`},Lt={blast:`border-destructive/40 bg-destructive/10 text-destructive`,unset:`border-amber-500/40 bg-amber-500/10 text-amber-700 dark:text-amber-400`,overdue:`border-amber-500/40 bg-amber-500/10 text-amber-700 dark:text-amber-400`,shared:`border-amber-500/40 bg-amber-500/10 text-amber-700 dark:text-amber-400`,dormant:`border-zinc-500/35 bg-zinc-500/10 text-zinc-500 dark:text-zinc-400`,healthy:Pt.secret,config:Pt.config},Rt={blast:le,unset:oe,overdue:m,shared:ue,dormant:oe,healthy:V.vault.icon,config:l},zt={blast:`text-destructive`,unset:`text-amber-800 dark:text-amber-400`,overdue:`text-amber-800 dark:text-amber-400`,shared:`text-amber-800 dark:text-amber-400`,dormant:`text-muted-foreground`,healthy:`text-indigo-600 dark:text-indigo-300`,config:`text-emerald-700 dark:text-emerald-400`};function Bt({groups:e,selectedName:n,loading:i=!1,matchCount:a,totalCount:o,now:s,onSelect:l}){let[f,p]=(0,K.useState)({secret:!0,config:!0});return(0,K.useEffect)(()=>{let t=e.find(e=>e.secrets.some(e=>e.name===n));t&&p(e=>e[t.kind]===!1?{...e,[t.kind]:!0}:e)},[e,n]),(0,Y.jsxs)(`div`,{className:`flex min-h-0 flex-1 flex-col overflow-hidden`,"data-slot":`vault-list`,children:[(0,Y.jsxs)(`div`,{className:`min-h-0 flex-1 overflow-y-auto`,children:[i&&e.length===0?(0,Y.jsx)(`p`,{className:M,children:`Loading…`}):null,!i&&e.length===0?(0,Y.jsxs)(`p`,{className:M,children:[`No contracts match. Try `,(0,Y.jsx)(`span`,{className:`font-mono`,children:`is:unset`}),` or clear the search.`]}):null,e.map(e=>{let i=f[e.kind]!==!1;return(0,Y.jsx)(`section`,{"aria-label":e.label,className:u,"data-slot":`vault-kind-band`,"data-kind":e.kind,children:(0,Y.jsxs)(We,{open:i,onOpenChange:t=>p(n=>({...n,[e.kind]:t})),children:[(0,Y.jsx)(Ue,{nativeButton:!1,className:t,"data-slot":`vault-kind-band-toggle`,render:t=>(0,Y.jsxs)(`div`,{...t,children:[(0,Y.jsx)(I,{icon:c,className:r(N,!i&&`-rotate-90`),"aria-hidden":!0}),(0,Y.jsx)(I,{icon:Ft[e.kind],className:r(k,d(Pt[e.kind])),"aria-hidden":!0}),(0,Y.jsx)(`span`,{className:r(C,`flex-1`),title:It[e.kind],children:e.label}),(0,Y.jsx)(`span`,{className:pe,children:e.secrets.length})]})}),(0,Y.jsx)(He,{children:(0,Y.jsx)(`ul`,{className:`flex flex-col`,children:e.secrets.map(e=>(0,Y.jsx)(Vt,{row:e,selected:e.name===n,now:s,onSelect:l},e.name))})})]})},e.kind)})]}),e.length>0?(0,Y.jsx)(`p`,{className:`sr-only`,children:a===o?`${o} contracts`:`${a} of ${o} contracts`}):null]})}function Vt({row:e,selected:t,now:n,onSelect:i}){let a=e.description?.trim()||e.name,o=e.kind===`config`?e.cleartext??`unset`:e.name,s=o!==a,c=pt(e,n),l=c.primary!==`healthy`&&c.primary!==`config`,u=e.readers.length===0?`no readers`:`${e.readers.length} reader${e.readers.length===1?``:`s`}`,f=[e.origin===`console`?`console`:null,e.kind===`secret`&&!q(e.rotate)?`no rotate`:null].filter(e=>e!==null);return(0,Y.jsx)(`li`,{children:(0,Y.jsxs)(`button`,{type:`button`,"aria-current":t?`true`:void 0,"aria-label":`${a}, ${o}, ${u}, ${gt(c.primary)}`,onClick:()=>i(e.name),className:r(S,`items-start py-2`,t&&`bg-muted/70 text-foreground`),children:[(0,Y.jsx)(`span`,{"aria-hidden":!0,className:r(F,t&&`bg-[var(--vault-accent)]`),style:{"--vault-accent":J}}),(0,Y.jsx)(B,{label:_t(c.primary,e.rotate),children:(0,Y.jsx)(I,{icon:Rt[c.primary],className:r(k,`mt-0.5`,d(Lt[c.primary])),"aria-hidden":!0})}),(0,Y.jsxs)(`span`,{className:`min-w-0 flex-1`,children:[(0,Y.jsxs)(`span`,{className:`flex items-center gap-2`,children:[(0,Y.jsx)(`span`,{className:`min-w-0 flex-1 truncate font-medium text-foreground`,children:a}),l?(0,Y.jsx)(Ht,{posture:c}):null]}),(0,Y.jsxs)(`span`,{className:`mt-0.5 flex min-w-0 items-center gap-1.5 text-[10px] text-muted-foreground`,children:[s?(0,Y.jsx)(`span`,{className:`min-w-0 truncate font-mono`,children:o}):null,s?(0,Y.jsx)(`span`,{"aria-hidden":!0,children:`·`}):null,(0,Y.jsx)(`span`,{className:`shrink-0 tabular-nums`,children:u}),f.map(e=>(0,Y.jsxs)(`span`,{className:`shrink-0`,children:[`· `,e]},e))]})]})]})})}function Ht({posture:e}){return(0,Y.jsx)(`span`,{role:`status`,className:r(`shrink-0 text-[10px] font-medium`,zt[e.primary]),children:gt(e.primary)})}var Ut=new Set([`unset`,`set`,`dormant`,`blast`,`shared`,`overdue`,`unread`,`healthy`]),Wt=new Set([`secret`,`config`]),Gt=new Set([`readers`,`rotate`,`blast`,`shared`]),Kt=[{token:`is:unset`,label:`No value in this environment`},{token:`is:set`,label:`Has a fingerprint or config value`},{token:`is:blast`,label:`In-flight durable runs hold this secret`},{token:`is:shared`,label:`Fingerprint matches another environment`},{token:`is:dormant`,label:`Unread for 90 days, or never`},{token:`is:overdue`,label:`Last read older than rotate — never-read counts`},{token:`is:healthy`,label:`Set, no blast, no shared, not dormant`},{token:`kind:secret`,label:`Sensitive contracts only`},{token:`kind:config`,label:`Non-sensitive config only`},{token:`from:.env.local`,label:`Winner is .env.local`},{token:`from:driver`,label:`Winner is the vault backend (built-in / managed / memory)`},{token:`has:readers`,label:`At least one Flow declares a read`},{token:`has:rotate`,label:`Contract declares a rotate cadence`},{token:`rotate:never`,label:`No rotate cadence (stable secret)`},{token:`reader:`,label:`Flow id contains…`},{token:`fp:`,label:`Fingerprint contains…`}],qt=[`driver`,`process.env`,`.env.local`,`dev-fallback`];function Jt(e){let t=[],n=/"([^"]+)"|(\S+)/g,r;for(;(r=n.exec(e))!==null;){let e=r[1]??r[2]??``;e.length>0&&t.push(e)}return t}function Yt(e){let t=[];for(let n of Jt(e)){let e=nn(n);e?t.push(e):t.push({kind:`text`,value:n})}return{tokens:t,raw:e}}function Xt(e){let t=[],n=[];for(let r of e){if(r.kind===`text`){n.push(sn(r.value)?`"${r.value}"`:r.value);continue}t.push(`${r.kind}:${r.value}`)}return[...t,...n].join(` `).trim()}function Zt(e,t){let n=Yt(e);return Xt(n.tokens.some(e=>e.kind===`is`&&e.value===t)?n.tokens.filter(e=>e.kind!==`is`||e.value!==t):[...n.tokens,{kind:`is`,value:t}])}function Qt(e,t){return Yt(e).tokens.some(e=>e.kind===`is`&&e.value===t)}function $t(e,t,n){if(t.tokens.length===0)return!0;let r=pt(e,n);for(let n of t.tokens)if(!rn(e,n,r))return!1;return!0}function en(e,t){let n=cn(e);if(n===null)return Kt;let r=n.toLowerCase();if(r.startsWith(`is:`)||r===`is`)return Z(Kt.filter(e=>e.token.startsWith(`is:`)),n);if(r.startsWith(`kind:`)||r===`kind`)return Z([{token:`kind:secret`,label:`Sensitive contracts only`},{token:`kind:config`,label:`Non-sensitive config only`}],n);if(r.startsWith(`from:`)||r===`from`)return Z(qt.map(e=>({token:`from:${e}`,label:e===`driver`?`Winner is the vault backend (built-in / managed / memory)`:`Winner is ${e}`})),n);if(r.startsWith(`has:`)||r===`has`)return Z(Kt.filter(e=>e.token.startsWith(`has:`)),n);if(r.startsWith(`reader:`)||r===`reader`){let e=r.startsWith(`reader:`)?r.slice(7):``,n=new Set;for(let r of t)for(let t of r.readers)(e.length===0||t.toLowerCase().includes(e))&&n.add(t);return[...n].slice(0,8).map(e=>({token:`reader:${e}`,label:`Flow that reads this contract`}))}if(r.startsWith(`fp:`)||r===`fp`){let e=r.startsWith(`fp:`)?r.slice(3):``,n=new Set;for(let r of t){for(let t of Object.values(r.fingerprints))(e.length===0||t.toLowerCase().includes(e))&&n.add(t);r.fingerprint&&(e.length===0||r.fingerprint.toLowerCase().includes(e))&&n.add(r.fingerprint)}return[...n].slice(0,8).map(e=>({token:`fp:${e}`,label:`Exact fingerprint`}))}if(r.startsWith(`rotate:`)||r===`rotate`)return Z([{token:`rotate:due`,label:`Last read older than rotate — never-read counts`},{token:`has:rotate`,label:`Contract declares a rotate cadence`},{token:`rotate:never`,label:`No rotate cadence (stable secret)`}],n);let i=r;return Kt.filter(e=>e.token.includes(i)||e.label.toLowerCase().includes(i))}function tn(e,t){if(e.length===0||/\s$/.test(e))return`${e}${t} `.replace(/^\s+/,``);let n=e.lastIndexOf(` `);return n<0?`${t} `:`${e.slice(0,n+1)}${t} `}function nn(e){if(e.startsWith(`"`))return null;let t=e.indexOf(`:`);if(t<=0)return null;let n=e.slice(0,t).toLowerCase(),r=e.slice(t+1);if(r.length===0)return null;if(n===`is`){let e=r.toLowerCase();return Ut.has(e)?{kind:`is`,value:e}:Wt.has(e)?{kind:`kind`,value:e}:null}if(n===`kind`){let e=r.toLowerCase();return Wt.has(e)?{kind:`kind`,value:e}:null}if(n===`from`)return{kind:`from`,value:r.toLowerCase()};if(n===`reader`)return{kind:`reader`,value:r.toLowerCase()};if(n===`fp`)return{kind:`fp`,value:r.toLowerCase()};if(n===`has`){let e=r.toLowerCase();return Gt.has(e)?{kind:`has`,value:e}:null}if(n===`rotate`){let e=r.toLowerCase();return e===`due`?{kind:`is`,value:`overdue`}:{kind:`rotate`,value:e}}return null}function rn(e,t,n){switch(t.kind){case`is`:return n[t.value];case`kind`:return e.kind===t.value;case`from`:return(e.winner??``).toLowerCase()===t.value;case`reader`:return e.readers.some(e=>e.toLowerCase().includes(t.value));case`fp`:return an(e).some(e=>e.includes(t.value));case`has`:return t.value===`readers`?e.readers.length>0:t.value===`rotate`?q(e.rotate):t.value===`blast`?e.blastRadius.count>0:e.sharedFingerprintEnvs.length>0;case`rotate`:return t.value===`never`?e.kind===`secret`&&!q(e.rotate):(e.rotate??``).toLowerCase()===t.value;case`text`:return on(e).includes(t.value.toLowerCase())}}function an(e){let t=Object.values(e.fingerprints).map(e=>e.toLowerCase());return e.fingerprint&&t.push(e.fingerprint.toLowerCase()),t}function on(e){return[e.name,e.description??``,e.winner??``,e.kind,...e.readers,...Object.keys(e.fingerprints),...Object.values(e.fingerprints),e.fingerprint??``,e.sensitive?``:e.cleartext??``].join(`
|
|
2
|
+
`).toLowerCase()}function sn(e){return/\s/.test(e)}function cn(e){if(e.length===0||/\s$/.test(e))return null;let t=Jt(e);return t[t.length-1]??null}function Z(e,t){let n=t.toLowerCase();return e.filter(e=>e.token.toLowerCase().startsWith(n)||e.token.toLowerCase().includes(n))}function ln({card:e,env:t,summary:n,query:i,progress:a,verifyNote:o,onQueryChange:s,onOpenSecurity:c}){return(0,Y.jsxs)(`section`,{"aria-label":`Vault posture`,className:`shrink-0 border-b border-border/60`,"data-slot":`vault-posture-strip`,children:[(0,Y.jsxs)(`div`,{className:`flex min-h-10 flex-wrap items-stretch`,children:[(0,Y.jsx)(`button`,{type:`button`,onClick:c,"aria-label":`Open vault security`,className:`flex items-center px-2 text-left text-xs font-medium text-foreground hover:bg-muted/50`,children:e?.title??`Vault backend`}),(0,Y.jsx)(`span`,{className:`flex items-center px-2 font-mono text-[10px] text-muted-foreground`,children:t}),e?.badges.map(e=>(0,Y.jsxs)(`span`,{role:e.tone===`warn`?`alert`:`status`,className:r(`flex items-center gap-1.5 px-2 text-[10px]`,e.tone===`warn`?`text-amber-800 dark:text-amber-400`:`text-muted-foreground`,e.id===`rewrap`&&`text-[color:var(--vault-accent)]`),style:e.id===`rewrap`?{"--vault-accent":J}:void 0,children:[(0,Y.jsx)(`span`,{"aria-hidden":!0,className:r(`size-1.5 shrink-0 rounded-full`,e.tone===`warn`?`bg-amber-500`:`bg-muted-foreground/50`,e.id===`rewrap`&&`bg-[var(--vault-accent)]`)}),e.label]},e.id)),st.map(e=>{let t=n[e.id],a=Qt(i,e.token);return t===0&&!a?null:(0,Y.jsx)(B,{label:_t(e.id),className:`flex self-stretch`,children:(0,Y.jsxs)(`button`,{type:`button`,"aria-pressed":a,onClick:()=>s(Zt(i,e.token)),className:r(_,a?ie:ge,e.tone===`danger`&&!a&&`text-destructive`,e.tone===`warn`&&!a&&`text-amber-800 dark:text-amber-400`),children:[e.label,(0,Y.jsx)(`span`,{className:`font-mono tabular-nums`,children:t})]})},e.id)}),(0,Y.jsx)(`span`,{className:`ml-auto flex items-center px-2 font-mono text-[10px] text-muted-foreground`,children:o??`${n.secrets}s · ${n.config}c`})]}),a?(0,Y.jsxs)(`p`,{className:`border-t border-border/60 px-2 py-1 font-mono text-[11px]`,style:{color:J},role:`status`,"data-slot":`vault-rewrap-progress`,"data-phase":a.phase,children:[a.headline,(0,Y.jsx)(`span`,{className:`ml-2 font-sans text-muted-foreground`,children:a.detail})]}):null]})}function un({query:e,secrets:t,onQueryChange:n}){let i=(0,K.useId)(),a=(0,K.useRef)(null),[o,s]=(0,K.useState)(!1),[c,l]=(0,K.useState)(0),u=(0,K.useMemo)(()=>en(e,t),[e,t]);(0,K.useEffect)(()=>{l(0)},[e]),(0,K.useEffect)(()=>{let e=e=>{a.current?.contains(e.target)||s(!1)};return document.addEventListener(`mousedown`,e),()=>document.removeEventListener(`mousedown`,e)},[]);let d=t=>{n(tn(e,t.token)),s(!0)};return(0,Y.jsxs)(`div`,{ref:a,className:`relative flex h-full min-w-0 flex-1`,"data-slot":`vault-search`,children:[(0,Y.jsx)(Ae,{"data-slot":`vault-search-input`,value:e,onChange:e=>{n(e.target.value),s(!0)},onFocus:()=>s(!0),onKeyDown:e=>{if(e.key===`Escape`){s(!1);return}if(!o||u.length===0){e.key===`ArrowDown`&&u.length>0&&(e.preventDefault(),s(!0));return}if(e.key===`ArrowDown`){e.preventDefault(),l(e=>(e+1)%u.length);return}if(e.key===`ArrowUp`){e.preventDefault(),l(e=>(e-1+u.length)%u.length);return}e.key===`Enter`&&u[c]&&(e.preventDefault(),d(u[c]))},placeholder:`Search vault…`,"aria-label":`Search vault`,"aria-autocomplete":`list`,"aria-expanded":o,"aria-controls":i,role:`combobox`,title:`name, fingerprint, reader… is:unset from:.env.local`}),o&&u.length>0?(0,Y.jsx)(`ul`,{id:i,role:`listbox`,className:`absolute top-full z-30 mt-1 max-h-72 w-[min(20rem,calc(100vw-4rem))] overflow-y-auto rounded-lg border border-border/70 bg-popover p-1 shadow-md`,children:u.map((e,t)=>(0,Y.jsx)(`li`,{role:`option`,"aria-selected":t===c,children:(0,Y.jsxs)(`button`,{type:`button`,onMouseEnter:()=>l(t),onClick:()=>d(e),className:r(`flex w-full items-baseline gap-2 rounded-md px-2 py-1.5 text-left`,t===c&&`bg-muted/70`),children:[(0,Y.jsx)(`span`,{className:`font-mono text-[11px] text-foreground`,children:e.token}),(0,Y.jsx)(`span`,{className:`min-w-0 flex-1 truncate text-[10px] text-muted-foreground`,children:e.label})]})},`${e.token}-${t}`))}):null]})}function dn(e,t=``,n=Date.now()){let r=Yt(t),i=e.filter(e=>$t(e,r,n)),a=[`secret`,`config`],o={secret:`Secrets`,config:`Config`};return a.map(e=>({kind:e,label:o[e],secrets:i.filter(t=>t.kind===e)})).filter(e=>e.secrets.length>0)}function fn(e){let t=e.remaining,n=e.rewrapTargetKekVersion;if(!(t!==null&&t>0||n!==null))return t===0?{phase:2,headline:`KEK v${e.kekVersion} — rotation complete`,detail:`The previous master key no longer opens this vault.`}:null;let r=n??e.kekVersion,i=t??0;return{phase:1,headline:`kek v${e.kekVersion} → v${r}`,detail:i>0?`${i} DEK${i===1?``:`s`} still on the old key. Both master keys stay live.`:`Both master keys stay live until remaining is 0.`}}function pn({masterKey:e,onDismiss:t}){let[n,r]=(0,K.useState)(!1);return(0,Y.jsx)(T,{open:e!==null,onOpenChange:e=>{e||t()},children:(0,Y.jsxs)(O,{side:`right`,showOverlay:!1,className:`sm:max-w-md`,"data-slot":`vault-master-key-sheet`,children:[(0,Y.jsxs)(E,{children:[(0,Y.jsx)(P,{children:`New master key`}),(0,Y.jsx)(j,{children:`Shown once. Store it offline. This Console process does not keep it for you.`})]}),(0,Y.jsxs)(`div`,{className:`flex min-h-0 flex-1 flex-col overflow-y-auto`,children:[(0,Y.jsx)(`p`,{className:`border-b border-border/50 px-4 py-3 font-mono text-[11px] break-all`,children:e}),(0,Y.jsx)(`p`,{className:`px-4 py-3 text-[11px] text-muted-foreground`,role:`status`,children:`Copying puts the key on the clipboard. Anyone with this device can read it until you clear it.`})]}),(0,Y.jsxs)(x,{children:[(0,Y.jsx)(W,{split:!0,disabled:!e,onClick:()=>{e&&(navigator.clipboard?.writeText(e),r(!0))},children:n?`Copied`:`Copy (clipboard warning)`}),(0,Y.jsx)(W,{variant:`destructive`,onClick:()=>{r(!1),t()},children:`I have stored this key`})]})]})})}function mn({open:e,onOpenChange:t,pending:n=!1,error:r,onConfirm:i}){return(0,Y.jsx)(ze,{open:e,onOpenChange:t,phrase:`ROTATE_MASTER`,title:`Rotate master key`,description:`Generates a new master key and rewraps DEKs in batches. Both keys stay live until remaining is 0. The new key is shown once.`,pending:n,error:r,confirmLabel:`Confirm rotate master`,slot:`vault-rotate-master-sheet`,onConfirm:i})}var hn=[{id:`status`,cmd:`oke vault status`,label:`Backend seal + KEK`},{id:`audit`,cmd:`oke vault audit`,label:`Hash-chained audit log`},{id:`verify`,cmd:`oke vault audit verify`,label:`Verify the chain on disk`},{id:`backup`,cmd:`oke vault backup`,label:`Encrypted backup`},{id:`restore`,cmd:`oke vault restore`,label:`Restore from backup`}];function gn({open:e,onOpenChange:t,card:n,env:i,progress:a,verifyPending:o=!1,verifyNote:s,onVerify:c,onRotateMaster:l,onExport:u}){return(0,Y.jsx)(T,{open:e,onOpenChange:t,children:(0,Y.jsxs)(O,{side:`right`,showOverlay:!1,className:`sm:max-w-md`,"data-slot":`vault-security-sheet`,children:[(0,Y.jsxs)(E,{children:[(0,Y.jsx)(P,{children:`Vault security`}),(0,Y.jsx)(j,{children:`Fingerprints and backend status only. Backup, restore, and unseal stay on the CLI.`})]}),(0,Y.jsxs)(`div`,{className:`flex min-h-0 flex-1 flex-col overflow-y-auto`,children:[(0,Y.jsxs)(`section`,{className:`flex flex-col gap-2 border-b border-border/50 px-4 py-3`,children:[(0,Y.jsx)(`h3`,{className:`text-[10px] font-semibold tracking-[0.12em] text-muted-foreground uppercase`,children:`Backend`}),(0,Y.jsx)(`p`,{className:`text-[12px] font-medium`,children:n?.title??`Unresolved`}),(0,Y.jsx)(`p`,{className:`text-[11px] text-muted-foreground`,children:n?.description??`The server could not resolve a vault backend.`}),(0,Y.jsxs)(`div`,{className:`flex flex-wrap items-center gap-1.5`,children:[(0,Y.jsxs)(`span`,{className:`font-mono text-[10px] text-muted-foreground`,children:[`env `,i]}),n?.badges.map(e=>(0,Y.jsx)(Ve,{variant:`outline`,role:e.tone===`warn`?`alert`:`status`,className:r(`h-5 rounded-md text-[10px]`,e.tone===`warn`&&`border-amber-500/35 bg-amber-500/10 text-amber-800 dark:text-amber-400`),children:e.label},e.id))]}),n?.facts.length?(0,Y.jsx)(`dl`,{className:`flex flex-col gap-1`,children:n.facts.map(e=>(0,Y.jsxs)(`div`,{className:`flex justify-between gap-3`,children:[(0,Y.jsx)(`dt`,{className:`text-[10px] tracking-[0.12em] text-muted-foreground uppercase`,children:e.label}),(0,Y.jsx)(`dd`,{className:`font-mono text-[11px]`,children:e.value})]},e.label))}):null,n?.hint?(0,Y.jsx)(`p`,{className:`text-[11px] text-muted-foreground`,role:`status`,children:n.hint}):null,a?(0,Y.jsxs)(`p`,{className:`font-mono text-[11px]`,style:{color:J},role:`status`,children:[a.headline,(0,Y.jsx)(`span`,{className:`ml-2 font-sans text-muted-foreground`,children:a.detail})]}):null]}),(0,Y.jsxs)(`section`,{className:`flex flex-col gap-2 border-b border-border/50 px-4 py-3`,children:[(0,Y.jsx)(`h3`,{className:`text-[10px] font-semibold tracking-[0.12em] text-muted-foreground uppercase`,children:`Actions`}),(0,Y.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,Y.jsx)(L,{type:`button`,variant:`outline`,size:`sm`,disabled:o,onClick:c,children:`Verify audit chain`}),s?(0,Y.jsx)(`p`,{className:`text-[11px] text-muted-foreground`,role:`status`,children:s}):null,(0,Y.jsx)(L,{type:`button`,variant:`outline`,size:`sm`,onClick:l,children:`Rotate master key`}),(0,Y.jsx)(L,{type:`button`,variant:`outline`,size:`sm`,onClick:u,children:`Export fingerprints`})]}),(0,Y.jsx)(`p`,{className:`text-[11px] text-muted-foreground`,children:`Master rotation rewraps DEKs in batches. Both keys stay live until remaining is 0. The new key is shown once.`})]}),(0,Y.jsxs)(`section`,{className:`flex flex-col gap-2 px-4 py-3`,children:[(0,Y.jsx)(`h3`,{className:`text-[10px] font-semibold tracking-[0.12em] text-muted-foreground uppercase`,children:`CLI`}),(0,Y.jsx)(`p`,{className:`text-[11px] text-muted-foreground`,children:`The Console never accepts a master key in the HTTP body.`}),(0,Y.jsx)(`ul`,{className:`flex flex-col gap-1`,children:hn.map(e=>(0,Y.jsx)(_n,{cmd:e.cmd,label:e.label},e.id))})]})]})]})})}function _n({cmd:e,label:t}){let[n,r]=(0,K.useState)(!1);return(0,Y.jsxs)(`li`,{className:`flex items-center gap-2`,children:[(0,Y.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,Y.jsx)(`p`,{className:`font-mono text-[11px]`,children:e}),(0,Y.jsx)(`p`,{className:`text-[10px] text-muted-foreground`,children:t})]}),(0,Y.jsx)(L,{type:`button`,variant:`ghost`,size:`icon-xs`,"aria-label":`Copy ${e}`,onClick:()=>{navigator.clipboard?.writeText(e),r(!0),window.setTimeout(()=>r(!1),1200)},children:(0,Y.jsx)(I,{icon:n?fe:s})})]})}function vn({result:e,onClose:t}){let n=e!==null&&e.ok===!1,r=e?.reason===`link`?`prev-hash does not match the previous row`:e?.reason===`payload`?`stored row hash does not match the payload`:`the chain failed verification`;return(0,Y.jsx)(T,{open:n,onOpenChange:e=>{e||t()},children:(0,Y.jsxs)(O,{side:`right`,showOverlay:!1,className:`sm:max-w-md`,"data-slot":`vault-verify-sheet`,children:[(0,Y.jsxs)(E,{children:[(0,Y.jsx)(P,{children:`Chain broken`}),(0,Y.jsxs)(j,{children:[`The audit hash chain failed at`,` `,(0,Y.jsx)(`span`,{className:`font-mono`,children:e?.brokenAt??`unknown`}),`.`]})]}),(0,Y.jsxs)(`div`,{className:`flex min-h-0 flex-1 flex-col overflow-y-auto text-[11px]`,children:[(0,Y.jsxs)(`p`,{className:`border-b border-border/50 px-4 py-3`,role:`alert`,children:[`Reason: `,r,`.`]}),e?.row?(0,Y.jsxs)(`dl`,{className:`divide-y divide-border/50`,children:[(0,Y.jsx)(Q,{label:`id`,value:e.row.id,mono:!0}),(0,Y.jsx)(Q,{label:`seq`,value:String(e.row.seq),mono:!0}),(0,Y.jsx)(Q,{label:`action`,value:e.row.action}),(0,Y.jsx)(Q,{label:`path`,value:e.row.path??`—`,mono:!0}),(0,Y.jsx)(Q,{label:`actor`,value:`${e.row.actorType} ${e.row.actorId??``}`}),(0,Y.jsx)(Q,{label:`time`,value:new Date(e.row.createdAt).toISOString(),mono:!0}),e.row.errorMessage?(0,Y.jsx)(Q,{label:`error`,value:e.row.errorMessage}):null]}):null]}),(0,Y.jsx)(x,{children:(0,Y.jsx)(W,{onClick:t,children:`Close`})})]})})}function Q({label:e,value:t,mono:n}){return(0,Y.jsxs)(`div`,{className:`px-4 py-2.5`,children:[(0,Y.jsx)(`dt`,{className:`text-[10px] font-semibold tracking-[0.12em] text-muted-foreground uppercase`,children:e}),(0,Y.jsx)(`dd`,{className:n?`font-mono text-[11px] break-all`:`text-[11px]`,children:t})]})}async function yn(e){let t=await crypto.subtle.digest(`SHA-256`,new TextEncoder().encode(e));return`sha256:${[...new Uint8Array(t)].map(e=>e.toString(16).padStart(2,`0`)).join(``).slice(0,16)}`}async function bn(e){let t=e.name.trim(),n=e.value;if(t.length===0)return{error:`Name is required`};if(n.trim().length===0)return{error:`Value is required`};if(e.action!==`create`&&(e.reason?.trim()??``).length<3)return{error:`Reason is required`};let r=e.kind??(e.sensitive?`secret`:`config`),i=await yn(n),a=e.action===`create`?null:e.reason?.trim()??null;return{action:e.action,name:t,kind:r,fingerprint:i,preview:e.sensitive?null:n,reason:a,rotate:e.rotate??null,commit:{name:t,value:n,reason:a,kind:r,description:e.description?.trim()??``,rotate:e.rotate??(r===`secret`?`90d`:`never`)}}}function xn(e,t){return e===null?null:t(e)}function Sn(){return null}function Cn(e){return A(`alert-dialog`,e)}function wn({...e}){return(0,Y.jsx)(Cn,{"data-slot":`alert-dialog`,...e})}function Tn({...e}){return(0,Y.jsx)(ae,{"data-slot":`alert-dialog-portal`,...e})}function En({className:e,...t}){return(0,Y.jsx)(b,{"data-slot":`alert-dialog-overlay`,className:r(`fixed inset-0 z-50 bg-black/20 transition-opacity duration-150 data-ending-style:opacity-0 data-starting-style:opacity-0 supports-backdrop-filter:backdrop-blur-xs`,e),...t})}function Dn({className:e,children:t,...n}){return(0,Y.jsxs)(Tn,{children:[(0,Y.jsx)(En,{}),(0,Y.jsx)(g,{"data-slot":`alert-dialog-content`,className:r(`fixed top-1/2 left-1/2 z-50 w-[min(100%-2rem,24rem)] -translate-x-1/2 -translate-y-1/2 overflow-hidden rounded-none border border-border bg-popover text-sm text-popover-foreground shadow-lg outline-none transition duration-150 data-ending-style:scale-95 data-ending-style:opacity-0 data-starting-style:scale-95 data-starting-style:opacity-0`,e),...n,children:t})]})}function On({className:e,...t}){return(0,Y.jsx)(`div`,{"data-slot":`alert-dialog-header`,className:r(`flex flex-col gap-1 border-b border-border/50 px-4 py-3`,e),...t})}function kn({className:e,...t}){return(0,Y.jsx)(`div`,{"data-slot":`alert-dialog-footer`,className:r(`flex flex-row items-stretch border-t border-border/50 p-0`,e),...t})}function An({className:e,...t}){return(0,Y.jsx)(re,{"data-slot":`alert-dialog-title`,className:r(`text-sm font-medium text-foreground`,e),...t})}function jn({className:e,...t}){return(0,Y.jsx)(ye,{"data-slot":`alert-dialog-description`,className:r(`text-[11px] text-muted-foreground`,e),...t})}var Mn={create:`Confirm add`,set:`Confirm set`,rotate:`Confirm rotate`},Nn={create:`Add contract`,set:`Set value`,rotate:`Rotate`};function Pn({review:e,pending:t=!1,onCancel:n,onConfirm:r}){return(0,Y.jsx)(wn,{open:e!==null,onOpenChange:e=>{!e&&!t&&n()},children:(0,Y.jsxs)(Dn,{"data-slot":`vault-write-review`,children:[(0,Y.jsxs)(On,{children:[(0,Y.jsx)(An,{children:e?`${Mn[e.action]} ${e.name}`:`Confirm write`}),(0,Y.jsx)(jn,{children:e?.preview==null?`Write-only. The value is never shown again.`:`Config is shown in the clear after submit.`})]}),e?(0,Y.jsx)(Fn,{review:e}):null,(0,Y.jsxs)(kn,{children:[(0,Y.jsx)(W,{split:!0,onClick:n,disabled:t,"data-slot":`vault-write-review-cancel`,children:`Cancel`}),(0,Y.jsx)(W,{variant:e?.action===`rotate`?`destructive`:`default`,disabled:t||e===null,onClick:r,"data-slot":`vault-write-review-confirm`,children:t?`Working…`:e?Nn[e.action]:`Confirm`})]})]})})}function Fn({review:e}){return(0,Y.jsxs)(`dl`,{className:`flex flex-col`,"data-slot":`vault-write-review-facts`,children:[(0,Y.jsx)($,{label:`Name`,value:e.name,mono:!0}),e.action===`create`?(0,Y.jsx)($,{label:`Kind`,value:e.kind}):null,(0,Y.jsx)($,{label:`Fingerprint`,value:e.fingerprint,mono:!0}),e.preview==null?null:(0,Y.jsx)($,{label:`Value`,value:e.preview,mono:!0}),e.reason?(0,Y.jsx)($,{label:`Reason`,value:e.reason}):null,e.action===`create`&&e.rotate?(0,Y.jsx)($,{label:`Rotate`,value:e.rotate}):null]})}function $({label:e,value:t,mono:n=!1}){return(0,Y.jsxs)(`div`,{className:`flex items-baseline justify-between gap-3 border-b border-border/50 px-4 py-2 last:border-b-0`,children:[(0,Y.jsx)(`dt`,{className:`shrink-0 text-[10px] font-semibold tracking-[0.12em] text-muted-foreground uppercase`,children:e}),(0,Y.jsx)(`dd`,{className:n?`min-w-0 truncate font-mono text-[11px]`:`min-w-0 truncate text-[12px]`,children:t})]})}function In({open:e,onOpenChange:t,pending:n=!1,error:a,onSubmit:o}){let[s,c]=(0,K.useState)(`secret`),[l,u]=(0,K.useState)(``),[d,f]=(0,K.useState)(``),[p,m]=(0,K.useState)(`90d`),[h,g]=(0,K.useState)(``),[_,v]=(0,K.useState)(null),[y,b]=(0,K.useState)(null);(0,K.useEffect)(()=>{e||(c(`secret`),u(``),f(``),m(`90d`),g(``),v(null),b(null))},[e]);let ee=l.trim().length>0&&h.trim().length>0&&!n,te=async()=>{let e=await bn({action:`create`,name:l.trim(),value:h,sensitive:s===`secret`,kind:s,description:d.trim(),rotate:s===`secret`?p:`never`});if(`error`in e){v(e.error);return}v(null),b(e)};return(0,Y.jsxs)(T,{open:e,onOpenChange:t,children:[(0,Y.jsxs)(O,{side:`right`,showOverlay:!1,className:`gap-0 p-0 data-[side=right]:sm:max-w-md`,"data-slot":`vault-create-sheet`,children:[(0,Y.jsxs)(E,{className:`gap-1 border-b border-border/50`,children:[(0,Y.jsx)(P,{className:`text-sm`,children:`Add vault contract`}),(0,Y.jsx)(j,{className:`text-[11px]`,children:s===`secret`?`Writes the value and lists the contract here. Promote it to vault.secret in source when a Flow should read it.`:`vault.config — shown in the clear on the Config band after submit.`})]}),(0,Y.jsxs)(`div`,{className:`flex min-h-0 flex-1 flex-col overflow-y-auto`,children:[(0,Y.jsxs)(Ie,{label:`Kind`,children:[(0,Y.jsx)(H,{active:s===`secret`,onClick:()=>c(`secret`),children:`secret`}),(0,Y.jsx)(H,{active:s===`config`,onClick:()=>c(`config`),children:`config`})]}),(0,Y.jsx)(U,{label:`Name`,children:(0,Y.jsx)(i,{value:l,onChange:e=>u(e.target.value.toUpperCase().replace(/[^A-Z0-9_]/g,``)),placeholder:`STRIPE_KEY`,autoComplete:`off`,"aria-label":`Contract name`,flat:!0,className:r(G,`font-mono`)})}),(0,Y.jsx)(U,{label:`Description`,children:(0,Y.jsx)(i,{value:d,onChange:e=>f(e.target.value),placeholder:`Optional title`,autoComplete:`off`,"aria-label":`Description`,flat:!0,className:G})}),s===`secret`?(0,Y.jsxs)(Ie,{label:`Rotate`,children:[(0,Y.jsx)(H,{active:p===`90d`,onClick:()=>m(`90d`),children:`90d`}),(0,Y.jsx)(H,{active:p===`never`,onClick:()=>m(`never`),children:`no rotate`})]}):null,(0,Y.jsx)(U,{label:`Value`,children:(0,Y.jsx)(i,{type:`password`,autoComplete:`off`,value:h,onChange:e=>g(e.target.value),placeholder:s===`secret`?`Paste the secret`:`Public value`,"aria-label":`New vault value`,flat:!0,className:G})}),_||a?(0,Y.jsx)(Le,{slot:`vault-create-error`,children:_??a}):null]}),(0,Y.jsxs)(x,{children:[(0,Y.jsx)(W,{split:!0,onClick:()=>t(!1),disabled:n,children:`Cancel`}),(0,Y.jsx)(W,{variant:`default`,disabled:!ee,onClick:()=>{te()},"data-slot":`vault-create-submit`,children:s===`secret`?`Review secret`:`Review config`})]})]}),(0,Y.jsx)(Pn,{review:y,pending:n,onCancel:()=>b(Sn()),onConfirm:()=>{xn(y,e=>{o({name:e.commit.name,value:e.commit.value,kind:e.commit.kind,description:e.commit.description,rotate:e.commit.rotate})})}})]})}var Ln=[{id:`first`,label:`first`,text:`Initial value`},{id:`fix`,label:`fix`,text:`Correct a bad value`},{id:`provider`,label:`provider`,text:`Provider changed it`},{id:`other`,label:`other`,text:``}],Rn=[{id:`scheduled`,label:`scheduled`,text:`Scheduled rotation`},{id:`leak`,label:`leak`,text:`Key compromise`},{id:`provider`,label:`provider`,text:`Provider rotated`},{id:`other`,label:`other`,text:``}];function zn(e){return e===`rotate`?Rn:Ln}function Bn(e){return e===`rotate`?`scheduled`:`first`}function Vn(e,t,n){return t===`other`?n.trim():zn(e).find(e=>e.id===t)?.text??``}function Hn({open:e,onOpenChange:t,mode:n,name:r,sensitive:a=!0,pending:o=!1,error:s,onSubmit:c}){let[l,u]=(0,K.useState)(``),[d,f]=(0,K.useState)(()=>Bn(n)),[p,m]=(0,K.useState)(``),[h,g]=(0,K.useState)(null),[_,v]=(0,K.useState)(null);(0,K.useEffect)(()=>{e||(u(``),f(Bn(n)),m(``),g(null),v(null))},[e,n]);let y=Vn(n,d,p),b=l.trim().length>0&&y.length>=3&&!o,ee=zn(n),te=async()=>{let e=await bn({action:n,name:r,value:l,sensitive:a,reason:y,kind:a?`secret`:`config`});if(`error`in e){g(e.error);return}g(null),v(e)};return(0,Y.jsxs)(T,{open:e,onOpenChange:t,children:[(0,Y.jsxs)(O,{side:`right`,showOverlay:!1,className:`gap-0 p-0 data-[side=right]:sm:max-w-md`,"data-slot":`vault-write-sheet`,children:[(0,Y.jsxs)(E,{className:`gap-1 border-b border-border/50`,children:[(0,Y.jsx)(P,{className:`text-sm`,children:n===`set`?`Set ${r}`:`Rotate ${r}`}),(0,Y.jsx)(j,{className:`text-[11px]`,children:a?`Write-only. The new value is never shown again after submit.`:`This vault.config value is shown in the clear on the Config band after submit.`})]}),(0,Y.jsxs)(`div`,{className:`flex min-h-0 flex-1 flex-col overflow-y-auto`,children:[(0,Y.jsx)(U,{label:`New value`,children:(0,Y.jsx)(i,{type:`password`,autoComplete:`off`,value:l,onChange:e=>u(e.target.value),placeholder:a?`Paste the new secret`:`Paste the new value`,"aria-label":`New vault value`,flat:!0,className:G})}),(0,Y.jsx)(Ie,{label:`Reason`,children:ee.map(e=>(0,Y.jsx)(H,{active:d===e.id,onClick:()=>f(e.id),children:e.label},e.id))}),d===`other`?(0,Y.jsx)(U,{label:`Other`,children:(0,Y.jsx)(i,{value:p,onChange:e=>m(e.target.value),placeholder:`Why is this change needed?`,"aria-label":`Custom reason`,flat:!0,className:G})}):null,h||s?(0,Y.jsx)(Le,{slot:`vault-write-error`,children:h??s}):null]}),(0,Y.jsxs)(x,{children:[(0,Y.jsx)(W,{split:!0,onClick:()=>t(!1),disabled:o,children:`Cancel`}),(0,Y.jsx)(W,{variant:n===`rotate`?`destructive`:`default`,disabled:!b,onClick:()=>{te()},"data-slot":`vault-write-submit`,children:n===`set`?`Review set`:`Review rotate`})]})]}),(0,Y.jsx)(Pn,{review:_,pending:o,onCancel:()=>v(Sn()),onConfirm:()=>{xn(_,e=>{c({value:e.commit.value,reason:e.commit.reason??y})})}})]})}function Un(){let e=qe(),t=o(),{query:i,selectedName:s,action:c,setQuery:l,setSelectedName:u,setAction:d}=Oe(),m=Me(),h=(0,Y.jsx)(Ne,{open:m.open,onToggle:m.toggle,noun:`vault`,controlsId:`vault-list`,dataSlot:`vault-list-toggle`}),[g]=(0,K.useState)(()=>Date.now()),[_,b]=(0,K.useState)(!1),[x,re]=(0,K.useState)(null),[S,C]=(0,K.useState)(null),[ie,ae]=(0,K.useState)(null),[w,T]=(0,K.useState)(null),[oe,se]=(0,K.useState)(null),[le,E]=(0,K.useState)(null),[ue,fe]=(0,K.useState)(null),[pe,O]=(0,K.useState)(null),k=e.data?.secrets??[],A=e.data?.env??`dev`,j=e.data?.backend??null,M=(0,K.useMemo)(()=>Ye(j),[j]),N=(0,K.useMemo)(()=>dn(k,i,g),[k,i,g]),P=(0,K.useMemo)(()=>mt(k,g),[k,g]),F=(0,K.useMemo)(()=>N.flatMap(e=>e.secrets),[N]),ge=F.length,L=F.find(e=>e.name===s)??F[0]??null,ve=fn({kekVersion:le??j?.status?.kekVersion??1,remaining:oe,rewrapTargetKekVersion:j?.status?.rewrapTargetKekVersion??null});(0,K.useEffect)(()=>{let e=e=>{if(e.key!==`/`||e.metaKey||e.ctrlKey||e.altKey)return;let t=e.target;if(t instanceof HTMLElement){let e=t.tagName;if(e===`INPUT`||e===`TEXTAREA`||t.isContentEditable)return}e.preventDefault(),document.querySelector(`[data-slot='vault-search-input']`)?.focus()};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[]);let ye=async()=>{await t.invalidateQueries({queryKey:Ze})},xe=()=>{let e=ot(k);navigator.clipboard?.writeText(e),re(`Exported fingerprints only (no secret values)`)},Se=be({mutationFn:async e=>{if(e.value.trim().length===0)throw Error(`New value is required`);let t=await(e.mode===`set`?de:he)({name:e.name,value:e.value,reason:e.reason});if(t.error)throw Error(f(t.error));return t.data},onSuccess:async()=>{C(null),d(null),await ye()},onError:e=>{C(e.message)}}),R=be({mutationFn:async e=>{if(e.name.trim().length===0)throw Error(`Name is required`);if(e.value.trim().length===0)throw Error(`Value is required`);let t=await v({name:e.name,value:e.value,kind:e.kind,...e.description.length>0?{description:e.description}:{},...e.rotate.length>0?{rotate:e.rotate}:{}});if(t.error)throw Error(f(t.error));return t.data},onSuccess:async e=>{C(null),d(null),e?.name&&u(e.name),await ye()},onError:e=>{C(e.message)}}),Ae=be({mutationFn:async e=>{let t=0,n=j?.status?.kekVersion??1;for(;;){let r=await te(e);if(r.error)throw Error(f(r.error));if(!r.data)throw Error(`Empty rotate-master response`);if(t=r.data.remaining,n=r.data.kekVersion,se(r.data.remaining),E(r.data.kekVersion),r.data.masterKey&&T(r.data.masterKey),await ye(),r.data.remaining===0)break}return{remaining:t,kekVersion:n}},onSuccess:()=>{ae(null),d(null)},onError:e=>{ae(e.message)}}),V=be({mutationFn:async()=>{let e=await ce();if(e.error)throw Error(f(e.error));if(!e.data)throw Error(`Empty verify response`);return e.data},onSuccess:e=>{e.ok?(O(null),fe(`chain intact`)):(fe(null),O(e))}});return(0,Y.jsxs)(`div`,{className:ne,"data-slot":`vault-page`,children:[(0,Y.jsxs)(ke,{orientation:`horizontal`,className:`min-h-0 flex-1`,children:[(0,Y.jsx)(je,{panelRef:m.panelRef,collapsible:!0,collapsedSize:0,defaultSize:D.start.defaultSize,minSize:D.start.minSize,onResize:m.onResize,className:`min-h-0 overflow-hidden`,children:(0,Y.jsxs)(`div`,{id:`vault-list`,className:`flex h-full min-h-0 flex-col overflow-hidden`,"data-slot":`vault-list`,children:[(0,Y.jsxs)(`div`,{className:r(ee,`relative z-20 pr-1.5`),children:[(0,Y.jsx)(un,{query:i,secrets:k,onQueryChange:l}),(0,Y.jsx)(B,{label:`Add secret or config`,className:`flex self-stretch`,children:(0,Y.jsx)(`button`,{type:`button`,"aria-label":`Add secret or config`,onClick:()=>d(`create`),className:y,children:(0,Y.jsx)(I,{icon:n,className:`size-3.5`})})}),x?(0,Y.jsx)(`span`,{className:`sr-only`,role:`status`,children:x}):null,(0,Y.jsx)(B,{label:`Verify the audit hash chain`,className:`flex self-stretch`,children:(0,Y.jsx)(`button`,{type:`button`,"aria-label":`Verify chain`,disabled:V.isPending,onClick:()=>V.mutate(),className:y,children:(0,Y.jsx)(I,{icon:p,className:`size-3.5`})})}),(0,Y.jsxs)(De,{children:[(0,Y.jsx)(B,{label:`Vault security`,className:`flex self-stretch`,children:(0,Y.jsx)(Ce,{render:e=>(0,Y.jsx)(`button`,{...e,type:`button`,"aria-label":`Vault security`,className:y,children:(0,Y.jsx)(I,{icon:a,className:`size-3.5`})})})}),(0,Y.jsxs)(Ee,{align:`end`,className:`min-w-52`,children:[(0,Y.jsxs)(we,{children:[(0,Y.jsx)(z,{onClick:()=>b(!0),children:`Security`}),(0,Y.jsxs)(z,{onClick:()=>d(`rotate-master`),children:[(0,Y.jsx)(I,{icon:_e,"data-icon":`inline-start`}),`Rotate master key`]}),(0,Y.jsxs)(z,{onClick:xe,children:[(0,Y.jsx)(I,{icon:me,"data-icon":`inline-start`}),`Export fingerprints`]})]}),(0,Y.jsx)(Te,{}),(0,Y.jsxs)(z,{disabled:V.isPending,onClick:()=>V.mutate(),children:[(0,Y.jsx)(I,{icon:p,"data-icon":`inline-start`}),`Verify audit chain`]})]})]})]}),(0,Y.jsx)(ln,{card:M,env:A,summary:P,query:i,progress:ve,verifyNote:ue,onQueryChange:l,onOpenSecurity:()=>b(!0)}),(0,Y.jsx)(Bt,{groups:N,selectedName:L?.name??s,loading:e.isLoading,matchCount:ge,totalCount:k.length,now:g,onSelect:u})]})}),m.open?(0,Y.jsx)(Pe,{withHandle:!0}):null,(0,Y.jsx)(je,{defaultSize:D.end.defaultSize,minSize:D.end.minSize,className:`min-h-0 overflow-hidden`,children:L?(0,Y.jsx)(Tt,{row:L,env:A,now:g,backend:j,onSet:()=>d(`set`),onRotate:()=>d(`rotate`),onQueryChange:l,leading:h}):(0,Y.jsx)(Nt,{loading:e.isLoading,hasContracts:k.length>0,query:i,onClearQuery:()=>l(``),leading:h})})]}),(0,Y.jsx)(In,{open:c===`create`,onOpenChange:e=>{e||(C(null),d(null))},pending:R.isPending,error:c===`create`?S:null,onSubmit:e=>R.mutate(e)}),(0,Y.jsx)(Hn,{open:c===`set`||c===`rotate`,onOpenChange:e=>{e||(C(null),d(null))},mode:c===`rotate`?`rotate`:`set`,name:L?.name??``,sensitive:L?.sensitive??!0,pending:Se.isPending,error:S,onSubmit:e=>{L&&Se.mutate({mode:c===`rotate`?`rotate`:`set`,name:L.name,...e})}}),(0,Y.jsx)(mn,{open:c===`rotate-master`,onOpenChange:e=>{e||(ae(null),d(null))},pending:Ae.isPending,error:ie,onConfirm:e=>Ae.mutate(e)}),(0,Y.jsx)(gn,{open:_,onOpenChange:b,card:M,env:A,progress:ve,verifyPending:V.isPending,verifyNote:ue,onVerify:()=>V.mutate(),onRotateMaster:()=>{b(!1),d(`rotate-master`)},onExport:xe}),(0,Y.jsx)(pn,{masterKey:w,onDismiss:()=>T(null)}),(0,Y.jsx)(vn,{result:pe,onClose:()=>O(null)})]})}export{Un as VaultPage};
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
<title>okengine Console</title>
|
|
7
7
|
<meta
|
|
8
8
|
name="description"
|
|
9
|
-
content="Operator Console for okengine — Flows, Store, Observability, and
|
|
9
|
+
content="Operator Console for okengine — Flows, Store, Observability, Vault, and Access."
|
|
10
10
|
/>
|
|
11
11
|
<meta name="application-name" content="okengine Console" />
|
|
12
12
|
<meta name="theme-color" content="#0D0D0D" />
|
|
@@ -14,14 +14,14 @@
|
|
|
14
14
|
<meta property="og:title" content="okengine Console" />
|
|
15
15
|
<meta
|
|
16
16
|
property="og:description"
|
|
17
|
-
content="Operator Console for okengine — Flows, Store, Observability, and
|
|
17
|
+
content="Operator Console for okengine — Flows, Store, Observability, Vault, and Access."
|
|
18
18
|
/>
|
|
19
19
|
<meta property="og:type" content="website" />
|
|
20
20
|
<meta name="twitter:card" content="summary" />
|
|
21
21
|
<meta name="twitter:title" content="okengine Console" />
|
|
22
22
|
<meta
|
|
23
23
|
name="twitter:description"
|
|
24
|
-
content="Operator Console for okengine — Flows, Store, Observability, and
|
|
24
|
+
content="Operator Console for okengine — Flows, Store, Observability, Vault, and Access."
|
|
25
25
|
/>
|
|
26
26
|
<link rel="icon" href="/favicon.svg" type="image/svg+xml" />
|
|
27
27
|
<link rel="apple-touch-icon" href="/favicon.svg" />
|
|
@@ -37,18 +37,20 @@
|
|
|
37
37
|
} catch (e) {}
|
|
38
38
|
})();
|
|
39
39
|
</script>
|
|
40
|
-
<script type="module" crossorigin src="/assets/index-
|
|
40
|
+
<script type="module" crossorigin src="/assets/index-CGoZkILK.js"></script>
|
|
41
41
|
<link rel="modulepreload" crossorigin href="/assets/rolldown-runtime-hePW80VL.js">
|
|
42
42
|
<link rel="modulepreload" crossorigin href="/assets/react-dom-Bph1y7z7.js">
|
|
43
43
|
<link rel="modulepreload" crossorigin href="/assets/xyflow-D7n4g6go.js">
|
|
44
|
-
<link rel="modulepreload" crossorigin href="/assets/shortcut-keys-
|
|
45
|
-
<link rel="modulepreload" crossorigin href="/assets/
|
|
46
|
-
<link rel="modulepreload" crossorigin href="/assets/
|
|
47
|
-
<link rel="modulepreload" crossorigin href="/assets/
|
|
44
|
+
<link rel="modulepreload" crossorigin href="/assets/shortcut-keys-DKxNTe_m.js">
|
|
45
|
+
<link rel="modulepreload" crossorigin href="/assets/useMutation-B8EO02Ej.js">
|
|
46
|
+
<link rel="modulepreload" crossorigin href="/assets/link-BX6Vqztd.js">
|
|
47
|
+
<link rel="modulepreload" crossorigin href="/assets/skeleton-D-czQJT6.js">
|
|
48
|
+
<link rel="modulepreload" crossorigin href="/assets/react-D8E3mtu1.js">
|
|
48
49
|
<link rel="modulepreload" crossorigin href="/assets/preload-helper-oH4irX4C.js">
|
|
49
|
-
<link rel="modulepreload" crossorigin href="/assets/
|
|
50
|
+
<link rel="modulepreload" crossorigin href="/assets/useRender-BE2A9BWC.js">
|
|
51
|
+
<link rel="modulepreload" crossorigin href="/assets/shortcut-JQIZlWfm.js">
|
|
50
52
|
<link rel="stylesheet" crossorigin href="/assets/xyflow-DZ0Ws1xk.css">
|
|
51
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
53
|
+
<link rel="stylesheet" crossorigin href="/assets/index-Ck88Jmv8.css">
|
|
52
54
|
</head>
|
|
53
55
|
<body>
|
|
54
56
|
<div id="root"></div>
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
<title>okengine Console</title>
|
|
7
7
|
<meta
|
|
8
8
|
name="description"
|
|
9
|
-
content="Operator Console for okengine — Flows, Store, Observability, and
|
|
9
|
+
content="Operator Console for okengine — Flows, Store, Observability, Vault, and Access."
|
|
10
10
|
/>
|
|
11
11
|
<meta name="application-name" content="okengine Console" />
|
|
12
12
|
<meta name="theme-color" content="#0D0D0D" />
|
|
@@ -14,14 +14,14 @@
|
|
|
14
14
|
<meta property="og:title" content="okengine Console" />
|
|
15
15
|
<meta
|
|
16
16
|
property="og:description"
|
|
17
|
-
content="Operator Console for okengine — Flows, Store, Observability, and
|
|
17
|
+
content="Operator Console for okengine — Flows, Store, Observability, Vault, and Access."
|
|
18
18
|
/>
|
|
19
19
|
<meta property="og:type" content="website" />
|
|
20
20
|
<meta name="twitter:card" content="summary" />
|
|
21
21
|
<meta name="twitter:title" content="okengine Console" />
|
|
22
22
|
<meta
|
|
23
23
|
name="twitter:description"
|
|
24
|
-
content="Operator Console for okengine — Flows, Store, Observability, and
|
|
24
|
+
content="Operator Console for okengine — Flows, Store, Observability, Vault, and Access."
|
|
25
25
|
/>
|
|
26
26
|
<link rel="icon" href="/favicon.svg" type="image/svg+xml" />
|
|
27
27
|
<link rel="apple-touch-icon" href="/favicon.svg" />
|
|
@@ -446,7 +446,7 @@ export type TracesReplayResult = {
|
|
|
446
446
|
readonly ok: true;
|
|
447
447
|
readonly rootId: string;
|
|
448
448
|
readonly dryRun: boolean;
|
|
449
|
-
readonly at:
|
|
449
|
+
readonly at: string;
|
|
450
450
|
readonly flow: string;
|
|
451
451
|
};
|
|
452
452
|
|
|
@@ -506,6 +506,11 @@ export type FlowsInvokeResult = {
|
|
|
506
506
|
readonly flowId: string;
|
|
507
507
|
readonly asUserId: string;
|
|
508
508
|
readonly asGate?: string | null;
|
|
509
|
+
readonly rls?: {
|
|
510
|
+
readonly gate: string | null;
|
|
511
|
+
readonly userId: string;
|
|
512
|
+
readonly applied: boolean;
|
|
513
|
+
};
|
|
509
514
|
readonly trigger: string;
|
|
510
515
|
readonly response: unknown;
|
|
511
516
|
/** True when classified PII keys were redacted. */
|
|
@@ -674,7 +679,7 @@ export type ClockRunNowResult = {
|
|
|
674
679
|
readonly ok: true;
|
|
675
680
|
readonly name: string;
|
|
676
681
|
readonly ran: boolean;
|
|
677
|
-
readonly at:
|
|
682
|
+
readonly at: string;
|
|
678
683
|
};
|
|
679
684
|
|
|
680
685
|
/**
|
|
@@ -721,6 +726,8 @@ export type StoreListChild = {
|
|
|
721
726
|
readonly columnDescriptions: Readonly<Record<string, string>>;
|
|
722
727
|
/** Live RLS when the engine reported `pg_class.relrowsecurity`. */
|
|
723
728
|
readonly rls?: boolean;
|
|
729
|
+
/** Live + declared RLS policy count when the child is a SQL table. */
|
|
730
|
+
readonly rlsPolicyCount?: number;
|
|
724
731
|
};
|
|
725
732
|
|
|
726
733
|
/** One store row from `GET /console/store` (matches server `StoreListOut`). */
|
|
@@ -772,6 +779,8 @@ export type StoreQueryInput = {
|
|
|
772
779
|
readonly topK?: number;
|
|
773
780
|
/** When true, SQL browse returns PII cleartext (audited). Default masks. */
|
|
774
781
|
readonly revealPii?: boolean;
|
|
782
|
+
readonly asGate?: string;
|
|
783
|
+
readonly asUserId?: string;
|
|
775
784
|
};
|
|
776
785
|
|
|
777
786
|
/** Success payload from `QUERY /console/store/query` (matches server `StoreQueryOut`). */
|
|
@@ -793,6 +802,11 @@ export type StoreQueryResult = {
|
|
|
793
802
|
}>;
|
|
794
803
|
readonly masked: boolean;
|
|
795
804
|
readonly routedRole?: "primary" | "replica";
|
|
805
|
+
readonly rls?: {
|
|
806
|
+
readonly gate: string | null;
|
|
807
|
+
readonly userId: string;
|
|
808
|
+
readonly applied: boolean;
|
|
809
|
+
};
|
|
796
810
|
};
|
|
797
811
|
|
|
798
812
|
/**
|
|
@@ -822,7 +836,7 @@ export type StoreRevealInput = {
|
|
|
822
836
|
export type StoreRevealResult = {
|
|
823
837
|
readonly ok: true;
|
|
824
838
|
readonly value: unknown;
|
|
825
|
-
readonly at:
|
|
839
|
+
readonly at: string;
|
|
826
840
|
};
|
|
827
841
|
|
|
828
842
|
/**
|
|
@@ -851,6 +865,8 @@ export type StoreEditInput = {
|
|
|
851
865
|
readonly confirmation?: string;
|
|
852
866
|
readonly reason?: string;
|
|
853
867
|
readonly commit?: boolean;
|
|
868
|
+
readonly asGate?: string;
|
|
869
|
+
readonly asUserId?: string;
|
|
854
870
|
};
|
|
855
871
|
|
|
856
872
|
/** Success payload from `POST /console/store/edit` (matches server). */
|
|
@@ -863,7 +879,12 @@ export type StoreEditResult = {
|
|
|
863
879
|
readonly kind: "send" | "ask";
|
|
864
880
|
readonly resource: string;
|
|
865
881
|
}>;
|
|
866
|
-
readonly at:
|
|
882
|
+
readonly at: string;
|
|
883
|
+
readonly rls?: {
|
|
884
|
+
readonly gate: string | null;
|
|
885
|
+
readonly userId: string;
|
|
886
|
+
readonly applied: boolean;
|
|
887
|
+
};
|
|
867
888
|
};
|
|
868
889
|
|
|
869
890
|
/**
|
|
@@ -907,7 +928,7 @@ export type StoreDeleteInput = {
|
|
|
907
928
|
export type StoreDeleteResult = {
|
|
908
929
|
readonly ok: true;
|
|
909
930
|
readonly deleted: number;
|
|
910
|
-
readonly at:
|
|
931
|
+
readonly at: string;
|
|
911
932
|
};
|
|
912
933
|
|
|
913
934
|
/**
|
|
@@ -934,6 +955,7 @@ export type StoreSqlInput = {
|
|
|
934
955
|
readonly revealPii?: boolean;
|
|
935
956
|
/** View rows as this Gate (`oke.gate` on postgres / pglite). */
|
|
936
957
|
readonly asGate?: string;
|
|
958
|
+
readonly asUserId?: string;
|
|
937
959
|
};
|
|
938
960
|
|
|
939
961
|
/** Success payload from `POST /console/store/sql` (matches server `StoreSqlOut`). */
|
|
@@ -942,7 +964,13 @@ export type StoreSqlResult = {
|
|
|
942
964
|
readonly masked: boolean;
|
|
943
965
|
readonly routedRole: "primary" | "replica";
|
|
944
966
|
readonly asGate: string | null;
|
|
967
|
+
readonly asUserId: string | null;
|
|
945
968
|
readonly gateApplied: boolean;
|
|
969
|
+
readonly rls?: {
|
|
970
|
+
readonly gate: string | null;
|
|
971
|
+
readonly userId: string;
|
|
972
|
+
readonly applied: boolean;
|
|
973
|
+
};
|
|
946
974
|
};
|
|
947
975
|
|
|
948
976
|
/**
|
|
@@ -1267,7 +1295,7 @@ export type VaultWriteResult = {
|
|
|
1267
1295
|
readonly ok: true;
|
|
1268
1296
|
readonly name: string;
|
|
1269
1297
|
readonly fingerprint: string | null;
|
|
1270
|
-
readonly at:
|
|
1298
|
+
readonly at: string;
|
|
1271
1299
|
};
|
|
1272
1300
|
|
|
1273
1301
|
/**
|
|
@@ -1331,7 +1359,7 @@ export type VaultRotateMasterResult = {
|
|
|
1331
1359
|
readonly kekVersion: number;
|
|
1332
1360
|
readonly remaining: number;
|
|
1333
1361
|
readonly masterKey: string | null;
|
|
1334
|
-
readonly at:
|
|
1362
|
+
readonly at: string;
|
|
1335
1363
|
};
|
|
1336
1364
|
|
|
1337
1365
|
/**
|
|
@@ -1377,3 +1405,170 @@ export type VaultAuditVerifyResult = {
|
|
|
1377
1405
|
export async function vaultAuditVerify(): Promise<ConsoleApiResult<VaultAuditVerifyResult>> {
|
|
1378
1406
|
return consoleFetch<VaultAuditVerifyResult>("/console/vault/audit/verify");
|
|
1379
1407
|
}
|
|
1408
|
+
|
|
1409
|
+
/** One Access API key row (`GET /console/access`). */
|
|
1410
|
+
export type AccessKeyRow = {
|
|
1411
|
+
readonly id: string;
|
|
1412
|
+
readonly name: string;
|
|
1413
|
+
readonly plane: "user" | "operator";
|
|
1414
|
+
/** Stored issuer — user id or operator id. Frozen after mint. */
|
|
1415
|
+
readonly creatorId: string;
|
|
1416
|
+
/** Issuer ceiling stored on the key. */
|
|
1417
|
+
readonly creatorScopes: readonly string[];
|
|
1418
|
+
readonly scopes: readonly string[];
|
|
1419
|
+
readonly createdAt: number;
|
|
1420
|
+
readonly lastUsedAt: number | null;
|
|
1421
|
+
readonly expiresAt: number | null;
|
|
1422
|
+
readonly revokedAt: number | null;
|
|
1423
|
+
readonly rateLimit: { max: number; per: string } | null;
|
|
1424
|
+
readonly ipAllowlist: readonly string[];
|
|
1425
|
+
readonly unused90d: boolean;
|
|
1426
|
+
};
|
|
1427
|
+
|
|
1428
|
+
/** One Access user row. */
|
|
1429
|
+
export type AccessUserRow = {
|
|
1430
|
+
readonly id: string;
|
|
1431
|
+
readonly email: string;
|
|
1432
|
+
readonly name: string;
|
|
1433
|
+
readonly status: "active" | "disabled";
|
|
1434
|
+
readonly roles: readonly string[];
|
|
1435
|
+
readonly scopes: readonly string[];
|
|
1436
|
+
};
|
|
1437
|
+
|
|
1438
|
+
/** One Access operator row. */
|
|
1439
|
+
export type AccessOperatorRow = {
|
|
1440
|
+
readonly id: string;
|
|
1441
|
+
readonly email: string;
|
|
1442
|
+
readonly name: string;
|
|
1443
|
+
readonly status: "active" | "suspended" | "invited";
|
|
1444
|
+
readonly roles: readonly string[];
|
|
1445
|
+
readonly scopes: readonly string[];
|
|
1446
|
+
};
|
|
1447
|
+
|
|
1448
|
+
/** Access plane section. */
|
|
1449
|
+
export type AccessPlaneSection = {
|
|
1450
|
+
readonly keys: readonly AccessKeyRow[];
|
|
1451
|
+
readonly users?: readonly AccessUserRow[];
|
|
1452
|
+
readonly operators?: readonly AccessOperatorRow[];
|
|
1453
|
+
readonly grantableScopes: readonly string[];
|
|
1454
|
+
};
|
|
1455
|
+
|
|
1456
|
+
/** Access list payload (`GET /console/access`). */
|
|
1457
|
+
export type AccessListPayload = {
|
|
1458
|
+
readonly operatorPlane: AccessPlaneSection;
|
|
1459
|
+
readonly userPlane: AccessPlaneSection;
|
|
1460
|
+
readonly catalog: readonly string[];
|
|
1461
|
+
readonly accessTtlMs: number;
|
|
1462
|
+
};
|
|
1463
|
+
|
|
1464
|
+
/**
|
|
1465
|
+
* GET /console/access — keys, users, grantable scopes.
|
|
1466
|
+
*/
|
|
1467
|
+
export async function accessList(): Promise<ConsoleApiResult<AccessListPayload>> {
|
|
1468
|
+
return consoleFetch<AccessListPayload>("/console/access");
|
|
1469
|
+
}
|
|
1470
|
+
|
|
1471
|
+
/** Blast radius for one key. */
|
|
1472
|
+
export type AccessKeyBlastPayload = {
|
|
1473
|
+
readonly callVolume: number;
|
|
1474
|
+
readonly lastUsedAt: number | null;
|
|
1475
|
+
readonly sourceAddresses: readonly string[];
|
|
1476
|
+
readonly accessTtlMs: number;
|
|
1477
|
+
readonly residualAccessNote: string;
|
|
1478
|
+
};
|
|
1479
|
+
|
|
1480
|
+
/**
|
|
1481
|
+
* POST /console/access/key-blast — usage from Runs.
|
|
1482
|
+
*
|
|
1483
|
+
* @param keyId - Key id
|
|
1484
|
+
*/
|
|
1485
|
+
export async function accessKeyBlast(
|
|
1486
|
+
keyId: string,
|
|
1487
|
+
): Promise<ConsoleApiResult<AccessKeyBlastPayload>> {
|
|
1488
|
+
return consoleFetch<AccessKeyBlastPayload>("/console/access/key-blast", {
|
|
1489
|
+
method: "POST",
|
|
1490
|
+
body: JSON.stringify({ keyId }),
|
|
1491
|
+
});
|
|
1492
|
+
}
|
|
1493
|
+
|
|
1494
|
+
/** Create-key request. */
|
|
1495
|
+
export type AccessCreateKeyInput = {
|
|
1496
|
+
readonly plane: "user" | "operator";
|
|
1497
|
+
readonly name: string;
|
|
1498
|
+
readonly scopes: readonly string[];
|
|
1499
|
+
readonly creatorUserId?: string;
|
|
1500
|
+
readonly expiresAt?: number | null;
|
|
1501
|
+
readonly rateLimit?: { max: number; per: string } | null;
|
|
1502
|
+
readonly ipAllowlist?: readonly string[];
|
|
1503
|
+
};
|
|
1504
|
+
|
|
1505
|
+
/** Create / rotate success — secret once. */
|
|
1506
|
+
export type AccessSecretOnceResult = {
|
|
1507
|
+
readonly key: AccessKeyRow;
|
|
1508
|
+
readonly secret: string;
|
|
1509
|
+
};
|
|
1510
|
+
|
|
1511
|
+
/**
|
|
1512
|
+
* POST /console/access/keys — mint an attenuated key (secret once).
|
|
1513
|
+
*
|
|
1514
|
+
* @param body - Create payload
|
|
1515
|
+
*/
|
|
1516
|
+
export async function accessCreateKey(
|
|
1517
|
+
body: AccessCreateKeyInput,
|
|
1518
|
+
): Promise<ConsoleApiResult<AccessSecretOnceResult>> {
|
|
1519
|
+
return consoleFetch<AccessSecretOnceResult>("/console/access/keys", {
|
|
1520
|
+
method: "POST",
|
|
1521
|
+
body: JSON.stringify(body),
|
|
1522
|
+
});
|
|
1523
|
+
}
|
|
1524
|
+
|
|
1525
|
+
/**
|
|
1526
|
+
* POST /console/access/keys/rotate — new secret once.
|
|
1527
|
+
*
|
|
1528
|
+
* @param body - Key id + ROTATE confirm
|
|
1529
|
+
*/
|
|
1530
|
+
export async function accessRotateKey(body: {
|
|
1531
|
+
readonly keyId: string;
|
|
1532
|
+
readonly confirmation: "ROTATE";
|
|
1533
|
+
readonly reason: string;
|
|
1534
|
+
}): Promise<ConsoleApiResult<AccessSecretOnceResult>> {
|
|
1535
|
+
return consoleFetch<AccessSecretOnceResult>("/console/access/keys/rotate", {
|
|
1536
|
+
method: "POST",
|
|
1537
|
+
body: JSON.stringify(body),
|
|
1538
|
+
});
|
|
1539
|
+
}
|
|
1540
|
+
|
|
1541
|
+
/**
|
|
1542
|
+
* POST /console/access/keys/revoke — irreversible.
|
|
1543
|
+
*
|
|
1544
|
+
* @param body - Key id + REVOKE confirm
|
|
1545
|
+
*/
|
|
1546
|
+
export async function accessRevokeKey(body: {
|
|
1547
|
+
readonly keyId: string;
|
|
1548
|
+
readonly confirmation: "REVOKE";
|
|
1549
|
+
readonly reason: string;
|
|
1550
|
+
}): Promise<ConsoleApiResult<{ readonly key: AccessKeyRow }>> {
|
|
1551
|
+
return consoleFetch<{ readonly key: AccessKeyRow }>("/console/access/keys/revoke", {
|
|
1552
|
+
method: "POST",
|
|
1553
|
+
body: JSON.stringify(body),
|
|
1554
|
+
});
|
|
1555
|
+
}
|
|
1556
|
+
|
|
1557
|
+
/**
|
|
1558
|
+
* POST /console/access/keys/update — metadata + scopes.
|
|
1559
|
+
*
|
|
1560
|
+
* @param body - Patch
|
|
1561
|
+
*/
|
|
1562
|
+
export async function accessUpdateKey(body: {
|
|
1563
|
+
readonly keyId: string;
|
|
1564
|
+
readonly name?: string;
|
|
1565
|
+
readonly scopes?: readonly string[];
|
|
1566
|
+
readonly expiresAt?: number | null;
|
|
1567
|
+
readonly rateLimit?: { max: number; per: string } | null;
|
|
1568
|
+
readonly ipAllowlist?: readonly string[];
|
|
1569
|
+
}): Promise<ConsoleApiResult<{ readonly key: AccessKeyRow }>> {
|
|
1570
|
+
return consoleFetch<{ readonly key: AccessKeyRow }>("/console/access/keys/update", {
|
|
1571
|
+
method: "POST",
|
|
1572
|
+
body: JSON.stringify(body),
|
|
1573
|
+
});
|
|
1574
|
+
}
|
|
@@ -61,6 +61,8 @@ export function Table<T>({
|
|
|
61
61
|
onInsertColumn,
|
|
62
62
|
onDeleteColumn,
|
|
63
63
|
onRowDoubleClick,
|
|
64
|
+
onRowContextMenu,
|
|
65
|
+
onViewportContextMenu,
|
|
64
66
|
cellRange = null,
|
|
65
67
|
onCellRangeChange,
|
|
66
68
|
onCellActivate,
|
|
@@ -192,6 +194,13 @@ export function Table<T>({
|
|
|
192
194
|
onPointerMove={cellSelect.onScrollerPointerMove}
|
|
193
195
|
onPointerUp={cellSelect.onPointerUp}
|
|
194
196
|
onPointerCancel={cellSelect.onPointerUp}
|
|
197
|
+
onContextMenu={(event) => {
|
|
198
|
+
if (!onViewportContextMenu) return;
|
|
199
|
+
const target = event.target;
|
|
200
|
+
if (target instanceof Element && target.closest("[data-slot='table-row']")) return;
|
|
201
|
+
event.preventDefault();
|
|
202
|
+
onViewportContextMenu();
|
|
203
|
+
}}
|
|
195
204
|
className={cn("overflow-auto", onCellRangeChange ? "select-none" : undefined)}
|
|
196
205
|
style={{ height }}
|
|
197
206
|
>
|
|
@@ -273,12 +282,19 @@ export function Table<T>({
|
|
|
273
282
|
ref={(el) => {
|
|
274
283
|
rowRefs.current[entry.id] = el;
|
|
275
284
|
}}
|
|
285
|
+
data-slot="table-row"
|
|
276
286
|
data-selected={isSelected}
|
|
277
287
|
style={{ height: rowHeight }}
|
|
278
288
|
onPointerEnter={
|
|
279
289
|
hasRowMenu ? () => activateRow(entry.id, vItem.index) : undefined
|
|
280
290
|
}
|
|
281
291
|
onPointerLeave={hasRowMenu ? deactivateRow : undefined}
|
|
292
|
+
onContextMenu={(event) => {
|
|
293
|
+
if (!onRowContextMenu) return;
|
|
294
|
+
event.preventDefault();
|
|
295
|
+
event.stopPropagation();
|
|
296
|
+
onRowContextMenu(entry.row, entry.id);
|
|
297
|
+
}}
|
|
282
298
|
onDoubleClick={(e) => {
|
|
283
299
|
if (!onRowDoubleClick) return;
|
|
284
300
|
const target = e.target;
|
|
@@ -78,6 +78,10 @@ export interface TableProps<T> {
|
|
|
78
78
|
readonly onDeleteColumn?: (columnKey: string, index: number) => void;
|
|
79
79
|
/** Double-click a body row. */
|
|
80
80
|
readonly onRowDoubleClick?: (row: T, id: string) => void;
|
|
81
|
+
/** Two-finger / right-click a body row (caller should `preventDefault`). */
|
|
82
|
+
readonly onRowContextMenu?: (row: T, id: string) => void;
|
|
83
|
+
/** Two-finger / right-click empty viewport (not a row). */
|
|
84
|
+
readonly onViewportContextMenu?: () => void;
|
|
81
85
|
/** Controlled cell range (visible row index × column index). */
|
|
82
86
|
readonly cellRange?: CellRange | null;
|
|
83
87
|
/** Enables drag / Shift+click cell-range selection. */
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import {
|
|
6
6
|
AccessIcon,
|
|
7
7
|
Archive02Icon,
|
|
8
|
+
BiometricAccessIcon,
|
|
8
9
|
ChartAnalysisIcon,
|
|
9
10
|
Shapes01Icon,
|
|
10
11
|
WorkflowSquare08Icon,
|
|
@@ -49,6 +50,7 @@ const navItems: ReadonlyArray<{
|
|
|
49
50
|
shortcut: "observability",
|
|
50
51
|
},
|
|
51
52
|
{ title: "Vault", to: "/vault", icon: AccessIcon, shortcut: "vault" },
|
|
53
|
+
{ title: "Access", to: "/access", icon: BiometricAccessIcon, shortcut: "access" },
|
|
52
54
|
];
|
|
53
55
|
|
|
54
56
|
/**
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import {
|
|
6
6
|
AccessIcon,
|
|
7
7
|
Archive02Icon,
|
|
8
|
+
BiometricAccessIcon,
|
|
8
9
|
ChartAnalysisIcon,
|
|
9
10
|
ComputerIcon,
|
|
10
11
|
Logout03Icon,
|
|
@@ -65,6 +66,13 @@ const MODULES: ReadonlyArray<{
|
|
|
65
66
|
keywords: ["secrets", "contracts"],
|
|
66
67
|
shortcut: "vault",
|
|
67
68
|
},
|
|
69
|
+
{
|
|
70
|
+
title: "Access",
|
|
71
|
+
to: "/access",
|
|
72
|
+
icon: BiometricAccessIcon,
|
|
73
|
+
keywords: ["keys", "api", "scopes"],
|
|
74
|
+
shortcut: "access",
|
|
75
|
+
},
|
|
68
76
|
];
|
|
69
77
|
|
|
70
78
|
/** Inputs for {@link consoleCommandItems}. */
|
|
@@ -20,7 +20,7 @@ import { cn } from "@/lib/utils";
|
|
|
20
20
|
/**
|
|
21
21
|
* Shell chrome around authenticated panel routes.
|
|
22
22
|
*
|
|
23
|
-
* `/overview`, `/flows`, `/store`, `/vault`, and `/observability` render full-bleed
|
|
23
|
+
* `/overview`, `/flows`, `/store`, `/vault`, `/access`, and `/observability` render full-bleed
|
|
24
24
|
* (no padding / gap); other sections keep the padded inset. Desktop sidebar
|
|
25
25
|
* stays icon-collapsed; mobile still uses the sheet trigger.
|
|
26
26
|
*
|
|
@@ -38,6 +38,7 @@ export function ShellLayout({ operator }: { readonly operator: SessionOperator }
|
|
|
38
38
|
pathname === "/flows" ||
|
|
39
39
|
pathname === "/store" ||
|
|
40
40
|
pathname === "/vault" ||
|
|
41
|
+
pathname === "/access" ||
|
|
41
42
|
pathname === "/observability";
|
|
42
43
|
|
|
43
44
|
const logout = useCallback(() => {
|