@rizom/ops 0.2.0-alpha.44 → 0.2.0-alpha.440

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 (70) hide show
  1. package/README.md +82 -1
  2. package/dist/age-key-bootstrap.d.ts +1 -1
  3. package/dist/brains-ops.js +736 -335
  4. package/dist/capability-bundle-migration.d.ts +22 -0
  5. package/dist/cert-bootstrap.d.ts +4 -2
  6. package/dist/content-repo-ref.d.ts +10 -0
  7. package/dist/content-repo.d.ts +1 -1
  8. package/dist/deploy.js +110 -166
  9. package/dist/directory-sync-stress-system.d.ts +75 -0
  10. package/dist/directory-sync-stress.d.ts +117 -0
  11. package/dist/entries/deploy.d.ts +4 -2
  12. package/dist/health-watchdog-smoke.d.ts +54 -0
  13. package/dist/image-inventory.d.ts +4 -0
  14. package/dist/image-types.d.ts +7 -0
  15. package/dist/images.d.ts +82 -0
  16. package/dist/index.d.ts +8 -0
  17. package/dist/index.js +736 -323
  18. package/dist/legacy-pilot-migration.d.ts +11 -0
  19. package/dist/legacy-projection-job-recovery.d.ts +29 -0
  20. package/dist/load-registry.d.ts +61 -6
  21. package/dist/observed-status.d.ts +1 -1
  22. package/dist/parse-args.d.ts +2 -12
  23. package/dist/preview-domain.d.ts +9 -0
  24. package/dist/reconcile-dry-run.d.ts +9 -0
  25. package/dist/run-command.d.ts +20 -4
  26. package/dist/schema.d.ts +126 -163
  27. package/dist/secrets-encrypt.d.ts +7 -13
  28. package/dist/secrets-push.d.ts +1 -1
  29. package/dist/ssh-key-bootstrap.d.ts +1 -26
  30. package/dist/stage-legacy-crossover.d.ts +25 -0
  31. package/dist/stress-command.d.ts +14 -0
  32. package/dist/stress-git-checkout.d.ts +21 -0
  33. package/dist/stress-health-monitor.d.ts +46 -0
  34. package/dist/upgrade.d.ts +10 -0
  35. package/dist/user-offboard.d.ts +61 -0
  36. package/dist/verify-user.d.ts +22 -0
  37. package/package.json +50 -42
  38. package/templates/rover-pilot/.env.schema +20 -5
  39. package/templates/rover-pilot/.github/actions/varlock-env/action.yml +47 -0
  40. package/templates/rover-pilot/.github/workflows/build.yml +70 -17
  41. package/templates/rover-pilot/.github/workflows/deploy.yml +74 -57
  42. package/templates/rover-pilot/.github/workflows/directory-sync-stress.yml +119 -0
  43. package/templates/rover-pilot/.github/workflows/health-watchdog-smoke.yml +95 -0
  44. package/templates/rover-pilot/.github/workflows/offboard.yml +107 -0
  45. package/templates/rover-pilot/.github/workflows/reconcile.yml +10 -4
  46. package/templates/rover-pilot/.github/workflows/upgrade.yml +104 -0
  47. package/templates/rover-pilot/README.md +13 -5
  48. package/templates/rover-pilot/deploy/scripts/create-predeploy-backup.ts +936 -0
  49. package/templates/rover-pilot/deploy/scripts/decrypt-user-secrets.ts +80 -24
  50. package/templates/rover-pilot/deploy/scripts/helpers.ts +2 -0
  51. package/templates/rover-pilot/deploy/scripts/install-health-watchdog.ts +144 -0
  52. package/templates/rover-pilot/deploy/scripts/provision-server.ts +51 -21
  53. package/templates/rover-pilot/deploy/scripts/resolve-deploy-handles.ts +4 -0
  54. package/templates/rover-pilot/deploy/scripts/resolve-missing-images.ts +13 -0
  55. package/templates/rover-pilot/deploy/scripts/resolve-user-config.ts +40 -9
  56. package/templates/rover-pilot/deploy/scripts/sync-content-repo.ts +51 -47
  57. package/templates/rover-pilot/deploy/scripts/update-dns.ts +72 -16
  58. package/templates/rover-pilot/deploy/scripts/validate-secrets.ts +12 -1
  59. package/templates/rover-pilot/deploy/scripts/verify-runtime-image.ts +18 -0
  60. package/templates/rover-pilot/docs/canonical-crossover-record.md +107 -0
  61. package/templates/rover-pilot/docs/onboarding-checklist.md +23 -14
  62. package/templates/rover-pilot/docs/operator-playbook.md +357 -29
  63. package/templates/rover-pilot/docs/user-onboarding.md +48 -463
  64. package/templates/rover-pilot/package.json +1 -0
  65. package/templates/rover-pilot/pilot.yaml +6 -4
  66. package/dist/origin-ca.d.ts +0 -1
  67. package/dist/push-secrets.d.ts +0 -9
  68. package/dist/push-target.d.ts +0 -2
  69. package/dist/run-subprocess.d.ts +0 -6
  70. package/templates/rover-pilot/.kamal/hooks/pre-deploy +0 -9
