Verified Partner Program

How a platform can host the human-decision step of an oakallow approval inside its own product, so a shared customer approves agent actions in the tool they already use. The program is intentionally registered and scoped by authority so that an approval decided outside the oakallow dashboard still carries the same cryptographic execution-token minting, the same immutable audit trail, and the same governance controls as one decided natively.

The shape in one line

A verified partner is a real legal entity that registers one or more named authorities. A customer opts an authority into their own organization, and from then on every approval in that org is mirrored to the partner over a signed, mutually-authenticated channel. The partner can present the decision in its own UI and write the answer back. oakallow still records the decision, still notifies the customer natively, and still holds the immutable log.

Three actors, one wire boundary

The program is for platforms that decide on behalf of other people's organizations. If you run a product your customers already log into, this is how their oakallow approvals surface there. The model has exactly three actors, and nothing crosses between them except the documented calls and webhooks. A partner hosts the decision surface; it never holds tokens, permissions, or the audit row.

Deciding inside your own org?You don't need this program. If you want to approve from your own Slack, your own dashboard, or any UI you build, your backend simply calls the standard decide endpoint with your API key. The Verified Partner Program exists for the harder case: deciding on behalf of organizations that are not yours, where the deciding party has to prove who it is first.

The three-actor model and its wire boundary. oakallow owns the permission cascade, the approval lifecycle, replay-protected decision recording, run-token minting, and the audit log. The verified partner receives an approval.created webhook, renders the request in its own UI, captures the human decision, and calls external-decide back to oakallow; it never touches tokens, permissions, or the audit row. The customer's agent system checks permission on every tool call, receives approval.decided, mints the run token, executes the tool, and logs the result. The only things that ever cross between the three actors are the documented API calls and webhooks.
oakallow

Runs the permission cascade, creates the approval, records the decision with replay protection and attribution, mints the run token, and holds the immutable audit log. The mechanisms that make a decision trustworthy live here.

Verified partner

Receives the approval, renders it in its own UI, routes it to the right reviewer, captures the decision, and posts it back. It is a decision surface and nothing more: no tokens, no permissions, no audit row.

Customer agent system

Checks permission on every tool call, receives the decision, mints the run token, executes, and logs. Its code path is identical whether the human decided in oakallow's app or the partner's.

When a partner is active for an org, the partner hosts the human-decision step for that org while oakallow still notifies the customer natively and records everything. The partner is where the human decides; oakallow is where the decision counts.

The two-tier identity model

A partner is verified once as a legal entity. Under that entity it registers as many customer-facing authorities as it needs. The legal entity is the trust anchor; the authority is what a customer actually opts into.

The legal entity

One verified record per company, anchored to a corporate domain the company proves it controls. This is the Primary Governing Authority: the entity that owns the corporate domain and accepts the program agreement. It does not appear in any customer-facing listing on its own.

The authorities

Named integrations registered under the legal entity. Each has its own display name, callback domain, and dedicated technical and security contacts, and each goes through its own domain and contact verification. A customer opts into an authority, so a single company can run several distinct integrations with separate trust boundaries.

How a partner gets verified

Verification proves control, not just identity. At the parent-partner level the applicant attests they are authorized to register the company, then proves control of the corporate domain it claims. Each authority under it then proves control of its own separate domain. Domain control is something we can actually prove, so it is the basis of the program, with the partner attestation putting accountability for the claim on the record.

The verification ladder, one rung per check in order. First the applicant submits the application. Then the applicant attests, at the parent-partner level, that they are authorized to register this company and corporate domain as a partner, recorded with email, timestamp, and IP. Then a DNS TXT record on the Primary Governing Authority corporate domain proves they control the company domain. Then, for each named authority, a contact email one-time code and a DNS TXT record on that authority's separate callback domain. Then an oakallow admin reviews the all-green application and approves it to active. Any failed rung routes to rejected. An active record can later be suspended as a recoverable kill switch or revoked terminally.
1

Apply from a corporate domain

The applicant submits the legal entity name, jurisdiction, the corporate domain, and a technical and a security contact email. The applying account's email must be on that corporate domain, and free-webmail and disposable email domains are rejected at the form, so a real corporate address is required from the start.
2

Partner attestation

Right after applying, the applicant attests that they are authorized to register this company and corporate domain as a partner. This is the parent-entity attestation, distinct from the per-authority agreement accepted later. oakallow records it with the accepting email, the timestamp, and the IP, so accountability for the claim is on the record from the start.
3

Prove the corporate domain

The applicant adds a DNS TXT record on the Primary Governing Authority domain. oakallow resolves it over DNS-over-HTTPS and matches a single-use token. This proves control of the company domain itself, not merely an address on it, which is the thing we can actually verify.
4

Verify each authority

For every named authority, the partner verifies its technical and security contacts by email one-time code (six digits, short-lived, attempt-capped) and proves the authority's own callback domain with its own DNS TXT record. That callback domain must be a different host from the bare corporate domain, so each authority demonstrates control of the specific surface its approvals run on. Authorities are verified independently, so one integration never rides on another's trust.
5

Accept the program agreement

The partner accepts a versioned, click-through agreement. oakallow records the version, the accepting email, the timestamp, the IP, and the user agent, so acceptance is a durable audit record rather than a third-party envelope.
6

Admin review, then active

With every rung green, the record sits at verified pending review. An oakallow admin approves it, and only then can a customer opt the authority in. An active record can be suspended (a recoverable pause) or revoked (terminal, cascading to every customer integration under it).

There is no public partner directory. A customer only ever sees an authority they have been pointed to, and authority assignments stay private to the customer's organization.

How a customer opts in

Verification only makes an authority eligible. Nothing flows until a customer enables it on an organization, and enabling is what mints the integration secret. No enabled integration means no secret, which means no approvals are ever delivered to the authority. The secret is the precondition for the whole program, not a detail of it.

Enabling generates the secret that turns it on

An owner or admin enables an authority on one of their organizations from the Verified-Partner Integrations section and supplies the authority's callback URL. Enabling generates a per-integration secret, shown exactly once and stored only as a hash. That secret is the key the authority uses to verify that every callback genuinely came from oakallow. Each organization-and-authority pair is its own integration with its own secret, so a leak is contained to one relationship.

The customer is always in control. An integration can be active, paused, or revoked from the same page; pausing stops delivery, and revoking is permanent, so re-enabling later mints a brand-new secret. The authority never writes to this record. It is the customer's switch, not the authority's.

What happens when an approval fires

oakallow still notifies the customer natively and keeps the record. When a partner is active for the org, the partner hosts the human-decision step and is sent the same approval over a signed, mutually-authenticated channel.

Runtime callback security, in two halves. Outbound: when an approval is created the oakallow auth worker posts it to the partner's callback URL over a mutually-authenticated TLS channel, with the body signed by an HMAC, and also notifies the customer through native and configured channels. Inbound: the partner posts the human decision back to external-decide, where a fixed deterministic check list runs before anything is recorded: a replay nonce and timestamp, an org-scoped lookup that returns a generic not-found across org boundaries, a pending-status lock, an echoed request hash compared in constant time, an optional reference-id match, and an approver-pool check on the deciding email. Only when every check passes is the decision recorded with attribution and an approval.decided callback fired back.
1

An approval is created

When a governed tool call resolves to requires-approval, the worker creates the approval request and notifies the customer natively: the dashboard, mobile push, and any Slack, PagerDuty, or webhook destinations they configured. None of that changes when a partner is involved.
2

The partner receives a signed callback

If an active integration exists for that organization, the worker also posts an approval.created event to the partner's callback URL. The body carries the authority and partner identity, the reference id, the tool name, and a request hash that binds the decision to this exact request.
3

The partner presents the decision

The partner surfaces the request to the right reviewer inside its own product. When the reviewer decides, the partner posts the answer back to oakallow and echoes the request hash it was given.
4

oakallow records and confirms

oakallow verifies the echoed hash against what it stored. A mismatch hard-rejects the decision. On a match, the decision is recorded with the same audit guarantees as any native approval, and an approval.decided callback fires back to the partner so both sides converge on one answer.

Why a partner decision is trustworthy

This is where verification and runtime meet. Every external decision is gated on a server-stored value, the request hash, that only a verified partner who actually received the callback can produce. Verification builds the chain; the runtime checks enforce it.

Why verification is required to decide outside oakallowA server-stored value, the request_hash, gates every external decision. Only verified partners ever receive it. 1 oakallow generates request_hash Random server-side value, computed when approval_requests is written. Stored on the row. request_hash 2 Lookup active integration Two-tier join: customer_platform_integrations × verified_authorities × verified_platforms. All three must be active. 3 approval.created callback delivered HMAC-signed POST to the partner's verified callback URL. Payload includes the request_hash for this approval. request_hash 4 Partner UI captures the decision Human approves or denies inside your product. No oakallow surface required. 5 Partner posts external-decide Includes the request_hash echoed back, plus replay nonce, timestamp, decided_by, reference id. request_hash 6 Constant-time compare at the gate Stored hash compared in constant time to the echoed hash. Mismatch returns 401 with no hint why. WHERE ATTACKS DIE Attack 1 · Stolen runtime API key Attacker has a valid customer key and POSTs external-decide. Fails at step 6. They never received the callback, so cannot produce a matching request_hash. → 401, real reason logged privately Attack 2 · Unverified party No D&B record, no domain proof, no admin approval, no opt-in. Fails at step 2. No active integration for this org, so no callback ever delivered. → Silent skip, attacker never sees a request_hash Verification produces the chain. Runtime checks enforce it. Only a verified partner who actually received THIS callback can decide this approval. oakallow

In practice that chain has two halves: the callback going out is signed and mutually authenticated, and the decision coming back must clear a fixed list of deterministic checks before oakallow records anything.

Outbound: the signed callback
Channel identity (mutual TLS)

The outbound callback presents an oakallow client certificate over mutually-authenticated TLS. A partner that pins our published certificate authority can reject any forged source at the TLS layer, before a byte of the body is read. Callback URLs are HTTPS-only and screened against internal addresses to prevent server-side request forgery.

Message identity (HMAC)

The exact callback body is signed with an HMAC keyed on the integration secret. The partner re-derives the same key from the secret it saved at enable-time and verifies the signature, so a tampered or spoofed body is rejected even if it reaches the endpoint. The secret itself is only ever stored as a hash.

Inbound: the deterministic gate

Every decision the partner posts back runs the same check list, in order. Any failure returns a deliberately vague error to the caller while the real reason is logged privately. The decision is recorded only if all of them pass.

Replay protection: a single-use nonce plus a timestamp inside a tight window, so a captured call cannot be replayed.
Org-scoped lookup: the approval is found only within the caller's own org; anything else returns a generic not-found with no enumeration leak.
Pending-status lock: the approval must still be pending; the status flip is the canonical race lock, so a duplicate decision loses.
Request-hash binding: the partner must echo the request hash it was sent, compared in constant time; a mismatch is rejected, so the decision is bound to the exact request shown.
Reference-id match: if a reference id is supplied it must match what oakallow recorded at create time.
Approver-pool check: the deciding email must belong to the org's approver group for the approval's current level.

Only after every check passes does oakallow record the decision, labeled with the platform and source it came from, and fire the confirmation back. The partner record can be suspended or revoked centrally at any time, and the customer keeps the native record no matter what the partner does.

Testing your integration

You can verify your integration end to end without spending anything and without standing up a sandbox. Two surfaces cover the parts partners most often get wrong: confirming a request is well formed, and getting the callback cryptography exactly right.

Free dry-run permission check

POST to /v1/permissions/check/dry-runwith your API key. It resolves your org's real policy and returns the same verdict shape as the live check (allowed, requires_approval, or disabled), tagged dry_run: true. It creates no approval, writes nothing, and is not billed, so you can confirm your request shape and see how your rules resolve as often as you like. It requires a valid key, so it is scoped to your own org, never open to anonymous traffic. Creating real approvals end to end is metered like any production call.

Offline crypto test vectors

We publish fixed sample inputs with the correct request_hash and the correct callback HMAC signature, computed with the exact algorithms oakallow uses. Run your own code against them on your own machine, with no calls to us and no account, and confirm you produce the same values. This pins down the two easy mistakes before they ever hit a live callback.

The two non-obvious details the vectors lock in:

request_hash normalization: the hash is computed over canonical fields with sorted keys; tool_name is trimmed and lowercased and reason is trimmed before hashing, so echo back the hash we send rather than recomputing from your own formatting.
HMAC key derivation: the callback signature key is the SHA-256 hex of your integration secret, not the raw secret, and it signs the exact raw body bytes. Verify against the raw bytes before any re-parsing.

Interested in becoming a verified partner?

The full program details, including the application flow and the agreement, live in the FAQ. Verification starts from an account on your corporate domain.

Read the program FAQ See the architecture