Skip to content
Closed
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 19 additions & 2 deletions claim-db-worker/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,27 @@ function errorResponse(title: string, message: string, details?: string, status
export default {
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
// --- Rate limiting ---
const { success } = await env.CLAIM_DB_RATE_LIMITER.limit({ key: request.url });
// Use client IP for consistent rate limiting across environments
const clientIP = request.headers.get('x-agent') || request.headers.get('cf-connecting-ip');
const rayId = request.headers.get('cf-ray') || request.headers.get('x-ray-id') || 'unknown-ray-id';

const { success } = await env.CLAIM_DB_RATE_LIMITER.limit({ key: clientIP! });

if (!success) {
return errorResponse('Rate Limit Exceeded', "We're experiencing high demand. Please try again later.", '', 429);
console.log(`Rate limit exceeded for IP: ${clientIP}. Ray ID: ${rayId}. Request blocked to prevent abuse.`);
return new Response(
JSON.stringify({
error: 'Too Many Requests',
message: 'You have exceeded the allowed number of requests. Please wait before trying again.',
code: 429,
ip: clientIP,
rayId,
}),
{
status: 429,
headers: { 'Content-Type': 'application/json' },
},
);
Comment on lines +43 to +56
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Minimize PII: avoid logging/echoing raw IP; return only non-sensitive identifiers

Logging IPs and returning them in responses can be considered PII. Prefer logging rayId only and omit the ip field (or rename to a generic key if truly needed).

-      console.log(`Rate limit exceeded for IP: ${clientIP}. Ray ID: ${rayId}. Request blocked to prevent abuse.`);
+      console.log(`[429] Rate limit exceeded. Ray ID: ${rayId}. Request blocked to prevent abuse.`);
       return new Response(
         JSON.stringify({
           error: 'Too Many Requests',
           message: 'You have exceeded the allowed number of requests. Please wait before trying again.',
           code: 429,
-          ip: clientIP,
           rayId,
         }),
         {
           status: 429,
           headers: { 'Content-Type': 'application/json' },
         },
       );
📝 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.

Suggested change
console.log(`Rate limit exceeded for IP: ${clientIP}. Ray ID: ${rayId}. Request blocked to prevent abuse.`);
return new Response(
JSON.stringify({
error: 'Too Many Requests',
message: 'You have exceeded the allowed number of requests. Please wait before trying again.',
code: 429,
ip: clientIP,
rayId,
}),
{
status: 429,
headers: { 'Content-Type': 'application/json' },
},
);
console.log(`[429] Rate limit exceeded. Ray ID: ${rayId}. Request blocked to prevent abuse.`);
return new Response(
JSON.stringify({
error: 'Too Many Requests',
message: 'You have exceeded the allowed number of requests. Please wait before trying again.',
code: 429,
rayId,
}),
{
status: 429,
headers: { 'Content-Type': 'application/json' },
},
);
🤖 Prompt for AI Agents
In claim-db-worker/src/index.ts around lines 40 to 53, the handler logs and
returns the client's raw IP and includes it in the JSON response (PII). Remove
the raw IP from logs and response: change console.log to only mention the rayId
(and any non-PII token), and remove the ip property from the returned JSON (or
replace it with a non-identifying generic key like clientTag if absolutely
required). Ensure headers and status remain unchanged and do not expose the IP
elsewhere in this block.

}

async function sendPosthogEvent(event: string, properties: Record<string, any>) {
Expand Down
2 changes: 1 addition & 1 deletion claim-db-worker/wrangler.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
"type": "ratelimit",
"namespace_id": "1006",
"simple": {
"limit": 100,
"limit": 10,
"period": 60,
},
Comment on lines +27 to 29
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

CLAIM_DB limit also tightened to 10 req/min — align expectations

Ensure clients and tests reflect the new ceiling to avoid false alarms. Consider staggered rollout or per-env overrides if needed.


🏁 Script executed:

#!/bin/bash
# Show the wrangler.jsonc around the rate limit config
echo "---- claim-db-worker/wrangler.jsonc (lines 1-100) ----"
sed -n '1,100p' claim-db-worker/wrangler.jsonc || true

echo -e "\n---- All occurrences of 'limit' in JSON/JSONC files ----"
rg --type-add 'jsonc:*.jsonc' --type-add 'json:*.json' -tjson -tjsonc '"limit"' -C 3

echo -e "\n---- References to rate limiting in code/tests ----"
rg -n "limit" -e "claim" -e "db" || true
rg -n "rate" -e "limit" || true

echo -e "\n---- Test files mentioning 10 or 60 ----"
rg -n "10" --glob '*test*' || true
rg -n "60" --glob '*test*' || true

Length of output: 2323


CLAIM_DB rate limit lowered to 10 req/min—update clients & tests

We’ve tightened CLAIM_DB_RATE_LIMITER (limit: 10, period: 60). Any clients or tests assuming a higher ceiling will now hit this threshold. To avoid failures or false alarms:

• tests/test-rate-limits.sh: lower the default TEST_COUNT (currently 110) to ≤ 10 or make it configurable per-env
• Client integrations/docs that reference CLAIM_DB throughput > 10 req/min
• Consider per-environment overrides or a staggered rollout if some workloads need more headroom

🤖 Prompt for AI Agents
In claim-db-worker/wrangler.jsonc around lines 27 to 29, the CLAIM_DB rate
limiter was reduced to 10 requests per 60 seconds which will break tests and
clients that assume higher throughput; update tests/test-rate-limits.sh to lower
TEST_COUNT to 10 or make TEST_COUNT configurable via env vars and default to
≤10, update any client integrations and documentation that reference >10 req/min
to reflect the new limit, and add a per-environment override (env var) or note a
staged rollout plan for workloads that need higher headroom.

},
Expand Down
25 changes: 22 additions & 3 deletions create-db-worker/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,29 @@ export { DeleteDbWorkflow };
export default {
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
// --- Rate limiting ---
const { success } = await env.CREATE_DB_RATE_LIMITER.limit({ key: request.url });
// Use client IP for consistent rate limiting across environments
const clientIP = request.headers.get('x-agent') || request.headers.get('cf-connecting-ip');
const rayId = request.headers.get('cf-ray') || request.headers.get('x-ray-id') || 'unknown-ray-id';

console.log(`Client IP: ${clientIP} - Request URL: ${request.url}`);

const { success } = await env.CREATE_DB_RATE_LIMITER.limit({ key: clientIP! });

if (!success) {
return new Response(`429 Failure - rate limit exceeded for ${request.url}`, { status: 429 });
console.log(`Rate limit exceeded for IP: ${clientIP}. Ray ID: ${rayId}. Request blocked to prevent abuse.`);
return new Response(
JSON.stringify({
error: 'Too Many Requests',
message: 'You have exceeded the allowed number of requests. Please wait before trying again.',
code: 429,
ip: clientIP,
rayId,
}),
{
status: 429,
headers: { 'Content-Type': 'application/json' },
},
);
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Reduce PII exposure in 429 path

Avoid logging IPs and do not echo them back; rely on rayId for correlation.

-      console.log(`Rate limit exceeded for IP: ${clientIP}. Ray ID: ${rayId}. Request blocked to prevent abuse.`);
+      console.log(`[429] Rate limit exceeded. Ray ID: ${rayId}. Request blocked to prevent abuse.`);
       return new Response(
         JSON.stringify({
           error: 'Too Many Requests',
           message: 'You have exceeded the allowed number of requests. Please wait before trying again.',
           code: 429,
-          ip: clientIP,
           rayId,
         }),
         {
           status: 429,
           headers: { 'Content-Type': 'application/json' },
         },
       );
📝 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.

Suggested change
console.log(`Rate limit exceeded for IP: ${clientIP}. Ray ID: ${rayId}. Request blocked to prevent abuse.`);
return new Response(
JSON.stringify({
error: 'Too Many Requests',
message: 'You have exceeded the allowed number of requests. Please wait before trying again.',
code: 429,
ip: clientIP,
rayId,
}),
{
status: 429,
headers: { 'Content-Type': 'application/json' },
},
);
console.log(`[429] Rate limit exceeded. Ray ID: ${rayId}. Request blocked to prevent abuse.`);
return new Response(
JSON.stringify({
error: 'Too Many Requests',
message: 'You have exceeded the allowed number of requests. Please wait before trying again.',
code: 429,
rayId,
}),
{
status: 429,
headers: { 'Content-Type': 'application/json' },
},
);
🤖 Prompt for AI Agents
In create-db-worker/src/index.ts around lines 24 to 37, the 429 response path
currently logs and returns the client's IP and echoes it in the JSON body;
remove PII exposure by eliminating any use of clientIP in logs and the response
body, keep and log only the rayId for correlation, and update the JSON payload
to exclude the ip field while still returning status 429 and Content-Type
application/json; ensure any console logs reference only non-PII context (e.g.,
"Rate limit exceeded. Ray ID: {rayId}") and that clientIP is not stored or
returned.

}

const url = new URL(request.url);
Expand All @@ -27,7 +46,7 @@ export default {
status: 'success',
service: 'create-db-worker',
timestamp: Date.now(),
message: 'Rate limit test endpoint - if you see this, rate limiting passed',
message: 'Rate limit test endpoint',
}),
{
status: 200,
Expand Down
2 changes: 1 addition & 1 deletion create-db-worker/wrangler.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
"type": "ratelimit",
"namespace_id": "1005",
"simple": {
"limit": 100,
"limit": 10,
"period": 60,
},
},
Expand Down
24 changes: 17 additions & 7 deletions tests/test-rate-limits.sh
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
#!/bin/bash

# Test Rate Limits Script
# Usage: ./tests/test-rate-limits.sh [test_count] [create_db_url] [claim_db_url]
# Usage: ./tests/test-rate-limits.sh [test_count] [create_db_url] [claim_db_url] [agent_id]
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Add strict mode and safer loop quoting

Improve robustness and satisfy shellcheck.

 # Test Rate Limits Script
-# Usage: ./tests/test-rate-limits.sh [test_count] [create_db_url] [claim_db_url] [agent_id]
+# Usage: ./tests/test-rate-limits.sh [test_count] [create_db_url] [claim_db_url] [agent_id]
+set -Eeuo pipefail

Also change the loop and seq usage:

-    for i in $(seq 1 $TEST_COUNT); do
+    for i in $(seq 1 "${TEST_COUNT}"); do
🤖 Prompt for AI Agents
In tests/test-rate-limits.sh around line 4, the script lacks strict shell
settings and uses unsafe loop/seq and unquoted variables; enable robust shell
behavior by adding at the top: set -euo pipefail and IFS=$'\n\t', then update
the loop to avoid unquoted seq and word-splitting (for example replace
constructs like for i in $(seq 1 $test_count) with for i in $(seq 1
"$test_count") or preferably a POSIX-safe while loop using a counter), and
ensure all variable expansions in the loop and commands are quoted (e.g.,
"$create_db_url" "$claim_db_url" "$agent_id") to satisfy shellcheck and prevent
word-splitting.


# Default values
TEST_COUNT=${1:-110}
CREATE_DB_URL=${2:-"http://127.0.0.1:8787"}
CLAIM_DB_URL=${3:-"http://127.0.0.1:9999"}
CREATE_DB_URL=${2:-"https://create-db-temp.prisma.io"}
CLAIM_DB_URL=${3:-"https://create-db.prisma.io"}
AGENT_ID=${4:-"meow"}

echo "🧪 Testing Rate Limits"
echo "======================"
echo "Test Count: $TEST_COUNT"
echo "Create DB URL: $CREATE_DB_URL"
echo "Claim DB URL: $CLAIM_DB_URL"
echo "Agent Header: X-Agent: $AGENT_ID"
echo "User-Agent: prisma-rate-limit-test/$AGENT_ID"
echo ""

# Function to test a worker
Expand All @@ -32,8 +35,15 @@ test_worker() {
for i in $(seq 1 $TEST_COUNT); do
echo -n "Request $i/$TEST_COUNT: "

# Make the request and capture both response body and status code
response=$(curl -s -w "%{http_code}" -o /tmp/response_$i.json "$endpoint" 2>/dev/null)
# Make the request with unique agent headers and capture body + status code
response=$(curl -s \
-H "x-agent: $AGENT_ID" \
-H "x-Agent: $AGENT_ID" \
-H "User-Agent: prisma-rate-limit-test/$AGENT_ID" \
-w "%{http_code}" \
-o /tmp/response_$i.json \
"$endpoint" 2>/dev/null)

Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Quote variables (SC2086), remove duplicate header, and safe temp files

  • Quote expansions to avoid word splitting/globbing and satisfy shellcheck.
  • Remove duplicate x-Agent header.
  • Use mktemp and trap for cleanup.
-        # Make the request with unique agent headers and capture body + status code
-        response=$(curl -s \
-          -H "x-agent: $AGENT_ID" \
-          -H "x-Agent: $AGENT_ID" \
-          -H "User-Agent: prisma-rate-limit-test/$AGENT_ID" \
-          -w "%{http_code}" \
-          -o /tmp/response_$i.json \
-          "$endpoint" 2>/dev/null)
+        # Make the request with unique agent header and capture body + status code
+        tmp_dir="${TMP_DIR:-$(mktemp -d)}"
+        trap 'rm -rf "$tmp_dir"' EXIT
+        response="$(
+          curl -s \
+            -H "x-agent: ${AGENT_ID}" \
+            -H "User-Agent: prisma-rate-limit-test/${AGENT_ID}" \
+            -w "%{http_code}" \
+            -o "${tmp_dir}/response_${i}.json" \
+            "${endpoint}" 2>/dev/null
+        )"
🧰 Tools
🪛 Shellcheck (0.10.0)

[info] 44-44: Double quote to prevent globbing and word splitting.

(SC2086)

🤖 Prompt for AI Agents
In tests/test-rate-limits.sh around lines 38 to 46, the curl call uses unquoted
variable expansions, repeats the x-Agent header, and writes to a fixed temp
path; fix it by removing the duplicate header, quoting all variable expansions
(e.g. "$AGENT_ID" and "$endpoint") to prevent word-splitting/globbing, create a
unique temp file with mktemp (e.g. tmp=$(mktemp)) and write curl output to that
quoted path, and add a trap to remove the temp file on exit to ensure safe
cleanup.

status_code=${response: -3}

case $status_code in
Expand All @@ -52,7 +62,7 @@ test_worker() {
esac

# Small delay between requests
sleep 0.1
#sleep 0.05
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Optional: throttle to reduce noisy bursts

Consider re-introducing a small sleep (e.g., 20–50ms) to avoid overwhelming remote endpoints during ad-hoc runs.

🤖 Prompt for AI Agents
In tests/test-rate-limits.sh around line 65, the commented-out small sleep
("#sleep 0.05") should be re-enabled to throttle bursts; uncomment it and use a
portable short delay such as sleep 0.02–0.05 (e.g., sleep 0.02 or sleep 0.05) to
reduce request bursts during ad-hoc runs, or if sub-second precision is required
in the environment, replace with a portable usleep/timeout helper that sleeps
for 20–50ms.

done

echo ""
Expand All @@ -76,4 +86,4 @@ echo "- Later requests should be rate limited (429)"
echo "- This confirms rate limiting is working correctly"
echo ""
echo "💡 To test with your actual deployed URLs, run:"
echo " ./tests/test-rate-limits.sh 110 https://create-db-temp.prisma.io https://create-db.prisma.io"
echo " ./tests/test-rate-limits.sh 110 https://create-db-temp.prisma.io https://create-db.prisma.io my-local-agent"
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Example invocation: consider demonstrating local defaults

Recommend showing a local/miniflare example first to prevent accidental production load.

🤖 Prompt for AI Agents
In tests/test-rate-limits.sh around line 89, the example invocation only shows
production endpoints which may cause accidental load; add a local/miniflare
first so users see a safe default. Update the echo line to print a local example
(e.g., using localhost or miniflare URL and a local agent name) before the
existing production example, ensuring both examples are clearly separated and
labeled (local first, then production).