@shield-agent/kya 0.21.0 → 0.23.0

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 (252) hide show
  1. package/.mcp.json +1 -1
  2. package/LIMITATIONS.md +1 -0
  3. package/README.md +90 -31
  4. package/amp/settings.example.json +1 -1
  5. package/claude/claude_desktop_config.example.json +1 -1
  6. package/cline/cline_mcp_settings.example.json +1 -1
  7. package/copilot/mcp-config.example.json +1 -1
  8. package/dist/certify/attest.js +5 -5
  9. package/dist/certify/catalog.d.ts +1 -1
  10. package/dist/certify/catalog.js +3 -3
  11. package/dist/certify/context.js +1 -1
  12. package/dist/certify/evaluate.d.ts +2 -2
  13. package/dist/certify/evaluate.js +12 -12
  14. package/dist/certify/live.js +2 -2
  15. package/dist/certify/render.d.ts +1 -1
  16. package/dist/certify/render.js +10 -10
  17. package/dist/cli.d.ts +4 -2
  18. package/dist/cli.d.ts.map +1 -1
  19. package/dist/cli.js +110 -37
  20. package/dist/cli.js.map +1 -1
  21. package/dist/commands/certify.d.ts +1 -1
  22. package/dist/commands/certify.js +3 -3
  23. package/dist/commands/connect.d.ts +2 -2
  24. package/dist/commands/connect.js +22 -22
  25. package/dist/commands/dash.js +4 -4
  26. package/dist/commands/gate-serve.d.ts.map +1 -1
  27. package/dist/commands/gate-serve.js +19 -5
  28. package/dist/commands/gate-serve.js.map +1 -1
  29. package/dist/commands/gate.d.ts +1 -1
  30. package/dist/commands/gate.js +16 -16
  31. package/dist/commands/hook.d.ts +1 -1
  32. package/dist/commands/hook.d.ts.map +1 -1
  33. package/dist/commands/hook.js +55 -18
  34. package/dist/commands/hook.js.map +1 -1
  35. package/dist/commands/import-traces.d.ts +16 -0
  36. package/dist/commands/import-traces.d.ts.map +1 -0
  37. package/dist/commands/import-traces.js +18 -0
  38. package/dist/commands/import-traces.js.map +1 -0
  39. package/dist/commands/init.js +1 -1
  40. package/dist/commands/investigate.d.ts +13 -0
  41. package/dist/commands/investigate.d.ts.map +1 -0
  42. package/dist/commands/investigate.js +22 -0
  43. package/dist/commands/investigate.js.map +1 -0
  44. package/dist/commands/notify-flush.d.ts +2 -0
  45. package/dist/commands/notify-flush.d.ts.map +1 -0
  46. package/dist/commands/notify-flush.js +47 -0
  47. package/dist/commands/notify-flush.js.map +1 -0
  48. package/dist/commands/orr.d.ts +3 -3
  49. package/dist/commands/orr.js +5 -5
  50. package/dist/commands/receipt-serve.d.ts +1 -1
  51. package/dist/commands/receipt-serve.js +1 -1
  52. package/dist/commands/receipt.d.ts +5 -2
  53. package/dist/commands/receipt.d.ts.map +1 -1
  54. package/dist/commands/receipt.js +7 -4
  55. package/dist/commands/receipt.js.map +1 -1
  56. package/dist/commands/serve-mcp.js +1 -1
  57. package/dist/commands/start.d.ts +2 -2
  58. package/dist/commands/start.js +20 -20
  59. package/dist/commands/stop.d.ts +1 -1
  60. package/dist/commands/stop.js +6 -6
  61. package/dist/commands/update.d.ts +19 -0
  62. package/dist/commands/update.d.ts.map +1 -0
  63. package/dist/commands/update.js +96 -0
  64. package/dist/commands/update.js.map +1 -0
  65. package/dist/commands/wire-hooks.d.ts +1 -1
  66. package/dist/commands/wire-hooks.js +14 -14
  67. package/dist/commands/wrap.d.ts.map +1 -1
  68. package/dist/commands/wrap.js +12 -7
  69. package/dist/commands/wrap.js.map +1 -1
  70. package/dist/config.d.ts +4 -4
  71. package/dist/config.js +5 -5
  72. package/dist/dash/dash.d.ts +1 -1
  73. package/dist/dash/dash.js +3 -3
  74. package/dist/dash/entitlement.d.ts +1 -1
  75. package/dist/dash/entitlement.js +1 -1
  76. package/dist/dash/render.js +2 -2
  77. package/dist/dash/screens/enterprise.js +9 -9
  78. package/dist/dash/screens/free.js +5 -5
  79. package/dist/diff-preview.d.ts +1 -1
  80. package/dist/diff-preview.js +2 -2
  81. package/dist/errors.d.ts +1 -1
  82. package/dist/errors.js +1 -1
  83. package/dist/fs-atomic.d.ts +1 -1
  84. package/dist/fs-atomic.js +2 -2
  85. package/dist/gate/binary.js +4 -4
  86. package/dist/gate/config-gen.d.ts +1 -1
  87. package/dist/gate/config-gen.js +7 -7
  88. package/dist/gate/config.d.ts +2 -2
  89. package/dist/gate/config.js +6 -6
  90. package/dist/gate/daemon.js +1 -1
  91. package/dist/gate/discover.d.ts +2 -2
  92. package/dist/gate/discover.js +7 -7
  93. package/dist/gate/hosted-sync.js +1 -1
  94. package/dist/gate/otlp-decode.d.ts +2 -2
  95. package/dist/gate/otlp-decode.js +2 -2
  96. package/dist/gate/otlp-receiver.d.ts +1 -1
  97. package/dist/gate/otlp-receiver.js +3 -3
  98. package/dist/host-reload.js +11 -11
  99. package/dist/host-tools.d.ts +1 -1
  100. package/dist/host-tools.js +1 -1
  101. package/dist/importers/formats.d.ts +26 -0
  102. package/dist/importers/formats.d.ts.map +1 -0
  103. package/dist/importers/formats.js +281 -0
  104. package/dist/importers/formats.js.map +1 -0
  105. package/dist/importers/index.d.ts +26 -0
  106. package/dist/importers/index.d.ts.map +1 -0
  107. package/dist/importers/index.js +122 -0
  108. package/dist/importers/index.js.map +1 -0
  109. package/dist/index.d.ts +1 -1
  110. package/dist/index.js +1 -1
  111. package/dist/investigate/detectors.d.ts +35 -0
  112. package/dist/investigate/detectors.d.ts.map +1 -0
  113. package/dist/investigate/detectors.js +277 -0
  114. package/dist/investigate/detectors.js.map +1 -0
  115. package/dist/investigate/fix-brief.d.ts +3 -0
  116. package/dist/investigate/fix-brief.d.ts.map +1 -0
  117. package/dist/investigate/fix-brief.js +88 -0
  118. package/dist/investigate/fix-brief.js.map +1 -0
  119. package/dist/investigate/incidents.d.ts +19 -0
  120. package/dist/investigate/incidents.d.ts.map +1 -0
  121. package/dist/investigate/incidents.js +84 -0
  122. package/dist/investigate/incidents.js.map +1 -0
  123. package/dist/investigate/index.d.ts +25 -0
  124. package/dist/investigate/index.d.ts.map +1 -0
  125. package/dist/investigate/index.js +46 -0
  126. package/dist/investigate/index.js.map +1 -0
  127. package/dist/mcp/protocol.d.ts +2 -2
  128. package/dist/mcp/protocol.d.ts.map +1 -1
  129. package/dist/mcp/protocol.js +39 -8
  130. package/dist/mcp/protocol.js.map +1 -1
  131. package/dist/mcp/stdio.d.ts +1 -1
  132. package/dist/mcp/stdio.js +2 -2
  133. package/dist/mcp-servers.d.ts +2 -2
  134. package/dist/mcp-servers.js +2 -2
  135. package/dist/node-upgrade.d.ts +2 -2
  136. package/dist/node-upgrade.js +9 -9
  137. package/dist/notify/dispatch.d.ts +20 -0
  138. package/dist/notify/dispatch.d.ts.map +1 -0
  139. package/dist/notify/dispatch.js +52 -0
  140. package/dist/notify/dispatch.js.map +1 -0
  141. package/dist/notify/index.d.ts +39 -0
  142. package/dist/notify/index.d.ts.map +1 -0
  143. package/dist/notify/index.js +119 -0
  144. package/dist/notify/index.js.map +1 -0
  145. package/dist/notify/sender.d.ts +56 -0
  146. package/dist/notify/sender.d.ts.map +1 -0
  147. package/dist/notify/sender.js +139 -0
  148. package/dist/notify/sender.js.map +1 -0
  149. package/dist/notify/templates.d.ts +33 -0
  150. package/dist/notify/templates.d.ts.map +1 -0
  151. package/dist/notify/templates.js +119 -0
  152. package/dist/notify/templates.js.map +1 -0
  153. package/dist/offline-evaluate.d.ts +2 -2
  154. package/dist/offline-evaluate.js +3 -3
  155. package/dist/orr/agentshield.d.ts +2 -2
  156. package/dist/orr/agentshield.js +4 -4
  157. package/dist/orr/scorecard.d.ts +1 -1
  158. package/dist/orr/scorecard.js +3 -3
  159. package/dist/otel/exporter.d.ts +64 -0
  160. package/dist/otel/exporter.d.ts.map +1 -0
  161. package/dist/otel/exporter.js +243 -0
  162. package/dist/otel/exporter.js.map +1 -0
  163. package/dist/parse-args.d.ts +1 -1
  164. package/dist/parse-args.js +1 -1
  165. package/dist/receipt/auto-open.d.ts +1 -1
  166. package/dist/receipt/auto-open.js +1 -1
  167. package/dist/receipt/daemon.d.ts +6 -6
  168. package/dist/receipt/daemon.js +15 -15
  169. package/dist/receipt/dashboard.d.ts +1 -1
  170. package/dist/receipt/dashboard.js +2 -2
  171. package/dist/receipt/embeddings.d.ts +15 -4
  172. package/dist/receipt/embeddings.d.ts.map +1 -1
  173. package/dist/receipt/embeddings.js +116 -35
  174. package/dist/receipt/embeddings.js.map +1 -1
  175. package/dist/receipt/enrich.d.ts +2 -2
  176. package/dist/receipt/enrich.js +5 -5
  177. package/dist/receipt/gate-card.d.ts +2 -2
  178. package/dist/receipt/gate-card.d.ts.map +1 -1
  179. package/dist/receipt/gate-card.js +3 -3
  180. package/dist/receipt/live-server.d.ts.map +1 -1
  181. package/dist/receipt/live-server.js +22 -8
  182. package/dist/receipt/live-server.js.map +1 -1
  183. package/dist/receipt/receipt-css.d.ts +1 -1
  184. package/dist/receipt/receipt-css.d.ts.map +1 -1
  185. package/dist/receipt/receipt-css.js +72 -11
  186. package/dist/receipt/receipt-css.js.map +1 -1
  187. package/dist/receipt/render-receipt.d.ts +1 -1
  188. package/dist/receipt/render-receipt.d.ts.map +1 -1
  189. package/dist/receipt/render-receipt.js +138 -87
  190. package/dist/receipt/render-receipt.js.map +1 -1
  191. package/dist/receipt/share.d.ts +21 -2
  192. package/dist/receipt/share.d.ts.map +1 -1
  193. package/dist/receipt/share.js +68 -5
  194. package/dist/receipt/share.js.map +1 -1
  195. package/dist/sample-tools.d.ts +1 -1
  196. package/dist/sample-tools.js +1 -1
  197. package/dist/sandbox/mock-driver.d.ts +1 -1
  198. package/dist/sandbox/mock-driver.js +1 -1
  199. package/dist/sdk/a2a.d.ts +2 -2
  200. package/dist/sdk/a2a.js +1 -1
  201. package/dist/sdk/adapters/claude-agent.d.ts +1 -1
  202. package/dist/sdk/adapters/claude-agent.js +1 -1
  203. package/dist/sdk/adapters/langgraph.d.ts +1 -1
  204. package/dist/sdk/adapters/langgraph.js +1 -1
  205. package/dist/sdk/adapters/mastra.d.ts +1 -1
  206. package/dist/sdk/adapters/mastra.js +1 -1
  207. package/dist/sdk/adapters/openai-agents.d.ts +1 -1
  208. package/dist/sdk/adapters/openai-agents.js +1 -1
  209. package/dist/sdk/adapters/vercel-ai.d.ts +2 -2
  210. package/dist/sdk/adapters/vercel-ai.js +1 -1
  211. package/dist/sdk/govern.d.ts +2 -2
  212. package/dist/sdk/govern.js +3 -3
  213. package/dist/sdk/index.d.ts +1 -1
  214. package/dist/sdk/index.js +1 -1
  215. package/dist/showback/trail-usage.d.ts +30 -0
  216. package/dist/showback/trail-usage.d.ts.map +1 -0
  217. package/dist/showback/trail-usage.js +50 -0
  218. package/dist/showback/trail-usage.js.map +1 -0
  219. package/dist/sign/evidence-bundle.d.ts +6 -6
  220. package/dist/sign/evidence-bundle.js +5 -5
  221. package/dist/star-cta.d.ts +1 -1
  222. package/dist/star-cta.d.ts.map +1 -1
  223. package/dist/star-cta.js +3 -3
  224. package/dist/telemetry.d.ts +135 -0
  225. package/dist/telemetry.d.ts.map +1 -0
  226. package/dist/telemetry.js +427 -0
  227. package/dist/telemetry.js.map +1 -0
  228. package/dist/trail-summary.d.ts +1 -1
  229. package/dist/trail-summary.js +3 -3
  230. package/dist/trail.d.ts +8 -2
  231. package/dist/trail.d.ts.map +1 -1
  232. package/dist/trail.js +18 -5
  233. package/dist/trail.js.map +1 -1
  234. package/dist/update-check.d.ts +17 -0
  235. package/dist/update-check.d.ts.map +1 -0
  236. package/dist/update-check.js +134 -0
  237. package/dist/update-check.js.map +1 -0
  238. package/droid/README.md +1 -1
  239. package/droid/mcp.example.json +1 -1
  240. package/gemini/settings.example.json +1 -1
  241. package/grok/README.md +1 -1
  242. package/kilo/kilo.example.json +1 -1
  243. package/kimi/mcp.example.json +1 -1
  244. package/kiro/mcp.example.json +1 -1
  245. package/manifest.json +1 -1
  246. package/mastracode/mcp.example.json +1 -1
  247. package/mcp.json +1 -1
  248. package/openai/codex.config.example.toml +1 -1
  249. package/opencode/opencode.example.json +1 -1
  250. package/package.json +4 -3
  251. package/qwen/settings.example.json +1 -1
  252. package/server.json +2 -2
package/.mcp.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "mcpServers": {
3
3
  "shield-kya": {
4
4
  "command": "npx",
5
- "args": ["--no-install", "@shield-agent/kya@0.21.0", "serve-mcp", "--stdio"],
5
+ "args": ["--no-install", "@shield-agent/kya@0.23.0", "serve-mcp", "--stdio"],
6
6
  "env": {
7
7
  "KYA_BASE_URL": "https://shield-agent.com",
8
8
  "KYA_API_KEY": "${KYA_API_KEY}",
package/LIMITATIONS.md CHANGED
@@ -21,6 +21,7 @@
21
21
  - Use OPA if you need a general policy language. On hosted, OPA is an optional PDP (Rego allowlists under `infra/podman/opa/packs/`) that may only further DENY on evaluate and invoke; Shield stays the PEP. Fail-closed when enabled and unreachable. Per-merchant package path + packId map ship; hosted IdP group→tool maps fail-closed without verified groups; `kya.policy.evaluated` SIEM webhook on evaluate. Agent OIDC assertion is a fail-closed stub until JWKS. Not inside this npm package.
22
22
  - Multi-tenant density, private registries, ORR board ops, pin, and support are separate from the solo `npx` path.
23
23
  - Growth counts are observe metrics (principals, evaluates, approvals).
24
+ - Anonymous usage stats (`kya telemetry`) are opt-in and off by default: asked once on a terminal, never in CI or `--json`. The long-running gate, report and gateway processes send a heartbeat. `kya hook` never touches the network itself; it starts a detached helper at most once a day that sends a single `ping`, so hook-only installs count as active but never as live sessions. See `docs/telemetry.md`.
24
25
  - OTLP metrics are opt-in and off by default. OSS CLI is thin (evaluate latency only). Hosted is richer Micrometer export. Neither path is a policy decision. See `docs/otlp.md`.
25
26
 
26
27
  - Showback USD is an estimate from a checked-in published rate table. Unknown models report tokens only. ORR / metrics never ALLOW, DENY, or kill on spend.
package/README.md CHANGED
@@ -8,7 +8,7 @@
8
8
  [![X](https://img.shields.io/badge/X-%40coscosmico-000000?logo=x&logoColor=white)](https://x.com/coscosmico)
9
9
 
10
10
 
11
- **AI agents audit trail & traceability.** Every tool call your coding agents make — gated (Allow / Review / Deny), recorded on a live local dashboard, and certifiable against the Agent Trust Baseline. One command. Free forever under MIT.
11
+ **AI agents audit trail & traceability.** Every tool call your coding agents make - gated (Allow / Review / Deny), recorded on a live local dashboard, and certifiable against the Agent Trust Baseline. One command. Free forever under MIT.
12
12
 
13
13
  ```bash
14
14
  npm i -g @shield-agent/kya@latest && kya start
@@ -27,7 +27,7 @@ Walkthrough: [how you use it](https://shield-agent.com/how-kya-works#using).
27
27
  npx @shield-agent/kya@latest --help
28
28
  ```
29
29
 
30
- Requires **Node.js 24+** (`engines.node: >=24`). On an older Node the CLI offers to install 24 for you (via volta / fnm / nvm / brew), reinstall itself, and finish the command — declining just prints a warning and continues.
30
+ Requires **Node.js 24+** (`engines.node: >=24`). On an older Node the CLI offers to install 24 for you (via volta / fnm / nvm / brew), reinstall itself, and finish the command - declining just prints a warning and continues.
31
31
 
32
32
  It works with any host that speaks MCP or OpenAPI. Vertical packs are optional. Shield is the only policy decision point: this gate never auto-approves an irreversible side effect.
33
33
 
@@ -43,17 +43,17 @@ npm i -g @shield-agent/kya@latest && kya start
43
43
 
44
44
  Run it in your project directory. (From a clone of this repo, `./scripts/install-local.sh` replaces the npm install.)
45
45
 
46
- That **inits** `.kya/`, **wires** local MCP (`.mcp.json`, `mcp.json`, `.cursor/mcp.json` → `kya serve-mcp --stdio`), also **wires user-level configs for every installed host it detects** (`~/.claude.json`, `~/.kimi-code/`, `~/.grok/`, `~/.cursor/`, …), and **opens** the live activity report. The report runs in the background — you get your terminal back; `kya stop` stops it, `kya receipt --open` reopens it. Cursor, Kiro, Qwen, Amp, Droid, Cline, and Grok pick the server up live with no restart (Kimi: just a new session); Claude Code, Codex, OpenCode, Gemini, Copilot CLI, and Kilo CLI load it on next launch — `claude --resume` keeps your conversation.
46
+ That **inits** `.kya/`, **wires** local MCP (`.mcp.json`, `mcp.json`, `.cursor/mcp.json` → `kya serve-mcp --stdio`), also **wires user-level configs for every installed host it detects** (`~/.claude.json`, `~/.kimi-code/`, `~/.grok/`, `~/.cursor/`, …), and **opens** the live activity report. The report runs in the background - you get your terminal back; `kya stop` stops it, `kya receipt --open` reopens it. Cursor, Kiro, Qwen, Amp, Droid, Cline, and Grok pick the server up live with no restart (Kimi: just a new session); Claude Code, Codex, OpenCode, Gemini, Copilot CLI, and Kilo CLI load it on next launch - `claude --resume` keeps your conversation.
47
47
 
48
- ![KYA report — live dashboard: Certify trust baseline, verdicts, analytics](https://raw.githubusercontent.com/The-Pixel-Boys/shield-kya/main/assets/report-overview.png)
48
+ ![KYA report - live dashboard: Certify trust baseline, verdicts, analytics](https://raw.githubusercontent.com/The-Pixel-Boys/shield-kya/main/assets/report-overview.png)
49
49
 
50
- ![Certify tab — full Agent Trust Baseline requirement table with evidence](https://raw.githubusercontent.com/The-Pixel-Boys/shield-kya/main/assets/report-certify.png)
50
+ ![Certify tab - full Agent Trust Baseline requirement table with evidence](https://raw.githubusercontent.com/The-Pixel-Boys/shield-kya/main/assets/report-certify.png)
51
51
 
52
- ![Activity tab — filterable agent tool-call feed with verdicts](https://raw.githubusercontent.com/The-Pixel-Boys/shield-kya/main/assets/report-activity.png)
52
+ ![Activity tab - filterable agent tool-call feed with verdicts](https://raw.githubusercontent.com/The-Pixel-Boys/shield-kya/main/assets/report-activity.png)
53
53
 
54
- ![Changes tab — what actually changed per session: files touched with redacted diff previews](https://raw.githubusercontent.com/The-Pixel-Boys/shield-kya/main/assets/report-changes.png)
54
+ ![Changes tab - what actually changed per session: files touched with redacted diff previews](https://raw.githubusercontent.com/The-Pixel-Boys/shield-kya/main/assets/report-changes.png)
55
55
 
56
- ![Gateway section — local MCP gate with listeners, routes, backends, policies, and a dry-run playground](https://raw.githubusercontent.com/The-Pixel-Boys/shield-kya/main/assets/report-gateway.png)
56
+ ![Gateway section - local MCP gate with listeners, routes, backends, policies, and a dry-run playground](https://raw.githubusercontent.com/The-Pixel-Boys/shield-kya/main/assets/report-gateway.png)
57
57
 
58
58
  <!-- Local paths kept in package for offline viewers: assets/report-overview.png, assets/report-certify.png, assets/report-activity.png, assets/report-changes.png, assets/report-gateway.png (legacy: assets/activity-receipt.png) -->
59
59
 
@@ -66,7 +66,7 @@ kya start --force # rewrite MCP blocks
66
66
 
67
67
  ## One command per host
68
68
 
69
- `kya start` covers Claude Code, Cursor, and any host that reads `.mcp.json` — and auto-wires the user-level config of every installed host it detects. For the rest, `kya connect` writes the host's own config dialect directly:
69
+ `kya start` covers Claude Code, Cursor, and any host that reads `.mcp.json` - and auto-wires the user-level config of every installed host it detects. For the rest, `kya connect` writes the host's own config dialect directly:
70
70
 
71
71
  ```bash
72
72
  kya connect claude # ~/.claude.json (merges mcpServers only)
@@ -78,17 +78,17 @@ kya connect qwen --project # project scope instead of global
78
78
  kya connect kiro --force # overwrite an existing shield-kya entry
79
79
  ```
80
80
 
81
- Connect merges — it never rewrites a host config it can't parse, and it keeps your other servers and keys. Supported hosts: `claude`, `grok`, `opencode`, `kilo`, `kiro`, `qwen`, `kimi`, `mastracode`, `amp`, `copilot`, `cursor`. Each wires `serve-mcp --stdio` with `KYA_OFFLINE=1` so the gate starts keyless; set `KYA_API_KEY` in the host env when you point at an authenticated plane.
81
+ Connect merges - it never rewrites a host config it can't parse, and it keeps your other servers and keys. Supported hosts: `claude`, `grok`, `opencode`, `kilo`, `kiro`, `qwen`, `kimi`, `mastracode`, `amp`, `copilot`, `cursor`. Each wires `serve-mcp --stdio` with `KYA_OFFLINE=1` so the gate starts keyless; set `KYA_API_KEY` in the host env when you point at an authenticated plane.
82
82
 
83
83
  Hosts without a `connect` target still work: `kya wrap --offline -- <agent command>` puts the same evaluate gate in front of any CLI. Per-host recipes with verify steps and troubleshooting live in [docs/hosts/](docs/hosts/).
84
84
 
85
85
  ## Hook interception
86
86
 
87
- `kya start` also wires a `PreToolUse` hook into every installed hook-capable host it detects: Claude Code (`~/.claude/settings.json`, merge-only), Grok (`~/.grok/hooks/shield-kya.json`, kya-managed file), and Kimi Code (`~/.kimi-code/config.toml`, `[[hooks]]` append). Every tool call the agent makes then passes through `kya hook` first: evaluated locally (offline, sub-second, no network) and recorded on the global trail.
87
+ `kya start` also wires a `PreToolUse` hook into every installed hook-capable host it detects: Claude Code (`~/.claude/settings.json`, merge-only), Grok (`~/.grok/hooks/shield-kya.json`, kya-managed file), and Kimi Code (`~/.kimi-code/config.toml`, `[[hooks]]` append). Every tool call the agent makes then passes through `kya hook` first: evaluated locally (offline, sub-second, no network) and recorded on the global trail. (If you opted in to anonymous usage stats, the hook also starts a detached helper at most once a day; see [Anonymous usage stats](#anonymous-usage-stats-opt-in-off-by-default).)
88
88
 
89
89
  Decision mapping: a local never-list **DENY** blocks the tool call (exit `2` plus `hookSpecificOutput` deny JSON with `permissionDecision: "deny"`). **ALLOW** and **REQUIRE_APPROVE** are recorded on the trail as advisory and the call proceeds. Manual wiring can pass `--strict` on the hook command to also block **REQUIRE_APPROVE**.
90
90
 
91
- Hooks are fail-open: any hook error or timeout allows the call. They are alerts plus local never-list enforcement, not the sole barrier — plane enforcement remains the MCP `kya.policy_evaluate` path. Hooks take effect in new sessions; all three hosts load hooks at session start.
91
+ Hooks are fail-open: any hook error or timeout allows the call. They are alerts plus local never-list enforcement, not the sole barrier - plane enforcement remains the MCP `kya.policy_evaluate` path. Hooks take effect in new sessions; all three hosts load hooks at session start.
92
92
 
93
93
  ```bash
94
94
  kya connect claude --hooks # wire the PreToolUse hook by hand
@@ -98,9 +98,9 @@ kya connect kimi --hooks
98
98
 
99
99
  ## Gate (local MCP gateway)
100
100
 
101
- `kya gate` puts one loopback-only listener (`127.0.0.1`, default port `3930`) in front of any MCP server you already use. Your host talks to the gateway; the gateway fans out to the real servers. Per-tool policy is generated from the [top-20 server taxonomy](docs/mcp-servers.md) — destructive names (`drop`/`truncate`/`purge`/`transfer`) and each server's ADMIN-tier tools are denied outright (and filtered from `tools/list`), everything else runs in observe mode: allowed, and audited. Every call is traced into the local trail and the live report, and can be forwarded as OTLP to the hosted intake.
101
+ `kya gate` puts one loopback-only listener (`127.0.0.1`, default port `3930`) in front of any MCP server you already use. Your host talks to the gateway; the gateway fans out to the real servers. Per-tool policy is generated from the [top-20 server taxonomy](docs/mcp-servers.md) - destructive names (`drop`/`truncate`/`purge`/`transfer`) and each server's ADMIN-tier tools are denied outright (and filtered from `tools/list`), everything else runs in observe mode: allowed, and audited. Every call is traced into the local trail and the live report, and can be forwarded as OTLP to the hosted intake.
102
102
 
103
- **Zero-touch:** `kya start` already does this for you. It scans your detected host configs for third-party MCP servers, imports them into `.kya/gateways.json` (recorded with an `importedFrom` provenance field), installs the gateway binary, starts the listener, and rewrites each source host so the imported servers route through the gateway — the original host config is preserved under `.kya/backups/` before anything is removed. Nothing found → nothing downloaded, no listener. Opt out with `kya start --no-gate` or `KYA_GATE=off`. If the binary download fails (offline, no network), `kya start` warns once and continues without the gateway — host configs stay untouched. The manual path below is still there when you want full control:
103
+ **Zero-touch:** `kya start` already does this for you. It scans your detected host configs for third-party MCP servers, imports them into `.kya/gateways.json` (recorded with an `importedFrom` provenance field), installs the gateway binary, starts the listener, and rewrites each source host so the imported servers route through the gateway - the original host config is preserved under `.kya/backups/` before anything is removed. Nothing found → nothing downloaded, no listener. Opt out with `kya start --no-gate` or `KYA_GATE=off`. If the binary download fails (offline, no network), `kya start` warns once and continues without the gateway - host configs stay untouched. The manual path below is still there when you want full control:
104
104
 
105
105
  ```bash
106
106
  kya gate init # scaffold .kya/gateways.json with ready-to-move recipes
@@ -111,7 +111,7 @@ kya connect claude --gate # point the host at the gateway (server key shield-k
111
111
  kya gate doctor # binary, config, listener health, loopback-only posture
112
112
  ```
113
113
 
114
- `kya gate stop` stops the supervisor and the binary with it. Honest notes: `kya gate setup` (and `kya start`'s auto-bootstrap, only when it found servers to govern) downloads the pinned gateway binary from our releases — nothing else fetches anything; `run` never downloads. Observe mode means allowed calls are recorded, not blocked — the deny set above is the only hard stop, and plane enforcement stays with `kya.policy_evaluate`. `kya connect <host> --gate` covers the same hosts as plain `connect` — grok gets a `[mcp_servers.shield-kya-gate]` url table in its config.toml (Grok supports remote MCP servers over HTTP). Per-server tiers and recipes: [docs/mcp-servers.md](docs/mcp-servers.md).
114
+ `kya gate stop` stops the supervisor and the binary with it. Honest notes: `kya gate setup` (and `kya start`'s auto-bootstrap, only when it found servers to govern) downloads the pinned gateway binary from our releases - nothing else downloads anything (the only other network use is the opt-in anonymous usage stats in [docs/telemetry.md](docs/telemetry.md), off unless you say yes); `run` never downloads. Observe mode means allowed calls are recorded, not blocked - the deny set above is the only hard stop, and plane enforcement stays with `kya.policy_evaluate`. `kya connect <host> --gate` covers the same hosts as plain `connect` - grok gets a `[mcp_servers.shield-kya-gate]` url table in its config.toml (Grok supports remote MCP servers over HTTP). Per-server tiers and recipes: [docs/mcp-servers.md](docs/mcp-servers.md).
115
115
 
116
116
  ## Longer path (optional)
117
117
 
@@ -130,17 +130,19 @@ Install hub: [https://shield-agent.com/install](https://shield-agent.com/install
130
130
 
131
131
  ## Activity trail (global)
132
132
 
133
- One trail for all projects: `~/.kya/trail.jsonl` (`KYA_HOME` overrides `~`). `kya receipt --open` from any directory shows activity from every project. Each event carries its project folder name — the report adds a Projects rollup once two or more projects appear, and shows the project on each feed entry. Older per-project `<project>/.kya/trail.jsonl` files are still read and merged; no migration. The trail is capped at 1 MB (tail-read: oldest events drop away), shared across all projects.
133
+ One trail for all projects: `~/.kya/trail.jsonl` (`KYA_HOME` overrides `~`). `kya receipt --open` from any directory shows activity from every project. Each event carries its project folder name - the report adds a Projects rollup once two or more projects appear, and shows the project on each feed entry. Older per-project `<project>/.kya/trail.jsonl` files are still read and merged; no migration. The trail is capped at 1 MB (tail-read: oldest events drop away), shared across all projects.
134
134
 
135
- The report itself is a dashboard: a hero row on top (live **Certify** result, verdict mix, activity sparkline, showback) with tabbed sections below — **Overview** (analytics, sessions, reasons), **Certify** (the full live requirement table — every requirement grouped by domain with status, evidence, and attestation), **Activity** (the filterable event feed), **System** (wired hosts, sandboxes, ORR). Everything is one standalone offline HTML page (the live view adds a single external link: "Star on GitHub"); the live daemon from `kya start` re-renders it on every event.
135
+ The report itself is a dashboard: a hero row on top (live **Certify** result, verdict mix, activity sparkline, showback) with tabbed sections below - **Overview** (analytics, sessions, reasons), **Certify** (the full live requirement table - every requirement grouped by domain with status, evidence, and attestation), **Activity** (the filterable event feed), **System** (wired hosts, sandboxes, ORR). Everything is one standalone offline HTML page (the live view adds a single external link: "Star on GitHub"); the live daemon from `kya start` re-renders it on every event.
136
136
 
137
137
  ### Sharing a report
138
138
 
139
- `kya receipt --share` publishes a **redacted summary** of the current window (aggregate verdict counts, product and reason-code rollups, and the Certify status — no paths, no tool arguments, no session IDs) to shield-agent.com and prints a public URL (`/r/<id>`, expires after 7 days) anyone can open — every shared page carries the one-line install so readers can audit their own agents. Point it at a different collector with `--share-url <base>` or `KYA_SHARE_URL`.
139
+ `kya receipt --share` publishes a **redacted summary** of the current window (aggregate verdict counts, product and reason-code rollups, and the Certify status - no paths, no tool arguments, no session IDs) to shield-agent.com and prints a public URL (`/r/<id>`, expires after 7 days) anyone can open - every shared page carries the one-line install so readers can audit their own agents. Point it at a different collector with `--share-url <base>` or `KYA_SHARE_URL`.
140
+
141
+ Sharing is a single attempt by design (storm-proof: no silent retries against the collector); `--share-retries <n>` (max 3) opts into bounded retries on 429/5xx/network failures with exponential backoff + jitter, honoring the server's `Retry-After`.
140
142
 
141
143
  ### Natural-language search
142
144
 
143
- The **Activity** search box understands plain English. It runs a hybrid of BM25 over tool IDs, summaries, reason codes, projects, and MCP server labels, plus optional local MiniLM semantic reranking. You can type things like `failed stripe transfers`, `files written by grok`, or `approval required production` — stopwords and stemming are handled automatically, and the same search works across the global trail.
145
+ The **Activity** search box understands plain English. It runs a hybrid of BM25 over tool IDs, summaries, reason codes, projects, and MCP server labels, plus optional local MiniLM semantic reranking. You can type things like `failed stripe transfers`, `files written by grok`, or `approval required production` - stopwords and stemming are handled automatically, and the same search works across the global trail.
144
146
 
145
147
  - Offline or `KYA_OFFLINE=1` keeps search purely lexical (no model download).
146
148
  - By default the live server downloads `BAAI/bge-small-en-v1.5` once into `~/.kya/models` and caches event vectors in `~/.kya/search-index.json`.
@@ -177,9 +179,11 @@ Tag sessions with `KYA_HOST=ide` or `KYA_HOST=runtime`. Same policy path either
177
179
  | `KYA_RECEIPT_AUTO` | No | `0` disables auto-open receipt after wrap; `1` forces |
178
180
  | `KYA_SEARCH_SEMANTIC` | No | `off` disables MiniLM semantic reranking (BM25 still works) |
179
181
  | `KYA_SHARE_URL` | No | `kya receipt --share` collector base (default `https://shield-agent.com`) |
182
+ | `KYA_TELEMETRY` | No | `0`/`off` forces anonymous usage stats off ([docs/telemetry.md](docs/telemetry.md)); they are off unless you opted in |
183
+ | `DO_NOT_TRACK` | No | `1` forces anonymous usage stats off, same as `KYA_TELEMETRY=0` |
180
184
 
181
185
  Gate mode can also be pinned in the project's `.kya/config.json`:
182
- `{"gateMode": "hold"}` or `{"gateMode": "offline"}` (exact values only —
186
+ `{"gateMode": "hold"}` or `{"gateMode": "offline"}` (exact values only -
183
187
  anything else is ignored). The gate itself (wrap / hook / eval) honors it
184
188
  with the precedence flags > env > config > observe, and `kya certify`
185
189
  reports through the same resolver, so a certify pass on gate mode always
@@ -200,7 +204,7 @@ MCP Registry entry: `server.json` plus package `mcpName` `io.github.The-Pixel-Bo
200
204
  "mcpServers": {
201
205
  "shield-kya": {
202
206
  "command": "npx",
203
- "args": ["--no-install", "@shield-agent/kya@0.21.0", "serve-mcp", "--stdio"],
207
+ "args": ["--no-install", "@shield-agent/kya@0.23.0", "serve-mcp", "--stdio"],
204
208
  "env": {
205
209
  "KYA_BASE_URL": "http://127.0.0.1:8090",
206
210
  "KYA_API_KEY": "${KYA_API_KEY}",
@@ -240,7 +244,7 @@ Offline evaluate by default (no network, no hosted plane); an explicit config ho
240
244
 
241
245
  ```bash
242
246
  # Prefer a preinstalled package (no registry auto-install):
243
- npx --no-install @shield-agent/kya@0.21.0 serve-mcp --stdio
247
+ npx --no-install @shield-agent/kya@0.23.0 serve-mcp --stdio
244
248
  # Or after npm i -g / local install:
245
249
  kya serve-mcp --stdio
246
250
  ```
@@ -251,7 +255,7 @@ Copy `claude/claude_desktop_config.example.json` into Claude Desktop MCP setting
251
255
 
252
256
  ## OpenAI (Codex / Responses)
253
257
 
254
- **Codex CLI / IDE:** copy `openai/codex.config.example.toml` into `~/.codex/config.toml`. Local stdio uses `npx --no-install @shield-agent/kya@0.21.0 serve-mcp --stdio`. Hosted Codex uses `url = "https://shield-agent.com/mcp"` with `bearer_token_env_var = "KYA_API_KEY"`.
258
+ **Codex CLI / IDE:** copy `openai/codex.config.example.toml` into `~/.codex/config.toml`. Local stdio uses `npx --no-install @shield-agent/kya@0.23.0 serve-mcp --stdio`. Hosted Codex uses `url = "https://shield-agent.com/mcp"` with `bearer_token_env_var = "KYA_API_KEY"`.
255
259
 
256
260
  **Responses API:** see `openai/responses-mcp.example.json` (`server_url` + `Authorization: Bearer <KYA_API_KEY>`).
257
261
 
@@ -273,8 +277,8 @@ Each ships a copy-paste example in its own directory; `kya connect <host>` write
273
277
 
274
278
  | Host | Setup | Example |
275
279
  |------|-------|---------|
276
- | Claude Code | `kya connect claude` (or `kya start`) | — (merges `~/.claude.json` / `.mcp.json`) |
277
- | Grok CLI | `kya connect grok` | — (appends `[mcp_servers.shield-kya]` to `~/.grok/config.toml`) |
280
+ | Claude Code | `kya connect claude` (or `kya start`) | - (merges `~/.claude.json` / `.mcp.json`) |
281
+ | Grok CLI | `kya connect grok` | - (appends `[mcp_servers.shield-kya]` to `~/.grok/config.toml`) |
278
282
  | OpenCode | `kya connect opencode` | `opencode/opencode.example.json` |
279
283
  | Kilo Code | `kya connect kilo` | `kilo/kilo.example.json` |
280
284
  | Kiro | `kya connect kiro` | `kiro/mcp.example.json` |
@@ -303,7 +307,7 @@ ORR is a reporting board. Scanners, `--scorecard`, and `harness.agentshield` are
303
307
 
304
308
  ## Certify (continuous agent assurance)
305
309
 
306
- `kya certify` evaluates the open **Agent Trust Baseline** catalog (`catalog/agent-trust-baseline-v0.json` — 30 requirements across Data & Privacy, Security, Safety, Reliability, Accountability, Society) against local evidence: the global trail, ORR output, wired hosts, sandbox inventory, receipts, showback, and your recorded attestations. It writes a gap report to `.kya/certify/` (JSON + Markdown + HTML). The gap list is your work plan. The receipt report shows the same state live: a **Certify** panel recomputed on every render (so `kya start`'s live report updates as events stream in), plus a dedicated **Certify** tab with the full live requirement table — run `kya certify` for the full gap report + signed evidence bundle.
310
+ `kya certify` evaluates the open **Agent Trust Baseline** catalog (`catalog/agent-trust-baseline-v0.json` - 30 requirements across Data & Privacy, Security, Safety, Reliability, Accountability, Society) against local evidence: the global trail, ORR output, wired hosts, sandbox inventory, receipts, showback, and your recorded attestations. It writes a gap report to `.kya/certify/` (JSON + Markdown + HTML). The gap list is your work plan. The receipt report shows the same state live: a **Certify** panel recomputed on every render (so `kya start`'s live report updates as events stream in), plus a dedicated **Certify** tab with the full live requirement table - run `kya certify` for the full gap report + signed evidence bundle.
307
311
 
308
312
  ```bash
309
313
  npx @shield-agent/kya certify # gap report; exit 1 when gaps exist (CI-friendly)
@@ -313,11 +317,49 @@ npx @shield-agent/kya certify --attest SOC-01 --text "Acceptable-use policy: htt
313
317
  npx @shield-agent/kya certify --sign # also emit a signed evidence-bundle.json
314
318
  ```
315
319
 
316
- Certify is **evidence-only**. It never ALLOWs, DENYs, or blocks anything — the sole PEP remains Shield KYA. Trail-based machine checks never pass on an empty trail (they report `insufficient_evidence`). What a machine cannot check is covered by explicit local attestations (`--attest`), recorded in `.kya/attestations.json` — unverified operator statements, labeled as such.
320
+ Certify is **evidence-only**. It never ALLOWs, DENYs, or blocks anything - the sole PEP remains Shield KYA. Trail-based machine checks never pass on an empty trail (they report `insufficient_evidence`). What a machine cannot check is covered by explicit local attestations (`--attest`), recorded in `.kya/attestations.json` - unverified operator statements, labeled as such.
321
+
322
+ `--sign` emits `evidence-bundle.json`: canonical JSON, ed25519-signed by a locally generated key (`~/.kya/keys/evidence-ed25519.json`, mode 0600, auto-created on first use). Each `--sign` run prints the signing key fingerprint; when the key was just created the CLI notes that key continuity resets there (earlier bundles stay verifiable only under the old pubkey). A self-signed developer key proves bundle **integrity** and **continuity of a key** - **not identity**. Identity binding and the verified badge are the hosted verification product (separate). The bundle format is open and documented in `docs/certify.md`; anyone can verify a bundle offline with the embedded pubkey.
323
+
324
+ `kya certify` is local, free, and offline: no account, no network calls, no license check (it never sends usage stats). The catalog is MIT-licensed and PRs are welcome. An EU AI Act crosswalk (baseline requirements mapped to Articles 9-15, 26, 72) ships in [docs/certify-eu-ai-act.md](docs/certify-eu-ai-act.md) and `src/certify/eu-ai-act-map.json`.
325
+
326
+ ## Import traces (LangSmith, Langfuse, Phoenix, OTel)
327
+
328
+ Bring existing observability exports into the trail so the receipt and certify see them:
329
+
330
+ ```bash
331
+ kya import --from langsmith ./runs.json
332
+ kya import --from langfuse ./observations.jsonl
333
+ kya import --from otel ./otraces.json
334
+ ```
335
+
336
+ Imports land as observe-mode events (`host: import`, `reasonCode: IMPORTED`, error runs become `DENY`/`IMPORTED_ERROR`), with latency and token counts mapped when the source carries them. Files over 50MB are refused; malformed records are skipped, never fatal.
337
+
338
+ ## Investigate (detections + fix briefs)
339
+
340
+ `kya investigate` runs deterministic local detectors over the trail - no LLM calls: PII leaks in summaries, DENY spikes, approval retry loops, repeated never-event attempts, unknown tools under hold, slow tools. Findings group into incidents, and each incident renders a markdown fix brief shaped to paste into Claude Code / Cursor / Codex.
341
+
342
+ ```bash
343
+ kya investigate # summary: counts by severity + top incidents
344
+ kya investigate --json # findings + incidents + briefs, machine-readable
345
+ ```
346
+
347
+ ## Alert webhooks (verdict routing)
348
+
349
+ Route DENY / REQUIRE_APPROVE events to Slack, Linear, Jira, or any webhook. Config lives in `.kya/config.json` (project) or `~/.kya/config.json` (global):
317
350
 
318
- `--sign` emits `evidence-bundle.json`: canonical JSON, ed25519-signed by a locally generated key (`~/.kya/keys/evidence-ed25519.json`, mode 0600, auto-created on first use). Each `--sign` run prints the signing key fingerprint; when the key was just created the CLI notes that key continuity resets there (earlier bundles stay verifiable only under the old pubkey). A self-signed developer key proves bundle **integrity** and **continuity of a key** — **not identity**. Identity binding and the verified badge are the hosted verification product (separate). The bundle format is open and documented in `docs/certify.md`; anyone can verify a bundle offline with the embedded pubkey.
351
+ ```json
352
+ {
353
+ "notify": {
354
+ "webhooks": [
355
+ { "url": "https://hooks.slack.com/services/...", "template": "slack", "events": ["DENY", "REQUIRE_APPROVE"] },
356
+ { "url": "https://example.invalid/jira", "template": "jira", "events": ["DENY"] }
357
+ ]
358
+ }
359
+ }
360
+ ```
319
361
 
320
- Everything here is local, free, and offline: no account, no network calls, no license check. The catalog is MIT-licensed and PRs are welcome.
362
+ `KYA_NOTIFY_WEBHOOK=<url>` is the zero-config variant (generic payload). Delivery retries with exponential backoff (250ms/1s/4s + jitter), per-attempt timeouts, a per-URL circuit breaker, and a send rate limiter; payloads are built only from redacted trail fields, with an automatic minimized fallback if the secret scan trips. From short-lived hook/wrap spawns delivery rides a detached helper (`kya notify-flush`), so the gate path never waits on the network.
321
363
 
322
364
  ## Optional sandbox wrap (Firecracker)
323
365
 
@@ -333,7 +375,7 @@ KYA_SANDBOX=mock kya sandbox kill --sandbox-id <id>
333
375
 
334
376
  ## Cost showback (observe only)
335
377
 
336
- `kya orr run --usage ./usage.json` (or `.kya/usage.json`) adds a showback section: tokens and estimated USD by agent and run. Subagents nest under `parentRunId`. That section is not a billing meter and not a policy gate. Hosted metrics show the same rollup when usage is ingested with a session.
378
+ `kya orr run --usage ./usage.json` (or `.kya/usage.json`) adds a showback section: tokens and estimated USD by agent and run. Subagents nest under `parentRunId`. That section is not a billing meter and not a policy gate. Hosted metrics show the same rollup when usage is ingested with a session. Trail events that carry host-reported token counts (hook payloads with a `usage` object, imported traces) are preferred over the static per-event estimate, and the report states how many window events had real usage.
337
379
 
338
380
  ## Enterprise (separate tier)
339
381
 
@@ -354,18 +396,35 @@ pnpm build
354
396
  - [Per-host recipes (23 hosts)](docs/hosts/)
355
397
  - [Top-20 MCP server support matrix (taxonomy + gate recipes)](docs/mcp-servers.md)
356
398
  - [OTLP metrics (OSS + hosted)](docs/otlp.md)
399
+ - [Anonymous usage stats (opt-in): what is sent, controls, retention](docs/telemetry.md)
357
400
  - [OWASP MCP governance map](docs/owasp-mcp-governance.md)
358
- - [kya certify — Agent Trust Baseline gap reports](docs/certify.md)
401
+ - [kya certify - Agent Trust Baseline gap reports](docs/certify.md)
402
+ - [EU AI Act crosswalk for the Agent Trust Baseline](docs/certify-eu-ai-act.md)
403
+ - [Works with your observability stack](docs/marketing/observability-stack.md)
359
404
  - [SDK & framework integrations (in-process shims)](docs/sdk-integrations.md)
360
405
  - [Hosted operator SSO / SCIM (not in OSS CLI)](docs/hosted-operator-sso.md)
361
406
  - See also `LIMITATIONS.md` in this repo
362
407
 
408
+ ## Anonymous usage stats (opt-in, off by default)
409
+
410
+ The first time you run `kya start`, `kya init` or `kya connect` in a terminal, KYA asks once whether to share anonymous usage stats (`[y/N]`, the default is No). Only an explicit `y` or `yes` turns it on. Nothing is sent in CI, in non-interactive runs, with `--json`, or when `DO_NOT_TRACK=1` / `KYA_TELEMETRY=0` is set. `kya hook` itself never touches the network; when you opted in it starts a detached helper at most once a day that sends one `ping`, so hook-only installs still count as active.
411
+
412
+ ```bash
413
+ kya telemetry show # the exact payload, field by field
414
+ kya telemetry status # on / off / not asked, and what overrides it
415
+ kya telemetry off --purge # turn off and erase what the server holds for this install
416
+ ```
417
+
418
+ Full details, the payload, retention and how to self-host the endpoint: [docs/telemetry.md](docs/telemetry.md).
419
+
363
420
  ## OTLP (optional)
364
421
 
365
422
  Opt-in. Default off.
366
423
 
367
424
  **OSS CLI:** set `KYA_OTLP_ENDPOINT` (or `OTEL_EXPORTER_OTLP_ENDPOINT`) to export thin evaluate latency (`kya.client.evaluate.latency`) with tags `verdict` and `host` only. No tool args or API keys.
368
425
 
426
+ **Verdict span export:** set `KYA_OTLP_EXPORT_ENDPOINT` (or `"otlpExport": { "endpoint": ... }` in `.kya/config.json`) to emit every verdict as an OTLP/JSON GenAI span (`gen_ai.tool.name`, `kya.verdict`, `kya.reason_code`, token attributes when known) to any OTLP/HTTP backend. Long-lived processes (MCP gate, gateway) export every verdict; hook/wrap spawns export DENY / REQUIRE_APPROVE via the detached `notify-flush` helper. Plaintext http is accepted for loopback only unless `"insecure": true`.
427
+
369
428
  **Hosted plane:** richer Micrometer gauges and timers when `KYA_OTLP_ENABLED=true`.
370
429
 
371
430
  Full env, Grafana/Datadog notes, forbid list, and a Collector sample: [`docs/otlp.md`](docs/otlp.md).
@@ -2,7 +2,7 @@
2
2
  "amp.mcpServers": {
3
3
  "shield-kya": {
4
4
  "command": "npx",
5
- "args": ["--no-install", "@shield-agent/kya@0.21.0", "serve-mcp", "--stdio"],
5
+ "args": ["--no-install", "@shield-agent/kya@0.23.0", "serve-mcp", "--stdio"],
6
6
  "env": {
7
7
  "KYA_BASE_URL": "https://shield-agent.com",
8
8
  "KYA_API_KEY": "${KYA_API_KEY}",
@@ -2,7 +2,7 @@
2
2
  "mcpServers": {
3
3
  "shield-kya": {
4
4
  "command": "npx",
5
- "args": ["--no-install", "@shield-agent/kya@0.21.0", "serve-mcp", "--stdio"],
5
+ "args": ["--no-install", "@shield-agent/kya@0.23.0", "serve-mcp", "--stdio"],
6
6
  "env": {
7
7
  "KYA_BASE_URL": "https://shield-agent.com",
8
8
  "KYA_API_KEY": "${KYA_API_KEY}",
@@ -2,7 +2,7 @@
2
2
  "mcpServers": {
3
3
  "shield-kya": {
4
4
  "command": "npx",
5
- "args": ["--no-install", "@shield-agent/kya@0.21.0", "serve-mcp", "--stdio"],
5
+ "args": ["--no-install", "@shield-agent/kya@0.23.0", "serve-mcp", "--stdio"],
6
6
  "env": {
7
7
  "KYA_BASE_URL": "https://shield-agent.com",
8
8
  "KYA_API_KEY": "${KYA_API_KEY}",
@@ -2,7 +2,7 @@
2
2
  "mcpServers": {
3
3
  "shield-kya": {
4
4
  "command": "npx",
5
- "args": ["--no-install", "@shield-agent/kya@0.21.0", "serve-mcp", "--stdio"],
5
+ "args": ["--no-install", "@shield-agent/kya@0.23.0", "serve-mcp", "--stdio"],
6
6
  "env": {
7
7
  "KYA_BASE_URL": "https://shield-agent.com",
8
8
  "KYA_API_KEY": "${KYA_API_KEY}",
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Operator attestations — the explicit escape hatch for requirements a machine
2
+ * Operator attestations - the explicit escape hatch for requirements a machine
3
3
  * cannot check. Local file only (<cwd>/.kya/attestations.json); never uploaded,
4
4
  * never a PEP. Latest attestation per requirement id wins.
5
5
  */
@@ -13,7 +13,7 @@ const MAX_ATTESTATIONS_BYTES = 256 * 1024;
13
13
  const MAX_TEXT_CHARS = 2000;
14
14
  const REQ_ID = /^[A-Z]+-\d+$/;
15
15
  // Attestation text and timestamps are interpolated into single-line evidence
16
- // strings, reports, and signed bundles — same rule as catalog attest prompts.
16
+ // strings, reports, and signed bundles - same rule as catalog attest prompts.
17
17
  const CONTROL_CHARS = /[\x00-\x1f\x7f]/;
18
18
  export function attestationsPath(cwd) {
19
19
  return join(configDir(cwd), "attestations.json");
@@ -80,7 +80,7 @@ export function recordAttestation(cwd, requirementId, text) {
80
80
  assertNoSecrets(clean);
81
81
  }
82
82
  catch {
83
- throw new UsageError("--text looks like it contains a secret — attestations describe policy, never credentials");
83
+ throw new UsageError("--text looks like it contains a secret - attestations describe policy, never credentials");
84
84
  }
85
85
  const record = {
86
86
  requirementId: id,
@@ -91,11 +91,11 @@ export function recordAttestation(cwd, requirementId, text) {
91
91
  const store = { version: 1, attestations: [...others, record] };
92
92
  mkdirSync(configDir(cwd), { recursive: true, mode: 0o700 });
93
93
  // Atomic tmp+rename: a crash or concurrent run must never truncate the
94
- // store — the fail-safe load would silently discard all attestation history.
94
+ // store - the fail-safe load would silently discard all attestation history.
95
95
  const path = attestationsPath(cwd);
96
96
  atomicWriteSync(path, `${JSON.stringify(store, null, 2)}\n`);
97
97
  try {
98
- chmodSync(path, 0o600); // operator statements are sensitive — evidence-bundle perms
98
+ chmodSync(path, 0o600); // operator statements are sensitive - evidence-bundle perms
99
99
  }
100
100
  catch {
101
101
  /* best-effort on non-POSIX */
@@ -63,7 +63,7 @@ export interface Catalog {
63
63
  readonly requirements: readonly CatalogRequirement[];
64
64
  }
65
65
  export declare const MAX_CATALOG_BYTES: number;
66
- /** Bundled catalog: <pkg>/catalog/… — works from both src/ (vitest) and dist/ (built). */
66
+ /** Bundled catalog: <pkg>/catalog/… - works from both src/ (vitest) and dist/ (built). */
67
67
  export declare function defaultCatalogPath(): string;
68
68
  export declare function loadCatalog(path?: string): Catalog;
69
69
  export declare function validateCatalog(raw: unknown): Catalog;
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Agent Trust Baseline catalog: types, loader, validator.
3
3
  * The bundled catalog/agent-trust-baseline-v0.json at the package root is the
4
- * source of truth (shipped via package.json "files"). Evidence only — a
4
+ * source of truth (shipped via package.json "files"). Evidence only - a
5
5
  * catalog requirement never ALLOWs anything.
6
6
  */
7
7
  import { existsSync, readFileSync, statSync } from "node:fs";
@@ -26,7 +26,7 @@ const CHECK_KINDS = new Set([
26
26
  const ORR_MAX = new Set(["green", "amber"]);
27
27
  const TRAIL_MODES = new Set(["observe", "hold", "offline"]);
28
28
  const REQ_ID = /^[A-Z]+-\d+$/;
29
- /** Bundled catalog: <pkg>/catalog/… — works from both src/ (vitest) and dist/ (built). */
29
+ /** Bundled catalog: <pkg>/catalog/… - works from both src/ (vitest) and dist/ (built). */
30
30
  export function defaultCatalogPath() {
31
31
  return fileURLToPath(new URL("../../catalog/agent-trust-baseline-v0.json", import.meta.url));
32
32
  }
@@ -172,7 +172,7 @@ function parseCheck(id, raw) {
172
172
  case "attest": {
173
173
  if (!nonEmpty(c.prompt))
174
174
  throw reqErr(id, "attest requires non-empty prompt");
175
- // Prompts are interpolated into one-line evidence — no control chars.
175
+ // Prompts are interpolated into one-line evidence - no control chars.
176
176
  if (/[\x00-\x1f\x7f]/.test(c.prompt)) {
177
177
  throw reqErr(id, "attest prompt must not contain control characters");
178
178
  }
@@ -34,7 +34,7 @@ export function assembleEvidenceContext(cwd, env, now = new Date()) {
34
34
  return {
35
35
  now,
36
36
  events,
37
- // The shared resolver the gate itself uses (config.ts) — certify can
37
+ // The shared resolver the gate itself uses (config.ts) - certify can
38
38
  // never report a mode the gate would not actually run.
39
39
  gateMode: resolveGateMode({ cwd, env }),
40
40
  wiredHostCount: wiredHosts.filter((h) => h.wired !== "none").length,
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Agent Trust Baseline evaluators. Pure functions over a pre-assembled
3
- * EvidenceContext — no I/O here; all loading lives in certify/context.ts.
3
+ * EvidenceContext - no I/O here; all loading lives in certify/context.ts.
4
4
  * Evidence only: never a second PEP, never ALLOWs anything. Empty evidence
5
5
  * windows yield insufficient_evidence, never a vacuous pass.
6
6
  */
@@ -88,7 +88,7 @@ export interface CertifyOverallCounts {
88
88
  export declare function countRequirements(requirements: readonly CertifyRequirementResult[]): CertifyOverallCounts;
89
89
  /**
90
90
  * Fail-closed overall: zero certifiable evidence (all insufficient_evidence)
91
- * must never headline as pass — a green badge requires real evidence.
91
+ * must never headline as pass - a green badge requires real evidence.
92
92
  * Shared by runCertify and computeLiveCertify so they can never diverge.
93
93
  */
94
94
  export declare function computeOverall(counts: CertifyOverallCounts): CertifyReport["overall"];
@@ -15,7 +15,7 @@ export function countRequirements(requirements) {
15
15
  }
16
16
  /**
17
17
  * Fail-closed overall: zero certifiable evidence (all insufficient_evidence)
18
- * must never headline as pass — a green badge requires real evidence.
18
+ * must never headline as pass - a green badge requires real evidence.
19
19
  * Shared by runCertify and computeLiveCertify so they can never diverge.
20
20
  */
21
21
  export function computeOverall(counts) {
@@ -138,7 +138,7 @@ export function evaluateRequirement(req, ctx) {
138
138
  }
139
139
  case "config_mode": {
140
140
  if (ctx.gateMode === check.not) {
141
- return result("gap", `gate mode is ${ctx.gateMode} — set KYA_HOLD=1 / KYA_OFFLINE=1 or "gateMode" in .kya/config.json`);
141
+ return result("gap", `gate mode is ${ctx.gateMode} - set KYA_HOLD=1 / KYA_OFFLINE=1 or "gateMode" in .kya/config.json`);
142
142
  }
143
143
  return result("pass", `gate mode is ${ctx.gateMode}`);
144
144
  }
@@ -146,33 +146,33 @@ export function evaluateRequirement(req, ctx) {
146
146
  if (ctx.wiredHostCount >= check.min) {
147
147
  return result("pass", `${ctx.wiredHostCount} wired host(s) (need ${check.min})`);
148
148
  }
149
- return result("gap", `${ctx.wiredHostCount} wired host(s), need ${check.min} — kya connect <host> --hooks`);
149
+ return result("gap", `${ctx.wiredHostCount} wired host(s), need ${check.min} - kya connect <host> --hooks`);
150
150
  }
151
151
  case "sandbox_inventory": {
152
152
  if (ctx.sandboxCount >= check.min) {
153
153
  return result("pass", `${ctx.sandboxCount} sandbox record(s)`);
154
154
  }
155
- return result("gap", `no sandbox inventory — KYA_SANDBOX=mock kya sandbox spawn`);
155
+ return result("gap", `no sandbox inventory - KYA_SANDBOX=mock kya sandbox spawn`);
156
156
  }
157
157
  case "receipts_present": {
158
158
  if (ctx.receiptCount >= check.min) {
159
159
  return result("pass", `${ctx.receiptCount} receipt file(s) in .kya/receipts`);
160
160
  }
161
- return result("gap", `no receipts yet — run kya receipt`);
161
+ return result("gap", `no receipts yet - run kya receipt`);
162
162
  }
163
163
  case "showback_present": {
164
164
  return ctx.showbackPresent
165
165
  ? result("pass", "showback card present (.kya/usage.json)")
166
- : result("gap", "no showback card — add .kya/usage.json or run orr with --usage");
166
+ : result("gap", "no showback card - add .kya/usage.json or run orr with --usage");
167
167
  }
168
168
  case "attest": {
169
169
  if (attestation)
170
170
  return result("attested", `attested ${attestation.at}`);
171
- return result("gap", `no attestation recorded — kya certify --attest ${req.id} --text "…" (${check.prompt})`);
171
+ return result("gap", `no attestation recorded - kya certify --attest ${req.id} --text "…" (${check.prompt})`);
172
172
  }
173
173
  case "orr_overall": {
174
174
  if (!ctx.orr) {
175
- return result("insufficient_evidence", "no ORR report — kya orr run --path .");
175
+ return result("insufficient_evidence", "no ORR report - kya orr run --path .");
176
176
  }
177
177
  if (RATING_RANK[ctx.orr.overall] <= RATING_RANK[check.max]) {
178
178
  return result("pass", `ORR overall ${ctx.orr.overall} (max ${check.max})`);
@@ -181,7 +181,7 @@ export function evaluateRequirement(req, ctx) {
181
181
  }
182
182
  case "orr_category": {
183
183
  if (!ctx.orrCategories) {
184
- return result("insufficient_evidence", "no ORR report — kya orr run --path .");
184
+ return result("insufficient_evidence", "no ORR report - kya orr run --path .");
185
185
  }
186
186
  const rating = ctx.orrCategories[check.id];
187
187
  if (!rating) {
@@ -194,7 +194,7 @@ export function evaluateRequirement(req, ctx) {
194
194
  }
195
195
  case "orr_fresh": {
196
196
  if (!ctx.orr || !ctx.orr.generatedAt) {
197
- return result("insufficient_evidence", "no ORR report — kya orr run --path .");
197
+ return result("insufficient_evidence", "no ORR report - kya orr run --path .");
198
198
  }
199
199
  const t = Date.parse(ctx.orr.generatedAt);
200
200
  if (Number.isNaN(t)) {
@@ -202,7 +202,7 @@ export function evaluateRequirement(req, ctx) {
202
202
  }
203
203
  const nowMs = ctx.now.getTime();
204
204
  if (t > nowMs) {
205
- return result("insufficient_evidence", "ORR generatedAt is in the future — clock skew, re-run kya orr run");
205
+ return result("insufficient_evidence", "ORR generatedAt is in the future - clock skew, re-run kya orr run");
206
206
  }
207
207
  const ageMs = nowMs - t;
208
208
  // Exact ms comparison decides; the floored day count is display-only.
@@ -210,7 +210,7 @@ export function evaluateRequirement(req, ctx) {
210
210
  if (ageMs <= check.maxAgeDays * DAY_MS) {
211
211
  return result("pass", `ORR is ${ageDays}d old (max ${check.maxAgeDays}d)`);
212
212
  }
213
- return result("gap", `ORR is ${ageDays}d old (max ${check.maxAgeDays}d) — re-run kya orr run`);
213
+ return result("gap", `ORR is ${ageDays}d old (max ${check.maxAgeDays}d) - re-run kya orr run`);
214
214
  }
215
215
  }
216
216
  // Unreachable: RequirementCheck union is exhaustive (checked at compile time).
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Live in-memory certify evaluation — the "certified right now" panel data.
2
+ * Live in-memory certify evaluation - the "certified right now" panel data.
3
3
  * Recomputes the full Agent Trust Baseline from local evidence on every call
4
4
  * and returns a real CertifyReport, identical in shape to `kya certify` output
5
5
  * so the receipt panel and any other consumer can treat them interchangeably.
@@ -11,7 +11,7 @@ import { loadCatalog } from "./catalog.js";
11
11
  import { assembleEvidenceContext } from "./context.js";
12
12
  import { computeOverall, countRequirements, DAY_MS, evaluateRequirement, trailStats, trailWindow, } from "./evaluate.js";
13
13
  export function computeLiveCertify(cwd, env = process.env, windowDays = 30, now = new Date()) {
14
- // Public SDK surface — enforce the same window rule as the CLI boundary.
14
+ // Public SDK surface - enforce the same window rule as the CLI boundary.
15
15
  if (!Number.isInteger(windowDays) || windowDays < 1 || windowDays > 366) {
16
16
  throw new UsageError("windowDays must be an integer between 1 and 366");
17
17
  }
@@ -1,5 +1,5 @@
1
1
  import type { CertifyReport } from "./evaluate.js";
2
- /** Shared domain display labels — the receipt Certify tab uses these too. */
2
+ /** Shared domain display labels - the receipt Certify tab uses these too. */
3
3
  export declare const DOMAIN_LABELS: Record<string, string>;
4
4
  /** Catalog order of domains, derived from requirement order. */
5
5
  export declare function domainOrder(requirements: readonly {