Standard: Networking Standards
Rules for the network/data layer. Enforced via checklists/api_review.md and the Networking Expert.
Client
- All requests go through an injectable
APIClientprotocol — never rawURLSessionin features. - One configured
JSONDecoder(key + date strategy) shared across the layer. - Explicit timeouts (request ≤ 30s default); honor
Taskcancellation.
Requests
- Endpoints are typed values (path, method, query, body, headers), not ad-hoc strings.
- Set
Content-Type/Acceptexplicitly; build query items viaURLComponents. - Idempotent requests (GET/PUT/DELETE) may retry with exponential backoff + jitter and a cap.
- Non-idempotent requests (POST) retry only with a server-supported idempotency key.
Responses & Errors
- Validate HTTP status before decoding; decode error bodies for non-2xx.
- Map transport/HTTP/decoding failures into a typed domain error; never surface raw
URLError/status codes to the UI. - GraphQL: treat a populated
errorsarray as a failure even on HTTP 200.
swift
guard (200..<300).contains(http.statusCode) else { throw NetworkError.http(http.statusCode) }
do { return try decoder.decode(R.self, from: data) } catch { throw NetworkError.decoding }Mapping
- DTOs mirror the wire format; map DTO→entity in a dedicated mapper.
- Unknown enum values decode to a safe
.unknowncase. - DTOs never leak past the Data layer.
Security
- Inject auth headers centrally; on 401, refresh once (single-flight) and retry.
- No tokens/PII in URLs, query strings, or logs. TLS enforced; pin sensitive hosts (see
security_standards.md).
Realtime
- WebSocket/SSE transports are actor-isolated state machines with heartbeat + backoff reconnection, exposed as
AsyncStream. Seechecklists/websocket_review.md.
Testing
- Client behavior tested via
URLProtocolstubbing or an injected fake client with JSON fixtures (success + error + empty). No live-server calls in tests.