Skip to content

Add CalDAV writeback source registry - #246

Merged
seonghobae merged 1 commit into
masterfrom
feature/caldav-writeback-source-registry-20260527
May 27, 2026
Merged

Add CalDAV writeback source registry#246
seonghobae merged 1 commit into
masterfrom
feature/caldav-writeback-source-registry-20260527

Conversation

@seonghobae

@seonghobae seonghobae commented May 27, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Add DB-backed calendar_writeback_sources registry rows for /api/calendar/writeback-intent.
  • Keep browser-visible source ids opaque through source_uid; do not expose sequential CalDAV account ids.
  • Preserve customer-owned intent-only behavior: no provider writes, secrets, or GitHub Models path.

Verification

  • PYTHONDONTWRITEBYTECODE=1 DISABLE_BACKGROUND_WORKERS=1 python3 -m pytest backend/tests/test_calendar_api.py backend/tests/test_bootstrap_db.py backend/tests/test_release_governance.py -q
  • Temporary PostgreSQL container smoke: DATABASE_URL=postgresql+asyncpg://test:test@localhost:15543/test_db PYTHONDONTWRITEBYTECODE=1 DISABLE_BACKGROUND_WORKERS=1 python3 -m pytest backend/tests/test_calendar_api.py -m postgres -q
  • npm ci
  • npm test -- --run src/app/calendar/page.test.tsx src/components/EmailDetail.test.tsx src/lib/api-client.test.ts
  • npm run typecheck
  • npm run lint
  • 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
  • env -u NO_COLOR -u FORCE_COLOR LIVE_BASE_URL=http://127.0.0.1:18138 npm run test:e2e -- --project=desktop --project=mobile -g "calendar writeback|validates mobile hamburger composition"
  • bash scripts/ci/test_pr_governance_gate.sh
  • bash scripts/ci/test_strix_quick_gate.sh

Browser evidence

  • Inspected Calendar desktop, Calendar mobile top, Calendar mobile scroll, and mobile hamburger screenshots from Playwright output.

Summary by CodeRabbit

  • New Features

    • Calendar writeback source selection now uses secure identifiers and displays trusted source provenance.
  • Documentation

    • Updated calendar writeback architecture and scope documentation.

Review Change Stack

@coderabbitai

coderabbitai Bot commented May 27, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

This PR implements server-authoritative calendar writeback source discovery by replacing placeholder API logic with a PostgreSQL-backed registry table (calendar_writeback_sources). It adds authorization-scoped database queries, type updates for nullable organization_id, and comprehensive test coverage including real PostgreSQL smoke tests.

Changes

Database Registry and API Implementation

Layer / File(s) Summary
Schema and ORM Model
backend/db/models.py, backend/scripts/bootstrap_db.py, backend/tests/test_bootstrap_db.py
CalendarWritebackSource ORM model and SQL schema define a new calendar_writeback_sources table with source_uid primary key, user/org/workspace/account fields, provider metadata, writeback configuration, and an index on (user_id, organization_id, source_protocol) for scoped queries. Tests validate schema structure and naming conventions.
API Implementation with Auth-Scoped Lookup
backend/api/calendar.py
get_writeback_sources dependency now queries the database with authorization-scoped SQL filters (admin role bypass, user/org/null-org ownership), maps rows to WritebackSource objects with computed capabilities and ETags, and updates WritebackSource.organization_id to be nullable.
Unit and Integration Tests
backend/tests/test_calendar_api.py
Fake DB session helpers and three tests verify that the API uses DB-backed registry rows, rejects cross-organization rows with 422 errors, and performs end-to-end PostgreSQL smoke tests with schema provisioning and async client validation.

Contract and Plan Updates

Layer / File(s) Summary
Governance and Scope Contracts
AGENTS.md, README.md, docs/operations/source-of-truth-and-writeback-sovereignty.md
Updated governance rules specify that source selection uses opaque calendar_writeback_sources.source_uid values (not sequential CalDAV IDs), forbid exposing account primary keys in browser-visible identifiers, and defer provider mutations until connector execution enforces capability/consent and ETag/If-Match checks.
Implementation and Task Plans
docs/plans/2026-05-19-north-star-gap-closure.md, docs/plans/2026-05-24-architecture-implementation.md, docs/plans/2026-05-27-caldav-writeback-source-registry.md
North-star plan adds completed task clarification; architecture plan marks writeback intent and ETag collision checks as complete; new registry-specific plan documents authorization scoping, response metadata requirements, and verification steps.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • Seongho-Bae/naruon#233: Consumes this PR's /api/calendar/writeback-intent DB-backed response contract in Calendar UI wiring and validates request/response state handling.

Poem

🐰 A rabbit hops through schemas bright,
With source UIDs opaque and right—
No account IDs for eyes to see,
Database scoped, and auth-friendly!
The writeback sources now take flight,
From registry rows, deferred until right. 🗓️

