aic-exec — varwof-exec-v1 (EN)EN

The varwof/exec-v1 capability scheme

A CLC-v1 capability scheme for command execution. It defines how a shell-free command vector (argv) is turned into a CLC operation and authorized against the AIC grant set. Policy lives entirely in CLC; the scheme supplies the identifier grammar and the projection rules only.

Status: design + reference implementation (local, uncommitted). Grounded in the behaviour of github.com/varwof/register/semantics (CLC-v1), verified by probe, not by reading.

1. Capability identifier

varwof/exec-v1:<tool>:<action>
  • <tool> — the executable family (git, ls, mysql, kubectl, …). It is the grantable unit.
  • <action> — the verb derived from argv (the subcommand), or the tool's fixed action. Segment charset [A-Za-z0-9._-]+.

A grant may use a trailing wildcard on the action:

Grant Covers
varwof/exec-v1:git:* every action of git
varwof/exec-v1:git:status exactly git status

There is no cross-tool wildcard (verified)

CLC's namespace is parts[0]+":"+parts[1] of the identifier, so varwof/exec-v1:* has namespace varwof/exec-v1:* and does not match varwof/exec-v1:git:status (namespace varwof/exec-v1:git) — the verdict is deny / different_namespace. Mid-segment wildcards (varwof/exec-v1:*:status) are unsupported_wildcard.

Consequences, by design:

  • Authority is granted per tool. There is no single "allow all exec" grant; an agent trusted for everything carries one grant per tool.
  • This is the least-privilege default and is intentional. Do not try to synthesize a global wildcard; enumerate grants.

2. Operation projection

The projector is deterministic and fail-closed: an argv it cannot fully classify is a deny (a projection failure, not a policy verdict).

argv[0] basename ──must be in the tool table──▶ <tool>
remaining tokens ──parsed by the tool's action kind──▶ <action>
every other token ──consumed by param rules or──▶ projection error

Action kinds

Kind Action Non-flag tokens
subcommand the first non-flag token (must match the action charset) the rest are positionals
fixed the constant value all are positionals

Examples: git status → action status; ls -la /tmp (tool ls, fixed action list) → action list, positional /tmp.

Parameters

A tool declares a fixed parameter schema. Key closure in CLC requires the operation's param key set to equal the covering grant's param key set, so the projector always emits every declared key (with a zero value when absent).

Kind Emitted value CLC meaning
flags sorted, deduped list of tokens starting with - array = allowed set
positionals remaining non-flag tokens array = allowed set
string value of --name=…, else "" exact match
number parsed value of --name=…, else 0 upper bound

Only flags is universal; the others are declared per tool.

3. Authorization (CLC decides)

op := semantics.Operation{ID: "varwof/exec-v1:<tool>:<action>", Params: <projected params>}
dec, err := aicverifier.AuthorizeOperation(ac.AIC, nil, op.ID, op.Params)

The verdict is one of:

  • allow — run the command.
  • deny + normative reason — do not run. Reasons observed: capability_not_authorized, params_exceed_grant, params_missing, undeclared_param: <k>, not_in_enum, different_namespace, wildcard_requires_trailing_segment.
  • allow_unresolved + unresolved[] — the grant carried recognized-but-unevaluated constraints. The executor must evaluate each before acting, else deny.

Constraints available to an exec grant

CLC-v1 recognizes exactly three constraint identities (unknown_constraint otherwise — a custom type requires extending register/semantics, a cross-repo change):

Constraint Core-evaluated Effect
varwof/constraint-v1:max_rows:N yes op max_rows must be present and ≤ N; else max_rows:violated
varwof/constraint-v1:time:window:[{"start":"09:00","end":"17:00"}] no allow_unresolved; executor checks the clock
varwof/constraint-v1:network:cidr:["10.0.0.0/8"] no allow_unresolved; executor checks the peer address

Everything else an exec policy needs must be expressed through the capability id + params (action granularity, flags/positionals enums, numeric bounds).

4. Example grants

// all git, nothing else
{"scheme":"varwof/exec-v1","id":"git:*"}

// git read verbs, but only the listed flags
{"scheme":"varwof/exec-v1","id":"git:status",
 "params":{"flags":["--short","--branch"]}}

// a query tool capped and time-boxed
{"scheme":"varwof/exec-v1","id":"mysql:query",
 "params":{"flags":[],"max_rows":10},
 "constraints":["varwof/constraint-v1:time:window:[{\"start\":\"09:00\",\"end\":\"17:00\"}]"]}

Note on params: because of key closure, a grant with params must declare exactly the tool's declared keys (flags plus any tool-specific keys).

5. What the scheme does not do

  • It does not authenticate — AIC + aic-verifier do (CLC consumes grants).
  • It does not execute or enforce timeouts — execer does.
  • It does not constrain argv order (arrays are sets in CLC), so positional sequences must be decomposed into the id or left unconstrained.
  • It does not allow arbitrary path/ref arguments under a constrained grant; use exact strings, or wrap the command behind a narrower tool.