@vainplex/openclaw-governance 0.1.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/README.md +297 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +30 -0
- package/dist/index.js.map +1 -0
- package/dist/src/audit-redactor.d.ts +3 -0
- package/dist/src/audit-redactor.d.ts.map +1 -0
- package/dist/src/audit-redactor.js +68 -0
- package/dist/src/audit-redactor.js.map +1 -0
- package/dist/src/audit-trail.d.ts +27 -0
- package/dist/src/audit-trail.d.ts.map +1 -0
- package/dist/src/audit-trail.js +192 -0
- package/dist/src/audit-trail.js.map +1 -0
- package/dist/src/builtin-policies.d.ts +3 -0
- package/dist/src/builtin-policies.d.ts.map +1 -0
- package/dist/src/builtin-policies.js +152 -0
- package/dist/src/builtin-policies.js.map +1 -0
- package/dist/src/conditions/context.d.ts +3 -0
- package/dist/src/conditions/context.d.ts.map +1 -0
- package/dist/src/conditions/context.js +60 -0
- package/dist/src/conditions/context.js.map +1 -0
- package/dist/src/conditions/index.d.ts +4 -0
- package/dist/src/conditions/index.d.ts.map +1 -0
- package/dist/src/conditions/index.js +28 -0
- package/dist/src/conditions/index.js.map +1 -0
- package/dist/src/conditions/simple.d.ts +10 -0
- package/dist/src/conditions/simple.d.ts.map +1 -0
- package/dist/src/conditions/simple.js +94 -0
- package/dist/src/conditions/simple.js.map +1 -0
- package/dist/src/conditions/time.d.ts +3 -0
- package/dist/src/conditions/time.d.ts.map +1 -0
- package/dist/src/conditions/time.js +48 -0
- package/dist/src/conditions/time.js.map +1 -0
- package/dist/src/conditions/tool.d.ts +3 -0
- package/dist/src/conditions/tool.d.ts.map +1 -0
- package/dist/src/conditions/tool.js +57 -0
- package/dist/src/conditions/tool.js.map +1 -0
- package/dist/src/config.d.ts +3 -0
- package/dist/src/config.d.ts.map +1 -0
- package/dist/src/config.js +80 -0
- package/dist/src/config.js.map +1 -0
- package/dist/src/cross-agent.d.ts +23 -0
- package/dist/src/cross-agent.d.ts.map +1 -0
- package/dist/src/cross-agent.js +142 -0
- package/dist/src/cross-agent.js.map +1 -0
- package/dist/src/engine.d.ts +29 -0
- package/dist/src/engine.d.ts.map +1 -0
- package/dist/src/engine.js +195 -0
- package/dist/src/engine.js.map +1 -0
- package/dist/src/frequency-tracker.d.ts +12 -0
- package/dist/src/frequency-tracker.d.ts.map +1 -0
- package/dist/src/frequency-tracker.js +44 -0
- package/dist/src/frequency-tracker.js.map +1 -0
- package/dist/src/hooks.d.ts +4 -0
- package/dist/src/hooks.d.ts.map +1 -0
- package/dist/src/hooks.js +198 -0
- package/dist/src/hooks.js.map +1 -0
- package/dist/src/policy-evaluator.d.ts +16 -0
- package/dist/src/policy-evaluator.d.ts.map +1 -0
- package/dist/src/policy-evaluator.js +99 -0
- package/dist/src/policy-evaluator.js.map +1 -0
- package/dist/src/policy-loader.d.ts +8 -0
- package/dist/src/policy-loader.d.ts.map +1 -0
- package/dist/src/policy-loader.js +105 -0
- package/dist/src/policy-loader.js.map +1 -0
- package/dist/src/risk-assessor.d.ts +8 -0
- package/dist/src/risk-assessor.d.ts.map +1 -0
- package/dist/src/risk-assessor.js +80 -0
- package/dist/src/risk-assessor.js.map +1 -0
- package/dist/src/trust-manager.d.ts +29 -0
- package/dist/src/trust-manager.d.ts.map +1 -0
- package/dist/src/trust-manager.js +219 -0
- package/dist/src/trust-manager.js.map +1 -0
- package/dist/src/types.d.ts +438 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +3 -0
- package/dist/src/types.js.map +1 -0
- package/dist/src/util.d.ts +28 -0
- package/dist/src/util.d.ts.map +1 -0
- package/dist/src/util.js +125 -0
- package/dist/src/util.js.map +1 -0
- package/openclaw.plugin.json +87 -0
- package/package.json +48 -0
package/README.md
ADDED
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
# @vainplex/openclaw-governance
|
|
2
|
+
|
|
3
|
+
**Your AI agents are powerful. That's the problem.**
|
|
4
|
+
|
|
5
|
+
An agent that can `exec("rm -rf /")` at 3 AM because a prompt injection told it to? That's not a feature, that's a liability. This plugin adds contextual, learning governance to OpenClaw — so your agents stay powerful but accountable.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Why This Exists
|
|
10
|
+
|
|
11
|
+
Every other guardrail tool works like a firewall: static rules, single-agent, no memory. *"Can agent X use tool Y? Yes/No."*
|
|
12
|
+
|
|
13
|
+
That's not governance. That's a whitelist.
|
|
14
|
+
|
|
15
|
+
Real governance asks: **"Should agent X run `docker rm` at 3 AM on production, given it failed twice this week and its trust score dropped to 25?"**
|
|
16
|
+
|
|
17
|
+
This plugin answers that question in <5ms.
|
|
18
|
+
|
|
19
|
+
## What It Does
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
Agent calls exec("git push origin main")
|
|
23
|
+
→ Governance evaluates: tool + time + trust + frequency + context
|
|
24
|
+
→ Verdict: DENY — "Forge cannot push to main (trust: restricted, score: 32)"
|
|
25
|
+
→ Audit record written (JSONL, ISO 27001 mapped)
|
|
26
|
+
→ Agent gets a clear rejection reason
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
**Four things no competitor does:**
|
|
30
|
+
|
|
31
|
+
1. **Contextual Policies** — Not just "which tool" but "which tool, when, by whom, in what conversation, at what risk level"
|
|
32
|
+
2. **Learning Trust** — Agents earn autonomy. Score 0-100, five tiers, decay on inactivity. A new sub-agent starts untrusted and works its way up.
|
|
33
|
+
3. **Cross-Agent Governance** — Parent policies cascade to sub-agents. A "no deploy" rule on main also blocks forge. Trust is capped: child can never exceed parent.
|
|
34
|
+
4. **Compliance Audit Trail** — Append-only JSONL with ISO 27001 Annex A control mapping. Every decision recorded, redacted, rotatable.
|
|
35
|
+
|
|
36
|
+
## Quick Start
|
|
37
|
+
|
|
38
|
+
### Install
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
npm install @vainplex/openclaw-governance
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Minimal Config
|
|
45
|
+
|
|
46
|
+
Add to `openclaw.json` → `plugins`:
|
|
47
|
+
|
|
48
|
+
```json
|
|
49
|
+
{
|
|
50
|
+
"openclaw-governance": {
|
|
51
|
+
"enabled": true,
|
|
52
|
+
"timezone": "Europe/Berlin",
|
|
53
|
+
"builtinPolicies": {
|
|
54
|
+
"nightMode": true,
|
|
55
|
+
"credentialGuard": true
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
That's it. Night mode blocks risky operations 23:00–08:00. Credential guard blocks access to secrets, `.env` files, and password stores.
|
|
62
|
+
|
|
63
|
+
### Realistic Config
|
|
64
|
+
|
|
65
|
+
```json
|
|
66
|
+
{
|
|
67
|
+
"openclaw-governance": {
|
|
68
|
+
"enabled": true,
|
|
69
|
+
"timezone": "Europe/Berlin",
|
|
70
|
+
"failMode": "open",
|
|
71
|
+
"trust": {
|
|
72
|
+
"defaults": {
|
|
73
|
+
"main": 60,
|
|
74
|
+
"forge": 45,
|
|
75
|
+
"cerberus": 50,
|
|
76
|
+
"*": 10
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
"builtinPolicies": {
|
|
80
|
+
"nightMode": { "after": "23:00", "before": "08:00" },
|
|
81
|
+
"credentialGuard": true,
|
|
82
|
+
"productionSafeguard": true,
|
|
83
|
+
"rateLimiter": { "maxPerMinute": 15 }
|
|
84
|
+
},
|
|
85
|
+
"policies": [
|
|
86
|
+
{
|
|
87
|
+
"id": "forge-no-deploy",
|
|
88
|
+
"name": "Forge Cannot Deploy",
|
|
89
|
+
"version": "1.0.0",
|
|
90
|
+
"scope": { "agents": ["forge"] },
|
|
91
|
+
"rules": [{
|
|
92
|
+
"id": "block-push",
|
|
93
|
+
"conditions": [
|
|
94
|
+
{ "type": "tool", "name": "exec", "params": { "command": { "matches": "git push.*(main|master)" } } }
|
|
95
|
+
],
|
|
96
|
+
"effect": { "action": "deny", "reason": "Forge cannot push to main — submit a PR instead" }
|
|
97
|
+
}]
|
|
98
|
+
}
|
|
99
|
+
],
|
|
100
|
+
"audit": {
|
|
101
|
+
"retentionDays": 90,
|
|
102
|
+
"level": "standard"
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Policy Examples
|
|
109
|
+
|
|
110
|
+
### "No dangerous commands at night"
|
|
111
|
+
|
|
112
|
+
```json
|
|
113
|
+
{
|
|
114
|
+
"id": "night-guard",
|
|
115
|
+
"name": "Night Guard",
|
|
116
|
+
"scope": {},
|
|
117
|
+
"rules": [{
|
|
118
|
+
"id": "deny-exec-at-night",
|
|
119
|
+
"conditions": [
|
|
120
|
+
{ "type": "tool", "name": ["exec", "gateway", "cron"] },
|
|
121
|
+
{ "type": "time", "after": "23:00", "before": "07:00" }
|
|
122
|
+
],
|
|
123
|
+
"effect": { "action": "deny", "reason": "High-risk tools blocked during night hours" }
|
|
124
|
+
}]
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### "Only trusted agents can spawn sub-agents"
|
|
129
|
+
|
|
130
|
+
```json
|
|
131
|
+
{
|
|
132
|
+
"id": "spawn-control",
|
|
133
|
+
"name": "Spawn Control",
|
|
134
|
+
"scope": {},
|
|
135
|
+
"rules": [{
|
|
136
|
+
"id": "require-trust",
|
|
137
|
+
"conditions": [
|
|
138
|
+
{ "type": "tool", "name": "sessions_spawn" },
|
|
139
|
+
{ "type": "agent", "maxScore": 39 }
|
|
140
|
+
],
|
|
141
|
+
"effect": { "action": "deny", "reason": "Agents below score 40 cannot spawn sub-agents" }
|
|
142
|
+
}]
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### "Rate limit external messaging"
|
|
147
|
+
|
|
148
|
+
```json
|
|
149
|
+
{
|
|
150
|
+
"id": "message-rate-limit",
|
|
151
|
+
"name": "Message Rate Limit",
|
|
152
|
+
"scope": {},
|
|
153
|
+
"rules": [{
|
|
154
|
+
"id": "throttle",
|
|
155
|
+
"conditions": [
|
|
156
|
+
{ "type": "tool", "name": "message" },
|
|
157
|
+
{ "type": "frequency", "maxCount": 5, "windowSeconds": 60, "scope": "agent" }
|
|
158
|
+
],
|
|
159
|
+
"effect": { "action": "deny", "reason": "Message rate limit exceeded (5/min)" }
|
|
160
|
+
}]
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### "Block production commands for untrusted agents"
|
|
165
|
+
|
|
166
|
+
```json
|
|
167
|
+
{
|
|
168
|
+
"id": "prod-safety",
|
|
169
|
+
"name": "Production Safety",
|
|
170
|
+
"scope": {},
|
|
171
|
+
"rules": [{
|
|
172
|
+
"id": "block-prod",
|
|
173
|
+
"conditions": [
|
|
174
|
+
{ "type": "tool", "name": "exec", "params": { "command": { "matches": "(systemctl|docker).*(restart|stop|rm|kill)" } } },
|
|
175
|
+
{ "type": "agent", "trustTier": ["untrusted", "restricted"] }
|
|
176
|
+
],
|
|
177
|
+
"effect": { "action": "deny", "reason": "Production operations require at least 'standard' trust tier" }
|
|
178
|
+
}]
|
|
179
|
+
}
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
## Condition Types
|
|
183
|
+
|
|
184
|
+
| Type | What it checks | Example |
|
|
185
|
+
|------|---------------|---------|
|
|
186
|
+
| `tool` | Tool name, parameters (exact, glob, regex) | `{ "type": "tool", "name": "exec", "params": { "command": { "contains": "rm" } } }` |
|
|
187
|
+
| `time` | Hour, day-of-week, named windows | `{ "type": "time", "after": "22:00", "before": "06:00", "days": [0, 6] }` |
|
|
188
|
+
| `agent` | Agent ID, trust tier, score range | `{ "type": "agent", "trustTier": "untrusted", "maxScore": 20 }` |
|
|
189
|
+
| `context` | Conversation, message content, channel | `{ "type": "context", "channel": "telegram" }` |
|
|
190
|
+
| `risk` | Computed risk level | `{ "type": "risk", "minRisk": "high" }` |
|
|
191
|
+
| `frequency` | Actions per time window | `{ "type": "frequency", "maxCount": 10, "windowSeconds": 60 }` |
|
|
192
|
+
| `any` | OR — at least one sub-condition | `{ "type": "any", "conditions": [...] }` |
|
|
193
|
+
| `not` | Negation | `{ "type": "not", "condition": { ... } }` |
|
|
194
|
+
|
|
195
|
+
All conditions in a rule are AND-combined. Use `any` for OR logic.
|
|
196
|
+
|
|
197
|
+
## Trust System
|
|
198
|
+
|
|
199
|
+
Agents start with a configured default score and earn (or lose) trust through actions:
|
|
200
|
+
|
|
201
|
+
| Tier | Score | What they can do |
|
|
202
|
+
|------|-------|-----------------|
|
|
203
|
+
| `untrusted` | 0–19 | Read-only, no external actions |
|
|
204
|
+
| `restricted` | 20–39 | Basic operations, no production |
|
|
205
|
+
| `standard` | 40–59 | Normal operation |
|
|
206
|
+
| `trusted` | 60–79 | Extended permissions, can spawn agents |
|
|
207
|
+
| `privileged` | 80–100 | Full autonomy |
|
|
208
|
+
|
|
209
|
+
- **+0.1** per successful tool call (capped at +30 total)
|
|
210
|
+
- **-2** per violation (resets clean streak)
|
|
211
|
+
- **+0.5/day** age bonus (capped at +20)
|
|
212
|
+
- **+0.3/day** clean streak (capped at +20)
|
|
213
|
+
- **Decay:** Score × 0.95 after 30 days of inactivity
|
|
214
|
+
|
|
215
|
+
Trust persists across restarts. Sub-agents inherit a trust ceiling from their parent — they can never exceed their parent's score.
|
|
216
|
+
|
|
217
|
+
## Cross-Agent Governance
|
|
218
|
+
|
|
219
|
+
When a main agent spawns a sub-agent (e.g. `forge`):
|
|
220
|
+
|
|
221
|
+
1. The parent→child relationship is tracked automatically
|
|
222
|
+
2. Parent's deny policies cascade to the child
|
|
223
|
+
3. Child's trust is capped at parent's score
|
|
224
|
+
4. Audit records include the full lineage (`parentAgentId`, `inheritedPolicyIds`)
|
|
225
|
+
|
|
226
|
+
This means: if you deny `main` from touching production, `forge` can't either. No escaping through sub-agents.
|
|
227
|
+
|
|
228
|
+
## Audit Trail
|
|
229
|
+
|
|
230
|
+
Every governance decision is logged to `{workspace}/governance/audit/YYYY-MM-DD.jsonl`:
|
|
231
|
+
|
|
232
|
+
```json
|
|
233
|
+
{
|
|
234
|
+
"id": "550e8400-e29b-41d4-a716-446655440000",
|
|
235
|
+
"timestamp": 1708300000000,
|
|
236
|
+
"timestampIso": "2026-02-18T14:00:00.000Z",
|
|
237
|
+
"verdict": "deny",
|
|
238
|
+
"context": {
|
|
239
|
+
"hook": "before_tool_call",
|
|
240
|
+
"agentId": "forge",
|
|
241
|
+
"toolName": "exec",
|
|
242
|
+
"toolParams": { "command": "git push origin main" },
|
|
243
|
+
"crossAgent": { "parentAgentId": "main", "trustCeiling": 60 }
|
|
244
|
+
},
|
|
245
|
+
"trust": { "score": 32, "tier": "restricted" },
|
|
246
|
+
"risk": { "level": "high", "score": 72 },
|
|
247
|
+
"matchedPolicies": [{ "policyId": "forge-no-deploy", "ruleId": "block-push" }],
|
|
248
|
+
"controls": ["A.8.3", "A.8.5", "A.5.24", "A.5.28"]
|
|
249
|
+
}
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
- **Rotation:** One file per day, auto-cleaned after `retentionDays`
|
|
253
|
+
- **Redaction:** Sensitive data (passwords, tokens, keys) redacted before write
|
|
254
|
+
- **ISO 27001:** Each record maps to Annex A controls for compliance audits
|
|
255
|
+
|
|
256
|
+
## Built-in Policies
|
|
257
|
+
|
|
258
|
+
Enable with a boolean or customize:
|
|
259
|
+
|
|
260
|
+
| Policy | What it does | Config |
|
|
261
|
+
|--------|-------------|--------|
|
|
262
|
+
| `nightMode` | Blocks risky tools during off-hours | `true` or `{ "after": "23:00", "before": "08:00" }` |
|
|
263
|
+
| `credentialGuard` | Blocks access to secrets, `.env`, passwords | `true` |
|
|
264
|
+
| `productionSafeguard` | Blocks `systemctl`, `docker rm`, destructive ops | `true` |
|
|
265
|
+
| `rateLimiter` | Throttles tool calls per minute | `true` or `{ "maxPerMinute": 15 }` |
|
|
266
|
+
|
|
267
|
+
## Commands
|
|
268
|
+
|
|
269
|
+
| Command | Description |
|
|
270
|
+
|---------|-------------|
|
|
271
|
+
| `/governance` | Show engine status, policy count, trust overview |
|
|
272
|
+
|
|
273
|
+
## Performance
|
|
274
|
+
|
|
275
|
+
- Evaluation: **<5ms** for 10+ regex policies
|
|
276
|
+
- Zero runtime dependencies (only Node.js builtins)
|
|
277
|
+
- Pre-compiled regex cache, ring buffer frequency tracking
|
|
278
|
+
- Fail-open by default (configurable to fail-closed)
|
|
279
|
+
|
|
280
|
+
## Requirements
|
|
281
|
+
|
|
282
|
+
- Node.js ≥ 22.0.0
|
|
283
|
+
- OpenClaw gateway
|
|
284
|
+
|
|
285
|
+
## Part of the Vainplex Plugin Suite
|
|
286
|
+
|
|
287
|
+
| # | Plugin | Status |
|
|
288
|
+
|---|--------|--------|
|
|
289
|
+
| 1 | [@vainplex/openclaw-nats-eventstore](https://github.com/alberthild/openclaw-nats-eventstore) | ✅ v0.2.0 |
|
|
290
|
+
| 2 | [@vainplex/openclaw-cortex](https://github.com/alberthild/openclaw-cortex) | ✅ v0.1.0 |
|
|
291
|
+
| 3 | **@vainplex/openclaw-governance** | ✅ v0.1.0 |
|
|
292
|
+
| 4 | [@vainplex/openclaw-knowledge-engine](https://github.com/alberthild/openclaw-knowledge-engine) | ✅ v0.1.2 |
|
|
293
|
+
| 5 | @vainplex/openclaw-membrane | 🔜 Planning |
|
|
294
|
+
|
|
295
|
+
## License
|
|
296
|
+
|
|
297
|
+
MIT © [Albert Hild](https://github.com/alberthild)
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { OpenClawPluginApi } from "./src/types.js";
|
|
2
|
+
declare const plugin: {
|
|
3
|
+
id: string;
|
|
4
|
+
name: string;
|
|
5
|
+
description: string;
|
|
6
|
+
version: string;
|
|
7
|
+
register(api: OpenClawPluginApi): void;
|
|
8
|
+
};
|
|
9
|
+
export default plugin;
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAOxD,QAAA,MAAM,MAAM;;;;;kBAMI,iBAAiB;CAiChC,CAAC;AAEF,eAAe,MAAM,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { resolveConfig } from "./src/config.js";
|
|
2
|
+
import { GovernanceEngine } from "./src/engine.js";
|
|
3
|
+
import { registerGovernanceHooks } from "./src/hooks.js";
|
|
4
|
+
const plugin = {
|
|
5
|
+
id: "openclaw-governance",
|
|
6
|
+
name: "OpenClaw Governance",
|
|
7
|
+
description: "Contextual, learning, cross-agent governance for AI agents",
|
|
8
|
+
version: "0.1.0",
|
|
9
|
+
register(api) {
|
|
10
|
+
const config = resolveConfig(api.pluginConfig);
|
|
11
|
+
if (!config.enabled) {
|
|
12
|
+
api.logger.info("[governance] Disabled via config");
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
const engine = new GovernanceEngine(config, api.logger);
|
|
16
|
+
api.registerService({
|
|
17
|
+
id: "governance-engine",
|
|
18
|
+
start: async () => engine.start(),
|
|
19
|
+
stop: async () => engine.stop(),
|
|
20
|
+
});
|
|
21
|
+
registerGovernanceHooks(api, engine, config);
|
|
22
|
+
api.registerGatewayMethod("governance.status", async () => engine.getStatus());
|
|
23
|
+
api.registerGatewayMethod("governance.trust", async (...args) => {
|
|
24
|
+
const params = args[0];
|
|
25
|
+
return engine.getTrust(params?.agentId);
|
|
26
|
+
});
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
export default plugin;
|
|
30
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AAIzD,MAAM,MAAM,GAAG;IACb,EAAE,EAAE,qBAAqB;IACzB,IAAI,EAAE,qBAAqB;IAC3B,WAAW,EAAE,4DAA4D;IACzE,OAAO,EAAE,OAAO;IAEhB,QAAQ,CAAC,GAAsB;QAC7B,MAAM,MAAM,GAAG,aAAa,CAC1B,GAAG,CAAC,YAAmD,CACxD,CAAC;QAEF,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,kCAAkC,CAAC,CAAC;YACpD,OAAO;QACT,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,gBAAgB,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;QAExD,GAAG,CAAC,eAAe,CAAC;YAClB,EAAE,EAAE,mBAAmB;YACvB,KAAK,EAAE,KAAK,IAAI,EAAE,CAAC,MAAM,CAAC,KAAK,EAAE;YACjC,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE;SAChC,CAAC,CAAC;QAEH,uBAAuB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;QAE7C,GAAG,CAAC,qBAAqB,CACvB,mBAAmB,EACnB,KAAK,IAAI,EAAE,CAAC,MAAM,CAAC,SAAS,EAAE,CAC/B,CAAC;QAEF,GAAG,CAAC,qBAAqB,CACvB,kBAAkB,EAClB,KAAK,EAAE,GAAG,IAAe,EAAE,EAAE;YAC3B,MAAM,MAAM,GAAG,IAAI,CAAC,CAAC,CAAc,CAAC;YACpC,OAAO,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAC1C,CAAC,CACF,CAAC;IACJ,CAAC;CACF,CAAC;AAEF,eAAe,MAAM,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit-redactor.d.ts","sourceRoot":"","sources":["../../src/audit-redactor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AA+D/C,wBAAgB,cAAc,CAC5B,cAAc,EAAE,MAAM,EAAE,GACvB,CAAC,GAAG,EAAE,YAAY,KAAK,YAAY,CAyBrC"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
const SENSITIVE_KEYS = new Set([
|
|
2
|
+
"password",
|
|
3
|
+
"secret",
|
|
4
|
+
"token",
|
|
5
|
+
"apikey",
|
|
6
|
+
"api_key",
|
|
7
|
+
"credential",
|
|
8
|
+
"auth",
|
|
9
|
+
"authorization",
|
|
10
|
+
"cookie",
|
|
11
|
+
"session",
|
|
12
|
+
]);
|
|
13
|
+
const MAX_MESSAGE_LENGTH = 500;
|
|
14
|
+
function isSensitiveKey(key) {
|
|
15
|
+
return SENSITIVE_KEYS.has(key.toLowerCase());
|
|
16
|
+
}
|
|
17
|
+
function redactValue(key, value, customPatterns) {
|
|
18
|
+
if (isSensitiveKey(key))
|
|
19
|
+
return "[REDACTED]";
|
|
20
|
+
if (typeof value === "string") {
|
|
21
|
+
for (const pattern of customPatterns) {
|
|
22
|
+
if (pattern.test(key) || pattern.test(value)) {
|
|
23
|
+
return "[REDACTED]";
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return value;
|
|
28
|
+
}
|
|
29
|
+
function redactRecord(obj, customPatterns) {
|
|
30
|
+
const result = {};
|
|
31
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
32
|
+
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
33
|
+
result[key] = redactRecord(value, customPatterns);
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
result[key] = redactValue(key, value, customPatterns);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return result;
|
|
40
|
+
}
|
|
41
|
+
function truncateMessage(content) {
|
|
42
|
+
if (!content)
|
|
43
|
+
return content;
|
|
44
|
+
if (content.length <= MAX_MESSAGE_LENGTH)
|
|
45
|
+
return content;
|
|
46
|
+
return content.slice(0, MAX_MESSAGE_LENGTH) + " [TRUNCATED]";
|
|
47
|
+
}
|
|
48
|
+
export function createRedactor(customPatterns) {
|
|
49
|
+
const compiled = customPatterns
|
|
50
|
+
.map((p) => {
|
|
51
|
+
try {
|
|
52
|
+
return new RegExp(p, "i");
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
})
|
|
58
|
+
.filter((r) => r !== null);
|
|
59
|
+
return (ctx) => {
|
|
60
|
+
const redacted = { ...ctx };
|
|
61
|
+
if (redacted.toolParams) {
|
|
62
|
+
redacted.toolParams = redactRecord(redacted.toolParams, compiled);
|
|
63
|
+
}
|
|
64
|
+
redacted.messageContent = truncateMessage(redacted.messageContent);
|
|
65
|
+
return redacted;
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=audit-redactor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit-redactor.js","sourceRoot":"","sources":["../../src/audit-redactor.ts"],"names":[],"mappings":"AAEA,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC;IAC7B,UAAU;IACV,QAAQ;IACR,OAAO;IACP,QAAQ;IACR,SAAS;IACT,YAAY;IACZ,MAAM;IACN,eAAe;IACf,QAAQ;IACR,SAAS;CACV,CAAC,CAAC;AAEH,MAAM,kBAAkB,GAAG,GAAG,CAAC;AAE/B,SAAS,cAAc,CAAC,GAAW;IACjC,OAAO,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC;AAC/C,CAAC;AAED,SAAS,WAAW,CAClB,GAAW,EACX,KAAc,EACd,cAAwB;IAExB,IAAI,cAAc,CAAC,GAAG,CAAC;QAAE,OAAO,YAAY,CAAC;IAE7C,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,KAAK,MAAM,OAAO,IAAI,cAAc,EAAE,CAAC;YACrC,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC7C,OAAO,YAAY,CAAC;YACtB,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,YAAY,CACnB,GAA4B,EAC5B,cAAwB;IAExB,MAAM,MAAM,GAA4B,EAAE,CAAC;IAC3C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QAC/C,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YACzE,MAAM,CAAC,GAAG,CAAC,GAAG,YAAY,CACxB,KAAgC,EAChC,cAAc,CACf,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,GAAG,CAAC,GAAG,WAAW,CAAC,GAAG,EAAE,KAAK,EAAE,cAAc,CAAC,CAAC;QACxD,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,eAAe,CAAC,OAA2B;IAClD,IAAI,CAAC,OAAO;QAAE,OAAO,OAAO,CAAC;IAC7B,IAAI,OAAO,CAAC,MAAM,IAAI,kBAAkB;QAAE,OAAO,OAAO,CAAC;IACzD,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,kBAAkB,CAAC,GAAG,cAAc,CAAC;AAC/D,CAAC;AAED,MAAM,UAAU,cAAc,CAC5B,cAAwB;IAExB,MAAM,QAAQ,GAAG,cAAc;SAC5B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QACT,IAAI,CAAC;YACH,OAAO,IAAI,MAAM,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;QAC5B,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC,CAAC;SACD,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC;IAE1C,OAAO,CAAC,GAAiB,EAAgB,EAAE;QACzC,MAAM,QAAQ,GAAG,EAAE,GAAG,GAAG,EAAE,CAAC;QAE5B,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC;YACxB,QAAQ,CAAC,UAAU,GAAG,YAAY,CAChC,QAAQ,CAAC,UAAU,EACnB,QAAQ,CACT,CAAC;QACJ,CAAC;QAED,QAAQ,CAAC,cAAc,GAAG,eAAe,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;QAEnE,OAAO,QAAQ,CAAC;IAClB,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { AuditConfig, AuditContext, AuditFilter, AuditRecord, AuditStats, AuditVerdict, MatchedPolicy, PluginLogger, RiskLevel, TrustTier } from "./types.js";
|
|
2
|
+
export declare class AuditTrail {
|
|
3
|
+
private readonly config;
|
|
4
|
+
private readonly auditDir;
|
|
5
|
+
private readonly logger;
|
|
6
|
+
private readonly redact;
|
|
7
|
+
private buffer;
|
|
8
|
+
private flushTimer;
|
|
9
|
+
private todayRecordCount;
|
|
10
|
+
constructor(config: AuditConfig, workspace: string, logger: PluginLogger);
|
|
11
|
+
load(): void;
|
|
12
|
+
record(verdict: AuditVerdict, context: AuditContext, trust: {
|
|
13
|
+
score: number;
|
|
14
|
+
tier: TrustTier;
|
|
15
|
+
}, risk: {
|
|
16
|
+
level: RiskLevel;
|
|
17
|
+
score: number;
|
|
18
|
+
}, matchedPolicies: MatchedPolicy[], evaluationUs: number): AuditRecord;
|
|
19
|
+
query(filter: AuditFilter): AuditRecord[];
|
|
20
|
+
flush(): void;
|
|
21
|
+
startAutoFlush(): void;
|
|
22
|
+
stopAutoFlush(): void;
|
|
23
|
+
getStats(): AuditStats;
|
|
24
|
+
private cleanOldFiles;
|
|
25
|
+
private countTodayRecords;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=audit-trail.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit-trail.d.ts","sourceRoot":"","sources":["../../src/audit-trail.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EACV,WAAW,EACX,YAAY,EACZ,WAAW,EACX,WAAW,EACX,UAAU,EACV,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,SAAS,EACT,SAAS,EACV,MAAM,YAAY,CAAC;AAuBpB,qBAAa,UAAU;IACrB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAc;IACrC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAe;IACtC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAsC;IAC7D,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,UAAU,CAA+C;IACjE,OAAO,CAAC,gBAAgB,CAAK;gBAG3B,MAAM,EAAE,WAAW,EACnB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,YAAY;IAQtB,IAAI,IAAI,IAAI;IASZ,MAAM,CACJ,OAAO,EAAE,YAAY,EACrB,OAAO,EAAE,YAAY,EACrB,KAAK,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,SAAS,CAAA;KAAE,EACzC,IAAI,EAAE;QAAE,KAAK,EAAE,SAAS,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EACzC,eAAe,EAAE,aAAa,EAAE,EAChC,YAAY,EAAE,MAAM,GACnB,WAAW;IA2Bd,KAAK,CAAC,MAAM,EAAE,WAAW,GAAG,WAAW,EAAE;IAuCzC,KAAK,IAAI,IAAI;IA8Bb,cAAc,IAAI,IAAI;IAMtB,aAAa,IAAI,IAAI;IAQrB,QAAQ,IAAI,UAAU;IAetB,OAAO,CAAC,aAAa;IAsBrB,OAAO,CAAC,iBAAiB;CAQ1B"}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { appendFileSync, existsSync, mkdirSync, readFileSync, readdirSync, unlinkSync, } from "node:fs";
|
|
2
|
+
import { randomUUID } from "node:crypto";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { createRedactor } from "./audit-redactor.js";
|
|
5
|
+
const ISO_CONTROLS_MAP = {
|
|
6
|
+
before_tool_call: ["A.8.3", "A.8.5"],
|
|
7
|
+
message_sending: ["A.5.14"],
|
|
8
|
+
trust_adjustment: ["A.5.15", "A.8.2"],
|
|
9
|
+
violation: ["A.5.24", "A.5.28"],
|
|
10
|
+
config_change: ["A.8.9"],
|
|
11
|
+
};
|
|
12
|
+
function getControls(hook, verdict) {
|
|
13
|
+
const controls = ISO_CONTROLS_MAP[hook] ?? [];
|
|
14
|
+
if (verdict === "deny") {
|
|
15
|
+
return [...controls, "A.5.24", "A.5.28"];
|
|
16
|
+
}
|
|
17
|
+
return controls;
|
|
18
|
+
}
|
|
19
|
+
function dateStr(ts) {
|
|
20
|
+
return new Date(ts).toISOString().slice(0, 10);
|
|
21
|
+
}
|
|
22
|
+
export class AuditTrail {
|
|
23
|
+
config;
|
|
24
|
+
auditDir;
|
|
25
|
+
logger;
|
|
26
|
+
redact;
|
|
27
|
+
buffer = [];
|
|
28
|
+
flushTimer = null;
|
|
29
|
+
todayRecordCount = 0;
|
|
30
|
+
constructor(config, workspace, logger) {
|
|
31
|
+
this.config = config;
|
|
32
|
+
this.auditDir = join(workspace, "governance", "audit");
|
|
33
|
+
this.logger = logger;
|
|
34
|
+
this.redact = createRedactor(config.redactPatterns);
|
|
35
|
+
}
|
|
36
|
+
load() {
|
|
37
|
+
if (!existsSync(this.auditDir)) {
|
|
38
|
+
mkdirSync(this.auditDir, { recursive: true });
|
|
39
|
+
}
|
|
40
|
+
this.cleanOldFiles();
|
|
41
|
+
this.countTodayRecords();
|
|
42
|
+
this.logger.info("[governance] Audit trail loaded");
|
|
43
|
+
}
|
|
44
|
+
record(verdict, context, trust, risk, matchedPolicies, evaluationUs) {
|
|
45
|
+
const now = Date.now();
|
|
46
|
+
const redacted = this.redact(context);
|
|
47
|
+
const rec = {
|
|
48
|
+
id: randomUUID(),
|
|
49
|
+
timestamp: now,
|
|
50
|
+
timestampIso: new Date(now).toISOString(),
|
|
51
|
+
verdict,
|
|
52
|
+
context: redacted,
|
|
53
|
+
trust,
|
|
54
|
+
risk,
|
|
55
|
+
matchedPolicies,
|
|
56
|
+
evaluationUs,
|
|
57
|
+
controls: [...new Set(getControls(context.hook, verdict))],
|
|
58
|
+
};
|
|
59
|
+
this.buffer.push(rec);
|
|
60
|
+
this.todayRecordCount++;
|
|
61
|
+
if (this.buffer.length >= 100) {
|
|
62
|
+
this.flush();
|
|
63
|
+
}
|
|
64
|
+
return rec;
|
|
65
|
+
}
|
|
66
|
+
query(filter) {
|
|
67
|
+
const results = [];
|
|
68
|
+
const limit = filter.limit ?? 100;
|
|
69
|
+
if (!existsSync(this.auditDir))
|
|
70
|
+
return results;
|
|
71
|
+
const files = readdirSync(this.auditDir)
|
|
72
|
+
.filter((f) => f.endsWith(".jsonl"))
|
|
73
|
+
.sort()
|
|
74
|
+
.reverse();
|
|
75
|
+
for (const file of files) {
|
|
76
|
+
const content = readFileSync(join(this.auditDir, file), "utf-8");
|
|
77
|
+
const lines = content.trim().split("\n").filter(Boolean);
|
|
78
|
+
for (const line of lines.reverse()) {
|
|
79
|
+
try {
|
|
80
|
+
const rec = JSON.parse(line);
|
|
81
|
+
if (matchesFilter(rec, filter)) {
|
|
82
|
+
results.push(rec);
|
|
83
|
+
if (results.length >= limit)
|
|
84
|
+
return results;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
// Skip malformed lines
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
// Also include buffered records
|
|
93
|
+
for (const rec of [...this.buffer].reverse()) {
|
|
94
|
+
if (matchesFilter(rec, filter)) {
|
|
95
|
+
results.push(rec);
|
|
96
|
+
if (results.length >= limit)
|
|
97
|
+
return results;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return results;
|
|
101
|
+
}
|
|
102
|
+
flush() {
|
|
103
|
+
if (this.buffer.length === 0)
|
|
104
|
+
return;
|
|
105
|
+
if (!existsSync(this.auditDir)) {
|
|
106
|
+
mkdirSync(this.auditDir, { recursive: true });
|
|
107
|
+
}
|
|
108
|
+
const groups = new Map();
|
|
109
|
+
for (const rec of this.buffer) {
|
|
110
|
+
const day = dateStr(rec.timestamp);
|
|
111
|
+
const list = groups.get(day) ?? [];
|
|
112
|
+
list.push(rec);
|
|
113
|
+
groups.set(day, list);
|
|
114
|
+
}
|
|
115
|
+
for (const [day, records] of groups) {
|
|
116
|
+
const filePath = join(this.auditDir, `${day}.jsonl`);
|
|
117
|
+
const lines = records.map((r) => JSON.stringify(r)).join("\n") + "\n";
|
|
118
|
+
try {
|
|
119
|
+
appendFileSync(filePath, lines);
|
|
120
|
+
}
|
|
121
|
+
catch (e) {
|
|
122
|
+
this.logger.error(`[governance] Failed to write audit: ${e instanceof Error ? e.message : String(e)}`);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
this.buffer = [];
|
|
126
|
+
}
|
|
127
|
+
startAutoFlush() {
|
|
128
|
+
if (this.flushTimer)
|
|
129
|
+
return;
|
|
130
|
+
this.flushTimer = setInterval(() => this.flush(), 1000);
|
|
131
|
+
this.flushTimer.unref();
|
|
132
|
+
}
|
|
133
|
+
stopAutoFlush() {
|
|
134
|
+
if (this.flushTimer) {
|
|
135
|
+
clearInterval(this.flushTimer);
|
|
136
|
+
this.flushTimer = null;
|
|
137
|
+
}
|
|
138
|
+
this.flush();
|
|
139
|
+
}
|
|
140
|
+
getStats() {
|
|
141
|
+
const files = existsSync(this.auditDir)
|
|
142
|
+
? readdirSync(this.auditDir)
|
|
143
|
+
.filter((f) => f.endsWith(".jsonl"))
|
|
144
|
+
.sort()
|
|
145
|
+
: [];
|
|
146
|
+
return {
|
|
147
|
+
totalRecords: this.todayRecordCount,
|
|
148
|
+
todayRecords: this.todayRecordCount,
|
|
149
|
+
oldestRecord: files[0]?.replace(".jsonl", ""),
|
|
150
|
+
newestRecord: files[files.length - 1]?.replace(".jsonl", ""),
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
cleanOldFiles() {
|
|
154
|
+
if (!existsSync(this.auditDir))
|
|
155
|
+
return;
|
|
156
|
+
const cutoff = Date.now() - this.config.retentionDays * 24 * 60 * 60 * 1000;
|
|
157
|
+
const files = readdirSync(this.auditDir).filter((f) => f.endsWith(".jsonl"));
|
|
158
|
+
for (const file of files) {
|
|
159
|
+
const dateStr = file.replace(".jsonl", "");
|
|
160
|
+
const fileDate = new Date(dateStr).getTime();
|
|
161
|
+
if (!Number.isNaN(fileDate) && fileDate < cutoff) {
|
|
162
|
+
try {
|
|
163
|
+
unlinkSync(join(this.auditDir, file));
|
|
164
|
+
this.logger.info(`[governance] Cleaned old audit file: ${file}`);
|
|
165
|
+
}
|
|
166
|
+
catch {
|
|
167
|
+
// ignore cleanup errors
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
countTodayRecords() {
|
|
173
|
+
const today = dateStr(Date.now());
|
|
174
|
+
const filePath = join(this.auditDir, `${today}.jsonl`);
|
|
175
|
+
if (existsSync(filePath)) {
|
|
176
|
+
const content = readFileSync(filePath, "utf-8");
|
|
177
|
+
this.todayRecordCount = content.trim().split("\n").filter(Boolean).length;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
function matchesFilter(rec, filter) {
|
|
182
|
+
if (filter.agentId && rec.context.agentId !== filter.agentId)
|
|
183
|
+
return false;
|
|
184
|
+
if (filter.verdict && rec.verdict !== filter.verdict)
|
|
185
|
+
return false;
|
|
186
|
+
if (filter.after && rec.timestamp < filter.after)
|
|
187
|
+
return false;
|
|
188
|
+
if (filter.before && rec.timestamp > filter.before)
|
|
189
|
+
return false;
|
|
190
|
+
return true;
|
|
191
|
+
}
|
|
192
|
+
//# sourceMappingURL=audit-trail.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit-trail.js","sourceRoot":"","sources":["../../src/audit-trail.ts"],"names":[],"mappings":"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"}
|