fix(dav): land capability honesty with tomllib CI import - #1380
fix(dav): land capability honesty with tomllib CI import#1380cursor[bot] wants to merge 22 commits into
Conversation
Keep the fail-closed DAV method set and the patched nanoid 5.1.16 pin when merging current develop. Align the incoming 3.x-only Nano ID lock test with that same patched override. Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
The develop merge added a cryptography pin test that calls tomllib.loads without importing the stdlib module, so App CI NameErrors before the pin assertions run. Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
|
PR governance metadata gate is not ready for
|
|
Bugbot is not enabled for your account, so this pull request was not reviewed. Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs. |
There was a problem hiding this comment.
Pull request overview
OpenCode cannot approve yet because required coverage evidence did not pass.
Review outcome
1. HIGH .github/workflows/opencode-review.yml:1 - Coverage evidence did not prove required test/docstring evidence
-
Problem: The required coverage-evidence job result was
failure, so OpenCode cannot establish approval sufficiency for this head. -
Root cause: Automated approval is only valid when the same-head coverage-evidence job proves supported repository test suites passed and configured docstring gates passed or were advisory, or reports not applicable because no supported source files or package manifests exist. Missing, failed, skipped, unavailable, or unsupported-tooling test evidence is a blocker.
-
Fix: Install or configure the repository test/docstring evidence tooling when source files or package manifests exist, rerun the current-head coverage-evidence job, and approve only after it reports
successwith required evidence or explicit no-source not-applicable evidence. -
Regression test: Keep the approval branch checking
needs.coverage-evidence.result == successbefore posting APPROVE, and publish REQUEST_CHANGES when coverage-evidence blocker states such as cancelled, skipped, failed, unsupported-tooling, or below-100 evidence are present. -
Result: REQUEST_CHANGES
-
Reason: coverage-evidence result was
failure, so required test/docstring evidence was not proven for current head3235e8d031d784fc140333feff9af2ed84004b0e. -
Head SHA:
3235e8d031d784fc140333feff9af2ed84004b0e -
Workflow run: 32123709037
-
Workflow attempt: 1
Coverage evidence
Coverage evidence job did not run or did not publish coverage evidence.
Changed-File Evidence Map
flowchart LR
PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
Evidence --> S1["Changed file: CHANGELOG.md"]
S1 --> I1["repository behavior"]
I1 --> R1["Review risk: Changed file: CHANGELOG.md"]
R1 --> V1["required checks"]
Evidence --> S2["Backend (8 files)"]
S2 --> I2["API and service runtime"]
I2 --> R2["Review risk: Backend (8 files)"]
R2 --> V2["backend tests"]
Evidence --> S3["Docs: nanoid-cve-2026-67214.md"]
S3 --> I3["operator or user guidance"]
I3 --> R3["Review risk: Docs: nanoid-cve-2026-67214.md"]
R3 --> V3["docs review"]
Evidence --> S4["Frontend (4 files)"]
S4 --> I4["browser runtime and bundle"]
I4 --> R4["Review risk: Frontend (4 files)"]
R4 --> V4["frontend tests"]
OpenCode Review Overview
Pull request overviewOpenCode cannot approve yet because required coverage evidence did not pass. Review outcome1. HIGH .github/workflows/opencode-review.yml:1 - Coverage evidence did not prove required test/docstring evidence
Coverage evidenceCoverage evidence job did not run or did not publish coverage evidence. Changed-File Evidence Mapflowchart LR
PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
Evidence --> S1["Changed file: CHANGELOG.md"]
S1 --> I1["repository behavior"]
I1 --> R1["Review risk: Changed file: CHANGELOG.md"]
R1 --> V1["required checks"]
Evidence --> S2["Backend (8 files)"]
S2 --> I2["API and service runtime"]
I2 --> R2["Review risk: Backend (8 files)"]
R2 --> V2["backend tests"]
Evidence --> S3["Docs: nanoid-cve-2026-67214.md"]
S3 --> I3["operator or user guidance"]
I3 --> R3["Review risk: Docs: nanoid-cve-2026-67214.md"]
R3 --> V3["docs review"]
Evidence --> S4["Frontend (4 files)"]
S4 --> I4["browser runtime and bundle"]
I4 --> R4["Review risk: Frontend (4 files)"]
R4 --> V4["frontend tests"]
|
Scan ContextualWisdomLab/naruon protected develop at minute 11 so live platform PRs receive the same bounded RCA worker as Clearfolio, DiskSage, and fast-mlsirm. Keep NVIDIA_NIM_API_KEY on the worker and never introduce COPILOT_GITHUB_TOKEN. Refs ContextualWisdomLab/naruon#1388 ContextualWisdomLab/naruon#1387 ContextualWisdomLab/naruon#1380
|
Current-head review request for PR #1380. HEAD: 3235e8d The exact DAV capability slice registers only authenticated |
Current-head restack and verification
|
| }, | ||
| "overrides": { | ||
| "brace-expansion": "5.0.9", | ||
| "nanoid": "5.1.16", |
There was a problem hiding this comment.
🔍 Global nanoid override forces postcss onto ESM-only nanoid 5.x
The pnpm override for nanoid is bumped to 5.1.16 (frontend/package.json:51, frontend/pnpm-workspace.yaml:18), and the lock now resolves postcss@8.5.24's nanoid to 5.1.16 (frontend/pnpm-lock.yaml:5193-5197). postcss declares nanoid: ^3.3.x and consumes it via nanoid/non-secure; nanoid 5.x is pure ESM. Node 26 supports require(esm), so this can work, but it forces a cross-major bump onto a transitive consumer. Confirm the Next.js build succeeds with postcss on nanoid 5.x.
Was this helpful? React with 👍 or 👎 to provide feedback.
There was a problem hiding this comment.
Build confirmed on head 658f69a — no change needed.
corepack pnpm@11.5.3 install --frozen-lockfile+next build(POSTCSS_WORKERS=1) in frontend/ → exit 0, all routes prerendered/rendered cleanly with postcss@8.5.24 resolving nanoid@5.1.16 (pnpm-lock.yaml:5193-5197).- Direct consumer check:
node -e "require('nanoid/non-secure')"succeeds under the repo's Node runtime (Node 26 require(esm)), returning a function — postcss's exact import path works against ESM-only nanoid 5.x.
Note the override is a deliberate fail-closed security pin, not an incidental bump: backend/tests/test_frontend_nanoid_security.py asserts the lock resolves ONLY nanoid@5.1.16 including postcss's transitive edge (postcss_snapshot['dependencies']['nanoid'] == '5.1.16'), and test_frontend_tooling_lock_uses_current_audit_fixed_transitive_versions enforces manifest/workspace/lock alignment. Scoping the override away from postcss would re-open the vulnerable resolution those gates exist to prevent. Both tests pass on this head.
| from db.models import Email, ProjectFolder, TicketTask, WebdavAccount | ||
| from services.knowledge_extractor import SELF_SENT_KNOWLEDGE_SOURCE | ||
|
|
||
| logger = logging.getLogger(__name__) | ||
|
|
||
|
|
||
| def safe_webdav_source_label(source_id: str | None) -> str: | ||
| """Return an operator-safe label that exposes only the opaque source ID.""" | ||
| if not source_id: | ||
| return "WebDAV source" | ||
| return f"WebDAV source {source_id}" | ||
|
|
||
|
|
||
| async def sync_webdav_folders(session, user_id: str, organization_id: str | None): | ||
| """ | ||
| Fetch folder structures for all WebDAV accounts of the user. | ||
| """ | ||
| from urllib.parse import urlsplit | ||
|
|
||
| from core.url_validation import _reject_unsafe_ip_literal | ||
|
|
||
| logger.info(f"Syncing WebDAV folders for user {user_id}") | ||
| organization_filter = ( | ||
| WebdavAccount.organization_id == organization_id | ||
| if organization_id is not None | ||
| else WebdavAccount.organization_id.is_(None) | ||
| ) | ||
| stmt = select(WebdavAccount.server_url, WebdavAccount.source_uid).where( | ||
| WebdavAccount.user_id == user_id, organization_filter | ||
| ) | ||
| res = await session.execute(stmt) | ||
| accounts = res.all() | ||
| for server_url, source_uid in accounts: | ||
| try: | ||
| if server_url: | ||
| parsed = urlsplit(server_url) | ||
| if parsed.scheme != "https": | ||
| raise ValueError("WebDAV server_url must use HTTPS") | ||
| if not parsed.hostname: | ||
| raise ValueError("WebDAV server_url must include a hostname") | ||
| _reject_unsafe_ip_literal("WebDAV server_url", parsed.hostname) | ||
| except ValueError as exc: | ||
| logger.warning( | ||
| "Invalid WebDAV server URL for source %s: %s", | ||
| source_uid or "unknown", | ||
| exc, | ||
| ) | ||
| continue | ||
|
|
||
| logger.info( | ||
| "Fetched folder structures for WebDAV source %s", | ||
| source_uid or "unknown", | ||
| ) | ||
| return True | ||
|
|
||
|
|
||
| class WebDavService: | ||
| def __init__(self): | ||
| self._mock_accounts = { | ||
| "demo_user": [ | ||
| { | ||
| "source_id": "webdav_src_demo_primary", | ||
| "server_url": "https://webdav.naruon.net", | ||
| "username": "demo_user", | ||
| "display_label": "WebDAV source webdav_src_demo_primary", | ||
| "writeback_enabled": True, | ||
| "etag": "etag-webdav-demo-primary", | ||
| } | ||
| ] | ||
| } | ||
| self._mock_folders = { | ||
| "demo_user": [ | ||
| { | ||
| "folder_uid": "webdav_folder_demo_roadmap", | ||
| "project_name": "Naruon Roadmap 2026", | ||
| "webdav_path": "/Projects/Naruon_Roadmap_2026", | ||
| "owner_user_id": "demo_user", | ||
| "organization_id": None, | ||
| }, | ||
| { | ||
| "folder_uid": "webdav_folder_demo_marketing", | ||
| "project_name": "Marketing Assets", | ||
| "webdav_path": "/Projects/Marketing_Assets", | ||
| "owner_user_id": "demo_user", | ||
| "organization_id": None, | ||
| }, | ||
| ] | ||
| } | ||
|
|
||
| def get_connected_accounts(self, user_id: str) -> List[Dict[str, Any]]: | ||
| """ | ||
| Fetch connected WebDAV accounts for a user. | ||
| In a real implementation, this queries the database. | ||
| """ | ||
| return self._mock_accounts.get(user_id, []) | ||
|
|
||
| def get_project_folders(self, user_id: str) -> List[Dict[str, Any]]: | ||
| """ | ||
| Fetch the list of project folders structured by AI. | ||
| """ | ||
| return self._mock_folders.get(user_id, []) | ||
| """Resolve tenant-scoped WebDAV discovery and signed writeback intents.""" |
There was a problem hiding this comment.
📝 Info: Removed WebDAV demo methods have no runtime callers
sync_webdav_folders, the demo mock stores, and the non-DB methods are deleted from webdav_service.py. The only non-test/doc references are in backend/api/webdav.py, which uses only the *_from_db methods, so the removal and the module-level logger deletion leave no dangling references.
(Refers to this code)
Was this helpful? React with 👍 or 👎 to provide feedback.
There was a problem hiding this comment.
Confirmed — matches your trace. grep -rn "sync_webdav_folders" backend/api/webdav.py returns nothing and webdav_service.py retains only the *_from_db methods consumed by the API layer; focused verification on head 658f69a: python -m pytest backend/tests/test_webdav_api.py backend/tests/test_webdav_service_unit.py -q → 23 passed, 3 skipped.
Stale review: cited a coverage-evidence/required-check failure on an earlier commit; current head has been verified (gh pr checks) to pass coverage-evidence and all other non-metadata-gate required checks, with no current-head review from this reviewer. Dismissing as superseded per AGENTS.md stale-review guidance.
Description
Landing vehicle for the DAV honesty contract on
develop, plus the App CINameErrorthat the254ba721merge head introduced.OPTIONS,PROPFIND) and advertiseDAV: 1.405 Method Not Allowedinstead of success-shaped or501handlers.nanoid@5.1.16pin across package, workspace, and frozen lock authorities.tomllibsotest_cryptography_runtime_pins_are_bleichenbacher_oracle_fixedcan execute the pin contract.This supersedes #1296 at head
254ba721, which stillNameErrors on that test. Do not merge #1296 once this branch is open.Fixes #1296 (successor)
Type of change
Checklist:
Verification