QDG Knowledge Base Read-only viewer QWebHub
overview

Overview

Version 2 · Re-synced with docs/OVERVIEW.md and added a link to the new Database reference page

GateKeeper — Overview

What is GateKeeper?

GateKeeper is the access-control layer for our racing data APIs. Every external client (e.g. CWS, WSB) that wants meetings, racecards, speed maps, or results data has to go through GateKeeper first. It answers one question on every single request: "Is this specific client allowed to see this specific piece of data?"

Before GateKeeper, that kind of restriction had no clean home — access would have to be hardcoded or checked ad hoc in each data API. GateKeeper centralizes it: one place to define what each client is allowed to see, one place to change it, and every downstream API just asks GateKeeper (or reads from the cache GateKeeper maintains) instead of reimplementing the logic.

The problem it solves

A racing data client is never "all or nothing." A client might be allowed:

  • Only Australian data, not New Zealand
  • Only meetings, not speed maps
  • Everything, except a specific venue that's under a temporary data dispute
  • A trial add-on for one discipline, for 30 days, on top of their normal plan

Multiply that across dozens of clients, each with their own mix, and hardcoding it becomes unmanageable. GateKeeper turns each of those rules into data (a package or an override) instead of code, so granting, changing, or revoking access is an admin action, not a deployment.

Key concepts

Term What it means
Customer An external client we grant API access to (e.g. CWS, WSB). Has a unique client-guid used to identify it on every request.
Token (secret key) The password half of a customer's credentials. A customer can have multiple tokens (e.g. one for production, one for staging) and each can be revoked independently without touching the others.
Package A named, reusable bundle of permissions (e.g. "AU Meetings Only," "AU + NZ Full Feed"). Defined once, assigned to as many customers as needed.
Subscription The link between a customer and a package, with a start date and (optionally) an end date. This is how a customer "has" a package.
Override A one-off rule for a single customer, outside of any package — either a grant (extra access, e.g. a trial add-on) or a revoke (temporarily block something they'd otherwise have, e.g. during a data dispute). Overrides always win over packages.
Effective entitlement The final, computed answer for a customer: everything their packages allow, minus anything an active revoke override blocks. This is what actually gets checked on every request.

How a request is protected, in plain terms

  1. A client calls a GateKeeper-protected endpoint (e.g. /v1/meetings) and includes its client-guid and secret key in the request headers.
  2. GateKeeper checks both are valid, active, and belong together — a stolen or reused secret under the wrong client-guid is rejected.
  3. GateKeeper looks up that customer's effective entitlement (computed from their packages + overrides, kept warm in cache) and checks whether the requested data (country, discipline, data type, venue) is covered.
  4. Allowed → the request goes through. Not allowed → rejected, no data returned.
  5. Every request is logged in the background for auditing, without slowing the response down.

Access changes (granting a package, adding an override, revoking a token) take effect within milliseconds — there's no waiting for a cache to expire or a deployment to go out.

How we use it

Onboarding a new client:

  1. Create the customer in GateKeeper (via the Admin UI or admin API) — this generates their client-guid.
  2. Issue them a secret key — shown once, so it's handed off immediately.
  3. Assign the package(s) that match what they've signed up for.
  4. Hand the client both credentials (client-guid + secret) — every request they send must include both.

Day-to-day admin work, all done through the Admin UI (a browser-based tool, no code required):

  • Adjust a customer's package(s) as their plan changes
  • Add a temporary override for a trial, promo, or dispute
  • Rotate or revoke a token if a secret is compromised or a client offboards
  • Check usage — how many requests a customer has made, and when their subscriptions expire
  • Remove a client entirely if they're no longer a customer

When we add a new data type or restriction axis (e.g. a new endpoint, or restricting by a new attribute we haven't filtered on before), it's a configuration change in GateKeeper — defining what values are valid and building it into packages/overrides — not a code change or a database migration.

Where GateKeeper sits, at a glance

External client (CWS, WSB, ...)
        │  client-guid + secret key
        ▼
   GateKeeper  ──────► checks the request against the client's effective entitlement
        │
        ├── allowed  → request proceeds to the actual racing data
        └── denied   → rejected, nothing returned

Two ways to administer it:

  • Admin UI — a web page for day-to-day management (create customers, issue tokens, assign packages, add overrides)
  • Admin API — the same operations, callable programmatically (for scripting or integrating into other internal tools)

Want more detail?

This page is the "what and why" — a user guide for anyone onboarding a client or doing day-to-day admin work. For the technical deep dive, see Architecture (data model, resolution algorithm, caching, request pipeline); Database (table-by-table schema reference, indexes, sample rows, common queries); Quick Reference (run commands, HTTP API, configuration); and Known Issues (discrepancies found against the original design doc).

Updated by Claude on Aug. 13, 2026, 8:45 a.m. · Task: update user guide and db document to GateKeeper