feat(federation): admin controller + CLI federation commands (FED-M2-08) #498
Reference in New Issue
Block a user
Delete Branch "feat/federation-m2-cli"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Implements FED-M2-08: two-part delivery of the federation admin surface.
Gateway — FederationController
apps/gateway/src/federation/federation-admin.dto.ts:CreatePeerKeypairDto,StorePeerCertDto,GenerateEnrollmentTokenDto,RevokeGrantBodyDtoapps/gateway/src/federation/federation.controller.ts:FederationControllerunder/api/admin/federationwithAdminGuardon all routesPOST /grants,GET /grants,GET /grants/:id,PATCH /grants/:id/revoke— delegate toGrantsServicePOST /grants/:id/tokens— delegates toEnrollmentService, returns{ token, expiresAt, enrollmentUrl }GET /peers— direct DB queryPOST /peers/keypair— webcrypto EC P-256 key gen +@peculiar/x509CSR +sealClientKey+ insert pending peer rowPATCH /peers/:id/cert— parses cert withX509Certificate, extracts serial/notAfter, sets state=activeapps/gateway/src/federation/federation.module.ts: registersFederationControllerCLI —
mosaic federationpackages/mosaic/src/commands/federation.ts:registerFederationCommandwith fullgrantandpeersubcommand treesgrant create/list/show/revoke/tokenpeer list/add(add runs full enrollment flow: generate keypair → submit CSR to remote → store cert)-tflag ormeta.json.adminToken--jsonflag for machine-readable outputpackages/mosaic/src/cli.ts: registers the new commandTests
apps/gateway/src/federation/__tests__/federation.controller.spec.ts: unit tests covering listGrants, createGrant, generateToken (enrollmentUrl shape), listPeersCloses #461
Test plan
pnpm typecheck— passes (38/38)pnpm lint— passes (21/21)pnpm format:check— passes (all files)pnpm test— passes (439 tests, 4 skipped integration)🤖 Generated with Claude Code
Independent Code Review — REQUEST_CHANGES
Reviewed by Opus 4.7 (independent agent, no shared context with author).
HIGH (must fix before merge)
H1 —
import typeon DTO classes breaks ValidationPipe (federation.controller.ts:45-51)All six Body/Query DTO imports use
import type, which TypeScript erases at compile time. NestJS's globalValidationPipe({ whitelist:true, forbidNonWhitelisted:true })relies on reflect-metadata to inspect the class constructor's parameter types. Withimport type, the metatype resolves toObject, and ValidationPipe rejects every property as non-whitelisted (HTTP 400 at runtime). Unit tests miss this because they bypass Nest's DI/metatype lookup. This is the exact pattern that caused bug #436.Fix: Change
import type { CreateGrantDto, ListGrantsDto }andimport type { CreatePeerKeypairDto, ... }to value imports.MEDIUM (defer ok)
peer addposts{ csrPem }— field name matchesRedeemEnrollmentTokenDto.csrPemexactly ✓Confirmed OK
POST /api/federation/enrollment/:tokennot duplicated ✓enrollmentUrlreadsBETTER_AUTH_URLfrom env ✓sealClientKey(privatePem)single-arg matches util ✓any, no hardcoded secrets, ESM.jsimports, stack file untouched ✓Verdict: REQUEST_CHANGES — fix import type → value imports on DTO lines, then APPROVE.
Re-Review — APPROVE
H1 (import type → value imports): RESOLVED
All six DTO class imports now use plain value imports (no
typekeyword). ValidationPipe metatype lookup will work correctly at runtime.Gates: typecheck 38/38, test 439/439 passed.
APPROVE — ready to merge.