Skip to content

chore: update docs#93

Open
waltergalvao wants to merge 2 commits intomainfrom
chore/update-docs
Open

chore: update docs#93
waltergalvao wants to merge 2 commits intomainfrom
chore/update-docs

Conversation

@waltergalvao
Copy link
Contributor

@waltergalvao waltergalvao commented Feb 23, 2026

Greptile Summary

This PR introduces rate limiting to the public deployments REST API and performs a comprehensive documentation overhaul migrating from Mintlify v1 (mint.json) to v2 (docs.json), restructuring the navigation and adding new content for the API Reference, Platform, and Metrics sections.

Key changes:

  • Rate limiting added to POST /v1/deployments using @fastify/rate-limit (100 req/min), keyed by the Authorization header with IP fallback. The @fastify/rate-limit dependency is correctly present in package.json.
  • Router reorganization in fastify.ts: slackRouter and bullBoardRouter are grouped under "Integration APIs" before the Stripe conditional; deploymentsRouter is now wrapped in a rate-limited scope.
  • Mintlify v2 migration: mint.json replaced by docs.json with an updated icon library (tabler), new "API Reference" tab, and restructured navigation (features split into Metrics & Insights, Automations, and Platform groups).
  • New documentation pages: API authentication, rate limits, POST /v1/deployments reference, DORA metrics, deployments/environments/incidents/applications platform pages, and incident detection automation docs.
  • Content fixes: Grammar corrections ("A even" → "An even", "within a hour" → "within an hour", "several of problems" → "several problems"), typo fixes in self-host.mdx, and removal of a spurious trailing ; in snippets/pr-badge.mdx.

Confidence Score: 5/5

  • This PR is safe to merge — the code change is small, correct, and well-tested by the existing structure.
  • The only non-documentation code change is the addition of @fastify/rate-limit to the deployments endpoint, which is a straightforward and self-contained addition. The dependency is already declared in package.json, the rate limit parameters match the documentation, the keyGenerator logic is correct (falls back from auth header to IP), and the scoped registration approach correctly avoids rate-limiting unrelated routes like GraphQL (which already has @envelop/rate-limiter). The documentation changes are purely additive and don't affect runtime behavior.
  • No files require special attention.

Important Files Changed

Filename Overview
apps/api/src/fastify.ts Adds rate limiting (100 req/min) to the deployments REST API endpoint using @fastify/rate-limit, scoped to the Authorization header or IP. Reorganizes router registration order with clearer grouping comments.
apps/docs/docs.json Migrates docs config from Mintlify v1 (mint.json) to v2 (docs.json), adding a new API Reference tab and restructuring navigation into Metrics & Insights, Automations, and Platform sections.
apps/docs/api-reference/authentication.mdx New file documenting API key authentication via Bearer token, consistent with the actual implementation in deploymentsRouter.ts.
apps/docs/api-reference/rate-limit.mdx New file documenting rate limits (100 req/min per API key), accurately reflecting the @fastify/rate-limit configuration in fastify.ts.
apps/docs/api-reference/deployments/create-deployment.mdx New file documenting the POST /v1/deployments REST endpoint with full parameter reference, cURL and GitHub Actions examples.
apps/docs/platform/deployments.mdx New detailed deployments feature page covering change types, triggers, PR linking logic, data quality comparisons, and archiving.
apps/docs/platform/incidents.mdx New incidents feature page covering key fields, manual and automatic creation, DORA impact, and archiving.
apps/docs/get-started/self-host.mdx Removes "Contents: Read-only" GitHub permission from self-host setup docs and fixes typos ("adresses"→"addresses", "you-web-app"→"your-web-app").
apps/docs/metrics-and-insights/dora.mdx New DORA metrics documentation page covering all four metrics: Deployment Frequency, Lead Time for Changes, Change Failure Rate, and MTTR.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Client: POST /v1/deployments] --> B{Rate Limiter\n100 req/min\nper auth header or IP}
    B -->|Limit exceeded| C[429 Too Many Requests]
    B -->|Within limit| D{Auth Validation\nfindApiKeyOrThrow}
    D -->|Invalid| E[401 Unauthorized]
    D -->|Valid| F{Body Validation\nzod schema}
    F -->|Invalid| G[422 Unprocessable Entity]
    F -->|Valid| H[Enqueue Job:\nDEPLOYMENT_TRIGGERED_BY_API]
    H --> I[202 Accepted]
Loading

Last reviewed commit: 0c32f97

@sweetr-dev sweetr-dev bot added the huge Huge PR - High risk of reviewer fatigue label Feb 23, 2026
@waltergalvao waltergalvao changed the title chore: wip chore: update docs Feb 23, 2026
@coderabbitai
Copy link

coderabbitai bot commented Feb 23, 2026

Walkthrough

This PR implements API rate limiting (100 req/min) in Fastify, introduces comprehensive API reference documentation including authentication and deployment endpoints, restructures documentation site configuration, reorganizes feature documentation from /features to /metrics-and-insights and /platform directories, adds new platform pages, updates icons and corrects grammar throughout, and removes obsolete documentation files.

Changes

Cohort / File(s) Summary
API Implementation & Rate Limiting
apps/api/src/fastify.ts
Added rate limiting middleware (100 requests/minute) scoped around deploymentsRouter with keyGenerator based on authorization header or IP address.
API Documentation
apps/docs/api-reference/*
New API reference documentation: introduction page describing REST API structure, authentication guide for API key generation and security best practices, deployment endpoint documentation with examples (curl and GitHub Actions), and rate limiting policy documentation.
Documentation Site Configuration
apps/docs/docs.json, apps/docs/mint.json
Added new Mintlify site configuration (docs.json) with complete navigation structure, tabs, styling, and footer links; removed legacy mint.json configuration file.
Metrics & Insights Documentation
apps/docs/metrics-and-insights/*
New DORA metrics page with computation details; updated pull-requests icon; added work-log and team subsection pages; updated navigation links from /features to /metrics-and-insights; updated WIP page with link and card restructuring.
Platform Documentation
apps/docs/platform/*
New platform pages: applications (monorepo support, creation methods), deployments (triggers, linking logic, archiving), environments (production flag, auto-creation), and incidents (lifecycle, manual/automatic creation); updated integrations icon and cards; updated teams and people with navigation changes.
Automations Documentation
apps/docs/automations/*
New incident-detection page; updated alert and digest icons and links; added icons to pr-size-labeler and pr-title-check.
About & Overview Pages
apps/docs/about/*, apps/docs/get-started/*
Updated icon and text corrections in data-privacy, open-source, and principles pages; restructured intro.mdx with Metrics & Insights and Automations sections; fixed typos in self-host.mdx; removed outdated get-started.mdx and features/intro pages.
Removed & Consolidated
apps/docs/features/automations/intro.mdx, apps/docs/features/deployments.mdx, apps/docs/features/environments.mdx
Deleted three documentation pages that were consolidated into new /platform and /metrics-and-insights structures.
Icon & Text Updates
apps/docs/about/*, apps/docs/automations/*, apps/docs/metrics-and-insights/*, apps/docs/platform/*, apps/docs/snippets/*
Multiple icon property updates (shield-keyhole → shield, gear-code → brand-open-source, newspaper → message, etc.); grammar corrections ("prevents...to use" → "prevents...from using", "a hour" → "an hour"); removed trailing semicolon in pr-badge snippet.
Navigation Link Restructuring
apps/docs/get-started/intro.mdx, apps/docs/metrics-and-insights/team/*, apps/docs/platform/teams.mdx, apps/docs/platform/people.mdx
Updated href paths throughout documentation from /features/* to /metrics-and-insights/* and /platform/*; updated card components and icon references to match new structure.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • sweetr-dev/sweetr.dev\feat: auto deployments from PR merge #63 — Adds scoped rate limiting to deployments router in Fastify, directly supporting the new API deployment endpoint documentation and rate limiting policy introduced in this PR.
🚥 Pre-merge checks | ❌ 3

❌ Failed checks (1 warning, 2 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'chore: update docs' is vague and generic, using non-descriptive language that doesn't convey meaningful information about the extensive changes. Provide a more specific title describing the main changes, such as 'docs: reorganize navigation structure and add API reference section' or 'docs: migrate from features to metrics-and-insights structure'.
Description check ❓ Inconclusive No pull request description was provided; cannot assess whether it relates to the changeset. Add a description explaining the main objectives and rationale for the documentation restructuring, such as the migration to API reference docs and reorganization of content sections.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch chore/update-docs
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Tip

CodeRabbit can use OpenGrep to find security vulnerabilities and bugs across 17+ programming languages.

OpenGrep is compatible with Semgrep configurations. Add an opengrep.yml or semgrep.yml configuration file to your project to enable OpenGrep analysis.

@sweetrdev sweetrdev marked this pull request as ready for review March 13, 2026 03:10
Copy link

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

5 issues found across 41 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="apps/api/src/fastify.ts">

<violation number="1" location="apps/api/src/fastify.ts:56">
P1: Using the unvalidated `Authorization` header as the rate-limit key lets callers bypass the new limit by rotating fake tokens.</violation>
</file>

<file name="apps/docs/platform/deployments.mdx">

<violation number="1" location="apps/docs/platform/deployments.mdx:12">
P2: This image path does not exist in the repository, so the Demo section will render a broken image.</violation>
</file>

<file name="apps/docs/automations/incident-detection.mdx">

<violation number="1" location="apps/docs/automations/incident-detection.mdx:40">
P2: The branch regex example is incorrect: `hotfix/*` will not match branches like `hotfix/foo`. Use a pattern such as `^hotfix/.*` so the documented rule actually detects hotfix branches.</violation>
</file>

<file name="apps/docs/metrics-and-insights/dora.mdx">

<violation number="1" location="apps/docs/metrics-and-insights/dora.mdx:12">
P2: The demo image points to `/images/dora.png`, but that asset is not present in the repository, so this page will show a broken image.</violation>
</file>

<file name="apps/docs/platform/environments.mdx">

<violation number="1" location="apps/docs/platform/environments.mdx:29">
P2: These example names will not be treated as production environments, so deployments to `production-us`/`production-eu` are excluded from default DORA metrics.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

await scope.register(rateLimit, {
max: 100,
timeWindow: "1 minute",
keyGenerator: (request) => request.headers.authorization || request.ip,
Copy link

@cubic-dev-ai cubic-dev-ai bot Mar 13, 2026

Choose a reason for hiding this comment

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

P1: Using the unvalidated Authorization header as the rate-limit key lets callers bypass the new limit by rotating fake tokens.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/api/src/fastify.ts, line 56:

<comment>Using the unvalidated `Authorization` header as the rate-limit key lets callers bypass the new limit by rotating fake tokens.</comment>

<file context>
@@ -37,17 +38,28 @@ export async function buildApp(opts: FastifyServerOptions = {}) {
+    await scope.register(rateLimit, {
+      max: 100,
+      timeWindow: "1 minute",
+      keyGenerator: (request) => request.headers.authorization || request.ip,
+    });
+
</file context>
Suggested change
keyGenerator: (request) => request.headers.authorization || request.ip,
keyGenerator: (request) => request.ip,
Fix with Cubic

## Demo

<Frame>
<img src="/images/deployments.png" />
Copy link

@cubic-dev-ai cubic-dev-ai bot Mar 13, 2026

Choose a reason for hiding this comment

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

P2: This image path does not exist in the repository, so the Demo section will render a broken image.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/docs/platform/deployments.mdx, line 12:

<comment>This image path does not exist in the repository, so the Demo section will render a broken image.</comment>

<file context>
@@ -0,0 +1,105 @@
+## Demo
+
+<Frame>
+  <img src="/images/deployments.png" />
+</Frame>
+
</file context>
Fix with Cubic

| Pattern | Description |
| ------------------ | -------------------------------------------------------- |
| **PR title regex** | Match pull request titles (e.g., `hotfix`, `emergency`). |
| **Branch regex** | Match branch names (e.g., `hotfix/*`). |
Copy link

@cubic-dev-ai cubic-dev-ai bot Mar 13, 2026

Choose a reason for hiding this comment

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

P2: The branch regex example is incorrect: hotfix/* will not match branches like hotfix/foo. Use a pattern such as ^hotfix/.* so the documented rule actually detects hotfix branches.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/docs/automations/incident-detection.mdx, line 40:

<comment>The branch regex example is incorrect: `hotfix/*` will not match branches like `hotfix/foo`. Use a pattern such as `^hotfix/.*` so the documented rule actually detects hotfix branches.</comment>

<file context>
@@ -0,0 +1,78 @@
+| Pattern            | Description                                              |
+| ------------------ | -------------------------------------------------------- |
+| **PR title regex** | Match pull request titles (e.g., `hotfix`, `emergency`). |
+| **Branch regex**   | Match branch names (e.g., `hotfix/*`).                   |
+| **PR label regex** | Match pull request labels.                               |
+
</file context>
Suggested change
| **Branch regex** | Match branch names (e.g., `hotfix/*`). |
| **Branch regex** | Match branch names (e.g., `^hotfix/.*`). |
Fix with Cubic

## Demo

<Frame>
<img src="/images/dora.png" />
Copy link

@cubic-dev-ai cubic-dev-ai bot Mar 13, 2026

Choose a reason for hiding this comment

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

P2: The demo image points to /images/dora.png, but that asset is not present in the repository, so this page will show a broken image.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/docs/metrics-and-insights/dora.mdx, line 12:

<comment>The demo image points to `/images/dora.png`, but that asset is not present in the repository, so this page will show a broken image.</comment>

<file context>
@@ -0,0 +1,89 @@
+## Demo
+
+<Frame>
+  <img src="/images/dora.png" />
+</Frame>
+
</file context>
Fix with Cubic

For most teams, the default `production` environment is all you need. Multiple environments are useful when:

- **You want to measure metrics for non-production environments** — for example, tracking deployment frequency to staging.
- **You have multiple production environments** — for example, regional deployments (`production-us`, `production-eu`).
Copy link

@cubic-dev-ai cubic-dev-ai bot Mar 13, 2026

Choose a reason for hiding this comment

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

P2: These example names will not be treated as production environments, so deployments to production-us/production-eu are excluded from default DORA metrics.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/docs/platform/environments.mdx, line 29:

<comment>These example names will not be treated as production environments, so deployments to `production-us`/`production-eu` are excluded from default DORA metrics.</comment>

<file context>
@@ -0,0 +1,47 @@
+For most teams, the default `production` environment is all you need. Multiple environments are useful when:
+
+- **You want to measure metrics for non-production environments** — for example, tracking deployment frequency to staging.
+- **You have multiple production environments** — for example, regional deployments (`production-us`, `production-eu`).
+
+## Archiving
</file context>
Fix with Cubic

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🧹 Nitpick comments (1)
apps/docs/metrics-and-insights/team/code-review-distribution.mdx (1)

48-48: Consider a small wording polish for readability.

“Assert your team members have…” reads a bit stiff here; “ensure communication stays healthy” is clearer.

✍️ Suggested copy tweak
-- Make sure your team feels safe giving feedback. Go through your team's <a href="/metrics-and-insights/pull-requests">Pull Requests</a> to assert your team members have a healthy communication style.
+- Make sure your team feels safe giving feedback. Go through your team's <a href="/metrics-and-insights/pull-requests">Pull Requests</a> to ensure communication stays respectful and healthy.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/docs/metrics-and-insights/team/code-review-distribution.mdx` at line 48,
Replace the stiff phrase "assert your team members have a healthy communication
style" with clearer wording like "ensure communication stays healthy" in the
sentence that links to /metrics-and-insights/pull-requests (the line containing
"Make sure your team feels safe giving feedback. Go through your team's <a
href=\"/metrics-and-insights/pull-requests\">Pull Requests</a>..."); update the
copy so the full sentence reads smoothly (for example: "Make sure your team
feels safe giving feedback. Go through your team's Pull Requests to ensure
communication stays healthy.") and keep the existing link target unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/api/src/fastify.ts`:
- Around line 53-56: The rate-limiting keyGenerator currently uses the raw
request.headers.authorization which fragments buckets; update the keyGenerator
in the rateLimit registration to normalize the authorization value: read
request.headers.authorization, trim whitespace, remove a case-insensitive
"Bearer" prefix if present, then use that normalized token (or fallback to
request.ip) as the key; optionally hash the normalized token before returning to
avoid storing raw credentials in memory. This change should be made inside the
existing keyGenerator function used when registering rateLimit.

In `@apps/docs/api-reference/deployments/create-deployment.mdx`:
- Around line 56-58: Update the curl examples in create-deployment.mdx so the
Authorization header sends the raw API key string (e.g., "Authorization:
YOUR_API_KEY") instead of using the "Bearer " prefix; locate the curl request
block that currently has -H "Authorization: Bearer YOUR_API_KEY" (the example
used for the /v1/deployments POST) and replace the header value to remove
"Bearer " in both occurrences (the example near the first curl block and the
repeated example later) so the server-side findApiKeyOrThrow receives the raw
key to hash and validate.

In `@apps/docs/automations/incident-detection.mdx`:
- Around line 35-40: Replace the glob example in the "Branch regex" table row
(the **Branch regex** entry) with a proper regular expression: use an anchored
pattern that begins with "hotfix/" and matches one or more characters after the
slash (escape the "/" if your renderer requires it) so branch names like
"hotfix/fix-login" are matched instead of the glob "hotfix/*".

In `@apps/docs/metrics-and-insights/team/time-to-merge.mdx`:
- Line 24: Fix the singular/plural mismatch in the sentence "Ideally, most small
Pull Requests should be merged within an hour of it being approved." by
replacing "it being approved" with a plural form such as "their approval" or
rephrasing to "they are approved" so the pronoun agrees with "Pull Requests".

In `@apps/docs/platform/environments.mdx`:
- Around line 26-29: Update the paragraph that lists "production-us" and
"production-eu" to explicitly state that only exact names "production" or "prod"
are auto-detected for default DORA metrics; for regional production environments
like "production-us" or "production-eu" you must explicitly set the production
flag so they will be counted. Reference the existing wording about
auto-detection (the sentence that currently says only exact `production`/`prod`
names are auto-detected) and add a short caveat after the bullet about multiple
production environments clarifying the need to set the production flag for
regional names.

---

Nitpick comments:
In `@apps/docs/metrics-and-insights/team/code-review-distribution.mdx`:
- Line 48: Replace the stiff phrase "assert your team members have a healthy
communication style" with clearer wording like "ensure communication stays
healthy" in the sentence that links to /metrics-and-insights/pull-requests (the
line containing "Make sure your team feels safe giving feedback. Go through your
team's <a href=\"/metrics-and-insights/pull-requests\">Pull Requests</a>...");
update the copy so the full sentence reads smoothly (for example: "Make sure
your team feels safe giving feedback. Go through your team's Pull Requests to
ensure communication stays healthy.") and keep the existing link target
unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c445e0ae-972b-44b9-b4a5-1e611d6b2baa

📥 Commits

Reviewing files that changed from the base of the PR and between 8be4116 and 0c32f97.

📒 Files selected for processing (41)
  • apps/api/src/fastify.ts
  • apps/docs/about/data-privacy-and-security.mdx
  • apps/docs/about/open-source.mdx
  • apps/docs/about/principles.mdx
  • apps/docs/api-reference/authentication.mdx
  • apps/docs/api-reference/deployments/create-deployment.mdx
  • apps/docs/api-reference/introduction.mdx
  • apps/docs/api-reference/rate-limit.mdx
  • apps/docs/automations/alerts.mdx
  • apps/docs/automations/digests.mdx
  • apps/docs/automations/incident-detection.mdx
  • apps/docs/automations/pr-size-labeler.mdx
  • apps/docs/automations/pr-title-check.mdx
  • apps/docs/docs.json
  • apps/docs/features/automations/intro.mdx
  • apps/docs/features/deployments.mdx
  • apps/docs/features/environments.mdx
  • apps/docs/get-started/get-started.mdx
  • apps/docs/get-started/intro.mdx
  • apps/docs/get-started/self-host.mdx
  • apps/docs/metrics-and-insights/code-reviews.mdx
  • apps/docs/metrics-and-insights/dora.mdx
  • apps/docs/metrics-and-insights/pull-requests.mdx
  • apps/docs/metrics-and-insights/team/code-review-distribution.mdx
  • apps/docs/metrics-and-insights/team/cycle-time.mdx
  • apps/docs/metrics-and-insights/team/intro.mdx
  • apps/docs/metrics-and-insights/team/pr-size-distribution.mdx
  • apps/docs/metrics-and-insights/team/time-to-approve.mdx
  • apps/docs/metrics-and-insights/team/time-to-first-review.mdx
  • apps/docs/metrics-and-insights/team/time-to-merge.mdx
  • apps/docs/metrics-and-insights/wip.mdx
  • apps/docs/metrics-and-insights/work-log.mdx
  • apps/docs/mint.json
  • apps/docs/platform/applications.mdx
  • apps/docs/platform/deployments.mdx
  • apps/docs/platform/environments.mdx
  • apps/docs/platform/incidents.mdx
  • apps/docs/platform/integrations.mdx
  • apps/docs/platform/people.mdx
  • apps/docs/platform/teams.mdx
  • apps/docs/snippets/pr-badge.mdx
💤 Files with no reviewable changes (6)
  • apps/docs/snippets/pr-badge.mdx
  • apps/docs/features/automations/intro.mdx
  • apps/docs/mint.json
  • apps/docs/features/environments.mdx
  • apps/docs/features/deployments.mdx
  • apps/docs/get-started/get-started.mdx

Comment on lines +53 to +56
await scope.register(rateLimit, {
max: 100,
timeWindow: "1 minute",
keyGenerator: (request) => request.headers.authorization || request.ip,
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, find and read the fastify.ts file
find . -name "fastify.ts" -path "*/apps/api/*" | head -20

Repository: sweetr-dev/sweetr.dev

Length of output: 90


🏁 Script executed:

# Get the file and inspect the specific lines
cat -n apps/api/src/fastify.ts | sed -n '40,70p'

Repository: sweetr-dev/sweetr.dev

Length of output: 1094


🏁 Script executed:

# Search for rate-limit usage in the file
rg "rateLimit|rate-limit" apps/api/src/fastify.ts -B 5 -A 10

Repository: sweetr-dev/sweetr.dev

Length of output: 1121


🌐 Web query:

@fastify/rate-limit keyGenerator documentation behavior

💡 Result:

In @fastify/rate-limit, keyGenerator is the function used to compute the unique “client key” that the limiter tracks counters against.

  • Signature/behavior: keyGenerator(request) can be sync or async and must return an identifier (typically a string) that will be used as the rate-limit key. The same generated key is also passed into other dynamic options like max, timeWindow, and allowList (as the key argument). [1]
  • Default: keyGenerator defaults to (request) => request.ip. [1]
  • What request.ip means here: Fastify resolves it from request.connection.remoteAddress, or from request.headers['x-forwarded-for'] only if Fastify’s trustProxy option is enabled. [1]
  • Related option: If you set groupId, it’s added on top of the keyGenerator result to group multiple routes under a separate shared limit bucket. [1]

Sources: [1]


🏁 Script executed:

# Check what deploymentsRouter does and if it uses bearer tokens
find . -name "*deployments*router*" -type f

Repository: sweetr-dev/sweetr.dev

Length of output: 116


🏁 Script executed:

# Look for any existing authorization/token handling patterns
rg "Authorization|Bearer" apps/api/src --type ts -B 2 -A 2 | head -40

Repository: sweetr-dev/sweetr.dev

Length of output: 3155


🏁 Script executed:

# Check if there are any tests or documentation about rate limiting
rg "rate.*limit|rateLimit" apps/api/src --type ts -l

Repository: sweetr-dev/sweetr.dev

Length of output: 963


🏁 Script executed:

# Check the deployments router to understand what API it handles
cat -n apps/api/src/app/deployment/deployments.router.ts | head -50

Repository: sweetr-dev/sweetr.dev

Length of output: 1342


🏁 Script executed:

# Check if there's a rate-limiter plugin that might give context
cat -n apps/api/src/lib/rate-limiter.plugin.ts

Repository: sweetr-dev/sweetr.dev

Length of output: 662


🏁 Script executed:

# Look for any API documentation or tests for deployments
find . -name "*deployment*" -type f | grep -E "(test|spec|doc|README)" | head -10

Repository: sweetr-dev/sweetr.dev

Length of output: 161


🏁 Script executed:

# Check the deployment API documentation
cat -n apps/docs/api-reference/deployments/create-deployment.mdx | head -60

Repository: sweetr-dev/sweetr.dev

Length of output: 2482


🏁 Script executed:

# Look at the findApiKeyOrThrow function to understand how it parses the Authorization header
find . -name "*api-key*" -type f | grep service

Repository: sweetr-dev/sweetr.dev

Length of output: 121


🏁 Script executed:

# Check how findApiKeyOrThrow processes the authorization header
rg "findApiKeyOrThrow" apps/api/src --type ts -A 20 | head -50

Repository: sweetr-dev/sweetr.dev

Length of output: 3785


🏁 Script executed:

# Check how `@fastify/rate-limit` treats the rate limit key - is it persisted or in-memory?
# Also check if there's any hashing happening
rg "class|function" --type ts -A 5 apps/api/src/lib/rate-limiter.plugin.ts

Repository: sweetr-dev/sweetr.dev

Length of output: 47


🏁 Script executed:

# Look at the full api-keys service to understand the complete flow
cat -n apps/api/src/app/api-keys/services/api-keys.service.ts

Repository: sweetr-dev/sweetr.dev

Length of output: 2044


🌐 Web query:

@fastify/rate-limit key storage persistence memory or persistent

💡 Result:

@fastify/rate-limit stores counters/keys in memory by default (per Node.js process), so limits reset on process restart and aren’t shared across multiple instances/PM2/containers. To make rate-limits survive process restarts and/or work across multiple servers, you need an external store—the plugin supports Redis via the redis option (uses ioredis), or you can provide your own persistent backend via the store option (e.g., SQL/Mongo/etc.). [1][2]


🏁 Script executed:

# Verify if there are any tests or usage patterns for the deployments API
rg "deployments" apps/api/src --type ts -l | grep -E "(test|spec)" | head -5

Repository: sweetr-dev/sweetr.dev

Length of output: 131


🏁 Script executed:

# Check if there's any existing Bearer token normalization pattern elsewhere
rg "Bearer|bearer" apps/api/src --type ts -B 2 -A 2 | grep -i strip\|replace\|normalize | head -10

Repository: sweetr-dev/sweetr.dev

Length of output: 47


🏁 Script executed:

# Look at how the authorization header is typically formatted when passed through
rg "headers\.authorization" apps/api/src --type ts -B 2 -A 2 | head -30

Repository: sweetr-dev/sweetr.dev

Length of output: 669


🏁 Script executed:

# Look for integration tests that might show how the deployment API is actually called
cat -n apps/api/src/app/metrics/services/dora-metrics.integration.test.ts | head -80

Repository: sweetr-dev/sweetr.dev

Length of output: 3217


🏁 Script executed:

# Check if there's any middleware or guard that normalizes the Authorization header before routing
rg "middleware|guard|pre-handler" apps/api/src/fastify.ts -B 5 -A 5

Repository: sweetr-dev/sweetr.dev

Length of output: 47


🏁 Script executed:

# Search for any normalization of authorization header in the codebase
rg "authorization" apps/api/src --type ts -B 3 -A 3 | grep -i "trim\|normalize\|strip\|replace\|Bearer" -A 2 -B 2

Repository: sweetr-dev/sweetr.dev

Length of output: 47


🏁 Script executed:

# Check if there's an HTTP client or test that calls the deployment API to understand how Authorization is formatted
rg "POST.*deployments\|/v1/deployments" apps/api/src --type ts -B 5 -A 10

Repository: sweetr-dev/sweetr.dev

Length of output: 47


🏁 Script executed:

# Look for any e2e or integration tests that hit the actual HTTP endpoint
find . -name "*.test.ts" -o -name "*.spec.ts" | xargs rg "/v1/deployments" 2>/dev/null | head -20

Repository: sweetr-dev/sweetr.dev

Length of output: 47


🏁 Script executed:

# Check if findApiKeyOrThrow is actually expecting just the token or the full Authorization header
rg "findApiKeyOrThrow" apps/api/src --type ts -B 3 -A 10 | head -60

Repository: sweetr-dev/sweetr.dev

Length of output: 2920


🏁 Script executed:

# Search for any Bearer prefix handling anywhere in the codebase
rg "Bearer" apps/api/src --type ts -C 3

Repository: sweetr-dev/sweetr.dev

Length of output: 2458


🏁 Script executed:

# Look at the full auth plugin to understand how it handles Bearer tokens
cat -n apps/api/src/app/auth/resolvers/plugins/auth.plugin.ts | head -50

Repository: sweetr-dev/sweetr.dev

Length of output: 1859


🏁 Script executed:

# Check if deployments router is part of a different auth flow or if it's broken
rg "deploymentsRouter" apps/api/src --type ts -B 2 -A 2

Repository: sweetr-dev/sweetr.dev

Length of output: 1183


🏁 Script executed:

# Verify: does API actually use bearerToken somewhere to normalize it?
rg "bearerToken\|authorization" apps/api/src/app/auth/resolvers/plugins/auth.plugin.ts -B 3 -A 3 | head -40

Repository: sweetr-dev/sweetr.dev

Length of output: 47


🏁 Script executed:

# Check if there's any middleware or pre-handler that normalizes the Authorization header before routing
rg "preHandler|hook|middleware" apps/api/src/fastify.ts -B 3 -A 3

Repository: sweetr-dev/sweetr.dev

Length of output: 47


🏁 Script executed:

# Look for any request normalization or auth header processing
rg "request.headers.authorization" apps/api/src --type ts -B 5 -A 5 | head -50

Repository: sweetr-dev/sweetr.dev

Length of output: 1643


Normalize the Authorization header key for rate-limiting to prevent bucketing fragmentation.

The current keyGenerator uses the raw Authorization header, which fragments the 100 req/min limit across variants: Bearer abc, abc, Bearer abc (extra space), and different casings all create separate rate-limit buckets. This allows clients to bypass the rate limit by varying header formatting. Additionally, the raw credential is retained as the rate-limit key in the in-memory store.

Extract and normalize the token before using it as the rate-limit key. Whitespace should be trimmed, and the Bearer prefix stripped if present. Hashing is optional for rate-limiting, but normalization is essential to enforce the limit per API key.

🔧 Suggested baseline fix
     await scope.register(rateLimit, {
       max: 100,
       timeWindow: "1 minute",
-      keyGenerator: (request) => request.headers.authorization || request.ip,
+      keyGenerator: (request) => {
+        const authorization = request.headers.authorization?.trim();
+        if (!authorization) {
+          return request.ip;
+        }
+
+        return authorization.replace(/^Bearer\s+/i, "");
+      },
     });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/api/src/fastify.ts` around lines 53 - 56, The rate-limiting keyGenerator
currently uses the raw request.headers.authorization which fragments buckets;
update the keyGenerator in the rateLimit registration to normalize the
authorization value: read request.headers.authorization, trim whitespace, remove
a case-insensitive "Bearer" prefix if present, then use that normalized token
(or fallback to request.ip) as the key; optionally hash the normalized token
before returning to avoid storing raw credentials in memory. This change should
be made inside the existing keyGenerator function used when registering
rateLimit.

Comment on lines +56 to +58
curl -X POST https://api.sweetr.dev/v1/deployments \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "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.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Verify whether /v1/deployments normalizes the Authorization header
# before calling findApiKeyOrThrow.
rg -n -C3 --type=ts 'findApiKeyOrThrow|authorization|Bearer|addHook|onRequest|preHandler' apps/api/src

Repository: sweetr-dev/sweetr.dev

Length of output: 31844


🏁 Script executed:

head -60 apps/api/src/app/api-keys/services/api-keys.service.ts

Repository: sweetr-dev/sweetr.dev

Length of output: 1524


Fix Authorization header format in curl examples.

The /v1/deployments endpoint passes request.headers.authorization directly to findApiKeyOrThrow without stripping the Bearer prefix. findApiKeyOrThrow hashes the value as-is and compares against the stored key hash, which is the hash of the raw API key alone. Requests with Authorization: Bearer YOUR_API_KEY will fail with 401 because the hashed value won't match.

Change the examples to send the raw API key without the Bearer prefix:

Correct format for lines 56-58 and 73-75
curl -X POST https://api.sweetr.dev/v1/deployments \
  -H "Authorization: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/docs/api-reference/deployments/create-deployment.mdx` around lines 56 -
58, Update the curl examples in create-deployment.mdx so the Authorization
header sends the raw API key string (e.g., "Authorization: YOUR_API_KEY")
instead of using the "Bearer " prefix; locate the curl request block that
currently has -H "Authorization: Bearer YOUR_API_KEY" (the example used for the
/v1/deployments POST) and replace the header value to remove "Bearer " in both
occurrences (the example near the first curl block and the repeated example
later) so the server-side findApiKeyOrThrow receives the raw key to hash and
validate.

Comment on lines +35 to +40
Detects incidents based on patterns in pull request titles, branch names, or labels. Configure regular expressions to match your team's conventions.

| Pattern | Description |
| ------------------ | -------------------------------------------------------- |
| **PR title regex** | Match pull request titles (e.g., `hotfix`, `emergency`). |
| **Branch regex** | Match branch names (e.g., `hotfix/*`). |
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Replace the branch example with an actual regex.

hotfix/* is a glob, not a regex. As written, it repeats /, so it will not match branch names like hotfix/fix-login.

✏️ Suggested doc tweak
-| **Branch regex**   | Match branch names (e.g., `hotfix/*`).                   |
+| **Branch regex**   | Match branch names (e.g., `^hotfix/.*`).                 |
📝 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
Detects incidents based on patterns in pull request titles, branch names, or labels. Configure regular expressions to match your team's conventions.
| Pattern | Description |
| ------------------ | -------------------------------------------------------- |
| **PR title regex** | Match pull request titles (e.g., `hotfix`, `emergency`). |
| **Branch regex** | Match branch names (e.g., `hotfix/*`). |
Detects incidents based on patterns in pull request titles, branch names, or labels. Configure regular expressions to match your team's conventions.
| Pattern | Description |
| ------------------ | -------------------------------------------------------- |
| **PR title regex** | Match pull request titles (e.g., `hotfix`, `emergency`). |
| **Branch regex** | Match branch names (e.g., `^hotfix/.*`). |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/docs/automations/incident-detection.mdx` around lines 35 - 40, Replace
the glob example in the "Branch regex" table row (the **Branch regex** entry)
with a proper regular expression: use an anchored pattern that begins with
"hotfix/" and matches one or more characters after the slash (escape the "/" if
your renderer requires it) so branch names like "hotfix/fix-login" are matched
instead of the glob "hotfix/*".

## What good looks like

Ideally, most small Pull Requests should be merged within a hour of it being approved. Teams should prioritize finishing work over starting new things.
Ideally, most small Pull Requests should be merged within an hour of it being approved. Teams should prioritize finishing work over starting new things.
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Fix singular/plural agreement in this sentence.

The sentence starts plural (“Pull Requests”) but later uses singular pronoun (“it”).

✍️ Proposed fix
-Ideally, most small Pull Requests should be merged within an hour of it being approved. Teams should prioritize finishing work over starting new things.
+Ideally, most small Pull Requests should be merged within an hour of being approved. Teams should prioritize finishing work over starting new things.
📝 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
Ideally, most small Pull Requests should be merged within an hour of it being approved. Teams should prioritize finishing work over starting new things.
Ideally, most small Pull Requests should be merged within an hour of being approved. Teams should prioritize finishing work over starting new things.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/docs/metrics-and-insights/team/time-to-merge.mdx` at line 24, Fix the
singular/plural mismatch in the sentence "Ideally, most small Pull Requests
should be merged within an hour of it being approved." by replacing "it being
approved" with a plural form such as "their approval" or rephrasing to "they are
approved" so the pronoun agrees with "Pull Requests".

Comment on lines +26 to +29
For most teams, the default `production` environment is all you need. Multiple environments are useful when:

- **You want to measure metrics for non-production environments** — for example, tracking deployment frequency to staging.
- **You have multiple production environments** — for example, regional deployments (`production-us`, `production-eu`).
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Mention that regional prod environments need the production flag set explicitly.

Lines 15-18 say only exact production/prod names are auto-detected. Without that caveat here, users can read production-us and production-eu as names that will count toward default DORA metrics automatically.

✏️ Suggested doc tweak
-- **You have multiple production environments** — for example, regional deployments (`production-us`, `production-eu`).
+- **You have multiple production environments** — for example, regional deployments (`production-us`, `production-eu`). Mark these as production manually, since only `production` and `prod` are auto-detected.
📝 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
For most teams, the default `production` environment is all you need. Multiple environments are useful when:
- **You want to measure metrics for non-production environments** — for example, tracking deployment frequency to staging.
- **You have multiple production environments** — for example, regional deployments (`production-us`, `production-eu`).
For most teams, the default `production` environment is all you need. Multiple environments are useful when:
- **You want to measure metrics for non-production environments** — for example, tracking deployment frequency to staging.
- **You have multiple production environments** — for example, regional deployments (`production-us`, `production-eu`). Mark these as production manually, since only `production` and `prod` are auto-detected.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/docs/platform/environments.mdx` around lines 26 - 29, Update the
paragraph that lists "production-us" and "production-eu" to explicitly state
that only exact names "production" or "prod" are auto-detected for default DORA
metrics; for regional production environments like "production-us" or
"production-eu" you must explicitly set the production flag so they will be
counted. Reference the existing wording about auto-detection (the sentence that
currently says only exact `production`/`prod` names are auto-detected) and add a
short caveat after the bullet about multiple production environments clarifying
the need to set the production flag for regional names.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

huge Huge PR - High risk of reviewer fatigue

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant