PasskeyBridge —

Engineering · 2026-03-23

Designing an Identity Playbook Engine: From Signal to Action in One API Call

By J. W. Bouckaert

Designing an Identity Playbook Engine: From Signal to Action in One API Call

The problem with sequential identity

Many identity platforms process signals one at a time, in sequence, through a queue. A carrier sends a SIM-swap alert. The platform logs it. A rules engine evaluates it. If it matches a policy, the platform dispatches an action—revoke a session, send an email, fire a webhook. Each step waits for the previous step to complete. Each step adds latency.

This architecture was adequate when identity verification was a batch process—something that happened during onboarding or password reset. It is inadequate when identity verification is a continuous, real-time operation that must respond to threats faster than an adversary can exploit them. The response window is the operational requirement, set by the gap between SIM-swap execution and fraudulent transaction initiation.

Event-driven identity orchestration replaces the sequential queue with a fan-out pipeline. A single ingest endpoint receives a signal, validates it, normalizes it, and dispatches it to multiple action handlers concurrently, so one slow action does not hold up the others.

Anatomy of the ingest endpoint

The PasskeyBridge ingest pipeline accepts carrier signals via a single POST endpoint. The request contains a JSON payload with a signal type, a phone hash, and carrier-specific metadata. The endpoint authenticates the request, validates the schema, normalizes the signal, matches a playbook and makes the decision, then runs the playbook's actions and stores the event. It does not call a carrier itself.

The decision comes before any outbound action, so the time PasskeyBridge's own work takes is recorded on every event as decision_ms, separately from the time the actions take.

Authentication and validation

Every request needs an API key with the ingest scope. The request can also carry an HMAC-SHA-256 signature of the body in the x-pb-signature header: the endpoint verifies it whenever it is present and rejects mismatches. An organization can turn on signed ingest, and from then on unsigned requests are rejected.

Schema validation uses Zod to enforce runtime type safety on the payload. The signal type is a string of up to 64 letters, digits, underscores and hyphens, such as sim_swap, so a tenant can send whatever signal names its sources use. A supplied phone hash must be a 64-character hexadecimal string. Malformed payloads receive a 422 with a structured error response.

Zero-PII normalization

The ingest endpoint enforces the platform's zero-PII architecture at the boundary. If a carrier sends a raw phone number (some legacy integrations still do), the endpoint replaces it with a keyed HMAC-SHA-256 digest under a server-held pepper before any persistence or downstream processing occurs. The raw value never touches a database, a log, or an in-memory cache. That is an architectural constraint enforced at the code level rather than a policy decision, consistent with GDPR Art. 25 data protection by design.

The normalized signal (a signal type, a phone hash, and validated metadata) is passed to the orchestrator as a typed event object. From this point forward, no component in the pipeline has access to the original phone number. The hash is the identity.

The orchestrator: fan-out over waterfall

The orchestrator is the core of the playbook engine. It receives a normalized signal event and determines which actions to execute, in what order, and with what parameters. The design principle is fan-out: the actions in a playbook start together and run concurrently.

Playbook matching

When a signal arrives, the orchestrator queries the tenant's active playbooks for a match. Matching is deterministic: a playbook names the signal type it responds to, and when an incoming signal has that type, the playbook's actions are run.

One playbook runs per signal. When more than one active playbook matches, the oldest one is used, so a SIM-swap response that revokes sessions, freezes credentials and emails the compliance team carries all of those actions in a single playbook.

Action chain execution

Each playbook defines a list of actions. The current action vocabulary includes:

Action TypeBehavior
revoke_sessionsRevoke the tenant's active A2A agent negotiations in PasskeyBridge. Does not end the tenant's own user sessions
freeze_credentialsInvalidate the tenant's cached passkey proofs in PasskeyBridge. Does not disable passkeys registered with the tenant's own application
suspend_agentsDeactivate the tenant's active agent delegates and clear their scopes
webhook_callbackPOST event to the tenant's configured endpoint
slack_webhookSend a formatted alert to a Slack channel
email_alertDispatch an email via Resend to a group on the tenant, resolved at send time
log_eventRecord the event at a chosen severity in the event's action results

Actions within a playbook run in parallel. What runs first is the hard-signal response: on a hard signal such as a SIM swap, the ingest endpoint deactivates the tenant's agent delegates and revokes open A2A negotiations inline, before any playbook action starts. Why detection needs an automatic response covers the reasoning.

Concurrency model

Playbook actions run inside the ingest request. After the decision, the endpoint starts every action in the matched playbook at once, races each one against an 8-second timeout, and waits for all of them before it writes the event to shield_events and responds. A slow webhook therefore lengthens the response, and the timeout bounds how far. It does not touch the decision, because decision_ms is taken before any action starts.

Because the actions run in parallel, a slow webhook callback does not hold up the session revocation running beside it.

Carrier lookup: A separate endpoint

The ingest endpoint does not query carriers. Carrier lookup is its own endpoint: it queries a configured provider such as Vonage, Sinch or Twilio Lookup for carrier metadata like SIM-swap and porting status, and forwards what it finds to the ingest endpoint as a signal. A lookup's provider latency therefore stays outside the ingest request.

