@ours.network/cowork 1.0.0 → 1.0.2
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 +3 -3
- package/dist/cli.js +232 -250
- package/dist/daemon.js +1107 -1120
- package/dist/web/assets/app.js +1 -1
- package/docs/01-prerequisites.md +1 -1
- package/docs/02-installation.md +1 -1
- package/docs/03-configuration.md +1 -4
- package/docs/05-room-workflow.md +2 -2
- package/docs/06-invites.md +13 -1
- package/docs/07-messaging-history.md +7 -0
- package/docs/08-backup-restore.md +2 -2
- package/docs/10-limitations.md +1 -1
- package/docs/11-web-console.md +2 -2
- package/package.json +3 -3
package/docs/01-prerequisites.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Prerequisites
|
|
2
2
|
|
|
3
|
-
ours-cowork requires Node.js 20 or newer and one already-running shared ours daemon. Install the operator lifecycle with `npm install --global @ours.network/cli@2.0
|
|
3
|
+
ours-cowork requires Node.js 20 or newer and one already-running shared ours daemon. Install the operator lifecycle with `npm install --global @ours.network/cli@2.5.0`, then use `ours daemon start` or `ours daemon install-service --yes`. The shared daemon owns broker connectivity and global identity state; cowork attaches through `@ours.network/sdk` 3.5.0 and never starts a runtime of its own.
|
|
4
4
|
|
|
5
5
|
The selected SDK and CLI must include the external-history storage epoch: structured `listIncomingMessages`/`getHistoryItem`/`getMessages` and `listIncomingFiles`/`fetchFile`/selected `getFiles` APIs backed by per-identity history and immutable blobs. A package with the same nominal version but the older packet-inbox contract is not compatible.
|
|
6
6
|
|
package/docs/02-installation.md
CHANGED
package/docs/03-configuration.md
CHANGED
|
@@ -6,14 +6,11 @@ The default cowork config file is `~/.ours-cowork/config.json`. It contains only
|
|
|
6
6
|
{
|
|
7
7
|
"version": 1,
|
|
8
8
|
"stateDir": "/absolute/private/path",
|
|
9
|
-
"roomIdentity": { "nameMode": "stable_id" },
|
|
10
9
|
"rest": { "enabled": true, "port": 3052 }
|
|
11
10
|
}
|
|
12
11
|
```
|
|
13
12
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
`stable_id` creates `ours-cowork-<full-room-id>`. `friendly` creates `ours-cowork-<slug>-<full-room-id>`. The slug is derived from the initial normalized room name by NFKD decomposition, removal of combining marks, ASCII lowercase conversion, replacement of each non-`[a-z0-9]` run with one hyphen, edge-hyphen trimming, and truncation to 25 characters followed by trailing-hyphen trimming. An empty result (including an entirely non-Latin or emoji name) becomes `room`. The full 26-character room ID keeps duplicate or collapsed slugs unique; the result satisfies the shared-daemon identity-name character set and 64-character maximum.
|
|
13
|
+
Room identity naming is not configurable. Creation uses exactly `ours-cowork:<normalized room name>`; ID-based and slug-based modes are unsupported.
|
|
17
14
|
|
|
18
15
|
Cowork overrides are `OURS_COWORK_CONFIG`, `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 cowork state directory must remain owned by the daemon account with the modes enforced at startup.
|
|
19
16
|
|
package/docs/05-room-workflow.md
CHANGED
|
@@ -8,9 +8,9 @@ ours-cowork room list
|
|
|
8
8
|
ours-cowork room show <room-id>
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
In the web console, choose Create room, enter Name, Goal, and Briefing, and submit once. Names are trimmed and Unicode NFC-normalized, must contain 1–64 Unicode characters, and cannot contain Unicode control or format characters.
|
|
11
|
+
In the web console, choose Create room, enter Name, Goal, and Briefing, and submit once. Names are trimmed and Unicode NFC-normalized, must contain 1–64 Unicode characters, and cannot contain Unicode control or format characters. The normalized name must not collide with an identity already in the shared daemon. 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
12
|
|
|
13
|
-
Update the display name with `ours-cowork room settings <room-id> --name "New name"`; other mutable mission fields use the same `room settings` command. A new room
|
|
13
|
+
Update the display name with `ours-cowork room settings <room-id> --name "New name"`; other mutable mission fields use the same `room settings` command. A new room identity is exactly `ours-cowork:<normalized creation name>`, and that exact authenticated name is persisted and frozen. Messenger therefore displays the room name from the identity itself rather than separate `room_name` metadata. Renaming a room changes only mutable local metadata; it does not change the identity name, CID, contacts, invites, URLs, history, or earlier author labels. Because identity names are daemon-global, attempting to create another room with the same normalized creation name fails closed. Earlier unreleased ID- and slug-based formats are unsupported and receive no migration. Inspect admitted seats with `room participants`. A room activates only when its recorded invite requirement is satisfied. Roles are display labels; participant identity CIDs, not roles, are authorization keys.
|
|
14
14
|
|
|
15
15
|
Close with `ours-cowork room close <room-id>`. Close is forward-only and removes the live standard SDK room identity while retaining the local archive. Archive deletion is a separate explicit operation described in the limitations topic.
|
|
16
16
|
|
package/docs/06-invites.md
CHANGED
|
@@ -10,7 +10,19 @@ ours-cowork room revoke <room-id> <invite-id>
|
|
|
10
10
|
|
|
11
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
12
|
|
|
13
|
-
|
|
13
|
+
Current SDK rooms expose the core's authenticated inviter-side mapping from an
|
|
14
|
+
established contact CID to the existing invite ID used by that handshake. Cowork
|
|
15
|
+
may therefore keep multiple invitations live concurrently: each established
|
|
16
|
+
contact is admitted only through that exact live invite ID and inherits that
|
|
17
|
+
invite's role and requirement. Missing, unknown, revoked, or
|
|
18
|
+
unconfirmed-recovery provenance never admits a seat. This is local read-only
|
|
19
|
+
metadata: it does not change the invite wire format and the redeemer does not
|
|
20
|
+
echo an invite ID back through `addContact`.
|
|
21
|
+
|
|
22
|
+
For compatibility, an older SDK that omits the `origins` field retains the
|
|
23
|
+
single-live restriction. Legacy contacts without a stored origin remain unseated
|
|
24
|
+
after upgrade; Cowork does not guess their role. Upgrade the ours SDK before
|
|
25
|
+
relying on concurrent invitations.
|
|
14
26
|
|
|
15
27
|
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.
|
|
16
28
|
|
|
@@ -41,6 +41,13 @@ Daemon history responses are capped at 3 MiB of JSON so one 2 MiB file record (a
|
|
|
41
41
|
|
|
42
42
|
Participant messages and files are accepted only from durable seats in an active room. A file is opaque binary data: cowork neither interprets its MIME metadata nor executes its contents. Its filename must be a path-free name of at most 255 UTF-8 bytes (not `.`, `..`, or a name containing `/`, `\\`, or NUL); MIME metadata may be empty and is limited to 255 UTF-8 bytes. Zero-byte files are valid. The maximum file size is 2 MiB (2,097,152 bytes), and a larger file is rejected explicitly.
|
|
43
43
|
|
|
44
|
+
Every participant-facing version-one room envelope includes the authenticated
|
|
45
|
+
top-level `room_name`, including messages, file metadata, and the
|
|
46
|
+
`room_not_member` notice. It is the room's validated presentation name (trimmed,
|
|
47
|
+
Unicode NFC, 1–64 characters, with control and format characters rejected), so
|
|
48
|
+
clients can render the task/room title without deriving it from the SDK identity
|
|
49
|
+
name, slug, or room ID.
|
|
50
|
+
|
|
44
51
|
Incoming message listings contain authorization metadata but no body. Cowork resolves each selected wire ID through persistent SDK history, verifies that the history row matches the listing, archives the message and complete recipient-intent fan-out, and then asks the SDK to read one oldest unread row. If an older introduction becomes unread between listing and acknowledgement, that authoritative row is archived through the same intake path before cowork retries the expected row. There is no defer operation; an empty acknowledgement means another reader already advanced the expected row.
|
|
45
52
|
|
|
46
53
|
For a file, cowork reads the identity-scoped immutable blob while the item is still unread and verifies its length and SHA-256 against SDK metadata. It then durably archives the exact bytes as canonical base64 together with the reply reference and every per-recipient relay intent before selecting that exact 64-hex wire ID with `getFiles`. Each other active seat receives two SDK items: an authenticated `room_file` metadata envelope and a binary file containing the original bytes. The SDK receives bytes, never a local filesystem path, so there is no staging-file or path-permission dependency. A seat removed after fan-out is skipped terminally without receiving metadata or bytes. A crash can redrive an unfinished recipient from the cowork archive; an already terminal recipient is not retried.
|
|
@@ -6,9 +6,9 @@ Back up the complete cowork state directory as one unit, preserving ownership an
|
|
|
6
6
|
|
|
7
7
|
For restore, stop cowork, replace the complete cowork state directory with the complete backup, restore its original owner and `0700`/`0600` permissions, ensure the shared daemon already contains the corresponding room identities, and then start cowork. 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.
|
|
8
8
|
|
|
9
|
-
An established
|
|
9
|
+
An established room restores only by choosing its exact persisted `ours-cowork:<normalized creation name>` identity with `force: false` and verifying the exact durable identity CID. Mutable `room_name` metadata does not participate in restore or Messenger display. If that exact identity is absent from the shared daemon or its CID differs, startup fails clearly; cowork never renames, adopts, or recreates an established identity. Only a durable `packet_pending` room may create a missing identity.
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
Earlier unreleased ID- and slug-based identity formats are rejected. This unreleased major provides no migration or down-migration.
|
|
12
12
|
|
|
13
13
|
Metadata using the exact legacy `cowork-room-<room_id>` form remains loadable so cowork can identify it and provide explicit migration guidance, but it is not a standard-restorable identity. Pre-1.0 custom packet state is refused rather than upgraded, renamed, or recreated in place: back it up with its compatible old release, recreate the room, and re-invite its participants.
|
|
14
14
|
|
package/docs/10-limitations.md
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
- 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.
|
|
16
16
|
- Web updates use periodic polling rather than push. A view can lag daemon state until its next refresh; confirmed mutations trigger an immediate refresh.
|
|
17
17
|
- Browser state is transient apart from the selected-room URL hash. Invite receipts disappear when closed and are not recoverable from browser storage.
|
|
18
|
-
- Room names are
|
|
18
|
+
- Room identity names are daemon-global. Creating another room with the same normalized name collides and fails closed. Each identity is exactly `ours-cowork:<normalized creation name>` and freezes at creation, so a later `room_name` edit does not rename Messenger contacts. Interfaces distinguish renamed rooms by CID/room ID; local aliases do not change authenticated provenance.
|
|
19
19
|
- Fresh and packet-pending provisioning refuses to adopt a same-name identity without a durably recorded expected CID. A crash after shared-daemon identity creation but before cowork's CID save can therefore leave an unproven orphan that prevents startup. After verifying no cowork metadata records its CID, an operator must remove that exact orphan with standard ours identity tooling and restart cowork. This destructive recovery is intentionally manual and fail-closed.
|
|
20
20
|
- Cowork selects room identities by the exact names stored in its local room records. That filter prevents unrelated daemon-global identities from appearing as cowork rooms, but it is bookkeeping rather than an ownership, provenance, membership, or same-user security model.
|
|
21
21
|
- Pre-1.0 custom room actor state cannot be opened by the standard SDK runtime. Back it up with the old release, recreate the room, and re-invite its participants.
|
package/docs/11-web-console.md
CHANGED
|
@@ -25,12 +25,12 @@ Every room operation is carried by the single route `POST /rpc` with the envelop
|
|
|
25
25
|
|
|
26
26
|
1. Choose Create room and enter the friendly Name, Goal, and Briefing. The name is shown in the room list, workspace header, and room details.
|
|
27
27
|
2. Submit once. The new room is selected and its Invite panel opens.
|
|
28
|
-
3. Add one
|
|
28
|
+
3. Add one or more invitation requirements. Choose one-time or public mode and set the minimum acceptances for a public invite. Each contact is admitted into the exact role authenticated by the invite it redeemed. An older SDK without invite provenance will ask you to revoke or consume the current invite before creating another.
|
|
29
29
|
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.
|
|
30
30
|
|
|
31
31
|
The room activates after its durable invitation requirements are satisfied. Participants shows admitted identities and their invite roles.
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
Names are trimmed and Unicode NFC-normalized, must contain 1–64 Unicode characters, and cannot contain Unicode control or format characters. At creation, the normalized name must not collide with an identity already in the shared daemon. Change local room metadata in Room settings. The browser continues to route by the opaque room ID; renaming does not change the URL, storage key, or underlying `ours-cowork:<creation name>` identity. Unnamed creation requests use `Room <first 8 room_id characters>`.
|
|
34
34
|
|
|
35
35
|
## Communication and records
|
|
36
36
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ours.network/cowork",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "Durable ours mission rooms on the shared ours daemon.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "FSL-1.1-Apache-2.0",
|
|
@@ -26,14 +26,14 @@
|
|
|
26
26
|
"test:release": "node --test tests/static-gates.test.mjs"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@ours.network/sdk": "3.0
|
|
29
|
+
"@ours.network/sdk": "3.5.0",
|
|
30
30
|
"react": "18.3.1",
|
|
31
31
|
"react-dom": "18.3.1",
|
|
32
32
|
"zod": "^3.23.8"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@adapt-toolkit/broker": "0.10.12",
|
|
36
|
-
"@ours.network/cli": "2.0
|
|
36
|
+
"@ours.network/cli": "2.5.0",
|
|
37
37
|
"@testing-library/jest-dom": "6.6.3",
|
|
38
38
|
"@testing-library/react": "16.1.0",
|
|
39
39
|
"@testing-library/user-event": "14.5.2",
|