Releases & Changelog
Releases
This section documents every version of the SONAN DIGITAL CRM, from the foundation alpha through the current production release. It includes full release notes, known issues, changelogs, and the production release checklist.
Current Release
v1.0.0 โ Released 2026-06-30 โ Initial production release of the SONAN DIGITAL CRM platform.
View v1.0.0 Release Notes View Known Issues View Release Checklist
Version History
| Version | Release Date | Type | Summary |
|---|---|---|---|
| v1.0.0 | 2026-06-30 | Major | Initial production release. Full multi-tenant CRM platform including client portal, Stripe payments, e-signatures, notifications, reports, and in-app Wiki. |
| v0.9.0 | 2026-05-15 | Beta | Feature complete. Full client portal implementation, Stripe Checkout, MFA enforcement across all roles. Pre-UAT candidate. |
| v0.8.0 | 2026-04-01 | Beta | Core commercial modules complete. Proposals, Contracts, Invoices, Support Tickets. |
| v0.7.0 | 2026-02-15 | Alpha | Platform foundation. Authentication, tenant system, Leads, Clients, Projects, Tasks, Time Logs. |
Release Documents
| Document | Description |
|---|---|
| v1.0 Release Notes | Complete feature list, security fixes, and upgrade notes for v1.0.0 |
| v1.0 Known Issues | Accepted risks and deferred issues in the v1.0.0 release |
| v1.0 Release Checklist | Pre-release and go-live verification checklist |
| Changelog | Full inline changelog from v0.7.0 to v1.0.0 |
| Release History | Complete release history table with semantic versioning policy |
Semantic Versioning
This project follows Semantic Versioning 2.0.0:
- Major version (X.0.0) โ Significant platform milestone, new module suite, or breaking change to integrations.
- Minor version (X.Y.0) โ New features added in a backward-compatible manner.
- Patch version (X.Y.Z) โ Backward-compatible bug fixes, security patches, or minor improvements.
See Release History for the full versioning policy as applied to this project.
v1.0.0 Release Notes
Release Date: 2026-06-30 Type: Major โ Initial Production Release Commit: (set at deployment) Deployed to: Vercel (production) Database: Supabase (production project)
Overview
v1.0.0 is the first full production release of the SONAN DIGITAL CRM platform. This release delivers a complete multi-tenant agency CRM covering the entire client lifecycle: lead capture โ client onboarding โ proposals and contracts โ invoicing and payment โ project delivery โ support.
The platform runs on Next.js 15 App Router with edge runtime, backed by Supabase (PostgreSQL + Auth + RLS + Storage), deployed on Vercel, with email via Resend and payments via Stripe.
What's New in v1.0.0
This is the initial release. All features listed below are new.
Platform & Infrastructure
- Multi-tenant architecture โ Full tenant isolation at the database level via Supabase Row-Level Security (RLS). Every table is scoped by
tenant_id. Tenants cannot access each other's data. - Edge Runtime โ All API routes and pages use
export const runtime = 'edge'for Vercel edge network deployment. Cold start times are minimized. - TOTP Multi-Factor Authentication โ All user roles (Admin, Employee, Client) must enroll in TOTP MFA using an authenticator app. MFA is enforced at login.
- Role-Based Access Control โ Three distinct roles with isolated portals:
- Admin โ full CRM access, all modules
- Employee โ task management, time logging, ticket handling, limited client visibility
- Client โ self-service portal (proposals, contracts, invoices, documents, support)
Lead Management
- Lead record creation with name, email, phone, source, and status fields
- Pipeline status tracking:
NewโContactedโQualifiedโProposal SentโConverted/Lost - One-click lead-to-client conversion
- In-app
new_leadnotification broadcast to all admins on new lead creation - Email notification to admin team on new lead (via Resend)
Client Management
- Full client record with company name, website, industry, and notes
- Contact management: multiple contacts per client, primary contact designation, per-contact email/phone/title
- Assigned manager field (
assigned_manager_id) for routing and reporting - Client portal access provisioning: admin invites client via email, client self-activates account with MFA
- Client status tracking (Active / Inactive / Archived)
Proposal Builder
- Line-item proposal creation: description, quantity, unit price, calculated subtotal
- Subtotal stored as
subtotal_centsin the database (integer cents, never floats) - Proposal statuses:
DraftโSentโApproved/Declined - Email delivery to client on proposal send (Resend)
- Client portal e-approval: client reviews and clicks Approve or Decline
proposal_approvedandproposal_declinedin-app notifications to admin- One-click conversion from approved proposal to invoice (line items and amount pre-populated)
- Optional notes and validity date fields
Contract Management
- Contract creation with rich-text body (HTML content)
- E-signature workflow: admin sends for signature โ client reviews and signs via portal
- Contract statuses:
DraftโPending SignatureโSigned/Declined contract_signedandcontract_declinednotifications to admin- Signed timestamp recorded on the contract record
- Client portal contract list showing all contracts and their current status
Invoice Management
- Invoice creation with line items, due date, and optional notes
- Invoice statuses:
DraftโSentโPaid/Overdue/Cancelled - Stripe Checkout integration: Pay Now button generates a Stripe Checkout session; client is redirected to hosted Stripe payment page
- Stripe webhook handler:
checkout.session.completedevent auto-marks invoice asPaidand records payment date invoice_paidin-app notification to admin on successful payment- Email delivery to client on invoice send (Resend)
Recurring Invoices
- Recurring invoice configuration: frequency (weekly, monthly, quarterly, annual), start date, end date (optional)
- Automated generation via Vercel Cron job (runs daily, protected by
CRON_SECRET) - Generated invoices inherit line items and amounts from the recurring invoice template
- Admin notification when a recurring invoice is generated
Overdue Invoice Detection
- Daily cron job scans all
Sentinvoices with a past due date - Invoices past due date are automatically updated to
Overduestatus - Admin notification generated for each newly-overdue invoice
Project Management
- Project records linked to clients
- Project status:
Active/On Hold/Completed - Task creation within projects: title, description, assigned employee, due date, status
- Task status pipeline:
To DoโIn ProgressโReviewโDone - Employee portal task list scoped to the logged-in employee
Time Logging
- Employees log time against specific tasks
- Fields: task, hours, logged date, optional note
- Time logs visible to admin in the Time Logs report
- Employee portal shows personal time log history
Support Ticket System
- Clients submit support tickets from the client portal: subject, message, priority
- Ticket statuses:
OpenโIn ProgressโClosed - Thread-based reply system: employee/admin appends replies to the ticket thread
support_replynotification delivered to client on each reply (in-app + email)- Admin/employee can close tickets; closed tickets visible to client as read-only
Document Sharing
- Admins upload files for specific clients (stored in Supabase Storage)
- Signed URLs with 1-hour expiry delivered to clients on document download request
- Client portal document list: view all documents shared by admin, download on demand
- Document metadata: name, upload date, file size, file type
Deployment Artifact Tracking
- Per-project deployment records: version, environment, deployment date, notes
- Admin creates and tracks deployment events for each client project
- Useful for audit trails and release coordination
Client Cost Ledger
- Internal cost tracking per client: cost entries with description, amount, date, category
- Separate from invoices โ this is the internal cost of delivery, not what the client pays
- Admin-only view; not exposed in client portal
- Supports profitability analysis per client
Reports
- Revenue Report: aggregates paid invoice amounts by date range; filterable by client or all clients; CSV export
- Time Log Report: aggregates hours by employee; filterable by employee, project, and date range
In-App Wiki
- Contextual help articles authored by admin
- Articles organized by category with icons and sort order
- Published/unpublished toggle for draft management
- Accessible via a help icon in the navigation; searchable
- Content stored as
content_html; rendered safely in the portal
Notification System
- In-app notification bell in the admin and employee navigation header
- Unread count badge on the bell icon
- Notification types:
new_lead,invoice_paid,contract_signed,contract_declined,proposal_approved,proposal_declined,support_reply - Broadcast notifications (
user_id = NULL) sent to all admins in the tenant - Targeted notifications sent to a specific user (
user_idset) - Mark-as-read on click; mark-all-read action
- Email counterpart for select notification types (via Resend)
Employee Portal
- Dedicated portal for employees (separate from admin)
- Visible modules: My Tasks, Time Logs, Projects (read-only), Support Tickets (reply access)
- Scoped to the employee's assigned records โ employees see only their own tasks and time logs
Client Portal
- Self-service portal accessible via invitation
- Visible modules: Dashboard, Proposals, Contracts, Invoices, Documents, Support
- Dashboard shows outstanding proposals, unpaid invoices, and open support tickets at a glance
- All interactions (approvals, signing, payments, ticket submission) performed within the portal
Security Fixes
The following security issues were identified during pre-release review and are fixed in v1.0.0:
CRIT-4 โ Tenant Isolation Enforcement on Admin API Routes
Issue: Several admin API route handlers were not calling requireAdminWithTenant() before accessing Supabase. A malicious authenticated user could construct requests to access or modify records belonging to a different tenant by manipulating request parameters.
Fix: All admin API routes now begin with:
const caller = await requireAdminWithTenant()
if (!caller) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
The caller.tenantId is used for all Supabase queries, making it impossible to access cross-tenant data regardless of request parameters.
Verified in UAT: TC security check for CRIT-4.
CRIT-7 โ RLS Policy Gaps on Documents and Contracts Tables
Issue: Supabase Row-Level Security policies on the documents and contracts tables were missing a tenant_id equality check in the USING clause. This allowed a service-role query (or a misconfigured client-side query) to return records across tenants.
Fix: RLS policies updated to include tenant_id = auth.jwt() ->> 'tenant_id' in all SELECT, INSERT, UPDATE, and DELETE policies on both tables. Migration applied to production.
Verified in UAT: TC security check for CRIT-7.
H8 โ Client Portal Access Token Validation Strengthened
Issue: The client portal session validation was checking only that a valid Supabase session existed, but was not verifying that the session's user_id belonged to the correct tenant and had the client role. A valid session from a different role or tenant could access the client portal.
Fix: Client portal middleware now explicitly checks:
1. Session is valid and not expired
2. User has role client in the users table
3. User's tenant_id matches the portal's expected tenant context
Verified in UAT: TC security check for H8.
Known Issues
The following issues are accepted for v1.0.0 and are documented in Known Issues. They do not block go-live but are scheduled for v1.1 or v1.2.
See Known Issues for full details, workarounds, and target fix versions.
| ID | Severity | Module | Summary | Target |
|---|---|---|---|---|
| HIGH-1 | High | API / Security | No custom rate limiting on API routes | v1.1 |
| HIGH-2 | High | Invoices / Contracts | PDF generation not implemented (browser print workaround) | v1.1 |
| HIGH-3 | High | Admin | No audit log for admin actions | v1.2 |
| HIGH-4 | High | Silent email delivery failures, no retry queue | v1.1 | |
| HIGH-5 | High | Recurring Invoices | Recurring invoice generation does not email client | v1.1 |
| HIGH-6 | High | Documents | Signed download URLs expire in 1 hour | v1.1 |
| HIGH-7 | High | Auth / MFA | No TOTP recovery codes โ lost device requires admin reset | v1.1 |
Upgrade Notes
v1.0.0 is the first production release. There is no prior production version to upgrade from. No migration path is required.
For initial deployment steps, see the Release Checklist.
v1.0.0 Known Issues
The issues on this page are accepted risks for the v1.0.0 production release. They were reviewed by the Technical Lead and Business Owner during UAT sign-off and determined not to block go-live. Each issue has a documented workaround and a target fix version. They must be addressed before v1.1 or v1.2 as indicated.
Issue Index
| ID | Severity | Module | Summary | Target Fix |
|---|---|---|---|---|
| HIGH-1 | High | API / Security | No custom rate limiting on API routes | v1.1 |
| HIGH-2 | High | Invoices / Contracts | PDF generation not implemented | v1.1 |
| HIGH-3 | High | Admin / Compliance | No audit log for admin actions | v1.2 |
| HIGH-4 | High | Email / Resend | Silent email delivery failures with no retry queue | v1.1 |
| HIGH-5 | High | Recurring Invoices | Recurring invoice generation does not email the client | v1.1 |
| HIGH-6 | High | Documents / Storage | Signed download URLs expire after 1 hour | v1.1 |
| HIGH-7 | High | Auth / MFA | No TOTP recovery codes โ lost device requires admin reset | v1.1 |
HIGH-1
Severity: High Module: API / Security Status: Accepted โ target fix v1.1
Description
No custom rate limiting has been implemented on the CRM API routes. Under normal operating conditions this presents no problem, but the absence of rate limiting creates a theoretical surface for brute-force attacks against the authentication endpoints and credential-stuffing against the login page.
Risk Assessment
The risk is partially mitigated by Supabase Auth's built-in rate limiting on the /auth/v1/token endpoint (default: 10 requests per hour per IP for password grants, configurable in the Supabase dashboard). However, application-level API routes (/api/**) do not have rate limiting and could be targeted.
For v1.0.0, the application operates in a controlled-access environment with a small number of known users. The likelihood of active brute-force targeting is low.
Workaround
- Supabase Auth built-in rate limiting is active and covers login attempts.
- Vercel's edge network provides DDoS protection at the infrastructure layer.
- Monitor Sentry and Vercel function invocation logs for anomalous traffic patterns post-launch.
Target Fix: v1.1
Implement rate limiting using an edge-compatible solution (e.g., Upstash Redis + @upstash/ratelimit) on critical API routes, particularly /api/auth/** and any unauthenticated endpoints.
HIGH-2
Severity: High Module: Invoices / Contracts / Proposals Status: Accepted โ target fix v1.1
Description
PDF generation for invoices, contracts, and proposals has not been implemented. When a user clicks a download or print action, the raw HTML view is presented rather than a properly formatted PDF document. Sending professional-looking PDF invoices or contracts to clients via email is not possible in v1.0.0.
Risk Assessment
This is a significant UX gap for a professional services CRM. Clients expect to receive PDF invoices and be able to sign or file them. The workaround is sufficient for v1.0 given the controlled client base, but must be prioritized for v1.1.
Workaround
Admins can print invoices and contracts to PDF directly from the browser:
- Open the invoice or contract detail page in Chrome or Firefox.
- Press
Cmd+P(Mac) orCtrl+P(Windows) to open the print dialog. - Change the destination to "Save as PDF".
- Click Save and download the PDF.
- Send the PDF to the client manually via email.
This workaround is functional but adds manual steps to the admin workflow.
Target Fix: v1.1
Integrate a server-side PDF generation library compatible with the edge runtime (e.g., Puppeteer via a dedicated Node.js serverless function, or a third-party PDF API such as PDFShift or Gotenberg). Generate PDFs on demand and store in Supabase Storage for download.
HIGH-3
Severity: High Module: Admin / Compliance Status: Accepted โ target fix v1.2
Description
No audit log records admin actions. When an admin modifies a client record, changes an invoice status, deletes a document, or any other write action, no record is kept of who performed the action and when. This makes it impossible to answer "who changed this and when?" after the fact.
Risk Assessment
For a client-facing CRM managing financial data, audit logging is a compliance and accountability requirement. However, because v1.0.0 operates with a small team of trusted admins in a controlled environment, the immediate risk is low. This is a v1.2 priority, not v1.1, because it requires a more significant architectural addition (trigger-based audit tables or application-level middleware).
Workaround
- Supabase's built-in PostgreSQL logs capture low-level database writes and are accessible via the Supabase dashboard under Database โ Logs.
- All Vercel function invocations are logged and include the caller's user ID for authenticated routes (via the
requireAdminWithTenant()pattern which logs theuserId). - In the event of a disputed change, the Technical Lead can cross-reference Supabase DB logs with Vercel function invocation logs to reconstruct the timeline.
Target Fix: v1.2
Implement an audit_log table with tenant_id, user_id, action, resource_type, resource_id, old_value (JSONB), new_value (JSONB), and created_at. Populate via Supabase database triggers on key tables or via application-level logging middleware.
HIGH-4
Severity: High Module: Email / Resend Status: Accepted โ target fix v1.1
Description
Email delivery failures from Resend are silent. When a transactional email fails to send (e.g., due to a Resend API error, invalid email address, or temporary outage), the failure is logged in Vercel function logs but there is no retry mechanism, no in-app alert to the admin, and no visibility from the CRM interface into whether an email was delivered.
In practical terms: if an invoice email or proposal email fails to send, the admin has no indication that the client did not receive it, and there is no automatic retry.
Workaround
- Admins should verify critical emails (proposals, invoices, contracts) were received by checking with the client directly or checking the Resend dashboard (https://resend.com โ Emails) after sending.
- The Resend dashboard shows delivery status for all outbound emails. Failed deliveries appear with an error reason.
- If an email failed, admins can resend manually by using the Send action again in the CRM (this creates a new send attempt, not a retry of the failed one).
Target Fix: v1.1
Implement a lightweight email queue or use Resend's webhook callbacks (email.bounced, email.failed) to capture delivery failures and surface them to the admin as in-app notifications or alerts on the relevant record.
HIGH-5
Severity: High Module: Recurring Invoices Status: Accepted โ target fix v1.1
Description
When the daily cron job automatically generates a recurring invoice, no notification email is sent to the client. The invoice is created with status Draft or Sent (depending on configuration), but the client receives no notification that a new invoice is available in their portal.
Admins receive an in-app notification that a recurring invoice was generated, but must manually trigger the email delivery to the client.
Workaround
After a recurring invoice is generated (visible in the admin Invoices list with a "Recurring" tag):
- Open the generated invoice.
- Review line items and amounts.
- Click Send Invoice to trigger the email delivery to the client.
This manual step should be done within 1 business day of the invoice generation date.
Target Fix: v1.1
Update the recurring invoice generation cron job to automatically mark the generated invoice as Sent and trigger the Resend email delivery in the same cron execution.
HIGH-6
Severity: High Module: Documents / Supabase Storage Status: Accepted โ target fix v1.1
Description
Document download URLs are generated as Supabase Storage signed URLs with a 1-hour expiry. If a client opens the Documents page and does not click the download link within 60 minutes, the link will have expired and the download will fail with a 403 or 400 error from Supabase Storage.
This is particularly problematic for clients who open the portal, get distracted, and return later to download โ they will see an error with no clear explanation.
Workaround
- If a download fails, instruct the client to refresh the Documents page. A fresh signed URL is generated on each page load.
- Document page refresh resolves the issue immediately in all tested cases.
Target Fix: v1.1
Generate signed URLs on demand (on each download click via an API route) rather than embedding them in the page HTML at render time. This ensures the URL is always fresh at the moment of the download request, regardless of how long the client has had the page open. Alternatively, increase the signed URL expiry to 24 hours.
HIGH-7
Severity: High Module: Auth / MFA Status: Accepted โ target fix v1.1
Description
TOTP multi-factor authentication does not generate recovery codes at enrollment time. If a user loses access to their authenticator app (phone lost, app deleted, new device without backup), they have no recovery codes to bypass MFA.
The only recovery path is for an admin to disable the user's MFA via the Supabase Auth dashboard and issue a new invitation, which forces the user to re-enroll. This is a manual process that requires admin intervention and causes downtime for the affected user.
This issue affects all roles: Admin, Employee, and Client.
Workaround
For affected users (Admin or Employee):
- User contacts the Technical Lead or Admin.
- Admin logs into the Supabase dashboard โ Authentication โ Users.
- Locate the affected user account.
- Disable or remove the MFA factor from the user's record.
- User logs in with email/password only.
- User is prompted to re-enroll MFA.
- User scans new QR code and completes enrollment.
For affected Client users:
- Client contacts their admin contact.
- Admin deactivates the client's portal account in the CRM.
- Admin re-invites the client via the portal invite flow.
- Client re-activates their account and re-enrolls MFA.
Prevention:
Advise all users at enrollment time to back up their TOTP secret key (most authenticator apps โ Authy, 1Password โ offer cloud backup). Store the seed key in a secure password manager.
Target Fix: v1.1
Generate and display one-time recovery codes at MFA enrollment time. Store hashed recovery codes in the database (mfa_recovery_codes table or in the Supabase Auth user metadata). Allow users to consume a recovery code once to bypass TOTP if their device is unavailable.
v1.0.0 Release Checklist
This checklist must be completed in full before the v1.0.0 production deployment is initiated. Each item must be verified by the Technical Lead.
Complete this checklist in order. Do not begin go-live steps until all pre-release items are confirmed. Do not deploy to production before receiving UAT sign-off.
Pre-Release Verification
Quality & Testing
-
[ ] All UAT test cases executed and passed โ All Phase 1โ5 test cases in UAT Execution Guide show PASS status in the test record.
-
[ ] UAT sign-off received from Technical Lead โ Signed UAT sign-off form from Technical Lead is on file (see UAT Sign-Off).
-
[ ] UAT sign-off received from Business Owner โ Signed UAT sign-off form from Business Owner is on file.
-
[ ] All Critical (P1) defects resolved โ Defect log shows zero open Critical defects. All resolved Critical defects have been retested and confirmed fixed.
-
[ ] All High (P2) defects resolved or formally accepted โ Each open High defect in the defect log has either been resolved+retested, or formally accepted as a known issue with documented rationale (see Known Issues).
-
[ ] Staging environment stable for 48 hours pre-release โ No Sentry errors, no function failures, no database errors in the 48 hours prior to release. Verify in Vercel logs and Sentry dashboard.
Environment & Configuration
- [ ] All environment variables set in Vercel production environment โ Verify in Vercel Dashboard โ Project โ Settings โ Environment Variables. Required variables:
| Variable | Notes |
|---|---|
NEXT_PUBLIC_SUPABASE_URL |
Production Supabase project URL |
NEXT_PUBLIC_SUPABASE_ANON_KEY |
Production Supabase anon key |
SUPABASE_SERVICE_ROLE_KEY |
Production Supabase service role key โ mark as Secret |
RESEND_API_KEY |
Production Resend API key |
STRIPE_SECRET_KEY |
Production Stripe secret key (must start with sk_live_) |
STRIPE_WEBHOOK_SECRET |
Production Stripe webhook signing secret |
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY |
Production Stripe publishable key (must start with pk_live_) |
CRON_SECRET |
Secret token protecting cron job endpoints |
NEXT_PUBLIC_SENTRY_DSN |
Sentry DSN for production error tracking |
SENTRY_AUTH_TOKEN |
Sentry auth token with org:ci scope for source map uploads |
Confirm STRIPE_SECRET_KEY starts with sk_live_ in production. A sk_test_ key in production means payments will appear to succeed in Stripe test mode but no real money will be charged.
- [ ] Stripe webhook registered for production domain โ In the Stripe Dashboard โ Developers โ Webhooks:
- Endpoint URL:
https://[production-domain]/api/webhooks/stripe - Events:
checkout.session.completed -
Copy the signing secret into
STRIPE_WEBHOOK_SECRETin Vercel production env vars. -
[ ] Resend domain DNS verified for production domain โ In the Resend dashboard, confirm the production domain's DNS records (MX, SPF, DKIM, DMARC) are verified. Emails sent from an unverified domain will be rejected or land in spam.
-
[ ] Cron jobs configured in vercel.json โ Confirm
vercel.jsoncontains cron job definitions for: - Recurring invoice generation (daily)
- Overdue invoice detection (daily)
Both cron routes must validate the
CRON_SECRETheader before executing.
json
{
"crons": [
{
"path": "/api/admin/invoices/recurring/generate",
"schedule": "0 9 * * *"
},
{
"path": "/api/admin/invoices/overdue",
"schedule": "0 10 * * *"
}
]
}
Database
-
[ ] All database migrations applied to production Supabase project โ Run any pending migrations via Supabase CLI or SQL editor:
bash supabase db push --linkedVerify no errors. Confirm all tables exist in the production database schema. -
[ ] RLS policies active on all tables โ In Supabase Dashboard โ Database โ Tables, confirm "Row Level Security" is enabled on every tenant-scoped table. Specifically verify:
documentsโ RLS enabled,tenant_idcheck in all policies (CRIT-7 fix)contractsโ RLS enabled,tenant_idcheck in all policies (CRIT-7 fix)notificationsโ RLS enabled-
clients,leads,proposals,invoices,projects,tasksโ RLS enabled -
[ ] Supabase Auth redirect URLs updated to production domain โ In Supabase Dashboard โ Authentication โ URL Configuration:
- Site URL:
https://[production-domain] - Redirect URLs (allowed list):
https://[production-domain]/auth/callback,https://[production-domain]/portal/auth/callback - Remove any staging or localhost URLs from the allowed list.
Go-Live Steps
Execute these steps on release day, in order:
-
[ ] Deploy to production โ Push the release commit to the production Vercel deployment:
bash git push origin <release-sha>:refs/heads/mainOr promote the staging preview deployment to production in the Vercel dashboard. -
[ ] Verify production homepage loads โ Open
https://[production-domain]in a fresh private browser window. Confirm the page loads without errors. Check browser console for any JavaScript errors. -
[ ] Verify admin login in production โ Log in with a dedicated production admin account (not the UAT test account โ create a real admin account for the production tenant). Confirm MFA prompt appears. Confirm dashboard loads after MFA.
Create a separate admin@[yourdomain].com production admin account before go-live. Do not use UAT credentials on production. UAT credentials use @sonandigital.test addresses which are not real email accounts.
-
[ ] Verify Stripe webhook receives a test event โ In the Stripe Dashboard โ Webhooks โ select the production webhook endpoint โ click Send test webhook โ select
checkout.session.completedโ Send. Confirm the webhook delivers with status 200 in the Stripe dashboard attempt log. -
[ ] Monitor Sentry for 30 minutes post-deployment โ Open the Sentry dashboard for the production project. Watch for any new error events in the first 30 minutes after deployment. Investigate and fix any Critical errors before notifying stakeholders.
-
[ ] Notify stakeholders of successful go-live โ Once all go-live checks pass, send go-live notification to:
- Business Owner
- Any clients who were waiting for portal access
- Internal team members
Post-Release โ First 24 Hours
The following checks should be performed in the 24 hours after go-live:
- [ ] Confirm the first cron job execution succeeds (check Vercel Cron logs the following day).
- [ ] Confirm at least one test notification is delivered correctly (create a test lead and verify the in-app notification appears).
- [ ] Confirm Resend email delivery is working (invite a test user and verify the invitation email is received).
- [ ] Review Sentry for any new errors that appeared post-launch.
- [ ] Confirm Supabase database connection pool is healthy (Supabase Dashboard โ Database โ Reports).
Rollback Plan
If a Critical issue is found within 2 hours of go-live:
- Revert Vercel deployment to the previous build: Vercel Dashboard โ Deployments โ select the prior deployment โ Promote to Production.
- Notify stakeholders of the rollback and expected resolution timeline.
- Fix the issue in staging, re-run affected UAT test cases, and re-deploy when resolved.
- Database rollback: if a migration is involved, run the rollback SQL script prepared by the Technical Lead before the migration was applied.
Changelog
All notable changes to the SONAN DIGITAL CRM are documented here. The format follows Keep a Changelog conventions. Versions follow Semantic Versioning.
Entries are listed in reverse chronological order (newest first).
[1.0.0] โ 2026-06-30
The first full production release of the SONAN DIGITAL CRM platform. This release delivers a complete multi-tenant agency CRM ready for live client use.
Added
Platform & Infrastructure
- Multi-tenant architecture with full RLS-based tenant isolation (every table scoped by tenant_id)
- Edge runtime deployment on Vercel (export const runtime = 'edge' on all routes)
- TOTP multi-factor authentication for all user roles (Admin, Employee, Client)
- Role-based access control with three isolated portals: Admin, Employee, Client
Lead Management
- Lead record creation with name, email, phone, source, and pipeline status
- Status pipeline: New โ Contacted โ Qualified โ Proposal Sent โ Converted / Lost
- One-click lead-to-client conversion
- new_lead in-app notification broadcast to all admins on new lead
Client Management - Client records with company name, website, industry, assigned manager, and notes - Multi-contact management per client with primary contact designation - Client portal access provisioning via email invitation - Client status tracking (Active / Inactive / Archived)
Proposal Builder
- Line-item proposals with description, quantity, unit price, and calculated subtotal
- Subtotal stored as integer cents (subtotal_cents) to avoid floating-point errors
- Full proposal status workflow: Draft โ Sent โ Approved / Declined
- Email delivery on send via Resend
- Client portal e-approval (Approve or Decline actions)
- proposal_approved and proposal_declined admin notifications
- One-click conversion from approved proposal to invoice
Contract Management
- Contract creation with HTML rich-text body
- E-signature workflow: Draft โ Pending Signature โ Signed / Declined
- contract_signed and contract_declined admin notifications
- Signed timestamp recorded on contract record
Invoice Management
- Invoice creation with line items, due date, and notes
- Stripe Checkout integration for client payment (hosted payment page)
- Stripe webhook handler: checkout.session.completed auto-marks invoice as Paid
- invoice_paid admin notification on payment
- Invoice status: Draft โ Sent โ Paid / Overdue / Cancelled
Recurring Invoices
- Recurring invoice configuration (weekly, monthly, quarterly, annual)
- Daily Vercel Cron job for automated invoice generation (protected by CRON_SECRET)
Overdue Invoice Detection - Daily cron job to detect and update overdue invoices - Admin notification for each newly overdue invoice
Project Management - Project records linked to clients with status tracking (Active / On Hold / Completed) - Task creation within projects: title, description, assigned employee, due date, status - Task status pipeline: To Do โ In Progress โ Review โ Done
Time Logging - Employee time log entries against tasks (hours, date, note) - Employee portal personal time log history
Support Tickets
- Client ticket submission from client portal (subject, message, priority)
- Thread-based reply system for employee/admin responses
- support_reply in-app and email notification to client on each reply
- Ticket status: Open โ In Progress โ Closed
Document Sharing - Admin file upload to Supabase Storage, associated with client - Signed download URLs (1-hour expiry) for client portal downloads - Client portal document list with download action
Deployment Artifact Tracking - Per-project deployment records (version, environment, date, notes)
Client Cost Ledger - Internal cost tracking per client (admin-only; not visible in client portal)
Reports - Revenue report with date range filter and CSV export - Time log report filterable by employee, project, and date range
In-App Wiki - Help articles organized by category with icons and sort order - Published/unpublished toggle; content stored as HTML
Notification System
- In-app notification bell with unread count badge
- Supported types: new_lead, invoice_paid, contract_signed, contract_declined, proposal_approved, proposal_declined, support_reply
- Broadcast (all admins) and targeted (specific user) notification modes
- Email counterpart for select notification types via Resend
Employee Portal - Scoped portal: My Tasks, Time Logs, Projects (read-only), Support Tickets
Client Portal - Dashboard: outstanding proposals, unpaid invoices, open tickets - Full self-service: Proposals, Contracts, Invoices, Documents, Support
Fixed
- CRIT-4 โ Tenant isolation enforcement: all admin API routes now call
requireAdminWithTenant()and usecaller.tenantIdfor all Supabase queries; cross-tenant data access via parameter manipulation is no longer possible. - CRIT-7 โ RLS policy gaps:
documentsandcontractstables now have correcttenant_id = auth.jwt() ->> 'tenant_id'equality checks in all USING clauses on SELECT, INSERT, UPDATE, DELETE policies.
Security
- H8 โ Client portal middleware now validates that the session user has the
clientrole and the correcttenant_idin addition to checking session validity. Sessions from other roles or tenants cannot access the client portal. - TOTP MFA enforced at login for all user roles; unenrolled users are redirected to MFA setup before accessing any portal.
[0.9.0] โ 2026-05-15
Feature-complete beta release. All modules implemented. Pre-UAT candidate.
Added
- Client Portal โ Full client self-service portal: proposals, contracts, invoices, documents, support tickets, dashboard
- Stripe Checkout โ Hosted payment page integration; Pay Now button on invoice detail
- Stripe Webhook Handler โ
checkout.session.completedevent handler; auto-marks invoice paid - MFA Enforcement โ TOTP MFA mandatory for all roles; enrollment gate at first login
- Client Portal Invitation Flow โ Admin sends invite; client receives email and self-activates with MFA
- Employee Portal โ Scoped portal for employees: tasks, time logs, tickets
Fixed
- RLS policy gaps on
documentstable: policies were missingtenant_idcheck, allowing cross-tenant reads in certain configurations - Supabase FK array typing: corrected TypeScript interfaces throughout the codebase to use array syntax (
[0]indexing) for nested Supabase joins, resolving widespread TypeScript build errors
[0.8.0] โ 2026-04-01
Core commercial modules complete. First testable version of the revenue cycle.
Added
- Proposals โ Full proposal builder with line items, subtotal calculation, status workflow, and email delivery
- Contracts โ Contract creation, e-signature workflow, signing portal (placeholder โ full portal in 0.9.0)
- Invoices โ Invoice creation, manual status management (Stripe integration in 0.9.0)
- Support Ticket System โ Client ticket creation and employee reply thread (portal access in 0.9.0)
- Document Sharing โ Admin upload and Supabase Storage integration; download link generation
- Notification System โ In-app bell, notification types defined,
createNotificationhelper - Reports โ Revenue report (basic) and time log report (basic)
- In-App Wiki โ Article CRUD, category management, published/unpublished toggle
Fixed
- Multiple TypeScript compilation errors caused by Supabase nested join return types being incorrectly typed as single objects rather than arrays
amount_centscolumn reference replaced withsubtotal_centsthroughout proposals and invoices codebase after DB schema clarification
[0.7.0] โ 2026-02-15
Platform foundation. First functional alpha.
Added
- Authentication โ Supabase Auth integration, email/password login, session management
- Tenant System โ Multi-tenant data model;
tenant_idon all tables; RLS policies (initial implementation) - Lead Management โ Lead record CRUD, pipeline status field
- Client Management โ Client record CRUD, contact management (single contact per client in this version)
- Project Management โ Project CRUD linked to clients
- Task Management โ Task CRUD linked to projects, employee assignment
- Time Logging โ Basic time log entry and list
- Admin Dashboard โ Summary statistics panel (counts of leads, clients, projects, invoices)
- Next.js 15 App Router โ Full migration to App Router with edge runtime; all routes use
export const runtime = 'edge' - Supabase Integration โ
createClient()for user-scoped queries,createServiceClient()for admin/service-role queries requireAdminWithTenant()Auth Guard โ Reusable admin API route protection helper
Release History
This page is the authoritative version history for the SONAN DIGITAL CRM platform, from the first alpha through the current production release.
Semantic Versioning Policy
This project follows Semantic Versioning 2.0.0. The version format is MAJOR.MINOR.PATCH.
| Part | When to Increment | Examples |
|---|---|---|
| MAJOR | Significant platform milestone, a new suite of modules, or a breaking change to an external integration (Stripe, Supabase schema, API contract) | v0.x โ v1.0.0 (production launch); future: v1 โ v2 if multi-org or white-label added |
| MINOR | New features added in a backward-compatible manner; new modules, pages, or API endpoints that do not break existing functionality | v1.0 โ v1.1 (PDF generation, rate limiting, recovery codes) |
| PATCH | Backward-compatible bug fixes, security patches, dependency updates, or minor UI improvements with no functional change | v1.0.0 โ v1.0.1 (fix webhook edge case); v1.1.0 โ v1.1.1 (fix decimal qty bug) |
Release Type Definitions Used in This Project
| Type | Description |
|---|---|
| Alpha | Internal development build. Core foundation only. Not suitable for external users or demos. May have known data integrity issues. |
| Beta | Feature-implemented but not fully tested. Suitable for internal UAT and stakeholder previews. Not for production client use. |
| RC (Release Candidate) | Feature-frozen, UAT passed on all critical paths. Minor polish remaining. Ready for production pending sign-off. (Not used in v1.0 cycle โ went directly from Beta to Release after UAT.) |
| Major Release | UAT signed off, all Critical and High defects resolved or accepted. Deployed to production. Suitable for live client use. |
| Hotfix | Emergency patch to a production release. Follows expedited testing (targeted retest only) and fast-track deployment. Versioned as a PATCH increment. |
Full Release History
| Version | Release Date | Type | Key Changes | Defects Fixed |
|---|---|---|---|---|
| v1.0.0 | 2026-06-30 | Major Release | Initial production release. Full multi-tenant CRM: Leads, Clients, Proposals, Contracts, Invoices (Stripe Checkout), Recurring Invoices, Projects, Tasks, Time Logs, Support Tickets, Documents, Reports, Wiki, Notifications, Employee Portal, Client Portal. TOTP MFA for all roles. | CRIT-4, CRIT-7, H8 |
| v0.9.0 | 2026-05-15 | Beta | Feature complete. Full client portal, Stripe Checkout integration, MFA enforcement, employee portal, client invitation flow. Pre-UAT candidate. | RLS gap on documents table; Supabase FK array typing errors throughout codebase |
| v0.8.0 | 2026-04-01 | Beta | Core commercial modules: Proposals, Contracts, Invoices (manual), Support Tickets, Documents, Notifications, Reports (basic), Wiki. | subtotal_cents vs amount_cents column naming fix; multiple TypeScript build errors |
| v0.7.0 | 2026-02-15 | Alpha | Platform foundation: Auth, multi-tenant model, RLS policies, Leads, Clients, Projects, Tasks, Time Logs, Admin Dashboard. Next.js 15 App Router + edge runtime migration. | โ (initial build) |
Upcoming Releases
The following releases are planned. Scope is subject to change based on UAT findings and prioritization.
| Version | Target Date | Type | Planned Scope |
|---|---|---|---|
| v1.0.1 | TBD | Patch | Emergency bug fixes identified post-launch (if any). Stripe webhook edge cases. |
| v1.1.0 | 2026-Q3 | Minor | PDF generation (invoices/contracts), rate limiting on API routes, TOTP recovery codes, email delivery failure visibility, recurring invoice auto-email to client, signed URL on-demand generation |
| v1.2.0 | 2026-Q4 | Minor | Audit log for admin actions, multi-currency support, proposal templates, invoice payment reminders, bulk client import |
| v2.0.0 | 2027 | Major | (Tentative) White-label multi-organization support, custom domain per tenant, reseller billing model |
Version Support Policy
| Version | Status | Support Until |
|---|---|---|
| v1.0.x | Active โ Current production version | Until v1.1.0 is released (all critical fixes backported) |
| v0.9.x | Retired โ Replaced by v1.0.0 | No further support |
| v0.8.x | Retired | No further support |
| v0.7.x | Retired | No further support |
Once a new MINOR version is released, the previous MINOR version receives critical security patches only for 30 days, then is retired. PATCH versions within the same MINOR are always cumulative โ apply the latest patch, never an intermediate one.
How Releases Are Made
- Development occurs on feature branches (or directly on
mainfor small fixes, per team convention). - Staging deployment is triggered automatically via Vercel preview on new commits to
main(or a staging branch). - UAT is run against the staging deployment per the UAT Execution Guide.
- Sign-off is obtained per UAT Sign-Off.
- Production deployment is performed by pushing the release commit SHA directly to
main:bash git push origin <sha>:refs/heads/main(Per the FUSE-safe git workflow documented inCLAUDE.md, the push is always done from the Windows terminal, not the sandbox.) - Post-release verification follows the Release Checklist.
- Release notes and this page are updated to reflect the new version.