Skip to content

Tags: Olib-AI/ConnectionPool

Tags

v1.6.0

Toggle v1.6.0's commit message

Unverified

The email in this signature doesn’t match the committer email.
Add cross-platform transport module for Android interop

Bonjour/mDNS + TCP transport with a platform-neutral wire protocol
(canonical JSON, HKDF-SHA256 key derivation, ChaCha20-Poly1305 AEAD
frames) interoperable with the Kotlin implementation. Includes session
resume, host-side rate limiting, and frozen cross-platform reference
vectors asserted byte-equal in tests. Legacy MultipeerConnectivity and
relay wire formats are unchanged.

v1.5.1

Toggle v1.5.1's commit message

Unverified

The email in this signature doesn’t match the committer email.
Persistent member identity + auto-rejoin without host

Members can now reconnect to a pool indefinitely without the host being
online. The load-bearing change is in WebSocketTransport: the
client_public_key in JoinRequest now comes from a Keychain-persistent
RemoteMemberIdentity (scoped per serverURL+poolID) instead of a fresh
Curve25519.Signing.PrivateKey() per session. That makes the relay's
new approved_peers set actually deliver value.

New types:
- RemoteMemberIdentity — Ed25519 keypair, Keychain-stored, per-pool
  scoped via sha256(serverURL + ":" + poolID), accessibility =
  WhenUnlockedThisDeviceOnly. Mirrors RemoteHostIdentity's raw-Security
  approach (no new dependencies).
- RemoteMemberRecord + RemoteMemberRecordStore — ledger of pools the
  user has joined. Persisted via the existing pluggable
  remotePoolStateStorageProvider.
- ServerFrame.memberRejoin — new client→server frame mirrored from
  StealthRelay v0.5.1. Domain-separated transcript prevents
  cross-replay against host_auth signatures.
- TransportError.notApproved / .poolNotFound — terminal states that
  trigger purgeMemberStateForCurrentPool().

New flow on every remote-pool reconnect:
1. If RemoteMemberIdentity exists for (server, pool), send
   member_rejoin (signed with the persistent key) and skip JoinRequest
   entirely. Works whether host online or offline.
2. Otherwise, if an invitation is present, fall through to the existing
   JoinRequest/PoW path and persist the identity + record on
   JoinAccepted.
3. 403 not_approved → drop identity + record, surface "membership
   revoked". 404 pool_not_found → drop both, surface "pool no longer
   exists". Other errors don't touch saved state.

UI:
- Home view gains a "Saved Pools" section showing past memberships;
  tap to rejoin, swipe/trash to forget.
- Lobby Disconnect for remote members now intercepts with a
  confirmation alert and routes to leaveRemoteMemberPool() (purges
  identity + record). Plain transient drops use the unchanged
  disconnect() path so blip-reconnects don't lose state.

183 ConnectionPool tests, 0 failures (160 baseline + 23 new). README
updated with rejoin protocol description, Quick Start example, and
new API entries. Bumped SPM version to 1.5.1.

v1.5.0

Toggle v1.5.0's commit message

Unverified

The email in this signature doesn’t match the committer email.
Tunnel-exit client + pool persistence past host disconnect

Two related additions targeting StealthRelay v0.5.0+:

1. Tunnel-exit client (RelayTunnelClient + TunnelStream + binary frame
   codec). Opens TCP/UDP streams through the relay so the relay's IP
   becomes the visible exit address. Per-stream credit-based flow
   control, monotonic stream IDs, async-stream-based receive, DNS query
   continuations. Hot-path bytes ride binary WebSocket frames
   (TUNNEL_DATA = 0x01, TUNNEL_UDP = 0x02, big-endian header) so the
   data path bypasses base64 + JSON. Control plane stays JSON for
   debuggability. The host bypasses their own per-pool tunnel-exit
   approval flag — it gates members.

