feat: add disabled IMAPS TLS transport and Notes scope #873

Open
kayg wants to merge 1 commit from feat/imap-notes-server-foundation into dev
Owner

Plan

Size: 10 files, 698 changed lines before Cargo.lock resolution; within #830's 700–1,000 line foundation estimate once the lockfile is included.

Big-O: certificate loading is O(chain bytes) only when current changes. The watcher keeps O(1) generation state. TCP permit accounting is O(1) per accept/release and bounded by 128 active connections. TLS handshakes run concurrently with a 10-second deadline.

Failure Effect Detection Recovery Gate
Missing, expired or hostname-mismatched certificate IMAPS accepts no TLS sessions; HTTP stays available. Certificate watcher reports generation and validation error without key material. Restore a valid generation under the mounted directory. Missing/invalid generation and trusted-host handshake.
current symlink moves to a new generation New handshakes use the new certificate; existing sessions keep their negotiated certificate. Watcher compares the resolved generation path. No action when loading succeeds; invalid generations disable new handshakes until corrected. Rotate the symlink and verify the served certificate changes.
Process or source-IP cap is reached The new socket closes before TLS; existing sessions continue. Permit counts are held from TCP accept. Reconnect after a permit is released. Source and process cap boundaries, including handshake sockets.
Unknown scope is written to auth storage Migration/trigger rejects the row; existing Contacts and Calendar scopes remain valid. SQLite trigger and migration test. Mint a supported scope. Upgrade from v10 and verify old and Notes scopes.

Design

  • Base is #824 head f1c1aa961e.
  • Add the explicit mail.notes.read scope while keeping the internal Installation kind dav and the Contacts default.
  • Add an IMAPS transport disabled unless CALTERNAL_IMAP_ENABLED=true. It binds container port 9993, uses implicit TLS 1.2+, loads /etc/calternal/imap-tls/current/{fullchain.pem,privkey.pem} from the read-only directory mount, and reloads on generation change.
  • The production port mapping remains 10.70.3.162:9993:9993; the already-installed 993 forwarder terminates no TLS.
  • This stack layer contains no mailbox projection or user-facing enablement. The next layer adds the bounded IMAP auth state machine; a later layer adds the Notes UID/MIME projection and read-only mailbox commands.

Gates

Run in the Nix devshell on dev-02 through ~/bin/slot:

  • cargo fmt --all -- --check
  • cargo test -p calternal-auth -j4
  • cargo test -p calternal-imap -j4
  • cargo clippy -p calternal-imap -j4 -- -D warnings
  • A trusted-host TLS handshake, missing/invalid certificate check, and symlink generation rotation check.

Results and command output will be posted as PR comments, not committed to the repository.

## Plan **Size:** 10 files, 698 changed lines before Cargo.lock resolution; within #830's 700–1,000 line foundation estimate once the lockfile is included. **Big-O:** certificate loading is O(chain bytes) only when current changes. The watcher keeps O(1) generation state. TCP permit accounting is O(1) per accept/release and bounded by 128 active connections. TLS handshakes run concurrently with a 10-second deadline. | Failure | Effect | Detection | Recovery | Gate | | --- | --- | --- | --- | --- | | Missing, expired or hostname-mismatched certificate | IMAPS accepts no TLS sessions; HTTP stays available. | Certificate watcher reports generation and validation error without key material. | Restore a valid generation under the mounted directory. | Missing/invalid generation and trusted-host handshake. | | current symlink moves to a new generation | New handshakes use the new certificate; existing sessions keep their negotiated certificate. | Watcher compares the resolved generation path. | No action when loading succeeds; invalid generations disable new handshakes until corrected. | Rotate the symlink and verify the served certificate changes. | | Process or source-IP cap is reached | The new socket closes before TLS; existing sessions continue. | Permit counts are held from TCP accept. | Reconnect after a permit is released. | Source and process cap boundaries, including handshake sockets. | | Unknown scope is written to auth storage | Migration/trigger rejects the row; existing Contacts and Calendar scopes remain valid. | SQLite trigger and migration test. | Mint a supported scope. | Upgrade from v10 and verify old and Notes scopes. | ### Design - Base is #824 head f1c1aa961e169ef99e132063a97ccbd9a89a5def. - Add the explicit mail.notes.read scope while keeping the internal Installation kind dav and the Contacts default. - Add an IMAPS transport disabled unless CALTERNAL_IMAP_ENABLED=true. It binds container port 9993, uses implicit TLS 1.2+, loads /etc/calternal/imap-tls/current/{fullchain.pem,privkey.pem} from the read-only directory mount, and reloads on generation change. - The production port mapping remains 10.70.3.162:9993:9993; the already-installed 993 forwarder terminates no TLS. - This stack layer contains no mailbox projection or user-facing enablement. The next layer adds the bounded IMAP auth state machine; a later layer adds the Notes UID/MIME projection and read-only mailbox commands. ### Gates Run in the Nix devshell on dev-02 through ~/bin/slot: - cargo fmt --all -- --check - cargo test -p calternal-auth -j4 - cargo test -p calternal-imap -j4 - cargo clippy -p calternal-imap -j4 -- -D warnings - A trusted-host TLS handshake, missing/invalid certificate check, and symlink generation rotation check. Results and command output will be posted as PR comments, not committed to the repository.
feat: add disabled IMAPS transport and Notes scope
Some checks failed
CI / server (pull_request) Has been cancelled
CI / rust (pull_request) Has been cancelled
CI / web (pull_request) Has been cancelled
d8f639374c
kayg changed target branch from feat/imap-766-uid-authority to dev 2026-11-07 20:24:57 +00:00
Author
Owner

housekeeping #1009: rebased+failing, left open for review.

rebased auth/IMAP foundation. preserved dev Notes read/write/share scopes and migrations 11–13; added IMAP at schema 14. corrected the new scope trigger to keep Notes-only DAV passwords valid, with a migration regression test. moved retained auth ownership and mutable certificate receiver into the foundation; TLS fixture paths are canonical on macOS and test-only direct fixture I/O is explicitly scoped.

head: a7309d6b55fa9918807e9f27e59affe7959b0107; based on dev cd7f84432febfc63b788fbb9b9f9950452982d74, pushed with the original exact force-with-lease.

frontend frozen install, check, lint, build and unit tests passed. bundle gate passed. first-paint brotli vs dev: JS 230777 B (+0 B), CSS 18386 B (+0 B).

Rust gate results (Mac VM):

exit command
0 cargo fmt -p calternal-auth -p calternal -p calternal-imap -- --check
0 cargo check -j4 --locked -p calternal --bins
101 cargo check -j4 --locked -p calternal-auth -p calternal -p calternal-imap --all-targets
101 cargo clippy -j4 --locked -p calternal-auth -p calternal -p calternal-imap --all-targets -- -D warnings
0 cargo test -j4 --locked -p calternal-auth --lib
0 cargo test -j4 --locked -p calternal-imap --lib
101 cargo test -j4 --locked -p calternal-auth -p calternal -p calternal-imap
0 cargo check -j4 --locked -p calternal-auth -p calternal-imap --all-targets
0 cargo clippy -j4 --locked -p calternal-auth -p calternal-imap --all-targets -- -D warnings
0 cargo test -j4 --locked -p calternal-auth -p calternal-imap --lib

server-wide all-target checks/tests are blocked on macOS by storage_startup.rs:147 borrowing Child immutably; clippy also reports unused state in storage.rs:265. both reproduce on dev. scoped auth/IMAP component checks, clippy and unit tests passed. native Apple Notes client qualification and perf qualification remain unrun.

all executed gates used the VM Nix environment, shared Mac lock and slot. exact commands, source heads, logs and dev baseline. frontend inputs are identical to the tested frontend tree when a Rust-only repair changed the head.

