Skip to content

edge.interface

edge.interface

Zone B — interface gateway + adapters (BUILD-SPEC §6, §12).

The networked relay between the owner's messaging front-end and the sealed core. The private default is the local app over Tailscale (LocalAdapter); WhatsApp-style adapters are opt-in (Invariant 11). The gateway reaches the core ONLY through the filesystem handoff (GatewayChannel), never by importing it; it cannot read the vault.

InterfaceAdapter

Bases: Protocol

name instance-attribute

transits_third_party instance-attribute

poll()

Return messages received since the last poll (may be empty).

send(message)

Deliver a reply to the owner.

LocalAdapter dataclass

Private default: a local app over loopback/Tailscale. The local UI pushes the owner's messages via receive(); replies land in sent (what the UI renders). No third party.

name = 'local' class-attribute instance-attribute

transits_third_party = False class-attribute instance-attribute

sent = field(default_factory=list) class-attribute instance-attribute

receive(text, *, conversation='default')

poll()

send(message)

WhatsAppAdapter dataclass

Opt-in convenience adapter that transits a third party (Invariant 11). Declared to demonstrate the pluggable contract + the privacy flag; the live integration (an unofficial library / Business Cloud API, with its ToS/stability caveats) is not built in Phase 6.

name = 'whatsapp' class-attribute instance-attribute

transits_third_party = True class-attribute instance-attribute

poll()

send(message)

GatewayChannel dataclass

handoff instance-attribute

submit(message)

read_response(request_id)

await_response(request_id, *, timeout_s=30.0, poll_interval=0.1)

InterfaceGateway dataclass

adapter instance-attribute

channel instance-attribute

allow_third_party = False class-attribute instance-attribute

submit_inbound()

Poll the adapter and hand any new messages to the core. Returns request ids.

deliver_responses()

Send any ready core responses back through the adapter. Returns how many.

ThirdPartyNotAllowedError

Bases: RuntimeError

A third-party-transiting adapter was used without an explicit opt-in (Invariant 11).

InboundMessage dataclass

text instance-attribute

conversation = 'default' class-attribute instance-attribute

id = field(default_factory=(lambda: uuid4().hex)) class-attribute instance-attribute

attachments = () class-attribute instance-attribute

ts = field(default_factory=_utcnow) class-attribute instance-attribute

to_request()

OutboundMessage dataclass

text instance-attribute

conversation = 'default' class-attribute instance-attribute

id = '' class-attribute instance-attribute

ts = field(default_factory=_utcnow) class-attribute instance-attribute

from_response(obj) classmethod

adapter

Interface adapters (BUILD-SPEC §12, Invariant 11).

One contract, many transports. The PRIVATE DEFAULT is LocalAdapter — a local app reached over loopback/Tailscale, so the owner's interactions never leave the trust boundary. Other transports (WhatsApp/Telegram/Signal) route through a third party, so the owner's interactions leave the boundary even though the corpus never does — those carry transits_third_party = True and are opt-in (the gateway refuses them unless explicitly allowed). The adapter only ever sees messages and replies; it cannot read the vault.

InterfaceAdapter

Bases: Protocol

name instance-attribute
transits_third_party instance-attribute
poll()

Return messages received since the last poll (may be empty).

send(message)

Deliver a reply to the owner.

LocalAdapter dataclass

Private default: a local app over loopback/Tailscale. The local UI pushes the owner's messages via receive(); replies land in sent (what the UI renders). No third party.

name = 'local' class-attribute instance-attribute
transits_third_party = False class-attribute instance-attribute
sent = field(default_factory=list) class-attribute instance-attribute
receive(text, *, conversation='default')
poll()
send(message)

WhatsAppAdapter dataclass

Opt-in convenience adapter that transits a third party (Invariant 11). Declared to demonstrate the pluggable contract + the privacy flag; the live integration (an unofficial library / Business Cloud API, with its ToS/stability caveats) is not built in Phase 6.

name = 'whatsapp' class-attribute instance-attribute
transits_third_party = True class-attribute instance-attribute
poll()
send(message)

channel

Gateway side of the core handoff (BUILD-SPEC §6, §12; Invariant 2).

The gateway writes a request into the shared handoff directory and polls for the core's response — the ONLY way the networked edge reaches the sealed core. No imports cross the boundary; the wire format (mirrored in core.interface) is: requests/.json = {"id", "conversation", "text", "ts"} responses/.json = {"id", "conversation", "text", "ts"} The gateway never reads the private vault — it only moves messages.

REQUESTS = 'requests' module-attribute

RESPONSES = 'responses' module-attribute

GatewayChannel dataclass

handoff instance-attribute
submit(message)
read_response(request_id)
await_response(request_id, *, timeout_s=30.0, poll_interval=0.1)

gateway

The interface gateway (BUILD-SPEC §6, §12) — Zone B.

Relays owner messages between an adapter and the sealed core over the filesystem handoff, and relays the core's replies back. The gateway holds the network-facing adapter; the core holds the vault. Neither reaches the other's resource — they meet only at the handoff (Invariant 2). Third-party adapters are refused unless the owner explicitly opts in (Invariant 11).

ThirdPartyNotAllowedError

Bases: RuntimeError

A third-party-transiting adapter was used without an explicit opt-in (Invariant 11).

InterfaceGateway dataclass

adapter instance-attribute
channel instance-attribute
allow_third_party = False class-attribute instance-attribute
submit_inbound()

Poll the adapter and hand any new messages to the core. Returns request ids.

deliver_responses()

Send any ready core responses back through the adapter. Returns how many.

protocol

Interface message contract (BUILD-SPEC §12).

The adapter-facing message types. The on-disk handoff format (the JSON the gateway writes for the core and reads back) is defined here on the edge side and mirrored, not imported, by core.interface — the core/edge boundary is a filesystem handoff, never a shared import (Invariant 2, CONVENTIONS).

InboundMessage dataclass

text instance-attribute
conversation = 'default' class-attribute instance-attribute
id = field(default_factory=(lambda: uuid4().hex)) class-attribute instance-attribute
attachments = () class-attribute instance-attribute
ts = field(default_factory=_utcnow) class-attribute instance-attribute
to_request()

OutboundMessage dataclass

text instance-attribute
conversation = 'default' class-attribute instance-attribute
id = '' class-attribute instance-attribute
ts = field(default_factory=_utcnow) class-attribute instance-attribute
from_response(obj) classmethod