@sanctuary-framework/mcp-server 0.5.4 → 0.5.6
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/dist/cli.cjs +1936 -1399
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +1936 -1399
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +1937 -1398
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +97 -2
- package/dist/index.d.ts +97 -2
- package/dist/index.js +1935 -1399
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -228,7 +228,7 @@ function defaultConfig() {
|
|
|
228
228
|
}
|
|
229
229
|
},
|
|
230
230
|
disclosure: {
|
|
231
|
-
proof_system: "
|
|
231
|
+
proof_system: "schnorr-pedersen",
|
|
232
232
|
default_policy: "minimum-necessary"
|
|
233
233
|
},
|
|
234
234
|
reputation: {
|
|
@@ -342,7 +342,7 @@ function validateConfig(config) {
|
|
|
342
342
|
`Unimplemented config value: execution.environment = "${config.execution.environment}". Only ${[...implementedEnvironment].map((v) => `"${v}"`).join(", ")} are currently implemented. Using an unimplemented environment would silently degrade security.`
|
|
343
343
|
);
|
|
344
344
|
}
|
|
345
|
-
const implementedProofSystem = /* @__PURE__ */ new Set(["commitment-only"]);
|
|
345
|
+
const implementedProofSystem = /* @__PURE__ */ new Set(["schnorr-pedersen", "commitment-only"]);
|
|
346
346
|
if (!implementedProofSystem.has(config.disclosure.proof_system)) {
|
|
347
347
|
errors.push(
|
|
348
348
|
`Unimplemented config value: disclosure.proof_system = "${config.disclosure.proof_system}". Only ${[...implementedProofSystem].map((v) => `"${v}"`).join(", ")} is currently implemented. Using an unimplemented proof system would silently degrade security.`
|
|
@@ -3635,6 +3635,8 @@ var DEFAULT_POLICY = {
|
|
|
3635
3635
|
"handshake_respond",
|
|
3636
3636
|
"handshake_complete",
|
|
3637
3637
|
"handshake_status",
|
|
3638
|
+
"handshake_exchange",
|
|
3639
|
+
"handshake_verify_attestation",
|
|
3638
3640
|
"reputation_query_weighted",
|
|
3639
3641
|
"federation_peers",
|
|
3640
3642
|
"federation_trust_evaluate",
|
|
@@ -3804,6 +3806,8 @@ tier3_always_allow:
|
|
|
3804
3806
|
- handshake_respond
|
|
3805
3807
|
- handshake_complete
|
|
3806
3808
|
- handshake_status
|
|
3809
|
+
- handshake_exchange
|
|
3810
|
+
- handshake_verify_attestation
|
|
3807
3811
|
- reputation_query_weighted
|
|
3808
3812
|
- federation_peers
|
|
3809
3813
|
- federation_trust_evaluate
|
|
@@ -4065,174 +4069,255 @@ function generateLoginHTML(options) {
|
|
|
4065
4069
|
return `<!DOCTYPE html>
|
|
4066
4070
|
<html lang="en">
|
|
4067
4071
|
<head>
|
|
4068
|
-
<meta charset="
|
|
4069
|
-
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
4070
|
-
<title>Sanctuary
|
|
4071
|
-
<
|
|
4072
|
-
|
|
4073
|
-
|
|
4074
|
-
|
|
4075
|
-
|
|
4076
|
-
|
|
4077
|
-
|
|
4078
|
-
|
|
4079
|
-
|
|
4080
|
-
|
|
4081
|
-
|
|
4082
|
-
|
|
4083
|
-
|
|
4084
|
-
|
|
4085
|
-
|
|
4086
|
-
|
|
4087
|
-
|
|
4088
|
-
|
|
4089
|
-
|
|
4090
|
-
|
|
4091
|
-
|
|
4092
|
-
|
|
4093
|
-
|
|
4094
|
-
|
|
4095
|
-
|
|
4096
|
-
|
|
4097
|
-
|
|
4098
|
-
|
|
4099
|
-
|
|
4100
|
-
|
|
4101
|
-
|
|
4102
|
-
|
|
4103
|
-
|
|
4104
|
-
|
|
4105
|
-
|
|
4106
|
-
|
|
4107
|
-
|
|
4108
|
-
|
|
4109
|
-
|
|
4110
|
-
|
|
4111
|
-
|
|
4112
|
-
|
|
4113
|
-
|
|
4114
|
-
|
|
4115
|
-
|
|
4116
|
-
|
|
4117
|
-
|
|
4118
|
-
|
|
4119
|
-
|
|
4120
|
-
|
|
4121
|
-
|
|
4122
|
-
|
|
4123
|
-
|
|
4124
|
-
|
|
4125
|
-
|
|
4126
|
-
|
|
4127
|
-
|
|
4128
|
-
|
|
4129
|
-
|
|
4130
|
-
|
|
4131
|
-
|
|
4132
|
-
|
|
4133
|
-
|
|
4134
|
-
|
|
4135
|
-
|
|
4136
|
-
|
|
4137
|
-
|
|
4138
|
-
|
|
4139
|
-
|
|
4140
|
-
|
|
4141
|
-
|
|
4142
|
-
|
|
4143
|
-
|
|
4144
|
-
|
|
4145
|
-
|
|
4146
|
-
|
|
4147
|
-
|
|
4148
|
-
|
|
4149
|
-
|
|
4150
|
-
|
|
4151
|
-
|
|
4152
|
-
|
|
4153
|
-
|
|
4154
|
-
|
|
4155
|
-
|
|
4156
|
-
|
|
4157
|
-
|
|
4158
|
-
|
|
4159
|
-
|
|
4160
|
-
|
|
4161
|
-
|
|
4162
|
-
|
|
4163
|
-
|
|
4164
|
-
|
|
4165
|
-
|
|
4166
|
-
|
|
4167
|
-
|
|
4168
|
-
|
|
4169
|
-
|
|
4170
|
-
|
|
4171
|
-
|
|
4172
|
-
|
|
4173
|
-
|
|
4174
|
-
|
|
4175
|
-
|
|
4176
|
-
|
|
4177
|
-
|
|
4178
|
-
|
|
4179
|
-
|
|
4180
|
-
|
|
4181
|
-
|
|
4072
|
+
<meta charset="UTF-8">
|
|
4073
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
4074
|
+
<title>Sanctuary Dashboard</title>
|
|
4075
|
+
<style>
|
|
4076
|
+
:root {
|
|
4077
|
+
--bg: #0d1117;
|
|
4078
|
+
--surface: #161b22;
|
|
4079
|
+
--border: #30363d;
|
|
4080
|
+
--text-primary: #e6edf3;
|
|
4081
|
+
--text-secondary: #8b949e;
|
|
4082
|
+
--green: #3fb950;
|
|
4083
|
+
--amber: #d29922;
|
|
4084
|
+
--red: #f85149;
|
|
4085
|
+
--blue: #58a6ff;
|
|
4086
|
+
}
|
|
4087
|
+
|
|
4088
|
+
* {
|
|
4089
|
+
margin: 0;
|
|
4090
|
+
padding: 0;
|
|
4091
|
+
box-sizing: border-box;
|
|
4092
|
+
}
|
|
4093
|
+
|
|
4094
|
+
body {
|
|
4095
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif;
|
|
4096
|
+
background-color: var(--bg);
|
|
4097
|
+
color: var(--text-primary);
|
|
4098
|
+
min-height: 100vh;
|
|
4099
|
+
display: flex;
|
|
4100
|
+
align-items: center;
|
|
4101
|
+
justify-content: center;
|
|
4102
|
+
}
|
|
4103
|
+
|
|
4104
|
+
.login-container {
|
|
4105
|
+
width: 100%;
|
|
4106
|
+
max-width: 400px;
|
|
4107
|
+
padding: 20px;
|
|
4108
|
+
}
|
|
4109
|
+
|
|
4110
|
+
.login-card {
|
|
4111
|
+
background-color: var(--surface);
|
|
4112
|
+
border: 1px solid var(--border);
|
|
4113
|
+
border-radius: 8px;
|
|
4114
|
+
padding: 40px 32px;
|
|
4115
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
|
|
4116
|
+
}
|
|
4117
|
+
|
|
4118
|
+
.login-header {
|
|
4119
|
+
display: flex;
|
|
4120
|
+
align-items: center;
|
|
4121
|
+
gap: 12px;
|
|
4122
|
+
margin-bottom: 32px;
|
|
4123
|
+
}
|
|
4124
|
+
|
|
4125
|
+
.logo {
|
|
4126
|
+
font-size: 24px;
|
|
4127
|
+
font-weight: 700;
|
|
4128
|
+
color: var(--blue);
|
|
4129
|
+
}
|
|
4130
|
+
|
|
4131
|
+
.logo-text {
|
|
4132
|
+
display: flex;
|
|
4133
|
+
flex-direction: column;
|
|
4134
|
+
}
|
|
4135
|
+
|
|
4136
|
+
.logo-text .title {
|
|
4137
|
+
font-size: 18px;
|
|
4138
|
+
font-weight: 600;
|
|
4139
|
+
letter-spacing: -0.5px;
|
|
4140
|
+
}
|
|
4141
|
+
|
|
4142
|
+
.logo-text .version {
|
|
4143
|
+
font-size: 12px;
|
|
4144
|
+
color: var(--text-secondary);
|
|
4145
|
+
margin-top: 2px;
|
|
4146
|
+
}
|
|
4147
|
+
|
|
4148
|
+
.form-group {
|
|
4149
|
+
margin-bottom: 24px;
|
|
4150
|
+
}
|
|
4151
|
+
|
|
4152
|
+
label {
|
|
4153
|
+
display: block;
|
|
4154
|
+
font-size: 14px;
|
|
4155
|
+
font-weight: 500;
|
|
4156
|
+
margin-bottom: 8px;
|
|
4157
|
+
color: var(--text-primary);
|
|
4158
|
+
}
|
|
4159
|
+
|
|
4160
|
+
input[type="text"],
|
|
4161
|
+
input[type="password"] {
|
|
4162
|
+
width: 100%;
|
|
4163
|
+
padding: 10px 12px;
|
|
4164
|
+
background-color: var(--bg);
|
|
4165
|
+
border: 1px solid var(--border);
|
|
4166
|
+
border-radius: 6px;
|
|
4167
|
+
color: var(--text-primary);
|
|
4168
|
+
font-size: 14px;
|
|
4169
|
+
font-family: 'JetBrains Mono', monospace;
|
|
4170
|
+
transition: border-color 0.2s;
|
|
4171
|
+
}
|
|
4172
|
+
|
|
4173
|
+
input[type="text"]:focus,
|
|
4174
|
+
input[type="password"]:focus {
|
|
4175
|
+
outline: none;
|
|
4176
|
+
border-color: var(--blue);
|
|
4177
|
+
box-shadow: 0 0 0 2px rgba(88, 166, 255, 0.1);
|
|
4178
|
+
}
|
|
4179
|
+
|
|
4180
|
+
.error-message {
|
|
4181
|
+
display: none;
|
|
4182
|
+
background-color: rgba(248, 81, 73, 0.1);
|
|
4183
|
+
border: 1px solid var(--red);
|
|
4184
|
+
color: #ff9999;
|
|
4185
|
+
padding: 12px;
|
|
4186
|
+
border-radius: 6px;
|
|
4187
|
+
font-size: 13px;
|
|
4188
|
+
margin-bottom: 20px;
|
|
4189
|
+
}
|
|
4190
|
+
|
|
4191
|
+
.error-message.show {
|
|
4192
|
+
display: block;
|
|
4193
|
+
}
|
|
4194
|
+
|
|
4195
|
+
button {
|
|
4196
|
+
width: 100%;
|
|
4197
|
+
padding: 10px 16px;
|
|
4198
|
+
background-color: var(--blue);
|
|
4199
|
+
color: var(--bg);
|
|
4200
|
+
border: none;
|
|
4201
|
+
border-radius: 6px;
|
|
4202
|
+
font-size: 14px;
|
|
4203
|
+
font-weight: 600;
|
|
4204
|
+
cursor: pointer;
|
|
4205
|
+
transition: background-color 0.2s;
|
|
4206
|
+
}
|
|
4207
|
+
|
|
4208
|
+
button:hover {
|
|
4209
|
+
background-color: #79c0ff;
|
|
4210
|
+
}
|
|
4211
|
+
|
|
4212
|
+
button:active {
|
|
4213
|
+
background-color: #4184e4;
|
|
4214
|
+
}
|
|
4215
|
+
|
|
4216
|
+
button:disabled {
|
|
4217
|
+
background-color: var(--text-secondary);
|
|
4218
|
+
cursor: not-allowed;
|
|
4219
|
+
opacity: 0.5;
|
|
4220
|
+
}
|
|
4221
|
+
|
|
4222
|
+
.info-text {
|
|
4223
|
+
font-size: 12px;
|
|
4224
|
+
color: var(--text-secondary);
|
|
4225
|
+
margin-top: 16px;
|
|
4226
|
+
text-align: center;
|
|
4227
|
+
}
|
|
4228
|
+
</style>
|
|
4182
4229
|
</head>
|
|
4183
4230
|
<body>
|
|
4184
|
-
<div class="login-container">
|
|
4185
|
-
|
|
4186
|
-
|
|
4187
|
-
|
|
4188
|
-
|
|
4189
|
-
|
|
4190
|
-
|
|
4191
|
-
|
|
4192
|
-
|
|
4193
|
-
|
|
4194
|
-
|
|
4195
|
-
|
|
4196
|
-
|
|
4231
|
+
<div class="login-container">
|
|
4232
|
+
<div class="login-card">
|
|
4233
|
+
<div class="login-header">
|
|
4234
|
+
<div class="logo">\u25C6</div>
|
|
4235
|
+
<div class="logo-text">
|
|
4236
|
+
<div class="title">SANCTUARY</div>
|
|
4237
|
+
<div class="version">v${options.serverVersion}</div>
|
|
4238
|
+
</div>
|
|
4239
|
+
</div>
|
|
4240
|
+
|
|
4241
|
+
<div id="error-message" class="error-message"></div>
|
|
4242
|
+
|
|
4243
|
+
<form id="login-form">
|
|
4244
|
+
<div class="form-group">
|
|
4245
|
+
<label for="auth-token">Bearer Token</label>
|
|
4246
|
+
<input
|
|
4247
|
+
type="text"
|
|
4248
|
+
id="auth-token"
|
|
4249
|
+
name="token"
|
|
4250
|
+
placeholder="Paste your session token..."
|
|
4251
|
+
autocomplete="off"
|
|
4252
|
+
spellcheck="false"
|
|
4253
|
+
required
|
|
4254
|
+
/>
|
|
4255
|
+
</div>
|
|
4256
|
+
|
|
4257
|
+
<button type="submit" id="login-button">Open Dashboard</button>
|
|
4258
|
+
</form>
|
|
4259
|
+
|
|
4260
|
+
<div class="info-text">
|
|
4261
|
+
Session tokens expire after 1 hour of inactivity
|
|
4262
|
+
</div>
|
|
4263
|
+
</div>
|
|
4197
4264
|
</div>
|
|
4198
|
-
|
|
4199
|
-
<script>
|
|
4200
|
-
|
|
4201
|
-
|
|
4202
|
-
|
|
4203
|
-
|
|
4204
|
-
|
|
4205
|
-
|
|
4206
|
-
|
|
4207
|
-
|
|
4208
|
-
|
|
4209
|
-
|
|
4210
|
-
|
|
4211
|
-
|
|
4212
|
-
|
|
4265
|
+
|
|
4266
|
+
<script>
|
|
4267
|
+
const loginForm = document.getElementById('login-form');
|
|
4268
|
+
const authTokenInput = document.getElementById('auth-token');
|
|
4269
|
+
const errorMessage = document.getElementById('error-message');
|
|
4270
|
+
const loginButton = document.getElementById('login-button');
|
|
4271
|
+
|
|
4272
|
+
loginForm.addEventListener('submit', async (e) => {
|
|
4273
|
+
e.preventDefault();
|
|
4274
|
+
const token = authTokenInput.value.trim();
|
|
4275
|
+
|
|
4276
|
+
if (!token) {
|
|
4277
|
+
showError('Token is required');
|
|
4278
|
+
return;
|
|
4279
|
+
}
|
|
4280
|
+
|
|
4281
|
+
loginButton.disabled = true;
|
|
4282
|
+
loginButton.textContent = 'Verifying...';
|
|
4283
|
+
errorMessage.classList.remove('show');
|
|
4284
|
+
|
|
4285
|
+
try {
|
|
4286
|
+
const response = await fetch('/auth/session', {
|
|
4287
|
+
method: 'POST',
|
|
4288
|
+
headers: {
|
|
4289
|
+
'Content-Type': 'application/json',
|
|
4290
|
+
'Authorization': 'Bearer ' + token,
|
|
4291
|
+
},
|
|
4292
|
+
body: JSON.stringify({ token }),
|
|
4293
|
+
});
|
|
4294
|
+
|
|
4295
|
+
if (response.ok) {
|
|
4296
|
+
const data = await response.json();
|
|
4297
|
+
sessionStorage.setItem('authToken', token);
|
|
4298
|
+
window.location.href = '/dashboard';
|
|
4299
|
+
} else if (response.status === 401) {
|
|
4300
|
+
showError('Invalid token. Please check and try again.');
|
|
4301
|
+
} else {
|
|
4302
|
+
showError('Authentication failed. Please try again.');
|
|
4303
|
+
}
|
|
4304
|
+
} catch (err) {
|
|
4305
|
+
showError('Connection error. Please check your network.');
|
|
4306
|
+
} finally {
|
|
4307
|
+
loginButton.disabled = false;
|
|
4308
|
+
loginButton.textContent = 'Open Dashboard';
|
|
4309
|
+
}
|
|
4213
4310
|
});
|
|
4214
|
-
|
|
4215
|
-
|
|
4216
|
-
|
|
4217
|
-
|
|
4218
|
-
|
|
4219
|
-
|
|
4220
|
-
|
|
4221
|
-
|
|
4222
|
-
|
|
4223
|
-
|
|
4224
|
-
'; path=/; SameSite=Strict; max-age=' + maxAge;
|
|
4225
|
-
// Reload to enter the dashboard
|
|
4226
|
-
window.location.reload();
|
|
4227
|
-
} catch (err) {
|
|
4228
|
-
errEl.textContent = err.message || 'Authentication failed. Check your token.';
|
|
4229
|
-
errEl.style.display = 'block';
|
|
4230
|
-
btn.disabled = false;
|
|
4231
|
-
btn.textContent = 'Open Dashboard';
|
|
4232
|
-
}
|
|
4233
|
-
return false;
|
|
4234
|
-
}
|
|
4235
|
-
</script>
|
|
4311
|
+
|
|
4312
|
+
function showError(message) {
|
|
4313
|
+
errorMessage.textContent = message;
|
|
4314
|
+
errorMessage.classList.add('show');
|
|
4315
|
+
}
|
|
4316
|
+
|
|
4317
|
+
authTokenInput.addEventListener('input', () => {
|
|
4318
|
+
errorMessage.classList.remove('show');
|
|
4319
|
+
});
|
|
4320
|
+
</script>
|
|
4236
4321
|
</body>
|
|
4237
4322
|
</html>`;
|
|
4238
4323
|
}
|
|
@@ -4240,1412 +4325,1648 @@ function generateDashboardHTML(options) {
|
|
|
4240
4325
|
return `<!DOCTYPE html>
|
|
4241
4326
|
<html lang="en">
|
|
4242
4327
|
<head>
|
|
4243
|
-
<meta charset="
|
|
4244
|
-
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
4245
|
-
<title>Sanctuary
|
|
4246
|
-
<
|
|
4247
|
-
|
|
4248
|
-
|
|
4249
|
-
|
|
4250
|
-
|
|
4251
|
-
|
|
4252
|
-
|
|
4253
|
-
|
|
4254
|
-
|
|
4255
|
-
|
|
4256
|
-
|
|
4257
|
-
|
|
4258
|
-
|
|
4259
|
-
|
|
4260
|
-
|
|
4261
|
-
|
|
4262
|
-
|
|
4263
|
-
|
|
4264
|
-
|
|
4265
|
-
|
|
4266
|
-
|
|
4267
|
-
|
|
4328
|
+
<meta charset="UTF-8">
|
|
4329
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
4330
|
+
<title>Sanctuary Dashboard</title>
|
|
4331
|
+
<style>
|
|
4332
|
+
:root {
|
|
4333
|
+
--bg: #0d1117;
|
|
4334
|
+
--surface: #161b22;
|
|
4335
|
+
--border: #30363d;
|
|
4336
|
+
--text-primary: #e6edf3;
|
|
4337
|
+
--text-secondary: #8b949e;
|
|
4338
|
+
--green: #3fb950;
|
|
4339
|
+
--amber: #d29922;
|
|
4340
|
+
--red: #f85149;
|
|
4341
|
+
--blue: #58a6ff;
|
|
4342
|
+
--success: #3fb950;
|
|
4343
|
+
--warning: #d29922;
|
|
4344
|
+
--error: #f85149;
|
|
4345
|
+
--muted: #21262d;
|
|
4346
|
+
}
|
|
4347
|
+
|
|
4348
|
+
* {
|
|
4349
|
+
margin: 0;
|
|
4350
|
+
padding: 0;
|
|
4351
|
+
box-sizing: border-box;
|
|
4352
|
+
}
|
|
4353
|
+
|
|
4354
|
+
html, body {
|
|
4355
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif;
|
|
4356
|
+
background-color: var(--bg);
|
|
4357
|
+
color: var(--text-primary);
|
|
4358
|
+
height: 100%;
|
|
4359
|
+
overflow: hidden;
|
|
4360
|
+
}
|
|
4361
|
+
|
|
4362
|
+
body {
|
|
4363
|
+
display: flex;
|
|
4364
|
+
flex-direction: column;
|
|
4365
|
+
}
|
|
4366
|
+
|
|
4367
|
+
/* Status Bar */
|
|
4368
|
+
.status-bar {
|
|
4369
|
+
position: fixed;
|
|
4370
|
+
top: 0;
|
|
4371
|
+
left: 0;
|
|
4372
|
+
right: 0;
|
|
4373
|
+
height: 56px;
|
|
4374
|
+
background-color: var(--surface);
|
|
4375
|
+
border-bottom: 1px solid var(--border);
|
|
4376
|
+
display: flex;
|
|
4377
|
+
align-items: center;
|
|
4378
|
+
padding: 0 24px;
|
|
4379
|
+
gap: 24px;
|
|
4380
|
+
z-index: 100;
|
|
4381
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
|
|
4382
|
+
}
|
|
4383
|
+
|
|
4384
|
+
.status-bar-left {
|
|
4385
|
+
display: flex;
|
|
4386
|
+
align-items: center;
|
|
4387
|
+
gap: 12px;
|
|
4388
|
+
flex: 0 0 auto;
|
|
4389
|
+
}
|
|
4268
4390
|
|
|
4269
|
-
|
|
4270
|
-
|
|
4271
|
-
|
|
4272
|
-
|
|
4273
|
-
|
|
4274
|
-
|
|
4275
|
-
body {
|
|
4276
|
-
font-family: var(--sans);
|
|
4277
|
-
background: var(--bg);
|
|
4278
|
-
color: var(--text-primary);
|
|
4279
|
-
display: flex;
|
|
4280
|
-
flex-direction: column;
|
|
4281
|
-
}
|
|
4282
|
-
|
|
4283
|
-
/* \u2500\u2500 Top Status Bar (fixed) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
|
|
4391
|
+
.logo-icon {
|
|
4392
|
+
font-size: 20px;
|
|
4393
|
+
color: var(--blue);
|
|
4394
|
+
font-weight: 700;
|
|
4395
|
+
}
|
|
4284
4396
|
|
|
4285
|
-
|
|
4286
|
-
|
|
4287
|
-
|
|
4288
|
-
|
|
4289
|
-
right: 0;
|
|
4290
|
-
height: 56px;
|
|
4291
|
-
background: var(--surface);
|
|
4292
|
-
border-bottom: 1px solid var(--border);
|
|
4293
|
-
display: flex;
|
|
4294
|
-
align-items: center;
|
|
4295
|
-
padding: 0 20px;
|
|
4296
|
-
gap: 24px;
|
|
4297
|
-
z-index: 1000;
|
|
4298
|
-
}
|
|
4397
|
+
.logo-info {
|
|
4398
|
+
display: flex;
|
|
4399
|
+
flex-direction: column;
|
|
4400
|
+
}
|
|
4299
4401
|
|
|
4300
|
-
|
|
4301
|
-
|
|
4302
|
-
|
|
4303
|
-
|
|
4304
|
-
|
|
4305
|
-
|
|
4402
|
+
.logo-title {
|
|
4403
|
+
font-size: 13px;
|
|
4404
|
+
font-weight: 600;
|
|
4405
|
+
line-height: 1;
|
|
4406
|
+
color: var(--text-primary);
|
|
4407
|
+
}
|
|
4306
4408
|
|
|
4307
|
-
|
|
4308
|
-
|
|
4309
|
-
|
|
4310
|
-
|
|
4311
|
-
|
|
4312
|
-
}
|
|
4409
|
+
.logo-version {
|
|
4410
|
+
font-size: 11px;
|
|
4411
|
+
color: var(--text-secondary);
|
|
4412
|
+
margin-top: 2px;
|
|
4413
|
+
}
|
|
4313
4414
|
|
|
4314
|
-
|
|
4315
|
-
|
|
4316
|
-
|
|
4415
|
+
.status-bar-center {
|
|
4416
|
+
flex: 1;
|
|
4417
|
+
display: flex;
|
|
4418
|
+
justify-content: center;
|
|
4419
|
+
}
|
|
4317
4420
|
|
|
4318
|
-
|
|
4319
|
-
|
|
4320
|
-
|
|
4321
|
-
|
|
4322
|
-
|
|
4421
|
+
.sovereignty-badge {
|
|
4422
|
+
display: flex;
|
|
4423
|
+
align-items: center;
|
|
4424
|
+
gap: 8px;
|
|
4425
|
+
padding: 8px 16px;
|
|
4426
|
+
background-color: rgba(63, 185, 80, 0.1);
|
|
4427
|
+
border: 1px solid rgba(63, 185, 80, 0.3);
|
|
4428
|
+
border-radius: 6px;
|
|
4429
|
+
font-size: 13px;
|
|
4430
|
+
font-weight: 500;
|
|
4431
|
+
}
|
|
4323
4432
|
|
|
4324
|
-
|
|
4325
|
-
|
|
4326
|
-
|
|
4327
|
-
|
|
4328
|
-
justify-content: center;
|
|
4329
|
-
}
|
|
4330
|
-
|
|
4331
|
-
.sovereignty-badge {
|
|
4332
|
-
display: flex;
|
|
4333
|
-
align-items: center;
|
|
4334
|
-
gap: 8px;
|
|
4335
|
-
padding: 6px 12px;
|
|
4336
|
-
background: rgba(88, 166, 255, 0.1);
|
|
4337
|
-
border: 1px solid var(--blue);
|
|
4338
|
-
border-radius: 20px;
|
|
4339
|
-
font-size: 13px;
|
|
4340
|
-
font-weight: 600;
|
|
4341
|
-
}
|
|
4433
|
+
.sovereignty-badge.degraded {
|
|
4434
|
+
background-color: rgba(210, 153, 34, 0.1);
|
|
4435
|
+
border-color: rgba(210, 153, 34, 0.3);
|
|
4436
|
+
}
|
|
4342
4437
|
|
|
4343
|
-
|
|
4344
|
-
|
|
4345
|
-
|
|
4346
|
-
|
|
4347
|
-
width: 28px;
|
|
4348
|
-
height: 28px;
|
|
4349
|
-
border-radius: 50%;
|
|
4350
|
-
font-family: var(--mono);
|
|
4351
|
-
font-weight: 700;
|
|
4352
|
-
font-size: 12px;
|
|
4353
|
-
background: var(--blue);
|
|
4354
|
-
color: var(--bg);
|
|
4355
|
-
}
|
|
4438
|
+
.sovereignty-badge.inactive {
|
|
4439
|
+
background-color: rgba(248, 81, 73, 0.1);
|
|
4440
|
+
border-color: rgba(248, 81, 73, 0.3);
|
|
4441
|
+
}
|
|
4356
4442
|
|
|
4357
|
-
|
|
4358
|
-
|
|
4359
|
-
|
|
4443
|
+
.sovereignty-score {
|
|
4444
|
+
font-weight: 700;
|
|
4445
|
+
color: var(--green);
|
|
4446
|
+
}
|
|
4360
4447
|
|
|
4361
|
-
|
|
4362
|
-
|
|
4363
|
-
|
|
4448
|
+
.sovereignty-badge.degraded .sovereignty-score {
|
|
4449
|
+
color: var(--amber);
|
|
4450
|
+
}
|
|
4364
4451
|
|
|
4365
|
-
|
|
4366
|
-
|
|
4367
|
-
|
|
4452
|
+
.sovereignty-badge.inactive .sovereignty-score {
|
|
4453
|
+
color: var(--red);
|
|
4454
|
+
}
|
|
4368
4455
|
|
|
4369
|
-
|
|
4370
|
-
|
|
4371
|
-
|
|
4372
|
-
|
|
4373
|
-
|
|
4374
|
-
|
|
4456
|
+
.status-bar-right {
|
|
4457
|
+
display: flex;
|
|
4458
|
+
align-items: center;
|
|
4459
|
+
gap: 16px;
|
|
4460
|
+
flex: 0 0 auto;
|
|
4461
|
+
}
|
|
4375
4462
|
|
|
4376
|
-
|
|
4377
|
-
|
|
4378
|
-
|
|
4379
|
-
|
|
4380
|
-
|
|
4381
|
-
|
|
4382
|
-
|
|
4383
|
-
}
|
|
4463
|
+
.status-item {
|
|
4464
|
+
display: flex;
|
|
4465
|
+
align-items: center;
|
|
4466
|
+
gap: 6px;
|
|
4467
|
+
font-size: 12px;
|
|
4468
|
+
color: var(--text-secondary);
|
|
4469
|
+
}
|
|
4384
4470
|
|
|
4385
|
-
|
|
4386
|
-
|
|
4387
|
-
|
|
4388
|
-
|
|
4471
|
+
.status-item strong {
|
|
4472
|
+
color: var(--text-primary);
|
|
4473
|
+
font-weight: 500;
|
|
4474
|
+
}
|
|
4389
4475
|
|
|
4390
|
-
|
|
4391
|
-
|
|
4392
|
-
|
|
4393
|
-
|
|
4394
|
-
|
|
4395
|
-
|
|
4396
|
-
font-family: var(--mono);
|
|
4397
|
-
}
|
|
4476
|
+
.status-dot {
|
|
4477
|
+
width: 8px;
|
|
4478
|
+
height: 8px;
|
|
4479
|
+
border-radius: 50%;
|
|
4480
|
+
background-color: var(--green);
|
|
4481
|
+
}
|
|
4398
4482
|
|
|
4399
|
-
|
|
4400
|
-
|
|
4401
|
-
|
|
4402
|
-
border-radius: 50%;
|
|
4403
|
-
background: var(--green);
|
|
4404
|
-
animation: pulse 2s ease-in-out infinite;
|
|
4405
|
-
}
|
|
4483
|
+
.status-dot.disconnected {
|
|
4484
|
+
background-color: var(--red);
|
|
4485
|
+
}
|
|
4406
4486
|
|
|
4407
|
-
|
|
4408
|
-
|
|
4409
|
-
|
|
4410
|
-
|
|
4487
|
+
.pending-badge {
|
|
4488
|
+
display: flex;
|
|
4489
|
+
align-items: center;
|
|
4490
|
+
gap: 6px;
|
|
4491
|
+
padding: 4px 8px;
|
|
4492
|
+
background-color: var(--blue);
|
|
4493
|
+
color: var(--bg);
|
|
4494
|
+
border-radius: 4px;
|
|
4495
|
+
font-size: 11px;
|
|
4496
|
+
font-weight: 600;
|
|
4497
|
+
cursor: pointer;
|
|
4498
|
+
}
|
|
4411
4499
|
|
|
4412
|
-
|
|
4413
|
-
|
|
4414
|
-
|
|
4415
|
-
|
|
4500
|
+
/* Main Content */
|
|
4501
|
+
.main-content {
|
|
4502
|
+
flex: 1;
|
|
4503
|
+
margin-top: 56px;
|
|
4504
|
+
overflow-y: auto;
|
|
4505
|
+
padding: 24px;
|
|
4506
|
+
}
|
|
4416
4507
|
|
|
4417
|
-
|
|
4418
|
-
|
|
4419
|
-
|
|
4420
|
-
|
|
4421
|
-
min-width: 24px;
|
|
4422
|
-
height: 24px;
|
|
4423
|
-
padding: 0 6px;
|
|
4424
|
-
background: var(--red);
|
|
4425
|
-
color: white;
|
|
4426
|
-
border-radius: 12px;
|
|
4427
|
-
font-size: 11px;
|
|
4428
|
-
font-weight: 700;
|
|
4429
|
-
animation: pulse 1s ease-in-out infinite;
|
|
4430
|
-
}
|
|
4508
|
+
.grid {
|
|
4509
|
+
display: grid;
|
|
4510
|
+
gap: 20px;
|
|
4511
|
+
}
|
|
4431
4512
|
|
|
4432
|
-
|
|
4433
|
-
|
|
4434
|
-
|
|
4513
|
+
/* Row 1: Sovereignty Layers */
|
|
4514
|
+
.sovereignty-layers {
|
|
4515
|
+
display: grid;
|
|
4516
|
+
grid-template-columns: repeat(4, 1fr);
|
|
4517
|
+
gap: 16px;
|
|
4518
|
+
}
|
|
4435
4519
|
|
|
4436
|
-
|
|
4520
|
+
.layer-card {
|
|
4521
|
+
background-color: var(--surface);
|
|
4522
|
+
border: 1px solid var(--border);
|
|
4523
|
+
border-radius: 8px;
|
|
4524
|
+
padding: 20px;
|
|
4525
|
+
display: flex;
|
|
4526
|
+
flex-direction: column;
|
|
4527
|
+
gap: 12px;
|
|
4528
|
+
}
|
|
4437
4529
|
|
|
4438
|
-
|
|
4439
|
-
|
|
4440
|
-
|
|
4441
|
-
|
|
4442
|
-
overflow: hidden;
|
|
4443
|
-
}
|
|
4530
|
+
.layer-card.degraded {
|
|
4531
|
+
border-color: var(--amber);
|
|
4532
|
+
background-color: rgba(210, 153, 34, 0.05);
|
|
4533
|
+
}
|
|
4444
4534
|
|
|
4445
|
-
|
|
4446
|
-
|
|
4447
|
-
|
|
4448
|
-
|
|
4449
|
-
border-right: 1px solid var(--border);
|
|
4450
|
-
overflow: hidden;
|
|
4451
|
-
}
|
|
4535
|
+
.layer-card.inactive {
|
|
4536
|
+
border-color: var(--red);
|
|
4537
|
+
background-color: rgba(248, 81, 73, 0.05);
|
|
4538
|
+
}
|
|
4452
4539
|
|
|
4453
|
-
|
|
4454
|
-
|
|
4455
|
-
|
|
4456
|
-
|
|
4457
|
-
|
|
4458
|
-
|
|
4459
|
-
|
|
4460
|
-
font-weight: 600;
|
|
4461
|
-
text-transform: uppercase;
|
|
4462
|
-
letter-spacing: 0.5px;
|
|
4463
|
-
color: var(--text-secondary);
|
|
4464
|
-
}
|
|
4540
|
+
.layer-name {
|
|
4541
|
+
font-size: 12px;
|
|
4542
|
+
font-weight: 600;
|
|
4543
|
+
color: var(--text-secondary);
|
|
4544
|
+
text-transform: uppercase;
|
|
4545
|
+
letter-spacing: 0.5px;
|
|
4546
|
+
}
|
|
4465
4547
|
|
|
4466
|
-
|
|
4467
|
-
|
|
4468
|
-
|
|
4469
|
-
|
|
4470
|
-
|
|
4471
|
-
}
|
|
4548
|
+
.layer-title {
|
|
4549
|
+
font-size: 14px;
|
|
4550
|
+
font-weight: 600;
|
|
4551
|
+
color: var(--text-primary);
|
|
4552
|
+
}
|
|
4472
4553
|
|
|
4473
|
-
|
|
4474
|
-
|
|
4475
|
-
|
|
4476
|
-
|
|
4477
|
-
|
|
4554
|
+
.layer-status {
|
|
4555
|
+
display: inline-flex;
|
|
4556
|
+
align-items: center;
|
|
4557
|
+
gap: 6px;
|
|
4558
|
+
padding: 4px 8px;
|
|
4559
|
+
background-color: rgba(63, 185, 80, 0.15);
|
|
4560
|
+
color: var(--green);
|
|
4561
|
+
border-radius: 4px;
|
|
4562
|
+
font-size: 11px;
|
|
4563
|
+
font-weight: 600;
|
|
4564
|
+
width: fit-content;
|
|
4565
|
+
}
|
|
4478
4566
|
|
|
4479
|
-
|
|
4480
|
-
|
|
4481
|
-
|
|
4482
|
-
|
|
4483
|
-
font-family: var(--mono);
|
|
4484
|
-
cursor: pointer;
|
|
4485
|
-
transition: background 0.15s;
|
|
4486
|
-
display: flex;
|
|
4487
|
-
align-items: flex-start;
|
|
4488
|
-
gap: 10px;
|
|
4489
|
-
}
|
|
4567
|
+
.layer-card.degraded .layer-status {
|
|
4568
|
+
background-color: rgba(210, 153, 34, 0.15);
|
|
4569
|
+
color: var(--amber);
|
|
4570
|
+
}
|
|
4490
4571
|
|
|
4491
|
-
|
|
4492
|
-
|
|
4493
|
-
|
|
4572
|
+
.layer-card.inactive .layer-status {
|
|
4573
|
+
background-color: rgba(248, 81, 73, 0.15);
|
|
4574
|
+
color: var(--red);
|
|
4575
|
+
}
|
|
4494
4576
|
|
|
4495
|
-
|
|
4496
|
-
|
|
4497
|
-
|
|
4498
|
-
|
|
4499
|
-
|
|
4500
|
-
|
|
4501
|
-
|
|
4502
|
-
|
|
4577
|
+
.layer-detail {
|
|
4578
|
+
font-size: 12px;
|
|
4579
|
+
color: var(--text-secondary);
|
|
4580
|
+
font-family: 'JetBrains Mono', monospace;
|
|
4581
|
+
padding: 8px;
|
|
4582
|
+
background-color: var(--bg);
|
|
4583
|
+
border-radius: 4px;
|
|
4584
|
+
border-left: 2px solid var(--blue);
|
|
4585
|
+
}
|
|
4503
4586
|
|
|
4504
|
-
|
|
4505
|
-
|
|
4506
|
-
|
|
4507
|
-
|
|
4587
|
+
/* Row 2: Info Cards */
|
|
4588
|
+
.info-cards {
|
|
4589
|
+
display: grid;
|
|
4590
|
+
grid-template-columns: repeat(3, 1fr);
|
|
4591
|
+
gap: 16px;
|
|
4592
|
+
}
|
|
4508
4593
|
|
|
4509
|
-
|
|
4510
|
-
|
|
4511
|
-
|
|
4512
|
-
|
|
4513
|
-
|
|
4594
|
+
.info-card {
|
|
4595
|
+
background-color: var(--surface);
|
|
4596
|
+
border: 1px solid var(--border);
|
|
4597
|
+
border-radius: 8px;
|
|
4598
|
+
padding: 20px;
|
|
4599
|
+
}
|
|
4514
4600
|
|
|
4515
|
-
|
|
4516
|
-
|
|
4517
|
-
|
|
4518
|
-
|
|
4519
|
-
|
|
4520
|
-
|
|
4601
|
+
.card-header {
|
|
4602
|
+
font-size: 12px;
|
|
4603
|
+
font-weight: 600;
|
|
4604
|
+
color: var(--text-secondary);
|
|
4605
|
+
text-transform: uppercase;
|
|
4606
|
+
letter-spacing: 0.5px;
|
|
4607
|
+
margin-bottom: 16px;
|
|
4608
|
+
}
|
|
4521
4609
|
|
|
4522
|
-
|
|
4523
|
-
|
|
4524
|
-
|
|
4525
|
-
|
|
4526
|
-
|
|
4527
|
-
|
|
4528
|
-
|
|
4529
|
-
font-weight: 700;
|
|
4530
|
-
border-radius: 3px;
|
|
4531
|
-
text-transform: uppercase;
|
|
4532
|
-
flex: 0 0 auto;
|
|
4533
|
-
}
|
|
4610
|
+
.card-row {
|
|
4611
|
+
display: flex;
|
|
4612
|
+
justify-content: space-between;
|
|
4613
|
+
align-items: center;
|
|
4614
|
+
margin-bottom: 12px;
|
|
4615
|
+
font-size: 13px;
|
|
4616
|
+
}
|
|
4534
4617
|
|
|
4535
|
-
|
|
4536
|
-
|
|
4537
|
-
|
|
4538
|
-
}
|
|
4618
|
+
.card-row:last-child {
|
|
4619
|
+
margin-bottom: 0;
|
|
4620
|
+
}
|
|
4539
4621
|
|
|
4540
|
-
|
|
4541
|
-
|
|
4542
|
-
|
|
4543
|
-
}
|
|
4622
|
+
.card-label {
|
|
4623
|
+
color: var(--text-secondary);
|
|
4624
|
+
}
|
|
4544
4625
|
|
|
4545
|
-
|
|
4546
|
-
|
|
4547
|
-
|
|
4548
|
-
|
|
4626
|
+
.card-value {
|
|
4627
|
+
color: var(--text-primary);
|
|
4628
|
+
font-family: 'JetBrains Mono', monospace;
|
|
4629
|
+
font-weight: 500;
|
|
4630
|
+
}
|
|
4549
4631
|
|
|
4550
|
-
|
|
4551
|
-
|
|
4552
|
-
|
|
4553
|
-
|
|
4632
|
+
.identity-badge {
|
|
4633
|
+
display: inline-flex;
|
|
4634
|
+
align-items: center;
|
|
4635
|
+
gap: 4px;
|
|
4636
|
+
padding: 2px 6px;
|
|
4637
|
+
background-color: rgba(88, 166, 255, 0.15);
|
|
4638
|
+
color: var(--blue);
|
|
4639
|
+
border-radius: 3px;
|
|
4640
|
+
font-size: 10px;
|
|
4641
|
+
font-weight: 600;
|
|
4642
|
+
text-transform: uppercase;
|
|
4643
|
+
}
|
|
4554
4644
|
|
|
4555
|
-
|
|
4556
|
-
|
|
4557
|
-
|
|
4645
|
+
.trust-tier-badge {
|
|
4646
|
+
display: inline-flex;
|
|
4647
|
+
align-items: center;
|
|
4648
|
+
gap: 4px;
|
|
4649
|
+
padding: 2px 6px;
|
|
4650
|
+
background-color: rgba(63, 185, 80, 0.15);
|
|
4651
|
+
color: var(--green);
|
|
4652
|
+
border-radius: 3px;
|
|
4653
|
+
font-size: 10px;
|
|
4654
|
+
font-weight: 600;
|
|
4655
|
+
}
|
|
4558
4656
|
|
|
4559
|
-
|
|
4560
|
-
|
|
4561
|
-
|
|
4657
|
+
.truncated {
|
|
4658
|
+
max-width: 200px;
|
|
4659
|
+
overflow: hidden;
|
|
4660
|
+
text-overflow: ellipsis;
|
|
4661
|
+
white-space: nowrap;
|
|
4662
|
+
}
|
|
4562
4663
|
|
|
4563
|
-
|
|
4564
|
-
|
|
4565
|
-
|
|
4566
|
-
|
|
4567
|
-
|
|
4664
|
+
/* Row 3: SHR & Activity */
|
|
4665
|
+
.main-panels {
|
|
4666
|
+
display: grid;
|
|
4667
|
+
grid-template-columns: 1fr 1fr;
|
|
4668
|
+
gap: 16px;
|
|
4669
|
+
min-height: 400px;
|
|
4670
|
+
}
|
|
4568
4671
|
|
|
4569
|
-
|
|
4570
|
-
|
|
4571
|
-
|
|
4572
|
-
|
|
4573
|
-
|
|
4574
|
-
|
|
4575
|
-
|
|
4576
|
-
|
|
4672
|
+
.panel {
|
|
4673
|
+
background-color: var(--surface);
|
|
4674
|
+
border: 1px solid var(--border);
|
|
4675
|
+
border-radius: 8px;
|
|
4676
|
+
display: flex;
|
|
4677
|
+
flex-direction: column;
|
|
4678
|
+
overflow: hidden;
|
|
4679
|
+
}
|
|
4577
4680
|
|
|
4578
|
-
|
|
4579
|
-
|
|
4580
|
-
|
|
4581
|
-
|
|
4582
|
-
|
|
4583
|
-
|
|
4584
|
-
|
|
4585
|
-
}
|
|
4681
|
+
.panel-header {
|
|
4682
|
+
padding: 16px 20px;
|
|
4683
|
+
border-bottom: 1px solid var(--border);
|
|
4684
|
+
display: flex;
|
|
4685
|
+
justify-content: space-between;
|
|
4686
|
+
align-items: center;
|
|
4687
|
+
}
|
|
4586
4688
|
|
|
4587
|
-
|
|
4588
|
-
|
|
4589
|
-
|
|
4590
|
-
|
|
4689
|
+
.panel-title {
|
|
4690
|
+
font-size: 14px;
|
|
4691
|
+
font-weight: 600;
|
|
4692
|
+
color: var(--text-primary);
|
|
4693
|
+
}
|
|
4591
4694
|
|
|
4592
|
-
|
|
4593
|
-
|
|
4594
|
-
|
|
4695
|
+
.panel-action {
|
|
4696
|
+
background: none;
|
|
4697
|
+
border: none;
|
|
4698
|
+
color: var(--blue);
|
|
4699
|
+
cursor: pointer;
|
|
4700
|
+
font-size: 12px;
|
|
4701
|
+
padding: 0;
|
|
4702
|
+
font-weight: 500;
|
|
4703
|
+
transition: color 0.2s;
|
|
4704
|
+
}
|
|
4595
4705
|
|
|
4596
|
-
|
|
4706
|
+
.panel-action:hover {
|
|
4707
|
+
color: #79c0ff;
|
|
4708
|
+
}
|
|
4597
4709
|
|
|
4598
|
-
|
|
4599
|
-
|
|
4600
|
-
|
|
4601
|
-
|
|
4602
|
-
|
|
4603
|
-
overflow: hidden;
|
|
4604
|
-
}
|
|
4710
|
+
.panel-content {
|
|
4711
|
+
flex: 1;
|
|
4712
|
+
overflow-y: auto;
|
|
4713
|
+
padding: 20px;
|
|
4714
|
+
}
|
|
4605
4715
|
|
|
4606
|
-
|
|
4607
|
-
|
|
4608
|
-
|
|
4609
|
-
|
|
4610
|
-
|
|
4611
|
-
|
|
4612
|
-
|
|
4613
|
-
color: var(--text-secondary);
|
|
4614
|
-
display: flex;
|
|
4615
|
-
align-items: center;
|
|
4616
|
-
gap: 8px;
|
|
4617
|
-
}
|
|
4716
|
+
/* SHR Viewer */
|
|
4717
|
+
.shr-json {
|
|
4718
|
+
font-family: 'JetBrains Mono', monospace;
|
|
4719
|
+
font-size: 12px;
|
|
4720
|
+
line-height: 1.6;
|
|
4721
|
+
color: var(--text-secondary);
|
|
4722
|
+
}
|
|
4618
4723
|
|
|
4619
|
-
|
|
4620
|
-
|
|
4621
|
-
|
|
4622
|
-
padding: 16px 16px;
|
|
4623
|
-
display: grid;
|
|
4624
|
-
grid-template-columns: 1fr 1fr;
|
|
4625
|
-
gap: 12px;
|
|
4626
|
-
}
|
|
4724
|
+
.shr-section {
|
|
4725
|
+
margin-bottom: 12px;
|
|
4726
|
+
}
|
|
4627
4727
|
|
|
4628
|
-
|
|
4629
|
-
|
|
4630
|
-
|
|
4631
|
-
|
|
4632
|
-
|
|
4633
|
-
|
|
4634
|
-
|
|
4635
|
-
|
|
4636
|
-
|
|
4728
|
+
.shr-section-header {
|
|
4729
|
+
display: flex;
|
|
4730
|
+
align-items: center;
|
|
4731
|
+
gap: 8px;
|
|
4732
|
+
cursor: pointer;
|
|
4733
|
+
font-weight: 600;
|
|
4734
|
+
color: var(--text-primary);
|
|
4735
|
+
padding: 8px;
|
|
4736
|
+
background-color: var(--bg);
|
|
4737
|
+
border-radius: 4px;
|
|
4738
|
+
user-select: none;
|
|
4739
|
+
}
|
|
4637
4740
|
|
|
4638
|
-
|
|
4639
|
-
|
|
4640
|
-
|
|
4741
|
+
.shr-section-header:hover {
|
|
4742
|
+
background-color: var(--muted);
|
|
4743
|
+
}
|
|
4641
4744
|
|
|
4642
|
-
|
|
4643
|
-
|
|
4644
|
-
|
|
4645
|
-
|
|
4646
|
-
|
|
4647
|
-
|
|
4648
|
-
|
|
4745
|
+
.shr-toggle {
|
|
4746
|
+
width: 16px;
|
|
4747
|
+
height: 16px;
|
|
4748
|
+
display: flex;
|
|
4749
|
+
align-items: center;
|
|
4750
|
+
justify-content: center;
|
|
4751
|
+
font-size: 10px;
|
|
4752
|
+
transition: transform 0.2s;
|
|
4753
|
+
}
|
|
4649
4754
|
|
|
4650
|
-
|
|
4651
|
-
|
|
4652
|
-
|
|
4653
|
-
gap: 6px;
|
|
4654
|
-
font-size: 12px;
|
|
4655
|
-
font-weight: 600;
|
|
4656
|
-
}
|
|
4755
|
+
.shr-section.collapsed .shr-toggle {
|
|
4756
|
+
transform: rotate(-90deg);
|
|
4757
|
+
}
|
|
4657
4758
|
|
|
4658
|
-
|
|
4659
|
-
|
|
4660
|
-
|
|
4759
|
+
.shr-section-content {
|
|
4760
|
+
padding: 8px 16px;
|
|
4761
|
+
background-color: rgba(0, 0, 0, 0.2);
|
|
4762
|
+
border-radius: 4px;
|
|
4763
|
+
margin-top: 4px;
|
|
4764
|
+
}
|
|
4661
4765
|
|
|
4662
|
-
|
|
4663
|
-
|
|
4664
|
-
|
|
4766
|
+
.shr-section.collapsed .shr-section-content {
|
|
4767
|
+
display: none;
|
|
4768
|
+
}
|
|
4665
4769
|
|
|
4666
|
-
|
|
4667
|
-
|
|
4668
|
-
|
|
4669
|
-
|
|
4670
|
-
margin-top: 4px;
|
|
4671
|
-
}
|
|
4770
|
+
.shr-item {
|
|
4771
|
+
display: flex;
|
|
4772
|
+
margin-bottom: 4px;
|
|
4773
|
+
}
|
|
4672
4774
|
|
|
4673
|
-
|
|
4775
|
+
.shr-key {
|
|
4776
|
+
color: var(--blue);
|
|
4777
|
+
margin-right: 8px;
|
|
4778
|
+
min-width: 120px;
|
|
4779
|
+
}
|
|
4674
4780
|
|
|
4675
|
-
|
|
4676
|
-
|
|
4677
|
-
|
|
4678
|
-
|
|
4679
|
-
bottom: 0;
|
|
4680
|
-
width: 0;
|
|
4681
|
-
background: var(--surface);
|
|
4682
|
-
border-left: 1px solid var(--border);
|
|
4683
|
-
z-index: 999;
|
|
4684
|
-
overflow-y: auto;
|
|
4685
|
-
transition: width 0.3s ease-out;
|
|
4686
|
-
display: flex;
|
|
4687
|
-
flex-direction: column;
|
|
4688
|
-
}
|
|
4781
|
+
.shr-value {
|
|
4782
|
+
color: var(--green);
|
|
4783
|
+
word-break: break-all;
|
|
4784
|
+
}
|
|
4689
4785
|
|
|
4690
|
-
|
|
4691
|
-
|
|
4692
|
-
|
|
4786
|
+
/* Activity Feed */
|
|
4787
|
+
.activity-feed {
|
|
4788
|
+
display: flex;
|
|
4789
|
+
flex-direction: column;
|
|
4790
|
+
gap: 12px;
|
|
4791
|
+
}
|
|
4693
4792
|
|
|
4694
|
-
|
|
4695
|
-
|
|
4696
|
-
|
|
4697
|
-
|
|
4698
|
-
|
|
4793
|
+
.activity-item {
|
|
4794
|
+
padding: 12px;
|
|
4795
|
+
background-color: var(--bg);
|
|
4796
|
+
border-left: 2px solid var(--border);
|
|
4797
|
+
border-radius: 4px;
|
|
4798
|
+
font-size: 12px;
|
|
4699
4799
|
}
|
|
4700
|
-
}
|
|
4701
4800
|
|
|
4702
|
-
|
|
4703
|
-
|
|
4704
|
-
|
|
4705
|
-
display: flex;
|
|
4706
|
-
align-items: center;
|
|
4707
|
-
justify-content: space-between;
|
|
4708
|
-
flex: 0 0 auto;
|
|
4709
|
-
}
|
|
4801
|
+
.activity-item.tool-call {
|
|
4802
|
+
border-left-color: var(--blue);
|
|
4803
|
+
}
|
|
4710
4804
|
|
|
4711
|
-
|
|
4712
|
-
|
|
4713
|
-
|
|
4714
|
-
text-transform: uppercase;
|
|
4715
|
-
letter-spacing: 0.5px;
|
|
4716
|
-
color: var(--text-primary);
|
|
4717
|
-
}
|
|
4805
|
+
.activity-item.context-gate {
|
|
4806
|
+
border-left-color: var(--amber);
|
|
4807
|
+
}
|
|
4718
4808
|
|
|
4719
|
-
|
|
4720
|
-
|
|
4721
|
-
|
|
4722
|
-
color: var(--text-secondary);
|
|
4723
|
-
cursor: pointer;
|
|
4724
|
-
font-size: 18px;
|
|
4725
|
-
padding: 0;
|
|
4726
|
-
display: flex;
|
|
4727
|
-
align-items: center;
|
|
4728
|
-
justify-content: center;
|
|
4729
|
-
}
|
|
4809
|
+
.activity-item.injection {
|
|
4810
|
+
border-left-color: var(--red);
|
|
4811
|
+
}
|
|
4730
4812
|
|
|
4731
|
-
|
|
4732
|
-
|
|
4733
|
-
|
|
4813
|
+
.activity-item.protection {
|
|
4814
|
+
border-left-color: var(--green);
|
|
4815
|
+
}
|
|
4734
4816
|
|
|
4735
|
-
|
|
4736
|
-
|
|
4737
|
-
|
|
4738
|
-
|
|
4817
|
+
.activity-type {
|
|
4818
|
+
font-weight: 600;
|
|
4819
|
+
color: var(--text-primary);
|
|
4820
|
+
margin-bottom: 4px;
|
|
4821
|
+
text-transform: uppercase;
|
|
4822
|
+
font-size: 11px;
|
|
4823
|
+
letter-spacing: 0.5px;
|
|
4824
|
+
}
|
|
4739
4825
|
|
|
4740
|
-
|
|
4741
|
-
|
|
4742
|
-
|
|
4743
|
-
|
|
4744
|
-
|
|
4745
|
-
|
|
4746
|
-
}
|
|
4826
|
+
.activity-content {
|
|
4827
|
+
color: var(--text-secondary);
|
|
4828
|
+
font-family: 'JetBrains Mono', monospace;
|
|
4829
|
+
margin-bottom: 4px;
|
|
4830
|
+
word-break: break-all;
|
|
4831
|
+
}
|
|
4747
4832
|
|
|
4748
|
-
|
|
4749
|
-
|
|
4750
|
-
|
|
4751
|
-
|
|
4752
|
-
}
|
|
4833
|
+
.activity-time {
|
|
4834
|
+
font-size: 11px;
|
|
4835
|
+
color: var(--text-secondary);
|
|
4836
|
+
}
|
|
4753
4837
|
|
|
4754
|
-
|
|
4755
|
-
|
|
4756
|
-
|
|
4757
|
-
|
|
4758
|
-
|
|
4759
|
-
|
|
4760
|
-
|
|
4838
|
+
.empty-state {
|
|
4839
|
+
display: flex;
|
|
4840
|
+
align-items: center;
|
|
4841
|
+
justify-content: center;
|
|
4842
|
+
height: 100%;
|
|
4843
|
+
color: var(--text-secondary);
|
|
4844
|
+
font-size: 13px;
|
|
4845
|
+
}
|
|
4761
4846
|
|
|
4762
|
-
|
|
4763
|
-
|
|
4764
|
-
|
|
4765
|
-
|
|
4766
|
-
|
|
4767
|
-
|
|
4768
|
-
|
|
4769
|
-
font-weight: 700;
|
|
4770
|
-
border-radius: 3px;
|
|
4771
|
-
text-transform: uppercase;
|
|
4772
|
-
color: white;
|
|
4773
|
-
}
|
|
4847
|
+
/* Row 4: Handshake History */
|
|
4848
|
+
.handshake-table {
|
|
4849
|
+
background-color: var(--surface);
|
|
4850
|
+
border: 1px solid var(--border);
|
|
4851
|
+
border-radius: 8px;
|
|
4852
|
+
overflow: hidden;
|
|
4853
|
+
}
|
|
4774
4854
|
|
|
4775
|
-
|
|
4776
|
-
|
|
4777
|
-
|
|
4855
|
+
.table-header {
|
|
4856
|
+
display: grid;
|
|
4857
|
+
grid-template-columns: 2fr 1fr 1fr 1fr 1.5fr 1.5fr;
|
|
4858
|
+
gap: 16px;
|
|
4859
|
+
padding: 16px 20px;
|
|
4860
|
+
border-bottom: 1px solid var(--border);
|
|
4861
|
+
background-color: var(--bg);
|
|
4862
|
+
font-size: 12px;
|
|
4863
|
+
font-weight: 600;
|
|
4864
|
+
color: var(--text-secondary);
|
|
4865
|
+
text-transform: uppercase;
|
|
4866
|
+
letter-spacing: 0.5px;
|
|
4867
|
+
}
|
|
4778
4868
|
|
|
4779
|
-
|
|
4780
|
-
|
|
4781
|
-
|
|
4869
|
+
.table-rows {
|
|
4870
|
+
max-height: 300px;
|
|
4871
|
+
overflow-y: auto;
|
|
4872
|
+
}
|
|
4782
4873
|
|
|
4783
|
-
|
|
4784
|
-
|
|
4785
|
-
|
|
4786
|
-
|
|
4874
|
+
.table-row {
|
|
4875
|
+
display: grid;
|
|
4876
|
+
grid-template-columns: 2fr 1fr 1fr 1fr 1.5fr 1.5fr;
|
|
4877
|
+
gap: 16px;
|
|
4878
|
+
padding: 14px 20px;
|
|
4879
|
+
border-bottom: 1px solid var(--border);
|
|
4880
|
+
align-items: center;
|
|
4881
|
+
font-size: 12px;
|
|
4882
|
+
cursor: pointer;
|
|
4883
|
+
transition: background-color 0.2s;
|
|
4884
|
+
}
|
|
4787
4885
|
|
|
4788
|
-
|
|
4789
|
-
|
|
4790
|
-
|
|
4791
|
-
gap: 6px;
|
|
4792
|
-
font-size: 11px;
|
|
4793
|
-
font-family: var(--mono);
|
|
4794
|
-
color: var(--text-secondary);
|
|
4795
|
-
}
|
|
4886
|
+
.table-row:hover {
|
|
4887
|
+
background-color: var(--bg);
|
|
4888
|
+
}
|
|
4796
4889
|
|
|
4797
|
-
|
|
4798
|
-
|
|
4799
|
-
|
|
4800
|
-
background: rgba(48, 54, 61, 0.8);
|
|
4801
|
-
border-radius: 2px;
|
|
4802
|
-
overflow: hidden;
|
|
4803
|
-
}
|
|
4890
|
+
.table-row:last-child {
|
|
4891
|
+
border-bottom: none;
|
|
4892
|
+
}
|
|
4804
4893
|
|
|
4805
|
-
|
|
4806
|
-
|
|
4807
|
-
|
|
4808
|
-
|
|
4809
|
-
}
|
|
4894
|
+
.table-cell {
|
|
4895
|
+
color: var(--text-secondary);
|
|
4896
|
+
font-family: 'JetBrains Mono', monospace;
|
|
4897
|
+
}
|
|
4810
4898
|
|
|
4811
|
-
|
|
4812
|
-
|
|
4813
|
-
|
|
4899
|
+
.table-cell.strong {
|
|
4900
|
+
color: var(--text-primary);
|
|
4901
|
+
font-weight: 500;
|
|
4902
|
+
}
|
|
4814
4903
|
|
|
4815
|
-
|
|
4816
|
-
|
|
4817
|
-
|
|
4818
|
-
|
|
4904
|
+
.table-empty {
|
|
4905
|
+
padding: 40px 20px;
|
|
4906
|
+
text-align: center;
|
|
4907
|
+
color: var(--text-secondary);
|
|
4908
|
+
font-size: 13px;
|
|
4909
|
+
}
|
|
4819
4910
|
|
|
4820
|
-
|
|
4821
|
-
|
|
4822
|
-
|
|
4823
|
-
|
|
4824
|
-
|
|
4825
|
-
|
|
4826
|
-
|
|
4827
|
-
|
|
4828
|
-
|
|
4829
|
-
|
|
4830
|
-
|
|
4911
|
+
/* Pending Overlay */
|
|
4912
|
+
.pending-overlay {
|
|
4913
|
+
position: fixed;
|
|
4914
|
+
top: 0;
|
|
4915
|
+
right: -400px;
|
|
4916
|
+
width: 400px;
|
|
4917
|
+
height: 100vh;
|
|
4918
|
+
background-color: var(--surface);
|
|
4919
|
+
border-left: 1px solid var(--border);
|
|
4920
|
+
box-shadow: -2px 0 8px rgba(0, 0, 0, 0.3);
|
|
4921
|
+
z-index: 200;
|
|
4922
|
+
transition: right 0.3s ease;
|
|
4923
|
+
display: flex;
|
|
4924
|
+
flex-direction: column;
|
|
4925
|
+
overflow-y: auto;
|
|
4926
|
+
}
|
|
4831
4927
|
|
|
4832
|
-
|
|
4833
|
-
|
|
4834
|
-
|
|
4835
|
-
}
|
|
4928
|
+
.pending-overlay.show {
|
|
4929
|
+
right: 0;
|
|
4930
|
+
}
|
|
4836
4931
|
|
|
4837
|
-
|
|
4838
|
-
|
|
4839
|
-
|
|
4932
|
+
.pending-header {
|
|
4933
|
+
padding: 16px 20px;
|
|
4934
|
+
border-bottom: 1px solid var(--border);
|
|
4935
|
+
font-weight: 600;
|
|
4936
|
+
color: var(--text-primary);
|
|
4937
|
+
}
|
|
4840
4938
|
|
|
4841
|
-
|
|
4842
|
-
|
|
4843
|
-
|
|
4844
|
-
|
|
4939
|
+
.pending-items {
|
|
4940
|
+
flex: 1;
|
|
4941
|
+
overflow-y: auto;
|
|
4942
|
+
padding: 16px;
|
|
4943
|
+
}
|
|
4845
4944
|
|
|
4846
|
-
|
|
4847
|
-
|
|
4848
|
-
|
|
4945
|
+
.pending-item {
|
|
4946
|
+
background-color: var(--bg);
|
|
4947
|
+
border: 1px solid var(--border);
|
|
4948
|
+
border-radius: 6px;
|
|
4949
|
+
padding: 16px;
|
|
4950
|
+
margin-bottom: 12px;
|
|
4951
|
+
}
|
|
4849
4952
|
|
|
4850
|
-
|
|
4953
|
+
.pending-title {
|
|
4954
|
+
font-weight: 600;
|
|
4955
|
+
color: var(--text-primary);
|
|
4956
|
+
margin-bottom: 8px;
|
|
4957
|
+
word-break: break-word;
|
|
4958
|
+
}
|
|
4851
4959
|
|
|
4852
|
-
|
|
4853
|
-
|
|
4854
|
-
|
|
4855
|
-
|
|
4856
|
-
|
|
4857
|
-
|
|
4858
|
-
border-top: 1px solid var(--border);
|
|
4859
|
-
max-height: 240px;
|
|
4860
|
-
z-index: 500;
|
|
4861
|
-
display: flex;
|
|
4862
|
-
flex-direction: column;
|
|
4863
|
-
transition: max-height 0.3s ease-out;
|
|
4864
|
-
}
|
|
4960
|
+
.pending-countdown {
|
|
4961
|
+
font-size: 12px;
|
|
4962
|
+
color: var(--amber);
|
|
4963
|
+
margin-bottom: 12px;
|
|
4964
|
+
font-weight: 500;
|
|
4965
|
+
}
|
|
4865
4966
|
|
|
4866
|
-
|
|
4867
|
-
|
|
4868
|
-
|
|
4967
|
+
.pending-actions {
|
|
4968
|
+
display: flex;
|
|
4969
|
+
gap: 8px;
|
|
4970
|
+
}
|
|
4869
4971
|
|
|
4870
|
-
|
|
4871
|
-
|
|
4872
|
-
|
|
4873
|
-
|
|
4874
|
-
|
|
4875
|
-
|
|
4876
|
-
|
|
4877
|
-
|
|
4878
|
-
|
|
4879
|
-
|
|
4880
|
-
color: var(--text-secondary);
|
|
4881
|
-
flex: 0 0 auto;
|
|
4882
|
-
}
|
|
4972
|
+
.pending-btn {
|
|
4973
|
+
flex: 1;
|
|
4974
|
+
padding: 8px 12px;
|
|
4975
|
+
border: none;
|
|
4976
|
+
border-radius: 4px;
|
|
4977
|
+
font-size: 12px;
|
|
4978
|
+
font-weight: 600;
|
|
4979
|
+
cursor: pointer;
|
|
4980
|
+
transition: background-color 0.2s;
|
|
4981
|
+
}
|
|
4883
4982
|
|
|
4884
|
-
|
|
4885
|
-
|
|
4886
|
-
|
|
4983
|
+
.pending-approve {
|
|
4984
|
+
background-color: var(--green);
|
|
4985
|
+
color: var(--bg);
|
|
4986
|
+
}
|
|
4887
4987
|
|
|
4888
|
-
|
|
4889
|
-
|
|
4890
|
-
|
|
4988
|
+
.pending-approve:hover {
|
|
4989
|
+
background-color: #3fa040;
|
|
4990
|
+
}
|
|
4891
4991
|
|
|
4892
|
-
|
|
4893
|
-
|
|
4894
|
-
|
|
4895
|
-
|
|
4896
|
-
display: flex;
|
|
4897
|
-
flex-direction: column;
|
|
4898
|
-
gap: 10px;
|
|
4899
|
-
}
|
|
4992
|
+
.pending-deny {
|
|
4993
|
+
background-color: var(--red);
|
|
4994
|
+
color: var(--bg);
|
|
4995
|
+
}
|
|
4900
4996
|
|
|
4901
|
-
|
|
4902
|
-
|
|
4903
|
-
|
|
4904
|
-
border-left: 2px solid var(--red);
|
|
4905
|
-
border-radius: 4px;
|
|
4906
|
-
font-size: 11px;
|
|
4907
|
-
color: var(--text-secondary);
|
|
4908
|
-
}
|
|
4997
|
+
.pending-deny:hover {
|
|
4998
|
+
background-color: #e03c3c;
|
|
4999
|
+
}
|
|
4909
5000
|
|
|
4910
|
-
|
|
4911
|
-
|
|
4912
|
-
|
|
4913
|
-
|
|
4914
|
-
|
|
5001
|
+
/* Threat Panel */
|
|
5002
|
+
.threat-panel {
|
|
5003
|
+
background-color: var(--surface);
|
|
5004
|
+
border: 1px solid var(--border);
|
|
5005
|
+
border-radius: 8px;
|
|
5006
|
+
margin-top: 20px;
|
|
5007
|
+
overflow: hidden;
|
|
5008
|
+
}
|
|
4915
5009
|
|
|
4916
|
-
|
|
4917
|
-
|
|
4918
|
-
|
|
4919
|
-
|
|
4920
|
-
|
|
4921
|
-
|
|
5010
|
+
.threat-header {
|
|
5011
|
+
padding: 16px 20px;
|
|
5012
|
+
border-bottom: 1px solid var(--border);
|
|
5013
|
+
display: flex;
|
|
5014
|
+
justify-content: space-between;
|
|
5015
|
+
align-items: center;
|
|
5016
|
+
cursor: pointer;
|
|
5017
|
+
user-select: none;
|
|
5018
|
+
}
|
|
4922
5019
|
|
|
4923
|
-
|
|
5020
|
+
.threat-title {
|
|
5021
|
+
font-weight: 600;
|
|
5022
|
+
color: var(--text-primary);
|
|
5023
|
+
}
|
|
4924
5024
|
|
|
4925
|
-
|
|
4926
|
-
|
|
4927
|
-
|
|
5025
|
+
.threat-toggle {
|
|
5026
|
+
font-size: 10px;
|
|
5027
|
+
color: var(--text-secondary);
|
|
5028
|
+
transition: transform 0.2s;
|
|
5029
|
+
}
|
|
4928
5030
|
|
|
4929
|
-
|
|
4930
|
-
|
|
4931
|
-
|
|
5031
|
+
.threat-panel.collapsed .threat-toggle {
|
|
5032
|
+
transform: rotate(-90deg);
|
|
5033
|
+
}
|
|
4932
5034
|
|
|
4933
|
-
|
|
4934
|
-
|
|
4935
|
-
|
|
4936
|
-
|
|
5035
|
+
.threat-content {
|
|
5036
|
+
padding: 16px 20px;
|
|
5037
|
+
max-height: 300px;
|
|
5038
|
+
overflow-y: auto;
|
|
5039
|
+
}
|
|
4937
5040
|
|
|
4938
|
-
|
|
4939
|
-
|
|
4940
|
-
|
|
5041
|
+
.threat-panel.collapsed .threat-content {
|
|
5042
|
+
display: none;
|
|
5043
|
+
}
|
|
4941
5044
|
|
|
4942
|
-
|
|
5045
|
+
.threat-alert {
|
|
5046
|
+
background-color: rgba(248, 81, 73, 0.1);
|
|
5047
|
+
border: 1px solid var(--red);
|
|
5048
|
+
border-radius: 4px;
|
|
5049
|
+
padding: 12px;
|
|
5050
|
+
margin-bottom: 8px;
|
|
5051
|
+
font-size: 12px;
|
|
5052
|
+
}
|
|
4943
5053
|
|
|
4944
|
-
|
|
4945
|
-
|
|
4946
|
-
display: none;
|
|
5054
|
+
.threat-alert:last-child {
|
|
5055
|
+
margin-bottom: 0;
|
|
4947
5056
|
}
|
|
4948
5057
|
|
|
4949
|
-
.
|
|
4950
|
-
|
|
5058
|
+
.threat-type {
|
|
5059
|
+
font-weight: 600;
|
|
5060
|
+
color: var(--red);
|
|
5061
|
+
margin-bottom: 4px;
|
|
5062
|
+
text-transform: uppercase;
|
|
5063
|
+
font-size: 10px;
|
|
5064
|
+
letter-spacing: 0.5px;
|
|
4951
5065
|
}
|
|
4952
|
-
}
|
|
4953
5066
|
|
|
4954
|
-
|
|
4955
|
-
|
|
4956
|
-
padding: 0 12px;
|
|
4957
|
-
gap: 12px;
|
|
4958
|
-
height: 48px;
|
|
5067
|
+
.threat-message {
|
|
5068
|
+
color: var(--text-secondary);
|
|
4959
5069
|
}
|
|
4960
5070
|
|
|
4961
|
-
|
|
4962
|
-
|
|
5071
|
+
/* Scrollbar */
|
|
5072
|
+
::-webkit-scrollbar {
|
|
5073
|
+
width: 8px;
|
|
4963
5074
|
}
|
|
4964
5075
|
|
|
4965
|
-
|
|
4966
|
-
|
|
5076
|
+
::-webkit-scrollbar-track {
|
|
5077
|
+
background-color: transparent;
|
|
4967
5078
|
}
|
|
4968
5079
|
|
|
4969
|
-
|
|
4970
|
-
|
|
5080
|
+
::-webkit-scrollbar-thumb {
|
|
5081
|
+
background-color: var(--border);
|
|
5082
|
+
border-radius: 4px;
|
|
4971
5083
|
}
|
|
4972
5084
|
|
|
4973
|
-
|
|
4974
|
-
|
|
5085
|
+
::-webkit-scrollbar-thumb:hover {
|
|
5086
|
+
background-color: var(--text-secondary);
|
|
4975
5087
|
}
|
|
4976
5088
|
|
|
4977
|
-
|
|
4978
|
-
|
|
5089
|
+
/* Responsive */
|
|
5090
|
+
@media (max-width: 1400px) {
|
|
5091
|
+
.sovereignty-layers {
|
|
5092
|
+
grid-template-columns: repeat(2, 1fr);
|
|
5093
|
+
}
|
|
5094
|
+
|
|
5095
|
+
.main-panels {
|
|
5096
|
+
grid-template-columns: 1fr;
|
|
5097
|
+
}
|
|
5098
|
+
|
|
5099
|
+
.pending-overlay {
|
|
5100
|
+
width: 100%;
|
|
5101
|
+
right: -100%;
|
|
5102
|
+
}
|
|
4979
5103
|
}
|
|
4980
5104
|
|
|
4981
|
-
|
|
4982
|
-
|
|
5105
|
+
@media (max-width: 768px) {
|
|
5106
|
+
.status-bar {
|
|
5107
|
+
flex-wrap: wrap;
|
|
5108
|
+
height: auto;
|
|
5109
|
+
padding: 12px;
|
|
5110
|
+
gap: 12px;
|
|
5111
|
+
}
|
|
5112
|
+
|
|
5113
|
+
.status-bar-center {
|
|
5114
|
+
order: 3;
|
|
5115
|
+
flex-basis: 100%;
|
|
5116
|
+
}
|
|
5117
|
+
|
|
5118
|
+
.main-content {
|
|
5119
|
+
margin-top: auto;
|
|
5120
|
+
}
|
|
5121
|
+
|
|
5122
|
+
.info-cards {
|
|
5123
|
+
grid-template-columns: 1fr;
|
|
5124
|
+
}
|
|
5125
|
+
|
|
5126
|
+
.table-header,
|
|
5127
|
+
.table-row {
|
|
5128
|
+
grid-template-columns: 1fr;
|
|
5129
|
+
}
|
|
4983
5130
|
}
|
|
4984
|
-
|
|
4985
|
-
</style>
|
|
5131
|
+
</style>
|
|
4986
5132
|
</head>
|
|
4987
5133
|
<body>
|
|
4988
|
-
|
|
4989
|
-
|
|
4990
|
-
<div class="status-bar">
|
|
4991
|
-
|
|
4992
|
-
|
|
4993
|
-
|
|
4994
|
-
|
|
4995
|
-
|
|
4996
|
-
<div class="sovereignty-badge">
|
|
4997
|
-
<div class="sovereignty-score" id="sovereigntyScore">85</div>
|
|
4998
|
-
<span>Sovereignty Health</span>
|
|
5134
|
+
<!-- Status Bar -->
|
|
5135
|
+
<div class="status-bar">
|
|
5136
|
+
<div class="status-bar-left">
|
|
5137
|
+
<div class="logo-icon">\u25C6</div>
|
|
5138
|
+
<div class="logo-info">
|
|
5139
|
+
<div class="logo-title">SANCTUARY</div>
|
|
5140
|
+
<div class="logo-version">v${options.serverVersion}</div>
|
|
5141
|
+
</div>
|
|
4999
5142
|
</div>
|
|
5000
|
-
|
|
5001
|
-
|
|
5002
|
-
|
|
5003
|
-
|
|
5143
|
+
|
|
5144
|
+
<div class="status-bar-center">
|
|
5145
|
+
<div id="sovereignty-badge" class="sovereignty-badge">
|
|
5146
|
+
<span>Sovereignty Health:</span>
|
|
5147
|
+
<span class="sovereignty-score" id="sovereignty-score">\u2014</span>
|
|
5148
|
+
<span>/ 100</span>
|
|
5149
|
+
</div>
|
|
5004
5150
|
</div>
|
|
5005
|
-
|
|
5006
|
-
|
|
5151
|
+
|
|
5152
|
+
<div class="status-bar-right">
|
|
5153
|
+
<div class="status-item">
|
|
5154
|
+
<strong id="protections-count">\u2014</strong>
|
|
5155
|
+
<span>Protections</span>
|
|
5156
|
+
</div>
|
|
5157
|
+
<div class="status-item">
|
|
5158
|
+
<strong id="uptime-value">\u2014</strong>
|
|
5159
|
+
<span>Uptime</span>
|
|
5160
|
+
</div>
|
|
5161
|
+
<div class="status-dot" id="connection-status"></div>
|
|
5162
|
+
<div id="pending-item-badge" class="pending-badge" style="display: none;">
|
|
5163
|
+
<span>\u23F3</span>
|
|
5164
|
+
<span id="pending-count">0</span>
|
|
5165
|
+
</div>
|
|
5007
5166
|
</div>
|
|
5008
|
-
<div class="status-dot" id="statusDot"></div>
|
|
5009
|
-
<div class="pending-badge hidden" id="pendingBadge">0</div>
|
|
5010
5167
|
</div>
|
|
5011
|
-
|
|
5012
|
-
|
|
5013
|
-
|
|
5014
|
-
<div class="
|
|
5015
|
-
|
|
5016
|
-
|
|
5017
|
-
|
|
5018
|
-
|
|
5019
|
-
|
|
5020
|
-
|
|
5021
|
-
|
|
5022
|
-
|
|
5023
|
-
<div class="
|
|
5024
|
-
|
|
5168
|
+
|
|
5169
|
+
<!-- Main Content -->
|
|
5170
|
+
<div class="main-content">
|
|
5171
|
+
<div class="grid">
|
|
5172
|
+
<!-- Row 1: Sovereignty Layers -->
|
|
5173
|
+
<div class="sovereignty-layers" id="sovereignty-layers">
|
|
5174
|
+
<div class="layer-card" data-layer="l1">
|
|
5175
|
+
<div class="layer-name">Layer 1</div>
|
|
5176
|
+
<div class="layer-title">Cognitive Sovereignty</div>
|
|
5177
|
+
<div class="layer-status"><span>\u25CF</span> <span id="l1-status">\u2014</span></div>
|
|
5178
|
+
<div class="layer-detail" id="l1-detail">Loading...</div>
|
|
5179
|
+
</div>
|
|
5180
|
+
<div class="layer-card" data-layer="l2">
|
|
5181
|
+
<div class="layer-name">Layer 2</div>
|
|
5182
|
+
<div class="layer-title">Operational Isolation</div>
|
|
5183
|
+
<div class="layer-status"><span>\u25CF</span> <span id="l2-status">\u2014</span></div>
|
|
5184
|
+
<div class="layer-detail" id="l2-detail">Loading...</div>
|
|
5185
|
+
</div>
|
|
5186
|
+
<div class="layer-card" data-layer="l3">
|
|
5187
|
+
<div class="layer-name">Layer 3</div>
|
|
5188
|
+
<div class="layer-title">Selective Disclosure</div>
|
|
5189
|
+
<div class="layer-status"><span>\u25CF</span> <span id="l3-status">\u2014</span></div>
|
|
5190
|
+
<div class="layer-detail" id="l3-detail">Loading...</div>
|
|
5191
|
+
</div>
|
|
5192
|
+
<div class="layer-card" data-layer="l4">
|
|
5193
|
+
<div class="layer-name">Layer 4</div>
|
|
5194
|
+
<div class="layer-title">Verifiable Reputation</div>
|
|
5195
|
+
<div class="layer-status"><span>\u25CF</span> <span id="l4-status">\u2014</span></div>
|
|
5196
|
+
<div class="layer-detail" id="l4-detail">Loading...</div>
|
|
5197
|
+
</div>
|
|
5198
|
+
</div>
|
|
5199
|
+
|
|
5200
|
+
<!-- Row 2: Info Cards -->
|
|
5201
|
+
<div class="info-cards">
|
|
5202
|
+
<div class="info-card">
|
|
5203
|
+
<div class="card-header">Identity</div>
|
|
5204
|
+
<div class="card-row">
|
|
5205
|
+
<span class="card-label">Primary</span>
|
|
5206
|
+
<span class="card-value" id="identity-label">\u2014</span>
|
|
5207
|
+
</div>
|
|
5208
|
+
<div class="card-row">
|
|
5209
|
+
<span class="card-label">DID</span>
|
|
5210
|
+
<span class="card-value truncated" id="identity-did" title="">\u2014</span>
|
|
5211
|
+
</div>
|
|
5212
|
+
<div class="card-row">
|
|
5213
|
+
<span class="card-label">Public Key</span>
|
|
5214
|
+
<span class="card-value truncated" id="identity-pubkey" title="">\u2014</span>
|
|
5215
|
+
</div>
|
|
5216
|
+
<div class="card-row">
|
|
5217
|
+
<span class="card-label">Type</span>
|
|
5218
|
+
<span class="identity-badge">Ed25519</span>
|
|
5219
|
+
</div>
|
|
5220
|
+
<div class="card-row">
|
|
5221
|
+
<span class="card-label">Created</span>
|
|
5222
|
+
<span class="card-value" id="identity-created">\u2014</span>
|
|
5223
|
+
</div>
|
|
5224
|
+
<div class="card-row">
|
|
5225
|
+
<span class="card-label">Identities</span>
|
|
5226
|
+
<span class="card-value" id="identity-count">\u2014</span>
|
|
5227
|
+
</div>
|
|
5228
|
+
</div>
|
|
5229
|
+
|
|
5230
|
+
<div class="info-card">
|
|
5231
|
+
<div class="card-header">Handshakes</div>
|
|
5232
|
+
<div class="card-row">
|
|
5233
|
+
<span class="card-label">Total</span>
|
|
5234
|
+
<span class="card-value" id="handshake-count">\u2014</span>
|
|
5235
|
+
</div>
|
|
5236
|
+
<div class="card-row">
|
|
5237
|
+
<span class="card-label">Latest Peer</span>
|
|
5238
|
+
<span class="card-value truncated" id="handshake-latest">\u2014</span>
|
|
5239
|
+
</div>
|
|
5240
|
+
<div class="card-row">
|
|
5241
|
+
<span class="card-label">Trust Tier</span>
|
|
5242
|
+
<span class="trust-tier-badge" id="handshake-tier">Unverified</span>
|
|
5243
|
+
</div>
|
|
5244
|
+
<div class="card-row">
|
|
5245
|
+
<span class="card-label">Timestamp</span>
|
|
5246
|
+
<span class="card-value" id="handshake-time">\u2014</span>
|
|
5247
|
+
</div>
|
|
5248
|
+
</div>
|
|
5249
|
+
|
|
5250
|
+
<div class="info-card">
|
|
5251
|
+
<div class="card-header">Reputation</div>
|
|
5252
|
+
<div class="card-row">
|
|
5253
|
+
<span class="card-label">Weighted Score</span>
|
|
5254
|
+
<span class="card-value" id="reputation-score">\u2014</span>
|
|
5255
|
+
</div>
|
|
5256
|
+
<div class="card-row">
|
|
5257
|
+
<span class="card-label">Attestations</span>
|
|
5258
|
+
<span class="card-value" id="reputation-attestations">\u2014</span>
|
|
5259
|
+
</div>
|
|
5260
|
+
<div class="card-row">
|
|
5261
|
+
<span class="card-label">Verified Sovereign</span>
|
|
5262
|
+
<span class="card-value" id="reputation-verified">\u2014</span>
|
|
5263
|
+
</div>
|
|
5264
|
+
<div class="card-row">
|
|
5265
|
+
<span class="card-label">Verified Degraded</span>
|
|
5266
|
+
<span class="card-value" id="reputation-degraded">\u2014</span>
|
|
5267
|
+
</div>
|
|
5268
|
+
<div class="card-row">
|
|
5269
|
+
<span class="card-label">Unverified</span>
|
|
5270
|
+
<span class="card-value" id="reputation-unverified">\u2014</span>
|
|
5271
|
+
</div>
|
|
5272
|
+
</div>
|
|
5273
|
+
</div>
|
|
5274
|
+
|
|
5275
|
+
<!-- Row 3: SHR & Activity -->
|
|
5276
|
+
<div class="main-panels">
|
|
5277
|
+
<div class="panel">
|
|
5278
|
+
<div class="panel-header">
|
|
5279
|
+
<div class="panel-title">Sovereignty Health Report</div>
|
|
5280
|
+
<button class="panel-action" id="copy-shr-btn">Copy JSON</button>
|
|
5281
|
+
</div>
|
|
5282
|
+
<div class="panel-content">
|
|
5283
|
+
<div class="shr-json" id="shr-viewer">
|
|
5284
|
+
<div class="empty-state">Loading SHR...</div>
|
|
5285
|
+
</div>
|
|
5286
|
+
</div>
|
|
5287
|
+
</div>
|
|
5288
|
+
|
|
5289
|
+
<div class="panel">
|
|
5290
|
+
<div class="panel-header">
|
|
5291
|
+
<div class="panel-title">Activity Feed</div>
|
|
5292
|
+
</div>
|
|
5293
|
+
<div class="panel-content">
|
|
5294
|
+
<div id="activity-feed" class="activity-feed">
|
|
5295
|
+
<div class="empty-state">Waiting for activity...</div>
|
|
5296
|
+
</div>
|
|
5297
|
+
</div>
|
|
5298
|
+
</div>
|
|
5299
|
+
</div>
|
|
5300
|
+
|
|
5301
|
+
<!-- Row 4: Handshake History -->
|
|
5302
|
+
<div class="handshake-table">
|
|
5303
|
+
<div class="table-header">
|
|
5304
|
+
<div>Counterparty</div>
|
|
5305
|
+
<div>Trust Tier</div>
|
|
5306
|
+
<div>Sovereignty</div>
|
|
5307
|
+
<div>Verified</div>
|
|
5308
|
+
<div>Completed</div>
|
|
5309
|
+
<div>Expires</div>
|
|
5310
|
+
</div>
|
|
5311
|
+
<div class="table-rows" id="handshake-table">
|
|
5312
|
+
<div class="table-empty">No handshakes completed yet</div>
|
|
5313
|
+
</div>
|
|
5314
|
+
</div>
|
|
5315
|
+
|
|
5316
|
+
<!-- Threat Panel -->
|
|
5317
|
+
<div class="threat-panel collapsed">
|
|
5318
|
+
<div class="threat-header">
|
|
5319
|
+
<div class="threat-title">Security Threats</div>
|
|
5320
|
+
<div class="threat-toggle">\u25B6</div>
|
|
5321
|
+
</div>
|
|
5322
|
+
<div class="threat-content" id="threat-alerts">
|
|
5323
|
+
<div class="empty-state">No threats detected</div>
|
|
5324
|
+
</div>
|
|
5025
5325
|
</div>
|
|
5026
5326
|
</div>
|
|
5027
5327
|
</div>
|
|
5028
5328
|
|
|
5029
|
-
<!--
|
|
5030
|
-
<div class="
|
|
5031
|
-
<div class="
|
|
5032
|
-
|
|
5033
|
-
|
|
5034
|
-
|
|
5035
|
-
|
|
5036
|
-
|
|
5037
|
-
|
|
5038
|
-
|
|
5039
|
-
|
|
5040
|
-
|
|
5329
|
+
<!-- Pending Overlay -->
|
|
5330
|
+
<div class="pending-overlay" id="pending-overlay">
|
|
5331
|
+
<div class="pending-header">Pending Approvals</div>
|
|
5332
|
+
<div class="pending-items" id="pending-items"></div>
|
|
5333
|
+
</div>
|
|
5334
|
+
|
|
5335
|
+
<script>
|
|
5336
|
+
// Constants
|
|
5337
|
+
const AUTH_TOKEN = '${options.authToken || ""}' || sessionStorage.getItem('authToken') || '';
|
|
5338
|
+
const TIMEOUT_SECONDS = ${options.timeoutSeconds};
|
|
5339
|
+
const API_BASE = '';
|
|
5340
|
+
|
|
5341
|
+
// State
|
|
5342
|
+
let apiState = {
|
|
5343
|
+
sovereignty: null,
|
|
5344
|
+
identity: null,
|
|
5345
|
+
handshakes: [],
|
|
5346
|
+
shr: null,
|
|
5347
|
+
status: null,
|
|
5348
|
+
};
|
|
5349
|
+
|
|
5350
|
+
let pendingRequests = new Map();
|
|
5351
|
+
let activityLog = [];
|
|
5352
|
+
const maxActivityItems = 50;
|
|
5353
|
+
|
|
5354
|
+
// Helpers
|
|
5355
|
+
function esc(text) {
|
|
5356
|
+
if (!text) return '';
|
|
5357
|
+
const div = document.createElement('div');
|
|
5358
|
+
div.textContent = text;
|
|
5359
|
+
return div.innerHTML;
|
|
5360
|
+
}
|
|
5361
|
+
|
|
5362
|
+
function formatTime(isoString) {
|
|
5363
|
+
if (!isoString) return '\u2014';
|
|
5364
|
+
const date = new Date(isoString);
|
|
5365
|
+
return date.toLocaleString('en-US', {
|
|
5366
|
+
month: 'short',
|
|
5367
|
+
day: 'numeric',
|
|
5368
|
+
hour: '2-digit',
|
|
5369
|
+
minute: '2-digit',
|
|
5370
|
+
});
|
|
5371
|
+
}
|
|
5372
|
+
|
|
5373
|
+
function truncate(str, len = 16) {
|
|
5374
|
+
if (!str) return '\u2014';
|
|
5375
|
+
if (str.length <= len) return str;
|
|
5376
|
+
return str.slice(0, len) + '...';
|
|
5377
|
+
}
|
|
5378
|
+
|
|
5379
|
+
function calculateSovereigntyScore(shr) {
|
|
5380
|
+
if (!shr || !shr.layers) return 0;
|
|
5381
|
+
const layers = shr.layers;
|
|
5382
|
+
let score = 100;
|
|
5383
|
+
|
|
5384
|
+
if (layers.l1?.status === 'degraded') score -= 20;
|
|
5385
|
+
if (layers.l1?.status === 'inactive') score -= 35;
|
|
5386
|
+
if (layers.l2?.status === 'degraded') score -= 15;
|
|
5387
|
+
if (layers.l2?.status === 'inactive') score -= 25;
|
|
5388
|
+
if (layers.l3?.status === 'degraded') score -= 15;
|
|
5389
|
+
if (layers.l3?.status === 'inactive') score -= 25;
|
|
5390
|
+
if (layers.l4?.status === 'degraded') score -= 10;
|
|
5391
|
+
if (layers.l4?.status === 'inactive') score -= 20;
|
|
5392
|
+
|
|
5393
|
+
return Math.max(0, Math.min(100, score));
|
|
5394
|
+
}
|
|
5395
|
+
|
|
5396
|
+
async function fetchAPI(endpoint) {
|
|
5397
|
+
try {
|
|
5398
|
+
const response = await fetch(API_BASE + endpoint, {
|
|
5399
|
+
headers: {
|
|
5400
|
+
'Authorization': 'Bearer ' + AUTH_TOKEN,
|
|
5401
|
+
},
|
|
5402
|
+
});
|
|
5403
|
+
|
|
5404
|
+
if (response.status === 401) {
|
|
5405
|
+
redirectToLogin();
|
|
5406
|
+
return null;
|
|
5407
|
+
}
|
|
5408
|
+
|
|
5409
|
+
if (!response.ok) {
|
|
5410
|
+
console.error('API Error:', response.status);
|
|
5411
|
+
return null;
|
|
5412
|
+
}
|
|
5413
|
+
|
|
5414
|
+
return await response.json();
|
|
5415
|
+
} catch (err) {
|
|
5416
|
+
console.error('Fetch error:', err);
|
|
5417
|
+
return null;
|
|
5418
|
+
}
|
|
5419
|
+
}
|
|
5420
|
+
|
|
5421
|
+
function redirectToLogin() {
|
|
5422
|
+
sessionStorage.removeItem('authToken');
|
|
5423
|
+
window.location.href = '/';
|
|
5424
|
+
}
|
|
5425
|
+
|
|
5426
|
+
// API Updates
|
|
5427
|
+
async function updateSovereignty() {
|
|
5428
|
+
const data = await fetchAPI('/api/sovereignty');
|
|
5429
|
+
if (!data) return;
|
|
5041
5430
|
|
|
5042
|
-
|
|
5043
|
-
<div class="protection-card-icon">\u2713</div>
|
|
5044
|
-
<div class="protection-card-label">Approval Gate</div>
|
|
5045
|
-
<div class="protection-card-status active" id="approvalStatus">\u2713 Active</div>
|
|
5046
|
-
<div class="protection-card-stat" id="approvalStat">T1: 2 | T2: 3</div>
|
|
5047
|
-
</div>
|
|
5431
|
+
apiState.sovereignty = data;
|
|
5048
5432
|
|
|
5049
|
-
|
|
5050
|
-
|
|
5051
|
-
|
|
5052
|
-
<div class="protection-card-status active" id="contextStatus">\u2713 Active</div>
|
|
5053
|
-
<div class="protection-card-stat" id="contextStat">12 filtered</div>
|
|
5054
|
-
</div>
|
|
5433
|
+
const score = calculateSovereigntyScore(data.shr);
|
|
5434
|
+
const badge = document.getElementById('sovereignty-badge');
|
|
5435
|
+
const scoreEl = document.getElementById('sovereignty-score');
|
|
5055
5436
|
|
|
5056
|
-
|
|
5057
|
-
<div class="protection-card-icon">\u26A0</div>
|
|
5058
|
-
<div class="protection-card-label">Injection Detection</div>
|
|
5059
|
-
<div class="protection-card-status active" id="injectionStatus">\u2713 Active</div>
|
|
5060
|
-
<div class="protection-card-stat" id="injectionStat">3 flags today</div>
|
|
5061
|
-
</div>
|
|
5437
|
+
scoreEl.textContent = score;
|
|
5062
5438
|
|
|
5063
|
-
|
|
5064
|
-
|
|
5065
|
-
|
|
5066
|
-
<div class="protection-card-status active" id="baselineStatus">\u2713 Active</div>
|
|
5067
|
-
<div class="protection-card-stat" id="baselineStat">0 anomalies</div>
|
|
5068
|
-
</div>
|
|
5439
|
+
badge.classList.remove('degraded', 'inactive');
|
|
5440
|
+
if (score < 70) badge.classList.add('degraded');
|
|
5441
|
+
if (score < 40) badge.classList.add('inactive');
|
|
5069
5442
|
|
|
5070
|
-
|
|
5071
|
-
|
|
5072
|
-
<div class="protection-card-label">Audit Trail</div>
|
|
5073
|
-
<div class="protection-card-status active" id="auditStatus">\u2713 Active</div>
|
|
5074
|
-
<div class="protection-card-stat" id="auditStat">284 entries</div>
|
|
5075
|
-
</div>
|
|
5076
|
-
</div>
|
|
5077
|
-
</div>
|
|
5078
|
-
</div>
|
|
5443
|
+
updateLayerCards(data.shr);
|
|
5444
|
+
}
|
|
5079
5445
|
|
|
5080
|
-
|
|
5081
|
-
|
|
5082
|
-
<div class="pending-overlay-header">
|
|
5083
|
-
<div class="pending-overlay-title">Pending Approvals</div>
|
|
5084
|
-
<button class="pending-overlay-close" onclick="closePendingOverlay()">\xD7</button>
|
|
5085
|
-
</div>
|
|
5086
|
-
<div class="pending-list" id="pendingList"></div>
|
|
5087
|
-
</div>
|
|
5088
|
-
|
|
5089
|
-
<!-- Threat Panel (collapsible footer) -->
|
|
5090
|
-
<div class="threat-panel collapsed" id="threatPanel">
|
|
5091
|
-
<div class="threat-header" onclick="toggleThreatPanel()">
|
|
5092
|
-
<span class="threat-icon">\u26A0</span>
|
|
5093
|
-
Recent Threats
|
|
5094
|
-
<span id="threatCount" style="margin-left: auto; color: var(--red); font-weight: 700;">0</span>
|
|
5095
|
-
</div>
|
|
5096
|
-
<div class="threat-content" id="threatContent">
|
|
5097
|
-
<div class="threat-empty">No threats detected</div>
|
|
5098
|
-
</div>
|
|
5099
|
-
</div>
|
|
5446
|
+
function updateLayerCards(shr) {
|
|
5447
|
+
if (!shr || !shr.layers) return;
|
|
5100
5448
|
|
|
5101
|
-
|
|
5102
|
-
(function() {
|
|
5103
|
-
'use strict';
|
|
5449
|
+
const layers = shr.layers;
|
|
5104
5450
|
|
|
5105
|
-
|
|
5451
|
+
updateLayerCard('l1', layers.l1, layers.l1?.encryption || 'AES-256-GCM');
|
|
5452
|
+
updateLayerCard('l2', layers.l2, layers.l2?.isolation_type || 'Process-level');
|
|
5453
|
+
updateLayerCard('l3', layers.l3, layers.l3?.proof_system || 'Schnorr-Pedersen');
|
|
5454
|
+
updateLayerCard('l4', layers.l4, layers.l4?.reputation_mode || 'Weighted');
|
|
5455
|
+
}
|
|
5106
5456
|
|
|
5107
|
-
|
|
5108
|
-
|
|
5109
|
-
const EMBEDDED_TOKEN = ${options.authToken ? JSON.stringify(options.authToken) : "null"};
|
|
5110
|
-
const AUTH_TOKEN = EMBEDDED_TOKEN || (function() { try { return sessionStorage.getItem('sanctuary_token'); } catch(_) { return null; } })();
|
|
5111
|
-
const MAX_ACTIVITY_ITEMS = 100;
|
|
5112
|
-
const MAX_THREAT_ITEMS = 20;
|
|
5457
|
+
function updateLayerCard(layer, layerData, detail) {
|
|
5458
|
+
if (!layerData) return;
|
|
5113
5459
|
|
|
5114
|
-
|
|
5460
|
+
const card = document.querySelector(\`[data-layer="\${layer}"]\`);
|
|
5461
|
+
if (!card) return;
|
|
5115
5462
|
|
|
5116
|
-
|
|
5117
|
-
|
|
5118
|
-
let startTime = Date.now();
|
|
5119
|
-
let activityCount = 0;
|
|
5120
|
-
let threatCount = 0;
|
|
5121
|
-
const pendingRequests = new Map();
|
|
5122
|
-
const activityItems = [];
|
|
5123
|
-
const threatItems = [];
|
|
5124
|
-
let sovereigntyScore = 85;
|
|
5125
|
-
let sessionRenewalTimer = null;
|
|
5463
|
+
const status = layerData.status || 'inactive';
|
|
5464
|
+
card.classList.remove('degraded', 'inactive');
|
|
5126
5465
|
|
|
5127
|
-
|
|
5466
|
+
if (status === 'degraded') {
|
|
5467
|
+
card.classList.add('degraded');
|
|
5468
|
+
} else if (status === 'inactive') {
|
|
5469
|
+
card.classList.add('inactive');
|
|
5470
|
+
}
|
|
5128
5471
|
|
|
5129
|
-
|
|
5130
|
-
|
|
5131
|
-
|
|
5132
|
-
return h;
|
|
5133
|
-
}
|
|
5472
|
+
document.getElementById(\`\${layer}-status\`).textContent = status.toUpperCase();
|
|
5473
|
+
document.getElementById(\`\${layer}-detail\`).textContent = detail;
|
|
5474
|
+
}
|
|
5134
5475
|
|
|
5135
|
-
|
|
5136
|
-
|
|
5137
|
-
|
|
5138
|
-
return url + sep + 'session=' + SESSION_ID;
|
|
5139
|
-
}
|
|
5476
|
+
async function updateIdentity() {
|
|
5477
|
+
const data = await fetchAPI('/api/identity');
|
|
5478
|
+
if (!data) return;
|
|
5140
5479
|
|
|
5141
|
-
|
|
5142
|
-
document.cookie = 'sanctuary_session=' + sessionId +
|
|
5143
|
-
'; path=/; SameSite=Strict; max-age=' + maxAge;
|
|
5144
|
-
}
|
|
5480
|
+
apiState.identity = data;
|
|
5145
5481
|
|
|
5146
|
-
|
|
5147
|
-
|
|
5148
|
-
|
|
5149
|
-
|
|
5150
|
-
|
|
5151
|
-
|
|
5152
|
-
|
|
5153
|
-
|
|
5154
|
-
// Update cookie with new session
|
|
5155
|
-
setCookie(SESSION_ID, ttl);
|
|
5156
|
-
// Schedule renewal at 80% of TTL
|
|
5157
|
-
if (sessionRenewalTimer) clearTimeout(sessionRenewalTimer);
|
|
5158
|
-
sessionRenewalTimer = setTimeout(function() {
|
|
5159
|
-
exchangeSession().then(function() { reconnectSSE(); });
|
|
5160
|
-
}, ttl * 800);
|
|
5161
|
-
} else if (resp.status === 401) {
|
|
5162
|
-
// Token invalid or expired \u2014 show non-destructive re-login overlay
|
|
5163
|
-
showSessionExpired();
|
|
5164
|
-
}
|
|
5165
|
-
} catch (e) {
|
|
5166
|
-
// Network error \u2014 retry in 30s
|
|
5167
|
-
if (sessionRenewalTimer) clearTimeout(sessionRenewalTimer);
|
|
5168
|
-
sessionRenewalTimer = setTimeout(function() {
|
|
5169
|
-
exchangeSession().then(function() { reconnectSSE(); });
|
|
5170
|
-
}, 30000);
|
|
5171
|
-
}
|
|
5172
|
-
}
|
|
5173
|
-
|
|
5174
|
-
function showSessionExpired() {
|
|
5175
|
-
// Clear stored token
|
|
5176
|
-
try { sessionStorage.removeItem('sanctuary_token'); } catch(_) {}
|
|
5177
|
-
// Redirect to login page
|
|
5178
|
-
document.cookie = 'sanctuary_session=; path=/; max-age=0';
|
|
5179
|
-
window.location.reload();
|
|
5180
|
-
}
|
|
5181
|
-
|
|
5182
|
-
// \u2500\u2500 UI Utilities \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
5183
|
-
|
|
5184
|
-
function esc(s) {
|
|
5185
|
-
const d = document.createElement('div');
|
|
5186
|
-
d.textContent = String(s || '');
|
|
5187
|
-
return d.innerHTML;
|
|
5188
|
-
}
|
|
5189
|
-
|
|
5190
|
-
function closePendingOverlay() {
|
|
5191
|
-
document.getElementById('pendingOverlay').classList.remove('active');
|
|
5192
|
-
}
|
|
5193
|
-
|
|
5194
|
-
function toggleThreatPanel() {
|
|
5195
|
-
document.getElementById('threatPanel').classList.toggle('collapsed');
|
|
5196
|
-
}
|
|
5197
|
-
|
|
5198
|
-
function updateUptime() {
|
|
5199
|
-
const elapsed = Math.floor((Date.now() - startTime) / 1000);
|
|
5200
|
-
const hours = Math.floor(elapsed / 3600);
|
|
5201
|
-
const mins = Math.floor((elapsed % 3600) / 60);
|
|
5202
|
-
const secs = elapsed % 60;
|
|
5203
|
-
let uptimeStr = '';
|
|
5204
|
-
if (hours > 0) uptimeStr += hours + 'h ';
|
|
5205
|
-
if (mins > 0) uptimeStr += mins + 'm ';
|
|
5206
|
-
uptimeStr += secs + 's';
|
|
5207
|
-
document.getElementById('uptimeText').textContent = uptimeStr;
|
|
5208
|
-
}
|
|
5209
|
-
|
|
5210
|
-
// \u2500\u2500 Sovereignty Score \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
5211
|
-
|
|
5212
|
-
function updateSovereigntyScore(score) {
|
|
5213
|
-
sovereigntyScore = Math.min(100, Math.max(0, score || 85));
|
|
5214
|
-
const badge = document.getElementById('sovereigntyScore');
|
|
5215
|
-
badge.textContent = sovereigntyScore;
|
|
5216
|
-
badge.className = 'sovereignty-score';
|
|
5217
|
-
if (sovereigntyScore >= 80) {
|
|
5218
|
-
badge.classList.add('high');
|
|
5219
|
-
} else if (sovereigntyScore >= 50) {
|
|
5220
|
-
badge.classList.add('medium');
|
|
5221
|
-
} else {
|
|
5222
|
-
badge.classList.add('low');
|
|
5482
|
+
const primary = data.primary || {};
|
|
5483
|
+
document.getElementById('identity-label').textContent = primary.label || '\u2014';
|
|
5484
|
+
document.getElementById('identity-did').textContent = truncate(primary.did, 24);
|
|
5485
|
+
document.getElementById('identity-did').title = primary.did || '';
|
|
5486
|
+
document.getElementById('identity-pubkey').textContent = truncate(primary.publicKey, 24);
|
|
5487
|
+
document.getElementById('identity-pubkey').title = primary.publicKey || '';
|
|
5488
|
+
document.getElementById('identity-created').textContent = formatTime(primary.createdAt);
|
|
5489
|
+
document.getElementById('identity-count').textContent = data.identities?.length || '\u2014';
|
|
5223
5490
|
}
|
|
5224
|
-
}
|
|
5225
5491
|
|
|
5226
|
-
|
|
5492
|
+
async function updateHandshakes() {
|
|
5493
|
+
const data = await fetchAPI('/api/handshakes');
|
|
5494
|
+
if (!data) return;
|
|
5227
5495
|
|
|
5228
|
-
|
|
5229
|
-
const {
|
|
5230
|
-
timestamp,
|
|
5231
|
-
tier,
|
|
5232
|
-
tool,
|
|
5233
|
-
outcome,
|
|
5234
|
-
detail,
|
|
5235
|
-
hasInjection,
|
|
5236
|
-
isContextGated
|
|
5237
|
-
} = data;
|
|
5238
|
-
|
|
5239
|
-
const item = {
|
|
5240
|
-
id: 'activity-' + activityCount++,
|
|
5241
|
-
timestamp: timestamp || new Date().toISOString(),
|
|
5242
|
-
tier: tier || 1,
|
|
5243
|
-
tool: tool || 'unknown_tool',
|
|
5244
|
-
outcome: outcome || 'executed',
|
|
5245
|
-
detail: detail || '',
|
|
5246
|
-
hasInjection: !!hasInjection,
|
|
5247
|
-
isContextGated: !!isContextGated
|
|
5248
|
-
};
|
|
5496
|
+
apiState.handshakes = data.handshakes || [];
|
|
5249
5497
|
|
|
5250
|
-
|
|
5251
|
-
|
|
5252
|
-
|
|
5498
|
+
document.getElementById('handshake-count').textContent = data.handshakes?.length || '0';
|
|
5499
|
+
|
|
5500
|
+
if (data.handshakes && data.handshakes.length > 0) {
|
|
5501
|
+
const latest = data.handshakes[0];
|
|
5502
|
+
document.getElementById('handshake-latest').textContent = truncate(latest.counterpartyId, 20);
|
|
5503
|
+
document.getElementById('handshake-latest').title = latest.counterpartyId || '';
|
|
5504
|
+
document.getElementById('handshake-tier').textContent = (latest.trustTier || 'Unverified').toUpperCase();
|
|
5505
|
+
document.getElementById('handshake-time').textContent = formatTime(latest.completedAt);
|
|
5506
|
+
} else {
|
|
5507
|
+
document.getElementById('handshake-latest').textContent = '\u2014';
|
|
5508
|
+
document.getElementById('handshake-tier').textContent = 'Unverified';
|
|
5509
|
+
document.getElementById('handshake-time').textContent = '\u2014';
|
|
5510
|
+
}
|
|
5511
|
+
|
|
5512
|
+
updateHandshakeTable(data.handshakes || []);
|
|
5253
5513
|
}
|
|
5254
5514
|
|
|
5255
|
-
|
|
5256
|
-
|
|
5515
|
+
function updateHandshakeTable(handshakes) {
|
|
5516
|
+
const table = document.getElementById('handshake-table');
|
|
5257
5517
|
|
|
5258
|
-
|
|
5259
|
-
|
|
5518
|
+
if (!handshakes || handshakes.length === 0) {
|
|
5519
|
+
table.innerHTML = '<div class="table-empty">No handshakes completed yet</div>';
|
|
5520
|
+
return;
|
|
5521
|
+
}
|
|
5260
5522
|
|
|
5261
|
-
|
|
5262
|
-
|
|
5263
|
-
|
|
5523
|
+
table.innerHTML = handshakes
|
|
5524
|
+
.map(
|
|
5525
|
+
(hs) => \`
|
|
5526
|
+
<div class="table-row">
|
|
5527
|
+
<div class="table-cell strong">\${esc(truncate(hs.counterpartyId, 24))}</div>
|
|
5528
|
+
<div class="table-cell">\${esc(hs.trustTier || 'Unverified')}</div>
|
|
5529
|
+
<div class="table-cell">\${esc(hs.sovereigntyLevel || '\u2014')}</div>
|
|
5530
|
+
<div class="table-cell">\${hs.verified ? 'Yes' : 'No'}</div>
|
|
5531
|
+
<div class="table-cell">\${formatTime(hs.completedAt)}</div>
|
|
5532
|
+
<div class="table-cell">\${formatTime(hs.expiresAt)}</div>
|
|
5533
|
+
</div>
|
|
5534
|
+
\`
|
|
5535
|
+
)
|
|
5536
|
+
.join('');
|
|
5264
5537
|
}
|
|
5265
5538
|
|
|
5266
|
-
|
|
5267
|
-
|
|
5268
|
-
|
|
5269
|
-
tr.className = 'activity-item';
|
|
5270
|
-
tr.id = item.id;
|
|
5271
|
-
|
|
5272
|
-
const time = new Date(item.timestamp);
|
|
5273
|
-
const timeStr = time.toLocaleTimeString();
|
|
5274
|
-
|
|
5275
|
-
const tierClass = 't' + item.tier;
|
|
5276
|
-
const outcomeClass = item.outcome === 'denied' ? 'outcome denied' : 'outcome';
|
|
5277
|
-
|
|
5278
|
-
let icon = '\u25CF';
|
|
5279
|
-
if (item.isContextGated) icon = '\u{1F3AF}';
|
|
5280
|
-
else if (item.hasInjection) icon = '\u26A0';
|
|
5281
|
-
else if (item.outcome === 'denied') icon = '\u2717';
|
|
5282
|
-
else icon = '\u2713';
|
|
5283
|
-
|
|
5284
|
-
tr.innerHTML =
|
|
5285
|
-
'<div class="activity-item-icon">' + esc(icon) + '</div>' +
|
|
5286
|
-
'<div class="activity-item-content">' +
|
|
5287
|
-
'<div class="activity-time">' + esc(timeStr) + '</div>' +
|
|
5288
|
-
'<div class="activity-main">' +
|
|
5289
|
-
'<span class="activity-tier ' + tierClass + '">T' + item.tier + '</span>' +
|
|
5290
|
-
'<span class="activity-tool">' + esc(item.tool) + '</span>' +
|
|
5291
|
-
'<span class="activity-outcome ' + (outcomeClass === 'outcome denied' ? 'denied' : '') + '">' + (item.outcome === 'denied' ? '\u2717 denied' : '\u2713 allowed') + '</span>' +
|
|
5292
|
-
'</div>' +
|
|
5293
|
-
'<div class="activity-detail">' + esc(item.detail) + '</div>' +
|
|
5294
|
-
'</div>' +
|
|
5295
|
-
'';
|
|
5296
|
-
|
|
5297
|
-
tr.addEventListener('click', () => {
|
|
5298
|
-
tr.classList.toggle('expanded');
|
|
5299
|
-
});
|
|
5539
|
+
async function updateSHR() {
|
|
5540
|
+
const data = await fetchAPI('/api/shr');
|
|
5541
|
+
if (!data) return;
|
|
5300
5542
|
|
|
5301
|
-
|
|
5543
|
+
apiState.shr = data;
|
|
5544
|
+
renderSHRViewer(data);
|
|
5302
5545
|
}
|
|
5303
|
-
}
|
|
5304
5546
|
|
|
5305
|
-
|
|
5547
|
+
function renderSHRViewer(shr) {
|
|
5548
|
+
const viewer = document.getElementById('shr-viewer');
|
|
5306
5549
|
|
|
5307
|
-
|
|
5308
|
-
|
|
5309
|
-
|
|
5310
|
-
|
|
5311
|
-
tier,
|
|
5312
|
-
reason,
|
|
5313
|
-
context,
|
|
5314
|
-
timestamp
|
|
5315
|
-
} = data;
|
|
5316
|
-
|
|
5317
|
-
const pending = {
|
|
5318
|
-
id: request_id,
|
|
5319
|
-
operation: operation || 'unknown',
|
|
5320
|
-
tier: tier || 1,
|
|
5321
|
-
reason: reason || '',
|
|
5322
|
-
context: context || {},
|
|
5323
|
-
timestamp: timestamp || new Date().toISOString(),
|
|
5324
|
-
remaining: TIMEOUT_SECONDS
|
|
5325
|
-
};
|
|
5550
|
+
if (!shr) {
|
|
5551
|
+
viewer.innerHTML = '<div class="empty-state">No SHR available</div>';
|
|
5552
|
+
return;
|
|
5553
|
+
}
|
|
5326
5554
|
|
|
5327
|
-
|
|
5328
|
-
|
|
5329
|
-
|
|
5555
|
+
let html = '';
|
|
5556
|
+
|
|
5557
|
+
// Implementation
|
|
5558
|
+
html += \`
|
|
5559
|
+
<div class="shr-section">
|
|
5560
|
+
<div class="shr-section-header">
|
|
5561
|
+
<div class="shr-toggle">\u25BC</div>
|
|
5562
|
+
<div>Implementation</div>
|
|
5563
|
+
</div>
|
|
5564
|
+
<div class="shr-section-content">
|
|
5565
|
+
<div class="shr-item">
|
|
5566
|
+
<div class="shr-key">sanctuary_version:</div>
|
|
5567
|
+
<div class="shr-value">\${esc(shr.implementation?.sanctuary_version || '\u2014')}</div>
|
|
5568
|
+
</div>
|
|
5569
|
+
<div class="shr-item">
|
|
5570
|
+
<div class="shr-key">node_version:</div>
|
|
5571
|
+
<div class="shr-value">\${esc(shr.implementation?.node_version || '\u2014')}</div>
|
|
5572
|
+
</div>
|
|
5573
|
+
<div class="shr-item">
|
|
5574
|
+
<div class="shr-key">generated_by:</div>
|
|
5575
|
+
<div class="shr-value">\${esc(shr.implementation?.generated_by || '\u2014')}</div>
|
|
5576
|
+
</div>
|
|
5577
|
+
</div>
|
|
5578
|
+
</div>
|
|
5579
|
+
\`;
|
|
5580
|
+
|
|
5581
|
+
// Metadata
|
|
5582
|
+
html += \`
|
|
5583
|
+
<div class="shr-section">
|
|
5584
|
+
<div class="shr-section-header">
|
|
5585
|
+
<div class="shr-toggle">\u25BC</div>
|
|
5586
|
+
<div>Metadata</div>
|
|
5587
|
+
</div>
|
|
5588
|
+
<div class="shr-section-content">
|
|
5589
|
+
<div class="shr-item">
|
|
5590
|
+
<div class="shr-key">instance_id:</div>
|
|
5591
|
+
<div class="shr-value">\${esc(truncate(shr.instance_id, 20))}</div>
|
|
5592
|
+
</div>
|
|
5593
|
+
<div class="shr-item">
|
|
5594
|
+
<div class="shr-key">generated_at:</div>
|
|
5595
|
+
<div class="shr-value">\${formatTime(shr.generated_at)}</div>
|
|
5596
|
+
</div>
|
|
5597
|
+
<div class="shr-item">
|
|
5598
|
+
<div class="shr-key">expires_at:</div>
|
|
5599
|
+
<div class="shr-value">\${formatTime(shr.expires_at)}</div>
|
|
5600
|
+
</div>
|
|
5601
|
+
</div>
|
|
5602
|
+
</div>
|
|
5603
|
+
\`;
|
|
5604
|
+
|
|
5605
|
+
// Layers
|
|
5606
|
+
if (shr.layers) {
|
|
5607
|
+
html += \`<div class="shr-section">
|
|
5608
|
+
<div class="shr-section-header">
|
|
5609
|
+
<div class="shr-toggle">\u25BC</div>
|
|
5610
|
+
<div>Layers</div>
|
|
5611
|
+
</div>
|
|
5612
|
+
<div class="shr-section-content">
|
|
5613
|
+
\`;
|
|
5614
|
+
|
|
5615
|
+
for (const [key, layer] of Object.entries(shr.layers)) {
|
|
5616
|
+
html += \`
|
|
5617
|
+
<div style="margin-bottom: 12px;">
|
|
5618
|
+
<div style="color: var(--blue); font-weight: 600; margin-bottom: 4px;">\${esc(key)}</div>
|
|
5619
|
+
<div style="padding-left: 12px;">
|
|
5620
|
+
\`;
|
|
5621
|
+
|
|
5622
|
+
for (const [lkey, lvalue] of Object.entries(layer || {})) {
|
|
5623
|
+
const displayValue =
|
|
5624
|
+
typeof lvalue === 'boolean'
|
|
5625
|
+
? lvalue
|
|
5626
|
+
? 'true'
|
|
5627
|
+
: 'false'
|
|
5628
|
+
: esc(String(lvalue));
|
|
5629
|
+
html += \`
|
|
5630
|
+
<div class="shr-item">
|
|
5631
|
+
<div class="shr-key">\${esc(lkey)}:</div>
|
|
5632
|
+
<div class="shr-value">\${displayValue}</div>
|
|
5633
|
+
</div>
|
|
5634
|
+
\`;
|
|
5635
|
+
}
|
|
5330
5636
|
|
|
5331
|
-
|
|
5332
|
-
|
|
5333
|
-
|
|
5334
|
-
|
|
5637
|
+
html += \`
|
|
5638
|
+
</div>
|
|
5639
|
+
</div>
|
|
5640
|
+
\`;
|
|
5641
|
+
}
|
|
5335
5642
|
|
|
5336
|
-
|
|
5337
|
-
|
|
5338
|
-
|
|
5643
|
+
html += \`
|
|
5644
|
+
</div>
|
|
5645
|
+
</div>
|
|
5646
|
+
\`;
|
|
5647
|
+
}
|
|
5648
|
+
|
|
5649
|
+
// Capabilities
|
|
5650
|
+
if (shr.capabilities) {
|
|
5651
|
+
html += \`
|
|
5652
|
+
<div class="shr-section">
|
|
5653
|
+
<div class="shr-section-header">
|
|
5654
|
+
<div class="shr-toggle">\u25BC</div>
|
|
5655
|
+
<div>Capabilities</div>
|
|
5656
|
+
</div>
|
|
5657
|
+
<div class="shr-section-content">
|
|
5658
|
+
\`;
|
|
5659
|
+
|
|
5660
|
+
for (const [key, value] of Object.entries(shr.capabilities)) {
|
|
5661
|
+
const displayValue = value ? 'true' : 'false';
|
|
5662
|
+
html += \`
|
|
5663
|
+
<div class="shr-item">
|
|
5664
|
+
<div class="shr-key">\${esc(key)}:</div>
|
|
5665
|
+
<div class="shr-value">\${displayValue}</div>
|
|
5666
|
+
</div>
|
|
5667
|
+
\`;
|
|
5668
|
+
}
|
|
5339
5669
|
|
|
5340
|
-
|
|
5341
|
-
|
|
5342
|
-
|
|
5343
|
-
|
|
5344
|
-
|
|
5345
|
-
|
|
5346
|
-
|
|
5670
|
+
html += \`
|
|
5671
|
+
</div>
|
|
5672
|
+
</div>
|
|
5673
|
+
\`;
|
|
5674
|
+
}
|
|
5675
|
+
|
|
5676
|
+
// Signature
|
|
5677
|
+
html += \`
|
|
5678
|
+
<div class="shr-section">
|
|
5679
|
+
<div class="shr-section-header">
|
|
5680
|
+
<div class="shr-toggle">\u25BC</div>
|
|
5681
|
+
<div>Signature</div>
|
|
5682
|
+
</div>
|
|
5683
|
+
<div class="shr-section-content">
|
|
5684
|
+
<div class="shr-item">
|
|
5685
|
+
<div class="shr-key">signed_by:</div>
|
|
5686
|
+
<div class="shr-value">\${esc(truncate(shr.signed_by, 20))}</div>
|
|
5687
|
+
</div>
|
|
5688
|
+
<div class="shr-item">
|
|
5689
|
+
<div class="shr-key">signature:</div>
|
|
5690
|
+
<div class="shr-value">\${esc(truncate(shr.signature, 32))}</div>
|
|
5691
|
+
</div>
|
|
5692
|
+
</div>
|
|
5693
|
+
</div>
|
|
5694
|
+
\`;
|
|
5695
|
+
|
|
5696
|
+
viewer.innerHTML = html;
|
|
5697
|
+
|
|
5698
|
+
// Add collapse functionality
|
|
5699
|
+
document.querySelectorAll('.shr-section-header').forEach((header) => {
|
|
5700
|
+
header.addEventListener('click', () => {
|
|
5701
|
+
header.closest('.shr-section').classList.toggle('collapsed');
|
|
5702
|
+
});
|
|
5703
|
+
});
|
|
5347
5704
|
}
|
|
5348
5705
|
|
|
5349
|
-
|
|
5350
|
-
|
|
5351
|
-
|
|
5352
|
-
function renderPendingList() {
|
|
5353
|
-
const list = document.getElementById('pendingList');
|
|
5354
|
-
list.innerHTML = '';
|
|
5706
|
+
async function updateStatus() {
|
|
5707
|
+
const data = await fetchAPI('/api/status');
|
|
5708
|
+
if (!data) return;
|
|
5355
5709
|
|
|
5356
|
-
|
|
5357
|
-
const item = document.createElement('div');
|
|
5358
|
-
item.className = 'pending-item';
|
|
5710
|
+
apiState.status = data;
|
|
5359
5711
|
|
|
5360
|
-
|
|
5361
|
-
|
|
5362
|
-
const pct = Math.max(0, Math.min(100, (req.remaining / TIMEOUT_SECONDS) * 100));
|
|
5363
|
-
const isUrgent = req.remaining <= 30;
|
|
5712
|
+
document.getElementById('protections-count').textContent = data.protectionsCount || '0';
|
|
5713
|
+
document.getElementById('uptime-value').textContent = formatUptime(data.uptime);
|
|
5364
5714
|
|
|
5365
|
-
|
|
5366
|
-
|
|
5367
|
-
|
|
5368
|
-
'<div class="pending-item-tier ' + tierClass + '">T' + tier + '</div>' +
|
|
5369
|
-
'</div>' +
|
|
5370
|
-
'<div class="pending-item-reason">' + esc(req.reason) + '</div>' +
|
|
5371
|
-
'<div class="pending-item-timer ' + (isUrgent ? 'urgent' : '') + '">' +
|
|
5372
|
-
'<div class="pending-item-timer-bar">' +
|
|
5373
|
-
'<div class="pending-item-timer-fill" style="width: ' + pct + '%"></div>' +
|
|
5374
|
-
'</div>' +
|
|
5375
|
-
'<span id="timer-' + id + '">' + req.remaining + 's</span>' +
|
|
5376
|
-
'</div>' +
|
|
5377
|
-
'<div class="pending-item-actions">' +
|
|
5378
|
-
'<button class="btn btn-approve" onclick="handleApprove('' + id + '')">Approve</button>' +
|
|
5379
|
-
'<button class="btn btn-deny" onclick="handleDeny('' + id + '')">Deny</button>' +
|
|
5380
|
-
'</div>' +
|
|
5381
|
-
'';
|
|
5715
|
+
const connectionStatus = document.getElementById('connection-status');
|
|
5716
|
+
connectionStatus.classList.toggle('disconnected', !data.connected);
|
|
5717
|
+
}
|
|
5382
5718
|
|
|
5383
|
-
|
|
5719
|
+
function formatUptime(seconds) {
|
|
5720
|
+
if (!seconds) return '\u2014';
|
|
5721
|
+
const hours = Math.floor(seconds / 3600);
|
|
5722
|
+
const minutes = Math.floor((seconds % 3600) / 60);
|
|
5723
|
+
if (hours > 0) return \`\${hours}h \${minutes}m\`;
|
|
5724
|
+
return \`\${minutes}m\`;
|
|
5384
5725
|
}
|
|
5385
|
-
}
|
|
5386
5726
|
|
|
5387
|
-
|
|
5388
|
-
|
|
5389
|
-
|
|
5390
|
-
|
|
5391
|
-
|
|
5727
|
+
// SSE Setup
|
|
5728
|
+
function setupSSE() {
|
|
5729
|
+
const eventSource = new EventSource(API_BASE + '/api/events', {
|
|
5730
|
+
headers: {
|
|
5731
|
+
'Authorization': 'Bearer ' + AUTH_TOKEN,
|
|
5732
|
+
},
|
|
5733
|
+
});
|
|
5392
5734
|
|
|
5393
|
-
|
|
5394
|
-
|
|
5395
|
-
|
|
5396
|
-
}).catch(() => {});
|
|
5397
|
-
};
|
|
5735
|
+
eventSource.addEventListener('init', (e) => {
|
|
5736
|
+
console.log('Connected to SSE');
|
|
5737
|
+
});
|
|
5398
5738
|
|
|
5399
|
-
|
|
5739
|
+
eventSource.addEventListener('sovereignty-update', () => {
|
|
5740
|
+
updateSovereignty();
|
|
5741
|
+
});
|
|
5400
5742
|
|
|
5401
|
-
|
|
5402
|
-
|
|
5403
|
-
|
|
5404
|
-
severity,
|
|
5405
|
-
type,
|
|
5406
|
-
details
|
|
5407
|
-
} = data;
|
|
5408
|
-
|
|
5409
|
-
const threat = {
|
|
5410
|
-
id: 'threat-' + threatCount++,
|
|
5411
|
-
timestamp: timestamp || new Date().toISOString(),
|
|
5412
|
-
severity: severity || 'medium',
|
|
5413
|
-
type: type || 'unknown',
|
|
5414
|
-
details: details || ''
|
|
5415
|
-
};
|
|
5743
|
+
eventSource.addEventListener('handshake-update', () => {
|
|
5744
|
+
updateHandshakes();
|
|
5745
|
+
});
|
|
5416
5746
|
|
|
5417
|
-
|
|
5418
|
-
|
|
5419
|
-
|
|
5420
|
-
|
|
5747
|
+
eventSource.addEventListener('tool-call', (e) => {
|
|
5748
|
+
const data = JSON.parse(e.data);
|
|
5749
|
+
addActivityItem({
|
|
5750
|
+
type: 'tool-call',
|
|
5751
|
+
title: 'Tool Call',
|
|
5752
|
+
content: data.toolName,
|
|
5753
|
+
timestamp: new Date().toISOString(),
|
|
5754
|
+
});
|
|
5755
|
+
});
|
|
5421
5756
|
|
|
5422
|
-
|
|
5423
|
-
|
|
5424
|
-
|
|
5757
|
+
eventSource.addEventListener('context-gate-decision', (e) => {
|
|
5758
|
+
const data = JSON.parse(e.data);
|
|
5759
|
+
addActivityItem({
|
|
5760
|
+
type: 'context-gate',
|
|
5761
|
+
title: 'Context Gate',
|
|
5762
|
+
content: data.decision,
|
|
5763
|
+
timestamp: new Date().toISOString(),
|
|
5764
|
+
});
|
|
5765
|
+
});
|
|
5425
5766
|
|
|
5426
|
-
|
|
5427
|
-
|
|
5767
|
+
eventSource.addEventListener('injection-alert', (e) => {
|
|
5768
|
+
const data = JSON.parse(e.data);
|
|
5769
|
+
addActivityItem({
|
|
5770
|
+
type: 'injection',
|
|
5771
|
+
title: 'Injection Alert',
|
|
5772
|
+
content: data.pattern,
|
|
5773
|
+
timestamp: new Date().toISOString(),
|
|
5774
|
+
});
|
|
5775
|
+
addThreatAlert(data);
|
|
5776
|
+
});
|
|
5777
|
+
|
|
5778
|
+
eventSource.addEventListener('pending-request', (e) => {
|
|
5779
|
+
const data = JSON.parse(e.data);
|
|
5780
|
+
addPendingRequest(data);
|
|
5781
|
+
});
|
|
5428
5782
|
|
|
5429
|
-
|
|
5430
|
-
|
|
5431
|
-
|
|
5783
|
+
eventSource.addEventListener('request-resolved', (e) => {
|
|
5784
|
+
const data = JSON.parse(e.data);
|
|
5785
|
+
removePendingRequest(data.requestId);
|
|
5786
|
+
});
|
|
5432
5787
|
|
|
5433
|
-
|
|
5434
|
-
|
|
5435
|
-
|
|
5436
|
-
|
|
5788
|
+
eventSource.onerror = () => {
|
|
5789
|
+
console.error('SSE error');
|
|
5790
|
+
setTimeout(setupSSE, 5000);
|
|
5791
|
+
};
|
|
5437
5792
|
}
|
|
5438
5793
|
|
|
5439
|
-
|
|
5440
|
-
|
|
5794
|
+
// Activity Feed
|
|
5795
|
+
function addActivityItem(item) {
|
|
5796
|
+
activityLog.unshift(item);
|
|
5797
|
+
if (activityLog.length > maxActivityItems) {
|
|
5798
|
+
activityLog.pop();
|
|
5799
|
+
}
|
|
5441
5800
|
|
|
5442
|
-
|
|
5443
|
-
const
|
|
5444
|
-
|
|
5445
|
-
|
|
5446
|
-
|
|
5447
|
-
|
|
5448
|
-
|
|
5449
|
-
|
|
5450
|
-
'</div>' +
|
|
5451
|
-
'<div>' + esc(threat.details) + '</div>' +
|
|
5452
|
-
'';
|
|
5453
|
-
content.appendChild(div);
|
|
5454
|
-
}
|
|
5455
|
-
}
|
|
5801
|
+
const feed = document.getElementById('activity-feed');
|
|
5802
|
+
const html = \`
|
|
5803
|
+
<div class="activity-item \${item.type}">
|
|
5804
|
+
<div class="activity-type">\${esc(item.title)}</div>
|
|
5805
|
+
<div class="activity-content">\${esc(item.content)}</div>
|
|
5806
|
+
<div class="activity-time">\${formatTime(item.timestamp)}</div>
|
|
5807
|
+
</div>
|
|
5808
|
+
\`;
|
|
5456
5809
|
|
|
5457
|
-
|
|
5810
|
+
if (feed.querySelector('.empty-state')) {
|
|
5811
|
+
feed.innerHTML = '';
|
|
5812
|
+
}
|
|
5458
5813
|
|
|
5459
|
-
|
|
5460
|
-
if (evtSource) evtSource.close();
|
|
5461
|
-
connect();
|
|
5462
|
-
}
|
|
5814
|
+
feed.insertAdjacentHTML('afterbegin', html);
|
|
5463
5815
|
|
|
5464
|
-
|
|
5465
|
-
|
|
5816
|
+
if (feed.children.length > maxActivityItems) {
|
|
5817
|
+
feed.lastChild.remove();
|
|
5818
|
+
}
|
|
5819
|
+
}
|
|
5466
5820
|
|
|
5467
|
-
|
|
5468
|
-
|
|
5469
|
-
|
|
5821
|
+
// Pending Requests
|
|
5822
|
+
function addPendingRequest(request) {
|
|
5823
|
+
pendingRequests.set(request.requestId, {
|
|
5824
|
+
id: request.requestId,
|
|
5825
|
+
title: request.title,
|
|
5826
|
+
details: request.details,
|
|
5827
|
+
expiresAt: new Date(Date.now() + TIMEOUT_SECONDS * 1000),
|
|
5828
|
+
});
|
|
5470
5829
|
|
|
5471
|
-
|
|
5472
|
-
|
|
5473
|
-
};
|
|
5830
|
+
updatePendingDisplay();
|
|
5831
|
+
}
|
|
5474
5832
|
|
|
5475
|
-
|
|
5476
|
-
|
|
5477
|
-
|
|
5478
|
-
|
|
5479
|
-
|
|
5480
|
-
|
|
5481
|
-
|
|
5833
|
+
function removePendingRequest(requestId) {
|
|
5834
|
+
pendingRequests.delete(requestId);
|
|
5835
|
+
updatePendingDisplay();
|
|
5836
|
+
}
|
|
5837
|
+
|
|
5838
|
+
function updatePendingDisplay() {
|
|
5839
|
+
const badge = document.getElementById('pending-item-badge');
|
|
5840
|
+
const count = pendingRequests.size;
|
|
5841
|
+
|
|
5842
|
+
if (count > 0) {
|
|
5843
|
+
document.getElementById('pending-count').textContent = count;
|
|
5844
|
+
badge.style.display = 'flex';
|
|
5845
|
+
} else {
|
|
5846
|
+
badge.style.display = 'none';
|
|
5482
5847
|
}
|
|
5483
|
-
|
|
5484
|
-
|
|
5848
|
+
|
|
5849
|
+
const overlay = document.getElementById('pending-overlay');
|
|
5850
|
+
const items = document.getElementById('pending-items');
|
|
5851
|
+
|
|
5852
|
+
if (count === 0) {
|
|
5853
|
+
items.innerHTML = '';
|
|
5854
|
+
overlay.classList.remove('show');
|
|
5855
|
+
return;
|
|
5485
5856
|
}
|
|
5486
|
-
});
|
|
5487
5857
|
|
|
5488
|
-
|
|
5489
|
-
const
|
|
5490
|
-
|
|
5491
|
-
|
|
5858
|
+
let html = '';
|
|
5859
|
+
for (const req of pendingRequests.values()) {
|
|
5860
|
+
const remaining = Math.max(0, Math.floor((req.expiresAt - Date.now()) / 1000));
|
|
5861
|
+
html += \`
|
|
5862
|
+
<div class="pending-item">
|
|
5863
|
+
<div class="pending-title">\${esc(req.title)}</div>
|
|
5864
|
+
<div class="pending-countdown">Expires in \${remaining}s</div>
|
|
5865
|
+
<div class="pending-actions">
|
|
5866
|
+
<button class="pending-btn pending-approve" data-id="\${req.id}">Approve</button>
|
|
5867
|
+
<button class="pending-btn pending-deny" data-id="\${req.id}">Deny</button>
|
|
5868
|
+
</div>
|
|
5869
|
+
</div>
|
|
5870
|
+
\`;
|
|
5871
|
+
}
|
|
5492
5872
|
|
|
5493
|
-
|
|
5494
|
-
const data = JSON.parse(e.data);
|
|
5495
|
-
removePendingRequest(data.request_id);
|
|
5496
|
-
});
|
|
5873
|
+
items.innerHTML = html;
|
|
5497
5874
|
|
|
5498
|
-
|
|
5499
|
-
|
|
5500
|
-
|
|
5501
|
-
|
|
5502
|
-
|
|
5503
|
-
tool: data.tool || 'unknown',
|
|
5504
|
-
outcome: data.outcome || 'executed',
|
|
5505
|
-
detail: data.detail || ''
|
|
5875
|
+
document.querySelectorAll('.pending-approve').forEach((btn) => {
|
|
5876
|
+
btn.addEventListener('click', async () => {
|
|
5877
|
+
const id = btn.getAttribute('data-id');
|
|
5878
|
+
await fetchAPI(\`/api/approve/\${id}\`);
|
|
5879
|
+
});
|
|
5506
5880
|
});
|
|
5507
|
-
});
|
|
5508
5881
|
|
|
5509
|
-
|
|
5510
|
-
|
|
5511
|
-
|
|
5512
|
-
|
|
5513
|
-
|
|
5514
|
-
tool: data.tool || 'unknown',
|
|
5515
|
-
outcome: data.outcome || 'gated',
|
|
5516
|
-
detail: data.fields_filtered ? 'Filtered ' + data.fields_filtered + ' fields' : data.reason || '',
|
|
5517
|
-
isContextGated: true
|
|
5882
|
+
document.querySelectorAll('.pending-deny').forEach((btn) => {
|
|
5883
|
+
btn.addEventListener('click', async () => {
|
|
5884
|
+
const id = btn.getAttribute('data-id');
|
|
5885
|
+
await fetchAPI(\`/api/deny/\${id}\`);
|
|
5886
|
+
});
|
|
5518
5887
|
});
|
|
5519
|
-
}
|
|
5888
|
+
}
|
|
5520
5889
|
|
|
5521
|
-
|
|
5522
|
-
|
|
5523
|
-
|
|
5524
|
-
|
|
5525
|
-
tier: data.tier || 2,
|
|
5526
|
-
tool: data.tool || 'unknown',
|
|
5527
|
-
outcome: data.allowed ? 'allowed' : 'denied',
|
|
5528
|
-
detail: data.signal || 'Injection detected',
|
|
5529
|
-
hasInjection: true
|
|
5530
|
-
});
|
|
5531
|
-
addThreat({
|
|
5532
|
-
timestamp: data.timestamp,
|
|
5533
|
-
severity: data.severity || 'medium',
|
|
5534
|
-
type: 'Injection Alert',
|
|
5535
|
-
details: data.signal || 'Suspicious pattern detected'
|
|
5536
|
-
});
|
|
5537
|
-
});
|
|
5890
|
+
// Threat Panel
|
|
5891
|
+
function addThreatAlert(alert) {
|
|
5892
|
+
const panel = document.querySelector('.threat-panel');
|
|
5893
|
+
const content = document.getElementById('threat-alerts');
|
|
5538
5894
|
|
|
5539
|
-
|
|
5540
|
-
|
|
5541
|
-
|
|
5542
|
-
});
|
|
5895
|
+
if (content.querySelector('.empty-state')) {
|
|
5896
|
+
content.innerHTML = '';
|
|
5897
|
+
}
|
|
5543
5898
|
|
|
5544
|
-
|
|
5545
|
-
const data = JSON.parse(e.data);
|
|
5546
|
-
// Audit entries don't show in activity by default, but we could add them
|
|
5547
|
-
});
|
|
5899
|
+
panel.classList.remove('collapsed');
|
|
5548
5900
|
|
|
5549
|
-
|
|
5550
|
-
|
|
5551
|
-
|
|
5552
|
-
|
|
5553
|
-
|
|
5901
|
+
const html = \`
|
|
5902
|
+
<div class="threat-alert">
|
|
5903
|
+
<div class="threat-type">\${esc(alert.type || 'Injection Alert')}</div>
|
|
5904
|
+
<div class="threat-message">\${esc(alert.message || alert.pattern || '\u2014')}</div>
|
|
5905
|
+
</div>
|
|
5906
|
+
\`;
|
|
5554
5907
|
|
|
5555
|
-
|
|
5556
|
-
if (!baseline) return;
|
|
5557
|
-
// Update baseline-derived stats if needed
|
|
5558
|
-
}
|
|
5908
|
+
content.insertAdjacentHTML('afterbegin', html);
|
|
5559
5909
|
|
|
5560
|
-
|
|
5561
|
-
|
|
5562
|
-
|
|
5563
|
-
|
|
5564
|
-
// Policy info updated
|
|
5910
|
+
const alerts = content.querySelectorAll('.threat-alert');
|
|
5911
|
+
if (alerts.length > 10) {
|
|
5912
|
+
alerts[alerts.length - 1].remove();
|
|
5913
|
+
}
|
|
5565
5914
|
}
|
|
5566
|
-
}
|
|
5567
5915
|
|
|
5568
|
-
|
|
5569
|
-
|
|
5570
|
-
|
|
5571
|
-
}
|
|
5572
|
-
if (status.active_protections !== undefined) {
|
|
5573
|
-
document.getElementById('activeProtections').textContent = status.active_protections;
|
|
5574
|
-
}
|
|
5575
|
-
// Update individual protection cards
|
|
5576
|
-
if (status.encryption !== undefined) {
|
|
5577
|
-
const el = document.getElementById('encryptionStatus');
|
|
5578
|
-
el.className = 'protection-card-status ' + (status.encryption ? 'active' : 'inactive');
|
|
5579
|
-
el.textContent = status.encryption ? '\u2713 Active' : '\u2717 Inactive';
|
|
5580
|
-
}
|
|
5581
|
-
if (status.approval_gate !== undefined) {
|
|
5582
|
-
const el = document.getElementById('approvalStatus');
|
|
5583
|
-
el.className = 'protection-card-status ' + (status.approval_gate ? 'active' : 'inactive');
|
|
5584
|
-
el.textContent = status.approval_gate ? '\u2713 Active' : '\u2717 Inactive';
|
|
5585
|
-
}
|
|
5586
|
-
if (status.context_gating !== undefined) {
|
|
5587
|
-
const el = document.getElementById('contextStatus');
|
|
5588
|
-
el.className = 'protection-card-status ' + (status.context_gating ? 'active' : 'inactive');
|
|
5589
|
-
el.textContent = status.context_gating ? '\u2713 Active' : '\u2717 Inactive';
|
|
5590
|
-
}
|
|
5591
|
-
if (status.injection_detection !== undefined) {
|
|
5592
|
-
const el = document.getElementById('injectionStatus');
|
|
5593
|
-
el.className = 'protection-card-status ' + (status.injection_detection ? 'active' : 'inactive');
|
|
5594
|
-
el.textContent = status.injection_detection ? '\u2713 Active' : '\u2717 Inactive';
|
|
5595
|
-
}
|
|
5596
|
-
if (status.baseline !== undefined) {
|
|
5597
|
-
const el = document.getElementById('baselineStatus');
|
|
5598
|
-
el.className = 'protection-card-status ' + (status.baseline ? 'active' : 'inactive');
|
|
5599
|
-
el.textContent = status.baseline ? '\u2713 Active' : '\u2717 Inactive';
|
|
5600
|
-
}
|
|
5601
|
-
if (status.audit_trail !== undefined) {
|
|
5602
|
-
const el = document.getElementById('auditStatus');
|
|
5603
|
-
el.className = 'protection-card-status ' + (status.audit_trail ? 'active' : 'inactive');
|
|
5604
|
-
el.textContent = status.audit_trail ? '\u2713 Active' : '\u2717 Inactive';
|
|
5605
|
-
}
|
|
5606
|
-
}
|
|
5916
|
+
// Threat Panel Toggle
|
|
5917
|
+
document.querySelector('.threat-header').addEventListener('click', () => {
|
|
5918
|
+
document.querySelector('.threat-panel').classList.toggle('collapsed');
|
|
5919
|
+
});
|
|
5607
5920
|
|
|
5608
|
-
|
|
5921
|
+
// SHR Copy Button
|
|
5922
|
+
document.getElementById('copy-shr-btn').addEventListener('click', async () => {
|
|
5923
|
+
if (!apiState.shr) return;
|
|
5609
5924
|
|
|
5610
|
-
|
|
5611
|
-
|
|
5612
|
-
|
|
5613
|
-
|
|
5614
|
-
|
|
5615
|
-
|
|
5616
|
-
|
|
5925
|
+
const json = JSON.stringify(apiState.shr, null, 2);
|
|
5926
|
+
try {
|
|
5927
|
+
await navigator.clipboard.writeText(json);
|
|
5928
|
+
const btn = document.getElementById('copy-shr-btn');
|
|
5929
|
+
const original = btn.textContent;
|
|
5930
|
+
btn.textContent = 'Copied!';
|
|
5931
|
+
setTimeout(() => {
|
|
5932
|
+
btn.textContent = original;
|
|
5933
|
+
}, 2000);
|
|
5934
|
+
} catch (err) {
|
|
5935
|
+
console.error('Copy failed:', err);
|
|
5936
|
+
}
|
|
5937
|
+
});
|
|
5617
5938
|
|
|
5618
|
-
//
|
|
5619
|
-
|
|
5620
|
-
|
|
5939
|
+
// Pending Overlay Toggle
|
|
5940
|
+
document.getElementById('pending-item-badge').addEventListener('click', () => {
|
|
5941
|
+
document.getElementById('pending-overlay').classList.toggle('show');
|
|
5942
|
+
});
|
|
5621
5943
|
|
|
5622
|
-
//
|
|
5623
|
-
|
|
5624
|
-
|
|
5625
|
-
|
|
5626
|
-
|
|
5627
|
-
if (el) {
|
|
5628
|
-
el.textContent = req.remaining + 's';
|
|
5629
|
-
}
|
|
5944
|
+
// Initialize
|
|
5945
|
+
async function initialize() {
|
|
5946
|
+
if (!AUTH_TOKEN) {
|
|
5947
|
+
redirectToLogin();
|
|
5948
|
+
return;
|
|
5630
5949
|
}
|
|
5631
|
-
}, 1000);
|
|
5632
5950
|
|
|
5633
|
-
|
|
5634
|
-
|
|
5635
|
-
|
|
5636
|
-
|
|
5637
|
-
|
|
5638
|
-
|
|
5639
|
-
|
|
5640
|
-
|
|
5641
|
-
} catch (e) {
|
|
5642
|
-
// Ignore
|
|
5643
|
-
}
|
|
5644
|
-
})();
|
|
5951
|
+
// Initial data fetch
|
|
5952
|
+
await Promise.all([
|
|
5953
|
+
updateSovereignty(),
|
|
5954
|
+
updateIdentity(),
|
|
5955
|
+
updateHandshakes(),
|
|
5956
|
+
updateSHR(),
|
|
5957
|
+
updateStatus(),
|
|
5958
|
+
]);
|
|
5645
5959
|
|
|
5646
|
-
|
|
5647
|
-
|
|
5960
|
+
// Setup SSE for real-time updates
|
|
5961
|
+
setupSSE();
|
|
5648
5962
|
|
|
5963
|
+
// Refresh status periodically
|
|
5964
|
+
setInterval(updateStatus, 30000);
|
|
5965
|
+
}
|
|
5966
|
+
|
|
5967
|
+
// Start
|
|
5968
|
+
initialize();
|
|
5969
|
+
</script>
|
|
5649
5970
|
</body>
|
|
5650
5971
|
</html>`;
|
|
5651
5972
|
}
|
|
@@ -7428,15 +7749,6 @@ function generateSHR(identityId, opts) {
|
|
|
7428
7749
|
mitigation: "TEE attestation planned for a future release"
|
|
7429
7750
|
});
|
|
7430
7751
|
}
|
|
7431
|
-
if (config.disclosure.proof_system === "commitment-only") {
|
|
7432
|
-
degradations.push({
|
|
7433
|
-
layer: "l3",
|
|
7434
|
-
code: "COMMITMENT_ONLY",
|
|
7435
|
-
severity: "info",
|
|
7436
|
-
description: "Commitment schemes only (no ZK proofs)",
|
|
7437
|
-
mitigation: "ZK proof support planned for future release"
|
|
7438
|
-
});
|
|
7439
|
-
}
|
|
7440
7752
|
const body = {
|
|
7441
7753
|
shr_version: "1.0",
|
|
7442
7754
|
implementation: {
|
|
@@ -7462,9 +7774,9 @@ function generateSHR(identityId, opts) {
|
|
|
7462
7774
|
attestation_available: config.execution.attestation
|
|
7463
7775
|
},
|
|
7464
7776
|
l3: {
|
|
7465
|
-
status:
|
|
7777
|
+
status: "active",
|
|
7466
7778
|
proof_system: config.disclosure.proof_system,
|
|
7467
|
-
selective_disclosure:
|
|
7779
|
+
selective_disclosure: true
|
|
7468
7780
|
},
|
|
7469
7781
|
l4: {
|
|
7470
7782
|
status: "active",
|
|
@@ -7677,7 +7989,7 @@ function extractAuthorizationSignals(body) {
|
|
|
7677
7989
|
behavioral_baseline_active: false,
|
|
7678
7990
|
// Would need explicit field in SHR v1.1
|
|
7679
7991
|
identity_verified: l1.identity_type === "ed25519" || l1.identity_type !== "none",
|
|
7680
|
-
zero_knowledge_capable: l3.status === "active"
|
|
7992
|
+
zero_knowledge_capable: l3.status === "active",
|
|
7681
7993
|
selective_disclosure_active: l3.selective_disclosure,
|
|
7682
7994
|
reputation_portable: l4.reputation_portable,
|
|
7683
7995
|
handshake_capable: body.capabilities.handshake
|
|
@@ -7755,14 +8067,6 @@ function generateAuthorizationConstraints(body, _degradations) {
|
|
|
7755
8067
|
priority: "high"
|
|
7756
8068
|
});
|
|
7757
8069
|
}
|
|
7758
|
-
if (layers.l3.proof_system === "commitment-only") {
|
|
7759
|
-
constraints.push({
|
|
7760
|
-
type: "restricted_scope",
|
|
7761
|
-
description: "No zero-knowledge proofs available \u2014 entire state context may be visible",
|
|
7762
|
-
rationale: "Proof system is commitment-only (no ZK)",
|
|
7763
|
-
priority: "medium"
|
|
7764
|
-
});
|
|
7765
|
-
}
|
|
7766
8070
|
if (layers.l4.status === "degraded") {
|
|
7767
8071
|
constraints.push({
|
|
7768
8072
|
type: "known_agents_only",
|
|
@@ -8094,6 +8398,154 @@ function deriveTrustTier(level) {
|
|
|
8094
8398
|
}
|
|
8095
8399
|
}
|
|
8096
8400
|
|
|
8401
|
+
// src/handshake/attestation.ts
|
|
8402
|
+
init_encoding();
|
|
8403
|
+
init_encoding();
|
|
8404
|
+
var ATTESTATION_VERSION = "1.0";
|
|
8405
|
+
function deriveTrustTier2(level) {
|
|
8406
|
+
switch (level) {
|
|
8407
|
+
case "full":
|
|
8408
|
+
return "verified-sovereign";
|
|
8409
|
+
case "degraded":
|
|
8410
|
+
return "verified-degraded";
|
|
8411
|
+
default:
|
|
8412
|
+
return "unverified";
|
|
8413
|
+
}
|
|
8414
|
+
}
|
|
8415
|
+
function generateAttestation(opts) {
|
|
8416
|
+
const {
|
|
8417
|
+
attesterSHR,
|
|
8418
|
+
subjectSHR,
|
|
8419
|
+
verificationResult,
|
|
8420
|
+
mutual = false,
|
|
8421
|
+
identityManager,
|
|
8422
|
+
masterKey,
|
|
8423
|
+
identityId
|
|
8424
|
+
} = opts;
|
|
8425
|
+
const identity = identityId ? identityManager.get(identityId) : identityManager.getDefault();
|
|
8426
|
+
if (!identity) {
|
|
8427
|
+
return { error: "No identity available for signing attestation" };
|
|
8428
|
+
}
|
|
8429
|
+
const now = /* @__PURE__ */ new Date();
|
|
8430
|
+
const attesterExpiry = new Date(attesterSHR.body.expires_at);
|
|
8431
|
+
const subjectExpiry = new Date(subjectSHR.body.expires_at);
|
|
8432
|
+
const earliestExpiry = attesterExpiry < subjectExpiry ? attesterExpiry : subjectExpiry;
|
|
8433
|
+
const sovereigntyLevel = verificationResult.valid ? verificationResult.sovereignty_level : "unverified";
|
|
8434
|
+
const body = {
|
|
8435
|
+
attestation_version: ATTESTATION_VERSION,
|
|
8436
|
+
attester_id: attesterSHR.body.instance_id,
|
|
8437
|
+
subject_id: subjectSHR.body.instance_id,
|
|
8438
|
+
attester_shr: attesterSHR,
|
|
8439
|
+
subject_shr: subjectSHR,
|
|
8440
|
+
verification: {
|
|
8441
|
+
subject_shr_valid: verificationResult.valid,
|
|
8442
|
+
subject_sovereignty_level: sovereigntyLevel,
|
|
8443
|
+
subject_trust_tier: deriveTrustTier2(sovereigntyLevel),
|
|
8444
|
+
mutual,
|
|
8445
|
+
errors: verificationResult.errors,
|
|
8446
|
+
warnings: verificationResult.warnings
|
|
8447
|
+
},
|
|
8448
|
+
attested_at: now.toISOString(),
|
|
8449
|
+
expires_at: earliestExpiry.toISOString()
|
|
8450
|
+
};
|
|
8451
|
+
const canonical = JSON.stringify(deepSortKeys(body));
|
|
8452
|
+
const payload = stringToBytes(canonical);
|
|
8453
|
+
const encryptionKey = derivePurposeKey(masterKey, "identity-encryption");
|
|
8454
|
+
const signatureBytes = sign(
|
|
8455
|
+
payload,
|
|
8456
|
+
identity.encrypted_private_key,
|
|
8457
|
+
encryptionKey
|
|
8458
|
+
);
|
|
8459
|
+
const summary = generateSummary(body);
|
|
8460
|
+
return {
|
|
8461
|
+
body,
|
|
8462
|
+
signed_by: identity.public_key,
|
|
8463
|
+
signature: toBase64url(signatureBytes),
|
|
8464
|
+
summary
|
|
8465
|
+
};
|
|
8466
|
+
}
|
|
8467
|
+
function layerLine(label, status) {
|
|
8468
|
+
const icon = status === "active" ? "\u2713" : status === "degraded" ? "~" : "x";
|
|
8469
|
+
return ` ${icon} ${label}: ${status}`;
|
|
8470
|
+
}
|
|
8471
|
+
function generateSummary(body) {
|
|
8472
|
+
const v = body.verification;
|
|
8473
|
+
const sLayers = body.subject_shr.body.layers;
|
|
8474
|
+
const aLayers = body.attester_shr.body.layers;
|
|
8475
|
+
const tierLabel = v.subject_trust_tier === "verified-sovereign" ? "Verified Sovereign" : v.subject_trust_tier === "verified-degraded" ? "Verified (Degraded)" : "Unverified";
|
|
8476
|
+
const lines = [
|
|
8477
|
+
`--- Sovereignty Attestation ---`,
|
|
8478
|
+
``,
|
|
8479
|
+
`Attester: ${body.attester_id.slice(0, 16)}...`,
|
|
8480
|
+
`Subject: ${body.subject_id.slice(0, 16)}...`,
|
|
8481
|
+
`Result: ${tierLabel}`,
|
|
8482
|
+
``,
|
|
8483
|
+
`Subject Sovereignty Posture:`,
|
|
8484
|
+
layerLine("L1 Cognitive Sovereignty", sLayers.l1.status),
|
|
8485
|
+
layerLine("L2 Operational Isolation", sLayers.l2.status),
|
|
8486
|
+
layerLine("L3 Selective Disclosure", sLayers.l3.status),
|
|
8487
|
+
layerLine("L4 Verifiable Reputation", sLayers.l4.status),
|
|
8488
|
+
``,
|
|
8489
|
+
`Attester Sovereignty Posture:`,
|
|
8490
|
+
layerLine("L1 Cognitive Sovereignty", aLayers.l1.status),
|
|
8491
|
+
layerLine("L2 Operational Isolation", aLayers.l2.status),
|
|
8492
|
+
layerLine("L3 Selective Disclosure", aLayers.l3.status),
|
|
8493
|
+
layerLine("L4 Verifiable Reputation", aLayers.l4.status),
|
|
8494
|
+
``,
|
|
8495
|
+
`Mutual: ${v.mutual ? "Yes" : "One-sided"}`,
|
|
8496
|
+
`Attested: ${body.attested_at}`,
|
|
8497
|
+
`Expires: ${body.expires_at}`,
|
|
8498
|
+
`Signature: ${body.attestation_version} / Ed25519`
|
|
8499
|
+
];
|
|
8500
|
+
if (v.warnings.length > 0) {
|
|
8501
|
+
lines.push(``, `Warnings: ${v.warnings.join("; ")}`);
|
|
8502
|
+
}
|
|
8503
|
+
if (v.errors.length > 0) {
|
|
8504
|
+
lines.push(``, `Errors: ${v.errors.join("; ")}`);
|
|
8505
|
+
}
|
|
8506
|
+
lines.push(``, `--- Verify: compare signed_by against attester's known public key ---`);
|
|
8507
|
+
return lines.join("\n");
|
|
8508
|
+
}
|
|
8509
|
+
function verifyAttestation(attestation, now) {
|
|
8510
|
+
const errors = [];
|
|
8511
|
+
const currentTime = now ?? /* @__PURE__ */ new Date();
|
|
8512
|
+
if (attestation.body.attestation_version !== ATTESTATION_VERSION) {
|
|
8513
|
+
errors.push(
|
|
8514
|
+
`Unsupported attestation version: ${attestation.body.attestation_version}`
|
|
8515
|
+
);
|
|
8516
|
+
}
|
|
8517
|
+
if (!attestation.body.attester_id || !attestation.body.subject_id) {
|
|
8518
|
+
errors.push("Missing attester_id or subject_id");
|
|
8519
|
+
}
|
|
8520
|
+
if (!attestation.body.attester_shr || !attestation.body.subject_shr) {
|
|
8521
|
+
errors.push("Missing attester or subject SHR");
|
|
8522
|
+
}
|
|
8523
|
+
const expired = new Date(attestation.body.expires_at) <= currentTime;
|
|
8524
|
+
if (expired) {
|
|
8525
|
+
errors.push("Attestation has expired");
|
|
8526
|
+
}
|
|
8527
|
+
try {
|
|
8528
|
+
const publicKey = fromBase64url(attestation.signed_by);
|
|
8529
|
+
const canonical = JSON.stringify(deepSortKeys(attestation.body));
|
|
8530
|
+
const payload = stringToBytes(canonical);
|
|
8531
|
+
const signatureBytes = fromBase64url(attestation.signature);
|
|
8532
|
+
const signatureValid = verify(payload, signatureBytes, publicKey);
|
|
8533
|
+
if (!signatureValid) {
|
|
8534
|
+
errors.push("Attestation signature is invalid");
|
|
8535
|
+
}
|
|
8536
|
+
} catch (e) {
|
|
8537
|
+
errors.push(`Signature verification error: ${e.message}`);
|
|
8538
|
+
}
|
|
8539
|
+
return {
|
|
8540
|
+
valid: errors.length === 0,
|
|
8541
|
+
errors,
|
|
8542
|
+
attester_id: attestation.body.attester_id ?? "unknown",
|
|
8543
|
+
subject_id: attestation.body.subject_id ?? "unknown",
|
|
8544
|
+
trust_tier: errors.length === 0 ? attestation.body.verification.subject_trust_tier : "unverified",
|
|
8545
|
+
expired
|
|
8546
|
+
};
|
|
8547
|
+
}
|
|
8548
|
+
|
|
8097
8549
|
// src/handshake/tools.ts
|
|
8098
8550
|
function createHandshakeTools(config, identityManager, masterKey, auditLog) {
|
|
8099
8551
|
const sessions = /* @__PURE__ */ new Map();
|
|
@@ -8279,6 +8731,103 @@ function createHandshakeTools(config, identityManager, masterKey, auditLog) {
|
|
|
8279
8731
|
result: session.result ?? null
|
|
8280
8732
|
});
|
|
8281
8733
|
}
|
|
8734
|
+
},
|
|
8735
|
+
// ─── Streamlined Exchange ─────────────────────────────────────────
|
|
8736
|
+
{
|
|
8737
|
+
name: "sanctuary/handshake_exchange",
|
|
8738
|
+
description: "One-shot sovereignty exchange. Accepts a counterparty's signed SHR, verifies it, generates our SHR, and produces a signed attestation artifact \u2014 all in a single call. Returns a shareable attestation with human-readable summary. Use this instead of the 4-step handshake protocol when you want a quick, portable sovereignty verification (e.g., for social posting or async exchanges).",
|
|
8739
|
+
inputSchema: {
|
|
8740
|
+
type: "object",
|
|
8741
|
+
properties: {
|
|
8742
|
+
counterparty_shr: {
|
|
8743
|
+
type: "object",
|
|
8744
|
+
description: "The counterparty's signed SHR (SignedSHR object with body, signed_by, signature)."
|
|
8745
|
+
},
|
|
8746
|
+
identity_id: {
|
|
8747
|
+
type: "string",
|
|
8748
|
+
description: "Identity to use for the exchange. Defaults to primary identity."
|
|
8749
|
+
}
|
|
8750
|
+
},
|
|
8751
|
+
required: ["counterparty_shr"]
|
|
8752
|
+
},
|
|
8753
|
+
handler: async (args) => {
|
|
8754
|
+
const counterpartySHR = args.counterparty_shr;
|
|
8755
|
+
const ourSHR = generateSHR(args.identity_id, shrOpts);
|
|
8756
|
+
if (typeof ourSHR === "string") {
|
|
8757
|
+
return toolResult({ error: ourSHR });
|
|
8758
|
+
}
|
|
8759
|
+
const verificationResult = verifySHR(counterpartySHR);
|
|
8760
|
+
const attestation = generateAttestation({
|
|
8761
|
+
attesterSHR: ourSHR,
|
|
8762
|
+
subjectSHR: counterpartySHR,
|
|
8763
|
+
verificationResult,
|
|
8764
|
+
mutual: false,
|
|
8765
|
+
identityManager,
|
|
8766
|
+
masterKey,
|
|
8767
|
+
identityId: args.identity_id
|
|
8768
|
+
});
|
|
8769
|
+
if ("error" in attestation) {
|
|
8770
|
+
auditLog.append("l4", "handshake_exchange", ourSHR.body.instance_id, void 0, "failure");
|
|
8771
|
+
return toolResult({ error: attestation.error });
|
|
8772
|
+
}
|
|
8773
|
+
if (verificationResult.valid) {
|
|
8774
|
+
const sovereigntyLevel = verificationResult.sovereignty_level;
|
|
8775
|
+
const trustTier = sovereigntyLevel === "full" ? "verified-sovereign" : sovereigntyLevel === "degraded" ? "verified-degraded" : "unverified";
|
|
8776
|
+
handshakeResults.set(verificationResult.counterparty_id, {
|
|
8777
|
+
counterparty_id: verificationResult.counterparty_id,
|
|
8778
|
+
counterparty_shr: counterpartySHR,
|
|
8779
|
+
verified: true,
|
|
8780
|
+
sovereignty_level: sovereigntyLevel,
|
|
8781
|
+
trust_tier: trustTier,
|
|
8782
|
+
completed_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8783
|
+
expires_at: verificationResult.expires_at,
|
|
8784
|
+
errors: []
|
|
8785
|
+
});
|
|
8786
|
+
}
|
|
8787
|
+
auditLog.append("l4", "handshake_exchange", ourSHR.body.instance_id);
|
|
8788
|
+
return toolResult({
|
|
8789
|
+
attestation,
|
|
8790
|
+
our_shr: ourSHR,
|
|
8791
|
+
verification: {
|
|
8792
|
+
counterparty_valid: verificationResult.valid,
|
|
8793
|
+
counterparty_sovereignty: verificationResult.sovereignty_level,
|
|
8794
|
+
counterparty_id: verificationResult.counterparty_id,
|
|
8795
|
+
errors: verificationResult.errors,
|
|
8796
|
+
warnings: verificationResult.warnings
|
|
8797
|
+
},
|
|
8798
|
+
instructions: "The 'attestation' object is a signed, portable sovereignty verification artifact. Share it with the counterparty or post attestation.summary publicly. The counterparty can verify the attestation signature using your public key. Our SHR is included so the counterparty can perform their own verification of us.",
|
|
8799
|
+
_content_trust: "external"
|
|
8800
|
+
});
|
|
8801
|
+
}
|
|
8802
|
+
},
|
|
8803
|
+
{
|
|
8804
|
+
name: "sanctuary/handshake_verify_attestation",
|
|
8805
|
+
description: "Verify a signed attestation artifact from another agent. Checks the Ed25519 signature, temporal validity, and structural integrity.",
|
|
8806
|
+
inputSchema: {
|
|
8807
|
+
type: "object",
|
|
8808
|
+
properties: {
|
|
8809
|
+
attestation: {
|
|
8810
|
+
type: "object",
|
|
8811
|
+
description: "The SignedAttestation object to verify (body, signed_by, signature, summary)."
|
|
8812
|
+
}
|
|
8813
|
+
},
|
|
8814
|
+
required: ["attestation"]
|
|
8815
|
+
},
|
|
8816
|
+
handler: async (args) => {
|
|
8817
|
+
const attestation = args.attestation;
|
|
8818
|
+
const result = verifyAttestation(attestation);
|
|
8819
|
+
auditLog.append(
|
|
8820
|
+
"l4",
|
|
8821
|
+
"handshake_verify_attestation",
|
|
8822
|
+
result.attester_id,
|
|
8823
|
+
void 0,
|
|
8824
|
+
result.valid ? "success" : "failure"
|
|
8825
|
+
);
|
|
8826
|
+
return toolResult({
|
|
8827
|
+
...result,
|
|
8828
|
+
_content_trust: "external"
|
|
8829
|
+
});
|
|
8830
|
+
}
|
|
8282
8831
|
}
|
|
8283
8832
|
];
|
|
8284
8833
|
return { tools, handshakeResults };
|
|
@@ -11890,11 +12439,6 @@ async function createSanctuaryServer(options) {
|
|
|
11890
12439
|
degradations.push(
|
|
11891
12440
|
"L2 isolation is process-level only; no TEE available"
|
|
11892
12441
|
);
|
|
11893
|
-
if (config.disclosure.proof_system === "commitment-only") {
|
|
11894
|
-
degradations.push(
|
|
11895
|
-
"L3 proofs are commitment-based only; ZK proofs not yet available"
|
|
11896
|
-
);
|
|
11897
|
-
}
|
|
11898
12442
|
return toolResult({
|
|
11899
12443
|
attestation: {
|
|
11900
12444
|
environment_type: config.execution.environment,
|
|
@@ -11920,7 +12464,7 @@ async function createSanctuaryServer(options) {
|
|
|
11920
12464
|
l1_state_encrypted: true,
|
|
11921
12465
|
l2_execution_isolated: false,
|
|
11922
12466
|
l2_isolation_type: "process-level",
|
|
11923
|
-
l3_proofs_available:
|
|
12467
|
+
l3_proofs_available: true,
|
|
11924
12468
|
l4_reputation_active: true,
|
|
11925
12469
|
overall_level: "mvs",
|
|
11926
12470
|
degradations
|
|
@@ -11943,14 +12487,6 @@ async function createSanctuaryServer(options) {
|
|
|
11943
12487
|
severity: "warning",
|
|
11944
12488
|
mitigation: "TEE support planned for a future release"
|
|
11945
12489
|
});
|
|
11946
|
-
if (config.disclosure.proof_system === "commitment-only") {
|
|
11947
|
-
degradations.push({
|
|
11948
|
-
layer: "l3",
|
|
11949
|
-
description: "Commitment schemes only (no ZK proofs)",
|
|
11950
|
-
severity: "info",
|
|
11951
|
-
mitigation: "ZK proof support planned for v0.2.0"
|
|
11952
|
-
});
|
|
11953
|
-
}
|
|
11954
12490
|
return toolResult({
|
|
11955
12491
|
status: degradations.some((d) => d.severity === "critical") ? "compromised" : degradations.some((d) => d.severity === "warning") ? "degraded" : "healthy",
|
|
11956
12492
|
storage_bytes: storageSizeBytes,
|
|
@@ -11969,7 +12505,7 @@ async function createSanctuaryServer(options) {
|
|
|
11969
12505
|
last_attestation: (/* @__PURE__ */ new Date()).toISOString()
|
|
11970
12506
|
},
|
|
11971
12507
|
l3: {
|
|
11972
|
-
status:
|
|
12508
|
+
status: "active",
|
|
11973
12509
|
proof_system: config.disclosure.proof_system,
|
|
11974
12510
|
circuits_loaded: 0,
|
|
11975
12511
|
proofs_generated_total: 0
|
|
@@ -12249,6 +12785,6 @@ async function createSanctuaryServer(options) {
|
|
|
12249
12785
|
return { server, config };
|
|
12250
12786
|
}
|
|
12251
12787
|
|
|
12252
|
-
export { ApprovalGate, AuditLog, AutoApproveChannel, BaselineTracker, TEMPLATES as CONTEXT_GATE_TEMPLATES, CallbackApprovalChannel, CommitmentStore, ContextGateEnforcer, ContextGatePolicyStore, DashboardApprovalChannel, FederationRegistry, FilesystemStorage, InjectionDetector, MemoryStorage, PolicyStore, ReputationStore, StateStore, StderrApprovalChannel, TIER_WEIGHTS, WebhookApprovalChannel, canonicalize, classifyField, completeHandshake, computeWeightedScore, createBridgeCommitment, createPedersenCommitment, createProofOfKnowledge, createRangeProof, createSanctuaryServer, evaluateField, filterContext, generateSHR, getTemplate, initiateHandshake, listTemplateIds, loadConfig, loadPrincipalPolicy, recommendPolicy, resolveTier, respondToHandshake, signPayload, tierDistribution, verifyBridgeCommitment, verifyCompletion, verifyPedersenCommitment, verifyProofOfKnowledge, verifyRangeProof, verifySHR, verifySignature };
|
|
12788
|
+
export { ATTESTATION_VERSION, ApprovalGate, AuditLog, AutoApproveChannel, BaselineTracker, TEMPLATES as CONTEXT_GATE_TEMPLATES, CallbackApprovalChannel, CommitmentStore, ContextGateEnforcer, ContextGatePolicyStore, DashboardApprovalChannel, FederationRegistry, FilesystemStorage, InjectionDetector, MemoryStorage, PolicyStore, ReputationStore, StateStore, StderrApprovalChannel, TIER_WEIGHTS, WebhookApprovalChannel, canonicalize, classifyField, completeHandshake, computeWeightedScore, createBridgeCommitment, createPedersenCommitment, createProofOfKnowledge, createRangeProof, createSanctuaryServer, evaluateField, filterContext, generateAttestation, generateSHR, getTemplate, initiateHandshake, listTemplateIds, loadConfig, loadPrincipalPolicy, recommendPolicy, resolveTier, respondToHandshake, signPayload, tierDistribution, verifyAttestation, verifyBridgeCommitment, verifyCompletion, verifyPedersenCommitment, verifyProofOfKnowledge, verifyRangeProof, verifySHR, verifySignature };
|
|
12253
12789
|
//# sourceMappingURL=index.js.map
|
|
12254
12790
|
//# sourceMappingURL=index.js.map
|