original-head cherry/patch inventory, pr-873.md; unmatched entries are missing-patch candidates, with semantic overlap/replacements noted above.

housekeeping #1009: rebased+failing, left open for review. rebased auth/IMAP foundation. preserved dev Notes read/write/share scopes and migrations 11–13; added IMAP at schema 14. corrected the new scope trigger to keep Notes-only DAV passwords valid, with a migration regression test. moved retained auth ownership and mutable certificate receiver into the foundation; TLS fixture paths are canonical on macOS and test-only direct fixture I/O is explicitly scoped. head: `a7309d6b55fa9918807e9f27e59affe7959b0107`; based on dev `cd7f84432febfc63b788fbb9b9f9950452982d74`, pushed with the original exact force-with-lease. frontend frozen install, check, lint, build and unit tests passed. bundle gate passed. first-paint brotli vs dev: JS 230777 B (+0 B), CSS 18386 B (+0 B). Rust gate results (Mac VM): | exit | command | |---|---| | 0 | `cargo fmt -p calternal-auth -p calternal -p calternal-imap -- --check` | | 0 | `cargo check -j4 --locked -p calternal --bins` | | 101 | `cargo check -j4 --locked -p calternal-auth -p calternal -p calternal-imap --all-targets` | | 101 | `cargo clippy -j4 --locked -p calternal-auth -p calternal -p calternal-imap --all-targets -- -D warnings` | | 0 | `cargo test -j4 --locked -p calternal-auth --lib` | | 0 | `cargo test -j4 --locked -p calternal-imap --lib` | | 101 | `cargo test -j4 --locked -p calternal-auth -p calternal -p calternal-imap` | | 0 | `cargo check -j4 --locked -p calternal-auth -p calternal-imap --all-targets` | | 0 | `cargo clippy -j4 --locked -p calternal-auth -p calternal-imap --all-targets -- -D warnings` | | 0 | `cargo test -j4 --locked -p calternal-auth -p calternal-imap --lib` | server-wide all-target checks/tests are blocked on macOS by `storage_startup.rs:147` borrowing Child immutably; clippy also reports unused `state` in `storage.rs:265`. both reproduce on dev. scoped auth/IMAP component checks, clippy and unit tests passed. native Apple Notes client qualification and perf qualification remain unrun. all executed gates used the VM Nix environment, shared Mac lock and slot. [exact commands, source heads, logs and dev baseline](https://git.kayg.org/attachments/bdb8d284-b80d-4185-b0be-6fa74f48a191). frontend inputs are identical to the tested frontend tree when a Rust-only repair changed the head. [original-head cherry/patch inventory](https://git.kayg.org/attachments/e05a38dc-c028-4d77-8655-efa9d5c8ea50), `pr-873.md`; unmatched entries are missing-patch candidates, with semantic overlap/replacements noted above.
Some checks failed
CI / server (pull_request) Has been cancelled
CI / rust (pull_request) Has been cancelled
CI / web (pull_request) Has been cancelled
Merge conflict checking is in progress. Try again in few moments.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin feat/imap-notes-server-foundation:feat/imap-notes-server-foundation
git switch feat/imap-notes-server-foundation

Merge

Merge the changes and update on Forgejo.

Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.

git switch dev
git merge --no-ff feat/imap-notes-server-foundation
git switch feat/imap-notes-server-foundation
git rebase dev
git switch dev
git merge --ff-only feat/imap-notes-server-foundation
git switch feat/imap-notes-server-foundation
git rebase dev
git switch dev
git merge --no-ff feat/imap-notes-server-foundation
git switch dev
git merge --squash feat/imap-notes-server-foundation
git switch dev
git merge --ff-only feat/imap-notes-server-foundation
git switch dev
git merge feat/imap-notes-server-foundation
git push origin dev
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
kayg/calternal!873
No description provided.