Commit Graph
3 Commits
Author SHA1 Message Date
Chris CoutinhoandClaude Opus 4.7 56f01b3499 fix(webdav): address PR #764 review round 4
- Guard against malformed PROPFIND responses where tag["id"] is None
  before calling get_files_by_tag (prevents
  <oc:systemtag>None</oc:systemtag> dispatch).
- Add OCS-APIRequest: true header to get_tag_by_name and
  get_files_by_tag to match every other PROPFIND/REPORT in the file —
  fixes a latent reverse-proxy compatibility hazard.
- Add test_copy_resource_blocks_excluded_source to mirror the
  existing move-source coverage; closes the asymmetric test gap.
- Add test_skips_tag_with_missing_id covering the new fail-open
  branch in _resolve_one_tag.
- Reword _resolve_one_tag docstring: "distinct slot" was misleading
  (tasks append rather than pre-allocate).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 20:24:11 +02:00
Chris CoutinhoandClaude Opus 4.7 d179ca8c8b fix(webdav): address PR #764 review round 2
Addresses the four points raised in the automated review on PR #764:

1. Scope guards on the four search tools (search_files, find_by_name,
   find_by_type, list_favorites) so an excluded `scope` raises ToolError
   instead of silently returning an empty result. Previously an LLM
   could probe the asymmetry between list_directory (raises) and the
   search tools (silent) to infer that an excluded directory exists.
   The 4 search tools now mirror the early-guard pattern from
   list_directory and avoid an unnecessary upstream query for known-
   excluded scopes.

2. Concurrent per-tag resolution in get_excluded_file_paths via
   anyio.create_task_group(). Previously the 2N network calls (1
   PROPFIND + 1 REPORT per tag) ran serially. Per-tag fail-open
   behaviour is preserved by extracting _resolve_one_tag, which
   swallows its own exceptions so a single tag failure does not abort
   the surrounding task group.

3. WebDAVClient.get_tag_by_name and get_files_by_tag now route through
   _make_request, inheriting the @retry_on_429 decorator. Previously
   they bypassed it; with tag exclusion invoked on every WebDAV tool
   call, a transient 429 from the systemtags endpoint was hitting the
   fail-open path instead of being transparently retried.

4. Test coverage: 6 new tests in test_webdav_tools_exclusion.py (4
   scope-guard, 2 missing filter tests for find_by_type and
   list_favorites) and 2 new tests in test_tag_exclusion.py (a
   concurrency proof using an event-barrier that would deadlock under
   sequential execution, and a fail-open-under-task-group test with
   order-independent side_effect callables).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 19:15:39 +02:00
Chris CoutinhoandClaude Opus 4.7 a6c188abbb fix(webdav): address PR #764 review
Six findings raised in the PR review:

🔴 Blocking
- Fail-open on tag-resolution errors. get_excluded_file_paths now
  wraps each tag's get_tag_by_name and get_files_by_tag call in
  try/except; failures log a warning and the tag is skipped, rather
  than propagating to the caller and disabling all WebDAV tools when
  the systemtags endpoint is degraded. Documented in the docstring as
  the intended fail-open behaviour (threat model is preventing
  accidental exfiltration, not surviving server compromise).

🟡 Important
- nc_webdav_list_directory now raises ToolError when the listed path
  itself is tagged, instead of silently returning an empty listing
  after a wasted PROPFIND. Behaviour now mirrors the mutating tools.
- Destination error messages in move/copy/create_directory said "is
  inside" but is_path_excluded matches exact paths too. Reworded to
  "is or is inside".

🟢 Nits
- get_excluded_file_paths log message clarified: N counts
  directly-tagged paths, not total descendants.
- Test isolation: tests/unit/conftest.py already has an autouse
  _reload_dynaconf_after_test fixture that handles teardown. Removed
  the redundant module-local fixture I had drafted; documented the
  reliance in the module docstring instead.
- Added tests/unit/test_webdav_tools_exclusion.py: 12 server-layer
  tests that register the WebDAV tools on a fresh FastMCP and invoke
  each tool's underlying function with a mocked excluded set, asserting
  ToolError is raised / results filtered as expected. Catches future
  guard-integration regressions (e.g. wrong argument order).

Also added two unit tests for the new fail-open behaviour.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 12:26:25 +02:00