aliasgar/module-customer-uuid

Adds an immutable, unique UUID attribute to Magento customers, exposed via GraphQL and the admin customer grid.

Maintainers

Package info

github.com/bharmalaliasgar/module-customer-uuid

Type:magento2-module

pkg:composer/aliasgar/module-customer-uuid

Statistics

Installs: 0

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v1.0.0 2026-06-11 13:54 UTC

This package is auto-updated.

Last update: 2026-06-11 14:19:30 UTC


README

Magento 2 extension that adds an immutable, unique uuid attribute to customers:

  • Every customer (existing and new) is automatically assigned a UUID v4.
  • Uniqueness is enforced by a database-level unique index — not just application validation.
  • Exposed via GraphQL on the Customer object for authenticated customers.
  • Shown as a column in the admin customer grid (sortable, filterable, searchable).
  • Read-only everywhere: rendered as a disabled field on the admin customer edit form, and a server-side guard reverts any attempted change through any channel (admin, REST, GraphQL, legacy model saves).

Design rationale and trade-offs are documented in DECISIONS.md.

Requirements

  • Magento 2.4.x (developed and tested on 2.4.9 CE, PHP 8.5)
  • ramsey/uuid ^4.7 (already a Magento core dependency)

Installation

Option A — Packagist (recommended)

The package is published on Packagist. No repository configuration is needed:

composer require aliasgar/module-customer-uuid:^1.0

Option B — VCS (GitHub) without Packagist

composer config repositories.aliasgar-customer-uuid \
  vcs https://github.com/bharmalaliasgar/module-customer-uuid.git
composer require aliasgar/module-customer-uuid:^1.0

Option C — Local path repository (for development in this docker-magento project)

composer config repositories.aliasgar-customer-uuid \
  '{"type":"path","url":"packages/aliasgar/module-customer-uuid","options":{"symlink":true}}'
composer require aliasgar/module-customer-uuid:^1.0

Prefix all composer and magento commands with bin/ when using the docker-magento wrappers.

Enable and set up (all options)

bin/magento module:enable Aliasgar_CustomerUuid
bin/magento setup:upgrade            # creates the column + attribute, backfills existing customers
bin/magento setup:di:compile
bin/magento cache:flush
bin/magento indexer:reindex customer_grid   # materializes the uuid column in the grid index

The customer_grid reindex is required: the grid reads from the flat index table (customer_grid_flat) and Magento hides columns that are not physically present in it. The backfill patch invalidates the indexer; this command (or your cron) rebuilds it.

What setup:upgrade does

  1. Declarative schema adds a nullable uuid varchar(36) column to customer_entity with unique index CUSTOMER_ENTITY_UUID.
  2. AddCustomerUuidAttribute data patch creates the uuid customer attribute (static backend, unique, grid-enabled, admin-form only).
  3. BackfillCustomerUuid data patch assigns a UUID v4 to every existing customer in batches of 1000 using direct, memory-safe SQL.

API access

GraphQL

The uuid field is available on the Customer type. It requires a customer token (the core customer query rejects unauthenticated requests):

mutation {
  generateCustomerToken(email: "customer@example.com", password: "password123") {
    token
  }
}
curl -s http://<host>/graphql \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer <token>' \
  -d '{"query":"{ customer { firstname email uuid } }"}'
{"data": {"customer": {"firstname": "Veronica", "email": "...", "uuid": "afdbadb4-b3e3-4780-80df-80f7f2307669"}}}

REST

Because the attribute is a regular (non-system) customer attribute, it also appears in REST responses under custom_attributes:

GET /rest/V1/customers/me            (customer token)
GET /rest/V1/customers/:id           (admin token)

Sending a different uuid value in a PUT /V1/customers/:id payload is silently reverted to the stored value — the attribute is immutable by design.

Read-only behavior

Channel Behavior
Admin customer grid Visible column (filter/search/sort)
Admin customer edit form Visible, disabled (greyed out)
Storefront account forms Not present at all
Repository / REST / GraphQL writes Stored value always wins; tampered values reverted
Legacy $customer->save() model saves customer_save_before observer enforces the same rule

Testing

A detailed step-by-step guide (one-time setup, expected output, troubleshooting) is in how-to.md. Quick reference:

Unit tests

bin/cli vendor/bin/phpunit -c dev/tests/unit/phpunit.xml.dist \
  vendor/aliasgar/module-customer-uuid/Test/Unit

Integration tests

One-time setup in this docker-magento project (creates the magento_integration_tests database and installs the test config):

make setup-integration-tests

Then:

bin/dev-test-run integration ../../../vendor/aliasgar/module-customer-uuid/Test/Integration

Explicit paths are required in both cases: Magento's phpunit.xml.dist test suites only scan app/code/*/*/Test/*, so tests inside composer-installed (vendor) modules are not auto-discovered.

Coverage:

  • Unit: UUID v4 format/randomness, repository plugin behavior (assign on create, revert on tamper), UuidManager resolution order (stored > candidate > generated).
  • Integration: attribute configuration (static/unique/grid flags/non-system/forms), automatic assignment through the repository, immutability through the repository, backfill of pre-existing rows, the DB unique constraint itself, and NULL tolerance of the unique index.

GraphQL end-to-end coverage belongs in Magento's dev/tests/api-functional suite, which this environment does not wire up; the resolver is deliberately thin (one guarded array access) and is exercised manually with the query above.

Uninstall

bin/magento module:disable Aliasgar_CustomerUuid
composer remove aliasgar/module-customer-uuid
bin/magento setup:upgrade

Note: declarative schema will drop the uuid column (and its data) once the module's db_schema.xml is removed and setup:upgrade runs.