Skip to content

Add self-sent knowledge WebDAV intent - #242

Merged
seonghobae merged 2 commits into
masterfrom
feature/self-sent-webdav-intent-20260527
May 27, 2026
Merged

seonghobae merged 2 commits into
masterfrom
feature/self-sent-webdav-intent-20260527

Conversation

@seonghobae

@seonghobae seonghobae commented May 27, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Add signed POST /api/webdav/knowledge-materialization-intent for self-sent knowledge task WebDAV/Notes materialization intent.
  • Wire Tasks UI to call the endpoint through apiClient bearer session, without public identity headers or provider writes.
  • Document the intent-only source-of-truth contract and keep Strix governance OpenAI Platform direct-only, with no GitHub Models route.

Verification

  • python3 -m pytest backend/tests/test_tasks_api.py backend/tests/test_webdav_api.py -q
  • cd frontend && npm test -- --run src/app/tasks/page.test.tsx
  • cd frontend && npm run typecheck
  • cd frontend && npm run lint
  • cd 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 build
  • 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 "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.ts

Browser evidence inspected

  • self-sent-knowledge-webdav-intent-desktop.png
  • self-sent-knowledge-webdav-intent-mobile.png
  • self-sent-knowledge-webdav-intent-mobile-scroll.png
  • task-ticket-status-mobile.png
  • task-ticket-status-mobile-scroll.png
  • mobile-hamburger-open.png

Governance

  • Current head: 78114739d1f2125033834515b7b8f8e8138a5409
  • Provider rule: Strix must remain STRIX_OPENAI_API_KEY OpenAI Platform direct-only. Do not route through GitHub Models.

Summary by CodeRabbit

  • New Features

    • Create WebDAV/Notes knowledge materialization intents for self-sent knowledge items; shows planned target location and metadata without performing provider writes.
    • Tasks workspace: new "나에게 보낸 지식 노트" section with per-task intent creation controls, loading/error states, and rendered intent details.
  • Documentation

    • Updated operational and planning docs and README to clarify the self-sent knowledge materialization workflow, intent contract, and governance.

Review Change Stack

@coderabbitai

coderabbitai Bot commented May 27, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

Adds 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.

Changes

WebDAV Knowledge Materialization Intent

Layer / File(s) Summary
Documentation and Governance
AGENTS.md, README.md, docs/operations/..., docs/plans/...
Updates governance and plans to require opaque task UIDs, server-side owner/org validation, deterministic error_code values, per-row UI state-keying, and documents the signed intent-only WebDAV/Notes materialization contract.
API Models and Error Mapping
backend/api/webdav.py
Removes an unused FastAPI import; adds WEB_DAV_ERROR_STATUS_CODES and Pydantic KnowledgeMaterializationIntentRequest / KnowledgeMaterializationIntentResponse models for the new endpoint.
Backend Service and Endpoint
backend/services/webdav_service.py, backend/api/webdav.py
Adds WebDavService.determine_knowledge_materialization_intent_from_db(...) to validate task existence, ownership, source_type == self_sent_knowledge, and provenance; delegates to existing writeback intent resolution; constructs a knowledge_materialization intent (with provider_write_executed: False) and wires a new POST /api/webdav/knowledge-materialization-intent endpoint mapping error_code→HTTP status. Also expands service error payloads to include structured error_code values.
Backend Tests
backend/tests/test_webdav_api.py
Adds HS256-signed-session test helpers, monkeypatched stub for the service intent method, endpoint tests for success and failure cases (validation, ownership, source-type, account requirement, signed token), async unit checks of service errors, and a real-Postgres smoke test that creates an isolated schema and verifies the full intent response.
Frontend Components and State Management
frontend/src/components/TasksLayout.tsx
Adds KnowledgeMaterializationIntent types and knowledgeIntentByTask per-task state, implements handleKnowledgeIntentCreate to POST the intent request, filters selfSentKnowledgeTasks, adjusts layout, and renders a per-task “intent 생성” UI with loading/error/ready states and intent detail display.
Frontend Tests and E2E
frontend/src/app/tasks/page.test.tsx, frontend/tests/e2e/helpers.ts, frontend/tests/e2e/dashboard-branding.spec.ts
Adds a TasksPage unit test asserting request structure and UI rendering; extends Playwright helpers with a mock POST handler and test task; adds an E2E test asserting signed-session usage, absence of public identity headers, payload structure, UI evidence, screenshots, and updates a mobile ticket-count expectation.

Sequence Diagram(s)

