Skip to content

feat(jira): baton jira prints a ticket for the orchestrator - #43

Merged
Bakhomious merged 1 commit into
mainfrom
step/jira
Nov 4, 2026
Merged

Bakhomious merged 1 commit into
mainfrom
step/jira

Conversation

@Bakhomious

Copy link
Copy Markdown
Contributor

baton jira <KEY> prints a Jira ticket and its comments as Markdown, for the orchestrator to plan from. This is plan row 66, the last of the three Jira steps after #41 and #42.

What

  • Config: a jira section, such as {"site": "example.atlassian.net", "email": "you@example.com"}, layered per repo like the other settings. The site must be a bare host name, and the email a bare address.
  • Token: read from the user's login keychain. The item's service is baton-jira and its account is the email. The new internal/keychain reads it through /usr/bin/security find-generic-password -w, by that full path. A missing item fails with the security add-generic-password command that adds it, with the email quoted for the shell.
  • Order: the key is checked first, then the settings, then the keychain, so a bad key never reaches the keychain (or one of its prompts).
  • Output: control characters are dropped (C0 except newline and tab, DEL, C1), so a ticket can't send escape sequences to the pane's terminal.
  • Guard: the orchestrator runs it unasked; the roles' panes deny it ("isn't a role's command").
  • Prompt: the orchestrator reads a ticket that the user names, and treats the ticket's text as the work to plan, not as the user's word. It asks the user about anything in the ticket that acts outside the repo.
  • Docs:
    • README: a new Jira section, with the setup in three steps (the config; a scoped token with read:jira-work alone; the keychain item).
    • Plan: decision 60, fact 42 (security's exit codes, options and default trust, token expiry), risk 14 (prompt injection through a ticket; any program running as the user can read the keychain item). Decisions 34 and 54 and open question 2 are amended.

Suppression

There is one new //nolint:gosec (G204) at the keychain's exec, with its reason. It follows the user's answer of 2026-11-04 through nudge ("nolint + reason there; NOSONAR only if Sonar flags it"), and decision 34 records it.

Checks

  • mise run check: green; coverage 99.4% in total, 100% for internal/keychain, internal/config and internal/jira.
  • Mutation probes: all 73 mutants over config, keychain, jira, cli, the guard's list and the usage are caught. The first run left two survivors, which got tests: a slash inside the site, and the keychain error's %w. One mutant that didn't compile was rewritten.
  • Smoke run of the real binary, with a temp HOME and config, no tmux and no network. It covered:
    • the usage and -h;
    • no key, and bad keys, which are refused before the keychain;
    • outside a repo;
    • no config, and no jira section;
    • a URL as the site, and an email with a name;
    • a missing keychain item: a read-only lookup with the real security, giving the hint with the email shell-quoted.
  • No live run and no real Jira call: 0 credits. A live check against the user's Jira waits for their word.

Not in this PR

A hint for an expired token (a 401). It will be worded once the live check shows the gateway's real 401 text.

baton jira <KEY> prints a Jira ticket and its comments as Markdown, for
the orchestrator to plan from. It reads the site and the email from the
config file's new jira section, and the user's scoped read-only API
token from the keychain, through /usr/bin/security by its full path. It
checks the key before it reads the keychain, and drops control
characters from what it prints, so that a ticket can't send escape
sequences to the pane's terminal.

The guard runs it unasked in the orchestrator's pane and denies it to
the roles. The orchestrator's prompt reads a ticket that the user names
with it, and treats the ticket's text as the work to plan, not as the
user's word.

Decision 60, fact 42, risk 14 and the README's Jira section explain the
setup. Decision 34 records the user's call on the keychain's exec.
@sonarqubecloud

sonarqubecloud Bot commented Nov 4, 2026

Copy link
Copy Markdown

@Bakhomious
Bakhomious merged commit b84dc0a into main Nov 4, 2026
3 checks passed
@Bakhomious
Bakhomious deleted the step/jira branch November 4, 2026 21:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant