@colony2/gitvend 0.0.3 → 0.0.4

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/README.md CHANGED
@@ -1,401 +1,64 @@
1
- # gitvend
1
+ # Gitvend
2
2
 
3
- A Go Git/HTTPS gateway with permissions carried in signed JWTs. Agents use ordinary Git and one gateway credential across their assigned repositories. The gateway holds a shared upstream token and enforces repository, ref-discovery, branch-write, tag and repository-creation permissions before forwarding requests.
3
+ Gitvend gives agents controlled access to GitHub repositories without giving them
4
+ your GitHub token. Agents use ordinary Git with short-lived credentials that
5
+ specify which repositories and branches they may read, write, or create.
4
6
 
5
- Implemented for GitHub and GitHub Enterprise-compatible APIs. Client and upstream Git connections use HTTPS; fetch/ref lookup requires protocol v2, while pushes use Git's normal receive-pack format. The service does not require a GitHub App. The gateway is stateless: it needs configuration, public verification keys and upstream credentials, with no database or writable state volume. Multiple instances can serve the same agents.
7
+ ## Gitvend gateway
6
8
 
7
- This guide takes an operator from configuring a gateway to giving an agent a credential, cloning a repository, and pushing an allowed branch.
9
+ The gateway sits between agents and GitHub. It holds your upstream GitHub tokens,
10
+ checks each agent's signed permissions, and forwards authorized Git requests.
11
+ You can configure different upstream tokens for different organizations, deny
12
+ writes to protected branches, and control whether new repositories are created
13
+ publicly or privately with issues, projects, wiki, and pull requests enabled.
8
14
 
9
- [Install](#install) · [Docker Compose](docs/docker-compose.md) · [Set up the gateway](#set-up-the-gateway) · [Issue a credential](#issue-an-agent-credential) · [Agent usage](#use-gitvend-as-an-agent) · [Permissions](#permission-strings) · [Operations](#provisioning-and-audit) · [Troubleshooting](#troubleshooting) · [CLI reference](#cli-reference)
15
+ The gateway supports GitHub and GitHub Enterprise-compatible endpoints. It needs
16
+ no database or GitHub App. Agents connect over HTTPS; GitHub's own access and
17
+ branch rules continue to apply.
10
18
 
11
- ## How credentials and permissions fit together
19
+ [Set up and use the gateway →](https://github.com/colony-2/gitvend/blob/v0.0.4/docs/gateway.md)
12
20
 
13
- ```text
14
- Agent running Git -- HTTPS + agent JWT --> gitvend -- HTTPS + upstream token --> GitHub
15
- ^
16
- trusts the issuer's public key
17
- ```
21
+ ## JobDB plugin
18
22
 
19
- | Credential | Who holds it | Purpose |
20
- | --- | --- | --- |
21
- | Upstream GitHub token | Gateway operator; available to the gateway process | Lets gitvend access repositories and, when enabled, create them. Shared across agents. |
22
- | Ed25519 private signing key | Trusted orchestrator or operator | Signs each agent's JWT with its identity, expiry and permissions. |
23
- | Ed25519 public signing key | Gateway | Verifies JWTs without contacting the issuer. |
24
- | Agent JWT | The assigned agent | Used as its Git HTTPS password. Contains the signed permission strings. |
23
+ The optional JobDB plugin issues Gitvend credentials for jobs automatically.
24
+ Configure a tenant's base permissions and extra permissions for its target cell
25
+ repository. JobDB workers can request a base token or a cell token; each token's
26
+ lifetime is limited by the job's verified lease authority.
25
27
 
26
- An operation must pass all configured checks: the provider's allowed owners, the signing key's allowed owners, the JWT's grants, gateway-wide deny rules, and the upstream account's permissions. A JWT cannot grant access outside these limits. Give agents their JWT; retain the upstream token on the gateway and the private signing key with the trusted issuer.
28
+ The plugin keeps its signing key on the JobDB host, and the gateway verifies the
29
+ resulting tokens with the matching public key. Workers receive neither the
30
+ signing key nor the upstream GitHub token.
27
31
 
28
- Read permissions hide ungranted ref names; they do **not** isolate Git objects by branch. An agent with any read grant for a repository may fetch objects by known hash, subject to what the upstream serves. Use separate repositories when you need object confidentiality.
32
+ [Set up the JobDB plugin →](https://github.com/colony-2/gitvend/blob/v0.0.4/docs/jobdb-secret-provider.md)
29
33
 
30
34
  ## Install
31
35
 
32
- Download the archive for your Linux/macOS system and amd64/arm64 architecture from [GitHub Releases](https://github.com/colony-2/gitvend/releases). Releases include SHA-256 checksums. Extract the archive and place its `gitvend` executable on `PATH`; keep the included documentation and example configuration for setup.
33
-
34
- Once the first release is published, install through Go or npm:
36
+ Install the npm package on Linux or macOS (amd64 or arm64):
35
37
 
36
38
  ```sh
37
- go install github.com/colony-2/gitvend/cmd/gitvend@latest
38
- # Or use the npm wrapper, which downloads and verifies the matching binary:
39
39
  npm install -g @colony2/gitvend
40
40
  gitvend version
41
+ jobdb-gitvend-secret-provider --help
41
42
  ```
42
43
 
43
- For a Go installation, add `$(go env GOPATH)/bin` to your `PATH` if needed. The npm wrapper requires Node 22+ and `tar`. Install scripts must be enabled so it can download the binary from GitHub Releases. Release builds report their release version; local builds report their Git revision when available.
44
-
45
- ### Docker Compose
46
-
47
- The [Compose deployment guide](docs/docker-compose.md) covers a container image,
48
- automatic signing-key initialization on persistent volumes, a mounted GitHub
49
- token, and on-demand JWT issuance. Only the gateway stays running; the private
50
- signing key is available to initialization and issuer containers, never mounted
51
- into the gateway. The default stack binds HTTP to host loopback for use behind
52
- an HTTPS reverse proxy.
53
-
54
- ## Build and verify
55
-
56
- Requires Go 1.25+ and Git for the integration tests. Supported server platforms are Linux and macOS. Run these commands from the source checkout's root:
57
-
58
- ```sh
59
- make build
60
- export PATH="$PWD/bin:$PATH"
61
- gitvend version
62
- make check
63
- ```
64
-
65
- `make check` runs race tests and vet. `make fuzz` exercises the permission, packet and JSON parsers. The default test suite uses real Git clients and a real `git-http-backend`, with a local GitHub API fixture; it needs neither a GitHub token nor external repository access.
66
-
67
- ## Set up the gateway
68
-
69
- The walkthrough uses organization `fooorg`, an existing repository `project` with a `main` branch, and gateway address `git-gateway.example:8443`. Replace these with your own values. Commands assume `gitvend` is on `PATH`. Agents need Git with protocol v2 support; the gateway serves HTTPS directly in this example.
70
-
71
- ### 1. Provide the upstream token
72
-
73
- Have your process supervisor or secret manager set `GITHUB_TOKEN` in the **gateway process** environment. The token's account must have access to the repositories the agents will use. For automatic creation, it must also be able to create private repositories in the organization and access them afterward. Gitvend does not generate or renew this upstream token.
74
-
75
- GitHub's [token guide](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens) describes account and organization restrictions. For private organization repository creation, GitHub documents `repo` scope for classic tokens or repository Administration write permission for fine-grained tokens; creation permissions alone do not establish Git read/write access. Check repository selection, organization approval and workflow-file access for your account. See [GitHub's create-repository requirements](https://docs.github.com/en/rest/repos/repos#create-an-organization-repository).
76
-
77
- If you prefer a mounted token file, use this credential object inside the provider entry:
78
-
79
- ```json
80
- {
81
- "credential": {
82
- "kind": "token",
83
- "secret_ref": "file:/run/secrets/github-token"
84
- }
85
- }
86
- ```
87
-
88
- The same credential is used for Git and REST API calls. An optional provider-level `api_credential` object with the same shape selects a separate REST token. This release supports token credentials; it does not use SSH keys or discover credentials from `gh auth` or Git credential helpers.
89
-
90
- ### 2. Generate and install the issuer key
91
-
92
- On the trusted orchestrator or operator machine:
93
-
94
- ```sh
95
- mkdir -p var
96
- gitvend keygen -private var/signing.key -public var/signing.pub
97
- ```
98
-
99
- Keep `var/signing.key` on that machine. Copy **only** `signing.pub` to `var/signing.pub` in the gateway's working directory. If the operator and gateway run on one machine, restrict the private key to the issuer's account. Each configured key has an ID and an issuer name; the token-signing command must use those exact values.
100
-
101
- ### 3. Configure and start the server
102
-
103
- On the gateway, prepare the public-key directory and copy the [configuration template](examples/gitvend.json) from the source checkout or release archive. If installed through Go or npm, obtain that template separately from this repository:
104
-
105
- ```sh
106
- mkdir -p var
107
- cp examples/gitvend.json gitvend.json
108
- ```
109
-
110
- Edit `gitvend.json` using this checklist:
111
-
112
- | Field | Set it to |
113
- | --- | --- |
114
- | `listen` | `0.0.0.0:8443` to accept connections on the gateway's network interfaces. The template binds to `127.0.0.1:8443` for local access. |
115
- | `tls_cert`, `tls_key` | Readable certificate/key files for `git-gateway.example`, trusted by the agents. |
116
- | `keys[].public_key_file` | The public key installed in step 2. |
117
- | `keys[].owners` and `providers[].allowed_owners` | Your lowercase organization names in both places. |
118
- | `providers[].credential.secret_ref` | `env:GITHUB_TOKEN` or the mounted token file reference. |
119
- | `providers[].allow_creation` | `true` for the scratch-repository example below; `false` to disable creation. |
120
- | `denies` | Replace `fooorg` in the example deny rule too. It blocks updates/deletion of `main` and `master`. |
121
-
122
- Configuration is JSON. Unknown fields and duplicate keys are rejected. Relative file paths are resolved from the server's **working directory**, not the configuration file's directory; use absolute paths when running under a supervisor.
123
-
124
- ```sh
125
- gitvend serve -config gitvend.json
126
- ```
127
-
128
- The process runs in the foreground and writes operational logs to stderr. From another terminal:
129
-
130
- ```sh
131
- curl --fail https://git-gateway.example:8443/healthz
132
- ```
133
-
134
- Expected response: `ok`. This is a liveness check; it does not verify a JWT or contact GitHub. The agent's `ls-remote` command below verifies the Git path.
135
-
136
- The remote URL has this structure:
137
-
138
- ```text
139
- https://GATEWAY/PROVIDER_ALIAS/OWNER/REPOSITORY.git
140
- https://git-gateway.example:8443/github/fooorg/project.git
141
- ```
142
-
143
- The `github` segment is the configured provider alias. Permission strings use the configured upstream authority (`github.com`), not that alias or the gateway hostname. Repository permission patterns omit the `.git` suffix. Add more provider entries for distinct GitHub-compatible endpoints or owner/credential mappings; overlapping host/owner routes are rejected. Other forge APIs require an adapter.
144
-
145
- ### Running behind a TLS terminator
146
-
147
- Set `allow_http: true` only for the protected HTTP listener behind the terminator, and bind it to the intended internal interface. This option makes the listener serve HTTP even if TLS files are present. Agents still use the public HTTPS address and its exact host/port in their credential helper.
148
-
149
- Preserve the URL, `Authorization` and `Git-Protocol` headers, allow streaming request/response bodies, and align ingress body, header and timeout limits with gitvend. `allow_http_upstream` is a separate local-test option; upstream GitHub connections remain HTTPS. Neither option disables certificate verification for HTTPS.
150
-
151
- ## Issue an agent credential
152
-
153
- On the trusted orchestrator, issue a short-lived JWT carrying the task's permissions:
154
-
155
- ```sh
156
- gitvend sign \
157
- -key var/signing.key \
158
- -kid orchestrator-1 \
159
- -issuer orchestrator \
160
- -subject agent-47 \
161
- -audience gitvend \
162
- -ttl 15m \
163
- -permission 'github.com/fooorg/project#main:r' \
164
- -permission 'github.com/fooorg/project#agents/47/*:rw' \
165
- -permission 'github.com/fooorg/agent-47-*:c' \
166
- -permission 'github.com/fooorg/agent-47-*#agents/47/*:rw' \
167
- -output var/agent-47.jwt
168
- ```
169
-
170
- Alternatively, pass `-grant examples/grant.json`. The file contains `v` and the `permissions` array. Permissions follow repository names, including future repositories with matching names; there are no repository-ID bindings. `-output` replaces the token file atomically with permissions `0600`; without it, `sign` writes the token to stdout. `keygen` refuses to overwrite existing key files.
171
-
172
- JWTs use Ed25519 signatures (`alg=EdDSA`, `typ=gitvend+jwt`). Verification requires the configured issuer, key ID and audience plus subject, token ID, issued-at, not-before, expiry and grant version. Unknown fields, duplicate JSON keys, unsupported algorithms and malformed rules are rejected. The gateway needs no issued-token database and never contacts the issuer on a Git request.
173
-
174
- The sample grant allows reading `main`, reading/writing `agents/47/*` branches, and creating private scratch repositories named `agent-47-*` with writable branches under the same prefix. It does not allow pushing `main`, deleting branches or creating tags. The sample server deny rule protects `main` and `master` even if a later JWT grants them writes.
175
-
176
- Deliver `var/agent-47.jwt` to the agent through your orchestrator's secret mechanism, for example as `/run/secrets/gitvend.jwt`. The file must be readable by that agent. Gitvend does not deliver tokens to agents itself.
177
-
178
- Refresh the injected file before expiry. Re-running the signing command with `-output` atomically replaces its output file; arrange the same replacement at the agent's token path. The credential helper reads the current file for each credential request, so Git remotes need no change. The default maximum lifetime is 15 minutes; a longer `-ttl` also requires a matching server-side `max_token_lifetime_seconds` setting.
179
-
180
- A task's existing token remains usable until expiry plus configured clock tolerance even if the issuer stops renewing it. There is no immediate per-agent revocation list. Removing a signing key or adding a gateway-wide deny rule affects new requests after reload; an admitted transfer may finish within its deadline.
181
-
182
- ## Use gitvend as an agent
183
-
184
- ### Configure Git authentication
185
-
186
- Run these commands inside the agent's own OS account or sandbox, with `gitvend` on `PATH`:
187
-
188
- ```sh
189
- git config --global protocol.version 2
190
- git config --global credential.https://git-gateway.example:8443.helper ''
191
- git config --global --add credential.https://git-gateway.example:8443.helper \
192
- '!gitvend credential -host git-gateway.example:8443 -token-file /run/secrets/gitvend.jwt'
193
- ```
194
-
195
- The empty entry resets inherited helpers for this host. The helper supplies username `git` and the JWT as the HTTPS Basic password only for the exact configured host and port. Use `git-gateway.example` in both settings if serving on standard HTTPS port 443 with no explicit port in the URL. The shell-style `!` helper invokes `gitvend` from `PATH`; Git appends its `get`, `store` or `erase` operation automatically. Store/erase are ignored because the orchestrator owns token replacement.
196
-
197
- `-token-env VARIABLE_NAME` can replace `-token-file` if you inject the JWT into the agent's environment. Do not put the JWT in a clone URL. A custom Git client can use HTTP Basic directly, with the JWT as its password, and must request protocol v2 for fetch/discovery.
198
-
199
- ### Clone and push an assigned branch
200
-
201
- ```sh
202
- # Confirm that the credential, route and upstream repository work.
203
- git ls-remote --heads https://git-gateway.example:8443/github/fooorg/project.git
204
-
205
- # Select main explicitly, even if the repository's default branch is hidden.
206
- git clone --branch main https://git-gateway.example:8443/github/fooorg/project.git
207
- git -C project switch -c agents/47/my-task
208
-
209
- # After making and committing your changes, push an explicit destination.
210
- git -C project push -u origin HEAD:refs/heads/agents/47/my-task
211
- ```
212
-
213
- With the sample grant, discovery shows `main` and any existing `agents/47/*` branches. The push can create the assigned branch or update it. A push to `refs/heads/main` is denied. If one push contains any unauthorized ref update, gitvend rejects the whole request before forwarding its push commands or pack to GitHub. GitHub may independently reject permitted updates through its branch rules; use `git push --atomic` when you require all permitted updates to succeed together and the upstream supports it.
214
-
215
- For an existing checkout, route its remote through the gateway:
216
-
217
- ```sh
218
- git -C project remote set-url origin https://git-gateway.example:8443/github/fooorg/project.git
219
- ```
220
-
221
- Changing a remote does not remove previously fetched objects or refs from that checkout. Use a fresh clone when you want its initial local refs to reflect the current discovery grant.
222
-
223
- ### Create a missing scratch repository on first push
224
-
225
- The sample token also grants creation of `fooorg/agent-47-*`. Create a local repository with a branch the agent can write, then push it through the gateway:
226
-
227
- ```sh
228
- git init -b agents/47/start agent-47-scratch
229
- git -C agent-47-scratch config user.name 'Agent 47'
230
- git -C agent-47-scratch config user.email 'agent-47@example.invalid'
231
- git -C agent-47-scratch commit --allow-empty -m 'Initialize agent scratch repository'
232
- git -C agent-47-scratch remote add origin \
233
- https://git-gateway.example:8443/github/fooorg/agent-47-scratch.git
234
- git -C agent-47-scratch push -u origin HEAD:refs/heads/agents/47/start
235
- ```
236
-
237
- Gitvend creates the missing private repository during push discovery, then forwards the authorized push. It creates no initial commit or `main` branch of its own. For a later clone, select `--branch agents/47/start` explicitly. A clone of a missing repository does not create it. Even `git push --dry-run` can create an empty repository; see [provisioning behavior](#provisioning-and-audit).
238
-
239
- ## Permission strings
240
-
241
- ```text
242
- [!]host/namespace/repository[#ref-selector]:actions
243
- ```
244
-
245
- | Action | Meaning |
246
- | --- | --- |
247
- | `r` | Read objects by hash and discover matching refs. |
248
- | `w` | Create/update matching refs, including force updates. |
249
- | `d` | Delete matching refs. |
250
- | `c` | Create matching private repositories; use without a ref selector. |
251
-
252
- ```text
253
- github.com/fooorg/*:r
254
- github.com/fooorg/blue*:rw
255
- github.com/*:r
256
- github.com/fooorg/red#(main|master|link):rw
257
- !github.com/fooorg/*#(main|master):wd
258
- ```
259
-
260
- Each rule is a separate `-permission` argument or an element in a grant's `permissions` array; do not combine rules into a comma-separated string. Quote rules in shell commands so glob and `!` characters reach gitvend unchanged.
261
-
262
- | Rule | Use |
263
- | --- | --- |
264
- | `github.com/fooorg/project#main:r` | Discover main and allow repository hash reads. |
265
- | `github.com/fooorg/project#agents/47/*:rw` | Read/create/update this agent's branches. Add `d` (`:rwd`) to allow deletion. |
266
- | `github.com/fooorg/project#refs/tags/agent-47-*:rw` | Read/create/update matching tags explicitly. |
267
- | `github.com/fooorg/agent-47-*:c` | Permit matching repository creation; also grant `rw` on at least one branch. |
268
- | `!github.com/fooorg/*#(main\|master):wd` | Deny main/master writes and deletion across the organization. |
269
-
270
- Repository `*` stays within one path segment; branch `*` can span `/`. `(a|b)` selects alternatives, not arbitrary regular expressions. `github.com/*` is the whole-host shorthand, still constrained by configured owners.
271
-
272
- Matching allows combine; any matching deny wins. No `#` covers branches and tags; `#*` covers branches only. A `w` or `d` operation also requires read/discovery permission. `r` scoped to a branch hides other refs but deliberately does not block known-hash reads from the same repository. A broad read grant is not narrowed by adding a more specific grant.
273
-
274
- See [the complete syntax](docs/permission-syntax.md) for wildcard, alternative, escaping and deny semantics. Inspect a decision without making network calls:
275
-
276
- ```sh
277
- gitvend explain \
278
- -permission 'github.com/fooorg/*:r' \
279
- -permission 'github.com/fooorg/blue*:w' \
280
- -permission '!github.com/fooorg/*#main:wd' \
281
- -repo github.com/fooorg/bluebird \
282
- -ref refs/heads/main \
283
- -action ref.update
284
- ```
285
-
286
- The example returns `"allowed": false`. `explain` evaluates only the rules you pass; include applicable deny rules yourself. It does not load server configuration, verify a JWT, or check GitHub permissions. A valid explanation command exits successfully even for a denied decision; inspect `allowed`. A `repo.create` explanation evaluates the `c` permission only, not the additional branch-overlap or upstream checks.
287
-
288
- ## Provisioning and audit
289
-
290
- Repository creation is opt-in twice: the provider must set `allow_creation: true` and the JWT must grant `c` plus an overlapping readable/writable branch. The gateway proves that overlap with bounded automata, including denies. It never guesses a branch name to establish permission.
291
-
292
- Creation occurs during receive-pack discovery. Consequently, `git push --dry-run`, abandoned pushes and later branch-policy rejections may leave empty repositories. Clone/fetch never creates repositories. Direct receive-pack POSTs cannot create missing repositories. Created repositories are private and uninitialized; the gateway never changes an existing repository's visibility, deletes it, or silently seeds `main`.
293
-
294
- Concurrent creation is coordinated by the forge's repository-name uniqueness. Different gateway instances may both attempt creation; after a conflict or ambiguous response, gitvend looks up the name and checks that the resulting repository is private and matches the requested owner/name. It never changes an existing repository's visibility. If the outcome cannot be confirmed, the request fails with 503; a later normal push discovery performs a fresh lookup. There are no background reconciliation jobs, creation quotas or stored attempts.
295
-
296
- Permissions follow repository names. Deleting and recreating a repository under the same name leaves a matching JWT grant applicable to that name. Gitvend does not enroll repositories or pin their IDs.
297
-
298
- ### Audit logs
299
-
300
- `gitvend serve` emits newline-delimited JSON audit records on **stdout** and operational logs on stderr. Collect stdout with your process supervisor or logging service. Gitvend keeps no audit database or outbox and has no `audit` command.
301
-
302
- Each JSON record has an `audit` object containing request ID, issuer/subject, token ID, repository, operation and outcome when available. A request can emit an `admitted` event before contacting the upstream and a final outcome with the same `audit.id`. Creation events have a separate ID and an `audit.parent_id` linking them to the Git request's `X-Request-ID` response header. JWT strings, upstream tokens and pack contents are excluded.
303
-
304
- For example, inspect an existing log export with `jq`:
305
-
306
- ```sh
307
- jq -c 'select(.audit.operation == "git-receive-pack") | .audit' audit.jsonl
308
- ```
309
-
310
- Push audit distinguishes `accepted`, `rejected`, `partial` and `unknown`; HTTP 200 alone is not success. Creation outcomes are `created`, `reconciled`, `rejected` or `unknown` and do not claim that a subsequent push succeeded. A crash can leave an admission with no final record. Log delivery is best-effort, with retention and durability handled by your logging infrastructure. Inspect the remote refs before retrying an interrupted push; gitvend never retries a push automatically.
311
-
312
- ### Multiple instances
313
-
314
- Run any number of instances behind the same HTTPS endpoint with matching configuration, trusted keys and credentials. No shared disk, database, distributed lock or sticky session is required. Configuration/key rotations must reach each instance; a reload on one instance does not update others. `max_concurrent` and request limits apply per instance. If you need fleet-wide rate limits or creation budgets, enforce them outside gitvend. A metrics export endpoint is not implemented.
315
-
316
- ## Configuration and limits
317
-
318
- Run the service under a supervisor with a consistent working directory and readable configuration/key/credential files. The running gateway can use a read-only filesystem; operator commands such as `keygen` and `sign -output` still write their explicitly requested files. `SIGTERM` or Ctrl-C starts graceful shutdown with a 10-second drain period; transfers still running afterward are closed.
319
-
320
- Send `SIGHUP` to atomically reload public keys, issuer ceilings, upstream token files, deny rules and limits. A failed reload preserves the last valid configuration. Changes to the listener or TLS paths require restart. Replacing an environment variable requires restarting the process. Config reload does not rewrite credentials already in use by an admitted operation.
321
-
322
- For signing-key rotation, add the new public key under a new `id`, reload, and issue tokens with that `-kid`. Keep the old key configured until its tokens have expired, including clock tolerance, if they should remain valid; then remove it and reload. To rotate an upstream file token, replace that file and reload; the gateway reads upstream credentials at startup/reload, unlike the agent helper, which reads its JWT for each credential request.
323
-
324
- Important defaults:
325
-
326
- | Setting | Default |
327
- | --- | --- |
328
- | `max_token_bytes` | 4,096 serialized JWT bytes; configurable up to 32,768 |
329
- | `max_token_lifetime_seconds` | 900 |
330
- | `clock_skew_seconds` | 30 |
331
- | `max_control_bytes` | 4 MiB |
332
- | `max_pack_bytes` | 1 GiB incoming encoded and decoded request body limits |
333
- | `max_concurrent` | 64 active Git requests |
334
- | `request_timeout_seconds` | 1,800 |
335
-
336
- The HTTP server accepts up to 64 KiB of headers. Basic authentication expands a JWT by roughly one-third, so ingress limits must accommodate the configured token budget too. Use `sign -max-token-bytes` with the same budget as the gateway. Oversized grants are rejected, never truncated or broadened.
337
-
338
- Incoming packs are streamed after their command prefix passes authorization. Pack contents are not inspected for file/path rules or commit ancestry.
339
-
340
- Ordinary clone/fetch/push requests need only the upstream Git endpoint. REST lookups are used during push discovery when both the configuration and JWT permit automatic creation. Those API calls share the upstream credential's rate limit; gitvend does not coordinate rate limits across instances.
341
-
342
- ## Troubleshooting
343
-
344
- Start with `gitvend version`, `/healthz`, and `git ls-remote --heads` as shown above. Use the HTTP `X-Request-ID` for authenticated Git requests to correlate a failure with the collected audit logs. Avoid sharing raw credentials or full authorization headers when collecting diagnostics.
345
-
346
- | Symptom | What to check |
347
- | --- | --- |
348
- | Connection refused or TLS certificate error | Confirm the listener interface/port, DNS, certificate hostname and trust chain. The template binds loopback; external agents need a reachable listener or TLS terminator. |
349
- | Git prompts for a password; helper returns no credential | Confirm `gitvend` is on the agent's `PATH`, the JWT file is readable, and the helper's host **and port** match the remote. Configure the helper in that agent's account. |
350
- | HTTP 401 / invalid or expired JWT | Refresh the JWT; check issuer, `kid`, audience, clock, lifetime and byte limits against gateway configuration. Agents use their JWT, not the upstream GitHub token. |
351
- | `Git protocol v2 required` | Set `protocol.version=2`; ensure an ingress proxy preserves the `Git-Protocol` header. Pushes still use standard receive-pack. |
352
- | HTTP 403 / `push denied for ...` | Inspect the exact destination ref, matching `r` plus `w`/`d` grants, issuer/owner limits and gateway denies. The sample denies writes to main/master. |
353
- | No refs shown; clone cannot find main or remote HEAD | The requested branch may be absent or hidden. Use an explicitly permitted branch with `--branch`; new scratch repos may have only `agents/47/start`. |
354
- | HTTP 404 / unsupported route or missing repository | Use `/alias/owner/repo.git`, check allowed owners, and verify the upstream identity can see the repository. Only authorized push discovery can create a missing repo. |
355
- | Missing repo is not created | Check `allow_creation`, `c`, overlapping branch `rw`, owner limits and upstream organization permissions. Check the audit logs for an unconfirmed create attempt. |
356
- | HTTP 429 / gateway busy | The concurrent-request limit is reached. Wait for active requests to finish and retry. |
357
- | HTTP 409 / private profile violation | A creation attempt resolved to a non-private repository. Investigate the upstream name/visibility; gitvend will not alter it automatically. |
358
- | HTTP 502 / upstream request refused or lookup failed | Check the upstream token, Git/API base URLs and forge availability/rate limits. A gateway JWT cannot overcome upstream restrictions. |
359
- | HTTP 503 / repository creation unconfirmed | The create attempt and follow-up lookup could not confirm success. Check upstream access/availability, then retry normal push discovery. |
360
- | HTTP 431 or large token rejected at ingress | Align ingress header limits, server `max_token_bytes` and signing `-max-token-bytes`; Basic authentication expands the token. |
361
- | Push disconnects or audit outcome is `unknown` | Fetch or inspect the permitted remote ref before deciding whether to retry; some or all updates may already have reached GitHub. |
362
- | npm-installed command reports a missing binary | Check whether install scripts were disabled and whether release downloads were reachable; after fixing that, run `npm rebuild @colony2/gitvend`. |
363
-
364
- When upgrading an earlier checkout, remove `state_file`, `creates_per_subject_per_day` and `creates_per_owner_per_day` from configuration. Remove `bindings` from grant files and reissue any JWTs containing that field. Unknown fields are rejected. Old database files are no longer read by the gateway.
365
-
366
- ## CLI reference
367
-
368
- For commands that take flags, use `-h` to list them, for example `gitvend sign -h`. The CLI expects flags before any positional argument; for credential helpers, Git appends the final operation.
369
-
370
- | Command | Purpose / useful flags |
371
- | --- | --- |
372
- | `gitvend version` | Show the release version or development build identity. |
373
- | `gitvend serve -config gitvend.json` | Start the gateway. |
374
- | `gitvend keygen -private signing.key -public signing.pub` | Generate a new issuer key pair without overwriting existing files. Add `-if-missing` to validate/reuse persistent keys or recover a missing public key. Parent directories must exist. |
375
- | `gitvend sign` | Issue a JWT; requires `-key`, `-kid`, `-issuer`, `-subject` and a grant. Use repeated `-permission` **or** `-grant`, not both; `-output` writes an atomic token file. |
376
- | `gitvend credential` | Git helper; specify `-host` and exactly one of `-token-file` or `-token-env`, followed by `get`, `store` or `erase`. |
377
- | `gitvend explain` | Explain explicit `-permission` rules for a `-repo`, optional `-ref`, and `-action`. Ref values are fully qualified, such as `refs/heads/main`. |
378
-
379
- `explain` actions are `repo.read`, `repo.create`, `ref.discover`, `ref.create`, `ref.update` and `ref.delete`. The default is `ref.update`.
380
-
381
- ## Compatibility and verification scope
382
-
383
- The automated tests cover real Git v2 discovery/clone/fetch, shallow and partial clones, known-hash reads, standard pushes, ref filtering, mixed denied pushes, tags, deletion, force updates, atomic and partial push outcomes, creation races/recovery, JWT tampering/expiry/size, secret/key reloads, independent replicas, name-based permissions and malformed/gzip requests. Parser fuzz targets and race checks are included.
384
-
385
- Supported object format is SHA-1. SSH, Git LFS, Git protocol v0/v1 fetch, signed push certificates, push options, named shallow exclusions, ref-in-want, offloaded pack/bundle URLs and provider-managed ref namespaces are rejected or not advertised. Branch writes can include workflow files; CI execution and secrets remain governed by the forge's configuration. GitHub branch rules continue to apply to the shared upstream identity.
386
-
387
- No live GitHub credentials were required for the local suite. Validate the chosen account/token, organization creation policy, workflow permissions and GitHub Enterprise version in a disposable organization before deployment; the local API fixture cannot establish those external permissions.
388
-
389
- The original requirements and implementation tradeoffs are in [the design](docs/git-proxy-design.md). [c2r](https://github.com/colony-2/c2r) informed the repository-provisioning approach. This implementation uses a small direct GitHub adapter; no c2r source was copied.
390
-
391
- ## Release automation
392
-
393
- The [release workflow](.github/workflows/release.yaml) follows [c2j's release pattern](https://github.com/colony-2/c2j/blob/main/.github/workflows/release.yaml). Successful pushes to `main` in the `colony-2` organization run the test suite, automatically bump and push a version tag (patch by default), build four binaries, and publish GitHub release archives and checksums. It then publishes `@colony2/gitvend` to npm after installing and smoke-testing the packed wrapper against the published assets. It also publishes Linux amd64/arm64 container images to `ghcr.io/colony-2/gitvend` with the release tag and `latest`, using `GITHUB_TOKEN` with package-write permission.
44
+ The package installs prebuilt executables; no Go toolchain or source checkout is
45
+ required. npm installation needs Node.js 22+, `tar`, and enabled install scripts.
46
+ The JobDB command is needed only on the host where JobDB launches the plugin.
394
47
 
395
- GitHub release/tag publication uses the workflow's `GITHUB_TOKEN`. Configure npm trusted publishing for `colony-2/gitvend`, workflow `release.yaml`, or provide an `NPM_TOKEN` with publishing access to `@colony2/gitvend`. The npm package must exist and its trusted publisher must be configured before token-free publication can work; bootstrap it with a token if needed.
48
+ For installation without Node.js, download your platform's archive and checksums
49
+ from [GitHub Releases](https://github.com/colony-2/gitvend/releases). Verify the
50
+ archive, extract it, and place the executables you need on `PATH`. Choose a release
51
+ that includes `jobdb-gitvend-secret-provider` when using the plugin; older packages
52
+ may contain only `gitvend`.
396
53
 
397
- macOS signing/notarization is optional. Set all five secrets to enable it: `MACOS_SIGN_P12`, `MACOS_SIGN_PASSWORD`, `APPLE_API_ISSUER`, `APPLE_API_KEY_ID`, and `APPLE_API_KEY`. No signing secrets skips this step; a partial configuration fails the build. Signing requires the matching Apple certificate and notarization credentials.
54
+ For a container deployment, use the published image with the
55
+ [Docker Compose guide](https://github.com/colony-2/gitvend/blob/v0.0.4/docs/docker-compose.md).
398
56
 
399
- The reusable [test workflow](.github/workflows/test.yml) runs Go race tests, vet, parser fuzzing, npm installer tests, and the Docker Compose smoke test. Run the installer tests locally with `npm test --prefix npm/gitvend` and the container checks with `make test-compose`. Release archive smoke tests also check all checksums and run the native binary's `version` command before upload.
57
+ ## Guides
400
58
 
401
- Copied release tooling retains its upstream Apache-2.0 license and attribution in [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md). This repository does not yet declare a project-wide license; npm metadata uses `UNLICENSED`.
59
+ - [Gateway setup, Git usage, and operations](https://github.com/colony-2/gitvend/blob/v0.0.4/docs/gateway.md)
60
+ - [Repository creation controls](https://github.com/colony-2/gitvend/blob/v0.0.4/docs/gateway.md#repository-creation-defaults)
61
+ - [JobDB plugin setup and issuer configuration](https://github.com/colony-2/gitvend/blob/v0.0.4/docs/jobdb-secret-provider.md)
62
+ - [Permission syntax](https://github.com/colony-2/gitvend/blob/v0.0.4/docs/permission-syntax.md)
63
+ - [Docker Compose deployment](https://github.com/colony-2/gitvend/blob/v0.0.4/docs/docker-compose.md)
64
+ - [Developer guide: source builds, tests, and releases](https://github.com/colony-2/gitvend/blob/v0.0.4/docs/development.md)
@@ -0,0 +1,4 @@
1
+ #!/bin/sh
2
+ # Replaced with the native executable by postinstall. JobDB needs no Node runtime.
3
+ echo "Plugin binary is missing. Run npm rebuild @colony2/gitvend." >&2
4
+ exit 1
@@ -0,0 +1,96 @@
1
+ # Developing Gitvend
2
+
3
+ This guide is for contributors and release maintainers. Users can install packages
4
+ and follow the [gateway guide](gateway.md) or [JobDB plugin guide](jobdb-secret-provider.md).
5
+
6
+ ## Build and verify
7
+
8
+ Requires the Go version in `go.mod` and Git for the integration tests. Supported server platforms are Linux and macOS. Run these commands from the source checkout's root:
9
+
10
+ ```sh
11
+ make build
12
+ export PATH="$PWD/bin:$PATH"
13
+ gitvend version
14
+ make check
15
+ ```
16
+
17
+ `make check` runs race tests and vet. `make fuzz` exercises the permission, packet and JSON parsers. The default test suite uses real Git clients and a real `git-http-backend`, with a local GitHub API fixture; it needs neither a GitHub token nor external repository access.
18
+
19
+ ## Install from source
20
+
21
+ For development or an unreleased revision, Go can build and install either command:
22
+
23
+ ```sh
24
+ go install github.com/colony-2/gitvend/cmd/gitvend@latest
25
+ go install github.com/colony-2/gitvend/cmd/jobdb-gitvend-secret-provider@latest
26
+ ```
27
+
28
+ Use a revision containing the desired changes. Add `$(go env GOPATH)/bin` to `PATH`
29
+ if necessary. Local gateway builds report their Git revision when available;
30
+ release builds of both commands report the release version.
31
+
32
+ ## JobDB plugin development
33
+
34
+ ```sh
35
+ make check-jobdb-provider
36
+ ```
37
+
38
+ Tests verify grants and effective expiry with Gitvend's actual verifier, tenant
39
+ and principal checks, metadata injection rejection, concurrent reloads, key
40
+ rotation, invalid-file recovery, and the built executable's real JobDB plugin
41
+ handshake and live reload. The executable lives in
42
+ `cmd/jobdb-gitvend-secret-provider`, with Cobra commands in its `internal/cmd`
43
+ package. Credential issuance and reloads live in the reusable `pkg/jobdbprovider`
44
+ package. `Load` creates a fixed provider; `WatchConfig` creates a reloadable one
45
+ that must be closed when finished. Both implement `jobdb.SecretProvider`.
46
+
47
+ The plugin shares the root Go module and Gitvend signing implementation.
48
+ `go test ./...`, `go vet ./...`, and `make check` include it automatically.
49
+ `make build` builds both executables; `make build-jobdb-provider` builds only
50
+ the plugin. The gateway executable does not import the JobDB provider package.
51
+
52
+ ## Container development
53
+
54
+ From the checkout, build the local image and start Compose:
55
+
56
+ ```sh
57
+ export GITHUB_TOKEN='your-github-access-token'
58
+ GITVEND_IMAGE=gitvend:local docker compose up -d --build
59
+ ```
60
+
61
+ See the [deployment guide](docker-compose.md) for configuration and key handling.
62
+ The published container runs the gateway; JobDB launches its plugin locally on
63
+ its own host, using the release archive or npm package.
64
+
65
+ ## Container tests
66
+
67
+ `make check` tests concurrent initialization, recovery, corrupt state rejection,
68
+ key reuse and token verification, plus the existing gateway suite.
69
+ `make test-compose` builds and tests an isolated Compose project with a fake
70
+ GitHub token environment variable and no local config: startup, health,
71
+ on-demand issuance, volume isolation, denied
72
+ requests, and JWT survival across container recreation. It requires Docker,
73
+ Compose v2 or newer and Python 3, uses no GitHub credentials, and removes only its own
74
+ test volumes. CI runs it before releases.
75
+
76
+ ## Verification scope
77
+
78
+ The automated tests cover real Git v2 discovery/clone/fetch, shallow and partial clones, known-hash reads, standard pushes, ref filtering, mixed denied pushes, tags, deletion, force updates, atomic and partial push outcomes, creation races/recovery, JWT tampering/expiry/size, secret/key reloads, independent replicas, name-based permissions and malformed/gzip requests. Parser fuzz targets and race checks are included.
79
+
80
+ Tests use local fixtures and do not establish live GitHub account permissions.
81
+ The [gateway compatibility section](gateway.md#compatibility) describes supported
82
+ Git features. See the [design](git-proxy-design.md) for requirements and tradeoffs.
83
+ [c2r](https://github.com/colony-2/c2r) informed the provisioning approach; Gitvend
84
+ uses a direct GitHub adapter and copies no c2r source.
85
+
86
+ ## Release automation
87
+
88
+ The [release workflow](../.github/workflows/release.yaml) follows [c2j's release pattern](https://github.com/colony-2/c2j/blob/main/.github/workflows/release.yaml). Successful pushes to `main` in the `colony-2` organization run the test suite, automatically bump and push a version tag (patch by default), build both executables for four platforms, and publish GitHub release archives and checksums. It then publishes `@colony2/gitvend` to npm with `gitvend` and `jobdb-gitvend-secret-provider` commands after installing and smoke-testing the installed commands against the published assets. It also publishes Linux amd64/arm64 container images to `ghcr.io/colony-2/gitvend` with the release tag and `latest`, using `GITHUB_TOKEN` with package-write permission.
89
+
90
+ GitHub release/tag publication uses the workflow's `GITHUB_TOKEN`. Configure npm trusted publishing for `colony-2/gitvend`, workflow `release.yaml`, or provide an `NPM_TOKEN` with publishing access to `@colony2/gitvend`. The npm package must exist and its trusted publisher must be configured before token-free publication can work; bootstrap it with a token if needed.
91
+
92
+ macOS signing/notarization is optional. Set all five secrets to enable it: `MACOS_SIGN_P12`, `MACOS_SIGN_PASSWORD`, `APPLE_API_ISSUER`, `APPLE_API_KEY_ID`, and `APPLE_API_KEY`. No signing secrets skips this step; a partial configuration fails the build. Signing requires the matching Apple certificate and notarization credentials.
93
+
94
+ The reusable [test workflow](../.github/workflows/test.yml) runs Go race tests, vet, parser fuzzing, npm installer tests, and the Docker Compose smoke test. Run the installer tests locally with `npm test --prefix npm/gitvend` and the container checks with `make test-compose`. Release archive smoke tests also check all checksums and run both native executables' `version` commands before upload.
95
+
96
+ Copied release tooling retains its upstream Apache-2.0 license and attribution in [THIRD_PARTY_NOTICES.md](../THIRD_PARTY_NOTICES.md). This repository does not yet declare a project-wide license; npm metadata uses `UNLICENSED`.