Copyright (C) 2026 Doan Luu Duc Tai This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . PRODUCTION CHAT INTEGRATION Implemented on main. Builds/tests do not activate the VPS. Experimental; no independent cryptographic or application security audit. Read CHAT-APPLICATION.txt limitations before private use. Rootless Podman runs Caddy, cgit, SearXNG, and chat. Releases contain static x86_64 GNU/Linux management/chat binaries, browser WASM, exact corresponding sources, and native images. Chat starts FROM scratch: no compiler, shell, package manager, or first-party Python. Root filesystem is read-only; capabilities are dropped; only private data is writable. Caddy serves HTTPS at CHAT_HOST and redirects www.CHAT_HOST, preserving paths. CHAT_UPSTREAM defaults to private chat:8080. Chat publishes no host ports; only gateway HTTP and TCP/UDP HTTPS are published. Host SSH policy is separate. Root .env selects the explicit external origin. Chat accepts exactly that HTTPS origin or the dedicated local gateway origin. Forwarded client headers cannot select it. Origin checks supplement cryptographic authentication. BUILD ON THE WORKSTATION Build host and target must be x86_64 GNU/Linux. Requires pinned Rust, Podman, Git, GnuPG, GCC-compatible C compiler, Linux UAPI headers, libclang, pkg-config, make, Perl, curl, tar, Node >=22.18.0, npm, and OpenSSL 3.5+ development libraries. Browser tests also need pinned Playwright, Chromium, and Firefox. Workstation tools stay local; production needs neither Cargo nor compiler. cargo stack release Runs TypeScript build/checks, formatting, strict Clippy, workspace tests, rustdoc, cargo-deny, and cargo-about. Builds static binaries, WASI, exact sources, chat/cgit images, and complete image export. Regenerates workspace THIRD-PARTY-LICENSES.html. Verify archive checksum and recovery before deployment. infra/chat/build-native.sh verifies OpenSSL 3.6.5's original source archive: a2157c2830efdec3788939b00c9b0638306d3f0bbb76dc4832ee503bb397df98 It verifies Alpine musl-dev 1.2.6-r3 headers: 310b51cff12e1d5ce5f135c558a82e2550427da5465bbd16c9ff9b05e63ee3d9 Sources: official OpenSSL GitHub release and Alpine CDN. Compilation uses isolated musl/GCC built-in and host Linux UAPI headers, excluding glibc. Static OpenSSL has no dynamic providers and seeds through getrandom. The native compatibility probe must pass. WASI uses separately verified SDK/OpenSSL inputs in CHAT-OPENSSL-MIGRATION.txt. Cryptographic algorithms stay fixed. Inputs cache under .tools/. Version/source/flag changes require an OpenSSL rebuild. Updates require upstream advisory review, every affected URL/hash, native/WASI rebuilds, both browsers, cargo-deny, regenerated notices/sources, and release recovery. Never waive advisories to pass. cargo-deny excludes C/OpenSSL. Source downloads include first-party code, Cargo-vendored dependencies, and unmodified OpenSSL, excluding development toolchain/sysroot inputs. Saved images preserve tested runtime. ARM requires a separately supported native release. LOCAL MODES AND ORIGIN BINDING Direct Rust development: cargo stack chat http://127.0.0.1:9080/ var/data/chat Container preview: cargo stack dev http://chat.localhost:8080/ var/data/chat-local Production: ./bin/stack up --production https://CHAT_HOST/ with the configured HTTPS_PORT var/data/chat Distinct origins require separate identity files. Direct development and production share a relative database path on separate machines; do not switch valuable installations between them. Integration tests need a fresh restored release. Rebuild after edits to refresh browser, server, sources, notices, and image. One root .env holds hostnames, ports, upstreams, backups, SEARXNG_SECRET, and CHAT_SETUP_TOKEN. Only the example is public; releases/source downloads exclude actual .env. Caddy keys/chat databases stay under var/data. Initialization preserves configured values and generates missing secrets. DEPLOY AND CREATE THE REAL OWNER FILE Follow OPERATIONS.txt. Extract the verified release's new management binary into var/incoming/bootstrap; invoke with --root set to the current installation. The new binary understands its release schema, verifies the archive, and installs chat artifacts before startup. The host needs rootless Podman prerequisites, user linger, low-port permission, DNS A/AAAA records for CHAT_HOST and www.CHAT_HOST, and the normal 80/443 firewall rules. Caddy obtains and renews public certificates automatically. Public certificate validation requires standard reachable ACME ports. The systemd user service runs ./bin/stack up --production at boot and ./bin/stack down on stop. Podman restarts failed containers. Complete matching-architecture releases need no compilation or registry pull. Check all four services after activation: ./bin/stack status Check HTTPS, HTTP-to-HTTPS and www redirects, the homepage Services entry, /LIMITATIONS.txt, /javascript.html, and /SOURCE.tar.gz on the chat origin. The displayed limitations are CHAT-APPLICATION.txt. Chat has its own origin; the main website remains JavaScript-free. Its Message Me links lead to chat. At the production HTTPS origin, choose OWNER SETUP. Read the root .env token locally; never publish or send it through chat. Choose a unique password; save, reopen, and unlock the downloaded owner file. Keep file/password in KeePassXC with a protected database backup. The token cannot replace the file. Never silently change a development file's pinned origin. BACKUP, RESTORE, AND KEY LOSS A complete encrypted application export: ./bin/stack backup --include-images Copy .gpg and .sha256 off the VPS; local backups cannot survive VPS loss. Configured recipients apply. Export includes one .env, online SQLite snapshots for chat/chat-local, Caddy certificates, repositories, static binaries, WASM, sources, and exact images. Chat stays unpaused so pending writers can complete. Database contents are ciphertext/public keys and CHAT-APPLICATION.txt metadata. Owner private file and GnuPG secret key need separate backups. Restore to a new directory, verify, then explicitly start production mode: ./bin/stack restore /path/export.tar.gz.gpg /path/stack-restored cd /path/stack-restored ./bin/stack up --production Restore defaults to local mode with fresh project names, avoiding replacement of another installation. up --production reselects production database/origin. Keep hostname/origin, repoint DNS, and use unchanged identity files/passwords. IP changes preserve origin; hostname/HTTPS-port changes do not. Never expose two restored copies under one origin. Restart invalidates sessions; reopening files authenticates again. Historical ciphertext/counters persist. CHAT_SETUP_TOKEN cannot recover a lost private file. If backups are also lost, reset deletes every conversation/message; it decrypts and recovers nothing. Reset has no HTTP endpoint and requires filesystem/Podman access: ./bin/stack chat --owner-fingerprint ./bin/stack down ./bin/stack chat --reset-owner PASTE_CURRENT_OWNER_FINGERPRINT_HERE ./bin/stack up --production Reset requires a stopped server and matching full fingerprint. Root .env and exports survive. Create a new production owner file; old visitor files reject its changed key and need fresh identities. Exports/external snapshots are not erased. VERIFICATION The browser harness supports packaged HTTPS installations without Rust or target/ inside them. It creates disposable identities and a separate temporary GnuPG key, takes a complete encrypted export with images during live chat, restores into a new directory, starts the saved images, and reopens the same files to decrypt history. It also exercises wrong passwords, safe text, counters, 0-to-N history, 50-row batches, retry deduplication, origin rejection, browser storage checks, and backend reset guards. It never resets real data. Example after restoring a release to a disposable staging directory and configuring fixture .localhost hostnames, WEB_BIND=127.0.0.1, HTTP_PORT=8181, HTTPS_PORT=8443, and LOCAL_HTTP_PORT=8180: ./bin/stack up --production CHAT_TEST_ROOT=/absolute/disposable/stack CHAT_TEST_ORIGIN=https://chat.fixture.localhost:8443 PLAYWRIGHT_BROWSERS_PATH=.tools/browsers npm run test:chat Run from the source checkout for the harness and Playwright installation. Add CHAT_LIBREJS=1 for Firefox with the actual GNU LibreJS add-on. That test verifies the add-on is active and blocks an unlicensed control script. Disposable staging needs a fresh database for each complete run. Browser automation permits the fixture's private CA only for functional tests. Separately verify its chain and hostname with curl --cacert and --resolve; test the canonical route and www redirect without disabling verification. Production uses ordinary trusted public certificates with no TLS bypass. Passing these checks demonstrates recovery and functional compatibility; it does not establish absence of attacks or constitute an independent audit. RECORDED RESULTS, 2026-10-31 The complete native workspace check passed: formatting, strict Clippy, 14 tests, private rustdoc, cargo-deny with no ignored advisories, and cargo-about generation. Static musl and WASI OpenSSL 3.6.5 probes passed without changing the required RFC 9980 algorithms. Direct development passed in Chromium. Packaged HTTPS passed independently in Chromium and Firefox with GNU LibreJS 7.21.1 active; its unlicensed-script control was rejected. Both packaged tests recovered a complete encrypted application export, including saved images, into a new directory, then reopened the unchanged owner/visitor files and decrypted the history. Export and checksum permissions were verified as 0600. Runtime inspection verified read-only root filesystem, zero effective capabilities, no chat host ports, and unless-stopped restart policy. Killing the disposable chat process with SIGKILL caused an automatic restart, and its owner fingerprint persisted. The supplied systemd user unit passed systemd-analyze verification; this did not reboot the real VPS. curl independently verified the fixture CA chain and hostname for canonical chat, www redirect, and homepage. The homepage Services limitations link resolved correctly. The source download matched the packaged source archive byte-for-byte and contained only .env.example, without actual .env. Upgrade testing started the 2026-10-30 three-service release, then activated the chat-enabled release through its new prebuilt management binary. All four services started, existing data and SearXNG secret persisted, and the new owner setup token was generated in the same root .env. These tests used disposable local data; they did not register a real production owner.