Three read-only Node.js tools that answer the question every Atlassian migration eventually has to answer out loud — did everything actually arrive?
A migration report tells you what the migration believes it did. It is generated by the same process that did the work, from the same assumptions — which makes it the one source that cannot independently confirm anything.
If the assumption that produced a defect is the same assumption used to check for it, the check passes. That is not dishonesty on the tool's part — it is a structural limit. The questions that matter have to be asked from outside.
If an issue security level hides a project's issues from the auditing account, the audit reports nothing missing and reads as good news. "This project is empty" and "my account cannot see this project" produce identical output.
A renamed priority quietly empties a filter. A missing link type makes every link restore fail. An issue-type scheme that differs by one type breaks every board built on it. All cheap to check in advance, all expensive to find after cutover.
Three tools, each answering one question, each producing a spreadsheet you can hand to a client. Nothing here writes to Jira — the remedy is always a separate, deliberate decision.
Compares by issue key across both instances and produces an .xlsx with one tab per affected project plus a summary. Supports label-based key remapping, so an issue recreated under a new key is not reported as missing.
Matches by name and emits a two-sheet workbook — the DC-to-Cloud field map, and the DC fields with no Cloud equivalent, each with a reason. Run it before the migration to predict, and after to confirm.
Compares issue types and schemes, link types, priority schemes and priorities, issue hierarchy, sprint and board configuration, and time-tracking settings between two Cloud instances, and reports every difference.
The same operating model throughout, deliberately — so that knowing one tool means knowing all of them.
An audit that could write is an audit whose findings you have to second-guess. These tools read two instances and produce a workbook. Every remedy lives in a sibling repository, behind its own deliberate decision.
Before a zero becomes a finding, prove the credentials can see that project's issues at all — on that same project. Permission and issue-security filters are per object, so a positive control somewhere else proves nothing.
One tab per affected project, written only where the count is non-zero, plus a summary. The workbook is the evidence: anyone can open it and redo the arithmetic without taking your word for anything.
Every difference the comparator finds is one you would rather fix while the target is still empty. Running it after the data migration tells you why something broke; running it first stops it breaking.
git clone https://github.com/leanzero-srl/leanzero-atlassian-migration-audit-toolkit.git cd leanzero-atlassian-migration-audit-toolkit/find_missing_issues npm install cp .env.example .env # DC_BASE_URL, DC_PAT, CLOUD_BASE_URL, CLOUD_API_TOKEN node main/find_missing_issues.js
Every question this repository raises, answered in order: what it reads and what it changes, why the migration's own report cannot answer this, why an empty result is not proof, what each of the three audits covers, and how to present the findings without overstating them. 17 sections.
Node 18 or newer, read access to both instances, and one shared .env. Nothing in this repository writes to Jira — every tool reads two instances and produces a spreadsheet.
DC_BASE_URL=https://jira-dc.example.com
DC_PAT=your-personal-access-token # or DC_USERNAME + DC_PASSWORD
CLOUD_BASE_URL=https://your-site.atlassian.net
CLOUD_API_TOKEN=base64-of-email-colon-apitokengit clone https://github.com/leanzero-srl/leanzero-atlassian-migration-audit-toolkit.git
cd leanzero-atlassian-migration-audit-toolkit/find_missing_issues
npm install
cp .env.example .env
node main/find_missing_issues.jscustomfield_10001-style stand-ins, not live ids, and they will not match your instance — resolve yours with GET /rest/api/2/field. For the fields a create screen requires but createmeta hides, probe_required_fields.js discovers them empirically: it attempts a create, reads each "Field X is required" error, supplies a synthesized value, retries until the create succeeds, then deletes the probe issue.Because that report is generated by the process that did the work, from the same assumptions. It is the one source that cannot independently confirm anything.
A migration report tells you what the migration believes it did. If the assumption that produced a defect is the same assumption used to check for it, the check passes. That is not dishonesty on the tool's part — it is a structural limit of self-verification.
Only after you have proved your credentials can see the project's issues at all. "This project is empty" and "my account cannot see this project's issues" produce identical output.
Stated up front, because discovering a limit mid-cutover is the expensive way to find it.
The toolkit is free and Apache-2.0. If you need the audit run, the findings defended in front of a stakeholder, or the gaps closed afterwards, that is what we do.