commit
bc5fbd6ba9
180 files changed
+63750
No files matched your search
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
File diff suppressed because it is too large.
Load diff
+21
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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
|
||||
```
|
||||
@@ -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.
|
||||
@@ -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/`.
|
||||
Reference in new issue
Block a user