# Outbound Connections — Admin Guide

Outbound connections are admin-managed HTTPS destinations that Cameleer Server can POST to. They are the building block for future alerting webhooks (Plan 02) and for any other outbound integration. This page explains how to create one, how the TLS trust modes work, and what happens when you click *Test*.

## What is an outbound connection?

An outbound connection is a reusable HTTPS destination with:

- A **URL** (must be `https://`)
- A **method** (`POST`, `PUT`, or `PATCH`)
- Optional **default headers** and a **default body template** (Mustache-style placeholders like `{{message}}` will be supported by the alerting engine in Plan 02)
- A **TLS trust mode** — how the server validates the destination's certificate
- Optional **HMAC signing secret** — if set, the server HMAC-signs the request body and sends the signature in an `X-Cameleer-Signature` header (wiring lands in Plan 02)
- Optional **authentication** — Bearer token or Basic auth, stored encrypted at rest
- An optional **allowed-environments** restriction — if empty, the connection is usable from all environments; if non-empty, only rules in listed environments may use it

Connections are tenant-scoped. Names must be unique within a tenant.

## Creating a connection

Admin → *Outbound Connections* → *New connection*.

Fill in:

- **Name** — short identifier, unique per tenant (e.g. `slack-ops`, `pagerduty-primary`).
- **URL** — must start with `https://`. `http://` is rejected.
- **Method** — pick `POST` for most webhooks.
- **Default headers** — e.g. `Content-Type: application/json` for JSON webhooks. Per-rule headers may override these in Plan 02.
- **Default body template** — the request body used when a rule doesn't specify its own. Plan 02 will interpolate Mustache variables.
- **TLS trust mode** — see below.
- **HMAC secret** — optional. If supplied, it's encrypted at rest using a key derived from the server's JWT signing secret (AES-GCM + HMAC-SHA256 KDF). The plaintext never leaves the browser-to-server path.
- **Auth** — `None`, `Bearer`, or `Basic`. Credentials are encrypted at rest alongside the HMAC secret.
- **Allow in all environments** — unchecked lets you restrict usage to a subset.

Hit *Create*. The connection is now listed on the index page.

## TLS trust modes

| Mode | When to use |
|---|---|
| `SYSTEM_DEFAULT` | Standard public endpoints (Slack, PagerDuty, GitHub, etc.). The JVM's default trust store is used. |
| `TRUST_PATHS` | Self-hosted endpoints signed by a private CA. Provide one or more absolute paths to PEM-encoded CA certificates on the server filesystem. The JVM defaults are preserved; the configured CAs are added on top. |
| `TRUST_ALL` | Local dev and staging against self-signed certs. **Disables certificate validation entirely.** The UI shows an amber warning and does not recommend this for production. |

You can also configure tenant-wide extras via `cameleer.server.outbound-http.trusted-ca-pem-paths` in `application.yml` — those CAs are added to every outbound HTTPS call. If a path in that list doesn't exist on disk, the server refuses to start (fail-fast).

## Testing a connection

On the edit page of a saved connection, click *Test*. The server issues a synthetic `POST` with body `{"probe":true}` to the connection's URL using the connection's stored trust/auth configuration and returns:

- HTTP status code (0 if the request never completed)
- Latency in milliseconds
- First 512 characters of the response body
- TLS protocol (reported as `TLS`; full protocol/cipher/peer-cert extraction is deferred to a Plan 02 follow-up)
- Error message, if any

The probe is audit-logged under `OUTBOUND_CONNECTION_CHANGE` so you can trace who tested what.

Any test endpoint with a real handler should accept `{"probe":true}` as a harmless payload. If a downstream rejects the body shape, you still see the HTTP status, which is usually enough to diagnose routing / auth / TLS issues.

## Allowed environments

When a connection's *Allow in all environments* toggle is off and a set of environments is chosen, the connection is only usable by alerting rules (Plan 02) that fire in those environments. Two guards enforce this:

1. **Narrowing guard on update** — if you remove an environment from the list while existing rules reference this connection in that environment, the server returns `409 Conflict` and names the rules. (Plan 01 stubs out the rules check; it returns empty. Plan 02 wires it to the real alert-rules table.)
2. **Delete guard** — attempting to delete a connection still referenced by any rule returns `409 Conflict`. Drop the rules (or reassign them) first.

An empty list means "allowed everywhere" — the default.

## HMAC signing semantics (for consumers)

When Plan 02 starts firing webhook requests, connections with an HMAC secret set will sign each request body as follows:

```
X-Cameleer-Signature: v1=<hex(HMAC-SHA256(secret, body))>
X-Cameleer-Timestamp: <ISO-8601 UTC>
```

Consumers should compute the same HMAC over the raw body bytes using their copy of the shared secret and reject requests where the signatures don't match. Rotate secrets by updating the connection in the UI — the old secret continues to sign until the change is saved.

## RBAC

- **ADMIN** can create, update, delete, and test connections.
- **OPERATOR** can list and view connections (read-only). This mirrors the "operators run playbooks, admins configure systems" split used elsewhere in the product.
- **VIEWER** has no visibility into outbound connections.

All mutations are recorded in the audit log (`/admin/audit`) under categories `OUTBOUND_CONNECTION_CHANGE` (create/update/delete/test) and — reserved for future use — `OUTBOUND_HTTP_TRUST_CHANGE` for tenant-wide trust store edits.

## Operational notes

- Outbound clients are memoized per `(trust mode, CA paths, timeouts)` tuple inside `ApacheOutboundHttpClientFactory`. Changing a connection's trust mode evicts its cached client on next call.
- Default connect timeout is 2s; default read timeout is 5s. Override per-tenant in `cameleer.server.outbound-http.default-*-timeout-ms`.
- Proxy support (`cameleer.server.outbound-http.proxy-*` properties) is wired through the properties record but not yet applied by the factory — a Plan 02 follow-up.
- OIDC still uses its own Nimbus HTTP client. Retrofitting OIDC onto `OutboundHttpClientFactory` is deliberately deferred so Plan 01 doesn't touch proven-working auth code.
