# Your Redweb application

Requirements: Node.js 18 or newer and npm for the realtime, chat, site, socket and http-ws templates; the dashboard template requires Node.js 22.13+ for native SQLite. Use a currently supported Node.js release in production.

For an unreleased checkout or tarball, first run `npm install --save-exact TARBALL`, replacing `TARBALL` with the absolute path to the same tested Redweb tarball used to generate this app (quote paths containing spaces). This installs the matching package and its published client dependency. Do not substitute an older registry release or `latest`. Published Redweb releases can use the installation command below directly.

```sh
npm install
npm test
npm run dev
```

HTTP starters open at http://localhost:8181; the authenticated dashboard uses http://127.0.0.1:8181/login and requires account provisioning described below. Set the `PORT` environment variable to change the listener.
`npm test` builds and runs real HTTP/WebSocket integration tests on an ephemeral loopback port. No mocks or external service are needed.
`npm run test:coverage` runs the same tests with application coverage mapped back to TypeScript. Reports are written to the ignored `coverage/` directory; this is separate from Redweb library coverage. TypeScript-generated decorator accessors can appear in function counts even when the framework does not call them. The report exposes remaining gaps; it does not certify complete application coverage. Source maps are generated during the build for diagnostics and coverage, but no coverage collector is loaded by `npm start`.

## Development and production

Edit `src/app.tsx`. `npm run dev` watches TypeScript, TSX, CSS, HTML, and the root TypeScript configuration,
then rebuilds and restarts the server. A type error stops startup until you fix it. On direct localhost access,
HTML pages refresh automatically when a new server revision is ready. If edits were detected, a keyboard-accessible
notice keeps the old document until you choose **Reload and discard drafts**. This is a conservative edit guard,
not autosave or browser hot-module replacement: restarts reset in-memory state and old socket sessions.
The generated development command sets `REDWEB_DEV_REFRESH=1`; `development: { refresh: false }` overrides it.
The refresh feature is refused under `NODE_ENV=production`, applies only to served HTML (not raw sockets or static exports),
and creates no local/session-storage copy of form contents. Use direct `localhost`, `127.x.x.x`, or `[::1]` access;
custom hostnames, tunnels and proxy-forwarded origins are not supported by this development helper.
`npm run build` checks types and copies CSS/HTML beside the compiled classes in `dist/`.
Run `npm start` to serve the compiled app. For deployment, build first, ship `dist/`, `package.json`, and the lockfile,
then install runtime dependencies with `npm ci --omit=dev`. The application does not require TypeScript or `src/` at runtime.

The standalone entrypoint calls `app.run()` on a `defineApp` definition. Importing it opens no listener and installs no process handlers. Redweb owns HTTP and WebSocket startup together, including signal handling and bounded shutdown; no generated `run-app.ts` helper is needed. Configure `startupTimeoutMs` and `shutdownTimeoutMs` on the definition (both default to five seconds). App-wide service classes acquire resources in `onInit(app, signal)` and release them in `onShutdown()`; the dashboard uses this for its auth/database resources. The dashboard's factory configures an independent private workspace but does not start it.

Repeated signals do not bypass cleanup. Failed process-owned cleanup sets a failure exit status and retains a deadline for surviving handles. Explicit `shutdown()` rejects on cleanup failures without terminating its caller. Deadlines cannot preempt synchronous code blocking Node's event loop or arbitrary operations that ignore cancellation. Tests can define an independent application from `{ ...app.options, port: 0, signals: false }` and await `run()`; app-owned state is isolated, but objects deliberately captured by page class closures remain shared unless a new class/room is created.

The shipped lifecycle tests exercise actual processes, HTTP/TCP/WebSocket peers and timers. Linux uses actual OS signals; Windows tests explicitly emit signal events inside the process because killing a Windows child does not exercise graceful POSIX signal delivery. This is not a claim that Windows console/service managers forward the same signals. Deploy with a supervisor that forwards the supported termination signal and allows longer than the configured cleanup deadline.

For public deployment, configure HTTPS/WSS at your Node server or reverse proxy, authentication, trusted origins,
and application-specific rate limits. These starters are demonstrations, not a hosted identity or database service.
Never commit secrets; `.env` is ignored but is not loaded automatically.

`npx --no-install redweb doctor --json` reports configuration problems without changing your files.
## Dependency security

This starter includes an application-root npm override for Express 4's `qs`
dependency, selecting patched `qs@6.16.0`. Keep the override when merging this
starter into an existing application, refresh its lockfile and run `npm audit`.
Overrides in Redweb's own package do not apply to installed consumers. Recheck
upstream Express/body-parser releases before removing this temporary mitigation.