Risk scoring: Deterministic and non-deterministic layers

The pipeline has two risk layers: a deterministic one inside the request and a non-deterministic one after it.

Deterministic response (in-line)

The ingest endpoint does not compute a risk score itself. A caller can send a risk_score between 0 and 1 with the signal, for example a carrier's fraud score, and it is stored on the event record. The deterministic response is the hard-signal rule and the matched playbook: both run inside the request and act on the signal type.

Non-deterministic scoring (shadow execution)

The intelligence layer runs asynchronously via shadow execution—a fire-and-forget invocation of the shield-intelligence-worker that has zero impact on the critical path. This layer uses behavioral clustering (Jaccard similarity) and LLM-assisted analysis to identify coordinated attack patterns, generate SHAP-style explainability reports, and flag signals for human-in-the-loop review.

Shadow execution means a slow intelligence run does not delay the ingest response or playbook execution. When an assessment scores above 0.95 and was not flagged as unreliable, the worker freezes the shadow identities for that phone hash and records the escalation in the audit log. It does not run playbooks.

Verifiable credentials are issued separately

The ingest pipeline does not issue credentials. W3C Verifiable Credentials come from PasskeyBridge's VC engine, a separate service that issues JWT credentials signed with ES256 and hybrid ML-DSA-65 post-quantum signatures (NIST FIPS 204). A relying party can combine a credential with the outcome of a signal check, but the playbook engine does not create one.

Webhook delivery: Reliability at the edge

Outbound webhook delivery is the most latency-variable component in the pipeline. The tenant's endpoint might respond in 5ms or 500ms. It might be down. It might rate-limit. The playbook engine handles this with a standard retry policy: up to 4 attempts in total, with the wait doubling after each failure and capped at 30 seconds. Each delivery attempt is logged to shield_webhook_deliveries with the stored request body, the response status, the response body (identifiers masked, truncated to 2,000 characters), the attempt number, latency, and error message.

The webhook payload includes the signal type, phone hash, tenant ID, timestamp, and the full event metadata—everything the tenant needs to take application-level action without querying the PasskeyBridge API. For tenants that require payload integrity verification, the platform signs the webhook body with HMAC-SHA-256 using the tenant's signing secret and includes the signature in the x-pb-signature header. Deliveries can also carry a post-quantum signature in x-pb-pqc-* headers. Either lets the receiving application verify that the payload was not altered in transit.

Audit trail: Append-only, zero-PII

Every action in the pipeline writes to the immutable audit trail. The audit record includes the actor (system, user hash, or API key hash), the action type, the resource type and ID, the result (success or failure), and a metadata object with action-specific details. It does not include PII—consistent with the platform's zero-PII architecture.

The audit trail serves three purposes: operational debugging (why did this playbook not fire?), compliance evidence (SOC 2, Reg S-ID), and forensic analysis (what happened in the moments after the SIM swap?). Every record is timestamped, tenant-scoped, and queryable via the dashboard's Audit Log viewer.

A single API call, end to end

When a carrier sends a SIM-swap signal to the PasskeyBridge ingest endpoint, the code runs these steps in order:

  1. Validate. The body is read under a size cap, parsed, and checked against the Zod schema before any database call.
  2. Load context. One database round trip returns the organization, the API-key row, the matching active playbook and the rate-limit counter.
  3. Authenticate. The API key must carry the ingest scope. An x-pb-signature HMAC-SHA-256 header is verified when present, and required when the organization has turned on signed ingest.
  4. Decide. A raw phone number is keyed with HMAC-SHA-256 under a server-held pepper, the decision is made, and the time taken so far is recorded as decision_ms.
  5. Hard-signal response. A SIM swap is a hard signal, so the tenant's agent delegates are deactivated and open A2A negotiations revoked inline.
  6. Playbook actions. Every action in the matched playbook runs in parallel, each raced against an 8-second timeout.
  7. Persist. The event row is written to shield_events. Only after that insert succeeds are the usage counter and the audit row written.
  8. Respond. For Enterprise organizations the intelligence worker is dispatched without waiting on it, and the response returns to the caller with latency_ms for the whole request.

The caller waits for every step above, playbook actions included. decision_ms covers PasskeyBridge's own work through step 4 and is recorded on every event; the full request is returned to the caller as latency_ms.

Detection with response

Gartner's Identity Threat Detection and Response (ITDR) category covers tools that detect identity attacks and help respond to them. PasskeyBridge's Identity Threat Response as a Service (ITRaaS) puts the response inside the same request that carries the signal.

The playbook engine is how that works in practice. It turns a single carrier signal into a response across A2A negotiations, cached passkey proofs, agent delegates, webhook and email notification, and audit logging, all within a single API call.

The pipeline stores no plaintext phone numbers, signs webhook deliveries, and writes to an append-only audit trail that supports SOC 2 readiness and SEC Reg S-ID record-keeping without recording a phone number.

Explore the API →

Start free · Test the API