Skip to main content
Loom Core docs

Tracking

Mobile Companion Security Model (v1 Additive Freeze)

This document defines the security model for Loom Companion iPhone/iPad access.

Status: v1 additive contract freeze (updated 2026-02-25). Auth, scope checks, and audit logging are implemented in internal/hud/api_mobile.go, including read-only parity-wave endpoints gated by mobile:read.

Tracking

Scope

  • Mobile monitoring and session lifecycle control APIs.
  • Dual connectivity modes:
    • LAN mode
    • Gateway mode
  • Authentication, authorization, auditing, and transport requirements.

Security Objectives

  • Ensure only authorized operators can monitor/control sessions from mobile.
  • Preserve least privilege for mobile-originated mutations.
  • Maintain auditability for all write actions.
  • Avoid weaker assumptions in gateway mode than in LAN mode.

Threat Model Summary

Primary threats:

  • stolen/compromised device token,
  • replay of captured credentials,
  • MITM on untrusted networks,
  • privilege escalation via broad endpoint exposure,
  • misuse of high-risk mutation endpoints from mobile.

Primary controls:

  • short-lived bearer tokens + rotation,
  • TLS required outside localhost testing paths,
  • strict endpoint allowlist for mobile role,
  • actor/device-aware audit logging,
  • rate limits and optional policy hooks.

Trust Boundaries

  1. Mobile app/device
  2. Network transport
  3. Loom HTTP surface (LAN or gateway)
  4. HUD/bridge/daemon internals
  5. Downstream MCP servers/tools

Boundary policy:

  • Every boundary crossing must maintain authenticated identity and scope.

Connectivity Modes

LAN Mode

  • Intended for trusted local/private networks.
  • Still requires authenticated API access.
  • TLS strongly recommended; required when crossing non-private segments.

