Skip to content

[PB-6505] Minimize secret data we store#2020

Open
TamaraFinogina wants to merge 10 commits into
masterfrom
minimize_stored_b2b
Open

[PB-6505] Minimize secret data we store#2020
TamaraFinogina wants to merge 10 commits into
masterfrom
minimize_stored_b2b

Conversation

@TamaraFinogina

@TamaraFinogina TamaraFinogina commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Description

This PR minimizes the data we store. We used to store the entire workspace (type WorkspaceData), but mostly used it for ID and mnemonic. Unfortunately, WorkspaceData has phoneNumber, email, and address - all sensitive fields we never use.

It got highlighted by Git Security once before, but it got fooled by the switch from setItem to set.

Related Issues

Relates to PB-6505

Related Pull Requests

Checklist

  • Changes have been tested locally.
  • Unit tests have been written or updated as necessary.
  • The code adheres to the repository's coding standards.
  • Relevant documentation has been added or updated.
  • No new warnings or errors have been introduced.
  • SonarCloud issues have been reviewed and addressed.
  • QA Passed

Testing Process

  • Ensure that the workspace is displayed correctly.
  • Check that files can be uploaded to the business workspace and downloaded.
  • Check that switching between individual and business workspace works.

Additional Notes

The only line I'm not fully sure about is line 199 of src/app/store/slices/workspaces/workspacesStore.ts:

dispatch(workspacesActions.setSelectedWorkspace(selectedWorkspace));

Summary by CodeRabbit

  • Bug Fixes
    • Improved B2B workspace handling so the app consistently remembers the selected workspace and related settings.
    • Fixed workspace configuration and trash views to use the correct workspace identifier, reducing errors when switching between personal and workspace contexts.
    • Updated workspace sign-out/reset behavior to fully clear stored workspace data.

@TamaraFinogina TamaraFinogina self-assigned this Jul 2, 2026
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jul 2, 2026

Copy link
Copy Markdown

Deploying drive-web with  Cloudflare Pages  Cloudflare Pages

Latest commit: b9325b2
Status: ✅  Deploy successful!
Preview URL: https://b21b7aef.drive-web.pages.dev
Branch Preview URL: https://minimize-stored-b2b.drive-web.pages.dev

View logs

@TamaraFinogina TamaraFinogina requested a review from sg-gs July 2, 2026 19:21
@TamaraFinogina TamaraFinogina marked this pull request as ready for review July 6, 2026 07:48
@coderabbitai

coderabbitai Bot commented Jul 6, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

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

Next review available in: 21 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 29d1dec7-fc30-4b5c-aaba-c3920bb0f28a

📥 Commits

Reviewing files that changed from the base of the PR and between e09cf6d and 7252336.

📒 Files selected for processing (3)
  • src/app/drive/services/network.service/getEnvironmentConfig.test.ts
  • src/services/local-storage.service.test.ts
  • src/views/Trash/services/getTrash.service.ts
📝 Walkthrough

Walkthrough

This PR replaces the single JSON-serialized LocalStorageItem.B2Bworkspace key with two separate keys, B2BworkspaceId and B2BworkspaceMnemonic. The LocalStorageService API is updated to expose getB2BWorkspaceMnemonic, setB2BWorkspace, and clearB2BWorkspace, replacing getB2BWorkspace. Consumers across SDK factory, environment config, workspaces store, navigation service, DriveView, and trash service are updated accordingly, along with corresponding tests.

Changes

B2B Workspace Storage Refactor

Layer / File(s) Summary
LocalStorageItem enum and service API contract
src/app/core/types.ts, src/services/local-storage.service.ts, src/services/local-storage.service.test.ts
B2Bworkspace enum key is replaced by B2BworkspaceId and B2BworkspaceMnemonic; getB2BWorkspace is replaced by getB2BWorkspaceMnemonic, setB2BWorkspace, and clearB2BWorkspace in the interface and implementation, with matching test updates.
SDK factory workspace token lookup
src/app/core/factory/sdk/index.ts, src/app/core/factory/sdk/index.test.ts
getWorkspaceToken now checks LocalStorageItem.B2BworkspaceId to decide whether to parse WorkspaceCredentials.
Environment config workspace encryption key
src/app/drive/services/network.service/getEnvironmentConfig.ts, getEnvironmentConfig.test.ts
Encryption key for workspace context is now derived from getB2BWorkspaceMnemonic() and required for the workspace early-return, replacing getB2BWorkspace().
Workspaces store selection and persistence
src/app/store/slices/workspaces/workspacesStore.ts, workspacesStore.test.ts
Selection checks, unselect/select flows, setupWorkspace, and patchWorkspace persist via get(B2BworkspaceId), setB2BWorkspace, and clearB2BWorkspace instead of JSON-serializing full workspace objects.
Navigation service credential reset
src/services/navigation.service.ts
resetB2BWorkspaceCredentials calls clearB2BWorkspace() instead of writing 'null'.
DriveView workspace-from-url persistence
src/views/Drive/DriveView.tsx
setWorkspaceWithUrl calls setB2BWorkspace with workspace id and user key instead of writing JSON.
Trash service workspace id lookup
src/views/Trash/services/getTrash.service.ts, getTrash.service.test.ts
getWorkspaceTrashPaginated derives workspaceId via get(LocalStorageItem.B2BworkspaceId) instead of getB2BWorkspace().

