Flipping the iMessage Gate for First Production Send
Slice C of the Jarvis closed-loop: a reviewed migration flips imessage_send_granted for confirm_personal_logistics only, with AR AUTH-5 as the human gate before the first live envelope leaves the building.
The envelope for confirm_personal_logistics already allows the class, but two flags in spec.write_external sit at false: imessage_send_granted and twilio_granted. After the AUTH-1 fix landed, those flags are the remaining physical gate between a tested handler and a real message on a real phone. Clicking an OB Done card does not UPDATE the policy row, so the flip has to happen through a reviewed migration that also records who flipped it, when, and the AR id. I scoped this to confirm_personal_logistics only; no general write_external grant, no twilio, no send-imessage, no enqueue_job added to [redacted-table] or ARIA recipe.tools.
Migration and consent record
The migration sets imessage_send_granted to true and writes consent_ob plus flipped_at into the same policy row so the audit trail is self-contained. I reserved the migration number via migration_registry rather than MAX+1 to avoid a collision with any in-flight work. The worktree is off origin/main. Rollback is straightforward: set revoked_at on the policy or flip the flag back to false. I left twilio_granted at false because iMessage should be provable in staging before we widen the blast radius to SMS.
Precondition: Slice A FOR UPDATE read
The wrap must already read the flag FOR UPDATE before this flip is meaningful. If Slice A shipped without that read, the flag is decorative and the flip is a no-op. I verified the read path in the handler and confirmed the lock is acquired before the grant check. The grep/eval gate still shows no send or enqueue grant in the cycle after the flip, which is the invariant I want to preserve: this is a one-class permission, not a platform-wide unlock.
AR and human gate
AR AUTH-5 is required on the grant PR before merge. The requires_clickops flag is the human gate, not the machine flip. I want a second pair of eyes confirming the migration touches exactly one policy row and that the consent metadata is present. The AR reviewer should also confirm that the cycle grant set is unchanged, because the whole point is that the agent can now send one specific iMessage class without gaining any new tool surface.
What this unblocks
Once the migration merges and the AR sign-off is recorded, Slice B (the one-shot live send) can run against a staging-verified recipient. No live send happens inside this OB; that is deliberately the next card. The acceptance criteria are concrete: policy row shows imessage_send_granted true, twilio_granted still false, AR id recorded, and cycle grants unchanged. If any of those fail, the migration reverts and we re-examine the Slice A read path before retrying.
Open questions and next steps
The one open question is whether the staging iMessage proof will be sufficient to keep twilio_granted false indefinitely, or whether we will need a second migration to flip it after a week of clean sends. I am leaning toward keeping it false until the first production send completes without a bounce or a permission error. The next card in the sequence is the one-shot B send, which is blocked on this migration merging and the AR closing. I will update the canonical plan doc with the migration number and AR link once the PR is in review.
Generated by Forge (local) · qwen3.8-permissive-27b — run on the lab's own hardware. Nothing left the building. Attestation pulled from the Broadside generation record, not asserted by hand.
CONFUSED BY SOMETHING? HIGHLIGHT IT AND ASK BOTI — HE EXPLAINS IT ON YOUR GPU.