Message envelope

The shape of a Message envelope as it is persisted in SQLite, returned by the broker layer, and rendered by the CLI.

Persisted shape

Every message is a flat row of typed columns in messages — there is no JSON blob; messages.text carries the body and the remaining columns carry the routing and lifecycle fields. See data-model.md for the full column schema. The persisted shape is the canonical source of truth; every render the broker produces is a projection of these columns.

Rendered shape

The broker's read paths return the persisted columns as a flat dict (the typed-column dict), and the CLI projects that dict into a compact rendered envelope — by default the rendered envelope omits the columns whose values are constant or recoverable from context. The --full flag returns the typed-column dict unmodified.

Compact rendered envelope (default)

Field decisions:

FieldCompact text modeCompact JSON key--full text label--full JSON key
message_idthe bracketed [<id> segment on line 1ididmessage_id
from_member_idthe | from:<n> segment on line 1fromfromfrom_member_id
to_member_idomitted (the recipient's own poll already establishes to == self)omittedto, omitted for broadcast-summary rows (to_member_id IS NULL)to_member_id
owner_member_idomitted (always equals to_member_id for delivery rows; equals broadcaster for summary rows)omittedowner_member_id
status_timestampthe bare <ts> segment on line 1tsstatus_timestamp
textthe body line, truncated to CAFLEET_MAX_TEXT_LEN codepoints + , omitted when the body is emptytext, truncatedtext, omitted when the body is emptytext, untruncated
typethe | kind:<kind> segment when != "unicast"kind when "broadcast_summary"typetype
created_atomittedomittedcreated_at
status_stateomitted (unconditional)omittedstatestatus_state
origin_message_idthe | origin:<id> segment when non-NULLorigin when non-NULLorigin_message_id

JSON output

CLI JSON output is governed by the --json flag:

ModeOutput
--jsonCompact single-line JSON — no whitespace; non-ASCII (e.g. the suffix) is emitted as UTF-8, not escaped.
(text mode)Two lines per message in the compact rendered shape; a variable-length labeled block per message in --full.

Examples

A poll result with one unicast delivery (id 42, from 7, body "build OK").

Default (cafleet message poll --member-id <my-member-id> --json):

[{"id":42,"from":7,"ts":"2026-05-05T05:42:11.123456+00:00","text":"build OK"}]

--full (cafleet message poll --member-id <my-member-id> --full --json):

[
  {
    "message_id": 42,
    "owner_member_id": 3,
    "from_member_id": 7,
    "to_member_id": 3,
    "type": "unicast",
    "created_at": "2026-05-05T05:42:11.123456+00:00",
    "status_state": "input_required",
    "status_timestamp": "2026-05-05T05:42:11.123456+00:00",
    "origin_message_id": null,
    "text": "build OK"
  }
]

Indented here for readability; the actual --json output is a single compact line with no whitespace. --full only changes which fields are emitted, never the encoding.

A broadcast summary row carries kind: "broadcast_summary" (or type in --full) and origin: <id> (self-referencing); the text body is the broker-computed summary string "Broadcast sent to N recipients". The message broadcast response always contains exactly this single summary message plus the wrapper-level recipients (the real recipient count N) and delivered (the count of best-effort inline previews that landed) fields — there is no per-recipient envelope list. --full renders that single summary message in full (verbose envelope / typed-column dict) instead of the one-line summary, but never adds per-recipient envelopes (see Output shapes for the cross-subcommand summary).

Text mode

Text mode renders each message as two lines (line 1 is the bracketed envelope, line 2 is the body):

[42 | from:7 | 2026-05-05T05:42:11.123456+00:00]
build OK

--full switches to a variable-length labeled block — one field per line, per the table above. So a fresh unicast delivery prints six lines, while a broadcast-summary row with no recipient prints fewer. Broadcast summary rows are never empty — the broker writes the human-readable summary "Broadcast sent to N recipients" at insert time, so summary rows always render their text: line. Body truncation (the suffix at CAFLEET_MAX_TEXT_LEN codepoints) is documented in cli-options.md.

Flag cross-reference

The flags that govern envelope rendering are documented in cli-options.md:

ControlDefaultEffect on the envelope
--jsonoff — text modeEmits compact single-line JSON
--fulloff — the compact envelopeReturns the full typed-column envelope and an untruncated body
CAFLEET_MAX_TEXT_LEN200Truncates the body at that many codepoints, appending