Skip to content

Calendar Architecture — One Calendar, Omniscient Read, No MCP

project: hinata-infrastructurestatus: livingowner: jimmy-neutron + irohcreated: 2026-05-26 The doctrine for how Hinata interacts with Apple Calendar, Reminders, and related event surfaces. Establishes the no-MCP rule, the single-write-target rule, and the omniscient-read rule.

Rule 1. No MCP for personal data surfaces

Michael ruling 2026-06-11: MCPs are BANNED from Hinata — absolute, all surfaces, not just personal data. No MCP server is installed, configured, or invoked by any Hinata harness, agent, or script. Every capability an MCP would provide is implemented as a vault-audited Hinata script instead. This elevates the rule below from preference to ban.

Hinata does not use third-party MCP servers (che-ical-mcp, mail MCPs, notes MCPs, contacts MCPs) for personal data access. Reasons:

  • MCP packages are not vault-audited; their dependencies can update silently.

  • MCPs inherit any Automation / Full Disk Access permission you grant them — blast radius if compromised is the entire scope of granted perms.

  • MCPs are local processes but have no default outbound-network restriction — they can POST what they read.

Instead: every "MCP-like" capability becomes a Hinata script in ~/Sandpit/hinata/scripts/, osascript-backed, reviewable in git, callable from Claude Code via Bash.

ReplacesHinata scriptCapability

che-ical-mcp calendar~/Sandpit/hinata/scripts/hinata-cal.pyread / write / probe / search Apple Calendar che-ical-mcp reminders~/Sandpit/hinata/scripts/hinata-reminders.py (TBD)read / write Reminders.app any notes MCP~/Sandpit/hinata/scripts/hinata-notes.py (TBD)read Notes.app any mail MCPnone — mail-poller.py is a plain IMAP systemd poller on Z2 ct102, not an MCP and not one of these osascript wrappers; no mail MCP-replacement script existsmail metadata + body archive (archive-mail-bodies.py retired 2026-06-11 — mail-poller owns body archiving)

Rule 2. Single write target — the "Hinata" iCloud calendar

The iCloud calendar named "Hinata" is the only calendar Hinata's automations write to. Confirmed to exist 2026-05-26. Every producer routes through hinata-cal.py create() — never inline osascript.

Consequence on iPhone: Michael toggles off every iCloud calendar except "Hinata" in Settings → Calendar → Accounts → iCloud → Calendars. iPhone now shows the Hinata-curated stream only. Other calendars stay on the Mac for context.

Producers (every script below MUST write only through hinata-cal.py):

  • eod-calendar-sync.sh — Reminders aggregates → calendar blocks

  • calendar-nudge.py (#840037) — pre/post-event nudges as standalone events (or alerts)

  • contacts-call-slots.py (#840038) — 15-min call windows

  • whatsapp-meetup-sync.py (#840039) — Meetup events from WhatsApp groups

  • Studio Calendar tab create flow

Rule 3. Omniscient read across all iCloud calendars

For context, Hinata reads every iCloud calendar Michael has — work, family, personal, holidays, Hinata. The iPhone toggle-off only affects iPhone display; the Mac Calendar.app holds everything. hinata-cal.py list_range() defaults to reading from ALL calendars unless restricted.

Reason: a "social event this evening" might be on the family calendar, not Hinata. The nudge engine still needs to know it's happening.

Trust model

SurfaceTrust levelWhy

Mac Calendar.app local DBtrustedmacOS-encrypted at rest if FileVault on; Automation perm gated iCloud sync of Hinata calendartrustedApple's encrypted-in-transit and at-rest infra; Michael's iCloud account iPhone Calendar.apptrustedSame iCloud account; same encryption Hinata scripts in SandpittrustedVault-audited code, version-controlled MCPs (third-party)untrustedReason for this doctrine

Network behavior

Every Hinata calendar script has zero outbound network calls by default. The only network traffic is:

* iCloud's own sync (out of Hinata's scope; Apple-managed).

* Optional Telegram delivery for nudges, via the existing `send-telegram.sh` (the only outbound point, audited).

FDA / Automation permission model

  * `hinata-cal.py` needs **Calendar Automation perm** — granted per-script in System Settings → Privacy & Security → Automation.

  * Reminders + Notes wrappers (when added) need the equivalent.

  * Mail body archive needs Mail Automation perm (#840024).

  * Screen Time needs Full Disk Access (#840031).

Each is granted to the running process (Terminal, launchd) one time; no MCP intermediary holds the perm.

Open architecture decisions

    * **Tagging propagation:** events emitted by Hinata automations should carry their `#tag:[slug]` in the Notes field per the calendar-tagging-schema. `hinata-cal.py create()` accepts a `tag` arg and writes it.

    * **Bi-directional sync:** the Studio Calendar tab edits MUST round-trip back into the Hinata calendar via `hinata-cal.py update()`. No "local-only" state in Studio.

    * **Subscribed calendars (read-only feeds):** if/when Meetup or other external feeds are subscribed, they remain READ surfaces — Hinata never writes to them.

Architecture stack summary

      * `#840049` calendar tagging schema — the data model

      * This doc — the access doctrine

      * `hinata-cal.py` — the implementation

      * `calendar-nudge.py` (#840037) — the first consumer

      * Studio Calendar tab rewire — makes the data visible

      * iPhone toggle-off + Hinata-as-default — the user-side configuration

◆ hinata · projects/hinata-infrastructure/calendar-architecture.html · phase-19 conversion