Three-phase triggers. Server-side invariants.
Triggers in Vadyl are first-class server-side rules — typed, branchable, audit-traced. The Gate phase decides whether the operation may even attempt. The Pre phase mutates the input under invariants. The Post phase reacts after commit. External handlers extend the system without bypassing it.
Gate, Pre, Post. Each with a distinct contract.
Gate
Decides whether the operation may even attempt. Cannot mutate. Returns allow / deny with a typed reason. The earliest place to fail loud.
Pre
Mutates the input under invariants. Compute derived fields. Normalize. Apply cross-field rules. The mutation plan is built from the post-Pre state.
Post
Reacts after commit. Emit a domain event. Schedule a follow-up. Update a related entity through another operation. Compensation-aware — Post triggers can compose into a saga.
Typed AST invariants
Cross-field constraints expressed as BoolExpr — same AST that drives access policies. Capability-validated against the provider before the trigger fires.
External handlers
Plug in custom triggers via TriggerEventKind binding. EntityAuditTriggerHandler is one canonical example. Your handlers run in the same pipeline as built-in ones.
Trigger diagnostics
Every trigger invocation emits a TriggerDiagnostics record — phase, decision, reason, timing. Surfaced through the canonical observability relay.
Gate · Pre · Post
Same BoolExpr as access policy
Trigger definitions move through the DAG
Phase, decision, reason, timing
Server-side rules that cannot be bypassed.
Every write path runs through the trigger pipeline. The shape of your data is enforced where the data lives — not in your client code, not in your handlers, not in code review.