# TokNext Codex to Claude Code Handoff

This is the authoritative handoff from Codex back to Claude Code for the TokNext production project.

Do not treat older phase notes as more current than this file. Read the code and re-check production state before changing anything.

## 1. Repository State

- Branch: `main`
- Repository remote: `origin https://github.com/alainarriola/Toknext.git`
- Current code commit before this documentation-only handoff commit: `a3d95691c66a0f45188eeabbb2c259b3d2750507`
- Latest pushed code commit before this handoff: `a3d95691c66a0f45188eeabbb2c259b3d2750507`
- Latest Phase 8 intelligence commit: `4fcdb5e feat: continue Phase 8 intelligence surfaces`
- Latest Phase 8 hardening commit: `a3d9569 fix: harden TikTok OAuth state validation`
- Working tree before creating this document: clean and synchronized with `origin/main`
- Production domain: `https://toknext.com`
- Production server path: `/home/toknext/public_html/app/toknext-next`
- PM2 process name: `toknext`
- PM2 start command: `/usr/bin/bash -c PATH=/opt/node20/bin:$PATH PORT=3001 npm run start`
- Production Node runtime: `/opt/node20/bin/node` (`v20.19.0`)
- PM2 `node env` field: `N/A`; the app is served by `next start`, which runs the production Next.js server.
- Deployed code commit: `a3d9569` via source archive. The production release directory is not a git checkout.
- This handoff commit is documentation-only and must not be assumed deployed unless a future operator explicitly deploys it.

## 2. Architecture Summary

- Next.js `16.2.11`, App Router, route groups under `src/app`.
- React `19.2.4`.
- TypeScript with strict project settings and path alias `@/*`.
- Prisma `6.19.3` with PostgreSQL. Schema is in `prisma/schema.prisma`; migrations are forward-only in `prisma/migrations`.
- Auth.js / NextAuth v5 beta with Prisma adapter. Auth config lives in `src/auth/`; protected app routes use middleware/proxy plus server-side `auth()` checks.
- Stripe Billing is server-side only: `src/lib/stripe/`, `src/config/plans.ts`, and `/api/stripe/webhook`. Checkout always resolves Price IDs from environment variables, never from client input.
- TikTok Shop integration uses official Partner API routes and clients under `src/lib/tiktok/` and `src/lib/product-data/providers/tiktok-provider.ts`. OAuth routes are `/api/auth/tiktok/connect`, `/api/auth/tiktok/callback`, and `/api/auth/tiktok/disconnect`.
- Product ingestion is provider-neutral: demo, CSV, JSON, and TikTok all flow through `src/lib/product-data/ingest.ts`, normalized provider contracts, `DataSource`, `Product`, `ProductMetricSnapshot`, and related tables.
- Scoring architecture is mostly pure functions in `src/lib/scoring/`; DB-facing recalculation is isolated in `src/lib/scoring/recalculate.ts`. `ProductScore` stores current values and `ProductScoreHistory` is append-only.
- Phase 8 dashboards are DB-backed:
  - Market Explorer: `/dashboard/products`
  - Store Intelligence: `/dashboard/stores`, `/dashboard/stores/[storeId]`
  - Creator Intelligence: `/dashboard/creators`, `/dashboard/creators/[creatorId]`
  - Dashboard overview: `src/database/dashboard.ts` plus `src/components/dashboard/dashboard-overview.tsx`
- Scheduler route: `GET /api/cron/sync`, Bearer-protected by `CRON_SECRET`, with advisory lock, TikTok sync, token refresh sweep, score recalculation, cleanup, and structured logs.
- Deployment: Apache reverse proxy on cPanel/AlmaLinux VPS routes HTTPS to PM2 on local port `3001`. PM2 process `toknext` runs the Next.js production server. `cellcuba` is a separate PM2 process and must not be restarted for TokNext work.

## 3. Work Completed by Codex

Phase 8 code is split mainly across these commits:

### `65ea4d0 feat: add Phase 8 intelligence scoring`

