This recipe exposes owned operations through HTTP and a resumable stream without turning routes, status codes, or frames into domain meaning.
The .one syntax below is illustrative end-product syntax.
1. Start with operations
semantic parcelhub.tracking
domain one.contracts@1
operation GetShipment@1
input GetShipmentRequest
output Shipment
faults [ShipmentNotFound]
effect read(shipment)
operation WatchShipment@1
input WatchShipmentRequest
output stream<ShipmentEvent>
delivery resumable(cursor: ShipmentCursor)
ordering per_shipment
backpressure bounded(256)
Neither operation implies a network boundary.
2. Add an HTTP projection
semantic parcelhub.tracking_http
domain one.communication.http@1
interface TrackingHttp@1
operation parcelhub.tracking#GetShipment@1
request GET "/shipments/{shipment_id}"
parameter shipment_id from input.shipment_id
result 200 json(output)
fault ShipmentNotFound -> 404 json(fault)
operation parcelhub.tracking#WatchShipment@1
request GET "/shipments/{shipment_id}/events"
result server_sent_events(output)
resume header("Last-Event-ID") from input.cursor
The profile validates path collisions, encoding, headers, status mappings, identity, deadlines, cancellation, disclosure, and semantic loss.
3. Consume the stream with explicit flow control
let mut events = client
.watch_shipment(WatchShipmentRequest { shipment_id, cursor })
.await?;
while let Some(event) = events.next().await? {
apply(event.value)?;
events.ack(event.cursor).await?;
}
A gap, expired cursor, slow reader, revocation, transport loss, and domain end remain different dispositions. Reconnect resumes from an accepted cursor; it does not replay a mutation.
4. Test the claimed boundary
one test --root TrackingHttp --scenario canonical-paths
one test --root TrackingHttp --scenario stream-gap-and-resnapshot
one test --root TrackingHttp --scenario slow-reader-backpressureSee communication.