@rizom/ops 0.2.0-alpha.483 → 0.2.0-alpha.485

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rizom/ops",
3
- "version": "0.2.0-alpha.483",
3
+ "version": "0.2.0-alpha.485",
4
4
  "description": "Operator CLI for managing private brain fleet registry repos",
5
5
  "keywords": [
6
6
  "brains",
@@ -30,8 +30,8 @@ The repo also checks in its deploy contract:
30
30
 
31
31
  `.env.schema` is the single source of truth for required and sensitive deploy vars.
32
32
  Use separate GitHub tokens: `CONTENT_REPO_ADMIN_TOKEN` for operator-side content repo creation/checks, and `GIT_SYNC_TOKEN` for runtime directory-sync git access.
33
- The fleet publishes one immutable `brain-${brainVersion}` image per effective Brain version. New images install the exact site/theme package union across the entire fleet, so smoke-to-fleet promotion reuses the tested image. Build and Deploy verify installed package versions before reusing existing images.
34
- When an effective brain version (`pilot.yaml.brainVersion`, or a cohort override) changes and you push, CI builds every missing version image, refreshes generated user env files, and redeploys affected users. Every external site and theme package keeps its own exact version pin; change that package set only together with a fresh Brain version so published tags remain immutable.
33
+ The fleet publishes one immutable image per effective Brain version and site pin set: `brain-${brainVersion}` for instances without a site override, `brain-${brainVersion}--<pins>` for instances with one (the pins spelled out and sorted, or a digest of them when too long). Instances with the same version and pins share an image; a site's pin change builds that site's image and no other, and smoke-to-fleet promotion reuses the tested image because its name already carries its pins. Build and Deploy verify installed package versions against an image's name before reusing it.
34
+ When an effective brain version (`pilot.yaml.brainVersion`, or a cohort override) or a site pin changes and you push, CI builds every missing image, refreshes generated user env files (an instance with site pins names its image there as `IMAGE_TAG`), and redeploys affected users. Every external site and theme package keeps its own exact version pin. Published tags remain immutable: a new pin set is a new tag.
35
35
  When a push changes only deploy contract files, CI prints `No affected user configs; skipping deploy.` and stops before Kamal.
36
36
 
37
37
  ## Commands
@@ -7,6 +7,7 @@ export {
7
7
  writeGitHubOutput,
8
8
  writeGitHubEnv,
9
9
  runtimeImageTag,
10
+ sitePackagesFor,
10
11
  runResolveMissingImages,
11
12
  } from "@rizom/ops/deploy";
12
13
  export type { EnvSchemaEntry } from "@rizom/ops/deploy";
@@ -6,6 +6,7 @@ import {
6
6
  parseEnvFile,
7
7
  requireEnv,
8
8
  runtimeImageTag,
9
+ sitePackagesFor,
9
10
  writeGitHubOutput,
10
11
  } from "./helpers";
11
12
 
@@ -42,9 +43,19 @@ const wwwDomain = isFleetDomain(
42
43
 
43
44
  const brainVersion = envEntries["BRAIN_VERSION"] ?? "";
44
45
 
45
- // Build and Deploy share one tag function: every instance on a Brain version
46
- // runs the same immutable fleet image.
47
- const imageTag = runtimeImageTag(brainVersion);
46
+ // Build and Deploy share one tag function: an instance runs the immutable
47
+ // image named by its Brain version and its own site pins. The generated env
48
+ // names the same image; a disagreement means the registry moved under it.
49
+ const imageTag = runtimeImageTag(
50
+ brainVersion,
51
+ sitePackagesFor(user.siteOverride),
52
+ );
53
+ const generatedTag = envEntries["IMAGE_TAG"];
54
+ if (generatedTag && generatedTag !== imageTag) {
55
+ throw new Error(
56
+ `${envPath} names ${generatedTag} but the registry resolves ${imageTag}; reconcile first`,
57
+ );
58
+ }
48
59
 
49
60
  const outputs: Record<string, string> = {
50
61
  brain_version: brainVersion,
@@ -12,7 +12,7 @@ const user = registry.users.find((entry) => entry.handle === handle);
12
12
  if (!user) throw new Error(`Unknown fleet handle: ${handle}`);
13
13
 
14
14
  await verifyRuntimeImage(`ghcr.io/${requireEnv("GITHUB_REPOSITORY")}`, {
15
- tag: runtimeImageTag(user.brainVersion),
15
+ tag: runtimeImageTag(user.brainVersion, sitePackagesFor(user.siteOverride)),
16
16
  brainVersion: user.brainVersion,
17
17
  sitePackages: sitePackagesFor(user.siteOverride),
18
18
  });
@@ -19,17 +19,16 @@ The deploy scripts and workflows should read from that contract instead of inven
19
19
 
20
20
  The fleet has one image topology:
21
21
 
22
- - one immutable `brain-${brainVersion}` image is published for each effective Brain version
23
- - every new image contains the union of exact site/theme package pins across the whole fleet, regardless of current Brain versions
24
- - conflicting versions of one package fail image resolution before build
25
- - generated `users/<handle>/.env` carries `BRAIN_VERSION=<brainVersion>`
22
+ - one immutable image is published for each effective Brain version and site pin set: `brain-${brainVersion}` for instances without a site override, `brain-${brainVersion}--<pins>` for instances with one (pins spelled out and sorted, or a digest when too long)
23
+ - instances with the same version and pins share an image; a site's pin change builds that site's image and no other
24
+ - generated `users/<handle>/.env` carries `BRAIN_VERSION=<brainVersion>`, and `IMAGE_TAG=<tag>` for an instance with site pins
26
25
  - build and deploy derive the same effective image tag from the resolved registry
27
26
 
28
27
  ## Version bump flow
29
28
 
30
29
  When `pilot.yaml.brainVersion` changes and you push:
31
30
 
32
- 1. build publishes each missing version image with the full fleet package union, and verifies existing images against their assigned instances
31
+ 1. build publishes each missing image, named by Brain version and site pins, and verifies existing images against what their names say they hold
33
32
  2. reconcile refreshes generated `users/<handle>/.env`
34
33
  3. deploy runs for handles whose generated config changed
35
34
  4. generated file commits happen once in a final aggregation step after the deploy matrix finishes
@@ -38,10 +37,10 @@ Every external site and theme package has its own exact version pin. A cohort or
38
37
  pilot brain-version bump never changes those package versions implicitly; update each
39
38
  pin deliberately from reviewed package and image evidence.
40
39
 
41
- Smoke-first upgrades build the full fleet package union before promotion. Moving
42
- other cohorts onto the tested Brain version then reuses that same immutable image.
43
- Explicit Build dispatches also include the fleet union; `site_packages` only adds
44
- extra pins and cannot replace or conflict with declared pins.
40
+ Smoke-first upgrades build the canary's image, named by its pins, before promotion.
41
+ Moving other instances onto the tested Brain version reuses that image where their
42
+ pins match it and builds their own where they do not. Explicit Build dispatches build
43
+ exactly the dispatched version and `site_packages` pins.
45
44
 
46
45
  Deploy verifies the actual installed Brain and selected instance's site/theme
47
46
  versions on the CI runner after image readiness and before provisioning or
@@ -307,24 +306,22 @@ siteOverride:
307
306
  themeVersion: <exact-theme-version>
308
307
  ```
309
308
 
310
- Missing external package versions fail desired-state validation. Every instance on one
311
- Brain version uses the same image and exact package union. Change a site/theme package
312
- pin only together with a fresh Brain version; published `brain-${brainVersion}` tags
313
- remain immutable. Conflicting pins for one package on the same Brain version fail before
314
- build. Bundled `@brains/*` themes omit `themeVersion` because they are not installed as
315
- separate packages.
309
+ Missing external package versions fail desired-state validation. An instance runs the
310
+ image named by its Brain version and its own pins, so a site/theme pin can change on its
311
+ own: the push builds that image and redeploys that instance. Published tags remain
312
+ immutable; a new pin set is a new tag. Bundled `@brains/*` themes omit `themeVersion`
313
+ because they are not installed as separate packages.
316
314
 
317
315
  ### Custom-package canary and rollback
318
316
 
319
317
  1. Confirm the exact site/theme versions are public-installable without npm credentials.
320
- 2. Apply the exact package names and versions to one healthy canonical site canary and select a fresh Brain version for that package set.
321
- 3. Push desired state and let the normal Build → Reconcile → Deploy chain create the shared version image and update the canary.
318
+ 2. Apply the exact package names and versions to one healthy canonical site canary.
319
+ 3. Push desired state and let the normal Build → Reconcile → Deploy chain create the canary's image and update the canary.
322
320
  4. Run `bunx brains-ops verify-user . <handle>`.
323
321
  5. Manually verify the site, theme, Studio, content sync, and passkey sign-in before adding more users.
324
322
 
325
- To roll back, remove or change `siteOverride` while selecting a fresh Brain version,
326
- then reconcile and redeploy that user. Never mutate an existing image tag; coordinate any
327
- other users intentionally sharing the selected version.
323
+ To roll back, remove or change `siteOverride`, then reconcile and redeploy that user.
324
+ Never mutate an existing image tag.
328
325
 
329
326
  ## Setup email checklist
330
327
 
@@ -346,7 +343,7 @@ Use this for browser/Studio-first users who should receive their own first-passk
346
343
  - `bunx brains-ops onboard . <handle>`
347
344
  - or `bunx brains-ops reconcile-cohort . <cohort>`
348
345
 
349
- 4. Verify the generated `users/<handle>/brain.yaml` contains `auth-service.setupEmail` and `email` interface config.
346
+ 4. Verify the generated `users/<handle>/brain.yaml` contains `auth-service.setupEmail` set to the user's address and `email` interface config.
350
347
  5. Ask the user to complete passkey setup from the email link, then use:
351
348
  - Dashboard: `https://<handle>.rizom.ai/`
352
349
  - Studio: `https://<handle>.rizom.ai/studio`