open-managed-agents 0.1.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/LICENSE +93 -0
- package/README.md +248 -0
- package/bin/oma.mjs +499 -0
- package/dist/scripts/alpha-openai-compatible-fixture.mjs +134 -0
- package/dist/scripts/alpha-smoke-models.mjs +92 -0
- package/dist/scripts/alpha-smoke.mjs +581 -0
- package/dist/scripts/oma-doctor.js +230 -0
- package/dist/scripts/oma-models.js +299 -0
- package/dist/scripts/oma-workspaces.js +133 -0
- package/dist/src/control-plane/admin/auth.js +43 -0
- package/dist/src/control-plane/admin/routes.js +76 -0
- package/dist/src/control-plane/admin/service.js +102 -0
- package/dist/src/control-plane/admission.js +90 -0
- package/dist/src/control-plane/agents/routes.js +63 -0
- package/dist/src/control-plane/agents/service.js +687 -0
- package/dist/src/control-plane/agents/store.js +391 -0
- package/dist/src/control-plane/agents/types.js +1 -0
- package/dist/src/control-plane/api-constants.js +3 -0
- package/dist/src/control-plane/app.js +907 -0
- package/dist/src/control-plane/console/auth.js +68 -0
- package/dist/src/control-plane/console/static.js +112 -0
- package/dist/src/control-plane/deployment-runtime-config.js +328 -0
- package/dist/src/control-plane/deployment-runtime-event-coordinator.js +25 -0
- package/dist/src/control-plane/deployment-runtime-turn-guard.js +14 -0
- package/dist/src/control-plane/deployment-session-coordinator.js +25 -0
- package/dist/src/control-plane/deployment-session-output-coordinator.js +27 -0
- package/dist/src/control-plane/deployment-storage.js +354 -0
- package/dist/src/control-plane/egress/image.js +48 -0
- package/dist/src/control-plane/egress/policy.js +571 -0
- package/dist/src/control-plane/egress/presets.js +77 -0
- package/dist/src/control-plane/egress/proxy.js +72 -0
- package/dist/src/control-plane/egress/ssrf.js +106 -0
- package/dist/src/control-plane/egress/utils/debug.js +14 -0
- package/dist/src/control-plane/egress/vendor/http-proxy.js +335 -0
- package/dist/src/control-plane/egress/vendor/mitm-ca.js +226 -0
- package/dist/src/control-plane/egress/vendor/mitm-leaf.js +124 -0
- package/dist/src/control-plane/egress/vendor/parent-proxy.js +438 -0
- package/dist/src/control-plane/egress/vendor/request-filter.js +105 -0
- package/dist/src/control-plane/egress/vendor/sandbox-config.js +1 -0
- package/dist/src/control-plane/egress/vendor/tls-terminate-proxy.js +269 -0
- package/dist/src/control-plane/environments/routes.js +54 -0
- package/dist/src/control-plane/environments/service.js +112 -0
- package/dist/src/control-plane/environments/store.js +132 -0
- package/dist/src/control-plane/environments/types.js +1 -0
- package/dist/src/control-plane/errors.js +81 -0
- package/dist/src/control-plane/events/broadcaster.js +217 -0
- package/dist/src/control-plane/events/constants.js +2 -0
- package/dist/src/control-plane/events/persist.js +39 -0
- package/dist/src/control-plane/events/request.js +190 -0
- package/dist/src/control-plane/events/routes.js +159 -0
- package/dist/src/control-plane/events/runtime-helpers.js +134 -0
- package/dist/src/control-plane/events/service.js +1985 -0
- package/dist/src/control-plane/events/session-guards.js +29 -0
- package/dist/src/control-plane/events/sse.js +6 -0
- package/dist/src/control-plane/events/store.js +772 -0
- package/dist/src/control-plane/events/tool-persistence.js +102 -0
- package/dist/src/control-plane/events/types.js +21 -0
- package/dist/src/control-plane/files/routes.js +121 -0
- package/dist/src/control-plane/files/service.js +65 -0
- package/dist/src/control-plane/files/store-common.js +87 -0
- package/dist/src/control-plane/files/store-local.js +488 -0
- package/dist/src/control-plane/files/store-memory.js +270 -0
- package/dist/src/control-plane/files/store.js +2 -0
- package/dist/src/control-plane/files/types.js +7 -0
- package/dist/src/control-plane/http.js +25 -0
- package/dist/src/control-plane/ids.js +43 -0
- package/dist/src/control-plane/logging.js +263 -0
- package/dist/src/control-plane/models/auth-storage-backend.js +238 -0
- package/dist/src/control-plane/models/catalog.js +78 -0
- package/dist/src/control-plane/models/config-security.js +376 -0
- package/dist/src/control-plane/models/deployment-config.js +93 -0
- package/dist/src/control-plane/models/routes.js +32 -0
- package/dist/src/control-plane/models/service.js +138 -0
- package/dist/src/control-plane/observability/instruments.js +65 -0
- package/dist/src/control-plane/observability/metrics.js +125 -0
- package/dist/src/control-plane/observability/routes.js +95 -0
- package/dist/src/control-plane/openapi/document.js +282 -0
- package/dist/src/control-plane/openapi/routes.js +78 -0
- package/dist/src/control-plane/request-idempotency.js +85 -0
- package/dist/src/control-plane/secrets/envelope.js +132 -0
- package/dist/src/control-plane/secrets/master-key.js +44 -0
- package/dist/src/control-plane/secrets/routes.js +20 -0
- package/dist/src/control-plane/secrets/service.js +71 -0
- package/dist/src/control-plane/secrets/store.js +212 -0
- package/dist/src/control-plane/secrets/types.js +3 -0
- package/dist/src/control-plane/sessions/pi/custom-tools.js +146 -0
- package/dist/src/control-plane/sessions/pi/mcp/bridge.js +527 -0
- package/dist/src/control-plane/sessions/pi/mcp/client.js +157 -0
- package/dist/src/control-plane/sessions/pi/mcp/credential.js +28 -0
- package/dist/src/control-plane/sessions/pi/mcp/fetch.js +69 -0
- package/dist/src/control-plane/sessions/pi/mcp/probe.js +202 -0
- package/dist/src/control-plane/sessions/pi/mcp/runtime.js +13 -0
- package/dist/src/control-plane/sessions/pi/runner.js +1104 -0
- package/dist/src/control-plane/sessions/pi/sandbox/cma-glob.js +388 -0
- package/dist/src/control-plane/sessions/pi/sandbox/cma-grep.js +124 -0
- package/dist/src/control-plane/sessions/pi/sandbox/docker-egress.js +347 -0
- package/dist/src/control-plane/sessions/pi/sandbox/docker.js +1589 -0
- package/dist/src/control-plane/sessions/pi/sandbox/glob.js +48 -0
- package/dist/src/control-plane/sessions/pi/sandbox/image.js +7 -0
- package/dist/src/control-plane/sessions/pi/sandbox/microsandbox.js +1677 -0
- package/dist/src/control-plane/sessions/pi/sandbox/provider.js +561 -0
- package/dist/src/control-plane/sessions/pi/sandbox/selection.js +168 -0
- package/dist/src/control-plane/sessions/pi/span-normalizer.js +82 -0
- package/dist/src/control-plane/sessions/pi/tool-permissions.js +392 -0
- package/dist/src/control-plane/sessions/pi/translator.js +100 -0
- package/dist/src/control-plane/sessions/request.js +164 -0
- package/dist/src/control-plane/sessions/resources.js +63 -0
- package/dist/src/control-plane/sessions/routes.js +88 -0
- package/dist/src/control-plane/sessions/serialize.js +24 -0
- package/dist/src/control-plane/sessions/service.js +733 -0
- package/dist/src/control-plane/sessions/store.js +538 -0
- package/dist/src/control-plane/sessions/types.js +1 -0
- package/dist/src/control-plane/skills/archive.js +169 -0
- package/dist/src/control-plane/skills/routes.js +41 -0
- package/dist/src/control-plane/skills/service.js +29 -0
- package/dist/src/control-plane/skills/store.js +233 -0
- package/dist/src/control-plane/skills/types.js +5 -0
- package/dist/src/control-plane/sqlite-transaction.js +15 -0
- package/dist/src/control-plane/vaults/mcp-oauth-validate.js +165 -0
- package/dist/src/control-plane/vaults/oauth-refresh-ticker.js +43 -0
- package/dist/src/control-plane/vaults/oauth-refresh.js +448 -0
- package/dist/src/control-plane/vaults/routes.js +66 -0
- package/dist/src/control-plane/vaults/service.js +553 -0
- package/dist/src/control-plane/vaults/store.js +691 -0
- package/dist/src/control-plane/vaults/types.js +1 -0
- package/dist/src/control-plane/wake-loop.js +65 -0
- package/dist/src/control-plane/wiring.js +92 -0
- package/dist/src/control-plane/workspace.js +4 -0
- package/dist/src/control-plane/workspaces/store.js +158 -0
- package/dist/src/egress-proxy-main.js +103 -0
- package/dist/src/main.js +124 -0
- package/dist/src/types/agents.js +1 -0
- package/dist/src/types/common.js +1 -0
- package/dist/src/types/environments.js +1 -0
- package/dist/src/types/events.js +121 -0
- package/dist/src/types/files.js +1 -0
- package/dist/src/types/json.js +19 -0
- package/dist/src/types/sessions.js +1 -0
- package/dist/ui/managed-agents-console/README.md +52 -0
- package/dist/ui/managed-agents-console/docs/agents.md +23 -0
- package/dist/ui/managed-agents-console/docs/console.md +23 -0
- package/dist/ui/managed-agents-console/docs/dreams.md +5 -0
- package/dist/ui/managed-agents-console/docs/environments.md +27 -0
- package/dist/ui/managed-agents-console/docs/events.md +19 -0
- package/dist/ui/managed-agents-console/docs/files.md +17 -0
- package/dist/ui/managed-agents-console/docs/github.md +11 -0
- package/dist/ui/managed-agents-console/docs/integrations.md +19 -0
- package/dist/ui/managed-agents-console/docs/memory.md +11 -0
- package/dist/ui/managed-agents-console/docs/migration.md +17 -0
- package/dist/ui/managed-agents-console/docs/multiagent.md +11 -0
- package/dist/ui/managed-agents-console/docs/outcomes.md +11 -0
- package/dist/ui/managed-agents-console/docs/overview.md +41 -0
- package/dist/ui/managed-agents-console/docs/permissions.md +24 -0
- package/dist/ui/managed-agents-console/docs/quickstart.md +51 -0
- package/dist/ui/managed-agents-console/docs/reference.md +27 -0
- package/dist/ui/managed-agents-console/docs/sandbox-reference.md +19 -0
- package/dist/ui/managed-agents-console/docs/sandbox-security.md +15 -0
- package/dist/ui/managed-agents-console/docs/scheduled-deployments.md +5 -0
- package/dist/ui/managed-agents-console/docs/self-hosted-sandboxes.md +15 -0
- package/dist/ui/managed-agents-console/docs/session-operations.md +21 -0
- package/dist/ui/managed-agents-console/docs/sessions.md +21 -0
- package/dist/ui/managed-agents-console/docs/skills.md +15 -0
- package/dist/ui/managed-agents-console/docs/tools.md +23 -0
- package/dist/ui/managed-agents-console/docs/vaults.md +19 -0
- package/dist/ui/managed-agents-console/docs/webhooks.md +11 -0
- package/dist/ui/managed-agents-console/index.html +47 -0
- package/dist/ui/managed-agents-console/serve.mjs +116 -0
- package/dist/ui/managed-agents-console/src/agents-files.jsx +273 -0
- package/dist/ui/managed-agents-console/src/api.js +1043 -0
- package/dist/ui/managed-agents-console/src/app.jsx +633 -0
- package/dist/ui/managed-agents-console/src/auth.jsx +215 -0
- package/dist/ui/managed-agents-console/src/console.css +733 -0
- package/dist/ui/managed-agents-console/src/data.js +188 -0
- package/dist/ui/managed-agents-console/src/detail.jsx +719 -0
- package/dist/ui/managed-agents-console/src/docs.jsx +200 -0
- package/dist/ui/managed-agents-console/src/environments.jsx +365 -0
- package/dist/ui/managed-agents-console/src/forms.jsx +494 -0
- package/dist/ui/managed-agents-console/src/icons.jsx +48 -0
- package/dist/ui/managed-agents-console/src/skills.jsx +21 -0
- package/dist/ui/managed-agents-console/src/sse.js +185 -0
- package/dist/ui/managed-agents-console/src/states.jsx +90 -0
- package/dist/ui/managed-agents-console/src/tweaks-panel.jsx +541 -0
- package/dist/ui/managed-agents-console/src/ui.jsx +190 -0
- package/dist/ui/managed-agents-console/src/vaults-data.js +89 -0
- package/dist/ui/managed-agents-console/src/vaults.jsx +171 -0
- package/dist/ui/managed-agents-console/vendor/babel.min.js +4 -0
- package/dist/ui/managed-agents-console/vendor/react-dom.production.min.js +267 -0
- package/dist/ui/managed-agents-console/vendor/react.production.min.js +31 -0
- package/dist/ui/openapi-docs/VENDOR.md +27 -0
- package/dist/ui/openapi-docs/index.html +16 -0
- package/dist/ui/openapi-docs/swagger-initializer.js +14 -0
- package/dist/ui/openapi-docs/vendor/LICENSE +202 -0
- package/dist/ui/openapi-docs/vendor/NOTICE +2 -0
- package/dist/ui/openapi-docs/vendor/swagger-ui-bundle.js +2 -0
- package/dist/ui/openapi-docs/vendor/swagger-ui-standalone-preset.js +2 -0
- package/dist/ui/openapi-docs/vendor/swagger-ui.css +3 -0
- package/package.json +53 -0
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
// auth.jsx — login view + admin panel (plan 0120 §3.4). → window
|
|
2
|
+
//
|
|
3
|
+
// Keys are used once to create an opaque, server-side console session. The
|
|
4
|
+
// browser cannot read that HttpOnly session token; the minted plaintext is
|
|
5
|
+
// still rendered exactly once, never stored, never logged.
|
|
6
|
+
const { useState: useStateA, useEffect: useEffectA } = React;
|
|
7
|
+
|
|
8
|
+
function LoginView({ onAdminLogin, onWorkspaceLogin, error, busy }) {
|
|
9
|
+
const [tier, setTier] = useStateA('workspace');
|
|
10
|
+
const [key, setKey] = useStateA('');
|
|
11
|
+
const valid = key.trim().length > 0 && !busy;
|
|
12
|
+
const submit = (e) => {
|
|
13
|
+
e.preventDefault();
|
|
14
|
+
if (!valid) return;
|
|
15
|
+
(tier === 'admin' ? onAdminLogin : onWorkspaceLogin)(key.trim());
|
|
16
|
+
};
|
|
17
|
+
return (
|
|
18
|
+
<div className="main-scroll scroll fade-in">
|
|
19
|
+
<PageHead title="Connect" sub="Enter a key once to create a revocable console session on this device." />
|
|
20
|
+
<div className="panel" style={{ maxWidth: 520, padding: 22 }}>
|
|
21
|
+
<form onSubmit={submit}>
|
|
22
|
+
<Labeled label="Credential">
|
|
23
|
+
<div className="seg-tools">
|
|
24
|
+
{[['admin', 'Admin key'], ['workspace', 'Workspace key']].map(([value, label]) => (
|
|
25
|
+
<span key={value} className={'tool-toggle' + (tier === value ? ' on' : '')}
|
|
26
|
+
onClick={() => setTier(value)}>
|
|
27
|
+
<span className="chk">{tier === value && <Icon name="checkCircle" size={9} />}</span>
|
|
28
|
+
<span className="mono">{label}</span>
|
|
29
|
+
</span>
|
|
30
|
+
))}
|
|
31
|
+
</div>
|
|
32
|
+
</Labeled>
|
|
33
|
+
<Labeled label={tier === 'admin' ? 'OMA_ADMIN_KEY' : 'x-api-key'} htmlFor="console-credential-key"
|
|
34
|
+
hint={tier === 'admin'
|
|
35
|
+
? 'Operator access: manage workspaces and select one directly.'
|
|
36
|
+
: 'Open this workspace. The server stores only a session-token hash.'}>
|
|
37
|
+
<input id="console-credential-key" name="credential" className="input mono" type="password" autoComplete="off"
|
|
38
|
+
placeholder={tier === 'admin' ? 'base64 admin key…' : 'oma_…'}
|
|
39
|
+
value={key} onChange={(e) => setKey(e.target.value)} autoFocus />
|
|
40
|
+
</Labeled>
|
|
41
|
+
{error && <div className="inline-warn"><Icon name="alert" size={14} /><span>{error}</span></div>}
|
|
42
|
+
<div className="actions" style={{ marginTop: 14 }}>
|
|
43
|
+
<button className="btn btn-primary" type="submit" disabled={!valid}
|
|
44
|
+
style={{ opacity: valid ? 1 : .5 }}>
|
|
45
|
+
<Icon name="arrowRight" size={15} />{busy ? 'Checking…' : 'Connect'}
|
|
46
|
+
</button>
|
|
47
|
+
</div>
|
|
48
|
+
</form>
|
|
49
|
+
</div>
|
|
50
|
+
</div>
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function MintedKeyModal({ minted, onClose, onBrowse }) {
|
|
55
|
+
const [copied, setCopied] = useStateA(false);
|
|
56
|
+
const copy = () => {
|
|
57
|
+
// Clipboard can be unavailable (non-secure context, denied permission);
|
|
58
|
+
// the plaintext stays visible in the modal either way.
|
|
59
|
+
navigator.clipboard.writeText(minted.api_key)
|
|
60
|
+
.then(() => setCopied(true))
|
|
61
|
+
.catch(() => {});
|
|
62
|
+
};
|
|
63
|
+
return (
|
|
64
|
+
<Modal icon="hash" title="Workspace key minted"
|
|
65
|
+
sub="Shown once. The server stores only a hash — copy it now." onClose={onClose}
|
|
66
|
+
footer={<>
|
|
67
|
+
<button className="btn" onClick={onClose}>Close</button>
|
|
68
|
+
<button className="btn" onClick={copy}>{copied ? 'Copied' : 'Copy key'}</button>
|
|
69
|
+
<button className="btn btn-primary" onClick={() => onBrowse(minted.api_key)}>
|
|
70
|
+
Browse as this workspace</button>
|
|
71
|
+
</>}>
|
|
72
|
+
<div className="code scroll" style={{ padding: 12 }}>
|
|
73
|
+
<pre style={{ margin: 0, whiteSpace: 'pre-wrap', wordBreak: 'break-all' }}>{minted.api_key}</pre>
|
|
74
|
+
</div>
|
|
75
|
+
<div className="field-hint" style={{ marginTop: 10 }}>
|
|
76
|
+
{minted.workspace_id} · {minted.label || 'no label'} · sha256 {shortId(minted.key_sha256)}
|
|
77
|
+
</div>
|
|
78
|
+
</Modal>
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function AdminPanel({ onBrowseWorkspace, onReauth, onCredentialHealth }) {
|
|
83
|
+
const [workspaces, setWorkspaces] = useStateA(null);
|
|
84
|
+
const [error, setError] = useStateA(null);
|
|
85
|
+
const [name, setName] = useStateA('');
|
|
86
|
+
const [open, setOpen] = useStateA(null); // expanded workspace id
|
|
87
|
+
const [keys, setKeys] = useStateA({}); // workspace id -> metadata[]
|
|
88
|
+
const [label, setLabel] = useStateA('');
|
|
89
|
+
const [minted, setMinted] = useStateA(null);
|
|
90
|
+
const [minting, setMinting] = useStateA(false);
|
|
91
|
+
const [revoking, setRevoking] = useStateA(null);
|
|
92
|
+
|
|
93
|
+
const fail = (err) => {
|
|
94
|
+
if (err.status === 401) onReauth();
|
|
95
|
+
else setError(err.message);
|
|
96
|
+
};
|
|
97
|
+
const refresh = () => {
|
|
98
|
+
OmaConsoleApi.listWorkspaces().then(setWorkspaces).catch(fail);
|
|
99
|
+
};
|
|
100
|
+
const refreshKeys = (workspaceId) => {
|
|
101
|
+
OmaConsoleApi.listKeys(workspaceId)
|
|
102
|
+
.then((list) => setKeys((prev) => ({ ...prev, [workspaceId]: list })))
|
|
103
|
+
.catch(fail);
|
|
104
|
+
};
|
|
105
|
+
useEffectA(refresh, []);
|
|
106
|
+
|
|
107
|
+
const create = (e) => {
|
|
108
|
+
e.preventDefault();
|
|
109
|
+
if (!name.trim()) return;
|
|
110
|
+
OmaConsoleApi.createWorkspace(name.trim())
|
|
111
|
+
.then(() => { setName(''); refresh(); })
|
|
112
|
+
.catch(fail);
|
|
113
|
+
};
|
|
114
|
+
const toggle = (workspaceId) => {
|
|
115
|
+
const next = open === workspaceId ? null : workspaceId;
|
|
116
|
+
setOpen(next);
|
|
117
|
+
setLabel('');
|
|
118
|
+
if (next) refreshKeys(next);
|
|
119
|
+
};
|
|
120
|
+
const mint = (workspaceId) => {
|
|
121
|
+
if (minting) return; // UI guard; api.js also dedupes in-flight mints
|
|
122
|
+
setMinting(true);
|
|
123
|
+
OmaConsoleApi.mintKey(workspaceId, label.trim() || undefined)
|
|
124
|
+
.then((key) => { setMinted(key); setLabel(''); refreshKeys(workspaceId); })
|
|
125
|
+
.catch(fail)
|
|
126
|
+
.finally(() => setMinting(false));
|
|
127
|
+
};
|
|
128
|
+
const revoke = (key) => {
|
|
129
|
+
OmaConsoleApi.revokeKey(key.key_sha256)
|
|
130
|
+
.then(() => { setRevoking(null); refreshKeys(key.workspace_id); })
|
|
131
|
+
.catch(fail);
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
return (
|
|
135
|
+
<div className="main-scroll scroll fade-in">
|
|
136
|
+
<PageHead title="Admin" sub="Workspaces and API keys. Every action is audit-logged server-side." />
|
|
137
|
+
{error && <div className="inline-warn"><Icon name="alert" size={14} /><span>{error}</span></div>}
|
|
138
|
+
|
|
139
|
+
<form className="toolbar" onSubmit={create}>
|
|
140
|
+
<Field icon="plus" placeholder="New workspace name" wide value={name} onChange={setName} />
|
|
141
|
+
<button className="btn btn-primary" type="submit" disabled={!name.trim()}
|
|
142
|
+
style={{ opacity: name.trim() ? 1 : .5 }}>
|
|
143
|
+
<Icon name="plus" size={15} />Create workspace</button>
|
|
144
|
+
</form>
|
|
145
|
+
|
|
146
|
+
{workspaces === null ? <SkeletonTable rows={4} cols={[160, 'grow', 90]} />
|
|
147
|
+
: workspaces.length === 0 ? <EmptyState icon="database" title="No workspaces"
|
|
148
|
+
message="Create a workspace, then mint an API key for it." />
|
|
149
|
+
: <div className="panel">
|
|
150
|
+
<div className="thead">
|
|
151
|
+
<span className="th" style={{ width: 170 }}>ID</span>
|
|
152
|
+
<span className="th grow">Name</span>
|
|
153
|
+
<span className="th" style={{ width: 110 }}>Created</span>
|
|
154
|
+
<span className="th" style={{ width: 70 }} />
|
|
155
|
+
</div>
|
|
156
|
+
{workspaces.map((workspace) => (
|
|
157
|
+
<React.Fragment key={workspace.id}>
|
|
158
|
+
<div className="trow" onClick={() => toggle(workspace.id)}>
|
|
159
|
+
<span className="td mono" style={{ width: 170, fontSize: 12, color: 'var(--soft)' }}>{workspace.id}</span>
|
|
160
|
+
<span className="td grow ell cell-strong">{workspace.name}</span>
|
|
161
|
+
<span className="td mono" style={{ width: 110, color: 'var(--faint)' }}>{shortDate(workspace.created_at)}</span>
|
|
162
|
+
<span className="td" style={{ width: 150, color: 'var(--faint)' }} onClick={(e) => e.stopPropagation()}>
|
|
163
|
+
<button className="btn" onClick={() => onCredentialHealth(workspace.id)}>Health</button>
|
|
164
|
+
{' '}{open === workspace.id ? 'close' : 'keys'}</span>
|
|
165
|
+
</div>
|
|
166
|
+
{open === workspace.id && (
|
|
167
|
+
<div style={{ padding: '10px 14px 16px', borderBottom: '1px solid var(--border)' }}>
|
|
168
|
+
<div className="toolbar" style={{ marginBottom: 8 }}>
|
|
169
|
+
<Field icon="hash" placeholder="Key label (optional)" value={label} onChange={setLabel} style={{ width: 240 }} />
|
|
170
|
+
<button className="btn btn-primary" onClick={() => mint(workspace.id)}
|
|
171
|
+
disabled={minting} style={{ opacity: minting ? .5 : 1 }}>
|
|
172
|
+
<Icon name="plus" size={15} />{minting ? 'Minting…' : 'Mint key'}</button>
|
|
173
|
+
</div>
|
|
174
|
+
{(keys[workspace.id] || []).length === 0
|
|
175
|
+
? <div className="field-hint">No keys yet.</div>
|
|
176
|
+
: (keys[workspace.id] || []).map((key) => (
|
|
177
|
+
<div className="trow" key={key.key_sha256} style={{ cursor: 'default' }}>
|
|
178
|
+
<span className="td mono" style={{ width: 150, fontSize: 12 }}>{shortId(key.key_sha256)}</span>
|
|
179
|
+
<span className="td grow ell">{key.label || '—'}</span>
|
|
180
|
+
<span className="td" style={{ width: 96 }}>
|
|
181
|
+
{key.revoked_at ? <St k="archived" /> : <St k="active" />}</span>
|
|
182
|
+
<span className="td mono" style={{ width: 110, color: 'var(--faint)' }}>{shortDate(key.created_at)}</span>
|
|
183
|
+
<span className="td" style={{ width: 80 }}>
|
|
184
|
+
{!key.revoked_at &&
|
|
185
|
+
<button className="btn" onClick={() => setRevoking(key)}>Revoke</button>}
|
|
186
|
+
</span>
|
|
187
|
+
</div>
|
|
188
|
+
))}
|
|
189
|
+
</div>
|
|
190
|
+
)}
|
|
191
|
+
</React.Fragment>
|
|
192
|
+
))}
|
|
193
|
+
</div>}
|
|
194
|
+
|
|
195
|
+
{minted && <MintedKeyModal minted={minted} onClose={() => setMinted(null)}
|
|
196
|
+
onBrowse={(plaintext) => { setMinted(null); onBrowseWorkspace(plaintext); }} />}
|
|
197
|
+
{revoking && <ConfirmDialog icon="alert" danger title="Revoke key"
|
|
198
|
+
message={`Revoke ${revoking.label || shortId(revoking.key_sha256)}? Clients using it get 401 immediately.`}
|
|
199
|
+
confirmLabel="Revoke" endpoint="DELETE /admin/keys/:sha256"
|
|
200
|
+
onClose={() => setRevoking(null)} onConfirm={() => revoke(revoking)} />}
|
|
201
|
+
</div>
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
function shortId(id) {
|
|
206
|
+
if (!id || id.length <= 14) return id;
|
|
207
|
+
return `${id.slice(0, 6)}…${id.slice(-4)}`;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
function shortDate(value) {
|
|
211
|
+
if (!value) return '—';
|
|
212
|
+
return new Intl.DateTimeFormat('en', { month: 'short', day: 'numeric' }).format(new Date(value));
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
Object.assign(window, { LoginView, AdminPanel });
|