Skip to main content
Version: v5.6.1

13.2 Jira Service Management

integrations:jira-service-management

After this you can: register a JSM connection, take tickets as triggers, bind changes to tickets, write back through the audited door and resolve with evidence.

Before you start — tick each one:

  • Lesson 5.2 — Triggers (opschain learn 5.2)

In the GUI: the ticket shows as a typed external reference on the bound change — on its Reviews & approvals inbox row and in its governance block — and every JSM write is a row on the Operations area's Activity panel; the connection is administered from the CLI.

Jira Service Management holds the ticket; OpsChain executes and governs the change — and proves it. The integration binds the two: tickets become typed references on governed changes, ticket events become triggers, every OpsChain-side JSM write goes through one audited door, and a request resolved via OpsChain closes with the evidence links attached. This lesson takes one ticket, SUP-123, from arrival to resolution. The guide opschain docs getting-started/integrations-jsm is the day-to-day reference; the component reference is opschain docs integrations-jsm.

Licence entitlement. The server side is gated on integrations:jira-service-management. Binding a ticket as a typed reference on a change (lesson 10.1's governance block) is base — the gate is on the connection, the ingestion and the write door.

You need an Atlassian cloud site (an account email plus API token) or a Jira Data Center instance (a personal access token), admin rights on the OpsChain server, and a service account for the firings to run as (opschain admin service-accounts create jsm-bot, lesson 7.3).

1. Register the connection​

An Atlassian cloud site authenticates as an account (email + API token); Jira Data Center uses a personal access token as a bearer (omit --auth-email). The token never rides the command line and no read ever returns it:

JSM_TOKEN=... opschain admin jsm-connections create limepoint-jsm \
--base-url https://yoursite.atlassian.net \
--auth-email support-bot@example.com \
--project-keys SUP \
--api-token-env JSM_TOKEN
Created JSM connection limepoint-jsm for https://yoursite.atlassian.net (api_token_ref secret-vault://jsm-connections/limepoint-jsm/credential)
opschain admin jsm-connections test limepoint-jsm
JSM connection limepoint-jsm: record validation succeeded

--project-keys scopes the connection: a write to a request outside those projects refuses by name. test validates the record without calling JSM.

2. Events in — tickets as triggers​

Provision webhook ingestion on the signed inbound lane and point the Jira webhook (issue created/updated, comment created) at the printed path:

opschain admin jsm-connections provision-webhook limepoint-jsm --service-account jsm-bot
Provisioned Jira webhook ingestion for limepoint-jsm as inbound connection jsm-limepoint-jsm
Point the Jira webhook at <server URL>/api/hooks/jsm-limepoint-jsm
Signing secret (shown ONCE - configure it as the Jira webhook secret): 3f9c…

Jira Data Center signs natively — configure the shown secret as the webhook secret and Jira sends a sha256 X-Hub-Signature. Each accepted delivery lands one external:webhook:received event with typed fields under event.data.jira (key, project, status, summary, priority, labels, comment id), so a trigger reacts to, say, every new support request:

# triage_new_request.yaml
code: triage_new_request
subject: external
events: [external:webhook:received]
conditions:
- event.data.jira.event eq jira:issue_created
- event.data.jira.project eq SUP
action_type: workflow_run
action_params:
workflow: triage
inputs:
request_key: ${{ event.data.jira.key }}
opschain triggers create support -f triage_new_request.yaml

Every firing executes as the connection's service account — never with ambient authority (the rule lesson 5.3 set for the generic lane).

3. Bind the change to the ticket​

A governed change carries the ticket as a typed reference on its governance metadata block (lesson 10.1):

opschain approvals set-metadata <run-id> --ref jsm:request:SUP-123
governance block updated on 01a2fb10-… — owner jessica, category normal, 1 external reference(s)
opschain admin jsm-requests links --request SUP-123
REQUEST SYSTEM RELATIONSHIP RUN KIND TARGET
SUP-123 jsm - 01a2fb10-… change /projects/demo/environments/prod

links answers the other direction — which OpsChain subjects carry this ticket — filtered to the subjects you may read. Approval policies with require_change_reference count these references, so "no change without a ticket" works for Atlassian shops out of the box.

4. Write back through the audited door​

All OpsChain-side JSM writes go through one entitlement-gated, project-scoped, evented door:

opschain admin jsm-requests comment SUP-123 --body "Change scheduled for tonight's window."
Posted internal comment 10042 on SUP-123
opschain admin jsm-requests transition SUP-123 "In Progress"
opschain admin jsm-requests set-fields SUP-123 --add-label opschain
Updated fields on SUP-123

Comments are always JSM internal notes — there is deliberately no customer-visible-comment capability on this surface, so drafted customer replies stay internal until a human posts them as themselves. An unknown transition refuses by name and lists what is available.

5. Resolve with evidence​

When the change lands, close the ticket with the proof attached:

opschain admin jsm-requests resolve SUP-123 \
--run <run-id> --transition Resolve \
--evidence-url https://opschain.example/changes/<run-id>
Resolved SUP-123 via 01a2fb10-… (Resolve) — typed reference recorded, evidence comment 10043 posted

One audited write records the jsm:request reference (relationship resolves) on the change's governance block, posts the internal evidence comment, and performs the resolving transition. The OpsChain ledger stays the source of truth; JSM holds a copy with provenance. Read the story back:

opschain events --type-search jsm --tail 4
WHEN ID TYPE NODE USER CORRELATION DETAIL
2026-10-27T13:10:02.118440Z 01a2fb20-… info:jsm:internal_comment - admin 01a2fb20-… SUP-123 · comment 10042 (41 chars)
2026-10-27T13:10:40.902113Z 01a2fb21-… info:jsm:transition - admin 01a2fb21-… SUP-123 · In Progress
2026-10-27T13:11:05.337208Z 01a2fb22-… info:jsm:fields - admin 01a2fb22-… SUP-123 · labels
2026-10-27T14:02:51.771004Z 01a2fb30-… info:jsm:resolution /projects/demo/environments/prod admin 01a2fb10-… SUP-123 · Resolve · comment 10043

Note what is not there: a comment event carries the comment id and length, never the note's content; a fields event carries field names, never values.

6. When something refuses​

Everything refuses by name: the missing entitlement, the project scope, a disabled connection, an unknown transition (listing what is available), an unresolvable credential. Every write and every refusal that matters is on the event stream — opschain events --type-search jsm tells the story.

Check yourself​

  • What may OpsChain post onto a ticket — internal notes, customer-visible comments, or both? Then: what three things does one resolve write do, and which relationship does the recorded reference carry?

What you learned​

  • A JSM connection vaults its token, is scoped to project keys, and serves a signed inbound lane whose firings run as a service account.
  • A ticket is a typed jsm:request reference on a change's governance block, countable by require_change_reference policies.
  • Every OpsChain-side write goes through one audited door — internal notes only — and resolve records the reference, posts the evidence comment and transitions the request in one write.

Next: lesson 13.3 — SIEM export (opschain learn 13.3), or back to your track (opschain learn).