package/README.md CHANGED
@@ -2,10 +2,19 @@
2
2
 
3
3
  Operator CLI package for managing pilot brain fleet registry repos.
4
4
 
5
+ ## Runtime images
6
+
7
+ The fleet builds one immutable `brain-${brainVersion}` image per effective Brain version. Every new image includes the union of exact site and theme package pins across the entire fleet, including users still running older Brain versions. Smoke-to-fleet promotion therefore reuses the same image without changing package pins or publishing another Brain release. Conflicting pins fail before build, even across cohorts on different Brain versions.
8
+
9
+ Before reusing an existing image, Build verifies its actual installed Brain and package versions against its current adopters. Deploy independently verifies the selected instance's requirements before provisioning or replacing containers, including manual deploys. Verification runs only a manifest-reading command in a read-only, network-disabled container on the CI runner; it never starts the Brain or mounts fleet data. Missing packages, mismatched versions, and verification failures stop the workflow. Existing images are not required to serve cohorts that have not adopted them yet.
10
+
11
+ Explicit builds also load the fleet registry and include its complete package union; `site_packages` adds extra exact pins rather than replacing the union. Package-set changes after an image was published may make that immutable image unsuitable: the gates reject reuse rather than silently rebuilding it. Recovery of an already deployed incomplete image requires a separately reviewed artifact recovery plan.
12
+
5
13
  ## Commands
6
14
 
7
15
  - `brains-ops init <repo>`
8
- - `brains-ops render <repo>` — regenerates `views/users.md` and fills status columns from built-in live probes (`DNS`, `/health`, unauthenticated `/mcp`)
16
+ - `brains-ops crossover:stage <source-repo> <output-dir> <bundle-review.yaml> [site-pins.yaml]` — creates a separate secret-free capability-bundle review copy without mutating the source; the bundle review must match every explicit source selection, and a reviewed pins file is required when hosted site overrides exist
17
+ - `brains-ops render <repo>` — regenerates `views/users.md` and fills status columns from built-in live probes (`DNS`, `/health/ready`, unauthenticated `/mcp`)
9
18
  - `brains-ops user:add <repo> <handle> --cohort <cohort>` — scaffolds a user file, per-user secrets template, and cohort membership
10
19
  - `brains-ops onboard <repo> <handle>` — creates/seeds the user's content repo using `CONTENT_REPO_ADMIN_TOKEN` for GitHub repo administration and `GIT_SYNC_TOKEN` for git clone/push
11
20
  - `brains-ops age-key:bootstrap <repo>`
