Policy Configuration

Comprehensive guide to configuring policies in ContextGraph OS.

Policy Anatomy

policy:
  # Identity
  id: pol_abc123
  name: "High Risk Action Guard"
  version: "1.0.0"
  description: "Requires approval for high-risk actions"

  # Effect
  effect: deny  # or 'allow'

  # Who does this apply to?
  subjects:
    - "*"  # All subjects
    # - "role:analyst"
    # - "agent:data-processor"

  # What actions?
  actions:
    - "delete"
    - "publish"
    - "export"

  # Which resources?
  resources:
    - "production/*"
    - "customer-data/*"

  # Under what conditions?
  conditions:
    - field: "risk.level"
      operator: "in"
      value: ["HIGH", "CRITICAL"]

  # Priority (higher = evaluated first)
  priority: 100

  # Temporal validity
  validFrom: "2024-01-01T00:00:00Z"
  validUntil: null  # No expiration

Policy Matching

Subject Matching

# Match all
subjects: ["*"]

# Match specific role
subjects: ["role:admin"]

# Match specific agent
subjects: ["agent:data-processor"]

# Match multiple
subjects: ["role:analyst", "role:data-scientist"]

# Match pattern
subjects: ["agent:*-processor"]

Action Matching

# Match specific action
actions: ["delete"]

# Match multiple
actions: ["read", "write", "delete"]

# Match all
actions: ["*"]

# Match pattern
actions: ["export:*"]

Resource Matching

# Exact match
resources: ["/api/users/123"]

# Wildcard suffix
resources: ["reports/*"]

# Wildcard prefix
resources: ["*/sensitive"]

# Multiple patterns
resources: ["pii/*", "*/personal/*", "customers/*"]

Condition Operators

OperatorDescriptionExample
equalsExact match{ field: "status", operator: "equals", value: "active" }
not_equalsNot equal{ field: "status", operator: "not_equals", value: "deleted" }
inIn array{ field: "role", operator: "in", value: ["admin", "super"] }
not_inNot in array{ field: "role", operator: "not_in", value: ["guest"] }
greater_thanNumeric comparison{ field: "risk.score", operator: "greater_than", value: 0.7 }
less_thanNumeric comparison{ field: "confidence", operator: "less_than", value: 0.5 }
betweenRange{ field: "hour", operator: "between", value: [9, 17] }
containsString contains{ field: "path", operator: "contains", value: "admin" }
starts_withString prefix{ field: "resource", operator: "starts_with", value: "/api/" }
matchesRegex match{ field: "email", operator: "matches", value: ".*@company\\.com$" }
existsField exists{ field: "approval.id", operator: "exists" }

Condition Fields

Built-in Fields

FieldDescription
subject.idSubject identifier
subject.roleSubject's role
subject.typeSubject type (agent, user)
actionAction being performed
resourceTarget resource
time.hourCurrent hour (0-23)
time.dayOfWeekDay name (Mon, Tue, etc.)
time.dateISO date
risk.levelRisk level (LOW, MEDIUM, HIGH, CRITICAL)
risk.scoreRisk score (0-1)
context.jurisdictionJurisdiction code
context.scopeScope

Custom Fields

Access any field from the action context:

conditions:
  - field: "parameters.count"
    operator: "greater_than"
    value: 100
  - field: "metadata.department"
    operator: "equals"
    value: "finance"

Policy Templates

Read-Only Access

policy:
  name: "Read Only Access"
  effect: allow
  subjects: ["role:viewer"]
  actions: ["read", "list", "get"]
  resources: ["*"]
  priority: 30

PII Protection

policy:
  name: "PII Protection"
  effect: deny
  subjects: ["*"]
  actions: ["*"]
  resources: ["pii/*", "*/personal/*"]
  conditions:
    - field: "subject.clearance"
      operator: "not_equals"
      value: "pii-authorized"
  priority: 100

Business Hours Only

policy:
  name: "Business Hours Only"
  effect: deny
  subjects: ["role:contractor"]
  actions: ["*"]
  resources: ["*"]
  conditions:
    - field: "time.hour"
      operator: "not_in"
      value: [9, 10, 11, 12, 13, 14, 15, 16, 17]
  priority: 80

High Risk Approval

policy:
  name: "High Risk Requires Approval"
  effect: deny
  subjects: ["*"]
  actions: ["delete", "publish", "deploy"]
  resources: ["production/*"]
  conditions:
    - field: "risk.level"
      operator: "in"
      value: ["HIGH", "CRITICAL"]
    - field: "approval.status"
      operator: "not_equals"
      value: "approved"
  priority: 90

Jurisdiction Restriction

policy:
  name: "EU Data in EU Only"
  effect: deny
  subjects: ["*"]
  actions: ["export", "transfer"]
  resources: ["eu-data/*"]
  conditions:
    - field: "context.jurisdiction"
      operator: "not_equals"
      value: "EU"
  priority: 95

Policy Evaluation Order

  1. Policies sorted by priority (highest first)
  2. For each policy:
    • Check subject match
    • Check action match
    • Check resource match
    • Evaluate conditions
  3. First DENY wins (deny-takes-precedence)
  4. If no deny, first ALLOW wins
  5. If no match, implicit DENY
Priority 100: Security policies
Priority 90:  Risk policies
Priority 80:  Compliance policies
Priority 50:  Business rules
Priority 30:  Role defaults
Priority 10:  Fallback rules

Testing Policies

Simulation

const simulator = new PolicySimulator(policyLedger, storage);

const result = await simulator.simulate({
  subject: "agent:report-generator",
  action: "publish",
  resource: "production/quarterly-report",
  context: {
    risk: { level: "HIGH" },
    time: { hour: 14 }
  }
});

console.log(result.effect);  // "deny"
console.log(result.matchedPolicies);
console.log(result.reason);

Batch Testing

const scenarios = [
  { subject: "role:admin", action: "delete", resource: "data/*" },
  { subject: "role:analyst", action: "read", resource: "reports/*" },
  { subject: "role:guest", action: "write", resource: "comments/*" },
];

const results = await simulator.simulateMany(scenarios);

Best Practices

  1. Start restrictive - Default deny, explicit allow
  2. Use high priority for security - Security > Compliance > Business
  3. Test before deploy - Use simulator
  4. Version policies - Semantic versioning
  5. Document conditions - Clear descriptions
  6. Monitor evaluations - Track deny rates
  7. Review regularly - Quarterly policy audits