Skip to content

feat: harvest the v1 vault browser read path over the snapshot adapter - #971

Merged
FSM1 merged 2 commits into
mainfrom
feat/805-vault-browser-read-path
Aug 3, 2026
Merged

feat: harvest the v1 vault browser read path over the snapshot adapter#971
FSM1 merged 2 commits into
mainfrom
feat/805-vault-browser-read-path

Conversation

@FSM1

@FSM1 FSM1 commented Aug 2, 2026

Copy link
Copy Markdown
Owner

Brings back the v1 vault browser — app shell, breadcrumbs, folder listing, navigation — sourced entirely from the engine's snapshot adapter.

Closes #805

What lands

  • useFolderNavigation reads the snapshot store, keys on the routed node id, and calls setFocus on every navigation. A view is only listed once its folder matches the route, so a pull for the folder just left cannot paint under the new one.
  • Listings hydrate progressively: name and kind render from the child ref, size and mtime fill in when the projection lands.
  • Breadcrumbs walk the ancestor trail in SnapshotView. No materialised tree anywhere — folder reads stay direct-children-only per feat(engine): wire the facade cold-start pipeline and live resolve-tick driver #789.
  • AppSidebar keeps /files live and renders /shared, /bin, /settings inert with a coming-soon affordance for web: ship sharing, bin, settings, and invite views over the facade #643.
  • The per-node pending and deadLetter flags render as compact row markers, and the staleness rung renders in the footer.

Harvested from v1, rewritten

Structure and CSS come from v1; the data path is new.

  • components/layout/{AppShell,AppHeader,AppFooter,AppSidebar,NavItem,UserMenu,StatusIndicator}.tsx — markup and class names kept, all v1 hooks (search palette, MFA prompts, device approval, storage quota) dropped.
  • components/file-browser/{FileBrowser,FileList,FileListItem,Breadcrumbs,ParentDirRow,EmptyState}.tsx — read-only: no selection, no drag-drop, no context menu, no upload dropzone.
  • styles/{layout,file-browser,breadcrumbs,responsive}.css — pruned to the class set this slice renders, on the v2 tokens in index.css.
  • utils/format.tsformatBytes and formatDate only.

Deliberate scope note

SnapshotView gained one field, folderName. The ancestor trail starts at the folder's parent, so the listed folder's own name is not recoverable from the snapshot, and a host must not cache a name across a navigation or a bookmarked deep link. Without it the last breadcrumb is nameless and the browser cannot say where you are. The change is one field across crates/engine, crates/wasm, and the client protocol, with the wasm boundary test extended to assert it crosses as folderName.

Verification

Gates run locally, all green: pnpm -r typecheck, pnpm -r test (380 tests), eslint ., cargo fmt --all --check, cargo check --workspace --all-targets, cargo test -p cipherbox-engine -p cipherbox-wasm.

Puppeteer against the dev server confirms the shell grid, the sidebar's live/inert split, and the harvested CSS at desktop and mobile widths. A signed-in list render needs a live vault, which #809's login-and-CRUD e2e smoke covers.

Summary by CodeRabbit

  • New Features

    • Added a terminal-style file browser with folder navigation, breadcrumbs, file metadata, queue statuses, loading and error states, and empty-directory messaging.
    • Added authenticated application layout with header, sidebar navigation, user menu, footer, and vault sync status indicator.
    • Added responsive mobile layouts and keyboard-accessible navigation.
    • Added accurate folder names, file sizes, modification dates, and route-based folder links.
  • Bug Fixes

    • Unauthenticated access to Files now returns to the login page.
    • Improved handling of invalid and stale folder routes.

@coderabbitai

coderabbitai Bot commented Aug 2, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@FSM1, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 37 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 68e1af29-c5e4-4c22-9e88-66a0a7c80c75

📥 Commits

Reviewing files that changed from the base of the PR and between e770ba2 and 2d3a75b.

