Webapp Dead-Surface Trim
Status: Phase 1 + 2a SHIPPED in #2640 (Phase 2b/3 gated on route traffic & SQL checks)
Scope: apps/webapp/src pages + components
Context: apps/docs/src/content/docs/design/inbox-is-the-product.md is
fully rolled out. /inbox (InboxCockpit.tsx) + orders/review-v2 (ReviewResponsiveBody.tsx) inside CockpitShell.astro are the product. Everything below is what the
pre-inbox app left behind.
Validated candidate inventory: 60 files / 11,080 LOC — measured by deleting all of them at once,
running the full unit suite and astro check clean, then reverting. A further ~5.3k LOC is a
candidate behind one SQL answer (Phase 3).
Not all 60 are equally safe, and the inventory is not the shipping unit:
| Files | LOC | Behavior change | Status | |
|---|---|---|---|---|
| Phase 1 + 2a | 40 | ~7,022 | none for the 37 modules; 2 unlinked routes start 404-ing | SHIPPED (#2640) |
| Phase 2b | 19 | ~4,051 | 6 served routes retired | redirect first, delete after traffic check |
The “60” figure is what the analysis found. The “41” is what was safe to ship without traffic data.
Method
Section titled “Method”Grep-by-component-name is not sufficient here — several components read as “in use” because they are mentioned in doc comments, and several pages read as “dead” because their only inbound link is a string built at runtime (an email body, a notification payload). Three independent passes:
- Import-graph BFS (
scratchpad/reach.ts): parse every static/dynamic/export ... fromspecifier in all 941 code files, resolve@/+ relative + barrel + extension-less forms, BFS from all 305 Astro entry points (src/pages/**,src/middleware*,src/actions/index.ts). Anything not visited is unreachable by import. - Route inbound-reference scan (
scratchpad/routes.ts): for each of the 51 page routes, regex the entire monorepo (all apps, all packages, scripts, data-engineering, Python workers, docs) for a link/redirect to that path, with dynamic segments wildcarded. Results split into code / test-only / docs-only. - Runtime string audit — manual read of every place a URL is constructed rather than
imported:
NotificationsDrawer,buildWorkItemReviewUrl,MailingService, the middleware redirect chain, and Temporal notification bodies. This pass is what caught the three false positives below; neither (1) nor (2) alone would have.
Then the whole deletion set was applied for real and validated against tests + astro check.
Corrections to v1 of this plan
Section titled “Corrections to v1 of this plan”| v1 claim | Verified reality |
|---|---|
ConsentManager.astro is dead |
Wrong. Imported by Layout, AuthLayout, PublicLegalLayout. |
QuoteSplitter.tsx is shared with review-v2 — keep |
Wrong, and inverted. 760 LOC, imported only by the dead DocumentOrderReview. QuoteSplitPanel.tsx:10 says outright that it replaces the legacy QuoteSplitter. It is the second-biggest dead file. |
/verify is safe to delete |
Wrong, and would have broken production. MailingService.sendVerificationEmail emails ${selfURL}/verify?token=…, reached from the Clerk webhook → generateAliasesForConnection → VerificationService. Live, external, already-sent links. |
/orders/email/[emailId] is a secondary “Open email” link |
Wrong. buildWorkItemReviewUrl returns /orders/email/${emailEventId} whenever a work item has no pdfDocumentId — it is the primary review destination for email-only items, used by InboxCockpit, cockpit/RowGroup, and SupervisorDetailDrawer. inbound-email.ts creates exactly such work items. |
/orders/[id] only renders pre-inbox orders |
Incomplete. NotificationsDrawer.getNotificationTargetUrl falls back to /orders/${meta.orderId} when a notification has no pdfDocumentId. Deleting the page silently breaks those notifications. |
/action-items → /inbox?lifecycle=needs_fix |
Wrong param. InboxLifecycleView is only active | archived | deleted. needs_fix is a uxState, and the cockpit already renders a needs_fix group (InboxCockpit.tsx:299). The overlap claim holds; the migration is not a lifecycle= value. |
/orders/index.astro redirects to /inbox?lifecycle=submitted |
Dead code. ordersInboxRedirectMiddleware intercepts /orders earlier in the chain and redirects to /inbox?ref=orders_redirect. The page never executes, and its lifecycle=submitted intent is already silently lost. |
| ~14.4k LOC | 11,080 LOC / 60 files, measured. |
Phase 0 — Pre-flight (gates Phase 3 only)
Section titled “Phase 0 — Pre-flight (gates Phase 3 only)”-- Do any orders lack a PDF? These are the ONLY rows /orders/[id] and /orders/edit/[id]-- still render — both already redirect to review-v2 when a pdf_document_id exists.select count(*) from orders o left join extracted_orders e on e.id = o.extracted_order_id where e.pdf_document_id is null;
-- Are there email-only work items? These are the only rows that route to /orders/email/[emailId].select count(*) from work_items where pdf_document_id is null and email_event_id is not null and deleted_at is null;Also pull 90-day PostHog $pageview counts for /action-items, /orders/email/*, /orders/[id],
/admin/flags. Note the caveat in [reference_posthog_three_runtimes_key_gap]: webapp-prod’s
POSTHOG_API_KEY gap means low counts may mean “not instrumented”, not “not used” — treat a zero as
unproven, not as permission.
Phases 1 and 2 need none of this.
Phase 1 — Zero-import orphans (36 files, 6,885 LOC)
Section titled “Phase 1 — Zero-import orphans (36 files, 6,885 LOC)”Unreachable from every Astro entry point. Verified: suite green, astro check clean.
Two need a manual smoke test rather than trust in the graph:
auth/ClerkInitializer.tsx(186) +services/authSync.ts(263) +hooks/useAuth.ts(98) +stores/clerkStore.ts(198).astro.config.mjsmountsclerk(), which injects the clerk-js bootstrap that keeps__sessionfresh, andchrome/AppChrome.astrodocuments that no Clerk island is mounted any more. The old island stack is orphaned. Smoke-test sign-in, sign-out, and org switch before merging — a broken session is not something a unit test will tell you.lib/api/auth-enforcement-anomalies.ts(288) has 19 passing tests and no production caller. It is security-adjacent instrumentation for the default-deny API middleware. 19 tests is not the shape of abandoned code — it is the shape of code someone finished and forgot to wire in. Confirm with whoever wroteapiAuthEnforcementMiddlewarebefore this goes; “dead” and “wired up wrong” look identical from an import graph, and only one of them is safe to delete.
| File | LOC |
|---|---|
components/orders/DocumentOrderReview.tsx — the v1 review page |
1318 |
components/orders/QuoteSplitter.tsx — superseded by review-v2/QuoteSplitPanel |
760 |
components/orders/CustomerProfileCard.tsx |
381 |
components/orders/ResponseDraftDrawer.tsx |
352 |
lib/api/auth-enforcement-anomalies.ts (+ test) |
288 |
components/orders/RetryExtractionButton.tsx |
274 |
services/authSync.ts |
263 |
hooks/useExtractionProgress.ts |
258 |
components/orders/DocumentMetadataCard.tsx |
238 |
components/orders/POHeaderCard.tsx |
210 |
stores/clerkStore.ts |
198 |
components/auth/ClerkInitializer.tsx (+ test) |
186 |
components/orders/AgentValidationBadge.tsx |
132 |
lib/inbox/source-document.ts |
132 |
components/inbox/InboxFeedbackModal.tsx (+ dead POST /api/inbox/feedback) |
129 |
components/orders/OrderTotalsCard.tsx |
121 |
components/ui/ErrorResolutionGuide.tsx |
121 |
components/inbox/InboxKeyboardHelp.tsx — duplicated into settings/sections/ShortcutsSection |
115 |
components/inbox/InboxTabNav.tsx — legacy flag-off surface |
96 |
hooks/useAuth.ts |
98 |
components/inbox/InboxZero.tsx — superseded by InboxEmptyState |
90 |
components/inbox/UploadModal.tsx — cockpit uses InboxUploadForm directly |
85 |
components/customers/CustomersList.tsx |
59 |
utils/errorContext.ts |
59 |
lib/langfuse-search-config.ts |
56 |
utils/customer-profile-meta.ts (+ test) |
56 |
components/ui/DragOverlay.tsx — name-collides with dnd-kit’s, which is the one actually used |
50 |
components/auth/AuthPerformanceMonitor.tsx |
47 |
components/orders/ReviewStatusBadge.tsx |
41 |
components/customers/CustomerDetail.tsx (+ test) |
35 |
components/inbox/cockpit/SkeletonRow.tsx |
15 |
src/tmp.ts — contents: // placeholder |
2 |
Phase 2 — Unlinked pages + their cascade (24 files, 4,172 LOC)
Section titled “Phase 2 — Unlinked pages + their cascade (24 files, 4,172 LOC)”Pages with zero inbound reference anywhere in the monorepo, plus the components that become
unreachable once they go. Verified with Phase 1: suite green, astro check clean, cascade stable
after one round.
Codex review changed this phase. An independent adversarial pass (review report) correctly attacked the word “delete”: an Astro page with no inbound link is still a served, functioning route for anyone who types or bookmarks the URL. Static analysis proves nothing renders a link to it; it does not prove nobody visits it. Phase 2 is therefore split into 2a (genuinely no surface to lose) and 2b (redirect via middleware, do not delete).
2a. Delete — nothing to reach
Section titled “2a. Delete — nothing to reach”| Page | LOC | Evidence |
|---|---|---|
erp/customers/index.astro |
63 | No inbound link, and its onSelectCustomer handler is a console.log — the page cannot complete its own task. |
thank-you.astro |
27 | Waitlist-era. Zero references anywhere, including email code. |
erp/edit-connection/[id].astro |
7 | Withdrawn — do not delete. It reads as an unlinked stub, but it is the only thing 301-ing old bookmarks to /admin/edit-connection/:id, which is still a live page. Deleting it orphaned that page (routes.ts reported /admin/edit-connection/[id] as NO-REF immediately after), for a 7-line gain. Restored. |
erp/connections.astro |
4 | 301 → /admin/connections. Fold into the middleware chain instead of a page file. |
orders/index.astro |
3 | Shadowed by ordersInboxRedirectMiddleware — never executes. |
2b. Redirect, do not delete — functioning routes with no inbound link
Section titled “2b. Redirect, do not delete — functioning routes with no inbound link”Each of these still authenticates, queries, and renders. Add a middleware 301 to the sensible destination and delete the page + its cascade only after Phase 0 shows no traffic.
| Page | LOC | Why it is not a free delete | Redirect to |
|---|---|---|---|
organizations/[orgId]/members/index.astro |
584 | Its feature gate is getFeatureFlag('org_members_enabled', Astro.locals) || true (line 39) — forced on, so the flag is dead code and the page is always live. It fetches members server-side and renders working management rows. |
/settings?section=users |
orders/new.astro |
543 | Live ERP write path. POST /api/erp/orders at line 414, with upload/customer/shipping/item islands hydrated. Nothing intercepts /orders/new — ordersInboxRedirectMiddleware is an exact-match guard on /orders only (line 5), which is why it passes through, not an intentional allowance. Given the repo rule that ERP writes stay flag-gated, removing a write surface deserves the same care as adding one. |
/inbox |
orders/wherefour-submit.astro |
56 | Gated on wherefour-order-validation, a flag registered in the deployed Flagsmith config, whose description names this exact route (infrastructure/flagsmith/configs/flags.json:398). Check Flagsmith for per-org overrides before assuming CK/WhereFour isn’t using it. |
retire flag first, then page |
orgs/[slug]/pipeline.astro |
~40 | Resolves the Clerk org and hydrates PipelineDashboard, which calls /api/orgs/[slug]/pipeline-metrics. A working ops page. |
/analytics or delete with the API |
sys-admin/revenue-leaks.astro |
~130 | Reachable whenever the sys-admin gate passes (middleware.ts:625, :646); does authenticated DB work and records a page view. |
/sys-admin |
error.astro |
24 | Reads Astro.props.status, which Astro never supplies for a page — so it always renders the generic branch. But /error is still a served route. |
/404 |
Keep the /api/organizations/[orgId]/members endpoint regardless — packages/ui/src/components/sys-admin/OrganizationMembers.tsx calls it.
Cascade (components orphaned once 2a+2b pages go): CustomerSearch · ItemSearch ·
ItemSearchResultRow · components/OrderItemsList · ShippingAddressSelector (+ test) ·
integrations/WhereFourValidateOrder · orders/DocumentUpload · orders/OrderCreationTabs ·
pipeline/PipelineDashboard · ui/MemberRow · types/item.ts
Do NOT delete — verified live and shared with review-v2 / cockpit:
PDFViewerWithHighlights, ImageViewerWithHighlights, SpreadsheetFullView, CSVPreview,
TextPreview, EmailPreview, PrintDocButton, modals/CustomerSearchModal,
modals/ShippingSearchModal, modals/SearchModalShell, actions/orderActions.ts,
TrashReasonModal, ui/LockedControl, BulkResolveModal, ConsentManager.astro.
Must stay — live email-borne flow: verify.astro. See the corrections table.
Precedent for how to retire a route
Section titled “Precedent for how to retire a route”middleware.ts already has three of these: legacyOrganizationPageRedirectsMiddleware (ENG-57),
notificationsPageRedirectMiddleware (ENG-50), ordersInboxRedirectMiddleware (ENG-61). Follow that
pattern — a 301 in the chain, not a stub .astro file whose redirect the middleware then shadows
(which is exactly the bug orders/index.astro is). Add entries for any retired path with plausible
bookmarks; skip it for paths nothing ever linked.
Phase 3 — Live-but-redundant surfaces (needs decisions, ~6.7k LOC)
Section titled “Phase 3 — Live-but-redundant surfaces (needs decisions, ~6.7k LOC)”Each of these is genuinely reachable. Do not batch them with Phase 1–2.
3a. Manual-order path — /orders/[id] + /orders/edit/[id] + the OrderEditor tree (5,279 LOC)
Section titled “3a. Manual-order path — /orders/[id] + /orders/edit/[id] + the OrderEditor tree (5,279 LOC)”Both pages redirect to review-v2 when the order has a PDF, so this tree only renders PDF-less
orders. It is reachable two ways: NotificationsDrawer’s metadata.orderId fallback, and
/orders/[id]’s own “Edit” link.
Correction (2026-07-30): the second reachability path does not hold — /orders/[id].astro’s
“Edit” <a href={/orders/edit/${order.id}}> is commented out (git blame: 6f15683edb,
2025-05-09, “fixing order viewer page”), 4 days after 4f6190c21 (2025-05-05) gutted
OrderEditor.tsx’s manual-mode support down to PDF-only. Grepping the whole repo for
orders/edit today finds zero live inbound references — only that dead comment and two unrelated
code comments. Two further findings from the same investigation, both consistent with this tree
being unreachable in practice, neither proving it on their own:
OrderEditor.tsx’smode/initialOrderprops (still declared inOrderEditorProps, the only remnant of the pre-4f6190c21dual-mode design) are dead — never destructured or read anywhere in the component body.orders/edit/[id].astrostill passesmode="manual" initialOrder={order}into them for nothing.- Even if a user reaches
/orders/edit/[id]by typed/bookmarked URL,OrderEditorreadsstores/pdfOrder’seditingOrderatom (not theinitialOrderprop), which is only ever populated viaselectedOrderId’s listener againstextractedOrders— both populated by review-v2’s PDF-document data flow, never by this route. So todayOrderEditoritself renders “No order selected or order not found” here regardless of whatdb.query.orders.findFirstfetched server-side;modals/ManualItemSearchModal(which reads the separate, likewise never-populatedstores/orderEditStore) is doubly so. modals/ItemSearchModal(distinct from review-v2’smodals/ERPSearchModal) has exactly one importer repo-wide:OrderEditor.tsx. It is not an independent “also used elsewhere” component — it lives or dies with this same tree.
None of this proves nobody ever hits /orders/edit/[id] (a stale bookmark or search-index entry
still resolves it), which is exactly what Phase 0 query 1 is for — it’s stronger evidence the
answer will come back 0, not a substitute for running it. Do not delete on the strength of this
alone.
If Phase 0 query 1 returns 0: change getNotificationTargetUrl to resolve the review URL (or return
null), redirect both routes to /inbox, delete the tree — OrderEditor (460),
CustomerInfoSection, ShippingInfoSection, OrderActionButtons, BillingAddressSearch,
SkippedItemsNotification, SubscriptionLimitWarning, OrderStatusAndValidation,
OrderSuccessNotification, orders/OrderItemsList, orders/OrderItemCard,
orders/OrderItemDiscountMatching, modals/ItemSearchModal, modals/ManualItemSearchModal,
modals/BaseSearchModal, stores/orderEditStore, stores/orderStore.
If non-zero: leave it. This is the only surface that can open those rows.
Nit either way: stores/orderStore.ts survives Phase 2 solely because
modals/ShippingSearchModal.tsx:26 does import type { Address } from it. Move the type to
types/ and the store is free.
3b. /action-items (147 + ActionItemsStack 210)
Section titled “3b. /action-items (147 + ActionItemsStack 210)”ActionItemsStack’s own header comment states it uses the inbox’s buildWorkItemInboxConditions and
uxStateSql() (filtered in SQL by loadActionItems in lib/inbox/action-items.ts), and that V1 is “five uxState
groups + a basic count” with bulk-select “in a follow-up” that never shipped. The cockpit already
renders needs_fix, needs_review and failed as groups; the page’s Price review group is the
needs_review rows that have an extracted order.
Its UX_STATE_GROUPS also includes awaiting_ref_data and awaiting_approval, which the UxState
union never defined — those two groups render empty, permanently.
Recommend: delete both, point the rail entry at /inbox. If a deep-link to the needs-fix group
is wanted, add a ?group=needs_fix param to the cockpit (it already tracks per-group collapse
state) — do not invent a lifecycle= value; that enum is storage-level.
3c. /orders/email/[emailId] (587 + EmailSenderBar + InboxDetailActions 497)
Section titled “3c. /orders/email/[emailId] (587 + EmailSenderBar + InboxDetailActions 497)”Load-bearing — do not delete as written in v1. It is where buildWorkItemReviewUrl sends any
work item without a pdfDocumentId, and api/webhook/inbound-email.ts creates work items with
emailEventId and no PDF. Retiring it means first giving email-only items a review surface inside
the cockpit. That is a feature, not a cleanup. Gate on Phase 0 query 2.
3d. /admin/flags — unlinked but working (FlagsConsole + FeatureFlagDashboard + OrgFeatureFlags, ~850 LOC)
Section titled “3d. /admin/flags — unlinked but working (FlagsConsole + FeatureFlagDashboard + OrgFeatureFlags, ~850 LOC)”Reachable only by typing the URL: admin/index.astro links analytics/billing/connections/roi/usage
and not flags. (/sys-admin/flags in SysAdminLayout is a different, proxied surface.)
Recommend adding the link, not deleting the console — it is functioning org-scoped flag tooling
and one <a> is cheaper than 850 LOC of rebuild later.
3e. Supervisor lenses — leave alone
Section titled “3e. Supervisor lenses — leave alone”/team offers Table (ConservativeInbox, 547) and Kanban (SupervisorKanban, 583) via
ViewSwitcher. Both wired, both reachable. Pull view-switch counts before touching either; do not
guess.
Phase 4 — Dead endpoints
Section titled “Phase 4 — Dead endpoints”Zero callers monorepo-wide (webapp, apps/internal, Python + TS Temporal workers, ops-mcp,
scripts, playwright):
GET/PUT /api/work-items/sla-policy+/sla-policy-historyPOST /api/alias/new-memberPOST /api/erp/tokenPOST /api/inbox/feedback(Phase 1 removes its only would-be caller)POST /api/billing/report-usage(docs-only references)POST /api/orders/generate-email-body-pdf— and it is inauth-allowlist.tsas “Runtime-public — stateless PDF generation”. An unauthenticated, uncalled PDF generator is attack surface for nothing. Highest-value item in this phase despite being the smallest.
Non-code dead weight found by the Codex pass (all four verified):
components/inbox/inbox-email-list.css— imported by nothing; its selectors appear only in itself. Missed by the import BFS, which only walked.ts/.tsx/.astro/.js.- Unused deps in
apps/webapp/package.json:@astrojs/partytown(line 33 — and Partytown is absent fromastro.config.mjs’s integration list),mupdf(85),pdf-parse(88),@types/pdf-parse(133). The onlymupdf-ish hits in the repo are Pythonpymupdf, a different package. - Dead feature flag
org_members_enabled— read atorganizations/[orgId]/members/index.astro:39and immediately|| true’d. Retire it in Flagsmith when 2b lands.
Explicitly keep — these look dead from webapp alone but have external callers:
/api/work-items/dashboard, /api/work-items/test-order, /api/work-items/supervisor-actions,
/api/admin/system-stats, /api/admin/unblock-ip (called by apps/internal),
/api/admin/generate-aliases (apps/internal + playwright),
/api/erp/orders/filter-invalid (apps/temporal-worker/activities/agentic_validation.py),
/api/auth/organization (packages/auth), /api/trigger/*, /api/organizations/[orgId]/members.
Phase 5 — Stop it regrowing
Section titled “Phase 5 — Stop it regrowing”Add knip to apps/webapp and run it in the existing lint job.
pnpm --filter @repo/webapp add -D knipConfig: entry: ["src/pages/**/*.{astro,ts}", "src/middleware.ts", "src/actions/index.ts"],
project: ["src/**"]. Ship it warn-only first — a red gate on day one gets the tool disabled
instead of used. Promote to error once Phases 1–2 land and the baseline is zero.
knip replaces pass (1) of the Method above. It does not replace passes (2) and (3): it cannot
see a route referenced only from an email body, a notification payload, a Flagsmith flag
description, or another app. Those need the route scan, and the route scan needs a human reading the
runtime string-builders — which is where all three of v1’s false positives lived. Say so in the PR
description so the next person doesn’t trust the tool further than it goes.
Also configure knip to include .css — the BFS here missed inbox-email-list.css for exactly that
reason.
Ordering and risk
Section titled “Ordering and risk”| Phase | Files | LOC | Risk | Gate |
|---|---|---|---|---|
| 1 | 36 | 6,885 | very low (proven) | suite + astro check + sign-in/out/org-switch smoke test; confirm auth-enforcement-anomalies was abandoned deliberately |
| 2a | 5 | ~104 | very low (proven) | suite + astro check |
| 2b | 19 | ~4,068 | medium | Phase 0 traffic check per route; middleware 301 lands before the page is deleted; Flagsmith override check for wherefour-order-validation |
| 3a | ~19 | 5,279 | medium | Phase 0 query 1 == 0; patch getNotificationTargetUrl first |
| 3b | 2 | 357 | low | product call |
| 3c | — | — | do not do yet | needs an in-cockpit surface for email-only items |
| 3d | 0 | +1 line | none | add the link |
| 4 | ~7 + 4 deps + 1 CSS | small | low | re-grep monorepo per route at merge time |
| 5 | +1 dep | — | none | warn-only |
Phase 1 + 2a ship as one PR (~7k LOC, both proven, zero reachable surface). Base staging.
2b is a second PR: redirects first, deletions after traffic confirms zero. Phase 3 is three
more.
The methodological lesson worth carrying forward: three passes found 11k LOC and still produced five overstated calls, because “no code links here” and “nobody goes here” are different claims. Only Phase 0’s traffic data settles the second one.
Reproducing the analysis
Section titled “Reproducing the analysis”Both scripts are checked in under scripts/dead-surface/ (~80 lines each, bun, no deps):
bun run scripts/dead-surface/reach.ts "$PWD/apps/webapp" # import-graph BFS → unreachable filesbun run scripts/dead-surface/routes.ts "$PWD" # per-route inbound refs, monorepo-widereach.ts should report 0 unreachable at any commit where this plan’s shipped phases are complete —
it is a cheap regression check until Phase 5’s knip gate lands. routes.ts has no tool equivalent
and is the one Phase 2b needs again, which is why both are tracked rather than left in a scratchpad.
Note the classifier hole that cost this analysis a false positive: routes.ts buckets hits by file
extension and drops anything outside its code/test/docs sets, which is how a route named in
infrastructure/flagsmith/configs/flags.json went unreported. Widen CODE_EXT before trusting a
NO-REF verdict on a config-referenced path.
The verification run: apply the deletion set, then
cd apps/webapp && bash ../../scripts/with-native-node.sh npx vitest run && bash ../../scripts/with-native-node.sh npx astro checkTest counts. Three different deletion sets were measured, so the numbers differ; the baseline row is the one an earlier draft of this document got wrong by reusing a post-deletion figure.
| Run | Deletion set | Test files | Tests passing | astro check |
|---|---|---|---|---|
Baseline (measured at b57c939c6) |
none | 249 | 2545 | 0 errors |
| Phase 1 + 2a (shipped) | 41 files | 245 | 2510 | 0 errors, 0 warnings |
| Full inventory (trial, reverted) | 60 files | 244 | 2507 | 0 errors, 0 warnings |
Phase 1 + 2a removes 4 whole test files, and the 35-test drop is exactly their contents:
auth-enforcement-anomalies 19 + ClerkInitializer 7 + customer-profile-meta 6 +
CustomerDetail 3 = 35, and 2545 − 2510 = 35. No surviving test changed behavior. The
full-inventory trial drops 3 further tests because Phase 2b also removes
ShippingAddressSelector.test.tsx.
Worth naming: 19 of those 35 tests covered lib/api/auth-enforcement-anomalies.ts. A module with
19 tests and no production caller is a stronger “someone meant to wire this up” signal than a module
with none — see the Phase 1 note asking for confirmation before it goes.
What this does not touch
Section titled “What this does not touch”admin/* (except the flags link), sys-admin/*, settings, analytics, audit, customers,
missed-orders, revenue-leaks, team, support, inbox, orders/pdf/*/review, billing, auth,
onboarding, and legal pages are all reachable and current. /analytics vs /admin/analytics vs
/admin/roi do overlap conceptually, but all three are linked and maintained — consolidating them
is a design question, not fat to trim.
GSTACK REVIEW REPORT
Section titled “GSTACK REVIEW REPORT”| Review | Trigger | Why | Runs | Status | Findings |
|---|---|---|---|---|---|
| CEO Review | /plan-ceo-review |
Scope & strategy | 0 | not run | — |
| Codex Review | /codex review |
Independent 2nd opinion | 1 | issues_found | 8 findings (6 P1, 2 P2), 8/8 folded in |
| Eng Review | /plan-eng-review |
Architecture & tests (required) | 0 | not run | — |
| Design Review | /plan-design-review |
UI/UX gaps | 0 | not run | — |
| DX Review | /plan-devex-review |
Developer experience gaps | 0 | not run | — |
CODEX: Attacked the framing, not the arithmetic. Confirmed all three load-bearing findings
(orders/email/[emailId] via work-item-review-url.ts, orders/[id] via NotificationsDrawer,
verify.astro via mailing-service.ts), found no false positive in Phase 1, and found no
glob/island loader reviving any Phase 1 module. Its real contribution: five Phase 2 pages were
labelled deletable on the strength of “no inbound link”, when each is a served, authenticating,
rendering route — orders/new is a live POST /api/erp/orders write path, and
wherefour-submit’s flag is named by description in the deployed Flagsmith config
(flags.json:398), which the route scan dropped because .json fell outside its code/test/docs
classifier. Phase 2 is now split 2a (delete) / 2b (redirect first, delete after traffic data). Also
surfaced three non-code items the import BFS structurally could not see: an unimported CSS file,
four unused npm deps, and the always-true org_members_enabled flag.
One Codex sub-claim does not hold: orders-inbox-redirect.ts:5 does not “explicitly pass
/orders/new through” — it is an exact-match guard on /orders, so the pass-through is incidental,
not intentional. The conclusion (the route is served) is right; the stated reason is not.
VERDICT: Phase 1 + 2a is CONDITIONALLY CLEARED in
#2640 — automated evidence is complete (2510
of 2545 baseline tests passing, the 35-test delta accounted for file-by-file above; astro check 0
errors, 0 warnings; Codex, CodeRabbit and Devin all raised zero objections to the deletion set
itself). Three prerequisites are not met and are merge blockers, not follow-ups:
- Sign-in / sign-out / org-switch smoke test — not run. The Clerk island removal is not covered by any test.
- Author confirmation that
lib/api/auth-enforcement-anomalies.ts(19 tests, 0 callers, security-adjacent) was abandoned deliberately. - Eng review — not run.
Phase 2b downgraded from “delete” to “redirect, then delete after traffic check”. Eng review also required before Phase 3.
UNRESOLVED DECISIONS:
- Phase 0 SQL + PostHog traffic data not yet pulled — gates 2b and 3a.
- Whether
lib/api/auth-enforcement-anomalies.tswas abandoned deliberately or never wired up (security-adjacent; needs the author ofapiAuthEnforcementMiddleware). - Flagsmith per-org override state for
wherefour-order-validation— blocks retiringorders/wherefour-submit. - 3b (
/action-itemsretirement) and 3d (/admin/flagslink) are product calls, not yet made.