@anura-gate/watcher-jira 0.2.0 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +197 -0
  2. package/lib/oauth.js +1 -1
  3. package/package.json +1 -1
package/README.md ADDED
@@ -0,0 +1,197 @@
1
+ # GATE Watcher — Jira
2
+
3
+ Self-hosted daemon that monitors your Jira Cloud projects for issue updates, comments, and transitions, pushing them to GATE for security processing. **Your Jira credentials never leave your machine.**
4
+
5
+ ## How it works
6
+
7
+ ```
8
+ Your Machine (Watcher) GATE Cloud
9
+ ┌─────────────────────┐ ┌──────────────────┐
10
+ │ Jira API polling │───────>│ Security pipeline │
11
+ │ (creds stay HERE) │<───────│ (redact, policy, │
12
+ │ │ poll │ audit, forward) │
13
+ └─────────────────────┘ └──────────────────┘
14
+ ```
15
+
16
+ ## Quick Start (CLI)
17
+
18
+ ```bash
19
+ cd gate-watcher-jira
20
+ npm install
21
+
22
+ # Create .env (or pass env vars directly)
23
+ cp .env.example .env
24
+ # Fill in GATE_KEY, GATE_INTEGRATION_ID, and Jira credentials
25
+
26
+ npm start
27
+ ```
28
+
29
+ On first run with OAuth, the browser opens automatically — click **Allow**, and you're connected.
30
+
31
+ ## Auth Modes
32
+
33
+ ### OAuth 2.0 (recommended)
34
+
35
+ Browser-based authorization. No manual tokens or emails needed.
36
+
37
+ 1. Register an app at [developer.atlassian.com/console/myapps](https://developer.atlassian.com/console/myapps)
38
+ 2. Set callback URL to `http://localhost:*/callback`
39
+ 3. Enable scopes: `read:jira-work`, `write:jira-work`, `read:jira-user`, `offline_access`
40
+ 4. Set `JIRA_CLIENT_ID` and `JIRA_CLIENT_SECRET` in `.env`
41
+ 5. Run the watcher — browser opens, click Allow, done
42
+
43
+ Tokens are stored in `~/.gate/jira-oauth.json` and auto-refresh. Use `--auth` to re-authorize or `--logout` to clear stored tokens.
44
+
45
+ ### API Token (headless / CI)
46
+
47
+ For environments without a browser.
48
+
49
+ 1. Create an API token at [id.atlassian.com/manage-profile/security/api-tokens](https://id.atlassian.com/manage-profile/security/api-tokens)
50
+ 2. Set `JIRA_DOMAIN`, `JIRA_EMAIL`, and `JIRA_TOKEN` in `.env`
51
+
52
+ ## Embed in Your App (SDK)
53
+
54
+ ```bash
55
+ npm install @anura-gate/watcher-jira
56
+ ```
57
+
58
+ ### With OAuth
59
+
60
+ ```js
61
+ const { GateJiraWatcher } = require("@anura-gate/watcher-jira");
62
+
63
+ const watcher = new GateJiraWatcher({
64
+ gateKey: "gk-xxx",
65
+ integrationId: "int_xxx",
66
+ oauth: {
67
+ accessToken: "eyJ...",
68
+ cloudId: "abcd-1234-...",
69
+ siteUrl: "https://yourcompany.atlassian.net",
70
+ },
71
+ projects: ["PROJ", "ENG"], // optional — omit to watch all projects
72
+ });
73
+
74
+ await watcher.start();
75
+ ```
76
+
77
+ ### With API Token
78
+
79
+ ```js
80
+ const watcher = new GateJiraWatcher({
81
+ gateKey: "gk-xxx",
82
+ integrationId: "int_xxx",
83
+ jiraDomain: "yourcompany.atlassian.net",
84
+ jiraEmail: "you@company.com",
85
+ jiraToken: "ATATT3x...",
86
+ projects: ["PROJ", "ENG"],
87
+ });
88
+
89
+ await watcher.start();
90
+ ```
91
+
92
+ ### Listening to Events
93
+
94
+ ```js
95
+ watcher.on("ready", (displayName) => {
96
+ console.log(`Jira connected: ${displayName}`);
97
+ });
98
+
99
+ watcher.on("event", (event, result) => {
100
+ console.log(`Event: ${event.eventType}, Issue: ${event.content.metadata.issueKey}`);
101
+ console.log(`Security actions: ${result.securityActions}`);
102
+ });
103
+
104
+ watcher.on("action_result", ({ action, success, error }) => {
105
+ console.log(`${action}: ${success ? "done" : error}`);
106
+ });
107
+
108
+ // Later...
109
+ await watcher.stop();
110
+ ```
111
+
112
+ ## Detected Events
113
+
114
+ | Event Type | Trigger |
115
+ |---|---|
116
+ | `issue_transitioned` | Status changed (e.g. To Do → In Progress) |
117
+ | `issue_assigned` | Assignee changed |
118
+ | `issue_resolved` | Resolution set (Done, Won't Fix, etc.) |
119
+ | `comment_added` | New comment on an issue |
120
+ | `priority_changed` | Priority changed |
121
+ | `labels_changed` | Labels added or removed |
122
+ | `sprint_changed` | Issue moved to a different sprint |
123
+ | `issue_updated` | Summary, description, or other field changed |
124
+
125
+ ## Outbound Actions
126
+
127
+ GATE can queue actions for the watcher to execute locally:
128
+
129
+ | Action | Required Params | Optional Params |
130
+ |---|---|---|
131
+ | `create_issue` | `project`, `summary` | `description`, `issueType`, `assignee`, `priority`, `labels` |
132
+ | `add_comment` | `issueKey`, `body` | — |
133
+ | `transition_issue` | `issueKey`, `transition` | — |
134
+ | `assign_issue` | `issueKey` | `accountId` (null = unassign) |
135
+ | `update_issue` | `issueKey` | `summary`, `description`, `priority`, `labels` |
136
+
137
+ ## SDK Events
138
+
139
+ | Event | Args | Description |
140
+ |---|---|---|
141
+ | `ready` | `(displayName)` | Connected to Jira |
142
+ | `event` | `(event, result)` | Jira event processed by GATE |
143
+ | `action` | `(action)` | Outbound action received from GATE queue |
144
+ | `action_result` | `({ actionId, action, success, result, error })` | Outbound action completed |
145
+ | `gate_error` | `({ path, status, error })` | GATE API call failed |
146
+ | `jira_error` | `({ path, error })` | Jira API call failed |
147
+ | `limit_reached` | `(type)` | Plan limit hit |
148
+ | `stopped` | — | Watcher fully shut down |
149
+
150
+ ## SDK Options
151
+
152
+ | Option | Required | Default | Description |
153
+ |---|---|---|---|
154
+ | `gateKey` | Yes | — | Virtual key (`gk-xxx`) |
155
+ | `integrationId` | Yes | — | Integration ID (`int_xxx`) |
156
+ | `oauth` | * | — | OAuth credentials (`{ accessToken, cloudId, siteUrl }`) |
157
+ | `jiraDomain` | * | — | Jira Cloud domain (`yourcompany.atlassian.net`) |
158
+ | `jiraEmail` | * | — | Atlassian account email |
159
+ | `jiraToken` | * | — | Jira API token |
160
+ | `gateUrl` | No | `"https://anuragate.com"` | GATE cloud URL |
161
+ | `projects` | No | `[]` | Project keys to watch. Empty = all |
162
+ | `pollInterval` | No | `30000` | ms between Jira API polls |
163
+ | `heartbeatInterval` | No | `30000` | ms between heartbeats |
164
+ | `sessionId` | No | — | Session ID for multi-tenant use |
165
+ | `sessionLabel` | No | — | Human-readable session label |
166
+ | `sessionMetadata` | No | `{}` | Arbitrary metadata for the session |
167
+
168
+ \* Either `oauth` or all three of `jiraDomain` + `jiraEmail` + `jiraToken` are required.
169
+
170
+ ## Environment Variables
171
+
172
+ | Variable | Required | Description |
173
+ |---|---|---|
174
+ | `GATE_KEY` | Yes | Your GATE virtual key |
175
+ | `GATE_INTEGRATION_ID` | Yes | Integration ID from the dashboard |
176
+ | `JIRA_CLIENT_ID` | OAuth | Atlassian OAuth app client ID |
177
+ | `JIRA_CLIENT_SECRET` | OAuth | Atlassian OAuth app client secret |
178
+ | `JIRA_DOMAIN` | API Token | Jira Cloud domain (`yourcompany.atlassian.net`) |
179
+ | `JIRA_EMAIL` | API Token | Atlassian account email |
180
+ | `JIRA_TOKEN` | API Token | Jira API token |
181
+ | `JIRA_PROJECTS` | No | Comma-separated project keys: `PROJ,ENG` |
182
+ | `GATE_URL` | No | Custom GATE cloud URL |
183
+ | `WEB_PORT` | No | Port for the dev dashboard (CLI only) |
184
+
185
+ ## CLI Flags
186
+
187
+ | Flag | Description |
188
+ |---|---|
189
+ | `--auth` | Force re-authorization (discard stored OAuth tokens) |
190
+ | `--logout` | Clear stored OAuth tokens and exit |
191
+
192
+ ## Security Model
193
+
194
+ - Jira credentials stored locally on YOUR machine (`.env` or `~/.gate/jira-oauth.json`)
195
+ - GATE cloud never sees or stores your Jira credentials
196
+ - All event content passes through GATE's security pipeline (redaction, policies, audit)
197
+ - Billing, limits, and security enforced server-side
package/lib/oauth.js CHANGED
@@ -53,7 +53,7 @@ const TOKEN_FILE = path.join(TOKEN_DIR, "jira-oauth.json");
53
53
  * @param {number} [opts.port] — Local callback port (0 = random)
54
54
  * @returns {Promise<OAuthResult>}
55
55
  */
56
- async function authorize({ clientId, clientSecret, port = 0 }) {
56
+ async function authorize({ clientId, clientSecret, port = 9876 }) {
57
57
  const state = crypto.randomBytes(16).toString("hex");
58
58
 
59
59
  // Start local server to receive the callback
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@anura-gate/watcher-jira",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "GATE Watcher — Self-hosted Jira event monitor with OAuth 2.0. Credentials never leave your machine.",
5
5
  "main": "index.js",
6
6
  "bin": {