📒 Files selected for processing (40)
  • apps/web/src/App.test.tsx
  • apps/web/src/components/file-browser/Breadcrumbs.tsx
  • apps/web/src/components/file-browser/EmptyState.tsx
  • apps/web/src/components/file-browser/FileBrowser.tsx
  • apps/web/src/components/file-browser/FileList.tsx
  • apps/web/src/components/file-browser/FileListItem.tsx
  • apps/web/src/components/file-browser/ParentDirRow.tsx
  • apps/web/src/components/layout/AppFooter.tsx
  • apps/web/src/components/layout/AppHeader.tsx
  • apps/web/src/components/layout/AppShell.tsx
  • apps/web/src/components/layout/AppSidebar.tsx
  • apps/web/src/components/layout/NavItem.tsx
  • apps/web/src/components/layout/StatusIndicator.tsx
  • apps/web/src/components/layout/UserMenu.test.tsx
  • apps/web/src/components/layout/UserMenu.tsx
  • apps/web/src/engine/snapshotStore.ts
  • apps/web/src/engine/testFakes.ts
  • apps/web/src/lib/nodeId.test.ts
  • apps/web/src/lib/nodeId.ts
  • apps/web/src/main.tsx
  • apps/web/src/routes/FilesPage.tsx
  • apps/web/src/styles/breadcrumbs.css
  • apps/web/src/styles/file-browser.css
  • apps/web/src/styles/layout.css
  • apps/web/src/styles/responsive.css
  • apps/web/src/utils/format.ts
  • apps/web/src/vault/listing.test.ts
  • apps/web/src/vault/listing.ts
  • apps/web/src/vault/useFolderNavigation.test.tsx
  • apps/web/src/vault/useFolderNavigation.ts
  • crates/engine/src/facade.rs
  • crates/wasm/src/lib.rs
  • crates/wasm/tests/boundary.rs
  • packages/client/src/broadcastTransport.test.ts
  • packages/client/src/index.ts
  • packages/client/src/testkit.ts
  • packages/client/src/worker/commandCodec.test.ts
  • packages/client/src/worker/commandCodec.ts
  • packages/client/src/worker/engineWasm.ts
  • packages/client/src/worker/protocol.ts

Walkthrough

The PR restores the authenticated vault browser read path. It adds snapshot folder names, route-driven navigation, file listings, breadcrumbs, application shell components, responsive styling, and authentication route handling.

Changes

Vault browser read path

