@ours.network/cowork 0.2.0

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,18 @@
1
+ # Installation
2
+
3
+ Install the package so its `ours-cowork` executable is on your `PATH`, then verify the offline help:
4
+
5
+ ```sh
6
+ ours-cowork --help
7
+ ours-cowork docs
8
+ ```
9
+
10
+ Open the local console with:
11
+
12
+ ```sh
13
+ ours-cowork web
14
+ ```
15
+
16
+ This starts the background daemon when it is absent, waits for `http://127.0.0.1:3052/`, and opens the system browser. Use `ours-cowork start` when no browser should open, or `ours-cowork serve` in the foreground while diagnosing startup. `ours-cowork --json web` verifies readiness and returns the URL without opening a browser.
17
+
18
+ The localhost HTTP console has no authentication. Do not proxy, forward, or expose its port to another host. The daemon hosts its own room packets and does not require another local ours process.
@@ -0,0 +1,18 @@
1
+ # Configuration
2
+
3
+ The default config file is `~/.ours-cowork/config.json`. It is a strict document:
4
+
5
+ ```json
6
+ {
7
+ "version": 1,
8
+ "brokerUrl": "wss://broker1.ours.network",
9
+ "stateDir": "/absolute/private/path",
10
+ "rest": { "enabled": true, "port": 3052 }
11
+ }
12
+ ```
13
+
14
+ Environment overrides are `OURS_COWORK_CONFIG`, `OURS_COWORK_BROKER_URL`, `OURS_COWORK_STATE_DIR`, and `OURS_COWORK_REST_PORT`. The default console URL is `http://127.0.0.1:3052/`. Setting the REST port enables the loopback listener on that port. Explicitly setting `rest.enabled` to `false` disables both the web console and HTTP room RPC. Configuration, private files, and the complete state directory must remain owned by the daemon account with the modes enforced at startup.
15
+
16
+ CLI room commands always use `management.sock`; they do not switch to REST.
17
+
18
+ The HTTP listener is unauthenticated and restricted to the `127.0.0.1` interface. The console works through both `http://127.0.0.1:<port>` and `http://localhost:<port>`. Do not expose it through port forwarding, a reverse proxy, or a non-loopback bind.
@@ -0,0 +1,18 @@
1
+ # Daemon lifecycle
2
+
3
+ Use these commands:
4
+
5
+ ```sh
6
+ ours-cowork start
7
+ ours-cowork status
8
+ ours-cowork restart
9
+ ours-cowork stop
10
+ ours-cowork serve
11
+ ours-cowork web
12
+ ```
13
+
14
+ `start` detaches the standalone CLI in `serve` mode and waits for the authenticated control session on `management.sock`. `serve` keeps the supervisor in the foreground. Status asks the responding worker to prove that its supervisor capability handshake completed. Stop sends a session-bound shutdown request to that worker; the worker asks its own supervisor over their existing authenticated IPC channel to enter the same bounded shutdown path used for signals. The CLI never signals a numeric PID. Stop reports success only after the accepted control session disappears. An occupied socket without this protocol blocks stop/restart with invalid state and is left untouched.
15
+
16
+ `web` uses the same safe start path: an already-running daemon is retained, an absent daemon is started, and readiness is checked with `GET /` before a browser opens. It never retries a room mutation. With `--json`, it returns the URL with `opened: false` and has no browser side effect. If HTTP is explicitly disabled, `web` exits `1` and explains how to enable it.
17
+
18
+ Exit codes are stable: `0` success, `1` web console disabled, `2` CLI usage, `3` not found, `4` invalid state or parameters, `5` unauthorized, `6` daemon unavailable, and `7` internal failure. With `--json`, stdout contains exactly one JSON value and stderr stays empty. This includes foreground `serve`: supervised worker output is suppressed, and its clean or failed terminal status becomes that one JSON result.
@@ -0,0 +1,17 @@
1
+ # Room workflow
2
+
3
+ Create a room and inspect its host-owned identity:
4
+
5
+ ```sh
6
+ ours-cowork room create --goal "Ship the fix" --briefing "Review evidence first"
7
+ ours-cowork room list
8
+ ours-cowork room show <room-id>
9
+ ```
10
+
11
+ In the web console, choose Create room, enter Goal and Briefing, and submit once. The created room is selected automatically and its Invite panel opens. Add invitation requirements one at a time; the UI does not combine room creation and invites into a fabricated atomic operation.
12
+
13
+ Update mutable mission fields with `room settings`. Inspect admitted seats with `room participants`. A room activates only when its recorded invite requirements are satisfied. Roles are display labels; participant identity CIDs, not roles, are authorization keys.
14
+
15
+ Close with `ours-cowork room close <room-id>`. Close is forward-only and removes live room packet state while retaining the local archive. Archive deletion is a separate explicit operation described in the limitations topic.
16
+
17
+ Every web action has an equivalent CLI fallback in the room commands above and in the invites and messaging topics.
@@ -0,0 +1,15 @@
1
+ # Invites
2
+
3
+ Create one-time or public invites:
4
+
5
+ ```sh
6
+ ours-cowork room invite <room-id> --role reviewer
7
+ ours-cowork room invite <room-id> --mode public --role observer --min-accepts 2
8
+ ours-cowork room revoke <room-id> <invite-id>
9
+ ```
10
+
11
+ The invite blob is returned only in an invite or recovery receipt. Store or transmit that receipt as needed; durable room metadata intentionally does not store the blob.
12
+
13
+ The web console shows each returned invite secret once in a blocking receipt. Copy and save it before choosing Done: closing the receipt discards the browser copy. The secret is not placed in the URL, browser storage, logs, or room metadata. One-time and public receipts use the same handling.
14
+
15
+ After restart, `room recover <room-id>` can mint replacements for durable invites marked as needing replacement. Preserve each returned replacement blob before confirming its exact old/new pair with `room recover <room-id> --confirm <old-invite-id> <new-invite-id>`. The web recovery receipt names both IDs and requires the same confirmation. Each invocation makes exactly one local management request.
@@ -0,0 +1,24 @@
1
+ # Messaging and history
2
+
3
+ Post in the room's host-owned voice:
4
+
5
+ ```sh
6
+ ours-cowork room message <room-id> --text "Decision recorded"
7
+ ```
8
+
9
+ The daemon assigns authorship. Author, identity, display-name, and role flags are rejected for this command.
10
+
11
+ An option value that begins with `--` uses the unambiguous inline form, for example `--text=--help` or `--text=--json`. A bare `--` ends option parsing for positional values. Only an exact standalone `--json` before `--` selects global JSON output; text inside `--text=VALUE` is never consumed as a global flag.
12
+
13
+ Read the ordered archive with numeric paging:
14
+
15
+ ```sh
16
+ ours-cowork room history <room-id>
17
+ ours-cowork room history <room-id> --after 40 --limit 20
18
+ ```
19
+
20
+ Participant messages are accepted only from durable seats in an active room. History records include messages and the durable relay intent/result trail used for restart recovery.
21
+
22
+ The web console projects participant and room-authored messages plus the briefing into Communication. Relay, recovery, close, and failure records are excluded from chat and shown in Events; Archive retains the complete ordered record stream. Messages appear only after the authoritative history refresh observes them.
23
+
24
+ Version one polls rather than receiving pushed updates: the room list refreshes every five seconds, while the selected room, participants, and history refresh every two seconds. Polling pauses in a hidden tab, coalesces overlap, and refreshes after confirmed mutations. CLI history remains the fallback when a browser is unavailable.
@@ -0,0 +1,7 @@
1
+ # Backup and restore
2
+
3
+ Stop the daemon before taking a backup. A live copy can split metadata, append-only archive records, packet state, and filesystem durability boundaries across different moments.
4
+
5
+ Back up the complete state directory as one unit, preserving ownership and file modes. Do not select only `rooms/` or only room JSON files.
6
+
7
+ For restore, stop the daemon, replace the complete state directory with the complete backup, restore its original owner and `0700`/`0600` permissions, and then start the daemon. Do not merge individual room directories from different snapshots. Restore to a compatible package version and verify `ours-cowork status` plus representative `room show` and `room history` calls.
@@ -0,0 +1,12 @@
1
+ # Service management
2
+
3
+ Install a per-user boot service with:
4
+
5
+ ```sh
6
+ ours-cowork install-service
7
+ ours-cowork uninstall-service
8
+ ```
9
+
10
+ Linux uses `ours-cowork.service` under the systemd user directory. macOS uses the `network.ours.cowork` launchd agent. Both definitions execute the installed cowork CLI directly in `serve` mode and preserve the effective broker, state directory, and optional REST port settings.
11
+
12
+ Installation rejects service values containing NUL, newline, carriage return, or other unsafe control characters before creating or replacing a definition. It then stops a manually detached daemon through the authenticated control session before the service takes ownership. Uninstall first requires systemd to disable/stop the unit or launchd to unload the agent. If that operation fails, uninstall reports failure and retains the service definition for inspection or retry. After a successful unload, uninstall removes only the service definition; it retains all cowork configuration, room archives, and packet state. Remove data only through the explicit closed-room deletion command or a separate, deliberate host-data operation.
@@ -0,0 +1,13 @@
1
+ # Limitations
2
+
3
+ - The retained archive is plaintext on this host. Filesystem ownership and `0700`/`0600` modes limit local access, but the archive is not encrypted at rest by ours-cowork.
4
+ - Invite secrets exist only for the process lifetime that minted them and in the receipt returned to the operator. Durable room metadata stores descriptors, not invite blobs. A prior one-time or public secret is not reconstructable; a durable invite marked as needing replacement requires explicit recovery to mint a new secret.
5
+ - Relay recovery is at-least-once. A crash after transport acceptance but before the durable result can retry a send, so participants may observe duplicates. The system does not provide exactly once relay semantics.
6
+ - The host records transport acceptance and failures; it does not observe delivery, reading, or remote processing. A successful operator command must not be interpreted as participant receipt.
7
+ - Backups require a stopped daemon. Back up and restore the complete state directory as one unit, preserving ownership and modes; partial or live copies are unsupported.
8
+ - Service uninstall retains data. It removes the systemd or launchd definition, not configuration, archives, room metadata, or packet state.
9
+ - Closing and deleting are separate. First close the room explicitly with `ours-cowork room close <room-id>`. Only a closed room can then be deleted with `ours-cowork room delete <room-id> --yes`.
10
+ - Confirmed deletion removes the retained archive and metadata from this host only. It does not claim remote purge, backup erasure, key wipe, or secure erase.
11
+ - The web console and HTTP room RPC have no authentication. They bind only to `127.0.0.1` and must not be forwarded, proxied, or exposed remotely.
12
+ - Web updates use periodic polling rather than push. A view can lag daemon state until its next refresh; confirmed mutations trigger an immediate refresh.
13
+ - Browser state is transient apart from the selected-room URL hash. Invite receipts disappear when closed and are not recoverable from browser storage.
@@ -0,0 +1,30 @@
1
+ # Web console
2
+
3
+ Open the production console with:
4
+
5
+ ```sh
6
+ ours-cowork web
7
+ ```
8
+
9
+ The command safely starts the daemon only when it is absent, waits for `GET /` readiness, then opens `http://127.0.0.1:3052/`. `ours-cowork --json web` performs the same readiness checks but returns `{ "url": "http://127.0.0.1:3052/", "opened": false }` inside the standard JSON result without opening a browser.
10
+
11
+ The console and HTTP room RPC have no authentication. They bind only to `127.0.0.1`; both the `127.0.0.1` and `localhost` browser URLs are accepted. Do not use port forwarding, a reverse proxy, or another mechanism to expose this listener to other hosts.
12
+
13
+ ## Room setup
14
+
15
+ 1. Choose Create room and enter the Goal and Briefing.
16
+ 2. Submit once. The new room is selected and its Invite panel opens.
17
+ 3. Add one invitation requirement at a time. Choose one-time or public mode and set the minimum acceptances for a public invite.
18
+ 4. Copy every invite from its blocking receipt before choosing Done. The secret is shown once and is not retained in browser storage, the URL, logs, or durable room metadata.
19
+
20
+ The room activates after its durable invitation requirements are satisfied. Participants shows admitted identities and their invite roles.
21
+
22
+ ## Communication and records
23
+
24
+ Communication is the human-readable chat: room and participant messages plus the mission briefing. Messages are not inserted optimistically; a sent message appears after the daemon's ordered history includes it. Events contains relay, recovery, close, and failure details. Archive contains the complete sequence-numbered stream and can show earlier loaded rows.
25
+
26
+ Room list and connection health poll every five seconds. The selected room, participants, and new history poll every two seconds. Polling pauses while the page is hidden, coalesces overlapping cycles, and refreshes after confirmed mutations. Version one does not use push updates.
27
+
28
+ Close requires the room title or exact ID and leaves the plaintext local archive. Delete is available only after close, requires the exact room ID, and removes local state only as described in the limitations topic.
29
+
30
+ Every operation remains available through `ours-cowork room ...` when no browser is available. Use `ours-cowork docs rooms`, `ours-cowork docs invites`, and `ours-cowork docs messaging` for the CLI workflows.
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "@ours.network/cowork",
3
+ "version": "0.2.0",
4
+ "description": "Standalone daemon for durable ours mission rooms.",
5
+ "type": "module",
6
+ "license": "FSL-1.1-Apache-2.0",
7
+ "bin": {
8
+ "ours-cowork": "dist/cli.js"
9
+ },
10
+ "files": [
11
+ "dist",
12
+ "LICENSE",
13
+ "README.md",
14
+ "docs/*.md"
15
+ ],
16
+ "engines": {
17
+ "node": ">=20"
18
+ },
19
+ "scripts": {
20
+ "build": "node build.mjs",
21
+ "compile:mufl": "scripts/compile-mufl.sh",
22
+ "typecheck": "tsc -p tsconfig.json --noEmit",
23
+ "typecheck:web": "tsc -p web/tsconfig.json --noEmit",
24
+ "test": "node --import tsx --test --test-concurrency=1 tests/*.test.mjs",
25
+ "test:web": "vitest run",
26
+ "test:browser": "node --test tests/browser-smoke.test.mjs",
27
+ "test:release": "node --test tests/static-gates.test.mjs"
28
+ },
29
+ "dependencies": {
30
+ "@adapt-toolkit/sdk": "0.10.12",
31
+ "@adapt-toolkit/sdk-native": "0.10.12",
32
+ "react": "18.3.1",
33
+ "react-dom": "18.3.1",
34
+ "zod": "^3.23.8"
35
+ },
36
+ "devDependencies": {
37
+ "@adapt-toolkit/broker": "0.10.12",
38
+ "@adapt-toolkit/mufl": "0.10.12",
39
+ "@testing-library/jest-dom": "6.6.3",
40
+ "@testing-library/react": "16.1.0",
41
+ "@testing-library/user-event": "14.5.2",
42
+ "@types/node": "^20.14.0",
43
+ "@types/react": "18.3.31",
44
+ "@types/react-dom": "18.3.7",
45
+ "@vitejs/plugin-react": "4.7.0",
46
+ "esbuild": "0.25.0",
47
+ "jsdom": "25.0.1",
48
+ "playwright-core": "1.60.0",
49
+ "tsx": "4.23.1",
50
+ "typescript": "^5.5.4",
51
+ "vite": "6.4.3",
52
+ "vitest": "3.2.6"
53
+ }
54
+ }