Phone Control

The Phone Control extension manages temporary access to high-risk commands on iOS phone nodes. It uses an arm/disarm model with timed expiry to grant and revoke camera, screen recording, and write access through the gateway.

Command groups

Commands are organized into three groups, plus an all shortcut:

GroupCommandsDescription
cameracamera.snap, camera.clipTake photos and short video clips
screenscreen.recordScreen recording
writescalendar.add, contacts.add, reminders.addCreate calendar events, contacts, reminders
allAll of the aboveArm everything at once

Arm/disarm model

Arming

When you arm a group, the extension:

  1. Adds the group's commands to the gateway allowCommands list
  2. Removes them from the denyCommands list (if present)
  3. Writes the armed state to disk for crash recovery
  4. Starts an expiry timer
bash
/phone arm camera 10m    # Allow camera commands for 10 minutes
/phone arm all 30s       # Allow everything for 30 seconds
/phone arm writes 2h     # Allow write commands for 2 hours

Duration format

UnitExampleDescription
s30sSeconds
m10mMinutes (default: 10m)
h2hHours
d1dDays

If no duration is specified, the default is 10 minutes.

Disarming

Disarming reverses the config changes:

  1. Removes commands that were added to allowCommands
  2. Restores commands to denyCommands that were removed during arming
  3. Deletes the state file
bash
/phone disarm            # Immediately revoke all armed commands

Auto-disarm

A background service checks the expiry timer every 15 seconds. When the armed duration expires, it automatically disarms by restoring the original gateway configuration.

The expiry check also runs on service startup, so if Mayros was restarted while armed, the state is recovered and expired states are cleaned up.

State persistence

Armed state is persisted to {stateDir}/plugins/phone-control/armed.json:

typescript
{
  version: 2,
  armedAtMs: number,          // When the arm was activated
  expiresAtMs: number | null, // null = manual disarm only
  group: "camera" | "screen" | "writes" | "all",
  armedCommands: string[],    // Commands in the armed group
  addedToAllow: string[],     // Commands added to allowCommands
  removedFromDeny: string[]   // Commands removed from denyCommands
}

The state file tracks exactly which config changes were made so disarming can precisely reverse them, even if the config was modified by other means in the interim.

Gateway integration

The extension modifies the gateway node configuration at config.gateway.nodes:

  • allowCommands: commands the gateway can invoke on phone nodes
  • denyCommands: commands the gateway must not invoke

Arming moves commands from deny to allow. Disarming moves them back. The extension writes the config file after each change, which triggers the config_change hook.

Slash command

The /phone slash command provides the full interface:

bash
/phone help              # Show usage and available groups
/phone status            # Show current arm state and expiry
/phone arm <group> [dur] # Arm a command group with optional duration
/phone disarm            # Immediately disarm

Status output

Phone control: armed (expires in 8m).
Temporarily allowed: camera.snap, camera.clip

Or when disarmed:

Phone control: disarmed.