feat: member portal Sprint 5 — onboarding portal experience + restore Thread schema

- Redesign onboarding into a 5-step wizard: welcome → phone → consent → code → done
- Progress bar, human-readable consent scopes (INGEST/ARCHIVE/REPLICATE/DISPLAY) with descriptions
- Resend-code action, back navigation, indigo theme matching member portal
- "Done" step introduces portal features (digests, events, privacy) with CTA
- Onboard page shell: rounded card, policy footer
- Restore Thread model + Message.expiresAt/quotedPlatformMsgId/threadId + RAW/DNC statuses to schema.prisma (wiped by prior reset; matches existing add_hybrid_ai_architecture migration) — unblocks ThreadsModule registration

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-17 16:30:58 +05:30
parent 0ffdc362b5
commit a0dc94ce79
3 changed files with 309 additions and 122 deletions
+44 -17
View File
@@ -91,6 +91,7 @@ model Tenant {
digestConfig DigestConfig?
digests Digest[]
events Event[]
threads Thread[]
}
enum AdminRole {
@@ -235,6 +236,7 @@ model Group {
consents ConsentRecord[]
claimTokens GroupClaimToken[]
groupAccesses GroupAccess[]
threads Thread[]
@@unique([platform, platformId])
@@index([accountId])
@@ -247,37 +249,62 @@ model Group {
// ============================================================================
model Message {
id String @id @default(cuid())
tenantId String
tenant Tenant @relation(fields: [tenantId], references: [id])
platform String
platformMsgId String
sourceGroupId String
sourceGroup Group @relation(fields: [sourceGroupId], references: [id])
senderJid String
senderName String?
senderTowerUserId String?
senderTowerUser TowerUser? @relation("senderTowerUser", fields: [senderTowerUserId], references: [id])
content String
mediaUrl String?
tags String[]
status MessageStatus @default(PENDING)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
id String @id @default(cuid())
tenantId String
tenant Tenant @relation(fields: [tenantId], references: [id])
platform String
platformMsgId String
sourceGroupId String
sourceGroup Group @relation(fields: [sourceGroupId], references: [id])
senderJid String
senderName String?
senderTowerUserId String?
senderTowerUser TowerUser? @relation("senderTowerUser", fields: [senderTowerUserId], references: [id])
content String
mediaUrl String?
tags String[]
status MessageStatus @default(PENDING)
expiresAt DateTime?
quotedPlatformMsgId String?
threadId String?
thread Thread? @relation(fields: [threadId], references: [id])
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
approval Approval?
@@unique([platform, platformMsgId])
@@index([tenantId])
@@index([senderTowerUserId])
@@index([status, expiresAt])
@@index([threadId])
}
enum MessageStatus {
RAW
PENDING
APPROVED
REJECTED
DISTRIBUTED
ARCHIVED
DNC
}
model Thread {
id String @id @default(cuid())
tenantId String
tenant Tenant @relation(fields: [tenantId], references: [id])
sourceGroupId String
sourceGroup Group @relation(fields: [sourceGroupId], references: [id])
lastActivityAt DateTime @default(now())
messageCount Int @default(0)
topic String?
createdAt DateTime @default(now())
messages Message[]
@@index([tenantId])
@@index([sourceGroupId, lastActivityAt])
}
model Approval {