@shield-agent/kya 0.32.9 → 0.33.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/.cursor-plugin/plugin.json +1 -1
- package/.mcp.json +1 -1
- package/LIMITATIONS.md +2 -2
- package/README.md +178 -12
- package/amp/settings.example.json +1 -1
- package/claude/claude_desktop_config.example.json +1 -1
- package/cline/cline_mcp_settings.example.json +1 -1
- package/copilot/mcp-config.example.json +1 -1
- package/data/iocs.json +17 -0
- package/dist/cli.d.ts +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +149 -16
- package/dist/cli.js.map +1 -1
- package/dist/commands/connect.d.ts +1 -1
- package/dist/commands/connect.d.ts.map +1 -1
- package/dist/commands/connect.js +11 -3
- package/dist/commands/connect.js.map +1 -1
- package/dist/commands/dash.d.ts.map +1 -1
- package/dist/commands/dash.js +25 -1
- package/dist/commands/dash.js.map +1 -1
- package/dist/commands/doctor.d.ts +8 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +26 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/eval-tool.d.ts +3 -0
- package/dist/commands/eval-tool.d.ts.map +1 -1
- package/dist/commands/eval-tool.js +2 -1
- package/dist/commands/eval-tool.js.map +1 -1
- package/dist/commands/export.d.ts +33 -0
- package/dist/commands/export.d.ts.map +1 -0
- package/dist/commands/export.js +121 -0
- package/dist/commands/export.js.map +1 -0
- package/dist/commands/hook.d.ts.map +1 -1
- package/dist/commands/hook.js +120 -26
- package/dist/commands/hook.js.map +1 -1
- package/dist/commands/hosted-hook.d.ts +8 -1
- package/dist/commands/hosted-hook.d.ts.map +1 -1
- package/dist/commands/hosted-hook.js +15 -5
- package/dist/commands/hosted-hook.js.map +1 -1
- package/dist/commands/map.d.ts +21 -0
- package/dist/commands/map.d.ts.map +1 -0
- package/dist/commands/map.js +76 -0
- package/dist/commands/map.js.map +1 -0
- package/dist/commands/notify-flush.d.ts.map +1 -1
- package/dist/commands/notify-flush.js +7 -1
- package/dist/commands/notify-flush.js.map +1 -1
- package/dist/commands/posture.d.ts +21 -0
- package/dist/commands/posture.d.ts.map +1 -0
- package/dist/commands/posture.js +177 -0
- package/dist/commands/posture.js.map +1 -0
- package/dist/commands/receipt-serve.d.ts +7 -0
- package/dist/commands/receipt-serve.d.ts.map +1 -1
- package/dist/commands/receipt-serve.js +50 -0
- package/dist/commands/receipt-serve.js.map +1 -1
- package/dist/commands/start.d.ts.map +1 -1
- package/dist/commands/start.js +5 -1
- package/dist/commands/start.js.map +1 -1
- package/dist/commands/team.d.ts.map +1 -1
- package/dist/commands/team.js +30 -11
- package/dist/commands/team.js.map +1 -1
- package/dist/commands/wire-hooks.d.ts +5 -1
- package/dist/commands/wire-hooks.d.ts.map +1 -1
- package/dist/commands/wire-hooks.js +23 -8
- package/dist/commands/wire-hooks.js.map +1 -1
- package/dist/commands/wrap.d.ts +38 -1
- package/dist/commands/wrap.d.ts.map +1 -1
- package/dist/commands/wrap.js +82 -6
- package/dist/commands/wrap.js.map +1 -1
- package/dist/daily-slot.d.ts +2 -0
- package/dist/daily-slot.d.ts.map +1 -0
- package/dist/daily-slot.js +29 -0
- package/dist/daily-slot.js.map +1 -0
- package/dist/dash/dash.d.ts.map +1 -1
- package/dist/dash/dash.js +10 -0
- package/dist/dash/dash.js.map +1 -1
- package/dist/dash/entitlement.d.ts +1 -1
- package/dist/dash/entitlement.d.ts.map +1 -1
- package/dist/dash/entitlement.js +1 -0
- package/dist/dash/entitlement.js.map +1 -1
- package/dist/dash/input.d.ts +1 -1
- package/dist/dash/input.d.ts.map +1 -1
- package/dist/dash/input.js +3 -0
- package/dist/dash/input.js.map +1 -1
- package/dist/dash/render.js +1 -1
- package/dist/dash/render.js.map +1 -1
- package/dist/dash/screens/free.js +1 -1
- package/dist/dash/screens/free.js.map +1 -1
- package/dist/device-id.d.ts +5 -0
- package/dist/device-id.d.ts.map +1 -0
- package/dist/device-id.js +78 -0
- package/dist/device-id.js.map +1 -0
- package/dist/fs-atomic.d.ts +9 -3
- package/dist/fs-atomic.d.ts.map +1 -1
- package/dist/fs-atomic.js +17 -11
- package/dist/fs-atomic.js.map +1 -1
- package/dist/gate/config-gen.d.ts +26 -2
- package/dist/gate/config-gen.d.ts.map +1 -1
- package/dist/gate/config-gen.js +53 -4
- package/dist/gate/config-gen.js.map +1 -1
- package/dist/gate/otlp-receiver.d.ts.map +1 -1
- package/dist/gate/otlp-receiver.js +3 -1
- package/dist/gate/otlp-receiver.js.map +1 -1
- package/dist/guard-pack.d.ts +58 -0
- package/dist/guard-pack.d.ts.map +1 -0
- package/dist/guard-pack.js +753 -0
- package/dist/guard-pack.js.map +1 -0
- package/dist/ioc/exec.d.ts +19 -0
- package/dist/ioc/exec.d.ts.map +1 -0
- package/dist/ioc/exec.js +49 -0
- package/dist/ioc/exec.js.map +1 -0
- package/dist/ioc/format.d.ts +4 -0
- package/dist/ioc/format.d.ts.map +1 -0
- package/dist/ioc/format.js +23 -0
- package/dist/ioc/format.js.map +1 -0
- package/dist/ioc/list.d.ts +29 -0
- package/dist/ioc/list.d.ts.map +1 -0
- package/dist/ioc/list.js +25 -0
- package/dist/ioc/list.js.map +1 -0
- package/dist/ioc/result.d.ts +18 -0
- package/dist/ioc/result.d.ts.map +1 -0
- package/dist/ioc/result.js +26 -0
- package/dist/ioc/result.js.map +1 -0
- package/dist/ioc/scan.d.ts +21 -0
- package/dist/ioc/scan.d.ts.map +1 -0
- package/dist/ioc/scan.js +247 -0
- package/dist/ioc/scan.js.map +1 -0
- package/dist/ioc/spawn.d.ts +26 -0
- package/dist/ioc/spawn.d.ts.map +1 -0
- package/dist/ioc/spawn.js +52 -0
- package/dist/ioc/spawn.js.map +1 -0
- package/dist/map/build.d.ts +58 -0
- package/dist/map/build.d.ts.map +1 -0
- package/dist/map/build.js +439 -0
- package/dist/map/build.js.map +1 -0
- package/dist/map/heat.d.ts +44 -0
- package/dist/map/heat.d.ts.map +1 -0
- package/dist/map/heat.js +96 -0
- package/dist/map/heat.js.map +1 -0
- package/dist/map/load.d.ts +38 -0
- package/dist/map/load.d.ts.map +1 -0
- package/dist/map/load.js +38 -0
- package/dist/map/load.js.map +1 -0
- package/dist/map/page.d.ts +90 -0
- package/dist/map/page.d.ts.map +1 -0
- package/dist/map/page.js +374 -0
- package/dist/map/page.js.map +1 -0
- package/dist/map/target-class.d.ts +22 -0
- package/dist/map/target-class.d.ts.map +1 -0
- package/dist/map/target-class.js +151 -0
- package/dist/map/target-class.js.map +1 -0
- package/dist/map/types.d.ts +102 -0
- package/dist/map/types.d.ts.map +1 -0
- package/dist/map/types.js +3 -0
- package/dist/map/types.js.map +1 -0
- package/dist/mcp/protocol.d.ts.map +1 -1
- package/dist/mcp/protocol.js +16 -5
- package/dist/mcp/protocol.js.map +1 -1
- package/dist/never-code.d.ts +7 -0
- package/dist/never-code.d.ts.map +1 -0
- package/dist/never-code.js +9 -0
- package/dist/never-code.js.map +1 -0
- package/dist/never-list-input.d.ts +48 -12
- package/dist/never-list-input.d.ts.map +1 -1
- package/dist/never-list-input.js +696 -29
- package/dist/never-list-input.js.map +1 -1
- package/dist/notify/dispatch.d.ts +4 -0
- package/dist/notify/dispatch.d.ts.map +1 -1
- package/dist/notify/dispatch.js +3 -1
- package/dist/notify/dispatch.js.map +1 -1
- package/dist/offline-evaluate.d.ts +26 -1
- package/dist/offline-evaluate.d.ts.map +1 -1
- package/dist/offline-evaluate.js +33 -4
- package/dist/offline-evaluate.js.map +1 -1
- package/dist/otel/exporter.d.ts +15 -2
- package/dist/otel/exporter.d.ts.map +1 -1
- package/dist/otel/exporter.js +52 -6
- package/dist/otel/exporter.js.map +1 -1
- package/dist/otel/map-attrs-optin.d.ts +39 -0
- package/dist/otel/map-attrs-optin.d.ts.map +1 -0
- package/dist/otel/map-attrs-optin.js +109 -0
- package/dist/otel/map-attrs-optin.js.map +1 -0
- package/dist/parse-args.d.ts +2 -0
- package/dist/parse-args.d.ts.map +1 -1
- package/dist/parse-args.js +4 -2
- package/dist/parse-args.js.map +1 -1
- package/dist/posture/card.d.ts +26 -0
- package/dist/posture/card.d.ts.map +1 -0
- package/dist/posture/card.js +46 -0
- package/dist/posture/card.js.map +1 -0
- package/dist/posture/collect.d.ts +19 -0
- package/dist/posture/collect.d.ts.map +1 -0
- package/dist/posture/collect.js +182 -0
- package/dist/posture/collect.js.map +1 -0
- package/dist/posture/send.d.ts +24 -0
- package/dist/posture/send.d.ts.map +1 -0
- package/dist/posture/send.js +162 -0
- package/dist/posture/send.js.map +1 -0
- package/dist/posture/spawn.d.ts +20 -0
- package/dist/posture/spawn.d.ts.map +1 -0
- package/dist/posture/spawn.js +33 -0
- package/dist/posture/spawn.js.map +1 -0
- package/dist/posture/store.d.ts +34 -0
- package/dist/posture/store.d.ts.map +1 -0
- package/dist/posture/store.js +107 -0
- package/dist/posture/store.js.map +1 -0
- package/dist/posture/validate.d.ts +33 -0
- package/dist/posture/validate.d.ts.map +1 -0
- package/dist/posture/validate.js +232 -0
- package/dist/posture/validate.js.map +1 -0
- package/dist/project-policy.d.ts +23 -0
- package/dist/project-policy.d.ts.map +1 -0
- package/dist/project-policy.js +95 -0
- package/dist/project-policy.js.map +1 -0
- package/dist/receipt/daemon.d.ts +9 -9
- package/dist/receipt/daemon.d.ts.map +1 -1
- package/dist/receipt/daemon.js +26 -11
- package/dist/receipt/daemon.js.map +1 -1
- package/dist/receipt/embeddings.d.ts +28 -10
- package/dist/receipt/embeddings.d.ts.map +1 -1
- package/dist/receipt/embeddings.js +221 -35
- package/dist/receipt/embeddings.js.map +1 -1
- package/dist/receipt/gate-page.d.ts.map +1 -1
- package/dist/receipt/gate-page.js +5 -22
- package/dist/receipt/gate-page.js.map +1 -1
- package/dist/receipt/live-server.d.ts +8 -0
- package/dist/receipt/live-server.d.ts.map +1 -1
- package/dist/receipt/live-server.js +136 -4
- package/dist/receipt/live-server.js.map +1 -1
- package/dist/receipt/render-receipt.d.ts +7 -1
- package/dist/receipt/render-receipt.d.ts.map +1 -1
- package/dist/receipt/render-receipt.js +118 -13
- package/dist/receipt/render-receipt.js.map +1 -1
- package/dist/receipt/search.d.ts +5 -0
- package/dist/receipt/search.d.ts.map +1 -1
- package/dist/receipt/search.js +23 -2
- package/dist/receipt/search.js.map +1 -1
- package/dist/receipt/semantic-setup.d.ts +21 -0
- package/dist/receipt/semantic-setup.d.ts.map +1 -0
- package/dist/receipt/semantic-setup.js +111 -0
- package/dist/receipt/semantic-setup.js.map +1 -0
- package/dist/receipt/semantic-status.d.ts +7 -0
- package/dist/receipt/semantic-status.d.ts.map +1 -0
- package/dist/receipt/semantic-status.js +26 -0
- package/dist/receipt/semantic-status.js.map +1 -0
- package/dist/sdk/govern.d.ts.map +1 -1
- package/dist/sdk/govern.js +7 -3
- package/dist/sdk/govern.js.map +1 -1
- package/dist/telemetry.d.ts.map +1 -1
- package/dist/telemetry.js +3 -23
- package/dist/telemetry.js.map +1 -1
- package/dist/trail-map-fields.d.ts +10 -0
- package/dist/trail-map-fields.d.ts.map +1 -0
- package/dist/trail-map-fields.js +53 -0
- package/dist/trail-map-fields.js.map +1 -0
- package/dist/trail-summary.d.ts.map +1 -1
- package/dist/trail-summary.js +11 -3
- package/dist/trail-summary.js.map +1 -1
- package/dist/trail.d.ts +9 -1
- package/dist/trail.d.ts.map +1 -1
- package/dist/trail.js +24 -1
- package/dist/trail.js.map +1 -1
- package/droid/README.md +1 -1
- package/droid/mcp.example.json +1 -1
- package/gemini/settings.example.json +1 -1
- package/grok/README.md +1 -1
- package/kilo/kilo.example.json +1 -1
- package/kimi/mcp.example.json +1 -1
- package/kiro/mcp.example.json +1 -1
- package/manifest.json +1 -1
- package/mastracode/mcp.example.json +1 -1
- package/mcp.json +1 -1
- package/openai/codex.config.example.toml +1 -1
- package/opencode/opencode.example.json +1 -1
- package/package.json +8 -4
- package/qwen/settings.example.json +1 -1
- package/server.json +2 -2
- package/vendor/cytoscape/LICENSE +19 -0
- package/vendor/cytoscape/README.md +7 -0
- package/vendor/cytoscape/cytoscape.min.js +31 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { TrailEventLike, Verdicts } from "./types.js";
|
|
2
|
+
export interface HeatOptions {
|
|
3
|
+
/** Window end. Without it the latest valid row is used, so the builder reads no clock. */
|
|
4
|
+
now?: Date;
|
|
5
|
+
/** Calendar days ending on the day of `now`. Default 7. */
|
|
6
|
+
days?: number;
|
|
7
|
+
/** Offset east of UTC in minutes (EET is 120). Default 0. */
|
|
8
|
+
tzOffsetMinutes?: number;
|
|
9
|
+
}
|
|
10
|
+
export interface WhenHeat {
|
|
11
|
+
/** `YYYY-MM-DD`, oldest first. */
|
|
12
|
+
days: string[];
|
|
13
|
+
/** 0 to 23. */
|
|
14
|
+
hours: number[];
|
|
15
|
+
/** Counts: cells[dayIndex][hour]. */
|
|
16
|
+
cells: number[][];
|
|
17
|
+
/** Verdict buckets per cell: verdictCells[dayIndex][hour].deny is the deny count. */
|
|
18
|
+
verdictCells: Verdicts[][];
|
|
19
|
+
/** Largest single cell count, for the colour scale. */
|
|
20
|
+
max: number;
|
|
21
|
+
}
|
|
22
|
+
export interface WhereRow extends Verdicts {
|
|
23
|
+
class: string;
|
|
24
|
+
family: string;
|
|
25
|
+
total: number;
|
|
26
|
+
/** Members folded into an "other" row. Absent on shown rows. */
|
|
27
|
+
grouped?: number;
|
|
28
|
+
}
|
|
29
|
+
export interface WhereHeat {
|
|
30
|
+
rows: WhereRow[];
|
|
31
|
+
/** Largest single bucket count across rows, for the colour scale. */
|
|
32
|
+
max: number;
|
|
33
|
+
}
|
|
34
|
+
export interface Heat {
|
|
35
|
+
when: WhenHeat;
|
|
36
|
+
where: WhereHeat;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Two views from one trail. Pure: same rows and options give the same output.
|
|
40
|
+
* `when`: counts per calendar day and hour of day. `where`: counts per target class by verdict.
|
|
41
|
+
* Rows outside the window (after `now`, or before the first day) are excluded.
|
|
42
|
+
*/
|
|
43
|
+
export declare function buildHeat(events: Iterable<TrailEventLike>, opts?: HeatOptions): Heat;
|
|
44
|
+
//# sourceMappingURL=heat.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"heat.d.ts","sourceRoot":"","sources":["../../src/map/heat.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3D,MAAM,WAAW,WAAW;IAC1B,0FAA0F;IAC1F,GAAG,CAAC,EAAE,IAAI,CAAC;IACX,2DAA2D;IAC3D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,6DAA6D;IAC7D,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,QAAQ;IACvB,kCAAkC;IAClC,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,eAAe;IACf,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,qCAAqC;IACrC,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC;IAClB,qFAAqF;IACrF,YAAY,EAAE,QAAQ,EAAE,EAAE,CAAC;IAC3B,uDAAuD;IACvD,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,QAAS,SAAQ,QAAQ;IACxC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,gEAAgE;IAChE,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,QAAQ,EAAE,CAAC;IACjB,qEAAqE;IACrE,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,IAAI;IACnB,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE,SAAS,CAAC;CAClB;AAeD;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,QAAQ,CAAC,cAAc,CAAC,EAAE,IAAI,GAAE,WAAgB,GAAG,IAAI,CA4CxF"}
|
package/dist/map/heat.js
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { bucketOf, isTrailRow, targetOf } from "./build.js";
|
|
2
|
+
const DAY_MS = 86_400_000;
|
|
3
|
+
const HOUR_MS = 3_600_000;
|
|
4
|
+
/** Schema section 7: top 40 targets, plus always-shown deny, hold and secret. */
|
|
5
|
+
const TOP_TARGETS = 40;
|
|
6
|
+
function zeroVerdicts() {
|
|
7
|
+
return { allow: 0, deny: 0, hold: 0, observed: 0 };
|
|
8
|
+
}
|
|
9
|
+
function addTo(v, b) {
|
|
10
|
+
v[b] += 1;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Two views from one trail. Pure: same rows and options give the same output.
|
|
14
|
+
* `when`: counts per calendar day and hour of day. `where`: counts per target class by verdict.
|
|
15
|
+
* Rows outside the window (after `now`, or before the first day) are excluded.
|
|
16
|
+
*/
|
|
17
|
+
export function buildHeat(events, opts = {}) {
|
|
18
|
+
const days = opts.days ?? 7;
|
|
19
|
+
if (!Number.isInteger(days) || days < 1)
|
|
20
|
+
throw new Error("buildHeat: days must be a positive integer");
|
|
21
|
+
const off = (opts.tzOffsetMinutes ?? 0) * 60_000;
|
|
22
|
+
const hours = Array.from({ length: 24 }, (_, i) => i);
|
|
23
|
+
const rows = [...events].filter(isTrailRow);
|
|
24
|
+
const nowMs = opts.now !== undefined ? opts.now.getTime() : rows.reduce((m, e) => Math.max(m, Date.parse(e.ts)), -Infinity);
|
|
25
|
+
if (!Number.isFinite(nowMs))
|
|
26
|
+
return { when: { days: [], hours, cells: [], verdictCells: [], max: 0 }, where: { rows: [], max: 0 } };
|
|
27
|
+
// All day arithmetic runs on local-offset milliseconds, so it never reads the host time zone.
|
|
28
|
+
const lastStart = Math.floor((nowMs + off) / DAY_MS) * DAY_MS;
|
|
29
|
+
const firstStart = lastStart - (days - 1) * DAY_MS;
|
|
30
|
+
const windowStart = firstStart - off;
|
|
31
|
+
const dayList = Array.from({ length: days }, (_, i) => new Date(firstStart + i * DAY_MS).toISOString().slice(0, 10));
|
|
32
|
+
const cells = dayList.map(() => new Array(24).fill(0));
|
|
33
|
+
const verdictCells = dayList.map(() => Array.from({ length: 24 }, zeroVerdicts));
|
|
34
|
+
const targets = new Map();
|
|
35
|
+
for (const e of rows) {
|
|
36
|
+
const ms = Date.parse(e.ts);
|
|
37
|
+
if (ms < windowStart || ms > nowMs)
|
|
38
|
+
continue;
|
|
39
|
+
const local = ms + off;
|
|
40
|
+
const d = Math.floor((local - firstStart) / DAY_MS);
|
|
41
|
+
const h = Math.floor((((local % DAY_MS) + DAY_MS) % DAY_MS) / HOUR_MS);
|
|
42
|
+
const b = bucketOf(e);
|
|
43
|
+
cells[d][h] += 1;
|
|
44
|
+
addTo(verdictCells[d][h], b);
|
|
45
|
+
const t = targetOf(e);
|
|
46
|
+
let r = targets.get(t.cls);
|
|
47
|
+
if (!r) {
|
|
48
|
+
r = { family: t.family, v: zeroVerdicts() };
|
|
49
|
+
targets.set(t.cls, r);
|
|
50
|
+
}
|
|
51
|
+
addTo(r.v, b);
|
|
52
|
+
}
|
|
53
|
+
const when = {
|
|
54
|
+
days: dayList,
|
|
55
|
+
hours,
|
|
56
|
+
cells,
|
|
57
|
+
verdictCells,
|
|
58
|
+
max: Math.max(0, ...cells.flat()),
|
|
59
|
+
};
|
|
60
|
+
return { when, where: whereRows(targets) };
|
|
61
|
+
}
|
|
62
|
+
function total(v) {
|
|
63
|
+
return v.allow + v.deny + v.hold + v.observed;
|
|
64
|
+
}
|
|
65
|
+
function bySize(a, b) {
|
|
66
|
+
return b.total - a.total || (a.class < b.class ? -1 : a.class > b.class ? 1 : 0);
|
|
67
|
+
}
|
|
68
|
+
function whereRows(targets) {
|
|
69
|
+
const all = [...targets].map(([cls, r]) => ({ class: cls, family: r.family, ...r.v, total: total(r.v) }));
|
|
70
|
+
all.sort(bySize);
|
|
71
|
+
const rows = [];
|
|
72
|
+
const folded = new Map();
|
|
73
|
+
all.forEach((r, i) => {
|
|
74
|
+
const alwaysShown = r.deny > 0 || r.hold > 0 || r.family === "secret";
|
|
75
|
+
if (i < TOP_TARGETS || alwaysShown) {
|
|
76
|
+
rows.push(r);
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
let g = folded.get(r.family);
|
|
80
|
+
if (!g) {
|
|
81
|
+
g = { class: `other:${r.family}`, family: r.family, allow: 0, deny: 0, hold: 0, observed: 0, total: 0, grouped: 0 };
|
|
82
|
+
folded.set(r.family, g);
|
|
83
|
+
}
|
|
84
|
+
g.allow += r.allow;
|
|
85
|
+
g.deny += r.deny;
|
|
86
|
+
g.hold += r.hold;
|
|
87
|
+
g.observed += r.observed;
|
|
88
|
+
g.total += r.total;
|
|
89
|
+
g.grouped = (g.grouped ?? 0) + 1;
|
|
90
|
+
});
|
|
91
|
+
rows.push(...folded.values());
|
|
92
|
+
rows.sort(bySize);
|
|
93
|
+
const max = Math.max(0, ...rows.flatMap((r) => [r.allow, r.deny, r.hold, r.observed]));
|
|
94
|
+
return { rows, max };
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=heat.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"heat.js","sourceRoot":"","sources":["../../src/map/heat.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Loads the map for one trail: streams the file, filters one session, builds the graph and the heat views.
|
|
3
|
+
* Shared by `kya map` and the live report, so both show the same numbers.
|
|
4
|
+
*/
|
|
5
|
+
import { type TrailRead } from "./build.js";
|
|
6
|
+
import { type Heat } from "./heat.js";
|
|
7
|
+
import type { MapGraph, TrailEventLike } from "./types.js";
|
|
8
|
+
/** The When view is always seven days, so the read covers at least seven. */
|
|
9
|
+
export declare const HEAT_DAYS = 7;
|
|
10
|
+
export interface LoadMapOptions {
|
|
11
|
+
readonly path: string;
|
|
12
|
+
/** Graph window in days. */
|
|
13
|
+
readonly days: number;
|
|
14
|
+
readonly now: Date;
|
|
15
|
+
/** Per-install salt for sessionHash. */
|
|
16
|
+
readonly salt: string;
|
|
17
|
+
readonly session?: string;
|
|
18
|
+
/** Offset east of UTC in minutes, for the When view. */
|
|
19
|
+
readonly tzOffsetMinutes: number;
|
|
20
|
+
}
|
|
21
|
+
export interface LoadedMap {
|
|
22
|
+
readonly graph: MapGraph;
|
|
23
|
+
readonly heat: Heat;
|
|
24
|
+
/** Events in the graph window (after the session filter). */
|
|
25
|
+
readonly windowEvents: number;
|
|
26
|
+
}
|
|
27
|
+
/** Rows of the last `days` days, one session when `session` is set. Shared by `kya map` and `kya export`. */
|
|
28
|
+
export declare function loadTrailEvents(opts: {
|
|
29
|
+
path: string;
|
|
30
|
+
days: number;
|
|
31
|
+
now: Date;
|
|
32
|
+
session?: string;
|
|
33
|
+
}): Promise<{
|
|
34
|
+
read: TrailRead;
|
|
35
|
+
events: TrailEventLike[];
|
|
36
|
+
}>;
|
|
37
|
+
export declare function loadMap(opts: LoadMapOptions): Promise<LoadedMap>;
|
|
38
|
+
//# sourceMappingURL=load.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"load.d.ts","sourceRoot":"","sources":["../../src/map/load.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAA2B,KAAK,SAAS,EAAE,MAAM,YAAY,CAAC;AACrE,OAAO,EAAa,KAAK,IAAI,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE3D,6EAA6E;AAC7E,eAAO,MAAM,SAAS,IAAI,CAAC;AAE3B,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,4BAA4B;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC;IACnB,wCAAwC;IACxC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,wDAAwD;IACxD,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;CAClC;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,6DAA6D;IAC7D,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B;AAcD,6GAA6G;AAC7G,wBAAsB,eAAe,CAAC,IAAI,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,IAAI,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,cAAc,EAAE,CAAA;CAAE,CAAC,CAG/J;AAED,wBAAsB,OAAO,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,SAAS,CAAC,CAWtE"}
|
package/dist/map/load.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Loads the map for one trail: streams the file, filters one session, builds the graph and the heat views.
|
|
3
|
+
* Shared by `kya map` and the live report, so both show the same numbers.
|
|
4
|
+
*/
|
|
5
|
+
import { buildMap, readTrailFile } from "./build.js";
|
|
6
|
+
import { buildHeat } from "./heat.js";
|
|
7
|
+
/** The When view is always seven days, so the read covers at least seven. */
|
|
8
|
+
export const HEAT_DAYS = 7;
|
|
9
|
+
const EMPTY_READ = { events: [], rowsRead: 0, rowsSkipped: 0, rowsOutOfWindow: 0 };
|
|
10
|
+
/** A missing trail is an empty trail. Any other read error is thrown. */
|
|
11
|
+
async function readOrEmpty(path, days, now) {
|
|
12
|
+
try {
|
|
13
|
+
return await readTrailFile(path, { days, now });
|
|
14
|
+
}
|
|
15
|
+
catch (err) {
|
|
16
|
+
if (err?.code === "ENOENT")
|
|
17
|
+
return EMPTY_READ;
|
|
18
|
+
throw err;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/** Rows of the last `days` days, one session when `session` is set. Shared by `kya map` and `kya export`. */
|
|
22
|
+
export async function loadTrailEvents(opts) {
|
|
23
|
+
const read = await readOrEmpty(opts.path, opts.days, opts.now);
|
|
24
|
+
return { read, events: opts.session ? read.events.filter((e) => e.sessionId === opts.session) : read.events };
|
|
25
|
+
}
|
|
26
|
+
export async function loadMap(opts) {
|
|
27
|
+
const { read, events } = await loadTrailEvents({ path: opts.path, days: Math.max(opts.days, HEAT_DAYS), now: opts.now, session: opts.session });
|
|
28
|
+
const graph = buildMap(events, {
|
|
29
|
+
salt: opts.salt,
|
|
30
|
+
now: opts.now,
|
|
31
|
+
days: opts.days,
|
|
32
|
+
read: { rowsRead: read.rowsRead, rowsSkipped: read.rowsSkipped, rowsOutOfWindow: read.rowsOutOfWindow },
|
|
33
|
+
});
|
|
34
|
+
const heat = buildHeat(events, { now: opts.now, days: HEAT_DAYS, tzOffsetMinutes: opts.tzOffsetMinutes });
|
|
35
|
+
const windowEvents = graph.nodes.filter((n) => n.kind === "device").reduce((s, n) => s + n.count, 0);
|
|
36
|
+
return { graph, heat, windowEvents };
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=load.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"load.js","sourceRoot":"","sources":["../../src/map/load.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAkB,MAAM,YAAY,CAAC;AACrE,OAAO,EAAE,SAAS,EAAa,MAAM,WAAW,CAAC;AAGjD,6EAA6E;AAC7E,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,CAAC;AAqB3B,MAAM,UAAU,GAAc,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,eAAe,EAAE,CAAC,EAAE,CAAC;AAE9F,yEAAyE;AACzE,KAAK,UAAU,WAAW,CAAC,IAAY,EAAE,IAAY,EAAE,GAAS;IAC9D,IAAI,CAAC;QACH,OAAO,MAAM,aAAa,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC;IAClD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAK,GAA6B,EAAE,IAAI,KAAK,QAAQ;YAAE,OAAO,UAAU,CAAC;QACzE,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC;AAED,6GAA6G;AAC7G,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,IAAiE;IACrG,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/D,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;AAChH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,IAAoB;IAChD,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,eAAe,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;IAChJ,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,EAAE;QAC7B,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,GAAG,EAAE,IAAI,CAAC,GAAG;QACb,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,IAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,eAAe,EAAE,IAAI,CAAC,eAAe,EAAE;KACxG,CAAC,CAAC;IACH,MAAM,IAAI,GAAG,SAAS,CAAC,MAAM,EAAE,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,eAAe,EAAE,IAAI,CAAC,eAAe,EAAE,CAAC,CAAC;IAC1G,MAAM,YAAY,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IACrG,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;AACvC,CAAC"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import type { Heat } from "./heat.js";
|
|
2
|
+
import type { MapGraph, Verdicts } from "./types.js";
|
|
3
|
+
/** The one line that says what the map is not. Shown on every map page. */
|
|
4
|
+
export declare const ADVISORY_LINE = "Recorded by KYA. The open source check is advisory; this map shows what was recorded, not what was enforced.";
|
|
5
|
+
/** Edge colours by dominant verdict. Deny beats hold, hold beats observed, observed beats allow (schema section 3). */
|
|
6
|
+
export declare const TONE_COLOUR: {
|
|
7
|
+
readonly deny: "#b42318";
|
|
8
|
+
readonly hold: "#b54708";
|
|
9
|
+
readonly observed: "#667085";
|
|
10
|
+
readonly allow: "#067647";
|
|
11
|
+
};
|
|
12
|
+
export type EdgeTone = keyof typeof TONE_COLOUR;
|
|
13
|
+
/** Tone of an edge from its verdict counts. Any deny makes the edge red. */
|
|
14
|
+
export declare function edgeTone(v: Verdicts): EdgeTone;
|
|
15
|
+
/** Edge width grows with log(count): 1 for one event, about 3 for 10, about 5 for 100. */
|
|
16
|
+
export declare function edgeWidth(count: number): number;
|
|
17
|
+
/**
|
|
18
|
+
* JSON for a `<script type="application/json">` body. `<`, `>` and `&` and the two line separators become
|
|
19
|
+
* \u escapes, so the text can never close the script element or start a tag. JSON.parse reads them back unchanged.
|
|
20
|
+
*/
|
|
21
|
+
export declare function jsonForScript(value: unknown): string;
|
|
22
|
+
export declare function scanMapOutput(text: string): void;
|
|
23
|
+
/** HTML text and attribute escape. */
|
|
24
|
+
export declare function esc(s: string): string;
|
|
25
|
+
/** Data the draw script reads: nodes with a label and detail, edges with tone and width (computed here, not in the browser). */
|
|
26
|
+
export declare function drawModel(graph: MapGraph): {
|
|
27
|
+
colours: {
|
|
28
|
+
readonly deny: "#b42318";
|
|
29
|
+
readonly hold: "#b54708";
|
|
30
|
+
readonly observed: "#667085";
|
|
31
|
+
readonly allow: "#067647";
|
|
32
|
+
};
|
|
33
|
+
nodes: {
|
|
34
|
+
id: string;
|
|
35
|
+
kind: "target" | "agent" | "device" | "tool";
|
|
36
|
+
label: string;
|
|
37
|
+
detail: string;
|
|
38
|
+
count: number;
|
|
39
|
+
verdicts: Verdicts;
|
|
40
|
+
firstTs: string;
|
|
41
|
+
lastTs: string;
|
|
42
|
+
}[];
|
|
43
|
+
edges: {
|
|
44
|
+
id: string;
|
|
45
|
+
source: string;
|
|
46
|
+
target: string;
|
|
47
|
+
kind: "runs" | "uses" | "touches";
|
|
48
|
+
tool: string | null;
|
|
49
|
+
tone: "hold" | "deny" | "allow" | "observed";
|
|
50
|
+
colour: "#b42318" | "#b54708" | "#667085" | "#067647";
|
|
51
|
+
width: number;
|
|
52
|
+
count: number;
|
|
53
|
+
verdicts: Verdicts;
|
|
54
|
+
firstTs: string;
|
|
55
|
+
lastTs: string;
|
|
56
|
+
}[];
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* The page body: summary, graph container, side panel, both heat tables, and the data. Used inside the standalone
|
|
60
|
+
* file and as the live report's Map fragment. The graph is drawn by MAP_SCRIPT from the data element.
|
|
61
|
+
*/
|
|
62
|
+
export declare function renderMapBody(graph: MapGraph, heat: Heat, days: number): string;
|
|
63
|
+
/** The vendored Cytoscape.js (MIT, see vendor/cytoscape/LICENSE). `</script` is broken so it cannot end the element. */
|
|
64
|
+
export declare function cytoscapeSource(): string;
|
|
65
|
+
/** Content-Security-Policy for the standalone file. No network: default-src none. */
|
|
66
|
+
export declare const MAP_CSP = "default-src 'none'; style-src 'unsafe-inline'; script-src 'unsafe-inline'; img-src data:";
|
|
67
|
+
/**
|
|
68
|
+
* The browser part. Labels go to Cytoscape (canvas) or textContent. The live body is parsed with DOMParser (the body
|
|
69
|
+
* has no executable script), so this file never assigns innerHTML.
|
|
70
|
+
*/
|
|
71
|
+
export declare const MAP_SCRIPT = "(function () {\n 'use strict';\n var cy = null;\n var last = null;\n var live = !!document.querySelector('main[data-live-token]');\n function token() {\n var m = /(?:^|[?&])t=([^&]*)/.exec(location.search);\n if (!m) return '';\n try { return decodeURIComponent(m[1]); } catch (e) { return m[1]; }\n }\n function model() {\n var el = document.getElementById('kya-map-data');\n if (!el) return null;\n try { return JSON.parse(el.textContent || 'null'); } catch (e) { return null; }\n }\n function add(parent, tag, text) {\n var n = document.createElement(tag);\n n.textContent = String(text);\n parent.appendChild(n);\n return n;\n }\n function showNode(node) {\n var panel = document.getElementById('kya-map-panel');\n if (!panel) return;\n while (panel.firstChild) panel.removeChild(panel.firstChild);\n add(panel, 'h3', node.kind + ': ' + node.label);\n add(panel, 'p', 'Class: ' + node.detail);\n var list = document.createElement('dl');\n panel.appendChild(list);\n [['Events', node.count], ['Allow', node.verdicts.allow], ['Deny', node.verdicts.deny], ['Hold', node.verdicts.hold],\n ['Observed', node.verdicts.observed], ['First seen', node.firstTs || '-'], ['Last seen', node.lastTs || '-']]\n .forEach(function (r) { add(list, 'dt', r[0]); add(list, 'dd', r[1]); });\n }\n function style(d) {\n var out = [\n { selector: 'node', style: { 'label': 'data(label)', 'font-size': 10, 'text-wrap': 'ellipsis', 'text-max-width': 130, 'min-zoomed-font-size': 9,\n 'text-background-color': '#ffffff', 'text-background-opacity': 0.8, 'text-background-padding': 1,\n 'width': 18, 'height': 18, 'background-color': '#98a2b3', 'color': '#101828' } },\n { selector: 'node[kind = \"device\"]', style: { 'background-color': '#344054', 'shape': 'round-rectangle', 'width': 34, 'height': 34 } },\n { selector: 'node[kind = \"agent\"]', style: { 'background-color': '#1d4ed8' } },\n { selector: 'node[kind = \"tool\"]', style: { 'background-color': '#7a5af8', 'shape': 'round-rectangle' } },\n { selector: 'node[kind = \"target\"]', style: { 'background-color': '#0e9384' } },\n { selector: 'edge', style: { 'width': 'data(width)', 'line-color': 'data(colour)', 'target-arrow-color': 'data(colour)',\n 'target-arrow-shape': 'triangle', 'curve-style': 'bezier', 'opacity': 0.9 } }\n ];\n return out;\n }\n var MAX_DRAW_NODES = 400;\n function draw() {\n var host = document.getElementById('kya-map-graph');\n var d = model();\n if (cy) { cy.destroy(); cy = null; }\n if (!host || !d || !window.cytoscape || !d.nodes || !d.nodes.length) return;\n // A force layout on thousands of nodes hangs the tab. The JSON and both heat views still hold everything.\n if (d.nodes.length > MAX_DRAW_NODES) {\n host.textContent = 'Graph not drawn: ' + d.nodes.length + ' nodes is too many for the page. Use a shorter window (kya map --days 1) or kya map --json.';\n return;\n }\n cy = window.cytoscape({\n container: host,\n elements: {\n nodes: d.nodes.map(function (n) { return { data: n }; }),\n edges: d.edges.map(function (e) { return { data: e }; })\n },\n style: style(d),\n layout: { name: 'cose', animate: false, randomize: true, fit: true, padding: 24, numIter: 900, nodeRepulsion: function () { return 9000; }, idealEdgeLength: function () { return 80; }, nodeOverlap: 14, gravity: 0.35 }\n });\n cy.on('tap', 'node', function (evt) { showNode(evt.target.data()); });\n cy.fit();\n }\n function refresh() {\n if (!live) return;\n var host = document.getElementById('frag-map');\n if (!host) return;\n fetch('/fragments?t=' + encodeURIComponent(token()), {\n method: 'POST', headers: { 'Content-Type': 'application/json' }, body: '{\"map\":true}'\n })\n .then(function (r) { if (!r.ok) throw new Error('HTTP ' + r.status); return r.json(); })\n .then(function (j) {\n if (!j || !j.ok || !j.fragments || typeof j.fragments.mapBody !== 'string') return;\n if (j.fragments.mapBody === last) return;\n last = j.fragments.mapBody;\n var doc = new DOMParser().parseFromString(j.fragments.mapBody, 'text/html');\n var nodes = Array.prototype.slice.call(doc.body.childNodes);\n while (host.firstChild) host.removeChild(host.firstChild);\n nodes.forEach(function (n) { host.appendChild(n); });\n draw();\n })\n .catch(function (err) { console.error('KYA map refresh failed', err); });\n }\n // Live only: fetch the vendored library with the token from this page's URL, then run it as a script element.\n function loadLibrary(next) {\n if (window.cytoscape) { next(); return; }\n fetch('/vendor/cytoscape.min.js?t=' + encodeURIComponent(token()))\n .then(function (r) { if (!r.ok) throw new Error('HTTP ' + r.status); return r.text(); })\n .then(function (text) {\n var s = document.createElement('script');\n s.id = 'kya-cytoscape';\n s.textContent = text;\n document.head.appendChild(s);\n next();\n })\n .catch(function (err) { console.error('KYA map library failed', err); });\n }\n window.kyaMapRefresh = refresh;\n window.addEventListener('hashchange', function () {\n if (location.hash !== '#map') return;\n refresh();\n setTimeout(function () { if (cy) { cy.resize(); cy.fit(); } }, 0);\n });\n if (live) loadLibrary(refresh); else draw();\n})();";
|
|
72
|
+
/**
|
|
73
|
+
* Live report: the draw script, in the page shell (not in the swapped fragment). The script reads the token from its
|
|
74
|
+
* own URL and fetches the library from /vendor/cytoscape.min.js, so the token never appears in the HTML.
|
|
75
|
+
*/
|
|
76
|
+
export declare function liveMapScripts(): string;
|
|
77
|
+
/** Map components. Shared by the standalone file and the live report, so it uses the report's tokens (--line, --mute, --fg, --bg). */
|
|
78
|
+
export declare const MAP_CSS = "\n .map-body .map-advisory { border-left: 3px solid var(--line, #d0d5dd); padding: 4px 10px; font-weight: 600; }\n .map-body .mute { color: var(--mute, #667085); }\n .map-stats p { margin: 4px 0; }\n .map-top { margin: 4px 0 12px 20px; padding: 0; }\n .map-canvas { display: grid; grid-template-columns: minmax(0, 1fr) 260px; gap: 12px; margin: 12px 0; }\n .map-graph { height: 60vh; min-height: 360px; border: 1px solid var(--line, #d0d5dd); border-radius: 6px; }\n .map-panel { border: 1px solid var(--line, #d0d5dd); border-radius: 6px; padding: 8px 12px; overflow: auto; }\n .map-panel dl { display: grid; grid-template-columns: auto 1fr; gap: 2px 10px; }\n .map-panel dt { color: var(--mute, #667085); }\n .map-panel dd { margin: 0; }\n .map-scroll { overflow-x: auto; }\n .map-heat { border-collapse: collapse; font-size: 12px; margin-bottom: 12px; }\n .map-heat caption { text-align: left; color: var(--mute, #667085); padding: 4px 0; }\n .map-heat th, .map-heat td { border: 1px solid var(--line, #d0d5dd); padding: 3px 5px; text-align: right; min-width: 22px; }\n .map-heat th { text-align: left; font-weight: 600; }\n .map-heat td.l0 { background: transparent; }\n .map-heat td.l1 { background: #d1fadf; color: #101828; }\n .map-heat td.l2 { background: #75e0a7; color: #101828; }\n .map-heat td.l3 { background: #12b76a; color: #fff; }\n .map-heat td.l4 { background: #027a48; color: #fff; }\n .map-heat td.deny { outline: 2px solid #b42318; outline-offset: -2px; }\n .map-empty { font-weight: 600; }\n @media (max-width: 760px) { .map-canvas { grid-template-columns: 1fr; } }\n";
|
|
79
|
+
/** Live report: the Map zone shows only on its tab (same :target rule as the other zones). */
|
|
80
|
+
export declare const MAP_LIVE_ZONE_CSS = "\n @supports selector(body:has(*)) {\n #map { display: none; }\n #map:target { display: block; }\n body:has(#map:target) #overview { display: none; }\n body:has(#map:target) .nav-link[href=\"#map\"] { color: var(--fg); background: var(--bg); border-color: var(--line); }\n }\n";
|
|
81
|
+
/** Standalone file only: its own tokens and page frame (the live report has its own). */
|
|
82
|
+
export declare const MAP_PAGE_CSS = "\n :root { --fg: #101828; --mute: #667085; --line: #d0d5dd; --bg: #ffffff; }\n @media (prefers-color-scheme: dark) { :root:not([data-theme=\"light\"]) { --fg: #f2f4f7; --mute: #98a2b3; --line: #344054; --bg: #101828; } }\n :root[data-theme=\"dark\"] { --fg: #f2f4f7; --mute: #98a2b3; --line: #344054; --bg: #101828; }\n body { background: var(--bg); color: var(--fg); font: 14px/1.45 system-ui, sans-serif; margin: 0; }\n .map-page { max-width: 1100px; margin: 0 auto; padding: 16px; }\n";
|
|
83
|
+
/** Standalone file: one page, no network, CSP on. */
|
|
84
|
+
export declare function renderMapPage(input: {
|
|
85
|
+
graph: MapGraph;
|
|
86
|
+
heat: Heat;
|
|
87
|
+
days: number;
|
|
88
|
+
title: string;
|
|
89
|
+
}): string;
|
|
90
|
+
//# sourceMappingURL=page.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"page.d.ts","sourceRoot":"","sources":["../../src/map/page.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,KAAK,EAAE,QAAQ,EAAW,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE9D,2EAA2E;AAC3E,eAAO,MAAM,aAAa,iHACsF,CAAC;AAEjH,uHAAuH;AACvH,eAAO,MAAM,WAAW;;;;;CAAuF,CAAC;AAChH,MAAM,MAAM,QAAQ,GAAG,MAAM,OAAO,WAAW,CAAC;AAEhD,4EAA4E;AAC5E,wBAAgB,QAAQ,CAAC,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAK9C;AAED,0FAA0F;AAC1F,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEpD;AAOD,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAEhD;AAED,sCAAsC;AACtC,wBAAgB,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAErC;AAED,gIAAgI;AAChI,wBAAgB,SAAS,CAAC,KAAK,EAAE,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+BxC;AAuED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAsB/E;AAKD,wHAAwH;AACxH,wBAAgB,eAAe,IAAI,MAAM,CAKxC;AAED,qFAAqF;AACrF,eAAO,MAAM,OAAO,6FAA6F,CAAC;AAElH;;;GAGG;AACH,eAAO,MAAM,UAAU,y5KA+GjB,CAAC;AAEP;;;GAGG;AACH,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED,sIAAsI;AACtI,eAAO,MAAM,OAAO,ilDAwBnB,CAAC;AAEF,8FAA8F;AAC9F,eAAO,MAAM,iBAAiB,uSAO7B,CAAC;AAEF,yFAAyF;AACzF,eAAO,MAAM,YAAY,ifAMxB,CAAC;AAEF,qDAAqD;AACrD,wBAAgB,aAAa,CAAC,KAAK,EAAE;IAAE,KAAK,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAyBzG"}
|