Skip to content

feat: Cloudflare feedback worker — core POST endpoint, rate limiting, Claude enrichment, GitHub issue creation #109

Description

@wcmchenry3-stack

In plain English

Build the shared Cloudflare Worker that receives feedback submissions from any app, validates and enriches them with Claude, enforces rate limits, and files a structured GitHub issue in the correct repo.

User story

As a developer, I want a single centralized worker to handle all feedback submissions so that I don't maintain identical backend code in every app repo.

Context

This is the backend backbone of the feedback system. All app UI widgets POST to this worker. It mirrors the architecture of the existing cloudflare/openai-policy-worker/ (see cloudflare/openai-policy-worker/src/index.js and wrangler.toml for patterns to follow).

Part of: #46

Acceptance criteria

  • Worker deployed at cloudflare/feedback-worker/ in this repo with its own wrangler.toml
  • POST /feedback endpoint accepts JSON: { appId, title, description, type, screenshotBase64?, sessionLogs? }
  • Rate limiting enforced: max 5 submissions per IP per 10 minutes (uses Cloudflare KV or Durable Objects)
  • Claude API call validates content — rejects submissions classified as spam, abuse, or hate speech (returns 422 with reason)
  • Claude API call enriches accepted submissions: adds headers, acceptance-criteria stub (for feature requests) or reproduction-steps stub (for bugs), while preserving the verbatim original user text in a quoted block
  • Session logs (if provided) are appended as a collapsed <details> block in the issue body
  • Screenshot (if provided) is uploaded to a GitHub Gist or attached as a comment — issue body includes the link
  • GitHub issue created in the correct repo based on appId (mapping configured in worker env, e.g. APP_REPO_MAP=gaming_app:wcmchenry3-stack/gaming_app,...)
  • Labels applied: bug or enhancement based on type, plus user-feedback (create this label in target repos if absent)
  • Worker returns { issueNumber, issueUrl } on success
  • CORS headers set to only allow requests from known app origins (configured via env var ALLOWED_ORIGINS)
  • All secrets (ANTHROPIC_API_KEY, GITHUB_TOKEN, ALLOWED_ORIGINS, APP_REPO_MAP) managed via wrangler secret put — none hardcoded

Technical notes

  • Follow cloudflare/openai-policy-worker/ structure: src/index.js, wrangler.toml, package.json
  • Use workers_dev = true for this worker (HTTP, not email)
  • Rate limit key: ratelimit:{ip} stored in Cloudflare KV binding RATE_LIMIT_KV
  • Claude model: use claude-3-haiku-3-5 for fast, cheap classification; claude-3-5-sonnet for enrichment (or combine in one call)
  • GitHub issue creation: reuse createGitHubIssue() pattern from openai-policy-worker
  • appId values: gaming_app, book_app (expandable)
  • Enrichment prompt must instruct Claude to wrap the original user text in a > blockquote section titled "Original submission (verbatim)"

Test coverage

Unit tests

  • Rate limit logic: first 5 requests pass, 6th returns 429
  • Claude classification: mock Anthropic SDK — spam input returns 422, clean input proceeds
  • Issue body builder: original text appears verbatim in blockquote, enriched sections present
  • appId → repo mapping: unknown appId returns 400

E2E tests

  • Not required: worker E2E covered by integration test against Cloudflare Workers dev environment

Performance

  • p95 response time < 5 seconds (Claude API is the bottleneck — acceptable for a feedback form)

Regression

  • Resubmitting same content within rate-limit window returns 429, not duplicate issue

Documentation to update

  • CLAUDE.md — add cloudflare/feedback-worker/ section describing the worker, its env vars, and how to add a new app

Unknowns / needs investigation

  • Cloudflare KV vs Durable Objects for rate limiting — KV has eventual consistency; Durable Objects are strongly consistent but add cost. Decide before implementation.
  • Screenshot storage: GitHub Gist upload vs. issue comment attachment — evaluate GitHub API limits for base64 image size.

Out of scope

  • Admin UI for reviewing submissions
  • Webhook retries / dead-letter queue (can add in a follow-up)
  • Localization suggestion type handled in separate story (#localization-story)

Dependencies

Definition of done

  • All acceptance criteria met
  • Test coverage added per above
  • Documentation updated
  • CI green (lint, type check, tests)
  • PR reviewed and merged to dev

Metadata

Metadata

Assignees

No one assigned

    Labels

    ai-agentsClaude sub-agent related workenhancementNew feature or requestinfrastructureCI/CD and tooling improvementspriority:highHigh priority - implement firstsecuritySecurity-related issues and improvements

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions