# Zync.is Spec Index

**Total specs:** 183 (175 active · 8 retired · 0 planned)  
**Status:** Writing foundation specs. Module specs follow after foundation lock.

Dependencies: write in order within each layer. Cross-layer: all Foundation specs must be reviewed + locked before module specs begin.

---

## Layer 0: Foundation (write first, advisor-review as a batch)

| # | File | Status | Notes |
|---|------|--------|-------|
| 1 | `2026-05-30-foundation-monorepo.md` | ✅ Reviewed | Turborepo, Cloudflare, Neon, shared packages |
| 2 | `2026-05-30-foundation-design-system.md` | ✅ Reviewed | Primitives, tokens, component registry, design-system page |
| 3 | `2026-05-30-foundation-auth-rbac.md` | ✅ Reviewed | Multi-tenant auth, roles, permissions, invitation/approval, **tier entitlements** |
| 47 | `2026-05-31-auth-2fa.md` | ✅ Draft | Foundation delta: phone OTP 2FA via Firebase; enrollment, login flow, backup codes, tenant enforce |
| 114 | `2026-05-31-dark-light-theme.md` | ✅ Draft | Dark/light theme OKLCH token sets; `.dark` class toggle; SSR flash prevention; `user_preferences.ui_theme`; supersedes oxblood/warm-paper palette |
| 115 | `2026-05-31-wcag-accessibility.md` | ✅ Draft | WCAG 2.1 AA: contrast tables, focus styles, skip links, ARIA landmarks, modal focus trap, axe-core CI |
| 122 | `2026-05-31-session-security.md` | ✅ Draft | Session lifecycle: active session list, remote revocation, idle timeout + re-auth modal, suspicious login, admin team sessions, `user_sessions` table; **consolidates spec 162** |

> Advisor batch review: complete (2 rounds).

---

## Layer 1: System Core

| # | File | Status | Notes |
|---|------|--------|-------|
| 4 | `2026-05-30-system-i18n.md` | ✅ Draft | Hebrew/English, country adapters, IL VAT history table |
| 117 | `2026-05-31-hebrew-locale-dates.md` | ✅ Draft | `Intl.*`-only date/number/currency formatting for `he-IL`; canonical format table; `useLocale()` hook; Gregorian only in v1 |
| 5 | `2026-05-30-system-communications-notifications.md` | ✅ Draft | Email/Telegram/Slack adapters, in-app notifications, webhook gateway |
| 6 | `2026-05-30-ai-assistant.md` | ✅ Draft | AI chat (Business+), Telegram/WhatsApp AI (Business/Enterprise) |
| 44 | `2026-05-31-system-ai.md` | ✅ Draft | AI infrastructure: provider adapters, fallback chain, credit accounting, admin/tenant settings |
| 45 | `2026-05-31-real-time-infrastructure.md` | ✅ Draft | WebSocket + Durable Object per-tenant hub, event fanout, reconnect strategy |

---

## Layer 2: App Shells

| # | File | Status | Notes |
|---|------|--------|-------|
| 7  | `2026-05-30-app-shell.md` | ✅ Draft | Sidebar, header, cmdk search, notifications, persistent state |
| 8  | `2026-05-30-admin-dashboard.md` | ✅ Draft | System admin: tenants, roles, users, stats, audit |
| 29 | `2026-05-31-onboarding.md` | ✅ Draft | First-time tenant onboarding wizard, 5 steps, OWNER/ADMIN only |
| 30 | `2026-05-31-home-dashboard.md` | ✅ Draft | Main app home screen: KPIs, activity feed, quick actions, upcoming, setup checklist |
| 31 | `2026-05-31-error-empty-states.md` | ✅ Draft | Error pages (404/500/403/401/429/offline/module-disabled), empty states, loading skeletons |
| 34 | `2026-05-31-zync-www-marketing-site.md` | ✅ Draft | Landing page, pricing, feature tour, public auth pages (login/signup/reset/invite-accept) |
| 35 | `2026-05-31-notification-center.md` | ✅ Draft | Full `/notifications` page: paginated history, mark-all-read, filter by type; extends app-shell dropdown |
| 36 | `2026-05-31-upgrade-upsell-modal.md` | ✅ Draft | Tier-gated upgrade modal: plan comparison, monthly/annual toggle, checkout handoff to payment adapter |
| ~~106~~ | ~~`2026-05-31-empty-error-states.md`~~ | 🗑 Retired | **Merged → spec 145** (`error-empty-states`) |

---

## Layer 3: Product Modules

| # | File | Status | Notes |
|---|------|--------|-------|
| 9  | `2026-05-30-customers-module.md` | ✅ Draft | Customer management, sub-tenant access, roles |
| 10 | `2026-05-30-projects-module.md` | ✅ Draft | Project types (fixed/hourly/retainer/overtime), analytics |
| 11 | `2026-05-30-tasks-board-engine.md` | ✅ Draft | Kanban/List/Timeline/Gantt, drag-drop, columns, filters |
| 12 | `2026-05-30-tasks-detail-communication.md` | ✅ Draft | Detail view, rich editor, correspondence, attachments, WebSocket |
| 13 | `2026-05-30-time-management.md` | ✅ Draft | Timer toggle, magic link (server-side start), idle detection, auto-pause |
| 14 | `2026-05-30-crm-support-center.md` | ✅ Draft | Ticket flow, priority/category/assignment, per-tenant Telegram bots, WhatsApp Enterprise |
| 15 | `2026-05-30-invoices-core.md` | ✅ Draft | IL law compliance, proforma→tax invoice lifecycle, HTML-only PDF |
| 16 | `2026-05-30-invoices-adapters.md` | ✅ Draft | Morning/iCount/Rivhit/Invoice4u/Easycount adapters, automation hooks |
| 17 | `2026-05-30-expenses-module.md` | ✅ Draft | Claude Vision OCR, IL tax deductibility (8 categories), PCN874 VAT report |
| 18 | `2026-05-30-billing-module.md` | ✅ Draft | Recurring payments, Morning/Isracard/Upay/iCount Pay adapters, auto-charge cron |
| 19 | `2026-05-30-calendar-module.md` | ✅ Draft | Google/Outlook 2-way sync (OAuth + webhooks), Calendly/Acuity/moCal scheduling |
| 20 | `2026-05-30-kb-module.md` | ✅ Draft | Internal wiki, client vaults, R2 + signed URLs, Tiptap JSONB, Vectorize search |
| 21 | `2026-05-30-contractor-payouts.md` | ✅ Draft | Ledger, hours reconciliation, payout bills (DRAFT→PAID) |
| 48 | `2026-05-31-contracts-esignature.md` | ✅ Draft | Contract creation + templates, e-signature (self-hosted, IL law 5761-2001), multi-signatory, PDF, lead→contract→invoice |
| 86 | `2026-05-31-invoice-credit-notes.md` | ✅ Draft | Credit note creation (חשבונית זיכוי): full/partial credit, link to original invoice, re-open flow, PDF |
| 87 | `2026-05-31-contractor-portal.md` | ✅ Draft | Contractor-only portal view: time entry, payout bill history, active project list; Business+ |
| 88 | `2026-05-31-expense-ocr-correction-ux.md` | ✅ Draft | OCR review UI + post-approval corrections + void flow; `expense_corrections` table; **consolidates spec 110** |
| 89 | `2026-05-31-contract-renewal-amendment.md` | ✅ Draft | Renew/amend signed contracts: new version clone, amendment history, bilateral link, expiry reminder cron |
| 90 | `2026-05-31-multi-signatory-coordination.md` | ✅ Draft | Multi-party signing flow: signing order, status per signatory, chaser emails, partial-signed state |
| 91 | `2026-05-31-ticket-sla-escalation.md` | ✅ Draft | SLA tiers (response/resolve targets), escalation rules, breach cron, SLA reporting; Business+ |
| 95 | `2026-05-31-time-entry-locking.md` | ✅ Draft | Period locking (weekly/monthly) for time entries; lock state machine; unlock requires OWNER; locked entries immutable |
| 96 | `2026-05-31-proposal-expiry-deadline.md` | ✅ Draft | `proposals.expires_at`; expiry cron → EXPIRED status; client-facing countdown; auto-reminder at T-2d |
| 101 | `2026-05-31-kb-article-editor.md` | ✅ Draft | Tiptap editor with slash commands, media uploads, autosave, publish/draft toggle, live preview |
| 102 | `2026-05-31-calendar-event-detail.md` | ✅ Draft | Event detail sheet: edit, attendees, task/project link, conflict detection, recurring event handling |
| 109 | `2026-05-31-calendar-task-creation.md` | ✅ Draft | "Add to calendar" from task detail; calendar → task creation modal; time-block scheduling |
| ~~110~~ | ~~`2026-05-31-expense-corrections-ui.md`~~ | 🗑 Retired | **Merged → spec 88** (`expense-ocr-correction-ux`) |
| 112 | `2026-05-31-task-estimates-burndown.md` | ✅ Draft | `tasks.estimated_hours`; burndown chart; progress bar per task; `SUM(duration_seconds)/3600.0` actual hours |
| 113 | `2026-05-31-recurring-tasks-templates.md` | ✅ Draft | `recurring_tasks` table with RRULE; cron spawns task instances + `task_labels` rows; Business+ |
| 119 | `2026-05-31-kb-versioning.md` | ✅ Draft | `kb_article_versions` snapshots; diff view (Tiptap → text → `diff` npm); restore with safety version; Business+ |
| 120 | `2026-05-31-expense-personal-business-split.md` | ✅ Draft | `expenses.business_percent` (0-100); business amount computed at query time; split slider UI; reports use business amount only |

---

## Layer 4: Marketing

| # | File | Status | Notes |
|---|------|--------|-------|
| 22 | `2026-05-30-marketing-leads-pipeline.md` | ✅ Draft | Lead forms, Kanban, conversion, FB/Google/Zapier webhooks, lead.* events |
| 23 | `2026-05-30-marketing-catalogs-campaigns.md` | ✅ Draft | Web proposals + UTM tracking, credit-based campaigns, AE funnel analytics |
| 58 | `2026-05-31-public-catalog-page.md` | ✅ Draft | zync-www `/c/{token}` — catalog renderer, embedded lead form, AE catalog_view, white-label |
| 75 | `2026-05-31-lead-to-customer-conversion.md` | ✅ Draft | Lead → customer modal UI; pre-fill from lead; optional project creation; post-conversion state |
| 99 | `2026-05-31-email-marketing-sequences.md` | ✅ Draft | Drip sequences: trigger events, multi-step email chains, delay rules, stop-on-reply; Business+ |
| 100 | `2026-05-31-leads-detail-view.md` | ✅ Draft | Lead detail sheet/page: all fields, activity feed, linked proposals/contracts, conversion action |
| 111 | `2026-05-31-lead-lost-re-engagement.md` | ✅ Draft | Re-open LOST leads; `reengagement_at` date; `lead_reengagement_due` notification; pipeline re-entry |
| 118 | `2026-05-31-lead-qualification-scoring.md` | ✅ Draft | BANT-based 0-100 score; `leads.score`; async recalc via Queue; configurable weights in `tenant_settings`; Business+ |

## Layer 4b: Public-Facing Pages (zync-www)

| # | File | Status | Notes |
|---|------|--------|-------|
| 51 | `2026-05-31-public-proposal-view.md` | ✅ Draft | `zync.is/p/{token}` — proposal renderer, accept/decline, view logging, ProposalContent type |
| 52 | `2026-05-31-contract-signing-page.md` | ✅ Draft | `zync.is/sign/{token}` — signing UI, draw/type tabs, page states, PDF download for recipients |
| 53 | `2026-05-31-invoice-payment-ux.md` | ✅ Draft | `zync.is/pay/{invoiceToken}` — payment preview, gateway redirect, return URL states, receipt |

---

## Layer 5: Cross-cutting

| # | File | Status | Notes |
|---|------|--------|-------|
| 24 | `2026-05-30-reports-analytics.md` | ✅ Draft | PCN874, revenue ledger, tenant Invoice + Payment reports (`/reports/invoices`, `/reports/payments`), expense deductibility, contractor withholding, income tax estimate, custom dashboards |
| 25 | `2026-05-30-settings-module.md` | ✅ Draft | Business profile, locale, integrations hub (app-store layout), user profile |
| 26 | `2026-05-30-tenant-portals.md` | ✅ Draft | Customer portal (/portal/{slug}/), portal auth (separate JWT), staff portal = RBAC main app |
| 32 | `2026-05-31-module-management.md` | ✅ Draft | Module enable/disable, dependency matrix, cascade rules, `/settings/modules` |
| 33 | `2026-05-31-zync-subscription.md` | ✅ Draft | Zync self-service billing, payment abstraction layer, plan management UI |
| 37 | `2026-05-31-search-completeness.md` | ✅ Draft | All entity types in cmdk palette + full-page `/search`, Postgres FTS, module/permission gating |
| 38 | `2026-05-31-staff-portal-detail.md` | ✅ Draft | Staff portal: role-based sidebar matrix, profile/prefs pages, CONTRACTOR restrictions, My Work, invite acceptance flow |
| 39 | `2026-05-31-tenant-public-api.md` | ✅ Draft | Tenant machine-to-machine REST API: `api.zync.is/v1/`, API key auth, scopes, rate limiting, OpenAPI schema |
| 40 | `2026-05-31-data-import.md` | ✅ Draft | Bulk CSV/XLSX import for customers + invoices; column mapping; async queue; partial success; Business+ only |
| 41 | `2026-05-31-unified-attachments.md` | ✅ Draft | Single `attachments` table + unified upload/signed-URL/delete API used by tasks, tickets, KB, expenses; supersedes per-entity attachment tables |
| 42 | `2026-05-31-bulk-operations.md` | ✅ Draft | Cross-module pattern: multi-select + bulk action (assign, archive, delete, export); DataTable integration, async queue for >100 items |
| 43 | `2026-05-31-telegram-bot.md` | ✅ Draft | Group assistant (message logging, /summarize, /search, @-mention Q&A via ai-assistant RAG), Zync module commands, Telegram notification channel + lists |
| 49 | `2026-05-31-payment-gateway-adapters.md` | ✅ Draft | Tenant invoice payment collection: Payplus/Cardcom/Stripe adapters, hosted pages, webhook verification, credential encryption |
| 56 | `2026-05-31-time-reports.md` | ✅ Draft | `/reports/time` — by-person/project/task aggregation, CSV/XLSX export, OWNER/ADMIN scope |
| 57 | `2026-05-31-expense-reports-ui.md` | ✅ Draft | `/expenses/reports` — Expense Detail, VAT/PCN874, Vendor Analysis tabs |
| 61 | `2026-05-31-expense-settings-ui.md` | ✅ Draft | `/settings/expenses` — default category, auto-approve threshold, VAT period, receipt intake |
| 62 | `2026-05-31-activity-timeline.md` | ✅ Draft | Per-entity activity feed (invoices, projects, customers, leads); shared component + per-entity tables |
| ~~63~~ | ~~`2026-05-31-webhook-delivery-log.md`~~ | 🗑 Retired | **Merged → spec 105** (`webhook-endpoint-detail`) |
| 64 | `2026-05-31-team-time-overview.md` | ✅ Draft | `/time/team` — live ACTIVE/IDLE/offline status per team member; 60s polling; OWNER/ADMIN only |
| 65 | `2026-05-31-expense-approval-workflow.md` | ✅ Draft | Expense approval gate for amounts above threshold; approval queue; Business+ |
| 66 | `2026-05-31-email-template-editor.md` | ✅ Draft | `/settings/email-templates` — customizable HTML templates; variable interpolation; Business+ |
| 67 | `2026-05-31-multi-currency.md` | ✅ Draft | ILS/USD/EUR invoices; manual exchange rates; ILS snapshot at TAX_ISSUED; IL law compliance |
| 68 | `2026-05-31-trial-expiry-conversion-ui.md` | ✅ Draft | Trial lifecycle UX: soft banner, T-3/T-1 emails, expiry interstitial, post-conversion toast |
| 69 | `2026-05-31-subscription-cancellation-flow.md` | ✅ Draft | Two-step cancel with offboarding survey; post-cancel state; reactivation before period end |
| 71 | `2026-05-31-customer-dedup-merge.md` | ✅ Draft | Duplicate detection (email + fuzzy name); merge modal; all linked entities reassigned; Business+ |
| 76 | `2026-05-31-contract-to-invoice.md` | ✅ Draft | Contract → invoice pre-fill; `/invoices/new?contract_id=`; contract detail Invoice tab |
| 77 | `2026-05-31-time-to-invoice.md` | ✅ Draft | Time entries → invoice: entry selector, grouping options, `invoice_id` tracking |
| 78 | `2026-05-31-proposal-to-contract.md` | ✅ Draft | Proposal acceptance → contract creation pre-fill; bilateral link (proposal↔contract) |
| 79 | `2026-05-31-invoice-payment-reminders.md` | ✅ Draft | Automated reminder schedule; 5-stage (−3d/0/+7/+14/+30); cron daily; per-invoice opt-out |
| 80 | `2026-05-31-partial-payment-recording.md` | ✅ Draft | `invoice_payments` table; `PARTIALLY_PAID` status; amount_paid denorm; auto-status transition |
| 81 | `2026-05-31-rtl-hebrew-ui.md` | ✅ Draft | RTL layout; CSS logical properties; ESLint rule; icon mirroring; `dir` on `<html>` |
| 82 | `2026-05-31-customer-portal-access-control.md` | ✅ Draft | Portal JWT claims; `portalQuery` factory; entity access rules; visibility config |
| 83 | `2026-05-31-operational-audit-trail.md` | ✅ Draft | `before_state`/`after_state` on tenant_audit_log; field-level diff; History tab |
| ~~84~~ | ~~`2026-05-31-webhook-event-filtering.md`~~ | 🗑 Retired | **Merged → spec 105** (`webhook-endpoint-detail`) |
| 85 | `2026-05-31-product-service-library.md` | ✅ Draft | `products` table; `/settings/products` UI; type-ahead in invoice line items |
| 92 | `2026-05-31-profitability-reports.md` | ✅ Draft | `/reports/profitability` — project margin (revenue - hours cost - expenses), per-project and period views; Business+ |
| 93 | `2026-05-31-payment-retry-dunning.md` | ✅ Draft | Automatic retry schedule for failed payment plans; dunning emails at D+1/D+3/D+7; subscription pause |
| 94 | `2026-05-31-api-usage-quota-ui.md` | ✅ Draft | `/settings/api` — usage gauges per scope, quota limits, overage policy, historical chart |
| 97 | `2026-05-31-notification-preferences.md` | ✅ Draft | Canonical `NotificationType` union (all 35 types incl. task_due_soon/overdue, budget_alert, contract_all_signed); per-channel prefs; digest mode; **consolidates spec 158** |
| 98 | `2026-05-31-expense-to-invoice-line.md` | ✅ Draft | Add approved expenses as invoice line items; bulk selector; `expense_invoice_lines` link; Business+ |
| 103 | `2026-05-31-reports-navigation-hub.md` | ✅ Draft | `/reports` hub: card grid linking all report sub-pages; tier badge per card; quick-filter by module |
| 105 | `2026-05-31-webhook-endpoint-detail.md` | ✅ Draft | Webhook endpoint edit UI: event subscriptions, delivery log tab, filter logic, test delivery, secret rotation, 30d retention cron; **consolidates specs 63 + 84** |
| 107 | `2026-05-31-proposal-to-invoice-direct.md` | ✅ Draft | Accepted proposal → invoice pre-fill from `proposals.content` JSONB; `invoices.proposal_id` FK; `default_payment_terms_days` |
| ~~108~~ | ~~`2026-05-31-time-approval-payroll-export.md`~~ | 🗑 Retired | **Merged → spec 52** (`time-approval-workflow`) |
| 116 | `2026-05-31-revenue-forecasting.md` | ✅ Draft | 3-source forecast (committed invoices + recurring + probability-weighted leads); stacked Recharts; `tenant_settings.lead_stage_probabilities`; Business+ |
| 121 | `2026-05-31-field-level-permissions.md` | ✅ Draft | `field_permission_rules` table; visible/read_only/hidden per field per role; KV-cached enforcement; Business+ |