Created:
- `prisma/migrations/20260725000000_add_phase8_intelligence/migration.sql`
- `src/lib/scoring/risk.ts`
- `src/lib/scoring/risk.test.ts`
- `src/lib/scoring/stability.ts`
- `src/lib/scoring/stability.test.ts`
- `src/lib/scoring/velocity.ts`
- `src/lib/scoring/velocity.test.ts`
- `src/lib/tiktok/metrics.ts`

Modified:
- `prisma/schema.prisma`
- `src/app/admin/data-sources/page.tsx`
- `src/app/api/auth/tiktok/callback/route.ts`
- `src/app/api/auth/tiktok/disconnect/route.ts`
- `src/components/admin/tiktok-connection-card.tsx`
- `src/database/product-scores.ts`
- `src/lib/i18n/translations.ts`
- `src/lib/product-data/ingest.ts`
- `src/lib/product-data/providers/csv-provider.ts`
- `src/lib/product-data/providers/demo-provider.ts`
- `src/lib/product-data/providers/json-provider.ts`
- `src/lib/product-data/providers/tiktok-provider.ts`
- `src/lib/product-data/providers/types.ts`
- `src/lib/scoring/config.ts`
- `src/lib/scoring/explanation.ts`
- `src/lib/scoring/explanation.test.ts`
- `src/lib/scoring/recalculate.ts`
- `src/lib/scoring/recalculate.test.ts`
- `src/lib/scoring/trend.test.ts`
- `src/lib/scoring/types.ts`
- `src/lib/tiktok/client.ts`
- `src/lib/tiktok/sync.ts`

Meaningful changes:
- Added Phase 8 scoring dimensions: growth velocity, demand acceleration, risk, competition trend, stability-related logic.
- Added TikTok metrics plumbing that fails soft until verified against a real seller.
- Extended official TikTok data model and ingestion shape.
- Extended tests for new scoring components.

### `4fcdb5e feat: continue Phase 8 intelligence surfaces`

Created:
- `prisma/migrations/20260725010000_add_phase8_market_indexes/migration.sql`
- `src/app/(dashboard)/dashboard/creators/[creatorId]/page.tsx`
- `src/app/(dashboard)/dashboard/stores/page.tsx`
- `src/app/(dashboard)/dashboard/stores/[storeId]/page.tsx`
- `src/components/dashboard/creators-page-content.tsx`
- `src/components/dashboard/stores-page-content.tsx`
- `src/database/creators.ts`
- `src/database/dashboard.ts`
- `src/database/stores.ts`
- `src/lib/scheduler/locks.ts`
- `src/lib/scheduler/locks.test.ts`
- `src/lib/scheduler/maintenance.ts`
- `src/lib/scheduler/retry.ts`
- `src/lib/scheduler/retry.test.ts`
- `src/lib/trends/engine.ts`
- `src/lib/trends/engine.test.ts`

Modified:
- `PROJECT_STATE.md`
- `README.md`
- `prisma/schema.prisma`
- `scripts/deploy.sh`
- `src/app/(app)/account/page.tsx`
- `src/app/(app)/profile/page.tsx`
- `src/app/(dashboard)/dashboard/billing/page.tsx`
- `src/app/(dashboard)/dashboard/creators/page.tsx`
- `src/app/(dashboard)/dashboard/page.tsx`
- `src/app/(dashboard)/dashboard/products/page.tsx`
- `src/app/(dashboard)/dashboard/products/[productId]/page.tsx`
- `src/app/(dashboard)/dashboard/saved/page.tsx`
- `src/app/admin/data-sources/page.tsx`
- `src/app/admin/imports/page.tsx`
- `src/app/admin/products/page.tsx`
- `src/app/api/cron/sync/route.ts`
- `src/components/dashboard/dashboard-nav.tsx`
- `src/components/dashboard/dashboard-overview.tsx`
- `src/components/dashboard/products-page-content.tsx`
- `src/database/products.ts`
- `src/lib/i18n/translations.ts`
- `src/lib/product-data/providers/registry.ts`
- `src/lib/product-data/view-models.ts`
- `src/lib/tiktok/client.ts`
- `src/lib/tiktok/oauth.ts`
- `src/lib/tiktok/sync.ts`

