@lenso/cli 0.2.13 → 0.2.14

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 CHANGED
@@ -16,34 +16,187 @@ cargo install lenso-cli
16
16
  lenso host init my-app
17
17
  cd my-app
18
18
  cp .env.example .env
19
- lenso console update
20
19
  lenso serve
21
20
  ```
22
21
 
23
22
  The package name defaults to the target directory name and can be overridden with
24
23
  `--name`. Pass `--force` to scaffold into a non-empty directory.
25
- Install or update the hosted Runtime Console with:
26
24
 
27
- ```sh
28
- lenso console update
29
- ```
30
-
31
- The command downloads the latest `lenso-runtime-console` release artifact and
32
- installs it under `.lenso/console`, so the host API can serve `/console`
33
- without requiring Node.js or pnpm in the host application. For local builds,
34
- pass `--artifact <dir-or-tar.gz>`. For a pinned release, pass
35
- `--console-version vX.Y.Z`.
25
+ ## Install Lenso Console
26
+
27
+ Lenso Console is installed as an independent Service, not embedded into a
28
+ business Service. Obtain an official GitHub-attested Console Release Manifest,
29
+ review the deterministic plan, and then approve that exact plan digest:
30
+
31
+ ```sh
32
+ lenso console install --manifest lenso-console-release.json \
33
+ --root /srv/lenso-console --output install-plan.json
34
+ lenso console install --manifest lenso-console-release.json \
35
+ --root /srv/lenso-console --env-file /secure/console.env --apply \
36
+ --approve-plan-digest sha256:<reviewed-plan-digest>
37
+ lenso console doctor --root /srv/lenso-console \
38
+ --live-url https://console.example.com --json
39
+ ```
40
+
41
+ The manifest must be attested by the repository's coordinator-only
42
+ `.github/workflows/publish.yml` signer and must pin an OCI image by digest. The
43
+ CLI rejects attestations from any other workflow and from self-hosted runners.
44
+ The apply environment must set `CONSOLE_RECOVERY_MODE=normal` explicitly. The
45
+ adapter pulls that image, runs its migration workload, starts the Console
46
+ workload, waits up to two minutes for container health, and then requires the
47
+ running `/health/authority` response to identify `lenso-console` in `normal`
48
+ mode. It records the canonical deployment and state only after both checks pass.
49
+ The secret-free `lenso.console-installation-state.v2` evidence retains that
50
+ exact authority probe and its canonical digest, so doctor can detect later
51
+ evidence drift without trusting the live endpoint alone.
52
+ A failed readiness or authority check preserves the previous canonical files
53
+ and state instead of recording the candidate as installed. `lenso console
54
+ doctor --live-url <console-url>` independently checks both endpoints before a
55
+ retry or intervention. Upgrade uses the same
56
+ protocol through `lenso console upgrade`. An upgrade that declares irreversible
57
+ migrations additionally requires
58
+ `--approve-irreversible`. Secrets remain in the operator-owned environment file
59
+ and are never copied into the plan, manifest, or installation state.
60
+
61
+ Before producing an upgrade plan, the CLI revalidates the installed manifest's
62
+ GitHub attestation, requires the manifest and generated Compose deployment to
63
+ exactly match the applied state, and requires the target version to be strictly
64
+ newer. Run `lenso console doctor` and resolve any local drift rather than editing
65
+ the CLI-owned installation files.
66
+
67
+ Every applied change also updates a secret-free `installation-attempt.json` with
68
+ its target release, approved plan digest, current phase, and final status. Doctor
69
+ reports an interrupted or failed attempt until a later change commits cleanly;
70
+ database credentials and other environment values are never included.
71
+
72
+ Apply holds an exclusive OS-backed `installation.lock` from the state reread
73
+ through readiness and evidence commit. A concurrent install or upgrade fails
74
+ without mutation. If the process exits without releasing the lock, the operating
75
+ system releases ownership while the active record remains as crash evidence;
76
+ doctor reports it as recoverable and the next apply safely claims the same lock.
77
+
78
+ Create a Recovery Set without ever writing plaintext Store bytes to disk. The
79
+ CLI verifies the installed release evidence and attestation, holds the same
80
+ installation lock used by upgrade, streams PostgreSQL custom-format output
81
+ directly into `age`, and atomically publishes a new output directory:
82
+
83
+ ```sh
84
+ lenso console backup --root /srv/lenso-console \
85
+ --env-file /secure/console.env --output ./console-recovery-2026-07-30 \
86
+ --recipient age1example
87
+ ```
88
+
89
+ The host must provide `pg_dump` and `age`. The secret database URL is read from
90
+ `CONSOLE_DATABASE_URL` in the environment file and is passed only through the
91
+ child-process environment. `recovery-set.json` binds the encrypted payload to
92
+ the exact release, image, Store schema, composition, contract, and configuration
93
+ digests. Live session rows under `auth.sessions` are explicitly excluded and the
94
+ exclusion is recorded in the protected manifest. Existing output is never
95
+ overwritten.
96
+
97
+ Restore is also a plan-and-approval operation. Use a current environment with
98
+ `CONSOLE_RECOVERY_MODE=normal` and a recovery environment with
99
+ `CONSOLE_RECOVERY_MODE=restore` that points to a distinct, empty PostgreSQL
100
+ database:
101
+
102
+ ```sh
103
+ lenso console restore --root /srv/lenso-console \
104
+ --recovery-set ./console-recovery-2026-07-30 \
105
+ --current-env-file /secure/console.env \
106
+ --recovery-env-file /secure/console-recovery.env \
107
+ --output restore-plan.json
108
+ lenso console restore --root /srv/lenso-console \
109
+ --recovery-set ./console-recovery-2026-07-30 \
110
+ --current-env-file /secure/console.env \
111
+ --recovery-env-file /secure/console-recovery.env \
112
+ --apply --approve-plan-digest sha256:<reviewed-plan-digest> \
113
+ --identity-file /secure/console-recovery-identity.txt
114
+ ```
115
+
116
+ Before fencing the current deployment, apply verifies the Recovery Set content
117
+ digest, proves that the owner-only `age` identity decrypts a readable PostgreSQL
118
+ archive, and confirms that the isolated target Store has no relations. It then
119
+ stops the previous Console, streams decryption directly into a transactional
120
+ `pg_restore`, and starts the Console against the recovery Store. No plaintext
121
+ Store file is written. A failed or completed restore writes durable
122
+ `recovery-state.json` evidence, and `lenso console doctor` remains failed while
123
+ that evidence exists. Successful restore therefore means “awaiting
124
+ reconciliation,” not activation: the CLI never changes recovery mode back to
125
+ normal or declares the restored deployment authoritative.
126
+
127
+ After restore, reconcile the passive Store with separately collected deployment,
128
+ identity/enrollment, and Outbox evidence. The reviewed input must name every
129
+ managed Service exactly as observed in the restored Store, in `serviceId` order,
130
+ and reference external evidence without embedding credentials:
36
131
 
37
- After creating a password user, grant the first Runtime Console admin:
38
-
39
- ```sh
40
- lenso console bootstrap-admin --identifier admin@example.com
41
- # or
42
- lenso console bootstrap-admin --user-id usr_...
132
+ ```json
133
+ {
134
+ "schema": "lenso.console-reconciliation-input.v1",
135
+ "recoverySetId": "rcv_<uuid>",
136
+ "observedAtUnixMs": 1785369600000,
137
+ "reviewedBy": "operator:alice",
138
+ "authorityEvidenceRef": "change:console-dr-42",
139
+ "identityEvidenceRef": "audit:identity-continuity-42",
140
+ "outboxEvidenceRef": "audit:outbox-reconciliation-42",
141
+ "singleAuthoritativeDeployment": true,
142
+ "identityAndEnrollmentContinuityVerified": true,
143
+ "outboxReconciled": true,
144
+ "managedServices": []
145
+ }
43
146
  ```
