Factorizer/Cluster ERP WikiCluster ERP Türkçe
Home / Operations

Explanation

Data residency check

What the residency_check command verifies about a country node, every finding code it can report, and what it cannot verify.

A Cluster ERP deployment can declare the country it serves. The command python -m cluster_erp.server.residency_check then looks for anything in the configuration or in the control plane that contradicts that declaration. This page explains the rule behind it, every finding code, and the limits of the check. The settings themselves are listed in the configuration reference.

In short

  • The declaration is CLUSTER_ERP_NODE_COUNTRY, a two-letter ISO 3166-1 code; without it the command prints that no policy is declared and exits with code 0 (src/cluster_erp/server/residency_check.py:347-355, src/cluster_erp/config/settings.py:756-760).
  • With a declaration the command prints a summary, then either CLEAN: nothing contradicts the declaration. with exit code 0 or the findings with exit code 1 (src/cluster_erp/server/residency_check.py:358-373).
  • The checks are pure functions over settings and tenant rows; only collect reads the control plane (src/cluster_erp/server/residency_check.py:28-29, src/cluster_erp/server/residency_check.py:325-344).
  • install.sh runs the check after every install and refuses to report the release as live when it fails (deploy/install.sh:258-259).

How it works

main builds Settings, calls collect, and prints the result (src/cluster_erp/server/residency_check.py:347-373). collect runs config_findings and, on a multi-tenant node, adds tenant_findings over the (key, region) pairs of every tenant whose registration is not deleted (src/cluster_erp/server/residency_check.py:325-344).

Finding codes

Nineteen codes, counted as the Finding(...) constructors in residency_check.py.

Code Reported when Source
BACKUP-REMOTE backup_dir is a network path. src/cluster_erp/server/residency_check.py:106-114
BACKUP-RELATIVE backup_dir is a relative path. src/cluster_erp/server/residency_check.py:115-122
STORAGE-REMOTE The local storage path is a network path. src/cluster_erp/server/residency_check.py:124-133
STORAGE-RELATIVE The local storage path is relative. src/cluster_erp/server/residency_check.py:134-141
STORAGE-S3-REGION-UNREVIEWED The S3 backend keeps the shipped default region. src/cluster_erp/server/residency_check.py:142-152
STORAGE-S3-ENDPOINT The S3 backend has no explicit endpoint. src/cluster_erp/server/residency_check.py:153-160
MAIL-RELAY-CONTRADICTION An SMTP host is set while mail_relay_none is true. src/cluster_erp/server/residency_check.py:165-172
MAIL-RELAY-UNDECLARED No SMTP host and no declaration that the node sends no mail. src/cluster_erp/server/residency_check.py:173-181
SIGNUP-RELAY-UNDECLARED Signup mail goes by SMTP but no signup SMTP host is set. src/cluster_erp/server/residency_check.py:182-189
REGION-FOREIGN The node serves a region whose code is not the declared country. src/cluster_erp/server/residency_check.py:194-204
REGION-DB-REMOTE A region's database server is another host; the operator must confirm its country. src/cluster_erp/server/residency_check.py:205-212
ARCHIVE-REMOTE wal_archive_dir or cold_storage_dir is a network path. src/cluster_erp/server/residency_check.py:213-227
ARCHIVE-RELATIVE wal_archive_dir or cold_storage_dir is relative. src/cluster_erp/server/residency_check.py:228-234
MAIL-RELAY-COUNTRY-UNDECLARED An SMTP relay is set but mail_relay_country is empty. src/cluster_erp/server/residency_check.py:235-244
MAIL-RELAY-ABROAD mail_relay_country differs from the declared country. src/cluster_erp/server/residency_check.py:245-252
STORAGE-S3-UNAVAILABLE The S3 backend is chosen but the S3 client library is not installed. src/cluster_erp/server/residency_check.py:253-263
MAIL-PROVIDERS-EXTERNAL Mailbox linking to an external provider is configured. src/cluster_erp/server/residency_check.py:264-292
COUNTRY-NODES-EMPTY CLUSTER_ERP_COUNTRY_NODES is empty. src/cluster_erp/server/residency_check.py:293-302
TENANT-FOREIGN-REGION A tenant is registered with a region that this node does not serve. src/cluster_erp/server/residency_check.py:305-322

A path counts as absolute when it is absolute in either the POSIX or the Windows convention, and as remote when it starts with two slashes after backslashes are turned into slashes (src/cluster_erp/server/residency_check.py:55-72).

Why it is built this way

  • The module states the policy: a customer's data stays in that customer's country, stored and processed there, so a deployment is one complete node per country (src/cluster_erp/server/residency_check.py:5-9).
  • Code cannot verify geography, so the check reports only contradictions with the declaration (src/cluster_erp/server/residency_check.py:11-14).

Rules and boundaries

  • Settings already refuses a country code that is not two letters, and a CLUSTER_ERP_COUNTRY_NODES map that omits the node's own country (src/cluster_erp/config/settings.py:756-767).
  • The tests are in tests/test_residency_check.py; the browser suite is web-client/_e2e_residency.mjs.

Interaction with other parts

  • The signup entry form and the operator console read node_country and country_nodes to send a customer to the node of their country (src/cluster_erp/server/routes/signup.py:126-138, src/cluster_erp/server/routes/vendor.py:157). See signup.
  • The backup, storage, and archive settings it checks are described in backups and restore.

Limits and open points

  • A drive letter mapped to a remote share reads as local; the module leaves that gap to the operator (src/cluster_erp/server/residency_check.py:25-26).
  • The check does not resolve host names or look up where an address is located; REGION-DB-REMOTE asks the operator to confirm (src/cluster_erp/server/residency_check.py:205-212).

Terms introduced

Term Code identifier Definition Turkish term Source
residency finding Finding One way the deployment contradicts its declared country, with a code and a detail. ikamet bulgusu src/cluster_erp/server/residency_check.py:44-52
node country node_country The country a node declares it serves. düğüm ülkesi src/cluster_erp/config/settings.py:111

Verified against commit 92f8051 on 2026-11-13.

Verified against commit 92f8051 · 2026-11-13