@cldmv/gh-broker 0.8.0 → 0.9.0

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 (92) hide show
  1. package/README.md +40 -10
  2. package/config.example.json +17 -1
  3. package/deploy/README.md +3 -2
  4. package/deploy/install.mjs +5 -3
  5. package/dist/index.mjs +4261 -1642
  6. package/dist/index.mjs.map +4 -4
  7. package/package.json +12 -2
  8. package/docs/TOOLS.md +0 -538
  9. package/docs/agent-user-model.md +0 -89
  10. package/docs/changelog/v0/v0.2.0.md +0 -26
  11. package/docs/changelog/v0/v0.2.1.md +0 -23
  12. package/docs/changelog/v0/v0.2.2.md +0 -23
  13. package/docs/changelog/v0/v0.2.3.md +0 -33
  14. package/docs/changelog/v0/v0.2.4.md +0 -25
  15. package/docs/changelog/v0/v0.2.5.md +0 -29
  16. package/docs/changelog/v0/v0.3.0.md +0 -84
  17. package/docs/changelog/v0/v0.3.1.md +0 -30
  18. package/docs/changelog/v0/v0.3.2.md +0 -24
  19. package/docs/changelog/v0/v0.3.3.md +0 -28
  20. package/docs/changelog/v0/v0.4.0.md +0 -58
  21. package/docs/changelog/v0/v0.4.1.md +0 -33
  22. package/docs/changelog/v0/v0.4.2.md +0 -45
  23. package/docs/changelog/v0/v0.5.0.md +0 -39
  24. package/docs/changelog/v0/v0.5.1.md +0 -28
  25. package/docs/changelog/v0/v0.6.0.md +0 -52
  26. package/docs/changelog/v0/v0.6.1.md +0 -48
  27. package/docs/changelog/v0/v0.7.0.md +0 -71
  28. package/docs/changelog/v0/v0.8.0.md +0 -115
  29. package/docs/deploy-architecture.md +0 -84
  30. package/src/appauth.ts +0 -56
  31. package/src/audit.ts +0 -34
  32. package/src/availability.ts +0 -42
  33. package/src/catalog.ts +0 -182
  34. package/src/config.ts +0 -157
  35. package/src/index.ts +0 -107
  36. package/src/paths.ts +0 -60
  37. package/src/router.ts +0 -299
  38. package/src/secrets.ts +0 -167
  39. package/src/server.ts +0 -91
  40. package/src/types.ts +0 -128
  41. package/src/upstream.ts +0 -85
  42. package/src/verbs/ghcr/archive.ts +0 -314
  43. package/src/verbs/ghcr/config.ts +0 -142
  44. package/src/verbs/ghcr/jobs.ts +0 -141
  45. package/src/verbs/ghcr/push.ts +0 -192
  46. package/src/verbs/ghcr/registry.ts +0 -275
  47. package/src/verbs/ghcr/tar.ts +0 -203
  48. package/src/verbs/ghcr_push.ts +0 -264
  49. package/src/verbs/issue_labels.ts +0 -329
  50. package/src/verbs/link_issue.ts +0 -84
  51. package/src/verbs/npm-registry.ts +0 -168
  52. package/src/verbs/npm-tarball.ts +0 -76
  53. package/src/verbs/npm_scaffold.ts +0 -325
  54. package/src/verbs/release-analysis.ts +0 -212
  55. package/src/verbs/repo-tier.ts +0 -90
  56. package/src/verbs/report_ci_status.ts +0 -358
  57. package/src/verbs/report_release_prs.ts +0 -238
  58. package/src/verbs/report_security_alerts.ts +0 -442
  59. package/src/verbs/report_unlabeled.ts +0 -194
  60. package/src/verbs/rest-client.ts +0 -181
  61. package/src/verbs/review_thread.ts +0 -138
  62. package/tests/appauth.test.vitest.mts +0 -76
  63. package/tests/audit.test.vitest.mts +0 -48
  64. package/tests/catalog.test.vitest.mts +0 -234
  65. package/tests/config-merge.test.vitest.mts +0 -325
  66. package/tests/config.test.vitest.mts +0 -388
  67. package/tests/credentials.test.vitest.mts +0 -127
  68. package/tests/ghcr-archive.test.vitest.mts +0 -439
  69. package/tests/ghcr-config.test.vitest.mts +0 -96
  70. package/tests/ghcr-push.test.vitest.mts +0 -526
  71. package/tests/ghcr-registry.test.vitest.mts +0 -206
  72. package/tests/helpers/ghcr-fixtures.mts +0 -373
  73. package/tests/install-args.test.vitest.mts +0 -152
  74. package/tests/issue-labels.test.vitest.mts +0 -362
  75. package/tests/npm-scaffold.test.vitest.mts +0 -479
  76. package/tests/npm-setup.test.vitest.mts +0 -196
  77. package/tests/paths.test.vitest.mts +0 -57
  78. package/tests/prompt.test.vitest.mts +0 -128
  79. package/tests/release-prs.test.vitest.mts +0 -247
  80. package/tests/rest-client.test.vitest.mts +0 -115
  81. package/tests/router.test.vitest.mts +0 -505
  82. package/tests/run-vitest.mjs +0 -51
  83. package/tests/secret-store.test.vitest.mts +0 -167
  84. package/tests/secrets.test.vitest.mts +0 -208
  85. package/tests/security-alerts.test.vitest.mts +0 -338
  86. package/tests/server.test.vitest.mts +0 -200
  87. package/tests/smoke.test.vitest.mts +0 -177
  88. package/tests/system.test.vitest.mts +0 -355
  89. package/tests/upstream.test.vitest.mts +0 -91
  90. package/tests/verb-helpers.test.vitest.mts +0 -377
  91. package/tests/verbs.test.vitest.mts +0 -624
  92. package/tsconfig.json +0 -21
package/README.md CHANGED
@@ -19,19 +19,19 @@ It runs as a dedicated `gh-broker` system user, holds a read-scoped and a write-
19
19
 
20
20
  ## ✨ What's New
21
21
 
22
- ### Latest: v0.8.0 (October 2026)
22
+ ### Latest: v0.9.0 (November 2026)
23
23
 
24
- - **`npm_scaffold`: new npm packages without a manual first publish.** The new write verb publishes a broker-built `0.0.0-stage` placeholder and registers the repo's publish workflow as its trusted publisher, so CI publishes the first real release through OIDC. The npm token has no 2FA bypass: each write takes a one-time password from the user, so it's two calls, and the verb refuses any package that already exists.
25
- - **`ghcr_push`: container image pushes without a registry token.** Push a `docker save` archive from a drop directory to an allowlisted `ghcr.io/<owner>/<image>` as a background job, follow it with `ghcr_push_status` and check it with `ghcr_tags`. Release tags are never overwritten, and the classic PAT stays with the broker.
26
- - **Optional credentials.** The npm and GHCR tokens can be skipped at install; their tools stay hidden until the token is stored. The installer also takes tokens via `--secret <cred-name>=<token>`.
27
- - [View full v0.8.0 Changelog](https://github.com/CLDMV/gh-broker/blob/master/docs/changelog/v0/v0.8.0.md)
24
+ - **Three report verbs for the release and fleet skills.** `report_alert_status` buckets each open Dependabot alert by where its fix stands (released but still open, fixed on `next`, open PR, closed PR, nothing). `report_release_changes` returns the PRs a release actually ships, grouped by changelog section, with the net `package.json` and dependency deltas. `report_dependents` finds every repo that declares an npm package, including dev-trunk repos on `dev`, and skips a `dev` that has fallen behind the default branch.
25
+ - **`ciVerbosity` on `list_pull_requests`.** The same opt-in CI detail as `pull_request_read`, across a whole PR list with one shared call budget.
26
+ - **Install from npm.** `sudo npx @cldmv/gh-broker <agent-user>` runs the installer from the prebuilt package. The tarball now ships only runtime files.
27
+ - [View full v0.9.0 Changelog](https://github.com/CLDMV/gh-broker/blob/master/docs/changelog/v0/v0.9.0.md)
28
28
 
29
29
  ### Recent Releases
30
30
 
31
+ - **v0.8.0** (November 2026) — `npm_scaffold` creates an npm package and its trusted publisher, `ghcr_push` pushes images without an agent-held token, and optional credentials hide their tools ([Changelog](https://github.com/CLDMV/gh-broker/blob/master/docs/changelog/v0/v0.8.0.md))
31
32
  - **v0.7.0** (October 2026) — `issue_labels` adds, removes or swaps single labels without replacing the set, and `issue_write` warns that its `labels` does ([Changelog](https://github.com/CLDMV/gh-broker/blob/master/docs/changelog/v0/v0.7.0.md))
32
33
  - **v0.6.1** (October 2026) — MCP SDK 1.32.0 (same-origin redirects only) and a refreshed vitest toolchain; no broker source changes ([Changelog](https://github.com/CLDMV/gh-broker/blob/master/docs/changelog/v0/v0.6.1.md))
33
34
  - **v0.6.0** (October 2026) — Compact per-repo roll-up, filters and flow tier for `report_security_alerts`, and release-readiness analysis for `report_release_prs` ([Changelog](https://github.com/CLDMV/gh-broker/blob/master/docs/changelog/v0/v0.6.0.md))
34
- - **v0.5.1** (October 2026) — The installer keeps the existing secrets backend instead of prompting on every upgrade ([Changelog](https://github.com/CLDMV/gh-broker/blob/master/docs/changelog/v0/v0.5.1.md))
35
35
 
36
36
  📚 For the complete version history, see the [docs/changelog/](https://github.com/CLDMV/gh-broker/tree/master/docs/changelog/) folder.
37
37
 
@@ -51,7 +51,7 @@ A tool not listed in `config.tools` is neither advertised nor executable. Adding
51
51
 
52
52
  ### 📊 **CI Visibility Without Per-Call Log Fetches**
53
53
 
54
- `report_ci_status` answers "does this PR have failing checks" at whatever detail level you ask for — counts only by default, escalating to which job failed, which step failed, and a tail of the failing job's actual log — paying for that detail only on runs that are genuinely failing. The same status can ride inline on a normal `pull_request_read` via an opt-in `ciVerbosity` parameter.
54
+ `report_ci_status` answers "does this PR have failing checks" at whatever detail level you ask for — counts only by default, escalating to which job failed, which step failed, and a tail of the failing job's actual log — paying for that detail only on runs that are genuinely failing. The same status can ride inline on a normal `pull_request_read` or `list_pull_requests` via an opt-in `ciVerbosity` parameter.
55
55
 
56
56
  ```json
57
57
  { "owner": "cldmv", "repo": "droidsock", "pull": 35, "verbosity": 2 }
@@ -91,12 +91,30 @@ npm only accepts a trusted publisher on a package that already exists, so every
91
91
 
92
92
  🛡️ **Full parameter reference: [docs/TOOLS.md](docs/TOOLS.md#report_security_alerts)**
93
93
 
94
+ ### 🩹 **Where Each Alert's Fix Stands**
95
+
96
+ `report_alert_status` puts every open Dependabot alert in one bucket — `released-still-open`, `fixed-on-next`, `open-pr`, `closed-unmerged` or `no-pr` — by reading the lockfile nearest the alert's manifest on the default branch, `next` and `hotfixes`, and the repo's PR history. An alert that reads open because its fix is waiting on `next` stops looking like work to do.
97
+
98
+ 🩹 **Full parameter reference: [docs/TOOLS.md](docs/TOOLS.md#report_alert_status)**
99
+
94
100
  ### 🚢 **Release PR Discovery**
95
101
 
96
102
  `report_release_prs` finds every open release PR across an owner's repos and says which ones still lack their per-version changelog file — the list an agent needs during a mass update.
97
103
 
98
104
  🚢 **Full parameter reference: [docs/TOOLS.md](docs/TOOLS.md#report_release_prs)**
99
105
 
106
+ ### 📝 **Changelog Source Material**
107
+
108
+ `report_release_changes` returns the PRs one release actually ships — already-released and reverted PRs dropped — grouped by changelog section at the detail level you ask for, with the release's `package.json` and dependency deltas and an optional skeleton in the per-version template.
109
+
110
+ 📝 **Full parameter reference: [docs/TOOLS.md](docs/TOOLS.md#report_release_changes)**
111
+
112
+ ### 📦 **Package Dependents**
113
+
114
+ `report_dependents` finds every repo an owner has that declares an npm package, with the declared range, the lockfile-resolved version and the repo's flow tier — where a fleet-wide version bump starts. It reads `dev` branches too, so dev-trunk repos are included, and skips a `dev` whose version has fallen behind the default branch.
115
+
116
+ 📦 **Full parameter reference: [docs/TOOLS.md](docs/TOOLS.md#report_dependents)**
117
+
100
118
  ### 🐳 **Container Image Pushes Without a Registry Token**
101
119
 
102
120
  `ghcr_push` pushes a `docker save` archive to `ghcr.io/<owner>/<image>:<tag>` with a classic `write:packages` PAT the agent never sees. The image must be on an allowlist, the archive must sit in a dedicated drop directory (symlinks, hard links and paths outside it are refused), and an existing release tag is never overwritten. The push runs as a background job, uploads only the blobs the registry doesn't already have, and is tracked with `ghcr_push_status`; `ghcr_tags` checks the result.
@@ -132,7 +150,15 @@ The broker presents its **own** MCP contract to the agent — a proxied tool's s
132
150
 
133
151
  ### Install
134
152
 
135
- gh-broker is published on npm as [`@cldmv/gh-broker`](https://www.npmjs.com/package/@cldmv/gh-broker), but it is a system service, not a library or a global CLI. Install it from a checkout with the installer, which handles both the first install and every upgrade:
153
+ gh-broker is a system service, not a library. The installer handles both the first install and every upgrade, and you can run it from npm or from a checkout.
154
+
155
+ From npm ([`@cldmv/gh-broker`](https://www.npmjs.com/package/@cldmv/gh-broker)), with the prebuilt bundle:
156
+
157
+ ```sh
158
+ sudo npx @cldmv/gh-broker <agent-user>
159
+ ```
160
+
161
+ From a checkout:
136
162
 
137
163
  ```sh
138
164
  git clone https://github.com/CLDMV/gh-broker.git
@@ -140,7 +166,7 @@ cd gh-broker
140
166
  sudo node deploy/install.mjs <agent-user>
141
167
  ```
142
168
 
143
- The installer creates the service user and the socket group, builds as the checkout's owner, merges the shipped defaults with the deployed config, stores the PATs in the backend you pick, installs the unit and runs a smoke test. Prerequisites, PAT scopes, unattended installs and every flag: [deploy/README.md](deploy/README.md).
169
+ Both take the same flags. The installer creates the service user and the socket group, builds as the checkout's owner when there's no bundle yet, merges the shipped defaults with the deployed config, stores the PATs in the backend you pick, installs the unit and runs a smoke test. Prerequisites, PAT scopes, unattended installs and every flag: [deploy/README.md](deploy/README.md).
144
170
 
145
171
  ---
146
172
 
@@ -179,6 +205,10 @@ src/
179
205
  report_unlabeled.ts issues/PRs with no labels, one repo or org-wide
180
206
  report_security_alerts.ts open Dependabot/CodeQL/secret alerts, one repo or org-wide
181
207
  report_release_prs.ts open release PRs + whether each has its changelog file
208
+ report_dependents.ts repos that declare an npm package, with range, resolved version and flow tier
209
+ report_alert_status.ts where each open Dependabot alert's fix stands (lockfiles + PRs)
210
+ report_release_changes.ts the PRs a release ships, grouped, with net package/dependency deltas
211
+ lockfile.ts npm / pnpm / yarn lockfile readers shared by the report verbs
182
212
  report_ci_status.ts tiered CI status for a PR or every open PR in a repo
183
213
  rest-client.ts shared rate-limit-floor + call-budget REST helpers
184
214
  issue_labels.ts add/remove/swap/set labels on an issue or PR (write PAT)
@@ -208,7 +238,7 @@ config.sample.json a full config with placeholder values, for reference only
208
238
 
209
239
  ## 📚 Documentation
210
240
 
211
- - **[Tools Reference](docs/TOOLS.md)** — every custom and augmented tool: `report_unlabeled`, `report_security_alerts`, `report_release_prs`, `report_ci_status`, the `pull_request_read` `ciVerbosity` extension, `issue_labels`, `npm_scaffold`, `resolve_review_thread`/`reply_review_thread`, `ghcr_push`/`ghcr_push_status`/`ghcr_tags`, and how to add a new one
241
+ - **[Tools Reference](docs/TOOLS.md)** — every custom and augmented tool: `report_unlabeled`, `report_security_alerts`, `report_alert_status`, `report_release_prs`, `report_release_changes`, `report_dependents`, `report_ci_status`, the `pull_request_read` and `list_pull_requests` `ciVerbosity` extensions, `issue_labels`, `npm_scaffold`, `resolve_review_thread`/`reply_review_thread`, `ghcr_push`/`ghcr_push_status`/`ghcr_tags`, and how to add a new one
212
242
  - **[Agent-as-Separate-User Model](docs/agent-user-model.md)** — the isolation model behind "use ≠ possession": users, groups, filesystem permissions, verified against a real host
213
243
  - **[Deploy Architecture](docs/deploy-architecture.md)** — config merge, secret store backends, node handling, the installer's full flow
214
244
  - **[Install Guide](deploy/README.md)** — prerequisites, PAT scopes, install/upgrade command, flags
@@ -28,7 +28,8 @@
28
28
  },
29
29
  {
30
30
  "name": "list_pull_requests",
31
- "mode": "read"
31
+ "mode": "read",
32
+ "augment": true
32
33
  },
33
34
  {
34
35
  "name": "pull_request_read",
@@ -265,11 +266,26 @@
265
266
  "mode": "read",
266
267
  "custom": true
267
268
  },
269
+ {
270
+ "name": "report_dependents",
271
+ "mode": "read",
272
+ "custom": true
273
+ },
268
274
  {
269
275
  "name": "report_release_prs",
270
276
  "mode": "read",
271
277
  "custom": true
272
278
  },
279
+ {
280
+ "name": "report_release_changes",
281
+ "mode": "read",
282
+ "custom": true
283
+ },
284
+ {
285
+ "name": "report_alert_status",
286
+ "mode": "read",
287
+ "custom": true
288
+ },
273
289
  {
274
290
  "name": "report_ci_status",
275
291
  "mode": "read",
package/deploy/README.md CHANGED
@@ -27,10 +27,11 @@ The installer also creates the drop directory from `ghcr.dropDir` (default `/srv
27
27
  ## 2. Install (first install AND upgrade — same command)
28
28
 
29
29
  ```sh
30
- sudo node deploy/install.mjs [agent-user]
30
+ sudo npx @cldmv/gh-broker [agent-user] # from npm
31
+ sudo node deploy/install.mjs [agent-user] # from a checkout
31
32
  ```
32
33
 
33
- `agent-user` defaults to `$SUDO_USER` (the account you ran `sudo` from). The installer walks the whole thing and is idempotent:
34
+ Both run the same installer and take the same flags; the npm package ships a prebuilt `dist/`, so step 5 has nothing to build. `agent-user` defaults to `$SUDO_USER` (the account you ran `sudo` from). The installer walks the whole thing and is idempotent:
34
35
 
35
36
  1. checks prerequisites,
36
37
  2. **creates or confirms the agent user** (stops if it can't — no silent half-install),
@@ -17,7 +17,8 @@
17
17
  /**
18
18
  * gh-broker installer — one command for first install AND upgrade.
19
19
  *
20
- * sudo node deploy/install.mjs [agent-user] [flags]
20
+ * sudo npx @cldmv/gh-broker [agent-user] [flags] (from npm)
21
+ * sudo node deploy/install.mjs [agent-user] [flags] (from a checkout)
21
22
  *
22
23
  * Prerequisite: node >= 20. Idempotent: re-run to upgrade (config regenerated by
23
24
  * layering, existing secrets kept). Interactive by default; pass flags plus
@@ -68,7 +69,8 @@ function readJson(path) {
68
69
 
69
70
  const HELP = `gh-broker installer — install and upgrade in one command.
70
71
 
71
- Usage: sudo node deploy/install.mjs [agent-user] [flags]
72
+ Usage: sudo npx @cldmv/gh-broker [agent-user] [flags] (from npm)
73
+ sudo node deploy/install.mjs [agent-user] [flags] (from a checkout)
72
74
 
73
75
  Flags:
74
76
  --agent-user <name> the unprivileged user the agent runs as
@@ -159,7 +161,7 @@ async function main() {
159
161
  }
160
162
  }
161
163
 
162
- if (!isRoot()) die("must run as root: sudo node deploy/install.mjs [agent-user] [flags]");
164
+ if (!isRoot()) die("must run as root: sudo npx @cldmv/gh-broker [agent-user] [flags], or sudo node deploy/install.mjs from a checkout");
163
165
  if (process.platform !== "linux") {
164
166
  die(`only Linux is implemented today (platform: ${process.platform}). The path/secret/service seams are ready; the impls are not.`);
165
167
  }