Skip to content

feat: complete Phase 2 Hono route migration#41

Merged
chitcommit merged 5 commits intophase2-hono-migrationfrom
main
Feb 26, 2026
Merged

feat: complete Phase 2 Hono route migration#41
chitcommit merged 5 commits intophase2-hono-migrationfrom
main

Conversation

@chitcommit
Copy link
Copy Markdown
Contributor

Summary

  • Migrated all Express routes to 17 Hono route modules on Cloudflare Workers
  • Added Wave OAuth (edge-compatible HMAC state tokens), recurring charges, and 21 forensic accounting endpoints
  • Updated CLAUDE.md and implementation plan to reflect completed Phase 2

Changes

  • 17 route modules: health, docs, accounts, summary, tenants, properties, transactions, integrations, tasks, ai, mercury, github, stripe, wave, charges, forensics, webhooks
  • Edge-compatible OAuth: server/lib/oauth-state-edge.ts using Web Crypto API
  • Forensic accounting: investigations CRUD, evidence chain of custody, Benford's law analysis, duplicate detection, flow of funds tracing, damage calculations, report generation
  • Per-prefix middleware: Protected routes use prefix-based middleware registration to avoid blocking public endpoints
  • Wave callback: Self-contained public route (creates own DB/storage, recovers tenantId from state token)

Test plan

  • All 30 vitest tests passing
  • Deployed to finance.chitty.cc
  • Health endpoint returns ok
  • Protected endpoints return 401 unauthorized without auth
  • Manual test: Wave OAuth flow end-to-end
  • Manual test: Forensic investigation CRUD with valid auth

🤖 Generated with Claude Code

chitcommit and others added 5 commits February 24, 2026 14:25
Remove stale references to demo-key fallback, mock data integrations,
and inaccurate testing integration docs. Reflects actual conditional
client init pattern and per-integration implementation status.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Empty catch block silently swallowed module load failures, making it
impossible to diagnose ChittyConnect JWT verification issues.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add 8 new Hono route modules for tenants, properties, transactions,
integrations, tasks, AI messages, webhooks, and OpenAPI docs. Refactor
app.ts with shared storageMiddleware for DRY auth+tenant+storage setup.
Add getProperty, getUnits, getLeasesByUnits to SystemStorage.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Mercury accounts via ChittyConnect proxy, GitHub repo/commits/PRs/issues
endpoints, Stripe customer connect and checkout session creation.
All routes use c.env for edge-compatible config access.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Complete Phase 2 Hono migration with final 3 route groups:
- Wave OAuth: edge-compatible HMAC state tokens, public callback
- Recurring charges: stub-based charge detection with optimization analysis
- Forensic accounting: 21 endpoints for investigations, evidence, analysis, reports

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@chatgpt-codex-connector
Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Feb 26, 2026

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)

✅ Unit Test PR creation complete.

  • Create PR with unit tests
  • Commit unit tests in branch main

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@claude
Copy link
Copy Markdown

claude Bot commented Feb 26, 2026

PR Review: feat: complete Phase 2 Hono route migration

Great work completing the Hono migration — the 17-module structure is clean, the per-prefix middleware pattern is well-reasoned, and the edge-compatible OAuth state implementation in oauth-state-edge.ts is solid. Below are findings organized by severity.


Critical — Security

1. Stripe webhook signature is never verified (server/routes/webhooks.ts)

The endpoint checks for the presence of stripe-signature but never calls stripe.webhooks.constructEvent() to cryptographically verify it. Any attacker with a random stripe-signature header and a crafted payload containing an unused event ID will have it accepted and stored in KV. The plan doc even notes this should be done — it just wasn't implemented.

Fix: instantiate Stripe and call stripe.webhooks.constructEvent(rawBody, signature, secret) before parsing the body. Return 400 on StripeSignatureVerificationError.


2. Forensic analysis sub-routes lack investigation ownership checks (server/routes/forensics.ts)

The individual analyze endpoints (/analyze/duplicates, /analyze/timing, /analyze/round-dollars, /analyze/benfords-law) call getUserTransactions() but never call verifyOwnership(). Any authenticated user can insert forensicAnomalies records into any investigation ID, including investigations belonging to other users (IDOR).

Same issue in: trace-funds, GET flow-of-funds, GET reports. Add verifyOwnership() guards consistently, matching the pattern used in POST /evidence and GET /evidence.


3. Hard-coded fallback OAuth secret (server/routes/wave.ts)

const secret = c.env.OAUTH_STATE_SECRET || 'default-secret-change-in-production';

If OAUTH_STATE_SECRET is missing in production, the HMAC protection is rendered useless. Return 503 instead of silently degrading:

const secret = c.env.OAUTH_STATE_SECRET;
if (!secret) return c.json({ error: 'OAuth not configured' }, 503);

High — Correctness

4. Repeat analysis inserts create duplicates

The /analyze endpoint and each sub-analyze route insert into forensicAnomalies and forensicTransactionAnalysis on every call with no deduplication. Running analysis twice doubles all records. Consider deleting existing records for the investigation before re-running, or adding an upsert/check.

5. Dynamic import inside request handlers (server/routes/forensics.ts)

const { transactions } = await import('../../shared/schema');

This appears inside hot-path handlers and runs on every request. Hoist to a top-level import — the runtime caches the module but the async overhead and hidden dependency are unnecessary.

6. Unvalidated body spread in PATCH routes

Both PATCH /api/integrations/:id and PATCH /api/tasks/:id pass the raw request body directly to storage with no field filtering. This allows callers to overwrite protected fields like tenantId, serviceType, or createdAt. Add a Zod schema or an explicit allowlist of patchable fields.


Medium — Code Quality / Architecture

7. Forensics routes bypass shared storageMiddleware

getDb(c.env) creates a new DB connection on every forensics request, independent of the connection storageMiddleware already attached to the context. This doubles connection overhead and diverges from the project pattern. Add forensic-specific methods to SystemStorage or reuse c.get('storage') where possible.

8. userId silently defaults to 0 on missing context

const userId = parseInt(c.get('userId') || '0', 10);

A missing userId should be a hard 401, not a silent fallback that could match real DB rows. Compare with the correct guard in tenants.ts: if (!userId) return c.json({ error: 'Authentication required' }, 401).

9. Stripe API version as any cast (server/routes/stripe.ts)

new Stripe(secretKey, { apiVersion: '2024-06-20' as any })

Use Stripe.LatestApiVersion or a string the SDK exports natively to retain type safety.

10. Service type typo in Wave callback (server/routes/wave.ts)

integrations.find((i) => i.serviceType === 'wavapps')

'wavapps' looks like a typo for 'wave' or 'waveapps'. If this doesn't match the value used when creating integrations elsewhere, the callback will always create a new record instead of updating the existing one.

11. forensics.ts is 725 lines — consider splitting

The file handles CRUD, evidence management, 4 analysis algorithms, flow of funds, damage calculations, and reports. Given the project's module-per-concern structure, breaking it into forensics/investigations.ts, forensics/analysis.ts, forensics/reports.ts would improve navigability.


Minor

  • server/routes/github.ts — raw GitHub API status codes are forwarded to clients. Log the response body server-side and return a generic message to avoid information leakage.
  • server/routes/mercury.tsfetch() calls have no try/catch. Network failures throw an unhandled error instead of returning a clean 502.
  • server/routes/charges.tsfetchChargesFromIntegration always returns [] but is called in a loop over all integrations. A // TODO: comment or early return would make the stub status clearer.
  • server/db/schema.ts — mixing integer-ID forensic exports with UUID-based system tables in the same schema module will cause long-term confusion. An inline // TODO: would make the known limitation harder to miss.

Summary

The three blocking issues before merge:

  1. Stripe webhook signature verification — the endpoint currently has no authentication
  2. Forensic analysis IDOR — any authenticated user can write anomaly records into any investigation
  3. OAuth secret fallback — production misconfiguration risk

Everything else can reasonably land in a follow-up PR.

Generated with Claude Code

@chitcommit chitcommit merged commit 2e39b10 into phase2-hono-migration Feb 26, 2026
6 checks passed
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 26, 2026

Note

Unit test generation is a public access feature. Expect some limitations and changes as we gather feedback and continue to improve it.


Generating unit tests... This may take up to 20 minutes.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 26, 2026

✅ Created PR with unit tests: #109

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant