feat: extract @kilocode/worker-utils shared package#683
Conversation
Create packages/worker-utils/ with 14 shared utilities extracted from individual workers, eliminating ~2900 lines of duplicated code: - withDORetry: DO retry with exponential backoff (6 copies → 1) - backendAuthMiddleware: Hono bearer auth (4 copies → 1) - withTimeout: async operation timeout (2 copies → 1) - createR2Client: R2 presigned URL factory (2 copies → 1) - resSuccess/resError: typed JSON response helpers (2 copies → 1) - zodJsonValidator: Hono Zod body validator (2 copies → 1) - timingSafeEqual: timing-safe string comparison (3 copies → 1) - formatError: error formatting for logging (2 copies → 1) - extractBearerToken: Bearer header extraction (7 inline → 1) - encryption: Web Crypto port of RSA-OAEP + AES-256-GCM envelope encryption, replacing node:crypto impl (3 copies → 1) - createErrorHandler/createNotFoundHandler: Hono handler factories - Owner, MCPServerConfig shared types Also removes dead deps (@hono/zod-validator from o11y, zod from auto-fix) and moves aws4fetch from cloud-agent/cloud-agent-next into worker-utils.
Code Review SummaryStatus: 2 Suggestions | Recommendation: Merge (address suggestions as follow-up) Overview
Other Observations (not in diff)Issues found in unchanged code or about missing files that cannot receive inline comments:
NotesThis is a well-executed refactoring PR that consolidates duplicated utilities from 8+ workers into a shared
Previous review comments about Files Reviewed (78 files)
|
…cryption - Restore JSDoc comments on do-retry (Cloudflare retry semantics, backoff formula, @param/@returns/@throws/@example, .overloaded note) - Add do-retry.test.ts with 18 tests (ported from cloud-agent-next + session-ingest) - Replace `as ArrayBuffer` casts in encryption.ts with safe .buffer.slice() - Parallelize independent encryptKiloClawSecret calls with Promise.all
…kages - Rewrite timingSafeEqual with JS polyfill fallback (removes global SubtleCrypto augmentation, works in Node.js/Next.js without crypto.subtle.timingSafeEqual) - Migrate timingSafeEqual consumers: kiloclaw, db-proxy, webhook-agent-ingest - Migrate formatError consumers: db-proxy, app-builder - Fix encryption.ts type errors (CryptoKey|CryptoKeyPair narrowing, ArrayBuffer|JsonWebKey narrowing) without using 'as' casts - Fix missing await on async mergeEnvVarsWithSecrets in both cloud-agent and cloud-agent-next session-service.ts - Fix deploy-builder env-decryptor: decryptWithPrivateKey is now async - Fix backendAuthMiddleware generic constraint so concrete Env types work - Parallelize buildWorkerChannelsPatch encryption calls - Add typecheck scripts to packages/db, session-ingest, o11y - Add typecheck:all script to root (pnpm -r run typecheck) - Add typescript devDep to cloudflare-session-ingest All 21 workspace packages pass pnpm typecheck:all.
|
Addressed the two unanswered review comments about unused deps in
Also completed the remaining migrations and fixed pre-existing type errors. Full details in b38963c. |
… extractBearerToken) - Replace gastown's res.util.ts with re-export shim from worker-utils - Use extractBearerToken from worker-utils in auth middleware - Make extractBearerToken case-insensitive per RFC 6750 §2.1 - Add @kilocode/worker-utils workspace dependency to gastown
… wrappers, auth migrations, split encryption - createErrorHandler: add includeMessage option (default true); cloud-agent-next and deploy-infra/builder opt out to preserve their existing no-message behavior - extractBearerToken: trim header before slicing to match old .trim() behavior - withDORetry: create thin logger-binding wrappers in cloud-agent, cloud-agent-next, and webhook-agent-ingest so structured logging is preserved - Complete backendAuthMiddleware migration in auto-fix, auto-triage, and deploy-infra/builder (removes inline auth boilerplate) - Complete extractBearerToken migration in gastown mayor-auth - Remove encryption changes (Web Crypto migration) — split to separate PR
These functions were changed from async to sync during the worker-utils extraction but call sites still had await, triggering await-thenable lint.
tsc is available directly via the typescript devDependency.
…ow-up PR Restore local timingSafeEqual implementations in cloudflare-db-proxy, cloudflare-webhook-agent-ingest, and kiloclaw to keep this PR focused on non-crypto utilities. The shared extraction will land in PR #697.
…ioral contracts - withDORetry and createErrorHandler now use logger.withFields() when available, preserving structured log output for WorkersLogger consumers - Restore original log message strings for grep/alert compatibility - extractBearerToken trims the extracted token, matching old gastown behavior - createErrorHandler falls back to 'Unknown error' for empty messages
2685a0f to
b9fb942
Compare
pandemicsyn
left a comment
There was a problem hiding this comment.
Pre-approving, but pretty sure scheduler.wait is what we want.
Ci's also complaining about a typecheck failure linting gastown.
…ble type inference The PR's broadened typecheck now includes gastown's individual tsgo check, which revealed that `unknown` in Agent.checkpoint and BeadRecord.metadata makes Cloudflare's Rpc.Serializable<T> resolve DO RPC return types to `never`. Recursive JSON value types cause 'excessively deep' instantiation. Using z.any() is the pragmatic fix — Zod still validates at runtime.
Prefer Cloudflare's scheduler.wait() over setTimeout for backoff delays in withDORetry, falling back to setTimeout in non-Workers environments. Consolidate duplicate @kilocode/worker-utils imports in session-ingest.
Summary
packages/worker-utils/as the second shared package (alongsidepackages/db/)Utilities extracted
withDORetrybackendAuthMiddlewarewithTimeoutcreateR2ClientresSuccess/resErrorzodJsonValidatortimingSafeEqualformatErrorextractBearerTokencreateErrorHandlerapp.onErrorfactorycreateNotFoundHandlerapp.notFoundfactoryOwnertypeMCPServerConfigtypeDesign decisions
withDORetrylogger injection: The shared implementation accepts an optional logger parameter (defaults toconsole). Workers with structured loggers (cloud-agent, cloud-agent-next, webhook-agent-ingest) use thin local wrappers that pre-bind theirWorkersLogger, preserving structured logging without touching call sites.createErrorHandlerincludeMessageoption: Defaults totrue(includesmessage: err.messagein 500 responses). Workers that previously had no message field (cloud-agent-next, deploy-infra/builder) opt out with{ includeMessage: false }.extractBearerToken: Trims the header before slicing, case-insensitive prefix match per RFC 6750.backendAuthMiddleware: Migrated in all 5 workers that had identical inline auth (auto-fix, auto-triage, code-review, deploy-infra/builder, plus the existing session-proxy usage).Dead dependency cleanup
aws4fetchfrom cloud-agent and cloud-agent-next (moved to worker-utils)@hono/zod-validatorfrom cloudflare-o11y (never imported)zodfrom cloudflare-auto-fix-infra (never imported)Not migrated (intentionally)
app.onError/app.notFoundin workers with non-standard response shapes (db-proxy, webhook-agent-ingest, ai-attribution, deploy-dispatcher)Follow-up
@kilocode/encryptionpackage (keeps existingnode:cryptoimplementation, no Web Crypto rewrite)