AUTH4D-35: Stitch provider client

@auth4/provider-stitch obtains Stitch Express access tokens and sends authenticated REST requests. It exposes no HTTP routes. Stitch Express (https://express.stitch.money) is a separate product from the Stitch Enterprise GraphQL API at api.stitch.money; Express credentials are not accepted there.

Tokens come from POST https://express.stitch.money/api/v1/token. The request is JSON: { clientId, clientSecret, scope }, and the response is { success: true, data: { accessToken } }. Express accepts one scope per token. API requests go to https://express.stitch.money/api/v1/... with Authorization: Bearer <token>, and every response is wrapped as { success, data }. Callers supply the client ID (STITCH_CLIENT_ID var), the client secret (STITCH_CLIENT_SECRET Worker secret) and the scope, such as client_paymentrequest. The package never reads globals or environment bindings.

Viewing the client secret in the Stitch Express dashboard regenerates it, and the previous secret stops working at once. A token request then fails with HTTP 400 invalid_credentials.

Tokens are valid for 15 minutes; the response carries no expiry. They are cached only in isolate memory and refreshed 60 seconds early by default. Concurrent callers share one token request. An HTTP 401 response invalidates the token and retries exactly once. Each HTTP attempt times out after 10 seconds by default.

Failures throw StitchError with a fixed message and a kind:

Response kind
Token 400 invalid_credentials, or a second 401 auth
403 (token minted with the wrong scope) auth
Other 4xx: 400 field errors, 404, 409 validation
429, 5xx, or a 2xx without success: true and data upstream
No response, or the client-side timeout network

The error also carries status, the fixed operationName, the envelope’s snake_case code, timedOut and retryable. Provider messages, response bodies, request bodies, tokens and credentials are never kept. Diagnostics contain only the phase (token or api), outcome, attempt, duration, status and operation name. createObservabilityStitchSink forwards them through the allowlisting @auth4/observability logger. redactText scrubs known secrets and credential-shaped text from any string that might reach a log.

Local development may override the endpoints with a loopback origin only.

Source: docs/api-spec/auth4d-35.md