# Web dashboard

The web dashboard is a Next.js app where you manage orgs, applications, environments, and secrets.
All encryption and decryption happens **in your browser** — the same envelope-encryption scheme
the CLI uses.

## Signing in

The dashboard supports two ways to authenticate:

- **Google / GitHub** via Stytch B2B (recommended). Requires a Stytch project (below).
- **Dev identity** — a local-only email form, active when the API runs with `AUTH_MODE=dev`.

### Sign in with Google or GitHub

Clicking **Continue with Google/GitHub** starts Stytch's B2B *discovery* OAuth flow: you
authenticate with the provider, then choose an existing organization or create a new one, and a
session is issued. seekrit provisions the matching org just-in-time on the API's first
authenticated request.

To enable these buttons, configure a Stytch B2B project once:

1. Create a **B2B** project at [stytch.com](https://stytch.com).
2. Under **OAuth**, enable **Google** and **GitHub**.
3. Under **Redirect URLs**, add `http://localhost:3000/auth/callback` as a **Discovery** URL (and
   your production URL later).
4. Put the keys in config:
   - `apps/web/.env.local` → `NEXT_PUBLIC_STYTCH_PUBLIC_TOKEN=public-token-test-…`
   - `apps/api/.dev.vars` → `STYTCH_SECRET=secret-test-…`
   - `apps/api/wrangler.jsonc` vars → `STYTCH_PROJECT_ID` and `STYTCH_API_URL`
     (`https://test.stytch.com` for the Test environment)

> **Note:** The web app receives only the Stytch **public** token. The secret key lives with the API worker, which uses it to verify sessions and resolve members. The browser never holds it.

## Key setup

The first time you sign in you'll be asked to create your encryption keys. The browser generates a
P-256 keypair and encrypts the private key with a passphrase you choose. Only your **public key**
and the **passphrase-encrypted** private key are uploaded.

> **Warning:** There is no passphrase reset. If you forget it, your encrypted data cannot be recovered. Store it in a password manager.

On later visits, the keyring starts **locked**. The first time you reveal or edit a secret in a
session, you'll be prompted to unlock it with your passphrase; it stays unlocked (in memory only)
until you lock it or reload.

## Managing secrets

- **Organizations** → **Applications** → **Environments** — create each from its list page.
  Creating an environment generates its data key in your browser and wraps it to your public key.
- On an environment page, the **Secrets** table lets you add, reveal, edit, and delete secrets.
  Values are encrypted on save and decrypted on reveal, locally.
- Secrets inherited from [composed groups](#groups) appear in the same table under an **inherited
  from groups** heading, greyed out and tagged with their source group. Click one to jump to the
  group environment it lives in. A secret you define here shadows an inherited one of the same name,
  so it's shown as your own (editable) row instead.
- The **Key access** panel (admins) shows who holds the environment key and lets you grant it to
  members or service tokens, or revoke it.
- The **Composed groups** panel (admins) layers shared [groups](#groups) beneath an environment's
  own secrets — see below.

## Groups

**Groups** are reusable secret bags shared across applications — a shared database cluster,
third-party API keys, anything more than one app needs. Manage them from the **Groups** entry in
the org sidebar.

- A group has its own **environments**, one per slug you want to share (e.g. `production`,
  `staging`). Each group environment holds secrets and key grants exactly like an application
  environment — same client-side crypto, same **Key access** panel.
- On an **application** environment's page, the **Composed groups** panel lets admins compose one or
  more groups. At resolve time the layers merge in order: composed groups first (a group lower in
  the list overrides one above it), then the environment's own secrets on top. Reorder with the
  arrows; remove with ✕.
- A group is matched into an app environment **by slug**: composing `shared-infra` into an app's
  `production` environment pulls in the group's `production` environment. Create the matching group
  environment before you rely on it.

> **Note:** Composition wires up *which* secrets layer together, not *who* can read them. Each principal — member or token — still needs its own key grant on every group environment it should decrypt. Minting a token (below) grants those automatically.

## Service tokens & audit

- **Service tokens** — mint machine credentials for CI and containers. Each token is **bound to one
  application environment**: pick the app and environment when minting, and the browser
  auto-grants the token that environment's key plus the keys of every group it composes (unwrapping
  each with your key and re-wrapping to the token). The token is shown once; copy it then. See
  [Service tokens](/docs/guides/service-tokens).
- **Audit trail** — every action in the org, append-only, with actor attribution.

## Troubleshooting sign-in

If the dashboard shows an error after sign-in, it will name the cause:

- **Session rejected (401)** — the API couldn't verify your session. Usually an expired session
  (sign in again) or a `STYTCH_PROJECT_ID`/secret mismatch on the API.
- **API unreachable** — the API worker isn't running or `NEXT_PUBLIC_SEEKRIT_API_URL` is wrong.

The API worker logs the underlying reason for verification failures.