Gateway Mode

  • Intended for remote/off-network operations.
  • Requires full zero-trust posture:
    • strong auth,
    • TLS,
    • strict role checks,
    • enhanced audit and anomaly visibility.
  • Unified host routing:
    • /ws, /hosts, /health, /ready stay on MCP gateway.
    • /api/mobile/v1/* is routed to the in-cluster mobile-hud backend.

Authentication Requirements

  • Mobile protected endpoints require bearer auth.
  • Bootstrap decision (MBL-1):
    • Default: native OAuth authorization code + PKCE with external user-agent/system browser.
    • Fallback: device-code pairing only when direct browser-mediated auth is not practical for the selected profile.
    • Flow selection must be explicit per profile/policy; implicit fallback is not allowed.
  • UI/profile requirement: operators must see which bootstrap mode is active and why fallback is being used.
  • Tokens must be:
    • short-lived,
    • revocable,
    • bound to actor identity and device/session context.
  • Pairing/bootstrap flow must avoid long-lived static secrets embedded in app builds.

Fallback hardening requirements:

  • Device/user codes must use short TTLs and bounded retry windows.
  • Pairing endpoints must enforce brute-force controls (attempt caps + rate limits).
  • Pairing UX must provide anti-phishing guidance and explicit endpoint confirmation.

Recommended claims:

  • sub (actor id)
  • scope or role claims
  • device_id
  • exp (expiry)
  • optional mode or aud for endpoint partitioning

Authorization Requirements

  • Introduce dedicated mobile role (for example mobile_operator).
  • Explicitly allow only v1 endpoints required by product scope.
  • Keep high-risk endpoints disabled by default on mobile:
    • arbitrary tool execution,
    • registry/config mutation,
    • destructive platform operations.

mobile_operator Endpoint/Authz Matrix (v1 Freeze Candidate)

Policy conventions:

  • allow means authenticated bearer token is required.
  • deny means request must return authorization failure for mobile_operator.
  • LAN and gateway share the same endpoint authorization; gateway enforces stricter transport posture.
EndpointPurposemobile_operator (LAN)mobile_operator (Gateway)Required scope
GET /api/mobile/v1/ping (optional)Connectivity probeallow (can be anonymous only if explicitly enabled)allow (same rule; prefer authenticated probe)mobile:read if authenticated
GET /api/mobile/v1/dashboardFleet/health summaryallowallowmobile:read
GET /api/mobile/v1/sessionsSession listallowallowmobile:read
GET /api/mobile/v1/sessions/{session_id}Session detailallowallowmobile:read
GET /api/mobile/v1/sessions/{session_id}/eventsSession event historyallowallowmobile:read
GET /api/mobile/v1/tasksTask list + status countsallowallowmobile:read
GET /api/mobile/v1/workflowsWorkflow summariesallowallowmobile:read
GET /api/mobile/v1/workflows/{workflow_id}Workflow detailallowallowmobile:read
GET /api/mobile/v1/presencePresence + claims/worktreesallowallowmobile:read
GET /api/mobile/v1/memory/statsMemory hierarchy statsallowallowmobile:read
GET /api/mobile/v1/memory/itemsMemory recall (read-only)allowallowmobile:read
GET /api/mobile/v1/streamContext stream snapshotallowallowmobile:read
GET /api/mobile/v1/topologyAgent topology graphallowallowmobile:read
GET /api/mobile/v1/graph/statsGraph aggregate statsallowallowmobile:read
GET /api/mobile/v1/graph/entitiesGraph entity list/searchallowallowmobile:read
GET /api/mobile/v1/graph/pathGraph path lookupallowallowmobile:read
GET /api/mobile/v1/reasoning/chainsReasoning chain summariesallowallowmobile:read
GET /api/mobile/v1/reasoning/chains/{chain_id}Reasoning chain detailallowallowmobile:read
GET /api/mobile/v1/events/streamRealtime SSE feedallowallowmobile:read
POST /api/mobile/v1/sessionsStart/create sessionallowallowmobile:session:create
POST /api/mobile/v1/sessions/{session_id}/endEnd sessionallowallowmobile:session:end
POST /api/mobile/v1/agents/{agent_id}/session/end (future)End by agent selectordeny (v1)deny (v1)N/A
POST /api/agent/session-start (direct HUD path)Internal mutation pathdeny for mobile tokens (must use /api/mobile/v1/*)deny for mobile tokens (must use /api/mobile/v1/*)N/A
POST /api/agent/session-end (direct HUD path)Internal mutation pathdeny for mobile tokens (must use /api/mobile/v1/*)deny for mobile tokens (must use /api/mobile/v1/*)N/A
POST /api/agent/* other mutation routesHigh-risk operator actionsdenydenyN/A

Additional authorization rules:

  • Gateway mode requires TLS and cert validation; plaintext transport is not permitted.
  • If token scope is missing, default to deny for all protected endpoints.
  • All allow mutation paths must write audit fields: actor, device, mode, endpoint, target, outcome.
  • Parity-wave endpoints are read-only only in v1; graph/memory/workflow/task mutations remain denied outside dedicated mobile mutation routes.

Transport Security

  • Gateway mode: HTTPS/TLS mandatory.
  • LAN mode: HTTPS strongly preferred; plaintext only for explicitly local debug scenarios.
  • Certificate validation must be enforced on mobile clients (no blanket trust bypass).

iOS TLS Enforcement (Validated)

The Loom Companion iOS app enforces TLS validation at two levels:

1. Gateway HTTPS-only gate (application layer)

ConnectionViewModel.pair() rejects gateway connections with non-HTTPS URLs before any network request:

if connectionMode == .gateway, url.scheme != "https" {
    pairingError = "Gateway mode requires HTTPS"
    return
}

Reference: apps/loom-companion-ios/Sources/LoomCompanionKit/ViewModels/ConnectionViewModel.swift:46-48

2. Certificate validation (platform layer)

iOS URLSession validates server certificates by default:

  • Rejects expired certificates.
  • Rejects self-signed certificates.
  • Rejects certificates with hostname mismatch.
  • Validates full certificate chain to a trusted root CA.

The app does not override URLSessionDelegate certificate evaluation and has no NSAppTransportSecurity exceptions. LAN mode permits HTTP for local debug scenarios but still validates certificates when HTTPS is used.

3. Server-side TLS support

The HUD server supports TLS via --tls-cert and --tls-key flags. A log warning is emitted when a mobile operator token is configured without TLS on a non-localhost bind address.

Reference: internal/hud/app.go (TLS listener wrapping)

Remediation for TLS failures

Certificate validation failures surface as network errors in the app. The ConnectionRemediation model provides gateway-specific guidance including "Verify TLS certificate validity if using HTTPS."

Common remediation steps:

  • Ensure the server certificate is issued by a trusted CA (not self-signed).
  • Verify the certificate hostname matches the gateway URL.
  • Check certificate expiry date.
  • For development/testing with self-signed certs, use LAN mode instead of gateway mode.

Session and Token Lifecycle

  • Access token lifetime should be short (minutes to low hours).
  • Refresh token usage (if enabled) must support immediate revocation.
  • Device logout must invalidate active token set for that device context.

Audit and Observability

For every mobile-originated mutation capture:

  • actor id
  • device id
  • connectivity mode (lan/gateway)
  • endpoint + action
  • target resource ids
  • result (success/error/denied) and reason
  • timestamp and request id

Alert candidates:

  • repeated auth failures,
  • repeated denied mutations,
  • unexpected mode changes per device,
  • high-rate mutation bursts.

Abuse and Rate Controls

  • Apply per-actor and per-endpoint rate limits.
  • Reuse existing RBAC/rate limit and gateway policy facilities where possible.
  • Add conservative defaults for mobile mutation endpoints.

Mutation Threat Analysis

This section documents specific attack scenarios and mitigations for each mutation endpoint.

POST /api/mobile/v1/sessions (session-create)

ThreatSeverityMitigationStatus
Unauthorized session spam — attacker floods create requests to exhaust resourcesHighScope mobile:session:create required; rate limiting per actorImplemented (scope + MobileRateLimiter)
Agent impersonation — creating sessions as another agent to pollute contextMediumAudit logging captures actor_id + agent_id + remote address; operator review via audit trailImplemented (logMobileAudit)
Replay of captured create request — attacker replays a valid session-create requestMediumShort-lived tokens reduce replay window; session-create is idempotent for same active context (no duplicate side effects)Token rotation deferred to M1; idempotency via bridge layer
Namespace injection — malicious namespace string to manipulate context isolationLowInput validation at agent-context bridge layer; namespace is treated as an opaque string with no path traversal semanticsImplemented in bridge layer

POST /api/mobile/v1/sessions/{session_id}/end (session-end)

ThreatSeverityMitigationStatus
Unauthorized termination — attacker ends a critical in-progress sessionHighScope mobile:session:end required; mobile UX should include confirmation stepScope: implemented. UX confirmation: deferred to M2/M3
Session ID enumeration — brute-forcing session IDs to end arbitrary sessionsMediumAuth required for all requests; session IDs are opaque; audit trail records all attemptsImplemented (auth + audit)
Replay of end request — attacker replays a captured end requestLowIdempotent: ending an already-ended session returns success with no side effectsImplemented in bridge layer
Mass session termination — attacker rapidly ends all sessions via automated requestsHighRate limiting per actor; audit alerting on high-rate mutation burstsImplemented (rate limiter + audit logging)

Cross-cutting controls

ControlCoverageStatus
Bearer token auth (constant-time comparison)All endpointsImplemented (requireMobileScope)
Per-endpoint scope checksAll endpointsImplemented (3 scopes: mobile:read, mobile:session:create, mobile:session:end)
Mobile-token-outside-mobile-API guardPrevents mobile tokens from accessing internal /api/agent/* routesImplemented (mobileTokenOutsideMobileAPI)
Structured audit loggingAll mutation endpointsImplemented (logMobileAudit with device_id)
Request ID in every responseAll endpointsImplemented (newRequestID in mobileEnvelope)
Per-actor rate limitingAll endpoints (mutation + read)Implemented (MobileRateLimiter, minute-window counters)
Token revocationRuntime revocation without restartImplemented (MobileTokenRevocationList + admin endpoint)
Device identity trackingAudit logs for mutationsImplemented (X-Device-ID header extraction)
TLS supportGateway mode HTTPSImplemented (--tls-cert, --tls-key config)

Hardening Checklist (Pre-Beta)

  • Protected mobile endpoints require auth in both modes.
  • Role policy tests enforce allowed/denied matrix. (Tracks MBL-3)
  • Scope checks enforce per-endpoint permission model.
  • Token expiry and revocation behavior verified. (Tracks MBL-2)
  • TLS and cert-validation behavior validated for gateway mode. (Tracks MBL-9)
  • Audit logs include actor + endpoint + target fields for mutations.
  • Mobile token blocked from non-mobile API paths.
  • Rate limiting configured for mutation endpoints.
  • Refresh token rotation implemented. (Tracks MBL-2)
  • Security incident runbook includes mobile credential revocation steps. (Tracks MBL-11)

Test Matrix

Security regression tests should include:

  • authorized vs unauthorized access in both LAN and gateway modes,
  • expired/revoked token behavior,
  • mobile role denied-path tests,
  • replay attempt handling,
  • audit field presence checks.

Security Review Signoff (M0)

Date: 2026-02-23 Scope: v1 contract freeze — review of implemented controls against threat model.

Controls verified as implemented

ControlImplementationReference
Bearer token authenticationConstant-time comparison via crypto/subtleapi_mobile.go:90-100, api_mobile.go:109-133
Per-endpoint scope checks3 scopes enforced: mobile:read, mobile:session:create, mobile:session:endapi_mobile.go:16-20, api_mobile.go:135-149
Structured audit logginglogMobileAudit records action, endpoint, remote_addr, targets, outcomeapi_mobile.go:152-167
Mobile-token-outside-mobile-API guardMobile tokens rejected for non-/api/mobile/v1/ pathsapi_mobile.go:102-107
Consistent error envelopeAll errors use mobileEnvelope with ok: false and structured error codesapi_mobile.go:60-73
Request traceabilityEvery response includes request_id and timestamp in metaapi_mobile.go:22-33

Controls deferred to M1 (now resolved)

ControlResolution
Rate limiting configurationImplemented: MobileRateLimiter with per-actor minute-window counters (mobile_ratelimit.go)
TLS enforcement for gateway modeImplemented: --tls-cert / --tls-key flags, tls.NewListener wrapping (app.go)
Device ID tracking in auditImplemented: X-Device-ID header extraction in logMobileAudit()
Token revocationImplemented: MobileTokenRevocationList with admin revoke endpoint (mobile_revoke.go)

Controls deferred to M2

ControlReason
Refresh token rotationRequires full OAuth 2.1 token lifecycle (M2 task, when iOS app consumes it)
Full OAuth 2.1 mobile flowRequires iOS app to implement PKCE authorization code flow (M2 task)

Assessment

The v1 mobile API surface now implements comprehensive security controls: authentication, fine-grained scoping, audit logging with device identity, mobile-token isolation, per-actor rate limiting, runtime token revocation, and TLS support for gateway mode. The remaining deferred control (OAuth token lifecycle with refresh rotation) requires the iOS app to exist and is tracked for M2.

Security Review Signoff (M1)

Date: 2026-02-23 Scope: M1 hardening — rate limiting, token revocation, device tracking, TLS.

M1 controls verified

ControlImplementationTests
Rate limiting (mutation)MobileRateLimiter, 10 req/min defaultTestMobileRateLimiter_* (5 tests), TestHandler_MobileRateLimit_Returns429
Rate limiting (read)MobileRateLimiter, 60 req/min defaultSame test suite
Token revocationMobileTokenRevocationList with SHA-256 hash storageTestMobileRevocation_* (4 tests)
Admin revoke endpointPOST /api/mobile/v1/admin/revoke (admin-token protected)TestMobileRevocation_AdminEndpoint* (2 tests)
Device ID trackingX-Device-ID header → audit logTestMobileAudit_DeviceIDExtraction
TLS support--tls-cert / --tls-key with tls.NewListenerBuild verification
Configurable bind address--bind flag (default: 127.0.0.1)Build verification
Non-localhost TLS warningLog warning when mobile token set without TLS on non-localhostBuild verification

Sources

  • docs/MOBILE_COMPANION_AUTH_BOOTSTRAP.md — consolidated auth bootstrap decision, flow descriptions, and LAN/gateway comparison
  • internal/hud/api_mobile.go — all mobile v1 handlers, auth, audit, revoke
  • internal/hud/mobile_ratelimit.go — rate limiter implementation
  • internal/hud/mobile_revoke.go — token revocation list
  • internal/hud/app.go — TLS, bind address, rate limiter + revocation init
  • cmd/loom/hud.go — CLI flags
  • internal/hud/app_test.go — M1 test suite
  • docs/MOBILE_CREDENTIAL_REVOCATION_RUNBOOK.md — incident runbook for mobile token revocation
  • docs/ENTERPRISE_SECURITY.md
  • docs/STREAMABLE_HTTP.md
  • .loom/20-product-spec.md
  • .loom/30-implementation-plan.md