# Persistent private dashboard

This recipe combines decorator-first pages, reusable live cards, validated actions, and real SQLite persistence. It is an application example, not an authentication framework or managed database.

## Run it

Requires **Node 22.13 or newer** (native `node:sqlite`, experimental in Node 22) and npm. Other Redweb starters retain their own Node requirements. Use a supported Node release in production.

After installing dependencies, create your account:

```sh
npm run add-user -- alice
npm test
npm run dev
```

The provisioning command displays a randomly generated password once. Save it securely; there are no default accounts or passwords. Open **http://127.0.0.1:8181/login** or **http://localhost:8181/login**, sign in, and add a card. A second signed-in tab updates immediately. Restart the app: your cards and unexpired credentials remain valid. Sign out all sessions to close every connected tab for that account and invalidate all its cookies.

`npm test` provisions temporary test accounts and a real temporary database, then exercises HTTP, WebSockets, isolation, restart, and session expiry. It never modifies your application database. Integration tests use no mocks, including hostile cross-loopback form and socket origins. Redweb's release gate also signs in with both valid and invalid credentials through a visible Chromium window, using `localhost` so synthetic request headers cannot hide browser-origin bugs. CI supplies a virtual display for that same headed test. A separately labelled unit test injects a cleanup error after closing a real SQLite database to verify rejection handling; it does not simulate a real operating-system failure.

`npm run test:coverage` measures the TypeScript application through source maps, separately from Redweb's own instrumented-library coverage. Login-window expiry uses the same real limiter with an explicitly short test configuration; it never waits through the production one-minute default. The report includes TypeScript-generated decorator accessor functions; inspect that distinction rather than assuming a library coverage figure applies to this recipe. The generated npm configuration enforces this recipe's Node engine requirement before installation.

## Where the behavior lives

- `app.tsx`: composition, login page, protected dashboard, listener and shutdown.
- `cards.tsx`: reusable `Cards` component and account-scoped live subscriptions. Normal TSX expressions update automatically. Forms call typed actions; feedback requires no browser glue.
- `store.ts`: prepared SQL, bounded cards/sessions, owner-filtered operations and synchronous transactions.
- `auth.ts`: asynchronous scrypt, bounded login attempts, hashed session tokens, cookies and sign-out.
- `admin.ts`: explicit local account provisioning.

## Production boundaries

Set `DASHBOARD_DATABASE` to a writable persistent file path (default `data/dashboard.sqlite`). Protect the directory with OS permissions: the database contains password hashes, private card text, and session metadata. It, its WAL/SHM files, and backups must never be served as public assets or committed. Stop the process cleanly before copying the database for a backup, or use a proper SQLite online backup facility; copying only the main file during live WAL writes is not a backup plan.

Set `NODE_ENV=production` and `DASHBOARD_ORIGIN=https://your-domain.example` behind an HTTPS reverse proxy. The origin must have no path or trailing slash. This enables Secure cookies; all session cookies are HttpOnly and SameSite=Strict. Both login/logout forms and socket upgrades require the exact trusted origin. The application does not trust Host or forwarded headers to establish origin or identity. The HTTP listener must not be publicly reachable around your TLS proxy.

Provision accounts on the same persistent volume before serving requests. Passwords use salted scrypt; only hashes of random session tokens are stored. Default sessions last one hour. Up to 32 unexpired sessions and 100 cards per account are supported. Login work is limited to four simultaneous checks and ten attempts per minute per direct peer IP, with at most 1,024 tracked IPs; clients behind one proxy share its bucket. Add appropriate proxy-level abuse controls for an Internet deployment. There is no registration, password reset, MFA, or account recovery; integrate a dedicated identity provider if your product needs those features.

SQL checks the current session and card owner inside each write transaction. Private subscriptions recheck session validity before publishing and close at expiry. Sign-out invalidates credentials before revoking Redweb sessions. An expired or disconnected page may need a reload/sign-in; the recipe does not silently retry actions with uncertain outcomes.

This is a **single-process live-update model**. SQLite transactions are synchronous and kept small; this is not a claim of unlimited concurrency. Do not put multiple app workers behind a load balancer and expect cross-worker notifications or revocation. Add a deliberate shared notification/session-revocation design before scaling horizontally. Static export cannot include protected dashboards.

Build and deploy using the shared instructions above, including the persistent data volume and the environment settings here. Neither `npm run dev` nor a process restart should erase durable cards. Redweb itself does not depend on SQLite.