---

## Layer 6: Enterprise

| # | File | Status | Notes |
|---|------|--------|-------|
| 27 | `2026-05-30-white-label-api.md` | ✅ Draft | Custom domains (CF custom hostnames), webhook gateway (all events, HMAC signed), API keys |
| 28 | `2026-05-30-audit-compliance.md` | ✅ Draft | Audit log (immutable, partitioned), GDPR erasure, 7yr retention, RLS decision, observability |
| 50 | `2026-05-31-tenant-audit-log.md` | ✅ Draft | Tenant-facing audit log UI + API (`/settings/audit-log` + `/reports/audit`); fire-and-forget Queue writes; 90d/1yr retention; before/after diff; OWNER/ADMIN only; **consolidates spec 104** |
| 51 | `2026-05-31-custom-smtp-email-whitelabel.md` | ✅ Draft | Custom From address (Business+) + DKIM via Resend; custom SMTP relay (Enterprise); TenantEmailAdapter |
| 52 | `2026-05-31-time-approval-workflow.md` | ✅ Draft | Contractor time entry approval gate; pending→approved→locked state machine; `/time/approvals` UI; payroll CSV export (Business+); **consolidates spec 108** |
| 53 | `2026-05-31-recurring-invoices.md` | ✅ Draft | Recurring invoice templates; daily cron generation; auto-send; frequency_day clamping; Business+ |
| 54 | `2026-05-31-data-export-gdpr.md` | ✅ Draft | Tenant full export (ZIP/R2/email); user personal data export; soft+hard delete; GDPR Art.17+20 |
| 55 | `2026-05-31-mobile-pwa.md` | ✅ Draft | PWA manifest, service worker (Workbox), Web Push (VAPID), offline timer sync, iOS Safari notes |
| 59 | `2026-05-31-admin-reports-analytics.md` | ✅ Draft | `/admin/reports` + `/admin/analytics` — MRR/ARR/churn, module adoption, AI usage, funnel health |
| 60 | `2026-05-31-api-keys-ui.md` | ✅ Draft | `/settings/api-keys` — create/list/revoke API keys; key-reveal-once UX; scope selection; Business+ |
| 72 | `2026-05-31-admin-impersonation.md` | ✅ Draft | SUPER_ADMIN login-as-tenant; 15min shadow session; tenant-visible audit; blocked destructive ops |
| 73 | `2026-05-31-system-status-page.md` | ✅ Draft | `status.zync.is` — incident management, service status, uptime history, email subscription |
| 74 | `2026-05-31-public-api-docs.md` | ✅ Draft | `developers.zync.is` — static API docs, code examples, "Try it" feature, webhook catalog |
| ~~104~~ | ~~`2026-05-31-audit-log-viewer.md`~~ | 🗑 Retired | **Merged → spec 50** (`tenant-audit-log`) | OWNER/ADMIN only |

---

## Layer 7: Gap Analysis Additions (2026-05-31)

Gap analysis identified missing UI screens, cross-module flows, and settings pages. Specs below fill those gaps.

### Product Module Gaps

| # | File | Status | Notes |
|---|------|--------|-------|
| 123 | `2026-05-31-timezone-handling.md` | ✅ Draft | `user_preferences.timezone`; `Intl.DateTimeFormat` everywhere; UTC storage; IL default `Asia/Jerusalem` |
| 126 | `2026-05-31-invoice-payment-link-generation.md` | ✅ Draft | Staff-generated pay links; HMAC token; `/pay/{token}` page; payment link tab on invoice detail |
| 127 | `2026-05-31-invoice-adapter-setup-ui.md` | ✅ Draft | `/settings/integrations/invoicing` — connects Morning/iCount/Rivhit/Invoice4u/Easycount with test + auto-sync |
| 132 | `2026-05-31-project-milestones.md` | ✅ Draft | `project_milestones` table; milestone markers on Gantt/Timeline; billing triggers; COMPLETED/MISSED states |
| 133 | `2026-05-31-bulk-invoice-generation.md` | ✅ Draft | Batch invoice creation from recurring work; customer multi-select; preview before generate; Business+ |
| 134 | `2026-05-31-contractor-management-ui.md` | ✅ Draft | `/contractors` list + detail page; invite flow; assignment history; payout history |
| 135 | `2026-05-31-invoice-pdf-customization.md` | ✅ Draft | `/settings/invoice-pdf` — logo, colors, font, column layout; live preview; `tenant_invoice_pdf_config` table |
| 139 | `2026-05-31-project-hourly-budget.md` | ✅ Draft | `billing_config.budget_hours` + `budget_alert_pct`; burn bar on project detail; alert at threshold |
| 142 | `2026-05-31-invoice-email-history.md` | ✅ Draft | Invoice email log tab; Resend webhook `POST /api/webhooks/resend` (NEW); `invoice_email_logs` table |
| 144 | `2026-05-31-invoice-draft-library.md` | ✅ Draft | `/invoices/drafts` — draft list + template library; `is_template` flag; `customer_id` nullable for templates |
| 145 | `2026-05-31-sla-config-ui.md` | ✅ Draft | `/settings/sla` — edit `sla_policies` (spec 91); add `notify_email`/`notify_in_app` columns; Business+ |
| 147 | `2026-05-31-project-archive-complete.md` | ✅ Draft | `completed`/`archived` project states; completion confirmation; `completed_at`/`archived_at` columns |
| 150 | `2026-05-31-project-analytics.md` | ✅ Draft | [Analytics] tab on project detail; time/task/budget stats (all tiers); revenue + margin (Business+) |

### Marketing Module Gaps

| # | File | Status | Notes |
|---|------|--------|-------|
| 128 | `2026-05-31-lead-form-builder.md` | ✅ Draft | Visual form builder for `lead_forms`; drag-drop fields; embed snippet; Business+ create/edit |
| 130 | `2026-05-31-proposal-editor.md` | ✅ Draft | Full proposal editor: Tiptap rich text, line items, pricing table, cover page, preview |
| 146 | `2026-05-31-lead-to-proposal-flow.md` | ✅ Draft | Lead → proposal pre-fill; `proposals.lead_id` FK; stage auto-advance on SENT/ACCEPTED/REJECTED |

### Settings & Cross-cutting Gaps

| # | File | Status | Notes |
|---|------|--------|-------|
| 124 | `2026-05-31-billing-plans-management-ui.md` | ✅ Draft | `/settings/billing` — plan overview, usage, upgrade/downgrade, invoice history |
| 125 | `2026-05-31-invoice-settings-page.md` | ✅ Draft | `/settings/invoicing` — number prefix, VAT defaults, payment terms, footer text, bank details |
| 129 | `2026-05-31-task-dependencies.md` | ✅ Draft | `task_dependencies` table; blocked-by/blocks visualization; dependency validation on status change; Business+ |
| 131 | `2026-05-31-calendar-integration-settings-ui.md` | ✅ Draft | `/settings/integrations/calendar` — connect/disconnect OAuth; sync direction; Calendly/Acuity config |
| 136 | `2026-05-31-customer-portal-settings-ui.md` | ✅ Draft | `/settings/portal` — logo, welcome message, module visibility, default portal section |
| 138 | `2026-05-31-team-users-settings.md` | ✅ Draft | `/settings/users` — member list, invite, role change (dynamic from `roles` table), freeze/remove |
| 140 | `2026-05-31-ar-aging-report.md` | ✅ Draft | `/reports/ar-aging` — 0-30/31-60/61-90/90+ buckets; customer drill-down; CSV export Business+ |
| 141 | `2026-05-31-portal-file-sharing.md` | ✅ Draft | Portal file uploads; `portal_files` table; `uploaded_by` nullable (staff) + `uploaded_by_portal_user` (client) |
| 143 | `2026-05-31-saved-list-filters.md` | ✅ Draft | `saved_filters` table; save/load/default per-module filters; team-shared vs personal |
| 148 | `2026-05-31-contractor-settings.md` | ✅ Draft | `/settings/contractors` — portal toggle, approval policy, payout defaults; extends `tenant_settings` |
| 149 | `2026-05-31-integration-hub.md` | ✅ Draft | `/settings/integrations` — unified hub: all integration statuses, [Manage→] deep links, search |

### Enterprise Gap

| # | File | Status | Notes |
|---|------|--------|-------|
| 137 | `2026-05-31-custom-domain-settings-ui.md` | ✅ Draft | `/settings/white-label` — add/verify CNAME custom domain; DNS instructions; Enterprise only |

---

## Foundation Deltas

Each module spec that adds a new Cloudflare binding, secret, or cross-cutting shared table appends it here. This list feeds back into `foundation-monorepo.md` bindings table before implementation.

### Bindings added by module specs
| Binding | Type | Purpose | Added by |
|---------|------|---------|----------|
| `DO_REALTIME` | Durable Object (`TenantRealtimeDO`) | Per-tenant WebSocket hub, one DO per tenant | specs 5, 12 |
| `VECTORIZE` | Vectorize index | Per-tenant RAG embeddings, namespace `tenant:{id}` | spec 6 |
| `RATE_LIMITER_AUTH` | CF native RateLimiter | Auth routes rate limiting (no KV cost) | spec 5 |
| `RATE_LIMITER_WEBHOOK` | CF native RateLimiter | Inbound webhook rate limiting | spec 5 |
| **Cloudflare Email Routing** | Email Routing (dashboard-only) | Route inbound email → Worker → Queue for tickets + expense receipts | specs 14, 17 |
| `RATE_LIMITER_EXPENSE_UPLOAD` | CF native RateLimiter | 10 uploads/min per user (protects OCR queue) | spec 17 |
| `RATE_LIMITER_LEAD_FORM` | CF native RateLimiter | 20 submissions/min per form (public endpoint abuse) | spec 22 |
| `ANALYTICS_ENGINE` | CF Analytics Engine (`[[analytics_engine_datasets]]`) | Funnel events: `catalog_view`, `lead_captured`, `proposal_accepted`, `invoice_paid`. Cross-cutting: needed by marketing Worker AND invoices-core Worker | spec 23 |
| `RATE_LIMITER_PROPOSAL` | CF native RateLimiter | 10 req/min per IP per proposal token (public proposal view) | spec 51 (public-proposal-view) |
| `RATE_LIMITER_SIGN` | CF native RateLimiter | 20 req/min per IP per signing token (contract signing page) | spec 52 (contract-signing-page) |
| `RATE_LIMITER_CATALOG` | CF native RateLimiter | 30 req/min per IP per catalog token (public catalog page) | spec 58 |
| `STATUS_KV` | CF KV namespace | System status page cache (30s TTL); key: `status:current`; invalidated on incident change | spec 73 |

> ⚠️ `email:*` scope absent from wrangler OAuth. Email Routing setup = dashboard click only (zone → Email → Email Routing → Enable). Not automatable via wrangler or MCP.

### Secrets added by module specs
| Secret | Purpose | Added by |
|--------|---------|----------|
| `JWT_SECRET` | Signing key for session JWTs (access/refresh); verified on every authenticated request | spec 3 (foundation-auth-rbac) |
| `CRON_SECRET` | Shared secret guarding internal `/api/cron/*` scheduled endpoints against external invocation | spec 1 (foundation-monorepo) |
| `ADMIN_ENCRYPTION_KEY` | AES-256 key for encrypting platform-admin TOTP secrets in `admin_users` | spec 8 (admin-dashboard) |
| `RESEND_API_KEY` | System transactional email | spec 5 |
| `TELEGRAM_BOT_TOKEN` | **REMOVED** — per-tenant bot tokens encrypted in DB (see spec 14) | spec 5 |
| `INTEGRATION_ENCRYPTION_KEY` | AES-256 for tenant SMTP/OAuth/Telegram creds in DB | spec 5 |
| `ANTHROPIC_API_KEY` | Claude Sonnet (chat + OCR categorization) | spec 6 |
| `OPENAI_API_KEY` | OpenAI adapter (fallback / backup models) | spec 44 |
| `GOOGLE_AI_API_KEY` | Google Gemini adapter (fallback / backup models) | spec 44 |
| `UNSUBSCRIBE_HMAC_KEY` | HMAC key for stateless unsubscribe tokens (never logged) | spec 23 |
| `CF_CUSTOM_HOSTNAME_API_TOKEN` | CF API token (`ssl_certs:write`) for custom hostname provisioning. Not in wrangler OAuth — must create in CF dashboard | spec 27 |
| `CF_ANALYTICS_READ_TOKEN` | CF API token (`Account Analytics: Read`) for AE SQL HTTP API reads. AE binding is write-only; reads (funnel dashboards, custom analytics) use SQL HTTP endpoint with this token. Not in wrangler OAuth — must create in CF dashboard | specs 23, 24 |
| `DATA_EXPORT_KEY` | AES-256-GCM key for encrypting tenant export ZIPs | spec 28 |
| `SMTP_ENCRYPTION_KEY` | AES-256-GCM key for encrypting tenant SMTP passwords in `tenant_email_config` | spec 51 |
| `VAPID_PUBLIC_KEY` | VAPID public key for Web Push subscription on client | spec 11 / 55 |
| `VAPID_PRIVATE_KEY` | VAPID private key for signing Web Push delivery requests | spec 11 / 55 |
| `FIREBASE_API_KEY` | Firebase Web API key (DEV + PROD env-specific); used in client SDK config + server REST token verification | spec 47 |
| `FIREBASE_PROJECT_ID` | Firebase project ID for ID token audience check (env-specific) | spec 47 |
| `PAYMENT_CONFIG_ENCRYPTION_KEY` | AES-256-GCM key for encrypting gateway credentials in `payment_gateway_configs` | spec 49 |
| `INVOICE_PAYMENT_LINK_KEY` | HMAC key for stateless invoice payment link tokens (`/pay/{invoiceToken}`) | spec 53 (invoice-payment-ux) |
| `IMPERSONATION_SECRET` | JWT signing key for admin impersonation tokens; separate from session JWT secret | spec 72 |

### Secrets added by module specs (calendar OAuth)

| Secret | Purpose | Added by |
|--------|---------|----------|
| `GOOGLE_OAUTH_CLIENT_ID` | Google Calendar OAuth app identity | spec 19 |
| `GOOGLE_OAUTH_CLIENT_SECRET` | Google Calendar OAuth app secret | spec 19 |
| `MICROSOFT_OAUTH_CLIENT_ID` | Outlook/MS Graph OAuth app identity | spec 19 |
| `MICROSOFT_OAUTH_CLIENT_SECRET` | Outlook/MS Graph OAuth app secret | spec 19 |

> These are Zync's own once-registered OAuth app credentials (global secrets). Per-user access/refresh tokens are stored encrypted in `calendar_connections` via `INTEGRATION_ENCRYPTION_KEY`.

### Crons added by module specs

| Cron | Schedule | Purpose | Added by |
|------|----------|---------|----------|
| `billing-charge` | Daily | Auto-charge due payment plans; enqueues `payment.charge` jobs | spec 18 |
| `calendar-sync` | Daily | Full re-sync of Google/Outlook calendars (catches webhook gaps) | spec 19 |
| `campaigns-send` | Every 5 min | Process due/scheduled campaigns; enqueues send batches | spec 23 |
| `domain-verify` | Every 15 min | DNS check + CF custom hostname provisioning for Enterprise custom domains | spec 27 |
| `data-retention-purge` | Monthly | Purge expired PII, export ZIPs, session tokens | spec 28 |
| `audit-partition-create` | 1st of month | Create next month's `audit_log` partition | spec 28 |
| `subscription-trial-check` | Daily | Expire Business trials past `trial_ends_at`; downgrade to `freelancer` | spec 33 |
| `audit-log-retention` | Daily 03:00 UTC | Purge tenant_audit_log rows older than plan retention limit (90d Business / 365d Enterprise) | spec 50 |
| `smtp-domain-verify` | Every 10 min | Poll Resend API for pending DKIM domain verifications; set domain_verified=1 on success | spec 51 |
| `recurring-invoices` | Daily 06:00 UTC | Generate due recurring invoice templates; advance next_generation_date; auto-send if configured | spec 53 |
| `webhook-log-retention` | Daily | Purge `webhook_delivery_log` rows older than 30 days | spec 63 |
| `export-expiry-cleanup` | Daily | Delete export_jobs rows with download_expires_at < now(); R2 lifecycle rule handles file deletion | spec 54 |
| `tenant-hard-delete` | Daily | Hard-delete tenants with deleted_at > 30 days ago: R2 purge + Postgres CASCADE + row delete | spec 54 |
| `boi-exchange-rates` | Weekdays 14:00 UTC | Fetch Bank of Israel XML feed; store suggested rates; notify staff for confirmation; `boi_rate_sync_enabled` toggle | spec 67 |
| `recurring-expenses` | Daily 06:00 UTC | Spawn expense records from due `recurring_expenses` templates; advance `next_due_date` | spec 172 |
| `scheduled-reports` | Every 15 min | Generate + email due `report_schedules`; update `last_run_at` + `next_run_at` | spec 174 |
| `invoice-reminders` | Daily 07:00 UTC | Send due invoice payment reminders; advance `next_reminder_at` per tenant reminder schedule | spec 79 |
| `invoice-dunning` | Daily 08:00 UTC | Dunning chase for failed/overdue payment plans; step through `dunning_schedules`, log to `dunning_log` | spec 93 |
| `contract-signing-reminders` | Daily 09:00 UTC | Chaser emails to signatories who have not yet signed pending multi-party contracts | spec 90 |
| `time-approval-digest` | Daily 09:00 (tenant-local) | In-app digest to approvers when pending time entries > 0 | spec 52 |
| `time-entry-period-lock` | Daily (period-close cutoff) | Lock all time entries before the configured period cutoff date; complements manual lock | spec 95 |
| `contract-expiry-reminder` | Daily 08:00 UTC | Chaser emails for contracts nearing expiry | spec 89 |

### Queues added by module specs

| Queue | Consumer | Purpose | Added by |
|-------|----------|---------|----------|
| `payment.charge` | billing Worker | Async charge + invoice creation + retry | spec 18 |
| `campaign.send_batch` | campaigns Worker | Batched email delivery (50 recipients/job) | spec 23 |
| `webhook.deliver` | webhook Worker | Async outbound webhook delivery with exponential backoff | spec 27 |
| `export.generate` | export Worker | Full tenant data export (DB + R2 → encrypted ZIP) | spec 28 |
| `import.process` | import Worker | Row-by-row async CSV/XLSX import; partial success; results to `import_job_results` | spec 40 |
| `bulk-action` | bulk-action Worker | Process bulk operations >100 items with retry + progress tracking | spec 42 |
| `zync-realtime` | `realtime-consumer` Worker | Fan out real-time events to tenant Durable Objects | spec 45 |
| `audit-log-queue` | `audit-log-consumer` Worker | Fire-and-forget audit event inserts; up to 3 retries with backoff | spec 50 |
| `export-generate` | `export-generator` Worker | Async tenant/user data export: Postgres → CSV → ZIP → R2; streaming to avoid memory limits | spec 54 |
| `tenant-deletion` | `tenant-deletion` Worker | Staged tenant hard-delete: blob purge → DB cascade → row delete; progress via `deletion_stage` column | spec 54 |

### Tables added by module specs (specs 13–21)

| Table | Owner spec | Notes |
|-------|-----------|-------|
| `time_entries` | spec 13 | `user_id` nullable when `contractor_id` set; CHECK constraint `user_or_contractor` |
| `magic_link_tokens` | spec 13 | |
| `tickets` | spec 14 | |
| `ticket_messages` | spec 14 | |
| `ticket_message_attachments` | spec 14 | superseded by `attachments` table (spec 41) |
| `ticket_categories` | spec 14 | |
| `invoices` | spec 15 | status enum extended: `PARTIALLY_PAID` added between `TAX_ISSUED` and `PAID` (spec 80); `amount_paid NUMERIC(12,2)` added (spec 80); reminder columns added (spec 79) |
| `invoice_lines` | spec 15 | |
| `invoice_sequences` | spec 15 | |
| `adapter_credentials` | spec 16 | |
| `integration_sync_logs` | spec 16 | |
| `expenses` | spec 17 | |
| `expense_corrections` | spec 17 | |
| `payment_methods` | spec 18 | `provider_token` encrypted; Isracard rows: type='direct_debit', last_four/expiry unused |
| `payment_plans` | spec 18 | |
| `payments` | spec 18 | |
| `calendar_events` | spec 19 | |
| `calendar_connections` | spec 19 | OAuth tokens AES-256-GCM encrypted via `INTEGRATION_ENCRYPTION_KEY` |
| `scheduling_connections` | spec 19 | API keys encrypted |
| `kb_spaces` | spec 20 | |
| `kb_articles` | spec 20 | Tiptap JSONB content; fractional index position |
| `kb_attachments` | spec 20 | superseded by `attachments` table (spec 41) |
| `contractors` | spec 21 | |
| `contractor_assignments` | spec 21 | `rate_override` wins over `contractors.hourly_rate` |
| `payout_bills` | spec 21 | |
| `payout_bill_lines` | spec 21 | FK to `time_entries` (nullable for fixed/retainer lines) |
| `leads` | spec 22 | UTM fields + stage + source; fractional index `stage_position` |
| `lead_activities` | spec 22 | |
| `lead_forms` | spec 22 | |
| `lead_form_submissions` | spec 22 | |
| `lead_webhooks` | spec 22 | HMAC secret per source |
| `catalog_templates` | spec 23 | |
| `proposals` | spec 23 | `public_token` for unauthenticated view; content snapshot at send time |
| `proposal_view_events` | spec 23 | AE funnel complement — DB record for drilldown |
| `mailing_lists` | spec 23 | |
| `mailing_list_subscribers` | spec 23 | UNIQUE (list_id, email) |
| `campaigns` | spec 23 | credit-based; status DRAFT→SCHEDULED→SENDING→SENT |
| `email_credits` | spec 23 | per-tenant balance |
| `email_credit_transactions` | spec 23 | top-ups + deductions |
| `catalog_shares` | spec 23 | public catalog share links; top-of-funnel; emits `catalog_view` AE event |
| `tax_rates` | spec 8 | IL statutory tax rates by type + effective date (corporate, personal brackets, withholding); read by reports + payouts |
| `dashboards` | spec 24 | per-user custom analytics dashboards |
| `dashboard_widgets` | spec 24 | widget configs on 12-col grid |
| `tenant_domains` | spec 27 | custom domain + CF hostname ID + verification status |
| `webhook_endpoints` | spec 27 | outbound webhook configs (HMAC signing key AES-256-GCM encrypted via `INTEGRATION_ENCRYPTION_KEY` — must be recoverable for outbound signing) |
| `webhook_deliveries` | spec 27 | delivery log with retry state |
| `tenant_api_keys` | spec 27 | machine-to-machine API keys (SHA-256 hashed, scoped) |
| `audit_log` | spec 28 | immutable, partitioned by month; INSERT-only via Postgres rules; 7yr retention |
| `tenant_export_jobs` | spec 28 | async export status tracking |

> **Schema deltas on existing foundation tables:**
> - `refresh_tokens`: add `user_agent TEXT, ip TEXT, last_seen_at TIMESTAMPTZ` (settings-module: sessions list UI)
> - `magic_link_tokens`: add `purpose TEXT DEFAULT 'timer'` discriminator (portal magic links use `purpose = 'portal'`)
> - `tenants`: add `onboarding_completed BOOLEAN NOT NULL DEFAULT false`, `onboarding_step INT NOT NULL DEFAULT 0` (spec 29); add `checklist_dismissed_at TIMESTAMPTZ` (spec 30)

**New tables added by specs 29–33:**

| Table | Owner spec | Notes |
|-------|-----------|-------|
| `tenant_modules` | spec 32 | Per-tenant module enable/disable state; `system` module never stored (always on) |
| `zync_subscriptions` | spec 33 | Zync's own subscription per tenant; adapter pattern for Stripe/PayPal/manual |
| `import_jobs` | spec 40 | Tracks upload, column mapping, status, row counts per import job |
| `import_job_results` | spec 40 | Per-row result (success/skipped/error); purged after 90 days |
| `telegram_group_chats` | spec 43 | Tenant-registered group chat IDs with bot membership |
| `telegram_messages` | spec 43 | Full message log for registered groups; FTS index; 12-month rolling retention |
| `telegram_notification_lists` | spec 43 | Named broadcast lists (arrays of chat_ids) |
| `telegram_notification_routing` | spec 43 | Per notification-type routing to lists/groups/personal chats |
| `ai_global_config` | spec 44 | Singleton: main model, backup list, use-case system prompts |
| `ai_model_pricing` | spec 44 | Per-model cost config ($/1M input+output tokens); admin-managed |
| `ai_tier_quotas` | spec 44 | Per-tier monthly token quotas with effective date ranges |
| `ai_tenant_settings` | spec 44 | Per-tenant AI personality, use-case overrides, extra-usage toggle |
| `ai_usage_log` | spec 44 | Per-call AI usage and cost log; FTS by tenant + period |
| `ai_credit_purchases` | spec 44 | Purchased extra credit balances with token conversion at purchase rate |
| `user_2fa_backup_codes` | spec 47 | Single-use backup codes (SHA-256 hashed) for 2FA recovery |
| `payment_gateway_configs` | spec 49 | Per-tenant payment gateway selection + AES-256-GCM encrypted credentials |
| `invoice_payment_sessions` | spec 49 | Gateway payment sessions: session_id, status, webhook audit trail |
| `contract_templates` | spec 48 | Reusable contract templates (Tiptap JSONB) with variable declarations |
| `contracts` | spec 48 | Contract instances: status DRAFT→SENT→VIEWED→SIGNED→VOIDED, signed PDF R2 key |
| `contract_signatories` | spec 48 | Per-contract signatories: UUID token, signature_data base64, IP, user_agent |
| `contract_audit_log` | spec 48 | Per-contract event log: viewed, signed, voided, downloaded |
| `tenant_audit_log` | spec 50 | Immutable tenant-level event log; INSERT-only from Queue Consumer; indexed by tenant+time, entity, user, event_type; `before_state`/`after_state` JSONB added (spec 83) |
| `invoice_payments` | spec 80 | Partial payment records; amount, currency, source, reference, recorded_by |
| `products` | spec 85 | Tenant product/service library; unit_price, unit, tax_rate_id FK; type-ahead in invoices |
| `tenant_email_config` | spec 51 | Custom From address + DKIM verification token + SMTP relay credentials (password AES-256-GCM encrypted) |
| `recurring_invoice_templates` | spec 53 | Recurring invoice templates with frequency/day/auto-send; `invoices.recurring_template_id` FK added |
| `export_jobs` | spec 54 | Async export status tracking (tenant_full + user_personal); R2 key + signed URL + expiry |
| `push_subscriptions` | spec 55 | Web Push endpoints per user/device (VAPID); UNIQUE(user_id, endpoint); stale entries pruned on 410 |
| `invoice_activities` | spec 62 | Per-invoice activity feed; FK CASCADE DELETE on invoice |
| `project_activities` | spec 62 | Per-project activity feed; FK CASCADE DELETE on project |
| `customer_activities` | spec 62 | Per-customer activity feed; FK CASCADE DELETE on customer |
| ~~`webhook_delivery_log`~~ | spec 63 | No new table — spec 63 extends `webhook_deliveries` (spec 27) with `status='test'` support |
| `tenant_email_templates` | spec 66 | Per-tenant custom HTML email templates; UNIQUE (tenant_id, template_key); fallback to system default when absent |
| `customer_merge_suggestions` | spec 71 | AI-detected duplicate customer pairs; status pending/accepted/dismissed |
| `system_incidents` | spec 73 | Platform incident records for public status page |
| `system_incident_updates` | spec 73 | Per-incident status updates |
| `status_subscribers` | spec 73 | Public email subscribers for status page notifications |

