Federated Learning
The Federated Learning API lets multiple Adjudon organisations
collaborate on shared pattern detection (fraud signatures, AI
incident archetypes, content-moderation drift) without sharing
the underlying decision data. Each org's local trainer pushes a
differentially-private model update; the aggregation service
combines updates with calibrated noise; the resulting global model
is published back to participants. Tested against API version v1.
Mounted at /api/v1/federated. JWT auth; plan-gated by
federatedLearning — Custom plans only.
Federated Learning is on the published roadmap as Phase 3 (Q3-Q4 2027). The endpoints below are wired today on the Custom tier; the cross-org coordination, DP-noise calibration, and participant onboarding go through Adjudon Solutions Engineering as part of the Custom-plan negotiation. The schema ships AS BUILT; the production rollout drains in waves through participating consortia.
How it works
┌──────────────────────────────────────────────────────────┐
│ 1. Coordinator creates a PatternFamily (consortium) │
│ ──> sets domain ('financial-fraud', etc.) │
│ ──> sets DP defaults (epsilon, delta) │
├──────────────────────────────────────────────────────────┤
│ 2. Each member org POSTs /families/:id/join │
├──────────────────────────────────────────────────────────┤
│ 3. Coordinator POSTs /families/:id/rounds (kickoff) │
│ ──> Round status: pending → collecting │
├──────────────────────────────────────────────────────────┤
│ 4. Each participant POSTs /rounds/:id/updates │
│ with a DP-clipped local-model vector │
├─────────── ───────────────────────────────────────────────┤
│ 5. Coordinator POSTs /rounds/:id/aggregate │
│ ──> Status: aggregating → completed │
│ ──> globalModelRef + aggregateHash published │
├──────────────────────────────────────────────────────────┤
│ 6. Coordinator POSTs /rounds/:id/evidence │
│ ──> Sigstore-signed attestation bundle │
└──────────────────────────────────────────────────────────┘
Two MongoDB collections back the API: PatternFamily (the
consortium) and FederatedRound (one row per coordination round).
The Adjudon coordinator process is the trusted aggregator; the
roadmap includes a Trusted-Execution-Environment (TEE) attestation
path so the aggregation can run in a hardware-attested enclave
that even the coordinator cannot inspect (gated by
teeAttestation, also Custom-only).
Endpoints
GET /api/v1/federated/families
GET /api/v1/federated/families/:id
POST /api/v1/federated/families/:id/join
POST /api/v1/federated/families/:id/leave
GET /api/v1/federated/families/:id/rounds
POST /api/v1/federated/families/:id/rounds ── kickoff
GET /api/v1/federated/rounds/:roundId
POST /api/v1/federated/rounds/:roundId/updates ── client update
POST /api/v1/federated/rounds/:roundId/aggregate
POST /api/v1/federated/rounds/:roundId/evidence
The PatternFamily object
| Field | Type | Description |
|---|---|---|
name | string | Consortium name (e.g. eu-fraud-2027-q1) |
domain | string | Free-text classification (financial-fraud, medical-triage, …) |
members[] | array | Each entry { organizationId, joinedAt, status: 'active'/'paused'/'left' } |
coordinatorOrgId | string | null | Adjudon-internal by default; can be a member-org for self-coordinated families |
currentRound | number | Round counter; advances on aggregate completion |
defaultEpsilon | number | DP epsilon default for rounds (1.0) |
defaultDelta | number | DP delta default (1e-5) |
status | enum | active, paused, archived |
The FederatedRound object
| Field | Type | Description |
|---|---|---|
familyId | string | Owning consortium |
roundNumber | number | Unique within familyId; compound index |
participantOrgIds[] | string[] | Orgs that submitted a client update |
minParticipants | number | Default 3; aggregation refuses to run below this |
status | enum | pending, collecting, aggregating, completed, failed |
epsilon, delta | number | DP parameters for the round |
noiseMechanism | enum | laplace, gaussian (default gaussian) |
expectedLength | number | null | Required client-update vector dimension |
clipNorm | number | L2 sensitivity bound; default 1.0 |
globalModelRef | string | null | S3-style reference or content hash post-aggregation |
aggregateVector | number[] | Computed aggregate; omitted until completion |
aggregateHash | string | SHA-256 of canonicalised aggregate |
participantCount | number | Successful contributions |
rejectedCount | number | Rejected contributions (clip-norm violation, malformed payload) |
rejectionReasons | object | orgId → reason; surfaces why each participant was excluded |
contributionWeights | object | orgId → weight; transparency on aggregation weighting |
attestationRef | string | null | TEE attestation hash (when teeAttestation is on) |
sigstoreBundleRef | string | null | Sigstore-signed evidence bundle |
chainHash | string | null | Hash-chain anchor on round completion |
Submit a client update
POST /api/v1/federated/rounds/:roundId/updates
Body: { vector: number[], orgId? }. The vector must match
expectedLength and respect the round's clipNorm (L2
sensitivity bound). Updates that violate the bound are rejected
synchronously with the violation reason landing in
FederatedRound.rejectionReasons[orgId]. The reason vocabulary
is curated — never raw error text, per Cardinal Rule #4
on the federated path.
curl -X POST https://api.adjudon.com/api/v1/federated/rounds/65b1f2c4/updates \
-H "Authorization: Bearer $ADJUDON_JWT" \
-H "Content-Type: application/json" \
-d '{ "vector": [0.124, -0.087, ...], "orgId": "65a8b2c1..." }'
The endpoint never accepts raw training data — only the DP-clipped model-update vector. Adjudon does not see the participant's underlying decisions; that is the entire point of the federated architecture.
Run aggregation
POST /api/v1/federated/rounds/:roundId/aggregate
Coordinator-only. Combines submitted updates with the configured
noise mechanism, computes the L2-clipped weighted average,
serialises the result, hashes it, and writes
globalModelRef + aggregateVector + aggregateHash. The round
status transitions aggregating → completed (or failed if
fewer than minParticipants valid updates were received).
The handler also computes per-participant contributionWeights
and persists them — an auditor or a participant org can
later read who contributed how much without trusting the
coordinator's claim.
Sign aggregation evidence
POST /api/v1/federated/rounds/:roundId/evidence
Generates a Sigstore-signed attestation bundle anchoring the
round's inputs, the noise parameters, the participant set, and
the resulting aggregateHash. The sigstoreBundleRef is
written back to the round so participants can fetch and verify
the bundle independently. Plan-gated by sigstoreEvidence
(Enterprise+).