Skip to content

feat(worker): Phase 2c — port external HTTP reads (evidence-ledger + ecosystem status)#38

Open
chitcommit wants to merge 1 commit into
feat/hono-phase-2b-simple-readsfrom
feat/hono-phase-2c-external-reads
Open

feat(worker): Phase 2c — port external HTTP reads (evidence-ledger + ecosystem status)#38
chitcommit wants to merge 1 commit into
feat/hono-phase-2b-simple-readsfrom
feat/hono-phase-2c-external-reads

Conversation

@chitcommit
Copy link
Copy Markdown
Contributor

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 ChittyLedger
  • GET /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.tsgetEvidence(env, chittyId), 3s AbortController timeout, typed LedgerClientError (preserves upstream HTTP status, 404 mapped distinctly).
  • ecosystem.tsgetEcosystemStatus(env), parallel fetch to 5 services, per-call 3s timeout, aggregate 5s deadline, never throws (per-service error rows).

New routes (worker/src/routes/):

  • evidence-ledger.ts — validates CHITTY_ID_PATTERN before 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-row error for degraded state (matches original Express semantics).

Env (env.ts):

  • Adds optional CHITTYID_URL, CHITTYASSETS_URL, CHITTYTRUST_URL, CHITTYRESOLUTION_URL, CHITTYFILE_URL (defaults to https://{svc}.chitty.cc).

Mount (index.ts):

  • evidenceLedgerRoutes and ecosystemRoutes registered under /api BEFORE the 501 catch-all. migration_status advanced to PHASE_2C_EXTERNAL_READS. migrated_routes list extended.

Timeout / retry strategy

Concern Choice
Per-call timeout (ledger) 3s via AbortController
Per-call timeout (each ecosystem service) 3s via AbortController
Aggregate deadline (fan-out) 5s via outer AbortController chained to per-call controllers
Retries None. Workers should fail fast; clients can retry at their own cadence.
Partial failure (ecosystem) HTTP 200 with ok: false, per-row error context
Upstream 404 (ledger) HTTP 404 with error: not_found
Upstream 5xx / network (ledger) HTTP 502 with error: ledger_unavailable, upstream_status preserved

Canonical compliance

  • // @canon: chittycanon://core/services/chittyassets header on every new file.
  • All five P/L/T/E/A entity types remain enumerated in env.ts (ENTITY_TYPES = ["P","L","T","E","A"]).
  • chittyId is type-agnostic per ledger schema; the chittyId may reference any of P/L/T/E/A.
  • Ecosystem services act as Authority (A) bearers — documented inline.
  • No tokens or credentials pasted; URLs read from c.env at runtime.

No-mocks compliance

Per the binding global "No mocks / fake data / placeholder endpoints" rule:

  • All new tests issue real fetch calls (no vi.mock, no nock).
  • Ledger test exercises the real 404/5xx path against https://ledger.chitty.cc and an unreachable host (real DNS failure).
  • Ecosystem test hits the live *.chitty.cc/health endpoints 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 in worker/ (pre-existing server/ errors only; grep -E '^worker/' on output is empty).

Tests: 5/5 new tests pass; all prior no-DB worker tests still pass.

✓ worker/__tests__/evidence-ledger.integration.test.ts (3 tests)
✓ worker/__tests__/ecosystem.integration.test.ts      (2 tests)

4 DB-backed test files require TEST_DB_URL to 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):

id.chitty.cc/health          -> HTTP 200 (53ms)
assets.chitty.cc/health      -> HTTP 522
trust.chitty.cc/health       -> HTTP 200 (52ms)
resolution.chitty.cc/health  -> DNS NXDOMAIN
file.chitty.cc/health        -> DNS NXDOMAIN

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

  • Unit/integration tests pass locally (5/5 new)
  • Typecheck clean for worker/
  • Wrangler dry-run succeeds
  • Live HTTP smoke test confirms real upstream behavior
  • After merge: deploy to prod and curl https://assets.chitty.cc/api/v1/status to confirm migration_status: PHASE_2C_EXTERNAL_READS
  • After merge: curl https://assets.chitty.cc/api/ecosystem/status with a valid ChittyAuth bearer and verify aggregated response

Unilateral decisions (called per no-clarifying-questions mode)

  1. 5 services exactly per spec: ChittyID, ChittyAssets, ChittyTrust, ChittyResolution, ChittyFile. The Express chittyEcosystem.ts lists 6 (adds SCHEMA, CHAIN, VERIFY); the spec called for 5, so I matched the spec.
  2. Defaults at https://{svc}.chitty.cc with 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).
  3. Degraded ecosystem → HTTP 200, not 502. Matches Express semantics and avoids cascading failures into callers that just want to poll.
  4. Invalid chittyId guard returns 400 before any upstream call — saves the 3s timeout on obviously malformed paths.
  5. No retries — Workers should fail fast; retry is a caller concern.

🤖 Generated with Claude Code

…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>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 17, 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.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9c6c0db8-b9f0-43ed-bf45-db0205dae9ac

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)
  • Create PR with unit tests
  • Commit unit tests in branch feat/hono-phase-2c-external-reads

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.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment on lines +33 to +37
export interface EcosystemStatus {
ok: boolean;
checked_at: string;
services: ServiceStatus[];
summary: {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge 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.tsservices.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 👍 / 👎.

Comment on lines +26 to +29
if (!CHITTY_ID_PATTERN.test(chittyId)) {
return c.json(
{ error: "invalid_chitty_id", message: "chittyId must match canonical format" },
400,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge 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 👍 / 👎.

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