Meaningful changes:
- Implemented Market Explorer filters and allowlisted DB-backed sorting.
- Added Store Intelligence list/detail pages and database access.
- Added Creator Intelligence list/detail pages and database access.
- Added deterministic Trend Engine utilities and tests.
- Rewired dashboard overview and several dashboard pages to live DB data.
- Added scheduler advisory locking, retry/backoff, cleanup, token refresh sweep, and per-connection TikTok sync isolation.
- Added forward-only performance indexes for Phase 8 query paths.
- Updated deployment script to use full `npm ci` because Next/Tailwind/Prisma build flow depends on dev dependencies being installed on the VPS.

### `a3d9569 fix: harden TikTok OAuth state validation`

Created:
- `src/lib/tiktok/oauth.test.ts`

Modified:
- `src/lib/tiktok/oauth.ts`

Meaningful changes:
- Hardened `verifySignedState()` to reject non-canonical signatures before converting with `Buffer.from(..., "hex")`.
- Added tests for valid state, payload tampering, signature tampering, trailing invalid characters, and missing state secret.
- Deployed to production after validation.

## 4. Database and Migration State

Current production migration status:
- `npx prisma migrate status` on the VPS reports: `7 migrations found` and `Database schema is up to date!`
- No failed migrations were reported.
- Phase 8 migrations deployed to production:
  - `20260725000000_add_phase8_intelligence`
  - `20260725010000_add_phase8_market_indexes`
- Both Phase 8 migrations are forward-only and non-destructive. Do not edit deployed migration files.

Phase 8 schema changes:
- `20260725000000_add_phase8_intelligence`
  - Converts `TikTokConnection` to multi-store uniqueness with `(userId, shopId)`.
  - Adds `Store`, `StoreMetricSnapshot`, `Creator`, and `ProductCreator`.
  - Adds official API product fields like `sellerId`, `storeId`, `region`, `stockQuantity`, `status`, `isDeleted`, `deletedAt`.
  - Adds product metric fields: `orders`, `ctr`, `conversionRate`, `returnRate`, `inventoryCount`, `affiliateCount`.
  - Adds `ProductScore` intelligence columns: `growthVelocityScore`, `demandAccelerationScore`, `riskScore`, `competitionTrendScore`.
- `20260725010000_add_phase8_market_indexes`
  - Adds indexes for Market Explorer, dashboard summaries, Store/Creator pages, saved product lookups, and search history cleanup.

Production backups:
- Database backup from the controlled Phase 8 deploy: `/root/toknext-db-backups/toknext_20260725T140807Z.dump`, size `120K`.
- App backup from the `4fcdb5e` deploy: `/root/toknext-release-backups/toknext_app_20260725T140807Z.tgz`, size `11M`.
- App rollback backup before the `a3d9569` deploy: `/root/toknext-release-backups/toknext_app_20260725T150328Z.tgz`, size `11M`.
- There is also `/root/toknext-release-backups/toknext_app_20260725T150235Z.tgz`, size `293M`, created during a failed backup command attempt before extraction; the app was not modified in that failed attempt. Prefer the `150328Z` backup for the actual `a3d9569` rollback point.

Rollback implications:
- Rolling back only `a3d9569` is code-only; no DB migration is involved.
- Rolling back below Phase 8 requires care because production DB has additive Phase 8 columns/tables/indexes. The migrations are forward-only; do not attempt to rewrite or delete them.

## 5. Production Deployment State

Latest controlled code deployment:
- Production URL: `https://toknext.com`
- Deployed code commit: `a3d9569`
- Deployment method: local `git archive` tarball, `scp` to VPS, extract over app directory, preserve `.env`, run remote install/build, restart only `toknext`.
- Apache unchanged.
- `cellcuba` untouched.
- Production app directory remains not a git repository.

Remote deploy results for `a3d9569`:
- `npm ci`: succeeded; audited 758 packages and reported 19 vulnerabilities.
- `npx prisma validate`: succeeded.
- `npx prisma generate`: succeeded.
- `npx prisma migrate deploy`: succeeded; no pending migrations.
- `npm run build`: succeeded on VPS.
- `pm2 restart toknext --update-env`: succeeded.
- `pm2 save`: succeeded.
- PM2 state: `toknext` online; `unstable restarts` 0.
- Health endpoint after deploy: `https://toknext.com/api/health` returned HTTP 200 with database `up`.

