---
title: "Secure Outbound"
manual: "nr-vault"
version: "1.0"
permalink: "https://docs.typo3.org/permalink/netresearch/nr-vault:developer-secure-outbound@1.0"
source: "Developer/SecureOutbound.rst"
rendered: "2026-09-18T07:37:50+00:00"
---

# Secure Outbound {#secure-outbound}

> [!NOTE]
> Secure Outbound is a planned feature for nr-vault. This documentation
> describes the planned architecture and API. Implementation is in progress —
> no class named on this page exists in `Classes/` yet.
>
> **If you need a vault-aware HTTP client today, you already have one:**
> `VaultHttpClientInterface` ([Vault HTTP client](https://docs.typo3.org/permalink/netresearch/nr-vault:api-http-client@1.0)) injects secrets
> into outbound requests without exposing them to calling code.
>
> Do not mistake the shipped `Classes/Http/SecureHttpClientFactory` for
> this feature. Despite the similar name it is an internal factory that
> configures Guzzle from TYPO3's HTTP settings, used by
> `VaultHttpClient`, `OAuthTokenManager` and
> `WebhookAuditSink`.

Secure Outbound extends nr-vault into a governed outbound integration platform
for TYPO3. It provides centralized credential management, policy enforcement,
and audit logging for all external API calls.

**Table of contents**

-   [Overview](https://docs.typo3.org/permalink/netresearch/nr-vault:overview@1.0)
-   [Core concepts](https://docs.typo3.org/permalink/netresearch/nr-vault:core-concepts@1.0)
-   [Security features](https://docs.typo3.org/permalink/netresearch/nr-vault:security-features@1.0)
-   [Transport backends](https://docs.typo3.org/permalink/netresearch/nr-vault:transport-backends@1.0)
-   [Usage example](https://docs.typo3.org/permalink/netresearch/nr-vault:usage-example@1.0)
-   [Related ADRs](https://docs.typo3.org/permalink/netresearch/nr-vault:related-adrs@1.0)

## Overview {#overview}

TYPO3 projects increasingly depend on external APIs (LLMs, shipping, payments,
CRM, marketing, internal platforms). Today, most integrations are implemented
per extension:

-   endpoints are configured in multiple places
-   credentials get passed around in PHP memory
-   every integration re-implements auth/retry/timeouts/logging
-   no centralized policy enforcement (SSRF hardening, allowed hosts/paths)
-   no consistent audit trail per outbound API call

Secure Outbound addresses these issues with three core components:

-   **Service Registry**

    Central definition of service endpoints with security policies.

-   **Credential Sets**

    Typed bundles of secrets (OAuth2, API key, Basic auth) managed as one unit.

-   **SecureHttpClient**

    Stable PHP API for extensions to call services by `serviceId`.

## Core concepts {#core-concepts}

### Service Registry {#service-registry}

Services are centrally configured with:

-   **serviceId**: stable identifier used by consuming code
-   **base URLs**: allowed endpoint URLs
-   **security policy**: allowed hosts, methods, path patterns, timeout caps
-   **credential binding**: link to a Credential Set

Extensions never hardcode endpoints. They reference services by `serviceId`.

### Credential Sets {#credential-sets}

Credential Sets are typed wrappers over nr-vault secrets. They store encrypted
JSON payloads containing all fields for a credential type:

**Bearer Token:**

**Bearer token payload**

```json
{"token": "sk-abc123..."}
```

**OAuth2 Client Credentials:**

**OAuth2 client credentials payload**

```json
{
  "client_id": "my-client",
  "client_secret": "secret123",
  "token_url": "https://oauth.example.com/token",
  "scopes": ["read", "write"]
}
```

Supported credential types (MVP):

-   Bearer Token
-   API Key Header
-   Basic Authentication
-   OAuth2 Client Credentials

### SecureHttpClient API {#securehttpclient-api}

Extensions call external services using a simple PHP API:

**SecureHttpClientInterface**

```php
interface SecureHttpClientInterface
{
    public function request(
        string $serviceId,
        string $method,
        string $path,
        array $options = []
    ): SecureHttpResponse;
}
```

**Request options:**

-   `query`: Query parameters
-   `headers`: Additional headers (non-secret)
-   `json`: JSON body
-   `body`: Raw body
-   `timeout`: Timeout override (clamped by policy)
-   `idempotencyKey`: Optional idempotency key

**Response:**

**SecureHttpResponse methods**

```php
$response->statusCode();  // int
$response->headers();     // array
$response->body();        // string
$response->json();        // array (throws on invalid JSON)
```

## Security features {#security-features}

### Policy enforcement {#policy-enforcement}

All requests are validated against the service's security policy:

-   **Allowed hosts/base URLs**: Requests can only go to configured endpoints
-   **Allowed methods**: Restrict to GET, POST, etc.
-   **Allowed path patterns**: Limit which paths can be called
-   **Private range blocking**: Block access to private IPs, link-local, metadata endpoints
-   **Timeout caps**: Maximum request duration
-   **Max body sizes**: Prevent resource exhaustion

### Audit logging {#audit-logging}

Every outbound call is logged with metadata:

-   serviceId, caller identity, timestamp
-   method, path template, status code
-   duration, bytes in/out
-   error classification, correlation ID

Request/response bodies and secrets are **never** logged.

### Secret protection {#secret-protection}

Credentials are:

-   stored encrypted at rest
-   never exposed in PHP variables when using Rust transport
-   redacted from all logs and debug output
-   rotated centrally without code changes

## Transport backends {#transport-backends}

Secure Outbound supports multiple transport backends:

### PhpTransport (default) {#phptransport-default}

Uses PSR-18 or Symfony HttpClient. Works everywhere, no special requirements.

### RustFfiTransport (optional) {#rustffitransport-optional}

Rust-based transport that:

-   decrypts credentials inside the Rust runtime
-   makes HTTP requests without exposing secrets to PHP
-   supports HTTP/2 and optional HTTP/3

Requires:

-   Rust library installed separately
-   PHP `ffi.enable=preload` configuration

See [ADR-013: Rust FFI preload-only mode](https://docs.typo3.org/permalink/netresearch/nr-vault:adr-013-rust-ffi-preload@1.0) for security considerations.

### SidecarTransport (future) {#sidecartransport-future}

For highest security requirements, a separate daemon process can provide
stronger isolation. See [ADR-016: Sidecar daemon option](https://docs.typo3.org/permalink/netresearch/nr-vault:adr-016-sidecar-option@1.0).

## Usage example {#usage-example}

**Calling an external API**

```php
use Netresearch\NrVault\Service\SecureHttpClientInterface;

final class MyApiService
{
    public function __construct(
        private readonly SecureHttpClientInterface $httpClient,
    ) {}

    public function fetchData(string $resourceId): array
    {
        $response = $this->httpClient->request(
            serviceId: 'my-api',
            method: 'GET',
            path: '/resources/' . $resourceId,
            options: [
                'query' => ['include' => 'metadata'],
            ]
        );

        return $response->json();
    }
}
```

The `my-api` service and its credentials are configured in the backend
module. The extension code never handles credentials directly.

## Related ADRs {#related-adrs}

Architecture decisions for Secure Outbound:

-   [ADR-010: Secure Outbound inside nr-vault](https://docs.typo3.org/permalink/netresearch/nr-vault:adr-010-secure-outbound@1.0) \- Feature scope decision
-   [ADR-011: Credential Sets data model](https://docs.typo3.org/permalink/netresearch/nr-vault:adr-011-credential-sets@1.0) \- Credential Sets data model
-   [ADR-012: SecureHttpClient API and transports](https://docs.typo3.org/permalink/netresearch/nr-vault:adr-012-secure-http-transports@1.0) \- Transport abstraction
-   [ADR-013: Rust FFI preload-only mode](https://docs.typo3.org/permalink/netresearch/nr-vault:adr-013-rust-ffi-preload@1.0) \- Rust FFI security
-   [ADR-014: Packaging native artifacts](https://docs.typo3.org/permalink/netresearch/nr-vault:adr-014-packaging-native@1.0) \- Native artifact distribution
-   [ADR-015: HTTP/3 feature flag](https://docs.typo3.org/permalink/netresearch/nr-vault:adr-015-http3-feature-flag@1.0) \- HTTP/3 support
-   [ADR-016: Sidecar daemon option](https://docs.typo3.org/permalink/netresearch/nr-vault:adr-016-sidecar-option@1.0) \- Sidecar daemon option
-   [ADR-017: Audit metadata retention](https://docs.typo3.org/permalink/netresearch/nr-vault:adr-017-audit-metadata-retention@1.0) \- Audit log design
