fix: patch three critical defects from the SDK review

- local delete_collection: validate the collection name before rmtree.
  An unvalidated name like "../.." escaped files_dir and deleted
  arbitrary directories (path traversal).

- legacy page_index(): restore the node_id/summary/text/description
  enhancements. IndexConfig now carries booleans (pydantic coerces the
  legacy 'yes'/'no' strings at the boundary), but page_index_main still
  compared `opt.if_add_node_id == 'yes'` — always False — so every
  enhancement was silently skipped for legacy-API callers. Conditions
  now branch on the booleans, matching pageindex/index/page_index.py.

- LegacyCloudAPI._request: bound every request with a timeout
  (30s, 120s read timeout for streamed responses) so a dead connection
  can't hang legacy submit/poll/chat callers forever. The legacy
  contract tests pinned the missing timeout; updated to pin its
  presence instead.

Adds regression tests: path-traversal rejection, 'yes'/'no' -> bool
coercion, and timeout assertions.

Claude-Session: https://claude.ai/code/session_01Kx5DgKbhK1N8autqXH8SmS
This commit is contained in:
mountain 2026-07-07 10:05:38 +08:00
parent 284ce005f5
commit 6a73279c0c
6 changed files with 38 additions and 9 deletions

View file

@ -155,3 +155,13 @@ def test_delete_document_missing_raises(backend):
backend.get_or_create_collection("papers")
with pytest.raises(DocumentNotFoundError, match="ghost"):
backend.delete_document("papers", "ghost")
def test_delete_collection_rejects_path_traversal(backend, tmp_path):
# Regression: an unvalidated name like "../.." would rmtree outside files_dir.
from pageindex.errors import PageIndexError
canary = tmp_path / "canary.txt"
canary.write_text("still here")
with pytest.raises(PageIndexError, match="Invalid collection name"):
backend.delete_collection("../..")
assert canary.exists()