@@ -13,13 +22,85 @@ Operator CLI package for managing pilot brain fleet registry repos.
13
22
  - `brains-ops cert:bootstrap <repo>`
14
23
  - `brains-ops secrets:push <repo>`
15
24
  - `brains-ops secrets:encrypt <repo> <handle>`
25
+ - `brains-ops verify-user <repo> <handle>` — checks `/health/operate`, unauthenticated `/mcp`, and site-enabled browser/Studio routes
26
+ - `brains-ops recover:retire-legacy-projection-job <database> <job-id> --type <legacy-type> --dry-run` — verifies that one exact pre-scheduler projection job has no owner or partial progress; replace `--dry-run` with `--confirm retire:<job-id>` only after reviewing the result
27
+ - `brains-ops stress:directory-sync <repo> <handle> --profile <regression|load|stress> --confirm stress:<handle>` — runs a smoke-only, reversible directory-sync workload and writes structured evidence
28
+ - `brains-ops stress:directory-sync:verify-access <repo> <handle> --confirm stress:<handle>` — clones the smoke content repository and verifies push authorization with `git push --dry-run`, without creating a ref or starting a workload
29
+ - `brains-ops stress:directory-sync:cleanup <repo> <handle> --confirm stress:<handle>` — idempotently removes residual stress probes
30
+ - `brains-ops smoke:health-watchdog <repo> <handle> --confirm watchdog-smoke:<handle> --run-id <id>` — verifies fleet watchdog selection and restart-budget isolation on the smoke host
31
+ - `brains-ops smoke:health-watchdog:cleanup <repo> <handle> --confirm watchdog-smoke:<handle> --run-id <id>` — removes deterministic residual watchdog smoke fixtures
16
32
  - `brains-ops reconcile-cohort <repo> <cohort>`
17
33
  - `brains-ops reconcile-all <repo>`
34
+ - `brains-ops reconcile-all <repo> --dry-run` — reconciles an isolated copy twice with external content-repository access blocked, lists both passes' changed files, and requires second-pass zero drift
35
+
36
+ `render` owns the observational `views/users.md` projection. Onboard and reconcile commands own generated per-user config and never rewrite live observed status in that view.
37
+
38
+ ### Per-user plugin configuration
39
+
40
+ Use canonical plugin configuration in `users/<handle>.yaml`, not edits to generated `brain.yaml`:
41
+
42
+ ```yaml
43
+ plugins:
44
+ dashboard:
45
+ ask: true
46
+ ```
47
+
48
+ The generator composes an object before serializing once. Explicit per-user fields override generated defaults; nested maps merge, arrays replace, and `false` is preserved. Null deletion markers remain in the generated document until the app resolves runtime defaults. Both stages use the same shared merger. The operator validates the configuration map shape; individual plugin schemas remain authoritative in the app.
49
+
50
+ The example enables only the dashboard Ask tab. It does not activate guest access, change allowances, or supply authored content. Users without `plugins` retain the same configuration values. New or changed configuration uses the standard YAML formatter. Reconciliation compares YAML values before writing an existing `brain.yaml`, so formatting-only differences are left untouched and cannot schedule unrelated deployments. Malformed or substantively changed configuration is regenerated.
51
+
52
+ ## Directory-sync stress profiles
53
+
54
+ Directory-sync stress is deliberately smoke-only. The handle, domain, and content repository must each identify smoke, and the operator must pass the exact `stress:<handle>` confirmation. The runner refuses production-like targets. The smoke user must also declare the hermetic posture below; reconcile and deploy it before running the workload:
55
+
56
+ ```yaml
57
+ embeddingEnabled: false
58
+ topicExtractionEnabled: false
59
+ skillDerivationEnabled: false
60
+ swotDerivationEnabled: false
61
+ ```
62
+
63
+ - `regression`: add 20 files, update all 20, then delete them;
64
+ - `load`: ramp through 50, 150, and 350 files, update 350, rename 100, update again, then delete all probes;
65
+ - `stress`: continue the same deterministic ramp to 700 files and 200 renames.
66
+
67
+ Each run creates a rollback branch, gates on health failures during the monitored workload window, preserves warmup and cleanup health samples as evidence without poisoning that gate, samples container CPU/memory/PIDs, detects watchdog restarts even when Docker's restart counter remains zero, rejects external AI usage, waits for Git and entity persistence, and always attempts cleanup. JSON, Markdown, runtime logs, and samples are written under `.brains-ops/stress/` unless `--artifacts-dir` is supplied. The scaffolded `Directory Sync Stress` workflow runs a weekly regression and supports manual profiles. Its manual `verify_only` mode exercises the Bitwarden/Varlock content credential path through clone and a dry-run push, skips the workload, and does not schedule cleanup. Workload runs retain a separate `always()` cleanup job. Successful idempotent cleanup also prunes retained stress backup branches; branches remain available when probes remain for recovery. The workflow never deploys or targets a non-smoke user.
68
+
69
+ ## Health watchdog smoke
70
+
71
+ The scaffolded manual `Health Watchdog Smoke` workflow uses the same pilot desired state, Hetzner lookup, Bitwarden/Varlock deploy key, and `deploy-<handle>` concurrency boundary as fleet deployment. It refuses non-smoke handles/domains and requires `watchdog-smoke:<handle>` confirmation. The runner requires the installed watchdog to match the packaged canonical payload, exercises that installed script, and verifies the deployed image label, active timer, exact selector, liveness healthcheck, diagnostics, negative container isolation, and three-per-hour restart budget without restarting the deployed rover. Evidence is uploaded from `RUNNER_TEMP`; an independent `always()` cleanup job removes deterministic temporary containers and remote files.
18
72
 
