# App settings

> Configure a realtime app's name, availability, capability flags, and allowed browser origins, and understand what deleting an app removes.

The **Settings** screen in the realtime console operates on the app currently
selected in the app switcher. Every control on it writes through a single
procedure, `realtime.apps.update`, and the danger zone calls
`realtime.apps.remove`.

The screen only renders fields that the app row actually carries. Toggles with
no backing field (encrypted channels, forced TLS, transport selection) are
deliberately absent rather than shown as controls that do nothing.

You need to be signed in and have an organization context for the screen to
load — settings are scoped to your organization. If no app is selected, the
screen points you at **Apps & keys** to create one first.

## How saves are applied

There is no local "unsaved changes" buffer for the toggles and origin list.
Each control mutates immediately and, on success, the screen refetches the app
list and re-seeds its local state from the returned row. A rejected update
therefore never leaves the UI displaying a value the backend refused — the
previous server value comes back, and the error message from the procedure is
shown above the cards. While a mutation is in flight, the page header shows
`Saving…`.

The fields `realtime.apps.update` accepts from this screen:

| Field            | Written by                                | Notes                                              |
| ---------------- | ----------------------------------------- | -------------------------------------------------- |
| `name`           | App name field + **Save**                 | Trimmed before sending.                            |
| `status`         | **App enabled** toggle                    | `active` or `disabled`.                            |
| `clientEvents`   | **Enable client events** toggle           | Boolean.                                           |
| `authorizedOnly` | **Authorized connections only** toggle    | Boolean.                                           |
| `allowedOrigins` | Add / remove in **CORS / allowed origins** | The full replacement list, not a delta.            |

Every call also carries `orgId` and the app's internal `id`.

## App identity and status

The **App** card shows the app's display name, its `app_id` (also printed in
the page subheading), and a status pill: `active` when the app is enabled, or
the raw status value when it is not.

The name is editable inline. **Save** is disabled while the field matches the
stored name or while a mutation is pending, and an empty or whitespace-only
name is rejected in the form before any request is sent. Renaming has a
side effect worth knowing about: the app name is also the confirmation token
for deletion, so renaming an app changes what you must type in the danger zone.

## Enabling and disabling an app

The **App enabled** toggle flips `status` between `active` and `disabled`.

Disabling an app removes it from the engine registry, so clients can no longer
connect with its credentials. The app's key and secret are **not** destroyed —
they stay on the row, and re-enabling the app restores connectivity with the
same credentials. Use this when you want to stop traffic without rotating keys
or rewriting client configuration.

Disabling is the reversible control. Deleting is not — see
[Deleting an app](#deleting-an-app).

## Capability flags enforced at the edge

The **App capabilities** card carries two protocol flags. Both are enforced by
the ClutchCall edge, not by the SDK, so changing them takes effect for
connections the edge is already handling rather than only for newly written
client code.

| Flag                             | Effect when on                                                     |
| -------------------------------- | ------------------------------------------------------------------ |
| **Enable client events**         | Subscribers may publish `client-*` events to channels.             |
| **Authorized connections only**  | Requires auth for `private-*` and `presence-*` channels.           |

Turning **Enable client events** off means subscriber-originated `client-*`
publishes are not accepted for this app; server-side publishing is unaffected.

## Allowed origins and the Origin check

The **CORS / allowed origins** card holds the list of browser origins permitted
to open a connection with this app's key. The edge compares a browser's
`Origin` request header against the entries in this list.

**An empty list means any origin is allowed.** The screen surfaces this as a
warning when the list is empty: any page on any origin can open a connection
with the app's key in that state. Add your site's origin before going to
production.

Entries are added and removed one at a time, and each change immediately
persists the whole new list via `allowedOrigins`.

### What a valid entry looks like

An allowed origin is **scheme plus host, with an optional port** — nothing
else. The form validates each entry before it is saved and rejects anything
that does not fit:

- The scheme must be `http://` or `https://`.
- No path, query string, or fragment. A bare trailing `/` is also rejected.
- No userinfo (`user:pass@`).
- The host must be a syntactically valid hostname.

Valid examples:

```
https://app.example.com
https://app.example.com:8443
https://*.example.com
```

### Wildcard rules

The `*` character is only accepted as the **entire leftmost label** of the
hostname. `https://*.example.com` is valid. A wildcard anywhere else — a
partial label like `https://*pp.example.com`, or a wildcard in an inner label
like `https://app.*.example.com` — is rejected with the same message as any
other malformed origin.

There is exactly one wildcard position, so a single entry cannot cover both
`example.com` and its subdomains. Add both entries if you need both.

### Ports

A port is optional. If you type one, it is part of the stored origin and part
of what the edge compares against; browsers include the port in the `Origin`
header whenever it is not the scheme's default. If your site is served on a
non-default port, include that port in the entry.

### Duplicates and errors

Adding an origin that is already in the list is refused in the form, as is
submitting an empty input. Validation messages appear directly under the add
row; failures from the procedure itself appear at the top of the page.

## Deleting an app

The danger zone deletes the selected app permanently. All keys, channels, and
webhooks belonging to the app are removed, and connected clients are dropped
immediately.

To arm the **Delete app** button you must type the app's name exactly into the
confirmation field. The button stays disabled until the typed value matches and
while the delete is in flight.

Two details about the confirmation field:

- Switching to a different app clears it, so a half-typed confirmation for one
  app can never be submitted against another.
- If the delete fails, the field is cleared as well — the error is shown, and a
  retry has to be typed out again deliberately.

On success the app selection is cleared and the app list is refetched.

If your goal is to stop traffic rather than discard configuration, disable the
app instead. Disabling keeps the key and secret; deleting does not, and there
is no undo.

## Related

- [Authentication](/concepts/authentication) — how keys and short-lived tokens
  are issued and scoped
- [Telemetry](/platform/telemetry) — operational data emitted per tenant
