mirror of
https://github.com/VectifyAI/PageIndex.git
synced 2026-07-18 21:21:05 +02:00
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:
parent
284ce005f5
commit
6a73279c0c
6 changed files with 38 additions and 9 deletions
|
|
@ -26,3 +26,11 @@ def test_model_copy_with_update():
|
|||
updated = config.model_copy(update={"model": "gpt-5.4"})
|
||||
assert updated.model == "gpt-5.4"
|
||||
assert updated.toc_check_page_num == 30
|
||||
|
||||
|
||||
def test_legacy_yes_no_strings_coerce_to_bool():
|
||||
"""Legacy page_index()/run_pageindex callers pass 'yes'/'no' strings;
|
||||
pydantic must coerce them to the booleans the pipeline now branches on."""
|
||||
config = IndexConfig(if_add_node_id="yes", if_add_node_summary="no")
|
||||
assert config.if_add_node_id is True
|
||||
assert config.if_add_node_summary is False
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ def test_submit_document_uses_legacy_endpoint(monkeypatch, tmp_path):
|
|||
assert calls[0]["method"] == "POST"
|
||||
assert calls[0]["url"] == "https://api.pageindex.ai/doc/"
|
||||
assert calls[0]["headers"] == {"api_key": "pi-test"}
|
||||
assert "timeout" not in calls[0]["kwargs"]
|
||||
assert calls[0]["kwargs"]["timeout"] == 30
|
||||
assert calls[0]["data"]["if_retrieval"] is True
|
||||
assert calls[0]["data"]["mode"] == "mcp"
|
||||
assert calls[0]["data"]["beta_headers"] == '["block_reference"]'
|
||||
|
|
@ -214,7 +214,8 @@ def test_chat_completions_stream_parses_text_chunks(monkeypatch):
|
|||
))
|
||||
|
||||
assert chunks == ["hel", "lo"]
|
||||
assert "timeout" not in calls[0]["kwargs"]
|
||||
# Streamed requests still get a (longer, between-chunk) read timeout.
|
||||
assert calls[0]["kwargs"]["timeout"] == 120
|
||||
|
||||
|
||||
def test_chat_completions_stream_metadata_returns_raw_chunks(monkeypatch):
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue