Skip to content

feat: launch-ready — watch_price + rate limit + disclosure + CI guard - #22

Merged
idanmann10 merged 1 commit into
mainfrom
feat/launch-readiness
May 12, 2026
Merged

idanmann10 merged 1 commit into
mainfrom
feat/launch-readiness

Conversation

@idanmann10

Copy link
Copy Markdown
Owner

Everything we need to actually post this on Twitter without getting torched.

1. watch_price MCP tool

Persists a "ping me when X drops to $Y" request to a new price_watches table (migration 0002). The killer agent-only feature — browser extensions can't watch prices because they only fire when the user opens a page. Per-client cap of 50 active watches; soft-deleted not hard. Notify-cron worker lands in a follow-up; this PR ships the contract + storage.

2. Token-bucket rate limiter

SerpApi credits are real money. A misbehaving agent looping find_best_deal could burn our monthly budget in minutes. RateLimiter (in-memory, per-clientHash, 20 capacity refilled at 0.5/sec) wraps both find_best_deal and find_products. Agents get a clean InvalidRequest with a retry-in-N-seconds hint instead of an opaque 5xx.

3. Affiliate disclosure + privacy footer

Required by Amazon Associates ToS and FTC. Preempts the #1 Twitter pile-on ("where's the disclosure?"). Says: we participate in Amazon Associates + Skimlinks; we never strip creator/community attribution; we don't store queries or identities.

4. CI regression test: no google.com URLs leak

A real Claude Desktop user hit a google.com/search URL yesterday. test/mcp/no-google-urls.test.ts walks the structured response of both find_products and find_best_deal, asserts no string field contains a Google search/shopping URL even when SerpApi's product_link is one. Locks the fix in.

Test plan

  • 180 tests pass (10 new across watch_price, rate-limit, no-google-urls)
  • typecheck + lint clean
  • Tool count 9 → 10, smoke test updated

🤖 Generated with Claude Code

Four launch-ready deltas in one push.

1) watch_price MCP tool + price_watches table (migration 0002).
   Persists a "ping me when X drops to $Y" request keyed to the
   calling agent's clientHash. Throws when a client has >50 active
   watches. The notify-cron worker lands in a follow-up; this PR
   ships the contract and storage so agents can already use it. The
   killer agent-only feature: browser extensions can't watch prices
   (they only fire when the user opens a page).

2) RateLimiter (src/lib/rate-limit.ts) — token-bucket, in-memory,
   per-client. Default: 20 capacity refilled at 0.5/sec. Wired into
   find_best_deal (2 SerpApi credits per call) and find_products
   (up to 4 credits per call). A looping or misbehaving agent now
   gets a clean InvalidRequest error with a retry hint instead of
   torching our monthly budget.

3) Landing footer: explicit affiliate disclosure + privacy note.
   We participate in Amazon Associates + Skimlinks; users earn no
   extra cost; we don't strip creator/community attribution; we
   don't store queries/identities. Required by Amazon Associates
   ToS and FTC, and preempts the #1 Twitter complaint.

4) CI regression test (test/mcp/no-google-urls.test.ts): walks
   the structured response of find_products and find_best_deal,
   asserts no string field contains a google.com/search or
   google.com/shopping URL — even when SerpApi's product_link is
   one. This is the regression that hit a real Claude Desktop user
   yesterday.

Tool count: 9 → 10. Smoke test updated.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@idanmann10
idanmann10 merged commit d103a2b into main May 12, 2026
1 check passed
@idanmann10
idanmann10 deleted the feat/launch-readiness branch May 12, 2026 01:23
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