Gatekeeping on a Mac mini (2028): A Practical Software Architecture

Thesis
Use a headless Mac mini as the on-premise “brain” of gatekeeping: it owns policy, state, and audit; it exposes local tools via MCP (Model Context Protocol); and it orchestrates cloud LLMs through a strict, provider-neutral Agent API. All customer data and schedules remain local; off-site storage is a single encrypted blob. No transactional mirroring. No cloud learning loops.

Why a Mac mini
• Headless-friendly: lives on a thermal backboard; tech brings a keyboard/monitor only for service.
• Secure enclave + FileVault: hardware-backed keys and full-disk encryption.
• Low power, quiet, reliable: perfect for always-on edge workloads.
• Mature admin surface: launchd, SSH, Apple Remote Desktop, MDM if desired.

Layered Software Stack (from metal to agents)

  1. Host OS (macOS, headless)
    • FileVault on; secure boot; auto-login disabled; no user GUI sessions.
    • Admin via SSH from a jump host; ARD allowed only during scheduled service windows.
    • Time sync is critical (signed logs/receipts); use multiple NTP sources.
  2. Process & Isolation
    • Prefer lightweight containers (Colima/Lima + containerd or Docker Desktop) for microservices; otherwise use signed app bundles + launchd.
    • One service = one identity = one log stream. Keep blast radius small.
  3. Data Plane (Local-Only)
    • Primary DB: PostgreSQL (on-device) with WAL; selected columns (PII, notes) field-level encrypted using keys sealed to the Secure Enclave.
    • “Master Calendar”: local canonical calendar tables; do not treat Google/Apple calendars as source of truth.
    • Outbound syncers (see below) write to staff calendars as views, not authorities.
  4. MCP Hub (on-prem)
    MCP = Model Context Protocol. Think of it as the local tool bus. It exposes capabilities and resources to any compliant agent while enforcing data locality.
    Core MCP tool namespaces (each its own microservice):
    • mcp.scheduling: query/commit availability; enforce durations, buffers, skills, rooms.
    • mcp.customers: create/update customers; attach notes; list cadence and flags.
    • mcp.pricing: compute price quotes, deposits, holds; returns itemized policy.
    • mcp.policy: read-only policy graph (cancellation, VIP, escalation, privacy redactions).
    • mcp.inventory: manage staff, rooms, equipment, and maintenance windows.
    • mcp.messaging: outbound SMS/email/voice receipts using business identity; queue on WAN loss.
    • mcp.audit: append-only, tamper-evident event log with hash chain, anchored to a daily notarization.
    • mcp.recovery: produce and ingest the encrypted blob; verify integrity; drive device rekey.
  5. Agent Orchestrator (Hybrid)
    • Talks to external LLM providers via the 2028 Agent API (provider-neutral plumbing for tools, function calls, and real-time).
    • All tool calls are MCP endpoints that live on the Mac mini; cloud LLMs never see raw tables—only answers to narrowly scoped tool requests.
    • Egress policy firewall: outbound prompts are templated and redacted by policy; PII, prices, and internal identifiers are either masked or replaced with context handles.
    • Provider neutrality: register multiple upstreams (OpenAI, Anthropic, Google, xAI); selection by policy (cost/latency/privacy class).
    • Deterministic rails: for scheduling, the LLM never “decides” a slot; it proposes; mcp.scheduling is the final arbiter.
  6. Telephony/Comms Bridge (Local)
    • If you terminate analog voice on-prem: use an ATA/FXO gateway that speaks SIP to a local soft-PBX (Asterisk/FreeSWITCH container). The PBX hands calls to the Agent Orchestrator, which invokes MCP tools.
    • If you route voice at the carrier during outages: the Orchestrator still handles SMS/email confirmations via mcp.messaging using the business identity; all transcripts/logs stay local.
  7. Backup & Recovery (Blob-Only)
    • Snapshot cadence (e.g., every 5–15 minutes) to produce a single encrypted blob containing DB state + audit chain checkpoints.
    • Client-side encryption (age/libsodium) using keys sealed to the enclave; upload blobs to off-site storage (iCloud Drive, S3-compatible, etc.) with zero knowledge to the provider.
    • No row-level replication; no cloud indices; no analytics sync.

