On-Disk Contract Spec (v1)
This specification defines the versioned on-disk data format and directory layout for Pibmo Relay stores. Any implementation agreeing with this contract can safely interoperate on a shared git transport store.
1. Directory Layout
A Relay store repository root contains two primary directory trees:
<store_root>/├── mail/│ └── <uuid>.md # Canonical Message files└── roles/ └── <role>/ # Directory per team member seat ├── inbox/ │ └── <uuid>.ref # Pointer Ref files (unread/read) ├── sent/ │ └── <uuid>.ref # Sender's copy pointer Ref files └── archive/ └── <uuid>.ref # Archived pointer Ref files<uuid>: A non-empty, valid UUID string (36 characters, e.g.0010e837-43d5-4f40-8b1e-976404987a1e).<role>: A validated team member role identifier (matching^[A-Za-z0-9_-]+$).
2. UUID Validation & Identity
- Format: Every UUID must be a valid RFC 4122 string matching:
^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$ - Non-empty requirement: Empty strings, missing UUIDs, or filenames resulting in
mail/.mdorroles/<role>/*/.refare strictly invalid. - Case Sensitivity: Implementations must handle case hex characters gracefully; standard UUID generation uses lowercase hexadecimal characters.
3. Timestamp Format
All timestamps MUST use ISO 8601 UTC format with second-resolution and a terminal Z suffix:
YYYY-MM-DDTHH:MM:SSZ (e.g., 2026-07-21T13:14:00Z). Fractional seconds and timezone offsets other than Z are not permitted.
4. Canonical Message Format
Location: mail/<uuid>.md
4.1 Structure
A canonical message consists of line-prefix key-value metadata (“frontmatter”) bounded by --- delimiters, followed by a blank line and the message body:
---id: <uuid>thread: <uuid>in_reply_to: null|<uuid>from: <role>to: [<role_list>]cc: [<role_list>]type: <enum>subject: <string>created: <ISO8601Z>---
<body>4.2 Field Specifications & Order
Keys in the frontmatter must appear in fixed order:
id: The UUID of this message.thread: The UUID of the conversation thread root. For a new top-level thread,threadequalsid.in_reply_to: The UUID of the immediate parent message, or literal stringnullif top-level.from: Sender’s valid role identifier.to: Bracketed CSV list of recipient roles, e.g.[role1, role2].cc(Optional): Present if and only if at least one CC recipient is declared, e.g.[role3]. Placed directly afterto.type: Enumerable string. Must be one of:info,request,report,ack,ping.subject: Single-line subject string.created: Timestamp string in ISO 8601 UTC format.
4.3 Immutability
Canonical message files are write-once. Once created under mail/<uuid>.md, their content is never modified or moved.
5. Pointer Ref Format
Location: roles/<role>/{inbox,sent,archive}/<uuid>.ref
5.1 Structure
A Ref file is a pointer carrying per-member state for a given message. It consists of exactly 4 lines in fixed key order:
id: <uuid>read_at: null|<ISO8601Z>status: unread|read|archivedclaimed_by: null5.2 Field Rules
id: Matching the message UUID.read_at: Literal stringnullwhen unread, or ISO 8601 UTC timestamp when read. Write-once once set.status: Folder-consistent state:- In
inbox/: status isunreadorread. - In
sent/: status isread. - In
archive/: status isarchived.
- In
claimed_by: Literal stringnull(reserved for future lease mechanics).
6. Directory vs. Status Consistency Invariants
- Folder Authority: Physical location (
inbox/vsarchive/) determines whether a message is archived. - Per-Member Scope: All mutation operations for a member occur exclusively under
roles/<role>/. - Read State: Status transition is strictly idempotent (
unread->read). Re-reading preserves originalread_at.