Fork Services documentation

From sandbox request to provider response

This page documents the current Mock SES slice and the contract future integrations should follow.

What this sandbox provides

services.<domain> is an ordinary Fork sandbox that serves a static authenticated organization dashboard. The dashboard calls host-owned Fork account APIs to manage the Mock SES installation, wallet, request history, and test execution. It has no application backend and never receives the Fork account cookie.

This sandbox does not store the control-plane signing key, provider credentials, wallet database, or a caller-supplied organization identity.

Live request flow

  1. The browser signs in with Fork and calls the same host-owned account API used by the installation and wallet controls.
  2. The account API verifies the Fork session, same-origin request, and organization-admin membership before the request can reach sandbox code.
  3. The account API binds the test to the registered services.<domain> workspace and invokes the same Gateway application used by port 9800.
  4. The Gateway asks Core for that workspace's authoritative project and organization and rejects any organization mismatch.
  5. The gateway checks that Mock SES is installed, prices the action, and reserves wallet funds.
  6. The gateway creates the provider request, adds the provider credential in memory, and signs the complete request with the host-only private key.
  7. The Mock SES adapter verifies the signature with its public key and executes the action.
  8. The gateway settles, releases, or holds the reservation and returns the platform response through the account API to the browser.

Application-facing request

POST http://<sandbox-default-gateway>:9800/v1/actions/email.send
Content-Type: application/json
Idempotency-Key: your-stable-request-id

{
  "from": "sender@example.com",
  "to": "recipient@example.com",
  "subject": "Hello",
  "text": "Sent through Fork Services"
}

The application does not send an organization ID, workspace ID, provider URL, provider key, or gateway signature. Those are derived or added after the request leaves the application.

Responses worth testing

Accepted

A normal recipient returns status: accepted. The reservation becomes a posted wallet charge.

Not installed

If Mock SES is not installed for the derived organization, the gateway rejects before contacting the provider.

Insufficient funds

If available credit is below the action price, the gateway returns a payment error before contacting the provider.

Provider rejection

Use recipient@reject.mock.fork. The reservation is released.

Unknown outcome

Use recipient@timeout.mock.fork. The reservation remains held for reconciliation.

Idempotent replay

Reuse the same idempotency key and payload. Fork returns the existing request without charging twice.

Where state and keys live

ItemOwnerLocation and purpose
Wallet and installationsControl plane/var/lib/fork-services/services.sqlite3; never copied into a sandbox.
Private signing keyControl plane/etc/fork/service-signing-private-key.pem; signs provider-bound requests and is never displayed or copied.
Public verification keyProvider sandbox/etc/fork/service-signing-public-key.pem; verifies that port 9800 authorized a request.
Provider credentialGateway/credential systemThe mock uses a request-bound placeholder. A production provider would receive a scoped credential only after authorization.
Fork account cookieHost-owned account serviceAuthorizes the dashboard and test route at the edge. It is stripped before traffic reaches the sandbox and is never accepted by port 9800 as workspace identity.

Adding a future provider

  1. Define a named action and validate its application-facing payload at port 9800.
  2. Build a provider adapter that accepts only the signed internal execution contract.
  3. Provision the provider as a Fork-owned sandbox and copy in only the public verification key.
  4. Register the provider route and installation price in the control-plane state model.
  5. Resolve the real provider credential after identity, installation, and wallet checks.
  6. Map provider results into accepted, rejected, or pending outcomes and test wallet settlement.
  7. Add a public documentation-only page on port 8080. Keep execution on a different private port.