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, andheaders; - 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.pyengine/services/gateway/app/main.pyengine/services/orchestrator/app/workflow_runner.pyengine/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_headersoauth_inboundrate_limitrate_limit_producttransform
Auth remains route-level through gateway_auth_mode.
Gateway pipeline¶
- Resolve
EdgeRouteand caller identity - Load
global + product + user + apipolicy chains - Apply inbound chain
- Forward request to orchestrator
- Apply outbound chain
- Return response
Identity changes¶
Identity stores and serves policy-chain data through:
products.policy_chainuser_policy_chainspolicy-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.jsengine/services/dashboard/app/static/app.developer-admin.jsengine/services/dashboard/app/static/app.triggers-panel.jsengine/services/dashboard/app/static/app.resource-modals.jsengine/services/dashboard/app/static/index.html
Validation, examples, and docs¶
flows/scripts/validate_triggers.pyvalidatesinvocation.policy_chainflows/policies/contains example definitions for the four new policy typesflows/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¶
- Chain model and evaluators in gateway
- Identity storage and APIs for product/user/global chains
- Gateway wiring for inbound/outbound application
- Trigger schema migration to
policy_chain - Dashboard chain editor and admin screens
- 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