Part I · SRS
Chapter 3 - Non-Functional Requirements Register
Status labels: Implemented, Present (not verified), To Be Confirmed (TBC), Gap.
NFR-SEC — Security
| ID | Ref | Requirement | Evidence / Notes | Status |
|---|---|---|---|---|
| NFR-SEC-001 | Auth mechanism | Session-based authentication (Laravel default), CSRF on state-changing requests (except callbacks). | bootstrap/app.php CSRF exceptions; auth.php routes. | Implemented & Verified (inspection). |
| NFR-SEC-002 | CSRF state-changing | All authenticated routes require CSRF (except allowed list with 24 payment callbacks). | bootstrap/app.php lines 45-64. | Implemented & Verified. |
| NFR-SEC-003 | Authorization (SaaS) | Roles/permissions via Spatie guarded 'web'. | config/permission.php; middleware. | Implemented & Verified. |
| NFR-SEC-004 | Authorization (non-SaaS) | Membership role column drives access instead of Spatie (alternative implemented branch). | User::scopeWorkspaceScoped, handle inertia request permission logic. | Implemented (depth unverified). |
| NFR-SEC-005 | Row-level tenant isolation | Workspace scoping and role scoping applied on queries. | User::scopeWorkspaceScoped, repository explicit filters. | Implemented (no global scope). |
| NFR-SEC-006 | IMAP password at rest | Encrypted mutator on EmailAccount.password. | app/Models/EmailAccount.php (accessor/mutator). | Implemented & Verified. |
| NFR-SEC-007 | Secret fallback in config | config/imap.php defines direct username/password in repo fallback. | !! Open security vulnerability | Gap — credentials shown in source. |
| NFR-SEC-008 | Sensitive fields encryption | IMAP secrets only; gateway credentials appear held in plaintext payment_settings values (likely encrypted at app level? verify). | payment_settings migration. | Unverified. |
| NFR-SEC-009 | Password nullable | users.password nullable (implies social/quick login possibility, currently unused). | User model casts. | Present. |
| NFR-SEC-010 | SaaS mode lock | SaaS-only routes return 404 for non-SaaS via SaasOnly. | SaasOnlyMiddleware. | Implemented & Verified. |
| NFR-SEC-011 | Demo mode lock | Non-GET blocked in demo. | DemoModeMiddleware. | Implemented & Verified. |
| NFR-SEC-012 | Workspace suspension lock | Suspended workspace blocks state changes. | CheckWorkspaceSuspension. | Implemented & Verified. |
| NFR-SEC-013 | Secret hygiene | No .env tracked; no secrets read in this audit; actual secrets are deployment-local. | environment files not present. | Implemented workflow. |
| NFR-SEC-014 | Login history (IP, etc.) | Stores sensitive IP and details array. | login_histories migration. | Implemented, privacy retention TBC. |
| NFR-SEC-015 | File (media) visibility | Spatie media uses private/public disks; media upload respects storage driver. | media_items migration + config/multimedia; MediaController. | Implemented. |
| NFR-SEC-016 | Security scanning/pentest | No scans or results. | Not found. | TBC / Gap. |
| NFR-SEC-017 | Rate limiting | Default Laravel throttle 6/min for reset tokens; AI chat 30/hr; IMAP connection backoff. | Code. | Implemented minimal. |
NFR-PRF — Performance
| ID | Item | Evidence | Notes | Status |
|---|---|---|---|---|
| NFR-PRF-001 | SLA / response budget | Not defined. | TBC (no documented SLO). | |
| NFR-PRF-002 | Query optimization in dashboard/evaluation. | DashboardService, PerformanceAnalyticsService. | Complex service code (8-15KB), queries possibly heavy — requires profiling. | |
| NFR-PRF-003 | Plan usage cache. | ai_token_usage aggregated; workspaces cache stats 300s in AiAgentService. | Implemented. | |
| NFR-PRF-004 | Indexes | audit_logs has compound; performance_metrics unique user/month; email_message unique message_id. | Partial (no migration-level full index audit beyond listed ones). | |
| NFR-PRF-005 | WEB with heavy pages | SPA with Vite chunk splitting (vendor/ui/utils) | Build config. | Implemented. |
| NFR-PRF-006 | IMAP polling interval | 10s per account; schedule everyMinute; withoutOverlapping. | EmailListenerService. | Implemented. |
| NFR-PRF-007 | Async report/email jobs | Only GenerateMonthlyReportsJob is queued. | app/Jobs. | Partial (emails remain synchronous). |
NFR-AVAIL — Availability / Reliability
| ID | Items | Status |
|---|---|---|
| NFR-AVAIL-001 | Defined uptime contract/Tier (TBC) | TBC. |
| NFR-AVAIL-002 | Retry behavior of IMAP listener (max 10 retries, 10 sec wait). | Implemented. |
| NFR-AVAIL-003 | Queue worker supervisor config (must be added by infra team); Docker queue:work --daemon --tries=3 --timeout=600; schema only has one job. | Present. |
| NFR-AVAIL-004 | Logging stack configurable (single/logger stacking). | Present. |
NFR-MAINT — Maintainability
| ID | Item | Evidence |
|---|---|---|
| NFR-MAINT-001 | Codebase size: backend ~85 models, 125 controllers, 32 services; JS 383 files. | File counts (535 Route:: lines in routes/web.php). |
| NFR-MAINT-002 | Architecture MVC + Service Layer + Repository (repository consistent for some domains). | app/Repositories; Controllers. |
| NFR-MAINT-003 | Stale/duplicate classes. | SlackSettingsController vs Settings\SlackSettingController; ZoomSettings test method mismatch; PermissionController extra methods may be unimplemented. |
| NFR-MAINT-004 | SpatieTeams unused (teams=false), but the migration includes team FK columns. | config permission; migration. |
| NFR-MAINT-005 | Frontend no component tests/no tests. | package.json. |
| NFR-MAINT-006 | Unresolved agent instructions / business copy | no docs for tenant settings/SaaS specifics. |
NFR-USAB — Usability
- UI uses Radix UI + shadcn, supports dark mode (app.css dark-mode); cookie consent; LTR/RTL; modal stacks.
- Responsiveness via mobile hooks.
- NFR-USAB-001 — Alt-text for design not audited (accessibility gap).
NFR-ACCESS — Accessibility
| Item | Status |
|---|---|
| WCAG 2.1 AA target? | TBC — no documented requirement. |
| Screen reader usage (ARIA) | Radix components usually provide round behavior; unverified. |
| Keyboard navigation | Not documented / unverified. |
| Contrast check | Not documented. |
| Internationalization 16 Locales; RTL support for Arabic/Hebrew. | Implemented. |
NFR-PORT — Compatibility & Localisation
- PHP 8.2, Laravel 12 (framework).
- 16 enabled languages (see resources/lang/language.json).
- Any browser that supports React 19 + modern CSS (Firefox, Chrome, Safari, Edge).
- Mobile responsiveness.
- NFR-PORT-001 — no IE11 (modern build).
- For timezone config,
config/app.phpdefault UTC.config/dateformat/timeformat/timezonescustom (not deeply inspected).
NFR-AUDIT — Auditability
- Audit logs for actions with entity metadata.
- Task/Budget events stored.
- Performance metrics stored per user/month.
- NFR-AUDIT-001 — retention periods to be defined; data deletion policy TBC.
NFR-PRIV — Privacy & Confidentiality
- Legal data sent to Gemini (AI email analysis + chat) must have consent; export of data GDPR-style not found.
- No "delete my data" workflow.
- No data export at user level (except CSV for contacts/newsletters/expenses).
- Need stakeholder decision on data residency.
NFR-BACKUP
- Backup strategy not documented; infra local/repo includes no backup script.
- Databases likely backup candidates for an official production routine (not provided).
NFR-MAINT-007 — Testability
- PHPUnit (phpunit.xml) config present, but
tests/folder and phpunit.xml are absent. Pest is a declared dev dependency but no tests. - frontend tests absent.
- Acceptance criteria captured separately.