Skip to main content
Your progress
0 of 5 complete0%
T3 / M3.9 / L4 OF 4 / Engineer LEVEL / 9 min

Bi-directional sync

Outcome

By the end of this lesson, you will be able to trace status and ownership changes in both directions, explain how the loop guard prevents ping-pong, and name the deferred limits.


PrerequisitesM3.9.L3
Time9 minutes

1. Concept

Recommendation status and Jira issue status stay in agreement automatically, and it is event-driven, with a 10-minute reconcile sweep as a safety net for the outbound direction.

Outbound: ZopNight to Jira

Terminal window
The recommender emits a status-changed event at its
transition chokepoints. The provisioner transitions or
comments the Jira issue.
closed / dismissed / optimised -> Done
applied / observing -> In Progress
open (re-opened) -> To Do, plus a
"Reopened in ZopNight" comment
drifted -> a COMMENT

The drifted case is deliberately a comment rather than a transition. Drift means the finding came back, and forcing an issue backwards through a workflow is presumptuous: the comment tells the assignee and lets them decide.

Inbound: Jira to ZopNight

Terminal window
A durable Jira admin webhook, HMAC-verified per
integration, with retries deduplicated on Atlassian's
own delivery identifier.
The org and recommendation are resolved by the
GLOBALLY-UNIQUE FINGERPRINT LABEL (L2).
It publishes an event; the recommender applies the
target status through its state machine.
ILLEGAL TRANSITIONS ARE DROPPED, NEVER FORCED.

That last line preserves an invariant from T2.M2.13: the recommender remains the sole writer of recommendation status. Jira can request a transition; it cannot impose one that the state machine does not permit.

The loop guard

Two systems that write to each other will ping-pong unless something stops them.

Terminal window
ZopNight sets status -> pushes to Jira -> Jira emits a
change event -> ZopNight receives it -> sets status ->
pushes to Jira -> ...
THE GUARD keys on the link's LOCALE-INDEPENDENT NEUTRAL
STATUS CATEGORY plus the LAST-PUSHED recommendation
status.
So an inbound event that merely reflects what we just
pushed is recognised and dropped.

The locale-independent part is worth noticing. Jira status names are localised, so a guard comparing display strings would break on a Jira instance running in another language. Comparing the neutral category rather than the label is what makes it work anywhere.

The whole thing is idempotent under at-least-once delivery, which it needs to be: Jira retries webhooks, and the dedup on the delivery identifier plus the loop guard together make reprocessing harmless.

Ownership sync, both directions

Terminal window
ZOPNIGHT -> JIRA
Set an owner on a recommendation, and it updates the
ticket link and RE-ASSIGNS THE SAME ISSUE.
It NEVER MINTS A NEW TICKET.
JIRA -> ZOPNIGHT
A Jira assignee change flows back onto the
recommendation's owner via the inbound webhook.
Prefers email; falls back to display name where
privacy settings hide the email; clears on unassign.
Both directions are loop-guarded.

The “never mints a new ticket” guarantee matters: changing an owner is an update to an existing thing, and a system that created a second ticket on reassignment would double its own queue.

A deleted Jira issue

Terminal window
SOFT-DELETES THE LINK. THE RECOMMENDATION IS UNTOUCHED.

The right behaviour: someone deleting a ticket is saying something about their queue, not about your infrastructure. The finding remains open in ZopNight, where it belongs.

The deferred limits

Worth knowing so you do not design around something absent:

Terminal window
SEARCH-BEFORE-CREATE ONLY FINDS LABELLED ISSUES
Before creating, ZopNight searches Jira for an issue
carrying the fingerprint label and adopts it. A ticket
someone created by hand, without the label, is not
found.
THE RECONCILE SWEEP IS OUTBOUND ONLY
Every 10 minutes it re-pushes recommendation status
to Jira, healing a dropped outbound update. It does
not re-read Jira: if an inbound webhook is lost past
Jira's own retries, that change is not reconciled.
NO JIRA-REOPEN -> RECOMMENDATION-REOPEN
Reopening a Jira issue does not reopen the
recommendation.
NO ACTIVITY-EVENTS TABLE, and observability counters
are follow-ups.

The first and third are the ones that show up in practice.

Terminal window
SEARCH-BEFORE-CREATE looks for the fingerprint label, so
a hand-made ticket without it is invisible to dedup, and
automation can open a second one for the same problem.
If your team creates cost tickets by hand today, either
route them through the integration or accept some
overlap during transition.

2. Demo

A quarter of sync, including the two things that surprised people:

Terminal window
NORMAL FLOW
A rec is applied in ZopNight
-> Jira issue moves to In Progress
Verification later confirms adoption; rec closes
-> issue moves to Done
Nobody touched Jira. That is the point.
INBOUND, WORKING
An engineer closes the Jira issue as Done from their
queue.
-> webhook fires, HMAC verified
-> org and rec resolved from the fingerprint label
-> the recommender applies the status through its
state machine
No ping-pong. The loop guard recognised the subsequent
outbound push as reflecting what had just arrived.
SURPRISE 1: A LOCALISED JIRA
A subsidiary ran Jira in German. Status labels came
through localised.
Sync worked. The loop guard keys on the NEUTRAL
STATUS CATEGORY rather than the display label, which
is exactly the case that would have broken a
string-comparison guard.
SURPRISE 2: A REOPENED TICKET
An engineer reopened a Done issue, expecting the
recommendation to reopen too.
It did not. Jira-reopen to recommendation-reopen is
DEFERRED.
The right mental model: the recommender is the sole
writer of recommendation status, and it reopens a
finding when the RULE FIRES AGAIN, not when a human
reopens a ticket. Jira can request transitions the
state machine permits; it cannot substitute for
detection.
THE HAND-MADE TICKET OVERLAP
During transition, the team had 11 hand-made cost
tickets with no fingerprint label.
Auto-ticketing opened new tickets for 6 of those
problems, because dedup and search-before-create both
look for the fingerprint label.
Not a bug, and they had been told. They closed the 6
hand-made duplicates and routed everything through
the integration afterwards.
AN ASSIGNEE ROUND TRIP
Rec owner set in ZopNight -> the SAME issue
reassigned, no new ticket.
A week later the Jira assignee changed during a
handover -> the rec's owner updated to match.
Loop-guarded in both directions.

3. Hands-on (6 min)

Terminal window
1. Apply a recommendation that has a linked ticket.
Did the issue move to In Progress? Y / N
How long did it take? ______ seconds
(Event-driven, so seconds rather than a cron cycle.)
2. Close the Jira issue from Jira. Did the rec status
follow? Y / N
Any ping-pong? Y / N
3. Reopen that Jira issue. Did the rec reopen? Y / N
Explain why not, in one line:
______________________________________________
4. Count your hand-made cost tickets that predate the
integration: ______
Those carry no fingerprint label. What will you do?
[ ] close and re-route [ ] accept overlap
5. If you run Jira in a non-English locale, confirm sync
works: Y / N
(The guard uses the neutral category, not labels.)

4. Knowledge check

Q1

What prevents recommendation status and Jira status from ping-ponging endlessly?

A. A cooldown period after each push
B. Outbound sync is disabled the moment inbound sync becomes active, so only one direction is ever live at a time and a loop is impossible by construction in the design itself entirely
C. Jira suppresses webhook events triggered by API calls
D. A loop guard keyed on the link’s locale-independent neutral status category plus the last-pushed recommendation status, so an inbound event that merely reflects what was just pushed is recognised and dropped

Show answer

Correct: D. Using the neutral category rather than display labels is what keeps it working on a Jira instance in another language. The localisation detail is the one that would break a naive implementation: status names are localised, so a guard comparing display strings would fail on a non-English Jira.

Q2

An engineer reopens a Done Jira issue. The linked recommendation:

A. Does not. Jira-reopen to recommendation-reopen is deferred
B. Reopens automatically
C. Reopens after the next evaluation cycle
D. Reopens only if the rec was closed by sync rather than by verification

Show answer

Correct: A. The recommender is the sole writer of recommendation status and reopens a finding when the rule fires again, so Jira can request transitions the state machine permits but cannot substitute for detection. The same invariant explains why illegal transitions arriving from Jira are dropped rather than forced: an external system requests, and the state machine decides.

Q3

A team has hand-made cost tickets predating the integration. When auto-ticketing is enabled:

A. Those tickets are found and reused
B. The hand-made tickets are labelled retroactively
C. The integration refuses to open tickets in any project that already contains untagged issues created by hand previously
D. New tickets may be opened for the same problems, because dedup and search-before-create both look for the fingerprint label

Show answer

Correct: D. A hand-made ticket without the label is invisible to dedup. This is a known limit rather than a defect, and it is worth planning for: either route existing tickets through the integration or accept some overlap during the transition and close the duplicates.


5. Apply

Test the round trip once in each direction before relying on it: apply a recommendation and watch the issue move, then close the issue and watch the recommendation follow. Seeing both work is what lets you stop reconciling by hand.

Deal with hand-made tickets before enabling auto-ticketing, since they carry no fingerprint and will not deduplicate.



Start with the bill.

Foundations takes about five hours. The first lesson is nine minutes.

Free curriculum. No paywall. 290 lessons across 7 courses, plus an optional 24-lesson beginner course. Browse every course without an account; a free account opens the lessons, saves your progress and opens the exams for three publicly verifiable credentials. Read it on the train, take the exam on a Saturday, list the credential on your résumé Monday.

5h median time to finish Foundations
free account, every course, no paywall
3 certifications, each with a public verifier
Multi-cloud automation· Production-ready in 30 min· SOC 2 · ISO 27001· 20–60% off the bill, first month· 4 platforms · 1 console· Multi-cloud automation· Production-ready in 30 min· SOC 2 · ISO 27001· 20–60% off the bill, first month· 4 platforms · 1 console·