chore(autonomous-session): consolidate uncommitted work from prior session

Bundles the prior autonomous-session output that was sitting unstaged:

- Em-dash sweep across src/ + tests/ (en-dash/em-dash to hyphen, ~2280 instances)
- country-flag-icons rollout (CountryFlag component, replaces emoji glyphs that
  never rendered on Windows; lazy-loads the 3x2 SVG index as a single chunk
  after the per-subpath dynamic-import approach silently failed in webpack)
- Admin IA Phase 1+2: 7-domain regroup, 41 to 38 pages, /admin/berths index,
  redirects (ocr to ai, reports to dashboard, invitations to users),
  docs/admin-ia-proposal.md
- Per-template email tester (registry + endpoint + UI on Email admin page)
- Cancel-document mode picker (delete-from-Documenso vs keep-for-audit)
- Dashboard PDF report: 25 widgets, SVG charts, date-range picker, 11 resolvers
- Customize-widgets per-region sortables at xl+ (charts/rails/feed); single
  flat sortable below xl when the layout stacks; per-viewport saved orders
- Audit doc updates capturing each shipped item
- Lint fixes: react-compiler immutability in DonutChart (reduce instead of
  let-reassign), set-state-in-effect disables in CountryFlag and
  UploadForSigning preview-bytes effect, unused 'confirm' destructures in
  interest contract + reservation tabs, unescaped apostrophe in test-template
  card copy
This commit is contained in:
2026-05-23 00:52:59 +02:00
parent 43719b49e9
commit 221ae5784e
749 changed files with 7440 additions and 3118 deletions

View File

@@ -1,23 +1,23 @@
/**
* Sends Documenso-related signing emails:
*
* - `sendSigningInvitation` initial "your turn to sign" email
* - `sendSigningInvitation` - initial "your turn to sign" email
* (one signer at a time). Used both for the first client
* invitation after generation AND for the cascading "your turn"
* emails when an upstream signer completes.
*
* - `sendSigningReminder` follow-up nudge for an unsigned signer.
* - `sendSigningReminder` - follow-up nudge for an unsigned signer.
* Rate-limited at the call site (existing
* `sendReminderIfAllowed`); this just dispatches the email.
*
* - `sendSigningCompleted` sent to all signers (with the signed
* - `sendSigningCompleted` - sent to all signers (with the signed
* PDF attached) when the document reaches fully-signed.
*
* The service handles two transformations the templates can't:
* 1. **Embedded URL wrapping** raw Documenso signing URLs get
* 1. **Embedded URL wrapping** - raw Documenso signing URLs get
* rewrapped to `{embeddedSigningHost}/sign/<type>/<token>` so
* clients sign on a branded page rather than Documenso's domain.
* 2. **Per-port branding lookup** fetches the port's branding
* 2. **Per-port branding lookup** - fetches the port's branding
* config (logo, primary color, header/footer HTML) and threads
* it into the email shell.
*
@@ -54,9 +54,9 @@ export interface SigningInvitationArgs {
recipient: { name: string; email: string };
/** Documenso's raw signing URL (e.g. https://signatures.portnimara.dev/sign/<token>). */
documensoSigningUrl: string;
/** Document type drives subject line and body copy. */
/** Document type - drives subject line and body copy. */
documentLabel: DocumentLabel;
/** Signer role drives copy variant + the embedded URL's role segment. */
/** Signer role - drives copy variant + the embedded URL's role segment. */
signerRole: SignerRole;
/** Optional rep-authored note inserted above the CTA. */
customMessage?: string | null;
@@ -75,7 +75,7 @@ export interface SigningReminderArgs extends Omit<SigningInvitationArgs, 'signer
export interface SigningCancelledArgs {
portId: string;
portName: string;
/** Recipients to notify of the cancellation. Caller decides who
/** Recipients to notify of the cancellation. Caller decides who -
* the rep typically picks a subset of the original signers via the
* cancel-with-notify modal. Empty list = no emails fire (the
* Regenerate flow path). */
@@ -88,7 +88,7 @@ export interface SigningCancelledArgs {
export interface SigningCompletedArgs {
portId: string;
portName: string;
/** All signers each gets the same email + attached signed PDF. */
/** All signers - each gets the same email + attached signed PDF. */
recipients: Array<{ name: string; email: string }>;
/** Display name of the linked client (the deal's primary subject). */
clientName: string;
@@ -126,7 +126,7 @@ export interface SigningCompletedArgs {
* legacy website only routes `client | cc | developer`; approver +
* witness + other all funnel through the `cc` page (which renders the
* same Documenso embed but with passive-recipient copy). See plan
* Risk #5 fixing this mapping prevents an `approver` invite from
* Risk #5 - fixing this mapping prevents an `approver` invite from
* landing on `/sign/error`.
*/
const ROLE_TO_URL_SEGMENT: Record<SignerRole, 'client' | 'cc' | 'developer' | 'witness'> = {
@@ -285,7 +285,7 @@ export async function sendSigningCompleted(args: SigningCompletedArgs): Promise<
{ err, portId: args.portId, recipient: recipient.email },
'Signing-completed email send failed',
);
// Don't throw sending to one recipient shouldn't block the others.
// Don't throw - sending to one recipient shouldn't block the others.
}
}),
),
@@ -294,7 +294,7 @@ export async function sendSigningCompleted(args: SigningCompletedArgs): Promise<
/**
* Notify a subset of signers that an EOI / contract has been cancelled.
* Called by the cancel-with-notify modal empty `recipients` is a
* Called by the cancel-with-notify modal - empty `recipients` is a
* no-op (the Regenerate path, where the rep wants to silently void).
*/
export async function sendSigningCancelled(args: SigningCancelledArgs): Promise<void> {