@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
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Activity feed HTML/MD for local trail events.
|
|
3
3
|
*/
|
|
4
|
+
import { liveMapScripts, MAP_CSS, MAP_LIVE_ZONE_CSS } from "../map/page.js";
|
|
5
|
+
import { semanticInstallCommand, semanticRuntimeInstalled } from "./semantic-status.js";
|
|
4
6
|
import { assertNoSecrets, clip, stripEscapes } from "../dash/render.js";
|
|
5
7
|
import { clipMultiline, DIFF_MAX_TOTAL_CHARS } from "../diff-preview.js";
|
|
6
8
|
import { DOMAIN_LABELS, domainOrder } from "../certify/render.js";
|
|
7
|
-
import { productLabel,
|
|
9
|
+
import { productLabel, eventsSince, readTrail } from "../trail.js";
|
|
8
10
|
import { mcpServerLabel, parseMcpToolId } from "../mcp-servers.js";
|
|
9
11
|
import { loadInvestigateLastRun, } from "../investigate/last-run.js";
|
|
10
12
|
import { readNotifyLog, summarizeNotifyLog, } from "../notify/log.js";
|
|
@@ -18,6 +20,8 @@ import { GATE_NOT_SETUP_QUICKSTART, loadGatePage, toolNameFromToolId, toolServer
|
|
|
18
20
|
import { receiptCss } from "./receipt-css.js";
|
|
19
21
|
import { applyChipFilters, rankEvents } from "./search.js";
|
|
20
22
|
import { emptyOpenshellCard, loadOpenshellCard } from "./openshell-card.js";
|
|
23
|
+
import { readIocResult } from "../ioc/result.js";
|
|
24
|
+
import { postureCard } from "../posture/card.js";
|
|
21
25
|
export const PAGE_SIZE = 50;
|
|
22
26
|
export function clampPage(page, total) {
|
|
23
27
|
if (total === 0)
|
|
@@ -282,6 +286,8 @@ export function buildReceiptModel(sessionId, events, extras) {
|
|
|
282
286
|
investigate: extras?.investigate,
|
|
283
287
|
alerts: extras?.alerts,
|
|
284
288
|
otel: extras?.otel,
|
|
289
|
+
ioc: extras?.ioc,
|
|
290
|
+
posture: extras?.posture,
|
|
285
291
|
};
|
|
286
292
|
}
|
|
287
293
|
export function buildWindowReceiptModel(events, days, extras) {
|
|
@@ -310,6 +316,8 @@ export function buildWindowReceiptModel(events, days, extras) {
|
|
|
310
316
|
investigate: extras?.investigate,
|
|
311
317
|
alerts: extras?.alerts,
|
|
312
318
|
otel: extras?.otel,
|
|
319
|
+
ioc: extras?.ioc,
|
|
320
|
+
posture: extras?.posture,
|
|
313
321
|
};
|
|
314
322
|
}
|
|
315
323
|
/** Shared loader for static artifacts and the live loopback server. */
|
|
@@ -317,13 +325,13 @@ export function loadReceiptModel(input) {
|
|
|
317
325
|
const days = input.days > 0 ? Math.floor(input.days) : 3;
|
|
318
326
|
const env = input.env ?? process.env;
|
|
319
327
|
const showback = loadShowbackCard(input.cwd);
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
: readTrailSince(input.cwd, new Date(Date.now() - days * 24 * 60 * 60 * 1000), env);
|
|
323
|
-
// The Import card aggregates the full trail, not just the window: imported
|
|
324
|
-
// spans keep their foreign timestamps and would fall out of a short window.
|
|
328
|
+
// One trail read per model. The Import card aggregates the full trail, not just the window:
|
|
329
|
+
// imported spans keep their foreign timestamps and would fall out of a short window.
|
|
325
330
|
// The OpenShell card rolls up the same full-trail view for the same reason.
|
|
326
|
-
const importEvents =
|
|
331
|
+
const importEvents = readTrail(input.cwd, env);
|
|
332
|
+
const events = input.sessionId
|
|
333
|
+
? importEvents
|
|
334
|
+
: eventsSince(importEvents, new Date(Date.now() - days * 24 * 60 * 60 * 1000));
|
|
327
335
|
const certify = loadCertifyCard(input.cwd);
|
|
328
336
|
const extras = {
|
|
329
337
|
page: input.page ?? 1,
|
|
@@ -343,6 +351,8 @@ export function loadReceiptModel(input) {
|
|
|
343
351
|
investigate: loadInvestigateLastRun(env),
|
|
344
352
|
alerts: summarizeNotifyLog(readNotifyLog(env)),
|
|
345
353
|
otel: readOtelStats(env),
|
|
354
|
+
ioc: readIocResult(env),
|
|
355
|
+
posture: postureCard(env),
|
|
346
356
|
spend: showback
|
|
347
357
|
? {
|
|
348
358
|
tokens: showback.totalTokensIn + showback.totalTokensOut,
|
|
@@ -389,8 +399,21 @@ function projectMeta(project) {
|
|
|
389
399
|
<span class="dot">-</span>
|
|
390
400
|
<span class="project">${esc(clip(p, 40))}</span>`;
|
|
391
401
|
}
|
|
392
|
-
|
|
402
|
+
/** Empty list while events exist: the search or the chip filters matched nothing. */
|
|
403
|
+
function noMatchHint(query, env = process.env) {
|
|
404
|
+
const q = query?.trim();
|
|
405
|
+
if (!q)
|
|
406
|
+
return "No events match these filters. Clear a filter to see more.";
|
|
407
|
+
const base = `No events match “${esc(clip(q, 60))}”.`;
|
|
408
|
+
if (semanticRuntimeInstalled(env))
|
|
409
|
+
return base;
|
|
410
|
+
return (`${base} Plain-language search is off, so only exact words match. ` +
|
|
411
|
+
`Turn it on once with <code>${esc(semanticInstallCommand(env))}</code>, then search again.`);
|
|
412
|
+
}
|
|
413
|
+
function renderFeed(events, nowMs, live, preserveOrder, noMatch) {
|
|
393
414
|
if (events.length === 0) {
|
|
415
|
+
if (noMatch)
|
|
416
|
+
return `<p class="empty">${noMatch}</p>`;
|
|
394
417
|
const hint = live
|
|
395
418
|
? "No events yet - evaluate a tool call with <code>kya wrap</code> and this page will refresh."
|
|
396
419
|
: "No events yet - evaluate a tool call with <code>kya wrap</code>, then regenerate this receipt.";
|
|
@@ -1837,7 +1860,7 @@ function normalizeTrailEvents(events) {
|
|
|
1837
1860
|
targetPath: e.targetPath ? clip(e.targetPath, 80) : undefined,
|
|
1838
1861
|
}));
|
|
1839
1862
|
}
|
|
1840
|
-
export function renderFeedPage(events, filters, page, nowMs, live, query, embeddings, queryEmbedding) {
|
|
1863
|
+
export function renderFeedPage(events, filters, page, nowMs, live, query, embeddings, queryEmbedding, indexVersion) {
|
|
1841
1864
|
const q = query?.trim();
|
|
1842
1865
|
let ordered;
|
|
1843
1866
|
let total;
|
|
@@ -1848,6 +1871,7 @@ export function renderFeedPage(events, filters, page, nowMs, live, query, embedd
|
|
|
1848
1871
|
embeddings,
|
|
1849
1872
|
queryEmbedding,
|
|
1850
1873
|
facetBoost: 0.05,
|
|
1874
|
+
indexVersion,
|
|
1851
1875
|
});
|
|
1852
1876
|
ordered = ranked.map((r) => r.event);
|
|
1853
1877
|
total = ranked.length;
|
|
@@ -1862,7 +1886,7 @@ export function renderFeedPage(events, filters, page, nowMs, live, query, embedd
|
|
|
1862
1886
|
const start = (p - 1) * PAGE_SIZE;
|
|
1863
1887
|
const pageEvents = ordered.slice(start, start + PAGE_SIZE);
|
|
1864
1888
|
return {
|
|
1865
|
-
feedHtml: renderFeed(pageEvents, nowMs, live, !!q),
|
|
1889
|
+
feedHtml: renderFeed(pageEvents, nowMs, live, !!q, pageEvents.length === 0 && events.length > 0 ? noMatchHint(q) : undefined),
|
|
1866
1890
|
paginationHtml: paginationBar(total, p, pages),
|
|
1867
1891
|
total,
|
|
1868
1892
|
page: p,
|
|
@@ -1948,6 +1972,70 @@ export function buildLiveFragments(model, livePaged) {
|
|
|
1948
1972
|
},
|
|
1949
1973
|
};
|
|
1950
1974
|
}
|
|
1975
|
+
/**
|
|
1976
|
+
* IoC banner: only when a scan found something. It sits above the zones, so it shows on every
|
|
1977
|
+
* page as a safety signal. The detail is in the System zone.
|
|
1978
|
+
*/
|
|
1979
|
+
function iocBannerHtml(ioc) {
|
|
1980
|
+
const n = ioc?.findings.length ?? 0;
|
|
1981
|
+
if (n === 0)
|
|
1982
|
+
return "";
|
|
1983
|
+
return `<aside class="alert" aria-label="IoC findings">
|
|
1984
|
+
<strong>IoC check: ${n} finding${n === 1 ? "" : "s"} (advisory)</strong>
|
|
1985
|
+
<a href="#system">See the details on the System page</a>
|
|
1986
|
+
</aside>`;
|
|
1987
|
+
}
|
|
1988
|
+
/** IoC card for the System zone: the findings list, or a quiet line when clean. Nothing before the first scan. */
|
|
1989
|
+
function iocSectionHtml(ioc) {
|
|
1990
|
+
if (!ioc)
|
|
1991
|
+
return "";
|
|
1992
|
+
const n = ioc.findings.length;
|
|
1993
|
+
if (n > 0) {
|
|
1994
|
+
const items = ioc.findings
|
|
1995
|
+
.map((f) => `<li><code>${esc(f.ioc)}</code> ${esc(f.check)} <code>${esc(f.evidence)}</code><br><span class="mute">Fix: ${esc(f.hint)}</span></li>`)
|
|
1996
|
+
.join("");
|
|
1997
|
+
return `<section class="card" aria-label="IoC check details">
|
|
1998
|
+
<h3>IoC check: ${n} finding${n === 1 ? "" : "s"} (advisory)</h3>
|
|
1999
|
+
<ul>${items}</ul>
|
|
2000
|
+
<p class="mute">List ${esc(ioc.listVersion)} · checked ${esc(ioc.checkedAt)}. A clean check does not prove the machine is clean.</p>
|
|
2001
|
+
</section>`;
|
|
2002
|
+
}
|
|
2003
|
+
return `<section class="card" aria-label="IoC check">
|
|
2004
|
+
<h3>IoC check</h3>
|
|
2005
|
+
<p class="mute">No findings. List ${esc(ioc.listVersion)} · checked ${esc(ioc.checkedAt)} · unreadable files skipped: ${ioc.skipped}. Advisory: a clean check does not prove the machine is clean.</p>
|
|
2006
|
+
</section>`;
|
|
2007
|
+
}
|
|
2008
|
+
/** Developer setup card (advisory). Shows what a send would contain and the local on/off switch. */
|
|
2009
|
+
function postureSectionHtml(card, live) {
|
|
2010
|
+
if (!card)
|
|
2011
|
+
return "";
|
|
2012
|
+
const list = (items) => items.length === 0 ? "none" : items.map((i) => `<code>${esc(i)}</code>`).join(", ");
|
|
2013
|
+
const toggle = live
|
|
2014
|
+
? card.share
|
|
2015
|
+
? `<button type="button" class="stat" data-report-action="posture" data-posture-share="off">Stop sharing</button>`
|
|
2016
|
+
: `<button type="button" class="stat" data-report-action="posture" data-posture-share="on">Turn sharing on</button>`
|
|
2017
|
+
: `<p class="mute small">To change this, run <code>kya posture on</code> or <code>kya posture off</code>.</p>`;
|
|
2018
|
+
const blocked = card.violations.length > 0
|
|
2019
|
+
? `<p class="mute">Not sendable as it is: ${esc(card.violations.map((v) => `${v.path || "report"} (${v.reason})`).join("; "))}.</p>`
|
|
2020
|
+
: "";
|
|
2021
|
+
return `<section class="card" aria-label="Developer setup">
|
|
2022
|
+
<h3>Developer setup</h3>
|
|
2023
|
+
<p class="mute">Sharing is <strong>${card.share ? "on" : "off"}</strong>. Hosted login: ${card.hosted ? "yes" : "no"}. Workspace policy (cached): ${esc(card.policy)}${card.lastSentAt ? `. Last sent: ${esc(card.lastSentAt)}` : ""}.</p>
|
|
2024
|
+
<p class="mute small">Nothing is sent unless you have a hosted login and your workspace admin turned it on. Turning this on only changes a setting on this machine.${card.hosted ? "" : " Hosted login: no, so nothing is sent from this machine."}</p>
|
|
2025
|
+
<p class="mute small">This list is what the report says about this machine. A send also adds a random device id and a label. The default label is 8 hex characters of a hash. Change it with <code>kya posture label NAME</code>. A send contains no paths, no environment values and no user name:</p>
|
|
2026
|
+
<ul>
|
|
2027
|
+
<li>Agent hosts: ${list(card.hosts)}</li>
|
|
2028
|
+
<li>Agent extensions: ${list(card.extensions)}</li>
|
|
2029
|
+
<li>MCP servers (name, transport, command name): ${list(card.mcpServers)}</li>
|
|
2030
|
+
<li>IoC check: ${esc(card.iocLine)}</li>
|
|
2031
|
+
<li>Never-list: mode ${esc(card.neverMode)}</li>
|
|
2032
|
+
</ul>
|
|
2033
|
+
${blocked}
|
|
2034
|
+
${toggle}
|
|
2035
|
+
<div id="report-action-result-posture"></div>
|
|
2036
|
+
<p class="mute small">Advisory. This card reports what is shared. It does not prevent anything.</p>
|
|
2037
|
+
</section>`;
|
|
2038
|
+
}
|
|
1951
2039
|
export function renderReceiptHtml(model) {
|
|
1952
2040
|
const nowMs = Date.now();
|
|
1953
2041
|
const events = normalizeTrailEvents(model.events);
|
|
@@ -1977,6 +2065,8 @@ export function renderReceiptHtml(model) {
|
|
|
1977
2065
|
const tools = model.mcpSeen && model.mcpSeen.length > 0
|
|
1978
2066
|
? model.mcpSeen.map((m) => m.toolId)
|
|
1979
2067
|
: [...new Set(events.map((e) => e.toolId))];
|
|
2068
|
+
// Only the findings banner repeats on every page; the quiet cards live in the System zone.
|
|
2069
|
+
const iocBanner = iocBannerHtml(model.ioc);
|
|
1980
2070
|
const blockedBanner = blocked.length === 0
|
|
1981
2071
|
? ""
|
|
1982
2072
|
: `<aside class="alert" aria-label="Blocked never-events">
|
|
@@ -2332,6 +2422,7 @@ export function renderReceiptHtml(model) {
|
|
|
2332
2422
|
dirty = false;
|
|
2333
2423
|
feedUpdate();
|
|
2334
2424
|
scheduleFragments();
|
|
2425
|
+
if (window.kyaMapRefresh && location.hash === '#map') window.kyaMapRefresh();
|
|
2335
2426
|
}
|
|
2336
2427
|
// EventSource is absent in DOM shims and very old engines; the page still
|
|
2337
2428
|
// works, it just does not stream updates.
|
|
@@ -2623,7 +2714,9 @@ export function renderReceiptHtml(model) {
|
|
|
2623
2714
|
var resultEl = document.getElementById('report-action-result-' + action);
|
|
2624
2715
|
btn.disabled = true;
|
|
2625
2716
|
setResult(resultEl, 'Working...', false);
|
|
2626
|
-
|
|
2717
|
+
var shareAttr = btn.getAttribute('data-posture-share');
|
|
2718
|
+
var body = shareAttr ? { share: shareAttr === 'on' } : {};
|
|
2719
|
+
post('/action/' + action, body)
|
|
2627
2720
|
.then(parseJson)
|
|
2628
2721
|
.then(function(data){
|
|
2629
2722
|
if (data && data.ok) {
|
|
@@ -2633,7 +2726,9 @@ export function renderReceiptHtml(model) {
|
|
|
2633
2726
|
? 'Done: ' + data.total + ' item(s) discovered'
|
|
2634
2727
|
: action === 'notify-test'
|
|
2635
2728
|
? (data.detail ? String(data.detail) : 'Test alert sent to ' + data.targets + ' target(s)')
|
|
2636
|
-
:
|
|
2729
|
+
: action === 'posture'
|
|
2730
|
+
? 'Developer setup sharing is ' + (data.share ? 'on' : 'off') + '.'
|
|
2731
|
+
: String(data.detail || 'ok');
|
|
2637
2732
|
setResult(resultEl, '<p>' + esc(msg) + '</p>', false);
|
|
2638
2733
|
if (action === 'otel-test') {
|
|
2639
2734
|
btn.disabled = false;
|
|
@@ -2714,6 +2809,8 @@ export function renderReceiptHtml(model) {
|
|
|
2714
2809
|
// (zoneBody lives at module level; buildLiveFragments above produces the
|
|
2715
2810
|
// overview and certify bodies through the same helper.)
|
|
2716
2811
|
const systemBody = zoneBody([
|
|
2812
|
+
iocSectionHtml(model.ioc),
|
|
2813
|
+
postureSectionHtml(model.posture, !!model.liveToken),
|
|
2717
2814
|
capabilitiesPanel(model),
|
|
2718
2815
|
gatePanel(model.gate, nowMs),
|
|
2719
2816
|
wiredHostsPanel(model.wiredHosts),
|
|
@@ -2729,7 +2826,7 @@ export function renderReceiptHtml(model) {
|
|
|
2729
2826
|
<meta charset="utf-8"/>
|
|
2730
2827
|
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
|
2731
2828
|
<title>${esc(model.title)} - ${esc(model.rangeLabel)}</title>
|
|
2732
|
-
<style>${receiptCss()}</style>
|
|
2829
|
+
<style>${receiptCss()}${model.liveToken ? MAP_CSS + MAP_LIVE_ZONE_CSS : ""}</style>
|
|
2733
2830
|
</head>
|
|
2734
2831
|
<body>
|
|
2735
2832
|
<aside class="sidebar">
|
|
@@ -2745,6 +2842,7 @@ export function renderReceiptHtml(model) {
|
|
|
2745
2842
|
${navItem("#changes", "Changes", changes.fileCount)}
|
|
2746
2843
|
${navItem("#certify", "Certify", model.certify?.gap ?? 0)}
|
|
2747
2844
|
${navItem("#orr", "ORR", model.orr ? model.orr.scorecards.fail : undefined)}
|
|
2845
|
+
${model.liveToken ? navItem("#map", "Map", undefined) : ""}
|
|
2748
2846
|
${navGroup("Gateway", model.gate?.state === "running")}
|
|
2749
2847
|
${navSubItem("#gateway-home", "Home", model.gate?.servers.length ?? 0)}
|
|
2750
2848
|
${navSubItem("#gateway-listeners", "Listeners", model.gate?.listeners?.length ?? 0)}
|
|
@@ -2770,6 +2868,7 @@ ${model.liveToken ? '<main data-live-token="1">' : '<main>'}
|
|
|
2770
2868
|
${identityLine(model.identity)}
|
|
2771
2869
|
</header>
|
|
2772
2870
|
${blockedBanner}
|
|
2871
|
+
${iocBanner}
|
|
2773
2872
|
<section class="zone" id="overview" aria-labelledby="tab-overview">
|
|
2774
2873
|
<div class="hero">
|
|
2775
2874
|
${fr.fragments.heroCertify}
|
|
@@ -2809,12 +2908,14 @@ ${fr.fragments.changesList}
|
|
|
2809
2908
|
<section class="zone" id="orr" aria-labelledby="tab-orr">
|
|
2810
2909
|
<div id="frag-orr">${fr.fragments.orrPanel}</div>
|
|
2811
2910
|
</section>
|
|
2911
|
+
${model.liveToken ? '<section class="zone" id="map" aria-labelledby="tab-map"><div id="frag-map"><p class="mute">Loading the map.</p></div></section>' : ""}
|
|
2812
2912
|
${gatePagePanel(model.gate, nowMs)}
|
|
2813
2913
|
<section class="zone" id="system" aria-labelledby="tab-system">
|
|
2814
2914
|
${systemBody}
|
|
2815
2915
|
</section>
|
|
2816
2916
|
</main>
|
|
2817
2917
|
${filterScript}
|
|
2918
|
+
${model.liveToken ? liveMapScripts() : ""}
|
|
2818
2919
|
${staticSearchScript}
|
|
2819
2920
|
${themeScript}
|
|
2820
2921
|
${gateScript}
|
|
@@ -2836,6 +2937,10 @@ export function renderReceiptMarkdown(model) {
|
|
|
2836
2937
|
`Allow ${c.allow} | Deny ${c.deny} | Review ${c.require} | Never ${c.never}`,
|
|
2837
2938
|
"",
|
|
2838
2939
|
];
|
|
2940
|
+
if (model.ioc) {
|
|
2941
|
+
const k = model.ioc.findings.length;
|
|
2942
|
+
lines.push(mdText(`IoC check (advisory): ${k === 0 ? "no findings" : `${k} finding${k === 1 ? "" : "s"}`}, list ${model.ioc.listVersion}, checked ${model.ioc.checkedAt}.`), "");
|
|
2943
|
+
}
|
|
2839
2944
|
if (model.identity) {
|
|
2840
2945
|
const id = model.identity;
|
|
2841
2946
|
const nameId = id.agentName && id.agentId
|