HPPR Replication
© R.A.Sol
Repository replication uses command 🖧EXCHANGE. It
synchronizes packets while preserving ACL decisions.
🖧EXCHANGE
🖧EXCHANGE has three phases:
- announce
- transfer
- finalize
Phase 1: Announce
Requester sends up to 1024 LF-separated lines:
NEED <versioned-coord>
HAVE <versioned-coord>
Responder returns FIN or PENDING
followed by status lines:
SEND <coord>
DENY <coord>
RECV <coord>
HAVE <coord>
Status meanings:
SEND: responder will send this packetDENY: denied by ACL or policyRECV: responder wants this packet from requesterHAVE: responder already has this packet
Phase 2: Transfer
Both peers stream raw packets concurrently in both directions.
Implementations MUST perform bidirectional I/O concurrently. Unidirectional blocking can deadlock the exchange.
Packet boundaries are parsed using Data-Length.
Phase 3: Finalize
Responder reports final per-coordinate results:
FIN
OK <coord>
FAIL <coord> <type> <msg>
ACL Rules in Phase 1
For NEED <coord>:
- check
read - if readable and exists:
SEND - else:
DENY
For HAVE <coord>:
- check
read - if denied:
DENY - if allowed and exists:
HAVE - if missing, check
write - if writable:
RECV - else:
DENY
Blob-Addressed 🖧EXCHANGE
🖧EXCHANGE also accepts blob hash addressing:
NEED ////B.<hash>.H3
HAVE ////B.<hash>.H3
Rules:
- only
B.hashes are valid P.andS.in blob-addressed mode are FATAL invalid requests- no ACL checks in this mode
- any authenticated session may request blob hash sync
Decision rules:
NEED: blob exists =>SEND, elseDENYHAVE: blob exists =>HAVE, elseRECV
Transfer still uses full raw blob packets.
🖧STREAM_IN
🖧STREAM_IN ingests live trailer-format Seal
segments.
Request:
App: 🖧STREAM_IN- data:
<coordinate-prefix>
Response:
- sealed
OK
After OK, connection enters relay mode and accepts
trailer segments.
Per segment:
- relay bytes to matching
🖧STREAM_OUTsubscribers - detect segment close marker
- verify hash and signature
- store packet
- emit
🖧WATCHevent
ACL: write checked per segment at store time.
Disconnect behavior:
- publisher disconnect ends stream
- no explicit end marker required
- partial in-flight segment is discarded
- subscriber sockets are closed
No FATAL is injected into relay stream. Subscribers detect truncation via trailer parsing.
Size rule:
- each segment must respect 32 MiB blob limit
Continuity recommendation:
- include
Previous-Segment: <hash>after first segment
🖧STREAM_OUT
🖧STREAM_OUT subscribes to live trailer bytes by
prefix.
Request:
App: 🖧STREAM_OUT- data:
<coordinate-prefix>
Behavior:
- enters dedicated relay mode immediately
- no
OKresponse packet - when no active publisher exists for the prefix, subscriber waits for one
- wait uses a fixed server timeout
- on wait timeout, repo writes
FATAL NOT_FOUND wait timeoutand closes - forwards bytes from matching active publishers
Late joiners receive bytes buffered from current in-flight segment and then continue live.
ACL: read checked at subscription time.
On publisher disconnect, repo closes subscriber sockets. Mid-segment disconnect yields partial trailer data followed by EOF.
Completed segments remain available via 🖧GET and
🖧EXCHANGE.
Relay Chaining
A downstream repo can relay a live stream by:
- subscribing upstream with
🖧STREAM_OUT - publishing downstream with
🖧STREAM_IN