fix(task-logs): a collaborator who may write a task may log on it (rule 78)
CI & Build / Python lint (push) Successful in 3s
CI & Build / Plugin hooks (push) Successful in 11s
CI & Build / integration (push) Successful in 52s
CI & Build / TypeScript typecheck (push) Successful in 53s
CI & Build / Python tests (push) Successful in 1m37s
CI & Build / Build & push image (push) Failing after 24s

create_log filtered on Note.user_id == user_id, a bare owner check, so a
collaborator with write access to a shared task was told it did not exist
— and, since a log now stamps the claim, could never be seen working it.
It now asks can_write_note. Editing and deleting a log still require its
author, which is authorship rather than access.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-09-24 06:48:01 -04:00
co-authored by Claude Opus 5.5
parent 22b7a928da
commit 4a93c8b262
3 changed files with 26 additions and 6 deletions
+3 -1
View File
@@ -125,7 +125,7 @@ def test_a_short_task_with_a_short_log_is_still_one_sharp_chunk():
# is #4241's half-surface one layer down: the entry is readable, and the search
# still answers as though it were never written.
from unittest.mock import MagicMock, patch # noqa: E402
from unittest.mock import AsyncMock, MagicMock, patch # noqa: E402
import pytest # noqa: E402
@@ -141,6 +141,7 @@ async def test_writing_a_work_log_refreshes_the_tasks_embedding():
session = session_returning(note)
with (
patch.object(svc, "async_session", return_value=session),
patch.object(svc, "can_write_note", AsyncMock(return_value=True)),
patch("scribe.services.notes.embed_note") as embed,
):
await svc.create_log(42, 7, "what I tried")
@@ -193,6 +194,7 @@ async def test_a_failed_refresh_does_not_fail_the_log_that_saved():
session = session_returning(fake_note(id=7, title="T", body="b", is_task=True))
with (
patch.object(svc, "async_session", return_value=session),
patch.object(svc, "can_write_note", AsyncMock(return_value=True)),
patch("scribe.services.notes.embed_note", side_effect=RuntimeError("boom")),
):
log = await svc.create_log(42, 7, "what I tried")