Generate the TLS certificates in process

gen-dev-cert.sh is gone. The server ensures its own certificates on start,
which removes a setup step to remember, a dependency on whatever openssl
was installed, and a second place for the "which addresses?" answer to
live -- the leaf now covers every local IPv4 plus loopback and the
emulator's host alias, so nobody maintains a hardcoded IP.

The split that mattered in the script is kept and now enforced by tests:
the CA is generated once and left alone, because the app pins it and
replacing it strands every installed copy; the leaf is cheap and reissued
every start, so covering a new address is a restart. Both are written
owner-only into a directory outside the repo.

Two things the tests caught. DirBuilder's mode applies only when the
directory is created, so a directory that already existed kept whatever
permissions it had while holding a private key -- the mode is now set
explicitly, in the session directories too. And loading the leaf into the
real RustlsConfig needs the crypto provider installed, which main does but
tests don't.

Verified end to end: deleted the certs, started the server, watched it
generate a CA and warn that installed apps now pin the wrong one, rebuilt
the APK against the new CA, and reinstalled -- the emulator connects over
a certificate that never existed as a pasted constant.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017xn8nHw1tw1R6PtiY1eEtw
This commit is contained in:
irisandClaude Fable 5 committed 2026-08-25 04:36:54 -04:00
1 parent eeb2dde4ab
commit 65743b899d
8 files changed
+550 -175

No files matched your search

+8 -3
View File
@@ -259,9 +259,14 @@ complete path out of everything spawning one created.
### Security
- TLS with a self-signed CA, pinned in the app — `gen-dev-cert.sh` and
`PinnedCert.kt` copied from local-updater, same idempotent-CA/reissued-leaf
scheme, same one-way-door caveat about regenerating the CA.
- TLS with a self-signed CA, pinned in the app — same
idempotent-CA/reissued-leaf scheme as local-updater, same one-way-door
caveat about regenerating the CA, but generated **in process on first
start** (`certs.rs`) rather than by a shell script calling openssl
(2026-08-25). One place then decides the extensions, the file modes, and
which addresses the leaf covers — every local IPv4 plus loopback and the
emulator's host alias, so nobody maintains a hardcoded IP — and there is
no setup step to forget.
- Unlike local-updater, the pinned CA is **not a constant in the source**:
the build reads `$XDG_CONFIG_HOME/ai-app/certs/ca.pem` from the machine
doing the build and generates the constant (`generatePinnedCert` in