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
153 lines
4.8 KiB
Markdown
153 lines
4.8 KiB
Markdown
---
|
|
id: ILIB-WP-0002
|
|
type: workplan
|
|
title: "Establish the inbound-library infrastructure"
|
|
domain: infotech
|
|
repo: inbound-library
|
|
status: active
|
|
flavor: implementation
|
|
owner: claude
|
|
topic_slug: custodian
|
|
created: "2026-10-05"
|
|
updated: "2026-10-05"
|
|
---
|
|
|
|
# Establish the inbound-library infrastructure
|
|
|
|
Build the first working library, following INTENT.md:
|
|
- read-only IMAP intake;
|
|
- an append-only item store;
|
|
- file-backed topics, sources and subscriptions;
|
|
- notices through State Hub messages, a pull CLI and digest files;
|
|
- a systemd user timer on the workstation.
|
|
|
|
Python 3.11+ standard library only. The first consumer is intelligence-radar
|
|
(IR-WP-0010).
|
|
|
|
## Repository baseline and data contracts
|
|
|
|
```task
|
|
id: ILIB-WP-0002-T01
|
|
status: todo
|
|
priority: high
|
|
```
|
|
|
|
Create the `inbound_library` package, `python3 -m inbound_library` with
|
|
`--help`, a Makefile (`check`, `test`, `demo`, `sync`) and `docs/data-contracts.md`.
|
|
The contracts define item, provenance, source, topic, subscription and notice,
|
|
with schema versions. Record the install, test and run commands in AGENTS.md
|
|
(taken over from ILIB-WP-0001-T02).
|
|
|
|
Acceptance: `make check` runs the unit tests on synthetic fixtures. The contracts
|
|
document every field that a consumer may rely on.
|
|
|
|
## Append-only item store
|
|
|
|
```task
|
|
id: ILIB-WP-0002-T02
|
|
status: todo
|
|
priority: high
|
|
```
|
|
|
|
Store original bytes under `data/items/<sha256>`, with a provenance record for
|
|
each delivery. Identical bytes delivered twice give one item with two
|
|
deliveries. Derive plain text and metadata into separate, rebuildable records.
|
|
Add an integrity check that rehashes every retained item. Never overwrite and
|
|
never delete. Items without provenance go to quarantine.
|
|
|
|
Acceptance: the tests prove there is no overwrite, that deduplication works,
|
|
that tampering is detected and that quarantine routing works.
|
|
|
|
## Read-only IMAP intake
|
|
|
|
```task
|
|
id: ILIB-WP-0002-T03
|
|
status: todo
|
|
priority: high
|
|
```
|
|
|
|
Poll one dedicated mailbox with `imaplib`, over TLS, using SELECT read-only and
|
|
BODY.PEEK[]. Credentials come only from environment variable names set in the
|
|
config. Keep a UIDVALIDITY/UID cursor in the library. Retain the full RFC 822
|
|
message as the item, and record each attachment as its own item linked to the
|
|
message. Map the sender (and optionally a List-Id or subject pattern) to a
|
|
registered source. Unknown senders are quarantined and not routed. Record
|
|
DKIM/SPF authentication results as provenance, not as trust. Reuse the
|
|
read-only IMAP approach of email-connect EMAIL-WP-0002 where that helps.
|
|
|
|
Acceptance: the tests run against a fixture mailbox. A live run is part of T07.
|
|
|
|
## File-backed registries
|
|
|
|
```task
|
|
id: ILIB-WP-0002-T04
|
|
status: todo
|
|
priority: high
|
|
```
|
|
|
|
Add `registry/topics.json` (a versioned vocabulary), `registry/sources/*.json`
|
|
(owner repo, channel, match rules, topics, expected cadence,
|
|
`visibility: shared|restricted`) and `registry/subscriptions/<repo>.json`
|
|
(topics, sources, channels, cadence, agent name, digest path). A consumer
|
|
registers a source from its own research with a commit. The commit is checked
|
|
for unknown topics, duplicate match rules and restricted sources that leak to
|
|
other repos.
|
|
|
|
Acceptance: `check` rejects invalid registries. A source registered by repo A
|
|
is matched for repo B through a shared topic.
|
|
|
|
## Matching and notification
|
|
|
|
```task
|
|
id: ILIB-WP-0002-T05
|
|
status: todo
|
|
priority: high
|
|
```
|
|
|
|
Match new items to subscriptions by source and topic. Then deliver:
|
|
- a State Hub agent message (`POST /messages/`) per subscriber and run, listing
|
|
the new item ids, sources and pull commands;
|
|
- a pull CLI: `new --repo … --topic … --since …`, `show <item>` and `get <item>`;
|
|
- a Markdown digest file per subscriber and cadence.
|
|
|
|
Record each notice in `data/notices/`, so a retry never notifies twice. If the
|
|
hub is unreachable, keep the notice pending and retry on the next run.
|
|
|
|
Acceptance: the tests prove idempotent delivery and recovery when the hub is
|
|
unreachable.
|
|
|
|
## Scheduling, health and source silence
|
|
|
|
```task
|
|
id: ILIB-WP-0002-T06
|
|
status: todo
|
|
priority: medium
|
|
```
|
|
|
|
Add a `run-due` that does the intake, then matching and delivery, under a lock.
|
|
Add a systemd user service and timer in `ops/systemd/`, and a `health` command.
|
|
Health reports:
|
|
- the last scan;
|
|
- items per source;
|
|
- sources that have stayed silent past their expected cadence;
|
|
- quarantine size;
|
|
- pending notices.
|
|
|
|
Acceptance: a silent source is reported, and repeated timer wakes are safe.
|
|
|
|
## Provision the dedicated mailbox
|
|
|
|
```task
|
|
id: ILIB-WP-0002-T07
|
|
status: todo
|
|
priority: high
|
|
```
|
|
|
|
Operator decisions:
|
|
- which mailbox (a new address, or a Gmail alias plus label or folder);
|
|
- how its IMAP credential is delivered (an app password through the
|
|
secrets-engine path, never committed).
|
|
|
|
Then do a live read-only scan.
|
|
|
|
Acceptance: one real mail retained with provenance. No mailbox state changed.
|