Replaced 174 em-dashes (—) with " - " (space-hyphen-space) across 49
files in src/components + src/app. The em-dash reads as a tell-tale
"AI-generated" marker per the user's design feedback; hyphens with
spaces preserve the connector semantics without the AI tint.
Touched only lines outside pure-comment context (// /* * */). Code
comments, JSDoc, audit-log strings, structured logging strings, and
templates outside the lint scope retain their em-dashes for now —
they're not user-visible.
Also captured two remaining cases that used the `—` HTML entity
instead of the literal character (system-monitoring-dashboard,
interest-stage-picker) — replaced with a plain hyphen.
Bumped the existing `no-restricted-syntax` rule from `warn` → `error`
in eslint.config.mjs scoped to src/components/**/*.tsx +
src/app/**/*.tsx. New code reintroducing em-dashes in JSX text now
fails the lint gate.
Verified: tsc clean, vitest 1448/1448, eslint 0 em-dash warnings.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Payments (deposit / balance / refund records on an interest) used to
share `invoices.record_payment`, which forces a port that doesn't
issue invoices at all to still navigate the invoicing permission
group to grant its sales reps payment-recording rights. Splitting
the resource lets admins gate the two surfaces independently.
The new resource has three actions:
- view — gates the UI affordance (API reads still go through
`interests.view`)
- record — POST / PATCH a payment
- delete — DELETE a payment record
Seed maps updated for all six system roles; existing role rows +
per-user permission overrides are backfilled by migration 0064 so
upgrades don't silently lose access. Two call sites (POST /interests/
[id]/payments, PATCH /payments/[id]) → payments.record; one
(DELETE /payments/[id]) → payments.delete. The PermissionGates on the
payments-section UI swap to the new keys.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Swap the one outlier (client-interests-tab.tsx) from Vaul Drawer to
Sheet side=right so every detail-preview surface uses the same
primitive. Document the doctrine: Sheet for side panels on both desktop
and mobile; Vaul Drawer reserved for mobile-only bottom-sheet UX
(currently just MoreSheet).
Closes ui/ux M11.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Tier 0.2: src/lib/env.ts now refuses boot when NODE_ENV=production AND
EMAIL_REDIRECT_TO is set. Sendmail logs the rewrite at warn (was debug)
so dev/staging windows where someone forgets to unset are immediately
visible.
Tier 0.6: backup_jobs.storage_path added to TABLES_WITH_STORAGE_KEYS in
src/lib/storage/migrate.ts. Flipping the storage backend used to
silently orphan every pg_dump artefact — last-resort recovery path is
now actually portable.
Tier 1.7: createAuditLog now runs metadata through maskSensitiveFields
(was only applied to old/new value diffs). Portal-auth, crm-invite,
hard-delete and email-accounts services were writing raw emails into
this column unbounded.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>