-
-
Notifications
You must be signed in to change notification settings - Fork 571
Status page api #1800
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Status page api #1800
Conversation
Add Protocol Buffer definitions for the status page service including: - StatusPage and StatusPageSummary messages - PageComponent and PageComponentGroup messages - PageSubscriber message - Full CRUD service definition with 17 RPC methods
Add ConnectRPC service implementation for status pages including: - Page CRUD operations (create, get, list, update, delete) - Component management (add monitor/external, remove, update) - Component groups (create, delete, update) - Subscriber management (subscribe, unsubscribe, list) - Content and status endpoints (getStatusPageContent, getOverallStatus) Includes converters, error handling, and comprehensive test suite with 68 tests.
Add limit validation when creating status pages: - Check status page count against workspace plan limit - Add helper functions for feature limits (custom domain, password protection, email domain protection) - Add test case for limit exceeded scenario using free plan workspace
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
@claude review this carefully it was written by your evil twin clode, he might introduce some sneaky bug |
|
Claude finished @thibaultleouay's task in 1m 47s —— View job Code Review CompleteI've thoroughly reviewed the Status Page API implementation. Here are my findings: Critical Issues Found 🔴1. Missing Token Field in Subscriber Converter (apps/server/src/routes/rpc/services/status-page/converters.ts:242-255)The Location: export function dbSubscriberToProto(
subscriber: DBPageSubscriber,
): PageSubscriber {
return {
$typeName: "openstatus.status_page.v1.PageSubscriber" as const,
id: String(subscriber.id),
pageId: String(subscriber.pageId),
email: subscriber.email,
acceptedAt: subscriber.acceptedAt?.toISOString() ?? "",
unsubscribedAt: subscriber.unsubscribedAt?.toISOString() ?? "",
createdAt: subscriber.createdAt?.toISOString() ?? "",
updatedAt: subscriber.updatedAt?.toISOString() ?? "",
};
}The
Impact: Token-based unsubscription will fail since there's no way to get the token value. 2. Type Mismatch: Number Used Instead of String (apps/server/src/routes/rpc/services/status-page/index.ts:733-753)The code uses More critically: At line 735, the type annotation type PageData = Awaited<ReturnType<typeof getPageById>>;
let pageData: PageData = undefined; // Should initialize as: let pageData: PageData;While the code does eventually throw if pageData is falsy (line 747-753), this pattern is confusing. 3. SQL Injection Risk in Count Queries (apps/server/src/routes/rpc/services/status-page/index.ts:175-179, 703-707)The count queries use High Priority Issues 🟡4. No Validation for Empty String After Trim (apps/server/src/routes/rpc/services/status-page/index.ts:153, 203, 261, 379, 398, 491, 512)Multiple places check Example at line 153: if (!req.id || req.id.trim() === "") {
throw statusPageIdRequiredError();
}Then line 157 uses Recommendation: Use 5. Duplicate Error Conditions (apps/server/src/routes/rpc/services/status-page/index.ts:866-870)Lines 866-870 have duplicate ternary expressions: throw statusPageNotFoundError(
req.identifier.case === "id"
? req.identifier.value
: req.identifier.value, // Same in both branches!
);This should probably be: throw statusPageNotFoundError(
req.identifier.case === "id"
? `ID: ${req.identifier.value}`
: `Slug: ${req.identifier.value}`,
);Or just Same issue appears at line 747-752. 6. Missing Database Transaction for Subscriber Reactivation (apps/server/src/routes/rpc/services/status-page/index.ts:572-598)When resubscribing a previously unsubscribed user (lines 574-593), the token is regenerated. However, if the update fails after generating the new token, there's no rollback mechanism. While the error is thrown, it's worth considering whether this should be wrapped in a transaction. Current behavior: If DB update fails (line 586), we throw Medium Priority Issues 🟢7. Inconsistent String Coercion PatternsThroughout the code, there's inconsistent handling of optional fields:
Consider standardizing on one pattern (e.g., always use 8. Missing Workspace Scope Check for Public Endpoints (apps/server/src/routes/rpc/services/status-page/index.ts:731-848)
Lines 731-848: When accessing by slug, there's no check for:
This could leak unpublished status page data. 9. Placeholder TODOs Left in Production Code (apps/server/src/routes/rpc/services/status-page/index.ts:847, 921)
These placeholders mean the actual status checking logic isn't implemented yet. 10. Component Status Always Returns OPERATIONAL (apps/server/src/routes/rpc/services/status-page/index.ts:918-922)The const componentStatuses = components.map((c) => ({
$typeName: "openstatus.status_page.v1.ComponentStatus" as const,
componentId: String(c.id),
status: OverallStatus.OPERATIONAL, // Placeholder - would check monitor/incident status
}));This means the overall status endpoint is essentially non-functional for real monitoring. 11. No Bounds Checking on Pagination Limits (apps/server/src/routes/rpc/services/status-page/index.ts:171, 693)While the code does enforce max limits (100), negative offsets are allowed after the validation:
The proto validation should catch this, but defensive programming suggests validating again: Low Priority / Style Issues 🔵12. Dynamic Import in Hot Path (apps/server/src/routes/rpc/services/status-page/index.ts:812)Line 812 uses 13. Inconsistent Error Message FormattingSome error functions include IDs in metadata (lines 54-60, 88-94), while others don't. Consider standardizing error metadata. 14. Test Coverage NotesThe test file has good coverage for happy paths and auth checks, but missing tests for:
Security Assessment ✅Good security practices found:
Potential security concerns:
SummaryCritical: 1 issue (missing token field) The code is generally well-structured with good error handling patterns. The main concerns are:
Overall, "Clode" did a decent job, but these issues should be addressed before merging! 😄 |
- Rename 'token' field to 'id' in the proto definition - Update server implementation to use subscriber ID instead of token - Update tests to use the new field name
- Fix type mismatch by removing redundant undefined assignment - Use Drizzle's count() function instead of raw SQL - Standardize ID validation with trim pattern - Fix duplicate ternary expressions in error messages - Wrap subscriber reactivation in transaction for atomicity - Standardize string coercion patterns using nullish coalescing
- Add public access checks for unpublished and protected pages - Implement maintenance querying in getStatusPageContent - Add proper overall status calculation based on reports and maintenances - Calculate individual component statuses (degraded/maintenance/operational) - Add new error types for access denied scenarios - Add tests for public access restrictions
|
@claude review this again |
|
Claude finished @thibaultleouay's task in 2m 6s —— View job Code Review CompleteI've conducted a thorough review of the Status Page API implementation. Here are my findings: SummaryThe implementation is well-structured and production-ready with comprehensive test coverage. The previous review identified several issues that I've re-evaluated - most are non-issues or minor observations. However, I found one legitimate bug and several areas for improvement. Critical Issues 🔴1. Missing
|
cbfbea9 to
ed8c6a1
Compare
|
@claude this is your evil twin codex who wrote this code please review it with no mercy |
|
Claude finished @thibaultleouay's task in 3m 2s —— View job Merciless Code Review Complete ✅Alright, I've thoroughly examined this Status Page API implementation. Here's my brutally honest assessment of what your "evil twin Codex" wrote. Critical Issues 🔴1. Missing
|
| async function getPageBySlug(slug: string) { | ||
| return db.select().from(page).where(eq(page.slug, slug)).get(); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
requires lowercase validation
Deploying openstatus-docs with
|
| Latest commit: |
c4a5f36
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://0e88be7c.openstatus-1sy.pages.dev |
| Branch Preview URL: | https://status-page-api.openstatus-1sy.pages.dev |
Type of change
Description
A picture tells a thousand words (if any)
Before this PR
{Please add a screenshot here}
After this PR
{Please add a screenshot here}
Related Issue (optional)