Skip to content

feat(compliance): add per-provider geo-blocking - #173

Merged
okapitula merged 13 commits into
devfrom
feat/add-provider-geo-blocking
Sep 18, 2026
Merged

okapitula merged 13 commits into
devfrom
feat/add-provider-geo-blocking

Conversation

@okapitula

Copy link
Copy Markdown
Collaborator

Summary

Operators can now block every game of a game provider in a country. Admin routes under /compliance/provider-geo-rules add, remove and list provider rules. Every change is audited, and new rounds are checked against these rules alongside the existing global and per-game rules.

Why

Per-game geo rules (#154) need one rule per game. A provider's licence restriction usually covers its whole catalogue. Blocking it game by game means many rules to maintain and audit, and any game added to the provider later is not blocked.

Alternatives considered

  • Bulk-create per-game rules for every game of the provider: rejected. Games added later are not covered, and the audit trail shows many unrelated rule changes instead of one decision.
  • Let the gaming module pass the provider id to the geo check: rejected. Compliance looks up the game's current provider itself, so a caller cannot supply a wrong or stale provider, and an unknown game is refused.
  • A generic helper shared by the game and provider rule methods: deferred. The new methods follow the feat(compliance): add per-game geo-blocking #154 pattern, and merging the two can be its own refactor.

Risks

  • GameGeoDenialReason gains provider_block and game_not_found. Consumer code that handles every reason explicitly needs updating.
  • checkGame on the geo-check port (GAME_GEO_CHECK) now denies a game id that does not exist instead of allowing it. startRound is unaffected because it rejects unknown games first; other callers of the port will see the new denial.
  • When the player's country cannot be determined and the game's provider has any rule, the start is refused. A flaky or unbound GeoIP adapter therefore blocks every game of that provider, not just the games with per-game rules.

Operators can block every game of a game provider in a country. Adds the provider_geo_rule table, admin routes to upsert, delete and list provider rules, audited change events, and a provider_block decision in the game geo check. The check now resolves provider and game rules in one query and denies an unknown game.
Comment thread packages/core/src/compliance/service/compliance.service.ts Outdated
Comment thread packages/core/src/compliance/service/compliance.service.ts
Comment thread packages/core/src/compliance/service/compliance.service.ts Outdated
Comment thread packages/core/src/compliance/service/compliance.service.ts Outdated
Null the country code on game_not_found, share the unresolved-country
match between the provider and game subqueries, and serialize geo rules
through one helper.
Comment thread packages/testing/src/__tests__/game-geo-blocking.e2e.test.ts
Comment thread packages/core/src/compliance/service/compliance.service.ts Outdated
Comment thread packages/core/src/audit/plugin.ts
@jakubfilinger-b

Copy link
Copy Markdown
Collaborator

Blocker: provider-country enforcement can be bypassed by spoofing x-real-ip; the other two comments cover a convention cleanup and missing audit-persistence coverage.

Drop the narrative comment in the game geo check, and assert the
persisted audit records for provider geo rule upsert and delete in the
lifecycle E2E.
@zaxovaiko

Copy link
Copy Markdown
Member

@codex

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 16, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-16T10:23:45.639198Z 542abfc Manual request
🔒 Security Review Completed 2026-09-16T10:26:48.386344Z 542abfc Manual request

Security findings

Advisory findings (1)

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. More of your lovely PRs please.

Reviewed commit: 542abfc76f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛡️ Codex Security Review · Automatically triggered

Here are some automated security review suggestions for this pull request.

Reviewed commit: 542abfc76f

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

Comment thread packages/core/src/compliance/service/compliance.service.ts
Comment thread packages/core/src/compliance/contract/index.ts
Comment thread packages/core/src/compliance/contract/index.ts Outdated
Comment thread packages/testing/src/__tests__/game-geo-blocking.e2e.test.ts
zaxovaiko
zaxovaiko previously approved these changes Sep 17, 2026
List game and provider geo rules with page/limit and gameIds[]/providerIds[] filters, returning the shared paginated shape.
@okapitula
okapitula requested a review from zaxovaiko September 17, 2026 18:29
@okapitula
okapitula added this pull request to stack #196 September 18, 2026 09:48
Blocking a game or provider in many countries took one request per country.
Add PUT and DELETE /compliance/{game,provider}-geo-rules/bulk taking
countryCodes (1-250) and a reason. Each request is one transaction: bulk
delete fails with 404 and removes nothing if any listed country has no rule.
Every rule still emits its own upserted/deleted event, so audit stays per rule.

Single-country upserts now delegate to the bulk path. withAdvisoryXactLocks
takes all rule locks in one statement, ordered by lock id so overlapping
bulk writes cannot deadlock.
Game and provider geo rules each had a single-country upsert, a delete by
rule id, and separate /bulk routes. Keep one pair per rule type, with the
game or provider id in the path and a list of countries in the body:

  PUT|DELETE /compliance/game-geo-rules/{gameId}          { countryCodes, reason }
  PUT|DELETE /compliance/provider-geo-rules/{providerId}  { countryCodes, reason }

To change one country, pass a one-element list.

BREAKING CHANGE: PUT /compliance/game-geo-rules and
DELETE /compliance/game-geo-rules/{id} are removed. Callers move the game
id into the path, send countryCodes instead of countryCode, and remove
rules by country code instead of rule id. Both routes now return an array.
@okapitula
okapitula merged commit 5251e06 into dev Sep 18, 2026
2 checks passed
@okapitula
okapitula deleted the feat/add-provider-geo-blocking branch September 18, 2026 14:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants