@zanii/monitor 0.2.0 → 0.2.2

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/README.md CHANGED
@@ -54,6 +54,8 @@ await monitor('https://ledger.zanii.agency', {
54
54
 
55
55
  ## Changelog
56
56
 
57
+ - **0.2.2** — Operations: `checkMany` logs at once, `watchlistOnce` for named agents, `anchorLag` alerts, alert sinks (`slackSink`, `webhookSink`, `alertAll`), split-view `compareViews` with peer monitors, signed `attestCheck` statements, `completenessAudit` of bundles, a serverless `scheduledCheck`, a script-free `statusPage` and a signed `dailyReport`.
58
+ - **0.2.1** — now depends on `@zanii/core` 0.5 (protocol 1.2), so it shares one core with `@zanii/sdk` 0.5 instead of pulling in a second, older copy. No API change.
57
59
  - **0.1.0** — initial release: `checkOnce`, `monitor`, and the `zanii-monitor` CLI.
58
60
 
59
61
  ## License
package/dist/index.d.ts CHANGED
@@ -32,4 +32,5 @@ export interface MonitorOptions {
32
32
  }
33
33
  /** Run forever, checking every `intervalMs` (default 60s). Never resolves. */
34
34
  export declare function monitor(server: string, opts?: MonitorOptions): Promise<never>;
35
+ export * from './operations.js';
35
36
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAcA,MAAM,MAAM,SAAS,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;AAEjF,uEAAuE;AACvE,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,KAAK;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,OAAO,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,qEAAqE;IACrE,KAAK,EAAE,YAAY,CAAC;CACrB;AAQD;;;GAGG;AACH,wBAAsB,SAAS,CAC7B,MAAM,EAAE,MAAM,EACd,IAAI,CAAC,EAAE,YAAY,EACnB,SAAS,GAAE,SAAiC,GAC3C,OAAO,CAAC,aAAa,CAAC,CAkExB;AAED,MAAM,WAAW,cAAc;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,QAAQ,CAAC,EAAE,CAAC,CAAC,EAAE,aAAa,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtD,WAAW,CAAC,EAAE,CAAC,CAAC,EAAE,aAAa,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1D;AAED,8EAA8E;AAC9E,wBAAsB,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,GAAE,cAAmB,GAAG,OAAO,CAAC,KAAK,CAAC,CAevF"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAcA,MAAM,MAAM,SAAS,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;AAEjF,uEAAuE;AACvE,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,KAAK;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,OAAO,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,qEAAqE;IACrE,KAAK,EAAE,YAAY,CAAC;CACrB;AAQD;;;GAGG;AACH,wBAAsB,SAAS,CAC7B,MAAM,EAAE,MAAM,EACd,IAAI,CAAC,EAAE,YAAY,EACnB,SAAS,GAAE,SAAiC,GAC3C,OAAO,CAAC,aAAa,CAAC,CAkExB;AAED,MAAM,WAAW,cAAc;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,QAAQ,CAAC,EAAE,CAAC,CAAC,EAAE,aAAa,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtD,WAAW,CAAC,EAAE,CAAC,CAAC,EAAE,aAAa,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1D;AAED,8EAA8E;AAC9E,wBAAsB,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,GAAE,cAAmB,GAAG,OAAO,CAAC,KAAK,CAAC,CAevF;AACD,cAAc,iBAAiB,CAAC"}
package/dist/index.js CHANGED
@@ -103,4 +103,5 @@ export async function monitor(server, opts = {}) {
103
103
  await new Promise((res) => setTimeout(res, interval));
104
104
  }
105
105
  }
106
+ export * from './operations.js';
106
107
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Running monitors in production: several logs at once, watchlists of agents, anchor-lag
3
+ * alerts, alert sinks, split-view comparison with peer monitors, signed attestations of
4
+ * what was checked, bundle completeness, a serverless entry point, a static status page,
5
+ * and a signed daily report for a supervisor.
6
+ */
7
+ import { type AuditBundle, type SignedObject, type SignedTreeHead } from '@zanii/core';
8
+ import { type FetchLike, type MonitorResult, type MonitorState } from './index.js';
9
+ /** Check several logs in one pass. Each keeps its own state; a failure on one does not stop the others. */
10
+ export declare function checkMany(servers: string[], states: Record<string, MonitorState | undefined>, fetchImpl?: FetchLike): Promise<Record<string, MonitorResult | {
11
+ ok: false;
12
+ error: string;
13
+ }>>;
14
+ /** New receipts by watched agents since the last poll (from the log's recent feed). */
15
+ export declare function watchlistOnce(server: string, dids: string[], seen: Set<string>, fetchImpl?: FetchLike): Promise<{
16
+ hash: string | null;
17
+ agent: any;
18
+ target: any;
19
+ ts: any;
20
+ }[]>;
21
+ /** How far on-chain anchoring lags the log, with an alert above the threshold. */
22
+ export declare function anchorLag(server: string, thresholdMs: number, fetchImpl?: FetchLike, now?: number): Promise<{
23
+ lagMs: null;
24
+ alert: boolean;
25
+ reason: string;
26
+ } | {
27
+ lagMs: number;
28
+ alert: boolean;
29
+ reason: string | null;
30
+ }>;
31
+ export type AlertSink = (r: MonitorResult & {
32
+ server?: string;
33
+ }) => Promise<void>;
34
+ /** Post violations to a Slack incoming webhook. */
35
+ export declare function slackSink(webhookUrl: string, fetchImpl?: FetchLike): AlertSink;
36
+ /** Post the full result as JSON to any webhook (PagerDuty, Opsgenie, your own). */
37
+ export declare function webhookSink(url: string, fetchImpl?: FetchLike): AlertSink;
38
+ /** Send to every sink; one failing sink does not stop the others. */
39
+ export declare function alertAll(r: MonitorResult & {
40
+ server?: string;
41
+ }, sinks: AlertSink[]): Promise<("rejected" | "fulfilled")[]>;
42
+ /**
43
+ * Compare our view of a log with views other monitors saw. Two valid heads for the same
44
+ * size with different roots is a split view: the log showed different histories.
45
+ */
46
+ export declare function compareViews(ours: SignedTreeHead, theirs: SignedTreeHead[]): {
47
+ consistent: boolean;
48
+ splits: SignedTreeHead[];
49
+ };
50
+ export type MonitorAttestation = SignedObject<{
51
+ v: 1;
52
+ type: 'monitor.attestation';
53
+ server: string;
54
+ size: number;
55
+ root: string;
56
+ ok: boolean;
57
+ ts: string;
58
+ }>;
59
+ /** A monitor's signed statement of what it checked. Collected from independent monitors, these become witness evidence. */
60
+ export declare function attestCheck(server: string, r: MonitorResult, monitorPrivateKey: Uint8Array, ts?: string): MonitorAttestation;
61
+ /** Is an agent's exported history complete, with no gaps in its chain? */
62
+ export declare function completenessAudit(bundle: AuditBundle): {
63
+ complete: boolean;
64
+ receipts: number;
65
+ detail: string | null;
66
+ failed: string[];
67
+ };
68
+ /**
69
+ * One scheduled check for serverless platforms (a cron trigger): load the last state,
70
+ * check, save the new state, alert on violation.
71
+ */
72
+ export declare function scheduledCheck(opts: {
73
+ server: string;
74
+ getState: () => Promise<MonitorState | undefined>;
75
+ putState: (s: MonitorState) => Promise<void>;
76
+ sinks?: AlertSink[];
77
+ fetchImpl?: FetchLike;
78
+ }): Promise<MonitorResult>;
79
+ /** A static status page from recent results (no scripts). */
80
+ export declare function statusPage(history: Array<{
81
+ server: string;
82
+ ts: string;
83
+ ok: boolean;
84
+ size: number;
85
+ }>): string;
86
+ export type DailyReport = SignedObject<{
87
+ v: 1;
88
+ type: 'monitor.daily';
89
+ server: string;
90
+ day: string;
91
+ checks: number;
92
+ violations: number;
93
+ firstSize: number;
94
+ lastSize: number;
95
+ ts: string;
96
+ }>;
97
+ /** A signed daily summary for a supervisor. */
98
+ export declare function dailyReport(server: string, day: string, results: MonitorResult[], monitorPrivateKey: Uint8Array): DailyReport;
99
+ //# sourceMappingURL=operations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"operations.d.ts","sourceRoot":"","sources":["../src/operations.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,107 @@
1
+ /**
2
+ * Running monitors in production: several logs at once, watchlists of agents, anchor-lag
3
+ * alerts, alert sinks, split-view comparison with peer monitors, signed attestations of
4
+ * what was checked, bundle completeness, a serverless entry point, a static status page,
5
+ * and a signed daily report for a supervisor.
6
+ */
7
+ import { signObject, verifyAuditBundle, verifySTH } from '@zanii/core';
8
+ import { checkOnce } from './index.js';
9
+ /** Check several logs in one pass. Each keeps its own state; a failure on one does not stop the others. */
10
+ export async function checkMany(servers, states, fetchImpl) {
11
+ const out = {};
12
+ await Promise.all(servers.map(async (s) => {
13
+ try {
14
+ out[s] = await checkOnce(s, states[s], fetchImpl);
15
+ }
16
+ catch (err) {
17
+ out[s] = { ok: false, error: err.message };
18
+ }
19
+ }));
20
+ return out;
21
+ }
22
+ /** New receipts by watched agents since the last poll (from the log's recent feed). */
23
+ export async function watchlistOnce(server, dids, seen, fetchImpl = (u, i) => fetch(u, i)) {
24
+ const r = await fetchImpl(`${server.replace(/\/$/, '')}/v1/recent?limit=100`);
25
+ if (!r.ok)
26
+ throw new Error(`/v1/recent → ${r.status}`);
27
+ const { receipts } = (await r.json());
28
+ const hits = receipts.filter((x) => {
29
+ const parties = x.receipt.agent_id ? [x.receipt.agent_id] : (x.receipt.body?.participants ?? [x.receipt.initiator?.agent_id, x.receipt.responder?.agent_id]).filter(Boolean);
30
+ const key = x.hash ?? JSON.stringify(x.receipt).slice(0, 80);
31
+ if (seen.has(key) || !parties.some((p) => dids.includes(p)))
32
+ return false;
33
+ seen.add(key);
34
+ return true;
35
+ });
36
+ return hits.map((h) => ({ hash: h.hash ?? null, agent: h.receipt.agent_id ?? null, target: h.receipt.target ?? h.receipt.body?.target ?? null, ts: h.receipt.ts ?? h.receipt.body?.ts ?? null }));
37
+ }
38
+ /** How far on-chain anchoring lags the log, with an alert above the threshold. */
39
+ export async function anchorLag(server, thresholdMs, fetchImpl = (u, i) => fetch(u, i), now = Date.now()) {
40
+ const r = await fetchImpl(`${server.replace(/\/$/, '')}/v1/stats`);
41
+ if (!r.ok)
42
+ throw new Error(`/v1/stats → ${r.status}`);
43
+ const s = (await r.json());
44
+ if (!s.last_anchor_ts)
45
+ return { lagMs: null, alert: true, reason: 'no anchor yet' };
46
+ const lagMs = now - Date.parse(s.last_anchor_ts);
47
+ return { lagMs, alert: lagMs > thresholdMs, reason: lagMs > thresholdMs ? `last anchor ${Math.round(lagMs / 60_000)} min ago` : null };
48
+ }
49
+ /** Post violations to a Slack incoming webhook. */
50
+ export function slackSink(webhookUrl, fetchImpl = (u, i) => fetch(u, i)) {
51
+ return async (r) => {
52
+ await fetchImpl(webhookUrl, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ text: `Zanii monitor: ${r.server ?? 'log'} ${r.ok ? 'OK' : 'VIOLATION'} at size ${r.size}${r.violations.length ? `\n${r.violations.join('\n')}` : ''}` }) });
53
+ };
54
+ }
55
+ /** Post the full result as JSON to any webhook (PagerDuty, Opsgenie, your own). */
56
+ export function webhookSink(url, fetchImpl = (u, i) => fetch(u, i)) {
57
+ return async (r) => {
58
+ await fetchImpl(url, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify(r) });
59
+ };
60
+ }
61
+ /** Send to every sink; one failing sink does not stop the others. */
62
+ export async function alertAll(r, sinks) {
63
+ const results = await Promise.allSettled(sinks.map((s) => s(r)));
64
+ return results.map((x) => x.status);
65
+ }
66
+ /**
67
+ * Compare our view of a log with views other monitors saw. Two valid heads for the same
68
+ * size with different roots is a split view: the log showed different histories.
69
+ */
70
+ export function compareViews(ours, theirs) {
71
+ const splits = theirs.filter((t) => verifySTH(t) && t.log_id === ours.log_id && t.size === ours.size && t.root !== ours.root);
72
+ return { consistent: splits.length === 0 && verifySTH(ours), splits };
73
+ }
74
+ /** A monitor's signed statement of what it checked. Collected from independent monitors, these become witness evidence. */
75
+ export function attestCheck(server, r, monitorPrivateKey, ts = new Date().toISOString()) {
76
+ return signObject({ v: 1, type: 'monitor.attestation', server, size: r.size, root: r.root, ok: r.ok, ts }, monitorPrivateKey);
77
+ }
78
+ /** Is an agent's exported history complete, with no gaps in its chain? */
79
+ export function completenessAudit(bundle) {
80
+ const r = verifyAuditBundle(bundle);
81
+ const chain = r.checks.find((c) => /chain/i.test(c.label));
82
+ return { complete: !!chain?.ok && r.ok, receipts: r.stats.receipts, detail: chain?.detail ?? null, failed: r.checks.filter((c) => !c.ok).map((c) => c.label) };
83
+ }
84
+ /**
85
+ * One scheduled check for serverless platforms (a cron trigger): load the last state,
86
+ * check, save the new state, alert on violation.
87
+ */
88
+ export async function scheduledCheck(opts) {
89
+ const r = await checkOnce(opts.server, await opts.getState(), opts.fetchImpl);
90
+ if (r.ok)
91
+ await opts.putState(r.state);
92
+ else
93
+ await alertAll({ ...r, server: opts.server }, opts.sinks ?? []);
94
+ return r;
95
+ }
96
+ const esc = (s) => s.replace(/[&<>"]/g, (c) => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;' })[c]);
97
+ /** A static status page from recent results (no scripts). */
98
+ export function statusPage(history) {
99
+ const rows = [...history].reverse().slice(0, 200).map((h) => `<tr><td>${esc(h.ts)}</td><td>${esc(h.server)}</td><td>${h.ok ? 'OK' : '<strong>VIOLATION</strong>'}</td><td>${h.size}</td></tr>`).join('');
100
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8"><title>Log monitor status</title></head><body><h1>Log monitor status</h1><table><tr><th>Checked</th><th>Log</th><th>Result</th><th>Size</th></tr>${rows}</table></body></html>`;
101
+ }
102
+ /** A signed daily summary for a supervisor. */
103
+ export function dailyReport(server, day, results, monitorPrivateKey) {
104
+ const sizes = results.map((r) => r.size);
105
+ return signObject({ v: 1, type: 'monitor.daily', server, day, checks: results.length, violations: results.filter((r) => !r.ok).length, firstSize: sizes[0] ?? 0, lastSize: sizes.at(-1) ?? 0, ts: new Date().toISOString() }, monitorPrivateKey);
106
+ }
107
+ //# sourceMappingURL=operations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"operations.js","sourceRoot":"","sources":["../src/operations.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zanii/monitor",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "Independent Zanii log monitor: continuously verify the transparency log is append-only (consistency proofs) and that anchored checkpoints hold. Makes 'trust no one' operational.",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://ledger.zanii.agency",
@@ -30,13 +30,13 @@
30
30
  },
31
31
  "dependencies": {
32
32
  "@noble/hashes": "^1.7.1",
33
- "@zanii/core": "0.4.0"
33
+ "@zanii/core": "^0.5.4"
34
34
  },
35
35
  "devDependencies": {
36
36
  "@types/node": "^26.1.0",
37
37
  "typescript": "^5.8.2",
38
38
  "vitest": "^3.0.9",
39
- "@zanii/testing": "0.1.1"
39
+ "@zanii/testing": "0.1.2"
40
40
  },
41
41
  "scripts": {
42
42
  "build": "tsc -p tsconfig.build.json",
package/src/index.ts CHANGED
@@ -143,3 +143,4 @@ export async function monitor(server: string, opts: MonitorOptions = {}): Promis
143
143
  await new Promise((res) => setTimeout(res, interval));
144
144
  }
145
145
  }
146
+ export * from './operations.js';
@@ -0,0 +1,118 @@
1
+ /**
2
+ * Running monitors in production: several logs at once, watchlists of agents, anchor-lag
3
+ * alerts, alert sinks, split-view comparison with peer monitors, signed attestations of
4
+ * what was checked, bundle completeness, a serverless entry point, a static status page,
5
+ * and a signed daily report for a supervisor.
6
+ */
7
+ import { signObject, verifyAuditBundle, verifySTH, type AuditBundle, type SignedObject, type SignedTreeHead } from '@zanii/core';
8
+ import { checkOnce, type FetchLike, type MonitorResult, type MonitorState } from './index.js';
9
+
10
+ /** Check several logs in one pass. Each keeps its own state; a failure on one does not stop the others. */
11
+ export async function checkMany(servers: string[], states: Record<string, MonitorState | undefined>, fetchImpl?: FetchLike) {
12
+ const out: Record<string, MonitorResult | { ok: false; error: string }> = {};
13
+ await Promise.all(servers.map(async (s) => {
14
+ try {
15
+ out[s] = await checkOnce(s, states[s], fetchImpl);
16
+ } catch (err) {
17
+ out[s] = { ok: false, error: (err as Error).message };
18
+ }
19
+ }));
20
+ return out;
21
+ }
22
+
23
+ /** New receipts by watched agents since the last poll (from the log's recent feed). */
24
+ export async function watchlistOnce(server: string, dids: string[], seen: Set<string>, fetchImpl: FetchLike = (u, i) => fetch(u, i)) {
25
+ const r = await fetchImpl(`${server.replace(/\/$/, '')}/v1/recent?limit=100`);
26
+ if (!r.ok) throw new Error(`/v1/recent → ${r.status}`);
27
+ const { receipts } = (await r.json()) as { receipts: Array<{ hash?: string; receipt: Record<string, any> }> };
28
+ const hits = receipts.filter((x) => {
29
+ const parties: string[] = x.receipt.agent_id ? [x.receipt.agent_id] : (x.receipt.body?.participants ?? [x.receipt.initiator?.agent_id, x.receipt.responder?.agent_id]).filter(Boolean);
30
+ const key = x.hash ?? JSON.stringify(x.receipt).slice(0, 80);
31
+ if (seen.has(key) || !parties.some((p) => dids.includes(p))) return false;
32
+ seen.add(key);
33
+ return true;
34
+ });
35
+ return hits.map((h) => ({ hash: h.hash ?? null, agent: h.receipt.agent_id ?? null, target: h.receipt.target ?? h.receipt.body?.target ?? null, ts: h.receipt.ts ?? h.receipt.body?.ts ?? null }));
36
+ }
37
+
38
+ /** How far on-chain anchoring lags the log, with an alert above the threshold. */
39
+ export async function anchorLag(server: string, thresholdMs: number, fetchImpl: FetchLike = (u, i) => fetch(u, i), now = Date.now()) {
40
+ const r = await fetchImpl(`${server.replace(/\/$/, '')}/v1/stats`);
41
+ if (!r.ok) throw new Error(`/v1/stats → ${r.status}`);
42
+ const s = (await r.json()) as { last_anchor_ts?: string | null; last_receipt_ts?: string | null };
43
+ if (!s.last_anchor_ts) return { lagMs: null, alert: true, reason: 'no anchor yet' };
44
+ const lagMs = now - Date.parse(s.last_anchor_ts);
45
+ return { lagMs, alert: lagMs > thresholdMs, reason: lagMs > thresholdMs ? `last anchor ${Math.round(lagMs / 60_000)} min ago` : null };
46
+ }
47
+
48
+ export type AlertSink = (r: MonitorResult & { server?: string }) => Promise<void>;
49
+
50
+ /** Post violations to a Slack incoming webhook. */
51
+ export function slackSink(webhookUrl: string, fetchImpl: FetchLike = (u, i) => fetch(u, i)): AlertSink {
52
+ return async (r) => {
53
+ await fetchImpl(webhookUrl, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ text: `Zanii monitor: ${r.server ?? 'log'} ${r.ok ? 'OK' : 'VIOLATION'} at size ${r.size}${r.violations.length ? `\n${r.violations.join('\n')}` : ''}` }) });
54
+ };
55
+ }
56
+
57
+ /** Post the full result as JSON to any webhook (PagerDuty, Opsgenie, your own). */
58
+ export function webhookSink(url: string, fetchImpl: FetchLike = (u, i) => fetch(u, i)): AlertSink {
59
+ return async (r) => {
60
+ await fetchImpl(url, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify(r) });
61
+ };
62
+ }
63
+
64
+ /** Send to every sink; one failing sink does not stop the others. */
65
+ export async function alertAll(r: MonitorResult & { server?: string }, sinks: AlertSink[]) {
66
+ const results = await Promise.allSettled(sinks.map((s) => s(r)));
67
+ return results.map((x) => x.status);
68
+ }
69
+
70
+ /**
71
+ * Compare our view of a log with views other monitors saw. Two valid heads for the same
72
+ * size with different roots is a split view: the log showed different histories.
73
+ */
74
+ export function compareViews(ours: SignedTreeHead, theirs: SignedTreeHead[]) {
75
+ const splits = theirs.filter((t) => verifySTH(t) && t.log_id === ours.log_id && t.size === ours.size && t.root !== ours.root);
76
+ return { consistent: splits.length === 0 && verifySTH(ours), splits };
77
+ }
78
+
79
+ export type MonitorAttestation = SignedObject<{ v: 1; type: 'monitor.attestation'; server: string; size: number; root: string; ok: boolean; ts: string }>;
80
+
81
+ /** A monitor's signed statement of what it checked. Collected from independent monitors, these become witness evidence. */
82
+ export function attestCheck(server: string, r: MonitorResult, monitorPrivateKey: Uint8Array, ts = new Date().toISOString()): MonitorAttestation {
83
+ return signObject({ v: 1 as const, type: 'monitor.attestation' as const, server, size: r.size, root: r.root, ok: r.ok, ts }, monitorPrivateKey);
84
+ }
85
+
86
+ /** Is an agent's exported history complete, with no gaps in its chain? */
87
+ export function completenessAudit(bundle: AuditBundle) {
88
+ const r = verifyAuditBundle(bundle);
89
+ const chain = r.checks.find((c) => /chain/i.test(c.label));
90
+ return { complete: !!chain?.ok && r.ok, receipts: r.stats.receipts, detail: chain?.detail ?? null, failed: r.checks.filter((c) => !c.ok).map((c) => c.label) };
91
+ }
92
+
93
+ /**
94
+ * One scheduled check for serverless platforms (a cron trigger): load the last state,
95
+ * check, save the new state, alert on violation.
96
+ */
97
+ export async function scheduledCheck(opts: { server: string; getState: () => Promise<MonitorState | undefined>; putState: (s: MonitorState) => Promise<void>; sinks?: AlertSink[]; fetchImpl?: FetchLike }) {
98
+ const r = await checkOnce(opts.server, await opts.getState(), opts.fetchImpl);
99
+ if (r.ok) await opts.putState(r.state);
100
+ else await alertAll({ ...r, server: opts.server }, opts.sinks ?? []);
101
+ return r;
102
+ }
103
+
104
+ const esc = (s: string) => s.replace(/[&<>"]/g, (c) => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;' })[c]!);
105
+
106
+ /** A static status page from recent results (no scripts). */
107
+ export function statusPage(history: Array<{ server: string; ts: string; ok: boolean; size: number }>): string {
108
+ const rows = [...history].reverse().slice(0, 200).map((h) => `<tr><td>${esc(h.ts)}</td><td>${esc(h.server)}</td><td>${h.ok ? 'OK' : '<strong>VIOLATION</strong>'}</td><td>${h.size}</td></tr>`).join('');
109
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8"><title>Log monitor status</title></head><body><h1>Log monitor status</h1><table><tr><th>Checked</th><th>Log</th><th>Result</th><th>Size</th></tr>${rows}</table></body></html>`;
110
+ }
111
+
112
+ export type DailyReport = SignedObject<{ v: 1; type: 'monitor.daily'; server: string; day: string; checks: number; violations: number; firstSize: number; lastSize: number; ts: string }>;
113
+
114
+ /** A signed daily summary for a supervisor. */
115
+ export function dailyReport(server: string, day: string, results: MonitorResult[], monitorPrivateKey: Uint8Array): DailyReport {
116
+ const sizes = results.map((r) => r.size);
117
+ return signObject({ v: 1 as const, type: 'monitor.daily' as const, server, day, checks: results.length, violations: results.filter((r) => !r.ok).length, firstSize: sizes[0] ?? 0, lastSize: sizes.at(-1) ?? 0, ts: new Date().toISOString() }, monitorPrivateKey);
118
+ }