Skip to main content

Observability & Audit

The Observability & Audit APIs help you capture every policy decision as an operational event.

This is critical for production systems where Actra decisions must be:

  • auditable
  • searchable
  • measurable
  • rollout-safe
  • compliance-ready

The JavaScript SDK provides two real observability surfaces:

  • runtime.setDecisionObserver()
  • runtime.audit()

Together, these enable both decision event streaming and non-blocking shadow evaluation.


Core Mental Model​

Runtime decision -> event -> logs / metrics / SIEM

Every evaluation can become a structured event for:

  • security logging
  • compliance exports
  • rollout analysis
  • anomaly detection
  • incident forensics

Decision Observer​

Use the runtime observer to receive every decision event.

runtime.setDecisionObserver((event) => {
console.log(event.decision.effect)
})

This is the primary hook for observability pipelines.


Event Payload​

The observer event includes runtime metadata such as:

  • decision
  • action
  • resolved actor
  • resolved snapshot
  • timestamp
  • durationMs

This makes it ideal for both logs and metrics.


Structured Logging​

A common production pattern is structured JSON logs.

runtime.setDecisionObserver((event) => {
logger.info({
effect: event.decision.effect,
matched_rule: event.decision.matched_rule,
durationMs: event.durationMs,
timestamp: event.timestamp,
})
})

Great for:

  • ELK
  • Datadog
  • CloudWatch
  • Loki
  • OpenSearch

Metrics & Dashboards​

Observers are perfect for metrics.

runtime.setDecisionObserver((event) => {
metrics.increment(`actra.${event.decision.effect}`)
})

Useful dashboards:

  • allow vs block rate
  • approval frequency
  • top matched rules
  • latency distribution
  • action hotspots

Security & SIEM​

A very strong enterprise use case.

runtime.setDecisionObserver((event) => {
siem.send({
effect: event.decision.effect,
actor: event.actor,
action: event.action,
matched_rule: event.decision.matched_rule,
})
})

Best for:

  • SOC workflows
  • insider risk
  • privilege escalation detection
  • destructive action tracing
  • regulated environments

Non-Blocking Audit Mode​

Use audit() for shadow evaluation.

const auditedRefund = runtime.audit("refund", refund)

This always executes the function while still:

  1. evaluating policy
  2. emitting observer events
  3. capturing decision metadata

This is ideal for:

  • safe rollouts
  • policy migrations
  • dry runs
  • measuring blast radius
  • legacy system onboarding

Shadow Rollout Pattern​

A highly recommended production workflow.

const guarded = runtime.audit("deploy", deployService)

Observe for:

  • unexpected blocks
  • approval spikes
  • missing resolver state
  • noisy rules
  • performance regressions

Then switch to:

runtime.admit("deploy", deployService)

once confidence is high.


Compliance Audit Trail​

Actra decision events are excellent compliance evidence.

Track:

  • who attempted the action
  • what was attempted
  • current state
  • which rule matched
  • whether approval was required
  • how long evaluation took

This is highly valuable for:

  • SOX
  • ISO 27001
  • PCI
  • internal audit
  • change management

Failure Behavior​

Observer Failures​

Observer exceptions are intentionally swallowed.

This means:

  • business execution continues
  • policy enforcement remains deterministic
  • telemetry failures do not break requests

This is a major production safety guarantee.


Best Practices​

Always instrument matched rules​

Track:

matched_rule

This makes incident forensics dramatically easier.


Start with audit() in rollouts​

Use shadow mode before enabling blocking enforcement.


Track latency budgets​

Use durationMs to watch policy cost under load.


Production Mental Model​

Function call
-> Evaluate policy
-> Emit decision event
-> Log / metric / SIEM
-> Execute or shadow-run

This makes Actra observable as a production control plane.


Next Steps​

  • Build Testing Policies
  • Add CI Validation
  • Combine with Explain & Debugging
  • Roll out with audit() shadow mode