2. Pool persistence past host disconnect. ConnectionPoolManager now
   publishes hostOnline / hostOfflineSince, mirrored on the view model.
   New ServerFrame.poolHostStatus broadcast with online + offline_since
   keeps the UI in sync. ServerPoolInfo.hostOnline added; legacy
   relays missing the field default to true. JoinRejected with reason
   "host_offline_unavailable" maps to TransportError.hostOffline and
   suppresses auto-reconnect on that path. The host re-authenticating
   with the same Ed25519 key + pool_id rebinds in place — no new
   pool_id is issued, members reconnect transparently.

154 ConnectionPool tests, 0 failures. README updated with feature
bullets, security subsections, and Quick Start examples for both
features. Bumped Swift Package version to 1.5.0.

v1.4.0

Toggle v1.4.0's commit message
Update README version to 0.1.0

v1.3.0

Toggle v1.3.0's commit message

Verified

This commit was signed with the committer’s verified signature.
ibnbd Akram H. Sharkar
Remote relay transport, security hardening, and 68 unit tests

Remote Relay Transport:
- WebSocketTransport for connecting to StealthRelay servers
- Ed25519 host authentication with Keychain-stored identity
- Invitation-based joining with stealth://invite/ URLs
- SHA-256 proof-of-work solver for anti-DoS challenges
- Session token injection for all privileged host operations
- TLS certificate pinning via SPKI SHA-256 hash
- Server claiming flow with QR code scanning
- Automatic reconnection with invitation expiry checks
- Auto-accept previously approved peers on reconnect

Security Hardening (5 audit laps):
- HMAC key derived from shared secret, not pool UUID
- Constant-time HMAC verification via CryptoKit
- Length-prefixed HMAC inputs prevent concatenation forgery
- Envelopes without HMAC rejected (no backwards compat)
- Hop path capped at maxTTL+1
- URLSession .ephemeral for WebSocket connections
- Global brute-force rate limiting (not bypassable by rotating names)
- Peer IDs use stable UUIDs, not attacker-controlled display names
- Topology broadcast spoofing detection
- Transport-authenticated player identity in multiplayer games
- Poll vote and reaction spoofing fixed (use sender ID from transport)
- Notification privacy (no message content in OS notifications)
- Voice note file protection with NSFileProtectionComplete
- Display name length capped at 128 characters
- Failed attempt counts stored in protected Application Support

UI Improvements:
- ScrollView layout prevents content clipping
- Delete button for saved relay servers
- Full-width remote pool buttons (no truncation)
- Share sheet auto-dismisses for join approval prompt
- Max members picker in Remote Host sheet (default 8)
- Single-use invitations removed after peer joins
- Only host can create new invitations
- Proper disconnect state cleanup with deferred reset

Tests:
- 68 unit tests across 6 test files
- RelayEnvelope, MeshTopology, PoolMessage, dedup cache, RemotePoolState

GitHub Actions:
- Fixed update-readme-version workflow (checkout main, push origin main)

v1.2.0

Toggle v1.2.0's commit message

Verified

This commit was signed with the committer’s verified signature.
ibnbd Akram H. Sharkar
Add Chess multiplayer game type support

v1.1.0

Toggle v1.1.0's commit message

Verified

This commit was signed with the committer’s verified signature.
ibnbd Akram H. Sharkar
Fix concurrency issues across the package

- ConnectionPoolConfiguration: protect logger with NSLock (was bare
  nonisolated(unsafe) mutable global)
- MeshTopology: remove TOCTOU-prone computed property wrappers; all
  callers already access backing storage directly under lock
- Peer: replace static var cache with static let closure for
  thread-safe one-time initialization
- ConnectionPoolManager: store delayed Tasks in array, cancel on
  disconnect to prevent stale ops on reconnect
- UncheckedSendableBox: add safety documentation

v1.0.0

Toggle v1.0.0's commit message

Verified

This commit was signed with the committer’s verified signature.
ibnbd Akram H. Sharkar
Initial release — secure local P2P mesh networking for iOS/macOS

Zero-dependency MultipeerConnectivity library with DTLS encryption,
HMAC-SHA256 envelope integrity, multi-hop relay routing, brute-force
protection, and host-side pool code authentication.