# @stravica-ai/engineering-pa-core-extensions-atlassian

Atlassian (Jira, Confluence) CLIs and library surface, promoted into core
for the alpha solo scaffold. Common-use tools ship with the platform; the
personal workspace pages colleagues build on top ship as extensions.

## Bins

Wrapped by `@stravica-ai/digital-operator-pa` and installed on `PATH` when
that package is installed:

- `jira` - Jira REST v3 CLI. Verbs: `auth`, `mine`, `search`, `issue`,
  `create`, `update`, `attach`, `transition`, `advance`, `cancel`,
  `comment`, `worklog`, `projects`, `boards`, `sprint`, `link`,
  `sync-statuses`, `bulk-transition`, `test`.
- `confluence` - Confluence Cloud CLI (v1 CQL search, v2 page CRUD).
  Verbs: `auth`, `spaces`, `pages`, `page`, `search`, `create`, `update`,
  `comment`, `label`, `tree`, `recent`, `mine`, `mirror-folder`,
  `mirror-page`, `test`.
- `confluence-fetch` - convenience wrapper: search + fetch + save a page
  to `operator/notes/` and open the workspace viewer.

Run `jira --help`, `confluence --help`, `confluence-fetch --help` for the
full verb list; each verb has its own `--help`.

## Auth

Both CLIs read three credentials from the environment first, else from the
platform `secrets` bin. The keys are shared because Jira and Confluence
target the same Atlassian site:

- `JIRA_DOMAIN` - subdomain of `atlassian.net` (`foo` for `foo.atlassian.net`)
- `JIRA_EMAIL` - your Atlassian account email
- `JIRA_API_TOKEN` - a token from `https://id.atlassian.com/manage-profile/security/api-tokens`

Two-step colleague setup, after installing `@stravica-ai/digital-operator-pa`:

```
secrets set JIRA_DOMAIN yoursite
secrets set JIRA_EMAIL   you@example.com
secrets set JIRA_API_TOKEN <paste-token>
```

Resolution order for each key:

1. Environment variable of the same name (`JIRA_DOMAIN`, ...).
2. `secrets get <prefix>JIRA_DOMAIN` (etc.), where `<prefix>` comes from
   `ATLASSIAN_SECRETS_PREFIX` (e.g. an org slug like `acme/` picks the `acme` vault scope in
   an operator estate; empty by default so a solo colleague's single scope
   just works).

The tool never prints or logs the values; child-process reads use
`stdio: ['ignore', 'pipe', 'pipe']`.

## Configuration

- `config/jira-workflow-chains.default.json` - shipped empty. `jira advance
  <KEY> <STATUS>` walks a per-site chain of statuses; override by writing
  `operator/config/jira-workflow-chains.json` in your workspace root.
- `operator/config/jira-status-mappings.json` - per-project status mapping
  used by `jira sync-statuses`; not shipped by default.
- `JIRA_DEFAULT_PROJECT` (optional, env or vault key of the same name) -
  when set, `jira mine` narrows to that project unless `--project KEY`
  or `--all` is passed. With nothing configured, `jira mine` returns
  issues across every project the account can see.

## Library surface

```js
import {
  createJiraClient,
  createConfluenceClient,
  storageToMarkdown,
} from '@stravica-ai/digital-operator-pa/dist/engineering-pa-core-extensions-atlassian/index.mjs';

const jira = createJiraClient();
const { data } = await jira.get('/rest/api/3/myself');
```

For tests, inject a stub credential resolver rather than the vault:

```js
const client = createJiraClient({
  domain: 'yoursite',
  email:  'you@example.com',
  apiToken: 'test-token',
  fetchFn: mockFetch,
});
```

## Workspace hook

`jira` writes POST to `http://127.0.0.1:<workspacePort>/__api/jira/invalidate`
after mutating verbs, so a workspace page can refresh cached data on
change. The endpoint is a workspace-extension concern; the CLI treats a
timeout or refused connection as fine (the write succeeded regardless).