> **Schema deltas on `users`:** `two_factor_enabled BOOLEAN DEFAULT false`, `two_factor_phone TEXT` (SHA-256 hash), `two_factor_phone_suffix TEXT` (last 2 digits) — spec 47
> **Schema delta on `tenants`:** `enforce_2fa BOOLEAN DEFAULT false` — spec 47; `payment_webhook_token TEXT` (routing token for payment webhooks) — spec 49
> **Schema deltas on `invoices` + `leads`:** add `contract_id UUID REFERENCES contracts(id)` — spec 48
> **Schema delta:** `user_preferences`: add `telegram_chat_id BIGINT` (nullable; set via `/connect` flow)
> **Schema deltas from new specs (50–55):**
> - `time_entries`: `approval_status TEXT DEFAULT 'auto_approved'` is a base column owned by `time-management` (spec 13); spec 52 adds only `approval_note TEXT`, `approved_by UUID REFERENCES users(id)`, `approved_at TIMESTAMPTZ`, `submitted_at TIMESTAMPTZ`
> - `invoices`: add `recurring_template_id UUID REFERENCES recurring_invoice_templates(id) ON DELETE SET NULL` — spec 53
> - `tenants`: add `deleted_at TIMESTAMPTZ`, `deletion_requested_by UUID REFERENCES users(id)` — spec 54
> - `users`: add `deleted_at TIMESTAMPTZ` — spec 54
> - `tenant_members`: add `permissions JSONB` (e.g. `{ "time:approve": true }`) — spec 52

> **Schema deltas from new specs (86–122):**
> - `expenses`: add `business_percent INTEGER NOT NULL DEFAULT 100 CHECK (business_percent >= 0 AND business_percent <= 100)` — spec 120
> - `proposals`: add `expires_at TIMESTAMPTZ` — spec 96
> - `leads`: add `reengagement_at TIMESTAMPTZ`, `reengagement_note TEXT` — spec 111
> - `leads`: add `score INTEGER DEFAULT 0 CHECK (score >= 0 AND score <= 100)`, `score_updated_at TIMESTAMPTZ` — spec 118
> - `invoices`: add `proposal_id UUID REFERENCES proposals(id)` — spec 107
> - `tasks`: add `estimated_hours NUMERIC(6,2)` — spec 112
> - `user_preferences`: add `ui_theme TEXT DEFAULT 'dark' CHECK (ui_theme IN ('dark','light','system'))` — spec 114
> - `user_preferences`: add `notify_new_login BOOLEAN DEFAULT true` — spec 122
> - `tenant_settings`: add `lead_stage_probabilities JSONB DEFAULT '{"NEW":5,"CONTACTED":15,"QUALIFIED":30,"PROPOSAL":60}'` — spec 116
> - `tenant_settings`: add `lead_scoring_criteria JSONB DEFAULT '...'` — spec 118
> - `tenant_settings`: add `default_payment_terms_days INTEGER DEFAULT 30`, `default_tax_rate NUMERIC(5,4) DEFAULT 0.18` — spec 107
>
> **New tables (specs 86–122):**
> - `recurring_tasks` — spec 113 (RRULE-based task templates; Business+)
> - `kb_article_versions` — spec 119 (full Tiptap JSON snapshots per article version)
> - `field_permission_rules` — spec 121 (per-field per-role visibility; KV-cached)
> - `user_sessions` — spec 122 (`token_hash`, `device_name`, `ip_address`, `last_active_at`, revocation)
> - `tenant_security_settings` — spec 122 (idle timeout, max sessions, 2FA policy, suspicious login block)
>
> **New crons (specs 86–122):**
> - `proposal-expiry` — Daily: mark expired proposals → EXPIRED, send reminder at T-2d — spec 96
> - `lead-reengagement` — Daily: notify on `leads.reengagement_at` — spec 111
> - `lead-score-refresh` — Daily: recalculate `leads.score` where `score_updated_at` stale — spec 118
> - `session-idle-cleanup` — Daily: revoke offline idle sessions; clean expired sessions — spec 122
> - `contract-expiry-reminder` — Daily: chaser emails for contracts nearing expiry — spec 89
> - `ticket-sla-breach` — Every 5 min: detect SLA breaches, escalate, send alerts — spec 91
>
> **New queues (specs 86–122):**
> - `lead-score` — async lead score recalculation consumer — spec 118

> **Schema deltas from new specs (56–78):**
> - `invoices`: add `ils_exchange_rate NUMERIC(10,4)`, `total_ils NUMERIC(12,2)` (multi-currency IL law snapshot at TAX_ISSUED) — spec 67
> - `invoices`: add `contract_id UUID REFERENCES contracts(id) ON DELETE SET NULL` (already in spec 48 delta, repeated here for cross-reference) — spec 48/76
> - `proposals`: add `contract_id UUID REFERENCES contracts(id) ON DELETE SET NULL` — spec 78
> - `contracts`: add `proposal_id UUID REFERENCES proposals(id) ON DELETE SET NULL` — spec 78
> - `expenses`: add `approval_status TEXT DEFAULT 'not_required'`, `approved_by UUID REFERENCES users(id)`, `approved_at TIMESTAMPTZ`, `approval_note TEXT` — spec 65
> - `expenses`: add `original_currency TEXT`, `original_amount NUMERIC(12,2)` (foreign-currency receipt storage) — spec 67
> - `time_entries`: add `invoice_id UUID REFERENCES invoices(id) ON DELETE SET NULL`, `billed_at TIMESTAMPTZ` — spec 77 (column name per migration order constraint below)
> - `zync_subscriptions`: add `trial_warning_sent_at TIMESTAMPTZ`, `trial_expiry_ack_at TIMESTAMPTZ` — spec 68
> - `zync_subscriptions`: add `cancellation_reason TEXT`, `cancellation_reason_freetext TEXT` — spec 69

> **Schema deltas from gap-fill specs (165–178):**
> - `invoices`: add `ita_confirmation_number TEXT`, `ita_registered_at TIMESTAMPTZ` — spec 165
> - `invoices`: add `void_reason TEXT`, `voided_at TIMESTAMPTZ`, `voided_by UUID REFERENCES users(id)` — spec 15 (G3)
> - `invoices`: add `bad_debt_at TIMESTAMPTZ`, `bad_debt_reason TEXT`, `bad_debt_note TEXT` — spec 168
> - `tenant_settings`: add `bad_debt_threshold_days INT NOT NULL DEFAULT 90` — spec 168
> - `expenses`: add `mileage_trip_id UUID REFERENCES mileage_trips(id) ON DELETE SET NULL`, `is_per_diem BOOLEAN DEFAULT false`, `per_diem_days NUMERIC(4,1)`, `per_diem_rate_ils NUMERIC(10,2)` — specs 166, 17
> - `expenses`: add `bank_transaction_id UUID REFERENCES bank_transactions(id) ON DELETE SET NULL` — spec 167
> - `tasks`: add `start_date DATE`, `end_date DATE`, `parent_task_id UUID REFERENCES tasks(id) ON DELETE SET NULL`, `depends_on_task_ids UUID[] DEFAULT '{}' `, `is_milestone BOOLEAN NOT NULL DEFAULT false` — spec 173
> - `tenant_settings`: add `time_rounding TEXT DEFAULT 'none'`, `time_min_billable_minutes INTEGER DEFAULT 0`, `time_idle_threshold_minutes INTEGER DEFAULT 10`, `time_auto_pause_on_idle BOOLEAN DEFAULT true`, `time_standard_hours_per_day NUMERIC(4,2) DEFAULT 8.0`, `time_flag_overtime BOOLEAN DEFAULT false`, `time_require_overtime_approval BOOLEAN DEFAULT false`, `time_magic_link_enabled BOOLEAN DEFAULT true`, `mileage_enabled BOOLEAN DEFAULT false`, `mileage_rate_ils NUMERIC(8,4)`, `per_diem_rates JSONB` — specs 169, 166, 13
> - `tenant_settings`: add `vat_period TEXT DEFAULT 'bimonthly'`, `advance_tax_rate_pct NUMERIC(5,2)`, `boi_rate_sync_enabled BOOLEAN DEFAULT false` — specs 171, 67
> - `tenants`: add `deletion_job_id UUID` — spec 54
>
> **New tables (specs 165–178):**
> - `mileage_trips` — spec 166 (trip log: vehicle, start/end odometer, purpose, distance_km, expense_id FK)
> - `mileage_vehicles` — spec 166 (tenant vehicle registry: name, license_plate, fuel_type, engine_cc)
> - `mileage_rates` — spec 166 (ITA mileage rate table: year, vehicle_type, rate_per_km; seeded from ITA schedule)
> - `bank_imports` — spec 167 (bank statement upload jobs: bank_id, status, row counts)
> - `bank_transactions` — spec 167 (parsed transactions: date, amount, description, confidence, matched_to_type, matched_to_id)
> - `bad_debt_vat_reclaims` — spec 168 (VAT reclaim per bad-debt invoice: status pending/submitted/approved/rejected, submitted_at)
> - `recurring_expenses` — spec 172 (templates: schedule, amount, category, next_due_date, state active/paused/cancelled)
> - `project_templates` — spec 178 (`tenant_id IS NULL` = system template; category, estimated_days, billing_type, usage_count)
> - `project_template_tasks` — spec 178 (relative_start_days, relative_due_days, phase, position, checklist_items)
> - `report_schedules` — spec 174 (12 report types, frequency, recipients JSONB, next_run_at, is_active)
> - `nii_advance_payments` — spec 175 (year+month advance NII contributions; UNIQUE per tenant+user+year+month)
> - `oauth_clients` — spec 177 (registered OAuth apps: redirect_uris, scopes, is_first_party)
> - `oauth_authorization_codes` — spec 177 (10-min TTL, single-use, PKCE challenge)
> - `oauth_access_tokens` — spec 177 (1-hour TTL, SHA-256 hash stored)
> - `oauth_refresh_tokens` — spec 177 (60-day TTL, rotated on use)
> - `oauth_connections` — spec 177 (active app connections for Settings > Integrations display)
> - `push_subscriptions` — spec 55/G10 (Web Push endpoints per user/device; UNIQUE(user_id, endpoint))
> - `user_trusted_devices` — spec auth-2fa/G39 (30-day device trust tokens; `zync_device_trust` cookie)
> - `customer_communications` — spec 9/G50 (direction/channel/subject/body log per customer)
> - ~~`tax_brackets` — spec 171~~ **RETIRED** — personal income brackets are read from `tax_rates` (spec 8); no separate table (gap-analysis 2026-06-01)

