What’s New
Release notes for ajat, newest first.
Latest
Secrets and automation cost in the risk report
Available from v1.0.8. The risk report gains seven findings, four of them high severity, and the grade on most estates drops until they are worked through.
- Exposed secrets. Tokens in webhook URLs (Google Chat, Slack, any
key=ortoken=parameter), literalAuthorizationand webhook-token headers, and GitHub, AWS, Atlassian, Slack, and Google token shapes are flagged as high-severity findings. The finding says what kind of secret it is and where, never any part of it. On a real 654-rule export this found 175 rules; Jira’s--redact-sensitive-fieldsexport option had left every one of them in place. Reports now mask credentials in every piece of configuration they quote, including the workflow report’s comment bodies. - What drives automation cost, counted on enabled rules only: schedules firing more than once an hour (high) or hourly (medium); triggers that fire on almost any change (medium, or high in global and multi-project scope); scheduled searches and JQL branches with no time window (high); and lookups and web requests on every run (medium). High-frequency schedules is split into Sub-hourly (30 points) and Hourly (12), and a disabled rule on a five-minute schedule no longer scores.
- The scoring is explained from the scoring itself. The points legend and the list of enabled-only findings are generated from the same table the score uses, and reasons appear as one chip per finding, coloured by severity, beside every rule — in the top table and under each finding’s list. Searching for
secretorthrottledfinds the rules, not only the heading.
See Risk for every finding and its points, and the secrets sweep and automation cost review recipes.
Measured searches and execution history
Available from v1.0.8.
ajat export --probe-jqlcounts every scheduled search and JQL branch through Jira, scoped to the rule’s projects the way Jira runs it, and writes the counts beside each rule. The risk report then flags searches over 1000 work items by their real size and stops flagging small ones: on a 654-rule estate, reading the JQL alone flagged nine searches; the probe cleared eight (0 to 46 work items) and confirmed one at 3,588. Off by default; one request per distinct search. See Probing search sizes.ajat audit-log importreads the CSV files Jira’s Automation audit-log page exports, andajat audit-log fetch(experimental) reads the last 15 days, or--daysup to 90, of the audit log itself. Both write per-rule execution statistics into the export, and the risk report gains Throttled runs (high), Runs without actions (medium), a flag for runs that touched 100 or more work items, and a Busiest rules table beside the risk score. On a real site, 85% of recent runs performed no action at all. The public API has no audit-log endpoint, sofetchuses the one Jira’s own page calls, which Atlassian can change;importuses nothing but Jira’s own export. See Rule Execution History.- Every report takes
--state all|enabled|disabled. The filter applies before anything is counted, so totals, charts, duplicate groups, and the risk grade all describe the subset, and the header says which.
Owners, actors, and the search that returned everything
Available from v1.0.8.
ajat search --ownertakes an account ID, an email address, or a display name; anything but an account ID is looked up in Jira and must match one person. The table gains State and Owner columns, and the JSON output carries each rule’s owner, actor, state, and labels.ajat search --authorand--scopereturned every rule. Both sent a field the Automation API does not recognise, and the API ignores what it does not recognise, so the filter was silently dropped. Both now send the fields Atlassian documents. The API cannot filter by the account a rule runs as, only by its owner, so--authoris a deprecated alias of--owner.ajat rule …selects by--owner(account ID, or the owner’s name or email from an enriched export) and--actor(the account a rule runs as).--authoralways matched the run-as account, which its name did not say; it keeps working as a deprecated alias of--actor, so a scripted bulk command selects exactly the rules it did before.
Reports: faces, links, and sortable tables
Available from v1.0.8.
- People have faces in every report.
ajat exportdownloads each resolved account’s picture into the account directory (about 4 KB per account;--avatars=falsekeeps the identities and skips the pictures), and every report embeds each picture once. The report is still one file that opens offline and fetches nothing from Atlassian.--remote-avatarsnow means “use Jira’s hosted images instead of the embedded ones”. Runajat exportonce to pick up the pictures for an existing backup. See Pictures and offline use. - Every rule opens in Jira. Open in Jira goes to the rule’s own page — under the project’s settings for a single-project rule, under the global automation page for the rest. The export records each project’s type and style in a new
.ajat_projects.json, which is what makes the path right for company-managed, team-managed, business, and service-management projects. Project chips show the project’s icon, the risk report’s Risk by project table links each project, and a JQL search on an inventory rule card links to that search in Jira. See Links into Jira. - Every report table sorts by its columns. Click a header to sort, click again to reverse. Columns sort by their real value — ”·” is zero, “3 d ago” by date, bars by their number, people by name, severity high to low — and sorting keeps your search. Wide tables scroll inside their section on a phone, and screen readers announce every table by name.
- Name your own services. A theme file can map hosts to names, such as
factorialhr.com: Factorial HR, and the inventory, risk, and workflow reports show the name wherever a rule calls that host or one of its subdomains. Integrations that are not well-known services are now shown by their domain. See Naming your own services. - The same things look the same everywhere. Disabled rules carry the Disabled badge in every list, every person is drawn by one component, “High-frequency” is now “Hourly or faster” and the cadence chart’s slices say what they hold, the label inventory lists projects rather than scope keys, counts above 999 have thousands separators, the Analytics panel starts collapsed outside the inventory, and printing opens every collapsed section first so the whole report prints.
Licenses: renewals and --force
Available from v1.0.8.
- Re-activating with a renewed key works. A renewed subscription keeps its key, but
ajat license activate --license-key <the same key>refused it with “license has expired” once the expiry had been seen locally, and so did every gated command. The command now asks the store and refreshes the installed license when the store reports the key active again, and says so when the store still reports it expired or cannot be reached. --forcedoes what its help promised with a key.ajat license activate --license-key <new-key> --forcereplaces an active license, releasing its seat first; before, the flag only applied to license files. See Runningactivateagain.
Fixes in v1.0.8
ajat importno longer treats identity sidecars as rules. The importer scanned the*.external-info.jsonfiles as rules, so a 654-rule export was read as 1308 and each sidecar was planned as an update of its own rule. Only rule files are imported now. If you ranajat importon an enriched export with an older release, check its plan or state file for failed updates.- Schedules use the method Jira actually runs, and cron schedules are measured, not guessed. Rules on the basic (RRULE) method that still carried a stale cron were described and scored from the cron; every-two-hours schedules such as
0 0 6-16/2 ? * MON-FRIand minute lists such as0,30are now read as the period they really have. - The “Scheduling load” insight counted the wrong rules, so a rule firing every 8 hours counted as “hourly or faster”; it now uses the same test the inventory’s card uses.
- Long non-English rule names no longer print broken characters in the search table.
- Highlighted insight cards were unreadable, printing left collapsed sections out, long risk headings squeezed their title, and the rule lists in the collision, consistency, and risk reports did not line up. All fixed.
Search and filters that match the way you look for things
Available from v1.0.7.
- Search matches words in any order.
kpi editfinds Edit and Check — Monitor and Modify KPI Value, and every word is highlighted. - Filter chips are grouped into State, Scope, and Traits, and a rule has to match one chip from each group you use. Picking Disabled and Scheduled shows the rules that are both, rather than either. The workflow report has chips and a result counter too, and the counter counts what the report is about: rules, duplicate groups, or findings.
- “Nothing matches” is stated, with one button to clear the search and all filters, and long lists are complete in the file with the tail behind a Show all button that opens when a search matches inside it.
- Reports open offline. People rendered as initials rather than as
<img>links to Atlassian’s CDN — around 1400 of them in a 654-rule inventory — which v1.0.8 replaced with pictures embedded from the export. Email addresses aremailto:links with a copy button, rule descriptions keep their line breaks, and there is no more theme flash. - Schedules that run every few hours are no longer called high-frequency: the interval is part of the arithmetic in the chips, the counts, the risk score, and the cadence chart. Jira’s own Quartz cron format (
0 0 9 ? * MON-FRI) is understood, so a schedule reads “every weekday at 09:00” instead of a raw field dump. - A CI/CD licence identifies itself as an ajat licence, the licensing guide names the plans customers can buy (Professional and Small Team), and the documentation no longer promises a Windows download.
Knowing when there is something to install
ajat doctor reports the newest release available to you, alongside the command that installs it; the check never fails the diagnosis and says “could not check” when offline. After an ordinary command, ajat also asks the update service at most once a day, waits at most two seconds, and prints a single line to stderr when a newer release exists. The notice stays out of your way: never in CI, never under sudo, never when stderr is not a terminal, and never after a command that needs no license. Turn it off with ajat config set update.notice false.
ajat update also keeps working when the store’s daily download limit is reached — each file may be downloaded ten times a day, and beyond that ajat fetches the same release from Climakers’ own storage.
Activation is steadier on Linux
License files are encrypted against a machine identifier, and on Linux that identifier now survives kernel and microcode updates and VM resizes. Licenses activated before this release keep working: a subscription license moves to the new identifier the first time it is opened, and a signed offline license keeps the identifier it was issued for. Nothing needs re-activating, and macOS is unaffected.
Updates from inside the tool
ajat update installs the newest release your license includes: it downloads it from Climakers, verifies its SHA-256 checksum and replaces the running binary. On macOS it installs the signed, notarized package and runs as sudo ajat update; on Linux it replaces the binary in place and never uses sudo. --check reports without changing anything. Signed offline (local) licenses update too, and after a subscription ends, releases published before the end date stay installable. Available from v1.0.4. See Updating ajat.
Reports
report workflowrenders every rule as a per-rule flow-diagram runbook — the shape of the automation estate as something a person can read and hand to an auditor. See Generate HTML Reports.- Per-rule SVG flow diagrams in the inventory, shown by default when a rule is expanded.
- Behavioural-duplicate detection in the collision report. Two rules that are written differently but do the same thing are now surfaced, not just literal name or trigger overlaps.
- The risk report explains its own scoring, and links each category-list rule through to the Jira automation it came from.
- People and projects deep-link into Jira, so a finding in a report is one click from the account or project it describes. Rules linked to the site’s automation rule list until v1.0.8, which opens each rule on its own page.
- Identity chips with status in member lists, and notification targets — emails and channels — surfaced directly in the report.
- The Analytics panel explains itself, and appears on the inventory, collision, consistency and risk reports. The workflow report is a per-rule runbook and deliberately carries no estate-level charts.
API failures tell you what to do about them
A rejected token used to surface as a bare HTTP status. Errors from the Jira and licensing APIs now carry a hint:
Error: resolve cloud id: GET https://acme.atlassian.net/rest/api/3/myself returned 401: {"message":"Unauthorized"}
Hint: Authentication failed — verify your jira.username and jira.api_tokenHints cover authentication (401), permissions (403), a wrong domain or resource (404), rate limiting (429) and Jira outages (5xx). An exhausted rate limit suggests lowering --workers rather than simply retrying, and a non-Cloud site is named explicitly.
Fixes
license activate --license-key <file>says which flag takes a file. Passing a license file to--license-keyanswered “invalid license key format: expected UUID v4”; it now explains that a license file is activated with--license-file, and prints the exact command.ajat updatesees a new release right away. Just after a release,updatecould report the previous version for several minutes because the update service answered from a cached copy. Installing, andupdate --check --force, now ask the service directly.
jira.automation_base_url was silently ignored by every command except
doctor. If you run against a private automation host, doctor reported a
healthy setup while export, import, invoke, search and every rule
subcommand kept talking to api.atlassian.com. The Jira client is now built
in one place, so every command reads the same configuration.
--debugproduced no output at all. It set the log level but left the destination at its default, which discards everything. It now logs to stderr unless--log-filesays otherwise, and stands the progress bar down so the two do not overwrite each other.- A broken
log.level,log.formator unwritablelog.fileblocked every command — including theconfigcommands that repair it, soajat config set log.level infocould not fix a badlog.level. Those commands now fall back to working settings for the run and name the key to change. - A global flag placed before an exempt command made it validate the configuration.
ajat --config-file broken.yaml config whereinspected--config-fileinstead ofconfigand refused to run, while the same command with the flag moved worked — which made theconfigcommands unusable for inspecting exactly the broken configuration you were trying to look at. - The progress bar could leave a goroutine rendering after it stopped, so the next command’s progress bar corrupted the previous one’s state. Stopping now waits for the renderer to return, which also removes a fixed 50 ms cost from every command that shows progress.
See also
- Generate HTML Reports — the five report types
- Export the Estate — backup and incremental export
- Configuration — credentials, hosts and logging