auth: put mail ingestion on the same rung as resolving a task

IngestMail was AuthRead and SetTaskStatus was AuthWrite, and they answer
the same question: may this module change what is on his lists? The old
argument for AuthRead — ingestion is additive, it can only produce
candidate tasks — is still true and is the weaker half, because a
compromised mail reader that can fill the review page indefinitely is
not a read.

Nothing loses access. AuthWrite outside WriteFact only requires
enrollment, which mavmaild already has, and the method does not exist
unless the operator wired a mail block.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TrVSBKe3RFDF4fGYKWYQnX
This commit is contained in:
kami
2026-08-01 16:29:45 +04:00
parent 76a251a20d
commit df3220d039
2 changed files with 36 additions and 5 deletions
+22
View File
@@ -417,6 +417,28 @@ func TestRequirement_SwapModel(t *testing.T) {
}
}
// TestRequirement_ListMutation — the three methods that change what is on his
// lists sit on one rung. IngestMail joined them on 2026-08-01; it used to be
// AuthRead, which made it disagree with SetTaskStatus about the same question.
// CaptureTask stays a read: it puts one line on a list he asked for.
func TestRequirement_ListMutation(t *testing.T) {
for _, m := range []ipc.Method{
ipc.MethodIngestMail, ipc.MethodSetTaskStatus,
} {
if got := Requirement(m); got != AuthWrite {
t.Errorf("%s authority = %v; want AuthWrite", m, got)
}
}
if got := Requirement(ipc.MethodCaptureTask); got != AuthRead {
t.Errorf("CaptureTask authority = %v; want AuthRead", got)
}
// mavmaild keeps working: AuthWrite outside WriteFact only needs enrollment.
maild := Scope{Surface: SurfaceCoreProcess, Module: "mavmaild", SourceScope: []string{"mail:*"}}
if err := Can(ipc.MethodIngestMail, maild, nil); err != nil {
t.Errorf("mavmaild ingesting mail = %v; want allowed", err)
}
}
// TestRequirement_Capture — recording other people is a write, not a read: it
// puts audio of them on disk. The read side, "что ты записываешь?", is not.
//