> **Tables surfaced by gap-fill audit (2026-06-01) — previously missing from this manifest:**
> - `admin_users` — spec 3 (`foundation-auth-rbac`): platform-admin accounts, separate from tenant `users`
> - `contractor_portal_sessions` — spec 87 (`contractor-portal`): contractor portal login sessions
> - `contractor_project_assignments` — spec 38 (`staff-portal-detail`): contractor↔project assignment grants
> - `dunning_log` — spec 93 (`payment-retry-dunning`): per-step dunning action log
> - `dunning_schedules` — spec 93 (`payment-retry-dunning`): per-tenant dunning step schedule (seeded on Business+)
> - `email_sequences` — spec 99 (`email-marketing-sequences`): drip-sequence definitions
> - `sequence_enrollments` — spec 99 (`email-marketing-sequences`): per-contact enrollment + position
> - `sequence_steps` — spec 99 (`email-marketing-sequences`): ordered steps within a sequence
> - `invoice_email_events` — spec 142 (`invoice-email-history`): per-invoice email send/open/click events
> - `kb_space_contractor_access` — spec 38 (`staff-portal-detail`): KB space access grants for contractors
> - `proposal_templates` — spec 130 (`proposal-editor`): reusable proposal templates
> - `report_shortcuts` — spec 103 (`reports-navigation-hub`): per-user pinned report configurations
> - `system_config` — spec 165 (`ita-einvoice`): admin-configurable global key/value config (e.g. ITA threshold)
> - `task_templates` — spec 113 (`recurring-tasks-templates`): reusable task templates (distinct from spec 178 `project_template_tasks`)
> - `vat_rates` — spec 4 (`system-i18n`): seeded VAT rate table by effective date (distinct from spec 8 `tax_rates`)
>
> *Audit false positive:* `statements` is **not** a table — the spec 122 (`session-security`) reference is to SQL "CREATE TABLE statements", not a table named `statements`. Skipped.

> **Cross-cutting constraint (spec 28):** All write route handlers must include an audit record in the **same DB transaction** as the business operation. ESLint rule `require-audit-in-transaction` enforces this. This retroactively applies to specs 9–27.

> **Migration order constraints:**
> - `time_entries` (spec 13) before `invoices` (spec 15) — `ALTER TABLE time_entries ADD COLUMN invoice_id UUID` after both
> - `time_entries` before `contractors` (spec 21) — `ALTER TABLE time_entries ADD COLUMN contractor_id UUID REFERENCES contractors(id)` after both; also `ALTER COLUMN user_id DROP NOT NULL`
> - `invoices` (spec 15) before `payments` (spec 18)

> **Email Routing dispatch note:** both spec 14 (tickets) and spec 17 (`expenses@…`) consume CF Email Routing → Worker → Queue. The Worker routes by recipient address: `expenses@{slug}.zync.is` → expenses queue; `support@{slug}.zync.is` → tickets queue. Single email Worker, routes by `to` header before enqueuing.

---

## Layer 8: Gap Analysis Additions II (2026-06-01)

Second gap analysis round. Specs below fill settings pages, missing list views, and workflow UIs.

### Settings Gaps

| # | File | Status | Notes |
|---|------|--------|-------|
| 151 | `2026-06-01-settings-projects.md` | ✅ Draft | `/settings/projects` — project defaults (billing type, rate, currency, time rounding, budget alert channel) |
| 152 | `2026-06-01-settings-customers.md` | ✅ Draft | `/settings/customers` — portal auto-invite mode, visibility defaults; `default_payment_terms_days` from spec 107 |
| 153 | `2026-06-01-settings-contracts.md` | ✅ Draft | `/settings/contracts` — default template, expiry, signing order, e-sig reminders (Business+), renewal reminders |
| 154 | `2026-06-01-settings-kb.md` | ✅ Draft | `/settings/kb` — publication workflow (direct/review), KB space CRUD, `PENDING_REVIEW` status added |

### Workflow & List View Gaps

| # | File | Status | Notes |
|---|------|--------|-------|
| 155 | `2026-06-01-invoice-approval-workflow.md` | ✅ Draft | `/invoices/approvals` — SENT invoice queue, bulk approve, rejection reason, sidebar badge |
| 156 | `2026-06-01-proposals-list.md` | ✅ Draft | `/proposals` — table + kanban pipeline views; total_value from JSONB; quick actions |
| 157 | `2026-06-01-payment-reconciliation.md` | ✅ Draft | `/invoices/reconcile` — unmatched payments staging; bank-to-invoice matching; `unmatched_payments` table |

### Notification & Export Gaps

| # | File | Status | Notes |
|---|------|--------|-------|
| ~~158~~ | ~~`2026-06-01-notification-trigger-gaps.md`~~ | 🗑 Retired | **Merged → spec 97** (`notification-preferences`) |
| 159 | `2026-06-01-proposal-pdf-export.md` | ✅ Draft | On-demand proposal PDF via `GET /api/proposals/:id/pdf`; HTML-to-PDF Worker; public page uses `window.print()` |

### UX & Frontend Gaps

| # | File | Status | Notes |
|---|------|--------|-------|
| 160 | `2026-06-01-keyboard-shortcuts.md` | ✅ Draft | ⌘K command palette; G+x navigation; N+x create shortcuts; `?` help overlay; per-page shortcuts |
| 161 | `2026-06-01-print-layouts.md` | ✅ Draft | `@media print` CSS for invoices, proposal public preview, customer statement (spec 34) |
| ~~162~~ | ~~`2026-06-01-inactivity-reauth.md`~~ | 🗑 Retired | **Merged → spec 122** (`session-security`) |
| 163 | `2026-06-01-settings-roles.md` | ✅ Draft | `/settings/roles` — custom role CRUD; permission matrix; delete-with-reassignment; `tenant_roles` table |
| 164 | `2026-06-01-settings-crm.md` | ✅ Draft | `/settings/crm` — lead scoring weights (spec 118), pipeline stages JSONB (spec 116), lost reasons (spec 111) |

---

## Layer 9: Gap-Fill Additions (2026-06-01)

Third gap-fill pass. Specs below add missing financial compliance, Israeli tax, reporting, and platform integration features.

### Finance & Invoicing Gaps

| # | File | Status | Notes |
|---|------|--------|-------|
| 165 | `2026-06-01-ita-einvoice.md` | ✅ Draft | ITA e-invoice registration (Shaba API) at `TAX_ISSUED`; `ita_confirmation_number` + `ita_registered_at`; blocks issue if registration fails |
| 167 | `2026-06-01-bank-statement-import.md` | ✅ Draft | Bank CSV/OFX import; 4-step flow (upload→parse→auto-match→review→complete); 8 IL bank parsers; confidence-based matching to invoices/expenses |
| 168 | `2026-06-01-bad-debt-writeoff.md` | ✅ Draft | `BAD_DEBT` invoice status; `bad_debt_vat_reclaims` table; VAT reclaim process; annual bad debt report; P&L deduction |

### Expenses Gaps

| # | File | Status | Notes |
|---|------|--------|-------|
| 166 | `2026-06-01-mileage-logbook.md` | ✅ Draft | `mileage_trips` + `mileage_vehicles` + `mileage_rates` tables; trip log UI; annual report; expense integration via `mileage_trip_id` FK |
| 172 | `2026-06-01-recurring-expenses.md` | ✅ Draft | `recurring_expenses` table with weekly/monthly/quarterly/annually schedule; daily 06:00 UTC cron; pause/resume; CRUD API |

### Reports & Tax Gaps

| # | File | Status | Notes |
|---|------|--------|-------|
| 170 | `2026-06-01-financial-statements.md` | ✅ Draft | P&L (gross revenue, credit notes, bad debt, net revenue, expenses, contractor payouts, gross/net profit) + cash flow statement; xlsx variants; Business+ |
| 171 | `2026-06-01-israeli-tax-reports.md` | ✅ Draft | PCN874 VAT report CSV in ITA machine-readable format; annual income summary Excel; advance tax estimate with `tax_brackets` table; `vat_period` + `advance_tax_rate_pct` columns |
| 174 | `2026-06-01-scheduled-reports.md` | ✅ Draft | `report_schedules` table; 15-min cron; 12 report types; recipients JSONB (users + external emails); "Run now"; Business+ |
| 175 | `2026-06-01-bituach-leumi.md` | ✅ Draft | Annual NII income report; two-tier contribution estimate; `nii_advance_payments` table; 5-tab Excel export; all tiers |

### Projects Gaps

| # | File | Status | Notes |
|---|------|--------|-------|
| 173 | `2026-06-01-project-gantt.md` | ✅ Draft | Gantt view on projects; `start_date`/`end_date`/`parent_task_id`/`depends_on_task_ids`/`is_milestone` on tasks; drag-to-reschedule; cycle detection; Business+ |
| 178 | `2026-06-01-project-templates.md` | ✅ Draft | `project_templates` (system + tenant) + `project_template_tasks` tables; gallery UI; template preview; apply with relative date computation; save-as-template; 7 system templates |

### Settings Gaps

| # | File | Status | Notes |
|---|------|--------|-------|
| 169 | `2026-06-01-settings-time-tracking.md` | ✅ Draft | `/settings/time-tracking` page; `time_rounding`, `time_min_billable_minutes`, `time_idle_threshold_minutes`, `time_auto_pause_on_idle`, `time_standard_hours_per_day`, `time_flag_overtime`, `time_require_overtime_approval`, contractor time + mileage settings |

