Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
VITE_PROOFLINE_API_BASE_URL=http://127.0.0.1:8080
VITE_PROOFLINE_API_MODE=mock
VITE_PROOFLINE_AUTH_MODE=bearer
VITE_PROOFLINE_SESSION_STORAGE=memory
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## Unreleased

- Implemented an explicit browser-cookie auth client mode with in-memory CSRF
handling.
- Enabled live owned-incident listing against authenticated
`GET /v1/incidents` responses.
- Added the reusable documentation and prompt review workflow and refreshed
Expand Down
31 changes: 20 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,16 @@ Use live mode only against a reviewed local backend:

```text
VITE_PROOFLINE_API_MODE=live
VITE_PROOFLINE_AUTH_MODE=bearer
VITE_PROOFLINE_API_BASE_URL=http://127.0.0.1:8080
```

For reviewed local browser-cookie auth testing, also set:

```text
VITE_PROOFLINE_AUTH_MODE=cookie
```

## Development

```bash
Expand Down Expand Up @@ -87,7 +94,7 @@ The current bootstrap includes:
- authenticated app shell
- conservative session state with memory-first token storage
- optional local-storage session persistence for local development only
- documented browser-cookie auth and CSRF client-mode planning boundary
- explicit bearer-token and browser-cookie auth client modes
- incident list UI backed by mock data in prototype mode and authenticated
owner-scoped `GET /v1/incidents` responses in live mode
- incident detail metadata UI
Expand All @@ -114,8 +121,8 @@ Planned account portal work includes:
- clear account-disabled, payment-required, expired-session, unauthorized, and forbidden states
- browser-safe API error handling
- browser token-storage review and hardening
- browser-cookie auth mode and CSRF handling, once server/deployment review
approves credentialed CORS for exact origins
- deployment review for browser-cookie auth, credentialed CORS, and exact
reviewed origins

Payment-gated registration must be implemented as a backend-supported account
lifecycle, not just a frontend form. The current server paid-registration mode
Expand Down Expand Up @@ -255,11 +262,11 @@ do not imply production readiness or public `/v1` API readiness.

## API Boundary

The server currently confirms bearer session auth, `POST /v1/auth/login`,
`POST /v1/auth/register`, `POST /v1/auth/email/verify`,
`POST /v1/auth/logout`, `GET /v1/account`, owner-scoped incident list/detail
routes, contact public-key routes, sharing-grant routes, and wrapped-key
routes. Current `open-proofline/server` documents authenticated
The server currently confirms bearer session auth, browser-cookie auth routes,
`POST /v1/auth/register`, `POST /v1/auth/email/verify`, `GET /v1/account`,
owner-scoped incident list/detail routes, contact public-key routes,
sharing-grant routes, and wrapped-key routes. Current `open-proofline/server`
documents authenticated
`GET /v1/incidents`, and this client parses that response shape in live mode.
Mock mode uses prototype incident records only and must not be treated as
backend truth.
Expand All @@ -285,9 +292,11 @@ private deployment details, or user safety data.

## Session Storage

Session tokens are kept in memory by default. A local-storage adapter exists for
developer convenience only behind `VITE_PROOFLINE_SESSION_STORAGE=localStorage`.
Browser token persistence must be reviewed before any production use.
Bearer session tokens are kept in memory by default. A local-storage adapter
exists for developer convenience only behind
`VITE_PROOFLINE_SESSION_STORAGE=localStorage`. Browser token persistence must
be reviewed before any production use. Cookie-mode sessions do not store bearer
tokens; the browser session cookie is HttpOnly and managed by the server.

## Catalyst And Tailwind

Expand Down
4 changes: 2 additions & 2 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ These docs describe the current experimental web-client prototype. The backend
source of truth remains `open-proofline/server`.

- [Architecture](architecture.md)
- [API client](api-client.md): current route contracts and browser-cookie auth
planning boundary.
- [API client](api-client.md): current route contracts and bearer/cookie auth
client modes.
- [Security model](security-model.md): implemented controls, non-controls, and
browser auth review areas.
- [Browser security headers](browser-security-headers.md): static-host header
Expand Down
42 changes: 25 additions & 17 deletions docs/api-client.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,14 @@ prototype data so browser smoke tests do not require a live backend.

`VITE_PROOFLINE_API_MODE=live` calls the current server API.

Live mode supports two explicit auth modes:

- `VITE_PROOFLINE_AUTH_MODE=bearer` uses bearer-session login/logout and omits
browser credentials from API requests.
- `VITE_PROOFLINE_AUTH_MODE=cookie` uses the browser-cookie auth routes,
includes browser credentials only for cookie-authenticated requests, and
never attaches an `Authorization` header.

## Confirmed Backend Routes

From current `open-proofline/server` docs and route registration:
Expand Down Expand Up @@ -91,22 +99,22 @@ Mock mode returns explicit prototype-only responses for these methods; it does
not create accounts, send email, verify real tokens, or model payment/billing
state.

## Browser Cookie Auth And CSRF Planning Boundary
## Browser Cookie Auth And CSRF

The current frontend implementation uses bearer-session auth in live mode:
`POST /v1/auth/login` returns a bearer token, authenticated requests attach
`Authorization: Bearer ...`, and session storage is memory-first with optional
local-storage persistence for local development only.
Bearer mode remains the default live mode. `POST /v1/auth/login` returns a
bearer token, authenticated bearer-mode requests attach
`Authorization: Bearer ...`, and bearer session storage is memory-first with
optional local-storage persistence for local development only. Bearer-mode
fetches use `credentials: "omit"` so browser session cookies are not relied on.

`open-proofline/server` also documents browser-cookie auth routes for a future
web-client mode:
Cookie mode is selected explicitly with `VITE_PROOFLINE_AUTH_MODE=cookie` and
uses the server browser-cookie auth routes:

- `POST /v1/auth/web/login`
- `POST /v1/auth/web/logout`
- `GET /v1/auth/web/csrf`

That mode is not implemented in this client yet. When it is implemented, the
API client must choose one credential mode per live client instance:
The API client chooses one credential mode per live client instance:

- bearer mode: call the existing bearer login/logout routes and never send
`credentials: "include"` for session cookies;
Expand All @@ -116,26 +124,26 @@ API client must choose one credential mode per live client instance:

The modes must not be mixed for the same request. Current server behavior
rejects requests that include both bearer credentials and a browser session
cookie with `400 ambiguous_credentials`; tests for a cookie-mode implementation
should assert that authenticated requests cannot add both.
cookie with `400 ambiguous_credentials`; the client treats that as a local
invariant and refuses to send bearer tokens from cookie-mode authenticated
requests.

Cookie-mode CSRF handling should be explicit in the client contract:
Cookie-mode CSRF handling is explicit in the client contract:

- fetch the CSRF token from `GET /v1/auth/web/csrf` after a successful cookie
login and before the first unsafe cookie-authenticated request;
- cache the token in memory only, scoped to the active browser session;
- attach the returned header name, defaulting to `X-CSRF-Token` per current
server docs, to unsafe methods such as `POST` and `PATCH`;
- refresh the token after login, after a `403 csrf_required`, and after any
auth/session reset;
- refresh the token after login, after a `403 csrf_required`, and before unsafe
cookie-authenticated requests when no in-memory CSRF token is available;
- clear the cached token on logout and when account/session state is cleared.

Credentialed CORS is a deployment boundary, not a frontend-only switch. A
cookie-mode client must be used only with exact reviewed origins configured in
`open-proofline/server`; wildcard origins are not acceptable for credentialed
requests. Browser tests should cover web login, CSRF fetch, unsafe request
header attachment, logout cleanup, and failure behavior when the CSRF token is
missing or rejected.
requests. Browser tests cover web login, CSRF fetch, unsafe request header
attachment, logout cleanup, and rejected CSRF refresh behavior.

## Logging Boundary

Expand Down
6 changes: 3 additions & 3 deletions docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ flowchart LR

- The app handles account login, public registration, email verification, and
incident metadata review.
- The current live API client uses bearer-token auth. Browser-cookie auth and
CSRF handling remain a documented future client-mode boundary, not an
implemented runtime mode.
- The live API client supports explicit bearer-token and browser-cookie auth
modes. Cookie mode uses server-managed HttpOnly cookies, in-memory CSRF
tokens, and `credentials: "include"` only for cookie-authenticated requests.
- The app does not record media.
- The app does not decrypt chunks or unwrap wrapped keys.
- The app does not export playable media.
Expand Down
22 changes: 11 additions & 11 deletions docs/browser-security-headers.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ approval. Backend behavior and public API readiness remain governed by
requires separate server, deployment, abuse-control, credential-storage, CSRF,
logging, and operations review.

If a future web-client mode uses the server browser-session cookie routes,
static hosting review must also cover credentialed CORS. The API origin must be
an exact reviewed origin configured in `open-proofline/server`; wildcard
origins are not acceptable for credentialed requests.
If the web client uses the server browser-session cookie mode, static hosting
review must also cover credentialed CORS. The API origin must be an exact
reviewed origin configured in `open-proofline/server`; wildcard origins are not
acceptable for credentialed requests.

## Recommended Starting Set

Expand Down Expand Up @@ -63,11 +63,11 @@ readiness than the server docs and deployment review support.

### Credentialed CORS And CSRF

The current implementation uses bearer-token live auth and does not implement
browser-cookie auth. If browser-cookie auth is added later, the frontend must
send `credentials: "include"` only to the reviewed API origin, must not attach
an `Authorization` header in cookie mode, and must attach the server-provided
CSRF header to unsafe cookie-authenticated requests.
The current implementation uses bearer-token live auth by default and supports
an explicit browser-cookie auth mode. Cookie mode sends
`credentials: "include"` only to the reviewed API origin, does not attach an
`Authorization` header, and attaches the server-provided CSRF header to unsafe
cookie-authenticated requests.

Static headers cannot make credentialed CORS safe by themselves. Server
configuration must use exact allowed origins, secure cookie settings for public
Expand Down Expand Up @@ -137,8 +137,8 @@ for HTTPS-only access.

- CSP names only the static origin and reviewed API origin.
- Credentialed CORS, if used, is limited to exact reviewed origins and not `*`.
- Cookie-auth requests, if implemented, do not also attach bearer credentials.
- Unsafe cookie-auth requests, if implemented, attach the reviewed CSRF header.
- Cookie-auth requests do not also attach bearer credentials.
- Unsafe cookie-auth requests attach the reviewed CSRF header.
- No public edge routes private admin surfaces such as `/v1/admin/...`.
- `nosniff`, referrer policy, permissions policy, and frame restrictions are
present on the static app.
Expand Down
11 changes: 8 additions & 3 deletions docs/development.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,16 @@ does not require a live backend for the bootstrap smoke test.
```text
VITE_PROOFLINE_API_BASE_URL=http://127.0.0.1:8080
VITE_PROOFLINE_API_MODE=mock
VITE_PROOFLINE_AUTH_MODE=bearer
VITE_PROOFLINE_SESSION_STORAGE=memory
```

Use `VITE_PROOFLINE_API_MODE=live` only when a local backend is running and the
route assumptions have been checked against `open-proofline/server/docs/api.md`.
The current live client uses bearer-token auth. There is no browser-cookie auth
environment switch yet; do not add one without updating the API client contract,
CSRF handling, tests, and deployment guidance together.
The default live auth mode is bearer-token auth. For local browser-cookie auth
testing, use `VITE_PROOFLINE_AUTH_MODE=cookie` only with a backend configured
for reviewed local origins, for example `SAFE_WEB_AUTH_ENABLED=true`,
`SAFE_WEB_ALLOWED_ORIGINS=http://127.0.0.1:5173`, a non-`__Host-` local cookie
name, and `SAFE_WEB_SESSION_COOKIE_SECURE=false`. Production cookie mode still
requires HTTPS, exact allowed origins, secure cookies, CSRF review, and public
API deployment review in `open-proofline/server`.
29 changes: 17 additions & 12 deletions docs/security-model.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ This web client is experimental and not production-ready.
- Session tokens are kept in memory by default.
- Optional local-storage session persistence is behind
`VITE_PROOFLINE_SESSION_STORAGE=localStorage` for local development only.
- Browser-cookie auth mode stores session state in an HttpOnly server cookie
and keeps CSRF tokens in API-client memory only.
- Expired or malformed loaded sessions are cleared before authenticating the UI.
- Loaded sessions are cleared when the configured API mode or auth mode no
longer matches the stored session metadata.
- API responses are parsed with Zod before use where route shapes are known.
- UI states avoid showing raw tokens, Authorization headers, request bodies,
plaintext, raw keys, wrapped-key ciphertext, stored paths, or object keys.
Expand All @@ -33,26 +37,27 @@ persisted in browser storage, screenshotted, copied into public issue drafts,
included in analytics, or exposed in UI beyond the transient browser URL
fragment needed to complete verification.

