diff --git a/modules/rinbox/mod.ts b/modules/rinbox/mod.ts index cf84658..209323c 100644 --- a/modules/rinbox/mod.ts +++ b/modules/rinbox/mod.ts @@ -1630,6 +1630,44 @@ routes.get("/", (c) => { // ── Seed template data ── +/** + * Initialize a clean team inbox for a space: {space}@rspace.online + * No demo threads — just an empty mailbox ready for multi-sig approval. + */ +function initSpaceInbox(space: string, ownerDid: string) { + if (!_syncServer) return; + // Skip if space already has mailboxes + const prefix = `${space}:inbox:mailboxes:`; + const existing = _syncServer.listDocs().filter((id) => id.startsWith(prefix)); + if (existing.length > 0) return; + + const mbId = crypto.randomUUID(); + const docId = mailboxDocId(space, mbId); + const now = Date.now(); + + const doc = Automerge.change(Automerge.init(), 'init space inbox', (d) => { + d.meta = { module: 'inbox', collection: 'mailboxes', version: 2, spaceSlug: space, createdAt: now }; + d.mailbox = { + id: mbId, workspaceId: null, slug: space, name: `${space.charAt(0).toUpperCase() + space.slice(1)} Inbox`, + email: `${space}@rspace.online`, + description: `Team inbox for the ${space} space. Multi-sig approval can be configured via Gnosis Safe.`, + visibility: 'members', ownerDid, + safeAddress: null, safeChainId: null, approvalThreshold: 1, createdAt: now, + }; + d.members = []; + d.threads = {}; + d.approvals = {}; + d.personalInboxes = {}; + d.agentInboxes = {}; + }); + + _syncServer.setDoc(docId, doc); + console.log(`[Inbox] Team inbox provisioned for "${space}": ${space}@rspace.online`); +} + +/** + * Seed demo mailbox with sample threads (for demo/template spaces only). + */ function seedTemplateInbox(space: string) { if (!_syncServer) return; // Skip if space already has mailboxes @@ -1714,7 +1752,7 @@ export const inboxModule: RSpaceModule = { if (SMTP_USER) getSmtpTransport().catch(() => {}); }, async onSpaceCreate(ctx) { - seedTemplateInbox(ctx.spaceSlug); + initSpaceInbox(ctx.spaceSlug, ctx.ownerDID || 'did:unknown'); }, standaloneDomain: "rinbox.online", feeds: [ diff --git a/server/index.ts b/server/index.ts index ab9bd88..e62e28b 100644 --- a/server/index.ts +++ b/server/index.ts @@ -31,7 +31,7 @@ import { } from "./community-store"; import type { NestPermissions, SpaceRefFilter } from "./community-store"; import { ensureDemoCommunity } from "./seed-demo"; -import { seedTemplateShapes, ensureTemplateSeeding } from "./seed-template"; +import { seedTemplateShapes } from "./seed-template"; // Campaign demo moved to rsocials module — see modules/rsocials/campaign-data.ts import type { SpaceVisibility } from "./community-store"; import { @@ -3076,7 +3076,6 @@ ensureDemoCommunity().then(() => console.log("[Demo] Demo community ready")).cat import { initTokenService, seedCUSDC } from "./token-service"; loadAllDocs(syncServer) .then(async () => { - ensureTemplateSeeding(); // Seed all modules' demo data so /demo routes always have content for (const mod of getAllModules()) { if (mod.seedTemplate) { diff --git a/server/spaces.ts b/server/spaces.ts index d7e7301..a7bf471 100644 --- a/server/spaces.ts +++ b/server/spaces.ts @@ -67,7 +67,7 @@ import type { EncryptIDClaims } from "@encryptid/sdk/server"; import { getAllModules, getModule } from "../shared/module"; import type { SpaceLifecycleContext } from "../shared/module"; import { syncServer } from "./sync-instance"; -import { seedTemplateShapes } from "./seed-template"; + import { notify, notifySpaceAdmins } from "./notification-service"; const ENCRYPTID_URL = process.env.ENCRYPTID_INTERNAL_URL || "http://encryptid:3000"; @@ -169,23 +169,9 @@ export async function createSpace(opts: CreateSpaceOpts): Promise { nestPolicy: DEFAULT_USER_NEST_POLICY, }); - // Fire module hooks + // Fire module hooks with proper lifecycle context + const { syncServer } = await import('../../server/sync-instance'); + const lifecycleCtx = { + spaceSlug, + ownerDID: did, + enabledModules: DEFAULT_USER_MODULES, + syncServer, + }; for (const mod of getAllModules()) { if (mod.onSpaceCreate) { - try { await mod.onSpaceCreate(spaceSlug); } catch (e) { + try { await mod.onSpaceCreate(lifecycleCtx); } catch (e) { console.error(`[EncryptID] Module ${mod.id} onSpaceCreate for user space:`, e); } }