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:
@@ -21,7 +21,7 @@ export async function resolvePortIdFromSlug(slug: string): Promise<string | null
|
||||
if (!inFlightPortsLookup) {
|
||||
inFlightPortsLookup = (async () => {
|
||||
try {
|
||||
// A17: use /me/ports — works for every authenticated user.
|
||||
// A17: use /me/ports - works for every authenticated user.
|
||||
// The prior code hit /admin/ports which is super-admin-gated, so
|
||||
// sales-reps/viewers fired a wasteful 400 on every page load.
|
||||
const res = await fetch('/api/v1/me/ports', { credentials: 'include' });
|
||||
@@ -46,7 +46,7 @@ export async function resolvePortIdFromSlug(slug: string): Promise<string | null
|
||||
* Client-side fetch wrapper that attaches the `X-Port-Id` header to
|
||||
* every request.
|
||||
*
|
||||
* multi-port-auditor C1: the URL slug is authoritative — Zustand
|
||||
* multi-port-auditor C1: the URL slug is authoritative - Zustand
|
||||
* is a cache that lags by one render after `PortProvider`'s reconcile
|
||||
* effect commits. The previous Zustand-first lookup caused first-load
|
||||
* queries on a freshly-navigated port to fire with the PRIOR port's
|
||||
@@ -65,7 +65,7 @@ export async function apiFetch<T = unknown>(url: string, opts: ApiFetchOptions =
|
||||
}
|
||||
}
|
||||
|
||||
// Fall back to the Zustand cache when the URL didn't yield a port —
|
||||
// Fall back to the Zustand cache when the URL didn't yield a port -
|
||||
// e.g. global routes (/dashboard) where the rep hasn't picked a port
|
||||
// yet but a previous session set one.
|
||||
if (!portId) {
|
||||
@@ -147,7 +147,7 @@ export async function apiFetch<T = unknown>(url: string, opts: ApiFetchOptions =
|
||||
* `/admin/errors/<requestId>`
|
||||
*
|
||||
* Mutations should use the `toastError(err)` helper rather than reading
|
||||
* these fields directly — that keeps the toast format consistent.
|
||||
* these fields directly - that keeps the toast format consistent.
|
||||
*/
|
||||
export class ApiError extends Error {
|
||||
status: number;
|
||||
|
||||
@@ -156,7 +156,7 @@ export function withAuth<TParams extends RouteParams = Record<string, string>>(
|
||||
// 3. Resolve port context. Port id comes from the X-Port-Id
|
||||
// header (set by the client after port selection), falling
|
||||
// back to the user's default port preference. NEVER from the
|
||||
// request body — SECURITY-GUIDELINES.md §2.1.
|
||||
// request body - SECURITY-GUIDELINES.md §2.1.
|
||||
const portIdFromHeader = req.headers.get('X-Port-Id');
|
||||
const portId =
|
||||
portIdFromHeader ??
|
||||
@@ -283,7 +283,7 @@ export function withAuth<TParams extends RouteParams = Record<string, string>>(
|
||||
/**
|
||||
* Throws ForbiddenError when the caller is not a super-admin. Use inside
|
||||
* route handlers (after withAuth) for endpoints that mutate global, cross-
|
||||
* tenant state — global roles, cross-port migrations, system jobs.
|
||||
* tenant state - global roles, cross-port migrations, system jobs.
|
||||
*
|
||||
* Logs the denied attempt to the audit trail (mirrors withPermission).
|
||||
*/
|
||||
@@ -393,8 +393,8 @@ export function withRateLimit(name: RateLimiterName, handler: RouteHandler): Rou
|
||||
// ─── withPublicContext ───────────────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
* Wraps a public (unauthenticated) route — webhooks, health checks,
|
||||
* public APIs — so it runs inside the same `runWithRequestContext` ALS
|
||||
* Wraps a public (unauthenticated) route - webhooks, health checks,
|
||||
* public APIs - so it runs inside the same `runWithRequestContext` ALS
|
||||
* frame that `withAuth` installs for authenticated routes. Without this
|
||||
* frame, `captureErrorEvent`, `getRequestId`, and the logger's request-id
|
||||
* mixin silently no-op for these endpoints, leaving webhook failures
|
||||
@@ -403,7 +403,7 @@ export function withRateLimit(name: RateLimiterName, handler: RouteHandler): Rou
|
||||
* Top-level errors thrown by the handler are forwarded to
|
||||
* `captureErrorEvent` (so they surface in admin/errors) and re-raised
|
||||
* so Next's runtime can return a 500. Webhook handlers that prefer to
|
||||
* always-return-200 can catch internally — this wrapper only catches the
|
||||
* always-return-200 can catch internally - this wrapper only catches the
|
||||
* uncaught path.
|
||||
*/
|
||||
export function withPublicContext(
|
||||
|
||||
@@ -24,7 +24,7 @@ export function parseQuery<T extends ZodSchema>(req: NextRequest, schema: T): z.
|
||||
* H-14: tolerates empty request bodies (content-length 0 or req.json()
|
||||
* throwing on an empty stream) by substituting `{}` so DELETE/PATCH
|
||||
* routes whose schemas have all-optional fields don't crash with a
|
||||
* 500 — the schema's own optionality decides whether the empty object
|
||||
* 500 - the schema's own optionality decides whether the empty object
|
||||
* is a valid input.
|
||||
*/
|
||||
export async function parseBody<T extends ZodSchema>(
|
||||
@@ -53,7 +53,7 @@ export function clientIp(req: NextRequest): string {
|
||||
|
||||
/**
|
||||
* Wraps an unauthenticated route handler with a per-IP (or per-key) rate
|
||||
* limit. Used for portal/auth endpoints that have no session yet — the
|
||||
* limit. Used for portal/auth endpoints that have no session yet - the
|
||||
* `withRateLimit` helper in api/helpers.ts is keyed on `ctx.userId` and
|
||||
* cannot apply here.
|
||||
*
|
||||
|
||||
@@ -5,7 +5,7 @@ import { toast } from 'sonner';
|
||||
import { ApiError } from '@/lib/api/client';
|
||||
|
||||
/**
|
||||
* Build a multi-line string suitable for an inline form banner — the
|
||||
* Build a multi-line string suitable for an inline form banner - the
|
||||
* primary message followed by `Error code:` / `Reference ID:` lines when
|
||||
* the error is an ApiError. Use from admin forms that want to keep
|
||||
* their inline error UX instead of switching to a toast.
|
||||
|
||||
Reference in New Issue
Block a user