Data Flows (what actually happens)

Inbound conversation

  1. Voice/SMS/Web enters the Orchestrator.
  2. LLM (Agent API) generates intent + parameters only; MCP tools read/update local state.
  3. mcp.scheduling computes legal options; Orchestrator presents them; upon confirm, mcp.scheduling commits; mcp.pricing issues deposit logic; mcp.messaging sends a receipt.
  4. mcp.audit logs every decision with a hash pointer to the prior event.

Outbound sync (staff tools)
• Google/Apple calendars: mcp.calendar_sync publishes read-only views per staffer; each entry carries a signed token for verification. Edits from staff calendars are treated as requests back into mcp.scheduling; they never overwrite canonical state.
• POS/CRM: pull only via MCP readers or one-way webhooks to avoid leaking internal models to a cloud. If POS must be updated, use a narrow, idempotent writer from mcp.pricing with redaction.

Security Model (no hand-waving)

Secrets & keys
• Root secrets live in the Secure Enclave; services receive capability-scoped derived keys at start via a local KMS.
• The Orchestrator holds only short-lived provider tokens; it rotates and revokes them; tokens are never persisted to disk.
• Staff OAuth (Google/Apple) is stored as encrypted refresh tokens bound to service accounts; rotation is monthly.

Surface minimization
• No inbound ports exposed beyond what you must serve (SIP if local PBX, HTTPS for admin/API on a private VLAN).
• Admin API requires mutual TLS with client certs and time-boxed access grants.
• All logs are local; if you need centralized visibility, push digest metrics, not raw transcripts.

Redaction & egress guard
• Before any outbound LLM call, Orchestrator applies:
– Entity scrubbing (names/phones replaced by handles like cust:8472).
– Numeric fuzzing where not material (e.g., drop last 2 digits of a price unless quoting).
– Scope limiters (context windows contain only the minimum policy text or summaries needed).

Policy Engine (determinism beats vibes)

Represent policy as code, not prose:
• Durations, buffers, staff skills, room constraints, eligibility, cancellation windows, deposit rules, VIP handling, lateness mitigation.
• State machine for exceptions: power loss, telco outage, staff illness, emergency closures.
• Always return explanations alongside decisions—for receipts and for staff trust.

Operational Modes

A) Normal
• WAN healthy; on-prem voice or carrier-routed voice terminates locally; Orchestrator + MCP do first-touch, schedule, and receipt.
• Blobs rotate and upload; daily notarization anchors the audit chain.

B) Degraded (WAN down)
• Voice continues (on-prem PBX or analog line); mcp.messaging queues outbound receipts until WAN returns.
• Orchestrator stays fully functional; providers with offline cache (local FAQ, policy) can still perform reasoning for common flows; otherwise fall back to deterministic prompts that do not need fresh LLM calls.

C) Recovery (hardware replaced)
• Fresh Mac mini → bootstrap → owner auth (hardware token + recovery phrase) → fetch latest blob → verify → restore DB + policies → ingest any off-device buffers (from authorized mobiles) → resume.
• Old device’s keys are revoked; audit chain continues with a new anchor.

Provisioning (Day 0 → Day 2)

Day 0: Hardening & base
• Install macOS, enable FileVault, secure boot, create “svc” account (no GUI login).
• Install container runtime (Colima) and Postgres.
• Create local KMS (sealed to enclave) and enroll service identities.
• Set up launchd units for each MCP service and the Orchestrator.
• Configure NTP, log rotation, snapshot cadence, and blob destination.

Day 1: MCP + tools
• Deploy mcp.scheduling, .customers, .pricing, .policy, .inventory, .messaging, .audit, .recovery.
• Load policies (YAML/JSON) signed by the owner key; services refuse unsigned policies.
• Stand up the Orchestrator and register Agent API providers (OpenAI/Anthropic/Google/xAI) with cost/latency/PII classes.

Day 2: Integrations & drills
• Configure staff calendar views (read-only); verify round-trip “request” edits.
• Bind telephony (SIP to PBX or carrier integration).
• Run outage drill: WAN down → complete a booking → queue receipts → restore WAN → receipts send; verify audit chain and blob integrity.

Minimal Example: Policy + Tool Contract (illustrative, not exhaustive)

policy.scheduling.yaml

version: 1
signature: owner-key-id-72A…   # detached sig stored separately; verified at load
services:
  haircut_basic:
    duration_min: 45
    cleanup_min: 10
    staff_skills: [cut_basic]
    rooms: [chair]
    price_code: CUT_BASIC
  color_partial:
    duration_min: 90
    cleanup_min: 15
    staff_skills: [color_lvl1]
    rooms: [chair,sink]
rules:
  buffers:
    before_open_min: 30
    before_close_min: 30
  cancellation:
    free_window_hr: 24
    deposit_policy:
      required: true
      amount_code: DEPOSIT_STD
vip:
  bypass_waitlist: true
  priority_weight: 1.5

mcp.scheduling tool schema (excerpt)

{
  "name": "mcp.scheduling.commit",
  "input": {
    "customer_handle": "cust:8472",
    "service_code": "haircut_basic",
    "preferred_staff": "staff:ana",
    "window_start": "2030-05-12T14:00:00-04:00",
    "window_end": "2030-05-12T16:00:00-04:00",
    "constraints": {"accessibility": ["ground_floor"]}
  },
  "output": {
    "status": "CONFIRMED|WINDOW_ONLY|DECLINED",
    "slot": "2030-05-12T14:30:00-04:00",
    "reason": "policy explanation string",
    "receipt_id": "rcpt:9F2A…"
  }
}

Governance & Evidence

Audit
• Every tool call records: who/what invoked it (provider, model, version), inputs (after redaction), outputs, policy hashes, and the prior log hash.
• Daily anchor: post a small hash to a public ledger or email it to the owner’s notarization inbox; proves log integrity without exposing data.

Metrics (local dashboards)
• First-Touch Autonomy (share of interactions completed without human).
• Human Escalation Rate (by reason).
• Waitlist Fill Rate; No-Show Recovery.
• Locality Ratio (writes on-device vs anywhere else; target ≈100%).
• Provider Mix (cost, latency, failure rate per upstream).

Hard Rules (non-negotiable)

  1. No transactional state leaves the Mac mini. Only encrypted blobs go off-site.
  2. Cloud LLMs never receive raw tables—only tool-scoped prompts and minimal context.
  3. Calendars outside are views, not sources. All writes flow through mcp.scheduling.
  4. The Orchestrator is policy-subordinate; it cannot commit state without MCP confirmation.
  5. Break-glass access (screen/keyboard) is time-boxed, logged, and requires the owner’s presence.

This pattern scales from a single-chair studio to a multi-room clinic because the invariant holds: the Mac mini is the authority for state and policy, MCP is the only doorway to that state, and the cloud is a replaceable reasoning layer—not a place where your business is quietly learned.

Author: John Rector

Co-founded E2open with a $2.1 billion exit in May 2025. Opened a 3,000 sq ft AI Lab on Clements Ferry Road called "Charleston AI" in January 2026 to help local individuals and organizations understand and use artificial intelligence. Authored several books: World War AI, Speak In The Past Tense, Ideas Have People, The Coming AI Subconscious, Robot Noon, and Love, The Cosmic Dance to name a few.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Discover more from John Rector

Subscribe now to keep reading and get access to the full archive.

Continue reading