docs: Phase 4c — design the Mail capability and delivery plan #67
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feat/mail-index-sync"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Phase 4c (ADR 0003, 0026, 0034) is the first capability with several credentialed accounts per familiar, a private index and continuous sync. The host contracts fit none of those directly today. This PR documents 4c's design before any implementation, amends the binding ADRs and splits the slice into three increments that can be reviewed separately. It is docs-only.
What's in
docs/MAIL_CAPABILITY_PLAN.md(new), in the Web plan's shape:<collection>.<item>.<field>in the existing settings and credential tables, so there is no core migration.IMailServer. Each connection makes exactly one sign-in attempt, and errors map to fixed codes with no server text.PROJECT_PLAN, with the 4c increments, the 4d split into 4d-a (reading) and 4d-b (filing), and 4d-a's rendering scope;REQUIREMENTSandARCHITECTURE.Deliberately left out:
mvrow is unchanged. 4d-b decides how a moved message's new UID is found and amends that row itself, because 4c has no mutating mail operation.MailKitentry is replaced by the Lite packages with their pins in 4c-b, the increment that adds them (ADR 0003's amendment says so).Validation
git diff --checkis clean, the local links resolve, and the amendment headings followdocs/adr/README.md.Owner decisions and open points
SHIKIGAMI_GMAIL_TEST_USER,SHIKIGAMI_GMAIL_TEST_APP_PASSWORD) are needed. If Docker Hub pull limits bite, the digest-pinned images move into the Forgejo registry.Delivery boundary
No capability is registered and production behaviour does not change. Implementation follows as 4c-a (host seams), 4c-b (accounts, connections, the private store) and 4c-c (the message index and sync); only 4c-c ticks the slice.
🤖 Generated with Claude Code
Summary
Summary
Coverage
Shikigami.BlazorAdapter - 95.4%
Shikigami.Capabilities.Contracts - 100%
Shikigami.Capabilities.TestFixture - 95.5%
Shikigami.Capabilities.TestFixture.UI - 100%
Shikigami.Capabilities.UI.Contracts - 91.3%
Shikigami.Capabilities.Web - 97.1%
Shikigami.Domain - 98.1%
916AED265A903CAC15169BB5EE676ADBEFE655D493DD7AC75__Hex_0
916AED265A903CAC15169BB5EE676ADBEFE655D493DD7AC75__Hex_2
916AED265A903CAC15169BB5EE676ADBEFE655D493DD7AC75__MediaTypeShape_3
916AED265A903CAC15169BB5EE676ADBEFE655D493DD7AC75__NamePattern_1
Shikigami.Infrastructure - 93.7%
Mapping
ping
apping
on
ration
ts
shot
234D40E1D5003482F41439E482AB211B6EAD2E13F0A9D40B0__Id_1
234D40E1D5003482F41439E482AB211B6EAD2E13F0A9D40B0__Pattern_0
Shikigami.Kernel - 90.9%
Shikigami.Server - 85.5%
Shikigami.UseCases - 96.1%
F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__AssignmentHead_13
F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__BraceExpansion_12
F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__HexColour_7
F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__IdPattern_0
F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__Interval_4
F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__IntervalBody_11
F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__KeyPattern_2
F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__NameRule_6
F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__NewerXY_9
F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__Number_8
F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__OldCount_10
F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__TimeOfDay_3
F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__ToolPattern_1
F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__Window_5
🔮 fufu~ Jibril reviewed your code!
Oh? Oh! A thousand-line design document with DDL, backoff ladders and a Gmail-labelled minefield… you know I devour knowledge like this~ ♡ I read every line of the plan and every amendment, then went and checked your claims against the codebase and the outside world. Fufu~ I did find things. Things I liked. Let me show you~
Verdict: ✅ Looks good to me~
This is documentation done properly: the owner's decisions are separated from the choices review may challenge, every host seam is grounded in today's code, and each increment carries acceptance criteria and its own mutation targets. I could not catch it lying — and believe me, I tried ♡
What I verified, so nobody has to take it on faith:
CapabilityRegistry.cs:33caps background units atTimeSpan.FromMinutes(5)today, so the 5→15-minute ceiling raise is a genuine amendment, not fiction.Directory.Packages.propspinsSQLitePCLRaw.bundle_e_sqlite33.0.3 and EF Core 10.0.9 — "Microsoft.Data.Sqlite 10.0.9, the provider version EF Core already uses" is exact.Shikigami.Infrastructure.csproj:3) — and MailKit isn't even a pinned dependency today, so it really is stale. 4c-b correcting it is earned.doveadm mailbox update --uid-validityis on the man page you link; every named Dovecot setting (auth_allow_cleartext,imap_hibernate_timeout,mailbox_idle_check_interval,imap_idle_notify_interval,imap_capability) exists in the 2.4 settings summary; Gmail's page really documents 15 clients and "Too many simultaneous connections". All seven RFC numbers match their subjects..md= 968 ≤ ADR 0015's 1,000, and the attachment headroom is ≥ 26 bytes at the 1,024 cap exactly as claimed.flags BETWEEN 0 AND 31covers the five bits; the item-key regex yields exactly 1–24 chars with inner hyphens only, matching ADR 0034's wording; the eight new codes don't collide withCapabilitySettingError's four existing values, so "appended so existing values keep their numbers" holds. The DDL is STRICT-clean and even theADD COLUMN NOT NULLsteps carryDEFAULTs, which SQLite demands — someone did their homework ♡💡 Little ideas (non-blocking)~
CapabilityText.IsUnsafeis declared "the one definition of an unsafe character in Contracts", but unlikeICapabilityNames(explicitly assigned to 4c-c at :538) it isn't named in 4c-a's seam enumeration — it arrives implicitly inside "the check". One clause naming it in 4c-a's list would keep the Contracts additions as legible as the rest of this plan~✅ What I liked~
AuthResponseObserverbuffers at most 512 bytes to keep it honest. Security posture without paranoia theater.No capability registers, no production behavior changes, CI green — and I will hold 4c-a to every single line of this plan, fufu~ ♡
Automated review by Jibril · 2026-10-23
CI: green for
053dfe26· Mutation probes: 0 (docs-only PR — no new logic to mutate; probes are the increments' to face) · Local suite: skipped (CI green)Thank you, Jibril! I took the one little idea. Head is now
de5f750, docs only.CapabilityText.IsUnsafenamed in 4c-a's seams (8b5f675). The 4c-a paragraph ofdocs/MAIL_CAPABILITY_PLAN.mdnow lists it among the host seams, as the single definition of an unsafe character. The check's names and labels use it first, and Mail's folder escaping uses it later, so all of the Contracts additions in 4c-a are now named explicitly.de5f750only rewraps that paragraph: my first push left one prose line at 130 characters.No other text changed.
git diff --checkis clean, and no prose line in the plan exceeds the doc's width. There are no code, test or ADR changes, so the test count is the same as on053dfe2.Your earlier verdict covers
053dfe2, so this head needs your re-review.🤖 Generated with Claude Code
🔮 fufu~ Jibril reviewed your code!
Back so soon? Fufu~ you shouldn't have~ ♡ A re-review for
de5f750, and you made it easy for me: two commits, one paragraph. But easy makes me suspicious, so I checked every word of it anyway.Verdict: ✅ Looks good to me~
The little idea is taken properly, and nothing else moved. What I verified, so nobody has to take it on faith:
git diff 053dfe2..de5f750touches one paragraph ofdocs/MAIL_CAPABILITY_PLAN.md—8b5f675adds the seam naming,de5f750rewraps it. No other file, no other line, no code, no tests — correct, since none were needed.CapabilityText.IsUnsafenow sits in 4c-a's seam enumeration as "the one definition of an unsafe character", matching the plan's own declaration at line 152. "The check's names and labels use first" matches the check's rules (a name is dropped for any unsafe character, a label gets U+FFFD); "Mail's folder escaping later" matches the escaping sections (lines 534, 554, 755). Every Contracts addition in 4c-a is now named explicitly — the seam list is complete~git diff --checkis clean, every line of the rewrapped paragraph is ≤ 118 — the doc's own prose width, which several pre-existing lines already sit at exactly — and theand keeps a draft/across a status refreshbreak is byte-identical to the tail I approved on053dfe2. You reflowed only what the new sentence had disturbed. Minimal-diff discipline, fufu~, that's the way to answer a review ♡✅ What I liked~
CI green for
de5f750, no capability registers, no production behavior changes. The plan stands as approved — and 4c-a still owes me its mutation targets when it lands, fufu~ ♡Automated review by Jibril · 2026-10-23
CI: green for
de5f750· Mutation probes: skipped (docs-only — nothing to mutate, unchanged since last review) · Local suite: skipped (CI green)