feat(#85): implement CONNECT/DISCONNECT protocol

Implemented connection handshake protocol for federation building on
the Instance Identity Model from issue #84.

**Services:**
- SignatureService: Message signing/verification with RSA-SHA256
- ConnectionService: Federation connection management

**API Endpoints:**
- POST /api/v1/federation/connections/initiate
- POST /api/v1/federation/connections/:id/accept
- POST /api/v1/federation/connections/:id/reject
- POST /api/v1/federation/connections/:id/disconnect
- GET /api/v1/federation/connections
- GET /api/v1/federation/connections/:id
- POST /api/v1/federation/incoming/connect

**Tests:** 70 tests pass (18 Signature + 20 Connection + 13 Controller + 19 existing)
**Coverage:** 100% on new code
**TDD Approach:** Tests written before implementation

Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
This commit is contained in:
Jason Woltje
2026-02-03 11:41:07 -06:00
co-authored by Claude Sonnet 4.5
parent b336d9c1f7
commit fc3919012f
13 changed files with 2063 additions and 19 deletions
+49 -14
View File
@@ -60,6 +60,9 @@ importers:
'@mosaic/shared':
specifier: workspace:*
version: link:../../packages/shared
'@nestjs/axios':
specifier: ^4.0.1
version: 4.0.1(@nestjs/[email protected]([email protected])([email protected])([email protected])([email protected]))([email protected])([email protected])
'@nestjs/bullmq':
specifier: ^11.0.4
version: 11.0.4(@nestjs/[email protected]([email protected])([email protected])([email protected])([email protected]))(@nestjs/[email protected])([email protected])
@@ -123,6 +126,9 @@ importers:
archiver:
specifier: ^7.0.1
version: 7.0.1
axios:
specifier: ^1.13.4
version: 1.13.4
better-auth:
specifier: ^1.4.17
version: 1.4.17(@prisma/[email protected]([email protected]([email protected])([email protected]))([email protected]))([email protected])([email protected](@opentelemetry/[email protected])(@prisma/[email protected]([email protected]([email protected])([email protected])))(@types/[email protected])([email protected])([email protected])([email protected])([email protected]([email protected])([email protected])))([email protected](@babel/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected]))([email protected])([email protected]([email protected])([email protected]))([email protected]([email protected]))([email protected])([email protected](@opentelemetry/[email protected])(@types/[email protected])([email protected])([email protected])([email protected])([email protected])([email protected]))
@@ -1499,6 +1505,13 @@ packages:
cpu: [x64]
os: [win32]
'@nestjs/[email protected]':
resolution: {integrity: sha512-68pFJgu+/AZbWkGu65Z3r55bTsCPlgyKaV4BSG8yUAD72q1PPuyVRgUwFv6BxdnibTUHlyxm06FmYWNC+bjN7A==}
peerDependencies:
'@nestjs/common': ^10.0.0 || ^11.0.0
axios: ^1.3.1
rxjs: ^7.0.0
'@nestjs/[email protected]':
resolution: {integrity: sha512-VBJcDHSAzxQnpcDfA0kt9MTGUD1XZzfByV70su0W0eDCQ9aqIEBlzWRW21tv9FG9dIut22ysgDidshdjlnczLw==}
peerDependencies:
@@ -3272,6 +3285,9 @@ packages:
[email protected]:
resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
[email protected]:
resolution: {integrity: sha512-1wVkUaAO6WyaYtCkcYCOx12ZgpGf9Zif+qXa4n+oYzK558YryKqiL6UWwd5DqiH3VRW0GYhTZQ/vlgJrCoNQlg==}
[email protected]:
resolution: {integrity: sha512-5Q2mfq2WfGuFp3uS//0s6baOJLMoVduPYVeNmDYxu5OUA1/cBfvr2RIS7vi62LdNj/urk1hfmj867I3qt6uZ7Q==}
peerDependencies:
@@ -4420,6 +4436,15 @@ packages:
[email protected]:
resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==}
[email protected]:
resolution: {integrity: sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==}
engines: {node: '>=4.0'}
peerDependencies:
debug: '*'
peerDependenciesMeta:
debug:
optional: true
[email protected]:
resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==}
engines: {node: '>=14'}
@@ -5502,6 +5527,9 @@ packages:
resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==}
engines: {node: '>= 0.10'}
[email protected]:
resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
[email protected]:
resolution: {integrity: sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==}
@@ -6954,7 +6982,7 @@ snapshots:
chalk: 5.6.2
commander: 12.1.0
dotenv: 17.2.3
drizzle-orm: 0.41.0(@opentelemetry/[email protected])(@prisma/client@5.22.0([email protected]([email protected])([email protected])))(@types/[email protected])([email protected])([email protected])([email protected])([email protected]([email protected])([email protected]))
drizzle-orm: 0.41.0(@opentelemetry/[email protected])(@prisma/client@6.19.2([email protected]([email protected])([email protected]))([email protected]))(@types/[email protected])([email protected])([email protected])([email protected])([email protected]([email protected])([email protected]))
open: 10.2.0
pg: 8.17.2
prettier: 3.8.1
@@ -7668,6 +7696,12 @@ snapshots:
'@msgpackr-extract/[email protected]':
optional: true
'@nestjs/[email protected](@nestjs/[email protected]([email protected])([email protected])([email protected])([email protected]))([email protected])([email protected])':
dependencies:
'@nestjs/common': 11.1.12([email protected])([email protected])([email protected])([email protected])
axios: 1.13.4
rxjs: 7.8.2
'@nestjs/[email protected](@nestjs/[email protected]([email protected])([email protected])([email protected])([email protected]))(@nestjs/[email protected])':
dependencies:
'@nestjs/common': 11.1.12([email protected])([email protected])([email protected])([email protected])
@@ -9810,6 +9844,14 @@ snapshots:
[email protected]: {}
[email protected]:
dependencies:
follow-redirects: 1.15.11
form-data: 4.0.5
proxy-from-env: 1.1.0
transitivePeerDependencies:
- debug
[email protected]: {}
[email protected]: {}
@@ -9843,7 +9885,7 @@ snapshots:
optionalDependencies:
'@prisma/client': 5.22.0([email protected]([email protected])([email protected]))
better-sqlite3: 12.6.2
drizzle-orm: 0.41.0(@opentelemetry/[email protected])(@prisma/client@5.22.0([email protected]([email protected])([email protected])))(@types/[email protected])([email protected])([email protected])([email protected])([email protected]([email protected])([email protected]))
drizzle-orm: 0.41.0(@opentelemetry/[email protected])(@prisma/client@6.19.2([email protected]([email protected])([email protected]))([email protected]))(@types/[email protected])([email protected])([email protected])([email protected])([email protected]([email protected])([email protected]))
next: 16.1.6(@babel/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected])
pg: 8.17.2
prisma: 6.19.2([email protected])([email protected])
@@ -9868,7 +9910,7 @@ snapshots:
optionalDependencies:
'@prisma/client': 6.19.2([email protected]([email protected])([email protected]))([email protected])
better-sqlite3: 12.6.2
drizzle-orm: 0.41.0(@opentelemetry/[email protected])(@prisma/client@5.22.0([email protected]([email protected])([email protected])))(@types/[email protected])([email protected])([email protected])([email protected])([email protected]([email protected])([email protected]))
drizzle-orm: 0.41.0(@opentelemetry/[email protected])(@prisma/client@6.19.2([email protected]([email protected])([email protected]))([email protected]))(@types/[email protected])([email protected])([email protected])([email protected])([email protected]([email protected])([email protected]))
next: 16.1.6(@babel/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected])
pg: 8.17.2
prisma: 6.19.2([email protected])([email protected])
@@ -10616,16 +10658,6 @@ snapshots:
[email protected]: {}
[email protected](@opentelemetry/[email protected])(@prisma/[email protected]([email protected]([email protected])([email protected])))(@types/[email protected])([email protected])([email protected])([email protected])([email protected]([email protected])([email protected])):
optionalDependencies:
'@opentelemetry/api': 1.9.0
'@prisma/client': 5.22.0([email protected]([email protected])([email protected]))
'@types/pg': 8.16.0
better-sqlite3: 12.6.2
kysely: 0.28.10
pg: 8.17.2
prisma: 6.19.2([email protected])([email protected])
[email protected](@opentelemetry/[email protected])(@prisma/[email protected]([email protected]([email protected])([email protected]))([email protected]))(@types/[email protected])([email protected])([email protected])([email protected])([email protected]([email protected])([email protected])):
optionalDependencies:
'@opentelemetry/api': 1.9.0
@@ -10635,7 +10667,6 @@ snapshots:
kysely: 0.28.10
pg: 8.17.2
prisma: 6.19.2([email protected])([email protected])
optional: true
[email protected]:
dependencies:
@@ -10995,6 +11026,8 @@ snapshots:
[email protected]: {}
[email protected]: {}
[email protected]:
dependencies:
cross-spawn: 7.0.6
@@ -12075,6 +12108,8 @@ snapshots:
forwarded: 0.2.0
ipaddr.js: 1.9.1
[email protected]: {}
[email protected]:
dependencies:
end-of-stream: 1.4.5