feat: customer contacts table, branded mail-from on root domain
Some checks failed
Build & Release / build (push) Has been cancelled
Some checks failed
Build & Release / build (push) Has been cancelled
- Add customer_contacts table for storing contacts per customer - Save initial user as primary contact during provisioning - Use "Store Name via LunarFront <noreply@lunarfront.tech>" as mail-from (root domain is verified with Resend, no per-customer DNS needed) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -40,6 +40,18 @@ export async function migrate() {
|
||||
`;
|
||||
await db`CREATE INDEX IF NOT EXISTS customer_size_snapshots_slug_date ON customer_size_snapshots (slug, recorded_at DESC)`;
|
||||
await db`ALTER TABLE users ADD COLUMN IF NOT EXISTS updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()`;
|
||||
await db`
|
||||
CREATE TABLE IF NOT EXISTS customer_contacts (
|
||||
id SERIAL PRIMARY KEY,
|
||||
slug TEXT NOT NULL REFERENCES customers(slug) ON DELETE CASCADE,
|
||||
email TEXT NOT NULL,
|
||||
first_name TEXT NOT NULL,
|
||||
last_name TEXT NOT NULL,
|
||||
is_primary BOOLEAN NOT NULL DEFAULT false,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
)
|
||||
`;
|
||||
await db`CREATE INDEX IF NOT EXISTS customer_contacts_slug ON customer_contacts (slug)`;
|
||||
await db`
|
||||
ALTER TABLE customers
|
||||
ADD COLUMN IF NOT EXISTS name TEXT NOT NULL DEFAULT '',
|
||||
|
||||
@@ -142,7 +142,7 @@ export async function customerRoutes(app: FastifyInstance) {
|
||||
"spaces-prefix": `${slug}/`,
|
||||
"encryption-key": encryptionKey,
|
||||
"resend-api-key": config.resendApiKey,
|
||||
"mail-from": `noreply@${slug}.lunarfront.tech`,
|
||||
"mail-from": `${body.name} via LunarFront <noreply@lunarfront.tech>`,
|
||||
"business-name": body.name,
|
||||
...(body.initialUser ? {
|
||||
"initial-user-email": body.initialUser.email,
|
||||
@@ -159,6 +159,14 @@ export async function customerRoutes(app: FastifyInstance) {
|
||||
await setStep("chart", "done");
|
||||
|
||||
await db`UPDATE customers SET status = 'provisioned', updated_at = NOW() WHERE slug = ${slug}`;
|
||||
|
||||
// Save initial user as primary contact
|
||||
if (body.initialUser) {
|
||||
await db`
|
||||
INSERT INTO customer_contacts (slug, email, first_name, last_name, is_primary)
|
||||
VALUES (${slug}, ${body.initialUser.email}, ${body.initialUser.firstName}, ${body.initialUser.lastName}, true)
|
||||
`;
|
||||
}
|
||||
} catch (err) {
|
||||
const failedStep = Object.entries(steps).find(([, v]) => v === "pending")?.[0];
|
||||
if (failedStep) await setStep(failedStep, "failed");
|
||||
|
||||
Reference in New Issue
Block a user