@agent-custody/receipts 0.6.8 → 0.6.9
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/log-admin.js +13 -3
- package/dist/portal.js +16 -2
- package/package.json +1 -1
package/dist/log-admin.js
CHANGED
|
@@ -204,9 +204,12 @@ export function adminRoutes(opts) {
|
|
|
204
204
|
const ADMIN_PAGE = `<!doctype html>
|
|
205
205
|
<meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1">
|
|
206
206
|
<title>agent-custody log admin</title>
|
|
207
|
+
<link rel="icon" href="/favicon.svg" type="image/svg+xml">
|
|
208
|
+
<script>(() => { try { const t = localStorage.getItem("agent-custody-theme"); if (t === "dark" || t === "light") document.documentElement.dataset.theme = t; } catch {} })();</script>
|
|
207
209
|
<style>
|
|
208
210
|
:root { color-scheme: light dark; --ink: #1b2430; --ink2: #5b6b7a; --line: #d7dfe5; --bg: #fafbfc; --panel: #ffffff; --accent: #0f6e63; --warn: #8a5a00; --warnbg: #fbf1dc; --mono: ui-monospace, Menlo, monospace; }
|
|
209
|
-
@media (prefers-color-scheme: dark) { :root { --ink: #e6ecf0; --ink2: #9fb0bd; --line: #27333c; --bg: #0e1418; --panel: #151d23; --accent: #4fc3b0; --warn: #e2b862; --warnbg: #2d2412; } }
|
|
211
|
+
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) { --ink: #e6ecf0; --ink2: #9fb0bd; --line: #27333c; --bg: #0e1418; --panel: #151d23; --accent: #4fc3b0; --warn: #e2b862; --warnbg: #2d2412; } }
|
|
212
|
+
:root[data-theme="dark"] { --ink: #e6ecf0; --ink2: #9fb0bd; --line: #27333c; --bg: #0e1418; --panel: #151d23; --accent: #4fc3b0; --warn: #e2b862; --warnbg: #2d2412; }
|
|
210
213
|
body { margin: 0; background: var(--bg); color: var(--ink); font: 15px/1.5 system-ui, sans-serif; }
|
|
211
214
|
main { max-width: 72rem; margin: 0 auto; padding: 2rem 1.25rem 4rem; }
|
|
212
215
|
h1 { font-size: 1.4rem; margin: 0 0 .25rem; } h2 { font-size: 1.05rem; margin: 2rem 0 .75rem; }
|
|
@@ -225,14 +228,16 @@ const ADMIN_PAGE = `<!doctype html>
|
|
|
225
228
|
.once { border-left: 3px solid var(--warn); background: var(--warnbg); padding: .8rem 1rem; border-radius: 0 4px 4px 0; margin: 1rem 0; }
|
|
226
229
|
.muted { color: var(--ink2); } .err { color: #b3261e; } .ok { color: var(--accent); }
|
|
227
230
|
.tok { font-family: var(--mono); font-size: 1.05rem; word-break: break-all; user-select: all; }
|
|
231
|
+
.head { display: flex; justify-content: space-between; align-items: start; gap: 1rem; }
|
|
232
|
+
button.theme { background: transparent; color: var(--ink2); border: 1px solid var(--line); padding: .25rem .6rem; font-size: .8rem; border-radius: 4px; } button.theme:hover { color: var(--ink); }
|
|
228
233
|
[hidden] { display: none !important; }
|
|
229
234
|
.stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr)); gap: .6rem; margin: 0 0 1rem; }
|
|
230
235
|
.stat { background: var(--panel); border: 1px solid var(--line); border-radius: 4px; padding: .6rem .8rem; }
|
|
231
236
|
.stat b { display: block; font-size: 1.4rem; font-variant-numeric: tabular-nums; } .stat span { color: var(--ink2); font-size: .8rem; }
|
|
232
237
|
</style>
|
|
233
238
|
<main>
|
|
234
|
-
<h1>Log admin</h1>
|
|
235
|
-
<p class="sub" id="where">Tenants and tokens on this log.</p>
|
|
239
|
+
<div class="head"><div><h1>Log admin</h1>
|
|
240
|
+
<p class="sub" id="where">Tenants and tokens on this log.</p></div><button class="theme" id="themeToggle" type="button">Dark mode</button></div>
|
|
236
241
|
<section id="app">
|
|
237
242
|
<h2>Registrations</h2>
|
|
238
243
|
<div class="row"><label>month<input id="rmonth" type="month"></label><button class="quiet" id="loadRegs">Show</button><a id="rcsv" class="quiet" href="#" style="align-self:center">Download CSV</a></div>
|
|
@@ -283,6 +288,11 @@ const ADMIN_PAGE = `<!doctype html>
|
|
|
283
288
|
};
|
|
284
289
|
const esc = (s) => String(s).replace(/[&<>"]/g, (c) => ({ "&": "&", "<": "<", ">": ">", '"': """ }[c]));
|
|
285
290
|
const say = (t, cls) => { $("msg").textContent = t; $("msg").className = cls || "muted"; };
|
|
291
|
+
// Light or dark by choice, kept in this browser; unset, the page follows the system. The button says where it is going.
|
|
292
|
+
const themeNow = () => document.documentElement.dataset.theme || (matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light");
|
|
293
|
+
const themeLabel = () => { $("themeToggle").textContent = themeNow() === "dark" ? "Light mode" : "Dark mode"; };
|
|
294
|
+
$("themeToggle").onclick = () => { const next = themeNow() === "dark" ? "light" : "dark"; document.documentElement.dataset.theme = next; try { localStorage.setItem("agent-custody-theme", next); } catch {} themeLabel(); };
|
|
295
|
+
themeLabel();
|
|
286
296
|
const loadTenants = async () => {
|
|
287
297
|
const list = await api("GET", "/admin/tenants");
|
|
288
298
|
const planPick = (t) => "<select data-plan=\\"" + esc(t.id) + "\\">" + ["free", "team", "enterprise"].map((p) => "<option" + (p === t.plan ? " selected" : "") + ">" + p + "</option>").join("") + "</select>";
|
package/dist/portal.js
CHANGED
|
@@ -241,6 +241,10 @@ export function portalHandler(o) {
|
|
|
241
241
|
try {
|
|
242
242
|
if (req.method === "GET" && url.pathname === "/health")
|
|
243
243
|
return json(200, { ok: true, stripe: !!o.stripe });
|
|
244
|
+
if (req.method === "GET" && url.pathname === "/favicon.svg") {
|
|
245
|
+
res.writeHead(200, { "content-type": "image/svg+xml", "cache-control": "public, max-age=86400" });
|
|
246
|
+
return void res.end(FAVICON);
|
|
247
|
+
}
|
|
244
248
|
if (req.method === "GET" && url.pathname === "/") {
|
|
245
249
|
res.writeHead(200, { "content-type": "text/html; charset=utf-8", "cache-control": "no-store", "x-frame-options": "DENY", "content-security-policy": "default-src 'none'; script-src 'unsafe-inline'; style-src 'unsafe-inline'; connect-src 'self'; form-action 'self'; base-uri 'none'" });
|
|
246
250
|
return void res.end(PORTAL_PAGE.replace("__LOG_BASE__", base.replace(/[&<>"]/g, (c) => ({ "&": "&", "<": "<", ">": ">", '"': """ })[c])));
|
|
@@ -417,18 +421,23 @@ export function servePortal(o, opts) {
|
|
|
417
421
|
});
|
|
418
422
|
}
|
|
419
423
|
// ---- the page: one file, no framework, no outside requests ----
|
|
424
|
+
const FAVICON = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><rect width="64" height="64" rx="14" fill="#b45309"/><circle cx="32" cy="32" r="19" fill="none" stroke="#fff" stroke-width="4.5"/><path d="M22 33.5l7 6.5 13-15" fill="none" stroke="#fff" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/></svg>';
|
|
420
425
|
const PORTAL_PAGE = `<!doctype html>
|
|
421
426
|
<meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1">
|
|
422
427
|
<title>agent-custody</title>
|
|
428
|
+
<link rel="icon" href="/favicon.svg" type="image/svg+xml">
|
|
429
|
+
<script>(() => { try { const t = localStorage.getItem("agent-custody-theme"); if (t === "dark" || t === "light") document.documentElement.dataset.theme = t; } catch {} })();</script>
|
|
423
430
|
<style>
|
|
424
431
|
:root { color-scheme: light dark; --ink: #1b2430; --ink2: #5b6b7a; --line: #d7dfe5; --bg: #f5f7f9; --panel: #ffffff; --accent: #b45309; --accent-bg: #fbf1dc; --warn: #8a5a00; --bad: #b3261e; --ok: #1f7a4d; --mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace; }
|
|
425
|
-
@media (prefers-color-scheme: dark) { :root { --ink: #e6ecf0; --ink2: #9fb0bd; --line: #27333c; --bg: #0e1418; --panel: #151d23; --accent: #f59e0b; --accent-bg: #2d2412; --warn: #e2b862; --bad: #ff8a80; --ok: #6fd39a; } }
|
|
432
|
+
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) { --ink: #e6ecf0; --ink2: #9fb0bd; --line: #27333c; --bg: #0e1418; --panel: #151d23; --accent: #f59e0b; --accent-bg: #2d2412; --warn: #e2b862; --bad: #ff8a80; --ok: #6fd39a; } }
|
|
433
|
+
:root[data-theme="dark"] { --ink: #e6ecf0; --ink2: #9fb0bd; --line: #27333c; --bg: #0e1418; --panel: #151d23; --accent: #f59e0b; --accent-bg: #2d2412; --warn: #e2b862; --bad: #ff8a80; --ok: #6fd39a; }
|
|
426
434
|
* { box-sizing: border-box; }
|
|
427
435
|
body { margin: 0; background: var(--bg); color: var(--ink); font: 15px/1.5 system-ui, -apple-system, "Segoe UI", sans-serif; }
|
|
428
436
|
.top { display: flex; align-items: center; gap: 1rem; padding: .7rem 1.25rem; border-bottom: 1px solid var(--line); background: var(--panel); }
|
|
429
437
|
.brand { font-weight: 700; letter-spacing: .04em; display: inline-flex; align-items: center; gap: .5rem; color: var(--ink); text-decoration: none; } .brand svg { width: 20px; height: 20px; display: block; } .brand rect { fill: var(--accent); }
|
|
430
438
|
.top .links { margin-left: auto; display: flex; gap: .9rem; font-size: .9rem; } .top .links a { color: var(--accent); text-decoration: none; }
|
|
431
439
|
.top .who { color: var(--ink2); font-size: .9rem; margin-left: .5rem; }
|
|
440
|
+
button.theme { background: transparent; color: var(--ink2); border: 1px solid var(--line); padding: .25rem .6rem; font-size: .8rem; border-radius: 4px; } button.theme:hover { color: var(--ink); }
|
|
432
441
|
.pill { display: inline-block; padding: .05rem .5rem; border-radius: 999px; font: 600 .72rem/1.6 var(--mono); letter-spacing: .06em; text-transform: uppercase; background: var(--accent-bg); color: var(--accent); }
|
|
433
442
|
.layout { display: grid; grid-template-columns: 15rem 1fr; min-height: calc(100vh - 3.3rem); }
|
|
434
443
|
nav { border-right: 1px solid var(--line); background: var(--panel); padding: 1rem 0; }
|
|
@@ -475,7 +484,7 @@ const PORTAL_PAGE = `<!doctype html>
|
|
|
475
484
|
[hidden] { display: none !important; }
|
|
476
485
|
@media (max-width: 48rem) { .layout { grid-template-columns: 1fr; } nav { display: flex; flex-wrap: wrap; padding: .3rem; border-right: 0; border-bottom: 1px solid var(--line); } nav .group { display: none; } nav a { border-left: 0; border-bottom: 3px solid transparent; } nav a.on { border-bottom-color: var(--accent); } }
|
|
477
486
|
</style>
|
|
478
|
-
<div class="top"><a class="brand" href="https://agent-custody.dev/"><svg viewBox="0 0 64 64" aria-hidden="true"><rect width="64" height="64" rx="14"/><circle cx="32" cy="32" r="19" fill="none" stroke="#fff" stroke-width="4.5"/><path d="M22 33.5l7 6.5 13-15" fill="none" stroke="#fff" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/></svg>agent-custody</a><span id="tenantTag" class="pill" hidden></span><span id="planTag" class="pill" hidden></span><span class="links"><a href="https://agent-custody.dev/guide/getting-started">Guide</a><a href="https://docs.agent-custody.dev/reference/">Docs</a><a href="https://agent-custody.dev/verify">Verify a receipt</a></span><span class="who" id="who"></span></div>
|
|
487
|
+
<div class="top"><a class="brand" href="https://agent-custody.dev/"><svg viewBox="0 0 64 64" aria-hidden="true"><rect width="64" height="64" rx="14"/><circle cx="32" cy="32" r="19" fill="none" stroke="#fff" stroke-width="4.5"/><path d="M22 33.5l7 6.5 13-15" fill="none" stroke="#fff" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/></svg>agent-custody</a><span id="tenantTag" class="pill" hidden></span><span id="planTag" class="pill" hidden></span><span class="links"><a href="https://agent-custody.dev/guide/getting-started">Guide</a><a href="https://docs.agent-custody.dev/reference/">Docs</a><a href="https://agent-custody.dev/verify">Verify a receipt</a></span><span class="who" id="who"></span><button class="theme" id="themeToggle" type="button">Dark mode</button></div>
|
|
479
488
|
<section id="auth" class="auth" hidden>
|
|
480
489
|
<h1 id="authTitle">Sign in</h1>
|
|
481
490
|
<form id="authForm">
|
|
@@ -598,6 +607,11 @@ const PORTAL_PAGE = `<!doctype html>
|
|
|
598
607
|
} catch (err) { $("authMsg").className = "msg err"; $("authMsg").textContent = err.message; }
|
|
599
608
|
};
|
|
600
609
|
$("copyFirst").onclick = () => navigator.clipboard.writeText($("firstToken").textContent);
|
|
610
|
+
// Light or dark by choice, kept in this browser; unset, the page follows the system. The button says where it is going.
|
|
611
|
+
const themeNow = () => document.documentElement.dataset.theme || (matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light");
|
|
612
|
+
const themeLabel = () => { $("themeToggle").textContent = themeNow() === "dark" ? "Light mode" : "Dark mode"; };
|
|
613
|
+
$("themeToggle").onclick = () => { const next = themeNow() === "dark" ? "light" : "dark"; document.documentElement.dataset.theme = next; try { localStorage.setItem("agent-custody-theme", next); } catch {} themeLabel(); };
|
|
614
|
+
themeLabel();
|
|
601
615
|
const snip = (text) => "<div class=snip><pre>" + esc(text) + "</pre><button type=button class=quiet data-copy>Copy</button></div>";
|
|
602
616
|
const step = (n, title, body) => "<div class=step><span class=n>" + n + "</span><div><h3>" + title + "</h3>" + body + "</div></div>";
|
|
603
617
|
const renderSetup = (el, s, atRegistration) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-custody/receipts",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.9",
|
|
4
4
|
"description": "Chain of custody for AI agents: signed, independently verifiable receipts for tool calls. MCP gateway + Cedar policy + Merkle transparency log",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|