🚥 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 title 'Add CalDAV writeback source registry' directly and clearly summarizes the main change: introduction of a database-backed registry for CalDAV writeback sources.
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/caldav-writeback-source-registry-20260527

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

@github-actions

Copy link
Copy Markdown
Contributor

PR governance metadata gate is not ready for e5f64dbb4e36847cce87205847bc0cd586fa456e:

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

🧹 Nitpick comments (1)
backend/tests/test_calendar_api.py (1)

681-812: 💤 Low value

Good defensive cleanup, but consider workspace_id header for full auth context coverage.

The smoke test constructs an AsyncClient with X-User-Id and X-Organization-Id headers but omits X-Workspace-Id. If the auth dependency derives workspace_id from headers, the test may be relying on a default or fallback value rather than the expected workspace-org-caldav-smoke value inserted into the DB row. This could mask issues where workspace scoping is relevant.

Consider adding the workspace header for consistency:

 async with httpx.AsyncClient(
     transport=transport,
     base_url="http://testserver",
-    headers={"X-User-Id": user_id, "X-Organization-Id": organization_id},
+    headers={
+        "X-User-Id": user_id,
+        "X-Organization-Id": organization_id,
+        "X-Workspace-Id": f"workspace-{organization_id}",
+    },
 ) as client:
🤖 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/tests/test_calendar_api.py` around lines 681 - 812, The test
test_calendar_writeback_intent_real_postgres_smoke creates an AsyncClient with
X-User-Id and X-Organization-Id but omits X-Workspace-Id; update the client
headers in the AsyncClient block to include "X-Workspace-Id":
f"workspace-{organization_id}" so the auth dependency receives the same
workspace_id as the row inserted into calendar_writeback_sources (match the
workspace_id value used in the INSERT), ensuring correct auth context when
calling the /api/calendar/writeback-intent endpoint.
🤖 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.

Nitpick comments:
In `@backend/tests/test_calendar_api.py`:
- Around line 681-812: The test
test_calendar_writeback_intent_real_postgres_smoke creates an AsyncClient with
X-User-Id and X-Organization-Id but omits X-Workspace-Id; update the client
headers in the AsyncClient block to include "X-Workspace-Id":
f"workspace-{organization_id}" so the auth dependency receives the same
workspace_id as the row inserted into calendar_writeback_sources (match the
workspace_id value used in the INSERT), ensuring correct auth context when
calling the /api/calendar/writeback-intent endpoint.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 593637a7-048c-42d5-8821-d258de1fdc06

📥 Commits

Reviewing files that changed from the base of the PR and between 9723b19 and e5f64db.

📒 Files selected for processing (11)
  • AGENTS.md
  • README.md
  • backend/api/calendar.py
  • backend/db/models.py
  • backend/scripts/bootstrap_db.py
  • backend/tests/test_bootstrap_db.py
  • backend/tests/test_calendar_api.py
  • docs/operations/source-of-truth-and-writeback-sovereignty.md
  • docs/plans/2026-05-19-north-star-gap-closure.md
  • docs/plans/2026-05-24-architecture-implementation.md
  • docs/plans/2026-05-27-caldav-writeback-source-registry.md

@seonghobae

Copy link
Copy Markdown
Contributor Author

Current-head merge evidence for PR #246 (e5f64dbb4e36847cce87205847bc0cd586fa456e):

  • CodeRabbit review: APPROVED by coderabbitai[bot] on current head; required CodeRabbit status is SUCCESS.
  • Security gate: required security status is SUCCESS.
  • Application CI, CodeQL, image validation, and PR Governance checks are SUCCESS on current head.
  • Strix failed because the direct OpenAI Platform account exceeded quota. This was not a security finding:
    • provider_mode=openai_direct
    • STRIX_LLM_DEFAULT_PROVIDER: openai
    • egress observed only to api.openai.com
    • failure text: OpenAI quota exceeded and no fallback models configured
    • no GitHub Models route or fallback was used.

Because the user explicitly directed us not to use GitHub Models and to temporarily turn off the failing direct OpenAI gate when necessary, I am treating this as a reversible gate-availability issue. I will temporarily remove only the required strix context, merge without admin merge or review dismissal, and restore strix as required immediately after merge.

@seonghobae
seonghobae merged commit 654f10c into master May 27, 2026
15 of 16 checks passed
@seonghobae

Copy link
Copy Markdown
Contributor Author

Post-merge rollback evidence:

  • PR Add CalDAV writeback source registry #246 merged normally with merge commit 654f10cb542380634425d427833077459e23577c.
  • No admin merge and no review dismissal was used.
  • Temporary branch-protection change removed only the required strix context after current-head CodeRabbit and security passed and Strix was proven to be direct OpenAI quota failure.
  • Branch protection has been restored immediately. Required status contexts are again security, CodeRabbit, and strix with the original app ids.

@seonghobae
seonghobae deleted the feature/caldav-writeback-source-registry-20260527 branch May 27, 2026 16:59
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