Federation

One policy floor. 50 business units. Zero ticket queues.

Hub-and-spoke federation for the platform team that owns the golden path. The hub sets a global policy floor and runs Billy's approval queue. Each BU overlays its own Rego and owns its own exceptions. One signed audit stream flows up. The platform team is not the ticket queue.

The problem

AppSec wants one global rule. BU teams want autonomy on exceptions. The platform team gets squeezed.

Most supply-chain tooling forces a choice. Run one central instance and BU teams file tickets to bend it. Let each BU run their own instance and lose the floor. Either way the platform team becomes the ticket queue — the central one, or the one routing requests between BU instances. Hub-and-spoke federation gives the hub a floor it can enforce and gives each BU a Rego overlay it owns end to end. Same binary, three policy layers, one audit stream.

Topology

Hub-and-spoke: one floor down, one stream up

The hub holds the global policy floor, the central audit stream, and Billy's approval queue for floor-level exceptions. Each spoke is a BU: BU-scoped Rego overlays, BU-scoped exception queue, per-region replicas for residency. Signed policy bundles flow down. Signed audit rows flow up.

Hubglobal Rego floorBilly approval queue · central auditBU-ARego overlayoverride: allow GPL-3.0per-region replicasBU-BRego overlaylocal exception queueBU-CRego overlaystricter floor + own SLAOverride precedencehub↓ BU↓ team↓ repomost-specific wins;hub floor non-overridableException lifecyclerequest↓ routing↓ approval↓ expiry↓ audit rowsolid: signed policy bundle ↓dashed: signed audit stream ↑
Figure 5 — Hub-and-spoke federation. Override precedence and exception lifecycle.

Hub publishes a signed policy bundle. Spokes verify the signature before applying it. Spokes publish their overlay as a second signed bundle, scoped to their BU. Audit rows from refuses, allows, and Billy transitions are signed at the spoke and forwarded to the hub stream. Nothing in the path trusts unsigned input.

Override precedence

Tighten down the stack, loosen only within the band above

Four layers, evaluated top to bottom. The hub sets a floor — BUs can tighten or (where the hub permits) loosen within a band. Teams can tighten further. Repos can ratchet stricter still. No layer can punch through the layer above.

Layer Tighten Loosen Log-only Exception Worked example
Hub (holdco policy) Yes — sets the floor No Yes No (BUs request, hub does not pre-approve) Global floor: block GPL-3.0 in commercial repos; require provenance on prod images.
BU (e.g. Foodora, Talabat) Yes Yes, within the hub-permitted band Yes Yes, BU-scoped Foodora overlays: allow GPL-3.0 for repo `open-source-licensing/*`; tighten npm typosquat score threshold.
Team Yes Only if the BU overlay opens the door Yes Yes, team-scoped, routed via CODEOWNERS Payments team in Talabat: require 14-day-old packages on prod branch; warn on staging.
Repo Yes (in-repo policy file) No Yes No Single repo can ratchet stricter — never weaker than the layer above.

Worked example end-to-end. Hub: "block GPL-3.0 in commercial repos." Foodora's BU overlay: "allow GPL-3.0 in repo open-source-licensing/*." A developer on that repo installs a GPL-3.0 dependency: the install path allows it, the audit row records hub-rule-id + BU-overlay-id + the developer's BU and team. A developer on a commercial Foodora repo tries the same: refuses on the install path, audit row records hub-rule-id + no overlay match. Same signed row format, both BUs visible to the holdco CISO.

Exception lifecycle

Auto-expiry kills permanent allow-list rot

Billy runs the queue. The platform team owns the policy mechanism, not the per-request decision. Routing follows ownership; expiry is the default, not the exception.

  1. 01

    Request

    Developer hits a refuse on the install path. CLI prints the rule that blocked them and a one-line `chainsaw exception request` command with the package, version, repo, and proposed expiry pre-filled.

  2. 02

    Routing

    Billy reads the repo's ownership glob (CODEOWNERS or BU mapping) and routes the request to the team that owns the rule — not a central queue. Hub-floor exceptions route to AppSec at the holdco. BU-overlay exceptions route to BU AppSec.

  3. 03

    Approval

    Reviewer sees a Billy queue entry with reviewer identity, written reason, scope (one repo, one BU, or wider), and a blast-radius preview computed against the live inventory: how many other repos would be affected if this exception widened.

  4. 04

    Expiry

    Every exception carries an expiry. Default 30 days, configurable per policy. At expiry the rule snaps back to refuse on the install path — no permanent allow-list rot.

  5. 05

    Renewal

    Renewal is a new request, not a silent extension. Same routing, same approval, fresh signed audit row. If nobody renews, the refuse returns automatically.

  6. 06

    Audit

    Every transition — request, approve, expire, renew, deny — writes a signed audit row to the central stream. Same row format as enforce/refuse decisions.

Identity flow per-BU

Okta or Entra group → SCIM custom attr → Rego scope

SCIM provisioning pulls custom attributes — typically cost_center and business_unit — onto every user record. Rego scopes every decision and every audit query by those attributes. No bespoke directory. No second source of truth for who-is-in-which-BU.

Worked example. Talabat AppSec logs in via Entra. SCIM sets business_unit=talabat on their session. The audit UI's Rego scope filters to business_unit == "talabat" — they see Talabat refuses, Talabat exceptions, Talabat metrics. They cannot list Foodora data; the query returns empty, not 403, because the Rego scope rewrites the filter. The CISO at the holdco has role=holdco_ciso, which the Rego scope treats as a wildcard across all BUs.

Per-BU rollup

What the CISO sees without micromanaging the BUs

The hub view is one audit stream and four rollups. Enough to see drift, not so much that the holdco starts dictating per-package decisions inside a BU.

  • Floor coverage

    % of BU repos receiving the hub policy bundle in the last 24h. Drops here mean an offline spoke, not a policy fight.

  • Open exceptions

    Per-BU count, plus the count of exceptions due to expire in 7 days. CISO can see which BUs are accumulating debt without reading the requests.

  • FP rate trend

    Per-BU rolling 30-day false-positive rate on hub-floor rules. Catches a rule that is fine for Foodora but breaking Talabat — before the BU files a ticket.

  • SLA on exception review

    Time from request to first reviewer action, per BU. CISO can see which BU's AppSec is the bottleneck without owning the queue.

Multi-region replication

Per-region replicas, residency honored, floor replicated

A spoke can run in any region with its own replica. The policy floor replicates to every region. Audit streams aggregate to the hub by default, or stay local if a BU's region contract requires it — the holdco rollup then shows that BU's counts without the raw rows.

  • Frankfurt (EU)

    Foodora DE/AT/NO/SE/FI, Glovo ES, Pyszne PL

    Audit stream stays in-region under GDPR. Policy bundle replicated from hub.

  • Dubai (MENA)

    Talabat AE/SA/KW/QA/BH/OM, foodpanda PK

    Audit stream replicated to hub for CISO rollup; raw payloads stay regional if BU contract requires it.

  • Singapore (APAC)

    foodpanda SG/MY/TH/PH/HK/TW/MM/LA/BD/KH

    Same binary, same Rego, same audit row schema. Local replica for latency on install-path enforcement.

Scope boundaries

What federation is not

  • Not a federated identity provider

    Bring Okta, Entra, or any SAML/OIDC IdP. Chainsaw consumes group membership and SCIM custom attributes — it does not issue them.

  • Not a CMDB

    Backstage, ServiceNow, or your homegrown service catalog stays the source of truth for ownership. Chainsaw reads it; it does not replace it.

  • Not a workflow orchestrator

    Billy handles policy edits and exception approvals. It is not a generic ticketing system, an incident tool, or a change-management board. Wire it into the one you already run.

  • Not a federated PR review tool

    Chainsaw refuses on the install path; it does not arbitrate code review. PR comments are advisory copies of the same decision the install path will enforce.

Case study

Top-5 European on-demand platform — anonymized

25,000 engineers, 40 business units, 3 regions. Migrated from a constellation of per-BU Xray instances (per-instance configuration, no shared floor) to a single hub-and-spoke Chainsaw deployment. Hub holds the holdco AppSec floor. Each BU retained autonomy on overlays and exceptions.

Central policy floor coverage moved from partial to comprehensive across business units. Ticket-queue load on the platform team measurably reduced. Per-BU autonomy on exception lifecycle preserved. Concrete metrics, BU shapes, and reference contact available under NDA after MSA.

Holdco-shaped AppSec?

30 minutes, your org chart on screen, our topology diagrams open.

Thirty minutes. Hub, spokes, override precedence, audit stream — walked against your BU layout. You'll leave with a draft topology for your environment and an honest read on which parts of your current tooling stay.