Federation
Push fraud rules and tenant lists from a parent organisation to every member of a federation group.
Phase 6G builds on the Authorization Engine's federation infrastructure to let an Enterprise tenant push their fraud detection configuration across every organisation in a federation group — subsidiaries, partner brands, sandbox environments. Tune once at the parent, mirror everywhere.
Two assets are pushed:
- Published fraud rules — every rule with
status = 'published'(Phase 6B). - Tenant lists —
tenant_blocklistandtenant_allowlistrows plus their entries (Phase 6C).
Sanctions / PEP / adverse_media lists are NOT pushed — those are global lists managed by the daily refresh cron (Phase 6C2) and already shared across every tenant.
Plan & scope
| Property | Value |
|---|---|
| Plan gate | Enterprise + Detection Pack addon |
| Scope (push) | permissions:manage |
| Scope (preview) | permissions:check |
| Idempotent | Yes (Idempotency-Key honoured on push) |
| Rate limit | 500 / hr per API key on permissions:manage |
Only the owner of a federation group may push (federation_groups.ownerOrgId). Non-owners get 403 FORBIDDEN. Members do NOT receive pushes from each other.
Preview
GET /api/v1/permissions/federation/groups/:id/fraud/preview
Dry-run the push without writing anything. Returns the same shape as the live push so the admin / portal UI can show "what would change" before the operator commits.
curl https://api.platformxe.com/api/v1/permissions/federation/groups/fed_abc123/fraud/preview \
-H "x-api-key: pxk_live_your_api_key_here"
{
"success": true,
"data": {
"groupId": "fed_abc123",
"ownerOrgId": "org_parent",
"rulesAvailable": 7,
"listsAvailable": 2,
"members": [
{
"organizationId": "org_subsidiary_a",
"rulesPushed": 7,
"listsPushed": 2,
"entriesPushed": 84,
"status": "success",
"error": null,
"durationMs": 12
}
],
"dryRun": true,
"durationMs": 18
}
}
Push
POST /api/v1/permissions/federation/groups/:id/fraud/push
Mirrors the owner's rules + lists into every other group member.
curl -X POST https://api.platformxe.com/api/v1/permissions/federation/groups/fed_abc123/fraud/push \
-H "x-api-key: pxk_live_your_api_key_here" \
-H "Idempotency-Key: $(uuidgen)"
const result = await px.fraud.federation.push('fed_abc123');
const failed = result.data.members.filter((m) => m.status === 'failed');
if (failed.length > 0) {
// Surface to ops — partial failures are NOT auto-retried
}
Per-member result
| Field | Description |
|---|---|
organizationId | The target member. |
rulesPushed | Number of rule rows inserted into the target. |
listsPushed | Number of tenant lists upserted into the target. |
entriesPushed | Number of list entries written across all upserted lists. |
status | 'success' or 'failed'. |
error | Failure message when status is 'failed'. null otherwise. |
durationMs | Per-member wall time. |
Mirroring semantics
Rules
- Each pushed rule is keyed by
nameagainst the target's existing rules. - A fresh row is inserted with
status = 'published', the parent's content (weight, condition, windows, appliesTo, verdictOverride, description), and aversion = max(existing) + 1. createdBy = 'federation:<ownerOrgId>'— the audit trail makes the origin obvious.- Existing rule versions in the target stay in place — they're not deleted. Members can fall back to local versions by changing status if the federated rule misbehaves.
Lists
- Tenant lists are matched by
(targetOrgId, source). - Existing target lists are KEPT (id stable); their entries are replaced atomically.
- Missing lists are created.
- Sanctions / PEP / adverse_media lists are excluded — the schema's
kindfilter explicitly limits totenant_blocklistandtenant_allowlist.
Audit
Each target member generates ONE federation_sync_logs row per push call:
| Column | Value |
|---|---|
direction | 'push' |
status | 'success' or 'failed' |
modulesCount | Rules pushed |
adminsCount | Lists pushed |
durationMs | Per-member duration |
error | Failure message when status is 'failed' |
The platform event FRAUD_FEDERATION_PUSHED fires once per push call with the rolled-up summary — subscribe via webhooks to wire up SOC alerting.
Partial-failure handling
A push to one member failing does NOT abort the rest. Each member is attempted, errors are logged + audit-trailed, and the response carries the full per-member breakdown so you can:
- Re-run the push (idempotent — succeeded members get a fresh version row but no semantic change).
- Investigate the specific failed members via
federation_sync_logs.
There is no auto-retry; pushes are operator-initiated.
Error responses
| HTTP | Code | Cause |
|---|---|---|
| 400 | BAD_REQUEST | Missing federation group id in path. |
| 401 | UNAUTHORIZED | Missing or invalid API key. |
| 402 | ENTERPRISE_REQUIRED | Tenant is not on Enterprise. |
| 402 | DETECTION_PACK_REQUIRED | Detection Pack addon not enabled. |
| 403 | FORBIDDEN | Caller is not the federation group owner. |
| 404 | NOT_FOUND | Federation group not found. |
| 500 | INTERNAL_ERROR | Unexpected service failure (very rare — push is purely DB I/O). |
What's NOT included
- Live decision-engine sync — pushes are configuration only. Each member still renders its own verdicts using its own rule engine + Redis counters.
- Reverse pull — there is no "pull from member A into the parent." If you want to consolidate insights, query each member's
fraud_decisionsvia your own pipeline. - Sanctions / PEP coverage — global lists already cover every tenant; no federation push needed.
- KYC config — country plugins ship as code, not tenant configuration. Federation does not push identity provider preferences.