
# Enterprise Setup & White-Label

A self-hosted ContextNest **Community** server can be run as your organization's own governed knowledge surface: your sign-in, your domain, your logo, and PromptOwl's login kept out of the way. This page covers the enterprise-relevant knobs the server actually exposes — SSO, sign-in gating, and branding — and is honest about where "white-label" today means *your logo and your domain* rather than a full re-skin.

Every setting below is an environment variable on the Community server. The auth and branding settings are **also editable at runtime from the admin UI** (Settings → General / Single sign-on), so setting them in the environment is optional — it's for operators who prefer config-as-code. Configure them once and hand your users a login page that looks and behaves like yours.

## Single sign-on (OIDC)

ContextNest speaks generic OpenID Connect, so it works with Microsoft Entra ID, Google, Okta, Keycloak, or any spec-compliant issuer. The server runs a standard authorization-code flow with PKCE (`GET /auth/oidc/login` → your IdP → `GET /auth/oidc/callback`).

| Variable | Default | Purpose |
| --- | --- | --- |
| `OIDC_ENABLED` | `false` | Turn on OIDC sign-in. The login-page SSO button appears only once the issuer, client ID, and client secret are all set. |
| `OIDC_ISSUER` | — | Issuer URL — **`https://` only**, must serve `<issuer>/.well-known/openid-configuration`. Entra: `https://login.microsoftonline.com/<tenant-id>/v2.0`; Google: `https://accounts.google.com`. |
| `OIDC_CLIENT_ID` | — | Application (client) ID from your IdP app registration. |
| `OIDC_CLIENT_SECRET` | — | Client secret. Write-only on the settings API — it is never read back, only reported as set/unset. |
| `OIDC_ALLOWED_DOMAINS` | _(any)_ | Comma-separated email-domain allowlist, e.g. `acme.com, contractors.acme.com`. **Empty allows any domain the IdP asserts** — set it (or turn auto-provision off) with a multi-tenant issuer. |
| `OIDC_AUTO_PROVISION` | `true` | Create a user automatically on first successful sign-in. Set `false` so only already-invited/registered emails may sign in (others bounce `not_invited`). |
| `OIDC_DEPARTMENT_TAGGING` | `false` | Auto-tag documents created by a user with their directory department (`dept:<slug>`) — read from the OIDC `department` claim, applied on create only. |

Register this redirect URI in your IdP app registration:

```
https://<your-server>/auth/oidc/callback
```

Set **`PUBLIC_BASE_URL`** to your server's canonical external URL (e.g. `https://nest.acme.com`) whenever OIDC is enabled. It pins the redirect URI instead of deriving it from the incoming request's `Host` header — closing off a `Host`-header spoofing vector and making the callback URL predictable for your IdP allowlist.

If the IdP advertises an `end_session_endpoint` (Entra, Okta, Keycloak), the server can drive **single logout**; where it doesn't, the local session is cleared and the user is bounced back to re-authenticate.

## Choosing who can sign in

Two independent gates control the two built-in sign-in methods, so you can present exactly the front door you want — for example **OIDC only**, with both PromptOwl and email/password turned off.

| Variable | Values | Effect |
| --- | --- | --- |
| `PROMPTOWL_SIGN_IN_GATE` | `open` · `admin-only` · `disabled` | Controls "Sign in with PromptOwl". `disabled` removes it entirely — the enterprise default when you want a fully self-contained login. `admin-only` leaves it for just the license owner (via `?admin=1`). |
| `MANUAL_SIGN_IN` | `open` · `invite-only` · `disabled` | Controls email + password. `invite-only` lets existing/invited users log in but refuses brand-new self-registration (the admin provisions accounts and shares the password); `disabled` turns email/password off entirely. |
| `AUTH_MODE` | `key` · `open` | API access mode. `key` (default) requires a `cnst_*` API key on every request — use it for any multi-user or internet-facing deployment. `open` requires no auth and should only be used on a trusted single-user LAN/VPN. |

The server refuses a configuration that would lock everyone out — you cannot set both `PROMPTOWL_SIGN_IN_GATE=disabled` and `MANUAL_SIGN_IN=disabled` unless OIDC is on to provide a way in.

**To hide PromptOwl entirely and run SSO-only:**

```bash
OIDC_ENABLED=true
OIDC_ISSUER=https://login.microsoftonline.com/<tenant-id>/v2.0
OIDC_CLIENT_ID=...
OIDC_CLIENT_SECRET=...
PROMPTOWL_SIGN_IN_GATE=disabled
MANUAL_SIGN_IN=disabled
PUBLIC_BASE_URL=https://nest.acme.com
```

## Branding

| Variable | Purpose |
| --- | --- |
| `LOGO_URL` | Custom logo shown in the UI header and on the login screen. Must start with `https://`, `http://`, or `data:image/`; other schemes (`file://`, relative paths, `javascript:`) are rejected with a warning and the bundled ContextNest icon is used instead. |
| `PUBLIC_BASE_URL` | Your server's canonical external URL — this is how the nest lives on **your** domain (you terminate TLS for `nest.acme.com` at your proxy and point it at the server). |

**Scope of white-label today, stated plainly:** branding is a **custom logo plus your own domain**. Setting `LOGO_URL` swaps the header/login logo; the "ContextNest" wordmark and the "Community" badge are **not** replaced, and there is no built-in custom color/theme palette. If you need full removal of ContextNest wordmarks or custom theming, treat that as a gap to raise rather than an existing toggle.

## Directory & team management

- **OIDC department auto-tagging** (`OIDC_DEPARTMENT_TAGGING`) stamps a `dept:<slug>` tag on documents as users create them, from the IdP's `department` claim — a low-effort way to make an org chart queryable inside the nest.
- **Import teams from PromptOwl** (`PROMPTOWL_TEAMS_ENABLED`, off by default) lets users who signed in with PromptOwl pull their PromptOwl teams in as local teams; when off, those routes 404 and the UI hides the panel.
- Governance is enforced through the **review lifecycle, stewards, grants, and teams** described on the [Governance](https://nest.promptowl.ai/d/promptowl-documents/platform/governance/governance-stewardship) page — the substance of "enterprise control" over what agents can read.

## Governance-event notifications

Route review-requested / approved / rejected and nest-shared events to your channels (optional; empty/unset = off):

- `SLACK_WEBHOOK_URL` — post governance events to a Slack channel via an incoming webhook (HTTPS only).
- `SMTP_URL` + `NOTIFY_EMAIL_FROM` + `NOTIFY_EMAIL_TO` — send the same events over SMTP.
- `NOTIFY_DEBOUNCE_MS` — buffer a burst of events (e.g. sharing a nest with a whole team) into one digest message.

## Data & storage

For a production enterprise deployment, back the server with Postgres / Cloud SQL rather than the embedded default, and set a durable storage root (`NEST_STORAGE_ROOT`, or GCS) for nest content. Tune the DB pool and TLS with `DB_POOL_MAX` / `DB_SSL` / `DB_SSL_CA`. See the server's `CONFIGURATION.md` for the full storage and database reference.

## Related

- [Governance](https://nest.promptowl.ai/d/promptowl-documents/platform/governance/governance-stewardship) — review lifecycle, stewards, grants, teams
- [Hosted Nest](https://nest.promptowl.ai/d/promptowl-documents/platform/hosted-nest/hosted-nest) — what a Community server adds over a local vault
- [Configuration](https://nest.promptowl.ai/d/promptowl-documents/protocol/configuration) — client-side (`ctx`) configuration
