Skip to main content

Workspace file evidence and reproduction

Use realm gj76anadpsc, workspace w-t5e2kcxjd, and Kubernetes context dev-north-alicloud. Use disposable files and two test users for sharing or authorization scenarios. Do not use another user's real workflow identifiers.

WSF-S001 — Browse, create, and root resolution​

  1. Open /admin/workspace without entering a user folder.
  2. Choose Create New → Add folder or Import.
  3. Observe whether the action resolves the current user's root.
  4. Enter the user's root folder and repeat.
  5. Inspect /workspace/v2/users: the contract is {folders: [...]}.

Expected: root actions select the signed-in user's root from folders, not the first visible root. Source currently reads roots || data in several root actions, while tests mock the obsolete roots shape.

WSF-S002 — Upload and partial completion​

  1. In a writable disposable folder, select two small files where one conflicts with an existing name.
  2. Import both in one selection.
  3. Observe the single batch error and refresh the folder.

Expected: each file shows pending, succeeded, failed, retry, and cancel state. Current requests run independently under Promise.all; one rejection suppresses refresh even though another upload may have committed.

WSF-S003 — Large transfer boundary​

  1. Inspect BFF upload middleware and Oqullus download handling.
  2. In a controlled environment, upload increasing file sizes and concurrent counts while recording BFF RSS, latency, HTTP status, and browser memory.
  3. Cancel or interrupt one transfer and inspect storage plus PostgreSQL.

Expected: documented limits, bounded concurrency, progress, cancellation, and no orphan. The source has no published limit and buffers each upload in BFF memory. Large-load execution remains pending to avoid destabilizing the shared sandbox.

  1. Share one disposable file with a second test user as Viewer.
  2. Verify read succeeds and edit/share/delete fail for that user.
  3. Copy the link from the list-view Share dialog and open it in a new tab.
  4. Compare it with the actual file route /admin/workspace/create/{publicId}.

Expected: the copied URL opens the exact authorized resource. Source currently copies /workspace/{publicId}, for which no application route exists. The page header Share action also targets the first paginated row, not an explicit selection.

WSF-S005 — Version history and revert​

  1. Save a disposable notebook at least three times with distinct content, with one rename or move between saves.
  2. Open Version History and inspect View Changes for each content and metadata event. Verify whether it represents the change introduced by the selected revision or a comparison with current.
  3. Confirm the diff identifies and displays both version identities, their direction, and whether current content is one side. A modal that opens with an empty diff is not sufficient evidence.
  4. Verify the restored bytes by closing and reopening the file.
  5. Ask a workspace database operator to report aggregate history and current-file counts split by whether an object-storage version identifier is present. Do not expose file names, paths, content, or user identities.

On 4 September 2026, w-t5e2kcxjd returned 173|0 and 17|0. The UI and API are exposed, but prior content is not recoverable without storage version IDs. The deployed backend's read-only OSS GetBucketVersioning request returned HTTP 200 with an empty VersioningConfiguration, which is the provider's default unversioned state. Current platform-stacks source has no bucket-versioning field or reconciliation step on either the AliCloud or AWS path.

Restore rejects such a history row. View Changes instead accepts the missing identifier and reads the current object for each side, so it can return a successful current-versus-current diff without retrieving either historical version. Independently, Oqullus always selects the clicked history row and the newest history row, so its current behavior is selected-versus-newest rather than the change introduced by the selected content revision; see UX-WSF-004.

Enabling versioning now cannot reconstruct content already overwritten under the unversioned configuration. Verification after remediation must distinguish new recoverable writes from these existing metadata-only history rows.

WSF-S006 — Concurrent save​

Follow NB-S018. The file update contract has no expected version or conditional write.

WSF-S007 — Failure versus empty state​

  1. Open a folder, Trash, Move target picker, or Share permissions.
  2. In browser tooling, fail the corresponding request once.
  3. Compare the result with a genuine empty response.

Expected: an error preserves known state and offers retry. Current folder and permission helpers return [], and Trash logs the error without a distinct failed state.

WSF-S008 — Trash, restore conflict, and cleanup​

  1. Trash disposable files and folders from a nested folder and directly from the user's workspace root where the UI permits it.
  2. Restore once with the original parent available, then repeat after creating a same-name item, revoking target access, trashing the parent, and injecting one transport failure.
  3. Record every restore request and destination. Confirm the UI requires the user to select or confirm a writable location and restored name before any mutation, retains that input after failure, and never sends an automatic fallback request.
  4. Confirm success returns the item to the location and name the user selected.
  5. Verify a scheduled cleanup controller exists and records success/failure.

On 4 September 2026, the qd-system namespace had no workspace trash cleanup CronJob. The UI displayed original creation time rather than trashed_at and did not expose the backend restored_name conflict option. Source review also found browser-side original-parent reconstruction and an automatic Home retry across unrelated failure classes; see UX-WSF-003.

WSF-S009 — Search and Favorites​

  1. Search for a file located outside the current folder.
  2. Mark an item as favorite, change folders or reload, and revisit Favorites.

Expected: labels state whether search is folder-local or workspace-wide, and Favorites persist. Current search filters only the loaded array and Favorites exist only in React state.

WSF-S010 — Large listing​

  1. Generate authorized folders with increasing child counts in a disposable environment.
  2. Record database rows scanned, response bytes, BFF latency, render time, and memory for folder, Shared, Trash, and search.
  3. Verify stable server-side pages under concurrent rename/delete.

Expected: authorization, ordering, and pagination execute in the database with a stable cursor or snapshot. Scale execution remains pending.

WSF-S011 — Workflow output authorization​

In an isolated security test environment:

  1. Create workflow output for test user A.
  2. Authenticate as test user B without access to A's workflow.
  3. Request /workspace/v2/file/notebook/output using A's run coordinates.
  4. Require 403 or indistinguishable 404 and an auditable denial.

Source review shows only workspace authentication before the object key is read. Live cross-user probing was intentionally not performed in the shared sandbox.

WSF-S012 — Source and deployment verification​

kubectl -n qd-system get deploy workspace-file-management-backend
kubectl -n qd-system get cronjob

The deployed image was workspace-file-management-backend:5dcbb22, with two replicas. Only workflow-backend-reconciliation was scheduled; no workspace trash cleanup job existed.

Source-test record​

  • Oqullus: 35 targeted Workspace context, toolbar, share-dialog, and tab-layout tests passed when the runner excluded unrelated nested worktrees.
  • Exact deployed backend commit: 56 tests passed. The two remaining API tests attempted to discover a real Keycloak realm at localhost during middleware construction and failed in the isolated test environment; they did not exercise a workspace operation.
  • Existing tests do not cover the real {folders: [...]} root response in the affected root resolvers, non-null object versions, cross-user output access, transfer load, partial object/database failure, cleanup scheduling, or large collections.