Jira Integration¶
The Jira integration connects WhiteLotusAI to Jira Cloud so users can retrieve project and issue information through conversational requests.
Documentation status
Source-inspected baseline. Jira Cloud OAuth, project listing, issue search, issue retrieval, and issue creation are present in the repository. End-to-end behavior, authorization boundaries, and production readiness require verification.
Read-only release requirement
The initial release must allow approved project and issue retrieval only. The registered create_issue tool, the requested write:jira-work OAuth scope, and the POST /jira/issue route must be addressed before the integration can be considered strictly read-only.
Integrations overview Gmail integration
1. Purpose and scope¶
The integration provides a path between the WhiteLotusAI chat service, its integrations service, and the Jira Cloud REST API v3.
The source currently represents the following capabilities:
- List Jira projects accessible to the connected account.
- Search issues by project and optional status.
- Retrieve an issue using its key.
- Create a Jira issue, subject to the required release restriction.
The implementation targets Jira Cloud. Jira Data Center compatibility must not be assumed without a separate authentication and API compatibility review.
Capability summary¶
| Capability | Registered operation | Initial release |
|---|---|---|
| Project discovery | list_projects |
Permitted, subject to authorization |
| Issue search | search_issues |
Permitted, subject to authorization |
| Issue retrieval | get_issue |
Permitted, subject to authorization |
| Issue creation | create_issue |
Blocked |
Scope of this document
This page distinguishes capabilities represented in source code from controls that still require testing. Registration of a tool, existence of a route, or successful compilation does not establish that the feature is secure or production-ready.
2. Architecture and request flow¶
The integration consists of the chat plugin, tool registry and permission checks, integrations routes, OAuth credential resolution, and the Jira API client.
Request lifecycle¶
flowchart TD
U["User request"] --> C["WhiteLotusAI chat service"]
C --> R["Tool registry and authorization"]
R --> P{"Approved operation?"}
P -- "No" --> D["Reject request"]
P -- "Yes" --> I["Integrations service"]
I --> A["Validate caller and resolve user connection"]
A --> T["Resolve access token and cloud ID"]
T --> J["Jira Cloud REST API v3"]
J --> N["Normalize result"]
N --> O["Return response through chat"]
classDef action fill:#E8F1FE,stroke:#356AC3,color:#172B4D
classDef decision fill:#FFF2CC,stroke:#B8860B,color:#4D3B00
classDef rejection fill:#FCE8E6,stroke:#C5221F,color:#5F1512
classDef success fill:#DDF5E5,stroke:#25804B,color:#16452B
class U,C,R,I,A,T,J,N action
class P decision
class D rejection
class O success
The diagram describes the intended request flow. It is not evidence that every boundary has been verified in a deployed environment.
Source components¶
| Component | Repository location | Responsibility |
|---|---|---|
| Jira chat plugin | chat/package/app/plugins/jira/plugin.py |
Tool definitions, intent routing, and execution |
| Tool registry | chat/package/app/plugins/registry.py |
Tool registration and dispatch |
| Permission checks | chat/package/app/plugins/permissions.py |
Default tool-category permissions |
| OAuth and integration routes | integrations/package/app/handlers/integration_handlers.py |
OAuth processing, credential resolution, and Jira routes |
| Jira API client | integrations/package/app/managers/jira_client.py |
Jira Cloud API requests and authentication modes |
| Alternate Jira handlers | integrations/package/app/handlers/jira_handlers.py |
Additional handlers requiring reachability review |
The plugin supplies X-User-Id and X-Internal-Secret headers when a user ID is available.
Internal service boundary
Do not trust a caller-supplied user ID solely because it appears in a header. Verify that the internal secret is validated server-side, that untrusted clients cannot impersonate another user, and that every reachable route enforces the intended authentication and authorization policy.
3. Registered tools and intent routing¶
The Jira plugin is implemented in chat/package/app/plugins/jira/plugin.py.
| Tool | Category | Purpose | Release policy |
|---|---|---|---|
list_projects |
READ |
Lists projects accessible to the account | Allow after authorization checks |
search_issues |
READ |
Searches issues by project and optional status | Allow after authorization checks |
get_issue |
READ |
Retrieves an issue by its key | Allow after authorization checks |
create_issue |
WRITE |
Creates an issue | Deny in read-only mode |
The intent-routing logic recognizes Jira-related terms and issue keys such as PROJ-123. Recognized issue keys are routed to get_issue; other Jira-related requests can be routed to search_issues.
Example user requests¶
| User request | Intended operation |
|---|---|
| “Show my accessible Jira projects.” | list_projects |
| “Find open issues in KAN.” | search_issues |
| “Show issue PROJ-123.” | get_issue |
| “Create a Jira issue for this bug.” | Reject during the read-only release |
These examples describe intended routing rather than verified end-to-end results.
Confirmation is not authorization
A tool definition containing requires_confirmation=True is not a substitute for a server-side read-only policy. A write operation must be rejected before the Jira client is invoked, including when a caller bypasses the chat interface.
4. Authentication and configuration¶
The Jira client supports two authentication modes. They have different identity and authorization implications.
This mode associates Jira credentials with an individual connected user.
- Uses a bearer access token.
- Uses an Atlassian cloud ID to construct the API base URL.
- Resolves credentials associated with the requesting user.
- Attempts access-token refresh when expiry is detected and a refresh token is available.
Preferred for multi-user deployments: this model can preserve each user's Jira permissions, provided token resolution, caching, and route authorization are correctly implemented.
This mode uses an account configured through environment variables.
JIRA_EMAILidentifies the configured account.JIRA_API_TOKENsupplies its API token.JIRA_BASE_URLspecifies the Jira site base URL.
This is a shared configured-account model rather than per-user OAuth. Its availability in the code does not establish that it is appropriate for a multi-user production environment.
Security requirement: prevent the shared account from becoming an unintended fallback for users who have not connected Jira individually.
Configuration reference¶
| Variable | Purpose |
|---|---|
JIRA_CLIENT_ID |
Atlassian OAuth client ID |
JIRA_CLIENT_SECRET |
Atlassian OAuth client secret |
JIRA_REDIRECT_URI |
Registered OAuth callback URI |
JIRA_BASE_URL |
Jira site base URL for environment-based Basic Auth |
JIRA_EMAIL |
Account email for Basic Auth |
JIRA_API_TOKEN |
API token for Basic Auth |
JIRA_DEFAULT_PROJECT |
Fallback project key for issue searches |
JWT_SECRET_KEY |
Secret used to validate application JWTs |
JWT_ALGORITHM |
Configured JWT validation algorithm |
INTERNAL_SECRET |
Secret for internal service authentication |
FRONTEND_URL |
Frontend destination after OAuth processing |
The plugin's env_vars property is empty because it expects user-specific OAuth credentials or the integrations service's configured Basic Auth mode. The plugin performs a separate configuration check for OAuth client settings and Basic Auth settings.
Safe configuration example¶
Use your existing environment-management mechanism and secret store. The following is a template, not a complete deployment configuration.
# Atlassian OAuth
JIRA_CLIENT_ID=<your-oauth-client-id>
JIRA_CLIENT_SECRET=<your-oauth-client-secret>
JIRA_REDIRECT_URI=<your-registered-callback-uri>
# Optional environment-based Basic Auth
JIRA_BASE_URL=<your-jira-site-url>
JIRA_EMAIL=<your-service-account-email>
JIRA_API_TOKEN=<your-jira-api-token>
# Application and internal service authentication
JWT_SECRET_KEY=<your-application-jwt-secret>
JWT_ALGORITHM=<your-configured-jwt-algorithm>
INTERNAL_SECRET=<your-internal-service-secret>
# Optional issue-search default
JIRA_DEFAULT_PROJECT=KAN
FRONTEND_URL=<your-frontend-url>
Protect credentials
- Never commit real tokens, client secrets, or signing secrets.
- Keep local environment files out of version control.
- Do not print credentials in logs or expose them in browser-visible URLs.
- Use separate credentials and access policies for development and production.
- Rotate exposed credentials and invalidate compromised sessions promptly.
5. OAuth authorization flow¶
The OAuth handlers are defined in integrations/package/app/handlers/integration_handlers.py.
Authorization sequence¶
sequenceDiagram
participant U as User browser
participant W as WhiteLotusAI
participant S as OAuth state store
participant A as Atlassian
U->>W: Start Jira connection
W->>W: Validate application JWT
W->>S: Store state bound to user
W-->>U: Redirect to Atlassian
U->>A: Authorize requested access
A-->>U: Redirect with code and state
U->>W: OAuth callback
W->>S: Validate and consume state
W->>A: Exchange authorization code
A-->>W: Access and refresh tokens
W->>A: Retrieve accessible resources
A-->>W: Cloud ID metadata
W->>W: Persist user connection
W-->>U: Connection result
The sequence reflects the documented implementation flow. State-store durability, expiry enforcement, token persistence, and callback behavior must be verified through tests.
Implemented flow¶
- The frontend sends an application JWT to the Jira authorization-start endpoint.
- The handler validates the JWT and extracts the user ID.
- An OAuth state value is created and stored against that user.
- The browser is redirected to Atlassian's authorization endpoint.
- The callback validates and consumes the stored state.
- The authorization code is exchanged for access and refresh tokens.
- The handler requests accessible resources to obtain the Jira cloud ID.
- Tokens, expiry information, and cloud ID metadata are stored for the user.
- The Jira connection is marked active.
- The frontend receives a connection result.
Requested OAuth scopes¶
The current source requests the following scopes:
| Scope | Purpose | Read-only review |
|---|---|---|
read:jira-work |
Read Jira work information | Review against the required operations |
write:jira-work |
Enables write capabilities within its granted scope | Remove if not required |
read:jira-user |
Read permitted Jira user information | Confirm whether the integration requires it |
offline_access |
Supports refresh-token access | Retain only as required by the OAuth design |
Least privilege
Before release, remove unnecessary write access and verify the scopes actually granted. Hiding a write tool from the interface does not revoke the authority of an already-issued token.
OAuth security requirements¶
The current authorization-start endpoint accepts the application JWT in a query parameter. This can expose credentials through browser history, server and proxy logs, monitoring systems, or other URL-handling infrastructure.
Before production approval:
- Replace query-string credential transport with a safer authenticated flow where possible.
- Verify JWT signature, expiry, issuer, audience, and applicable claims.
- Ensure OAuth state is unpredictable, single-use, expires appropriately, and is bound to the initiating user.
- Validate the callback and authorization-code exchange.
- Store access and refresh tokens securely and associate them with the correct user.
- Ensure refresh-token rotation and persistence are handled correctly where applicable.
- Sanitize provider errors and token-exchange failures before logging.
- Validate the configured redirect URI against the registered OAuth callback.
6. Jira Cloud API behavior¶
6.1 Project listing¶
The client calls the Jira project search endpoint and requests up to 50 results.
The normalized response includes:
- Project key.
- Project name.
- Project type.
The current implementation does not establish that every page of a large Jira site is retrieved. Treat full pagination as unsupported until implemented and tested.
6.2 Issue search¶
The client constructs JQL using a project key and, when supplied, a status value. Results are ordered by most recently updated, with a limit of 20 issues and selected fields.
| Field | Purpose |
|---|---|
| Summary | Issue title |
| Status | Current workflow status |
| Assignee | Assigned user |
| Priority | Issue priority |
| Issue type | Classification of the issue |
The chat plugin displays up to eight returned issues in its formatted response.
The plugin currently defaults searches without a project argument to KAN. The integrations route also supports JIRA_DEFAULT_PROJECT as its fallback. Confirm that the intended default is consistent across the plugin, service configuration, and any frontend input.
Search behavior
Verify JQL construction, escaping, supported status values, result limits, and permission-filtered results. Do not assume that an issue's absence from search means the issue does not exist; the connected account may not have access to it.
6.3 Issue retrieval¶
The client retrieves a single issue using its key and formats the following fields:
- Issue key.
- Summary.
- Status.
- Assignee.
- Priority.
- Description.
- Browse URL.
The current chat response includes the key, summary, status, assignee, and issue URL. A field returned by the client is not necessarily displayed by the chat layer.
6.4 Issue creation¶
The client and plugin include issue-creation functionality. However, the initial release is intended to be read-only.
Do not enable issue creation in production until a separately approved write-capability design establishes the required scopes, authorization checks, user confirmation behavior, audit logging, and tests.
6.5 Error handling and logging¶
The integrations service translates Jira client failures into HTTP errors. The chat plugin catches execution errors and often returns a generic availability response.
The client currently logs the upstream response body when issue creation fails.
Review that logging path to avoid recording confidential issue content, personal data, tokens, or unnecessary provider response details. Prefer sanitized error categories, correlation identifiers, and relevant HTTP status codes.
7. Read-only security enforcement¶
Read-only behavior must be enforced by the backend, not merely by the interface or the tool registry.
Required controls¶
- Allow only explicitly approved read tools in the server-side execution path.
- Reject
create_issuebefore the Jira client is invoked. - Restrict write-capable integration routes independently of chat registration.
- Protect
POST /jira/issuefrom unauthorized and direct callers. - Verify that confirmation flags cannot bypass the read-only policy.
- Ensure denied requests never reach Jira's issue-creation endpoint.
- Verify that denied requests leave Jira unchanged.
- Review alternate and legacy handlers for bypass paths.
- Test the policy using direct HTTP requests as well as conversational requests.
Authorization decision flow¶
flowchart TD
A["Incoming Jira operation"] --> B["Authenticate caller"]
B --> C{"Valid identity and connection?"}
C -- "Yes" --> D{"Operation explicitly allowlisted?"}
D -- "No" --> Y["Deny before provider call"]
D -- "Yes" --> E["Authorize user and resource"]
E --> F{"Access permitted?"}
F -- "Yes" --> G["Execute approved Jira read"]
C -- "No" --> X["Reject request"]
F -- "No" --> X
G --> H["Return sanitized result"]
classDef action fill:#E8F1FE,stroke:#356AC3,color:#172B4D
classDef decision fill:#FFF2CC,stroke:#B8860B,color:#4D3B00
classDef rejection fill:#FCE8E6,stroke:#C5221F,color:#5F1512
classDef success fill:#DDF5E5,stroke:#25804B,color:#16452B
class A,B,E,G action
class C,D,F decision
class X,Y rejection
class H success
This is the required policy model, not a claim that all checks are currently implemented.
Release-blocking defect
If issue creation succeeds while read-only mode is active, treat it as an authorization defect. Disable the affected route or capability and resolve the bypass before release.
8. Credential isolation and caching¶
The OAuth resolver checks the user's Jira connection, resolves a token and cloud ID, checks token expiry, and attempts refresh when necessary.
Verify the following conditions:
| Control | Required behavior |
|---|---|
| User isolation | One user cannot access another user's tokens or Jira data |
| Cache isolation | Cache keys are scoped to the correct user and relevant query |
| Connection state | Connection authorization is checked before cached data is returned |
| Cache invalidation | Disconnects and relevant permission changes invalidate affected data |
| Token lookup failure | A failed lookup does not fall back to another user's credentials |
| Shared account | Environment-based Basic Auth cannot unintentionally expose shared-account data |
| Refresh behavior | Refreshed credentials are persisted and associated with the correct user |
| Legacy handlers | Alternate routes cannot bypass per-user authorization |
The repository also contains integrations/package/app/handlers/jira_handlers.py. Its handler functions call the Jira client without explicitly passing per-user OAuth parameters.
Verify whether these handlers are registered or reachable in the deployed application. If reachable, ensure they cannot bypass user-specific authorization or the read-only policy.
9. Troubleshooting¶
| Symptom | Investigation |
|---|---|
| Jira cannot be connected | Check OAuth client configuration, callback URI, state validation, and Atlassian consent |
| No accessible resources returned | Verify the Atlassian account's accessible sites and granted access |
| Connection appears inactive | Inspect connection state and per-user token persistence |
| Access token has expired | Verify refresh-token availability, configuration, and refreshed-token persistence |
| Project listing is empty | Check the connected site, project permissions, and response handling |
| Issue search returns no results | Verify project key, status filter, JQL construction, and account permissions |
| Issue retrieval fails | Validate the issue key and confirm the connected user can view the issue |
| Insufficient permissions | Review Jira project permissions, user access, and OAuth scopes |
| Issue creation succeeds in read-only mode | Treat as a release-blocking authorization defect |
| Jira is temporarily unavailable | Inspect sanitized provider status, request timeouts, and service health |
Safe diagnostic procedure
- Record the timestamp, affected operation, and correlation ID.
- Check the chat and integrations service logs.
- Verify connection status and non-secret configuration.
- Inspect the sanitized upstream status and error category.
- Reproduce with a test account that has the minimum required Jira permissions.
- Confirm that denied operations do not modify Jira.
Never troubleshoot by placing real tokens or secrets into source files, query strings, screenshots, or documentation.
10. Testing and verification¶
Use a non-production Jira site and test accounts with controlled permissions. Record test evidence rather than treating checklist completion as implied by source inspection.
Functional tests¶
- List accessible projects.
- Search issues by project.
- Search issues by status.
- Retrieve an issue by key.
- Handle invalid issue keys and inaccessible issues.
- Handle empty project and issue results.
- Verify default-project behavior.
- Verify result limits and pagination behavior.
- Handle expired tokens, revoked access, rate limits, and provider outages.
- Verify that errors and logs do not expose secrets or unnecessary issue content.
Authorization tests¶
- An unconnected user cannot access Jira through the user-specific OAuth path.
- One user cannot use another user's token or cached results.
- Only approved read tools are executable in the initial release.
-
create_issueis rejected before provider invocation. - Direct requests to
POST /jira/issueare blocked. - Alternate or legacy handlers cannot bypass per-user authorization.
- Denied operations leave Jira unchanged.
OAuth tests¶
- Invalid or expired application JWTs fail safely.
- OAuth state is validated and cannot be reused.
- Tokens and cloud ID metadata are associated with the correct user.
- Access-token refresh works and refreshed credentials persist.
- Revoked and insufficient-scope credentials fail safely.
- Disconnecting Jira prevents subsequent access.
- Sensitive credentials are not exposed in URLs or logs.
Release acceptance criteria¶
The integration should not be marked ready until the following are evidenced:
- Approved read operations work with the intended Jira permissions.
- OAuth state validation and user-specific token isolation pass testing.
- Requested and granted scopes match the approved security policy.
- Cache isolation and disconnect behavior are verified.
- Every reachable write path is blocked during read-only operation.
- Logs and error responses meet the application's data-handling requirements.
- Tests are repeatable and their results are recorded for the release.
11. Source references¶
Use these files when investigating or updating the integration:
| File | Review focus |
|---|---|
chat/package/app/plugins/jira/plugin.py |
Tool definitions, categories, intent routing, and plugin execution |
integrations/package/app/handlers/integration_handlers.py |
OAuth flow, token resolution, and project/issue routes |
integrations/package/app/managers/jira_client.py |
Jira Cloud REST API v3 calls and authentication modes |
integrations/package/app/handlers/jira_handlers.py |
Alternate handlers and potential authorization bypasses |
chat/package/app/plugins/registry.py |
Tool registration, dispatch, and permission checks |
chat/package/app/plugins/permissions.py |
Default tool-category permissions |
12. Readiness decision¶
Current assessment: not yet verified as production-ready for a strictly read-only release.
The source includes issue creation, requests write:jira-work, and exposes an issue-creation route. These capabilities must be removed, restricted, or otherwise proven unreachable under the approved release policy.
Production approval also depends on verified OAuth security, per-user credential isolation, cache isolation, route protection, and repeatable functional and authorization tests.
Documentation maintenance: Update this page whenever Jira tool definitions, OAuth scopes, authentication modes, API routes, caching behavior, or release permissions change. Keep implementation claims aligned with inspected source and recorded test evidence.