feat(tenant): welcome email, admin email display, async delete fix
All checks were successful
CI / build (push) Successful in 2m20s
CI / docker (push) Successful in 1m29s

- Send branded welcome email to tenant admin after provisioning completes
  (includes username and dashboard URL)
- Store admin_email on tenant entity (V004 migration)
- Show admin email in vendor tenant list table and detail page
- Fix ClickHouse cleanup: skip materialized views (can't ALTER DELETE on MVs)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-04-28 19:53:47 +02:00
parent bd301ad1fe
commit 345bc4a92b
12 changed files with 186 additions and 5 deletions

View File

@@ -400,6 +400,12 @@ export function TenantDetailPage() {
<span className={styles.kvLabel}>Slug</span>
<span className={styles.kvValueMono}>{tenant.slug}</span>
</div>
{tenant.adminEmail && (
<div className={styles.kvRow}>
<span className={styles.kvLabel}>Admin</span>
<span className={styles.kvValue}>{tenant.adminEmail}</span>
</div>
)}
<div className={styles.kvRow}>
<span className={styles.kvLabel}>Created</span>
<span className={styles.kvValue}>{new Date(tenant.createdAt).toLocaleDateString()}</span>

View File

@@ -41,6 +41,13 @@ const columns: Column<VendorTenantSummary>[] = [
<span style={{ fontFamily: 'monospace', fontSize: '0.875rem' }}>{row.slug}</span>
),
},
{
key: 'adminEmail',
header: 'Admin',
render: (_v, row) => (
<span style={{ fontSize: '0.875rem' }}>{row.adminEmail ?? '—'}</span>
),
},
{
key: 'tier',
header: 'Tier',

View File

@@ -4,6 +4,7 @@ export interface TenantResponse {
slug: string;
tier: string;
status: string;
adminEmail: string | null;
serverEndpoint: string | null;
provisionError: string | null;
createdAt: string;
@@ -75,6 +76,7 @@ export interface VendorTenantSummary {
slug: string;
tier: string;
status: string;
adminEmail: string | null;
serverState: string;
licenseExpiry: string | null;
provisionError: string | null;