Layer / File(s) Summary
Snapshot folder-name contract
crates/engine/src/facade.rs, crates/wasm/..., packages/client/src/worker/...
Snapshot folder names now cross the engine, WASM, worker, and client transport boundaries.
Route and snapshot navigation
apps/web/src/lib/nodeId.ts, apps/web/src/vault/..., apps/web/src/utils/format.ts
The web app parses folder routes, synchronizes snapshot focus, rejects stale results, derives breadcrumbs, and projects sorted listing rows.
File-browser interaction
apps/web/src/components/file-browser/*
The browser renders breadcrumbs, listings, parent navigation, loading and error states, queue status, and empty directories.
Application shell and responsive presentation
apps/web/src/components/layout/*, apps/web/src/styles/*, apps/web/src/main.tsx
The app now renders the shell, navigation, user menu, status indicator, terminal styling, and mobile layouts.
Authenticated files route
apps/web/src/routes/FilesPage.tsx, apps/web/src/App.test.tsx
The files route checks authentication, redirects signed-out sessions, and renders the browser inside the shell. Tests cover authenticated and signed-out routing.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant FilesPage
  participant useFolderNavigation
  participant SnapshotStore
  participant FileBrowser

  User->>FilesPage: open /files
  FilesPage->>useFolderNavigation: load route state
  useFolderNavigation->>SnapshotStore: set folder focus
  SnapshotStore-->>useFolderNavigation: return snapshot
  useFolderNavigation->>FileBrowser: provide rows and breadcrumbs
  FileBrowser-->>User: render vault contents
Loading

Possibly related PRs

  • FSM1/cipher-box#883: Introduces the routing and client snapshot structures extended by this authenticated browser flow.
  • FSM1/cipher-box#899: Adds snapshot-store and test-fake infrastructure reused by the browser.
  • FSM1/cipher-box#911: Provides the authentication integration used by FilesPage and route tests.

Suggested labels: release:web:feat

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes restoring the v1 vault browser read path through the snapshot adapter.
Linked Issues check ✅ Passed The changes implement snapshot-based browsing, navigation, breadcrumbs, hydration, disabled routes, status markers, and required tests for issue #805.
Out of Scope Changes check ✅ Passed The listed changes support the vault browser read path, its engine seams, UI styling, protocol propagation, and verification.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/805-vault-browser-read-path

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@FSM1
FSM1 marked this pull request as ready for review August 3, 2026 12:47

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/web/src/components/file-browser/FileBrowser.tsx`:
- Around line 26-34: Update the EmptyState rendering condition in FileBrowser so
it only renders when the current folder is root and rows.length is zero.
Preserve the existing FileList behavior for empty non-root folders, including
the parent navigation row.

In `@apps/web/src/components/file-browser/FileListItem.tsx`:
- Around line 24-28: Update the onKeyDown handler in FileListItem to invoke
open() for both Enter and Space keys, while preserving preventDefault and
ignoring other keys, matching ParentDirRow’s keyboard activation behavior.

In `@apps/web/src/components/layout/UserMenu.tsx`:
- Around line 11-38: Move the Escape key handling from the user-menu-trigger
button to the outer user-menu container so Escape closes the menu when focus is
on LogoutButton or another descendant. Add outside-interaction handling while
isOpen, such as a document-level click or focusout listener, to close the menu
for interactions outside the container, including touch input; preserve the
existing hover and toggle behavior.

In `@apps/web/src/vault/listing.ts`:
- Around line 56-58: Update projected to avoid converting bigint descriptor
values with Number; use bigint-aware formatting for size and mtime, and guard
mtime against the safe Date range before formatting. Preserve UNRESOLVED for
null values and ensure oversized timestamps render safely rather than losing
precision or producing an invalid date.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 7dfb3b6d-d15a-4160-905a-5d2b621bbabe

📥 Commits

Reviewing files that changed from the base of the PR and between 7a17c9f and e770ba2.

📒 Files selected for processing (39)
  • apps/web/src/App.test.tsx
  • apps/web/src/components/file-browser/Breadcrumbs.tsx
  • apps/web/src/components/file-browser/EmptyState.tsx
  • apps/web/src/components/file-browser/FileBrowser.tsx
  • apps/web/src/components/file-browser/FileList.tsx
  • apps/web/src/components/file-browser/FileListItem.tsx
  • apps/web/src/components/file-browser/ParentDirRow.tsx
  • apps/web/src/components/layout/AppFooter.tsx
  • apps/web/src/components/layout/AppHeader.tsx
  • apps/web/src/components/layout/AppShell.tsx
  • apps/web/src/components/layout/AppSidebar.tsx
  • apps/web/src/components/layout/NavItem.tsx
  • apps/web/src/components/layout/StatusIndicator.tsx
  • apps/web/src/components/layout/UserMenu.tsx
  • apps/web/src/engine/snapshotStore.ts
  • apps/web/src/engine/testFakes.ts
  • apps/web/src/lib/nodeId.test.ts
  • apps/web/src/lib/nodeId.ts
  • apps/web/src/main.tsx
  • apps/web/src/routes/FilesPage.tsx
  • apps/web/src/styles/breadcrumbs.css
  • apps/web/src/styles/file-browser.css
  • apps/web/src/styles/layout.css
  • apps/web/src/styles/responsive.css
  • apps/web/src/utils/format.ts
  • apps/web/src/vault/listing.test.ts
  • apps/web/src/vault/listing.ts
  • apps/web/src/vault/useFolderNavigation.test.tsx
  • apps/web/src/vault/useFolderNavigation.ts
  • crates/engine/src/facade.rs
  • crates/wasm/src/lib.rs
  • crates/wasm/tests/boundary.rs
  • packages/client/src/broadcastTransport.test.ts
  • packages/client/src/index.ts
  • packages/client/src/testkit.ts
  • packages/client/src/worker/commandCodec.test.ts
  • packages/client/src/worker/commandCodec.ts
  • packages/client/src/worker/engineWasm.ts
  • packages/client/src/worker/protocol.ts

Comment thread apps/web/src/components/file-browser/FileBrowser.tsx
Comment thread apps/web/src/components/file-browser/FileListItem.tsx
Comment thread apps/web/src/components/layout/UserMenu.tsx
Comment thread apps/web/src/vault/listing.ts Outdated
@FSM1
FSM1 marked this pull request as draft August 3, 2026 18:48
…dapter

Brings back the v1 vault browser — app shell, breadcrumbs, folder listing,
navigation — sourced entirely from the engine's snapshot adapter.

`useFolderNavigation` reads the snapshot store, keys on the routed node id,
and moves the engine's focus window on every navigation. A view is only
listed once its `folder` matches the route, so a pull for the folder just
left cannot paint under the new one. Listings hydrate progressively: name
and kind render from the child ref, size and mtime fill in when the
projection lands.

Breadcrumbs walk the ancestor trail the snapshot carries. That trail starts
at the folder's parent, so `SnapshotView` now also carries the listed
folder's own name — a host cannot recover it from `ancestors` and must not
cache a name across a navigation.

The sidebar keeps /files live and renders /shared, /bin and /settings inert
with a coming-soon affordance for #643.

Closes #805
@FSM1
FSM1 force-pushed the feat/805-vault-browser-read-path branch from e770ba2 to 32d521a Compare August 3, 2026 18:53
The engine's mtime is a u64, but JS `Date` tops out at 8.64e15 ms. Past that
`Intl.DateTimeFormat` throws `RangeError: Invalid time value`, so a single
child ref authored elsewhere blanked the whole listing. Render those as `-`.

Also activate a file row on Space, matching the `[..]` row beside it, and move
the user menu's Escape handler onto the container so it still closes once focus
moves into the dropdown.
@FSM1
FSM1 marked this pull request as ready for review August 3, 2026 19:13
@FSM1
FSM1 merged commit 6ab2a3c into main Aug 3, 2026
22 of 23 checks passed
@FSM1
FSM1 deleted the feat/805-vault-browser-read-path branch August 3, 2026 19:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

web: harvest the v1 vault browser read path over the snapshot adapter

1 participant