fix: unbreak raisely start and raisely create for CLI logins - #83
Merged
xolott-ark merged 5 commits intoAug 10, 2026
Conversation
CLI tokens are OAuth app authorizations with no linked user, and /authenticate returns identity flat at the top level with no organisation record, so start crashed in informLocalDev and create 404d on /users/me. Read the organisation from .raisely.json (falling back to /authenticate), fetch the org record separately for the localDevelopment flag and fail open on the expected 403, and skip the organisation switch when the session identifies no user instead of calling /users/null/move.
handleCampaignChange only handled files under <campaign>/stylesheets, so saving a page JSON was dropped with no upload and no message, leaving the preview unchanged after a refresh with nothing to explain why. Route <campaign>/pages/*.json through uploadPage, reusing the deploy guards: skip files that are invalid JSON, have no uuid, or belong to a campaign that is not configured, reporting each on the spinner.
There was a problem hiding this comment.
Risk: high.
Risk Assessment (Framework v2.0)
Framework (v2.0)
| Dimension | Tier | Score | Rationale |
|---|---|---|---|
| Security | 1 | Low | No findings |
| Sensitive domains | 1 | High | Modifies CLI auth/session identity handling: /authenticate shape, org-switch via /users/.../move, and organisation private-flag fetch used by start/create |
| Data integrity | 1 | Low | No database/query/scoping changes |
| Deployment | 1 | Low | None |
| Scope | 2 | Medium | ~140 LOC of mutative changes across 4 existing source files; tests mostly additive |
| Architecture | 2 | Low | Changes stay within the CLI package boundaries |
| Feature flags | 2 | Low | Developer CLI tooling; feature flag not required |
| Dependencies | 2 | Low | No changes |
Mitigating Factors
- New Vitest coverage for auth, components, helpers, and start page-upload path
- Page upload reuses existing deploy guards (uuid/campaign checks)
Findings
| # | Finding | Status | Resolution |
|---|---|---|---|
| 1 | When org-switch is confirmed but userUuid is missing, checkCorrectOrganisation returns and getToken still returns the token, so the CLI can continue against the wrong organisation after a failed switch |
Open | -- |
| 2 | auth.test.js case titled for undefined userUuid still supplies userUuid: 'user-1', so the CLI-login no-user guard is not actually asserted |
Open | -- |
Outstanding findings: 2
Overall risk: HIGH
Decision: ESCALATE
Rationale: Tier 1 Sensitive domains is High because the PR changes authentication/session identity resolution and organisation-switch behavior for CLI OAuth logins; escalate for human review.
Sent by Cursor Approval Agent: Nemo - Pull Request Router and Approver
The no-user branch logged and returned, so getToken carried on and the command ran against the organisation the user had just asked to leave. For deploy that means writing to the wrong organisation. Both failure branches now exit(-1) like the permission check above them, so neither continues and neither leaks a bare stack trace. The test named for an undefined user uuid was still passing userUuid: 'user-1', duplicating the case above it and never reaching the early return. It now omits userUuid, and a new case covers the move request failing. Both fail without the change above.
Runs pnpm test on Node 18, 20, and 22, covering the >=18 floor declared in engines, plus pushes to master and develop so merge results are checked too. Installs with --frozen-lockfile so a stale lockfile fails the run instead of resolving something different from local.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort 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.
Reviewed by Cursor Bugbot for commit 9b4ec03. Configure here.
checkout, setup-node, and action-setup all ran on node 20, which runners deprecated in September 2025 and now force onto node 24, warning on every job. The explicit `cache: pnpm` input still works: setup-node v6 narrowed only the automatic packageManager-based caching to npm, which this workflow does not rely on.
KeinerM
approved these changes
Aug 10, 2026
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.



Fixes SIR-1934.
Summary
Three commands were broken for anyone who authenticated with
raisely login. Two root causes, both confirmed with runtime instrumentation against the live API rather than by reading code.CLI tokens have no user record. They are OAuth app authorizations, so
/users/meresolvesmeto the authorization uuid and returns 404./authenticatealso returns identity flat at the top level, with itsdatakey holding authorization metadata (type,scopes,appUuid,authorizationUuid) rather than an organisation record. Three call sites assumed otherwise:informLocalDevreadauthData.data.organisation.privateand threw a TypeError, crashingraisely startbefore the local server came up. It now readsorganisationUuidfrom.raisely.json(falling back to/authenticate) and fetches the org record separately. No OAuth app scope grants reading an organisation, so that request 403s for every CLI login and only succeeds for admin tokens viaRAISELY_TOKEN; since thelocalDevelopmentflag is advisory, it fails open rather than blocking the command.createComponentcalled/users/mefor the organisation uuid and 404'd before creating anything. It now resolves the uuid the same way, and throws an actionable message namingraisely logout/login/initwhen neither source has it.checkCorrectOrganisationcalled/users/${authData.userUuid}/move, which became/users/null/move. It now explains that the session identifies no user and points at the admin instead.raisely startwatched only stylesheets.handleCampaignChangereturned early unless the changed path was<campaign>/stylesheets/..., so saving a page JSON was dropped with no upload and no message; the preview looked broken with nothing to explain why. Page JSON now routes throughuploadPage, reusing the same guards asdeploy: skip invalid JSON, skip pages with no uuid, and skip pages whosecampaignUuidis not configured, reporting each on the spinner.Test plan
helpers,components, andauth, plus addedstartcases for the page upload pathraisely startreaches a running local server instead of crashingraisely create debug-test-componentcreates the component and syncs both files down; verified the record and the generated.js/.jsonon disklocalDevelopmentwarning is now skipped for standard CLI loginsNotes
Targets
develop, matching the convention for feature work here. Verifyingcreateleft adebug-test-componentrecord in the Raisely org used for testing; the CLI has no delete command, so it needs removing through the admin panel.Note
Medium Risk
Touches authentication, org switching, and live upload paths used during local dev; behavior changes are intentional but could affect edge cases around org mismatch and advisory local-dev warnings.
Overview
Fixes CLI login breakage by treating
/authenticateidentity as top-level fields (notdata), and by stopping reliance on/users/mefor app-token sessions.raisely startno longer crashes ininformLocalDevwhen org details aren’t on the auth payload; it loadsorganisationUuidfrom config or auth and optionally fetches/organisations/:uuid(403 on CLI tokens is ignored so start isn’t blocked). Org mismatch handling in auth now refuses/users/undefined/movewhen there’s nouserUuid, and exits on failed moves instead of continuing.createComponentresolvesorganisationUuidfrom.raisely.jsonor/authenticate, with a clear recovery message when resolution fails.Watch mode uploads campaign page JSON changes via
uploadPage, with the same skip rules as deploy (valid JSON, uuid, configured campaign).Adds a GitHub Actions test workflow (Node 18/20/22) and Vitest coverage for auth, components, helpers, and start page uploads.
Reviewed by Cursor Bugbot for commit 98408b4. Bugbot is set up for automated code reviews on this repo. Configure here.