19
73
  ## Scope
20
74
 
21
75
  `brains-ops` lives in the `brains` monorepo and is consumed as a separate package.
22
76
 
77
+ The active loader accepts one schema requiring `bundleContract: capability-bundles-v1` and the nine capability/policy bundle IDs. Offline parsing of prior desired state is isolated to `crossover:stage` and is never used by render, verify, or reconciliation paths.
78
+
79
+ Crossover staging excludes source `.git`, `.operator`, `.brains-ops`, `.turbo`, `dist`, `node_modules`, plaintext `.env`/`.env.local`, and `*.secrets.yaml` artifacts. It generates fresh per-user `.env` selector files in the review copy without copying source secret values. A review manifest must name both sides of the pilot selection and every explicit cohort selection; source drift fails staging:
80
+
81
+ ```yaml
82
+ bundleContract: capability-bundles-v1
83
+ pilot:
84
+ sourceBundles: [core]
85
+ targetBundles: [core, media, web, chat]
86
+ cohorts:
87
+ sites:
88
+ sourceBundles: [core, site, publishing]
89
+ targetBundles:
90
+ [core, media, automation, web, chat, site, publishing, federation]
91
+ ```
92
+
93
+ Hosted sites must also be enumerated in a separate reviewed file; staging rejects missing, extra, or identity-mismatched pins instead of inferring versions:
94
+
95
+ ```yaml
96
+ sites:
97
+ example:
98
+ package: "@rizom/site-example"
99
+ version: 0.2.0-alpha.1
100
+ theme: "@rizom/theme-example"
101
+ themeVersion: 0.2.0-alpha.1
102
+ ```
103
+
23
104
  It operates on a separate private data repo, such as `rover-pilot/`, which stores:
24
105
 
25
106
  - `pilot.yaml`
@@ -1,4 +1,4 @@
1
- import { type RunCommand } from "./run-subprocess";
1
+ import { type RunCommand } from "@brains/deploy-support/run-subprocess";
2
2
  export interface AgeKeyBootstrapOptions {
3
3
  logger?: (message: string) => void;
4
4
  pushTo?: string | undefined;