@ours.network/install 1.2.1-nightly.4 → 1.2.1-nightly.40
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/GATEWAY_SETUP.md +178 -0
- package/README.md +453 -9
- package/ROOTLESS_PODMAN_VALIDATION.md +210 -0
- package/assets/Dockerfile +14 -12
- package/assets/Dockerfile.gateway +5 -0
- package/assets/docker-compose.yaml +8 -1
- package/assets/fleet-settings.example.json +48 -0
- package/assets/gateway-entrypoint.sh +37 -0
- package/assets/release-lock.json +1139 -4470
- package/assets/release.json +37 -19
- package/assets/scripts/build/build-common.mjs +2 -1
- package/assets/scripts/build/build-sdk.mjs +6 -1
- package/assets/scripts/maintenance/build-context.mjs +1 -1
- package/assets/scripts/maintenance/daemon-owner.mjs +15 -0
- package/assets/scripts/maintenance/docker-layout-conversion.mjs +7 -3
- package/assets/scripts/maintenance/release-graph.mjs +18 -1
- package/assets/scripts/maintenance/state-operation.mjs +12 -2
- package/assets/scripts/runtime/README.md +7 -0
- package/assets/scripts/runtime/client-setup.mjs +80 -6
- package/assets/scripts/runtime/dependency-ready.mjs +13 -0
- package/assets/scripts/runtime/diagnostics.mjs +72 -0
- package/assets/scripts/runtime/entrypoint.sh +5 -1
- package/assets/scripts/runtime/health-messenger.mjs +7 -6
- package/assets/scripts/runtime/notifications-gateway.mjs +90 -0
- package/assets/scripts/runtime/recover.mjs +165 -0
- package/assets/scripts/runtime/start-cowork.sh +5 -0
- package/assets/scripts/runtime/start-messenger.sh +29 -4
- package/assets/scripts/runtime/start-telegram.sh +5 -0
- package/assets/scripts/runtime/supervise.mjs +35 -0
- package/assets/sources.json +54 -28
- package/install.mjs +7 -2
- package/lib/boot-readiness.mjs +43 -0
- package/lib/build-transition.mjs +3 -0
- package/lib/client-cli.mjs +127 -0
- package/lib/container-engine.mjs +127 -0
- package/lib/diagnostics.mjs +1 -0
- package/lib/docker-conversion-runtime.mjs +3 -2
- package/lib/docker-layout-installation.mjs +2 -1
- package/lib/docker-recovery.mjs +55 -0
- package/lib/docker-runtime-repair.mjs +160 -0
- package/lib/effects.mjs +323 -132
- package/lib/gateway-transition.mjs +87 -0
- package/lib/gateway.mjs +158 -0
- package/lib/legacy-migration.mjs +13 -2
- package/lib/orchestrate-uninstall.mjs +18 -6
- package/lib/orchestrate.mjs +193 -43
- package/lib/plan.mjs +27 -11
- package/lib/podman-preflight.mjs +40 -0
- package/lib/server-onboarding.mjs +164 -16
- package/lib/server-ports.mjs +17 -0
- package/lib/setup-options.mjs +99 -28
- package/lib/setup.mjs +35 -17
- package/lib/target.mjs +24 -8
- package/lib/uninstall.mjs +2 -2
- package/lib/usage.mjs +21 -7
- package/lib/workspace-setup.mjs +83 -0
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -1,3 +1,32 @@
|
|
|
1
|
+
## Install first, connect the App afterwards
|
|
2
|
+
|
|
3
|
+
```sh
|
|
4
|
+
ours-install --username alex --name Alex --surname Taylor --disable-fleet-agents-setup
|
|
5
|
+
```
|
|
6
|
+
|
|
7
|
+
This permanent command contains no tunnel credentials or enrollment expiry. On a terminal it asks for the remaining installation choices, including Docker, Podman or native packages. The username is local and has no global uniqueness check. A fresh root is named `<username>@<hostname>`; the optional `--hostname` defaults to the machine name. Messenger stores Name and Surname through its supported profile API. Retried setup retains root identities and existing Messenger profiles.
|
|
8
|
+
|
|
9
|
+
`--disable-fleet-agents-setup` installs the Fleet CLI and saves the choice without opening its agent/model wizard or rewriting existing Fleet configuration. Configure agents in the App after device linking. Complete presets still work unattended; partial presets require a terminal and cannot use `OURS_ASSUME_YES`.
|
|
10
|
+
|
|
11
|
+
### Fleet task commands from a harness command sandbox
|
|
12
|
+
|
|
13
|
+
After Fleet configuration, and again on update, the installer asks the exact Fleet it installed to run `ours-fleet managed-cli setup`. Fleet owns that policy; the installer writes no Codex rule or Claude setting itself, and the step starts no agent session and no model. It runs only when the installed Fleet declares the `managed-cli.setup-v1` capability; the Fleet release this installer pins does. With an earlier Fleet (a retained or development installation) it is skipped (and `--fleet-task-workflow` reports that it was not applied), and it never fails an installation: an unsupported combination is printed with Fleet's reason and left exactly as sandboxed as before.
|
|
14
|
+
|
|
15
|
+
Nothing is prepared unless an Agent declares `managed_cli: [task-workflow]`. To opt agents in from the installer, name them:
|
|
16
|
+
|
|
17
|
+
```sh
|
|
18
|
+
ours-install client --config /private/profile.json --integrations codex,fleet \
|
|
19
|
+
--fleet-settings /private/fleet-settings.json --fleet-task-workflow FleetCoordinator
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
`--fleet-task-workflow` takes a comma-separated list of Fleet agent names, requires the Fleet integration and conflicts with `--disable-fleet-agents-setup`. It adds that one key to each named Agent and changes no permission. The prepared scope is the packaged Coordinator task workflow (`task create|start|finish|block|unblock|review|list|show`, `room show|members`, template/plan/help inspection) for one pinned Fleet configuration; `task start` and `task finish` provision and retire rooms and agents, which is real authority, and the installer prints that scope. The result is generated configuration only. It is not evidence that a command reached a supervisor: `ours-fleet managed-cli status` and `ours-fleet doctor` report what running agents actually observed. Fleet's `docs/validation/managed-cli-permissions.md` lists the qualified harnesses and platforms.
|
|
23
|
+
|
|
24
|
+
The separate `ours-fleet setup-tunnel <encoded-v2-grant>` step is supported by the pinned Fleet release. Its private App payload remains scoped, signed-root-bound and expiring. Fleet prints its QR and private single-use connection code immediately after successful setup; scan or paste it into the App. `ours-fleet link-device` remains available for additional devices or expired codes. Do not put the expiring tunnel payload in the permanent installer command.
|
|
25
|
+
|
|
26
|
+
Native packages currently provide server-only installation; full Fleet/App onboarding requires the supported gateway (Docker or Podman). The installer refuses unsupported native full-stack setup before changing anything. This flow does not add a native gateway.
|
|
27
|
+
|
|
28
|
+
See [one-connection setup, localhost:4050 and systemd migration](GATEWAY_SETUP.md) for the gateway-only client workflow.
|
|
29
|
+
|
|
1
30
|
# @ours.network/install — one installer for the whole stack
|
|
2
31
|
|
|
3
32
|
Requires Node.js 22+ and npm. Install the selected release channel:
|
|
@@ -10,8 +39,8 @@ ours-install
|
|
|
10
39
|
With no arguments, the wizard explains each step and offers keyboard choices.
|
|
11
40
|
Use arrow keys and Enter to choose, and Space to select integrations. Recommended
|
|
12
41
|
settings keep advanced ports and package overrides out of the usual flow. Text
|
|
13
|
-
input is used for your name and explicitly customized paths or ports.
|
|
14
|
-
|
|
42
|
+
input is used for your name and explicitly customized paths or ports. Docker is recommended for the integrated full-stack gateway on every platform;
|
|
43
|
+
native packages remain available for server-only setup. On Windows run the
|
|
15
44
|
installer inside WSL with Docker Desktop integration. This recommendation concerns
|
|
16
45
|
packaging and isolation, not a guarantee that emulated x64 is faster on ARM Macs.
|
|
17
46
|
|
|
@@ -45,7 +74,7 @@ installers. `--integrations none` explicitly skips client integrations. Use
|
|
|
45
74
|
Fleet's own wizard is available only in interactive setup; CLI Fleet setup requires
|
|
46
75
|
its JSON settings file. Fleet stays stopped until you review and activate it.
|
|
47
76
|
|
|
48
|
-
The server installs the daemon/SDK/CLI,
|
|
77
|
+
The server installs the daemon/SDK/CLI, Telegram, Cowork and Messenger.
|
|
49
78
|
It starts the daemon, preserves the existing Human identity (or creates it once),
|
|
50
79
|
then starts its applications. Full-stack setup issues a separate local client
|
|
51
80
|
credential and configures the selected Codex, Claude Code and Fleet integrations.
|
|
@@ -56,6 +85,28 @@ The installer embeds exact component versions and SHA-512 values for its release
|
|
|
56
85
|
An existing server's retained release selects matching local clients. Secrets are
|
|
57
86
|
read from protected files, and client setup never copies the daemon API master.
|
|
58
87
|
|
|
88
|
+
## Runtime and client packages
|
|
89
|
+
|
|
90
|
+
Server selections include `@ours.network/daemon`, whose `ours-daemon` binary owns
|
|
91
|
+
runtime startup and service administration. Docker runs `ours-daemon serve`;
|
|
92
|
+
native installations install its systemd/launchd service. Existing retained
|
|
93
|
+
installations can still stop and restore their older CLI-owned runtime.
|
|
94
|
+
|
|
95
|
+
Client selections contain the thin SDK and CLI, plus MCP when a harness needs
|
|
96
|
+
it. They exclude the daemon and its native database/ADAPT dependencies. Fleet
|
|
97
|
+
runs beside the harnesses on the client machine and calls the daemon HTTP API.
|
|
98
|
+
Client commands report an unavailable server and never start one automatically.
|
|
99
|
+
|
|
100
|
+
The checked-in source policy and packed installer retain the existing server
|
|
101
|
+
release set (SDK `3.8.1-nightly.11`, CLI `2.8.1-nightly.9`, daemon
|
|
102
|
+
`3.8.1-nightly.3`). The isolated host CLI uses published SDK
|
|
103
|
+
`3.8.1-nightly.13` and CLI `2.8.1-nightly.11`, including the shared gateway
|
|
104
|
+
profile resolver. `releases/nightly.json` binds both selections to verified
|
|
105
|
+
SHA512 integrities. Gateway-only Fleet/MCP release adoption is still pending;
|
|
106
|
+
see [GATEWAY_SETUP.md](GATEWAY_SETUP.md). Mixed or unselected nested ours
|
|
107
|
+
versions remain rejected within each selected graph. An explicit `--sources`
|
|
108
|
+
override remains available for development.
|
|
109
|
+
|
|
59
110
|
## Migrate an existing global installation
|
|
60
111
|
|
|
61
112
|
The wizard detects the old `~/.ours/config.json` and offers to keep its identities,
|
|
@@ -137,8 +188,8 @@ native package acquisition, and reports completion only after service readiness.
|
|
|
137
188
|
If a Docker service fails, the error includes its last 50 log lines (bounded in
|
|
138
189
|
size) and a command to inspect the logs. A failed daemon prevents consumers from
|
|
139
190
|
starting; a failed consumer does not prevent checks of unrelated consumers.
|
|
140
|
-
Server runtime installation selects SDK/CLI,
|
|
141
|
-
Messenger.
|
|
191
|
+
Server runtime installation selects SDK/CLI, Telegram, Cowork and
|
|
192
|
+
Messenger. MCP runs locally with the Codex and Claude Code plugins and calls the daemon API through the SDK.
|
|
142
193
|
The daemon starts first; consumers are checked through their owning readiness
|
|
143
194
|
interfaces. Messenger uses its existing identity prerequisite and never creates an
|
|
144
195
|
identity. Its failure is reported after attempting unrelated consumers. Package
|
|
@@ -195,9 +246,9 @@ relative to the profile file. Select any nonempty subset of integrations; Fleet
|
|
|
195
246
|
When Fleet settings are supplied, the installer passes them to Fleet's strict
|
|
196
247
|
noninteractive `init --settings`; otherwise it opens Fleet's existing wizard.
|
|
197
248
|
Fleet validates and publishes its own configuration. Client setup verifies the selected
|
|
198
|
-
daemon
|
|
249
|
+
authenticated daemon API before registering native integrations. It acquires
|
|
199
250
|
only selected integration packages and their actual client dependencies. It does
|
|
200
|
-
not
|
|
251
|
+
not administer daemon state or invoke Docker. Codex and Claude Code include the local stdio MCP server as a dependency. Exact npm client
|
|
201
252
|
installation needs no Python; Git source builds use the supplied source recipes
|
|
202
253
|
and their build prerequisites. Normal native clients need neither Docker nor
|
|
203
254
|
server maintenance tools.
|
|
@@ -213,7 +264,8 @@ an existing override and does not edit shell configuration or running sessions.
|
|
|
213
264
|
Repeat with `ours-install client install` to reuse imported inputs and installed
|
|
214
265
|
package records. Existing settings and Fleet-generated files are preserved. A
|
|
215
266
|
prepared profile for the same endpoint/instance may supply a valid replacement
|
|
216
|
-
issued token;
|
|
267
|
+
issued token; a different server instance is refused without changing the default. A verified
|
|
268
|
+
new gateway address for the same instance updates the shared profile for new clients. Invalid
|
|
217
269
|
server access is rejected before import. An acquisition or component failure
|
|
218
270
|
reports incomplete setup and keeps the saved configuration for retry. Selected
|
|
219
271
|
native integrations whose executable is unavailable are incomplete, not installed.
|
|
@@ -224,7 +276,7 @@ Interactive no-argument installation asks for package/Docker server mode, a
|
|
|
224
276
|
prepared client profile, or `client`. Client setup offers the saved server when
|
|
225
277
|
present. On first setup it asks for the server HTTP endpoint, issued-token file,
|
|
226
278
|
source manifest and integration choices, obtains the instance UUID from
|
|
227
|
-
|
|
279
|
+
`/.well-known/ours` at the gateway, displays it, then checks authenticated daemon API access before
|
|
228
280
|
saving anything. No UUID must be entered manually. The 2.0 HTTP flow assumes the
|
|
229
281
|
approved trusted same-host deployment; selection metadata is not cryptographic
|
|
230
282
|
server authentication. Fleet collects missing setup answers through its own wizard.
|
|
@@ -281,3 +333,395 @@ maintenance reads both formats. Format2 is not readable by older maintenance too
|
|
|
281
333
|
so this change does not promise executable downgrade support. Restore validates the
|
|
282
334
|
original archive records unchanged, then writes markers for the active target runtime.
|
|
283
335
|
Mixed/incomplete context and component record sets are refused before activation.
|
|
336
|
+
|
|
337
|
+
### Retrying a Docker installation after a source-policy permission failure
|
|
338
|
+
|
|
339
|
+
Setup verifies the selected Docker image before reusing it, including when the image
|
|
340
|
+
already exists. If an older installer left a root-owned, mode-0600
|
|
341
|
+
`/opt/ours/sources.json`, setup repairs only that image file's permissions and
|
|
342
|
+
continues. The selected package bytes, build provenance, image execution settings,
|
|
343
|
+
credentials and stored data are retained. The old materialized Dockerfile's known
|
|
344
|
+
COPY instruction is also corrected for future builds. No manual image or volume
|
|
345
|
+
deletion is required; repeat the original setup with the updated installer.
|
|
346
|
+
|
|
347
|
+
The repair runs isolated verification containers without state mounts or network
|
|
348
|
+
access. Other image verification failures stop setup without replacing the image.
|
|
349
|
+
An interrupted repair can be retried, including after the image tag was replaced.
|
|
350
|
+
|
|
351
|
+
### Remote clients over HTTPS
|
|
352
|
+
|
|
353
|
+
A client may select an `https://` origin backed by a TLS reverse proxy. Keep the
|
|
354
|
+
daemon listener private and configure the proxy separately with a certificate
|
|
355
|
+
trusted by the client and matching the hostname. Node uses its normal trust
|
|
356
|
+
store; a private CA may be supplied through `NODE_EXTRA_CA_CERTS` before starting
|
|
357
|
+
the client. Certificate verification must remain enabled.
|
|
358
|
+
|
|
359
|
+
The existing issued client credential works over either transport; changing the
|
|
360
|
+
URL scheme does not require a new credential. Keep the server's master on the
|
|
361
|
+
server. Forward `x-ours-api-token` and the `x-ours-*` session headers unchanged,
|
|
362
|
+
and support streamed request/response bodies and long polling. Client requests
|
|
363
|
+
refuse redirects, including HTTPS-to-HTTP redirects: configure the final HTTPS
|
|
364
|
+
origin directly. UUID/capability checks still precede credential-bearing calls.
|
|
365
|
+
|
|
366
|
+
This adds client HTTPS support, not an HTTPS daemon listener, certificate
|
|
367
|
+
provisioning or automatic reverse-proxy configuration. Existing local HTTP and
|
|
368
|
+
SSH-tunnel profiles continue to work.
|
|
369
|
+
|
|
370
|
+
## One-URL Docker gateway
|
|
371
|
+
|
|
372
|
+
New Docker installations use one loopback-published nginx port (default 3050).
|
|
373
|
+
Clients import one `serverUrl`; their daemon endpoint is `<serverUrl>/daemon` and
|
|
374
|
+
Fleet derives `<serverUrl>/cowork/management/rpc`. Cowork, Messenger and Telegram
|
|
375
|
+
backend ports are internal only. Existing installations retain their prior layout
|
|
376
|
+
on ordinary install/update. Select compatible releases before explicitly migrating:
|
|
377
|
+
|
|
378
|
+
```sh
|
|
379
|
+
ours-install server gateway-enable --state-dir /private/ours
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
Migration checks the installed Cowork, Messenger and Telegram capabilities before
|
|
383
|
+
stopping services, verifies authenticated daemon and read-only Cowork management,
|
|
384
|
+
and preserves the existing credential and client integration settings. Failure
|
|
385
|
+
restores routing, client profile and prior service selection. An interrupted
|
|
386
|
+
migration blocks other mutations: repeat `gateway-enable` to finish rollback,
|
|
387
|
+
then run it again to attempt migration. The private `gateway-transition.json`
|
|
388
|
+
retains recovery state until rollback or migration completes. Back up the whole
|
|
389
|
+
installation using the normal server backup procedure before maintenance.
|
|
390
|
+
|
|
391
|
+
For a nested external URL, pass `--server-url https://ours.example/base` during
|
|
392
|
+
Docker install or `gateway-enable`. This sets browser origin and path configuration;
|
|
393
|
+
it does **not** publish a public listener, provide TLS, or install external
|
|
394
|
+
credentials. Configure the authenticated entry first and retain the `/base` path
|
|
395
|
+
when proxying. A compatible release must contain these capabilities:
|
|
396
|
+
`cowork.http-management-v1`, `messenger.gateway-prefix-v1`, and
|
|
397
|
+
`telegram.gateway-listener-v1`. Older releases are rejected without enabling the
|
|
398
|
+
new listener; no package version is silently substituted.
|
|
399
|
+
|
|
400
|
+
### Notifications
|
|
401
|
+
|
|
402
|
+
When the selected release includes `@ours.network/notifications`, gateway
|
|
403
|
+
installations run it inside the Messenger container, under one supervisor with
|
|
404
|
+
Messenger: a signal stops both, and either one exiting stops the container so
|
|
405
|
+
its normal restart recovers both. It publishes no host port. The gateway routes
|
|
406
|
+
`<serverUrl>/notifications/` to it after the same daemon credential check as
|
|
407
|
+
Telegram, and the service's adapter checks that credential again before acting
|
|
408
|
+
as the installation owner. Browser cookies, origins and fetch metadata are
|
|
409
|
+
removed. Messenger produces message notifications over loopback.
|
|
410
|
+
|
|
411
|
+
`prepare` creates the private configuration once in
|
|
412
|
+
`storage/state/notifications/config.json`: the owner token, separate Fleet and
|
|
413
|
+
Messenger producer tokens, and VAPID keys. Later runs only validate it; rotating
|
|
414
|
+
the owner token or VAPID keys would orphan every browser subscription, so a
|
|
415
|
+
differing configuration is refused rather than rewritten. Back it up with the
|
|
416
|
+
rest of the server state. A local client setup binds the Fleet producer token
|
|
417
|
+
to this server in `~/.ours-client/notifications-producer.json`; Fleet then sends
|
|
418
|
+
agent completions through `<serverUrl>/notifications/`. Remote clients and
|
|
419
|
+
native installations do not produce notifications. The gateway discovery
|
|
420
|
+
document is unchanged, so existing clients keep accepting the server. A
|
|
421
|
+
retained source policy without the package keeps working without notifications.
|
|
422
|
+
|
|
423
|
+
An existing complete installation gains them with its normal update, which
|
|
424
|
+
prepares the credentials after activating the new runtime and hands the Fleet
|
|
425
|
+
producer credential to the local client, then a web-only Fleet restart (agents
|
|
426
|
+
keep running):
|
|
427
|
+
|
|
428
|
+
```sh
|
|
429
|
+
ours-install all update --mode docker --state-dir /private/ours --identity-name "Your Name" --integrations codex,fleet --fleet-settings /private/fleet.json --compatible
|
|
430
|
+
ours-fleet web restart
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
### Authenticated external entry
|
|
434
|
+
|
|
435
|
+
Messenger has no application authentication. Loopback access trusts local users;
|
|
436
|
+
never forward this gateway publicly without authentication. All applications on
|
|
437
|
+
this origin share one trust boundary: scripts or XSS in any application can make
|
|
438
|
+
requests to the others. Cowork's entered server credential grants operator room
|
|
439
|
+
administration and stays in memory until reload. Path prefixes do not isolate
|
|
440
|
+
applications. Only expose this origin to trusted operators.
|
|
441
|
+
|
|
442
|
+
A supported external entry is nginx TLS plus HTTP Basic authentication for browser
|
|
443
|
+
paths, with machine paths left to their existing server-token checks. Create the
|
|
444
|
+
password file using an interactive `htpasswd` prompt and make it readable by the
|
|
445
|
+
proxy worker. Use real certificates and the matching `--server-url`. The inner
|
|
446
|
+
gateway remains bound to `127.0.0.1:3050`; neither backend ports nor the inner
|
|
447
|
+
listener should be externally forwarded. Example for `/base`:
|
|
448
|
+
|
|
449
|
+
```nginx
|
|
450
|
+
# In http {}:
|
|
451
|
+
map $http_upgrade $ours_connection { default upgrade; '' close; }
|
|
452
|
+
server {
|
|
453
|
+
listen 443 ssl;
|
|
454
|
+
server_name ours.example;
|
|
455
|
+
ssl_certificate /private/tls/fullchain.pem;
|
|
456
|
+
ssl_certificate_key /private/tls/key.pem;
|
|
457
|
+
auth_basic "ours operators";
|
|
458
|
+
auth_basic_user_file /private/ours-users;
|
|
459
|
+
access_log off;
|
|
460
|
+
proxy_set_header Host $http_host;
|
|
461
|
+
proxy_set_header Upgrade $http_upgrade;
|
|
462
|
+
proxy_set_header Connection $ours_connection;
|
|
463
|
+
proxy_http_version 1.1;
|
|
464
|
+
proxy_read_timeout 300s;
|
|
465
|
+
proxy_buffering off;
|
|
466
|
+
location = /base/.well-known/ours { auth_basic off; proxy_pass http://127.0.0.1:3050; }
|
|
467
|
+
location /base/daemon/ { auth_basic off; proxy_pass http://127.0.0.1:3050; }
|
|
468
|
+
location = /base/cowork/management/rpc { auth_basic off; proxy_pass http://127.0.0.1:3050; }
|
|
469
|
+
location /base/tg-connector/ { auth_basic off; proxy_pass http://127.0.0.1:3050; }
|
|
470
|
+
location /base/ { proxy_pass http://127.0.0.1:3050; }
|
|
471
|
+
location / { return 404; }
|
|
472
|
+
}
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
Browser requests include same-origin proxy credentials. Fleet/SDK use the issued
|
|
476
|
+
`X-Ours-Api-Token`, require no browser login, and reject redirects. An SSH tunnel
|
|
477
|
+
to the loopback gateway is another private transport option, but every client must
|
|
478
|
+
establish its own tunnel and use a URL/origin matching that tunnel; it is not
|
|
479
|
+
automatic remote access. Do not treat a token entered in Cowork as Messenger auth.
|
|
480
|
+
|
|
481
|
+
Publish compatible Cowork, Messenger, Telegram and Fleet artifacts before enabling
|
|
482
|
+
gateway defaults in a qualified installer release. Gateway client setup acquires
|
|
483
|
+
and checks Fleet before activating the managed profile or publishing native
|
|
484
|
+
commands. Migration also checks the installed `ours-fleet version --json`
|
|
485
|
+
capability before stopping services when the selected managed profile includes
|
|
486
|
+
Fleet. Upgrade that executable first. The gate does not inventory differently pinned
|
|
487
|
+
running Fleet instances or remote clients: upgrade every client using this server
|
|
488
|
+
to a compatible Fleet release before cutover.
|
|
489
|
+
|
|
490
|
+
### Cross-repository gateway qualification
|
|
491
|
+
|
|
492
|
+
Build Cowork, Fleet, Messenger and Telegram checkouts with their locked dependencies.
|
|
493
|
+
The real-service test uses disposable local daemon state, a local test broker,
|
|
494
|
+
nginx Docker containers and Chromium; it never uses installed identities or tokens.
|
|
495
|
+
It requires Linux Docker host networking and `openssl`. Set:
|
|
496
|
+
|
|
497
|
+
```sh
|
|
498
|
+
OURS_TEST_GATEWAY_SERVICES=1 \
|
|
499
|
+
OURS_TEST_COWORK_ROOT=/checkouts/ours-cowork \
|
|
500
|
+
OURS_TEST_FLEET_ROOT=/checkouts/ours-fleet \
|
|
501
|
+
OURS_TEST_MESSENGER_ROOT=/checkouts/ours-messenger-server \
|
|
502
|
+
OURS_TEST_TELEGRAM_ROOT=/checkouts/ours-tg-connector \
|
|
503
|
+
OURS_TEST_BROWSER=/opt/google/chrome/chrome \
|
|
504
|
+
node --test packages/installer/test/gateway-services.test.mjs
|
|
505
|
+
```
|
|
506
|
+
|
|
507
|
+
Run `OURS_TEST_DOCKER=1 node --test packages/installer/test/gateway-docker.test.mjs`
|
|
508
|
+
separately for Compose port isolation with a client container. That routing test
|
|
509
|
+
uses echo upstreams; the real-service test covers Fleet room operations, browser
|
|
510
|
+
paths, external authentication and Messenger WebSocket access. Neither test is
|
|
511
|
+
cross-platform Docker Desktop qualification or a live deployment test.
|
|
512
|
+
|
|
513
|
+
### Rootless Podman (qualification in progress)
|
|
514
|
+
|
|
515
|
+
Container installations can select a local Linux rootless backend explicitly:
|
|
516
|
+
|
|
517
|
+
```sh
|
|
518
|
+
export PODMAN_COMPOSE_PROVIDER=/absolute/path/to/docker-compose
|
|
519
|
+
ours-install server install --mode docker --container-engine podman \
|
|
520
|
+
--state-dir "$HOME/.ours-server-podman" --identity-name "Your Name"
|
|
521
|
+
```
|
|
522
|
+
|
|
523
|
+
`mode: docker` remains the legacy container-layout name. `containerEngine` and
|
|
524
|
+
`containerBinding` retain Podman, the invoking UID, native storage paths, socket
|
|
525
|
+
and standalone Compose provider, plus the UID/GID mapping fingerprint. Records without `containerEngine` continue to
|
|
526
|
+
use Docker. Package/client installs reject the engine option. Existing records
|
|
527
|
+
cannot change engines through a flag or ambient connection change; automatic
|
|
528
|
+
Docker-to-Podman data migration is not provided. Legacy local-daemon migration
|
|
529
|
+
(`--migrate-from`) to Podman is also unsupported and is refused before source
|
|
530
|
+
shutdown or managed CLI publication, including migration retries. Use a fresh
|
|
531
|
+
Podman installation, or migrate the legacy daemon with Docker/packages.
|
|
532
|
+
|
|
533
|
+
Podman uses its native build command, with the same resolved Compose build
|
|
534
|
+
context, target, architecture, arguments and secret references, followed by
|
|
535
|
+
Compose `--no-build` startup. It does not require the Docker CLI or daemon.
|
|
536
|
+
The selected standalone Docker Compose provider must be version 2.35 or newer;
|
|
537
|
+
version checks do not replace the behavioral capability probe. `podman-compose`
|
|
538
|
+
is not an interchangeable provider for this implementation. Secrets sourced
|
|
539
|
+
from environment variables use Podman's native build-secret mechanism, never
|
|
540
|
+
build arguments or temporary copies.
|
|
541
|
+
|
|
542
|
+
Prerequisites include a working rootless API socket, sufficient subordinate
|
|
543
|
+
UID/GID mappings, and native volume-subpath isolation. Before setup/start, an
|
|
544
|
+
isolated disposable project tests Compose `!reset`, health waiting, JSON status,
|
|
545
|
+
service DNS, private UID-1000 storage and subpath isolation. A failed check stops
|
|
546
|
+
installation rather than substituting the whole volume. Existing volumes must
|
|
547
|
+
have this installation's project and volume labels. Docker contexts, unrelated
|
|
548
|
+
containers and host directory ownership are not changed.
|
|
549
|
+
|
|
550
|
+
Server boot recovery requires an enabled user `podman.socket`, an enabled
|
|
551
|
+
`podman-restart.service` using `--filter should-start-on-boot=true`, and user
|
|
552
|
+
linger. The standard user-service environment/default socket must select the
|
|
553
|
+
same storage; custom XDG paths and sockets are rejected for server startup.
|
|
554
|
+
The installer diagnoses missing prerequisites and never runs hidden sudo or
|
|
555
|
+
rewrites the vendor unit. Long-running Podman services get `unless-stopped`;
|
|
556
|
+
administration jobs do not. Stop/status remain available when boot prerequisites
|
|
557
|
+
are missing, provided the retained backend is accessible. Runtime-only test
|
|
558
|
+
harnesses may select a separate local socket with `OURS_PODMAN_SOCKET`; its
|
|
559
|
+
storage must match native Podman and the selection cannot change afterward.
|
|
560
|
+
|
|
561
|
+
Gateway images read and validate IPv4/IPv6 nameservers from their container at
|
|
562
|
+
startup. Only the resolver placeholder is replaced; nginx variables and existing
|
|
563
|
+
authentication/routes remain intact. UID 101, read-only rootfs, dropped
|
|
564
|
+
capabilities and tmpfs are retained. Setup and start verify authenticated
|
|
565
|
+
upstream requests in addition to liveness.
|
|
566
|
+
|
|
567
|
+
This change is **not yet a fully qualified server-support release**. Debian's
|
|
568
|
+
Podman 5.4.2 with Compose 5.5.1 failed subpath isolation and has incompatible boot
|
|
569
|
+
recovery semantics. Podman 6.1.2 passed the isolated capability probe on native
|
|
570
|
+
Linux amd64; production and prerelease-source builds, service lifecycle, rebuild and scoped maintenance also passed. See [validation evidence](ROOTLESS_PODMAN_VALIDATION.md). The full public installer/maintenance matrix,
|
|
571
|
+
SELinux Enforcing, logout/reboot, explicit-stop recovery, and Docker regression
|
|
572
|
+
matrix must all be recorded before declaring a supported engine/provider pair.
|
|
573
|
+
The supplied ARM VM results are historical feasibility evidence, not this
|
|
574
|
+
release's qualification.
|
|
575
|
+
|
|
576
|
+
Opt-in gateway fixture (isolated project, only owned resources removed):
|
|
577
|
+
|
|
578
|
+
```sh
|
|
579
|
+
OURS_TEST_DOCKER=1 node --test test/gateway-docker.test.mjs
|
|
580
|
+
PODMAN_COMPOSE_PROVIDER=/absolute/path/to/docker-compose \
|
|
581
|
+
OURS_TEST_PODMAN=1 node --test test/gateway-docker.test.mjs
|
|
582
|
+
```
|
|
583
|
+
|
|
584
|
+
## Account workspace enrollment (task build)
|
|
585
|
+
|
|
586
|
+
The unmerged account onboarding feature requires matching reviewed installer,
|
|
587
|
+
Fleet and Messenger task builds. Do not advertise it as available in `@latest`.
|
|
588
|
+
Use an owned private directory and a 0600 downloaded payload:
|
|
589
|
+
|
|
590
|
+
```sh
|
|
591
|
+
node /absolute/task-ours-network/packages/installer/install.mjs \
|
|
592
|
+
--setup-workspace-file /absolute/private/workspace.payload \
|
|
593
|
+
--workspace-fleet-bin /absolute/task-ours-fleet/dist/cli.js \
|
|
594
|
+
--sources /absolute/private/task-sources.json
|
|
595
|
+
```
|
|
596
|
+
|
|
597
|
+
The wrapper defaults fresh hosts to the full Docker stack and retains existing
|
|
598
|
+
Human roots through the installed SDK with exact instance/private credential
|
|
599
|
+
selection. For an existing supported gateway add `--scope client --config` with
|
|
600
|
+
its private profile. It clears competing inherited daemon selectors before Fleet
|
|
601
|
+
initialization and enrollment; it never copies a browser device bearer to the
|
|
602
|
+
account server. A private stdin payload is also accepted by `--setup-workspace -`.
|
|
603
|
+
Encoding is not encryption; command arguments can enter history/process listings.
|
|
604
|
+
Cloudflare management tokens are forbidden in these payloads.
|
|
605
|
+
|
|
606
|
+
Docker and `cloudflared` are required for the fresh workflow. Supply a complete
|
|
607
|
+
`--fleet-settings` JSON for noninteractive Fleet initialization, or answer its
|
|
608
|
+
terminal prompts. Dry-run never initializes or enrolls Fleet. Read the matching
|
|
609
|
+
ours-app `server/DEPLOYMENT.md` for exact task source-policy generation, external
|
|
610
|
+
Google/Cloudflare prerequisites and account-server setup. On uncertain enrollment
|
|
611
|
+
check account status before requesting a new payload; do not reset identities or
|
|
612
|
+
replay a consumed invitation.
|
|
613
|
+
|
|
614
|
+
Workspace setup accepts exactly https://app.ours.network and the controlled test
|
|
615
|
+
account origin https://app.ours-tunnel.com. To move an existing same workspace to
|
|
616
|
+
the other origin, obtain a fresh payload from the moved account server and add
|
|
617
|
+
`--workspace-migrate-app-origin`. Fleet verifies the signed binding receipt before
|
|
618
|
+
changing local origin trust, preserves identities/config/device records, and
|
|
619
|
+
restarts the runtime. An implicit origin change is rejected. Browser account
|
|
620
|
+
cookies/device IndexedDB must be linked anew on the new origin. See the app
|
|
621
|
+
server/DEPLOYMENT.md switching procedure.
|
|
622
|
+
|
|
623
|
+
Workspace setup automatically reuses the saved managed gateway profile (or explicit `--config`/`OURS_CONFIG`), including a host with a non-default server state directory. It does not reinstall server/client state, create a root, or initialize an existing Fleet configuration. It requires Fleet capability `workspace.enroll.preserve-profile-v1` and passes `--preserve-profile`; Fleet requires the matching Messenger capability before posting signed enrollment. Hosts running older Messenger must first update that host service through its supported installer lifecycle; this wrapper never guesses or replaces its server directory. After Owner releases Messenger/Fleet/installer, app bootstrap pins must be updated before removing the preview guard.
|
|
624
|
+
|
|
625
|
+
### Private-context Docker script permissions
|
|
626
|
+
|
|
627
|
+
Fresh image builds explicitly make non-secret maintenance/runtime scripts readable by the container user even when the host build context was copied under umask077. Host scripts, selected source policy and state retain their private permissions.
|
|
628
|
+
|
|
629
|
+
For a pending installation using an older image, run the corrected installer against the same pending workspace. It recognizes older shipped script COPY instructions combined with private host script modes, updates those image COPY modes and rebuilds the daemon image from the retained source selection. It leaves host data and enrollment state intact and qualifies the rebuilt image before preparing services. A private retry marker retains the rebuild requirement after interruption; it is removed only after verification succeeds. This rebuild resolves third-party transitive dependencies using the existing testing-delivery rules; selected Ours versions and integrity remain release-checked. It is not a byte-identical image permission-layer repair.
|
|
630
|
+
|
|
631
|
+
Fresh server setup checks its loopback daemon, Cowork and Messenger ports before
|
|
632
|
+
writing the installation configuration. Occupied implicit defaults advance to a
|
|
633
|
+
free port, skipping reserved sibling ports; the selected values are saved in the
|
|
634
|
+
installation record and used by native/container services, gateway and client
|
|
635
|
+
profile generation. An explicitly requested occupied port fails with a diagnostic.
|
|
636
|
+
Existing installation records keep their ports and identities. A listener acquired
|
|
637
|
+
by another process after preflight still causes startup to fail safely; no foreign
|
|
638
|
+
process is stopped and no retained installation is silently moved.
|
|
639
|
+
|
|
640
|
+
Workspace setup pins Fleet `1.2.0-nightly.52` with its recorded registry integrity. This release includes first-time Fleet setup through the host API for the account App, direct App access to the workspace services with the device credential, v2 positional one-use grants and automatic QR/connection-code output from `ours-fleet setup-tunnel`, optional private file/stdin inputs for legacy v1 payloads, a separate `ours-fleet link-device` command for additional devices, host prerequisite checks before the one-time workspace proof (`setup-tunnel --check`), `setup-tunnel --resume` to finish a setup that stopped after the host saved its private pending setup record (not when the proof's answer was lost, or after the setup window expired with an unconfirmed non-default port), and persists the available Fleet loopback port used by the workspace tunnel. It also accepts a setup-generated configuration left behind after the host enrollment state was removed, runs the host Codex when it is at least as new as the packaged one, offers only the Codex models the signed-in account can use, and removes the temporary setup contact after confirmation. Fleet serves no pages and opens no browser: every screen is in the App. Fleet also serves the workspace notification routes, produces notifications through the server gateway with the imported producer credential, accepts the App's device credential on the notification presence socket so an open App receives no push, and defaults agent wakes to `monitor.interrupt: after_tool` (Hermes: no interrupt; role snapshots saved before this default keep no interrupt). Existing installation identities and configured ports remain retained; a retained-port collision fails safely.
|
|
641
|
+
|
|
642
|
+
### App tunnel setup prerelease sequencing
|
|
643
|
+
|
|
644
|
+
The simplified App flow shows one copyable `ours-fleet setup-tunnel <encoded-v2-grant>`
|
|
645
|
+
command for the installed host, including an SSH session on a VPS. Its argument
|
|
646
|
+
contains only the existing v2 single-use grant (`version`, `appOrigin`, `code`,
|
|
647
|
+
`expiresAt`), never a connector token or broad provider credential. The command can
|
|
648
|
+
appear in shell history and process listings: keep it private and remove it from
|
|
649
|
+
history after use. Base64 is encoding, not encryption. Server-side expiry and
|
|
650
|
+
one-time redemption remain enforced. Fleet checks prerequisites before HTTPS POST
|
|
651
|
+
redemption; it never prints the grant or puts it in a URL, and retains existing
|
|
652
|
+
signed-root binding and scoped connector token-file controls. It prints the QR and
|
|
653
|
+
connection code automatically; the App checks readiness and opens the code field.
|
|
654
|
+
Private `--file`/`--stdin` transports remain optional and are the only transports
|
|
655
|
+
for legacy v1 payloads with long-lived credentials.
|
|
656
|
+
|
|
657
|
+
The nightly installer release manifest selects published Fleet `1.2.0-nightly.52`
|
|
658
|
+
and its actual registry integrity through the normal release manifest/source-policy
|
|
659
|
+
generators. This release includes v2 argument and private-input support. The former
|
|
660
|
+
nightly.41 selection predates this capability. Merge and publish the repinned
|
|
661
|
+
installer before deploying the App; the pin change alone is not an installer
|
|
662
|
+
publication. Existing v1 private-file enrollment remains compatible. The legacy
|
|
663
|
+
App wrapper refuses an older Fleet before reading or redeeming its grant.
|
|
664
|
+
|
|
665
|
+
The notification gateway permits daemon-authenticated producer selection only on
|
|
666
|
+
POST `/api/v1/send` and `/api/v1/delete-target`. The latter retires a removed
|
|
667
|
+
conversation using the credential's fixed user/source scope. Browser inbox
|
|
668
|
+
`/api/v1/delete` continues to require the user credential. The notification
|
|
669
|
+
service must support the scoped lifecycle route; this change does not repin or
|
|
670
|
+
publish an installer release.
|
|
671
|
+
|
|
672
|
+
## Boot and failure recovery
|
|
673
|
+
|
|
674
|
+
Docker long-running daemon, Telegram, Cowork, Messenger/Notifications and gateway
|
|
675
|
+
containers use `unless-stopped`. They resume when the selected Docker Engine
|
|
676
|
+
starts, and Docker restarts a failed container with its built-in backoff. A manual
|
|
677
|
+
`docker stop`, `ours-install server stop`, or uninstall stays stopped across
|
|
678
|
+
Engine restarts. Administrative/maintenance jobs have no automatic restart.
|
|
679
|
+
Docker health status alone does not restart a container.
|
|
680
|
+
|
|
681
|
+
The four application containers also supervise their locked entrypoints. After
|
|
682
|
+
90 seconds of startup grace, probes run every 5 seconds with a 15-second timeout.
|
|
683
|
+
Three consecutive local health failures or a child exit stop its entire process
|
|
684
|
+
group (TERM, then KILL within 20 seconds) before restarting. Cowork's detached
|
|
685
|
+
workers carry an explicit supervisor-PID marker; recovery also kills those
|
|
686
|
+
owned groups and waits for them to stop before launching a replacement. Each container start
|
|
687
|
+
allows three automatic child recovery attempts. Exhaustion leaves the container
|
|
688
|
+
running but unhealthy, with its children stopped and a diagnostic in its logs.
|
|
689
|
+
Correct the cause and use `ours-install server restart --state-dir PATH` to
|
|
690
|
+
reset that circuit; `server start` alone does not reset a running circuit holder.
|
|
691
|
+
Consumers wait for authenticated readiness of their pinned daemon instance and
|
|
692
|
+
do not spend their recovery budget on a daemon outage. The gateway uses Docker
|
|
693
|
+
process recovery only; a gateway hang requires operator restart.
|
|
694
|
+
|
|
695
|
+
Re-run `server install` to deliver recovery to an existing installation without
|
|
696
|
+
changing its retained exact packages, identity, credentials, volumes or config.
|
|
697
|
+
This explicit install starts its selected services, as before. `server update`
|
|
698
|
+
with reviewed storage compatibility delivers the new selected release and
|
|
699
|
+
restores only previously running services. Retained runtime scripts are refreshed
|
|
700
|
+
and rebuilt on install; an interrupted refresh retains a rebuild marker. The
|
|
701
|
+
restart policy overlay also covers retained Compose files. Reconciliation updates
|
|
702
|
+
only this project's recorded long-running containers and does not start or
|
|
703
|
+
recreate a deliberately stopped container. `server start` can reconcile policies
|
|
704
|
+
but does not retrofit health supervision into an old image: run install/update.
|
|
705
|
+
Backup, migration and update still stop writers before maintenance, and a failed
|
|
706
|
+
maintenance operation keeps them stopped. `server uninstall` (also `ours-uninstall --state-dir PATH` for a managed
|
|
707
|
+
schema-2 installation) stops and removes managed services, retaining volumes,
|
|
708
|
+
identity and credentials. It refuses unfinished transitions and data purge.
|
|
709
|
+
Recovery introduces no host watchdog or service.
|
|
710
|
+
|
|
711
|
+
Host boot is a separate prerequisite. On Linux, enable the selected Docker
|
|
712
|
+
Engine system service; rootless Docker additionally needs its user service and
|
|
713
|
+
user linger. The installer reports read-only boot diagnostics and does not enable
|
|
714
|
+
or restart host services. A reachable remote Engine or Docker Desktop context
|
|
715
|
+
cannot prove boot recovery on this machine. A custom Unix socket also has an
|
|
716
|
+
unverified boot-service binding; a host unit cannot establish its startup. On macOS/Windows with WSL, enable Docker
|
|
717
|
+
Desktop startup at sign-in; this does not provide pre-login startup. Rootless
|
|
718
|
+
Podman's existing enabled socket/restart-service and linger preflight remains.
|
|
719
|
+
Native package mode retains its package-owned systemd user/launchd services:
|
|
720
|
+
Linux needs user linger for pre-login startup, macOS needs a GUI login session,
|
|
721
|
+
and native hung-process recovery is not supplied by this Docker supervisor.
|
|
722
|
+
Fleet stays on the host with Fleet-owned lifecycle and crash protection. Installing
|
|
723
|
+
the exact Fleet nightly binary does not upgrade or restart an existing supervisor.
|
|
724
|
+
The published no-policy core delivery is a verified recovery omission that
|
|
725
|
+
reproduces the reported symptom. The original incident cause remains unconfirmed:
|
|
726
|
+
actual host Engine availability, installed policies and pre-reboot stopped state
|
|
727
|
+
still require Owner confirmation.
|