@raishin/vanguard-frontier-agentic 3.15.0 → 3.16.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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.cursor-plugin/plugin.json +1 -1
- package/.github/plugin/marketplace.json +1 -1
- package/catalog/AGENTS.md +2 -1
- package/catalog/asset-integrity.json +476 -29
- package/catalog/index.json +3 -2
- package/catalog/mods.json +131 -0
- package/mods/README.md +220 -0
- package/mods/audit-trail/README.md +70 -0
- package/mods/audit-trail/bin/hook.mjs +65 -0
- package/mods/audit-trail/claude-code/UNSUPPORTED.md +11 -0
- package/mods/audit-trail/claude-code/settings.hooks.json +14 -0
- package/mods/audit-trail/codex/hooks.json +14 -0
- package/mods/audit-trail/kiro/UNSUPPORTED.md +7 -0
- package/mods/audit-trail/kiro/audit-trail-post-tool-use-hook.json +14 -0
- package/mods/audit-trail/lib/common.mjs +213 -0
- package/mods/audit-trail/lib/core.mjs +50 -0
- package/mods/audit-trail/lib/runtime.mjs +140 -0
- package/mods/audit-trail/mod.toml +37 -0
- package/mods/blast-radius-guard/.claude-plugin/plugin.json +5 -0
- package/mods/blast-radius-guard/README.md +53 -0
- package/mods/blast-radius-guard/bin/hook.mjs +18 -0
- package/mods/blast-radius-guard/claude-code/settings.hooks.json +14 -0
- package/mods/blast-radius-guard/codex/UNSUPPORTED.md +7 -0
- package/mods/blast-radius-guard/codex/hooks.json +14 -0
- package/mods/blast-radius-guard/hooks/hooks.json +5 -0
- package/mods/blast-radius-guard/hooks/register.test.ts +97 -0
- package/mods/blast-radius-guard/hooks/register.ts +13 -0
- package/mods/blast-radius-guard/kiro/UNSUPPORTED.md +7 -0
- package/mods/blast-radius-guard/kiro/blast-radius-guard-pre-tool-use-hook.json +14 -0
- package/mods/blast-radius-guard/lib/common.mjs +213 -0
- package/mods/blast-radius-guard/lib/core.mjs +66 -0
- package/mods/blast-radius-guard/lib/patterns.mjs +102 -0
- package/mods/blast-radius-guard/lib/runtime.mjs +140 -0
- package/mods/blast-radius-guard/mod.toml +34 -0
- package/mods/blast-radius-guard/patterns.json +101 -0
- package/mods/context-burn/.claude-plugin/plugin.json +5 -0
- package/mods/context-burn/README.md +66 -0
- package/mods/context-burn/bin/hook.mjs +38 -0
- package/mods/context-burn/claude-code/UNSUPPORTED.md +7 -0
- package/mods/context-burn/claude-code/settings.hooks.json +24 -0
- package/mods/context-burn/codex/UNSUPPORTED.md +7 -0
- package/mods/context-burn/codex/hooks.json +24 -0
- package/mods/context-burn/hooks/hooks.json +5 -0
- package/mods/context-burn/hooks/register.test.ts +151 -0
- package/mods/context-burn/hooks/register.ts +35 -0
- package/mods/context-burn/kiro/UNSUPPORTED.md +7 -0
- package/mods/context-burn/kiro/context-burn-post-tool-use-hook.json +14 -0
- package/mods/context-burn/kiro/context-burn-session-start-hook.json +14 -0
- package/mods/context-burn/lib/common.mjs +213 -0
- package/mods/context-burn/lib/core.mjs +79 -0
- package/mods/context-burn/lib/runtime.mjs +140 -0
- package/mods/context-burn/mod.toml +37 -0
- package/mods/live-guard-gate/.claude-plugin/plugin.json +5 -0
- package/mods/live-guard-gate/README.md +43 -0
- package/mods/live-guard-gate/bin/hook.mjs +12 -0
- package/mods/live-guard-gate/claude-code/settings.hooks.json +14 -0
- package/mods/live-guard-gate/codex/UNSUPPORTED.md +7 -0
- package/mods/live-guard-gate/codex/hooks.json +14 -0
- package/mods/live-guard-gate/hooks/hooks.json +5 -0
- package/mods/live-guard-gate/hooks/register.test.ts +59 -0
- package/mods/live-guard-gate/hooks/register.ts +11 -0
- package/mods/live-guard-gate/kiro/UNSUPPORTED.md +7 -0
- package/mods/live-guard-gate/kiro/live-guard-gate-pre-tool-use-hook.json +14 -0
- package/mods/live-guard-gate/lib/common.mjs +213 -0
- package/mods/live-guard-gate/lib/core.mjs +24 -0
- package/mods/live-guard-gate/lib/live-agents.mjs +65 -0
- package/mods/live-guard-gate/lib/patterns.mjs +523 -0
- package/mods/live-guard-gate/lib/runtime.mjs +140 -0
- package/mods/live-guard-gate/mod.toml +34 -0
- package/mods/live-guard-gate/patterns.json +522 -0
- package/mods/secret-redactor/.claude-plugin/plugin.json +5 -0
- package/mods/secret-redactor/README.md +86 -0
- package/mods/secret-redactor/bin/hook.mjs +35 -0
- package/mods/secret-redactor/claude-code/UNSUPPORTED.md +7 -0
- package/mods/secret-redactor/claude-code/settings.hooks.json +24 -0
- package/mods/secret-redactor/codex/UNSUPPORTED.md +11 -0
- package/mods/secret-redactor/codex/hooks.json +14 -0
- package/mods/secret-redactor/hooks/hooks.json +5 -0
- package/mods/secret-redactor/hooks/register.test.ts +150 -0
- package/mods/secret-redactor/hooks/register.ts +19 -0
- package/mods/secret-redactor/kiro/UNSUPPORTED.md +11 -0
- package/mods/secret-redactor/kiro/secret-redactor-pre-tool-use-hook.json +14 -0
- package/mods/secret-redactor/lib/common.mjs +213 -0
- package/mods/secret-redactor/lib/core.mjs +61 -0
- package/mods/secret-redactor/lib/patterns.mjs +75 -0
- package/mods/secret-redactor/lib/runtime.mjs +140 -0
- package/mods/secret-redactor/mod.toml +43 -0
- package/mods/secret-redactor/patterns.json +74 -0
- package/package.json +8 -4
- package/plugins/vanguard-frontier-agentic/.codex-plugin/plugin.json +1 -1
- package/scripts/generate-mods.mjs +784 -0
- package/scripts/mods/common.mjs +213 -0
- package/scripts/mods/runtime.mjs +140 -0
- package/tests/fixtures/README.md +1 -1
- package/tests/fuzz-properties.test.mjs +254 -0
- package/tests/mods.test.mjs +768 -0
- package/tests/validate-asset-integrity.py +1 -0
- package/tests/validate-mods.py +821 -0
package/catalog/index.json
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vanguard-frontier-agentic",
|
|
3
|
-
"summary": "Curated cross-harness marketplace for cloud-focused agent skills, agents, rules, MCP references,
|
|
3
|
+
"summary": "Curated cross-harness marketplace for cloud-focused agent skills, agents, rules, MCP references, delegation workflows, and mods.",
|
|
4
4
|
"last_updated": "2026-05-09",
|
|
5
5
|
"catalogs": {
|
|
6
6
|
"skills": "catalog/skills.json",
|
|
7
7
|
"agents": "catalog/agents.json",
|
|
8
8
|
"rules": "catalog/rules.json",
|
|
9
9
|
"mcp_references": "catalog/mcp-references.json",
|
|
10
|
-
"workflows": "catalog/workflows.json"
|
|
10
|
+
"workflows": "catalog/workflows.json",
|
|
11
|
+
"mods": "catalog/mods.json"
|
|
11
12
|
}
|
|
12
13
|
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"id": "audit-trail",
|
|
4
|
+
"name": "Audit Trail",
|
|
5
|
+
"version": "1.0.0",
|
|
6
|
+
"description": "Appends one JSON line per tool call to a per-session log with sha256 hashes of the arguments and result.",
|
|
7
|
+
"reach_level": 1,
|
|
8
|
+
"events": [
|
|
9
|
+
"PostToolUse"
|
|
10
|
+
],
|
|
11
|
+
"harnesses": [
|
|
12
|
+
"claude-code",
|
|
13
|
+
"codex",
|
|
14
|
+
"kiro"
|
|
15
|
+
],
|
|
16
|
+
"path": "mods/audit-trail",
|
|
17
|
+
"footprint": {
|
|
18
|
+
"env_reads": [
|
|
19
|
+
"VANGUARD_AUDIT_TRAIL_LOG_DIR",
|
|
20
|
+
"VANGUARD_AUDIT_TRAIL_SESSION_ID",
|
|
21
|
+
"VANGUARD_AUDIT_TRAIL_AGENT_ID"
|
|
22
|
+
],
|
|
23
|
+
"file_writes": [
|
|
24
|
+
".audit/**"
|
|
25
|
+
],
|
|
26
|
+
"spawns": [],
|
|
27
|
+
"egress_hosts": []
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"id": "blast-radius-guard",
|
|
32
|
+
"name": "Blast Radius Guard",
|
|
33
|
+
"version": "1.0.0",
|
|
34
|
+
"description": "Asks before, or blocks, destructive shell commands and writes to system paths.",
|
|
35
|
+
"reach_level": 0,
|
|
36
|
+
"events": [
|
|
37
|
+
"PreToolUse"
|
|
38
|
+
],
|
|
39
|
+
"harnesses": [
|
|
40
|
+
"claude-code",
|
|
41
|
+
"codex",
|
|
42
|
+
"kiro"
|
|
43
|
+
],
|
|
44
|
+
"path": "mods/blast-radius-guard",
|
|
45
|
+
"footprint": {
|
|
46
|
+
"env_reads": [
|
|
47
|
+
"VANGUARD_BLAST_RADIUS_GUARD_MODE",
|
|
48
|
+
"VANGUARD_BLAST_RADIUS_GUARD_PATTERNS"
|
|
49
|
+
],
|
|
50
|
+
"file_writes": [],
|
|
51
|
+
"spawns": [],
|
|
52
|
+
"egress_hosts": []
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"id": "context-burn",
|
|
57
|
+
"name": "Context Burn",
|
|
58
|
+
"version": "1.0.0",
|
|
59
|
+
"description": "Tracks context use per session in a status file and warns at 70% and 90% where the harness reports token use.",
|
|
60
|
+
"reach_level": 1,
|
|
61
|
+
"events": [
|
|
62
|
+
"PostToolUse",
|
|
63
|
+
"SessionStart"
|
|
64
|
+
],
|
|
65
|
+
"harnesses": [
|
|
66
|
+
"claude-code",
|
|
67
|
+
"codex",
|
|
68
|
+
"kiro"
|
|
69
|
+
],
|
|
70
|
+
"path": "mods/context-burn",
|
|
71
|
+
"footprint": {
|
|
72
|
+
"env_reads": [
|
|
73
|
+
"VANGUARD_CONTEXT_BURN_STATUS_PATH"
|
|
74
|
+
],
|
|
75
|
+
"file_writes": [
|
|
76
|
+
".claude/context-burn-status/*.json",
|
|
77
|
+
".kiro/context-burn-status/*.json",
|
|
78
|
+
".codex/context-burn-status/*.json"
|
|
79
|
+
],
|
|
80
|
+
"spawns": [],
|
|
81
|
+
"egress_hosts": []
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
"id": "live-guard-gate",
|
|
86
|
+
"name": "Live Guard Gate",
|
|
87
|
+
"version": "1.0.0",
|
|
88
|
+
"description": "Asks before live cloud mutations and names the guard agent that should review them.",
|
|
89
|
+
"reach_level": 0,
|
|
90
|
+
"events": [
|
|
91
|
+
"PreToolUse"
|
|
92
|
+
],
|
|
93
|
+
"harnesses": [
|
|
94
|
+
"claude-code",
|
|
95
|
+
"codex",
|
|
96
|
+
"kiro"
|
|
97
|
+
],
|
|
98
|
+
"path": "mods/live-guard-gate",
|
|
99
|
+
"footprint": {
|
|
100
|
+
"env_reads": [],
|
|
101
|
+
"file_writes": [],
|
|
102
|
+
"spawns": [],
|
|
103
|
+
"egress_hosts": []
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
"id": "secret-redactor",
|
|
108
|
+
"name": "Secret Redactor",
|
|
109
|
+
"version": "1.0.0",
|
|
110
|
+
"description": "Asks before tool calls whose input carries a credential and redacts credentials from tool output.",
|
|
111
|
+
"reach_level": 0,
|
|
112
|
+
"events": [
|
|
113
|
+
"PreToolUse",
|
|
114
|
+
"PostToolUse"
|
|
115
|
+
],
|
|
116
|
+
"harnesses": [
|
|
117
|
+
"claude-code",
|
|
118
|
+
"codex",
|
|
119
|
+
"kiro"
|
|
120
|
+
],
|
|
121
|
+
"path": "mods/secret-redactor",
|
|
122
|
+
"footprint": {
|
|
123
|
+
"env_reads": [
|
|
124
|
+
"VANGUARD_SECRET_REDACTOR_PATTERNS"
|
|
125
|
+
],
|
|
126
|
+
"file_writes": [],
|
|
127
|
+
"spawns": [],
|
|
128
|
+
"egress_hosts": []
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
]
|
package/mods/README.md
ADDED
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
# Vanguard Mods
|
|
2
|
+
|
|
3
|
+
<div align="center">
|
|
4
|
+
|
|
5
|
+
<img src="../assets/logos/vanguard-frontier-agentic-logo.png" alt="Vanguard Frontier Agentic" width="140" />
|
|
6
|
+
|
|
7
|
+
<p><strong>Less “oops.” More visibility.</strong></p>
|
|
8
|
+
<p>Tool-call guardrails and observers for Claude Code, Kiro and Codex.</p>
|
|
9
|
+
|
|
10
|
+
<p>
|
|
11
|
+
<a href="#pick-a-mod">Pick a mod</a> ·
|
|
12
|
+
<a href="#get-started">Get started</a> ·
|
|
13
|
+
<a href="#know-the-limits">Know the limits</a> ·
|
|
14
|
+
<a href="#under-the-hood">Under the hood</a>
|
|
15
|
+
</p>
|
|
16
|
+
|
|
17
|
+
</div>
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
Skills guide the agent. **Mods inspect its tool calls.** Ask before risky actions,
|
|
22
|
+
redact supported output, or record what happened. Pick what you need—not everything at once.
|
|
23
|
+
|
|
24
|
+
<a id="pick-a-mod"></a>
|
|
25
|
+
|
|
26
|
+
## 🧰 Pick your guardrails
|
|
27
|
+
|
|
28
|
+
| Mod | The job | Reach |
|
|
29
|
+
| --- | --- | --- |
|
|
30
|
+
| [Secret Redactor](secret-redactor/README.md) | Spot credential-shaped input; redact supported output. | L0 |
|
|
31
|
+
| [Blast Radius Guard](blast-radius-guard/README.md) | Ask or deny on destructive commands and system-path writes. | L0 |
|
|
32
|
+
| [Live Guard Gate](live-guard-gate/README.md) | Flag cloud mutations and name guard agents to consult. | L0 |
|
|
33
|
+
| [Context Burn](context-burn/README.md) | Count tool calls; warn on reported context use where supported. | L1 |
|
|
34
|
+
| [Audit Trail](audit-trail/README.md) | Append call hashes and per-session sequence numbers. | L1 |
|
|
35
|
+
|
|
36
|
+
**Reach is a label, not a sandbox:** L0 = no declared writes/spawns/network;
|
|
37
|
+
L1 = file writes; L2 = subprocesses; L3 = network (warned, not blocked).
|
|
38
|
+
Reads are allowed at L0; starting the Node adapter is not a mod-spawned subprocess.
|
|
39
|
+
|
|
40
|
+
**Support differs:** Kiro/Codex deny instead of asking and cannot redact output.
|
|
41
|
+
Claude Code Audit Trail needs classic. Classic Post hooks miss failed calls.
|
|
42
|
+
|
|
43
|
+
<details>
|
|
44
|
+
<summary><strong>🔎 Same mod, different harness? Check the fine print.</strong></summary>
|
|
45
|
+
|
|
46
|
+
| Mod | Claude Code native | Claude Code classic | Kiro / Codex |
|
|
47
|
+
| --- | --- | --- | --- |
|
|
48
|
+
| Secret Redactor | Ask on input; redact or withhold output | Ask on input; replace successful output only | Deny matching input; no output redaction |
|
|
49
|
+
| Blast Radius Guard | Ask in confirm mode; deny in block mode | Same | Deny in either mode |
|
|
50
|
+
| Live Guard Gate | Ask and name guard agents | Same | Deny and name guard agents |
|
|
51
|
+
| Context Burn | Session context usage and threshold toasts | Tool-call counter only | Tool-call counter only |
|
|
52
|
+
| Audit Trail | Unsupported—use classic | Append after successful calls | Append; Kiro payload interpretation is degraded |
|
|
53
|
+
|
|
54
|
+
Guards use `PreToolUse`; supported redaction and observers use `PostToolUse`;
|
|
55
|
+
Context Burn also uses `SessionStart`.
|
|
56
|
+
Native equivalents are `tool.check`, `tool.call` and `session.start`.
|
|
57
|
+
|
|
58
|
+
Kiro's stdin fields are undocumented: guards scan the whole payload if input is
|
|
59
|
+
unrecognized; Audit Trail hashes that payload as arguments and `null` as the result.
|
|
60
|
+
Set `VANGUARD_AUDIT_TRAIL_SESSION_ID` to avoid its shared `unsessioned` fallback.
|
|
61
|
+
See generated `<harness>/UNSUPPORTED.md` for remaining limits.
|
|
62
|
+
|
|
63
|
+
</details>
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
<a id="get-started"></a>
|
|
68
|
+
|
|
69
|
+
## 🚀 Get started
|
|
70
|
+
|
|
71
|
+
Use a local checkout. Command adapters need **Node 22+**; native modules use the
|
|
72
|
+
harness runtime. No service needed.
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
source=/absolute/path/to/vanguard-frontier-agentic
|
|
76
|
+
target=/absolute/path/to/your/project
|
|
77
|
+
mod=blast-radius-guard
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
> [!IMPORTANT]
|
|
81
|
+
> **Native or classic. Not both for the same mod.** They duplicate checks and can
|
|
82
|
+
> double-count Context Burn. Audit Trail has no native adapter—use classic.
|
|
83
|
+
|
|
84
|
+
<details>
|
|
85
|
+
<summary><strong>🤖 Claude Code native</strong> — load a plugin root</summary>
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
cd "$target"
|
|
89
|
+
claude --plugin-dir "$source/mods/$mod"
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Not for `audit-trail`. Native API: early access. Check the verified build in the
|
|
93
|
+
[implementation notes](#under-the-hood) before upgrading.
|
|
94
|
+
|
|
95
|
+
</details>
|
|
96
|
+
|
|
97
|
+
<details>
|
|
98
|
+
<summary><strong>🤖 Claude Code classic</strong> — copy, then merge hooks</summary>
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
mkdir -p "$target/.claude/vanguard-mods/$mod"
|
|
102
|
+
cp -R "$source/mods/$mod/bin" "$source/mods/$mod/lib" "$target/.claude/vanguard-mods/$mod/"
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Append `mods/<id>/claude-code/settings.hooks.json` entries under `hooks` in the
|
|
106
|
+
target's `.claude/settings.json`. **Keep existing hooks/settings.** Generated command:
|
|
107
|
+
|
|
108
|
+
```text
|
|
109
|
+
node "$CLAUDE_PROJECT_DIR/.claude/vanguard-mods/<id>/bin/hook.mjs" --harness claude-code --event <event>
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
`CLAUDE_PROJECT_DIR` stays at the initial project root, even across worktree changes.
|
|
113
|
+
Observers resolve relative writes from the installed adapter location.
|
|
114
|
+
|
|
115
|
+
</details>
|
|
116
|
+
|
|
117
|
+
<details>
|
|
118
|
+
<summary><strong>🔮 Kiro</strong> — copy the adapters and hook JSON</summary>
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
mkdir -p "$target/.kiro/hooks" "$target/.kiro/vanguard-mods/$mod"
|
|
122
|
+
cp -R "$source/mods/$mod/bin" "$source/mods/$mod/lib" "$target/.kiro/vanguard-mods/$mod/"
|
|
123
|
+
cp "$source/mods/$mod/kiro/"*-hook.json "$target/.kiro/hooks/"
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Copy only `*-hook.json`, not `UNSUPPORTED.md`. Replace the relative script path
|
|
127
|
+
inside each hook with its **absolute installed path**: hook cwd is undocumented.
|
|
128
|
+
Commands use `--harness kiro --event <event>`; confirmation requests deny with exit 2.
|
|
129
|
+
|
|
130
|
+
</details>
|
|
131
|
+
|
|
132
|
+
<details>
|
|
133
|
+
<summary><strong>⚡ Codex</strong> — copy, merge, then review trust</summary>
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
mkdir -p "$target/.codex/vanguard-mods/$mod"
|
|
137
|
+
cp -R "$source/mods/$mod/bin" "$source/mods/$mod/lib" "$target/.codex/vanguard-mods/$mod/"
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Append event entries from `mods/<id>/codex/hooks.json` to the target's
|
|
141
|
+
`.codex/hooks.json`, preserving existing hooks. Replace relative script paths with
|
|
142
|
+
**absolute installed paths**; hook cwd is undocumented. Complete Codex's hook trust review.
|
|
143
|
+
|
|
144
|
+
Commands use `--harness codex --event <event>`; asks deny with exit 2.
|
|
145
|
+
Redactor Post is unsupported; the narrower MCP output field is not substituted.
|
|
146
|
+
|
|
147
|
+
</details>
|
|
148
|
+
|
|
149
|
+
**Try it before trusting it:** run ordinary and harmless pattern-matching calls in
|
|
150
|
+
the harness. Inspect the decision, output or observer file—not just exit codes.
|
|
151
|
+
Repeat after path, permission, Node or harness changes.
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
<a id="know-the-limits"></a>
|
|
156
|
+
|
|
157
|
+
## ⚠️ Guardrails, not guarantees
|
|
158
|
+
|
|
159
|
+
- **A hook must run to help.** Guards deny handler/input errors; missing Node,
|
|
160
|
+
moved scripts, startup crashes and timeouts can leave calls unguarded.
|
|
161
|
+
CLI errors may not block; Kiro IDE handling differs.
|
|
162
|
+
- **Regex is not complete DLP.** Pre checks never rewrite arguments; approved input
|
|
163
|
+
still reaches the tool. Post redaction does not scrub other logs or network traffic.
|
|
164
|
+
Redactor errors attempt withholding; classic shape mismatches may be ignored.
|
|
165
|
+
[Withholding has limits, too](secret-redactor/README.md#limitations).
|
|
166
|
+
- **A review prompt is not authorization.** Live Guard Gate names agents—it never
|
|
167
|
+
spawns them or verifies production accounts. Guards scan strings, not shell semantics;
|
|
168
|
+
relative paths stay unresolved. Bypass modes can auto-approve an ask.
|
|
169
|
+
- **Observers are not compliance proof.** Node counters track calls, not tokens or
|
|
170
|
+
spend; only native Context Burn uses reported context data. Unlocked updates can
|
|
171
|
+
lose increments. Audit logs are mutable, unsigned and not tamper-evident.
|
|
172
|
+
Observer failures do not block tools.
|
|
173
|
+
|
|
174
|
+
<details>
|
|
175
|
+
<summary><strong>🗂️ State files and custom patterns</strong></summary>
|
|
176
|
+
|
|
177
|
+
- **Context Burn:** `.<harness>/context-burn-status/<session-hash>.json`
|
|
178
|
+
(`.claude` for Claude Code). Filenames use the full lowercase SHA-256 of the UTF-8
|
|
179
|
+
session ID, never raw IDs. Missing/empty Node IDs share `unsessioned` state.
|
|
180
|
+
`VANGUARD_CONTEXT_BURN_STATUS_PATH` is an exact override; sharing it opts out of
|
|
181
|
+
isolation. Old single-file state is not migrated automatically.
|
|
182
|
+
- **Audit Trail:** `.audit/<UTC-date>/<session>.jsonl`; an earlier file is reused
|
|
183
|
+
across dates. `VANGUARD_AUDIT_TRAIL_LOG_DIR` overrides the directory.
|
|
184
|
+
- **Footprints disclose defaults, not containment.** Overrides can write outside
|
|
185
|
+
declared globs; overlap checks do not constrain operator overrides.
|
|
186
|
+
- **Patterns append, never replace.** `VANGUARD_SECRET_REDACTOR_PATTERNS` and
|
|
187
|
+
`VANGUARD_BLAST_RADIUS_GUARD_PATTERNS` accept extra pattern files. Use absolute paths.
|
|
188
|
+
Unreadable/invalid configured files deny guards or withhold redactor output.
|
|
189
|
+
Each mod README documents schemas and environment names.
|
|
190
|
+
|
|
191
|
+
</details>
|
|
192
|
+
|
|
193
|
+
<a id="under-the-hood"></a>
|
|
194
|
+
|
|
195
|
+
## 🔧 Under the hood
|
|
196
|
+
|
|
197
|
+
`mod.toml` declares support and footprint; `lib/core.mjs` holds shared behavior.
|
|
198
|
+
Edit those sources, `patterns.json`, entries and native modules—not generated adapters.
|
|
199
|
+
The generator produces manifests, shared runtime copies, pattern modules and `catalog/mods.json`.
|
|
200
|
+
|
|
201
|
+
<details>
|
|
202
|
+
<summary><strong>🛠️ Contributing? Run the gates.</strong></summary>
|
|
203
|
+
|
|
204
|
+
```bash
|
|
205
|
+
npm run mods:write
|
|
206
|
+
npm run validate:mods
|
|
207
|
+
npm run test:fuzz
|
|
208
|
+
npm run asset-integrity:write # last generator, on its own
|
|
209
|
+
npm run validate
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
The Python gate needs **Python 3.11+**. For each supported native mod, also run
|
|
213
|
+
`claude plugin validate mods/<id>` and `claude plugin test mods/<id>` locally;
|
|
214
|
+
CI has no native CLI. Spelling and Markdown lint are separate gates.
|
|
215
|
+
Static checks are not proof that an installed hook runs.
|
|
216
|
+
|
|
217
|
+
</details>
|
|
218
|
+
|
|
219
|
+
[Implementation plan](https://github.com/VincentChuWaiChow/vanguard-frontier-agentic/blob/dc8b29c823fb89dc4246413f38a7b82fdd34aa18/.claude/plan/cross-harness-mods.md)
|
|
220
|
+
· [Spec deviations](https://github.com/VincentChuWaiChow/vanguard-frontier-agentic/blob/dc8b29c823fb89dc4246413f38a7b82fdd34aa18/.kiro/specs/cross-harness-mods/deviations.md)
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# Audit Trail
|
|
2
|
+
|
|
3
|
+
Appends one JSON line per tool call to a per-session log. It is an honest append log: it makes
|
|
4
|
+
no claim of immutability, carries no signatures, and any process with write access can edit or
|
|
5
|
+
delete the file.
|
|
6
|
+
|
|
7
|
+
## Reach and declared footprint
|
|
8
|
+
|
|
9
|
+
**L1 (file writes).** The manifest declares default writes to `.audit/**`, reads
|
|
10
|
+
`VANGUARD_AUDIT_TRAIL_LOG_DIR`, `VANGUARD_AUDIT_TRAIL_SESSION_ID` and
|
|
11
|
+
`VANGUARD_AUDIT_TRAIL_AGENT_ID`, and declares no subprocess spawns or network egress.
|
|
12
|
+
This is capability disclosure, not isolation; the log-directory override can write
|
|
13
|
+
outside the declared default footprint.
|
|
14
|
+
|
|
15
|
+
## What it records
|
|
16
|
+
|
|
17
|
+
| Field | Value |
|
|
18
|
+
|---|---|
|
|
19
|
+
| `timestamp` | UTC ISO 8601 time of the hook run |
|
|
20
|
+
| `session_id` | The safe session id (see below) |
|
|
21
|
+
| `agent_id` | `VANGUARD_AUDIT_TRAIL_AGENT_ID`, or `null` |
|
|
22
|
+
| `tool_name` | The payload `tool_name`, or `null` |
|
|
23
|
+
| `args_hash` | SHA-256 of the canonical JSON of `tool_input` (`null` when absent) |
|
|
24
|
+
| `result_hash` | SHA-256 of the canonical JSON of `tool_response` (`null` when absent) |
|
|
25
|
+
| `sequence_number` | 1, 2, 3 ... per session file |
|
|
26
|
+
|
|
27
|
+
Only hashes are stored, never the arguments or results themselves.
|
|
28
|
+
|
|
29
|
+
## File layout
|
|
30
|
+
|
|
31
|
+
`<dir>/<YYYY-MM-DD>/<session>.jsonl`, where `<dir>` defaults to `.audit` and dates are UTC. If
|
|
32
|
+
the session already has a file under an earlier date directory, that file is reused, so the
|
|
33
|
+
sequence does not reset at midnight. A relative `<dir>` resolves against the project root when
|
|
34
|
+
the hook runs from its installed location, otherwise against the working directory.
|
|
35
|
+
|
|
36
|
+
## Session ids
|
|
37
|
+
|
|
38
|
+
1. `VANGUARD_AUDIT_TRAIL_SESSION_ID`, when set and non-empty.
|
|
39
|
+
2. The payload `session_id`, when a non-empty string.
|
|
40
|
+
3. Otherwise `unsessioned`.
|
|
41
|
+
|
|
42
|
+
An id that does not match `[A-Za-z0-9._-]{1,128}` is replaced by the first 32 hex characters of
|
|
43
|
+
its SHA-256, so it can never escape the date directory.
|
|
44
|
+
|
|
45
|
+
## Environment
|
|
46
|
+
|
|
47
|
+
| Variable | Purpose |
|
|
48
|
+
|---|---|
|
|
49
|
+
| `VANGUARD_AUDIT_TRAIL_LOG_DIR` | Log directory (default `.audit`). It can point outside the declared `.audit/**` write footprint; that is the operator's choice. |
|
|
50
|
+
| `VANGUARD_AUDIT_TRAIL_SESSION_ID` | Session id override |
|
|
51
|
+
| `VANGUARD_AUDIT_TRAIL_AGENT_ID` | Value for `agent_id` |
|
|
52
|
+
|
|
53
|
+
## Harness support
|
|
54
|
+
|
|
55
|
+
| Harness | Status |
|
|
56
|
+
|---|---|
|
|
57
|
+
| Claude Code native | Unsupported: the native API has no file append. Install the classic hook instead. |
|
|
58
|
+
| Claude Code classic | Supported. `PostToolUse` fires only after a tool succeeds, so failed calls are not logged. |
|
|
59
|
+
| Kiro | Degraded: stdin field names are undocumented, so `args_hash` covers the whole payload, `result_hash` hashes `null`, and without a session id env var every session shares the `unsessioned` log. |
|
|
60
|
+
| Codex | Supported. |
|
|
61
|
+
|
|
62
|
+
## Locking and failure
|
|
63
|
+
|
|
64
|
+
Each append takes an exclusive `<dir>/<session>.lock` before selecting the session file
|
|
65
|
+
(retrying for up to 2 s). Locks are never automatically stolen or removed based on age.
|
|
66
|
+
After a crash, confirm no writer remains before manually removing its orphaned lock.
|
|
67
|
+
A corrupt or unterminated last line, a lock timeout, or any I/O error exits 1 with a message on stderr and
|
|
68
|
+
appends nothing. A failure is loud but never blocks the tool call.
|
|
69
|
+
|
|
70
|
+
Requires Node 22+. Install: see `mods/README.md`.
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
// Node hook for audit-trail: appends one JSON line per tool call to a per-session log.
|
|
2
|
+
// An honest append log, not tamper-evident: anything with write access can edit it.
|
|
3
|
+
import { appendFileSync, closeSync, existsSync, mkdirSync, openSync, readFileSync, readdirSync, unlinkSync } from 'node:fs'
|
|
4
|
+
import { dirname, join } from 'node:path'
|
|
5
|
+
import { runHook, projectPath } from '../lib/runtime.mjs'
|
|
6
|
+
import { buildRecord, lastSequence, rawSessionId, safeSessionId } from '../lib/core.mjs'
|
|
7
|
+
|
|
8
|
+
const sleep = (ms) => Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms)
|
|
9
|
+
|
|
10
|
+
// Reuses the earliest date dir that already holds this session, so the sequence never
|
|
11
|
+
// resets at midnight.
|
|
12
|
+
// ponytail: scans every date dir, O(days); index it if slow.
|
|
13
|
+
function logFile(base, sid, today) {
|
|
14
|
+
const days = existsSync(base) ? readdirSync(base).filter((d) => /^\d{4}-\d{2}-\d{2}$/.test(d)).sort() : []
|
|
15
|
+
const hit = days.find((d) => existsSync(join(base, d, `${sid}.jsonl`)))
|
|
16
|
+
return join(base, hit ?? today, `${sid}.jsonl`)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Never steal a lock: its age does not prove the owner is dead. Explicit recovery is safer
|
|
20
|
+
// than racing two writers after an automatic stale-lock takeover.
|
|
21
|
+
function acquire(lock, file) {
|
|
22
|
+
const deadline = Date.now() + 2000
|
|
23
|
+
for (;;) {
|
|
24
|
+
try {
|
|
25
|
+
return openSync(lock, 'wx')
|
|
26
|
+
} catch (err) {
|
|
27
|
+
if (err.code !== 'EEXIST') throw err
|
|
28
|
+
}
|
|
29
|
+
if (Date.now() > deadline) throw new Error(`audit-trail: could not lock ${file} within 2s`)
|
|
30
|
+
sleep(20)
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Read directly instead of exists-then-read, so there is no check/use gap.
|
|
35
|
+
function readIfExists(file) {
|
|
36
|
+
try {
|
|
37
|
+
return readFileSync(file, 'utf8')
|
|
38
|
+
} catch (err) {
|
|
39
|
+
if (err.code === 'ENOENT') return ''
|
|
40
|
+
throw err
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async function PostToolUse(payload, ctx) {
|
|
45
|
+
const base = projectPath(process.env.VANGUARD_AUDIT_TRAIL_LOG_DIR || '.audit', ctx.harness, import.meta.dirname)
|
|
46
|
+
const sid = await safeSessionId(rawSessionId(process.env.VANGUARD_AUDIT_TRAIL_SESSION_ID, payload))
|
|
47
|
+
const timestamp = new Date().toISOString()
|
|
48
|
+
mkdirSync(base, { recursive: true })
|
|
49
|
+
// Serialize session-file selection as well as appends, including across midnight.
|
|
50
|
+
const lock = join(base, `${sid}.lock`)
|
|
51
|
+
const fd = acquire(lock, lock)
|
|
52
|
+
try {
|
|
53
|
+
const file = logFile(base, sid, timestamp.slice(0, 10))
|
|
54
|
+
mkdirSync(dirname(file), { recursive: true })
|
|
55
|
+
const sequence = lastSequence(readIfExists(file), file) + 1
|
|
56
|
+
const agentId = process.env.VANGUARD_AUDIT_TRAIL_AGENT_ID
|
|
57
|
+
const record = await buildRecord({ timestamp, sessionId: sid, agentId, payload, harness: ctx.harness, sequence })
|
|
58
|
+
appendFileSync(file, JSON.stringify(record) + '\n')
|
|
59
|
+
} finally {
|
|
60
|
+
closeSync(fd)
|
|
61
|
+
unlinkSync(lock)
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
process.exitCode = await runHook({ name: 'audit-trail', handlers: { PostToolUse } })
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Audit Trail on Claude Code
|
|
2
|
+
|
|
3
|
+
<!-- Generated by scripts/generate-mods.mjs from mod.toml. Do not edit. -->
|
|
4
|
+
|
|
5
|
+
## Unsupported
|
|
6
|
+
|
|
7
|
+
- `native`: The native mod API has no file append; rewriting the whole log would break append-only writes. Install the classic hook instead.
|
|
8
|
+
|
|
9
|
+
## Degraded
|
|
10
|
+
|
|
11
|
+
- `classic`: Classic PostToolUse fires only after a tool succeeds, so failed tool calls are not logged.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Audit Trail on Kiro
|
|
2
|
+
|
|
3
|
+
<!-- Generated by scripts/generate-mods.mjs from mod.toml. Do not edit. -->
|
|
4
|
+
|
|
5
|
+
## Degraded
|
|
6
|
+
|
|
7
|
+
- `PostToolUse`: Kiro does not document stdin field names; args_hash covers the whole payload, result_hash hashes null, and without VANGUARD_AUDIT_TRAIL_SESSION_ID every session shares the unsessioned log.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "v1",
|
|
3
|
+
"hooks": [
|
|
4
|
+
{
|
|
5
|
+
"name": "audit-trail:PostToolUse",
|
|
6
|
+
"description": "Appends one JSON line per tool call to a per-session log with sha256 hashes of the arguments and result.",
|
|
7
|
+
"trigger": "PostToolUse",
|
|
8
|
+
"action": {
|
|
9
|
+
"type": "command",
|
|
10
|
+
"command": "node .kiro/vanguard-mods/audit-trail/bin/hook.mjs --harness kiro --event PostToolUse"
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
]
|
|
14
|
+
}
|