feat(worker): Phase 2b — port simple owner-scoped reads (warranties/insurance/legal-cases/tools)#37
Conversation
Ports 5 read-only GET routes from Express to the Cloudflare Worker (Hono + Drizzle/Hyperdrive). Stacks on Phase 2a (#36). Routes ported: - GET /api/assets/:assetId/warranties (server/routes.ts:453) - GET /api/warranties/expiring (server/routes.ts:464) - GET /api/assets/:assetId/insurance (server/routes.ts:497) - GET /api/legal-cases (server/routes.ts:529) - GET /api/tools/resources (server/routes.ts:117, static) Mounted in worker/src/index.ts BEFORE the 501 catch-all. Express server/routes.ts untouched — all unmigrated routes still return not_yet_migrated. Ownership scoping matches the Phase 2a pattern: warranties.userId / insurance_policies.userId / legal_cases.userId == claims.chitty_id. Direct (no JOIN), since each table denormalizes user_id on insert. Tool resource catalog mirrored inline in worker/src/routes/tools.ts — worker bundle cannot import Express-side modules. Kept in lockstep with server/toolRegistry.ts; documented in module header. NO MOCKS, NO FAKE DATA — every test exercises real Neon via br-spring-star-aky6u1mc with chitty_id-scoped fixtures + afterAll cleanup. drizzle-kit upgrade attempted but blocked by peer-dep conflict (@uppy/aws-s3); deferred. Test branch strategy unchanged from Phase 2a fallback. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6c52ed2302
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const userId = claims.chitty_id; | ||
| const daysRaw = c.req.query("days"); | ||
| const parsed = daysRaw ? parseInt(daysRaw, 10) : 30; | ||
| const daysAhead = Number.isFinite(parsed) && parsed > 0 ? parsed : 30; |
There was a problem hiding this comment.
Preserve query semantics for negative
days values
The new /api/warranties/expiring handler changes behavior from the Express path it ports: in server/routes.ts + storage.ts, days=-7 is passed through and yields an empty result window, but this worker code coerces any non-positive value back to 30, which can return active near-term warranties instead. That is a migration regression for callers that send negative values (intentionally or via client bugs), because the same request now returns materially different data after the move to Hono.
Useful? React with 👍 / 👎.
Summary
Phase 2b of the Express→Hono migration. Ports 5 read-only GET routes for warranties, insurance, legal cases, and the tool-resources catalog to the Cloudflare Worker (Hono + Drizzle/Hyperdrive).
Stacks on #36 (Phase 2a asset reads) → #34 (schema canonical remediation) → #33 (Phase 1 Hono skeleton).
Routes Ported
Mounted in
worker/src/index.tsBEFORE the 501 catch-all. Expressserver/routes.tsis untouched — all unmigrated routes still returnnot_yet_migrated.Decided Unilaterally
1. Ownership without JOIN
warranties,insurance_policies, andlegal_casesall carryuser_iddirectly (denormalized on insert by the Express writer side). The storage-layer methods filter onuser_id(andasset_idfor the asset-scoped routes) without a JOIN toassets. The Hono port matches that exactly — no JOIN required. This preserves the Express semantics; if asset-level ownership ever diverges from row-leveluser_id, that's a Phase 3 reconciliation, not a 2b change.2. Tool resource catalog inlined
The worker bundle cannot import
server/toolRegistry.ts(Express-side ESM with sibling imports). The catalog is re-declared inworker/src/routes/tools.tswith a header comment instructing maintainers to keep both lists in lockstep. The schema-overlord audit will diff them at PR time. Test asserts all 5 known IDs are present so silent drift is caught.3. drizzle-kit upgrade — attempted, deferred
npm install drizzle-kit@latestblocked by@uppy/aws-s3@^4.3.2peer-dep conflict (ERESOLVE). Not worth introducing--legacy-peer-depsin a read-only-routes PR. Path taken: Phase 2a fallback — Neon branchbr-spring-star-aky6u1mc+ chitty_id-scoped fixtures + fullafterAllcleanup. Documented in commit message; Phase 3 should pick this up as part of a broader dependency unwind.4. Test seam identical to Phase 2a
registerWarrantyRoutes(app, authMiddleware)etc. — same factory pattern. Tests inject a pass-through middleware; production instantiation (export const warrantyRoutes) uses realrequireChittyAuth. Zero production code paths bypass auth.5.
/api/warranties/expiringregistered before/api/assets/:assetId/warrantiesBoth share the
/apiprefix on the same sub-app. Registered in safety order so Hono never tries to match"expiring"as an:assetId. Verified empirically by the/warranties/expiringtest passing.Validation Evidence
TypeCheck (
npm run check)Zero NEW errors in
worker/src/**and the 4 new test files. All 85 remaining errors are pre-existing inserver/andclient/(Replit-era code untouched by this PR) — identical count to Phase 2a baseline.Integration Tests
24/24 pass against Neon branch
br-spring-star-aky6u1mc(12 Phase 2a + 12 new Phase 2b):Sample SQL via Neon MCP
run_sql(on br-spring-star-aky6u1mc)For
GET /api/warranties/expiring?days=30(the non-trivial predicate route):Result (after seeding one fixture row with
end_date = NOW() + INTERVAL '10 days'):[ { "id": "74e4563c-6750-4e58-a919-8736b5d96443", "user_id": "01-A-CHT-ASST-P-9X-1-X", "provider": "Sub-Zero Manufacturer Warranty", "end_date": "2026-05-27T07:23:34.153Z", "is_active": true } ]Confirms the Drizzle-emitted predicate parses, executes against Neon, and returns the expected single row. Fixture cleaned up after capture.
Wrangler Dry-Run
Upload size +5.76 KiB over Phase 2a — within the expected envelope for 4 route modules + inlined tool catalog.
Canonical Compliance
@canon: chittycanon://core/services/chittyassetson all 8 new filesENTITY_TYPES = ["P", "L", "T", "E", "A"]unchanged inenv.ts— all five P/L/T/E/A presentchitty_prefix workaroundStack
PR (this) → #36 → #34 → #33 (base:
feat/hono-phase-2a-asset-reads)Test Plan
/warranties/expiringreturns only active+in-window/warranties/expiring?days=Nadjusts window correctly🤖 Generated with Claude Code