> ## Documentation Index
> Fetch the complete documentation index at: https://forst-lang.org/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Invoke security

> Local transport, authentication, and header rules for calling Forst over HTTP.

Forst invoke is a local process boundary. It is designed for a Node application and its local Forst server. Do not expose the invoke listener directly to the public network.

## Default protections

On Unix, the invoke server listens on a mode `0600` Unix domain socket at `.forst/invoke.sock` by default. Windows and `FORST_INVOKE_TRANSPORT=tcp` use HTTP over loopback TCP instead. The server also checks the request `Host` header, requires JSON for `POST /invoke`, limits concurrent invoke work, and returns sanitized errors.

HMAC challenge-response auth is on by default. Set `FORST_INVOKE_AUTH=off` only for local debugging. The server and Node clients log a startup warning every time auth is disabled.

When Forst writes `.forst/invoke.ready`, it uses mode `0600`. The file contains server metadata such as the URL, socket path, and auth generation. It does not contain the token.

<Warning>
  `AllowNonLoopback` is an explicit opt-in for trusted deployments. It does not turn the local invoke protocol into a public API. Place a separately authenticated application API in front of Forst instead.
</Warning>

## Local transports

<Tabs>
  <Tab title="Unix (default)">
    A Unix domain socket at `.forst/invoke.sock` is the default local transport on non-Windows hosts. The socket has mode `0600`. Linux and macOS verify that the connecting peer has the same UID as the Forst process.

    `invoke.ready` advertises this transport through `socketPath`. The sidecar, `@forst/client`, CLI helpers, and generated `@forst/gen` transport read that path and dial the socket.
  </Tab>

  <Tab title="TCP fallback">
    Windows and `FORST_INVOKE_TRANSPORT=tcp` use HTTP over loopback TCP. The invoke server rejects non-loopback remote addresses.
  </Tab>
</Tabs>

## Authentication flow

Invoke RPC requests use a single-use challenge and an HMAC proof. The client first requests `GET /invoke/challenge`. It then sends the nonce, current generation, and an HMAC-SHA256 proof on the RPC request.

The proof binds the protocol version, generation, and nonce. A replayed nonce, wrong generation, malformed proof, or proof from another token is rejected. The server applies an exponential backoff for repeated failures from the same peer.

The secret is a 32-byte token. Connect mode delivers it through the `FORST_INVOKE_TOKEN` environment variable (base64url). The server sets this on the `forst dev` process when it starts. Worker processes that attach to an existing dev server must inherit `FORST_INVOKE_TOKEN` from the parent or receive it explicitly.

In sidecar spawn mode, the child sends the secret through an inherited `FORST_INVOKE_AUTH_FD` file descriptor instead. This keeps the secret out of the ready file and avoids writing it to disk.

When `bridge.hostMode` is enabled, the Node app process (the host) may start before the embedded invoke server inside the compiled Go program is ready. The `forst dev` parent process opens a pipe, passes the read end into the Node host as an inherited file descriptor (an open pipe handle the child receives at startup), and relays auth lines from the Go program’s `FORST_INVOKE_AUTH_FD` write end to the host’s `FORST_INVOKE_AUTH_RECV_FD` read end. That way the host never reads a token file.

`.forst/invoke.ready` includes `tokenDelivery` (`env` or `handoff`) so clients know which channel to use.

In a Node host process, call `prepareInvokeConnect()` from `@forst/cli/invoke` at startup. It sets connect-mode env and listens on `FORST_INVOKE_AUTH_RECV_FD`. Use `getInvokeAuthHandoff()` with your generated client's `resolveAuth` option when auth arrives over the pipe.

<Note>
  Use the Forst sidecar transport for authenticated invoke requests. Do not build a raw `curl` request to `POST /invoke`: it cannot complete the challenge-response flow without the local secret.
</Note>

## Reserved request headers

The client owns these headers:

* `X-Forst-Invoke-Nonce`
* `X-Forst-Invoke-Generation`
* `X-Forst-Invoke-Proof`
* `X-Forst-Invoke-Token`

Forst removes caller-provided values for these names before it merges default or per-request headers. This prevents application configuration from replacing the authenticated proof. You may still send application headers such as `Authorization`, `X-Request-Id`, and `X-Tenant-Id`.

## TLS and the local threat model

TLS is intentionally not used for the local invoke transport. A mode-`0600` Unix socket plus same-user peer checks and proof authentication covers the normal local development threat model. Loopback TCP still uses proof authentication. Revisit TLS if invoke must bind beyond localhost or a deployment requires encryption on loopback traffic.

## Test-only escape hatch

Set `FORST_INVOKE_AUTH=off` only for isolated tests or controlled CI fixtures. It disables proof verification. The invoke server and Node transport log a warning on startup whenever auth is off. Do not set it in development or production application environments.

## Troubleshoot invoke security errors

Use this table to find and resolve invoke security and authentication errors.

| Error                            | Cause                                                       | Solution                                                                         |
| -------------------------------- | ----------------------------------------------------------- | -------------------------------------------------------------------------------- |
| `401 Unauthorized`               | Missing or invalid HMAC token or nonce proof                | Ensure worker process inherits `FORST_INVOKE_TOKEN` or uses sidecar transport    |
| `invoke challenge missing nonce` | Request attempted raw `POST /invoke` without challenge flow | Use generated client or `@forst/cli/invoke` client instead of raw HTTP requests  |
| `contract version mismatch`      | Client and server contract versions disagree                | Upgrade `@forst/gen` client and server binary together                           |
| `non-loopback IP rejected`       | Remote network client connected over TCP                    | Keep invoke server on loopback interface or put authenticated API proxy in front |
| `EACCES` on socket file          | User UID mismatch on Unix domain socket                     | Run Node client and Forst server under the same user account                     |

## Related

<CardGroup cols={2}>
  <Card title="Call Forst over HTTP" icon="https://mintcdn.com/forst/r5GJChnfkgCSJa-b/icons/typescript.svg?fit=max&auto=format&n=r5GJChnfkgCSJa-b&q=85&s=8a8c0cd7b4bf60c264d51f66d0f52e91" href="/docs/interop/invoke/call-forst" width="512" height="512" data-path="icons/typescript.svg">
    Configure generated clients and invoke functions.
  </Card>

  <Card title="Dev server" icon="server" href="/docs/workflow/dev-server">
    Run `forst dev` during local development.
  </Card>
</CardGroup>
