Merge branch 'dev'

This commit is contained in:
Jeff Emmett 2026-03-21 13:59:44 -07:00
commit 55cd1743c2
4 changed files with 53 additions and 23 deletions

View File

@ -1630,6 +1630,44 @@ routes.get("/", (c) => {
// ── Seed template data ── // ── 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<MailboxDoc>(), '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) { function seedTemplateInbox(space: string) {
if (!_syncServer) return; if (!_syncServer) return;
// Skip if space already has mailboxes // Skip if space already has mailboxes
@ -1714,7 +1752,7 @@ export const inboxModule: RSpaceModule = {
if (SMTP_USER) getSmtpTransport().catch(() => {}); if (SMTP_USER) getSmtpTransport().catch(() => {});
}, },
async onSpaceCreate(ctx) { async onSpaceCreate(ctx) {
seedTemplateInbox(ctx.spaceSlug); initSpaceInbox(ctx.spaceSlug, ctx.ownerDID || 'did:unknown');
}, },
standaloneDomain: "rinbox.online", standaloneDomain: "rinbox.online",
feeds: [ feeds: [

View File

@ -31,7 +31,7 @@ import {
} from "./community-store"; } from "./community-store";
import type { NestPermissions, SpaceRefFilter } from "./community-store"; import type { NestPermissions, SpaceRefFilter } from "./community-store";
import { ensureDemoCommunity } from "./seed-demo"; 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 // Campaign demo moved to rsocials module — see modules/rsocials/campaign-data.ts
import type { SpaceVisibility } from "./community-store"; import type { SpaceVisibility } from "./community-store";
import { import {
@ -3076,7 +3076,6 @@ ensureDemoCommunity().then(() => console.log("[Demo] Demo community ready")).cat
import { initTokenService, seedCUSDC } from "./token-service"; import { initTokenService, seedCUSDC } from "./token-service";
loadAllDocs(syncServer) loadAllDocs(syncServer)
.then(async () => { .then(async () => {
ensureTemplateSeeding();
// Seed all modules' demo data so /demo routes always have content // Seed all modules' demo data so /demo routes always have content
for (const mod of getAllModules()) { for (const mod of getAllModules()) {
if (mod.seedTemplate) { if (mod.seedTemplate) {

View File

@ -67,7 +67,7 @@ import type { EncryptIDClaims } from "@encryptid/sdk/server";
import { getAllModules, getModule } from "../shared/module"; import { getAllModules, getModule } from "../shared/module";
import type { SpaceLifecycleContext } from "../shared/module"; import type { SpaceLifecycleContext } from "../shared/module";
import { syncServer } from "./sync-instance"; import { syncServer } from "./sync-instance";
import { seedTemplateShapes } from "./seed-template";
import { notify, notifySpaceAdmins } from "./notification-service"; import { notify, notifySpaceAdmins } from "./notification-service";
const ENCRYPTID_URL = process.env.ENCRYPTID_INTERNAL_URL || "http://encryptid:3000"; const ENCRYPTID_URL = process.env.ENCRYPTID_INTERNAL_URL || "http://encryptid:3000";
@ -169,23 +169,9 @@ export async function createSpace(opts: CreateSpaceOpts): Promise<CreateSpaceRes
} }
} }
// Seed generic template content (non-fatal) // NOTE: New spaces start with a blank canvas.
try { // Template shapes and module demo data are NOT seeded here.
seedTemplateShapes(slug); // The rinbox onSpaceCreate hook provisions a {slug}@rspace.online mailbox.
} catch (e) {
console.error(`[createSpace:${source}] Template seeding failed for ${slug}:`, e);
}
// Seed module-specific demo data (calendar events, sample tasks, etc.)
for (const mod of getAllModules()) {
if (mod.seedTemplate) {
try {
mod.seedTemplate(slug);
} catch (e) {
console.error(`[createSpace:${source}] Module ${mod.id} seedTemplate failed for ${slug}:`, e);
}
}
}
console.log(`[createSpace:${source}] Created space: ${slug}`); console.log(`[createSpace:${source}] Created space: ${slug}`);
return { ok: true, slug, name, visibility, ownerDID }; return { ok: true, slug, name, visibility, ownerDID };

View File

@ -637,10 +637,17 @@ app.post('/api/register/complete', async (c) => {
nestPolicy: DEFAULT_USER_NEST_POLICY, 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()) { for (const mod of getAllModules()) {
if (mod.onSpaceCreate) { 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); console.error(`[EncryptID] Module ${mod.id} onSpaceCreate for user space:`, e);
} }
} }