Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a06ed7-828d-7ca0-a8d4-0c3e5a0c4102
3.9 KiB
State Hub inbox read pilot
GET /ports/projections/statehub-inbox is an opt-in, authenticated read-only
projection over the existing agent_messages model. It is distinct from
/ports/messaging/messages, which accepts new message envelopes and does not
implement State Hub's read/archive lifecycle.
Enable only after validating and importing a consistent source snapshot:
HUB_CORE_STATEHUB_INBOX_READS=1, HUB_CORE_STATEHUB_INBOX_AGENT=state-hub.
PostgreSQL and the configured operator bearer token are required. Disabled by
default. No POST/PATCH/DELETE exists on the pilot endpoint. Imported history
never emits messages or notifications.
The response is the State Hub MessageRead list shape. Parameters are
to_agent (must match the configured pilot agent), exact from_agent,
unread_only and limit (1–1000, default 50). Broadcast messages are included;
archived messages are excluded. Results order by created_at descending, then ID
for ties. Query transactions are read-only. Responses carry Cache-Control: no-store and X-Hub-Core-Read-Mode: snapshot-pilot.
This proves one literal agent inbox. It does not claim repository rename/alias resolution, unscoped fleet reads, thread lookup, continuous freshness, or writer cutover. The importer preserves thread roots so later history work need not reconstruct dangling identities.
Snapshot and import
Capture messages with one source PostgreSQL read-only, repeatable-read transaction. Preserve id, sender, recipient, subject, body, thread_id, read_at, archived_at and created_at, including archived/thread-root records. Keep the raw snapshot in private temporary storage; commit only hashes and counts.
The bundle has schema hub-core.statehub-inbox-snapshot.v1, source,
captured_at, messages, count, and content_hash. Use snapshot_hash from
hub_core.runtime.inbox_projection for canonical UTC/UUID normalization.
import_snapshot(session, bundle, expected_hash=..., apply=False) validates;
apply=True imports under a caller-owned transaction. The caller must commit
only on success and roll back any exception. PostgreSQL apply locks the target
message table before inspecting it. Different existing content refuses all
changes; exact repeats are no-ops. Thread roots insert before replies. Duplicate
IDs, malformed rows, hash/count mismatch, absent provenance, missing roots and
cycles are rejected.
Use the existing workload database credential delivery inside the receiving pod; never export database credentials into evidence. No schema migration or new secret is required. This is a one-time migration helper, not a message sending API or an automated synchronization loop.
Pilot sequence and rollback
- Keep State Hub as sole message writer; capture source revision, instance, repeatable-read snapshot, data hash and expected filtered inbox results.
- Import only into an empty receiver, verify all row hashes/counts and replay as a no-op. Deploy the disabled reader image, then enable the private pilot.
- Compare the same frozen source rows with authenticated receiver responses: all/unread/sender/limit cases, broadcast inclusion and archive exclusion. Check unauthenticated rejection and absence of writes. A later live State Hub read is a freshness observation, not the original snapshot oracle.
- Disable the reader flag and verify the endpoint returns 404; re-enable and recheck the same hash. Retain the imported rows for review; do not delete history as a rollback technique. Runtime rollback uses the previous image.
Transport from State Hub must be explicitly admitted by rapp-core-hub's NetworkPolicy. Scope any pilot exception to State Hub API pod labels and the candidate port. No public Ingress or production message-writer change is part of this pilot. The operator bearer stays in its existing credential lane; production caller credentials and ongoing freshness require their own cutover.