This commit is contained in:
kevin zhao
2025-11-10 16:14:38 -08:00
parent 687a8c38ff
commit ca9e61497d
2 changed files with 60 additions and 10 deletions

View File

@@ -0,0 +1,57 @@
# codex-execpolicy2
## Overview
- Policy engine and CLI built around `prefix_rule(pattern=[...], decision?, match?, not_match?, id?)`.
- Tokens are matched in order; any `pattern` element may be a list to denote alternatives. `decision` defaults to `allow`; valid values: `allow`, `prompt`, `forbidden`.
- `match` / `not_match` supply example invocations that are validated at load time (think of them as unit tests). `id` is optional; auto-generated if omitted.
- The CLI always prints the JSON serialization of the evaluation result (whether a match or not).
## Policy shapes
- Prefix rules use Starlark syntax:
```starlark
prefix_rule(
id = "rule_id", # optional; autogenerated if omitted
pattern = ["cmd", ["alt1", "alt2"]], # ordered tokens; list entries denote alternatives
decision = "prompt", # allow | prompt | forbidden; defaults to allow
match = [["cmd", "alt1"]], # examples that must match this rule
not_match = [["cmd", "oops"]], # examples that must not match this rule
)
```
## Response shapes
- Match:
```json
{
"Match": {
"decision": "allow|prompt|forbidden",
"matched_rules": [
{
"rule_id": "<rule id>",
"matched_prefix": ["<token>", "..."],
"decision": "allow|prompt|forbidden"
}
]
}
}
```
- No match:
```json
"NoMatch"
```
- `matched_rules` lists every rule whose prefix matched the command; `matched_prefix` is the exact prefix that matched.
- The effective `decision` is the strictest severity across all matches (`forbidden` > `prompt` > `allow`).
## CLI
- Check a command against a policy (default bundled policy shown):
```bash
cargo run -p codex-execpolicy2 -- check git status
```
- Use a specific policy file instead of the default:
```bash
cargo run -p codex-execpolicy2 -- --policy path/to/policy.star check git status
```
- Example outcomes:
- Match: `{"Match": { ... "decision": "allow" ... }}`
- No match: `"NoMatch"`

View File

@@ -4,7 +4,6 @@ use std::path::Path;
use anyhow::Context;
use anyhow::Result;
use anyhow::bail;
use codex_execpolicy2::Evaluation;
use codex_execpolicy2::PolicyParser;
use codex_execpolicy2::load_default_policy;
@@ -49,15 +48,9 @@ fn cmd_check(policy_path: Option<String>, args: Vec<String>) -> Result<()> {
}
let policy = load_policy(policy_path)?;
match policy.evaluate(&args) {
eval @ Evaluation::Match { .. } => {
let json = serde_json::to_string_pretty(&eval)?;
println!("{json}");
}
Evaluation::NoMatch => {
println!("no match");
}
};
let eval = policy.evaluate(&args);
let json = serde_json::to_string_pretty(&eval)?;
println!("{json}");
Ok(())
}