---
description: crit — proxy auth transport
alwaysApply: false
---

# Proxy Auth Transport Rules



## Rule 1: Both transport modes required

Every CLI command or browser UI action that calls a crit-web API must work in both modes:
- **Direct** (default): Go server makes HTTP requests with bearer token
- **Browser relay** (`proxy_auth: true`): Browser popup mediates the same API call through an authenticated session

When adding a new crit-web interaction:
1. Add the direct HTTP path in Go (share.go or relevant file)
2. Add a server endpoint that returns the payload for the popup relay (server.go)
3. Add a popup handler in `crit-web/assets/js/share_receiver/handlers.js` (note: the directory/route is named `share_receiver` / `/share-receiver` — this describes what the component *does* (receives share data), while `proxy_auth` describes *why* it's needed. Both names are correct at their level.)
4. Add the relay call in `web/app.js` gated on `proxy_auth`

## Rule 2: Relay is transport, not protocol

The popup relay must hit the **same crit-web API endpoints** with the **same payload shapes** as the direct path. No relay-specific endpoints on crit-web. The popup handlers are same-origin fetch proxies.

## Rule 3: Terminal CLI commands cannot use direct HTTP when proxy_auth is on

When `proxy_auth: true` (global config), crit-web sits behind an SSO reverse proxy. The terminal cannot complete that auth flow — only the browser can (via the `/share-receiver` popup relay).

**Terminal subcommands** that HTTP-call crit-web directly (today: `crit share`, `crit fetch`, `crit unpublish`) must call `checkProxyAuthCLIAllowed("crit <cmd>")` at the top of their `Run*` entrypoint and exit with the shared error message. Do not attempt the network call.

**Browser UI actions** (Share / Pull / Unpublish / Re-share buttons in the review page) must still work: implement both transports per Rule 1 — direct when `proxy_auth` is false, popup relay when true (`web/crit-share.js` + crit-web `share_receiver/handlers.js`).

Direct (non-proxy_auth) browser actions must go through the **local Go server**, never `fetch(shareURL + …)` cross-origin:

| Action    | Local endpoint                          |
|-----------|-----------------------------------------|
| Share     | `POST /api/share`                       |
| Pull      | `POST /api/share/pull`                  |
| Re-share  | `POST /api/share/reshare`               |
| Unpublish | `DELETE /api/share-url`                 |

(The Go handlers attach the bearer token and talk to crit-web. Cross-origin browser fetches fail CORS on selfhosted+OAuth instances because preflight has no `Authorization`, and even with CORS fixed the browser never sends the token.)

The `share-transport` Playwright project (`test/e2e/tests/share-transport.sharetransport.spec.ts`) drives these three actions against a stub crit-web on a different origin and fails if the page issues any request to it, so a regression to cross-origin fetches is caught in CI. Extend that spec when you add a browser action that talks to crit-web.

When adding a **new** crit-web interaction, decide which surface owns it:
- **Browser-only** (like today's share/pull/unpublish behind SSO): block the terminal path with `checkProxyAuthCLIAllowed`; add relay handler + frontend branch.
- **Terminal-only** (rare): document that it won't work behind SSO, or don't add it.
- **Both**: direct Go HTTP path + browser relay path; terminal path still blocked when `proxy_auth` is on unless you have a non-HTTP auth story.

Integration tests that spawn the `crit` binary must isolate config — use `runCritCmd` / `runCritCmdWithHome` with a temp `HOME`, not the developer's real `~/.crit.config.json`.
