Skip to content

Implement per-organization SMTP configuration and sign-up flow#12

Merged
simpros merged 18 commits intomainfrom
feat/multi-org
Mar 17, 2026
Merged

Implement per-organization SMTP configuration and sign-up flow#12
simpros merged 18 commits intomainfrom
feat/multi-org

Conversation

@simpros
Copy link
Owner

@simpros simpros commented Mar 14, 2026

Fixed also #10

simpros and others added 18 commits March 14, 2026 17:55
Add a dedicated table for per-organisation SMTP credentials so each org
can send lead emails through its own mail server.

- New organization_smtp_config schema with unique constraint on org id
- RLS policy using the existing createOrganizationPolicy helper
- ID prefix 'osc' and exported id schema
- Relations: organization has many organizationSmtpConfig
- Auto-generated Drizzle migration

Generated with Devin (https://cli.devin.ai/docs)

Co-Authored-By: Devin <noreply@cognition.ai>
Allow org admins to configure SMTP credentials per organisation. The
password is encrypted at rest using AES-256-GCM with a key derived
from BETTER_AUTH_SECRET via HKDF — no additional env var needed.

- AES-256-GCM encrypt/decrypt utility (key derived from BETTER_AUTH_SECRET)
- Valibot schema for SMTP config validation
- Remote functions: getSmtpConfig, saveSmtpConfig, testSmtpConnection
- SMTP form in organisation settings with save and test-connection buttons

Generated with Devin (https://cli.devin.ai/docs)

Co-Authored-By: Devin <noreply@cognition.ai>
Emails to leads must use the SMTP server configured by the organisation,
not the instance-level SMTP from environment variables.

- Add sendOrgEmail() that looks up org SMTP config, decrypts the
  password, and sends through the org's mail server
- Replace all sendEmail() calls in initiatives.remote.ts with
  sendOrgEmail(organizationId, ...) for test emails, bulk sends,
  and retries
- Auth emails (verification, invitations) remain on instance SMTP

Generated with Devin (https://cli.devin.ai/docs)

Co-Authored-By: Devin <noreply@cognition.ai>
Sign-up is off by default (ALLOW_SIGN_UP=false). When enabled, users
can self-register and create their own organisation in a single flow.
The server refuses to start with sign-up enabled unless OTel tracing
is configured.

- Sign-up page collecting user details + org name/slug
- signUpSchema with org fields in auth.ts
- Server guard: redirects to login when sign-up is disabled
- signUpGuardHandle skips invitation check when ALLOW_SIGN_UP=true
- Startup validation: ALLOW_SIGN_UP=true requires DYNATRACE_OTLP_ENDPOINT,
  DYNATRACE_API_TOKEN, and LEADER_TELEMETRY != false
- Root layout.server.ts exposes allowSignUp to all pages
- Conditional 'Create an account' link on login page
- Fix test mocks to include allowSignUp in page data

Generated with Devin (https://cli.devin.ai/docs)

Co-Authored-By: Devin <noreply@cognition.ai>
Users with multiple org memberships can now switch between them from
the app header. The layout data includes the full org list.

- OrgSwitcher dropdown component (hidden for single-org users)
- Layout server returns user's organisations list
- App header shows org name next to logo, with dropdown when multi-org
- Document ALLOW_SIGN_UP and SMTP_ENCRYPTION_KEY in environment.md

Generated with Devin (https://cli.devin.ai/docs)

Co-Authored-By: Devin <noreply@cognition.ai>
…tation

- Introduced a new skill for best practices in Svelte development, including guidance on reactivity, event handling, and styling.
- Updated skills-lock.json to include the new skill.
- Created SKILL.md with detailed instructions and examples for using Svelte features effectively.
- Added references for $inspect, @Attach, and await expressions to enhance developer understanding.
- Included examples for function bindings, keyed each blocks, and hydratable content to improve usability.
- Implemented `organizationSmtpConfigSchema` with validation rules for SMTP settings.
- Added unit tests for the new schema to ensure proper validation of SMTP configuration inputs.
- Updated forms in lead project creation and existing forms to use `placeId` for unique identification.
- Refactored organization settings to use raw state for members and invitations.
- Created a second organization in the test seed for multi-org testing.
- Added end-to-end tests for organization switcher functionality and sign-up process.
- Introduced new utility functions for encrypting and decrypting SMTP passwords.
- Added tests for email sending functionality using organization SMTP settings.
- Updated UI components to follow lower-kebab-case naming conventions.
On case-insensitive macOS, git was tracking both PascalCase and
lower-kebab-case versions of UI component files. Remove the uppercase
duplicates so only the lowercase names are tracked, preventing issues
on case-sensitive systems (Linux/CI).

Files cleaned: Badge, Breadcrumbs, Button, Card, Input (.svelte/.test.ts)
and field/ subcomponents (Description, Error, Field, Group, Label).

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <noreply@cognition.ai>
@simpros simpros merged commit 8094249 into main Mar 17, 2026
4 checks passed
@simpros simpros deleted the feat/multi-org branch March 17, 2026 10:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant