@shield-agent/kya 0.32.7 → 0.33.1

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.
Files changed (306) hide show
  1. package/.cursor-plugin/plugin.json +1 -1
  2. package/.mcp.json +1 -1
  3. package/LIMITATIONS.md +2 -2
  4. package/README.md +232 -17
  5. package/amp/settings.example.json +1 -1
  6. package/claude/claude_desktop_config.example.json +1 -1
  7. package/cline/cline_mcp_settings.example.json +1 -1
  8. package/copilot/mcp-config.example.json +1 -1
  9. package/data/iocs.json +17 -0
  10. package/dist/cli.d.ts +1 -1
  11. package/dist/cli.d.ts.map +1 -1
  12. package/dist/cli.js +237 -53
  13. package/dist/cli.js.map +1 -1
  14. package/dist/client.d.ts +2 -0
  15. package/dist/client.d.ts.map +1 -1
  16. package/dist/client.js +1 -1
  17. package/dist/client.js.map +1 -1
  18. package/dist/commands/connect.d.ts +1 -1
  19. package/dist/commands/connect.d.ts.map +1 -1
  20. package/dist/commands/connect.js +11 -3
  21. package/dist/commands/connect.js.map +1 -1
  22. package/dist/commands/dash.d.ts.map +1 -1
  23. package/dist/commands/dash.js +25 -1
  24. package/dist/commands/dash.js.map +1 -1
  25. package/dist/commands/doctor.d.ts +8 -0
  26. package/dist/commands/doctor.d.ts.map +1 -0
  27. package/dist/commands/doctor.js +26 -0
  28. package/dist/commands/doctor.js.map +1 -0
  29. package/dist/commands/eval-tool.d.ts +3 -0
  30. package/dist/commands/eval-tool.d.ts.map +1 -1
  31. package/dist/commands/eval-tool.js +2 -1
  32. package/dist/commands/eval-tool.js.map +1 -1
  33. package/dist/commands/export.d.ts +33 -0
  34. package/dist/commands/export.d.ts.map +1 -0
  35. package/dist/commands/export.js +121 -0
  36. package/dist/commands/export.js.map +1 -0
  37. package/dist/commands/hook.d.ts.map +1 -1
  38. package/dist/commands/hook.js +135 -26
  39. package/dist/commands/hook.js.map +1 -1
  40. package/dist/commands/hosted-hook.d.ts +8 -1
  41. package/dist/commands/hosted-hook.d.ts.map +1 -1
  42. package/dist/commands/hosted-hook.js +15 -5
  43. package/dist/commands/hosted-hook.js.map +1 -1
  44. package/dist/commands/login.d.ts +34 -0
  45. package/dist/commands/login.d.ts.map +1 -0
  46. package/dist/commands/login.js +74 -0
  47. package/dist/commands/login.js.map +1 -0
  48. package/dist/commands/map.d.ts +21 -0
  49. package/dist/commands/map.d.ts.map +1 -0
  50. package/dist/commands/map.js +76 -0
  51. package/dist/commands/map.js.map +1 -0
  52. package/dist/commands/notify-flush.d.ts.map +1 -1
  53. package/dist/commands/notify-flush.js +7 -1
  54. package/dist/commands/notify-flush.js.map +1 -1
  55. package/dist/commands/posture.d.ts +21 -0
  56. package/dist/commands/posture.d.ts.map +1 -0
  57. package/dist/commands/posture.js +177 -0
  58. package/dist/commands/posture.js.map +1 -0
  59. package/dist/commands/receipt-serve.d.ts +7 -0
  60. package/dist/commands/receipt-serve.d.ts.map +1 -1
  61. package/dist/commands/receipt-serve.js +50 -0
  62. package/dist/commands/receipt-serve.js.map +1 -1
  63. package/dist/commands/start.d.ts.map +1 -1
  64. package/dist/commands/start.js +5 -1
  65. package/dist/commands/start.js.map +1 -1
  66. package/dist/commands/team.d.ts.map +1 -1
  67. package/dist/commands/team.js +30 -11
  68. package/dist/commands/team.js.map +1 -1
  69. package/dist/commands/wire-hooks.d.ts +5 -1
  70. package/dist/commands/wire-hooks.d.ts.map +1 -1
  71. package/dist/commands/wire-hooks.js +23 -8
  72. package/dist/commands/wire-hooks.js.map +1 -1
  73. package/dist/commands/wrap.d.ts +38 -1
  74. package/dist/commands/wrap.d.ts.map +1 -1
  75. package/dist/commands/wrap.js +82 -6
  76. package/dist/commands/wrap.js.map +1 -1
  77. package/dist/config.d.ts +2 -0
  78. package/dist/config.d.ts.map +1 -1
  79. package/dist/config.js.map +1 -1
  80. package/dist/cta.d.ts +23 -0
  81. package/dist/cta.d.ts.map +1 -0
  82. package/dist/cta.js +86 -0
  83. package/dist/cta.js.map +1 -0
  84. package/dist/daily-slot.d.ts +2 -0
  85. package/dist/daily-slot.d.ts.map +1 -0
  86. package/dist/daily-slot.js +29 -0
  87. package/dist/daily-slot.js.map +1 -0
  88. package/dist/dash/dash.d.ts.map +1 -1
  89. package/dist/dash/dash.js +10 -0
  90. package/dist/dash/dash.js.map +1 -1
  91. package/dist/dash/entitlement.d.ts +1 -1
  92. package/dist/dash/entitlement.d.ts.map +1 -1
  93. package/dist/dash/entitlement.js +1 -0
  94. package/dist/dash/entitlement.js.map +1 -1
  95. package/dist/dash/input.d.ts +1 -1
  96. package/dist/dash/input.d.ts.map +1 -1
  97. package/dist/dash/input.js +3 -0
  98. package/dist/dash/input.js.map +1 -1
  99. package/dist/dash/render.js +1 -1
  100. package/dist/dash/render.js.map +1 -1
  101. package/dist/dash/screens/free.js +1 -1
  102. package/dist/dash/screens/free.js.map +1 -1
  103. package/dist/device-id.d.ts +5 -0
  104. package/dist/device-id.d.ts.map +1 -0
  105. package/dist/device-id.js +78 -0
  106. package/dist/device-id.js.map +1 -0
  107. package/dist/fs-atomic.d.ts +15 -3
  108. package/dist/fs-atomic.d.ts.map +1 -1
  109. package/dist/fs-atomic.js +31 -14
  110. package/dist/fs-atomic.js.map +1 -1
  111. package/dist/gate/config-gen.d.ts +26 -2
  112. package/dist/gate/config-gen.d.ts.map +1 -1
  113. package/dist/gate/config-gen.js +53 -4
  114. package/dist/gate/config-gen.js.map +1 -1
  115. package/dist/gate/otlp-receiver.d.ts.map +1 -1
  116. package/dist/gate/otlp-receiver.js +3 -1
  117. package/dist/gate/otlp-receiver.js.map +1 -1
  118. package/dist/guard-pack.d.ts +58 -0
  119. package/dist/guard-pack.d.ts.map +1 -0
  120. package/dist/guard-pack.js +753 -0
  121. package/dist/guard-pack.js.map +1 -0
  122. package/dist/ioc/exec.d.ts +19 -0
  123. package/dist/ioc/exec.d.ts.map +1 -0
  124. package/dist/ioc/exec.js +49 -0
  125. package/dist/ioc/exec.js.map +1 -0
  126. package/dist/ioc/format.d.ts +4 -0
  127. package/dist/ioc/format.d.ts.map +1 -0
  128. package/dist/ioc/format.js +23 -0
  129. package/dist/ioc/format.js.map +1 -0
  130. package/dist/ioc/list.d.ts +29 -0
  131. package/dist/ioc/list.d.ts.map +1 -0
  132. package/dist/ioc/list.js +25 -0
  133. package/dist/ioc/list.js.map +1 -0
  134. package/dist/ioc/result.d.ts +18 -0
  135. package/dist/ioc/result.d.ts.map +1 -0
  136. package/dist/ioc/result.js +26 -0
  137. package/dist/ioc/result.js.map +1 -0
  138. package/dist/ioc/scan.d.ts +21 -0
  139. package/dist/ioc/scan.d.ts.map +1 -0
  140. package/dist/ioc/scan.js +247 -0
  141. package/dist/ioc/scan.js.map +1 -0
  142. package/dist/ioc/spawn.d.ts +26 -0
  143. package/dist/ioc/spawn.d.ts.map +1 -0
  144. package/dist/ioc/spawn.js +52 -0
  145. package/dist/ioc/spawn.js.map +1 -0
  146. package/dist/login/credentials.d.ts +17 -0
  147. package/dist/login/credentials.d.ts.map +1 -0
  148. package/dist/login/credentials.js +64 -0
  149. package/dist/login/credentials.js.map +1 -0
  150. package/dist/login/device-flow.d.ts +44 -0
  151. package/dist/login/device-flow.d.ts.map +1 -0
  152. package/dist/login/device-flow.js +205 -0
  153. package/dist/login/device-flow.js.map +1 -0
  154. package/dist/map/build.d.ts +58 -0
  155. package/dist/map/build.d.ts.map +1 -0
  156. package/dist/map/build.js +439 -0
  157. package/dist/map/build.js.map +1 -0
  158. package/dist/map/heat.d.ts +44 -0
  159. package/dist/map/heat.d.ts.map +1 -0
  160. package/dist/map/heat.js +96 -0
  161. package/dist/map/heat.js.map +1 -0
  162. package/dist/map/load.d.ts +38 -0
  163. package/dist/map/load.d.ts.map +1 -0
  164. package/dist/map/load.js +38 -0
  165. package/dist/map/load.js.map +1 -0
  166. package/dist/map/page.d.ts +90 -0
  167. package/dist/map/page.d.ts.map +1 -0
  168. package/dist/map/page.js +374 -0
  169. package/dist/map/page.js.map +1 -0
  170. package/dist/map/target-class.d.ts +22 -0
  171. package/dist/map/target-class.d.ts.map +1 -0
  172. package/dist/map/target-class.js +151 -0
  173. package/dist/map/target-class.js.map +1 -0
  174. package/dist/map/types.d.ts +102 -0
  175. package/dist/map/types.d.ts.map +1 -0
  176. package/dist/map/types.js +3 -0
  177. package/dist/map/types.js.map +1 -0
  178. package/dist/mcp/protocol.d.ts.map +1 -1
  179. package/dist/mcp/protocol.js +16 -5
  180. package/dist/mcp/protocol.js.map +1 -1
  181. package/dist/never-code.d.ts +7 -0
  182. package/dist/never-code.d.ts.map +1 -0
  183. package/dist/never-code.js +9 -0
  184. package/dist/never-code.js.map +1 -0
  185. package/dist/never-list-input.d.ts +92 -0
  186. package/dist/never-list-input.d.ts.map +1 -0
  187. package/dist/never-list-input.js +1889 -0
  188. package/dist/never-list-input.js.map +1 -0
  189. package/dist/notify/dispatch.d.ts +4 -0
  190. package/dist/notify/dispatch.d.ts.map +1 -1
  191. package/dist/notify/dispatch.js +3 -1
  192. package/dist/notify/dispatch.js.map +1 -1
  193. package/dist/offline-evaluate.d.ts +42 -5
  194. package/dist/offline-evaluate.d.ts.map +1 -1
  195. package/dist/offline-evaluate.js +96 -9
  196. package/dist/offline-evaluate.js.map +1 -1
  197. package/dist/otel/exporter.d.ts +15 -2
  198. package/dist/otel/exporter.d.ts.map +1 -1
  199. package/dist/otel/exporter.js +52 -6
  200. package/dist/otel/exporter.js.map +1 -1
  201. package/dist/otel/map-attrs-optin.d.ts +39 -0
  202. package/dist/otel/map-attrs-optin.d.ts.map +1 -0
  203. package/dist/otel/map-attrs-optin.js +109 -0
  204. package/dist/otel/map-attrs-optin.js.map +1 -0
  205. package/dist/otel.d.ts +8 -2
  206. package/dist/otel.d.ts.map +1 -1
  207. package/dist/otel.js +32 -16
  208. package/dist/otel.js.map +1 -1
  209. package/dist/parse-args.d.ts +2 -0
  210. package/dist/parse-args.d.ts.map +1 -1
  211. package/dist/parse-args.js +4 -2
  212. package/dist/parse-args.js.map +1 -1
  213. package/dist/posture/card.d.ts +26 -0
  214. package/dist/posture/card.d.ts.map +1 -0
  215. package/dist/posture/card.js +46 -0
  216. package/dist/posture/card.js.map +1 -0
  217. package/dist/posture/collect.d.ts +19 -0
  218. package/dist/posture/collect.d.ts.map +1 -0
  219. package/dist/posture/collect.js +182 -0
  220. package/dist/posture/collect.js.map +1 -0
  221. package/dist/posture/send.d.ts +24 -0
  222. package/dist/posture/send.d.ts.map +1 -0
  223. package/dist/posture/send.js +162 -0
  224. package/dist/posture/send.js.map +1 -0
  225. package/dist/posture/spawn.d.ts +20 -0
  226. package/dist/posture/spawn.d.ts.map +1 -0
  227. package/dist/posture/spawn.js +33 -0
  228. package/dist/posture/spawn.js.map +1 -0
  229. package/dist/posture/store.d.ts +34 -0
  230. package/dist/posture/store.d.ts.map +1 -0
  231. package/dist/posture/store.js +107 -0
  232. package/dist/posture/store.js.map +1 -0
  233. package/dist/posture/validate.d.ts +33 -0
  234. package/dist/posture/validate.d.ts.map +1 -0
  235. package/dist/posture/validate.js +232 -0
  236. package/dist/posture/validate.js.map +1 -0
  237. package/dist/project-policy.d.ts +23 -0
  238. package/dist/project-policy.d.ts.map +1 -0
  239. package/dist/project-policy.js +95 -0
  240. package/dist/project-policy.js.map +1 -0
  241. package/dist/receipt/daemon.d.ts +9 -9
  242. package/dist/receipt/daemon.d.ts.map +1 -1
  243. package/dist/receipt/daemon.js +26 -11
  244. package/dist/receipt/daemon.js.map +1 -1
  245. package/dist/receipt/embeddings.d.ts +29 -7
  246. package/dist/receipt/embeddings.d.ts.map +1 -1
  247. package/dist/receipt/embeddings.js +282 -33
  248. package/dist/receipt/embeddings.js.map +1 -1
  249. package/dist/receipt/gate-page.d.ts.map +1 -1
  250. package/dist/receipt/gate-page.js +5 -22
  251. package/dist/receipt/gate-page.js.map +1 -1
  252. package/dist/receipt/live-server.d.ts +8 -0
  253. package/dist/receipt/live-server.d.ts.map +1 -1
  254. package/dist/receipt/live-server.js +136 -4
  255. package/dist/receipt/live-server.js.map +1 -1
  256. package/dist/receipt/render-receipt.d.ts +7 -1
  257. package/dist/receipt/render-receipt.d.ts.map +1 -1
  258. package/dist/receipt/render-receipt.js +101 -13
  259. package/dist/receipt/render-receipt.js.map +1 -1
  260. package/dist/receipt/search.d.ts +5 -0
  261. package/dist/receipt/search.d.ts.map +1 -1
  262. package/dist/receipt/search.js +23 -2
  263. package/dist/receipt/search.js.map +1 -1
  264. package/dist/receipt/semantic-setup.d.ts +21 -0
  265. package/dist/receipt/semantic-setup.d.ts.map +1 -0
  266. package/dist/receipt/semantic-setup.js +111 -0
  267. package/dist/receipt/semantic-setup.js.map +1 -0
  268. package/dist/receipt/semantic-status.d.ts +7 -0
  269. package/dist/receipt/semantic-status.d.ts.map +1 -0
  270. package/dist/receipt/semantic-status.js +26 -0
  271. package/dist/receipt/semantic-status.js.map +1 -0
  272. package/dist/sdk/govern.d.ts.map +1 -1
  273. package/dist/sdk/govern.js +7 -3
  274. package/dist/sdk/govern.js.map +1 -1
  275. package/dist/telemetry.d.ts.map +1 -1
  276. package/dist/telemetry.js +3 -23
  277. package/dist/telemetry.js.map +1 -1
  278. package/dist/trail-map-fields.d.ts +10 -0
  279. package/dist/trail-map-fields.d.ts.map +1 -0
  280. package/dist/trail-map-fields.js +53 -0
  281. package/dist/trail-map-fields.js.map +1 -0
  282. package/dist/trail-summary.d.ts.map +1 -1
  283. package/dist/trail-summary.js +11 -3
  284. package/dist/trail-summary.js.map +1 -1
  285. package/dist/trail.d.ts +13 -1
  286. package/dist/trail.d.ts.map +1 -1
  287. package/dist/trail.js +38 -1
  288. package/dist/trail.js.map +1 -1
  289. package/droid/README.md +1 -1
  290. package/droid/mcp.example.json +1 -1
  291. package/gemini/settings.example.json +1 -1
  292. package/grok/README.md +1 -1
  293. package/kilo/kilo.example.json +1 -1
  294. package/kimi/mcp.example.json +1 -1
  295. package/kiro/mcp.example.json +1 -1
  296. package/manifest.json +1 -1
  297. package/mastracode/mcp.example.json +1 -1
  298. package/mcp.json +1 -1
  299. package/openai/codex.config.example.toml +1 -1
  300. package/opencode/opencode.example.json +1 -1
  301. package/package.json +8 -7
  302. package/qwen/settings.example.json +1 -1
  303. package/server.json +2 -2
  304. package/vendor/cytoscape/LICENSE +19 -0
  305. package/vendor/cytoscape/README.md +7 -0
  306. 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, readTrail, readTrailSince } from "../trail.js";
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
- const events = input.sessionId
321
- ? readTrail(input.cwd, env)
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 = input.sessionId ? events : readTrail(input.cwd, env);
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
- function renderFeed(events, nowMs, live, preserveOrder) {
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 &ldquo;${esc(clip(q, 60))}&rdquo;.`;
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,56 @@ export function buildLiveFragments(model, livePaged) {
1948
1972
  },
1949
1973
  };
1950
1974
  }
1975
+ /** IoC check: a banner when a scan found something, otherwise a quiet card. Nothing before the first scan. */
1976
+ function iocSectionHtml(ioc) {
1977
+ if (!ioc)
1978
+ return "";
1979
+ const n = ioc.findings.length;
1980
+ if (n > 0) {
1981
+ const items = ioc.findings
1982
+ .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>`)
1983
+ .join("");
1984
+ return `<aside class="alert" aria-label="IoC findings">
1985
+ <strong>IoC check: ${n} finding${n === 1 ? "" : "s"} (advisory)</strong>
1986
+ <ul>${items}</ul>
1987
+ <span class="mute">List ${esc(ioc.listVersion)} · checked ${esc(ioc.checkedAt)}. A clean check does not prove the machine is clean.</span>
1988
+ </aside>`;
1989
+ }
1990
+ return `<section class="card" aria-label="IoC check">
1991
+ <h3>IoC check</h3>
1992
+ <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>
1993
+ </section>`;
1994
+ }
1995
+ /** Developer setup card (advisory). Shows what a send would contain and the local on/off switch. */
1996
+ function postureSectionHtml(card, live) {
1997
+ if (!card)
1998
+ return "";
1999
+ const list = (items) => items.length === 0 ? "none" : items.map((i) => `<code>${esc(i)}</code>`).join(", ");
2000
+ const toggle = live
2001
+ ? card.share
2002
+ ? `<button type="button" class="stat" data-report-action="posture" data-posture-share="off">Stop sharing</button>`
2003
+ : `<button type="button" class="stat" data-report-action="posture" data-posture-share="on">Turn sharing on</button>`
2004
+ : `<p class="mute small">To change this, run <code>kya posture on</code> or <code>kya posture off</code>.</p>`;
2005
+ const blocked = card.violations.length > 0
2006
+ ? `<p class="mute">Not sendable as it is: ${esc(card.violations.map((v) => `${v.path || "report"} (${v.reason})`).join("; "))}.</p>`
2007
+ : "";
2008
+ return `<section class="card" aria-label="Developer setup">
2009
+ <h3>Developer setup</h3>
2010
+ <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>
2011
+ <p class="mute small">What a send would contain. No device id, no label, no paths, no environment values, no user name:</p>
2012
+ <ul>
2013
+ <li>Agent hosts: ${list(card.hosts)}</li>
2014
+ <li>Agent extensions: ${list(card.extensions)}</li>
2015
+ <li>MCP servers (name, transport, command name): ${list(card.mcpServers)}</li>
2016
+ <li>IoC check: ${esc(card.iocLine)}</li>
2017
+ <li>Never-list: mode ${esc(card.neverMode)}</li>
2018
+ </ul>
2019
+ ${blocked}
2020
+ ${toggle}
2021
+ <div id="report-action-result-posture"></div>
2022
+ <p class="mute small">Advisory. This card reports what is shared. It does not prevent anything.</p>
2023
+ </section>`;
2024
+ }
1951
2025
  export function renderReceiptHtml(model) {
1952
2026
  const nowMs = Date.now();
1953
2027
  const events = normalizeTrailEvents(model.events);
@@ -1977,6 +2051,7 @@ export function renderReceiptHtml(model) {
1977
2051
  const tools = model.mcpSeen && model.mcpSeen.length > 0
1978
2052
  ? model.mcpSeen.map((m) => m.toolId)
1979
2053
  : [...new Set(events.map((e) => e.toolId))];
2054
+ const iocHtml = iocSectionHtml(model.ioc) + postureSectionHtml(model.posture, !!model.liveToken);
1980
2055
  const blockedBanner = blocked.length === 0
1981
2056
  ? ""
1982
2057
  : `<aside class="alert" aria-label="Blocked never-events">
@@ -2332,6 +2407,7 @@ export function renderReceiptHtml(model) {
2332
2407
  dirty = false;
2333
2408
  feedUpdate();
2334
2409
  scheduleFragments();
2410
+ if (window.kyaMapRefresh && location.hash === '#map') window.kyaMapRefresh();
2335
2411
  }
2336
2412
  // EventSource is absent in DOM shims and very old engines; the page still
2337
2413
  // works, it just does not stream updates.
@@ -2623,7 +2699,9 @@ export function renderReceiptHtml(model) {
2623
2699
  var resultEl = document.getElementById('report-action-result-' + action);
2624
2700
  btn.disabled = true;
2625
2701
  setResult(resultEl, 'Working...', false);
2626
- post('/action/' + action, {})
2702
+ var shareAttr = btn.getAttribute('data-posture-share');
2703
+ var body = shareAttr ? { share: shareAttr === 'on' } : {};
2704
+ post('/action/' + action, body)
2627
2705
  .then(parseJson)
2628
2706
  .then(function(data){
2629
2707
  if (data && data.ok) {
@@ -2633,7 +2711,9 @@ export function renderReceiptHtml(model) {
2633
2711
  ? 'Done: ' + data.total + ' item(s) discovered'
2634
2712
  : action === 'notify-test'
2635
2713
  ? (data.detail ? String(data.detail) : 'Test alert sent to ' + data.targets + ' target(s)')
2636
- : String(data.detail || 'ok');
2714
+ : action === 'posture'
2715
+ ? 'Developer setup sharing is ' + (data.share ? 'on' : 'off') + '.'
2716
+ : String(data.detail || 'ok');
2637
2717
  setResult(resultEl, '<p>' + esc(msg) + '</p>', false);
2638
2718
  if (action === 'otel-test') {
2639
2719
  btn.disabled = false;
@@ -2729,7 +2809,7 @@ export function renderReceiptHtml(model) {
2729
2809
  <meta charset="utf-8"/>
2730
2810
  <meta name="viewport" content="width=device-width, initial-scale=1"/>
2731
2811
  <title>${esc(model.title)} - ${esc(model.rangeLabel)}</title>
2732
- <style>${receiptCss()}</style>
2812
+ <style>${receiptCss()}${model.liveToken ? MAP_CSS + MAP_LIVE_ZONE_CSS : ""}</style>
2733
2813
  </head>
2734
2814
  <body>
2735
2815
  <aside class="sidebar">
@@ -2745,6 +2825,7 @@ export function renderReceiptHtml(model) {
2745
2825
  ${navItem("#changes", "Changes", changes.fileCount)}
2746
2826
  ${navItem("#certify", "Certify", model.certify?.gap ?? 0)}
2747
2827
  ${navItem("#orr", "ORR", model.orr ? model.orr.scorecards.fail : undefined)}
2828
+ ${model.liveToken ? navItem("#map", "Map", undefined) : ""}
2748
2829
  ${navGroup("Gateway", model.gate?.state === "running")}
2749
2830
  ${navSubItem("#gateway-home", "Home", model.gate?.servers.length ?? 0)}
2750
2831
  ${navSubItem("#gateway-listeners", "Listeners", model.gate?.listeners?.length ?? 0)}
@@ -2770,6 +2851,7 @@ ${model.liveToken ? '<main data-live-token="1">' : '<main>'}
2770
2851
  ${identityLine(model.identity)}
2771
2852
  </header>
2772
2853
  ${blockedBanner}
2854
+ ${iocHtml}
2773
2855
  <section class="zone" id="overview" aria-labelledby="tab-overview">
2774
2856
  <div class="hero">
2775
2857
  ${fr.fragments.heroCertify}
@@ -2809,12 +2891,14 @@ ${fr.fragments.changesList}
2809
2891
  <section class="zone" id="orr" aria-labelledby="tab-orr">
2810
2892
  <div id="frag-orr">${fr.fragments.orrPanel}</div>
2811
2893
  </section>
2894
+ ${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
2895
  ${gatePagePanel(model.gate, nowMs)}
2813
2896
  <section class="zone" id="system" aria-labelledby="tab-system">
2814
2897
  ${systemBody}
2815
2898
  </section>
2816
2899
  </main>
2817
2900
  ${filterScript}
2901
+ ${model.liveToken ? liveMapScripts() : ""}
2818
2902
  ${staticSearchScript}
2819
2903
  ${themeScript}
2820
2904
  ${gateScript}
@@ -2836,6 +2920,10 @@ export function renderReceiptMarkdown(model) {
2836
2920
  `Allow ${c.allow} | Deny ${c.deny} | Review ${c.require} | Never ${c.never}`,
2837
2921
  "",
2838
2922
  ];
2923
+ if (model.ioc) {
2924
+ const k = model.ioc.findings.length;
2925
+ lines.push(mdText(`IoC check (advisory): ${k === 0 ? "no findings" : `${k} finding${k === 1 ? "" : "s"}`}, list ${model.ioc.listVersion}, checked ${model.ioc.checkedAt}.`), "");
2926
+ }
2839
2927
  if (model.identity) {
2840
2928
  const id = model.identity;
2841
2929
  const nameId = id.agentName && id.agentId