Skip to content

chore(zod): upgrade zod 4.4.3 to 4.6.5 (ETL schemas) #642

Description

@jasonhnd

Series

Part of #635. Order 6. Blocked by order 5 (#641) merged to preview.

Why

zod ^4.4.3 (released 2026-05-04) → 4.6.5 (2026-09-13). Releases in between: 4.5.0–4.5.4 (2026-08-28/29), 4.6.0–4.6.5 (2026-09-09…13).

Where zod runs — build time only (ETL + scoring scripts), never in a Vercel Function or in the browser:

  • src/data/schema/{occupation,sector,labels,translation,score-run,worktypes,haid-release,stats-legacy}.ts
  • src/data/loaders.ts, src/lib/strict-load.ts (+ strict-load.test.ts), src/lib/projection-schemas.ts, src/site/geo-facts.ts
  • scripts/lib/scoring/contract.ts

All use import { z } from 'zod' or import type { ZodTypeAny, infer } from 'zod'.

Astro also depends on zod (^4.3.6). After the bump the lockfile has one zod@4.6.5 entry (Astro's range accepts it).

Dry run 2026-09-24 (throwaway worktree: preview 9b4e7197 + orders 1–5 applied, Bun 1.4.2, Node 24.20.0, no PUBLIC_* env)

Step Result
^4.6.5 → bun install single zod@4.6.5; lockfileVersion 1; diff = package.json 1 line, bun.lock (+1 / −3)
ETL output: bun run build:data with 4.4.3 vs 4.6.5, all 616 files under public/data* identical after removing "generated_at" (the only field that differs between any two runs, even on the same version)
typecheck / test / build / REQUIRE_BUILT_ARTIFACTS / verify:gates all OK
bun x playwright test --reporter=line 356 passed, 26 skipped, 0 failed
bun audit No vulnerabilities found

やること

  1. Branch chore/zod-4.6.5 from origin/preview (order 5 merged).
  2. package.json dependencies.zod: ^4.4.3 → ^4.6.5.
  3. bun install, then:
    grep -c '"zod": \["zod@' bun.lock   # 1
    grep -n '"zod": \["zod@' bun.lock   # zod@4.6.5
    grep -n 'lockfileVersion' bun.lock  # 1
  4. ETL output oracle (zod parses every data file; a behaviour change would show up here):
    norm() { find "$1" -type f | sort | while read f; do sed -E 's/"generated_at": ?"[^"]*"//g' "$f"; done | shasum -a 256; }
    git stash && bun install && bun run build:data && rm -rf /tmp/etl-old && mkdir /tmp/etl-old && cp -R public/data* /tmp/etl-old/
    git stash pop && bun install && bun run build:data && rm -rf /tmp/etl-new && mkdir /tmp/etl-new && cp -R public/data* /tmp/etl-new/
    norm /tmp/etl-old; norm /tmp/etl-new           # must be equal
    find /tmp/etl-new -type f | wc -l               # 616 on preview 9b4e7197 (may grow with new data; must equal the old count)
    If the hashes differ, find the file (diff -r after the same sed) and stop; report it in the PR.
  5. Standard chain:
    unset PUBLIC_GA4_MEASUREMENT_ID PUBLIC_X_PIXEL_ID PUBLIC_META_PIXEL_ID
    bun run typecheck && bun run test && bun run test:consistency && bun run build
    REQUIRE_BUILT_ARTIFACTS=1 bun test scripts/home-css-loading.test.ts src/site/models-built.test.ts
    bun run verify:gates
    bun x playwright test --reporter=line
    bun audit
    git diff --exit-code
  6. Docs: docs/TOOLCHAIN.md §11 order 6 done + PR number (zod has no §2 row; do not add one). CHANGELOG.md ### Changed: - **zod 4.4.3 → 4.6.5** — build-time schemas only; 616 ETL outputs identical (ignoring generated_at).

やらないこと

  • No schema edits, no switching to zod/mini or new 4.5/4.6 APIs.
  • No other package bumps.

Acceptance

  • One zod@4.6.5 in bun.lock; lockfileVersion: 1; only package.json + bun.lock changed.
  • ETL oracle: normalized hashes equal, file counts equal (pasted).
  • Step 5 chain green.
  • quality + Vercel green. TOOLCHAIN §11 + CHANGELOG updated.

Branch / PR

chore/zod-4.6.5 → base preview, Closes #642.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    delivery:unitloopcoder work unitenhancementNew feature or requestrisk:medmedium risk work itemtier:2tier 2 work item

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions