@0xordek/git-me 0.3.0 → 0.4.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 (4) hide show
  1. package/README.md +150 -112
  2. package/dist/cli.js +606 -26
  3. package/dist/worker.js +635 -0
  4. package/package.json +28 -23
package/README.md CHANGED
@@ -1,33 +1,70 @@
1
- # git-me
2
-
3
- A small self-hosted Git LFS utility for Cloudflare Workers, R2, Durable Objects, and KV-backed legacy-user migration.
4
-
5
- Built as a TypeScript Cloudflare Worker.
6
-
7
- ## Requirements
8
-
9
- - Node.js 22+
10
- - Wrangler CLI or project-local `wrangler`
11
- - Cloudflare account with Workers, R2, KV, and Durable Objects enabled
12
-
13
- ## Quick Start
14
-
15
- ```bash
16
- git clone git@github.com:0xordek/git-me.git
17
- cd git-me
1
+ # git-me
2
+
3
+ A zero-config self-hosted Git LFS service for Cloudflare Workers, R2, Durable Objects, and KV-backed legacy-user migration.
4
+
5
+ Built as a TypeScript Cloudflare Worker.
6
+
7
+ ## Zero-Config Quick Start
8
+
9
+ Requires Node.js 22+ and a Cloudflare account. Wrangler is bundled as the deploy engine; users do not need to install or configure it.
10
+
11
+ ```bash
12
+ npm install -g @0xordek/git-me
13
+ git-me worker deploy
14
+ ```
15
+
16
+ The command opens Cloudflare login, creates the Worker, R2 bucket, KV namespace, and Durable Object migration, generates the admin secret, stores it in the operating system credential store, checks `/health`, and saves a local profile.
17
+
18
+ Use `--account-id <id>` when Cloudflare login has more than one account. A profile name cannot be deployed twice; use another `--profile <name>` for another Worker.
19
+
20
+ Example output:
21
+
22
+ ```text
23
+ Deployed: https://git-me-abc.workers.dev
24
+ Profile: default
25
+ LFS URL: https://git-me-abc.workers.dev
26
+ ```
27
+
28
+ Add and manage users without copying Worker URLs or admin tokens:
29
+
30
+ ```bash
31
+ git-me user add 0xordek --access write
32
+ git-me user list
33
+ git-me user list --json
34
+ git-me user delete 0xordek
35
+ ```
36
+
37
+ Passwords are read from a hidden prompt. For automation, use stdin; secrets are never accepted as command arguments:
38
+
39
+ ```bash
40
+ printf '%s' "$LFS_PASSWORD" | git-me user add 0xordek --access write --password-stdin
41
+ git-me user delete 0xordek --yes
42
+ ```
43
+
44
+ If the operating system credential store is unavailable, pass the admin secret explicitly with `--token-stdin` or `--token-env`.
45
+
46
+ Existing users created before user listing are added to the list after their next successful login; Durable Objects cannot enumerate them safely.
47
+
48
+ ## Quick Start (development)
49
+
50
+ ```bash
51
+ git clone git@github.com:0xordek/git-me.git
52
+ cd git-me
18
53
  npm ci
19
54
  npm run check
20
- ```
21
-
22
- ## Cloudflare Setup
23
-
24
- Create storage resources:
25
-
26
- ```bash
27
- wrangler r2 bucket create git-me-objects
28
- wrangler kv namespace create git-me-metadata
29
- ```
30
-
55
+ ```
56
+
57
+ ## Manual Cloudflare Setup (development/legacy)
58
+
59
+ The zero-config path above is recommended for users. The manual setup remains useful for local Worker development and existing deployments.
60
+
61
+ Create storage resources:
62
+
63
+ ```bash
64
+ wrangler r2 bucket create git-me-objects
65
+ wrangler kv namespace create git-me-metadata
66
+ ```
67
+
31
68
  Wrangler prints the KV namespace id. Create private deployment config, then replace its placeholder ID:
32
69
 
33
70
  ```bash
@@ -35,48 +72,48 @@ cp wrangler.example.toml wrangler.local.toml
35
72
  ```
