Add self-sent knowledge WebDAV intent - #242
Conversation
📝 WalkthroughWalkthroughAdds a signed POST endpoint and service to derive WebDAV/Notes materialization intents for self-sent knowledge tasks (intent-only, provider_write_executed=false), a Tasks UI flow with per-task intent state, comprehensive tests (unit, e2e, real-Postgres smoke), and documentation/governance updates specifying request/validation/error semantics. ChangesWebDAV Knowledge Materialization Intent
Sequence Diagram(s)sequenceDiagram
participant ComponentA
participant ComponentB
ComponentA->>ComponentB: observable interaction
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@backend/api/webdav.py`:
- Around line 101-104: The current code derives HTTP status by substring
matching result.get("message") which is brittle; instead read a deterministic
service error field (e.g., result.get("code") or result.get("error_code")) and
map those codes to HTTP statuses when result.get("status") == "error": check for
known codes like "not_found" -> 404, "validation_error" -> 422, etc., and fall
back to 500 or a default (e.g., 422) if the code is missing; update the logic
that sets status_code (the variable shown) to use this explicit mapping and
ensure result is not mutated.
In `@backend/services/webdav_service.py`:
- Around line 136-178: The query uses an outerjoin which allows task rows with
no linked Email to pass through, so when source_email_id is None the function
still returns intent_ready; change the join to an inner join (or explicitly
require Email exists) when selecting TicketTask with Email to ensure provenance,
and add an explicit guard after fetching row: if source_email_id is None return
an error like "Self-sent knowledge task missing source email provenance."
Reference the TicketTask/Email select block (task_result), the outerjoin usage,
the SELF_SENT_KNOWLEDGE_SOURCE check, and the returned task.task_uid/
source_email_id to locate and implement the fix.
In `@backend/tests/test_webdav_api.py`:
- Around line 194-320: Add a real PostgreSQL smoke/integration test that
exercises the DB-backed path for the
/api/webdav/knowledge-materialization-intent endpoint (in addition to the
existing fast/mocked tests like test_get_self_sent_knowledge_webdav_intent and
the unit test calling
webdav_service.determine_knowledge_materialization_intent_from_db);
specifically, create a new integration test that boots the real test Postgres
(using the project's existing DB bootstrap fixture), seeds the required
TicketTask row and a connected WebDAV account, issues an HTTP POST to the
endpoint via TestClient with real dependency injection (do not override
get_auth_context), and asserts the endpoint returns 200 and the expected JSON
fields — leaving the existing mocked/unit tests unchanged. Ensure the
integration test references the service function
determine_knowledge_materialization_intent_from_db and the endpoint path
"/api/webdav/knowledge-materialization-intent" so the smoke path verifies the
actual DB interactions.
In `@frontend/src/components/TasksLayout.tsx`:
- Around line 91-95: The shared knowledgeIntentStatus state causes cross-task
overwrites; change it to a map keyed by taskId (e.g. Record<string, { state:
'idle'|'loading'|'ready'|'error'; result: KnowledgeMaterializationIntent | null
}>) and replace uses of knowledgeIntentStatus and setKnowledgeIntentStatus so
each update targets the specific taskId (merge/update the map entry rather than
replacing whole state). Update all places interacting with knowledgeIntentStatus
(creation, polling, rendering and clearing logic—functions/components that call
setKnowledgeIntentStatus, and reads that expect a single object) to read/write
by taskId and default to idle/null when missing. Ensure places that passed
result.taskId continue to supply the taskId key so per-task status is isolated
and race conditions are avoided.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 9ab91028-c772-4fe3-a433-0fe9739a47e2
📒 Files selected for processing (12)
AGENTS.mdREADME.mdbackend/api/webdav.pybackend/services/webdav_service.pybackend/tests/test_webdav_api.pydocs/operations/source-of-truth-and-writeback-sovereignty.mddocs/plans/2026-05-19-branding-menu-task-tracking-gap-closure.mddocs/plans/2026-05-27-self-sent-webdav-materialization-intent.mdfrontend/src/app/tasks/page.test.tsxfrontend/src/components/TasksLayout.tsxfrontend/tests/e2e/dashboard-branding.spec.tsfrontend/tests/e2e/helpers.ts
|
PR governance metadata gate is not ready for
|
|
CodeRabbit follow-up pushed in b839687: added deterministic WebDAV error codes, provenance guard for self-sent knowledge materialization, DB-backed endpoint smoke coverage, and per-task UI intent state. Verification rerun locally: backend tasks/webdav pytest, Tasks vitest, typecheck, lint, production build, and self-sent WebDAV intent Playwright screenshot check. |
|
PR #242 current-head gate evidence at
@coderabbitai review |
|
✏️ Learnings added
✅ Actions performedFull review triggered. |
There was a problem hiding this comment.
♻️ Duplicate comments (1)
backend/services/webdav_service.py (1)
165-170:⚠️ Potential issue | 🟠 Major | ⚡ Quick winEnforce thread provenance before returning
intent_ready.The success path still allows
source_thread_idto be null, which breaks the required email/thread source linkage for email-derived tasks.🔧 Minimal fix
- if source_email_id is None: + if source_email_id is None or task.related_thread_id is None: return { "status": "error", "error_code": "missing_provenance", - "message": "Self-sent knowledge task missing source email provenance.", + "message": "Self-sent knowledge task missing source email/thread provenance.", }As per coding guidelines: "Email-derived tasks must stay source-linked to the email/thread and tenant owner scope".
Also applies to: 186-186
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@backend/services/webdav_service.py` around lines 165 - 170, The code checks source_email_id but still allows source_thread_id to be null before returning intent_ready; add a provenance guard to verify source_thread_id is not None (alongside source_email_id) and return the same error structure (e.g., status:"error", error_code:"missing_provenance", message:"Self-sent knowledge task missing source email provenance.") if it is missing; apply this check in the same places where intent_ready is returned (references: source_thread_id, source_email_id, and the intent_ready success path) so email-derived tasks remain linked to their thread/tenant owner.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Duplicate comments:
In `@backend/services/webdav_service.py`:
- Around line 165-170: The code checks source_email_id but still allows
source_thread_id to be null before returning intent_ready; add a provenance
guard to verify source_thread_id is not None (alongside source_email_id) and
return the same error structure (e.g., status:"error",
error_code:"missing_provenance", message:"Self-sent knowledge task missing
source email provenance.") if it is missing; apply this check in the same places
where intent_ready is returned (references: source_thread_id, source_email_id,
and the intent_ready success path) so email-derived tasks remain linked to their
thread/tenant owner.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: dfe2d1a1-f64f-4c99-9446-4d7e7b49285c
📒 Files selected for processing (12)
AGENTS.mdREADME.mdbackend/api/webdav.pybackend/services/webdav_service.pybackend/tests/test_webdav_api.pydocs/operations/source-of-truth-and-writeback-sovereignty.mddocs/plans/2026-05-19-branding-menu-task-tracking-gap-closure.mddocs/plans/2026-05-27-self-sent-webdav-materialization-intent.mdfrontend/src/app/tasks/page.test.tsxfrontend/src/components/TasksLayout.tsxfrontend/tests/e2e/dashboard-branding.spec.tsfrontend/tests/e2e/helpers.ts
Summary
POST /api/webdav/knowledge-materialization-intentfor self-sent knowledge task WebDAV/Notes materialization intent.apiClientbearer session, without public identity headers or provider writes.Verification
python3 -m pytest backend/tests/test_tasks_api.py backend/tests/test_webdav_api.py -qcd frontend && npm test -- --run src/app/tasks/page.test.tsxcd frontend && npm run typecheckcd frontend && npm run lintcd frontend && env -u NO_COLOR -u FORCE_COLOR NEXT_TELEMETRY_DISABLED=1 POSTCSS_WORKERS=1 DISABLE_POSTCSS_WORKERS=true NEXT_STATIC_GENERATION_MAX_CONCURRENCY=1 npm run buildcd frontend && env -u NO_COLOR -u FORCE_COLOR PLAYWRIGHT_PORT=18134 LIVE_BASE_URL=http://127.0.0.1:18134 NEXT_TELEMETRY_DISABLED=1 POSTCSS_WORKERS=1 DISABLE_POSTCSS_WORKERS=true NEXT_STATIC_GENERATION_MAX_CONCURRENCY=1 npm run test:e2e -- --project=desktop -g "self-sent knowledge WebDAV intent"cd frontend && env -u NO_COLOR -u FORCE_COLOR PLAYWRIGHT_PORT=18134 LIVE_BASE_URL=http://127.0.0.1:18134 NEXT_TELEMETRY_DISABLED=1 POSTCSS_WORKERS=1 DISABLE_POSTCSS_WORKERS=true NEXT_STATIC_GENERATION_MAX_CONCURRENCY=1 npm run test:e2e -- --project=desktop -g "updates source-linked task ticket status"cd frontend && env -u NO_COLOR -u FORCE_COLOR PLAYWRIGHT_PORT=18134 LIVE_BASE_URL=http://127.0.0.1:18134 NEXT_TELEMETRY_DISABLED=1 POSTCSS_WORKERS=1 DISABLE_POSTCSS_WORKERS=true NEXT_STATIC_GENERATION_MAX_CONCURRENCY=1 npm run test:e2e -- --project=mobile mobile-hamburger.spec.tsBrowser evidence inspected
self-sent-knowledge-webdav-intent-desktop.pngself-sent-knowledge-webdav-intent-mobile.pngself-sent-knowledge-webdav-intent-mobile-scroll.pngtask-ticket-status-mobile.pngtask-ticket-status-mobile-scroll.pngmobile-hamburger-open.pngGovernance
78114739d1f2125033834515b7b8f8e8138a5409STRIX_OPENAI_API_KEYOpenAI Platform direct-only. Do not route through GitHub Models.Summary by CodeRabbit
New Features
Documentation