Daily note reads must preserve read-only App Password access #752

Open
opened 2026-10-02 13:08:57 +00:00 by kayg · 4 comments
Owner

Context: #427 rev-mcp-api review, #484, DESIGN §41. Source base c4a61e8cf090170f35b1bed3350d9de20c83ecd5. Priority: High. No product edits or live reproduction in this review.

Evidence:

  • crates/calternal-server/src/wire.rs:2320 derives App Password access from is_read_request; :2375 treats GET as read.
  • crates/plugins/notes/src/lib.rs:3867 enters the missing Daily note branch and :3871 writes a new Note, indexes it and updates adjacent Daily note navigation.
  • scripts/action_registry.py:146 marks the GET action read-only. crates/calternal-server/src/mcp.rs:797 describes calternal_today as a read.
  • On origin/job/agentdocs-630 at 183ac356359f1f84afad30932f02e07323ddb7ed, crates/calternal-server/src/agent_docs/skill_intro.md:29 recommends a read-only MCP App Password and :59 uses calternal_today as the first read.

Impact:

Source review shows that a route classified as a read contains a content-creation branch. Its authorization and its tool hints do not describe that branch. No live authorization test was run.

Expected:

Keep read-only requests free of content writes. Missing Daily notes need a read result or an explicit write action that checks write access on the server. Preserve the ordinary Daily note flow for a User who can write. Update the tool hints and agent examples from the same action intent.

Regression test idea:

Add a route-level regression for a missing Daily note under a read-only principal. Assert unchanged Home content and adjacent Daily notes. Check the API, MCP and generated adapters against the same contract. Keep existing status expectations.

Duplicate check:

Searched all issue states for daily, read-only, and MCP; read #661. #661 concerns a viewing-triggered rewrite of an existing Note in the editor, not the missing-Daily-note creation branch.

Context: #427 rev-mcp-api review, #484, DESIGN §41. Source base `c4a61e8cf090170f35b1bed3350d9de20c83ecd5`. Priority: High. No product edits or live reproduction in this review. Evidence: - `crates/calternal-server/src/wire.rs:2320` derives App Password access from `is_read_request`; `:2375` treats GET as read. - `crates/plugins/notes/src/lib.rs:3867` enters the missing Daily note branch and `:3871` writes a new Note, indexes it and updates adjacent Daily note navigation. - `scripts/action_registry.py:146` marks the GET action read-only. `crates/calternal-server/src/mcp.rs:797` describes `calternal_today` as a read. - On `origin/job/agentdocs-630` at `183ac356359f1f84afad30932f02e07323ddb7ed`, `crates/calternal-server/src/agent_docs/skill_intro.md:29` recommends a read-only MCP App Password and `:59` uses `calternal_today` as the first read. Impact: Source review shows that a route classified as a read contains a content-creation branch. Its authorization and its tool hints do not describe that branch. No live authorization test was run. Expected: Keep read-only requests free of content writes. Missing Daily notes need a read result or an explicit write action that checks write access on the server. Preserve the ordinary Daily note flow for a User who can write. Update the tool hints and agent examples from the same action intent. Regression test idea: Add a route-level regression for a missing Daily note under a read-only principal. Assert unchanged Home content and adjacent Daily notes. Check the API, MCP and generated adapters against the same contract. Keep existing status expectations. Duplicate check: Searched all issue states for `daily`, `read-only`, and `MCP`; read #661. #661 concerns a viewing-triggered rewrite of an existing Note in the editor, not the missing-Daily-note creation branch.
Author
Owner

Starting work on job/notesperf, based on job/merge-round-7a at 2f4482ded066d9c5d9c59130377907f7fd2916c9. I will address the issue with focused changes and regression coverage, then report the final head SHA and verbatim gate output here.

Starting work on `job/notesperf`, based on `job/merge-round-7a` at `2f4482ded066d9c5d9c59130377907f7fd2916c9`. I will address the issue with focused changes and regression coverage, then report the final head SHA and verbatim gate output here.
Author
Owner
  • Evidence: contracts/action-policy.json:1409 declares daily with
    authority: read, read_only: true and replay: safe_read.
  • Handler: crates/plugins/notes/src/lib.rs:4233 creates a missing Daily
    note. Lines 4236–4241 write the file, index it and update nearby navigation.
  • Effect: the new explicit policy retains the known mismatch in #752.
    Generated adapters omit write confirmation. MCP publishes a read-only,
    idempotent hint. This review does not claim a new live authorization failure.
  • Rule: DESIGN §41 and #833 acceptance 2 require the contract to describe
    route authority. Read-only access must not write Home content (#752).
  • Fix: implement the read/write split in #752, then declare each operation's
    actual authority and replay policy. Until then, do not publish this operation
    as a safe read. Keep the normal Daily note flow for a User with write access.
  • Test idea: read a missing Daily note with read-only access. Assert unchanged
    Home content and adjacent Daily notes. Check hints on each adapter.
  • Existing issue: #752. No duplicate issue is required.

P2: User plugin toggle policy names the wrong scope

- Evidence: `contracts/action-policy.json:1409` declares `daily` with `authority: read`, `read_only: true` and `replay: safe_read`. - Handler: `crates/plugins/notes/src/lib.rs:4233` creates a missing Daily note. Lines 4236–4241 write the file, index it and update nearby navigation. - Effect: the new explicit policy retains the known mismatch in #752. Generated adapters omit write confirmation. MCP publishes a read-only, idempotent hint. This review does not claim a new live authorization failure. - Rule: DESIGN §41 and #833 acceptance 2 require the contract to describe route authority. Read-only access must not write Home content (#752). - Fix: implement the read/write split in #752, then declare each operation's actual authority and replay policy. Until then, do not publish this operation as a safe read. Keep the normal Daily note flow for a User with write access. - Test idea: read a missing Daily note with read-only access. Assert unchanged Home content and adjacent Daily notes. Check hints on each adapter. - Existing issue: #752. No duplicate issue is required. ## P2: User plugin toggle policy names the wrong scope
Author
Owner

Implemented the read/write split for Daily notes: GET now only finds and reads an existing file; POST creates or returns the date. Updated web, CLI, MCP guidance, and E2E fixture callers. Regression evidence: cargo test -p calternal-plugin-notes --lib reading_a_missing_daily_note_does_not_write_home_content passed (1 passed), and bunx vitest run src/lib/api/notes.test.ts passed (2 passed). The E2E/API adversarial checks and post-merge gates are still pending. Commit: 64197bb06.

Implemented the read/write split for Daily notes: GET now only finds and reads an existing file; POST creates or returns the date. Updated web, CLI, MCP guidance, and E2E fixture callers. Regression evidence: `cargo test -p calternal-plugin-notes --lib reading_a_missing_daily_note_does_not_write_home_content` passed (1 passed), and `bunx vitest run src/lib/api/notes.test.ts` passed (2 passed). The E2E/API adversarial checks and post-merge gates are still pending. Commit: 64197bb06.
Author
Owner

Implemented in 64197bb06; missing Daily GET read returns 404 without a filesystem write, POST creates or reads, and MCP GET remains read-only. Focused Notes regression passed. Agent Skill examples were aligned in 109b5b4cf; full server rerun remained blocked by shared filesystem load.

Implemented in 64197bb06; missing Daily GET read returns 404 without a filesystem write, POST creates or reads, and MCP GET remains read-only. Focused Notes regression passed. Agent Skill examples were aligned in 109b5b4cf; full server rerun remained blocked by shared filesystem load.
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
kayg/calternal#752
No description provided.