36
73
 
37
74
  `wrangler.local.toml` is ignored by Git. Before a real deploy, replace its placeholder KV namespace ID with your namespace ID. `npm run deploy` creates the `AuthUser` Durable Object migration.
38
-
75
+
39
76
  Set the admin token as a secret:
40
-
41
- ```bash
42
- wrangler secret put GITME_AUTH_TOKEN
43
- ```
44
-
45
- ## Transfer Modes
46
-
47
- - `proxy`: default mode. The Worker handles Git LFS upload and download bytes through the `PUT /objects/{oid}` and `GET /objects/{oid}` endpoints.
77
+
78
+ ```bash
79
+ wrangler secret put GITME_AUTH_TOKEN
80
+ ```
81
+
82
+ ## Transfer Modes
83
+
84
+ - `proxy`: default mode. The Worker handles Git LFS upload and download bytes through the `PUT /objects/{oid}` and `GET /objects/{oid}` endpoints.
48
85
  - `direct`: opt-in download acceleration. Uploads still use the Worker so every object gets SHA-256 verification; downloads receive short-lived signed R2 `GET` URLs.
49
-
86
+
50
87
  Leave `GITME_TRANSFER_MODE` unset for `proxy`, or set it to `direct` to opt in to signed R2 downloads. Give direct mode a bucket-scoped, read-only R2 S3 API token.
51
-
52
- ## Configuration
53
-
88
+
89
+ ## Configuration
90
+
54
91
  | Name | Required | Purpose |
55
92
  |------|----------|---------|
56
93
  | `GITME_AUTH_TOKEN` | Yes | Admin bearer token for user management and emergency LFS access |
57
94
  | `GITME_TRANSFER_MODE` | No | `proxy` by default; set `direct` for signed R2 downloads |
58
- | `GITME_SIGNED_URL_TTL_SECONDS` | No | Signed URL TTL for `direct` mode; defaults to `900` |
59
- | `GITME_R2_ACCOUNT_ID` | Direct mode | Cloudflare account id for R2 S3-compatible signing |
95
+ | `GITME_SIGNED_URL_TTL_SECONDS` | No | Signed URL TTL for `direct` mode; defaults to `900` |
96
+ | `GITME_R2_ACCOUNT_ID` | Direct mode | Cloudflare account id for R2 S3-compatible signing |
60
97
  | `GITME_R2_ACCESS_KEY_ID` | Direct mode | Read-only R2 API access key id |
61
98
  | `GITME_R2_SECRET_ACCESS_KEY` | Direct mode | Read-only R2 API secret access key |
62
99
  | `GITME_R2_BUCKET_NAME` | Direct mode | R2 bucket used in signed download URLs |
63
-
64
- Use Wrangler secrets for sensitive values:
65
-
66
- ```bash
67
- wrangler secret put GITME_R2_SECRET_ACCESS_KEY
68
- ```
69
-
70
- Deploy:
71
-
72
- ```bash
73
- npm run deploy:dry
74
- npm run deploy
75
- ```
76
-
100
+
101
+ Use Wrangler secrets for sensitive values:
102
+
103
+ ```bash
104
+ wrangler secret put GITME_R2_SECRET_ACCESS_KEY
105
+ ```
106
+
107
+ Deploy:
108
+
109
+ ```bash
110
+ npm run deploy:dry
111
+ npm run deploy
112
+ ```
113
+
77
114
  ## Git LFS Client Setup
78
115
 
79
- Create a user as the deploy admin. Pass secrets through environment variables or standard input, never command arguments:
116
+ For the zero-config flow, use the profile-based commands above. The explicit URL/token form remains available for another machine or when the credential store is unavailable; pass secrets through environment variables or standard input, never command arguments:
80
117
 
