@shield-agent/kya 0.32.4 → 0.32.6-rc.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 (59) hide show
  1. package/.cursor-plugin/plugin.json +2 -2
  2. package/.mcp.json +1 -1
  3. package/LICENSE +1 -1
  4. package/LIMITATIONS.md +3 -1
  5. package/README.md +58 -50
  6. package/amp/settings.example.json +1 -1
  7. package/catalog/agent-trust-baseline-v0.json +75 -75
  8. package/claude/claude_desktop_config.example.json +1 -1
  9. package/cline/cline_mcp_settings.example.json +1 -1
  10. package/copilot/mcp-config.example.json +1 -1
  11. package/dist/certify/evaluate.js +23 -23
  12. package/dist/certify/evaluate.js.map +1 -1
  13. package/dist/client.d.ts +29 -3
  14. package/dist/client.d.ts.map +1 -1
  15. package/dist/client.js +121 -13
  16. package/dist/client.js.map +1 -1
  17. package/dist/commands/orr.d.ts.map +1 -1
  18. package/dist/commands/orr.js +43 -43
  19. package/dist/commands/orr.js.map +1 -1
  20. package/dist/commands/team.d.ts +4 -0
  21. package/dist/commands/team.d.ts.map +1 -1
  22. package/dist/commands/team.js +12 -9
  23. package/dist/commands/team.js.map +1 -1
  24. package/dist/errors.d.ts +3 -1
  25. package/dist/errors.d.ts.map +1 -1
  26. package/dist/errors.js +12 -1
  27. package/dist/errors.js.map +1 -1
  28. package/dist/notify/index.d.ts +1 -1
  29. package/dist/notify/index.d.ts.map +1 -1
  30. package/dist/notify/index.js +2 -2
  31. package/dist/notify/index.js.map +1 -1
  32. package/dist/notify/templates.d.ts +18 -2
  33. package/dist/notify/templates.d.ts.map +1 -1
  34. package/dist/notify/templates.js +56 -1
  35. package/dist/notify/templates.js.map +1 -1
  36. package/dist/receipt/live-server.js +1 -1
  37. package/dist/receipt/live-server.js.map +1 -1
  38. package/dist/receipt/render-receipt.d.ts.map +1 -1
  39. package/dist/receipt/render-receipt.js +61 -49
  40. package/dist/receipt/render-receipt.js.map +1 -1
  41. package/dist/update-check.d.ts +5 -0
  42. package/dist/update-check.d.ts.map +1 -1
  43. package/dist/update-check.js +38 -5
  44. package/dist/update-check.js.map +1 -1
  45. package/droid/README.md +1 -1
  46. package/droid/mcp.example.json +1 -1
  47. package/gemini/settings.example.json +1 -1
  48. package/grok/README.md +1 -1
  49. package/kilo/kilo.example.json +1 -1
  50. package/kimi/mcp.example.json +1 -1
  51. package/kiro/mcp.example.json +1 -1
  52. package/manifest.json +1 -1
  53. package/mastracode/mcp.example.json +1 -1
  54. package/mcp.json +1 -1
  55. package/openai/codex.config.example.toml +1 -1
  56. package/opencode/opencode.example.json +1 -1
  57. package/package.json +2 -2
  58. package/qwen/settings.example.json +1 -1
  59. package/server.json +2 -2
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "shield-kya",
3
- "version": "0.32.4",
4
- "description": "Audit trail and traceability for AI agents. See what every coding agent did, with opt-in human approval and signed certify.",
3
+ "version": "0.32.6-rc.1",
4
+ "description": "Audit trail and traceability for AI agents. See what every coding agent did, block risky calls, ask a human for approval, and prove it with signed trust checks.",
5
5
  "author": {
6
6
  "name": "Shield Agent",
7
7
  "email": "it@shield-agent.com"
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.32.4", "serve-mcp", "--stdio"],
5
+ "args": ["--no-install", "@shield-agent/kya@0.32.6-rc.1", "serve-mcp", "--stdio"],
6
6
  "env": {
7
7
  "KYA_BASE_URL": "https://shield-agent.com",
8
8
  "KYA_API_KEY": "${KYA_API_KEY}",
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2026 The Pixel Boys / Shield Agent
3
+ Copyright (c) 2026 MFR Limited
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/LIMITATIONS.md CHANGED
@@ -13,6 +13,8 @@
13
13
  - `invoke` authorizes on a live plane after Allow or APPROVED. It never runs the customer write in the CLI. There is no `--offline` invoke.
14
14
  - The TUI (`dash`) can `a`/`x` decide only after `y` confirm, and only with a JWT that has `kya.approve`. Machine `sk_*` keys are refused (print the CLI hint instead).
15
15
  - Human decide is also `kya approve --id` / `kya reject --id` against `POST /api/v1/kya/approvals/{id}/approve|reject` (`kya.approve` scope).
16
+ - A create, decide or priority change that cannot get a lock in time gets `503 kya.approval_busy` with `Retry-After`. The usual cause is another call that holds the same approval (the limit is 5 s; a deadlock can end the wait after about 1 s). A short table lock of a server maintenance job can also cause it. The approval did not change. Send the same call again after the delay. Exception: a console approve with a two-factor code uses up the code before the 503, so send it again with a new code.
17
+ - The SDK client (`requestApproval`, `decideApproval`) sends a busy create or decide again. It waits `Retry-After` seconds (default 2 s, at most 10 s, plus up to 20 percent jitter). It makes at most 3 retries in 20 s and stops when the caller's `AbortSignal` fires. Then it gives `PLANE_BUSY` ("approval service busy; retry later"). A busy approval is never an approval: `wrap` stops and MCP `kya.request_approval` returns an error. Other calls and other HTTP errors (500, 429, other 503) are not retried.
16
18
  - Shield KYA evaluate/approve is the only policy decision point (`ALLOW` / `DENY` / `REQUIRE_APPROVE`). Scanners, `--scorecard`, `harness.agentshield`, and the ORR CLI write evidence. They never ALLOW a side effect. AgentShield is opt-in (`--producer harness.agentshield` or `--agentshield-json`). Trust scores never authorize writes. The CLI never passes `--fix`, never starts MiniClaw, and never installs `ecc-agentshield`.
17
19
  - OWASP MCP Governance / MCP Top 10 alignment is documented in `docs/owasp-mcp-governance.md`. That guide is not a certificate. Org MCP inventory, Tier UI, and auto risk score are hosted roadmap (not in this CLI).
18
20
  - Operator SSO (OIDC/SAML), SCIM 2.0, IdP-group → role maps, and IdP group→tool maps (raise/deny) are hosted Scale only. See `docs/hosted-operator-sso.md`. They never ALLOW a tool write from this CLI.
@@ -33,4 +35,4 @@
33
35
  - Grok (grok.com) custom connectors need a public HTTPS URL. Localhost and private IPs are rejected. If the UI only offers OAuth or no auth, use Codex, Gemini CLI, or the xAI SDK instead of turning auth off.
34
36
  - Local HTTP MCP remains loopback-only. Do not bind it to a public interface.
35
37
  - Optional `kya sandbox` (Firecracker) is a runtime wrap beside the gate, not a hypervisor product. Binaries are not in npm. Default off (`KYA_SANDBOX`). MCP still never executes spawn/exec. Kernel bugs and unwrapped shells remain residual risk (see ADR 0007).
36
- - `kya certify` is evidence-only: it reads local state (trail, ORR, wired hosts, sandboxes, receipts, showback, attestations) and writes a gap report. It never ALLOWs, DENYs, approves, or blocks a tool call, and it is not a second PEP. `pass` means "local evidence shows no gap" - not certification by any third party. Signed evidence bundles (`--sign`) are self-signed: they prove integrity and continuity of a key, not identity; identity binding is the hosted verification product. Attestations are unverified operator statements recorded locally in `.kya/attestations.json`.
38
+ - `kya certify` is evidence-only: it reads local state (trail, ORR, wired hosts, sandboxes, receipts, showback, attestations) and writes a gap report. It never ALLOWs, DENYs, approves, or blocks a tool call, and it is not a second PEP. `pass` means "local evidence shows no gap" - not certification by any third party. Signed evidence bundles (`--sign`) are self-signed: they prove integrity and continuity of a key, not identity, and show a grey `self-signed` badge on the public verify endpoint (`POST /api/v1/kya/evidence/verify`) and badge. Only a bundle signed by an active hosted workspace key earns the green badge, which ties it to a hosted account, not to a checked legal identity. Attestations are unverified operator statements recorded locally in `.kya/attestations.json`.
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
- **Audit trail and traceability for AI agents.** See what every coding agent did, with opt-in human approval and signed certify. Every tool call is recorded on a live local dashboard and certifiable against the Agent Trust Baseline. Locally KYA is advisory and fails open, except for a small never-list that is denied; enforcement lives on the MCP gate path and the hosted plane. One command. Free forever under MIT.
11
+ **Audit trail and traceability for AI agents.** See what every coding agent did, block risky calls, ask a human for approval, and prove it with signed trust checks. Every tool call is recorded on a live local dashboard and can be checked against the Agent Trust Baseline. Locally KYA gives warnings, not blocks, and fails open (an error lets the call through). The one exception is a small never-list (a short list of dangerous calls that is always denied). Real enforcement runs on the MCP gate path and the hosted plane (the Shield Agent cloud service). One command. Free forever under MIT.
12
12
 
13
13
  ```bash
14
14
  npm i -g @shield-agent/kya@latest && kya start
@@ -19,7 +19,7 @@ Requires **Node.js 22+** (24 recommended). Restart Cursor / Claude Code / Codex
19
19
 
20
20
  CLI and local MCP gate for Shield’s Know Your Agent path.
21
21
 
22
- An agent that asks Shield first gets Allow, Review, or Deny: you register the agent, wrap the tool (or route it through the MCP gate or the hosted plane), and Review waits for a person. Local hooks only record and block the never-list (see [Hook interception](#hook-interception)); hosted is where enforcement lives. This package does not scan your network. Agents that never call evaluate stay invisible on purpose.
22
+ An agent that asks Shield first gets Allow, Review, or Deny: you register the agent, wrap the tool (or route it through the MCP gate or the hosted plane), and Review waits for a person. Local hooks only record and block the never-list (see [Hook interception](#hook-interception)). Hosted is where enforcement lives. This package does not scan your network. Agents that never call evaluate stay invisible on purpose.
23
23
 
24
24
  Walkthrough: [how you use it](https://shield-agent.com/how-kya-works#using).
25
25
 
@@ -27,13 +27,13 @@ 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 22+** (`engines.node: >=22`); 24 is the recommended line. Node 20 and 21 are unsupported but work: the CLI prints a one-line warning. Node 18 and older are unsupported and some features break there (HTTP `serve-mcp`, the gateway OTLP receiver). Below 22 the CLI offers to install Node 24 for you (via volta / fnm / nvm / brew), reinstall itself, and finish the command - declining just prints the warning and continues. `kya hook` never warns or prompts.
30
+ Requires **Node.js 22+** (`engines.node: >=22`); 24 is the recommended line. Node 20 and 21 are unsupported but work: the CLI prints a one-line warning. Node 18 and older are unsupported and some features break there (HTTP `serve-mcp`, the gateway OTLP receiver). Below 22 the CLI offers to install Node 24 for you (via volta / fnm / nvm / brew), reinstall itself, and finish the command. If you decline, it just prints the warning and continues. `kya hook` never warns or prompts.
31
31
 
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.
32
+ It works with any host that speaks MCP or OpenAPI. Vertical packs are optional. Shield is the only policy decision point (the one place that decides Allow or Deny). This gate never auto-approves an irreversible side effect (a change you cannot undo).
33
33
 
34
34
  If `KYA_API_KEY` is empty against an authenticated plane, network commands exit non-zero. `eval-tool`, `wrap`, and `invoke` exit `0` on ALLOW, `4` on REQUIRE_APPROVE, and `1` on DENY or unknown, so a line like `eval-tool && write` cannot skip the gate.
35
35
 
36
- `--offline` runs sample evaluate without a paid cloud (useful for DENY and REQUIRE_APPROVE demos). Creating an agent is itself a tool: offline, `kya.agent.register` comes back REQUIRE_APPROVE. Allow, break-glass, and approve mint modes live on the control plane.
36
+ `--offline` runs sample evaluate without a paid cloud (useful for DENY and REQUIRE_APPROVE demos). Creating an agent is itself a tool: offline, `kya.agent.register` comes back REQUIRE_APPROVE. Allow, break-glass, and approve mint modes (the modes that create approvals) live on the control plane.
37
37
 
38
38
  ## One liner
39
39
 
@@ -57,17 +57,17 @@ scoop install shield-kya
57
57
 
58
58
  Claude Code users can also install the [plugin](#claude-code-plugin); GitHub Copilot CLI users the [Copilot CLI plugin](#github-copilot-cli-plugin) (read its first paragraph before installing); Codex CLI users the [Codex plugin](#codex-plugin); Gemini CLI users the [Gemini CLI extension](#gemini-cli-extension). Cline users: `npm install -g @shield-agent/kya@latest`, then follow [`llms-install.md`](llms-install.md). It is written so Cline can follow it; a Cline run from that file alone has not been tested yet.
59
59
 
60
- 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.
60
+ 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, so 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.
61
61
 
62
- ![KYA report - live dashboard: Certify trust baseline, verdicts, analytics](https://raw.githubusercontent.com/The-Pixel-Boys/shield-kya/main/assets/report-overview.png)
62
+ ![KYA report live dashboard: Certify trust baseline, decisions, analytics](https://raw.githubusercontent.com/The-Pixel-Boys/shield-kya/main/assets/report-overview.png)
63
63
 
64
- ![Certify tab - full Agent Trust Baseline requirement table with evidence](https://raw.githubusercontent.com/The-Pixel-Boys/shield-kya/main/assets/report-certify.png)
64
+ ![Certify tab: full Agent Trust Baseline requirement table with evidence](https://raw.githubusercontent.com/The-Pixel-Boys/shield-kya/main/assets/report-certify.png)
65
65
 
66
- ![Activity tab - filterable agent tool-call feed with verdicts](https://raw.githubusercontent.com/The-Pixel-Boys/shield-kya/main/assets/report-activity.png)
66
+ ![Activity tab: filterable agent tool-call feed with decisions](https://raw.githubusercontent.com/The-Pixel-Boys/shield-kya/main/assets/report-activity.png)
67
67
 
68
- ![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)
68
+ ![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)
69
69
 
70
- ![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)
70
+ ![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)
71
71
 
72
72
  <!-- 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) -->
73
73
 
@@ -80,7 +80,7 @@ kya start --force # rewrite MCP blocks
80
80
 
81
81
  ## One command per host
82
82
 
83
- `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:
83
+ `kya start` covers Claude Code, Cursor, and any host that reads `.mcp.json`. It also 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:
84
84
 
85
85
  ```bash
86
86
  kya connect claude # ~/.claude.json (merges mcpServers only)
@@ -92,17 +92,17 @@ kya connect qwen --project # project scope instead of global
92
92
  kya connect kiro --force # overwrite an existing shield-kya entry
93
93
  ```
94
94
 
95
- 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.
95
+ Connect merges. It never rewrites a host config it cannot 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 (no API key). Set `KYA_API_KEY` in the host env when you point at an authenticated plane.
96
96
 
97
97
  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/).
98
98
 
99
99
  ## Hook interception
100
100
 
101
- `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).)
101
+ `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: it is evaluated locally (offline, sub-second, no network) and written to the global record (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).)
102
102
 
103
- 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**.
103
+ 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 written to the record as advisory and the call proceeds. Manual wiring can pass `--strict` on the hook command to also block **REQUIRE_APPROVE**.
104
104
 
105
- 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.
105
+ 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 stays on the MCP `kya.policy_evaluate` path. Hooks take effect in new sessions; all three hosts load hooks at session start.
106
106
 
107
107
  ```bash
108
108
  kya connect claude --hooks # wire the PreToolUse hook by hand
@@ -119,7 +119,7 @@ This repo is also a Claude Code plugin marketplace named `shield-kya` with one p
119
119
  /plugin install kya@shield-kya
120
120
  ```
121
121
 
122
- The plugin is **advisory and fails open**: it records every tool call on the local trail (`~/.kya/trail.jsonl`) and blocks only the small never-list. If kya is missing, crashes or times out, the tool call proceeds and nothing is recorded. It evaluates offline, so it has no Hold and no approval; hosted enforcement is the MCP gate path.
122
+ The plugin is **advisory and fails open**: it records every tool call on the local record (`~/.kya/trail.jsonl`) and blocks only the small never-list. If kya is missing, crashes or times out, the tool call proceeds and nothing is recorded. It evaluates offline, so it has no Hold and no approval. Hosted enforcement is the MCP gate path.
123
123
 
124
124
  Team rollout: commit `extraKnownMarketplaces` (the `shield-kya` GitHub source) and `enabledPlugins` (`"kya@shield-kya": true`) to the repository's `.claude/settings.json`, or force it org-wide with managed settings. Details and limits: [docs/hosts/claude-plugin.md](docs/hosts/claude-plugin.md).
125
125
 
@@ -134,7 +134,7 @@ copilot plugin marketplace add The-Pixel-Boys/shield-kya
134
134
  copilot plugin install kya@shield-kya
135
135
  ```
136
136
 
137
- Copilot reads `.plugin/marketplace.json` before `.claude-plugin/marketplace.json`, so `kya@shield-kya` resolves to `plugins/kya-copilot`: an Agent Plugins v1 manifest (`plugin.json`), hooks in `com.github.copilot/hooks/hooks.json` and the MCP server in `mcp.json`. Claude Code and Codex keep loading `plugins/kya` and never see this folder. Same behaviour: advisory, fails open. Copilot denies a tool call when a pre-tool hook exits non-zero, so the hook is a `bash` command that does nothing when `node` is not on Copilot's `PATH`, otherwise runs `scripts/copilot-hook.mjs` (which forwards only kya's never-list deny), and turns any exit other than `2` into `0`. Recording needs Node.js 22 or later on that `PATH`. Copilot names MCP tools `<server>-<tool>` (for example `postgres-drop_table`); the never-list does not recognise that form yet, so MCP calls are recorded but not blocked. Trail rows show the product as `other`. Tested with Copilot CLI 1.0.98 on macOS. **Do not install it on Windows yet**: the pre-tool hook has only a `bash` form and has not been run on Windows; use `kya connect copilot` there. Details: [docs/hosts/copilot.md](docs/hosts/copilot.md#plugin).
137
+ Copilot reads `.plugin/marketplace.json` before `.claude-plugin/marketplace.json`, so `kya@shield-kya` resolves to `plugins/kya-copilot`: an Agent Plugins v1 manifest (`plugin.json`), hooks in `com.github.copilot/hooks/hooks.json` and the MCP server in `mcp.json`. Claude Code and Codex keep loading `plugins/kya` and never see this folder. Same behaviour: advisory, fails open. Copilot denies a tool call when a pre-tool hook exits non-zero. So the hook is a `bash` command that does nothing when `node` is not on Copilot's `PATH`. Otherwise it runs `scripts/copilot-hook.mjs` (which forwards only kya's never-list deny) and turns any exit other than `2` into `0`. Recording needs Node.js 22 or later on that `PATH`. Copilot names MCP tools `<server>-<tool>` (for example `postgres-drop_table`); the never-list does not recognise that form yet, so MCP calls are recorded but not blocked. Rows in the record show the product as `other`. Tested with Copilot CLI 1.0.98 on macOS. **Do not install it on Windows yet**: the pre-tool hook has only a `bash` form and has not been run on Windows; use `kya connect copilot` there. Details: [docs/hosts/copilot.md](docs/hosts/copilot.md#plugin).
138
138
 
139
139
  ## Codex plugin
140
140
 
@@ -159,9 +159,9 @@ Same behaviour as the other plugins: advisory, fails open, records every tool ca
159
159
 
160
160
  ## Gate (local MCP gateway)
161
161
 
162
- `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.
162
+ `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 comes 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 recorded. Every call is written to the local record and the live report, and can be forwarded as OTLP to the hosted intake.
163
163
 
164
- **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:
164
+ **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` field that says where each server came from), 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 kept 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:
165
165
 
