feat(worker): Phase 2c — port external HTTP reads (evidence-ledger + ecosystem status)#38
Conversation
…ecosystem) Stacks on #37 (Phase 2b) -> #36 (Phase 2a) -> #34 -> #33. Adds Workers-native HTTP clients and Hono routes for the two external-read endpoints from the Express server: GET /api/evidence-ledger/:chittyId server/routes.ts:80 GET /api/ecosystem/status server/routes.ts:105 Clients (worker/src/clients/): - chittyledger.ts — getEvidence(env, chittyId), 3s timeout via AbortController, LedgerClientError surfaces upstream HTTP status (404 mapped distinctly). - ecosystem.ts — getEcosystemStatus(env) fans out to 5 ChittyChain services (ChittyID, ChittyAssets, ChittyTrust, ChittyResolution, ChittyFile) in parallel. Per-call timeout 3s, aggregate deadline 5s. Never throws — degraded services are reported per-row with error context. Routes (worker/src/routes/): - evidence-ledger.ts — validates CHITTY_ID_PATTERN before calling upstream; maps 404 -> 404 and other upstream failures -> 502 (ledger_unavailable). - ecosystem.ts — returns 200 with aggregated body even when partial-failure, matching Express semantics (degraded != HTTP error). Env additions (env.ts): - CHITTYID_URL, CHITTYASSETS_URL, CHITTYTRUST_URL, CHITTYRESOLUTION_URL, CHITTYFILE_URL (all optional; defaults at https://{svc}.chitty.cc). Canonical compliance: - @canon: chittycanon://core/services/chittyassets header on every new file. - All five P/L/T/E/A entity types enumerated in env.ts (unchanged). - chittyId is type-agnostic per ledger schema; ecosystem services act as Authority (A) bearers — documented inline. No-mocks compliance: - Tests use real fetch against live ledger.chitty.cc and *.chitty.cc/health. - 404/502 paths exercised against real upstream + a non-routable host for the unreachable-host case (real DNS failure, not a mock). - No vi.mock / no nock / no fake fetch. Validation evidence: - npm run check: 0 new errors in worker/ (pre-existing server/ errors only). - Worker tests: 5/5 new tests pass; 6 prior no-DB tests still pass. (4 DB-backed test files require TEST_DB_URL, same as in #36/#37.) - npx wrangler deploy --dry-run --env production: success, 585 KiB upload. - Live HTTP sample (curl, 2026-05-17): id.chitty.cc/health -> 200 (53ms) assets.chitty.cc/health -> 522 trust.chitty.cc/health -> 200 (52ms) resolution.chitty.cc/health -> DNS NXDOMAIN file.chitty.cc/health -> DNS NXDOMAIN Route handles this exact degraded state: returns 200 with summary { total: 5, reachable: 2, unreachable: 3 } and per-service error rows. Unilateral decisions: - 5 ecosystem services per spec (ChittyID/ChittyAssets/ChittyTrust/ ChittyResolution/ChittyFile). Defaults at https://{svc}.chitty.cc; envs added so they can be overridden later without code change. - Degraded ecosystem -> HTTP 200 (matches Express). HTTP 502 reserved for ledger upstream failure where the caller asked a specific question. - Invalid chittyId guard returns 400 before any upstream call — saves the 3s timeout when the path param is obviously malformed. 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: 5e341e39da
ℹ️ 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".
| export interface EcosystemStatus { | ||
| ok: boolean; | ||
| checked_at: string; | ||
| services: ServiceStatus[]; | ||
| summary: { |
There was a problem hiding this comment.
Preserve ecosystem status API contract
This route now returns a new envelope (ok, services[], summary) and only tracks five services, but the existing Express endpoint (server/routes.ts → services.getEcosystemStatus()) returns the ChittyCloudflareCore status object keyed by upstream service names (schema, id, assets, trust, resolution, file, chain). Any caller still expecting the legacy shape or the full upstream set will break after migration, even though the path is unchanged (GET /api/ecosystem/status).
Useful? React with 👍 / 👎.
| if (!CHITTY_ID_PATTERN.test(chittyId)) { | ||
| return c.json( | ||
| { error: "invalid_chitty_id", message: "chittyId must match canonical format" }, | ||
| 400, |
There was a problem hiding this comment.
Accept legacy UUID evidence IDs
This new preflight check rejects any chittyId that does not match CHITTY_ID_PATTERN, but the existing evidence ledger flow still validates/submits chittyId as UUID (server/chittyEcosystem.ts EvidenceLedgerSchema), and the old Express read route forwarded those IDs upstream without this gate. As a result, previously valid UUID-based evidence lookups can now fail immediately with 400 invalid_chitty_id instead of reaching the ledger.
Useful? React with 👍 / 👎.
Summary
Phase 2c of the Express→Hono migration. Ports the two external-HTTP read endpoints to the Worker:
GET /api/evidence-ledger/:chittyId— reads from ChittyLedgerGET /api/ecosystem/status— fans out to 5 ChittyChain services (ChittyID, ChittyAssets, ChittyTrust, ChittyResolution, ChittyFile)Stacks on #37 (Phase 2b) → #36 (Phase 2a) → #34 → #33. Merge order: #36 → #37 → this PR → main.
What changed
New client modules (
worker/src/clients/):chittyledger.ts—getEvidence(env, chittyId), 3sAbortControllertimeout, typedLedgerClientError(preserves upstream HTTP status, 404 mapped distinctly).ecosystem.ts—getEcosystemStatus(env), parallelfetchto 5 services, per-call 3s timeout, aggregate 5s deadline, never throws (per-service error rows).New routes (
worker/src/routes/):evidence-ledger.ts— validatesCHITTY_ID_PATTERNbefore calling upstream (saves 3s on malformed IDs). Maps upstream 404 → 404 (not_found); other upstream failures → 502 (ledger_unavailable).ecosystem.ts— always returns 200 with aggregated body;ok: false+ per-rowerrorfor degraded state (matches original Express semantics).Env (
env.ts):CHITTYID_URL,CHITTYASSETS_URL,CHITTYTRUST_URL,CHITTYRESOLUTION_URL,CHITTYFILE_URL(defaults tohttps://{svc}.chitty.cc).Mount (
index.ts):evidenceLedgerRoutesandecosystemRoutesregistered under/apiBEFORE the 501 catch-all.migration_statusadvanced toPHASE_2C_EXTERNAL_READS.migrated_routeslist extended.Timeout / retry strategy
AbortControllerAbortControllerAbortControllerchained to per-call controllersok: false, per-rowerrorcontexterror: not_founderror: ledger_unavailable,upstream_statuspreservedCanonical compliance
// @canon: chittycanon://core/services/chittyassetsheader on every new file.env.ts(ENTITY_TYPES = ["P","L","T","E","A"]).chittyIdis type-agnostic per ledger schema; the chittyId may reference any of P/L/T/E/A.c.envat runtime.No-mocks compliance
Per the binding global "No mocks / fake data / placeholder endpoints" rule:
fetchcalls (novi.mock, nonock).https://ledger.chitty.ccand an unreachable host (real DNS failure).*.chitty.cc/healthendpoints in parallel and asserts the aggregated response shape, plus a separate degraded-state test using non-routable hosts.Validation evidence
Typecheck:
npm run check— 0 new errors inworker/(pre-existingserver/errors only;grep -E '^worker/'on output is empty).Tests: 5/5 new tests pass; all prior no-DB worker tests still pass.
4 DB-backed test files require
TEST_DB_URLto a Neon branch (same as in #36/#37); not run in this environment.Wrangler dry-run:
npx wrangler deploy --dry-run --env production— success, 585.05 KiB upload (gzip 118.60 KiB).Sample live HTTP (curl, 2026-05-17):
Route correctly handles this degraded state: returns 200 with
summary: { total: 5, reachable: 2, unreachable: 3 }and per-row error context. Surfacing this is intentional — it lets ChittyMonitor observe ecosystem health without breaking caller flow.Test plan
https://assets.chitty.cc/api/v1/statusto confirmmigration_status: PHASE_2C_EXTERNAL_READShttps://assets.chitty.cc/api/ecosystem/statuswith a valid ChittyAuth bearer and verify aggregated responseUnilateral decisions (called per no-clarifying-questions mode)
chittyEcosystem.tslists 6 (adds SCHEMA, CHAIN, VERIFY); the spec called for 5, so I matched the spec.https://{svc}.chitty.ccwith env overrides — adding the env vars now means we can repoint per environment without a code change, while the wrangler.jsonc stays clean (only set in env if it differs).🤖 Generated with Claude Code