Estimated code review effort: 2 (Simple) | ~15 minutes

Sequence Diagram(s)

sequenceDiagram
  participant UI as DriveView / TrashService / SdkFactory
  participant Store as workspacesStore
  participant LocalStorage as localStorageService

  UI->>LocalStorage: setB2BWorkspace(workspaceId, workspaceMnemonic)
  Store->>LocalStorage: get(B2BworkspaceId)
  LocalStorage-->>Store: workspaceId
  alt unselect workspace
    Store->>LocalStorage: clearB2BWorkspace()
  else fetch encryption key
    UI->>LocalStorage: getB2BWorkspaceMnemonic()
    LocalStorage-->>UI: mnemonic
  end
Loading

Related PRs: None identified.

Suggested labels: refactor, storage, workspaces

Suggested reviewers: None identified.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title is concise and clearly reflects the main change: reducing stored sensitive workspace data.
Description check ✅ Passed The description follows the template well and includes summary, issue link, related PR, checklist, testing process, and notes.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch minimize_stored_b2b

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.

@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: 2

🧹 Nitpick comments (3)
src/app/drive/services/network.service/getEnvironmentConfig.test.ts (1)

42-42: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Stale helper name after refactor.

createMockWorkspace now returns a plain mnemonic string ('workspace-key'), not a workspace object. Consider renaming to createMockWorkspaceMnemonic for clarity, since the old name is misleading post-refactor.

🤖 Prompt for 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.

In `@src/app/drive/services/network.service/getEnvironmentConfig.test.ts` at line
42, The helper name is stale after the refactor: `createMockWorkspace` now
returns a mnemonic string rather than a workspace object, so rename it to
`createMockWorkspaceMnemonic` in `getEnvironmentConfig.test.ts` and update any
nearby references to match the new meaning for clarity.
src/services/local-storage.service.ts (1)

2-2: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Minor API asymmetry: no getB2BWorkspaceId() accessor.

getB2BWorkspaceMnemonic() is exposed as a dedicated method, but callers needing the workspace id (SdkFactory, workspacesStore, getTrash.service) must import LocalStorageItem and call the generic get(LocalStorageItem.B2BworkspaceId) directly. Adding a matching getB2BWorkspaceId() would keep the service's encapsulation consistent for both halves of the same conceptual value.

♻️ Suggested addition
 function getB2BWorkspaceMnemonic(): string | null {
   return get(LocalStorageItem.B2BworkspaceMnemonic);
 }
+
+function getB2BWorkspaceId(): string | null {
+  return get(LocalStorageItem.B2BworkspaceId);
+}

Also applies to: 64-76, 115-117, 135-137

🤖 Prompt for 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.

In `@src/services/local-storage.service.ts` at line 2, Add a dedicated B2B
workspace ID accessor to LocalStorageService to match the existing
getB2BWorkspaceMnemonic() helper and avoid leaking LocalStorageItem usage to
callers. Update the LocalStorageService class by introducing getB2BWorkspaceId()
that reads the same underlying B2B workspace ID entry currently accessed via
LocalStorageItem.B2BworkspaceId, and then switch the affected call sites in
SdkFactory, workspacesStore, and getTrash.service to use the new method instead
of calling get(...) directly. Keep the naming and behavior consistent with the
existing mnemonic accessor so both parts of the workspace credentials API are
exposed symmetrically.
src/services/local-storage.service.test.ts (1)

127-127: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value

Seed B2BworkspaceId with a plain string

LocalStorageItem.B2BworkspaceId is stored as a raw workspace id, so JSON.stringify(mockWorkspaceData) is misleading here. Use a simple id fixture like 'test-workspace-id', or drop the seed if nothing reads it.

🤖 Prompt for 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.

