@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.
- package/README.md +150 -112
- package/dist/cli.js +606 -26
- package/dist/worker.js +635 -0
- package/package.json +28 -23
package/README.md
CHANGED
|
@@ -1,33 +1,70 @@
|
|
|
1
|
-
# git-me
|
|
2
|
-
|
|
3
|
-
A
|
|
4
|
-
|
|
5
|
-
Built as a TypeScript Cloudflare Worker.
|
|
6
|
-
|
|
7
|
-
##
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
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
|
-
|
|
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
|
|
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`.
|