All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
- Consolidated the root and backend Cargo workspaces into one unified workspace with a single
Cargo.lock, removing the nestedbackend/Cargo.tomlworkspace and eliminating ambiguous dependency resolution. - Reduced development and test build overhead by setting
debug = 1in thedevandtestCargo profiles; this preserves line-level debugging while shrinking the target directory and improving test-linking times. - Updated CI so documentation-only and frontend-only changes no longer trigger the full Rust workflow; the DCO check now runs in its own always-on workflow.
-
Added safe asynchronous garbage collection for orphaned global
blobs/<sha256>objects, with durable coalesced candidates, a 24-hour default grace period, cross-process writer/collector locking, global reference checks, leased workers, conservative retry, metrics, and disabled-by-default operator controls. -
Separated the Notes filename from the first Markdown H1: the note name is now independently editable, changing the H1 does not rename the note, and renaming the note does not rewrite the H1.
-
Corrected Kanban comment actor attribution so the comment author matches the authenticated actor.
-
Made the internal-mail-server validation tests deterministic by serializing environment-variable mutations with an async mutex and restoring values after each test.
-
Restored skipped
FileThumbnaillifecycle tests and added coverage for prop-change replacement and object-URL cleanup.
- Hardened the production Compose contract by requiring same-host external TLS termination on a dedicated loopback port, preserving the validated upstream HTTPS scheme, probing dependency readiness, and pinning RustFS to an immutable image digest.
- Audited and hardened permission-aware AI indexing. All indexed note chunks now carry a canonical
IndexAclProjectionresolved from the authoritative permission model; retrieval pre-filters by tenant, caller principals, visibility, and embedding policy; missing, malformed, stale, and cross-tenant ACL data fail closed; share revocation and note lifecycle events propagate to the index without requiring a full rebuild. Added backend-agnostic contract tests against bothInMemoryVectorStoreandPgVectorStore.
- Aligned metadata-backend support and launch-readiness claims around PostgreSQL production deployments and target-environment release gates.
- Added safe WebUI editing for eligible vault files. Vaults now have a
write_policy(read_only,web_editing_enabled, orsync_client_only) defaulting toread_only. The WebUI can load and save Markdown/text files throughGET/PUT /api/vault-sync/v1/vaults/{id}/content/{*path}whenweb_editing_enabledis set, using optimistic revision locking to prevent silent overwrites. AddedPATCH /api/vault-sync/v1/vaults/{id}/write-policyfor policy updates, a vault detail page policy selector, and aVaultFileEditorcomponent with dirty state, conflict handling, and save shortcuts. - Added RustShare Mail Phase 3: IMAP selected import. Users can connect IMAP accounts with encrypted credentials, browse folders and messages, and create import jobs that copy selected messages into RustShare as durable mail artifacts. Includes account management, an import-job worker, audit events, and REST endpoints for accounts, folders, messages, and jobs.
- Added RustShare Mail Phase 4: archive jobs. Users can create folder/date-range IMAP archive jobs that incrementally copy messages into RustShare, resume from the last imported UID, apply optional retention soft-deletion, and retry failed runs with exponential backoff. Includes audit events and REST endpoints under
/api/v1/mail/accounts/{id}/archive-jobsand/api/v1/mail/archive-jobs/{id}. Refs #147. - Added RustShare Mail Phase 5 WebUI client. Users can manage IMAP accounts, browse folders and message summaries, queue selected imports, view archive/import status, read imported mail with sanitized HTML, inspect attachments, and manage links to RustShare objects.
- Hardened RustShare Mail daily-use workflows with idempotent outbound sends, account-bound sender identities, SMTP timeouts, durable import status, bounded classic search, IMAP special-use folders, modified UTF-7 labels, inline-image rendering, explicit partial-send warnings, safer draft replacement/cleanup, and reference-aware object cleanup queueing.
- Fixed RustShare Mail mailbox action gating so read/unread, archive, and trash buttons each key on their own folder availability, blocked scheme-relative and uppercase-scheme remote images in sanitized HTML, and kept deferred content-addressed blob keys from starving the object cleanup queue.
- Polished RustShare Mail release readiness: the local copy of sent mail now retains its Bcc recipients, reply headers emit RFC 5322 angle-bracketed message ids, mail view events no longer fail reads, import-job listings are bounded, the message-page composer tracks drafts end-to-end (update on re-save, discard after send, SMTP guard, forward attachment race), saving a draft reflects the real save result, the dead folder-mapping settings section and unreachable IMAP TLS options were removed, and the published OpenAPI contract was refreshed with a CI freshness check.
- Hardened RustShare Mail outbound safety: plaintext SMTP modes persisted before the ban are now rejected at send and test time, and send idempotency claims left pending by a crashed send are reclaimed after ten minutes so retries with the same key are never blocked forever. Fixed the integration-test environment-variable toggle so concurrent plaintext-SMTP tests no longer race and unset the override mid-send.
- Fixed a rustls 0.23 startup panic that blocked Gmail/real-provider IMAP and SMTP tests: the server now explicitly installs the
aws-lc-rsCryptoProvider before any TLS handshake. - Added an operator opt-in (
RUSTSHARE_ALLOW_INTERNAL_MAIL_SERVERS=true) for self-hosted or air-gapped deployments to use internal/private IMAP and SMTP servers;localhostremains rejected for SSRF safety. - Expanded the RustShare-style Mail workspace into a responsive three-pane webmail client with mailbox counts, remote message reading, bulk actions, search, move/star/delete controls, reply/reply-all/forward threading, drafts, attachments, RustShare imports, and synchronization activity. Settings → Mail was redesigned as account list plus selected-account details with collapsible sections, one unified save workflow, saved-vs-replace password states, and a Gmail provider preset.
- IMAP and SMTP connections to internal/private mail servers (opted in via
RUSTSHARE_ALLOW_INTERNAL_MAIL_SERVERS=true) now accept invalid or hostname-mismatched TLS certificates by default, since internal servers are commonly self-signed or reached by IP address. Public destinations always keep full verification, andRUSTSHARE_MAIL_TLS_ACCEPT_INVALID_CERTS=neverrestores strict verification for internal servers. - Fixed IMAP message listing against servers that return raw UTF-8 in ENVELOPE responses (e.g. Stalwart with UTF8=ACCEPT): message summaries are now fetched via
BODY.PEEK[HEADER]and parsed with mailparse, which handles both RFC 2047 encoded-words and raw UTF-8. - The compose dialog now uses compact labeled To/Cc/Bcc/Subject rows, an inline attachment strip, and a compact action footer. Forwards no longer emit
In-Reply-To/Referencesheaders, and forward drafts no longer persist the original message as a reply target, so forwarded mail starts a fresh thread in recipients' clients. - Compose now has a rich-text body editor (the same TipTap stack as the note editor) with a compact formatting toolbar; Cc/Bcc fields reveal on demand. Outbound mail and drafts carry a real
text/htmlalternative part rendered from sanitized Markdown, so sent mail renders as formatted HTML in recipients' clients instead of wrapped plain text. - Fixed imported mail and draft listings returning 500: the
mail_messages.reference_idscolumn aliasing broke the runtime row mapping in the paginated message and draft queries after a struct rename, which also made imported mail invisible in the workspace.
0.6.0 - 2026-06-29
- Added streaming download support for object storage via
ObjectStore::get_stream, preserving Content-Type and preserving Content-Length when integrity verification does not require EOF validation. Authenticated file downloads, file previews, and public-share downloads now return a streaming body instead of buffering the entire object in memory. - Added multipart upload streaming to temporary files, with automatic cleanup on success and error, and configurable size limits.
- Added unit and integration tests for large-object streaming upload/download, resumable-upload abort/cleanup, and low-memory
ObjectStore::get_streamconsumption. - Added request-scoped correlation IDs. Every HTTP request receives an
X-Request-ID(preserved from the client when valid, otherwise generated), propagated into tracing spans asrequest_id, and returned in response headers. - Added
X-Tenant-IDheader support for unauthenticated public-share and public-chat-unfurl requests. - Added tenant-scoped public share link resolution.
get_share_by_token,validate_and_create_session, andget_public_share_infonow require atenant_idand reject cross-tenant share tokens withShareNotFoundByToken. - Added
tenant_idto share-session JWT claims so share-session routes can scope share lookups to the issuing tenant. - Added HMAC-SHA256 signature verification for incoming chat webhook events.
- Added operational runbooks for backup/restore and security incidents.
- Added production-readiness documentation (
docs/PRODUCTION_READINESS.md) summarizing completed workstreams, residual risks, and operator checklists. - Implemented a functional admin SMTP test action.
POST /api/v1/admin/config/smtp/testnow sends a real test email to the acting admin's address using the stored SMTP configuration, replacing the previous501 Not Implementedstub. - Added ACL-aware indexing contract for OKF notes. Indexed note chunks now carry
NoteAclPayload(tenant, workspace, note id, source file/folder ids, owner, read ACL, visibility, ACL hash/version, embedding policy).ContentIndexersupportsindex_note,search_with_acl,update_note_acl, andremove_note_chunks.NoteServiceemits indexing callbacks through an optionalNoteIndexSink, wired to the sharedContentIndexerwhen AI is enabled. - Wired real permission-resolver principals into the AI index.
NoteIndexSinknow resolves owner, direct-share, group-share, and public principals so indexed chunks carry accurateread_aclvalues instead of the owner placeholder. - Persisted the AI vector index in PostgreSQL using pgvector. Added
note_index_chunkstable andPgVectorStoreimplementation; production builds use the database backend while in-memory storage remains available for tests. - Added frontend conflict-resolution actions for OKF notes, allowing users to choose YAML, folder-name, or a custom title when the note frontmatter and bundle metadata disagree.
- Added purpose color tags for files and notes. Users can assign a color to a file from the file browser and to a note from the note editor; colors are persisted on the file record (for files) and in note sidecar metadata (for notes) and returned in folder/share listings.
- Added full item action menus to Decisions, Meetings, and Standups module lists, matching the Notes module: Show attachments, Rename, Move to folder, Duplicate, and Delete. Added backend
moveandduplicateendpoints for all three module types.
- Aligned maximum upload size configuration with the existing
MAX_UPLOAD_SIZE_MBenvironment variable (default 5000 MB) for authenticated file uploads and file updates. - Restored distinct trust-boundary limits for public-share uploads (
MAX_PUBLIC_UPLOAD_SIZE, 100 MB) and resumable chunk uploads (MAX_CHUNK_SIZE, 100 MB). - Enforced HTTPS-only webhook registration; HTTP URLs are allowed only in debug builds or when
RUSTSHARE_ALLOW_HTTP_WEBHOOKSis set to"true"or"1". - Switched session and CSRF cookie defaults to
Secure=true. Opting out requires explicitly settingRUSTSHARE_SESSION_COOKIE_SECURE=false(or the legacySESSION_COOKIE_SECURE=false). - CI/CD workflows now generate per-run secrets via
openssl randinstead of using hardcoded values. - Updated
docs/security-model.mdanddocs/architecture.mdto document tenant isolation, secret rotation, webhook security, and request correlation IDs. - Bumped the OpenAPI specification version from
1.0.0to2.0.0to signal breaking contract changes (tenant-scoped share sessions, optionalX-Tenant-IDon public endpoints, new admin/security response fields).
- Removed the no-op PostgreSQL RLS context middleware. The middleware set
app.current_tenant_id/app.current_user_idon a connection that was returned to the pool before handlers ran, so handler queries never saw the context. Repository-level tenant filtering remains the primary isolation mechanism. - Removed the
rustshare migrate-notes-okfCLI binary and the OKF notes migration helpers (NoteMigrationReport,migrate_notes_to_okf, migration integration tests). No production deployments have legacy notes to migrate, so the migration path is unnecessary.
- Fixed the back button in the Markdown editor to return to the previous
/fileslocation (including folder and filter state) instead of always going to/notes. - Fixed the Markdown editor formatting toolbar so it remains visible (sticky) at the top of the editor while scrolling through long documents.
- Fixed the app layout height for non-files pages so the Markdown editor fills the available viewport and scrolls internally, keeping both the document header and formatting toolbar visible on long notes.
- Sanitized
Content-Dispositionfilename parameters to strip control characters, backslashes, and quotes. - Fixed resumable upload chunk integrity validation so
Content-MD5is verified as MD5 instead of being compared to SHA-256 chunk hashes. - Fixed resumable upload completion to assemble chunks through streaming temporary files instead of materializing full files in memory.
- Fixed concurrent resumable chunk uploads by using conditional chunk object writes and merging upload-session chunk state.
- Fixed ignored backend tests by re-enabling, replacing, or removing them with documented justifications.
- Resolved clippy warnings across all targets.
- Renamed the notes module primary action from "Create from Template" to "New note" and made the action label respect the module configuration instead of a hardcoded string.
- Addressed
cargo auditadvisories forrustls-webpkiand RSA. - Fixed permission resolver caching so source-aware lookups preserve owner, direct-share, group-share, inherited, and no-permission sources.
- Fixed inherited folder permission aggregation to select the highest active user share instead of an arbitrary share.
- Added object-store integrity checks for content-addressed
blobs/{sha256}uploads and downloads. - Fixed Markdown table preprocessing so backslashes no longer multiply on each save/load round-trip. Cell content is now rendered through markdown-it, preserving inline formatting and consuming escape sequences correctly.
- Fixed Markdown table serialization so cell content is treated as inline text. This prevents unnecessary escaping of block markers such as
1.,-, and#at the start of a table cell. - Fixed the Notes module list so clicking a note opens the note editor (
note.md) instead of the folder bundle.
- Added pre-commit/CI secret-scan gate to block hardcoded secrets in CI/CD, config, and shell files.
- Hardened multi-tenant isolation for share links: cross-tenant share tokens are no longer resolved.
- Enforced admin authentication on all
/api/v1/admin/*routes, including chat integration and replication admin endpoints. - Removed hardcoded credentials from GitHub Actions workflows.
- Documented required production secrets and rotation guidance in
docs/DEPLOYMENT.md,docs/CI_SECRETS.md, and.env.example. - Hardened chat webhook URLs against SSRF: registration and dispatch now reject loopback, private IPv4, link-local, multicast, CGNAT, localhost, and IPv4-mapped IPv6 addresses, with a 5-second DNS timeout and re-validation at dispatch time to mitigate DNS rebinding.
- Added replay-age checks for incoming chat webhook events: timestamps outside
RUSTSHARE_WEBHOOK_MAX_AGE_SECONDS(default 300) are rejected without revealing that the failure was a replay. - Re-verify current folder write permission when completing resumable uploads, and use current public-share permissions instead of stale JWT permission claims for public folder uploads.
- Prevented password-protected public share info from exposing filename, size, MIME type, or folder name before password-backed session creation.
- Restricted private user-share chat unfurls to the share recipient in the requesting tenant.
- Added explicit wrong-tenant regression coverage for infrastructure file and folder repository lookups.
- Disabled implicit object-store bucket creation by default; local/dev deployments can opt in with
RUSTSHARE_OBJECT_STORE_AUTO_CREATE_BUCKET=true.
0.5.1 - 2026-06-12
- Aligned
Cargo.lockandbackend/Cargo.lockwith the0.5.0workspace version. Thev0.5.0tag shipped with internal crates still listed as0.1.0in the lockfiles; this hotfix regenerates both lockfiles and bumpsbackend/Cargo.tomlworkspace.package.versionto0.5.0for consistency.
0.5.0 - 2026-06-12
- Added automatic OpenAPI specification generation (
/api-docs/openapi.json) and Swagger UI integration via utoipa. - Added optional bearer-token authentication for the Prometheus
/metricsendpoint (METRICS_API_TOKEN). - Added pagination support for file, folder, share, and module list endpoints.
- Added retention cleanup support and admin replication summary endpoints.
- Added OpenAPI annotation tooling (
backend/scripts/add_openapi_annotations.py).
- Redesigned the workspace overview dashboard to be backend-driven by enabled module metadata.
- Bumped Rust and npm dependencies via Dependabot rollup.
- Hardened CI pipelines: added PostgreSQL service to dependency checks, pinned
aws-smithy-typesandtimefor build compatibility, and enforced DCO sign-off.
- Removed stale root files and directories:
CLAUDE.md,convert_files.py,quick-fix.sh,test-deployment.sh, rootpackage-lock.json, and therustshare_public_preview_handover/directory.
- Fixed unbounded list views in the frontend by walking paginated endpoints for decisions, standups, meetings, shares, kanban boards, and brainstorming boards.
- Fixed CSRF lockout when a browser holds a stale session cookie but no CSRF cookie by exempting
POST /api/v1/auth/loginfrom CSRF checks. - Fixed hardcoded database credentials in test code; tests now require
DATABASE_URLor a local.envfile. - Fixed overlapping
/openapi.jsonroute.
- Removed hardcoded credentials from scripts and test helpers.
- Restricted access to the Prometheus
/metricsendpoint with an optional bearer token. - Improved dependency auditing with
cargo-denyandcargo-auditconfigurations.
0.4.0 - 2026-06-05
- Added third-party vault synchronization with Obsidian vault support.
- Added
/api/vault-sync/v1endpoints for vault creation, listing, manifest retrieval, file upload/download/delete/rename, and device registration. - Added the
rustshare-vault-syncObsidian plugin for manual vault synchronization. - Added vault file metadata, badges, and Obsidian deep links in the web UI.
- Added undo and redo controls to the markdown and note editor toolbars.
- Hardened vault sync state convergence and consistency behavior.
- Reduced the vault sync PR surface while preserving the v1 API contract.
- Fixed file content API prefix handling.
- Fixed folder drag-and-drop uploads in the web UI so dropped folders preserve their hierarchy.
- Fixed PDF previews in the web UI by allowing same-origin framing for file preview responses.
- Fixed vault sync atomic revision increments for upload, delete, and rename operations.
- Fixed vault sync handling for non-UUID device IDs when creating vaults.
- Fixed vault sync RLS, deleted-file filtering, API contract edge cases, content length handling, and unique-name behavior.
- Fixed the Obsidian plugin to detect MIME types and avoid unnecessary CSRF headers.
- Added vault sync authorization and tenant isolation coverage.
0.3.0 - 2026-06-02
Stable release for the 0.3.0 release line.
0.3.0-rc.1 - 2026-05-31
- Added backend activity feed support with cursor pagination and frontend activity wiring.
- Added readiness checks for database, object storage, events, and auth dependencies, with AI treated as optional.
- Added module event types and WebSocket invalidation coverage for module edits.
- Added shared UI states for loading, empty, error, offline, disabled, and unauthorized module workflows.
- Added canonical module/template contracts and expanded cross-tenant, share-link, attachment, search, AI permission, and module permission tests.
- Dashboard module rendering is now backend-driven through enabled module metadata instead of a static frontend registry.
- Module defaults now normalize toward canonical
/Workspace/<Module>paths while preserving read compatibility for legacy roots. - Documented permission-visible dashboard summary semantics, including directly shared Kanban boards whose module root is not shared.
- Documented attachment folder side-effect rules: upload may create the
attachments/folder, while read/list/delete paths must not.
- Fixed tenant propagation across services, handlers, WebSocket auth, and collaboration paths.
- Fixed public share access checks so revoked and expired shares are revalidated per request.
- Fixed activity event filtering for stored JSON event types.
- Fixed search and AI permission filtering to avoid exposing unauthorized content.
- Fixed attachment path traversal, hidden-file, metadata filtering, and portability edge cases.
- Kanban attachment deletion now rejects non-attachment files without deleting them or creating a missing
attachments/folder. - Kanban dashboard summaries now include directly shared board folders even when
/Workspace/Kanbanitself is not shared.
- Hardened tenant isolation and authorization contracts across module, share, search, AI, public upload, and attachment flows.
0.2.0 - 2026-05-26
- Real-time WebSocket sync for module edits, with collaborative cursor support and conflict resolution.
- Note bundle architecture: notes now store as folders with
index.md,.rustshare.json, andevents.jsonl, enabling richer metadata and attachment handling. - H1-based folder rename on save: editing the top-level heading in a note automatically renames its backing folder.
- Cross-user share isolation tests and public share validation.
- Dependency updates:
- Rust:
rand0.9 (with API migration),keyring4.0,uuid1.23, and other cargo dependency bumps. - Frontend: 37 npm dependency updates including SvelteKit, TanStack Query, and Excalidraw.
- Docker: Node.js 22 base image update.
- Rust:
- Meeting note creation:
- Fixed routing so folder-backed module artifacts (meetings, standups, kanban, notes, etc.) navigate to their dedicated editor instead of the generic file browser.
- Added a title prompt in
MeetingsModuleViewinstead of silently creating an "Untitled Meeting Note." - Fixed default meeting and standup
.rustshare.jsontemplate schemas to matchMeetingMetadataandStandupMetadatastructs.
- Frontend type safety: Fixed pre-existing svelte-check and eslint errors across
MarkdownEditor,KanbanCardModal,Topbar.test, admin forms, and dashboard widgets. - Backend tests: Hardened integration tests for cross-user isolation, validated JSON doctests, and brainstorming handler formatting.
- CI: Added
RUSTFS_ALLOW_INSECURE_DEFAULT_CREDENTIALSto integration test workflow; fixed DCO sign-off checks.