first commit
RustBox CI / rustbox (push) Waiting to run

This commit is contained in:
Mateusz Gruszczyński committed 2026-10-29 15:24:59 +01:00
commit bc5fbd6ba9
180 files changed
+63750

No files matched your search

+157
View File
@@ -0,0 +1,157 @@
# RustBox 0.0.1 - implementation status
This file tracks the internal `0.0.1` baseline. The user-approved `docs/RUSTBOX_PLAN.md` remains authoritative. A feature is only listed as implemented when working code exists in this source tree; partial items are called out explicitly.
## Implemented / wired in this working snapshot
### Runtime and upstream
- Single Rust runtime with embedded HTML/CSS/vanilla-JavaScript UI.
- No TypeScript, React, Next.js, Node.js or Bun product build/runtime.
- Oxi upstream tracking and mapped backend-port scripts retained.
- EN/PL language assets embedded in the binary.
### Mail and IMAP workflow
- IMAP folder list, hierarchy, create, create subfolder, rename, delete, subscribe/unsubscribe, plus collapsible branch navigation with per-account remembered expansion state.
- Special folders stored per account: Sent, Drafts, Trash, Junk and Archive. Spam/Junk additionally supports a browser-wide default destination with a per-account override and IMAP special-use/name fallback.
- Special-folder references follow folder renames and are cleared when a referenced folder is deleted.
- Sent-copy, delete-to-Trash, Archive and Junk actions use the configured special folders.
- Mark-all-read and empty-folder operations.
- Message move and copy operations.
- Multi-select and bulk read/unread, flag/unflag, archive, move, copy, label and delete actions, including explicit select-all across the complete cached search result set.
- Drag-and-drop a message onto a folder to move it.
- Previous/next message navigation plus keyboard actions for common reader operations, compose, selection mode and selecting the current message.
- Message reading, collapsible thread navigation, attachments, raw headers, full RFC822 `.eml` download via `BODY.PEEK[]` and `.eml` import into a selected IMAP folder via APPEND.
- Message/folder context menus with common Roundcube-style actions, including folder properties, full message source, Message-ID/address copy and mailing-list unsubscribe; the reader sender line also exposes compose/contact/search/filter actions.
- Mailbox quota display where the IMAP server exposes quota, including warning/danger states at 80%/95%.
- Per-account mailbox behavior: 20/50/100/200 messages per page, date/sender/subject/size sorting in both directions, configurable mark-read delay, threaded/flat reader mode, HTML/plain preference, remote-image policy including Contacts-only loading, quote limiting, optional list snippets and a default “flagged on top” mode. Each folder can inherit, force-enable or force-disable flagged-first ordering; sorting is applied before pagination.
- IMAP capability diagnostics for IDLE, MOVE, UIDPLUS, CONDSTORE, QRESYNC, SORT, THREAD, NAMESPACE, SPECIAL-USE, QUOTA, ACL, LIST-EXTENDED and UTF8=ACCEPT.
- Forward-as-attachment using `message/rfc822`.
- Mailing-list unsubscribe action from `List-Unsubscribe`; RFC 8058 one-click HTTPS requests are sent by the backend only when `List-Unsubscribe-Post: List-Unsubscribe=One-Click` is advertised, with redirect-free public-address SSRF checks. Ordinary HTTPS/mailto links remain user-confirmed UI actions.
- Explicit upload-body limits for attachments, contact imports/photos, ICS imports and `.eml` import so Axum does not reject allowed uploads at its smaller default limit.
- Attachment context menu supports in-app preview/download for safe image/PDF/text MIME classes; multiple attachments can be downloaded as a client-built UTF-8 ZIP without external runtime dependencies.
- Message rows expose compact hover/focus quick actions for read/unread and flag/unflag; flagged rows also receive a subtle red lower-edge marker.
### Composer / identities
- HTML, plain-text and Markdown compose modes. Markdown keeps its source text for the plain alternative and generates escaped/sanitized HTML for preview and delivery without accepting raw Markdown HTML.
- Expanded HTML toolbar: bold, italic, underline, strike, lists, quote, alignment, links, font, size, color, clear formatting, undo/redo.
- Draft autosave, explicit recovery of saved/browser-emergency drafts, and attachment upload/delete. Deliberate IMAP Drafts snapshots carry a stable RustBox draft identifier; the previous remote snapshot is removed only after the new UID is resolved unambiguously and UIDVALIDITY still matches.
- Drag-and-drop attachments with visible upload progress. Attachment uploads stream multipart chunks into `.part` files with an enforced size limit, atomic final rename and stale/incomplete temporary-file cleanup instead of buffering the whole attachment in memory.
- Inline image upload using CID attachments, including paste and drag/drop of PNG/JPEG/GIF/WebP images into the composer. During editing, CID images use authenticated same-origin draft-attachment preview URLs and are serialized back to `cid:` references for saved/sent MIME content. Inline images can be resized, aligned left/center/right/inline and cropped in-app (GIF cropping is intentionally disabled to preserve animation); display-only resizing does not rewrite the source file. Unused CID attachments are cleaned when their image is removed from the editor.
- Attachment reminder for common English/Polish wording.
- Multiple identities.
- Identity Reply-To, automatic Bcc, Organization metadata, text/HTML signatures and per-action signature rules/position; replies/forwards auto-select the matching identity from To/Cc/Delivered-To/Envelope-To when possible.
- Composer From identity selection and signature insertion.
- Outgoing priority (normal/high/low) and MDN/read-receipt requests are persisted in drafts and emitted consistently in SMTP delivery and the IMAP Sent copy; all envelope/header mailboxes are parsed before SMTP delivery. Administrators can also configure validated additional outgoing headers; structural/MIME headers and CR/LF-injected values are rejected.
### Search, labels and contacts
- Tantivy/search backend retained.
- Search operators including `from:`, `to:`, `subject:`, `folder:`, `has:attachment`, `is:read`, `is:unread`, `is:flagged`, `is:unflagged` and date filters. Active search terms are highlighted in sender, subject and snippet text using DOM text nodes rather than result HTML.
- Advanced-search dialog and saved searches.
- User labels/tags with validated HEX colors, message chips, context actions and bulk assignment. Optional native IMAP-keyword synchronization writes stable RustBox keywords only on folders advertising persistent custom-keyword support, imports observed RustBox keywords and provides an authoritative reconcile action that also applies remote removals only on confirmed keyword-capable folders.
- Contacts CRUD/search with phone, job title, postal address, website and birthday fields.
- Contact photo upload/remove/display (PNG/JPEG/WebP, 2 MB limit, MIME signature validation).
- Contact groups, membership editing and group filtering.
- vCard import/export includes the expanded profile fields and multiple e-mail/phone/address values.
- Duplicate-contact detection checks primary and alternate e-mail addresses; merge keeps target data, alternate values, group memberships and a source photo when the target has none.
- vCard attachments can be imported directly from a message attachment.
- Composer To/Cc/Bcc fields use the existing contact/known-address autocomplete API with keyboard navigation.
### Sieve
- ManageSieve raw script list/get/put/delete/rename/activate/deactivate/check.
- STARTTLS, implicit TLS and explicit plaintext opt-in.
- Quick filters generated from sender/domain/subject use an in-app wizard with condition/action preview, capability-aware actions, optional mark-as-read chaining, target-script selection, server validation and direct save/activation; an Advanced editor handoff remains available. The wizard explicitly states that Sieve changes apply to future incoming messages.
- Visual rule builder with From/domain/To/Subject/List-ID/custom-header conditions, three-condition nested AND/OR grouping and per-condition negation.
- Visual actions: move, copy, redirect, discard, mark read, add IMAP flag and keep, with an optional second action.
- RustBox-generated visual rules carry stable markers and can be reordered by drag/drop or keyboard-accessible up/down controls without rewriting unrelated raw-script text.
- Builder merges `require` extensions, disables actions unsupported by advertised server capabilities and validates generated scripts with the server.
- Autoresponder/vacation builder supports subject, body, reply interval, mailing-list/automated-mail suppression and optional inclusive start/end dates using `currentdate` when the server advertises `date` + `relational`.
- Sieve scripts can be backed up/restored as a validated RustBox JSON bundle; restore validates all scripts before writing, and saving over an active script requires an explicit application confirmation.
### Calendar and realtime
- Calendar event CRUD UI with Month, Week, Day and Agenda views.
- iCalendar/ICS import UI over the existing parser/backend, plus direct import from message attachments and full local ICS export.
- Calendar event editor includes all-day mode, RRULE storage, attendees, organizer, status, reminder, meeting URL and color metadata.
- Browser WebSocket client connected to the existing IMAP IDLE/event backend.
- Realtime folder/message refresh for NewMessages/FlagsChanged/FolderUpdated events.
- Desktop notifications, optional sound, per-folder selection and persisted Do Not Disturb hours. Aggregate unread count updates the browser-tab title and the application badge where the Badging API is available.
- Account switch/remove/add workflow for multiple authenticated accounts in one browser session.
- Active-session list across browsers while the RustBox process is running, with creation/last-active timestamps, friendly browser/device labels, full User-Agent hover detail, individual revoke and revoke-all-others.
- Diagnostics panel exposing IMAP capabilities (including persistent custom-keyword support), authenticated SMTP connectivity, ManageSieve status, browser WebSocket state, local synchronization-cache timestamps/counts and live IMAP IDLE task/subscriber counts without returning server host names or credentials. Public liveness (`/api/health`) and local-storage readiness (`/api/ready`) endpoints are available for service supervision.
- Search-index diagnostics expose cached/indexed counts, with a rebuild operation from the local SQLite cache.
- IMAP reconnect control drops reusable request-path sessions and verifies a fresh authenticated connection.
- Graceful SIGTERM/Ctrl+C shutdown stops accepting new requests and aborts dedicated IMAP IDLE tasks before process exit.
### Personalization
- Persistent per-user display preferences in SQLite.
- Light/dark/system theme.
- Presets: sage, blue, teal, cyan, indigo, slate, graphite, amber, orange, violet, rose, red and custom.
- Custom accent, background, panel and text colors.
- Font family and size, message row height, folder/message pane widths, border radius and contrast. Advanced controls include icon size, toolbar/sidebar density, reader/composer widths, selection color, unread font/badge styling, compact headers, border visibility, scrollbar density, monochrome mode and per-pane background overrides.
- Date-format (locale/ISO/EU/US) and time-format (locale/24-hour/12-hour) preferences.
- Compact/comfortable density, preview right/bottom/off, UI scale and reduced motion.
- Avatar/attachment/flag visibility toggles.
- Folder and message-list pane widths can also be adjusted directly with draggable splitters and persist through the existing per-user display preferences. Keyboard shortcuts are documented in an in-app reference dialog.
### Build/installation fixes in this snapshot
- Fixed the `E0499` mutable-borrow failure in `mark_all_read`: the `uid_store()` stream is dropped before `session.logout()`.
- Fixed a duplicate `else` introduced in the calendar delete handler during the calendar expansion.
- All 36 SQLite migrations are present, contiguous and wired sequentially in the migration runner during static validation; V032–V036 add advanced appearance controls, draft compose-format persistence, optional IMAP-keyword sync, composer behavior preferences and remote IMAP-draft tracking.
## Partially implemented - keep visible as incomplete
- Sieve visual builder now supports a three-condition nested AND/OR group, negation, two actions, capability-aware disabling, managed-rule ordering and scheduled vacation dates. An arbitrary-depth condition tree, arbitrary-length action stack and full capability-aware condition/action matrix remain unfinished.
- Drafts are stored locally and can be recovered after interrupted editing/SMTP failure. Remote replacement is implemented conservatively: RustBox resolves the new UID with UIDNEXT plus an exact per-draft header search and only removes the previous snapshot when resolution and UIDVALIDITY are safe; wider real-server compatibility still needs the release gate.
- Calendar is local/ICS-capable and stores recurrence/attendee/reminder metadata, but recurrence expansion/edit semantics, invitation responses and CalDAV synchronization are not finished.
- Notifications are wired through IMAP IDLE/WebSocket, but richer per-account notification policy and service-worker/background delivery are not finished.
- Identities emit Organization metadata; composer priority, MDN request headers and validated administrator-defined outbound headers are wired. SMTP DSN negotiation remains to be completed.
## Not yet complete - do not claim Roundcube parity
- MOVE-based Undo is available for move/delete-to-Trash/archive/spam when the destination UID can be resolved unambiguously from pre-MOVE UIDNEXT plus exact Message-ID. A persistent multi-step undo history and servers/messages without a safely resolvable destination UID remain unfinished.
- Contact model supports multiple e-mails/phones/addresses and duplicate merge UI; CardDAV and LDAP synchronization/UI remain.
- OpenPGP roadmap scope is implemented end-to-end: per-user keyring, generate/import/export/delete, passphrase test/change, identity binding, sign/encrypt/sign+encrypt, PGP/MIME + inline PGP, verify/decrypt, trust/fingerprint UI, WKD and optional HTTPS HKP. Real `cargo test` and interoperability regression coverage are still release-gate work.
- TNEF/`winmail.dat` decoding and full SMTP DSN negotiation are still not implemented. SMTPUTF8/IDN behavior still requires the real-server compatibility matrix from the release plan.
- IMAP ACL/shared-folder management and full capabilities settings UI remain the next major protocol block.
- Spam backend adapters for rspamd/SpamAssassin/custom command.
- Calendar Month/Week/Day/Agenda views are present; recurrence expansion/exceptions, invitation response workflow and CalDAV remain.
- Full CardDAV synchronization.
- Password-change adapters and persistent cross-restart session inventory/device metadata. Live cross-browser sessions can already be listed/revoked while the process is running.
- Diagnostics now includes IMAP reconnect, SMTP connectivity, index rebuild and last local folder/message synchronization metadata; deeper background task/queue metrics and repair workflows remain.
- Full security, acceptance and performance matrix from `docs/RUSTBOX_PLAN.md`.
## UI reliability / workflow fixes in the current snapshot
- Contact editor, calendar, raw-header and message-source dialogs use viewport-bounded layouts with independent scrolling and non-overlapping actions. Generic dialogs also fall back to whole-card scrolling when their content exceeds the browser workspace. Settings uses an explicit header + flexible-content grid so short panels no longer push the navigation/content block toward the bottom of the modal; settings navigation/content scroll independently when needed.
- Month calendar grid and toolbar layout are responsive and remain usable under browser/UI scaling.
- UI scale now affects font size, row height, pane widths, icons, field/button padding and control/header dimensions without being overwritten by the separate font-size setting.
- Responsive layout keeps user-selected folder/message pane widths within safe viewport bounds instead of reverting to fixed widths.
- Application actions have reusable success/error/warning/info toast feedback, including from within native modal dialogs.
- Primary and bulk message toolbars include Spam / Not spam, driven by the configured Junk folder.
- Reader includes Print, Source viewer and quick Create-filter-from-sender actions.
- Header viewer shows a structured common-header summary and the raw header block.
- vCard/iCalendar attachment SVG action icons no longer leak their markup as visible text; reader cleanup also strips only RustBox-owned icon-sprite fragments from malformed MIME content.
- Message HTML receives an additional client-side sanitization pass before sandboxed iframe rendering; plain text is preserved exactly.
- Embedded 0.0.1 UI assets are served with `Cache-Control: no-store` so development snapshots do not mix stale and current bundles.
- Native browser confirmation/text prompts are no longer used by the main UI workflows; destructive actions and folder/label/text choices use RustBox application dialogs.
- Message selection has an explicit mode: per-row checkboxes only appear while selecting, with select-all and bulk actions grouped in the selection toolbar.
- Search selection can materialize and select every cached matching result, not only the currently rendered page.
- Folder/message list state now preserves the last folder, loaded-page depth and scroll position; active searches also retain their query and scroll position during normal realtime/refresh flows.
- Network failures surface an offline/reconnecting banner. Only idempotent GET/HEAD requests receive bounded automatic retries; send/move/delete and other mutating requests are never auto-replayed.
- Toasts with actions keep Undo and the close button adjacent in a dedicated action group so closing a toast cannot trigger Undo.
- MOVE-based actions expose a toast Undo only when the backend can identify the server-assigned destination UID without guessing; bulk Undo reverses resolved moves in reverse order.
- Thread lookup now validates complete References Message-ID tokens after the SQL candidate query, preventing partial-ID false matches.
- Safe attachment previews stay inside a RustBox modal instead of opening a browser popup.
- Composer uploads expose progress, clipboard images become CID inline attachments, and browser-local recovery preserves edits when a draft save fails.
- Compact/comfortable density now visibly affects controls/toolbars/dialog headers without overwriting the separate row-height and pane-width preferences.
- Toasts show the remaining auto-dismiss time and pause their countdown while hovered or keyboard-focused.
- Appearance settings include Compact, Balanced, Comfortable and Reading layout presets persisted through display preferences.
- Composing settings now persist the default format, autosave interval, default priority, default read-receipt request, attachment-reminder behavior, default font, reply placement, quote style, forward mode and browser spellcheck through display preferences.
- Message Print uses an in-page print frame instead of a popup and prints sanitized HTML or plain text with From/To/Date metadata.
+23
View File
@@ -0,0 +1,23 @@
# Releasing RustBox
1. Update the version in `Cargo.toml` and the RustBox package entry in `Cargo.lock`.
2. Confirm `UPSTREAM_BASE` is the Oxi revision actually consumed by the release.
3. Ensure no TypeScript sources or separate frontend build dependencies are present.
4. Run:
```bash
cargo fmt --all -- --check
cargo test --locked
cargo clippy --locked --all-targets -- -D warnings
./scripts/build-release.sh
```
5. Verify:
```bash
./target/release/rustbox --version
RUSTBOX_CONFIG=./config.dev.toml ./target/release/rustbox --check-config
```
6. Package the repository without `target/`, `.dev/` or `.git/`.
7. Generate SHA-256 sums for release archives.
+107
View File
@@ -0,0 +1,107 @@
# RustBox 0.0.1 — remaining roadmap gaps
Snapshot after the OpenPGP/key-lifecycle and unbounded Sieve action/condition work in this iteration.
## OpenPGP status
OpenPGP is functionally complete for the scope defined in `RUSTBOX_PLAN.md` §9:
- generate/import/export/delete public and private keys;
- per-user protected keyring and identity assignment;
- passphrase validation and passphrase change (GnuPG is used only for secret-packet re-wrapping; passphrases are sent via stdin/status-fd, never argv or database);
- sign, encrypt, sign+encrypt, PGP/MIME and inline OpenPGP;
- verify/decrypt with signer fingerprint, trust and invalid-signature warning;
- recipient-key checks, public-key attachment, WKD and optional HTTPS HKP discovery;
- private-key filesystem isolation and export policy.
`RUSTBOX_PGP_GPG_BINARY` may override the `gpg` executable used by the passphrase-change operation. Other cryptographic operations use rPGP directly.
## Remaining functional items — 45
### Advanced IMAP / shared folders / ACL — 11
- [ ] Namespace/shared/global folder browser driven by NAMESPACE.
- [ ] GETACL read path.
- [ ] SETACL rights editor.
- [ ] DELETEACL entry removal.
- [ ] Inherited/default rights presentation where the server exposes it.
- [ ] Clear own/shared/global folder distinction in the folder tree.
- [ ] Full production QRESYNC resynchronization path.
- [ ] Server-side SORT when advertised.
- [ ] Server-side THREAD when advertised.
- [ ] LIST-EXTENDED production behavior when advertised.
- [ ] Complete UTF8/UTF8=ACCEPT behavior across mailbox/message edge cases.
### Contacts / calendars — 12
- [ ] CardDAV discovery.
- [ ] Multiple CardDAV address books.
- [ ] CardDAV sync-token + ETag synchronization.
- [ ] CardDAV conflict/retry/delete synchronization.
- [ ] LDAP address-book adapter (RO/RW policy-driven).
- [ ] CalDAV discovery.
- [ ] Multiple and shared CalDAV calendars.
- [ ] CalDAV sync-token + ETag synchronization.
- [ ] Recurrence expansion, exceptions and edit semantics.
- [ ] Full timezone correctness behavior.
- [ ] iTIP invitation parsing/delivery workflow.
- [ ] Accept / Decline / Tentative invitation responses.
### Core mail / composer / Sieve — 7
- [ ] Full SMTP DSN negotiation.
- [ ] TNEF / `winmail.dat` decoding.
- [ ] Complete identity/signature default policy for every new/reply/forward edge case.
- [ ] Persistent multi-step Undo history beyond the current safe single MOVE undo.
- [ ] Arbitrarily branching visual Sieve groups, e.g. `(A AND (B OR C))`; the builder now supports an unlimited left-nested AND/OR chain.
- [ ] Full capability-aware Sieve condition/action matrix for all advertised extensions.
- [ ] Visual editing of existing non-RustBox/raw Sieve rules without falling back to raw text.
### Spam / password / account integration — 11
- [ ] rspamd HTTP spam adapter.
- [ ] SpamAssassin adapter.
- [ ] Custom spam-command adapter.
- [ ] Password-change API adapter.
- [ ] Password-change LDAP adapter.
- [ ] Password-change SQL adapter.
- [ ] Password-change PAM/command adapter.
- [ ] Persistent session inventory/device metadata across process restarts.
- [ ] Administrator-facing autologout/remember-me policy controls.
- [ ] New-user/onboarding identity workflow.
- [ ] Optional login → mailbox/address mapping (virtuser equivalent).
### Search / notifications / diagnostics — 4
- [ ] Complete attachment content/metadata indexing policy and limits.
- [ ] Background/service-worker notifications while the page is inactive, if retained for 0.0.1.
- [ ] Richer per-account notification policy beyond global/per-folder controls.
- [ ] Background task/queue status plus recent-error/repair workflows.
## UI / i18n work still required (not counted as separate functional features)
- Final Settings information architecture: General, Message view, separate Signatures, Autoresponder, Contacts, Calendar, Encryption, Privacy, Security and Sessions.
- Complete keyboard-only/focus-order/accessibility audit.
- Remaining hard-coded EN/PL strings moved to locale files.
- Missing-key detection/fallback audit.
- Locale-aware date/time/number formatting audit.
- Documentation/structure for additional languages.
## Release/security/acceptance work (not counted in the 45 functional items)
- complete HTML/CSS/SVG sanitizer regression matrix;
- tracking-pixel/data-URI/CID matrix;
- malformed/nested MIME and huge-message tests;
- CRLF/header injection, CSRF, XSS and cross-account authorization matrix;
- session fixation/hijacking and secure-cookie verification;
- archive/ZIP-bomb and dangerous-filename tests;
- temporary-storage cleanup verification;
- OpenPGP key-isolation/passphrase/PGP-MIME regression matrix;
- `cargo fmt --check`, `cargo clippy --all-targets`, `cargo test`, release build;
- Dovecot/Postfix/ManageSieve real-server matrix;
- SMTPUTF8/IDN real-server compatibility;
- large mailbox/large attachment/performance tests;
- long-running IDLE/reconnect storm/UIDVALIDITY/index-consistency tests;
- memory stability and restart/resume tests.
OpenPGP is no longer a functional blocker. The largest remaining feature blockers are shared folders/ACL, CardDAV/CalDAV+iTIP and integration adapters. The release remains blocked by the real Rust/server/security/performance gate until those tests are executed successfully.
+1357
View File
File diff suppressed because it is too large. Load diff
+21
View File
@@ -0,0 +1,21 @@
# RustBox UI
RustBox owns its browser interface under `src/web/`.
Design direction:
- mail-first three-pane layout: folders, message list, message reader;
- compact typography and spacing, small radii, flat surfaces and restrained color use;
- dark, light and system themes;
- compact/comfortable density, preview-pane position and UI scale preferences;
- a single embedded SVG icon sprite for interface actions;
- no CSS gradients and no Unicode pseudo-icons;
- HTML compose formatting, threaded reading, folder operations and ManageSieve filters.
The supplied RustProxy source was used as a reference for disciplined asset organization, modular CSS, compact typography and Cargo-driven UI assembly. RustBox does not depend on RustProxy at runtime and retains its own mail-oriented layout and components.
## Build
`build.rs` reads `src/web/css/manifest.txt`, concatenates the CSS modules in the declared order and writes the bundle to Cargo `OUT_DIR`. `src/ui.rs` embeds that bundle together with `index.html`, `app.js` and `icons.svg` into the RustBox executable.
No Node.js, Bun, TypeScript, React or Next.js build step exists.
+134
View File
@@ -0,0 +1,134 @@
# Oxi upstream policy
RustBox is derived from `c0h1b4/oxi`. `UPSTREAM_BASE` contains the exact Oxi commit whose backend changes have been consumed by RustBox.
RustBox uses a flat Cargo layout, while Oxi uses a `backend/` subtree. The sync tooling therefore treats Oxi as a source upstream and maps its backend paths into RustBox rather than reintroducing the Oxi directory layout.
## Path mapping
Examples:
```text
Oxi backend/Cargo.toml -> RustBox Cargo.toml
Oxi backend/Cargo.lock -> RustBox Cargo.lock
Oxi backend/rust-toolchain.toml -> RustBox rust-toolchain.toml
Oxi backend/src/... -> RustBox src/...
Oxi backend/migrations/... -> RustBox migrations/...
Oxi backend/tests/... -> RustBox tests/...
Oxi backend/examples/... -> RustBox examples/...
Oxi backend/docs/... -> RustBox docs/...
```
RustBox-owned `src/web/` has no automatic mapping from the Oxi frontend.
## Configure the upstream
A release archive does not contain `.git`. Initialize the RustBox repository once:
```bash
git init
git add .
git commit -m "RustBox 0.0.1 baseline"
./scripts/setup-upstream.sh
```
The script adds:
```text
upstream-oxi -> https://github.com/c0h1b4/oxi.git
```
and fetches Oxi history/tags.
## Inspect a newer Oxi state
```bash
./scripts/oxi-status.sh
```
or inspect a specific Oxi ref:
```bash
./scripts/oxi-status.sh upstream-oxi/main
./scripts/oxi-status.sh <tag-or-commit>
```
The report separates:
1. Oxi `backend/` changes that can be mapped into RustBox;
2. Oxi `frontend/` changes that require a manual UI port;
3. other Oxi root-level changes that require manual review;
4. upstream commits since `UPSTREAM_BASE`.
## Advance the consumed Oxi backend state
```bash
./scripts/sync-upstream.sh
```
The operation:
1. requires a clean RustBox Git worktree;
2. fetches `upstream-oxi`;
3. verifies that the target descends from the recorded `UPSTREAM_BASE`;
4. creates a `sync/oxi-*` review branch;
5. generates the Oxi backend delta from `UPSTREAM_BASE` to the target;
6. rewrites only patch metadata so `backend/<path>` becomes `<path>`;
7. applies the mapped delta with Git three-way merge support;
8. does not import Oxi frontend sources;
9. records the target as a pending sync inside Git metadata;
10. deliberately leaves `UPSTREAM_BASE` unchanged until the maintainer finishes review.
Conflicts are expected when Oxi and RustBox changed the same functionality. Resolve them in the flat RustBox paths, keeping RustBox-specific behavior where required.
After resolving backend conflicts and porting any relevant UI behavior, finish the sync:
```bash
./scripts/finish-upstream.sh
```
If Oxi changed its frontend or root-level files, the finish step refuses to advance the baseline until you explicitly acknowledge those reviews:
```bash
./scripts/finish-upstream.sh --ui-reviewed --root-reviewed
```
The finish step runs the RustBox release build gate and only then stages the new `UPSTREAM_BASE`. Review `git status` and commit the sync. `--skip-build` exists for exceptional local workflows, but CI should still run the full gate before merge.
If the sync is rejected, discard the review branch; the main branch and its `UPSTREAM_BASE` remain unchanged.
## Port one Oxi feature
For a useful Oxi commit that should be brought in before a full baseline update:
```bash
./scripts/oxi-port-commit.sh <oxi-commit>
```
This creates `port/oxi-<sha>` and maps only the backend portion of that single commit. It intentionally does not change `UPSTREAM_BASE`, because RustBox has not consumed the complete Oxi history up to that revision.
When a later full sync includes a previously ported feature, Git may report that some hunks are already present; review those conflicts instead of duplicating the code.
## UI policy
Oxi frontend source is never copied into RustBox. For a new Oxi feature that includes frontend work:
- consume or port the backend/API changes;
- inspect the corresponding Oxi frontend diff to understand behavior;
- implement that behavior in RustBox `src/web/`;
- keep the same-origin RustBox API/UI model;
- do not add `.ts` or `.tsx` sources.
## RustBox-owned boundaries
These areas require explicit review and should not be replaced blindly by upstream changes:
- `src/web/`;
- `src/ui.rs`;
- RustBox UI routing and same-origin behavior;
- RustBox ManageSieve integration;
- `dev.sh`;
- native packaging/release scripts;
- RustBox branding and documentation.
The goal is to keep following Oxi protocol/backend improvements without restoring its split frontend/backend repository structure.
+28
View File
@@ -0,0 +1,28 @@
# RustBox validation
Release source checks:
- one root Cargo package (`Cargo.toml` at repository root);
- no `backend/` application directory;
- no separate `frontend/` directory;
- no `.ts` or `.tsx` source files;
- no Node/Bun/Next/React build dependency;
- UI files live under `src/web/` and are embedded into the Rust executable;
- mail endpoints are configuration-owned; the login request contains only email/password/session preference;
- authenticated mail routes reuse the resolved session connection profile;
- CSS is built by Cargo `build.rs` from `src/web/css/manifest.txt`;
- no CSS gradients and no Unicode pseudo-icons in the browser UI;
- all UI action icons are served from the embedded SVG sprite;
- `dev.sh` runs the root Cargo package;
- native release build outputs `target/release/rustbox`;
- `UPSTREAM_BASE` records the consumed Oxi backend revision;
- upstream tooling maps Oxi `backend/` deltas into RustBox's flat paths and never imports Oxi frontend source.
Full release gate on a host with Rust/Cargo and dependency access:
```bash
cargo fmt --all -- --check
cargo test --locked
cargo clippy --locked --all-targets -- -D warnings
./scripts/build-release.sh
```
+54
View File
@@ -0,0 +1,54 @@
# Request-path IMAP reuse
`RealImapClient` owns a pool shared by all request tasks using that client.
The identity includes host, port, TLS, email and password, stored as a SHA-256
digest of length-prefixed fields. Credential changes cannot reuse old sessions.
Each identity has at most three pooled connections, including connections being
established or exclusively leased. Checkout waits at most ten seconds for a slot.
Reused sessions must pass a ten-second NOOP; failed validation closes the socket
and checkout opens a replacement. TCP/TLS/LOGIN establishment is bounded by ten
seconds. Only a fully consumed, successful operation explicitly returns its
session. Errors and cancellation close it, so partial responses cannot leak into
another operation. No request operation is automatically retried.
Idle sessions expire after two minutes, checked on checkout and by a sweep every
30 seconds. The sweep removes unused identity entries too. Closing sockets avoids
IMAP CLOSE, which would expunge deleted messages. Selected-mailbox operations
always SELECT their own folder; STATUS and LIST do not rely on prior selection.
Background header sync discovers existing UIDs with one UID/flag fetch, filters
them to the requested range, and fetches headers in sets of at most 250 UIDs.
Large gaps left by deleted messages do not create empty FETCH batches.
Pooled paths: LIST, SELECT status, extended STATUS, headers, body, UID/flag
reconciliation, CONDSTORE changed flags, quota and folder-size reads. The public
trait and HTTP API remain unchanged. Dedicated realtime IDLE sessions still use `connect` directly.
Follow-up: pool mutations after auditing MOVE/UID EXPUNGE fallbacks that catch
protocol errors. Mutations retain fresh connections and logout.
Quota reads return sessions only after a matching tagged OK, including an empty
quota result. Unsupported QUOTA (NO/BAD) returns None but discards the lease.
Errors, EOF and quota timeouts discard it too. Folder-size reads reuse sessions
after successful FETCH completion (or an empty SELECT); a timed-out FETCH retains
the existing partial-size result but discards the unfinished session.
Debug logs include a short credential-identity digest prefix and checkout/return
actions (connect, reuse, discard, recycle), without logging credentials.
Tests use a local plaintext fake IMAP server and the actual async-imap client to
verify login reuse, error disposal, failed NOOP recovery, exclusive checkout
bounds, abandoned leases, credential isolation and stale-session eviction.
An ignored TLS regression can be run against a real server with credentials in
`TEST_IMAP_HOST`, `TEST_IMAP_EMAIL`, and `TEST_IMAP_PASSWORD`:
`cargo test real_tls_reads_reuse_one_login -- --ignored --nocapture`.
It asserts one connection for repeated LIST/SELECT/header/quota/size operations
on a server that returns tagged OK for quota requests (including no quota).
The original read-path pool did reuse TLS sessions, but omitted quota and size
reads. A server returning OK without quota data sends `/api/quota` into its
per-folder size fallback, opening and logging out one fresh connection per
folder while ordinary pooled sessions remain open. Regression coverage now
includes that fallback rather than only LIST and SELECT operations.
+26
View File
@@ -0,0 +1,26 @@
# RustBox 0.0.1
Initial development release of RustBox based on Oxi.
## Repository/runtime
- One Cargo package at repository root.
- Application source in `src/`.
- RustBox-owned browser UI in `src/web/`, embedded into the executable.
- No TypeScript, React, Next.js, Node.js or Bun build step.
- Development starts with `./dev.sh` or ordinary `cargo run`.
## Mail and UI
- Existing Oxi-derived IMAP/SMTP, synchronization, search, contacts/calendar and related backend functionality retained as the starting base.
- New compact three-pane RustBox interface with dark/light/system appearance, density/preview/scale preferences, threaded reading, HTML compose formatting and SVG-only action icons.
- IMAP/SMTP endpoints are configured only by the administrator; login accepts user email and password.
- Mail operations use the resolved connection profile stored in the authenticated session, fixing the Inbox 503 path where Sieve could work while mail routes considered the server unconfigured.
- ManageSieve integration with STARTTLS, implicit TLS and explicitly opt-in insecure transport.
## Oxi follow-up
- `UPSTREAM_BASE` records the consumed Oxi revision.
- Oxi's `backend/...` changes can be mapped to RustBox's flat repository paths using `scripts/sync-upstream.sh`.
- Individual Oxi backend commits can be ported with `scripts/oxi-port-commit.sh`.
- Oxi frontend sources are excluded; useful UI behavior is reimplemented in `src/web/`.