inbound-library/docs/data-contracts.md
tegwick 65887ef637 Route forwarded mail by its original sender; register Grok briefs via founder.
Adds forwarded_from (original sender from the forwarded header block,
English/German) to delivery provenance and source match rules, so only
founder forwards of noreply@x.ai mail route as Grok briefs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 1170398@bnt-lap001
Assistant-Session: 622cd705-cb31-4322-ba08-dd42e44fa583
2026-10-05 16:24:33 +02:00

3.7 KiB

Data contracts — schema inbound-library/v1

Consumers may rely on every field listed here. Any change that breaks one of them bumps the schema version.

Layout

Path Mutability Versioned in git
registry/topics.json edited by commit yes
registry/sources/<id>.json edited by commit yes
registry/subscriptions/<repo>.json edited by commit yes
config/library.json edited by commit, no secrets yes
data/items/<sha256> immutable original bytes no
data/deliveries/<sha256>.json immutable no
data/notices/<sha256>.json immutable no
data/derived/<item>.json rebuildable, replaceable no
data/digests/<repo>/<cadence>/<period>.md rebuildable, replaceable no
data/state/*.json cursor and hub-sent state no

data/ is gitignored because mail can be private. A record's id is the SHA-256 of its canonical JSON (sorted keys, no whitespace). An item's id is the SHA-256 of its bytes. check rehashes both.

Item

The original bytes, exactly as delivered. For mail, the item is the full RFC 822 message. Each attachment is also an item of its own.

Delivery (provenance)

One record per delivery of an item.

Field Meaning
schema inbound-library/v1
item item id
channel imap or attachment
status routed (a source matched) or quarantined (no source)
source source id, or null
received_at IMAP INTERNALDATE (UTC ISO 8601)
mailbox <user>/<folder>; for imap only
message_id, sender, subject, list_id for imap only; sender is lowercased
forwarded_from for imap: the original sender from the first forwarded header block in the body (From:/Von: after a forward marker), or ''
authentication_results raw headers, recorded as provenance, not as trust
parent_item, filename, content_type for attachment only

IMAP UIDs are kept out of the delivery record on purpose. After a UIDVALIDITY change, the rescan reproduces identical records. When a source is registered later, a quarantined mail gets an additional routed delivery. The quarantined record stays as history.

Derived

subject, sender, date, text (text/plain, otherwise stripped HTML) and attachments (item, filename, content_type). It can be rebuilt from the item at any time.

Topic

In topics.json: {"version": n, "topics": {"<name>": "<description>"}}. Names use dots, from domain to specific, for example intelligence.daily-brief. Add new topics here first; sources and subscriptions may only use registered topics.

Source

Field Meaning
id the file name without .json
owner_repo the repository that registered it
channel email or url
match for email: from (required), subject (substring), list_id, forwarded_from (the original sender of a forwarded mail)
url for url
topics list of registered topics
cadence daily, weekly or irregular; daily and weekly email sources are watched for silence (36 h or 9 days)
visibility shared (any matching repo) or restricted (owner only)

Subscription

Field Meaning
repo the file name without .json
agent State Hub agent name that receives notices
topics, sources matched by either
channels a subset of hub, pull, digest
cadence daily or weekly; required for digest

Notice

{schema, repo, delivery, item, source, received_at}. It is deterministic, so each (repo, delivery) pair gets exactly one notice. Hub delivery sends one message per subscriber per run. A failed send stays pending and is retried on the next run.