### Platform & Integration Gaps

| # | File | Status | Notes |
|---|------|--------|-------|
| 176 | `2026-06-01-zapier-make-integration.md` | ✅ Draft | Native Zapier (8 triggers, 7 actions, 2 searches) + Make modules; OAuth 2.0 via spec 177; REST hooks; Business+ |
| 177 | `2026-06-01-oauth-authorization-code.md` | ✅ Draft | Full OAuth 2.0 AS: consent screen, code→token exchange, refresh, revoke; 5 tables; 12 scopes; PKCE required; White Label (issuing) / Business+ (connecting) |

---

## Layer 10: Gap Analysis Additions III (2026-06-01)

Fourth gap pass. Closes Israeli-compliance legal gaps, missing entities/screens, and reconciles the appendix architecture/security/a11y findings.

### Finance & Compliance Gaps (legal)

| # | File | Status | Notes |
|---|------|--------|-------|
| 179 | `2026-06-01-invoice-receipt-document.md` | ✅ Draft | קבלה (standalone receipt) + חשבונית מס/קבלה (combined); `receipts`, `receipt_payment_lines`, `receipt_sequences` tables; issue-on-payment; void; PDF; `invoice_payments.receipt_id`; `/receipts` list + `/receipts/:id` detail |
| 180 | `2026-06-01-uniform-format-export.md` | ✅ Draft | מבנה אחיד / BKMVDATA audit-file export (INI.txt + BKMVDATA.txt, CP1255); `/reports/uniform-format`; `uniform_export_jobs`; distinct from spec 165 |
| 181 | `2026-06-01-accountant-export.md` | ✅ Draft | Hashavshevet movement file (קובץ תנועות) + Form 6111; derived ledger; `coa_accounts`/`coa_mappings`/`accountant_export_jobs`; Accountant role; `/settings/integrations/accounting` |

### Entity & Screen Gaps

| # | File | Status | Notes |
|---|------|--------|-------|
| 182 | `2026-06-01-vendors-suppliers.md` | ✅ Draft | First-class `vendors` entity + `/vendors` CRUD; expense `vendor_id` FK; completes supplier Form 856 withholding flow at `/reports/withholding` |
| 183 | `2026-06-01-customer-statement.md` | ✅ Draft | `/customers/:id/statement` (כרטסת לקוח); read-only projection; PDF + email + portal; no new tables |

> Mailing-list management promoted to a dedicated `/marketing/lists` (+ `/marketing/lists/:id`) screen in spec 23 (`marketing-catalogs-campaigns`) — the `mailing_lists` table had no first-class UI/route.

### New tables (specs 179–183)
| Table | Owner spec | Notes |
|-------|-----------|-------|
| `receipts` | spec 179 | doc_type `receipt`/`invoice_receipt`; own sequence; ISSUED/VOIDED |
| `receipt_payment_lines` | spec 179 | per-payment method detail (cash/cheque/card/bank) for D120 export |
| `receipt_sequences` | spec 179 | gap-free per-doc-type receipt numbering |
| `uniform_export_jobs` | spec 180 | מבנה אחיד export job status + record counts |
| `coa_accounts` | spec 181 | tenant chart of accounts; carries `form6111_code` |
| `coa_mappings` | spec 181 | document-category → account-code mapping |
| `accountant_export_jobs` | spec 181 | movement-file / 6111 export job status |
| `vendors` | spec 182 | supplier entity: tax id, withholding rate+cert, defaults |

> **Schema deltas (specs 179–183):**
> - `invoice_payments`: add `receipt_id UUID REFERENCES receipts(id) ON DELETE SET NULL` — spec 179
> - `expenses`: add `vendor_id UUID REFERENCES vendors(id) ON DELETE SET NULL` — spec 182
> - `recurring_expenses`: add `vendor_id UUID REFERENCES vendors(id) ON DELETE SET NULL` — spec 182
> - `tenant_memberships`: add `is_accountant BOOLEAN DEFAULT false` (Accountant scoped role) — spec 181
> - `bank_transactions`: add `unmatched_payment_id UUID REFERENCES unmatched_payments(id) ON DELETE SET NULL`; `match_status` gains `'sent_to_reconcile'` — spec 167 (cross-flow with spec 157)

> **Appendix scan reconciliations (edits to existing specs, same report):**
> - **`tax_brackets` table REMOVED** — spec 171 now reads personal income brackets from `tax_rates` (spec 8) via `tax_type LIKE 'personal_bracket_%'`; the manifest line below is retired.
> - `tasks`: add `CREATE INDEX ... USING GIN (depends_on_task_ids)` — spec 173 (reverse-dependency lookups)
> - Report-path indexes specified in spec 170: `expenses(tenant_id,status,expense_date)`, `invoice_payments(tenant_id,paid_at)`, `payout_bills(tenant_id,status,paid_at)`, `invoices(tenant_id,status,tax_issue_date)`
> - OAuth (spec 177): access tokens are opaque DB-backed (not stateless JWT) for revocability; `oauth_refresh_tokens` gains `family_id`+`rotated_to` for reuse-detection; consent POST gains own CSRF token
> - Shared financial export writer (spec 170): xlsx `rightToLeft`+Hebrew font and CSV/xlsx formula-injection guard — used by specs 170, 171, 175; PCN874 CSV emits CP1255 (spec 171)
> - Scheduled reports (spec 174): require `reports:export` to create, `reports:export_external` for external recipients; generated under creator's permission scope

> ~~`tax_brackets` (spec 171)~~ — **retired**; brackets sourced from `tax_rates` (spec 8). Was: `(year, min_income, max_income, rate)`.

---

## Canonical Route Names (T3 — route fragmentation fix)

Gap analysis found a handful of screens referred to by two different paths across specs. Pre-launch (no live users), these were **renamed inline to one path** — no redirects/backwards-compat. The table below records the genuine consolidations and, deliberately, the pairs that look like duplicates but are **distinct features** (do not merge).

**Consolidated (one screen, was two names → renamed everywhere):**

| Screen | Canonical | Was also called | Owner |
|--------|-----------|-----------------|-------|
| API key management UI | `/settings/api-keys` | `/settings/developer` | spec 60 |
| Calendar integration (Google + Outlook on one page) | `/settings/integrations/calendar` | `/settings/integrations/google-calendar`, `/settings/integrations/outlook` | spec 113 |
| Notification preferences | `/profile/notifications` | `/settings/notifications` | spec 97 |
| Vendor list | `/vendors` | `/settings/vendors` | spec 182 |
| Dunning settings | `/settings/invoicing/dunning` | `/settings/billing/dunning` | spec 93 |
| Withholding (Mas 856) report | `/reports/withholding` | `/reports/mas856` | spec 171 (nav label stays "Mas 856") |
| Proposal detail (staff) | `/proposals/:id` | `/marketing/proposals/:id` | spec 155 (`proposal-editor` owns detail; non-DRAFT state hosts Create-Contract/Invoice + PDF CTAs) |
| Webhook settings | `/settings/integrations/webhooks` | `/settings/webhooks` | spec 105 |
| Contractor detail | `/contractors/:id` | `/team/contractors`, `/payouts/contractors/:id` | spec 134 |
| Team / user management | `/settings/users` | `/settings/team` | spec 138 |

**Distinct — NOT duplicates (kept separate; flagged so they aren't re-merged):**

| A | B | Why distinct |
|---|---|--------------|
| `/settings/plan` (Zync subscription) | `/billing/plans` (customer installment plans) | One is the tenant's own Zync plan; the other is the tenant's payment plans for *their* customers (spec 30 CRUD). Different domains. |
| `/settings/api-keys` (key management, spec 60) | `/settings/api` (usage/quota dashboard, spec 94) | Managing keys vs viewing API consumption — two pages. |
| Invoice settings `/settings/invoicing` (spec 125) | — | Owner spec 125 defines `/settings/invoicing`; several consumers had drifted to the plural `/settings/invoices` (incl. `/adapters`, `/dunning`, reminders API) — swept to the owner spelling. One canonical base. |
| VAT report `/reports/vat` | Withholding `/reports/withholding` | Different statutory reports; never a single route. |

> Statutory report routes are named descriptively (`vat`, `pnl`, `cashflow`, `advance-tax`, `withholding`, `bituach-leumi`) — `withholding` chosen over `mas856` to match that convention; the nav tile label remains "Mas 856".

---

## Out-of-Scope / Deferred (T4 — confirmed product decisions, not gaps)

Surfaced by gap analysis; intentionally **not** built in v1. Recorded so they aren't re-flagged. Revisit per tier demand.

| Item | Decision | Rationale |
|------|----------|-----------|
| SSO / SAML | Deferred (post-v1 Enterprise) | `foundation-auth-rbac` notes "Social/SSO (future)"; no Enterprise SAML buyer committed yet |
| SMS notification channel | Deferred | SMS used only for 2FA (Firebase); reminder-channel SMS adds per-message cost + provider; revisit if demanded |
| Support canned responses / macros | Deferred | CRM support center ships with ticket messages; saved-reply library is a later efficiency add |
| Referral / affiliate program | Deferred | Growth-loop feature; not core to the SMB workflow |
| Multi-business per owner (איחוד עוסקים) | Deferred | One tenant = one business in v1; accountant-managing-many is a separate future surface |

---

## Prerequisites

- [ ] Read `~/Projects/Virtuac` before writing specs 17 and 24
- [ ] Foundation specs (1–3) advisor-reviewed and locked before any Layer 2+ spec begins implementation

---

---

## Dependency Graph

```
Foundation (1-3)
    └─► System Core (4-6)
    └─► App Shells (7-8, 29-31, 34-36)
    └─► Product Modules (9-21, 37-42)
            └─► Marketing (22-23)
            └─► Cross-cutting (24-26, 32-33)
            └─► Enterprise (27-28)
```
