@cldmv/gh-broker 0.0.0-stage โ 0.8.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.
- package/LICENSE +202 -0
- package/README.md +279 -2
- package/config.example.json +294 -0
- package/config.sample.json +45 -0
- package/deploy/README.md +150 -0
- package/deploy/gh-broker.service +57 -0
- package/deploy/install.mjs +409 -0
- package/deploy/install.sh +29 -0
- package/deploy/lib/config-merge.mjs +214 -0
- package/deploy/lib/credentials.mjs +143 -0
- package/deploy/lib/install-args.mjs +144 -0
- package/deploy/lib/npm-setup.mjs +164 -0
- package/deploy/lib/prompt.mjs +98 -0
- package/deploy/lib/secret-store.mjs +132 -0
- package/deploy/lib/smoke.mjs +137 -0
- package/deploy/lib/system.mjs +246 -0
- package/dist/index.mjs +24406 -0
- package/dist/index.mjs.map +7 -0
- package/docs/TOOLS.md +538 -0
- package/docs/agent-user-model.md +89 -0
- package/docs/changelog/v0/v0.2.0.md +26 -0
- package/docs/changelog/v0/v0.2.1.md +23 -0
- package/docs/changelog/v0/v0.2.2.md +23 -0
- package/docs/changelog/v0/v0.2.3.md +33 -0
- package/docs/changelog/v0/v0.2.4.md +25 -0
- package/docs/changelog/v0/v0.2.5.md +29 -0
- package/docs/changelog/v0/v0.3.0.md +84 -0
- package/docs/changelog/v0/v0.3.1.md +30 -0
- package/docs/changelog/v0/v0.3.2.md +24 -0
- package/docs/changelog/v0/v0.3.3.md +28 -0
- package/docs/changelog/v0/v0.4.0.md +58 -0
- package/docs/changelog/v0/v0.4.1.md +33 -0
- package/docs/changelog/v0/v0.4.2.md +45 -0
- package/docs/changelog/v0/v0.5.0.md +39 -0
- package/docs/changelog/v0/v0.5.1.md +28 -0
- package/docs/changelog/v0/v0.6.0.md +52 -0
- package/docs/changelog/v0/v0.6.1.md +48 -0
- package/docs/changelog/v0/v0.7.0.md +71 -0
- package/docs/changelog/v0/v0.8.0.md +115 -0
- package/docs/deploy-architecture.md +84 -0
- package/package.json +71 -5
- package/src/appauth.ts +56 -0
- package/src/audit.ts +34 -0
- package/src/availability.ts +42 -0
- package/src/catalog.ts +182 -0
- package/src/config.ts +157 -0
- package/src/index.ts +107 -0
- package/src/paths.ts +60 -0
- package/src/router.ts +299 -0
- package/src/secrets.ts +167 -0
- package/src/server.ts +91 -0
- package/src/types.ts +128 -0
- package/src/upstream.ts +85 -0
- package/src/verbs/ghcr/archive.ts +314 -0
- package/src/verbs/ghcr/config.ts +142 -0
- package/src/verbs/ghcr/jobs.ts +141 -0
- package/src/verbs/ghcr/push.ts +192 -0
- package/src/verbs/ghcr/registry.ts +275 -0
- package/src/verbs/ghcr/tar.ts +203 -0
- package/src/verbs/ghcr_push.ts +264 -0
- package/src/verbs/issue_labels.ts +329 -0
- package/src/verbs/link_issue.ts +84 -0
- package/src/verbs/npm-registry.ts +168 -0
- package/src/verbs/npm-tarball.ts +76 -0
- package/src/verbs/npm_scaffold.ts +325 -0
- package/src/verbs/release-analysis.ts +212 -0
- package/src/verbs/repo-tier.ts +90 -0
- package/src/verbs/report_ci_status.ts +358 -0
- package/src/verbs/report_release_prs.ts +238 -0
- package/src/verbs/report_security_alerts.ts +442 -0
- package/src/verbs/report_unlabeled.ts +194 -0
- package/src/verbs/rest-client.ts +181 -0
- package/src/verbs/review_thread.ts +138 -0
- package/tests/appauth.test.vitest.mts +76 -0
- package/tests/audit.test.vitest.mts +48 -0
- package/tests/catalog.test.vitest.mts +234 -0
- package/tests/config-merge.test.vitest.mts +325 -0
- package/tests/config.test.vitest.mts +388 -0
- package/tests/credentials.test.vitest.mts +127 -0
- package/tests/ghcr-archive.test.vitest.mts +439 -0
- package/tests/ghcr-config.test.vitest.mts +96 -0
- package/tests/ghcr-push.test.vitest.mts +526 -0
- package/tests/ghcr-registry.test.vitest.mts +206 -0
- package/tests/helpers/ghcr-fixtures.mts +373 -0
- package/tests/install-args.test.vitest.mts +152 -0
- package/tests/issue-labels.test.vitest.mts +362 -0
- package/tests/npm-scaffold.test.vitest.mts +479 -0
- package/tests/npm-setup.test.vitest.mts +196 -0
- package/tests/paths.test.vitest.mts +57 -0
- package/tests/prompt.test.vitest.mts +128 -0
- package/tests/release-prs.test.vitest.mts +247 -0
- package/tests/rest-client.test.vitest.mts +115 -0
- package/tests/router.test.vitest.mts +505 -0
- package/tests/run-vitest.mjs +51 -0
- package/tests/secret-store.test.vitest.mts +167 -0
- package/tests/secrets.test.vitest.mts +208 -0
- package/tests/security-alerts.test.vitest.mts +338 -0
- package/tests/server.test.vitest.mts +200 -0
- package/tests/smoke.test.vitest.mts +177 -0
- package/tests/system.test.vitest.mts +355 -0
- package/tests/upstream.test.vitest.mts +91 -0
- package/tests/verb-helpers.test.vitest.mts +377 -0
- package/tests/verbs.test.vitest.mts +624 -0
- package/tsconfig.json +21 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
|
|
2
|
+
Apache License
|
|
3
|
+
Version 2.0, January 2004
|
|
4
|
+
http://www.apache.org/licenses/
|
|
5
|
+
|
|
6
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
7
|
+
|
|
8
|
+
1. Definitions.
|
|
9
|
+
|
|
10
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
11
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
12
|
+
|
|
13
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
14
|
+
the copyright owner that is granting the License.
|
|
15
|
+
|
|
16
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
17
|
+
other entities that control, are controlled by, or are under common
|
|
18
|
+
control with that entity. For the purposes of this definition,
|
|
19
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
20
|
+
direction or management of such entity, whether by contract or
|
|
21
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
22
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
23
|
+
|
|
24
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
25
|
+
exercising permissions granted by this License.
|
|
26
|
+
|
|
27
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
28
|
+
including but not limited to software source code, documentation
|
|
29
|
+
source, and configuration files.
|
|
30
|
+
|
|
31
|
+
"Object" form shall mean any form resulting from mechanical
|
|
32
|
+
transformation or translation of a Source form, including but
|
|
33
|
+
not limited to compiled object code, generated documentation,
|
|
34
|
+
and conversions to other media types.
|
|
35
|
+
|
|
36
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
37
|
+
Object form, made available under the License, as indicated by a
|
|
38
|
+
copyright notice that is included in or attached to the work
|
|
39
|
+
(an example is provided in the Appendix below).
|
|
40
|
+
|
|
41
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
42
|
+
form, that is based on (or derived from) the Work and for which the
|
|
43
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
44
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
45
|
+
of this License, Derivative Works shall not include works that remain
|
|
46
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
47
|
+
the Work and Derivative Works thereof.
|
|
48
|
+
|
|
49
|
+
"Contribution" shall mean any work of authorship, including
|
|
50
|
+
the original version of the Work and any modifications or additions
|
|
51
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
52
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
53
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
54
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
55
|
+
means any form of electronic, verbal, or written communication sent
|
|
56
|
+
to the Licensor or its representatives, including but not limited to
|
|
57
|
+
communication on electronic mailing lists, source code control systems,
|
|
58
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
59
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
60
|
+
excluding communication that is conspicuously marked or otherwise
|
|
61
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
62
|
+
|
|
63
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
64
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
65
|
+
subsequently incorporated within the Work.
|
|
66
|
+
|
|
67
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
68
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
69
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
70
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
71
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
72
|
+
Work and such Derivative Works in Source or Object form.
|
|
73
|
+
|
|
74
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
75
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
76
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
77
|
+
(except as stated in this section) patent license to make, have made,
|
|
78
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
79
|
+
where such license applies only to those patent claims licensable
|
|
80
|
+
by such Contributor that are necessarily infringed by their
|
|
81
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
82
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
83
|
+
institute patent litigation against any entity (including a
|
|
84
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
85
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
86
|
+
or contributory patent infringement, then any patent licenses
|
|
87
|
+
granted to You under this License for that Work shall terminate
|
|
88
|
+
as of the date such litigation is filed.
|
|
89
|
+
|
|
90
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
91
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
92
|
+
modifications, and in Source or Object form, provided that You
|
|
93
|
+
meet the following conditions:
|
|
94
|
+
|
|
95
|
+
(a) You must give any other recipients of the Work or
|
|
96
|
+
Derivative Works a copy of this License; and
|
|
97
|
+
|
|
98
|
+
(b) You must cause any modified files to carry prominent notices
|
|
99
|
+
stating that You changed the files; and
|
|
100
|
+
|
|
101
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
102
|
+
that You distribute, all copyright, patent, trademark, and
|
|
103
|
+
attribution notices from the Source form of the Work,
|
|
104
|
+
excluding those notices that do not pertain to any part of
|
|
105
|
+
the Derivative Works; and
|
|
106
|
+
|
|
107
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
108
|
+
distribution, then any Derivative Works that You distribute must
|
|
109
|
+
include a readable copy of the attribution notices contained
|
|
110
|
+
within such NOTICE file, excluding those notices that do not
|
|
111
|
+
pertain to any part of the Derivative Works, in at least one
|
|
112
|
+
of the following places: within a NOTICE text file distributed
|
|
113
|
+
as part of the Derivative Works; within the Source form or
|
|
114
|
+
documentation, if provided along with the Derivative Works; or,
|
|
115
|
+
within a display generated by the Derivative Works, if and
|
|
116
|
+
wherever such third-party notices normally appear. The contents
|
|
117
|
+
of the NOTICE file are for informational purposes only and
|
|
118
|
+
do not modify the License. You may add Your own attribution
|
|
119
|
+
notices within Derivative Works that You distribute, alongside
|
|
120
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
121
|
+
that such additional attribution notices cannot be construed
|
|
122
|
+
as modifying the License.
|
|
123
|
+
|
|
124
|
+
You may add Your own copyright statement to Your modifications and
|
|
125
|
+
may provide additional or different license terms and conditions
|
|
126
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
127
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
128
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
129
|
+
the conditions stated in this License.
|
|
130
|
+
|
|
131
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
132
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
133
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
134
|
+
this License, without any additional terms or conditions.
|
|
135
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
136
|
+
the terms of any separate license agreement you may have executed
|
|
137
|
+
with Licensor regarding such Contributions.
|
|
138
|
+
|
|
139
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
140
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
141
|
+
except as required for reasonable and customary use in describing the
|
|
142
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
143
|
+
|
|
144
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
145
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
146
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
147
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
148
|
+
implied, including, without limitation, any warranties or conditions
|
|
149
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
150
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
151
|
+
appropriateness of using or redistributing the Work and assume any
|
|
152
|
+
risks associated with Your exercise of permissions under this License.
|
|
153
|
+
|
|
154
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
155
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
156
|
+
unless required by applicable law (such as deliberate and grossly
|
|
157
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
158
|
+
liable to You for damages, including any direct, indirect, special,
|
|
159
|
+
incidental, or consequential damages of any character arising as a
|
|
160
|
+
result of this License or out of the use or inability to use the
|
|
161
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
162
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
163
|
+
other commercial damages or losses), even if such Contributor
|
|
164
|
+
has been advised of the possibility of such damages.
|
|
165
|
+
|
|
166
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
167
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
168
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
169
|
+
or other liability obligations and/or rights consistent with this
|
|
170
|
+
License. However, in accepting such obligations, You may act only
|
|
171
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
172
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
173
|
+
defend, and hold each Contributor harmless for any liability
|
|
174
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
175
|
+
of your accepting any such warranty or additional liability.
|
|
176
|
+
|
|
177
|
+
END OF TERMS AND CONDITIONS
|
|
178
|
+
|
|
179
|
+
APPENDIX: How to apply the Apache License to your work.
|
|
180
|
+
|
|
181
|
+
To apply the Apache License to your work, attach the following
|
|
182
|
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
183
|
+
replaced with your own identifying information. (Don't include
|
|
184
|
+
the brackets!) The text should be enclosed in the appropriate
|
|
185
|
+
comment syntax for the file format. We also recommend that a
|
|
186
|
+
file or class name and description of purpose be included on the
|
|
187
|
+
same "printed page" as the copyright notice for easier
|
|
188
|
+
identification within third-party archives.
|
|
189
|
+
|
|
190
|
+
Copyright [yyyy] [name of copyright owner]
|
|
191
|
+
|
|
192
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
193
|
+
you may not use this file except in compliance with the License.
|
|
194
|
+
You may obtain a copy of the License at
|
|
195
|
+
|
|
196
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
197
|
+
|
|
198
|
+
Unless required by applicable law or agreed to in writing, software
|
|
199
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
200
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
201
|
+
See the License for the specific language governing permissions and
|
|
202
|
+
limitations under the License.
|
package/README.md
CHANGED
|
@@ -1,3 +1,280 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @cldmv/gh-broker
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**@cldmv/gh-broker** is a local **credential-routing MCP proxy** for GitHub. It lets an autonomous agent read and write issues, pull requests and more across several orgs **without ever holding a token**: the agent gets to *act*, never to *possess* the credential.
|
|
4
|
+
|
|
5
|
+
The hosted GitHub MCP authenticates with one token per server, so several orgs means several servers, and the token sits in a config file the agent can read. A classic PAT spans orgs but is coarse; a GitHub App acts as a bot and can't drive the MCP; `gh` and raw PATs are readable by the agent (`gh auth token`). gh-broker covers what none of them do together: the user's own identity, least privilege, several orgs, one server, and a secret the agent cannot exfiltrate.
|
|
6
|
+
|
|
7
|
+
It runs as a dedicated `gh-broker` system user, holds a read-scoped and a write-scoped fine-grained PAT per org in an agent-unreadable secret store (`systemd-creds` or a `0640` file), and picks the right one per call by repo owner and read/write mode. The toolset is config-driven and default-deny: mostly proxied to GitHub's hosted MCP, plus custom verbs for what the hosted MCP has no tool for, and augmented tools that extend a proxied tool's result. The agent reaches it over a permissioned Unix socket that carries MCP frames and never credential material.
|
|
8
|
+
|
|
9
|
+
> _The agent gets to act, never to hold the credential._
|
|
10
|
+
|
|
11
|
+
[![npm version]][npm_version_url] [![npm downloads]][npm_downloads_url] [![GitHub downloads]][github_downloads_url] [![Last commit]][last_commit_url] [![npm last update]][npm_last_update_url] [![Coverage]][coverage_url]
|
|
12
|
+
|
|
13
|
+
> [!NOTE]
|
|
14
|
+
> **Status: 0.x, in production.** Running under systemd and brokering live GitHub reads and writes. Linux and systemd only for now ([#9](https://github.com/CLDMV/gh-broker/issues/9)). `link_issue` (App-token only) is implemented but not wired in, see [deploy/README.md](deploy/README.md#enabling-link_issue-github-app--deferred).
|
|
15
|
+
|
|
16
|
+
[![Contributors]][contributors_url] [![Sponsor shinrai]][sponsor_url]
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## โจ What's New
|
|
21
|
+
|
|
22
|
+
### Latest: v0.8.0 (October 2026)
|
|
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)
|
|
28
|
+
|
|
29
|
+
### Recent Releases
|
|
30
|
+
|
|
31
|
+
- **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
|
+
- **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
|
+
- **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
|
+
|
|
36
|
+
๐ For the complete version history, see the [docs/changelog/](https://github.com/CLDMV/gh-broker/tree/master/docs/changelog/) folder.
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## ๐ Key Features
|
|
41
|
+
|
|
42
|
+
### ๐ **Use โ Possession**
|
|
43
|
+
|
|
44
|
+
The agent can trigger a GitHub read/write; it can never hold the token that performs it. A separate system user owns the secret store and the daemon; the agent reaches it only over a permissioned Unix socket carrying MCP frames, never credential material.
|
|
45
|
+
|
|
46
|
+
๐ **For the full isolation model โ users, groups, filesystem permissions, verified against this host โ see [docs/agent-user-model.md](docs/agent-user-model.md)**
|
|
47
|
+
|
|
48
|
+
### ๐ฏ **Default-Deny, Config-Driven Toolset**
|
|
49
|
+
|
|
50
|
+
A tool not listed in `config.tools` is neither advertised nor executable. Adding an org is a config entry plus two credentials โ no new server, no new agent-visible tool-list bloat. Each entry is `mode: "read"` or `"write"`, optionally `custom` (handled entirely locally) or `augment` (proxied, then enriched) โ see below.
|
|
51
|
+
|
|
52
|
+
### ๐ **CI Visibility Without Per-Call Log Fetches**
|
|
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.
|
|
55
|
+
|
|
56
|
+
```json
|
|
57
|
+
{ "owner": "cldmv", "repo": "droidsock", "pull": 35, "verbosity": 2 }
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
๐ **For every tier, the classification rules, and real verified examples, see [docs/TOOLS.md](docs/TOOLS.md#report_ci_status)**
|
|
61
|
+
|
|
62
|
+
### ๐ท๏ธ **Cross-Repo Label Auditing**
|
|
63
|
+
|
|
64
|
+
`report_unlabeled` finds every issue/PR with no labels โ in one repo, or every repo an owner has โ bounded by fan-out safety caps and a rate-limit floor that reads the token's own real limit rather than assuming one.
|
|
65
|
+
|
|
66
|
+
๐ท๏ธ **Full parameter reference: [docs/TOOLS.md](docs/TOOLS.md#report_unlabeled)**
|
|
67
|
+
|
|
68
|
+
### ๐ท๏ธ **Label Edits That Leave Other Labels Alone**
|
|
69
|
+
|
|
70
|
+
The hosted MCP's `issue_write` takes `labels` as a full replacement, so changing one status label that way drops every other label on the issue. `issue_labels` edits labels one at a time instead: `add` and `remove` (one or several, combinable), `swap` (drop every `status: ` label and add `status: verified` in one call), and an explicit `set`. A misspelled label is refused rather than created, and the call returns the resulting set.
|
|
71
|
+
|
|
72
|
+
```json
|
|
73
|
+
{ "owner": "cldmv", "repo": "gh-broker", "issue_number": 117, "swap": { "prefix": "status: ", "to": "status: implemented" } }
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
๐ท๏ธ **Full parameter reference: [docs/TOOLS.md](docs/TOOLS.md#issue_labels)**
|
|
77
|
+
|
|
78
|
+
### ๐ฆ **New npm Packages Without a Manual First Publish**
|
|
79
|
+
|
|
80
|
+
npm only accepts a trusted publisher on a package that already exists, so every new package used to need a hand-run first publish and a form on npmjs.com. `npm_scaffold` does both: it publishes a broker-built placeholder (`0.0.0-stage`, no code) and registers the repo's publish workflow as the trusted publisher, after which CI publishes every release through OIDC. The broker's npm token has no 2FA bypass, so every npm write needs a one-time password from the user: one call publishes, a second call with the next code adds the trusted publisher. The verb refuses any package that already exists.
|
|
81
|
+
|
|
82
|
+
```json
|
|
83
|
+
{ "owner": "cldmv", "repo": "new-thing", "package": "@cldmv/new-thing", "otp": "123456" }
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
๐ฆ **Full parameter reference: [docs/TOOLS.md](docs/TOOLS.md#npm_scaffold)**
|
|
87
|
+
|
|
88
|
+
### ๐ก๏ธ **Org-Wide Security Alerts**
|
|
89
|
+
|
|
90
|
+
`report_security_alerts` lists every open Dependabot, CodeQL and secret-scanning alert โ for one repo or across everything an owner has โ using the org-level endpoints where the token can read them and a per-repo sweep where it can't. Secret values are never returned.
|
|
91
|
+
|
|
92
|
+
๐ก๏ธ **Full parameter reference: [docs/TOOLS.md](docs/TOOLS.md#report_security_alerts)**
|
|
93
|
+
|
|
94
|
+
### ๐ข **Release PR Discovery**
|
|
95
|
+
|
|
96
|
+
`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
|
+
|
|
98
|
+
๐ข **Full parameter reference: [docs/TOOLS.md](docs/TOOLS.md#report_release_prs)**
|
|
99
|
+
|
|
100
|
+
### ๐ณ **Container Image Pushes Without a Registry Token**
|
|
101
|
+
|
|
102
|
+
`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.
|
|
103
|
+
|
|
104
|
+
```json
|
|
105
|
+
{ "owner": "cldmv", "image": "hoot", "tag": "1.4.0", "archive": "hoot-1.4.0.tar" }
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
๐ณ **Full parameter reference and threat model: [docs/TOOLS.md](docs/TOOLS.md#ghcr_push)**
|
|
109
|
+
|
|
110
|
+
### ๐ง **Extensible By Design**
|
|
111
|
+
|
|
112
|
+
The broker presents its **own** MCP contract to the agent โ a proxied tool's schema and response are not required to match the hosted MCP's exactly. Adding a custom verb or extending a proxied tool with new parameters follows a documented pattern, not a one-off hack.
|
|
113
|
+
|
|
114
|
+
๐ง **How to add one: [docs/TOOLS.md ยง Extending this](docs/TOOLS.md#extending-this-adding-a-new-custom-verb-or-augmented-tool)**
|
|
115
|
+
|
|
116
|
+
### ๐ฆ **One-Command Install & Upgrade**
|
|
117
|
+
|
|
118
|
+
`sudo node deploy/install.mjs` handles first install and every upgrade: builds under the checkout's own owner (no `chown`, ever), merges shipped config defaults over the deployed config, lets you choose how PATs are stored at rest, and runs a post-deploy smoke test.
|
|
119
|
+
|
|
120
|
+
๐ฆ **Full prerequisites, PAT scopes, and flags: [deploy/README.md](deploy/README.md)**
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## ๐ฆ Installation
|
|
125
|
+
|
|
126
|
+
### Requirements
|
|
127
|
+
|
|
128
|
+
- **Linux with systemd.** The broker runs as a hardened systemd service and listens on a Unix socket.
|
|
129
|
+
- **Node.js 22.12.0 or later** (`engines.node` is `>=22.12.0`). The installer points `/usr/local/bin/node` at the node it runs under.
|
|
130
|
+
- **The agent runs as its own Linux user**, without passwordless sudo, so it can't read the broker's secrets. The model behind that is in [docs/agent-user-model.md](docs/agent-user-model.md).
|
|
131
|
+
- **Two fine-grained PATs per org** (read and write). The scopes are listed in [deploy/README.md](deploy/README.md).
|
|
132
|
+
|
|
133
|
+
### Install
|
|
134
|
+
|
|
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:
|
|
136
|
+
|
|
137
|
+
```sh
|
|
138
|
+
git clone https://github.com/CLDMV/gh-broker.git
|
|
139
|
+
cd gh-broker
|
|
140
|
+
sudo node deploy/install.mjs <agent-user>
|
|
141
|
+
```
|
|
142
|
+
|
|
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).
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## ๐ Quick Start
|
|
148
|
+
|
|
149
|
+
Point the agent's MCP client at the socket ([deploy/README.md ยง 3](deploy/README.md#3-point-claude-at-the-broker)). From then on the client sees an ordinary `tools/call`, and the broker resolves the credential, routes it, and (for custom/augmented tools) does the extra work in between:
|
|
150
|
+
|
|
151
|
+
```json
|
|
152
|
+
// tools/call
|
|
153
|
+
{ "name": "report_ci_status", "arguments": { "owner": "cldmv", "repo": "droidsock", "pull": 35, "verbosity": 1 } }
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
```json
|
|
157
|
+
// result
|
|
158
|
+
{ "pull": 35, "summary": { "passed": 6, "failed": 1, "pending": 0 }, "failures": [{ "workflow": "๐งช CI Tests & Build", "job": "Build & Test (22.12)", "runId": 34787050719, "runUrl": "https://github.com/CLDMV/droidsock/actions/runs/34787050719", "conclusion": "failure" }] }
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
No token ever appears in the request, the response, or anywhere the agent can read. See [docs/TOOLS.md](docs/TOOLS.md) for every custom and augmented tool, with full parameter tables and real verified examples.
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
## ๐ Layout
|
|
166
|
+
|
|
167
|
+
```
|
|
168
|
+
src/
|
|
169
|
+
index.ts entry โ resolve paths, load config + secrets, start server
|
|
170
|
+
paths.ts platform-neutral config/secrets path resolution
|
|
171
|
+
config.ts load + validate the token-free config
|
|
172
|
+
secrets.ts resolve cred refs from the secrets file (provider seam)
|
|
173
|
+
router.ts allowlist (default-deny) + owner/mode โ PAT + dispatch (custom/augment/forward)
|
|
174
|
+
upstream.ts pool of MCP clients to the hosted GitHub MCP (per-token, Bearer)
|
|
175
|
+
catalog.ts build the advertised tool list (real upstream schemas + custom + augmented)
|
|
176
|
+
server.ts Unix-socket MCP server toward the agent (StdioServerTransport)
|
|
177
|
+
audit.ts structured audit log (never tokens)
|
|
178
|
+
verbs/
|
|
179
|
+
report_unlabeled.ts issues/PRs with no labels, one repo or org-wide
|
|
180
|
+
report_security_alerts.ts open Dependabot/CodeQL/secret alerts, one repo or org-wide
|
|
181
|
+
report_release_prs.ts open release PRs + whether each has its changelog file
|
|
182
|
+
report_ci_status.ts tiered CI status for a PR or every open PR in a repo
|
|
183
|
+
rest-client.ts shared rate-limit-floor + call-budget REST helpers
|
|
184
|
+
issue_labels.ts add/remove/swap/set labels on an issue or PR (write PAT)
|
|
185
|
+
npm_scaffold.ts create an npm package + its trusted publisher (npm token + user OTP)
|
|
186
|
+
npm-registry.ts the npm registry requests npm_scaffold makes
|
|
187
|
+
npm-tarball.ts minimal npm tarball builder for the placeholder
|
|
188
|
+
review_thread.ts resolve/reply PR review threads (write PAT)
|
|
189
|
+
ghcr_push.ts ghcr_push / ghcr_push_status / ghcr_tags (GHCR classic PAT)
|
|
190
|
+
ghcr/ config policy, tar + image-archive reader, OCI registry client, push, job queue
|
|
191
|
+
link_issue.ts addClosingIssueReference (App token) โ DEFERRED, not wired in
|
|
192
|
+
deploy/
|
|
193
|
+
install.mjs interactive installer โ first install AND upgrade (sudo node)
|
|
194
|
+
install.sh optional Linux bootstrap โ set up node, then hand off to install.mjs
|
|
195
|
+
lib/ installer pieces (config merge, secret store, system ops, smoke test, npm token setup)
|
|
196
|
+
gh-broker.service systemd unit (hardened)
|
|
197
|
+
README.md prerequisites + PAT scopes + install/upgrade/wiring
|
|
198
|
+
docs/
|
|
199
|
+
TOOLS.md reference for every custom/augmented tool, with real examples
|
|
200
|
+
deploy-architecture.md config merge, secret store, node handling, installer flow
|
|
201
|
+
agent-user-model.md the agent-as-separate-user isolation model (example setup)
|
|
202
|
+
changelog/ per-version release notes
|
|
203
|
+
config.example.json shipped generic defaults (socket, upstream, tools allowlist)
|
|
204
|
+
config.sample.json a full config with placeholder values, for reference only
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
## ๐ Documentation
|
|
210
|
+
|
|
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
|
|
212
|
+
- **[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
|
+
- **[Deploy Architecture](docs/deploy-architecture.md)** โ config merge, secret store backends, node handling, the installer's full flow
|
|
214
|
+
- **[Install Guide](deploy/README.md)** โ prerequisites, PAT scopes, install/upgrade command, flags
|
|
215
|
+
- **[Changelog](docs/changelog/)** โ per-version release notes
|
|
216
|
+
|
|
217
|
+
[![CodeFactor]][codefactor_url] [![OpenSSF Scorecard]][ossf_scorecard_url] [![npms.io score]][npms_url] [![npm unpacked size]][npm_size_url] [![Repo size]][repo_size_url]
|
|
218
|
+
|
|
219
|
+
---
|
|
220
|
+
|
|
221
|
+
## ๐ค Contributing
|
|
222
|
+
|
|
223
|
+
Bug reports and pull requests are welcome on [GitHub](https://github.com/CLDMV/gh-broker/issues). Pull requests target the `next` branch; releases ship from `next` to `master`. Run `npm run build:ci` and `npm run ci:coverage` before opening one; coverage is held at 100%.
|
|
224
|
+
|
|
225
|
+
[![Contributors]][contributors_url] [![Sponsor shinrai]][sponsor_url]
|
|
226
|
+
|
|
227
|
+
---
|
|
228
|
+
|
|
229
|
+
## ๐ Links
|
|
230
|
+
|
|
231
|
+
- **npm**: [@cldmv/gh-broker](https://www.npmjs.com/package/@cldmv/gh-broker)
|
|
232
|
+
- **GitHub**: [CLDMV/gh-broker](https://github.com/CLDMV/gh-broker)
|
|
233
|
+
- **Issues**: [GitHub Issues](https://github.com/CLDMV/gh-broker/issues)
|
|
234
|
+
- **Changelog**: [docs/changelog/](https://github.com/CLDMV/gh-broker/tree/master/docs/changelog/)
|
|
235
|
+
- **Releases**: [GitHub Releases](https://github.com/CLDMV/gh-broker/releases)
|
|
236
|
+
|
|
237
|
+
---
|
|
238
|
+
|
|
239
|
+
## ๐ License
|
|
240
|
+
|
|
241
|
+
[![GitHub license]][github_license_url] [![npm license]][npm_license_url]
|
|
242
|
+
|
|
243
|
+
Apache-2.0 ยฉ Shinrai / CLDMV. See [LICENSE](https://github.com/CLDMV/gh-broker/blob/master/LICENSE) for the full text.
|
|
244
|
+
|
|
245
|
+
<!-- Badge definitions -->
|
|
246
|
+
<!-- [github release]: https://img.shields.io/github/v/release/CLDMV/gh-broker?style=for-the-badge&logo=github&logoColor=white&labelColor=181717 -->
|
|
247
|
+
<!-- [github_release_url]: https://github.com/CLDMV/gh-broker/releases -->
|
|
248
|
+
<!-- [release date]: https://img.shields.io/github/release-date/CLDMV/gh-broker?style=for-the-badge&logo=github&logoColor=white&labelColor=181717 -->
|
|
249
|
+
<!-- [release_date_url]: https://github.com/CLDMV/gh-broker/releases -->
|
|
250
|
+
|
|
251
|
+
[npm version]: https://img.shields.io/npm/v/%40cldmv%2Fgh-broker.svg?style=for-the-badge&logo=npm&logoColor=white&labelColor=CB3837
|
|
252
|
+
[npm_version_url]: https://www.npmjs.com/package/@cldmv/gh-broker
|
|
253
|
+
[npm downloads]: https://img.shields.io/npm/dm/%40cldmv%2Fgh-broker.svg?style=for-the-badge&logo=npm&logoColor=white&labelColor=CB3837
|
|
254
|
+
[npm_downloads_url]: https://www.npmjs.com/package/@cldmv/gh-broker
|
|
255
|
+
[github downloads]: https://img.shields.io/github/downloads/CLDMV/gh-broker/total?style=for-the-badge&logo=github&logoColor=white&labelColor=181717
|
|
256
|
+
[github_downloads_url]: https://github.com/CLDMV/gh-broker/releases
|
|
257
|
+
[last commit]: https://img.shields.io/github/last-commit/CLDMV/gh-broker?style=for-the-badge&logo=github&logoColor=white&labelColor=181717
|
|
258
|
+
[last_commit_url]: https://github.com/CLDMV/gh-broker/commits
|
|
259
|
+
[npm last update]: https://img.shields.io/npm/last-update/%40cldmv%2Fgh-broker?style=for-the-badge&logo=npm&logoColor=white&labelColor=CB3837
|
|
260
|
+
[npm_last_update_url]: https://www.npmjs.com/package/@cldmv/gh-broker
|
|
261
|
+
[coverage]: https://img.shields.io/endpoint?url=https%3A%2F%2Fraw.githubusercontent.com%2FCLDMV%2Fgh-broker%2Fbadges%2Fcoverage.json&style=for-the-badge&logo=vitest&logoColor=white
|
|
262
|
+
[coverage_url]: https://github.com/CLDMV/gh-broker/blob/badges/coverage.json
|
|
263
|
+
[contributors]: https://img.shields.io/github/contributors/CLDMV/gh-broker.svg?style=for-the-badge&logo=github&logoColor=white&labelColor=181717
|
|
264
|
+
[contributors_url]: https://github.com/CLDMV/gh-broker/graphs/contributors
|
|
265
|
+
[sponsor shinrai]: https://img.shields.io/github/sponsors/shinrai?style=for-the-badge&logo=githubsponsors&logoColor=white&labelColor=EA4AAA&label=Sponsor
|
|
266
|
+
[sponsor_url]: https://github.com/sponsors/shinrai
|
|
267
|
+
[codefactor]: https://img.shields.io/codefactor/grade/github/CLDMV/gh-broker?style=for-the-badge&logo=codefactor&logoColor=white&labelColor=F44A6A
|
|
268
|
+
[codefactor_url]: https://www.codefactor.io/repository/github/cldmv/gh-broker
|
|
269
|
+
[openssf scorecard]: https://img.shields.io/ossf-scorecard/github.com/CLDMV/gh-broker?style=for-the-badge&label=OpenSSF%20Scorecard
|
|
270
|
+
[ossf_scorecard_url]: https://scorecard.dev/viewer/?uri=github.com/CLDMV/gh-broker
|
|
271
|
+
[npms.io score]: https://img.shields.io/npms-io/final-score/%40cldmv%2Fgh-broker?style=for-the-badge&logo=npms&logoColor=white&labelColor=0B5D57
|
|
272
|
+
[npms_url]: https://npms.io/search?q=%40cldmv%2Fgh-broker
|
|
273
|
+
[npm unpacked size]: https://img.shields.io/npm/unpacked-size/%40cldmv%2Fgh-broker.svg?style=for-the-badge&logo=npm&logoColor=white&labelColor=CB3837
|
|
274
|
+
[npm_size_url]: https://www.npmjs.com/package/@cldmv/gh-broker
|
|
275
|
+
[repo size]: https://img.shields.io/github/repo-size/CLDMV/gh-broker?style=for-the-badge&logo=github&logoColor=white&labelColor=181717
|
|
276
|
+
[repo_size_url]: https://github.com/CLDMV/gh-broker
|
|
277
|
+
[npm license]: https://img.shields.io/npm/l/%40cldmv%2Fgh-broker.svg?style=for-the-badge&logo=npm&logoColor=white&labelColor=CB3837
|
|
278
|
+
[npm_license_url]: https://www.npmjs.com/package/@cldmv/gh-broker
|
|
279
|
+
[github license]: https://img.shields.io/github/license/CLDMV/gh-broker.svg?style=for-the-badge&logo=github&logoColor=white&labelColor=181717
|
|
280
|
+
[github_license_url]: https://github.com/CLDMV/gh-broker/blob/master/LICENSE
|