Skip to content

fix(export): give each exported document its own path - #2093

Merged
MODSetter merged 1 commit into
MODSetter:devfrom
MohammadHijjawi97:fix/export-unique-document-paths
Oct 1, 2026
Merged

MODSetter merged 1 commit into
MODSetter:devfrom
MohammadHijjawi97:fix/export-unique-document-paths

Conversation

@MohammadHijjawi97

@MohammadHijjawi97 MohammadHijjawi97 commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

What

When the exporter adds a _2, _3 suffix to a clashing title, it now keeps counting until the path is free, instead of taking the first suffix without checking it. Adds a unit test for build_account_export_zip. The file is also run through ruff format, since the backend-lint hook checks every changed file.

Why

A suffixed name can already belong to another document. With Notes, Notes_2 and Notes in one folder, the third was written to Notes_2.md as well:

before: Notes.md, Notes_2.md, Notes_2.md   (zipfile: "Duplicate name")
after:  Notes.md, Notes_2.md, Notes_3.md

The manifest then listed the same path for two documents. Import opens members by name, so both entries read the last one, and the dedup key drops the second: one document is silently missing after the migration.

How to test

cd surfsense_backend
uv run pytest tests/unit/services/test_export_document_paths.py tests/unit/services/test_account_export.py tests/unit/services/okf

The new test fails before the change and passes after. ruff check, ruff format --check and bandit are clean on the changed files. Locally I ran these tests with --noconftest and a small stub for app.config, because the root conftest loads an embedding model at import time.

High-level PR Summary

This PR fixes a bug in the document export service where files with duplicate names (e.g., Notes, Notes_2, Notes) could overwrite each other during export. The fix ensures that when generating suffixed filenames for duplicates, the system keeps incrementing the suffix counter until it finds an unused path, preventing silent data loss during export/import cycles. The changes include the core fix in the export logic, formatting updates via ruff format, and a new unit test to verify the behavior.

⏱️ Estimated Review Time: 5-15 minutes

💡 Review Order Suggestion
Order File Path
1 surfsense_backend/tests/unit/services/test_export_document_paths.py
2 surfsense_backend/app/services/export_service.py

Need help? Join our Discord

Summary by CodeRabbit

  • Bug Fixes
    • Fixed duplicate filenames in account ZIP exports, including collisions with titles that already have numeric suffixes. Exported documents now receive unique paths, with each path linked to the correct document content.

When two documents in one folder share a title, the second gets a _2
suffix. The suffix was not checked, so if another document was already
titled "Notes_2", both were written to Notes_2.md: the ZIP held two
entries with that name and the manifest listed the path twice. Import
reads the last entry for both, so one document never arrived.

Keep counting until the path is free. Also apply ruff format to the
file, which the backend-lint hook checks for every changed file.
@vercel

vercel Bot commented Sep 30, 2026

Copy link
Copy Markdown

@MohammadHijjawi97 is attempting to deploy a commit to the Rohan Verma's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitai Bot commented Sep 30, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

Note

Repository guideline files applied to this review (2)
.cursor/rules/ponytail.mdc — auto-discovered
docs/architecture/sunset.md — configured

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: MODSetter/SurfSense/.coderabbit.yaml

Review profile: CHILL

Plan: Advanced

Run ID: 00003374-bc34-43b4-8da9-4a2d2465b008

📥 Commits

Reviewing files that changed from the base of the PR and between 6860530 and 083f0aa.

📒 Files selected for processing (2)
  • surfsense_backend/app/services/export_service.py
  • surfsense_backend/tests/unit/services/test_export_document_paths.py

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.


📝 Walkthrough

Walkthrough

The export service now checks successive filename candidates until it finds an unused path. A new unit test covers duplicate document titles, including a title with a numeric suffix, and verifies unique manifest paths and matching document contents.

Changes

Document export paths

Layer / File(s) Summary
Select unique document paths
surfsense_backend/app/services/export_service.py, surfsense_backend/tests/unit/services/test_export_document_paths.py
The service checks filename candidates until it finds an unused path and records the selected path. The test checks that manifest paths are unique and contain the corresponding document bodies. Other service edits reformat existing expressions and signatures without changing behavior.

Priority: ⬇️ Low

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

Change: Bug fix

Merge Risk: ⚪ Minimal · up to 083f0

The change prevents colliding document paths in account exports and adds focused regression coverage. No actionable merge-blocking risk is identified; merge after normal checks.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 30.77% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 13 functions across 2 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: preventing exported documents from sharing duplicate paths by assigning each document its own path.
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.
  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Autopilot is currently an internal CodeRabbit preview.


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.

@MODSetter
MODSetter merged commit ed1da3a into MODSetter:dev Oct 1, 2026
20 of 24 checks passed
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