[data-reveal]{opacity:1!important;transform:none!important}
Security
Frontend

Security

[object Object]

The frontend server sits between the browser and the backend, and holds what the browser must never see: the access and refresh tokens, the session secret, the bootstrap credential and the modules' private options.

Credentials

  • The bootstrap credential (DMS_BOOTSTRAP_SECRET) is used only by the CLI's server-to-server requests for the frontend manifest and module archive, in the x-dms-bootstrap header. Browser traffic never sends or receives it. Pass it through the environment rather than --bootstrap-secret: a command line is visible to every process on the machine.
  • A discovered development credential is presented only to the backend that published it. Point -b at a staging or production host from inside a running project, and the local credential is withheld rather than sent there.
  • Generated files that hold secrets, the manifest cache and the private module options, are owner-only in an owner-only workspace. The development server refuses to serve them, and the modules' server code, whatever the query.

Sessions and cookies

  • The session lives in a sealed, HttpOnly cookie. The tokens stay on the server; the browser gets page props built by the sign-in module's publicSession.
  • DMS_SESSION_SECRET seals it: 32 characters or more, required by build and start, and kept across restarts.
  • start sets Secure cookies (DMS_COOKIE_SECURE=true), so the browser only sends them over HTTPS. dev does not, since it runs over HTTP.
  • Module cookies are sealed, scoped to the backend, HttpOnly, SameSite=Lax and Secure, and isolated per module. See Server routes.

Same-origin checks

A state-changing request that the server proxies with the session, or that reaches a module route, must carry the frontend's own Origin.

The exceptions are explicit:

ExceptionAuthentication boundary
A proxy prefix declared with auth: "none"Never sends the session.
A public endpointNever sends the session.
A module route that passes { sameOrigin: false }Authenticates its caller another way.

Behind a reverse proxy

DMS_TRUSTED_PROXY_HOPS is the number of reverse proxies in front of the server, counted from the right of X-Forwarded-For; it defaults to 0.

  • With 0, the server takes the client's address from the socket, and replaces any X-Forwarded-For the client sent.
  • Above 0, it trusts that many rightmost hops, and extends the client's X-Forwarded-For with the socket's address when it proxies.

Forwarding the client's country

DMS_COUNTRY_HEADER names the header a trusted proxy sets with the client's country:

  • The default is CF-IPCountry.
  • An empty value relays none.
  • The server relays it to the backend only when DMS_TRUSTED_PROXY_HOPS is above 0, like the client address.

Name the same header in the backend's auth.signInCountry.header.

Set DMS_TRUSTED_PROXY_HOPS to the exact number of proxies you run. A higher value lets a client choose the address the backend rate-limits and logs.

The development server

ajs dms dev listens on 127.0.0.1 unless HOST says otherwise, so only the machine it runs on reaches it. It serves module sources to Vite, but never the generated secrets (generated-server-options.json, .manifest-cache.json) or the modules' server code (dms.server.*, server/).

Trusting module code

A module's dms.server.ts runs in the frontend server's process, next to the session secret. Every route it declares can read and write the session, tokens included.

It is trusted code, as the module's backend half is. Only install a module whose server code you trust as much as the DMS's own.