What it does

Preflight is a pre-dial compliance interlock inside your own Vonage account. It reads the call flow your server is about to serve, runs monitors compiled from the federal and Georgia telemarketing rules over it, and refuses the call before the carrier is asked to place it when the flow would reach a prohibited state. A refused call names the rule, the citation and the exact sequence of actions that would have reached it. The fix is made, the same phone rings. Every decision is an entry in a hash-chained evidence log sealed daily to a public transparency log, and every night the platform's own call records are reconciled against it.

On the live host today: the broken reference flow is refused through the gateway in 136 to 169 ms with "47 CFR 64.1200(b)(3)" on the response, the line stays silent for the measured minute after it, and the fixed flow is placed in 316 ms, both legs answered and both branches passed at the hook.

Who it is for

A small team running outbound notification calls on Vonage (a clinic, a county office, a campus alert system) that cannot read every branch of the flow its own server serves, because the platform asks the server for a new object on every keypress and every silence. Georgia removed the knowledge requirement from its telemarketing statute on July 1, 2024 and extended liability to whoever the call is made on behalf of, so such a team is exposed for a vendor's flow it has never seen. The builder is the first user: the reference flow behind the public number is the one written at the Atlanta workshop, defect included.

Lens

Real-World Use.

Vonage APIs and features, exactly as the code calls them

  • Voice API: call-control objects (talk, input, connect, notify, stream, record, conversation, pay parsed and evaluated), the answer, event and fallback webhooks, signed callbacks verified with @vonage/jwt (HS256 with the payload hash checked), POST /v1/calls through the create-call gateway with the caller's own token.
  • Verify v2, voice channel: the consent gate speaks a code to the visitor's phone before the interlock will dial it.
  • Identity Insights: the paid lookup that resolves a hold the free prefix tables could not, after the response and never inside a decision.
  • Application API: one-click install and rollback of the three webhooks with signed callbacks on, verified by read-back.
  • Reports API: the nightly carrier-side reconciliation of the account's call records against the evidence log.
  • Users API and Client SDK user tokens: the browser softphone's sessions (judge tokens capped per day; the scheduler's behind the dashboard token). The application carries the RTC capability.
  • Numbers: the public Atlanta-overlay number and the outbound caller id.

How it works, in four steps

  1. Read the flow. The platform calls Preflight instead of your server; Preflight verifies the signature, forwards the request unchanged, reads the object that comes back.
  2. Compile the statute. Five properties as formulas over what the object does, each with its citation, each quoted clause a byte-for-byte substring of the fetched text, enforced by a test. Three rate properties over the calls the host has seen.
  3. Decide before the dial. True passes the bytes through, false refuses with a safe object naming the rule, undecided holds for a person, and a person's release travels with the call. Outbound calls go through the gateway because the platform asks for the flow only once a call is answered (measured: answered at 868 ms, the flow asked for at 1,009 ms).
  4. Write the receipt. A hash-chained log, sealed to Sigstore Rekor daily, reconciled nightly against the platform's own records.

Try it without an account

  • Open https://preflight-web-nine.vercel.app: every number on the page is read from the host on load, and the sandbox runs the engine in your browser on the labelled corpus.
  • curl -s https://preflight-api-rc34.onrender.com/api/summary
  • npx -y preflight-interlock@0.2.0 verify-ledger https://preflight-api-rc34.onrender.com recomputes the chain from genesis on your machine.
  • docs/judges.md in the repository walks the rest in three minutes.
  • Dial +1 943 244 5023: the reference flow behind it is the broken one, and the interlock answers.

Honest limits

Preflight verifies the structure and position of a call flow, never whether the spoken words are true. Coverage is bounded by observed traffic and the header says how much has been seen. A rate center is a proxy for where the called party is. The consent gate records consent to one demonstration call, not campaign-level consent. It is a compliance tool, not legal advice.

Challenges

The specification had a hole: the answer webhook fires only once a call is answered, so a webhook-only interlock cannot keep a phone silent. Measuring it on a real call (two written predictions, one confirmed) turned the design into a create-call gateway. Ten corrections to the specification were found by construction, each recorded with the check that found it: two of the five formulas were wrong as first written, calling hours and caller id turned out to be facts about the call rather than guards on spoken actions, a Client SDK user's leg arrives with no from and no direction and had to be recognised as inbound. Executing the film prep on the live host found two more defects the same afternoon: an operator's release of a held call was inert at answer time, and the platform's input event on a timeout carries uuid: null, so the branch hook had lost the call it belonged to. Both are fixed, tested against the measured payload shapes, and written up in the fact sheet.

What we learned

That the phone staying silent is a claim about timing, and timing has to be measured, not read from the documentation. That a claim in a README rots faster than code, so the numbers are generated from the repository and the live host, and CI fails when the two drift. That the most convincing negative is one checked against the sponsor's own records, not against our own log. And that under a strict policy every branch has to be seen once by a person before it can be trusted, which is a product story, not a limitation.

Numbers, every one from docs/fact-sheet.md

  • 307 tests across the monorepo; 48 hand-labelled call-control objects replayed by the published CLI; a mutation harness with every mutant killed.
  • Mid-call audio control on the platform: median 103 ms, p95 183 ms over 50 flips, 0 errors.
  • The answer webhook arrives 1,009 ms after the request for a call answered at 868 ms, so the gateway exists.
  • Gateway refusals of the broken flow: 136 to 169 ms; the fixed flow placed in 316 ms; decision latency p50 52 ms over the last 30 decisions.
  • Signed webhooks verified live on both legs of a real call; the evidence log recomputes from genesis; the daily seal is a public Rekor entry.

Built With

  • fastify
  • gsap
  • neon
  • node.js
  • playwright
  • postgresql
  • render
  • sigstore-rekor
  • typescript
  • vercel
  • vite
  • vonage-application-api
  • vonage-client-sdk
  • vonage-identity-insights
  • vonage-reports-api
  • vonage-verify
  • vonage-voice-api
  • web-push
Share this project:

Updates