firevault 0.2.0-beta.0 → 0.2.0-beta.1

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.
@@ -0,0 +1,418 @@
1
+ # firevault doctor Design
2
+
3
+ `firevault doctor` should answer:
4
+
5
+ > Is my Firevault setup correctly configured?
6
+
7
+ This is different from `firevault status`.
8
+
9
+ - `status` is the current operational state: compact, confidence-oriented, and useful for quick checks.
10
+ - `doctor` is validation: more detailed, actionable, and focused on fixes.
11
+
12
+ ## Scope
13
+
14
+ First version: local validation only.
15
+
16
+ Doctor must not:
17
+
18
+ - contact Firebase,
19
+ - call GitHub APIs,
20
+ - use the network,
21
+ - write files,
22
+ - stage,
23
+ - commit,
24
+ - push,
25
+ - print secrets.
26
+
27
+ ## Output Shape
28
+
29
+ Output should be grouped but still compact:
30
+
31
+ ```txt
32
+ Firevault doctor
33
+
34
+ OK Workspace found
35
+ OK Config valid
36
+ WARN No Git remote origin configured
37
+ FAIL Service account file missing
38
+
39
+ Next fixes:
40
+ 1. Save your Firebase service account JSON to .firevault/serviceAccountKey.json
41
+ 2. Add Git remote:
42
+ git -C .firevault remote add origin <private-repo-url>
43
+ ```
44
+
45
+ Use clear severity:
46
+
47
+ - `OK`: check passed.
48
+ - `WARN`: setup can work locally but recovery posture is weaker.
49
+ - `FAIL`: setup is incomplete or unsafe enough that normal recovery workflows may fail.
50
+
51
+ Exit codes:
52
+
53
+ - `0` if all checks are `OK`.
54
+ - `1` if warnings are present and no checks fail.
55
+ - `2` if any `FAIL`.
56
+
57
+ ## Checks
58
+
59
+ ### Workspace
60
+
61
+ Checks:
62
+
63
+ - `.firevault/config.json` can be discovered from the current directory.
64
+
65
+ Result:
66
+
67
+ - `OK Workspace found`
68
+ - `FAIL Workspace not found`
69
+
70
+ Fix:
71
+
72
+ ```txt
73
+ Run `firevault init`
74
+ ```
75
+
76
+ ### Config
77
+
78
+ Checks:
79
+
80
+ - config file exists,
81
+ - JSON parses,
82
+ - required fields are present:
83
+ - `projectId`,
84
+ - `serviceAccountPath`,
85
+ - `outputDir`,
86
+ - `collections`,
87
+ - `collections` is a non-empty string array.
88
+
89
+ Reuse `loadConfig()` for validation.
90
+
91
+ Result:
92
+
93
+ - `OK Config valid`
94
+ - `FAIL Config invalid`
95
+
96
+ Fix:
97
+
98
+ ```txt
99
+ Edit .firevault/config.json or rerun `firevault init --force`
100
+ ```
101
+
102
+ ### Service Account File
103
+
104
+ Checks:
105
+
106
+ - configured `serviceAccountPath` resolves inside `.firevault`,
107
+ - file exists.
108
+
109
+ Do not parse the service account JSON in the first version. Parsing is local, but it starts pulling doctor toward credential validation. Save that for a later `--verify` mode.
110
+
111
+ Result:
112
+
113
+ - `OK Service account file present`
114
+ - `FAIL Service account file missing`
115
+
116
+ Fix:
117
+
118
+ ```txt
119
+ Save your Firebase service account JSON to .firevault/serviceAccountKey.json
120
+ ```
121
+
122
+ Use the actual configured relative path in output. Never print file contents.
123
+
124
+ ### Backup Output Directory
125
+
126
+ Checks:
127
+
128
+ - configured output directory exists, or
129
+ - parent workspace exists and the path could be created by normal backup flow.
130
+
131
+ Because doctor is read-only, it should not create the directory.
132
+
133
+ Result:
134
+
135
+ - `OK Backup output directory exists`
136
+ - `WARN Backup output directory has not been created yet`
137
+ - `FAIL Backup output path is unsafe or outside .firevault`
138
+
139
+ Fix:
140
+
141
+ ```txt
142
+ Run `firevault snapshot`
143
+ ```
144
+
145
+ ### Workspace Git Repository
146
+
147
+ Checks:
148
+
149
+ - `.firevault` is a Git repository.
150
+
151
+ Result:
152
+
153
+ - `OK .firevault Git repository found`
154
+ - `FAIL .firevault is not a Git repository`
155
+
156
+ Fix:
157
+
158
+ ```txt
159
+ git -C .firevault init
160
+ ```
161
+
162
+ ### Remote Origin
163
+
164
+ Checks:
165
+
166
+ - `.firevault` has `origin` configured.
167
+
168
+ Do not call `git fetch`.
169
+
170
+ Result:
171
+
172
+ - `OK Git remote origin configured`
173
+ - `WARN No Git remote origin configured`
174
+
175
+ Fix:
176
+
177
+ ```txt
178
+ git -C .firevault remote add origin <private-repo-url>
179
+ ```
180
+
181
+ ### GitHub Actions Workflow
182
+
183
+ Checks:
184
+
185
+ - `.firevault/.github/workflows/firevault-snapshot.yml` exists,
186
+ - contains `schedule:`,
187
+ - contains `workflow_dispatch:`,
188
+ - contains `FIREVAULT_SERVICE_ACCOUNT_JSON`,
189
+ - contains `firevault snapshot`.
190
+
191
+ This should remain text-based in the first version. A YAML parser is not required yet unless false positives become a problem.
192
+
193
+ Result:
194
+
195
+ - `OK GitHub Actions workflow configured`
196
+ - `WARN GitHub Actions workflow missing`
197
+ - `WARN GitHub Actions workflow missing schedule trigger`
198
+ - `WARN GitHub Actions workflow missing manual dispatch`
199
+ - `WARN GitHub Actions workflow missing FIREVAULT_SERVICE_ACCOUNT_JSON`
200
+ - `WARN GitHub Actions workflow missing firevault snapshot`
201
+
202
+ Fix:
203
+
204
+ ```txt
205
+ Run `firevault setup-github-action`
206
+ ```
207
+
208
+ If the file exists but is incomplete:
209
+
210
+ ```txt
211
+ Review .firevault/.github/workflows/firevault-snapshot.yml or rerun `firevault setup-github-action --force`
212
+ ```
213
+
214
+ ### Service Account Ignored
215
+
216
+ Checks:
217
+
218
+ - `.firevault/.gitignore` exists,
219
+ - configured service account path is ignored by Git.
220
+
221
+ Best check:
222
+
223
+ ```bash
224
+ git -C .firevault check-ignore <serviceAccountPath>
225
+ ```
226
+
227
+ Fallback:
228
+
229
+ - read `.firevault/.gitignore`,
230
+ - look for exact configured service account path or basename.
231
+
232
+ Result:
233
+
234
+ - `OK Service account file ignored`
235
+ - `FAIL Service account file is not ignored`
236
+
237
+ Fix:
238
+
239
+ ```txt
240
+ Add serviceAccountKey.json to .firevault/.gitignore
241
+ ```
242
+
243
+ Use configured path in output.
244
+
245
+ ### Parent App Repo Ignores .firevault
246
+
247
+ Checks:
248
+
249
+ - parent app repo exists,
250
+ - parent app repo ignores `.firevault/`.
251
+
252
+ Best check:
253
+
254
+ ```bash
255
+ git -C <app-root> check-ignore .firevault
256
+ ```
257
+
258
+ If parent app is not a Git repo, this can be a warning rather than failure.
259
+
260
+ Result:
261
+
262
+ - `OK Parent app repo ignores .firevault/`
263
+ - `WARN Parent app directory is not a Git repository`
264
+ - `FAIL Parent app repo does not ignore .firevault/`
265
+
266
+ Fix:
267
+
268
+ ```txt
269
+ Add .firevault/ to .gitignore
270
+ ```
271
+
272
+ ### Secret Files Tracked By Git
273
+
274
+ Checks:
275
+
276
+ - no obvious credential or environment files are tracked in `.firevault` Git.
277
+
278
+ Candidate tracked paths:
279
+
280
+ - configured `serviceAccountPath`,
281
+ - `serviceAccountKey.json`,
282
+ - `service-account.json`,
283
+ - `firebase-service-account.json`,
284
+ - `credentials/firebase.json`,
285
+ - `.env`,
286
+ - `.env.*`,
287
+ - `*.pem`,
288
+ - `*.key`.
289
+
290
+ Use local Git only:
291
+
292
+ ```bash
293
+ git -C .firevault ls-files
294
+ ```
295
+
296
+ Result:
297
+
298
+ - `OK No obvious secret files tracked`
299
+ - `FAIL Possible secret files tracked`
300
+
301
+ Fix:
302
+
303
+ ```txt
304
+ Remove tracked secret files from Git history and rotate exposed credentials.
305
+ ```
306
+
307
+ Be careful not to print secret contents. Printing suspicious file paths is acceptable.
308
+
309
+ ### Backup Directory Not Ignored
310
+
311
+ Checks:
312
+
313
+ - configured backup output directory is not ignored inside `.firevault`.
314
+
315
+ Use:
316
+
317
+ ```bash
318
+ git -C .firevault check-ignore <outputDir>
319
+ ```
320
+
321
+ Result:
322
+
323
+ - `OK Backup directory is trackable`
324
+ - `FAIL Backup directory is ignored`
325
+
326
+ Fix:
327
+
328
+ ```txt
329
+ Remove firestore-backups/ from .firevault/.gitignore
330
+ ```
331
+
332
+ Use configured path in output.
333
+
334
+ ### Working Tree State
335
+
336
+ Checks:
337
+
338
+ - `.firevault` working tree clean or dirty,
339
+ - uncommitted backup changes under `outputDir`.
340
+
341
+ Result:
342
+
343
+ - `OK Working tree clean`
344
+ - `WARN Working tree has uncommitted changes`
345
+ - `WARN Backup output has uncommitted changes`
346
+
347
+ Fix:
348
+
349
+ ```txt
350
+ Run `firevault commit` after reviewing changes
351
+ ```
352
+
353
+ Doctor should report dirty state clearly but not treat it as a failure.
354
+
355
+ ## Suggested Implementation Shape
356
+
357
+ Likely files:
358
+
359
+ - `src/commands/doctor.ts`
360
+ - `src/index.ts`
361
+ - `src/git/git.ts`
362
+ - `package.json`
363
+ - `README.md`
364
+ - `docs/roadmap.md`
365
+ - `docs/doctor-design.md`
366
+
367
+ Useful shared types:
368
+
369
+ ```ts
370
+ type DoctorSeverity = "OK" | "WARN" | "FAIL";
371
+
372
+ interface DoctorCheck {
373
+ severity: DoctorSeverity;
374
+ label: string;
375
+ fix?: string;
376
+ }
377
+ ```
378
+
379
+ Formatting should be intentionally simple:
380
+
381
+ ```txt
382
+ OK Config valid
383
+ WARN No Git remote origin configured
384
+ FAIL Service account file missing
385
+ ```
386
+
387
+ ## Relationship To status
388
+
389
+ `status` should stay compact and operational.
390
+
391
+ `doctor` can be more explicit:
392
+
393
+ - reports all setup issues,
394
+ - lists fixes,
395
+ - may have more checks,
396
+ - can return non-zero when failures exist.
397
+
398
+ `status` should not grow into doctor.
399
+
400
+ ## Future Extensions
401
+
402
+ Later versions can add:
403
+
404
+ - `firevault doctor --verify`
405
+ - parse service account JSON,
406
+ - connect to Firestore,
407
+ - verify configured collections exist,
408
+ - verify read permissions,
409
+ - never write to Firestore.
410
+ - GitHub API-backed checks:
411
+ - repository visibility,
412
+ - Actions enabled,
413
+ - secret exists,
414
+ - latest workflow run status.
415
+ - structured output:
416
+ - `firevault doctor --json`.
417
+
418
+ These should not be part of the first doctor implementation.
@@ -0,0 +1,317 @@
1
+ # GitHub Actions Automation Design
2
+
3
+ Firevault should help users create scheduled offsite Firestore snapshots using GitHub Actions.
4
+
5
+ This is Phase 2 automation awareness and setup. It should stay local and explicit.
6
+
7
+ ## Goal
8
+
9
+ Enable this model:
10
+
11
+ ```txt
12
+ my-app/
13
+ .firevault/
14
+ config.json
15
+ firestore-backups/
16
+ .git/
17
+ .github/workflows/firevault-snapshot.yml
18
+ ```
19
+
20
+ The `.firevault` workspace is its own Git repository. Users push that repository to a private GitHub repository for offsite recovery history.
21
+
22
+ The workflow should:
23
+
24
+ 1. Run on a schedule.
25
+ 2. Install Node.
26
+ 3. Install Firevault.
27
+ 4. Write service account JSON from a GitHub secret.
28
+ 5. Run `firevault snapshot`.
29
+ 6. Push a commit only if backup files changed.
30
+
31
+ ## Command Name
32
+
33
+ Recommended command:
34
+
35
+ ```bash
36
+ firevault setup-github-action
37
+ ```
38
+
39
+ Reasoning:
40
+
41
+ - explicit that this is GitHub-specific,
42
+ - clear that it creates a GitHub Actions workflow,
43
+ - avoids implying broader automation support,
44
+ - leaves room for future commands like `setup-gitlab-ci` without hiding provider-specific behavior.
45
+
46
+ `firevault setup-action` is shorter, but too generic. Firevault should avoid multi-platform abstraction until the core recovery workflow is stable.
47
+
48
+ ## Workflow Location
49
+
50
+ The workflow should be written inside the `.firevault` repository:
51
+
52
+ ```txt
53
+ .firevault/.github/workflows/firevault-snapshot.yml
54
+ ```
55
+
56
+ This keeps automation with the recovery repo, not the parent application repo.
57
+
58
+ ## Firevault Version In Workflow
59
+
60
+ Default recommendation:
61
+
62
+ ```bash
63
+ npm install -g firevault@next
64
+ ```
65
+
66
+ For early prerelease dogfooding, `@next` matches the current publishing model and avoids silently installing an older stable line once one exists.
67
+
68
+ Later, setup can support:
69
+
70
+ - `--version exact` to pin the currently installed CLI version,
71
+ - `--tag next` as the default prerelease tag,
72
+ - `--tag latest` once Firevault has a stable release.
73
+
74
+ The generated workflow currently installs `firevault@next`.
75
+
76
+ ## Secret Name
77
+
78
+ Recommended secret:
79
+
80
+ ```txt
81
+ FIREVAULT_SERVICE_ACCOUNT_JSON
82
+ ```
83
+
84
+ This name is specific enough to avoid collision with application secrets and clear enough for GitHub repository settings.
85
+
86
+ The workflow should write it to the configured service account path:
87
+
88
+ ```bash
89
+ printf '%s' "$FIREVAULT_SERVICE_ACCOUNT_JSON" > .firevault/serviceAccountKey.json
90
+ ```
91
+
92
+ In GitHub Actions syntax, prefer reading from `secrets.FIREVAULT_SERVICE_ACCOUNT_JSON` into an environment variable for one step only.
93
+
94
+ ## Schedule
95
+
96
+ Default schedule:
97
+
98
+ ```yaml
99
+ on:
100
+ schedule:
101
+ - cron: "0 3 * * *"
102
+ workflow_dispatch:
103
+ ```
104
+
105
+ Daily is the right default because:
106
+
107
+ - it is simple,
108
+ - it limits operational cost and noise,
109
+ - it is enough for initial dogfooding,
110
+ - users can run manually through `workflow_dispatch`.
111
+
112
+ Custom cron should be supported later with:
113
+
114
+ ```bash
115
+ firevault setup-github-action --cron "0 */6 * * *"
116
+ ```
117
+
118
+ Do not add cron customization in the first implementation unless it stays very small.
119
+
120
+ ## Setup Behavior
121
+
122
+ Phase 2 setup should create only the local workflow file and print next steps.
123
+
124
+ It should not:
125
+
126
+ - create GitHub repositories,
127
+ - call GitHub APIs,
128
+ - create or set GitHub secrets,
129
+ - push,
130
+ - stage,
131
+ - commit,
132
+ - store secrets.
133
+
134
+ After writing the workflow, print concise next steps:
135
+
136
+ ```txt
137
+ Created .firevault/.github/workflows/firevault-snapshot.yml
138
+
139
+ Next steps:
140
+ 1. Push .firevault to a private GitHub repository.
141
+ 2. Add GitHub secret FIREVAULT_SERVICE_ACCOUNT_JSON with the full service account JSON.
142
+ 3. Review and commit the workflow file yourself.
143
+ 4. Run the workflow manually once before relying on the schedule.
144
+ ```
145
+
146
+ ## Manual Commit Policy
147
+
148
+ Firevault should not commit the workflow automatically.
149
+
150
+ Rationale:
151
+
152
+ - this is infrastructure configuration,
153
+ - users must review secret handling,
154
+ - Firevault and AI agents must not create commits automatically,
155
+ - the current product posture keeps Git writes explicit.
156
+
157
+ ## Secret Safety
158
+
159
+ The workflow must avoid exposing service account JSON.
160
+
161
+ Rules:
162
+
163
+ - never echo the secret,
164
+ - never print the generated credential file,
165
+ - write the secret directly to the configured service account path,
166
+ - ensure `.firevault/.gitignore` ignores the service account path,
167
+ - remove the credential file at the end of the job if practical,
168
+ - do not upload backup artifacts containing credentials,
169
+ - do not put the JSON in workflow YAML.
170
+
171
+ The setup command should validate only local file paths and text generation. It should not inspect or store the secret value.
172
+
173
+ ## GitHub-Specific Without GitHub API Dependency
174
+
175
+ Keep this as a local workflow-file generator.
176
+
177
+ Provider-specific assumptions are acceptable in the generated YAML and command name, but Firevault should not depend on GitHub APIs for setup.
178
+
179
+ This means:
180
+
181
+ - no GitHub token required,
182
+ - no `gh` dependency,
183
+ - no repository creation,
184
+ - no secret creation,
185
+ - no workflow run polling.
186
+
187
+ ## Push Logic
188
+
189
+ The workflow should commit and push only when backup files changed.
190
+
191
+ Sketch:
192
+
193
+ ```yaml
194
+ - name: Run snapshot
195
+ run: firevault snapshot
196
+
197
+ - name: Push backup commit
198
+ run: |
199
+ if git diff --quiet origin/main..HEAD; then
200
+ echo "No new backup commit to push."
201
+ exit 0
202
+ fi
203
+
204
+ git push
205
+ ```
206
+
207
+ Implementation should be careful here because `firevault snapshot` may create a commit only when backup files changed. The workflow needs to distinguish:
208
+
209
+ - no changes: do nothing,
210
+ - local backup commit created: push,
211
+ - command failed: fail the workflow.
212
+
213
+ The exact push check should be verified in a temporary Git repository before shipping.
214
+
215
+ ## Status Detection
216
+
217
+ `firevault status` should detect Phase 2 by local file existence first:
218
+
219
+ ```txt
220
+ .firevault/.github/workflows/firevault-snapshot.yml
221
+ ```
222
+
223
+ Phase 2 status awareness can later inspect workflow text and report:
224
+
225
+ - scheduled trigger present,
226
+ - `workflow_dispatch` present,
227
+ - `firevault snapshot` present,
228
+ - `FIREVAULT_SERVICE_ACCOUNT_JSON` referenced,
229
+ - workflow installed but not validated.
230
+
231
+ No GitHub API calls should be used by `status` in Phase 2.
232
+
233
+ ## Initial Workflow Shape
234
+
235
+ Draft workflow:
236
+
237
+ ```yaml
238
+ name: Firevault snapshot
239
+
240
+ on:
241
+ schedule:
242
+ - cron: "0 3 * * *"
243
+ workflow_dispatch:
244
+
245
+ permissions:
246
+ contents: write
247
+
248
+ jobs:
249
+ snapshot:
250
+ runs-on: ubuntu-latest
251
+
252
+ steps:
253
+ - name: Check out recovery repository
254
+ uses: actions/checkout@v4
255
+ with:
256
+ path: .firevault
257
+ fetch-depth: 0
258
+
259
+ - name: Set up Node
260
+ uses: actions/setup-node@v4
261
+ with:
262
+ node-version: "22"
263
+
264
+ - name: Install Firevault
265
+ run: npm install -g firevault@next
266
+
267
+ - name: Write Firebase service account
268
+ env:
269
+ FIREVAULT_SERVICE_ACCOUNT_JSON: ${{ secrets.FIREVAULT_SERVICE_ACCOUNT_JSON }}
270
+ run: |
271
+ mkdir -p "$(dirname ".firevault/serviceAccountKey.json")"
272
+ printf '%s' "$FIREVAULT_SERVICE_ACCOUNT_JSON" > ".firevault/serviceAccountKey.json"
273
+
274
+ - name: Configure Git author
275
+ working-directory: .firevault
276
+ run: |
277
+ git config user.name "firevault"
278
+ git config user.email "firevault@users.noreply.github.com"
279
+
280
+ - name: Run snapshot
281
+ run: firevault snapshot
282
+
283
+ - name: Push backup commit
284
+ working-directory: .firevault
285
+ run: |
286
+ branch="$(git rev-parse --abbrev-ref HEAD)"
287
+
288
+ if git rev-parse --verify "origin/$branch" >/dev/null 2>&1; then
289
+ commits_to_push="$(git rev-list --count "origin/$branch..HEAD")"
290
+
291
+ if [ "$commits_to_push" = "0" ]; then
292
+ echo "No new backup commit to push."
293
+ exit 0
294
+ fi
295
+ fi
296
+
297
+ git push origin "HEAD:$branch"
298
+
299
+ - name: Remove service account file
300
+ if: always()
301
+ run: rm -f ".firevault/serviceAccountKey.json"
302
+ ```
303
+
304
+ The implementation avoids hardcoding `main` by using `git rev-parse --abbrev-ref HEAD` in the checked-out recovery repository.
305
+
306
+ ## First Implementation Files
307
+
308
+ Likely files:
309
+
310
+ - `src/commands/setupGithubAction.ts`
311
+ - `src/index.ts`
312
+ - `package.json`
313
+ - `README.md`
314
+ - `docs/roadmap.md`
315
+ - `docs/status-design.md`
316
+
317
+ Tests should use temporary directories and local file reads only. No Firebase emulator is required for workflow generation.