Smoke-tested:
- `/api/health`: 200.
- Protected dashboard routes redirect unauthenticated users to login:
  - `/dashboard`
  - `/dashboard/products`
  - `/dashboard/stores`
  - `/dashboard/creators`
  - `/admin/data-sources`
- TikTok unauthenticated route behavior:
  - `/api/auth/tiktok/connect`: 401 without session.
  - `/api/auth/tiktok/callback`: redirects to login without session.

Not manually authenticated-tested:
- `/dashboard`
- `/dashboard/products`
- `/dashboard/stores`
- `/dashboard/creators`
- Market Explorer filters/pagination after login
- Store detail navigation after login
- Creator detail navigation after login

Cron state:
- Most recent systemd cron log observed: `2026-07-25T12:02:28Z http=200`, `scored=32`, `failed=0`, `tiktokConnectionsSynced=0`, `tiktokConnectionsFailed=0`.
- Manual authorized run during Phase 8 verification also returned success with 32 products scored and 0 TikTok connections.

## 6. Validation Results

Local validation after `a3d9569`:
- `npm run lint`: passed.
- `npm test`: passed, 29 test files, 224 tests.
- `npx tsc --noEmit`: passed.
- `npm run build`: passed.

Production validation:
- `npx prisma validate`: passed during deploy.
- `npx prisma generate`: passed during deploy.
- `npx prisma migrate deploy`: passed, no pending migrations.
- `npx prisma migrate status`: 7 migrations found, database schema up to date.
- `npm run build`: passed on VPS.
- Health endpoint: HTTP 200.

No full application build is required for this documentation-only handoff commit unless code changes are added later.

## 7. Current Known Issues

- Critical: Historical `PROJECT_STATE.md` notes that a Stripe live secret and webhook secret were exposed in a previous tool transcript on 2026-07-24. No secret values are repeated here. Rotation was not confirmed in this Codex session. Account owner should confirm whether keys were rotated; if not, rotate manually in Stripe and update VPS `.env`.
- Informational: Old PM2 error log lines still contain a Stripe TEST-key warning from before the latest verification. Current `.env` is Live and no new Stripe TEST-key warning appeared after restart/deploy.
- Informational: Live Stripe environment-mode audit was completed and verified on 2026-07-25. Claude should re-check before any billing work but should not restore values unless drift is found.
- High: Authenticated dashboard flows have not been manually browser-tested with a real authorized account.
- High: No real TikTok seller is connected; `TikTokConnection` count is 0.
- High: TikTok seller OAuth, token exchange, authorized-shop verification, product import, and score recalculation have not been observed end to end against a live seller.
- Medium: TikTok analytics endpoint paths and real response fields in `src/lib/tiktok/metrics.ts` are unverified against a live authorized seller. The code fails soft rather than fabricating data.
- Informational: Server Action mismatch warnings were observed during deployment. They did not recur after restart and are currently classified as transient requests crossing deployments.
- Medium: `npm audit` reports 19 vulnerabilities: 3 moderate, 16 high. Do not run `npm audit fix --force`.
- Low: GitHub fetch/clone from the VPS is blocked by credentials. The production release directory has no `.git`; deployments use source archives or the local deploy script from a developer machine.
- Informational: AI Assistant/OpenAI workflow and Video Research are intentionally not implemented yet. Existing UI routes are placeholders/coming-soon where applicable.
- Medium: No real paid Stripe live transaction was performed in this session. API config was verified without creating a charge.

## 8. Stripe State

Never print or commit Stripe secret values.

Production status verified on 2026-07-25:
- `STRIPE_SECRET_KEY`: `LIVE` mode.
- `NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY`: `LIVE` mode.
- `STRIPE_WEBHOOK_SECRET`: present. A `whsec_` value is opaque and mode must be inferred from the matching live webhook endpoint and live key.
- Stripe Price env vars are present and were verified through the live Stripe API:
  - `STRIPE_PRICE_PRO_MONTHLY`: live, `usd`, monthly, active.
  - `STRIPE_PRICE_PRO_ANNUAL`: live, `usd`, yearly, active.
  - `STRIPE_PRICE_AGENCY_MONTHLY`: live, `usd`, monthly, active.
  - `STRIPE_PRICE_AGENCY_ANNUAL`: live, `usd`, yearly, active.
- Stripe API authentication: OK with live key.
- Customer Portal: active default configuration exists.
- App webhook route: `https://toknext.com/api/stripe/webhook`.
- Stripe Dashboard has one enabled live webhook endpoint for `https://toknext.com/api/stripe/webhook` with the 8 expected events.
- The path `https://toknext.com/api/webhooks/stripe` is not the app route and was not registered in Stripe during verification.
- No real charge was performed.
- Stripe secret rotation remains manual. Do not rotate keys automatically.

Variables that must always be checked together:
- `STRIPE_SECRET_KEY`
- `NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY`
- `STRIPE_WEBHOOK_SECRET`
- `STRIPE_PRICE_PRO_MONTHLY`
- `STRIPE_PRICE_PRO_ANNUAL`
- `STRIPE_PRICE_AGENCY_MONTHLY`
- `STRIPE_PRICE_AGENCY_ANNUAL`

## 9. TikTok State

Production callback URL:
- `https://toknext.com/api/auth/tiktok/callback`

Environment variable names:
- `TIKTOK_SHOP_APP_KEY`
- `TIKTOK_SHOP_APP_SECRET`
- `TIKTOK_SHOP_STATE_SECRET`
- `TIKTOK_TOKEN_ENCRYPTION_KEY`

Production status verified on 2026-07-25:
- All four required TikTok variables are present.
- `TIKTOK_TOKEN_ENCRYPTION_KEY` format is valid 64+ hex characters.
- OAuth routes exist:
  - `GET /api/auth/tiktok/connect`
  - `GET /api/auth/tiktok/callback`
  - `POST /api/auth/tiktok/disconnect`
- OAuth state validation uses `nonce.timestamp.signature`, HMAC-SHA256, timing-safe comparison, 10-minute expiry, and now rejects non-canonical hex signatures.
- Tokens are encrypted with AES-256-GCM before persistence.
- Connection model is admin-level and site-wide, not per-customer. A connected TikTok Shop populates the shared product catalog as a `DataSource`.
- Multi-store support exists via `(userId, shopId)` uniqueness.
- No seller currently connected; `TikTokConnection` count is 0.

Next manual browser step:
1. Log in as an `ADMIN`.
2. Go to `/admin/data-sources`.
3. Click **Connect TikTok Shop**.
4. Complete TikTok Shop authorization in the browser.
5. Expect redirect back to `/admin/data-sources?connected=tiktok`.
6. Verify the connection card, DB row, PM2 logs, product import, and subsequent score recalculation.

Do not claim seller OAuth or analytics verified until a real seller authorization completes.

## 10. Scheduler State

Cron route:
- `GET /api/cron/sync`

Authentication:
- Requires `Authorization: Bearer $CRON_SECRET`.
- Missing `CRON_SECRET`: 503.
- Missing/wrong bearer token: 401.
- Duplicate run while lock held: 409 with skipped response.

Behavior:
- Uses Postgres advisory lock: `toknext:cron:sync`.
- Runs TikTok token refresh sweep before sync.
- Syncs all `CONNECTED` TikTok connections with per-connection isolation.
- Uses retry/backoff for transient TikTok HTTP failures.
- Recalculates scores for active products.
- Appends score history.
- Cleans old search history.
- Logs run IDs and counts.

Most recent observed production cron result:
- `2026-07-25T12:02:28Z http=200`
- `scored=32`
- `failed=0`
- `tiktokConnectionsSynced=0`
- `tiktokConnectionsFailed=0`

## 11. Exact Next Recommended Task

Immediate next task for Claude Code:

Production post-deploy verification, beginning with a Stripe environment-mode audit that confirms the current Live status has not drifted. Do not restore or rotate secrets unless the audit shows a real mismatch and the user provides/approves the secure values.

