You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
feat: add get project endpoint under v1-alpha - #2231
Adds the first route in the public API, GET /v1-alpha/projects/{slug}, and turns on the /v1-alpha version it lives under. Development callers use it to learn which values to pass in repos and platform.
api/src/versions/registry.ts and api/src/versions/v1-alpha/index.ts: register /v1-alpha. Its spec is served at /v1-alpha/openapi.json as 1.0.0-alpha. The docs reference page still renders only /v1, so alpha routes stay unannounced until the closed-alpha allowlist lands.
api/src/versions/v1-alpha/projects.ts: the route. It makes one projects_list call (slug, details=true), the same call as the Nuxt handler.
api/src/lib/errors.ts: NotFoundError (404 not_found) and UpstreamUnavailableError (503 upstream_unavailable), in the same style as InvalidDateRangeError. It also takes notFoundHandler from feat: version deprecation and sunset headers #2224's src/errors/not-found.ts, which is deleted: each branch had created a home for error code without seeing the other, and one file gives the error envelope and the promotion-time GoneError a single place to land. The version-bump playbook now points there (review on #2224).
api/tests/version-lifecycle.test.ts (from feat: version deprecation and sunset headers #2224): the registry case pinned /v1 as the only version. It now expects ['/v1', '/v1-alpha'], neither with lifecycle metadata.
Decisions worth a look
repositories is a list of { url } objects. The Overviews group will add repo fields here, and objects keep that additive.
Platform keys drop the -nango suffix and any resulting duplicates, the same way the UI does. Every value is then one a caller can pass straight into platform.
An unknown slug returns 404. The epic's "unknown slug returns empty data" rule fits the metric endpoints, where an empty series is a valid answer.
Every Tinybird failure returns 503 upstream_unavailable, and the original error is logged. Without this, Fastify would pass Tinybird's own status to the caller, so a Tinybird 401 would read as the caller's auth failure.
One onRequest hook in the alpha plugin sets Cache-Control: private, max-age=0 on every /v1-alpha response, errors included (ADR-0013). api/ has no Redis response cache yet. When it lands, this endpoint belongs in the 24h tier.
Error bodies use Fastify's default shape, with code set, until the error envelope lands.
Testing
api/tests/project-endpoint.test.ts: runs the real app and Tinybird client, with fetch stubbed at the HTTP boundary. It covers the response body, the pipe call, platform and repo edge cases, the 404, Tinybird 500/401/429, network and non-JSON failures mapping to 503, the cache header on successes and errors, and the /v1-alpha spec (version, Projects tag, field descriptions, kept out of /v1).
api/tests/openapi-versions.test.ts: the registry now lists ['/v1', '/v1-alpha'].
References
JIRA: IN-1345, a sub-task of IN-1141 (Endpoints phase 1: Development)
The reason will be displayed to describe this comment to others. Learn more.
🟡 Changes recommended
The route lacks required authentication and allowlist enforcement, while malformed upstream responses and the alpha specification violate documented response contracts.
Get a fresh assessment by requesting another Copilot review.
Pull request overview
Adds the first /v1-alpha public API endpoint for retrieving project metadata.
Changes:
Registers /v1-alpha and its OpenAPI specification.
Adds project lookup, normalization, and upstream error handling.
Adds comprehensive endpoint and version-registry tests.
The lifecycle test from IN-1139 pinned the registry to /v1 alone; this branch adds
/v1-alpha, so the case now expects both while still asserting neither carries
lifecycle metadata.
Signed-off-by: anilb <epipav@gmail.com>
Fold notFoundHandler from src/errors/not-found.ts into src/lib/errors.ts next to
NotFoundError and UpstreamUnavailableError, so error code has one home before the
error envelope lands. The version-bump playbook now names that file for GoneError.
Signed-off-by: anilb <epipav@gmail.com>
The reason will be displayed to describe this comment to others. Learn more.
Traced this against the Nuxt handler (frontend/server/api/project/[slug]/index.ts): same projects_list call, same -nango suffix stripping. Confirmed the deleted not-found.ts has no leftover references and the registry tests match the new /v1-alpha entry. Solid edge case coverage on the error mapping. LGTM.
The reason will be displayed to describe this comment to others. Learn more.
Copilot review overview
🔵 Needs a closer look
Unmatched /v1-alpha 404 responses bypass the scoped cache-header hook.
Review effort: Balanced Findings: None
Previously missed (1)
In code that hasn't changed since last review
Scoped unmatched paths miss required cache header
api/src/versions/v1-alpha/index.ts:11
Unmatched paths such as /v1-alpha/does-not-exist bypass this plugin's scoped hook and use the root 404 handler, so they lack the cache header required for every response by ADR-0013. Register the shared not-found handler in this scope, as applyLifecycle does for scoped headers, and add an unmatched-path assertion.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds the first route in the public API,
GET /v1-alpha/projects/{slug}, and turns on the/v1-alphaversion it lives under. Development callers use it to learn which values to pass inreposandplatform.{ "slug": "kubernetes", "name": "Kubernetes", "repositories": [{ "url": "https://github.com/kubernetes/kubernetes" }], "connectedPlatforms": ["github", "git"] }api/src/versions/registry.tsandapi/src/versions/v1-alpha/index.ts: register/v1-alpha. Its spec is served at/v1-alpha/openapi.jsonas1.0.0-alpha. The docs reference page still renders only/v1, so alpha routes stay unannounced until the closed-alpha allowlist lands.api/src/versions/v1-alpha/projects.ts: the route. It makes oneprojects_listcall (slug,details=true), the same call as the Nuxt handler.api/src/lib/errors.ts:NotFoundError(404not_found) andUpstreamUnavailableError(503upstream_unavailable), in the same style asInvalidDateRangeError. It also takesnotFoundHandlerfrom feat: version deprecation and sunset headers #2224'ssrc/errors/not-found.ts, which is deleted: each branch had created a home for error code without seeing the other, and one file gives the error envelope and the promotion-timeGoneErrora single place to land. The version-bump playbook now points there (review on #2224).api/tests/version-lifecycle.test.ts(from feat: version deprecation and sunset headers #2224): the registry case pinned/v1as the only version. It now expects['/v1', '/v1-alpha'], neither with lifecycle metadata.Decisions worth a look
repositoriesis a list of{ url }objects. The Overviews group will add repo fields here, and objects keep that additive.-nangosuffix and any resulting duplicates, the same way the UI does. Every value is then one a caller can pass straight intoplatform.upstream_unavailable, and the original error is logged. Without this, Fastify would pass Tinybird's own status to the caller, so a Tinybird 401 would read as the caller's auth failure.onRequesthook in the alpha plugin setsCache-Control: private, max-age=0on every/v1-alpharesponse, errors included (ADR-0013).api/has no Redis response cache yet. When it lands, this endpoint belongs in the 24h tier.codeset, until the error envelope lands.Testing
api/tests/project-endpoint.test.ts: runs the real app and Tinybird client, withfetchstubbed at the HTTP boundary. It covers the response body, the pipe call, platform and repo edge cases, the 404, Tinybird 500/401/429, network and non-JSON failures mapping to 503, the cache header on successes and errors, and the/v1-alphaspec (version,Projectstag, field descriptions, kept out of/v1).api/tests/openapi-versions.test.ts: the registry now lists['/v1', '/v1-alpha'].References
ProjectSlugParams) are onmainand merged into this branch. That merge is what letnotFoundHandlermove intosrc/lib/errors.tsand made the registry test expect/v1-alpha.main