@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.
- package/.mcp.json +1 -1
- package/LIMITATIONS.md +1 -0
- package/README.md +90 -31
- package/amp/settings.example.json +1 -1
- package/claude/claude_desktop_config.example.json +1 -1
- package/cline/cline_mcp_settings.example.json +1 -1
- package/copilot/mcp-config.example.json +1 -1
- package/dist/certify/attest.js +5 -5
- package/dist/certify/catalog.d.ts +1 -1
- package/dist/certify/catalog.js +3 -3
- package/dist/certify/context.js +1 -1
- package/dist/certify/evaluate.d.ts +2 -2
- package/dist/certify/evaluate.js +12 -12
- package/dist/certify/live.js +2 -2
- package/dist/certify/render.d.ts +1 -1
- package/dist/certify/render.js +10 -10
- package/dist/cli.d.ts +4 -2
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +110 -37
- package/dist/cli.js.map +1 -1
- package/dist/commands/certify.d.ts +1 -1
- package/dist/commands/certify.js +3 -3
- package/dist/commands/connect.d.ts +2 -2
- package/dist/commands/connect.js +22 -22
- package/dist/commands/dash.js +4 -4
- package/dist/commands/gate-serve.d.ts.map +1 -1
- package/dist/commands/gate-serve.js +19 -5
- package/dist/commands/gate-serve.js.map +1 -1
- package/dist/commands/gate.d.ts +1 -1
- package/dist/commands/gate.js +16 -16
- package/dist/commands/hook.d.ts +1 -1
- package/dist/commands/hook.d.ts.map +1 -1
- package/dist/commands/hook.js +55 -18
- package/dist/commands/hook.js.map +1 -1
- package/dist/commands/import-traces.d.ts +16 -0
- package/dist/commands/import-traces.d.ts.map +1 -0
- package/dist/commands/import-traces.js +18 -0
- package/dist/commands/import-traces.js.map +1 -0
- package/dist/commands/init.js +1 -1
- package/dist/commands/investigate.d.ts +13 -0
- package/dist/commands/investigate.d.ts.map +1 -0
- package/dist/commands/investigate.js +22 -0
- package/dist/commands/investigate.js.map +1 -0
- package/dist/commands/notify-flush.d.ts +2 -0
- package/dist/commands/notify-flush.d.ts.map +1 -0
- package/dist/commands/notify-flush.js +47 -0
- package/dist/commands/notify-flush.js.map +1 -0
- package/dist/commands/orr.d.ts +3 -3
- package/dist/commands/orr.js +5 -5
- package/dist/commands/receipt-serve.d.ts +1 -1
- package/dist/commands/receipt-serve.js +1 -1
- package/dist/commands/receipt.d.ts +5 -2
- package/dist/commands/receipt.d.ts.map +1 -1
- package/dist/commands/receipt.js +7 -4
- package/dist/commands/receipt.js.map +1 -1
- package/dist/commands/serve-mcp.js +1 -1
- package/dist/commands/start.d.ts +2 -2
- package/dist/commands/start.js +20 -20
- package/dist/commands/stop.d.ts +1 -1
- package/dist/commands/stop.js +6 -6
- package/dist/commands/update.d.ts +19 -0
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/update.js +96 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/commands/wire-hooks.d.ts +1 -1
- package/dist/commands/wire-hooks.js +14 -14
- package/dist/commands/wrap.d.ts.map +1 -1
- package/dist/commands/wrap.js +12 -7
- package/dist/commands/wrap.js.map +1 -1
- package/dist/config.d.ts +4 -4
- package/dist/config.js +5 -5
- package/dist/dash/dash.d.ts +1 -1
- package/dist/dash/dash.js +3 -3
- package/dist/dash/entitlement.d.ts +1 -1
- package/dist/dash/entitlement.js +1 -1
- package/dist/dash/render.js +2 -2
- package/dist/dash/screens/enterprise.js +9 -9
- package/dist/dash/screens/free.js +5 -5
- package/dist/diff-preview.d.ts +1 -1
- package/dist/diff-preview.js +2 -2
- package/dist/errors.d.ts +1 -1
- package/dist/errors.js +1 -1
- package/dist/fs-atomic.d.ts +1 -1
- package/dist/fs-atomic.js +2 -2
- package/dist/gate/binary.js +4 -4
- package/dist/gate/config-gen.d.ts +1 -1
- package/dist/gate/config-gen.js +7 -7
- package/dist/gate/config.d.ts +2 -2
- package/dist/gate/config.js +6 -6
- package/dist/gate/daemon.js +1 -1
- package/dist/gate/discover.d.ts +2 -2
- package/dist/gate/discover.js +7 -7
- package/dist/gate/hosted-sync.js +1 -1
- package/dist/gate/otlp-decode.d.ts +2 -2
- package/dist/gate/otlp-decode.js +2 -2
- package/dist/gate/otlp-receiver.d.ts +1 -1
- package/dist/gate/otlp-receiver.js +3 -3
- package/dist/host-reload.js +11 -11
- package/dist/host-tools.d.ts +1 -1
- package/dist/host-tools.js +1 -1
- package/dist/importers/formats.d.ts +26 -0
- package/dist/importers/formats.d.ts.map +1 -0
- package/dist/importers/formats.js +281 -0
- package/dist/importers/formats.js.map +1 -0
- package/dist/importers/index.d.ts +26 -0
- package/dist/importers/index.d.ts.map +1 -0
- package/dist/importers/index.js +122 -0
- package/dist/importers/index.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/investigate/detectors.d.ts +35 -0
- package/dist/investigate/detectors.d.ts.map +1 -0
- package/dist/investigate/detectors.js +277 -0
- package/dist/investigate/detectors.js.map +1 -0
- package/dist/investigate/fix-brief.d.ts +3 -0
- package/dist/investigate/fix-brief.d.ts.map +1 -0
- package/dist/investigate/fix-brief.js +88 -0
- package/dist/investigate/fix-brief.js.map +1 -0
- package/dist/investigate/incidents.d.ts +19 -0
- package/dist/investigate/incidents.d.ts.map +1 -0
- package/dist/investigate/incidents.js +84 -0
- package/dist/investigate/incidents.js.map +1 -0
- package/dist/investigate/index.d.ts +25 -0
- package/dist/investigate/index.d.ts.map +1 -0
- package/dist/investigate/index.js +46 -0
- package/dist/investigate/index.js.map +1 -0
- package/dist/mcp/protocol.d.ts +2 -2
- package/dist/mcp/protocol.d.ts.map +1 -1
- package/dist/mcp/protocol.js +39 -8
- package/dist/mcp/protocol.js.map +1 -1
- package/dist/mcp/stdio.d.ts +1 -1
- package/dist/mcp/stdio.js +2 -2
- package/dist/mcp-servers.d.ts +2 -2
- package/dist/mcp-servers.js +2 -2
- package/dist/node-upgrade.d.ts +2 -2
- package/dist/node-upgrade.js +9 -9
- package/dist/notify/dispatch.d.ts +20 -0
- package/dist/notify/dispatch.d.ts.map +1 -0
- package/dist/notify/dispatch.js +52 -0
- package/dist/notify/dispatch.js.map +1 -0
- package/dist/notify/index.d.ts +39 -0
- package/dist/notify/index.d.ts.map +1 -0
- package/dist/notify/index.js +119 -0
- package/dist/notify/index.js.map +1 -0
- package/dist/notify/sender.d.ts +56 -0
- package/dist/notify/sender.d.ts.map +1 -0
- package/dist/notify/sender.js +139 -0
- package/dist/notify/sender.js.map +1 -0
- package/dist/notify/templates.d.ts +33 -0
- package/dist/notify/templates.d.ts.map +1 -0
- package/dist/notify/templates.js +119 -0
- package/dist/notify/templates.js.map +1 -0
- package/dist/offline-evaluate.d.ts +2 -2
- package/dist/offline-evaluate.js +3 -3
- package/dist/orr/agentshield.d.ts +2 -2
- package/dist/orr/agentshield.js +4 -4
- package/dist/orr/scorecard.d.ts +1 -1
- package/dist/orr/scorecard.js +3 -3
- package/dist/otel/exporter.d.ts +64 -0
- package/dist/otel/exporter.d.ts.map +1 -0
- package/dist/otel/exporter.js +243 -0
- package/dist/otel/exporter.js.map +1 -0
- package/dist/parse-args.d.ts +1 -1
- package/dist/parse-args.js +1 -1
- package/dist/receipt/auto-open.d.ts +1 -1
- package/dist/receipt/auto-open.js +1 -1
- package/dist/receipt/daemon.d.ts +6 -6
- package/dist/receipt/daemon.js +15 -15
- package/dist/receipt/dashboard.d.ts +1 -1
- package/dist/receipt/dashboard.js +2 -2
- package/dist/receipt/embeddings.d.ts +15 -4
- package/dist/receipt/embeddings.d.ts.map +1 -1
- package/dist/receipt/embeddings.js +116 -35
- package/dist/receipt/embeddings.js.map +1 -1
- package/dist/receipt/enrich.d.ts +2 -2
- package/dist/receipt/enrich.js +5 -5
- package/dist/receipt/gate-card.d.ts +2 -2
- package/dist/receipt/gate-card.d.ts.map +1 -1
- package/dist/receipt/gate-card.js +3 -3
- package/dist/receipt/live-server.d.ts.map +1 -1
- package/dist/receipt/live-server.js +22 -8
- package/dist/receipt/live-server.js.map +1 -1
- package/dist/receipt/receipt-css.d.ts +1 -1
- package/dist/receipt/receipt-css.d.ts.map +1 -1
- package/dist/receipt/receipt-css.js +72 -11
- package/dist/receipt/receipt-css.js.map +1 -1
- package/dist/receipt/render-receipt.d.ts +1 -1
- package/dist/receipt/render-receipt.d.ts.map +1 -1
- package/dist/receipt/render-receipt.js +138 -87
- package/dist/receipt/render-receipt.js.map +1 -1
- package/dist/receipt/share.d.ts +21 -2
- package/dist/receipt/share.d.ts.map +1 -1
- package/dist/receipt/share.js +68 -5
- package/dist/receipt/share.js.map +1 -1
- package/dist/sample-tools.d.ts +1 -1
- package/dist/sample-tools.js +1 -1
- package/dist/sandbox/mock-driver.d.ts +1 -1
- package/dist/sandbox/mock-driver.js +1 -1
- package/dist/sdk/a2a.d.ts +2 -2
- package/dist/sdk/a2a.js +1 -1
- package/dist/sdk/adapters/claude-agent.d.ts +1 -1
- package/dist/sdk/adapters/claude-agent.js +1 -1
- package/dist/sdk/adapters/langgraph.d.ts +1 -1
- package/dist/sdk/adapters/langgraph.js +1 -1
- package/dist/sdk/adapters/mastra.d.ts +1 -1
- package/dist/sdk/adapters/mastra.js +1 -1
- package/dist/sdk/adapters/openai-agents.d.ts +1 -1
- package/dist/sdk/adapters/openai-agents.js +1 -1
- package/dist/sdk/adapters/vercel-ai.d.ts +2 -2
- package/dist/sdk/adapters/vercel-ai.js +1 -1
- package/dist/sdk/govern.d.ts +2 -2
- package/dist/sdk/govern.js +3 -3
- package/dist/sdk/index.d.ts +1 -1
- package/dist/sdk/index.js +1 -1
- package/dist/showback/trail-usage.d.ts +30 -0
- package/dist/showback/trail-usage.d.ts.map +1 -0
- package/dist/showback/trail-usage.js +50 -0
- package/dist/showback/trail-usage.js.map +1 -0
- package/dist/sign/evidence-bundle.d.ts +6 -6
- package/dist/sign/evidence-bundle.js +5 -5
- package/dist/star-cta.d.ts +1 -1
- package/dist/star-cta.d.ts.map +1 -1
- package/dist/star-cta.js +3 -3
- package/dist/telemetry.d.ts +135 -0
- package/dist/telemetry.d.ts.map +1 -0
- package/dist/telemetry.js +427 -0
- package/dist/telemetry.js.map +1 -0
- package/dist/trail-summary.d.ts +1 -1
- package/dist/trail-summary.js +3 -3
- package/dist/trail.d.ts +8 -2
- package/dist/trail.d.ts.map +1 -1
- package/dist/trail.js +18 -5
- package/dist/trail.js.map +1 -1
- package/dist/update-check.d.ts +17 -0
- package/dist/update-check.d.ts.map +1 -0
- package/dist/update-check.js +134 -0
- package/dist/update-check.js.map +1 -0
- package/droid/README.md +1 -1
- package/droid/mcp.example.json +1 -1
- package/gemini/settings.example.json +1 -1
- package/grok/README.md +1 -1
- package/kilo/kilo.example.json +1 -1
- package/kimi/mcp.example.json +1 -1
- package/kiro/mcp.example.json +1 -1
- package/manifest.json +1 -1
- package/mastracode/mcp.example.json +1 -1
- package/mcp.json +1 -1
- package/openai/codex.config.example.toml +1 -1
- package/opencode/opencode.example.json +1 -1
- package/package.json +4 -3
- package/qwen/settings.example.json +1 -1
- 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.
|
|
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
|
[](https://x.com/coscosmico)
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
**AI agents audit trail & traceability.** Every tool call your coding agents make
|
|
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
|
|
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
|
|
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
|
-

|
|
49
49
|
|
|
50
|
-

|
|
51
51
|
|
|
52
|
-

|
|
53
53
|
|
|
54
|
-

|
|
55
55
|
|
|
56
|
-

|
|
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`
|
|
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
|
|
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
|
|
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)
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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`
|
|
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.
|
|
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.
|
|
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.
|
|
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`) |
|
|
277
|
-
| Grok CLI | `kya connect grok` |
|
|
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`
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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/dist/certify/attest.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Operator attestations
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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/…
|
|
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;
|
package/dist/certify/catalog.js
CHANGED
|
@@ -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
|
|
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/…
|
|
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
|
|
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
|
}
|
package/dist/certify/context.js
CHANGED
|
@@ -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)
|
|
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
|
|
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
|
|
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"];
|
package/dist/certify/evaluate.js
CHANGED
|
@@ -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
|
|
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}
|
|
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}
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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)
|
|
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).
|
package/dist/certify/live.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Live in-memory certify evaluation
|
|
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
|
|
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
|
}
|
package/dist/certify/render.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { CertifyReport } from "./evaluate.js";
|
|
2
|
-
/** Shared domain display labels
|
|
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 {
|