Add developer API beta#365
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Warning Review limit reached
Next review available in: 27 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (7)
📝 WalkthroughWalkthroughAdds a gated Developer API with hashed keys, rate limiting, usage tracking, read-only search/gear/spec endpoints, developer and admin portals, localized UI, documentation, and tests. It also expands BotID route protection and narrows sensor-spec data passed to the API. ChangesDeveloper API foundation
Sequence Diagram(s)sequenceDiagram
participant Client
participant API Route
participant HTTP Wrapper
participant Developer Service
participant Database
Client->>API Route: Send authenticated GET request
API Route->>HTTP Wrapper: Run endpoint handler
HTTP Wrapper->>Developer Service: Authenticate and rate-limit key
Developer Service->>Database: Read key and update rate bucket
API Route->>Developer Service: Fetch domain data
Developer Service-->>API Route: Return search, gear, or spec data
HTTP Wrapper->>Developer Service: Record endpoint usage
API Route-->>Client: Return JSON with request and rate-limit metadata
Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 13
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
messages/de.json (1)
1-1: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winTranslate the new
developerApistrings in all locale files.messages/de.json,messages/es.json,messages/fr.json,messages/it.json,messages/ja.json,messages/ms.json, andmessages/zh.jsonstill leave 77 of 80developerApientries identical tomessages/en.json, so the developer portal/docs/admin UI will mostly render in English for those locales.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@messages/de.json` at line 1, Translate the 77 untranslated developerApi entries in messages/de.json, messages/es.json, messages/fr.json, messages/it.json, messages/ja.json, messages/ms.json, and messages/zh.json, using messages/en.json as the source while preserving all keys, placeholders, and formatting.
🧹 Nitpick comments (8)
src/server/developer-api/data.ts (1)
175-189: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueConsider conditionally spreading the
setproperties.While this implementation is perfectly safe and functional, it produces SQL that redundantly assigns unmatched columns to their existing values (e.g.,
search_requests = search_requests). Conditionally spreading the properties results in a more compactUPDATEclause payload.♻️ Proposed refactor
set: { totalRequests: sql`${developerApiUsageDaily.totalRequests} + 1`, - searchRequests: - params.endpoint === "search" - ? sql`${developerApiUsageDaily.searchRequests} + 1` - : developerApiUsageDaily.searchRequests, - suggestionRequests: - params.endpoint === "suggestions" - ? sql`${developerApiUsageDaily.suggestionRequests} + 1` - : developerApiUsageDaily.suggestionRequests, - gearRequests: - params.endpoint === "gear" - ? sql`${developerApiUsageDaily.gearRequests} + 1` - : developerApiUsageDaily.gearRequests, + ...(params.endpoint === "search" && { searchRequests: sql`${developerApiUsageDaily.searchRequests} + 1` }), + ...(params.endpoint === "suggestions" && { suggestionRequests: sql`${developerApiUsageDaily.suggestionRequests} + 1` }), + ...(params.endpoint === "gear" && { gearRequests: sql`${developerApiUsageDaily.gearRequests} + 1` }), },🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/server/developer-api/data.ts` around lines 175 - 189, Update the `set` payload in the developer API usage update to conditionally spread only the counter matching `params.endpoint`, while always incrementing `totalRequests`. Remove the unmatched-column self-assignments so the generated UPDATE includes only relevant properties, preserving the existing endpoint-specific increments.src/server/developer-api/http.ts (2)
1-3: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winNon-standard conditional
server-onlyguard duplicated in two files.Both files gate the
server-onlyimport behindprocess.env.NEXT_RUNTIMEwith a dynamicimport(), unlikeservice.ts's plainimport "server-only";. The package's protection is driven by the bundler's export-condition resolution, not a runtime env var, so this pattern likely doesn't add the intended safety net and just adds inconsistency.
src/server/developer-api/http.ts#L1-L3: replace with a plainimport "server-only";at the top, matchingservice.ts, unless there's a confirmed reason (e.g. Vitest import-time crash) this workaround is needed.src/server/developer-api/serializers.ts#L1-L3: same fix — align with the standard unconditional import.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/server/developer-api/http.ts` around lines 1 - 3, Replace the conditional dynamic server-only guard with a standard unconditional import at the top of src/server/developer-api/http.ts lines 1-3, matching service.ts. Apply the same change to src/server/developer-api/serializers.ts lines 1-3; remove the NEXT_RUNTIME checks and dynamic imports in both files.
71-122: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick winUsage recording blocks the response instead of using
after().
recordUsageBestEffortis awaited before the success/error response is returned, adding a DB write to the critical path of every request. Next.js'safter()(stable, importable fromnext/server) is designed exactly for this "log/record after responding" pattern and would remove this from the request's latency.⚡ Sketch using after()
+import { after } from "next/server"; ... - const response = await handler(); - await recordUsageBestEffort({ apiKeyId: credential.apiKeyId, endpoint }); + const response = await handler(); + after(() => recordUsageBestEffort({ apiKeyId: credential.apiKeyId, endpoint }));🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/server/developer-api/http.ts` around lines 71 - 122, Update runDeveloperApiRequest to schedule both success and error calls to recordUsageBestEffort through Next.js after() instead of awaiting them before returning. Import after from next/server, preserve the existing credential, endpoint, and allowed-rate-limit conditions, and keep the response and error handling paths otherwise unchanged.src/lib/specs/registry.tsx (2)
2265-2278: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win
hideInSpecsTablenow doubles as a developer-API exclusion flag.
getDeveloperApiMetadatatreatsfield.hideInSpecsTableas equivalent toapi: null(Line 2270).hideInSpecsTablewas designed to control website-UI visibility (e.g., a field surfaced elsewhere on the page) — reusing it to also gate the developer API means a field hidden from the specs table for unrelated reasons is silently excluded from the API too, with no explicit signal that this was intentional for the API contract.♻️ Suggested decoupling
- if (!config || field.hideInSpecsTable || field.api === null) return undefined; + if (!config || field.api === null) return undefined;If any currently
hideInSpecsTablefield should indeed stay out of the API, mark it explicitly withapi: nullinstead of relying on the coupling.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/lib/specs/registry.tsx` around lines 2265 - 2278, Update getDeveloperApiMetadata to stop using field.hideInSpecsTable as a developer-API exclusion condition; gate metadata generation only on the section configuration and field.api === null. For any fields that must remain excluded from the developer API, set their api value explicitly to null at the field definitions.
2211-2278: 🎯 Functional Correctness | 🔵 TrivialDeveloper API exposure is opt-in per section but opt-out per field — new fields leak by default.
Once a section is registered in
developerApiSectionConfig, every field in it is exposed via the public API unless explicitly markedapi: null(Line 2270). This PR already needed to retroactively addapi: nullforvideoSummary/videoAvailableCodecs(Lines 1289, 1311-1312) to prevent leaking video-mode UI internals — a sign that this opt-out model requires developers to remember to exclude every future sensitive/internal field added to an already-registered section, or it ships to the public API unreviewed.Consider flipping to an explicit opt-in (e.g., require
api: {...}metadata to include a field, rather thanapi: nullto exclude it) so new fields default to private until a conscious decision is made.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/lib/specs/registry.tsx` around lines 2211 - 2278, The developer API exposure logic in getDeveloperApiMetadata currently includes every field unless api is null, causing newly added fields in registered sections to leak. Change the eligibility check to require explicit field.api metadata, returning undefined when api is absent or null, and preserve the existing hideInSpecsTable exclusion and metadata construction for explicitly opted-in fields.tests/playwright/developer-api.spec.ts (1)
11-14: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueSimplify JSON assertions.
While
await expect(...).resolvesworks correctly due to the underlying matcher engine, the standard Playwright idiom is to simplyawaitthe JSON parser result directly insideexpect(...).
tests/playwright/developer-api.spec.ts#L11-L14: Change toexpect(await response.json()).toMatchObject({ ... }).tests/playwright/developer-api.spec.ts#L28-L30: Change toexpect(await response.json()).toMatchObject({ ... }).🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/playwright/developer-api.spec.ts` around lines 11 - 14, Update both JSON assertions in tests/playwright/developer-api.spec.ts at lines 11-14 and 28-30 to await response.json() directly inside expect(...), then call toMatchObject without resolves. Preserve the existing expected object matchers and assertions at both sites.src/app/[locale]/(admin)/admin/developer-api/developer-api-admin-manager.tsx (1)
246-246: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick winUse the shared key-limit constant here instead of hardcoding
3.
DEVELOPER_API_MAX_ACTIVE_KEYSalready defines the server-side cap, so threading that value into the admin UI keeps the button state aligned if the limit ever changes.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/app/`[locale]/(admin)/admin/developer-api/developer-api-admin-manager.tsx at line 246, Replace the hardcoded 3 in the disabled condition with the shared DEVELOPER_API_MAX_ACTIVE_KEYS constant, preserving the existing isPending check and keys.length comparison.src/app/[locale]/(admin)/admin/sidebar.tsx (1)
195-198: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueConsider a consistent localization pattern for sidebar items.
Special-casing the
"developerApi"label works for this addition, but it makes the render logic slightly fragile if more items require translations in the future. Consider adding an optionali18nKeyproperty to theSidebarItemtype and mapping it generically, or using a common translation namespace for all navigation items.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/app/`[locale]/(admin)/admin/sidebar.tsx around lines 195 - 198, Update the SidebarItem type and sidebar rendering to support an optional i18nKey for localized labels, replacing the developerApi-specific conditional with generic translation lookup when i18nKey is present and falling back to item.label otherwise. Configure developerApi to use the appropriate i18nKey while preserving existing labels for items without translations.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@messages/de.json`:
- Around line 1856-1943: Translate all newly added developerApi entries in
messages/de.json, messages/es.json, messages/fr.json, and messages/it.json,
covering the portal, docs, and admin sections. Replace the remaining English
values while preserving translation keys, placeholders such as {name}, {count},
and {current}, and technical terms where appropriate; keep existing localized
values unchanged.
In `@messages/es.json`:
- Around line 1856-1943: Translate every remaining English string under
developerApi.portal, developerApi.docs, and developerApi.admin in
messages/es.json into Spanish, while preserving the already localized
portal.welcome, docs.serverOnlyNote, and docs.exampleRequest values. Keep
placeholders such as {name}, {count}, and {current} unchanged.
In `@messages/fr.json`:
- Around line 1856-1943: Translate every remaining English string under
developerApi in messages/fr.json, messages/de.json, and messages/es.json,
including portal, docs, and admin sections. Preserve all placeholders,
formatting, and API terminology while keeping the existing localized strings
intact.
In `@messages/it.json`:
- Around line 1856-1943: Translate every remaining English string under
developerApi in messages/it.json into Italian, covering portal, docs, and admin
while preserving placeholders, meaning, and formatting. Keep the already
localized portal.welcome, docs.serverOnlyNote, and docs.exampleRequest
unchanged.
In
`@src/app/`[locale]/(admin)/admin/developer-api/developer-api-admin-manager.tsx:
- Line 155: Update the error paragraph rendered by the developer API admin
manager to include role="alert", ensuring the existing error message remains
visually unchanged while action failures are announced to screen readers.
- Around line 85-96: Update createKey and the form’s name input to use
controlled draft-name state instead of an uncontrolled field. Preserve the
entered name while actionCreateDeveloperApiKeyForAdmin is pending or fails, and
clear the state only when result.ok is true after setting the secret and
refreshing.
In `@src/app/`[locale]/(pages)/developer/developer-portal.tsx:
- Line 1: Add role="alert" to the error message <p> elements in the developer
portal and admin developer API manager, using the existing {error} rendering so
action failures are announced to assistive technologies.
- Line 1: Update both create-key forms to make the name fields controlled with
state and bind their value and change handler, so form action completion does
not clear failed input. In each form, reset the name state only after the action
result is successful (`result.ok`), preserving the typed value on failure.
- Line 212: Add role="alert" to the error message paragraph in the developer
portal JSX so dynamically rendered {error} content is announced to assistive
technologies, while preserving the existing conditional rendering and styling.
- Around line 62-64: Update the dateFormatter construction in the developer
portal to pass an explicit, deterministic timeZone alongside locale and
dateStyle. Apply the same timezone configuration to the other date formatting
call around the referenced second location, preserving the existing medium-date
formatting behavior.
- Around line 66-79: Update createKey and the developer key name input to
preserve the submitted name while actionCreateDeveloperApiKey is pending or
fails: make the input controlled or otherwise retain its value, and clear it
only after a successful result before closing the dialog.
In `@src/server/developer-api/actions.ts`:
- Around line 12-17: Update actionError to preserve and return the
DeveloperApiError code and message for expected errors, while logging unexpected
errors server-side before returning the failure result. Use the existing
DeveloperApiError type or identifying fields to distinguish expected errors, and
remove the unused void error handling.
In `@src/server/developer-api/service.ts`:
- Around line 196-221: The duplicated parse → count → generate → insert logic in
createDeveloperApiKey and createDeveloperApiKeyForAdmin should be centralized in
a shared key-creation helper. Make enforcement of DEVELOPER_API_MAX_ACTIVE_KEYS
atomic by moving the limit check into the insert operation or wrapping the check
and createApiKeyData call in a transaction, ensuring concurrent requests cannot
exceed the limit while preserving the existing validation and error behavior.
---
Outside diff comments:
In `@messages/de.json`:
- Line 1: Translate the 77 untranslated developerApi entries in
messages/de.json, messages/es.json, messages/fr.json, messages/it.json,
messages/ja.json, messages/ms.json, and messages/zh.json, using messages/en.json
as the source while preserving all keys, placeholders, and formatting.
---
Nitpick comments:
In
`@src/app/`[locale]/(admin)/admin/developer-api/developer-api-admin-manager.tsx:
- Line 246: Replace the hardcoded 3 in the disabled condition with the shared
DEVELOPER_API_MAX_ACTIVE_KEYS constant, preserving the existing isPending check
and keys.length comparison.
In `@src/app/`[locale]/(admin)/admin/sidebar.tsx:
- Around line 195-198: Update the SidebarItem type and sidebar rendering to
support an optional i18nKey for localized labels, replacing the
developerApi-specific conditional with generic translation lookup when i18nKey
is present and falling back to item.label otherwise. Configure developerApi to
use the appropriate i18nKey while preserving existing labels for items without
translations.
In `@src/lib/specs/registry.tsx`:
- Around line 2265-2278: Update getDeveloperApiMetadata to stop using
field.hideInSpecsTable as a developer-API exclusion condition; gate metadata
generation only on the section configuration and field.api === null. For any
fields that must remain excluded from the developer API, set their api value
explicitly to null at the field definitions.
- Around line 2211-2278: The developer API exposure logic in
getDeveloperApiMetadata currently includes every field unless api is null,
causing newly added fields in registered sections to leak. Change the
eligibility check to require explicit field.api metadata, returning undefined
when api is absent or null, and preserve the existing hideInSpecsTable exclusion
and metadata construction for explicitly opted-in fields.
In `@src/server/developer-api/data.ts`:
- Around line 175-189: Update the `set` payload in the developer API usage
update to conditionally spread only the counter matching `params.endpoint`,
while always incrementing `totalRequests`. Remove the unmatched-column
self-assignments so the generated UPDATE includes only relevant properties,
preserving the existing endpoint-specific increments.
In `@src/server/developer-api/http.ts`:
- Around line 1-3: Replace the conditional dynamic server-only guard with a
standard unconditional import at the top of src/server/developer-api/http.ts
lines 1-3, matching service.ts. Apply the same change to
src/server/developer-api/serializers.ts lines 1-3; remove the NEXT_RUNTIME
checks and dynamic imports in both files.
- Around line 71-122: Update runDeveloperApiRequest to schedule both success and
error calls to recordUsageBestEffort through Next.js after() instead of awaiting
them before returning. Import after from next/server, preserve the existing
credential, endpoint, and allowed-rate-limit conditions, and keep the response
and error handling paths otherwise unchanged.
In `@tests/playwright/developer-api.spec.ts`:
- Around line 11-14: Update both JSON assertions in
tests/playwright/developer-api.spec.ts at lines 11-14 and 28-30 to await
response.json() directly inside expect(...), then call toMatchObject without
resolves. Preserve the existing expected object matchers and assertions at both
sites.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 3747764b-45a5-485e-8a30-e0fd9591b57d
📒 Files selected for processing (58)
docs/configuration.mddocs/developer-api.mddocs/search-system.mddocs/server-structure.mddrizzle/0024_tiresome_lilandra.sqldrizzle/meta/0024_snapshot.jsondrizzle/meta/_journal.jsonmessages/de.jsonmessages/en.jsonmessages/es.jsonmessages/fr.jsonmessages/it.jsonmessages/ja.jsonmessages/ms.jsonmessages/zh.jsonsrc/app/[locale]/(admin)/admin/developer-api/developer-api-admin-manager.tsxsrc/app/[locale]/(admin)/admin/developer-api/page.tsxsrc/app/[locale]/(admin)/admin/sidebar.tsxsrc/app/[locale]/(pages)/developer/developer-portal.tsxsrc/app/[locale]/(pages)/developer/docs/page.tsxsrc/app/[locale]/(pages)/developer/docs/request-example-tabs.tsxsrc/app/[locale]/(pages)/developer/docs/spec-selector-dialog.tsxsrc/app/[locale]/(pages)/developer/page.tsxsrc/app/api/v1/gear/[slug]/route.tssrc/app/api/v1/gear/[slug]/specs/route.tssrc/app/api/v1/search/route.tssrc/app/api/v1/search/suggestions/route.tssrc/app/api/v1/specs/route.tssrc/components/layout/header-client.tsxsrc/components/layout/header-model.tssrc/components/layout/header.tsxsrc/components/layout/user-menu.tsxsrc/lib/auth/additional-fields.tssrc/lib/mapping/sensor-map.tssrc/lib/security/botid-protected-routes.tssrc/lib/specs/registry.tsxsrc/server/db/schema.tssrc/server/developer-api/actions.tssrc/server/developer-api/constants.tssrc/server/developer-api/data.tssrc/server/developer-api/errors.tssrc/server/developer-api/http.tssrc/server/developer-api/schemas.tssrc/server/developer-api/serializers.tssrc/server/developer-api/service.tssrc/server/developer-api/specs.tssrc/server/gear/data.tstests/playwright/developer-api.spec.tstests/unit/botid-protected-routes.test.tstests/unit/developer-api-http.test.tstests/unit/developer-api-portal-service.test.tstests/unit/developer-api-schemas-serializers.test.tstests/unit/developer-api-spec-routes.test.tstests/unit/developer-api-specs.test.tstests/unit/developer-docs-page.test.tstests/unit/header-model.test.tstests/unit/header-server.test.tstests/unit/user-menu.test.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{test,spec}.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Include or update automated tests (vitest and/or playwright) covering the primary path and at least one meaningful edge case when introducing or modifying behavior
Files:
tests/unit/botid-protected-routes.test.tstests/playwright/developer-api.spec.tstests/unit/developer-api-http.test.tstests/unit/user-menu.test.tstests/unit/developer-api-portal-service.test.tstests/unit/header-model.test.tstests/unit/developer-api-spec-routes.test.tstests/unit/header-server.test.tstests/unit/developer-api-schemas-serializers.test.tstests/unit/developer-api-specs.test.tstests/unit/developer-docs-page.test.ts
**/{app,src}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Replace any new hardcoded user-facing strings with translation keys for all locales
Files:
src/app/api/v1/specs/route.tssrc/app/api/v1/search/suggestions/route.tssrc/app/api/v1/gear/[slug]/route.tssrc/app/[locale]/(admin)/admin/developer-api/developer-api-admin-manager.tsxsrc/app/api/v1/gear/[slug]/specs/route.tssrc/lib/auth/additional-fields.tssrc/lib/security/botid-protected-routes.tssrc/server/developer-api/errors.tssrc/app/api/v1/search/route.tssrc/app/[locale]/(pages)/developer/docs/spec-selector-dialog.tsxsrc/app/[locale]/(pages)/developer/docs/request-example-tabs.tsxsrc/server/developer-api/constants.tssrc/app/[locale]/(admin)/admin/developer-api/page.tsxsrc/server/developer-api/specs.tssrc/components/layout/header.tsxsrc/server/db/schema.tssrc/app/[locale]/(pages)/developer/page.tsxsrc/app/[locale]/(pages)/developer/developer-portal.tsxsrc/server/developer-api/http.tssrc/app/[locale]/(admin)/admin/sidebar.tsxsrc/lib/mapping/sensor-map.tssrc/server/gear/data.tssrc/components/layout/header-model.tssrc/server/developer-api/schemas.tssrc/server/developer-api/actions.tssrc/components/layout/header-client.tsxsrc/server/developer-api/serializers.tssrc/app/[locale]/(pages)/developer/docs/page.tsxsrc/components/layout/user-menu.tsxsrc/server/developer-api/service.tssrc/server/developer-api/data.tssrc/lib/specs/registry.tsx
src/server/db/schema.ts
📄 CodeRabbit inference engine (AGENTS.md)
src/server/db/schema.ts: Make all schema changes insrc/server/db/schema.ts; never modify the database directly without going through the schema
All schema changes must be backwards compatible by default, using deprecations instead of deletions
Use Drizzle's type-safe schema definitions for database schema insrc/server/db/schema.ts
Files:
src/server/db/schema.ts
messages/**/*.json
📄 CodeRabbit inference engine (AGENTS.md)
Maintain translation key parity: if a key is added, removed, or renamed in
messages/en.json, apply the same key change across all locale files inmessages/directory
Files:
messages/zh.jsonmessages/en.jsonmessages/fr.jsonmessages/ja.jsonmessages/de.jsonmessages/es.jsonmessages/ms.jsonmessages/it.json
🪛 Betterleaks (1.6.1)
src/app/[locale]/(pages)/developer/docs/page.tsx
[high] 160-161: Discovered a potential authorization token provided in a curl command header, which could compromise the curl accessed resource.
(curl-auth-header)
[high] 211-212: Discovered a potential authorization token provided in a curl command header, which could compromise the curl accessed resource.
(curl-auth-header)
[high] 267-268: Discovered a potential authorization token provided in a curl command header, which could compromise the curl accessed resource.
(curl-auth-header)
[high] 308-309: Discovered a potential authorization token provided in a curl command header, which could compromise the curl accessed resource.
(curl-auth-header)
🪛 LanguageTool
docs/developer-api.md
[style] ~11-~11: Consider using a different verb to strengthen your wording.
Context: ...tores a SHA-256 hash, not the secret. - Removing developer access immediately revokes al...
(REMOVE_REVOKE)
[style] ~11-~11: Consider removing “of” to be more concise
Context: ...ng developer access immediately revokes all of the user’s keys. - Send keys with `Authoriz...
(ALL_OF_THE)
🪛 OpenGrep (1.25.0)
src/server/developer-api/service.ts
[ERROR] 77-77: Dynamic command passed to child_process.exec/execSync. Use child_process.execFile or spawn with an argument array instead.
(coderabbit.command-injection.exec-js)
🪛 React Doctor (0.7.6)
src/app/[locale]/(pages)/developer/developer-portal.tsx
[error] 161-161: This can cause a hydration mismatch because Intl.DateTimeFormat().format() formats with the server's locale and timezone during server rendering but the user's in the browser. Format it in a post-mount useEffect, or pass an explicit locale and timeZone.
Format locale/timezone-dependent values in a post-mount useEffect + state, or pass an explicit locale and timeZone so the server and the browser render the same text. Only runs on SSR-capable projects.
(no-locale-format-in-render)
[error] 163-163: This can cause a hydration mismatch because Intl.DateTimeFormat().format() formats with the server's locale and timezone during server rendering but the user's in the browser. Format it in a post-mount useEffect, or pass an explicit locale and timeZone.
Format locale/timezone-dependent values in a post-mount useEffect + state, or pass an explicit locale and timeZone so the server and the browser render the same text. Only runs on SSR-capable projects.
(no-locale-format-in-render)
🔇 Additional comments (69)
drizzle/0024_tiresome_lilandra.sql (1)
1-39: LGTM!drizzle/meta/0024_snapshot.json (1)
1-9340: LGTM!drizzle/meta/_journal.json (1)
172-178: LGTM!src/server/db/schema.ts (2)
2532-2536: LGTM!
2562-2632: LGTM!src/lib/auth/additional-fields.ts (1)
39-43: LGTM!src/server/developer-api/constants.ts (1)
1-13: LGTM!src/server/developer-api/data.ts (2)
1-174: LGTM!
190-217: LGTM!src/server/developer-api/actions.ts (1)
19-27: LGTM!Also applies to: 29-37, 39-50, 52-65, 67-75
src/server/developer-api/errors.ts (1)
1-18: LGTM!src/server/developer-api/service.ts (7)
69-106: Confirm whether API error message strings are in scope of the i18n guideline.This file (and
schemas.ts,http.ts) constructs many hardcoded English messages viaDeveloperApiError(e.g. "An API key is required.", "The supplied API key is invalid."). Per path instructions, new hardcoded user-facing strings undersrc/**should use translation keys, but these are developer-facing HTTP API response bodies, not rendered UI — conventionally kept in one language for API consumers.As per path instructions,
**/{app,src}/**/*.{ts,tsx}: "Replace any new hardcoded user-facing strings with translation keys for all locales." Please confirm whether this rule is intended to cover machine-readable API error payloads, or only UI-rendered strings; if it applies here, these messages (and the similar ones throughoutservice.ts,schemas.ts, andhttp.ts) would need extraction intomessages/*.json.Source: Path instructions
42-57: LGTM!Also applies to: 69-151
153-194: LGTM!
223-295: LGTM!
328-332: LGTM!
59-67: 🔒 Security & Privacy
keyPrefixonly exposes 7 characters of the random secret (sharply_live_+ 7 base64url chars), so it doesn't meaningfully reduce API key entropy.> Likely an incorrect or invalid review comment.
334-358: 🗄️ Data Integrity & IntegrationThese passthroughs already return published gear only.
searchGearandgetSuggestionsenforcepublicationState = PUBLISHEDinsrc/server/search/data.ts, andfetchGearBySlugfilters out hidden/rumored items.> Likely an incorrect or invalid review comment.src/server/developer-api/schemas.ts (1)
1-89: LGTM!src/server/developer-api/http.ts (1)
5-70: LGTM!src/server/developer-api/serializers.ts (2)
5-127: LGTM!Also applies to: 155-165
138-146: 🔒 Security & PrivacyNo change needed here.
fetchGearBySlugalready filtersrawSamplestoisDeleted = false, soserializeGearonly serializes active samples.> Likely an incorrect or invalid review comment.src/lib/mapping/sensor-map.ts (1)
4-8: LGTM!Also applies to: 37-39
src/lib/specs/registry.tsx (2)
4-43: LGTM!Also applies to: 90-111, 193-203, 254-262, 426-448, 649-698, 1198-1203, 1289-1289, 1311-1312, 1621-1621, 1688-1694, 2400-2406
2312-2354: 🎯 Functional CorrectnessNo issue: boolean spec values already have explicit formatters
Every boolean-like developer API field in
src/lib/specs/registry.tsxpasses throughformatDisplay/yesNoNull, sotextFromSpecDisplaydoes not drop a current spec value.> Likely an incorrect or invalid review comment.tests/unit/developer-api-schemas-serializers.test.ts (1)
1-175: LGTM!tests/unit/developer-api-specs.test.ts (1)
1-147: LGTM!tests/unit/developer-docs-page.test.ts (1)
1-103: LGTM!tests/unit/header-model.test.ts (1)
1-14: LGTM!Also applies to: 56-61, 77-77
tests/unit/header-server.test.ts (1)
2-2: LGTM!Also applies to: 40-42, 55-55, 68-71
src/server/developer-api/specs.ts (1)
1-63: LGTM!src/app/api/v1/gear/[slug]/specs/route.ts (1)
7-28: LGTM!tests/unit/botid-protected-routes.test.ts (1)
1-15: LGTM!tests/unit/developer-api-http.test.ts (1)
14-98: LGTM!tests/unit/developer-api-portal-service.test.ts (1)
56-99: LGTM!tests/unit/developer-api-spec-routes.test.ts (1)
34-91: LGTM!src/server/gear/data.ts (1)
351-362: LGTM!src/app/api/v1/search/route.ts (1)
6-15: LGTM!src/app/api/v1/search/suggestions/route.ts (1)
6-15: LGTM!src/app/api/v1/gear/[slug]/route.ts (1)
6-21: LGTM!tests/unit/user-menu.test.ts (1)
1-67: LGTM!src/app/api/v1/specs/route.ts (1)
4-9: 🎯 Functional CorrectnessNo endpoint change needed.
DeveloperApiEndpointonly includessearch,suggestions, andgear, and this route is recorded under the sharedgearbucket.> Likely an incorrect or invalid review comment.src/app/[locale]/(pages)/developer/developer-portal.tsx (1)
1-278: The rest of the component (dialog wiring, revoke flow, translation usage) looks correct and consistent with the messages files.src/app/[locale]/(admin)/admin/developer-api/developer-api-admin-manager.tsx (1)
1-289: Pagination, search filtering, and access/revoke flows are otherwise implemented soundly.messages/de.json (1)
9-9: LGTM!messages/en.json (1)
9-9: LGTM!Also applies to: 1856-1943
messages/es.json (1)
9-9: LGTM!messages/fr.json (1)
9-9: LGTM!messages/it.json (1)
9-9: LGTM!src/app/[locale]/(pages)/developer/page.tsx (1)
1-51: LGTM!src/app/[locale]/(pages)/developer/docs/page.tsx (1)
1-338: LGTM!src/app/[locale]/(pages)/developer/docs/request-example-tabs.tsx (1)
1-38: LGTM!src/app/[locale]/(pages)/developer/docs/spec-selector-dialog.tsx (1)
1-85: LGTM!docs/configuration.md (1)
29-30: LGTM!src/lib/security/botid-protected-routes.ts (1)
26-33: LGTM!src/app/[locale]/(admin)/admin/developer-api/page.tsx (1)
1-16: LGTM!src/app/[locale]/(admin)/admin/sidebar.tsx (3)
4-4: LGTM!
46-53: LGTM!
121-130: LGTM!messages/ja.json (1)
9-9: LGTM!docs/developer-api.md (1)
1-79: LGTM!docs/search-system.md (1)
49-52: LGTM!docs/server-structure.md (1)
81-87: LGTM!messages/ms.json (1)
9-9: LGTM!Also applies to: 1856-1943
messages/zh.json (1)
9-9: LGTM!Also applies to: 1856-1943
src/components/layout/header-client.tsx (1)
10-13: LGTM!Also applies to: 40-42, 83-90, 103-108, 235-235
src/components/layout/header-model.ts (1)
38-38: LGTM!Also applies to: 83-83, 95-95, 107-109, 191-191
src/components/layout/header.tsx (1)
21-21: LGTM!src/components/layout/user-menu.tsx (1)
3-3: LGTM!Also applies to: 12-19, 32-49, 102-117
Summary
Adds the first gated Developer API beta for published Sharply gear data.
What changed
/api/v1search, gear detail, live spec catalog, and selected-spec endpoints.src/server/developer-apiwhile reusing existing search and gear services.Deployment notes
0024_tiresome_lilandrabefore serving the new routes./api/v1/*.Validation
npm run test— 691 tests passed.npm run typecheckis still blocked by the pre-existingtests/unit/spec-registry-i18n.test.tsweightGramstyping error.