anolilab/lunora/lunora-cloudflare-audit
Claude Code and agent skill by anolilab/lunora
- community
Checking that the SKILL.md file is still in the repository.
Audits a Lunora app for Cloudflare cost and reliability risk before launch or after a surprise bill. Chains the read-only `lunora doctor`, `lunora advisor` and `lunora insights` signals, then traces what they cannot see — retry and fan-out loops, cron cadence, public routes that reach a metered product (Workers AI, Browser, Containers, Vectorize, R2, D1), preview environments with paid bindings, and missing usage alerts (`lunora cloudflare alerts`). Reports each finding with the billing meter i…
Install
npx vskill@latest install anolilab/lunora/lunora-cloudflare-auditSKILL.md
Lunora Cloudflare Audit
Diagnose from evidence: name the mechanism that spends money or breaks, point at the line, and prescribe the smallest fix. Lunora already ships three scanners, so this skill is mostly the order to run them in and the judgment they lack.
Recurring work (crons, queue consumers, workflows) has no public entry point, so check it before concluding costs are modest. If nothing metered is reachable from outside, traffic is modest and nothing recurs, say so and stop. Do not manufacture findings to fill a report.
Ground rules
- Evidence first. Every finding needs a file and line (or command output)
and a concrete Cloudflare mechanism. "Could be expensive" is not a finding.
- Prices and limits come from current docs, never memory. Name the meter
(DO requests, DO duration, SQLite rows read, D1 rows written, R2 Class A ops, Workers AI neurons, Browser duration, Vectorize queried dimensions, …) and fetch the current Cloudflare pricing/limits page before quoting a unit, an allowance or a cap. If you could not fetch it, say the claim is unverified.
- Do not infer account state from the repo. Alerts, WAF, cache rules, Access
and billing live in the dashboard. Without an export or screenshot, list that scope as _not inspected_.
- Confirmed vs suspected. A scanner hit is a lead. Confirm it against the
code path before it becomes a finding.
- Read-only. Never run
lunora doctor --fix,deploy, or `cloudflare
alerts setup` from an audit. Show the change and get explicit approval first.
Workflow
- Scope. Which wrangler environments (read each
env.<name>block in
wrangler.jsonc or wrangler.json, the two files Lunora reads; the scan commands below take no --env), and which paths are hot: public queries/mutations, HTTP actions, crons, queue consumers, workflows.
- Preflight signal (read-only; never pass
--fix):
``bash lunora doctor --format json # wrangler bindings, paid products, sampling, DO class budget lunora advisor --format json --no-write # static lints, scored per procedure ``
lunora doctor reports paid-product-bound (a metered binding is declared: Workers AI, Browser, Images), observability-full-sampling, observability-query-unredacted (request logs or traces keep the ?token= in auth links), r2-lifecycle-unset, cpu-limit-missing and do-class-budget-*. lunora advisor lint ids are listed below.
- **Runtime signal, only if the user points you at a worker that has served
traffic.** lunora insights (local by default). Production needs --prod and the user's admin token, plus --url … when the checkout has no production link; do not go looking for a token.
- Account signal.
lunora cloudflare alerts(status) reads last month's
usage and which products have a usage alert. Needs Cloudflare credentials; ask first. Budget alerts have no API, so they are always _not inspected_.
- Trace the gaps in the next section by reading code.
- Report in the format at the end.
What each signal already covers
Check this table before reading code by hand. Only the last column is yours.
| Risk | Already flagged by | Still read by hand | |
|---|---|---|---|
| Full-table reads re-sent to every subscriber | unbounded_collect, unbounded_collect_on_open_range, filter_without_index, count_without_index, filter_after_index_scan | Whether the table will actually grow; .global() D1 cost | |
| Runaway loops and re-arming schedules | unbounded_loop, self_reschedule_without_progress, dispatch_cycle, queue_dispatch_cycle | Loops spanning a Queue → Worker → DO hop the graph cannot see | |
| Sweeps that re-read the same rows | unbounded_collect_on_open_range | — | |
| Cron cadence | cron_every_minute (sees cronJobs() registrations only) | Every-minute schedules the lint cannot see: createWorker({ crons }) handlers and backupCron in the worker entry; what any tick does: rows read, calls made per fire | |
| Queue retries losing messages | queue_without_dlq | Retry delay and maxRetries against the downstream's own rate limit | |
| Hot shard / wide fan-out | privileged_fanout_from_public_procedure; hot_shard and fan_out_breadth are runtime lints, shown in the Studio Advisors tab against a live worker, not by lunora advisor | Shard traffic on a live worker (Studio Advisors); singleton shard keys ("global", an env var) on .shardBy() | |
| Unbounded AI use | ai_unbounded_generation_public, ai_run_without_logging | Output and usage bounds on every raw ctx.ai.run() (ai_raw_run_escape_hatch only checks where the model id comes from, so a fixed-model call escapes it); a ctx.ai call inside a retry or Promise.all over user-sized input | |
| Browser / Containers left running | browser_user_url_without_allowlist, container_long_sleep_after, container_oversized_instance (the container lints read configuration, not lifecycle) | A browser session opened without a close path in an action; named container starts that are never stopped or destroyed once their work finishes, within the configured idle window | |
| Public mutations with no throttle | public_mutation_without_ratelimit, ratelimit_default_memory_store, ratelimit_key_spoofable_or_global | Public _reads_ that reach a metered product | |
| Upload size and type | storage_upload_without_max_size, storage_upload_without_content_type_allowlist | Egress and lifecycle on the bucket (r2-lifecycle-unset) | |
| Secrets in the repo | hardcoded_secret, plaintext_secret_in_wrangler_vars | — | |
| Log volume | observability-full-sampling (doctor) | Retention and plan | |
| Handled by construction | Codegen reconciles bindings, DO migrations and the compatibility date; ShardDO uses the WebSocket Hibernation API | Nothing, unless wrangler.jsonc was hand-edited |
Gaps to trace by hand
For each, find the call site, then count the billed units per user action.
- Fan-out without a cap.
Promise.all(items.map(...))or a loop that calls
ctx.db, ctx.runMutation, ctx.scheduler.runAfter, a queue send (ctx.queues.<name>.send / sendBatch) or ctx.ai once per element of user-sized input. Cap the batch or hand the list to a Queue/workpool with a concurrency limit.
- Retry storms. A retry (hand-rolled, queue
maxRetries, workflow step
retry) around a call that is itself billed or rate-limited, with no backoff or circuit breaker. A workflow step that retries a paid ctx.ai call bills each attempt.
- Webhooks with side effects and no dedupe. An
httpActionfor a provider
webhook that writes or sends mail without keying on the event id. Providers redeliver. (Payment webhooks have their own lints; this is every other provider.)
- Preview / staging with paid bindings. An
env.<name>block that binds
Workers AI, Browser, Containers or the production R2 bucket and is reachable without auth.
- Enumeration on hot paths. Storage enumeration through
ctx.db.system.query("_storage") or a Vectorize query (ctx.vectors.query) inside a query that every subscriber re-runs. (ctx.storage.list is action-only.)
- Third-party origins. An action that fetches a public serverless URL on
every request instead of caching, queueing, or using a service binding.
Public-path cost gate
Run this whenever an anonymous caller (an unauthenticated query, a public httpAction, a crawlable GET) can reach a metered product. The caller does not have to be a crawler: any script can repeat the request.
This is the start of the file. Read the full SKILL.md on GitHub.
Security
- Security scanPassed, 90 of 100Pattern checks on the skill's files.
- Model reviewPassed
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingpackages/cli/skills/lunora-cloudflare-audit/SKILL.md
Popularity
- 7-day trend score
- 0
Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/anolilab/lunora/lunora-cloudflare-audit)