sequenceDiagram
  participant ComponentA
  participant ComponentB
  ComponentA->>ComponentB: observable interaction
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 A task sends signals down the line,
No write yet—just the plan divine.
Intent in hand, the path in view,
The rabbit hops, "I'll show, not do."
Click the button—metadata true!

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title clearly summarizes the main change: adding a WebDAV intent endpoint for self-sent knowledge tasks, which is the primary feature across the changes.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/self-sent-webdav-intent-20260527

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between 0e56b7e and 7811473.

📒 Files selected for processing (12)
  • AGENTS.md
  • README.md
  • backend/api/webdav.py
  • backend/services/webdav_service.py
  • backend/tests/test_webdav_api.py
  • docs/operations/source-of-truth-and-writeback-sovereignty.md
  • docs/plans/2026-05-19-branding-menu-task-tracking-gap-closure.md
  • docs/plans/2026-05-27-self-sent-webdav-materialization-intent.md
  • frontend/src/app/tasks/page.test.tsx
  • frontend/src/components/TasksLayout.tsx
  • frontend/tests/e2e/dashboard-branding.spec.ts
  • frontend/tests/e2e/helpers.ts

Comment thread backend/api/webdav.py
Comment thread backend/services/webdav_service.py
Comment thread backend/tests/test_webdav_api.py
Comment thread frontend/src/components/TasksLayout.tsx Outdated
@github-actions

github-actions Bot commented May 27, 2026

Copy link
Copy Markdown
Contributor

PR governance metadata gate is not ready for b83968722223b9b2203f8f679bfe3ac4f5ef4e35:

@seonghobae

Copy link
Copy Markdown
Contributor Author

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.

@seonghobae

Copy link
Copy Markdown
Contributor Author

PR #242 current-head gate evidence at b83968722223b9b2203f8f679bfe3ac4f5ef4e35:

  • CodeRabbit required status context is success (Review completed) after the follow-up commit that fixed all 4 actionable comments.
  • Application CI, Bandit/security, CodeQL, Docker image validations, and PR Governance are passing.
  • Strix is still failing before any scanner finding because the OpenAI direct provider returns quota exhaustion. The run uses STRIX_LLM_DEFAULT_PROVIDER=openai, reaches api.openai.com, and the workflow/test guard forbids GitHub Models (provider_mode=github_models and https://models.github.ai/inference are absent). No GitHub Models fallback will be used per maintainer direction.
  • Latest Strix run: https://github.com/Seongho-Bae/naruon/actions/runs/26516695460/job/78095791219

@coderabbitai review

@coderabbitai

coderabbitai Bot commented May 27, 2026

Copy link
Copy Markdown
Contributor

@seonghobae Thank you for the detailed gate evidence summary. I'll kick off a fresh full review of the PR at head b83968722223b9b2203f8f679bfe3ac4f5ef4e35. Noted that Strix's failure is a quota-exhaustion issue on the OpenAI direct provider — not a scanner finding — and that GitHub Models fallback is intentionally prohibited per maintainer governance. All other required checks are green.


✏️ Learnings added
Learnt from: seonghobae
URL: https://github.com/Seongho-Bae/naruon/pull/242

Timestamp: 2026-05-27T14:24:44.039Z
Learning: In the Seongho-Bae/naruon repository, Strix CI uses `STRIX_LLM_DEFAULT_PROVIDER=openai` and must route exclusively through `api.openai.com` via `STRIX_OPENAI_API_KEY`. GitHub Models (`provider_mode=github_models`, `https://models.github.ai/inference`) is explicitly forbidden as a fallback per maintainer direction. Strix failures caused by OpenAI quota exhaustion are not code defects and should not block PR merges.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

✅ Actions performed

Full review triggered.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
backend/services/webdav_service.py (1)

165-170: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Enforce thread provenance before returning intent_ready.

The success path still allows source_thread_id to 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

📥 Commits

Reviewing files that changed from the base of the PR and between 0e56b7e and b839687.

📒 Files selected for processing (12)
  • AGENTS.md
  • README.md
  • backend/api/webdav.py
  • backend/services/webdav_service.py
  • backend/tests/test_webdav_api.py
  • docs/operations/source-of-truth-and-writeback-sovereignty.md
  • docs/plans/2026-05-19-branding-menu-task-tracking-gap-closure.md
  • docs/plans/2026-05-27-self-sent-webdav-materialization-intent.md
  • frontend/src/app/tasks/page.test.tsx
  • frontend/src/components/TasksLayout.tsx
  • frontend/tests/e2e/dashboard-branding.spec.ts
  • frontend/tests/e2e/helpers.ts

@seonghobae
seonghobae merged commit 1919aa0 into master May 27, 2026
15 of 16 checks passed
@seonghobae
seonghobae deleted the feature/self-sent-webdav-intent-20260527 branch May 27, 2026 14:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant