D7 users live in a separate shared database, not any per-site dump
Area: migration / users / infrastructure
Raised during: Session 2026-07-10 (1b.1 — planning the user migration)
Jira: (add when available)
Priority: High — blocks the user migration (Sequencing item 1) and everything gated on it: d7_images_collection_memberships (211/249 rows currently skipped), Group membership uid correctness, SAML/NetBadge account mapping
What we found
D7 Mandala's five sites (AV, Images, Sources, Texts, Home) don't each have
their own user base — they share one, via a MySQL cross-database table-prefix
kludge. Confirmed in the legacy repo,
mandala-drupal/docroot/sites/all/platform.settings.php:
$shared = 'mandala_shared_dev.';
$databases['default']['default']['prefix'] = array(
'default' => '',
'users' => $shared,
'users_roles' => $shared,
'role' => $shared,
'authmap' => $shared,
'sessions' => $shared,
'field_data_field_first_name' => $shared,
'field_revisions_field_first_name' => $shared,
'field_data_field_last_name' => $shared,
'field_revisions_field_last_name' => $shared,
'realname' => $shared,
);
(Dev shown; production uses mandala_shared. per mandala-drupal/CLAUDE.md.)
Each site's own local users/users_roles/role/authmap/sessions
tables exist but are entirely shadowed and unused — every one of these
table names resolves to the shared database instead. The real, authoritative
D7 user data — for all five sites at once — lives only in mandala_shared
(prod) / mandala_shared_dev (dev).
mandala-drupal/CLAUDE.md also confirms production authentication is
SimpleSAMLphp/Shibboleth (UVA NetBadge) layered on top of this shared
base, and that shanti_general handles cross-site /user redirects (a
D7-multisite-specific behavior, not migration-relevant on its own).
What this means for the migration
- Wrong source, silently wrong data. Any D7 source dump/connection scoped
to one site (e.g. the
d7_imagesdump this session's Images work has used throughout) does not contain real user data — its localuserstable is the shadowed, unused one. Pointing a user migration at it would produce garbage or empty results without erroring. - The user migration needs its own source DB connection, pointed at
mandala_shared— separate from the per-site dumps (d7_images, and whatever the eventual Sources/Texts/AV/Home dumps are named). - One user migration serves all five site tracks. Since the D7 source is
already unified, the D11 side should be too — this is naturally a
cross-cutting migration, not a per-site one like Images'
d7_images_*migrations, and probably belongs outside any single site's migration group. - SAML/NetBadge account mapping is a separate, real question, not solved
by migrating the
userstable alone — how migrated D11 accounts link to UVA Shibboleth-authenticated sessions needs its own mapping strategy (name/mailmatch? a stored NetBadge identifier field?). Relevant to ADR 013/014's SAML+OAuth2 coexistence work (Spike 10, 1b.1 part 4) — that work assumes a Drupal account already exists to keysuboff of; user migration is the thing that has to create it.
What's already gated on this
d7_images_collection_memberships(1b.2): 38/249 rows created, 211 skipped — those 211 reference D7 users that don't exist in D11 yet. Re-run once users are migrated.- The 174 collection/subcollection groups that got
uid: 1forced during 1b.2 (working around Group's uid=0-on-insert bug, itself since fixed by PR #28) were never meant to be permanently owned by the admin account — once real users exist, decide whether/how to correct historical group ownership to the actual D7 creator.
Open questions for the actual migration design
- Cardinality/scope: does
mandala_sharedcontain users for sites outside Mandala entirely (a truly shared UVA-wide user base), or is it scoped to just these five? Affects whether the D11 migration needs to filter. Fill in once the shared DB schema/dump is actually in hand. - Password hashes: D7 uses phpass; D11/current Drupal core uses phpass-
compatible hashing too (core still ships
PhpassHashedPasswordera logic for legacy migrations), so password migration is likely straightforward — confirm during implementation rather than assuming. realnamefield migration: D11 has norealnamemodule by default: decide whether to bring it in as a dependency or fold the name into core user fields.
Cross-references
- Critical Path §7 — Migration Sequencing already lists "Users (no dependencies)" first; this note is why that's not as simple as it sounds
- ADR 014 — SAML+OAuth2 coexistence, which needs migrated D11 accounts to key tokens off of