166
166
  ```bash
167
167
  kya gate init # scaffold .kya/gateways.json with ready-to-move recipes
@@ -172,7 +172,7 @@ kya connect claude --gate # point the host at the gateway (server key shield-k
172
172
  kya gate doctor # binary, config, listener health, loopback-only posture
173
173
  ```
174
174
 
175
- `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).
175
+ `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).
176
176
 
177
177
  ## Longer path (optional)
178
178
 
@@ -189,21 +189,21 @@ kya dash --once --offline
189
189
 
190
190
  Install hub: [https://shield-agent.com/install](https://shield-agent.com/install)
191
191
 
192
- ## Activity trail (global)
192
+ ## Activity record (global)
193
193
 
194
- 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.
194
+ One record (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 record is capped at 1 MB (tail-read: oldest events drop away) and shared across all projects.
195
195
 
196
- 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.
196
+ The report itself is a dashboard. A hero row on top shows the live **Certify** result, the decision mix, an activity sparkline, and showback (cost per agent). Tabbed sections sit 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.
197
197
 
198
198
  ### Sharing a report
199
199
 
200
- `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>`) with its expiry date (7 days) that anyone can open, plus one line suggesting you send it to your security lead. Every shared page carries the one-line install so readers can audit their own agents, and a button to start a hosted workspace for the team. The Certify status on the page is labelled as self-reported by the CLI, not verified by Shield Agent. With `--json` the command prints only `{"url", "expiresAt"}`. Point it at a different collector with `--share-url <base>` or `KYA_SHARE_URL`.
200
+ `kya receipt --share` publishes a **redacted summary** of the current window (aggregate decision 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>`) with its expiry date (7 days) that anyone can open, plus one line suggesting you send it to your security lead. Every shared page carries the one-line install so readers can audit their own agents, and a button to start a hosted workspace for the team. The Certify status on the page is labelled as self-reported by the CLI, not verified by Shield Agent. With `--json` the command prints only `{"url", "expiresAt"}`. Point it at a different collector with `--share-url <base>` or `KYA_SHARE_URL`.
201
201
 
202
- 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`.
202
+ 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 plus jitter, and respects the server's `Retry-After`.
203
203
 
204
204
  ### Natural-language search
205
205
 
206
- The **Activity** search box understands plain English. It runs a hybrid of BM25 over tool IDs, summaries, reason codes, verdicts, projects, and MCP server labels, plus local MiniLM semantic reranking (shipped as an optional dependency; the report falls back to lexical-only if the model runtime is unavailable). A built-in concept glossary maps everyday words to the vocabulary events actually use, so `dangerous` finds rm/kill/delete/sudo calls, `blocked` finds denials, and `held` finds approval requests. You can also 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.
206
+ The **Activity** search box understands plain English. It runs a hybrid of BM25 over tool IDs, summaries, reason codes, decisions, projects, and MCP server labels, plus local MiniLM semantic reranking (shipped as an optional dependency; the report falls back to lexical-only if the model runtime is unavailable). A built-in concept glossary maps everyday words to the vocabulary events actually use, so `dangerous` finds rm/kill/delete/sudo calls, `blocked` finds denials, and `held` finds approval requests. You can also 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 record.
207
207
 
208
208
  - Offline or `KYA_OFFLINE=1` keeps search purely lexical (no model download).
209
209
  - 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`.
@@ -243,9 +243,9 @@ Tag sessions with `KYA_HOST=ide` or `KYA_HOST=runtime`. Same policy path either
243
243
  | `KYA_TELEMETRY` | No | `0`/`off` forces anonymous usage stats off ([docs/telemetry.md](docs/telemetry.md)); they are off unless you opted in |
244
244
  | `DO_NOT_TRACK` | No | `1` forces anonymous usage stats off, same as `KYA_TELEMETRY=0` |
245
245
 
246
- Gate mode can also be pinned in the project's `.kya/config.json`:
247
- `{"gateMode": "hold"}` or `{"gateMode": "offline"}` (exact values only -
248
- anything else is ignored). The gate itself (wrap / hook / eval) honors it
246
+ Gate mode can also be set in the project's `.kya/config.json`:
247
+ `{"gateMode": "hold"}` or `{"gateMode": "offline"}` (exact values only;
248
+ anything else is ignored). The gate itself (wrap / hook / eval) follows it
249
249
  with the precedence flags > env > config > observe, and `kya certify`
250
250
  reports through the same resolver, so a certify pass on gate mode always
251
251
  reflects how the gate actually runs.
@@ -265,7 +265,7 @@ MCP Registry entry: `server.json` plus package `mcpName` `io.github.The-Pixel-Bo
265
265
  "mcpServers": {
266
266
  "shield-kya": {
267
267
  "command": "npx",
268
- "args": ["--no-install", "@shield-agent/kya@0.32.4", "serve-mcp", "--stdio"],
268
+ "args": ["--no-install", "@shield-agent/kya@0.32.6-rc.1", "serve-mcp", "--stdio"],
269
269
  "env": {
270
270
  "KYA_BASE_URL": "http://127.0.0.1:8090",
271
271
  "KYA_API_KEY": "${KYA_API_KEY}",
@@ -284,6 +284,8 @@ npx @shield-agent/kya approve --id <approval-id>
284
284
  npx @shield-agent/kya reject --id <approval-id>
285
285
  ```
286
286
 
287
+ A hosted high-risk request (HIGH priority now or before, or created with the irreversible hint) cannot be approved from the CLI or the TUI: the hosted plane answers 403 `kya.approval_console_mfa_required`. Approve it in the hosted console with a two-factor code. `reject` always works.
288
+
287
289
  `wrap` evaluates and may open a pending ticket. It never executes the side effect. `invoke` asks the live plane to authorize after Allow or APPROVED. It does not run the write on this machine. The TUI (`dash`) can `a`/`x` decide only after `y` confirm with a JWT (`sk_*` refused).
288
290
 
289
291
  ## In-process SDK shims
@@ -297,7 +299,7 @@ const run = governed({ toolId: "write_file", server: "filesystem", fn: myWrite }
297
299
  await run({ path: "out.txt", content: "hi" }); // throws KyaDeniedError on DENY
298
300
  ```
299
301
 
300
- Offline evaluate by default (no network, no hosted plane); an explicit config honors the live plane. `governA2aSend` gates in-process agent-to-agent sends. A fail-open Python shim with a LangChain middleware is in development and not yet released. Support matrix and recipes: `docs/sdk-integrations.md`; runnable scripts: `examples/sdk/`.
302
+ Offline evaluate by default (no network, no hosted plane); an explicit config uses the live plane. `governA2aSend` gates in-process agent-to-agent sends. A fail-open Python shim with a LangChain middleware is in development and not yet released. Support matrix and recipes: `docs/sdk-integrations.md`; runnable scripts: `examples/sdk/`.
301
303
 
302
304
  ## Claude connector
303
305
 
@@ -305,7 +307,7 @@ Offline evaluate by default (no network, no hosted plane); an explicit config ho
305
307
 
306
308
  ```bash
307
309
  # Prefer a preinstalled package (no registry auto-install):
308
- npx --no-install @shield-agent/kya@0.32.4 serve-mcp --stdio
310
+ npx --no-install @shield-agent/kya@0.32.6-rc.1 serve-mcp --stdio
309
311
  # Or after npm i -g / local install:
310
312
  kya serve-mcp --stdio
311
313
  ```
@@ -316,7 +318,7 @@ Copy `claude/claude_desktop_config.example.json` into Claude Desktop MCP setting
316
318
 
317
319
  ## OpenAI (Codex / Responses)
318
320
 
319
- **Codex CLI plugin (hooks):** see [Codex plugin](#codex-plugin). **Codex CLI / IDE (MCP):** copy `openai/codex.config.example.toml` into `~/.codex/config.toml`. Local stdio uses `npx --no-install @shield-agent/kya@0.32.4 serve-mcp --stdio`. Hosted Codex uses `url = "https://shield-agent.com/mcp"` with `bearer_token_env_var = "KYA_API_KEY"`.
321
+ **Codex CLI plugin (hooks):** see [Codex plugin](#codex-plugin). **Codex CLI / IDE (MCP):** copy `openai/codex.config.example.toml` into `~/.codex/config.toml`. Local stdio uses `npx --no-install @shield-agent/kya@0.32.6-rc.1 serve-mcp --stdio`. Hosted Codex uses `url = "https://shield-agent.com/mcp"` with `bearer_token_env_var = "KYA_API_KEY"`.
320
322
 
321
323
  **Responses API:** see `openai/responses-mcp.example.json` (`server_url` + `Authorization: Bearer <KYA_API_KEY>`).
322
324
 
@@ -364,11 +366,11 @@ npx @shield-agent/kya orr run --path . --out ./orr-report --scorecard ./scorecar
364
366
  npx @shield-agent/kya orr run --path . --out ./orr-report --producer harness.agentshield --agentshield-json ./agentshield-report.json
365
367
  ```
366
368
 
367
- ORR is a reporting board. Scanners, `--scorecard`, and `harness.agentshield` are evidence. They never ALLOW a high-stakes side effect, so they are not a second policy gate. AgentShield is optional and read-only: no `--fix`, no MiniClaw, no runtime hook. This package does not depend on `ecc-agentshield`. If you pass `--producer harness.agentshield` and have neither `--agentshield-json` nor an `agentshield` binary, ORR records a coverage gap and still exits 0. Explicit `--producer` always attempts; `--skip-optional-producers` only skips producers you did not ask for.
369
+ ORR checks if your agent setup is safe to run. It is a reporting board only. Scanners, `--scorecard`, and `harness.agentshield` are evidence. They never ALLOW a high-stakes side effect, so they are not a second policy gate. AgentShield is optional and read-only: no `--fix`, no MiniClaw, no runtime hook. This package does not depend on `ecc-agentshield`. If you pass `--producer harness.agentshield` and have neither `--agentshield-json` nor an `agentshield` binary, ORR records a coverage gap and still exits 0. Explicit `--producer` always attempts; `--skip-optional-producers` only skips producers you did not ask for.
368
370
 
369
- ## Certify (continuous agent assurance)
371
+ ## Certify (ongoing trust checks)
370
372
 
371
- `kya certify` evaluates the open **Agent Trust Baseline** catalog (`catalog/agent-trust-baseline-v0.json` - 31 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.
373
+ `kya certify` evaluates the open **Agent Trust Baseline** catalog (`catalog/agent-trust-baseline-v0.json`: 31 requirements across Data & Privacy, Security, Safety, Reliability, Accountability, Society) against local evidence: the global record, 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 plus a signed evidence bundle.
372
374
 
373
375
  ```bash
374
376
  npx @shield-agent/kya certify # gap report; exit 1 when gaps exist (CI-friendly)
@@ -378,15 +380,15 @@ npx @shield-agent/kya certify --attest SOC-01 --text "Acceptable-use policy: htt
378
380
  npx @shield-agent/kya certify --sign # also emit a signed evidence-bundle.json
379
381
  ```
380
382
 
381
- 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.
383
+ Certify is **evidence-only**. It never ALLOWs, DENYs, or blocks anything. The sole PEP (policy enforcement point: the component that can block a call) remains Shield KYA. Record-based machine checks never pass on an empty record (they report `insufficient_evidence`). What a machine cannot check is covered by explicit local attestations (`--attest`), recorded in `.kya/attestations.json`. These are unverified operator statements, labeled as such.
382
384
 
383
- `--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.
385
+ `--sign` emits `evidence-bundle.json`: canonical JSON, ed25519-signed (a public-key signature) 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**. Bundles from `--sign` verify offline. On the public verify endpoint (`POST /api/v1/kya/evidence/verify`) and badge, they show a grey `self-signed` badge. Only a bundle signed with the key of an active hosted workspace earns the green Shield Verified badge. That ties the badge to a hosted account. It does not prove the legal identity of the company or the agent. The bundle format is open and documented in `docs/certify.md`; anyone can verify a bundle offline with the embedded pubkey.
384
386
 
385
387
  `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`.
386
388
 
387
389
  ## Import traces (LangSmith, Langfuse, Phoenix, OTel, AGT, ADR Sensor, OpenShell)
388
390
 
389
- Bring existing observability exports into the trail so the receipt and certify see them:
391
+ Bring existing monitoring exports into the record so the receipt and certify see them:
390
392
 
391
393
  ```bash
392
394
  kya import --from langsmith ./runs.json
@@ -397,13 +399,13 @@ kya import --from adr-sensor ./adr-sensor-events.jsonl
397
399
  kya import --from openshell ./openshell-events.jsonl
398
400
  ```
399
401
 
400
- The AGT importer verifies AGT's hash chain, flags tampered logs with chainVerified=false, and never duplicates rows on re-import; see [docs/import-agt.md](docs/import-agt.md). ADR Sensor events map one `AgentEvent` to one or more trail events, with stable `uuid` dedup on re-import; see [docs/import-adr-sensor.md](docs/import-adr-sensor.md). OpenShell OCSF logs map one record to one trail event, with stable `uid` dedup on re-import; see [docs/import-openshell.md](docs/import-openshell.md). AGT's hash chain is unkeyed, so "verified" means internally consistent, not authentic. The hosted console accepts the same formats ([docs/import-agt-hosted.md](docs/import-agt-hosted.md)).
402
+ The AGT importer verifies AGT's hash chain (a checksum link between log rows), flags tampered logs with chainVerified=false, and never duplicates rows on re-import; see [docs/import-agt.md](docs/import-agt.md). ADR Sensor events map one `AgentEvent` to one or more KYA events, with stable `uuid` dedup on re-import; see [docs/import-adr-sensor.md](docs/import-adr-sensor.md). OpenShell OCSF logs map one log line to one KYA event, with stable `uid` dedup on re-import; see [docs/import-openshell.md](docs/import-openshell.md). AGT's hash chain is unkeyed (it has no secret key), so "verified" means internally consistent, not authentic. The hosted console accepts the same formats ([docs/import-agt-hosted.md](docs/import-agt-hosted.md)).
401
403
 
402
- 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. The report (`kya start` / `kya receipt`) shows an **Import** card with per-format counts, error count, and the latest imported event once any import has landed.
404
+ 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. Broken records are skipped; they never stop the import. The report (`kya start` / `kya receipt`) shows an **Import** card with per-format counts, error count, and the latest imported event once any import has landed.
403
405
 
404
406
  ## Investigate (detections + fix briefs)
405
407
 
406
- `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. Every run also persists a compact summary to `~/.kya/investigate-last.json`, which the report renders as an **Investigations** card (findings by severity with detector ids, plus the top fix brief).
408
+ `kya investigate` runs fixed local detectors over the record, with 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. Each incident renders a Markdown fix brief shaped to paste into Claude Code, Cursor, or Codex. Every run also saves a compact summary to `~/.kya/investigate-last.json`, which the report renders as an **Investigations** card (findings by severity with detector ids, plus the top fix brief).
407
409
 
408
410
  ```bash
409
411
  kya investigate # summary: counts by severity + top incidents
@@ -412,7 +414,7 @@ kya investigate --json # findings + incidents + briefs, machine-readable
412
414
 
413
415
  ## Endpoint discovery
414
416
 
415
- `kya discover` inventories AI agents, IDE extensions, desktop apps, model runtimes, and MCP servers on the current workstation. The scanner only inspects paths and config files; it never executes discovered binaries and never connects to runtime ports. Snapshots are written to `~/.kya/discovery/<iso-ts>.json` with a `latest.json` copy, and the live report shows a **Discovery** card with totals, sanctioned/review counts, and top categories.
417
+ `kya discover` lists AI agents, IDE extensions, desktop apps, model runtimes, and MCP servers on the current workstation. The scanner only inspects paths and config files; it never executes discovered binaries and never connects to runtime ports. Snapshots are written to `~/.kya/discovery/<iso-ts>.json` with a `latest.json` copy, and the live report shows a **Discovery** card with totals, sanctioned/review counts, and top categories.
416
418
 
417
419
  ```bash
418
420
  kya discover # scan, save snapshot, print summary
@@ -429,24 +431,29 @@ export KYA_API_KEY=your-token
429
431
  kya discover --push
430
432
  ```
431
433
 
432
- Home-directory prefixes are redacted from evidence paths (replaced with `~`). The snapshot includes a stable `endpointUid` derived from the OS, hostname hash, and user hash - no raw hostname or username leaves the machine. See [docs/discovery.md](docs/discovery.md) for the full scan list and privacy notes.
434
+ Home-directory prefixes are redacted from evidence paths (replaced with `~`). The snapshot includes a stable `endpointUid` derived from the OS, a hostname hash, and a user hash. No raw hostname or username leaves the machine. See [docs/discovery.md](docs/discovery.md) for the full scan list and privacy notes.
433
435
 
434
- ## Alert webhooks (verdict routing)
436
+ ## Alert webhooks (decision routing)
435
437
 
436
- Route DENY / REQUIRE_APPROVE events to Slack, Linear, Jira, or any webhook. Config lives in `.kya/config.json` (project) or `~/.kya/config.json` (global):
438
+ Route DENY / REQUIRE_APPROVE events to Slack, Microsoft Teams, Linear, Jira, or any webhook. Config lives in `.kya/config.json` (project) or `~/.kya/config.json` (global):
437
439
 
438
440
  ```json
439
441
  {
440
442
  "notify": {
441
443
  "webhooks": [
442
444
  { "url": "https://hooks.slack.com/services/...", "template": "slack", "events": ["DENY", "REQUIRE_APPROVE"] },
445
+ { "url": "https://<env>.environment.api.powerplatform.com:443/powerautomate/...", "template": "teams", "events": ["DENY"] },
443
446
  { "url": "https://example.invalid/jira", "template": "jira", "events": ["DENY"] }
444
447
  ]
445
448
  }
446
449
  }
447
450
  ```
448
451
 
449
- `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. Every delivery attempt is appended to `~/.kya/notify-log.jsonl` (target host only, never the full URL; capped at the last 500 entries), and the report's System tab shows an **Alerts** panel with per-target delivered/failed counts and the last attempt.
452
+ Every Slack message ends with a line that says a Slack reaction or reply is not an approval. The hosted plane can also post new approval requests to Slack (Approvals > Slack notify in the console); that message only links to the console and has no approve button.
453
+
454
+ The `teams` template sends one Adaptive Card to a Teams Workflows webhook (in Teams: channel, Workflows, "Send webhook alerts to a channel", copy the webhook link). The card has no buttons and ends with a line that says a Teams reaction or reply is not an approval. Event text loses the characters that Teams uses for links, mentions and Markdown. The workflow URL holds a signature, so keep it secret; the notify log stores the host only. The hosted plane can also post new approval requests to Teams (Approvals > Teams notify in the console).
455
+
456
+ `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 (stops sending to a target that keeps failing), and a send rate limiter. Payloads are built only from redacted record fields, with an automatic minimized fallback if the secret scan finds something. From short-lived hook/wrap spawns, a detached helper (`kya notify-flush`) sends the webhooks, so the gate path never waits on the network. Every delivery attempt is appended to `~/.kya/notify-log.jsonl` (target host only, never the full URL; capped at the last 500 entries), and the report's System tab shows an **Alerts** panel with per-target delivered/failed counts and the last attempt.
450
457
 
451
458
  ## Optional sandbox wrap (Firecracker, OpenShell)
452
459
 
@@ -462,7 +469,7 @@ KYA_SANDBOX=mock kya sandbox kill --sandbox-id <id>
462
469
 
463
470
  ## Cost showback (observe only)
464
471
 
465
- `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.
472
+ `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. Events in the record that carry host-reported token counts (hook payloads with a `usage` object, imported traces) are used before the static per-event estimate, and the report states how many window events had real usage.
466
473
 
467
474
  ## Enterprise (separate tier)
468
475
 
@@ -493,6 +500,7 @@ pnpm build
493
500
  - [Works with your observability stack](docs/marketing/observability-stack.md)
494
501
  - [SDK & framework integrations (in-process shims)](docs/sdk-integrations.md)
495
502
  - [Hosted operator SSO / SCIM (not in OSS CLI)](docs/hosted-operator-sso.md)
503
+ - [What is open source and what is hosted](docs/oss-vs-hosted.md)
496
504
  - See also `LIMITATIONS.md` in this repo
497
505
 
498
506
  ## Anonymous usage stats (opt-in, off by default)
@@ -513,7 +521,7 @@ Opt-in. Default off.
513
521
 
514
522
  **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.
515
523
 
516
- **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`. Flush outcomes accumulate in `~/.kya/otel-stats.json` (endpoint host label, spans sent/failed, last export time), rendered as the **OTel export** panel on the report's System tab.
524
+ **Decision span export:** set `KYA_OTLP_EXPORT_ENDPOINT` (or `"otlpExport": { "endpoint": ... }` in `.kya/config.json`) to emit every decision 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 decision. Hook/wrap spawns export DENY / REQUIRE_APPROVE via the detached `notify-flush` helper. Plaintext http is accepted for loopback only unless `"insecure": true`. Flush results collect in `~/.kya/otel-stats.json` (endpoint host label, spans sent/failed, last export time), shown as the **OTel export** panel on the report's System tab.
517
525
 
518
526
  **Hosted plane:** richer Micrometer gauges and timers when `KYA_OTLP_ENABLED=true`.
519
527
 
@@ -2,7 +2,7 @@
2
2
  "amp.mcpServers": {
3
3
  "shield-kya": {
4
4
  "command": "npx",
5
- "args": ["--no-install", "@shield-agent/kya@0.32.4", "serve-mcp", "--stdio"],
5
+ "args": ["--no-install", "@shield-agent/kya@0.32.6-rc.1", "serve-mcp", "--stdio"],
6
6
  "env": {
7
7
  "KYA_BASE_URL": "https://shield-agent.com",
8
8
  "KYA_API_KEY": "${KYA_API_KEY}",