44
147
 
45
- `console.admin` is always added. Pass extra `--scope <name>` flags when the
46
- user should also see scoped module data, then restart the API/worker.
148
+ ```sh
149
+ lenso console recovery reconcile --root /srv/lenso-console \
150
+ --env-file /secure/console-recovery.env \
151
+ --evidence reconciliation-input.json --output reconciliation-plan.json
152
+ lenso console recovery reconcile --root /srv/lenso-console \
153
+ --env-file /secure/console-recovery.env \
154
+ --evidence reconciliation-input.json --apply \
155
+ --approve-plan-digest sha256:<reviewed-plan-digest>
156
+ ```
157
+
158
+ The command reads the restored Store without mutation, rejects any browser
159
+ session predating recovery while allowing newly authenticated recovery
160
+ operators, binds a streamed digest of exact Outbox rows plus status counts and
161
+ the managed-Service identity set, and writes content-addressed
162
+ `reconciliation-evidence.json`. It advances only to
163
+ `ready_for_activation`; doctor continues to fail and neither the Worker nor
164
+ management mutations are enabled.
165
+
166
+ Generated deployments set `CONSOLE_RECOVERY_MODE` explicitly. `normal` runs the
167
+ API and Worker; `restore` keeps the inspection API available while the Console
168
+ Service suppresses background work and rejects management mutations. Recovery
169
+ mode can only be changed through the external installation authority. During
170
+ activation and activation recovery, the CLI reads the running container's
171
+ minimal `/health/authority` response and requires the exact Console Service
172
+ identity plus the expected `normal` or `restore` mode before committing durable
173
+ evidence. A healthy process with the wrong workload mode is treated as a failed
174
+ authority transfer and is fenced again.
175
+
176
+ After installing and starting the independent Lenso Console Service, create its
177
+ first password user and bootstrap that user as the first Console Operator from
178
+ outside the Service. In an interactive terminal, the CLI securely prompts for
179
+ and confirms the password without echoing it:
180
+
181
+ ```sh
182
+ lenso console operator bootstrap \
183
+ --console-root ../lenso-console \
184
+ --console-url http://127.0.0.1:3030 \
185
+ --identifier admin@example.com
186
+ ```
187
+
188
+ The command grants only the Console Minimum operator scopes plus explicit
189
+ `--scope <name>` additions, writes append-only audit evidence, and refuses to
190
+ run after an operator grant already exists. It also verifies the mandatory
191
+ System Registry state before writing, so a business Service Store is rejected.
192
+ Password-user creation goes through the Console Service's own Auth Module over
193
+ HTTPS, with loopback HTTP allowed for local installation. Non-interactive
194
+ automation must use `--password-stdin` or a private regular file through
195
+ `--password-file`. For recovery after Auth registration succeeded but the grant
196
+ did not, rerun without `--console-url` or a password option and select the
197
+ existing identity with `--identifier` or `--user-id`. Restart the Console API
198
+ and Worker after bootstrapping. Business Service users and Auth state are never
199
+ modified.
47
200
 
48
201
  The generated host depends on the crates.io `lenso` crate with the `host`
49
202
  feature, which is the current narrow host API for booting API, worker, and
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lenso/cli",
3
- "version": "0.2.13",
3
+ "version": "0.2.14",
4
4
  "description": "Lenso command-line interface for scaffolding and operating Lenso backend projects.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://github.com/LioRael/lenso-cli",
Binary file
Binary file
Binary file
Binary file