81
118
  ```bash
82
119
  read -rsp 'Admin token: ' GITME_ADMIN_TOKEN; echo
@@ -125,23 +162,23 @@ Then use `git push` and `git pull` as normal. On first LFS access, Git asks for
125
162
 
126
163
  The admin bearer token also works for LFS as an emergency write credential, but normal users should use Basic auth users created through `/admin/users/{username}`.
127
164
 
128
- If you do not want the CLI, the same operations are available through `PUT` and `DELETE /admin/users/{username}`.
129
-
130
- ## Migrating Existing LFS Objects
131
-
132
- Use the migration CLI from a local repository to copy objects from the current LFS server into `git-me`:
133
-
165
+ If you do not want the CLI, the same operations are available through `GET /admin/users`, `PUT /admin/users/{username}`, and `DELETE /admin/users/{username}`.
166
+
167
+ ## Migrating Existing LFS Objects
168
+
169
+ Use the migration CLI from a local repository to copy objects from the current LFS server into `git-me`:
170
+
134
171
  ```bash
135
172
  read -rsp 'Target token: ' GITME_TARGET_TOKEN; echo
136
173
  export GITME_TARGET_TOKEN
137
174
  npx @0xordek/git-me migrate --target https://your-worker.workers.dev --token-env GITME_TARGET_TOKEN --dry-run
138
175
  unset GITME_TARGET_TOKEN
139
- ```
140
-
141
- Run `--dry-run` first. It scans local Git LFS pointer files, deduplicates object IDs, and reports `scanned`, `unique`, `migrated`, `skipped`, and `failed` without transferring object bytes or writing Git config.
142
-
143
- For a GitHub source, pass the source LFS URL explicitly when it is not already in `git config lfs.url`:
144
-
176
+ ```
177
+
178
+ Run `--dry-run` first. It scans local Git LFS pointer files, deduplicates object IDs, and reports `scanned`, `unique`, `migrated`, `skipped`, and `failed` without transferring object bytes or writing Git config.
179
+
180
+ For a GitHub source, pass the source LFS URL explicitly when it is not already in `git config lfs.url`:
181
+
145
182
  ```bash
146
183
  read -rsp 'Target token: ' GITME_TARGET_TOKEN; echo
147
184
  export GITME_TARGET_TOKEN
@@ -151,10 +188,10 @@ npx @0xordek/git-me migrate \
151
188
  --token-env GITME_TARGET_TOKEN \
152
189
  --dry-run
153
190
  unset GITME_TARGET_TOKEN
154
- ```
155
-
156
- For another Git LFS server, use its Batch API base URL as `--source-url`:
157
-
191
+ ```
192
+
193
+ For another Git LFS server, use its Batch API base URL as `--source-url`:
194
+
158
195
  ```bash
159
196
  read -rsp 'Target token: ' GITME_TARGET_TOKEN; echo
160
197
  export GITME_TARGET_TOKEN
@@ -164,10 +201,10 @@ npx @0xordek/git-me migrate \
164
201
  --token-env GITME_TARGET_TOKEN \
165
202
  --dry-run
166
203
  unset GITME_TARGET_TOKEN
167
- ```
168
-
204
+ ```
205
+
169
206
  Private source repositories usually require an extra source header. Repeat `--source-header-env` for every environment variable containing a `name: value` header:
170
-
207
+
171
208
  ```bash
172
209
  read -rsp 'Target token: ' GITME_TARGET_TOKEN; echo
173
210
  export GITME_TARGET_TOKEN
@@ -180,10 +217,10 @@ npx @0xordek/git-me migrate \
180
217
  --token-env GITME_TARGET_TOKEN \
181
218
  --dry-run
182
219
  unset GITME_TARGET_TOKEN GITME_SOURCE_AUTH
183
- ```
184
-
185
- After a successful real migration, add `--write-config` to update the repository's `lfs.url` to the target:
186
-
220
+ ```
221
+
222
+ After a successful real migration, add `--write-config` to update the repository's `lfs.url` to the target:
223
+
187
224
  ```bash
188
225
  read -rsp 'Target token: ' GITME_TARGET_TOKEN; echo
189
226
  export GITME_TARGET_TOKEN
@@ -192,39 +229,40 @@ npx @0xordek/git-me migrate \
192
229
  --token-env GITME_TARGET_TOKEN \
193
230
  --write-config
194
231
  unset GITME_TARGET_TOKEN
195
- ```
196
-
197
- Safety model: the CLI uses the generic Git LFS Batch API for source downloads and target uploads. Object bytes are streamed through temporary files named `git-me-migrate-*` in the OS temp directory, not buffered in memory, and each downloaded file must match the pointer SHA-256 OID before upload. Temporary files are removed after each object attempt, and `--write-config` only runs when the migration has no failures.
198
-
199
- ## API Endpoints
200
-
201
- | Method | Path | Purpose |
202
- |--------|------|---------|
232
+ ```
233
+
234
+ Safety model: the CLI uses the generic Git LFS Batch API for source downloads and target uploads. Object bytes are streamed through temporary files named `git-me-migrate-*` in the OS temp directory, not buffered in memory, and each downloaded file must match the pointer SHA-256 OID before upload. Temporary files are removed after each object attempt, and `--write-config` only runs when the migration has no failures.
235
+
236
+ ## API Endpoints
237
+
238
+ | Method | Path | Purpose |
239
+ |--------|------|---------|
203
240
  | POST | `/objects/batch` | Git LFS Batch API |
204
241
  | PUT | `/objects/{oid}` | Upload object bytes |
205
242
  | GET | `/objects/{oid}` | Download object bytes |
206
243
  | PUT | `/admin/users/{username}` | Create or update LFS user |
244
+ | GET | `/admin/users` | List usernames and access levels |
207
245
  | DELETE | `/admin/users/{username}` | Delete LFS user |
208
246
  | GET | `/health` | Configuration health check |
209
-
210
- Batch requests and error responses use `application/vnd.git-lfs+json`.
211
- `GET /health` returns `application/json`.
212
-
213
- ## Storage Layout
214
-
247
+
248
+ Batch requests and error responses use `application/vnd.git-lfs+json`.
249
+ `GET /health` returns `application/json`.
250
+
251
+ ## Storage Layout
252
+
215
253
  - R2 object key: `objects/<oid>`
216
254
  - Temporary proxy-upload key prefix: `objects/.tmp/`
217
- - Durable Object: one `AuthUser` instance per normalized username
255
+ - Durable Object: one `AuthUser` instance per normalized username, plus reserved `admin:users` instance for the serialized admin index
218
256
  - KV user key: `user:<username>` only during legacy SHA-256 credential upgrade
219
-
220
- ## Development
221
-
222
- ```bash
257
+
258
+ ## Development
259
+
260
+ ```bash
223
261
  npm ci
224
262
  npm run check
225
263
  wrangler dev --config wrangler.local.toml
226
- ```
227
-
264
+ ```
265
+
228
266
  ## Security
229
267
 
230
268
  Do not commit auth tokens or R2 API secrets. Use `wrangler secret put GITME_AUTH_TOKEN` and `wrangler secret put GITME_R2_SECRET_ACCESS_KEY`.
@@ -236,13 +274,13 @@ Existing deployments upgraded from a release that signed direct uploads must fir
236
274
  New passwords use salted PBKDF2-SHA-256 records in Durable Objects. Existing KV SHA-256 records upgrade after one successful login. Deleted users leave a Durable Object tombstone, so stale KV reads cannot restore access. Authentication locks one client source for one username for one minute after five failed attempts in one minute.
237
275
 
238
276
  `GET /health` checks configuration only. It does not prove R2, KV, or Durable Object availability. Failed requests emit a request ID in `X-Request-Id`; logs never include credentials or request bodies.
239
-
240
- Report vulnerabilities through GitHub Security Advisories. See `SECURITY.md`.
241
-
242
- ## Contributing
243
-
244
- Small fixes and focused issues are welcome. See `CONTRIBUTING.md`.
245
-
246
- ## License
247
-
248
- MIT — see `LICENSE`.
277
+
278
+ Report vulnerabilities through GitHub Security Advisories. See `SECURITY.md`.
279
+
280
+ ## Contributing
281
+
282
+ Small fixes and focused issues are welcome. See `CONTRIBUTING.md`.
283
+
284
+ ## License
285
+
286
+ MIT — see `LICENSE`.