Then:

1. Verify authenticated dashboard manually with an authorized account.
2. Review Server Action mismatch warnings and confirm they remain transient.
3. Connect a real TikTok seller from `/admin/data-sources`.
4. Verify OAuth, token storage, authorized-shop verification, product import, and score recalculation.
5. Validate real TikTok analytics fields and update `src/lib/tiktok/metrics.ts` only if the live API proves field/path differences.
6. Triage `npm audit` vulnerabilities with the smallest safe upgrade plan.
7. Confirm whether the historical Stripe secret exposure documented in `PROJECT_STATE.md` was rotated.

## 12. Safety Rules for Claude Code

- Do not rewrite deployed migrations.
- Do not deploy without explicit user approval.
- Do not expose secrets, tokens, credentials, database URLs, CRON secrets, OAuth secrets, encryption keys, session secrets, or private SSH keys.
- Do not modify Apache unless clear evidence proves Apache is responsible for the issue.
- Do not restart `cellcuba`.
- Do not claim TikTok analytics verified without real seller testing.
- Do not run `npm audit fix --force`.
- Preserve the existing Next.js/React/Prisma/Auth.js/Stripe architecture.
- Inspect current code before changing files.
- Keep commits small and scoped.
- For code changes, run the project validation sequence before deploy: `npm run lint`, `npm test`, `npx tsc --noEmit`, `npm run build`.

## 13. Suggested First Prompt for Claude Code

Use this prompt:

```text
Read CODEX_HANDOFF.md first, then inspect git status, current HEAD, and the current code. Compare the handoff against README.md, PROJECT_STATE.md, package.json, prisma/schema.prisma, and the relevant source files. Do not make changes initially. Report the current repository state, production state, any doc/code drift you find, and propose the next safest actions. Begin with a non-secret Stripe environment-mode audit to confirm production is still Live, then plan authenticated dashboard verification and real TikTok seller authorization.
```

## 14. Addendum (2026-07-26) — TikTok official SDK adapter built, then its transport rewritten

Since this handoff was written, a Claude Code session did the following
(none of it deployed; production is unaffected):

1. Vendored TikTok's official Node.js Partner API SDK at
   `packages/tiktok-shop-sdk/vendor/` and built an opt-in adapter
   (`src/lib/tiktok/sdk/`) behind `TIKTOK_USE_OFFICIAL_SDK` (default
   `"false"`). See PROJECT_STATE.md's "TikTok official SDK adapter" section
   for the full scope-to-endpoint mapping and discrepancies found against
   the existing hand-rolled implementation.
2. That first version depended on the deprecated `request` npm package
   (2 critical CVEs) to make its HTTP calls. It was never deployed, and was
   immediately replaced with a TokNext-owned `fetch`-based transport
   (`src/lib/tiktok/sdk/fetch-transport.ts`) that reuses the official SDK's
   own signing algorithm and response deserialization, with zero runtime
   dependency on `request`. `request` has since been removed from
   `package.json` entirely (`@types/request` stays, devDependency only, for
   a type declaration `import type` resolves against at build time).
3. A read-only live-seller verification script exists at
   `scripts/tiktok-sdk-live-verify.ts` (`npm run tiktok:sdk:live-verify`)
   but has not been run — there is still no connected `TikTokConnection`
   row (item 3/4 in section 11 above, "Connect a real TikTok seller", is
   still the actual next step once a human completes that OAuth screen).
4. Full validation suite passed: `npm run lint`, `npm test` (288 tests),
   `npx tsc --noEmit`, `npm run build`, `npx prisma validate`. `npm audit`
   itself could not be run in that session's sandbox (registry gzip-decode
   error on the bulk advisory endpoint, reproduced 3×, unrelated to this
   change) — re-run it from an environment with reliable registry access
   before relying on an exact vulnerability count; `npm ls request` /
   `npm ls form-data` were used instead to directly confirm the dependency
   tree no longer contains `request`.

Section 11's "Exact Next Recommended Task" list is otherwise still accurate
and still the right next steps — none of those items were addressed by
this addendum's work.
