Documentation
¶
Overview ¶
Package mailbox is the intra-island agent message store — Lane 5, Phase 1 of docs/inter-island-exchange-spec.md. Agents in the SAME island exchange small typed messages through the daemon (a shared blackboard / mailbox). It is the low-risk layer: same-island agents are one trust domain (they already share /workspace + home), so intra-island messaging is allowed by default.
Cross-island exchange is deliberately NOT here — that is the brokered, operator-granted, audited "link" layer (Phase 2+), with a separate deny-all posture and an action-delegation gate. Keeping the two apart is the whole point.
Index ¶
- type Message
- type MessageAction
- type Origin
- type Store
- func (s *Store) DeliverAction(island, sourceIsland, from, fromLabel, to, topic, actionType, params string) Message
- func (s *Store) DeliverExternal(island, sourceIsland, from, fromLabel, to, topic, payload string) Message
- func (s *Store) Latest(island string) int64
- func (s *Store) Poll(island, agent string, since int64) []Message
- func (s *Store) Send(island, from, to, topic, payload string) Message
- func (s *Store) SetArrivalHook(fn func(m Message))
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Message ¶
type Message struct {
Seq int64 `json:"seq"`
Island string `json:"island"`
From string `json:"from"` // sender agent id (literal)
To string `json:"to,omitempty"` // recipient agent id; empty = broadcast to the island
Topic string `json:"topic,omitempty"` // optional channel within the island
Payload string `json:"payload"`
Time time.Time `json:"time"`
// Origin is daemon-stamped provenance, set ONLY for messages delivered from
// another island over a brokered link (Lane 5). nil for ordinary intra-island
// messages. Agents cannot set it — see DeliverExternal vs Send.
Origin *Origin `json:"origin,omitempty"`
// Action, when non-nil, marks this as a cross-island ACTION delegation (Lane 5
// Phase 3) rather than free-form info: a NAMED, typed operation the recipient
// island exposed, authorized by the daemon's action gate. Set only by
// DeliverAction. The recipient runs its handler for Action.Type — it must not
// interpret Payload as a free-form prompt.
Action *MessageAction `json:"action,omitempty"`
}
Message is one intra-island message.
type MessageAction ¶
MessageAction is a named, typed action invocation carried by a cross-island action delegation. Type is one of the recipient island's exposed action types.
type Origin ¶
type Origin struct {
SourceIsland string `json:"source_island"`
CrossIsland bool `json:"cross_island"`
// FromLabel is the sender agent's display label, stamped by the daemon at
// send time from the SOURCE island's roster. A receiving island can't resolve
// another island's roster (containment), so this is the only way it can show
// a sender name instead of a bare id. Display-only + omitempty: absent when
// the sender has no label, and consumers fall back to From (the id). Like the
// rest of Origin it's unforgeable — only the cross-island delivery path sets it.
FromLabel string `json:"from_label,omitempty"`
}
Origin marks a message that entered this island's mailbox from ANOTHER island over a brokered link. It's machine-read provenance (SDK / activity feed / audit tooling branch on CrossIsland) — a structured field rather than a parseable sender-string prefix, and unforgeable because only the daemon's cross-island delivery path sets it.
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store is a per-island ring of recent messages. The ring bounds memory so a chatty island can't grow it unbounded. When opened with a path (see Open) the store also persists every append to disk so undelivered messages AND the seq cursor survive a daemon restart — without that, a restart wiped the ring and reset seq to 1, silently dropping unread cross-session coordination (the no-lost-work bar). NewStore keeps the pure in-memory form for tests.
func NewStore ¶
NewStore returns an in-memory store retaining up to maxPerIsland messages per island. Nothing is persisted — use Open for a restart-durable store.
func Open ¶ added in v0.6.9
Open returns a store backed by path: it loads any previously persisted messages + seq on startup, and persists every append back to path so they survive a daemon restart. A missing file starts empty; a corrupt/unreadable one is logged and started empty (the daemon must still come up). A nil logger is tolerated. maxPerIsland bounds each island's ring as in NewStore.
func (*Store) DeliverAction ¶
func (s *Store) DeliverAction(island, sourceIsland, from, fromLabel, to, topic, actionType, params string) Message
DeliverAction appends a cross-island ACTION delegation into `island`'s mailbox (Lane 5 Phase 3): a named, typed operation (actionType/params) the daemon's action gate authorized. Like DeliverExternal it stamps Origin; it additionally sets the structured Action field. Distinct from Send/DeliverExternal so only the gated action path can mark a message as an action.
func (*Store) DeliverExternal ¶
func (s *Store) DeliverExternal(island, sourceIsland, from, fromLabel, to, topic, payload string) Message
DeliverExternal appends a message delivered into `island`'s mailbox from another island (sourceIsland) over a brokered link, stamping daemon-controlled Origin (CrossIsland=true). `from` is the source agent's literal id, `fromLabel` its display label resolved by the caller from the source roster (may be ""), and `to` the local recipient agent. It is distinct from Send precisely so the intra-island path can never set Origin — provenance is the daemon's to assert.
func (*Store) Latest ¶
Latest returns the highest seq retained for an island (0 if none) — a cheap cursor for "everything after now".
func (*Store) Poll ¶
Poll returns the retained messages in island visible to agent `agent` with Seq > since, ordered by Seq. Visible = broadcasts (To == "") plus messages addressed To == agent. since == 0 returns all retained. An empty agent sees only broadcasts (an operator/observer view).
func (*Store) Send ¶
Send appends a message to an island's ring and returns it with Seq/Time set. from is the sender agent id; to is a recipient agent id, or "" to broadcast to every agent in the island.
func (*Store) SetArrivalHook ¶
SetArrivalHook registers a callback fired (in its own goroutine, so it never holds the store lock or blocks the sender) after every message is appended — the wake-on-message seam (Lane 5 Phase 3.5). nil disables it.