summaryrefslogtreecommitdiff
path: root/docs/CHAT-PRODUCTION.txt
blob: 7e0e315f5ebfabf7549ecf11e89a8747de9837a9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
Copyright (C) 2026 Doan Luu Duc Tai <doan@luuduct.ai>

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 <https://www.gnu.org/licenses/>.


PRODUCTION CHAT INTEGRATION

    Implemented on feature/private-chat. Building and testing a release does not
    merge main or activate the VPS. This is experimental software without an
    independent cryptographic or application security audit. Read the limitations
    in CHAT-APPLICATION.txt before using it for private conversations.

    Four services run through rootless Podman: Caddy, cgit, SearXNG, and chat.
    The release contains statically linked x86_64 GNU/Linux management and chat
    binaries, the WASM browser module, exact corresponding sources, and saved
    native container images. The chat image starts FROM scratch: no compiler,
    shell, package manager, or first-party Python. Its root filesystem is read
    only, capabilities are dropped, and only its private data directory is writable.

    Caddy terminates HTTPS at CHAT_HOST and redirects www.CHAT_HOST while keeping
    the requested path. CHAT_UPSTREAM defaults to chat:8080 on the private
    container network. Chat publishes no host ports. Production publishes only
    the gateway HTTP and TCP/UDP HTTPS ports. Existing host SSH policy is separate.

    The gateway supplies an explicit external origin selected from root .env.
    The server accepts that exact HTTPS origin or the dedicated local gateway
    origin. Forwarded client headers never select the trusted origin. Origin
    checks supplement cryptographic authentication; they are not authentication.

BUILD ON THE WORKSTATION

    Current releases require an x86_64 GNU/Linux build host and matching target.
    Use the pinned Rust toolchain, Podman, Git, GnuPG, a GCC-compatible C compiler,
    Linux UAPI headers, libclang, pkg-config, make, Perl, curl, and tar. Native
    workspace checks need OpenSSL 3.5+ development libraries. Browser testing
    additionally needs Node, Playwright, Chromium, and Firefox. These tools remain
    on the workstation; production does not need Cargo or a compiler.

        cargo stack release

    This runs formatting, strict Clippy, all workspace tests, rustdoc, cargo-deny,
    and cargo-about. It then builds static native binaries, the WASI module,
    corresponding sources, the chat/cgit images, and the complete image export.
    THIRD-PARTY-LICENSES.html is regenerated from the full workspace before
    packaging. Check the archive checksum and test 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 come from the official OpenSSL GitHub release and Alpine CDN. The
    compiler uses isolated musl/GCC built-in headers plus host Linux UAPI headers;
    glibc headers are excluded. OpenSSL is static, has no dynamic providers, and
    seeds its RNG through getrandom. The native cryptographic compatibility probe
    must pass after the build. WASI uses its separately verified SDK and OpenSSL
    build recorded in CHAT-OPENSSL-MIGRATION.txt. No crypto algorithm was changed.

    Cached inputs live only under .tools/. Rebuild OpenSSL when its version,
    source, or build flags change. An OpenSSL update requires reviewing upstream
    security notices, updating every affected URL/hash, native and WASI rebuilds,
    rerunning both browsers and cargo-deny, regenerating notices and exact source,
    and repeating release recovery. Never approve a dependency advisory merely
    to make the build pass. cargo-deny does not audit C/OpenSSL advisories.

    The source download includes first-party code, Cargo-vendored dependencies,
    and unmodified OpenSSL source. Toolchain/sysroot development inputs are not
    bundled as application sources. Saved images preserve the tested runtime.
    An ARM host needs a separately supported native release; do not copy these
    x86_64 binaries there and assume they will work.

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

    These are distinct browser origins and require separate identity files. The
    direct process and production deliberately use the same relative database
    name on their respective machines. Do not switch an installation containing
    valuable identities between direct development and production. Use a fresh
    restored release directory for integration tests. Rebuild the release after
    edits to refresh the packaged browser, server, sources, notices, and image.

    The single root .env holds public hostnames, ports, upstreams, backup settings,
    SEARXNG_SECRET, and CHAT_SETUP_TOKEN. The example is public; actual .env is
    ignored and never included in public releases or source downloads. Caddy keys
    and chat databases are generated private runtime state under var/data.
    Initialization preserves configured values and generates missing secrets.

DEPLOY AND CREATE THE REAL OWNER FILE

    Use the release upload/activation instructions in OPERATIONS.txt. Extract
    the new prebuilt management binary into var/incoming/bootstrap and invoke
    it with --root pointing at the current installation. The older three-service
    management binary cannot parse the new chat service schema; do not use that
    older binary to activate this release. The new binary verifies the archive
    and installs packaged chat artifacts before starting services.
    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 restart policies restart failed containers.
    Neither mechanism compiles code or requests a registry pull for a complete
    release on the matching architecture. 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.

    In the browser on the production HTTPS origin, choose OWNER SETUP. Read the
    setup token from the production root .env locally; never publish it or send it
    through chat. Choose a unique owner-file password, save the downloaded file,
    reopen it, and unlock it. Store that file and password in KeePassXC and keep
    a protected backup of the database. The setup token cannot replace this file.
    Never copy a development owner file and silently change its pinned origin.

BACKUP, RESTORE, AND KEY LOSS

    A complete encrypted application export:
        ./bin/stack backup --include-images

    Download the .gpg and .sha256 files off the VPS. A backup on the same VPS is
    vulnerable to loss of that VPS. Existing configured backup recipients apply.
    This export includes the single .env, consistent SQLite snapshots for chat
    and chat-local, Caddy certificate state, repositories, static binaries, WASM,
    sources, and exact container images. SQLite uses its online backup API; chat
    is left unpaused so a pending writer cannot block snapshot completion.
    The database contains ciphertext and public keys, plus the metadata described
    in CHAT-APPLICATION.txt. The owner private file and GnuPG secret key are not
    server data; back them up separately.

    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 and changes container project names to avoid
    accidentally replacing another installation. up --production selects the
    production database and HTTPS origin again. Keep the same hostname/origin,
    point DNS at the replacement host, and use unchanged owner/visitor files and
    passwords. A new IP does not change an origin. A changed hostname or HTTPS
    port does. Do not expose two restored copies simultaneously under one origin.
    Server restart invalidates sessions; reopening identity files authenticates
    again. Historical ciphertext and counters persist across restart and recovery.

    Losing the owner private file cannot be repaired by CHAT_SETUP_TOKEN. If its
    backups are also lost, reset deliberately deletes every stored conversation
    and message. It does not decrypt or recover anything. This backend operation
    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

    A running server holds a filesystem lock; reset refuses until it stops. The
    full fingerprint must match. Root .env and previous exports are preserved.
    Create a new production owner file afterward. Old visitor files reject its
    changed pinned owner key and need a new chat identity. A reset does not erase
    copies already present in exports or external snapshots.

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 node crates/chat-server/tests/browser.mjs

    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.