feat(api): REST API (server/api, Hono) を Cloudflare Workers ランタイム対応にする (#1091) - #1123
Conversation
Phase 2b of the Railway -> Cloudflare migration (#1088). Makes server/api runtime-compatible with Workers while keeping Railway/Node behavior intact: - Split LangGraph agent routes into appAgents.ts; the Worker entry no longer bundles @langchain/* / src/agents (createApp registerAgentRoutes hook) - clientIp: CF-Connecting-IP first on Workers (gated by the explicit RUNTIME var, never header sniffing); Node socket fallback moved to clientIpNode.ts - Sentry: runtime-neutral scrub helpers in sentryShared.ts, capture DI in errorHandler, @sentry/cloudflare withSentry wrapper on the Worker entry - KvStore: ioredis adapter moved behind createKvStoreNode.ts injection - articleExtractor: jsdom loaded lazily so the Worker module graph boots - worker:bundle:check: credential-free dry-run guard (5 forbidden markers, gzip size budget) wired into ci.yml and the dev deploy workflow - test:worker: workerd runtime tests via @cloudflare/vitest-pool-workers (health runtime field, CORS, route split, auth mount, masked errors, KV DO counters/one-time codes/deny-list, @aws-sdk presign) - wrangler.jsonc: RUNTIME var; .env.worker examples list all boot-required secrets (auth vars and placeholder DATABASE_URL until #1090) DB-backed success paths remain unverifiable until #1090 (D1) by design; they must return masked 5xx instead of Worker runtime errors. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…tices - Intent record 260718-api-workers-migration: requirements, NFR requirements/design, infrastructure design, CI/CD and operation artifacts (13 stages, infra scope), including reviewer verdicts and stage diaries - Promote affirmed team practices to aidlc/spaces/default/memory (team.md sections + project.md mandated/forbidden rules and learnings) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughThis PR adapts ChangesAPI Worker migration
Estimated code review effort: 5 (Critical) | ~120 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c48d6ef3c6
ℹ️ 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".
| import { describe, it, expect } from "vitest"; | ||
| import { FORBIDDEN_MARKERS, findForbiddenMarkers } from "./checkWorkerBundle.lib.js"; |
There was a problem hiding this comment.
Move server/api test out of scripts
For files under server/api, the root AGENTS.md placement table says tests must live under src/__tests__/ with the source tree mirrored, and colocated tests are forbidden; this new *.test.ts under server/api/scripts violates that documented layout. Please move it to the approved mirrored test location so future server/api tests remain discoverable and consistent with the project rule.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Actionable comments posted: 20
🧹 Nitpick comments (2)
server/api/src/__tests__/worker/kvDurableObject.test.ts (1)
23-30: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winAssert that subsequent increments do not refresh the TTL.
This only verifies the count. A regression that renews the fixed-window expiry on every increment still passes; assert the remaining TTL decreases after a delayed second increment.
As per coding guidelines, “Mutation scoreを第一指標とする” and tests must serve as specifications rather than implementation mirrors.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@server/api/src/__tests__/worker/kvDurableObject.test.ts` around lines 23 - 30, Extend the incrWithTtl test to verify fixed-window expiry behavior, not only returned counts. After the first increment, record the key’s remaining TTL using the store’s existing TTL inspection API, delay before the second increment, then assert the remaining TTL has decreased rather than being refreshed. Keep the existing count assertions intact.Source: Coding guidelines
aidlc/spaces/default/intents/260718-api-workers-migration/construction/api-worker/infrastructure-design/monitoring-design.md (1)
17-18: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick winMake CI assert the Worker runtime marker.
curl --failonly checks the HTTP status, so a stale or incorrect endpoint can pass without provingruntime: "cloudflare-workers". Parse the health response and fail unless that field matches; keep manual inspection as a supplement.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@aidlc/spaces/default/intents/260718-api-workers-migration/construction/api-worker/infrastructure-design/monitoring-design.md` around lines 17 - 18, Update the CI health-check flow referenced by deploy-api-worker-dev.yml so it parses the /api/health response and fails unless the runtime field exactly equals "cloudflare-workers". Retain the existing HTTP failure handling and manual dev verification as supplementary checks.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@aidlc/spaces/default/intents/260718-api-workers-migration/aidlc-state.md`:
- Line 21: The tracked artifacts contain workstation-specific absolute paths
that must be removed. In
aidlc/spaces/default/intents/260718-api-workers-migration/aidlc-state.md:21,
replace the Project Root value with a repository-relative path or placeholder;
in
aidlc/spaces/default/intents/260718-api-workers-migration/audit/saedgewell-353e06d8a0b4.md:214,
225, 338, 349, 445, 520, 531, 594, and 605, redact each absolute Destination
path; and at lines 246 and 255, redact each absolute --project-dir path,
preserving the surrounding audit content.
In
`@aidlc/spaces/default/intents/260718-api-workers-migration/audit/saedgewell-353e06d8a0b4.md`:
- Line 53: Update the generated audit-log format around the Stage Start heading
so repeated headings such as Stage Completion, Stage Start, and Human Turn are
either made unique per occurrence or excluded through a narrowly scoped MD024
lint exception specific to this format.
In
`@aidlc/spaces/default/intents/260718-api-workers-migration/construction/api-worker/infrastructure-design/deployment-architecture.md`:
- Line 7: Update the fenced topology block in the deployment architecture
document by adding the text language identifier immediately after its opening
fence, preserving the block’s existing contents so it passes MD040.
In
`@aidlc/spaces/default/intents/260718-api-workers-migration/construction/api-worker/infrastructure-design/infrastructure-design-questions.md`:
- Line 15: Update the recorded answer in the infrastructure design questions
document to use plain text rather than Markdown reference-definition syntax:
replace the bracketed “Answer” label with an unbracketed label while preserving
the approval value and timestamp.
In
`@aidlc/spaces/default/intents/260718-api-workers-migration/construction/api-worker/infrastructure-design/shared-infrastructure.md`:
- Line 9: Update the BETTER_AUTH_SECRET entry in the shared infrastructure
design so deployment preflight enforces parity across api, mcp, hocuspocus, and
the Worker. Require either one shared secret-manager version or comparison of
non-reversible fingerprints, and ensure secret values are never logged.
In
`@aidlc/spaces/default/intents/260718-api-workers-migration/construction/api-worker/nfr-design/nfr-design-questions.md`:
- Line 21: Update the answer entry in the NFR design questions document to use
plain text rather than Markdown link-reference syntax, removing the brackets
around “Answer” while preserving the approval value and date.
In
`@aidlc/spaces/default/intents/260718-api-workers-migration/construction/api-worker/nfr-requirements/reliability-requirements.md`:
- Around line 10-13: Define one enforceable client-safe 5xx response contract in
reliability-requirements.md lines 10-13, requiring normalized sanitized
responses for all internal failures while sending detailed exceptions only to
Sentry or logging. Apply the same contract requirement in
security-requirements.md lines 10-13, and align the implementation guidance in
tech-stack-decisions.md line 43 so it does not expose err.message to clients.
In
`@aidlc/spaces/default/intents/260718-api-workers-migration/construction/api-worker/nfr-requirements/tech-stack-decisions.md`:
- Around line 36-43: Update the audit findings in the Findings section to remove
or mark resolved the RL-5 and PR-4 findings, since the requirements now
distinguish CI HTTP checks from manual runtime validation and require observing
CPU errors during dev verification. Keep an explicit unresolved finding for the
PR-1 checklist gap, identifying who performs the manual parity check and through
which path, and retain its dependency on resolving C-2 credentials.
In
`@aidlc/spaces/default/intents/260718-api-workers-migration/construction/ci-pipeline/ci-config.md`:
- Around line 9-10: Align the Worker-test CI records with the resolved
compatibility decision in tech-stack-decisions.md: in
aidlc/spaces/default/intents/260718-api-workers-migration/construction/ci-pipeline/ci-config.md
lines 9-10, remove the undecided fallback wording or document the selected
fallback; in
aidlc/spaces/default/intents/260718-api-workers-migration/construction/ci-pipeline/ci-pipeline-questions.md
lines 3-5, update the “no questions” record to reflect the finalized CI
contract.
In
`@aidlc/spaces/default/intents/260718-api-workers-migration/operation/deployment-execution/deployment-execution-questions.md`:
- Line 5: Synchronize the deployment records with the current PR state: update
the implementation-status statement in deployment-execution-questions.md at line
5 and deployment-log.md at line 7 to remove or clearly mark the stale
“implementation not yet present” claim, so the rollout is not incorrectly
deferred.
In
`@aidlc/spaces/default/intents/260718-api-workers-migration/operation/deployment-execution/health-check-report.md`:
- Around line 7-9: Update the deployment health validation so a missing
WORKER_API_BASE_URL cannot silently skip the health gate or report success.
Configure the workers.dev URL before enabling the rollout, or make the
validation job fail explicitly when the variable is unset, while preserving the
/api/health polling behavior when it is configured.
In
`@aidlc/spaces/default/intents/260718-api-workers-migration/operation/deployment-execution/smoke-test-results.md`:
- Around line 5-12: Update the implementation status in the smoke-test results
table to indicate that the Worker implementation and validation files are
complete, while preserving the separate status that deployment and manual dev
verification have not yet occurred.
In
`@aidlc/spaces/default/intents/260718-api-workers-migration/operation/deployment-pipeline/cd-config.md`:
- Around line 7-14: Specify a language on the fenced Markdown block containing
the deployment pipeline diagram, using text (or another appropriate non-code
language) while preserving its contents unchanged.
In
`@aidlc/spaces/default/intents/260718-api-workers-migration/operation/environment-provisioning/environment-inventory.md`:
- Around line 26-28: Update the “ローカル wrangler” entry in the environment
inventory to reflect that authentication was corrected, removing the stale
wrong-account/C-2 status. Keep the “CI トークン(CLOUDFLARE_API_TOKEN)” entry marked
as unresolved, and leave the Cloudflare MCP entry unchanged.
In
`@aidlc/spaces/default/intents/260718-api-workers-migration/operation/environment-provisioning/validation-report.md`:
- Around line 9-11: Remove the operator email address and Cloudflare account
identifier from the deployment evidence in validation-report.md lines 9-11.
Apply the same redaction to the duplicated identifiers in deployment-log.md
lines 13-16, preserving the remaining validation and deployment details.
In `@server/api/src/__tests__/worker/worker.test.ts`:
- Around line 70-76: Update the test named “responds to /api/auth/get-session as
well-formed JSON (no workerd crash)” to verify its promised response shape:
assert an application/json content type and successfully parse the response body
as JSON, while retaining the existing status-range and non-rejection checks.
In `@server/api/src/lib/sentryShared.ts`:
- Around line 101-120: Update scrubSentryEvent to recursively scrub request
query strings and contexts: make the query_string handling pass object values
through scrubDeep while preserving string handling via scrubQueryStringField,
and replace shallow contexts scrubbing with scrubDeep. Keep the existing
behavior for other request, user, and extra fields unchanged.
In `@server/api/src/middleware/errorHandler.ts`:
- Line 42: Sanitize attacker-controlled request and error values before the
console.error calls in the error handler’s branches, including c.req.path,
err.message, and the thrown error at the referenced logging sites. Remove or
escape CR/LF characters, or use a structured logger that safely encodes these
fields, while preserving the existing method, path, status, and error context.
- Around line 40-49: Update the HTTPException handling branch to return the
generic “Internal server error” message for all 5xx statuses, while preserving
err.message for non-5xx responses. Keep the existing logging, capture behavior,
and status code unchanged.
In `@server/api/src/services/articleExtractor.ts`:
- Around line 12-20: The lazy loadJsdom import still allows the Node-only jsdom
dependency to be reached through the shared /api/clip Worker route. Remove this
dependency from the Worker execution path by routing extractArticleFromUrl to a
Worker-compatible parser or excluding the route from Worker deployment, and add
a contract test confirming the Worker path does not load or invoke jsdom.
---
Nitpick comments:
In
`@aidlc/spaces/default/intents/260718-api-workers-migration/construction/api-worker/infrastructure-design/monitoring-design.md`:
- Around line 17-18: Update the CI health-check flow referenced by
deploy-api-worker-dev.yml so it parses the /api/health response and fails unless
the runtime field exactly equals "cloudflare-workers". Retain the existing HTTP
failure handling and manual dev verification as supplementary checks.
In `@server/api/src/__tests__/worker/kvDurableObject.test.ts`:
- Around line 23-30: Extend the incrWithTtl test to verify fixed-window expiry
behavior, not only returned counts. After the first increment, record the key’s
remaining TTL using the store’s existing TTL inspection API, delay before the
second increment, then assert the remaining TTL has decreased rather than being
refreshed. Keep the existing count assertions intact.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: d3352752-19bc-466c-9912-f92cfeef02f7
⛔ Files ignored due to path filters (1)
server/api/bun.lockis excluded by!**/*.lock
📒 Files selected for processing (95)
.github/workflows/ci.yml.github/workflows/deploy-api-worker-dev.ymlaidlc/spaces/default/intents/260718-api-workers-migration/aidlc-state.mdaidlc/spaces/default/intents/260718-api-workers-migration/audit/saedgewell-353e06d8a0b4.mdaidlc/spaces/default/intents/260718-api-workers-migration/construction/api-worker/infrastructure-design/cicd-pipeline.mdaidlc/spaces/default/intents/260718-api-workers-migration/construction/api-worker/infrastructure-design/deployment-architecture.mdaidlc/spaces/default/intents/260718-api-workers-migration/construction/api-worker/infrastructure-design/infrastructure-design-questions.mdaidlc/spaces/default/intents/260718-api-workers-migration/construction/api-worker/infrastructure-design/infrastructure-services.mdaidlc/spaces/default/intents/260718-api-workers-migration/construction/api-worker/infrastructure-design/monitoring-design.mdaidlc/spaces/default/intents/260718-api-workers-migration/construction/api-worker/infrastructure-design/shared-infrastructure.mdaidlc/spaces/default/intents/260718-api-workers-migration/construction/api-worker/nfr-design/logical-components.mdaidlc/spaces/default/intents/260718-api-workers-migration/construction/api-worker/nfr-design/nfr-design-questions.mdaidlc/spaces/default/intents/260718-api-workers-migration/construction/api-worker/nfr-design/performance-design.mdaidlc/spaces/default/intents/260718-api-workers-migration/construction/api-worker/nfr-design/reliability-design.mdaidlc/spaces/default/intents/260718-api-workers-migration/construction/api-worker/nfr-design/scalability-design.mdaidlc/spaces/default/intents/260718-api-workers-migration/construction/api-worker/nfr-design/security-design.mdaidlc/spaces/default/intents/260718-api-workers-migration/construction/api-worker/nfr-requirements/nfr-requirements-questions.mdaidlc/spaces/default/intents/260718-api-workers-migration/construction/api-worker/nfr-requirements/performance-requirements.mdaidlc/spaces/default/intents/260718-api-workers-migration/construction/api-worker/nfr-requirements/reliability-requirements.mdaidlc/spaces/default/intents/260718-api-workers-migration/construction/api-worker/nfr-requirements/scalability-requirements.mdaidlc/spaces/default/intents/260718-api-workers-migration/construction/api-worker/nfr-requirements/security-requirements.mdaidlc/spaces/default/intents/260718-api-workers-migration/construction/api-worker/nfr-requirements/tech-stack-decisions.mdaidlc/spaces/default/intents/260718-api-workers-migration/construction/ci-pipeline/ci-config.mdaidlc/spaces/default/intents/260718-api-workers-migration/construction/ci-pipeline/ci-pipeline-questions.mdaidlc/spaces/default/intents/260718-api-workers-migration/construction/ci-pipeline/memory.mdaidlc/spaces/default/intents/260718-api-workers-migration/construction/ci-pipeline/quality-gates.mdaidlc/spaces/default/intents/260718-api-workers-migration/construction/infrastructure-design/memory.mdaidlc/spaces/default/intents/260718-api-workers-migration/construction/nfr-design/memory.mdaidlc/spaces/default/intents/260718-api-workers-migration/construction/nfr-requirements/memory.mdaidlc/spaces/default/intents/260718-api-workers-migration/inception/practices-discovery/discovered-rules.mdaidlc/spaces/default/intents/260718-api-workers-migration/inception/practices-discovery/evidence.mdaidlc/spaces/default/intents/260718-api-workers-migration/inception/practices-discovery/memory.mdaidlc/spaces/default/intents/260718-api-workers-migration/inception/practices-discovery/practices-discovery-questions.mdaidlc/spaces/default/intents/260718-api-workers-migration/inception/practices-discovery/practices-discovery-timestamp.mdaidlc/spaces/default/intents/260718-api-workers-migration/inception/practices-discovery/team-practices.mdaidlc/spaces/default/intents/260718-api-workers-migration/inception/requirements-analysis/memory.mdaidlc/spaces/default/intents/260718-api-workers-migration/inception/requirements-analysis/requirements-analysis-questions.mdaidlc/spaces/default/intents/260718-api-workers-migration/inception/requirements-analysis/requirements.mdaidlc/spaces/default/intents/260718-api-workers-migration/operation/deployment-execution/deployment-execution-questions.mdaidlc/spaces/default/intents/260718-api-workers-migration/operation/deployment-execution/deployment-log.mdaidlc/spaces/default/intents/260718-api-workers-migration/operation/deployment-execution/health-check-report.mdaidlc/spaces/default/intents/260718-api-workers-migration/operation/deployment-execution/memory.mdaidlc/spaces/default/intents/260718-api-workers-migration/operation/deployment-execution/smoke-test-results.mdaidlc/spaces/default/intents/260718-api-workers-migration/operation/deployment-pipeline/cd-config.mdaidlc/spaces/default/intents/260718-api-workers-migration/operation/deployment-pipeline/deployment-pipeline-questions.mdaidlc/spaces/default/intents/260718-api-workers-migration/operation/deployment-pipeline/deployment-strategy.mdaidlc/spaces/default/intents/260718-api-workers-migration/operation/deployment-pipeline/memory.mdaidlc/spaces/default/intents/260718-api-workers-migration/operation/deployment-pipeline/rollback-runbook.mdaidlc/spaces/default/intents/260718-api-workers-migration/operation/environment-provisioning/environment-inventory.mdaidlc/spaces/default/intents/260718-api-workers-migration/operation/environment-provisioning/environment-provisioning-questions.mdaidlc/spaces/default/intents/260718-api-workers-migration/operation/environment-provisioning/memory.mdaidlc/spaces/default/intents/260718-api-workers-migration/operation/environment-provisioning/validation-report.mdaidlc/spaces/default/intents/260718-api-workers-migration/operation/observability-setup/alarms.mdaidlc/spaces/default/intents/260718-api-workers-migration/operation/observability-setup/anomaly-config.mdaidlc/spaces/default/intents/260718-api-workers-migration/operation/observability-setup/dashboards.mdaidlc/spaces/default/intents/260718-api-workers-migration/operation/observability-setup/log-queries.mdaidlc/spaces/default/intents/260718-api-workers-migration/operation/observability-setup/memory.mdaidlc/spaces/default/intents/260718-api-workers-migration/operation/observability-setup/observability-setup-questions.mdaidlc/spaces/default/intents/260718-api-workers-migration/operation/observability-setup/slo-config.mdaidlc/spaces/default/intents/260718-api-workers-migration/operation/observability-setup/tracing-config.mdaidlc/spaces/default/intents/intents.jsonaidlc/spaces/default/memory/project.mdaidlc/spaces/default/memory/team.mdserver/api/.env.worker.dev.exampleserver/api/.env.worker.production.exampleserver/api/package.jsonserver/api/scripts/checkWorkerBundle.lib.test.tsserver/api/scripts/checkWorkerBundle.lib.tsserver/api/scripts/checkWorkerBundle.tsserver/api/src/__tests__/app.test.tsserver/api/src/__tests__/lib/clientIp.test.tsserver/api/src/__tests__/lib/kv/createKvStore.test.tsserver/api/src/__tests__/lib/sentryWorkerOptions.test.tsserver/api/src/__tests__/middleware/errorHandler.test.tsserver/api/src/__tests__/services/articleExtractor.test.tsserver/api/src/__tests__/worker/kvDurableObject.test.tsserver/api/src/__tests__/worker/presign.test.tsserver/api/src/__tests__/worker/worker.test.tsserver/api/src/app.tsserver/api/src/appAgents.tsserver/api/src/index.tsserver/api/src/lib/clientIp.tsserver/api/src/lib/clientIpNode.tsserver/api/src/lib/kv/createKvStore.tsserver/api/src/lib/kv/createKvStoreNode.tsserver/api/src/lib/sentry.tsserver/api/src/lib/sentryShared.tsserver/api/src/lib/sentryWorker.tsserver/api/src/lib/sentryWorkerOptions.tsserver/api/src/middleware/errorHandler.tsserver/api/src/services/articleExtractor.tsserver/api/src/worker.tsserver/api/vitest.config.tsserver/api/vitest.config.worker.tsserver/api/wrangler.jsonc
| - **Test Strategy**: Standard | ||
|
|
||
| ## Workspace State | ||
| - **Project Root**: C:\Users\saedg\apps\zedi |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win
Remove workstation-specific absolute paths from the tracked artifacts.
aidlc/spaces/default/intents/260718-api-workers-migration/aidlc-state.md#L21-L21: replaceC:\Users\saedg\apps\zediwith a repository-relative path or placeholder.aidlc/spaces/default/intents/260718-api-workers-migration/audit/saedgewell-353e06d8a0b4.md#L214-L214: redact the absoluteDestinationpath.aidlc/spaces/default/intents/260718-api-workers-migration/audit/saedgewell-353e06d8a0b4.md#L225-L225: redact the absoluteDestinationpath.aidlc/spaces/default/intents/260718-api-workers-migration/audit/saedgewell-353e06d8a0b4.md#L246-L246: redact the absolute--project-dirpath.aidlc/spaces/default/intents/260718-api-workers-migration/audit/saedgewell-353e06d8a0b4.md#L255-L255: redact the absolute--project-dirpath.aidlc/spaces/default/intents/260718-api-workers-migration/audit/saedgewell-353e06d8a0b4.md#L338-L338: redact the absoluteDestinationpath.aidlc/spaces/default/intents/260718-api-workers-migration/audit/saedgewell-353e06d8a0b4.md#L349-L349: redact the absoluteDestinationpath.aidlc/spaces/default/intents/260718-api-workers-migration/audit/saedgewell-353e06d8a0b4.md#L445-L445: redact the absoluteDestinationpath.aidlc/spaces/default/intents/260718-api-workers-migration/audit/saedgewell-353e06d8a0b4.md#L520-L520: redact the absoluteDestinationpath.aidlc/spaces/default/intents/260718-api-workers-migration/audit/saedgewell-353e06d8a0b4.md#L531-L531: redact the absoluteDestinationpath.aidlc/spaces/default/intents/260718-api-workers-migration/audit/saedgewell-353e06d8a0b4.md#L594-L594: redact the absoluteDestinationpath.aidlc/spaces/default/intents/260718-api-workers-migration/audit/saedgewell-353e06d8a0b4.md#L605-L605: redact the absoluteDestinationpath.
📍 Affects 2 files
aidlc/spaces/default/intents/260718-api-workers-migration/aidlc-state.md#L21-L21(this comment)aidlc/spaces/default/intents/260718-api-workers-migration/audit/saedgewell-353e06d8a0b4.md#L214-L214aidlc/spaces/default/intents/260718-api-workers-migration/audit/saedgewell-353e06d8a0b4.md#L225-L225aidlc/spaces/default/intents/260718-api-workers-migration/audit/saedgewell-353e06d8a0b4.md#L246-L246aidlc/spaces/default/intents/260718-api-workers-migration/audit/saedgewell-353e06d8a0b4.md#L255-L255aidlc/spaces/default/intents/260718-api-workers-migration/audit/saedgewell-353e06d8a0b4.md#L338-L338aidlc/spaces/default/intents/260718-api-workers-migration/audit/saedgewell-353e06d8a0b4.md#L349-L349aidlc/spaces/default/intents/260718-api-workers-migration/audit/saedgewell-353e06d8a0b4.md#L445-L445aidlc/spaces/default/intents/260718-api-workers-migration/audit/saedgewell-353e06d8a0b4.md#L520-L520aidlc/spaces/default/intents/260718-api-workers-migration/audit/saedgewell-353e06d8a0b4.md#L531-L531aidlc/spaces/default/intents/260718-api-workers-migration/audit/saedgewell-353e06d8a0b4.md#L594-L594aidlc/spaces/default/intents/260718-api-workers-migration/audit/saedgewell-353e06d8a0b4.md#L605-L605
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@aidlc/spaces/default/intents/260718-api-workers-migration/aidlc-state.md` at
line 21, The tracked artifacts contain workstation-specific absolute paths that
must be removed. In
aidlc/spaces/default/intents/260718-api-workers-migration/aidlc-state.md:21,
replace the Project Root value with a repository-relative path or placeholder;
in
aidlc/spaces/default/intents/260718-api-workers-migration/audit/saedgewell-353e06d8a0b4.md:214,
225, 338, 349, 445, 520, 531, 594, and 605, redact each absolute Destination
path; and at lines 246 and 255, redact each absolute --project-dir path,
preserving the surrounding audit content.
|
|
||
| --- | ||
|
|
||
| ## Stage Start |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Resolve the repeated-heading lint failures.
This generated log reuses headings such as Stage Completion, Stage Start, and Human Turn, triggering the reported MD024 warnings. Either make headings unique or add a narrowly scoped lint exception for this audit-log format.
🧰 Tools
🪛 markdownlint-cli2 (0.23.0)
[warning] 53-53: Multiple headings with the same content
(MD024, no-duplicate-heading)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@aidlc/spaces/default/intents/260718-api-workers-migration/audit/saedgewell-353e06d8a0b4.md`
at line 53, Update the generated audit-log format around the Stage Start heading
so repeated headings such as Stage Completion, Stage Start, and Human Turn are
either made unique per occurrence or excluded through a narrowly scoped MD024
lint exception specific to this format.
Source: Linters/SAST tools
|
|
||
| ## 構成トポロジ(本 Issue 完了時点) | ||
|
|
||
| ``` |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Add a language identifier to the fenced topology block.
Use text (or another appropriate identifier) after the opening fence so the document passes the reported MD040 check.
🧰 Tools
🪛 markdownlint-cli2 (0.23.0)
[warning] 7-7: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@aidlc/spaces/default/intents/260718-api-workers-migration/construction/api-worker/infrastructure-design/deployment-architecture.md`
at line 7, Update the fenced topology block in the deployment architecture
document by adding the text language identifier immediately after its opening
fence, preserving the block’s existing contents so it passes MD040.
Source: Linters/SAST tools
|
|
||
| Infrastructure Design 5成果物(READY)の承認ゲート。チャットに approve / request changes をタイプしてください。 | ||
|
|
||
| [Answer]: approve (typed, 2026-07-18) |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Avoid Markdown reference-definition syntax for the recorded answer.
[Answer]: approve ... is interpreted as an unused link reference and triggers MD053. Use plain text such as Answer: approve (typed, 2026-07-18).
🧰 Tools
🪛 markdownlint-cli2 (0.23.0)
[warning] 15-15: Link and image reference definitions should be needed
Unused link or image reference definition: "answer"
(MD053, link-image-reference-definitions)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@aidlc/spaces/default/intents/260718-api-workers-migration/construction/api-worker/infrastructure-design/infrastructure-design-questions.md`
at line 15, Update the recorded answer in the infrastructure design questions
document to use plain text rather than Markdown reference-definition syntax:
replace the bracketed “Answer” label with an unbracketed label while preserving
the approval value and timestamp.
Source: Linters/SAST tools
|
|
||
| | 共有物 | 共有先 | 本 Issue での扱い | | ||
| |--------|--------|------------------| | ||
| | `BETTER_AUTH_SECRET` | api ↔ mcp ↔ hocuspocus | 値の同期は運用ルールのまま(自動強制なし、既知ギャップ)。Worker へは `wrangler secret bulk` で供給 | |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift
Enforce BETTER_AUTH_SECRET parity before deployment.
This migration adds another independently managed secret copy while leaving synchronization unenforced. A drifted Worker secret can invalidate sessions or break cross-service authentication without failing deployment. Consume one secret-manager version or compare non-reversible fingerprints in a preflight; never log the secret values.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@aidlc/spaces/default/intents/260718-api-workers-migration/construction/api-worker/infrastructure-design/shared-infrastructure.md`
at line 9, Update the BETTER_AUTH_SECRET entry in the shared infrastructure
design so deployment preflight enforces parity across api, mcp, hocuspocus, and
the Worker. Require either one shared secret-manager version or comparison of
non-reversible fingerprints, and ensure secret values are never logged.
| it("responds to /api/auth/get-session as well-formed JSON (no workerd crash)", async () => { | ||
| const res = await dispatch("/api/auth/get-session"); | ||
| // DB 未接続のため成功は要求しない。Worker ランタイム例外(fetch reject)に | ||
| // ならず、HTTP レスポンスとして整形されていることが合格条件。 | ||
| expect(res.status).toBeGreaterThanOrEqual(200); | ||
| expect(res.status).toBeLessThan(600); | ||
| }); |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Verify the claimed JSON response shape.
The test name promises well-formed JSON, but any response with a 200–599 status passes. Assert an application/json content type and parse the body, or rename the test to describe status-only compatibility.
As per coding guidelines, tests serve as a source of truth for specifications alongside implementation documentation.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@server/api/src/__tests__/worker/worker.test.ts` around lines 70 - 76, Update
the test named “responds to /api/auth/get-session as well-formed JSON (no
workerd crash)” to verify its promised response shape: assert an
application/json content type and successfully parse the response body as JSON,
while retaining the existing status-range and non-rejection checks.
Source: Coding guidelines
| export function scrubSentryEvent<T extends ScrubbableSentryEvent>(event: T): T { | ||
| if (event.request) { | ||
| event.request = { | ||
| ...event.request, | ||
| url: scrubRequestUrl(event.request.url), | ||
| headers: scrubShallowRecord(event.request.headers), | ||
| data: scrubDeep(event.request.data, new WeakSet()), | ||
| query_string: scrubQueryStringField(event.request.query_string), | ||
| cookies: scrubCookies(event.request.cookies), | ||
| }; | ||
| } | ||
| if (event.user) { | ||
| event.user = scrubShallowRecord(event.user) ?? event.user; | ||
| } | ||
| if (event.extra) { | ||
| event.extra = scrubDeep(event.extra, new WeakSet()) as typeof event.extra; | ||
| } | ||
| if (event.contexts) { | ||
| event.contexts = scrubShallowRecord(event.contexts) ?? event.contexts; | ||
| } |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
Recursively scrub object query strings and nested contexts.
query_string objects pass through unchanged, while contexts only receives top-level scrubbing. Both can therefore retain nested token, password, or cookie values sent to Sentry.
Proposed fix
if (event.contexts) {
- event.contexts = scrubShallowRecord(event.contexts) ?? event.contexts;
+ event.contexts = scrubDeep(event.contexts, new WeakSet()) as typeof event.contexts;
}
function scrubQueryStringField(value: unknown): unknown {
- if (typeof value !== "string") return value;
- return value.replace(SENSITIVE_QUERY_PARAM_RE, `$1${FILTERED}`);
+ if (typeof value === "string") {
+ return value.replace(SENSITIVE_QUERY_PARAM_RE, `$1${FILTERED}`);
+ }
+ if (value !== null && typeof value === "object") {
+ return scrubDeep(value, new WeakSet());
+ }
+ return value;
}Also applies to: 224-228
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@server/api/src/lib/sentryShared.ts` around lines 101 - 120, Update
scrubSentryEvent to recursively scrub request query strings and contexts: make
the query_string handling pass object values through scrubDeep while preserving
string handling via scrubQueryStringField, and replace shallow contexts
scrubbing with scrubDeep. Keep the existing behavior for other request, user,
and extra fields unchanged.
| if (err instanceof HTTPException) { | ||
| const status = err.status; | ||
| console.error(`[api] ${c.req.method} ${c.req.path} → ${status}`, err.message); | ||
| if (shouldCaptureApiException(status)) { | ||
| capture(err, status, { | ||
| method: c.req.method, | ||
| routePath: c.req.routePath, | ||
| }); | ||
| } | ||
| return c.json({ error: err.message }, status); |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
Preserve 5xx masking in the HTTPException branch.
Unlike the generic branch, this returns err.message for status 500+, so new HTTPException(500, { message: ... }) can expose database, schema, or connection details. The documented contract requires { error: "Internal server error" } for every 5xx response.
Proposed fix
- return c.json({ error: err.message }, status);
+ const responseMessage = status >= 500 ? "Internal server error" : err.message;
+ return c.json({ error: responseMessage }, status);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if (err instanceof HTTPException) { | |
| const status = err.status; | |
| console.error(`[api] ${c.req.method} ${c.req.path} → ${status}`, err.message); | |
| if (shouldCaptureApiException(status)) { | |
| capture(err, status, { | |
| method: c.req.method, | |
| routePath: c.req.routePath, | |
| }); | |
| } | |
| return c.json({ error: err.message }, status); | |
| if (err instanceof HTTPException) { | |
| const status = err.status; | |
| console.error(`[api] ${c.req.method} ${c.req.path} → ${status}`, err.message); | |
| if (shouldCaptureApiException(status)) { | |
| capture(err, status, { | |
| method: c.req.method, | |
| routePath: c.req.routePath, | |
| }); | |
| } | |
| const responseMessage = status >= 500 ? "Internal server error" : err.message; | |
| return c.json({ error: responseMessage }, status); |
🧰 Tools
🪛 ast-grep (0.44.1)
[warning] 41-41: Logging request-derived input unsanitized allows log forging (CRLF injection); strip newlines / encode the value before logging.
Context: console.error([api] ${c.req.method} ${c.req.path} → ${status}, err.message)
Note: [CWE-117] Improper Output Neutralization for Logs. OWASP A09:2021 Security Logging and Monitoring Failures.
(log-injection-typescript)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@server/api/src/middleware/errorHandler.ts` around lines 40 - 49, Update the
HTTPException handling branch to return the generic “Internal server error”
message for all 5xx statuses, while preserving err.message for non-5xx
responses. Keep the existing logging, capture behavior, and status code
unchanged.
| return (err, c) => { | ||
| if (err instanceof HTTPException) { | ||
| const status = err.status; | ||
| console.error(`[api] ${c.req.method} ${c.req.path} → ${status}`, err.message); |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win
Neutralize request and error values before logging.
c.req.path, err.message, and the thrown error can contain attacker-controlled CR/LF characters. Writing them directly permits log-line injection and can corrupt downstream parsing and alerts. Escape or remove CR/LF characters in both branches, or use a structured logger that guarantees safe JSON encoding.
Also applies to: 65-65
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@server/api/src/middleware/errorHandler.ts` at line 42, Sanitize
attacker-controlled request and error values before the console.error calls in
the error handler’s branches, including c.req.path, err.message, and the thrown
error at the referenced logging sites. Remove or escape CR/LF characters, or use
a structured logger that safely encodes these fields, while preserving the
existing method, path, status, and error context.
Source: Linters/SAST tools
| // jsdom は Node 専用(workerd では実行不可)のため静的 import しない。 | ||
| // Worker のモジュールロードを通し、clip 実行時のみ評価する(呼ばれた場合の | ||
| // 失敗は onError でマスク済み 5xx になる — #1091 RL-3)。 | ||
| // jsdom is Node-only; load it lazily so the Worker module graph still boots. | ||
| type JsdomModule = typeof import("jsdom"); | ||
| let _jsdom: JsdomModule | null = null; | ||
| async function loadJsdom(): Promise<JsdomModule> { | ||
| if (!_jsdom) _jsdom = await import("jsdom"); | ||
| return _jsdom; |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
rg -n -C 4 'extractArticleFromUrl|app\.route\("/api/clip"' server/api/srcRepository: otomatty/zedi
Length of output: 34209
Keep jsdom out of the Worker path The lazy import only shifts the failure to first use; jsdom is still Node-only, and the shared app mounts /api/clip, which reaches extractArticleFromUrl() at runtime. Exclude this flow from the Worker graph or swap in a Worker-compatible parser, and add a Worker-path contract test.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@server/api/src/services/articleExtractor.ts` around lines 12 - 20, The lazy
loadJsdom import still allows the Node-only jsdom dependency to be reached
through the shared /api/clip Worker route. Remove this dependency from the
Worker execution path by routing extractArticleFromUrl to a Worker-compatible
parser or excluding the route from Worker deployment, and add a contract test
confirming the Worker path does not load or invoke jsdom.
Source: Coding guidelines
knip misreads the cloudflare:test virtual module (vitest-pool-workers) as an unlisted 'cloudflare' npm dependency in the worker runtime tests. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…al split Deploy validation runs module-load code (auth.ts) which needs DATABASE_URL + the Better Auth / OAuth secrets before wrangler deploy can pass startup check. Mark those 8 as required, separate optional/no-op secrets, and note which values come from wrangler.jsonc vars/bindings rather than secrets (#1091). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@server/api/.env.worker.production.example`:
- Around line 39-41: Remove the localhost placeholder from the production
environment configuration and provide a reachable production DATABASE_URL;
alternatively, update resolveCheckpointerForRun() so boot-time DATABASE_URL
initialization does not implicitly enable PostgresSaver checkpointing. Ensure
compose-session requests do not attempt to connect to 127.0.0.1:5432 in
production.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 87edc5bd-254c-439f-9eff-1bbe06c6cc68
📒 Files selected for processing (2)
server/api/.env.worker.dev.exampleserver/api/.env.worker.production.example
| # DB 接続文字列。auth.ts の drizzle アダプタがモジュールロード時に pg.Pool を | ||
| # 構築するため **起動時に必須**。D1 移行(#1090)までは到達しないプレースホルダで良い。 | ||
| DATABASE_URL=postgresql://placeholder:unused@127.0.0.1:5432/unused |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift
Do not ship the localhost placeholder as an active production DATABASE_URL.
Because resolveCheckpointerForRun() enables Postgres checkpointing whenever DATABASE_URL is present (server/api/src/agents/core/checkpoint/index.ts:17-24), this value makes production attempt PostgresSaver.setup() against 127.0.0.1:5432, causing compose-session requests to fail. Provide a reachable database URL, or change the runtime contract so boot-time DB initialization does not implicitly enable checkpointing.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@server/api/.env.worker.production.example` around lines 39 - 41, Remove the
localhost placeholder from the production environment configuration and provide
a reachable production DATABASE_URL; alternatively, update
resolveCheckpointerForRun() so boot-time DATABASE_URL initialization does not
implicitly enable PostgresSaver checkpointing. Ensure compose-session requests
do not attempt to connect to 127.0.0.1:5432 in production.
Complements secrets-template.md (lifecycle ledger) with a practical guide on where each .env.worker value comes from — mostly copy from Railway api vars, plus R2 access keys and OAuth console pointers (#1091). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
🧹 Nitpick comments (1)
.agents/skills/cloudflare-zedi/references/worker-secret-values.md (1)
85-90: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick winUse a least-privilege Worker-specific R2 token by default.
The guide currently recommends reusing the
zedi-migrationtoken without documenting or verifying its scope, expiry, and rotation policy. Make a dedicated runtime token the default; mention the migration token only as a time-bounded fallback after its permissions are confirmed.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.agents/skills/cloudflare-zedi/references/worker-secret-values.md around lines 85 - 90, Update the STORAGE_ACCESS_KEY / STORAGE_SECRET_KEY guidance to make a dedicated Worker-specific R2 API token the default, with only the permissions required at runtime. Relegate the zedi-migration token to a time-bounded fallback, and document that its scope, expiry, and rotation policy must be confirmed before use; preserve the warning that existing Railway STORAGE_* credentials must not be changed.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In @.agents/skills/cloudflare-zedi/references/worker-secret-values.md:
- Around line 85-90: Update the STORAGE_ACCESS_KEY / STORAGE_SECRET_KEY guidance
to make a dedicated Worker-specific R2 API token the default, with only the
permissions required at runtime. Relegate the zedi-migration token to a
time-bounded fallback, and document that its scope, expiry, and rotation policy
must be confirmed before use; preserve the warning that existing Railway
STORAGE_* credentials must not be changed.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 2d606b9b-ef2e-41f8-a2cd-9f03644ba010
📒 Files selected for processing (2)
.agents/skills/cloudflare-zedi/references/secrets-template.md.agents/skills/cloudflare-zedi/references/worker-secret-values.md
…atty subdomain) Not a copy-from-Railway migration: dev Worker gets freshly generated values. Generate BETTER_AUTH_SECRET, use zedi-api-dev.otomatty.workers.dev, and add a minimum-to-unblock-deploy path (boot check only needs non-empty values; real OAuth/DB deferred to #1090). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.agents/skills/cloudflare-zedi/references/worker-secret-values.md:
- Around line 125-127: Update the guidance around worker:secrets:put --dry-run
to require verifying the exact eight required secret names, including
BETTER_AUTH_SECRET and DATABASE_URL, rather than only confirming that eight
entries are printed; alternatively, add explicit required-key validation in
putWorkerSecrets.ts.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 7d5bce7b-99c3-4b9c-918e-40e0256aaedd
📒 Files selected for processing (2)
.agents/skills/cloudflare-zedi/references/worker-secret-values.mdserver/api/.env.worker.dev.example
🚧 Files skipped from review as they are similar to previous changes (1)
- server/api/.env.worker.dev.example
| - ⚠️ `worker:secrets:put` は **空値をスキップ**する。必須 8 項目に値(プレースホルダ含む)が | ||
| 入っていないとアップロードされず、deploy が `... must be set` で失敗する。`--dry-run` で | ||
| 8 項目が出ることを確認する。 |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Validate the required key names, not just the entry count.
worker:secrets:put --dry-run currently prints all non-empty parsed entries; it does not verify that the eight required keys are present. Therefore, seeing eight entries can still leave BETTER_AUTH_SECRET, DATABASE_URL, or another required key missing and cause deployment to fail.
Update this guidance to require checking the exact eight names, or add required-key validation to putWorkerSecrets.ts.
Suggested documentation correction
-- `--dry-run` で 8 項目が出ることを確認する。
+- `--dry-run` の出力に、次の必須 8 キーがすべて含まれることを確認する:
+ `BETTER_AUTH_SECRET`, `BETTER_AUTH_URL`, `CORS_ORIGIN`,
+ `GOOGLE_CLIENT_ID`, `GOOGLE_CLIENT_SECRET`,
+ `GITHUB_CLIENT_ID`, `GITHUB_CLIENT_SECRET`, `DATABASE_URL`。📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| - ⚠️ `worker:secrets:put` は **空値をスキップ**する。必須 8 項目に値(プレースホルダ含む)が | |
| 入っていないとアップロードされず、deploy が `... must be set` で失敗する。`--dry-run` で | |
| 8 項目が出ることを確認する。 | |
| - ⚠️ `worker:secrets:put` は **空値をスキップ**する。必須 8 項目に値(プレースホルダ含む)が | |
| 入っていないとアップロードされず、deploy が `... must be set` で失敗する。`--dry-run` の出力に、次の必須 8 キーがすべて含まれることを確認する: | |
| `BETTER_AUTH_SECRET`, `BETTER_AUTH_URL`, `CORS_ORIGIN`, | |
| `GOOGLE_CLIENT_ID`, `GOOGLE_CLIENT_SECRET`, | |
| `GITHUB_CLIENT_ID`, `GITHUB_CLIENT_SECRET`, `DATABASE_URL`。 |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.agents/skills/cloudflare-zedi/references/worker-secret-values.md around
lines 125 - 127, Update the guidance around worker:secrets:put --dry-run to
require verifying the exact eight required secret names, including
BETTER_AUTH_SECRET and DATABASE_URL, rather than only confirming that eight
entries are printed; alternatively, add explicit required-key validation in
putWorkerSecrets.ts.
Drop GitHub OAuth from Better Auth, sign-in/invite/extension UI, and Worker secret examples so boot only requires Google client credentials. Co-authored-by: Cursor <cursoragent@cursor.com>
Expanded the audit log for the saedgewell migration with additional HUMAN_TURN event entries, documenting timestamps for improved tracking and analysis.
Disable the Vitest plugin for server/api so CI root install does not try to require @cloudflare/vitest-pool-workers via vitest.config.worker.ts. Co-authored-by: Cursor <cursoragent@cursor.com>
概要
Railway → Cloudflare 移行(#1088)Phase 2b として、
server/api(Hono REST API)を Cloudflare Workers で実行可能にする。Node/Railway 側の挙動は不変(並行稼働維持)。DoD は「Worker ランタイム適合 + 非 DB 経路の dev 検証」— DB 依存経路の検証は #1090(D1)後、本番切替・prod ワークフローはスコープ外。設計・要件は AI-DLC ワークフロー記録(
aidlc/spaces/default/intents/260718-api-workers-migration/、本 PR に同梱)が正本。変更点
src/appAgents.ts新設。LangGraph 依存(compose-sessions / ingest / graph 登録)を隔離し、createApp({ registerAgentRoutes })フックでindex.tsのみが配線。Worker では該当ルートは 404src/lib/clientIpNode.ts新設(conninfo 分離 + resolver 注入)。Workers ではRUNTIMEvar ゲートでCF-Connecting-IP第一候補(ヘッダ存在判定はしない = Node 経路の偽装ガード)src/lib/sentryShared.ts(SDK 非依存の scrub/判定)+ errorHandler の capture DI 化 + Worker は@sentry/cloudflareのwithSentryラッパ(waitUntil flush 保証)src/lib/kv/createKvStoreNode.tsの注入式に分離(workerd でモジュールロード不能だったのを解消)scripts/checkWorkerBundle.ts(worker:bundle:check): dry-run 出力に禁止依存 5 種(@langchain / src/agents / @hono/node-server / @sentry/node / ioredis)が無いこと + gzip 10MB 予算を fail-fast。資格情報不要@cloudflare/vitest-pool-workers@0.18.6(vitest 4 対応)+vitest.config.worker.ts(test:worker)。health ランタイム判定 / CORS / ルート分割 / auth マウント / エラーマスキング / KV DO 3 用途 / @aws-sdk presign の 10 テストci.ymlに bundle check + test:worker、deploy-api-worker-dev.ymlにデプロイ直前 bundle check、wrangler.jsoncにRUNTIMEvar、.env.worker.*.exampleに起動必須シークレット全記載変更の種類
テスト方法
cd server/api && bun install --frozen-lockfilebunx vitest run— Node スイート 154 ファイル / 1703 テスト green(Railway 側パリティ)bun run test:worker— workerd 実機テスト 10 件 greenbun run worker:bundle:check— 禁止依存ゼロ、gzip 3.06MB / 10MB(資格情報不要)bunx tsc --noEmit— 型チェック greenbun run worker:devでローカル workerd 起動 →/api/healthが"runtime":"cloudflare-workers"を返すことチェックリスト
src/lib/storageAdapter/IndexedDBStorageAdapter.integration.test.tsはローカルで failing だが origin/develop でも同一再現の既存問題で本 PR と無関係)スクリーンショット(UI 変更がある場合)
UI 変更なし。
関連 Issue
Closes #1091
Related to #1088, #1090, #1095
補足:
CLOUDFLARE_API_TOKEN再発行(直近の deploy-api-worker-dev.yml は認証エラーで failure 継続中)と、リポジトリ変数WORKER_API_BASE_URLの設定(未設定のため CI health-poll がスキップされ続けている)。いずれも本 PR のコードとは独立に対応可能。🤖 Generated with Claude Code
Summary by CodeRabbit
/api/healthnow returns the Worker runtime identifier.