In `@src/services/local-storage.service.test.ts` at line 127, The test setup is
seeding LocalStorageItem.B2BworkspaceId with a JSON string, but this key is
supposed to hold a raw workspace id. Update the localStorage fixture in
local-storage.service.test.ts to use a plain string value such as a simple
workspace id, or remove the seed entirely if LocalStorageItem.B2BworkspaceId is
not consumed by the test; keep the change focused around the
localStorage.setItem setup and any related
mockWorkspaceData/stringifyWorkspaceData usage.
🤖 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 `@src/app/store/slices/workspaces/workspacesStore.ts`:
- Around line 74-76: Delay the local workspace restore in
checkAndSetLocalWorkspace until fetchWorkspaces has finished populating state,
since the current B2BworkspaceId branch can run before
state.workspaces.selectedWorkspace and state.workspaces.workspaces are ready and
dispatch null. Update the login flow around
fetchWorkspaces/checkAndSetLocalWorkspace so restoration happens after the fetch
completes, or trigger the restore from the fetch completion path using the
existing workspacesStore logic and the LocalStorageItem.B2BworkspaceId check.

In `@src/views/Trash/services/getTrash.service.ts`:
- Around line 87-89: The workspaceId handling in getTrash.service.ts is unsafe
because localStorageService.get can return null and the current workspaceId as
string cast hides the missing-value case. Update getTrashItems call-site in the
getTrash service to explicitly guard for a missing B2BworkspaceId before calling
workspacesService.getTrashItems, and handle that branch appropriately instead of
forcing the nullable value through a cast. Use the existing workspaceId,
trashType, and getTrashItems symbols to keep the fix localized.

---

Nitpick comments:
In `@src/app/drive/services/network.service/getEnvironmentConfig.test.ts`:
- Line 42: The helper name is stale after the refactor: `createMockWorkspace`
now returns a mnemonic string rather than a workspace object, so rename it to
`createMockWorkspaceMnemonic` in `getEnvironmentConfig.test.ts` and update any
nearby references to match the new meaning for clarity.

In `@src/services/local-storage.service.test.ts`:
- Line 127: The test setup is seeding LocalStorageItem.B2BworkspaceId with a
JSON string, but this key is supposed to hold a raw workspace id. Update the
localStorage fixture in local-storage.service.test.ts to use a plain string
value such as a simple workspace id, or remove the seed entirely if
LocalStorageItem.B2BworkspaceId is not consumed by the test; keep the change
focused around the localStorage.setItem setup and any related
mockWorkspaceData/stringifyWorkspaceData usage.

In `@src/services/local-storage.service.ts`:
- Line 2: Add a dedicated B2B workspace ID accessor to LocalStorageService to
match the existing getB2BWorkspaceMnemonic() helper and avoid leaking
LocalStorageItem usage to callers. Update the LocalStorageService class by
introducing getB2BWorkspaceId() that reads the same underlying B2B workspace ID
entry currently accessed via LocalStorageItem.B2BworkspaceId, and then switch
the affected call sites in SdkFactory, workspacesStore, and getTrash.service to
use the new method instead of calling get(...) directly. Keep the naming and
behavior consistent with the existing mnemonic accessor so both parts of the
workspace credentials API are exposed symmetrically.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 460b80a9-71b4-45de-a165-640e5896e037

📥 Commits

Reviewing files that changed from the base of the PR and between ae2ae97 and e09cf6d.

📒 Files selected for processing (13)
  • src/app/core/factory/sdk/index.test.ts
  • src/app/core/factory/sdk/index.ts
  • src/app/core/types.ts
  • src/app/drive/services/network.service/getEnvironmentConfig.test.ts
  • src/app/drive/services/network.service/getEnvironmentConfig.ts
  • src/app/store/slices/workspaces/workspacesStore.test.ts
  • src/app/store/slices/workspaces/workspacesStore.ts
  • src/services/local-storage.service.test.ts
  • src/services/local-storage.service.ts
  • src/services/navigation.service.ts
  • src/views/Drive/DriveView.tsx
  • src/views/Trash/services/getTrash.service.test.ts
  • src/views/Trash/services/getTrash.service.ts

Comment on lines +74 to +76
const b2bWorkspaceId = localStorageService.get(LocalStorageItem.B2BworkspaceId);
if (b2bWorkspaceId) {
const workspaceId = b2bWorkspaceId;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
rg -n "checkAndSetLocalWorkspace|fetchWorkspaces\(" --type=ts -C3 -g '!*.test.ts'

Repository: internxt/drive-web

Length of output: 156


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Map the workspace store file and nearby symbols.
git ls-files 'src/app/store/slices/workspaces/*' 'src/app/**' | sed -n '1,200p'
echo '---'
ast-grep outline src/app/store/slices/workspaces/workspacesStore.ts --view expanded || true
echo '---'
sed -n '1,220p' src/app/store/slices/workspaces/workspacesStore.ts

echo '---SEARCH---'
rg -n "checkAndSetLocalWorkspace|setSelectedWorkspace|fetchWorkspaces|selectedWorkspace|workspaces\.workspaces|LocalStorageItem\.B2Bworkspace" src/app -g '!*.test.ts'

Repository: internxt/drive-web

Length of output: 37876


🏁 Script executed:

#!/bin/bash
set -euo pipefail

git ls-files 'src/app/store/slices/workspaces/*' 'src/app/**' | sed -n '1,200p'
echo '---'
ast-grep outline src/app/store/slices/workspaces/workspacesStore.ts --view expanded || true
echo '---'
sed -n '1,220p' src/app/store/slices/workspaces/workspacesStore.ts

echo '---SEARCH---'
rg -n "checkAndSetLocalWorkspace|setSelectedWorkspace|fetchWorkspaces|selectedWorkspace|workspaces\.workspaces|LocalStorageItem\.B2Bworkspace" src/app -g '!*.test.ts'

Repository: internxt/drive-web

Length of output: 37876


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '---REDUCERS---'
sed -n '235,390p' src/app/store/slices/workspaces/workspacesStore.ts

echo '---BOOTSTRAP SEARCH---'
rg -n "workspaceThunks\.(checkAndSetLocalWorkspace|fetchWorkspaces)|checkAndSetLocalWorkspace\(|fetchWorkspaces\(" src/app src -g '!*.test.ts'

echo '---INIT FILES CANDIDATES---'
git ls-files 'src/app/**/index.ts' 'src/app/**/index.tsx' 'src/app/**/App*' 'src/app/**/bootstrap*' 'src/app/**/main*' 'src/app/**/store*' | sed -n '1,200p'

Repository: internxt/drive-web

Length of output: 8442


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '---GLOBAL SEARCH---'
rg -n "checkAndSetLocalWorkspace|fetchWorkspaces|workspaceThunks" . -g '!*.test.ts' -g '!node_modules/**'

echo '---FILES WITH APP INIT/BOOT---'
fd -H -a 'index.ts|index.tsx|main.ts|main.tsx|App.tsx|bootstrap.ts|bootstrap.tsx' src app . 2>/dev/null | sed -n '1,200p' || true

Repository: internxt/drive-web

Length of output: 15589


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '---GLOBAL SEARCH---'
rg -n "checkAndSetLocalWorkspace|fetchWorkspaces|workspaceThunks" . -g '!*.test.ts' -g '!node_modules/**'

echo '---BOOT FILES---'
fd -H -a 'index.ts|index.tsx|main.ts|main.tsx|App.tsx|bootstrap.ts|bootstrap.tsx' src . 2>/dev/null | sed -n '1,200p' || true

Repository: internxt/drive-web

Length of output: 15575


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '---AUTH INIT SECTION---'
sed -n '560,620p' src/services/auth.service.ts

echo '---APP INIT SECTION---'
sed -n '120,150p' src/App.tsx

echo '---NAVIGATION SERVICE SECTION---'
sed -n '60,95p' src/services/navigation.service.ts

Repository: internxt/drive-web

Length of output: 4363


Delay local-workspace restoration until fetchWorkspaces() has populated state
checkAndSetLocalWorkspace() is dispatched immediately after fetchWorkspaces() in the login flow, so this branch can run while state.workspaces.selectedWorkspace and state.workspaces.workspaces are still empty. It then dispatches null, and the saved B2B workspace is lost. Await the fetch before restoring, or re-run this from the fetch completion path.

🤖 Prompt for 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.

In `@src/app/store/slices/workspaces/workspacesStore.ts` around lines 74 - 76,
Delay the local workspace restore in checkAndSetLocalWorkspace until
fetchWorkspaces has finished populating state, since the current B2BworkspaceId
branch can run before state.workspaces.selectedWorkspace and
state.workspaces.workspaces are ready and dispatch null. Update the login flow
around fetchWorkspaces/checkAndSetLocalWorkspace so restoration happens after
the fetch completes, or trigger the restore from the fetch completion path using
the existing workspacesStore logic and the LocalStorageItem.B2BworkspaceId
check.

Comment thread src/views/Trash/services/getTrash.service.ts Outdated
@sonarqubecloud

sonarqubecloud Bot commented Jul 7, 2026

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
64.9% Coverage on New Code (required ≥ 80%)

See analysis details on SonarQube Cloud

dispatch(workspacesActions.setSelectedWorkspace(null));
dispatch(workspacesActions.setCredentials(null));
localStorageService.set(LocalStorageItem.WorkspaceCredentials, 'null');
} else if (isSelectedWorkspace) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think that here mabye we should check if the workspace exists isSelectedWorkspace && isSelectedWorkspace && selectedWorkspace?.workspace.id === workspaceId to avoid unexpected errores, because before the workspace was already stored in local storage and now comes from redux and http calls.
Add an await or move these lines into a thunk that handles the situation to wait the workspaces fetch here

 await dispatch(workspaceThunks.fetchWorkspaces());
 dispatch(workspaceThunks.checkAndSetLocalWorkspace());

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.

2 participants