## Browser Cookie Auth And CSRF Planning Boundary
## Browser Cookie Auth And CSRF

The implemented live client remains bearer-token based. A future browser-cookie
auth mode must be a separate client mode, not an additive flag on top of bearer
auth. In that mode, authenticated requests would use
`credentials: "include"` with the reviewed API origin and must not attach an
`Authorization` header. Bearer mode must not rely on browser session cookies.
The implemented live client supports bearer-token auth and explicit
browser-cookie auth mode. Cookie auth is a separate client mode, not an
additive flag on top of bearer auth. In that mode, authenticated requests use
`credentials: "include"` with the reviewed API origin and do not attach an
`Authorization` header. Bearer mode uses `credentials: "omit"` and must not
rely on browser session cookies.

Current `open-proofline/server` behavior rejects mixed bearer and browser-cookie
credentials with `400 ambiguous_credentials`. The frontend must treat that as a
security invariant: a request builder should make the credential mode
unambiguous before the request is sent, and tests should verify that both
credential types cannot be attached together.

Cookie-authenticated unsafe requests require a session-bound CSRF header. A
future implementation should fetch the token from `GET /v1/auth/web/csrf`,
store it in memory only, attach the returned header name to unsafe methods, and
clear it on logout or session reset. Missing or rejected CSRF tokens should
produce a controlled error state and a token refresh attempt where appropriate,
not a fallback to bearer credentials.
Cookie-authenticated unsafe requests require a session-bound CSRF header. The
client fetches the token from `GET /v1/auth/web/csrf`, stores it in memory only,
attaches the returned header name to unsafe methods, refreshes after
`403 csrf_required`, and clears it on logout or session reset. Missing or
rejected CSRF tokens produce controlled request failures or token refreshes, not
a fallback to bearer credentials.

