Skip to content

feat: add public v1 endpoints (CM-967)#3864

Open
skwowet wants to merge 14 commits intomainfrom
feat/CM-967
Open

feat: add public v1 endpoints (CM-967)#3864
skwowet wants to merge 14 commits intomainfrom
feat/CM-967

Conversation

@skwowet
Copy link
Member

@skwowet skwowet commented Feb 20, 2026

Note

Cursor Bugbot is generating a summary for commit a1b3652. Configure here.

@skwowet skwowet self-assigned this Feb 20, 2026
Co-authored-by: Cursor <cursoragent@cursor.com>
@skwowet skwowet marked this pull request as ready for review March 4, 2026 05:47
@joanagmaia joanagmaia requested a review from themarolt March 4, 2026 10:30
Copy link
Contributor

@joanagmaia joanagmaia left a comment

Choose a reason for hiding this comment

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

@skwowet only 1 endpoint missing at this point which is to get the project affiliations with the associated maintainers roles services/apps/data_sink_worker/src/service/member.service.ts.

We can add this after, non-blocking for the PR

await qx.tx(async (tx) => {
await cleanSoftDeletedMemberOrganization(tx, memberId, data.organizationId, data)

newMemberOrgId = await createMemberOrganization(tx, memberId, memberOrgData)
Copy link
Contributor

Choose a reason for hiding this comment

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

If createMemberOrganization fails to insert undefined is returned because on conflict do nothing returning id means that if there is a conflict do nothing but if there is no conflict insert and return id. Meaning that in case of a conflict we don't get existing id from the db so we return undefined... Meaning that end result could be NotFoundError('Work experience not found after creation') even though we could create work experience for existing org.

Copy link
Contributor

Choose a reason for hiding this comment

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

Updated it so that the query now uses a CTE with UNION ALL to fall back to selecting the existing row on conflict.

if (unmerge) {
const { preview, result } = unmerge

await captureApiChange(
Copy link
Contributor

Choose a reason for hiding this comment

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

If captureApiChange or startMemberUnmergeWorkflow fails we get 500 back even though the db changes are done in the above code and the tx is commited.

Copy link
Contributor

Choose a reason for hiding this comment

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

Wrapped post-commit side effects (audit log, cache invalidation, workflow start) in individual try/catch blocks so failures in these don't return 500 when the DB transaction already committed successfully.
Also added support for slack notification so that we are alerted about it. Even if the DB changes go through we should still be able to know that these async processes failed to run.

import type { ApiRequest, Auth0TokenPayload } from '@/types/api'
import type { Auth0TokenPayload } from '@/types/api'

function resolveActor(req: Request, _res: Response, next: NextFunction): void {
Copy link
Contributor

Choose a reason for hiding this comment

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

Not actually in this file but the errorHandler.ts that handles error never logs anything. Unknown errors become generic "Internal server error" with the original error discarded. No logs, no alerts — complete observability blind spot for all public API failures. We should do logging there and/or do a slack notification to alert for critical errors.

Copy link
Contributor

Choose a reason for hiding this comment

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

Added req.log.error logging and a Slack alert via sendSlackNotification for unhandled errors, matching the pattern used in apiResponseHandler.

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

]
: []),
],
)
Copy link

Choose a reason for hiding this comment

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

Unawaited promise may cause unhandled rejection crash

Low Severity

sendSlackNotification returns a Promise that is neither awaited nor has a .catch() handler. If the Slack call fails (e.g., network timeout), the rejected promise becomes an unhandled rejection, which can crash the Node.js process depending on the runtime configuration.

Fix in Cursor Fix in Web

@joanagmaia joanagmaia requested a review from themarolt March 4, 2026 15:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants