Initial Commit

This commit is contained in:
2026-05-27 23:29:53 +01:00
commit fbc70f96e6
10000 changed files with 1102152 additions and 0 deletions

View File

@@ -0,0 +1,77 @@
# drive-transport-https spec — v1
## ADDED Requirements
### Requirement: Implements TransportLike<MessageEnvelope>
`HttpsTransport` SHALL implement the structural
`TransportLike<MessageEnvelope>` contract from
`@suaveplan/types/transport`: `connect(peerId, address)`,
`disconnect(peerId)`, `send(peerId, envelope)`,
`onMessage(handler) → Unsubscribe`, `getConnectedPeers()`. It SHALL
add lifecycle methods `start()` / `stop()` so the long-poll loop
does not begin until the consumer is ready and so the loop can be
cleanly torn down on shutdown.
**Verified by:** `tests/lifecycle.test.ts` (eleven scenarios).
### Requirement: Long-poll receive with cursor
The transport SHALL maintain a string `cursor` initialised to `""`.
Every long-poll request SHALL include the cursor as the `since`
query parameter when non-empty; on response, the cursor SHALL be
replaced with the `nextCursor` field from the parsed
`RecvResponse`.
**Verified by:** `tests/recv.test.ts`::"includes since=cursor on
subsequent /recv calls" AND "cursor starts empty and updates after
a successful /recv" (`tests/lifecycle.test.ts`).
### Requirement: Auth-failure short-circuit
A `401` or `403` response from `/recv` SHALL terminate the receive
loop. The transport's `state` SHALL transition to `"stopped"` and
the `lastAuthError` getter SHALL expose the typed
`HttpsTransportError(HTTPS_TRANSPORT.AUTH_FAILED, ...)`. The
transport SHALL NOT auto-retry on auth failure — credential refresh
belongs to the consumer.
**Verified by:** `tests/recv.test.ts`::"AUTH_FAILED on /recv stops
the loop" AND "AUTH_FAILED on /recv propagates via lastAuthError".
### Requirement: Exponential backoff with equal jitter
On a transient receive failure (`5xx` /
`HTTPS_TRANSPORT.RECV_FAILED` /
`HTTPS_TRANSPORT.MALFORMED_RESPONSE`), the loop SHALL back off and
retry. Wait times SHALL follow an equal-jitter formula
`exp / 2 + rand(0, exp/2)` clamped to `[backoffBaseMs,
backoffMaxMs]` with `exp = backoffBaseMs * 2^(failures-1)`.
**Verified by:** `tests/recv.test.ts`::"backs off on 503 and
retries", "backs off on 4xx other than auth (RECV_FAILED) and
retries", "backs off on malformed JSON body (MALFORMED_RESPONSE)
and retries".
### Requirement: Send wire contract
`send(peerId, envelope)` SHALL `POST` to `${relayUrl}/send` with
`{ to, envelope }` as JSON. The peer SHALL be in the `connected`
set or `HTTPS_TRANSPORT.PEER_UNKNOWN` is thrown. `401`/`403`
responses SHALL throw `AUTH_FAILED`; `5xx` responses SHALL throw
`RELAY_UNAVAILABLE`; other non-2xx responses SHALL throw
`SEND_FAILED`. `200` responses SHALL be Zod-validated against
`SendResponseSchema`; `ok: false` SHALL throw `SEND_FAILED` with
the relay's `code` (or `"unknown"`) in the message.
**Verified by:** `tests/send.test.ts` (fifteen scenarios).
### Requirement: Lifecycle invariants
`start()` SHALL throw `HTTPS_TRANSPORT.CLOSED` if called after
`stop()`. `start()` SHALL be idempotent while `state === "running"`.
`stop()` SHALL be idempotent. `connect()` and `send()` SHALL throw
`HTTPS_TRANSPORT.NOT_CONNECTED` if the transport has not been
started, and `HTTPS_TRANSPORT.CLOSED` if it has been stopped.
**Verified by:** `tests/lifecycle.test.ts` and `tests/send.test.ts`.