Files
pnpm/pnpr/docs/auth-backends.md
Zoltan Kochan 5d366c3f27 refactor(pnpr)!: apply PHILOSOPHY.md and consolidate pre-1.0 shims (#17360)
Extend PHILOSOPHY.md, pnpr/AGENTS.md, REVIEW_GUIDE.md, .coderabbit.yaml, and
.pr_agent.toml so the repository philosophy applies to pnpr and establishes
that pnpr is pre-1.0 on the alpha prerelease lane (experimental per
PHILOSOPHY.md), consolidating storage layouts, internal record formats,
configuration keys, and CLI flags in place before 1.0 without
backward-compatibility fallbacks, aliases, or migration commands between alpha
builds.

- Remove pnpr upgrade-storage and Command::UpgradeStorage.
- Remove legacy .pnpr-journal recovery path and journal manifest serde aliases
  (packument_file, tarballs).
- Remove StoredDerivedTar::Legacy and DerivedTar::scanned in .tar-integrity
  records.
- Remove the redundant /v1 segment from compiler_cache_path.
- Remove CLI subcommand and flag aliases (pnpr config-check,
  --packument-ttl-secs, --no-check-hashes, --min-age-secs, --max-age-secs) and
  the PNPR_PACKUMENT_TTL_SECS env fallback.
- Remove YAML configuration snake_case, *_secs, maxage, and backend.postgresql
  serde aliases, standardizing on camelCase.
2026-10-26 09:28:07 +01:00

4.5 KiB

id, title
id title
auth-backends Auth backends (shared SQL)

Auth state (the registered users and their bearer tokens) is per-instance disk state. By default users live in an htpasswd file and tokens in a local SQLite database (see auth), so two pnpr replicas don't see each other's accounts.

Adding a backend: block moves both into one shared SQL database, so several stateless replicas share a consistent set of logins and tokens. This is the auth half of running pnpr horizontally scaled. Only one backend may be selected in a config file.

Database drivers are Cargo-feature gated:

Backend Config key Cargo feature
libsql / Turso backend.libsql backend-libsql (enabled by default)
PostgreSQL backend.postgres backend-postgres
MySQL-compatible backend.mysql backend-mysql

For PostgreSQL or MySQL support, build pnpr with the matching Cargo feature, for example cargo build -p pnpr --features backend-postgres.

:::tip

Token lookups happen on the request hot path, so the database should be low-latency from the server.

:::

libsql / Turso

storage: ./storage

backend:
  libsql:
    # libsql/Turso database URL. `libsql://…` for Turso, or
    # `http://127.0.0.1:8080` for a local `sqld`.
    url: ${PNPR_LIBSQL_URL}
    # Bearer token for the database. Omit for an unauthenticated local `sqld`.
    authToken: ${PNPR_LIBSQL_TOKEN}
Key Required Description
url yes Database URL: libsql://<db>.turso.io (Turso) or http://<host>:<port> (self-hosted sqld).
authToken no Bearer token for the database. Omit for an unauthenticated local sqld. pnpr sends it only over https:// or libsql://, or over http:// to a loopback host, and refuses to start otherwise.
replicaPath no Path to a local embedded replica. When set, reads (token lookups) hit this local file instead of a network round-trip; writes still go to the primary. Absent ⇒ every read is a remote query.
syncInterval no How often the embedded replica pulls from the primary. Accepts an interval string (such as 60s or 1m) or integer seconds. Only meaningful with replicaPath; bounds how stale a read can be (token-revocation lag). 0 disables background sync. Defaults to 60s.
maxConnections no Most auth database operations pnpr runs at once, each on a connection of its own. Defaults to 10.

Token lookups happen on the request hot path, so for a remote primary such as Turso Cloud or a self-hosted sqld, set replicaPath to serve reads from a local replica. pnpr uses the sync protocol the primary offers, so the same setting works with Turso Cloud and with a self-hosted sqld.

backend:
  libsql:
    url: ${PNPR_LIBSQL_URL}
    authToken: ${PNPR_LIBSQL_TOKEN}
    replicaPath: ./auth-replica.db
    syncInterval: 60s

The trade-off is read freshness: an embedded replica reflects another replica's writes (a token issued or revoked elsewhere) only after the next background sync, so a lower positive syncInterval means less revocation lag. Omit replicaPath to always read the primary directly.

PostgreSQL

backend:
  postgres:
    url: ${PNPR_POSTGRES_URL}
    maxConnections: 16
    timeout: 30s
    startupTimeout: 5m

MySQL

backend:
  mysql:
    url: ${PNPR_MYSQL_URL}
    maxConnections: 16
    timeout: 30s
    startupTimeout: 5m
Key Required Description
url yes Driver connection URL, such as postgres://user:pass@host/db or mysql://user:pass@host/db.
maxConnections no Maximum connections in the backend pool. Omit to use the driver's default.
timeout no Request-path auth database deadline. Defaults to 30s.
startupTimeout no Startup connection and schema setup deadline. Defaults to 5m.

When the backend: block is absent, the auth.htpasswd / auth.tokens settings apply. Without auth.htpasswd.file, accounts live in memory, and so do tokens unless auth.tokens.file is set. With a backend: block, auth.htpasswd.file and auth.tokens.file are ignored, and only the auth.htpasswd.maxUsers registration cap is read. Omitted maxUsers and maxUsers: -1 both disable self-registration; set a non-negative cap to let new users register.

Extensibility model

Custom user and token backends are compiled into pnpr. There is no plugin runtime.