Skip to content

Trigger policy-chain redesign plan

Implementation plan and design notes for issue #41.

This document captures the chosen redesign for trigger policies as a linear policy chain with layered resolution:

flowchart LR
  req[Request] --> global[GlobalChain]
  global --> product[ProductChain]
  product --> user[UserChain]
  user --> api[ApiChain]
  api --> run[ForwardOrRespond]

Goal

Replace the old flat policy-pool plus gateway_policy_bindings approach with an explicit chain model that supports:

  • linear execution, no branching;
  • policy types throttle, oauth_outbound, xml_json, and headers;
  • fixed layer order global → product → user → API;
  • runtime enforcement plus dashboard editing;
  • unit-testable policy evaluators;
  • no backward compatibility requirement.

Core model

A policy definition is a reusable named YAML document:

name: throttle-default
type: throttle
direction: inbound
config: { ... }

A policy chain is an ordered list of refs, optionally with a direction override:

policy_chain:
  - throttle-default
  - ref: example-headers-strip-secret
    direction: inbound

Layers and storage

Layer Storage Scope
Global identity policy-chains/global/{http,schedule,amqp} with disk fallback flows/policy_chains/global/*.yaml per trigger type
Product identity products.policy_chain product API-set layer
User identity user_policy_chains authenticated user
API trigger invocation.policy_chain workflow/API-specific layer

Request-time resolution concatenates all layers in order and evaluates them strictly left-to-right.

Runtime changes

Main implementation areas:

  • engine/services/gateway/app/policy_engine.py
  • engine/services/gateway/app/main.py
  • engine/services/orchestrator/app/workflow_runner.py
  • engine/services/orchestrator/app/policy_store.py

Supported policy types

Type Direction Behavior
throttle inbound fixed-window rate limit by ip, authorization, or sub
oauth_outbound outbound fetch and inject client-credentials token
xml_json inbound/outbound convert body XML ↔ JSON
headers inbound/outbound add, set, and remove headers

Legacy first-class flow policy types are removed from the new design:

  • required_headers
  • oauth_inbound
  • rate_limit
  • rate_limit_product
  • transform

Auth remains route-level through gateway_auth_mode.

Gateway pipeline

  1. Resolve EdgeRoute and caller identity
  2. Load global + product + user + api policy chains
  3. Apply inbound chain
  4. Forward request to orchestrator
  5. Apply outbound chain
  6. Return response

Identity changes

Identity stores and serves policy-chain data through:

  • products.policy_chain
  • user_policy_chains
  • policy-chains/global/{trigger}
  • /me/policy-context

Products still keep allowed_route_ids as the API-set mechanism; the policy chain is an additional field, not a replacement.

Dashboard changes

The dashboard exposes a shared PolicyChainEditor for:

  • global chains;
  • product chains;
  • user chains;
  • trigger/API chains.

Relevant files:

  • engine/services/dashboard/app/static/app.policy-chain-editor.js
  • engine/services/dashboard/app/static/app.developer-admin.js
  • engine/services/dashboard/app/static/app.triggers-panel.js
  • engine/services/dashboard/app/static/app.resource-modals.js
  • engine/services/dashboard/app/static/index.html

Validation, examples, and docs

  • flows/scripts/validate_triggers.py validates invocation.policy_chain
  • flows/policies/ contains example definitions for the four new policy types
  • flows/policy_chains/global/ contains example global-chain documents
  • flow and engine docs were updated to describe the new chain model

Test strategy

The redesign is covered with focused tests for:

  • each policy evaluator;
  • chain composition order;
  • inbound and outbound transformation behavior;
  • identity CRUD for product and user chains;
  • storage/runtime policy upload behavior.

Implementation order used

  1. Chain model and evaluators in gateway
  2. Identity storage and APIs for product/user/global chains
  3. Gateway wiring for inbound/outbound application
  4. Trigger schema migration to policy_chain
  5. Dashboard chain editor and admin screens
  6. Docs and examples cleanup

Deliberate decisions

  • No backward compatibility for old trigger policy bindings
  • Route auth stays separate from policy chains
  • Product API-set stays in allowed_route_ids
  • The dashboard designer is an ordered list editor, not a branching graph