Credentialed CORS and cookie attributes are deployment-sensitive server
configuration. The web client documentation may describe the required
Expand Down
21 changes: 10 additions & 11 deletions docs/threat-model.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@ in `open-proofline/server`.
## Assets

- Opaque bearer session tokens returned by the server.
- Future browser session cookies, if cookie auth mode is implemented.
- Future CSRF tokens for cookie-authenticated unsafe requests, if cookie auth
mode is implemented.
- Browser session cookies when cookie auth mode is enabled.
- CSRF tokens for cookie-authenticated unsafe requests.
- Raw email-verification tokens carried in verification URL fragments.
- Account metadata visible to the authenticated user.
- Incident, stream, chunk, contact public-key, sharing-grant, and wrapped-key
Expand All @@ -20,8 +19,8 @@ in `open-proofline/server`.
- Browser JavaScript is not trusted with raw media keys in this prototype.
- The backend remains authoritative for authorization.
- Registration availability and account activation are backend decisions.
- Browser-cookie auth, credentialed CORS, cookie attributes, and CSRF header
names remain server/deployment decisions until a client mode is implemented.
- Credentialed CORS, cookie attributes, and CSRF header names remain
server/deployment decisions.
- Bearer-token auth and browser-cookie auth must remain mutually exclusive for
a given authenticated request.
- Catalyst components are app-internal UI source, not a redistributed kit.
Expand All @@ -35,9 +34,9 @@ in `open-proofline/server`.
debugging tools, copied issue text, or analytics if handled carelessly.
- Registration UI wording could expose account-existence state if it diverges
from the server's generic verification-required response.
- A future cookie-auth mode could accidentally mix bearer and cookie
credentials, triggering server rejection and weakening client-side reasoning
about which credential protects the request.
- Cookie-auth mode could accidentally mix bearer and cookie credentials,
triggering server rejection and weakening client-side reasoning about which
credential protects the request.
- Missing, stale, logged, or over-persisted CSRF tokens could break unsafe
cookie-authenticated requests or expand the effect of XSS.
- Credentialed CORS configured with broad or unreviewed origins could expose
Expand All @@ -50,6 +49,6 @@ in `open-proofline/server`.
## Out Of Scope

Recording, decryption, key escrow, break-glass access, trusted-contact
decryption, browser-cookie auth implementation, payment processing,
public-production account portal claims, emergency notifications, and playable
media export are out of scope until explicitly designed and reviewed.
decryption, payment processing, public-production account portal claims,
emergency notifications, and playable media export are out of scope until
explicitly designed and reviewed.
Loading