Refresh the source inventory
Run these commands from the repository root after a frozen dependency install:Preserve Finance route ownership
Finance has 17 workspace pages plus the token verification page. Workspace pages cover the overview, analytics, budgets, categories, debts and debt detail, invoices and invoice creation/detail, promotions, recurring transactions, tags, transactions and transaction detail/categories, and wallets and wallet detail. The 82 local handlers include both/api/workspaces/* and
/api/v1/workspaces/*. Preserve every exported method and unsupported-method
response. The Next configuration sends selected workspace routes to Web before
local route matching and forwards unmatched /api/* requests to Web afterwards.
Port that precedence with the bridge’s guarded forwarding contract. A page
catch-all must never capture an API request.
The codemod reads Finance’s Next configuration and generates central-first.ts
from the reserved Web rewrite definitions. /api/workspaces/invitations reaches
Web before the local /api/workspaces/[wsId] wildcard. The shared handler strips
the mount and preserves method/body/query and each response cookie. Ordinary
Finance routes retain their local handlers. reserved-api.test.ts exercises
that actual dispatch boundary.
The generated app-base.ts, API entry, page route and router register IA-BASE’s
shared resolver in each environment. The client-safe appApiPatterns list and
reserved Web paths decide which API calls gain /finance. Server callbacks read
the incoming request on each call; explicit caller base URLs retain precedence.
api-base.test.ts covers generated registration, Web ownership and interleaved
request isolation. App code does not maintain a competing registrar or RSC
entry wrapper.
start-bridge.config.ts owns Finance’s response security policy. Every response
sends X-Robots-Tag: noindex, nofollow, nosnippet, X-Frame-Options: DENY,
X-Content-Type-Options: nosniff, and Referrer-Policy: strict-origin-when-cross-origin. The CSP includes frame-ancestors 'none'.
The exact shared WebGL asset path is the framing exception:
^/api/v1/workspaces/[^/]+/external-projects/assets/[^/]+/webgl(/|$).
Its upstream sandbox CSP passes through unchanged and Finance removes
X-Frame-Options. Neighbouring paths retain framing denial. Both root hosts
must pass the emitted forwarding and boundary regressions before cutover.
Personalized SSR and API responses use Cache-Control: private, no-store and
vary on Cookie, Authorization and Accept-Language. Compiled static assets keep
their own caching policy. Root hosts are explicitly admitted; unlisted hosts and
apex mounts fail closed.
The codemod creates that config once and preserves its contents on regeneration.
The Worker, router, Vite config, lazy API registry and registration remain
fully generated. API dependencies load on the matching route’s first request.
Refresh the route registries with:
fetchWorkspaces is Finance’s app-owned server action. It calls
fetchSatelliteWorkspaces in the shared satellite package, which reads request
headers and forwards internal API authorization. Convert the complete call path
with the bridge server-function transport. Preserve same-origin CSRF protection,
session admission, and workspace visibility.
The root layout needs replacements for next/root-params, the Next Nuqs
adapter, shared font/metadata helpers, and Vercel analytics. Retain the current
offline provider’s register={false} behavior. The workspace layout reads
request cookies and headers, checks membership and permissions, and renders
async shared components. Verify those components through the bridge page adapter
before expanding their children.
The proxy currently pins Vercel’s __vdpl cookie with Path=/. The native
candidate must leave deployment pinning to the Vercel control path. Do not turn
that cookie into cohort identity or copy it onto the shared origin.
Qualify both Finance URL modes
Root mode atfinance.<host> is the first release gate. Finance disables
workers_dev for its fail-closed root hosts. The sealed artifact and emitted
runtime checks enforce the same setting; staging uses its explicitly admitted
custom hostname. <host>/finance remains
compatibility coverage and does not admit apex traffic. The bridge owns
request-based mount resolution and the shared session model. Preserve the
external prefix on redirects, ordinary links, assets, action requests, and API
calls while matching the internal route once.
All apps on tuturuuu.com use one shared apex session. Finance must not add
an app-specific session cookie name or path. The shared bridge and auth owner
implement that model; app code consumes it. Preserve subdomain behavior until
cutover. Session handover follows the shared bridge contract, with no cross-host
token copy.
A mounted request must retain the shared session during refresh and failure
handling. Signing out on the apex is global. Require independent security
acceptance of the mounted-auth implementation before any apex cutover. Root-mode
session acceptance remains a separate gate. The bridge’s proposal alone does
not qualify authentication behavior.
Acceptance covers English and Vietnamese URLs, anonymous login, cross-app token
verification, refresh and logout, MFA recovery, personal/internal workspace
aliases, invitations, permission denial, and query preservation. Inspect every
Set-Cookie separately. Exercise parallel requests with different users and
workspaces to detect request-context leakage.
Before any hosted staging publish, declare and admit its exact account, Worker,
hostname, bindings and rollback mapping. Finance declares two native profiles in
apps/finance/cloudflare/native-profiles.json, selected at build time with
VITE_FINANCE_NATIVE_PROFILE. Staging is the default: Worker
tuturuuu-finance-vite-staging, root host finance-staging.tuturuuu.com,
INTERNAL_WEB_API_ORIGIN and NEXT_PUBLIC_WEB_APP_URL set to
https://staging.tuturuuu.com, and the staging Supabase URL. production must be
requested explicitly: Worker tuturuuu-finance, root host
finance.tuturuuu.com, Web at https://tuturuuu.com and the production Supabase
URL. Each profile admits only its own root host, so the staging-data Worker
answers 404 for finance.tuturuuu.com and the production Worker answers 404 for
the staging host. Both keep workers_dev off and declare no routes or custom
domains; hostnames are attached by the operator at admission or flip time. The
Vite config pins every NEXT_PUBLIC_* profile value before the browser bundle
is built and fails on a conflicting shell value; production also requires a real
publishable key. The qualifier seals each profile’s identity, rejects the other’s
output, and scans the emitted bundles (source maps excepted) for the other
profile’s Supabase project and, for production, the staging Web origin and host.
It also rejects any bundle that still carries the local development
coordination secret. Secrets
(SUPABASE_SECRET_KEY, TUTURUUU_APP_COORDINATION_SECRET and the Supabase
publishable key) are provisioned on the Worker by the owner, never in source.
Never forward staging tokens to production Web, and never attach the staging
Worker to the production hostname.
Keep global_fetch_strictly_public enabled and verify hosted same-zone SSR
self-fetches reach the Finance Worker, including its public build identity;
the retained Vercel origin must not answer those subrequests. Source configuration alone
does not prove that a hosted staging environment exists. Follow the
Apps artifact and runtime contract
for sealed original/restored artifact and browser acceptance.
Prepare direct cutover and instant rollback
The first Finance release targetsfinance.tuturuuu.com in root mode; Pay
likewise targets pay.tuturuuu.com. Root-mode staging acceptance gates go-live.
Apex-mounted cutover stays held until the shared auth-boundary guard ships and
the user decides the shared-session model. Mounted evidence remains useful
compatibility coverage.
Finance and Pay cut over directly after their gates pass. There is no cohort
selector, staged percentage, minimum session count, or canary operator.
Before the flip, capture the current Vercel deployment, source identity, and
routing configuration. Prepare and verify a single-step command that restores
that deployment and routing. Record who owns that command and the regression
signal that invokes it. Do not flip traffic without a ready rollback.
Finance’s root rollout retains the Vercel CNAME, enables its proxy, and attaches
only finance.tuturuuu.com/* to the admitted Worker. Capture the prior immutable
Vercel deployment and DNS record ID, content, proxy state, and TTL. The rollback
assigns only the Finance hostname to that immutable deployment if necessary
(project-wide promotion is prohibited), removes only the new Finance Worker
route, and restores the captured DNS payload. Keep apex and shared routes out
of this transition; a Custom Domain requires a different rollback plan.
Use the zone-scoped DNS credential for DNS reads/edits and the existing Workers
deploy credential for Worker route reads/edits. Keep the two tokens separate in
capture and rollback clients. Validate provider identities before any write,
keep the original route and DNS record IDs, and reconcile ambiguous responses
with reads before continuing. Persist mutation intent before dispatch in one
host-scoped journal, including outcomes that remain unknown across invocations.
An old or stale read never authorizes replay. Reconcile the original operation
or stop; preserve a campaign-wide request budget. A DNS-only partial cutover may
restore DNS without a route ID only after proving no Finance route or Custom
Domain exists. Require an exclusive provider-writer window and fresh full
identity reads immediately before each write; send conditional updates where
the provider exposes a strong revision. These APIs do not guarantee atomic CAS,
so report that remaining check/write window explicitly.
After cutover, run smoke checks and watch 5xx rates, authentication failures,
and p95 latency for 30 to 60 minutes. Roll back immediately on regression and
report the observed outcome. Keep telemetry free of session tokens, user
identities, and payment data.
Require Pay sandbox acceptance
Pay’s six pages cover the locale root, dashboard, login, token verification, workspace billing, and billing success. Its billing action module exports six functions for billing details, payment methods, billing address, and the customer portal. Preserve each action’s current actor and permission checks. The 26 handlers include payment webhooks, checkout, subscription changes, seat changes, billing invoices, credits, auth, existing cron endpoints, and subscription migration endpoints. Inventory is not authority to invoke those jobs or migrations. Preserve Web fallback and local payment-route precedence. Before staging sign-off, run payment-provider sandbox acceptance for checkout completion/cancellation, signed webhook rejection and replay, subscription and seat changes, billing details, customer portal, and invoice delivery. Reuse the original operation identity when a write outcome is unknown. Do not send live payments or enable live provider bindings to obtain acceptance.Close the migration gates
Before applying a codemod update, inspect its plan for Finance’s app-owned runtime suite, CI caller, and artifact wrapper. Preserve their strict mounted auth and CDP-fence assertions when adopting generated changes. The generated Worker uses the bridge’s portableAssetsBinding; do not substitute DOM or
global Workers request types.
finance-cloudflare.yaml calls the reviewed reusable native Start workflow.
It supplies the Finance artifact wrapper, the native type check, and a bounded
workerd/Chromium acceptance command. The wrapper reuses the Apps seal/restore
implementation with Finance’s Worker identity, public files and
FINANCE_SOURCE_SHA; its source tests reject drift and a generic SHA fallback.
The workflow repeats runtime acceptance after restoring the sealed bytes.
Only exact GET/HEAD /api/build-info are public. The proxy strips ambient
cookies and Authorization before forwarding them and retains the shared API
guard. Other methods and path lookalikes remain protected. The cutover smoke
must compare this endpoint’s commitHash with the sealed artifact’s source SHA.
The emitted suite covers public GET/HEAD build identity, negative method/path
controls, anonymous API denial, signed-in synthetic EN/VI SSR, security headers,
private response caching, function
method/content-type admission, reserved Web routing and separate response
cookies, bilingual auth and verification redirects, wildcard Accept-Language, root-mode
assets and browser navigation. Browser redirects use the existing CDP fence because Playwright
page routing does not intercept every redirect hop. Anonymous host-admission probes send a raw HTTP Host header to the disposable
listener. Functional SSR uses the HTTPS SDK transport; the plain loopback
listener cannot prove HTTPS redirects. SDK fetch defaults must not turn an
apex or unknown host into an admitted root host. Each signed-in fixture accepts credentials only for its configured
Finance origin; cross-host calls stay unadmitted and fail the egress assertion. Every Worker and browser request is bounded and fixture-fenced; the
suite never authenticates to Cloudflare or a real provider. Production token
verification runs on the server, so a missing token redirects and does not
render a public React shell. Signed-in SSR uses synthetic auth, database, profile, overview and transaction-list
responses; it exercises the emitted page adapter without live identities. The
suite does not qualify authenticated UI hydration, Finance operations or hosted
shared-session behavior. Those remain
required staging acceptance, including workspace and mutation flows.
Run exact-head unit, type, lint, and real vp build checks on Sonha through
ttr resources run, then seal the output and transfer it through the M4 for
restored-runtime and browser acceptance on Thanh. Keep its heavy work within
the shared six-ticket and two-build limits; Finance has priority for an admitted
Thanh build slot when required. Install frozen dependencies. Keep the M4 for
editing and focused source checks; it runs no builds, Docker, or local Supabase.
If its check:changed gate refuses admission, run the same committed source
through a Thanh bundle. Never bypass the gate.
An independent Claude review is required before integration. Conversion runs
without --hold, preserving the existing Vercel publisher. No CI workflow
publishes either Finance profile. finance-cloudflare.yaml qualifies both: the
staging job, and a same-repository native-production job that builds with
VITE_FINANCE_NATIVE_PROFILE=production and the PRODUCTION_SUPABASE_PUBLISHABLE_KEY
repository variable. Native deploys are operator actions inside an approved
custody window. The Vercel publisher (vercel-production-finance.yaml) still
runs on production pushes, so freeze production sync for the flip and watch;
a new Vercel deployment would move the alias the DNS-only rollback relies on.
Finance owns its CSP in the app config. Preparation cannot stand in for the real
Start build, provider sandbox, hosted acceptance, or cutover.