prepare('SELECT id FROM tenants WHERE slug = ?'); $stmt->execute([$slug]); $tenantId = $stmt->fetchColumn(); if ($tenantId === false) { continue; } $tenantId = (int)$tenantId; $pdo->prepare('DELETE FROM tenant_domains WHERE tenant_id = ?')->execute([$tenantId]); $pdo->prepare('DELETE FROM participants WHERE tenant_id = ?')->execute([$tenantId]); $pdo->prepare('DELETE FROM tenant_memberships WHERE tenant_id = ?')->execute([$tenantId]); $pdo->prepare('DELETE FROM tenant_settings WHERE tenant_id = ?')->execute([$tenantId]); $pdo->prepare('DELETE FROM tenants WHERE id = ?')->execute([$tenantId]); } $pdo->prepare('DELETE FROM users WHERE email_norm = ?')->execute([$emailNorm]); } $pdo = dev_pdo(); dev_apply_schema($pdo); $slugs = ['m3-tenant-choice-a', 'm3-tenant-choice-b']; $email = 'm3-tenant-choice@test.local'; $emailNorm = saas_email_norm($email); $password = 'M3-tenant-choice-123'; $failures = []; $passes = 0; tenant_resolution_cleanup($pdo, $slugs, $emailNorm); $first = saas_register_tenant_owner($pdo, [ 'tenant_name' => 'M3 Tenant Choice A', 'tenant_slug' => $slugs[0], 'display_name' => 'M3 Tenant Choice', 'email' => $email, 'password' => $password, 'password_confirm' => $password, ]); $second = saas_register_tenant_owner($pdo, [ 'tenant_name' => 'M3 Tenant Choice B', 'tenant_slug' => $slugs[1], 'display_name' => 'M3 Tenant Choice', 'email' => $email, 'password' => $password, 'password_confirm' => $password, ]); tenant_resolution_assert('first registration succeeds', $first['ok'] === true, $failures, $passes); tenant_resolution_assert('second registration succeeds', $second['ok'] === true, $failures, $passes); if ($first['ok'] && $second['ok']) { $userId = (int)$first['identity']['user_id']; $memberships = saas_list_user_memberships($pdo, $userId); tenant_resolution_assert('user has two memberships', count($memberships) === 2, $failures, $passes); $genericLogin = saas_authenticate($pdo, $email, $password); tenant_resolution_assert('generic login succeeds', $genericLogin['ok'] === true, $failures, $passes); tenant_resolution_assert('generic login needs tenant selection', !empty($genericLogin['needs_tenant_selection']), $failures, $passes); tenant_resolution_assert('generic login exposes memberships', count($genericLogin['memberships'] ?? []) === 2, $failures, $passes); $specificLogin = saas_authenticate($pdo, $email, $password, $slugs[1]); tenant_resolution_assert('specific login succeeds', $specificLogin['ok'] === true, $failures, $passes); tenant_resolution_assert( 'specific login selects requested tenant', ($specificLogin['identity']['tenant_slug'] ?? null) === $slugs[1], $failures, $passes ); $identity = saas_identity_for_user_tenant($pdo, $userId, (int)$second['identity']['tenant_id']); tenant_resolution_assert('tenant selection identity exists', $identity !== null, $failures, $passes); if ($identity !== null) { tenant_resolution_assert('tenant selection returns requested tenant', $identity['tenant_slug'] === $slugs[1], $failures, $passes); } $pdo->prepare( 'INSERT INTO tenant_domains (tenant_id, domain, domain_norm, domain_type, status, verified_at) VALUES (?, ?, ?, ?, ?, NOW())' )->execute([(int)$second['identity']['tenant_id'], 'kaffee.example.test', 'kaffee.example.test', 'custom', 'active']); $domainTenant = saas_resolve_tenant_domain($pdo, 'kaffee.example.test:443'); tenant_resolution_assert('fixed domain resolves tenant', $domainTenant !== null, $failures, $passes); if ($domainTenant !== null) { tenant_resolution_assert('fixed domain returns requested tenant', $domainTenant['tenant_slug'] === $slugs[1], $failures, $passes); } } tenant_resolution_cleanup($pdo, $slugs, $emailNorm); if ($failures !== []) { echo "\nM3 tenant resolution check failed with " . count($failures) . " failure(s):\n"; foreach ($failures as $failure) { echo "- {$failure}\n"; } exit(1); } echo "\nM3 tenant resolution check passed with {$passes} assertions.\n";