You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
docs: audit and refresh docs to match shipped features (#12)
## What
A docs audit + refresh to bring all four user-facing doc surfaces back
in sync with what actually ships. Recent PRs (dashboard #9, IPv6 #10, Go
bump #11, and earlier masking) added features and changed defaults that
never made it into the docs.
Kept it useful and tight — no bloat, just fixing what was missing or
wrong.
## Gaps fixed
| Area | Before | After |
|------|--------|-------|
| `aigate serve` / web dashboard | undocumented everywhere | documented
in README, user guide, AI ref, `help-ai` |
| Audit log (`~/.aigate/audit.jsonl`) | undocumented | own section in
user guide + `help-ai`, with event examples |
| Default config example (user guide) | missing `*.p12`,
`terraform.tfstate`, `*.tfvars`, `ncat/netcat/rsync/ftp`,
`registry.npmjs.org`, `proxy.golang.org`, and the whole `mask_stdout`
block | matches `InitDefaultConfig` |
| `aws_secret` preset | absent (docs said "5 presets") | added; correct
description (`AWS_SECRET_ACCESS_KEY=` match), "6 presets" |
| Go version | badge `1.24+`, "From Source (Go 1.24+)" | `1.25+` (go.mod
is 1.25.11) |
| README Features | claimed cgroups resource limits are **enforced** |
removed — the user guide correctly notes they're *not yet* enforced |
| AI architecture map | missing `audit_service.go`, `masker.go`,
`internal/web/`, `setup.go`, `help_ai.go`, escape tests | added, plus a
note on the append-only audit log + read-only dashboard design |
| `help-ai` | no `doctor`, no `serve`/dashboard | added `doctor` to
setup + a DASHBOARD & AUDIT LOG section |
## Files
- `README.md`
- `docs/user/README.md`
- `docs/AI/README.md`
- `actions/help_ai.go` (the `aigate help-ai` output)
## Verified
- `go build ./...` and `go test -short ./...` pass
- pre-commit hooks green: structlint, gofmt, govet, golangci-lint
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
-**Audit log + dashboard** - Every run and blocked command is recorded to `~/.aigate/audit.jsonl`; `aigate serve` exposes a local web dashboard over it
57
57
-**Tool-agnostic** - Works with any AI tool: Claude Code, Cursor, Copilot, Aider
58
58
-**Sensible defaults** - Ships with deny rules for .env, secrets/, .ssh/, *.pem, etc.
59
59
-**Project-level config** - `.aigate.yaml` extends global rules per project
-**No CGO**: All platform operations use `exec.Command` to call system utilities (setfacl, groupadd, dscl, chmod, bwrap, slirp4netns, iptables/ip6tables).
48
60
-**IPv6 sandbox is opt-in by capability detection**: `ipv6SandboxSupported()` requires both kernel v6 enabled and `ip6tables` on PATH. Either missing → sandbox runs IPv4-only. Partial v6 (NAT but no filter) is refused — it would silently bypass `allow_net`.
49
61
-**Config merging**: Global config (`~/.aigate/config.yaml`) + project config (`.aigate.yaml`) merge with project extending global.
62
+
-**Audit log is append-only JSON Lines**: `AuditService` writes `run_started` / `blocked` events to `~/.aigate/audit.jsonl` under a mutex. `aigate serve` (`internal/web`) is a read-only dashboard over that file; it never mutates sandbox state. Keep the dashboard out of the sandbox enforcement path.
The dashboard shows live counters and a timeline of `run_started` and `blocked` events drawn from `~/.aigate/audit.jsonl` (see [Audit log](#audit-log)).
205
+
195
206
### reset
196
207
197
208
Remove everything (group, user, config):
@@ -217,27 +228,49 @@ deny_read:
217
228
- "~/.ssh/"
218
229
- "*.pem"
219
230
- "*.key"
231
+
- "*.p12"
220
232
- "~/.aws/"
221
233
- "~/.gcloud/"
222
234
- "~/.kube/config"
223
235
- "~/.npmrc"
224
236
- "~/.pypirc"
237
+
- "terraform.tfstate"
238
+
- "*.tfvars"
225
239
deny_exec:
226
240
- "curl"
227
241
- "wget"
228
242
- "nc"
243
+
- "ncat"
244
+
- "netcat"
229
245
- "ssh"
230
246
- "scp"
247
+
- "rsync"
248
+
- "ftp"
231
249
- "kubectl delete"
232
250
- "kubectl exec"
233
251
allow_net:
234
252
- "api.anthropic.com"
235
253
- "api.openai.com"
236
254
- "api.github.com"
255
+
- "registry.npmjs.org"
256
+
- "proxy.golang.org"
237
257
resource_limits:
238
258
max_memory: "4G"
239
259
max_cpu_percent: 80
240
260
max_pids: 1000
261
+
mask_stdout:
262
+
presets:
263
+
- openai
264
+
- anthropic
265
+
- aws_key
266
+
- aws_secret
267
+
- github
268
+
- bearer
269
+
patterns:
270
+
# Generic key=value / key: value assignments for common secret names
@@ -380,6 +414,20 @@ Without `bwrap`, aigate falls back to `unshare --user --map-root-user` + shell s
380
414
381
415
Resource limits (`max_memory`, `max_cpu_percent`, `max_pids`) are defined in the config but **not yet enforced**. Enforcement via cgroups v2 controllers is planned for a future release.
382
416
417
+
## Audit log
418
+
419
+
Each sandboxed run appends a line to `~/.aigate/audit.jsonl` (JSON Lines). Two kinds of events are recorded:
420
+
421
+
- `run_started`— a sandbox launched, with the command and a count of active `deny_read` / `deny_exec` / `allow_net` / masking rules
422
+
- `blocked`— a command was refused by the `deny_exec` preflight check, with the matched rule
0 commit comments