* refactor(auth): one signup path for form, temp, OIDC and team accounts
Signup steps (validate hook, phone/card forcing, bonus verdict, provisioning,
signup events) move from AuthController and OIDCService into SignupService.
Username rules, availability and generation move to util/username.ts, and
user-row + group + default-folder creation to provisionUser, which
TeamService and DefaultUserService now share.
Behaviour fixes: a provisioned team seat joins default_user_group like every
other account, and generated temp usernames skip names whose home path is
occupied.
* refactor(auth): one web-session start for password and OIDC sign-in
startWebSession creates the session with the request's IP, user agent, origin
and host and sets the session cookie. OIDC sign-ins used to create their
session without that metadata, so they showed up blank in the session list.
* refactor(auth): one confirmEmail for the code and link confirmation routes
Both routes now re-run the email checks, refuse an address another account
confirmed, strip it from other rows, promote the group and push
user.email_confirmed to the account's sockets (with the originating socket id
on the code route). The link route's full-table UPDATE clearing other
accounts' pending change-email requests is dropped: /change_email/confirm
already refuses an address a confirmed account owns.
* refactor(auth): build window.user once for whoami and sign-in
buildUserDetails and scrubSensitive move from the whoami extension into
util/userDetails.ts. /whoami calls them; sign-in responses now return the same
user-actor payload, scrubbed, so the login copy no longer ships the phone
number and a no-reload login gets oidc_only/otp/directories up front. Taskbar
resolution is best-effort on both.
* refactor(http): userProtected route option replaces AuthController's route walker copy
The user-protected gate is materialized from a userProtected RouteOption
(implies requireUserActor), so AuthController no longer re-implements the
decorator walker to wire it per instance; those routes and the session
routes are plain decorators now. AuthRequired also counts requireVerified
and userProtected.
* refactor(http): internalAuth route option and a shared bodyRecord
EventsController and PeerController each checked x-puter-internal-auth by
hand with different compares; an internalAuth RouteOption now picks the
secret from config and one constant-time gate checks it. ShareController and
EventsController share bodyRecord instead of private copies.
* fix(fs): cap legacy /delete at 500 paths per request
The bulk form resolved, ACL-checked and removed an unbounded paths[] list one
by one. It now refuses more than FS_BATCH_WRITE_MAX_ITEMS (500), the cap the
batch write routes already use, before touching any entry.
* refactor(controllers): user and subdomain writes and reads through their stores
AuthController's 2FA setup/enable/disable and recovery-code writes go through
UserStore.update instead of raw UPDATEs plus a manual invalidate, and
/readdir-subdomains pages SubdomainStore.listByUserId instead of an unbounded
SELECT; the response shape is unchanged.
* refactor(auth): note SignupService's call-time peers
* fix(auth): type userDetails' taskbar deps independently of TaskbarDeps.clients
- declare rate + concurrency limits on every route and driver that lacked one
- add acquireConcurrent for websocket connections and the DAV mount
- bucket AI models by identity key only; keep resold duplicates of any vendor
- skip recently-failed provider routes; cap the fallback chain at 3 attempts
- let full-access access tokens bind a worker to an app their own user owns
- cache resolved subscriptions so tiered limits don't add a round trip
* feat(database): add postgres database client
Adds the PostgreSQL database client, native bootstrap migration, SQL preparation helpers, and database config/factory wiring.\n\nRefs #3165.
* feat(database): make backend queries postgres-aware
Updates runtime SQL call sites for database-specific booleans, identifiers, insert-ignore, upserts, JSON extraction, intervals, and Postgres insert ids.\n\nRefs #3165.
* test(database): cover postgres client behavior
Adds unit coverage for SQL preparation, factory selection, write-result mapping, and transaction rollback/commit ordering, plus an env-gated PostgreSQL integration flow.\n\nRefs #3165.
* docs(self-hosting): document postgres database setup
Adds PostgreSQL configuration examples and migration path guidance for self-hosted deployments.\n\nRefs #3165.
* fix: harden postgres oidc tests
* fix(postgres): normalize query results and SQL prep
* fix(user): preserve normalized cache booleans
* test(postgres): run integration coverage with pgmock
* tests: add way to run all tests with postgres though slow
Also adding note that postgres is not in active use so might not work out the box
---------
Co-authored-by: Daniel Salazar <daniel.salazar@puter.com>
Covers each config-gated branch (client_libs_root, puterjs_root,
gui_assets_root, builtin_apps) using real temp directories so the
existsSync checks see real files instead of mocked module behavior.
Asserts both registration outcomes (which routes appear, on which
subdomains) and the file resolution rules for the puter.js / puter.dev.js
fallback.
Closes#2974