Skip to main content

Field & Behavior Reference

What every field does — and, just as importantly, what it doesn't. In a security component the worst kind of field is one that looks like a control but enforces nothing, so each field below is marked:

  • Enforced — the engine reads it and it changes the decision.
  • Advisory — accepted and carried (e.g. into lineage), but it does not constrain the decision in the Developer Edition.
  • Platform — populated and enforced by the governed control plane (Watchlight Beacon); inert / stubbed in the in-process engine.

Everything here was checked against the published watchlight-engine wheel.

authorize request

{ "principal": "...", "action": "...", "resource": "...",
"context": { ... }, "intent": { ... } }
FieldStatusNotes
principalEnforcedMatched as User::"<value>".
actionEnforcedMatched as Action::"<value>".
resourceEnforcedMatched as Resource::"<value>".
context.<key>EnforcedRead by Cedar when/unless conditions. A missing key referenced by a forbid fails closed (denies) — safer than raw Cedar, and a deliberate deviation.
context.agent.anomaly_scorePlatformBehavioral drift score. A caller cannot forge it — the engine supplies its own value; stubbed at 0 in DE (no drift detection in-process).
context.agent.quarantinedPlatformSet by the platform's anomaly/quarantine pipeline; always false in DE.
intent.categoryEnforcedDrives the intent rules below.
intent.risk_levelEnforcedcritical escalates (below).
intent.objective / justificationEnforcedSome categories require a justification (below).

Intent enforcement (above Cedar)

The engine makes a few decisions no policy expresses — declare them so you can predict a decision from your own inputs. All verified against the wheel:

import json, watchlight_engine
eng = watchlight_engine.PolicyEngine()
eng.add_policy(json.dumps({"name": "allow", "code": "permit(principal, action, resource);"}))

def authorize(intent):
r = json.loads(eng.authorize(json.dumps({
"principal": "agent", "action": "read", "resource": "db",
"context": {}, "intent": intent})))
return r["decision"], (r.get("details") or {}).get("escalation_required")

authorize({"category": "financial_operation", "objective": "pay vendor"})
# -> ('Deny', True) human-approval gate (escalation_required)

authorize({"category": "data_analysis", "objective": "x", "risk_level": "critical"})
# -> ('Deny', True) critical risk escalates

authorize({"category": "system_administration", "objective": "x"})
# -> ('Deny', None) 'system_administration' requires a justification
IntentBehavior
financial_operationEscalates to human approval (Deny + escalation_required)
risk_level: criticalEscalates to human approval
system_administrationDenied unless a justification is supplied
security_complianceDenied unless a justification is supplied

attenuate_scope (sub-agent confinement)

FieldStatusNotes
allowed_toolsEnforcedChild must be a subset of the parent's.
allowed_intentsEnforcedChild must be a subset.
allowed_resourcesEnforcedSubset by exact string; see the matcher note below.
max_depthEnforcedA decrementing budget: a child's max_depth must be ≤ parent − 1; 0 means the scope can no longer delegate.
time_budget_secondsEnforcedClamped to the parent's remaining budget and deadline.
depthAdvisoryCarried into the granted scope for lineage. In DE it is not cross-checked against max_depth — don't rely on it as a ceiling; max_depth is the enforced control.
Resource matchers are exact strings, not globs

Only the bare * is a wildcard. tickets/* is treated as a literal string — tickets/* does not match tickets/123. Model allowed_resources as an enumeration of exact values (or * for "any"), not as glob patterns.

Reject unknown fields

Prefer explicit, minimal request/scope objects. An unrecognized key (a typo like max_dept, or a field the engine doesn't read) is currently ignored, so a misspelled constraint silently does nothing — always diff your object against the tables above.

See also