summaryrefslogtreecommitdiff
path: root/docs/CHAT-PRODUCTION.txt
blob: fdb48a6a4b37869b4106cb84d61e2aa4b3c050fc (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
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 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.