feat(credentials): add Atlassian service account credentials#4432
feat(credentials): add Atlassian service account credentials#4432TheodoreSpeaks wants to merge 58 commits intostagingfrom
Conversation
…ership workflow edits via sockets, ui improvements
…ng improvements, posthog, secrets mutations
…ration, signup method feature flags, SSO improvements
…nts, secrets performance, polling refactors, drag resources in mothership
…y invalidation, HITL docs
…endar triggers, docs updates, integrations/models pages improvements
…ions, jira forms endpoints
…mat, logs performance improvements fix(csp): add missing analytics domains, remove unsafe-eval, fix workspace CSP gap (#4179) fix(landing): return 404 for invalid dynamic route slugs (#4182) improvement(seo): optimize sitemaps, robots.txt, and core web vitals across sim and docs (#4170) fix(gemini): support structured output with tools on Gemini 3 models (#4184) feat(brightdata): add Bright Data integration with 8 tools (#4183) fix(mothership): fix superagent credentials (#4185) fix(logs): close sidebar when selected log disappears from filtered list; cleanup (#4186)
v0.6.46: mothership streaming fixes, brightdata integration
…m integration, atlassian triggers
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
PR SummaryMedium Risk Overview Updates the OAuth token API/contracts to return provider-specific extras ( Refactors the integrations UI by extracting a reusable Reviewed by Cursor Bugbot for commit 287dade. Bugbot is set up for automated code reviews on this repo. Configure here. |
Greptile SummaryAdds Confidence Score: 4/5Safe to merge; all findings are P2 (description copy error, TOCTOU on duplicate check, minor duplication). No P0 or P1 issues found. The validation flow, encryption, transaction pattern, and selector migration are all correct. Three P2 findings keep the score from a 5. apps/sim/app/api/auth/atlassian-service-account/route.ts (duplicate-name check outside transaction), apps/sim/lib/oauth/oauth.ts (description copy mismatch). Important Files Changed
Sequence DiagramsequenceDiagram
participant UI as AtlassianServiceAccountForm
participant API as /api/auth/atlassian-service-account
participant ATL as Atlassian (_edge/tenant_info)
participant JIRA as api.atlassian.com/ex/jira/.../myself
participant DB as Database
UI->>API: POST { apiToken, domain, displayName }
API->>ATL: GET https://{domain}/_edge/tenant_info
ATL-->>API: { cloudId }
API->>JIRA: GET /myself (Bearer apiToken)
JIRA-->>API: { accountId, displayName }
API->>DB: Check duplicate displayName
DB-->>API: existing?
API->>DB: transaction: INSERT credential + credentialMember
API-->>UI: 201 { credential }
Note over UI,DB: Runtime token fetch
participant TK as /api/auth/oauth/token
participant SEL as Jira/Confluence Selectors
SEL->>TK: POST { credentialId }
TK->>DB: decrypt encryptedServiceAccountKey
DB-->>TK: { apiToken, cloudId, domain }
TK-->>SEL: { accessToken, cloudId, domain }
SEL->>JIRA: selector call with cloudId (skips accessible-resources)
|
- Collapse fetchOAuthTokenBundle into fetchOAuthToken (returns the bundle) - Reuse serviceAccountJsonSchema in the JSON form instead of hand-rolled checks - Use parseAtlassianErrorMessage for log details; drop one-line bearer helper - Extract ATLASSIAN_SERVICE_ACCOUNT_PROVIDER_ID/_SECRET_TYPE constants - Use Drizzle .returning() instead of post-insert SELECT - Helper for the duplicated 401/403 + non-OK pattern in the validator
- New /integrations/atlassian-service-account doc covers token creation, scope selection, and adding the credential to Sim - Form's "View setup guide" link now points at the doc - Fix the existing Google form link that pointed to the wrong path Screenshot TODOs left inline as MDX comments for the docs team.
- Auth type picker, Sim add-credential modal, Jira block credential dropdown - Scope-picker screenshot still TODO
- Drop stale 'email and API token' copy from the service description (we only collect a token + domain, no email field) - Move duplicate display-name check inside the create transaction so concurrent POSTs can't both pass the check and insert duplicates
Docs site serves /static/* from apps/docs/public, not apps/sim/public — matches the existing google-service-account screenshot convention.
…e-account # Conflicts: # scripts/check-api-validation-contracts.ts
- SSRF: only accept *.atlassian.net / *.jira-dev.com hosts before fetching tenant_info, blocking probes against localhost/internal IPs - Confluence spaces selector: pull cloudId from the SA secret instead of calling accessible-resources, which 401s for scoped service-account tokens - Case-insensitive https?:// strip so HTTPS://team.atlassian.net normalizes correctly
|
| GitGuardian id | GitGuardian status | Secret | Commit | Filename | |
|---|---|---|---|---|---|
| 29606901 | Triggered | Generic High Entropy Secret | a54dcbe | apps/sim/providers/utils.test.ts | View secret |
🛠 Guidelines to remediate hardcoded secrets
- Understand the implications of revoking this secret by investigating where it is used in your code.
- Replace and store your secret safely. Learn here the best practices.
- Revoke and rotate this secret.
- If possible, rewrite git history. Rewriting git history is not a trivial act. You might completely break other contributing developers' workflow and you risk accidentally deleting legitimate data.
To avoid such incidents in the future consider
- following these best practices for managing and storing secrets including API keys and other credentials
- install secret detection on pre-commit to catch secret before it leaves your machine and ease remediation.
🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 287dade. Configure here.
| upstreamStatus: error.status, | ||
| ...error.logDetail, | ||
| }) | ||
| return NextResponse.json({ code: error.code, error: error.code }, { status: 400 }) |
There was a problem hiding this comment.
Upstream 5xx errors returned as 400 client error
Low Severity
When Atlassian's API is unreachable (e.g., 502 from the upstream), AtlassianValidationError captures the real upstream status in error.status, but the catch handler always responds with HTTP 400. This misrepresents a server-side/upstream failure as a client input error. While the front-end works around this by switching on the code field, the HTTP status is misleading for monitoring, retry logic, and non-UI consumers. The error.status is available and could be forwarded directly.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 287dade. Configure here.
| const cloudId = | ||
| resolved?.providerId === ATLASSIAN_SERVICE_ACCOUNT_PROVIDER_ID && resolved.credentialId | ||
| ? (await getAtlassianServiceAccountSecret(resolved.credentialId)).cloudId | ||
| : await getConfluenceCloudId(domain, accessToken) |
There was a problem hiding this comment.
Redundant credential resolution and secret decryption in selector
Low Severity
For Atlassian service-account credentials, resolveOAuthAccountId is called twice (once inside refreshAccessTokenIfNeeded at line 47, and again directly at line 65), and the encrypted secret is decrypted twice (once inside getAtlassianServiceAccountToken via refreshAccessTokenIfNeeded, and again at line 68 via getAtlassianServiceAccountSecret). This triples the DB and crypto work for every Confluence spaces selector request with a service account credential.
Reviewed by Cursor Bugbot for commit 287dade. Configure here.


Summary
atlassian-service-accountcredential type backed by a scoped Atlassian API token, surfaced in Jira and Confluence credential dropdowns alongside OAuth_edge/tenant_info(unauth) to discover cloudId, thenapi.atlassian.com/ex/jira/{cloudId}/rest/api/3/myselfwith Bearer to verify the token workscloudIdfrom the token route through tools and selectors so blocks skip the runtimeaccessible-resourcescall (which 401s for scoped service-account tokens)ServiceAccountForm(Google JSON-key paste/upload) and newAtlassianServiceAccountForm(token + domain) fromintegrations-manager; map typed server error codes to friendly inline copycodefrom error response bodies intoApiClientError.codeso any form/hook can switch on it without re-parsingType of Change
Testing
Tested manually end-to-end (credential creation, project picker, runtime block call).
bun run lintandbun run check:api-validation:strictboth pass.Checklist