@openwop/cli 1.0.1 → 1.1.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.
Files changed (4) hide show
  1. package/README.md +266 -10
  2. package/dist/cli.js +17158 -1335
  3. package/dist/openwop.js +17140 -1335
  4. package/package.json +1 -1
package/README.md CHANGED
@@ -19,8 +19,15 @@ The CLI is a host-agnostic **control plane**: every group drives one protocol su
19
19
  | **Memory & workspace** | `memory` · `workspace` · `prompts` |
20
20
  | **Automation & messaging** | `cron` · `webhooks` · `messaging` · `relay` · `notifications` · `notify` |
21
21
  | **Observability & admin** | `analytics` (`usage`) · `account` · `admin` · `brand` · `conformance` |
22
- | **Product surfaces** | `crm` · `csm` · `comments` · `sharing` · `forms` · `email` · `chat-widget` · `marketplace` · `kb` · `cms` · `documents` · `projects` · `strategy` · `advisors` · `campaigns-orchestration` · `notebooks` · `podcasts` · `priority-matrix` |
22
+ | **Product surfaces** | `crm` · `csm` · `comments` · `sharing` · `forms` · `email` · `chat-widget` · `marketplace` · `kb` · `cms` · `documents` · `projects` · `strategy` · `advisors` · `campaigns-orchestration` · `notebooks` · `podcasts` · `priority-matrix` · `docs` · `knowledge-sync` · `entities` · `creative-briefs` · `creative-video` · `production` · `tutorials` · `walkthroughs` · `widgets` · `ui-state` · `ui-plugin` · `canvas-collab` · `workflow-collab` · `canvas-packs` · `present` |
23
+ | **Commerce & sales** | `commerce` · `commerce-connect` · `promotions` · `recommendations` · `dealers` · `commissions` · `territories` · `sales-maps` (+ `crm` extensions) |
24
+ | **Marketing** | `brand-kits` · `campaign-brief` · `campaign-connectors` · `campaign-intel` · `campaign-journeys` · `cdp` · `destination-sync` · `discovery` · `funnels` · `webinars` · `public` |
25
+ | **Operator administration** | `vault` · `developer-keys` · `billing` · `environments` · `custom-domains` · `site-config` · `runtime-posture` · `maintenance` · `menu-config` |
26
+ | **Operations & work management** | `operations` · `service-desk` · `job-search` · `kicktodo` · `dashboard` · `bi` · `insights-suite` · `intent-ledger` · `work-graph` · `work-selection` · `tasks` · `model-router` · `dev` (+ `strategy` / `priority-matrix` / `projects` / `goals` / `workforces` / `roster` / `profiles` / `twin` / `agent-ops` / `analytics` / `marketplace` / `connections` / `workspace` extensions) |
23
27
  | **Protocol surfaces (RFC)** | `a2a` · `triggers` · `goals` · `proposals` · `export` / `import` |
28
+ | **Protocol + run operations** | `content` (RFC 0103) · `dispatch` (RFC 0118) · `openapi` · `agent-knowledge` · `compat-endpoints` (RFC 0108) · `host-events` · `client-support` (+ `runs` / `interrupts` / `workflows` / `approvals` / `reviews` / `webhooks` / `prompts` / `catalog` extensions) |
29
+ | **Conversations & messaging** | `chat` (sessions/messages/search/export/tools) · `assistant` · `channels` · `scheduled-chats` · `voice` · `ai` · `computer-use` · `whatsapp` · `agent-author` · `workflow-author` · `workflow-proposals` (+ `a2a`, `notifications` extensions) |
30
+ | **Settings & policy** | `capability-firewall` · `heartbeat` · `settings` (+ `cms` / `email` / `kb` / `forms` / `chat-widget` / `consent` / `approvals` / `profiles` / `advisors` / `campaigns-orchestration` / `notifications` / `workflows` / `kanban` / `job-search` extensions) |
24
31
 
25
32
  > **`0.18.x`:** the catalog now covers the full app feature surface — the agent
26
33
  > platform (`agent-profile`, `agent-packs`, `agent-allowlists`, `agent-ops`,
@@ -30,16 +37,68 @@ The CLI is a host-agnostic **control plane**: every group drives one protocol su
30
37
  > `triggers`, `goals`, `proposals`, `export`/`import`). See [`CHANGELOG.md`](./CHANGELOG.md)
31
38
  > for the per-group detail.
32
39
 
40
+ > **Knowledge + content surfaces:** `documents` (+ `artifacts`, `locate`,
41
+ > templates catalog/assemble), `notebooks` (sources/transformations/chat/search),
42
+ > `podcasts` (shows + episode/speaker profiles), `knowledge-sync`, the `media`
43
+ > library (assets, collections, AI image edit/upscale, local-file `upload`),
44
+ > `entities` (+ anonymous `public` reads), `creative-briefs`, `creative-video`,
45
+ > `production`, and the smaller `tutorials` / `walkthroughs` / `widgets` /
46
+ > `ui-state` / `ui-plugin` / `canvas-collab` / `workflow-collab` / `canvas-packs`
47
+ > / `present` groups. Example:
48
+ >
49
+ > ```bash
50
+ > openwop media assets create ./logo.png --org org_1 --tags brand
51
+ > openwop entities types list --json
52
+ > openwop documents render doc_1 --org org_1 --format docx
53
+ > ```
54
+
55
+ > **Protocol + run operations:** `agents list|info`, `roster list` and
56
+ > `org-chart get|dept` now read the NORMATIVE `/v1/agents`, `/v1/agents/roster`
57
+ > and `/v1/agents/org-chart[/{departmentId}]`, falling back to the host-extension
58
+ > path only when the host does not serve the normative read (`--host` forces it,
59
+ > `--verbose` names the path that answered). New: `content` (RFC 0103
60
+ > `/v1/content/*`), `runs effects|revision|pin|unpin|redrive`, `interrupts
61
+ > inspect|respond`, `webhooks rotate-secret|dead-letters`, `catalog packs
62
+ > search|get|export`, `workflows archive|promote|revisions|rollback|stats|estimate|pins|debug-run|eval-set…`,
63
+ > `approvals sla-policy|email-pref|delegations`, `prompts library …`,
64
+ > `agent-knowledge`, `compat-endpoints`, `host-events`, `client-support`,
65
+ > `dispatch fanout`, `openapi`. Example:
66
+ >
67
+ > ```bash
68
+ > openwop content page pricing --locale es
69
+ > openwop runs effects run_123 --json
70
+ > openwop interrupts respond run_123 approve-gate --data-json '{"action":"approve"}'
71
+ > openwop workflows promote wf_123 && openwop workflows revisions wf_123
72
+ > openwop webhooks rotate-secret sub_1 --generate
73
+ > ```
74
+
33
75
  ## Protocol version support (v2 and v1)
34
76
 
35
77
  The CLI speaks the **OpenWOP wire directly** — no SDK dependency — and negotiates the protocol major once per invocation (`src/protocol.ts`, per `spec/v2/core/versioning.md` §1.5):
36
78
 
37
- - It reads `/.well-known/openwop` and selects the **highest major it implements that the host advertises** in `protocolVersions[]` — 2 when the host lists any `2.x`, otherwise 1.
38
- - Under major 2, every request for an operation named in `spec/v2/path-manifest.json` goes to the **unversioned path with `OpenWOP-Version: 2.0`** (`/v1/runs` → `/runs`). Host-proprietary routes the manifest does not name — the demo backend's `/v1/host/sample/*` — are sent exactly as written; they have no v2 home yet (`versioning.md` §5).
79
+ - It reads `/.well-known/openwop` once (asking for the v2 representation with `OpenWOP-Version: 2`; a host that doesn't serve major 2 answers `406` with the list it does serve) and selects the **highest major it implements that the host advertises** in `protocolVersions[]` — 2 when the host lists any `2.x`, otherwise 1.
80
+ - Under major 2, every request for an operation named in `spec/v2/path-manifest.json` goes to the **unversioned path with `OpenWOP-Version: 2.0`** (`/v1/runs` → `/runs`). Host-proprietary routes the manifest does not name — the reference host's `/v1/host/openwop-app/*` — go to the **unversioned root the host advertises** for that org under `extensions.*` (`{ "root": "/host/openwop-app/", "twin": "/v1/host/openwop-app/" }`, `versioning.md` §5), with **no** version header (a `/host/<org>/` path has no major). With no advertised root, the `/v1/host/<org>/…` twin is sent as written.
39
81
  - Under major 1 nothing changes: `/v1/…` paths, header-less, the v1 default the overlap guarantees.
40
82
  - `OPENWOP_PROTOCOL_MAJOR=1` or `=2` pins the major without probing discovery.
41
83
 
42
- `openwop doctor`'s `protocol` row reports `protocolVersions`, `preferredVersion`, and the major this process selected; it fails only when the host advertises neither major the CLI implements.
84
+ `openwop doctor`'s `protocol` row reports `protocolVersions`, `preferredVersion`, and the major this process selected; it fails when the host advertises neither major the CLI implements. Its `response version` row reports the `OpenWOP-Version` the host answered with and fails on a silent downgrade (`versioning.md` §1.4); its `min client` row fails when the host's `minClientVersion` is above the version the CLI speaks (2.0 / 1.1) — the host MAY then refuse requests with `426 client_version_unsupported` (§1.5).
85
+
86
+ What else the CLI does as a v2 client (audited against `spec/v2/core/*` at corpus `v2.42.6`):
87
+
88
+ | Obligation | Behaviour |
89
+ |---|---|
90
+ | Tenant-bound ids (`identity.md` §5) | A `<tenantId>/<id>` run id is sent in the projected wire form (`acme~2Fr1`) on every `/runs/{runId}…` path under major 2 — never `%2F`, which a decoding front door turns into a 404. Pass ids as the host prints them. |
91
+ | Error envelope (`errors.md`) | Errors print as `HTTP <status> <code>: <message>`; `426`/`406`/`429` add an actionable hint (`Retry-After` for 429). |
92
+ | Poll cursor (`events.md` §Poll) | `afterSequence` under major 2, `lastSequence` under major 1; `isTerminal` / `isComplete`. |
93
+ | SSE resume (`events.md` §Resuming with `Last-Event-ID`; v1 `stream-modes.md` §Resumption) | Every run stream (`runs events --follow` / `runs watch`, `chat`, `workflow-author`) remembers the last `id:` and, when the connection drops or closes before the terminal event, reconnects with `Last-Event-ID` after the server's `retry:` delay (doubling per attempt without progress, cap 30 s, 5 attempts). A close is first checked against the run's status, so a mode that never carries the terminal event (`messages`) ends cleanly. Events are deduped by `sequence`, so nothing prints twice even from a host that re-emits the resumption point. `--since N` / `--last-event-id ID` start mid-log: both majors send the `Last-Event-ID` header (neither defines a `since` stream parameter); v2 requires an integer id, v1's is sent verbatim. |
94
+ | Stream modes (`events.md` §Stream modes; v1 `stream-modes.md`) | `--stream-mode` `updates`, `values`, `messages`, `debug` or a comma list of `updates`/`messages`/`debug` → `?streamMode=`, validated against the spec pattern before any request (`values` never combines). A host `400 unsupported_stream_mode` is reported with its `details.supported`, never silently replaced by the (mode-less) poll fallback. `state.snapshot` and `ai.message.chunk` frames are rendered by their frame name; `event: batch` arrays are unpacked. |
95
+ | Event names (`events.md` §Types) | v1 and v2 names (`run.resuming` / `run.resume-started`, `agent.toolCalled` / `agent.tool-called`, …) render identically; the table is pinned to `spec/v2/event-codemap.json`. |
96
+ | `Idempotency-Key` (`idempotency.md`) | Sent on run create/fork, chat turns, interrupt resolve, and webhook / trigger / prompt creation; `--idempotency-key` on `runs create|fork` and `interrupts resolve`. |
97
+ | Interrupt resolve (`interrupt.md`) | Body is the closed `{ "resumeValue": … }`. |
98
+ | Discovery (`capabilities.md`) | `openwop capabilities` renders the v2 root (records by status, `minClientVersion`, `eventLogSchemaVersion`, `extensions`) from the negotiation read. |
99
+ | Run list (`runs.md` §List) | `runs list --cursor` / `--workflow-id`; the `nextCursor` hint is printed. |
100
+
101
+ When the host's `minClientVersion` is above the CLI, every command prints one warning (from the discovery read it already made); refusing is left to the host (`426`). Not exposed: the `bufferMs` batching hint (batched frames from a host that batches anyway are consumed).
43
102
 
44
103
  The pre-1.0 `0.18.x` line was frozen v1-only; that decision was reversed with 1.0.0 (CHANGELOG). The frozen line stays on branch `cli-v1-frozen` for anyone who needs a client that never sends `OpenWOP-Version`.
45
104
 
@@ -74,7 +133,7 @@ The `onboard` wizard walks you through:
74
133
 
75
134
  1. **Host URL** — `https://app.openwop.dev/api` (shared demo), `http://localhost:8080` (local), or a custom URL.
76
135
  2. **AI provider** — `anthropic`, `openai`, `google`, or `minimax` (matches what the demo backend dispatches to).
77
- 3. **API key** — auto-detects `ANTHROPIC_API_KEY` / `OPENAI_API_KEY` / `GOOGLE_API_KEY` / `MINIMAX_API_KEY`, or hidden-input via raw-mode stdin. The key is POSTed to `/v1/host/sample/byok/secrets` on the configured host. **The key is never written to your local config file** — only a credential ref pointer is stored.
136
+ 3. **API key** — auto-detects `ANTHROPIC_API_KEY` / `OPENAI_API_KEY` / `GOOGLE_API_KEY` / `MINIMAX_API_KEY`, or hidden-input via raw-mode stdin. The key is POSTed to `/v1/host/openwop-app/byok/secrets` on the configured host. **The key is never written to your local config file** — only a credential ref pointer is stored.
78
137
  4. **Model** — provider-specific recommended defaults plus a custom option.
79
138
  5. **Test the connection** — verifies the credential ref appears in the host's BYOK list.
80
139
 
@@ -99,7 +158,7 @@ openwop providers remove openai
99
158
  openwop providers test anthropic
100
159
  ```
101
160
 
102
- `providers add` POSTs to `/v1/host/sample/byok/secrets`; `remove` DELETEs; `list` and `test` read.
161
+ `providers add` POSTs to `/v1/host/openwop-app/byok/secrets`; `remove` DELETEs; `list` and `test` read.
103
162
 
104
163
  ## Chat
105
164
 
@@ -116,6 +175,35 @@ openwop chat sample.chat.turn --no-stream --json
116
175
  - **Quitting** — `/exit`, `/quit`, or Ctrl-D (EOF).
117
176
  - **`--json`** — emits raw event records (one JSON object per event) instead of the pretty `assistant>` rendering.
118
177
  - Extra per-turn inputs (`--input k=v`, `--inputs-json`) ride along on every run, so you can pin a `credentialRef`, model, or other configurable input.
178
+
179
+ ### Conversations, channels & voice
180
+
181
+ `chat` is the ONE chat group: besides the REPL it drives the host's persistent
182
+ conversations (`/v1/host/openwop-app/chat/*`) — sessions, messages, reactions,
183
+ participants, feedback, search, export/import, and per-conversation tool scope.
184
+ Team channels, scheduled agent chats, the executive assistant, voice, and the AI
185
+ authoring surfaces each have their own group; every `--help` names the exact path.
186
+
187
+ ```bash
188
+ openwop chat sessions create --title "Launch plan" --type group --participant agent:core.openwop.agents.planner.default
189
+ openwop chat messages send <sessionId> --content "Summarize the thread"
190
+ openwop chat search "pricing" --limit 5 --json
191
+ openwop chat export <sessionId> --format md --output thread.md
192
+ openwop chat tools set <sessionId> --mode restricted --enable openwop:fs.read
193
+ openwop channels post <channelId> --content "@planner draft the agenda"
194
+ openwop channels stream <channelId> --max-events 5
195
+ openwop scheduled-chats create --org org_1 --conversation <id> --agent <agentId> --prompt "Weekly status" --cron "0 9 * * 1"
196
+ openwop assistant pending approve <actionId> --content-hash <hash-from-the-card>
197
+ openwop voice session audio <sessionId> --file hello.webm && openwop voice session commit <sessionId>
198
+ openwop workflow-author draft --intent "Every Monday, summarize open tickets and email me" --follow
199
+ openwop notifications stream --max-events 3
200
+ ```
201
+
202
+ Streams (`channels stream|presence`, `notifications stream`, `voice realtime
203
+ transcript`) stop after `--max-events` or `--timeout-ms` (default 30 s). Secrets
204
+ stay server-side: the realtime voice token is redacted unless `--reveal-token`,
205
+ and `ai bind-credential` reads the credential from a file or env var and prints
206
+ only the returned reference.
119
207
  ## Packs (signed node-pack registry)
120
208
 
121
209
  ```bash
@@ -136,7 +224,7 @@ These talk to the signed node-pack registry — a **separate surface** from the
136
224
 
137
225
  ## Messaging & relay
138
226
 
139
- Connect chat channels (Signal / WhatsApp / iMessage) to the host so inbound messages drive workflow runs and replies are delivered back. Channels are a **host-extension** surface (`/v1/host/sample/messaging`), not part of the normative OpenWOP wire — the protocol stays channel-agnostic.
227
+ Connect chat channels (Signal / WhatsApp / iMessage) to the host so inbound messages drive workflow runs and replies are delivered back. Channels are a **host-extension** surface (`/v1/host/openwop-app/messaging`), not part of the normative OpenWOP wire — the protocol stays channel-agnostic.
140
228
 
141
229
  ```bash
142
230
  openwop relay setup --channel signal # register + activate a device, store its token
@@ -182,9 +270,10 @@ openwop runs annotate <runId> --rating 5 [--note "great"] # attach a rating/labe
182
270
  openwop runs annotate <runId> --label triage --event-id <id>
183
271
  openwop runs debug-bundle <runId> [--max-events n] [--out bundle.json]
184
272
  openwop runs ancestry <runId> # RFC 0040 cross-host parent chain
273
+ openwop runs watch <runId> [--since N] [--stream-mode updates,messages] # SSE follow, auto-resumes on a drop
185
274
  ```
186
275
 
187
- `runs events --since N` maps to the spec-canonical `lastSequence` query param (events with `sequence > N`). `runs annotate` posts exactly one signal kind (`--rating 1-5` | `--label` | `--correction` | `--flag`), validated client-side. `runs debug-bundle --out <file>` saves the full event bundle to disk.
276
+ `runs events --since N` polls with the poll cursor (`afterSequence` under v2, `lastSequence` under v1; events with `sequence > N`). `runs events --follow` / `runs watch` stream over SSE instead, where `--since N` becomes the `Last-Event-ID` header (see §Protocol version support). `runs annotate` posts exactly one signal kind (`--rating 1-5` | `--label` | `--correction` | `--flag`), validated client-side. `runs debug-bundle --out <file>` saves the full event bundle to disk.
188
277
 
189
278
  ## Operator surfaces
190
279
 
@@ -268,7 +357,7 @@ Exit codes: `0` success · `1` host/HTTP error (including consent not enabled)
268
357
 
269
358
  ## MCP server mount
270
359
 
271
- An MCP client for the host's JSON-RPC server mount (RFC 0020) — a single JSON-RPC 2.0 endpoint at `POST /v1/host/sample/mcp` speaking modelcontextprotocol.io 2025-06-18. The mount is **host-controlled**: it's env-gated (`OPENWOP_MCP_SERVER_ENABLED`, **OFF by default**) and the CLI cannot toggle it. When the mount isn't exposed the endpoint 404s and these commands **fail closed legibly** (exit 2).
360
+ An MCP client for the host's JSON-RPC server mount (RFC 0020) — a single JSON-RPC 2.0 endpoint at `POST /v1/host/openwop-app/mcp` speaking modelcontextprotocol.io 2025-06-18. The mount is **host-controlled**: it's env-gated (`OPENWOP_MCP_SERVER_ENABLED`, **OFF by default**) and the CLI cannot toggle it. When the mount isn't exposed the endpoint 404s and these commands **fail closed legibly** (exit 2).
272
361
 
273
362
  ```bash
274
363
  openwop mcp ping # liveness probe of the mount
@@ -328,7 +417,7 @@ Identity `source` is one of `oidc | password | saml | scim | manual`. Exit codes
328
417
 
329
418
  ## Feature toggles
330
419
 
331
- `toggles` renders the caller's **resolved** feature-toggle assignments (a non-normative host extension under `/v1/host/sample/feature-toggles/assignments`). The **host** is the sole authority — it resolves every toggle server-side from the authenticated principal — and the CLI only *displays* what the host returns. It **never** computes, asserts, or overrides a toggle decision locally, and it does not author config (the superadmin config surface is intentionally not exposed). When the host doesn't serve the surface the command fails closed (exit 2).
420
+ `toggles` renders the caller's **resolved** feature-toggle assignments (a non-normative host extension under `/v1/host/openwop-app/feature-toggles/assignments`). The **host** is the sole authority — it resolves every toggle server-side from the authenticated principal — and the CLI only *displays* what the host returns. It **never** computes, asserts, or overrides a toggle decision locally, and it does not author config (the superadmin config surface is intentionally not exposed). When the host doesn't serve the surface the command fails closed (exit 2).
332
421
 
333
422
  ```bash
334
423
  openwop toggles list # every toggle's resolved state for you (incl. off)
@@ -443,6 +532,63 @@ openwop a2a task run_abc123 --json # the durable task's live state
443
532
 
444
533
  The record is content-free by design (state, `interruptKind`, push config — never run inputs/outputs/credentials); the CLI renders the host's resolved state and never derives one locally. Gated on `capabilities.a2a` (the durable read needs `durableTasks: true`). `task` exit codes: `0` completed · `3` submitted/working/input-required/auth-required · `1` failed/canceled/rejected or error.
445
534
 
535
+ ## Commerce & sales
536
+
537
+ Host-extension groups over the reference host's commerce and sales surfaces
538
+ (`/v1/host/openwop-app/{commerce,commerce-connect,promotions,recommendations,dealers,commissions,territories,sales-maps,crm}/…`,
539
+ plus the public visitor routes `public-store`, `public-recommendations`, `partner`,
540
+ `public-book`, `public-sign`, sent without auth). Each group's `--help` lists every
541
+ command with the exact method + path it hits. Org-scoped commands take `--org <orgId>`;
542
+ flags are the host's field names in kebab-case, and `--body`/`--body-file` supply a
543
+ full JSON body. Money amounts pass through exactly in the unit the host's field
544
+ names (`priceMinor`, `priceMajorUnits`, `price` …) — the CLI never computes a total.
545
+ Stripe Connect seller onboarding returns a hosted link only; no card or bank data
546
+ ever passes through the CLI.
547
+
548
+ ```bash
549
+ openwop commerce products list --org org_1 --q shirt
550
+ openwop commerce orders get ord_1 --org org_1 --json
551
+ openwop commerce public products --org org_1 # the anonymous storefront view
552
+ openwop commerce ucp token --org org_1 --client-id c_1 --client-secret-env UCP_SECRET
553
+ openwop commerce-connect seller onboard # prints the Stripe-hosted onboarding link
554
+ openwop promotions create --org org_1 --name "10% off 50+" --type cart_threshold --min-spend 50 --reward '{"kind":"percentage","value":10}'
555
+ openwop crm deals list --org org_1
556
+ openwop crm segments members seg_1 --json
557
+ openwop crm public-sign get <token>
558
+ openwop territories models activate mdl_1 --org org_1
559
+ openwop commissions statements pay st_1 --org org_1
560
+ ```
561
+
562
+ Destructive commands (deletes, refunds, cancels, voids) refuse without `--yes`.
563
+ Exit codes: `0` ok · `2` usage error / request rejected · `4` not signed in or not permitted · `1` server error.
564
+
565
+ ## Marketing surfaces
566
+
567
+ Marketing features on the reference host's `/v1/host/openwop-app/*` extension
568
+ (each is feature-toggled and org-scoped host-side; the CLI renders the host's decision):
569
+
570
+ ```bash
571
+ openwop brand-kits list --org org_1 # marketing brand kits (NOT `openwop brand`, the app-wide identity)
572
+ openwop campaign-brief briefs create --org org_1 --name "Q4 launch" --objective "Pipeline"
573
+ openwop campaign-connectors kpi --org org_1 --json # ad-platform performance roll-up
574
+ openwop campaign-intel plan-budget --org org_1 --total-budget-minor 500000 --target-conversions 200 --horizon-days 30
575
+ openwop cdp resolve --type email --value a@example.com
576
+ openwop destination-sync dry-run sync_1 --sample-json '{"email":"a@example.com"}'
577
+ openwop funnels publish fn_1 --org org_1
578
+ openwop webinars list --org org_1
579
+
580
+ # Anonymous visitor surfaces (no bearer sent) — test what your visitors see:
581
+ openwop public pages org_1
582
+ openwop public sitemap org_1
583
+ openwop public pricing --json
584
+ openwop funnels public view org_1 webinar
585
+ openwop forms public get form_1
586
+ openwop email public click <token> # prints the redirect target, does not follow it
587
+ ```
588
+
589
+ Destructive commands (`delete`, a live `campaign-intel apply`, an email
590
+ unsubscribe/preference change) refuse without `--yes`.
591
+
446
592
  ## Config
447
593
 
448
594
  `~/.openwop/config.json` (or `$OPENWOP_CONFIG_HOME/.openwop/`) stores the host URL, default provider, default model, and credential ref. **API keys are never stored locally.**
@@ -455,6 +601,116 @@ openwop config set defaultModel gpt-4o
455
601
  openwop config unset credentialRef
456
602
  ```
457
603
 
604
+ ## Identity & operator administration
605
+
606
+ Identity, RBAC, tenancy and operator surfaces of the reference host (all under
607
+ `/v1/host/openwop-app/…`; each group's `--help` names the exact path). Super-admin
608
+ surfaces (`vault`, `site-config get|set`, `runtime-posture`, `maintenance`,
609
+ `toggles admin`, `governance`, `billing` import/coupons/seats, `menu-config set tenant`,
610
+ `brand get|set|asset`) fail **closed** with exit `4` and say how to get a super-admin
611
+ principal (`OPENWOP_SUPERADMIN_TENANTS`); `admin …` needs the host admin token.
612
+ Secrets are refs only: vault values, the break-glass token and an anonymous session
613
+ cookie are read from a file or a no-echo prompt, never argv, and never printed. A
614
+ developer key's token is printed once, when the host issues it.
615
+
616
+ ```bash
617
+ openwop orgs invites org_1 create --email jo@acme.com --role editor
618
+ openwop orgs decide --principal user:jo --action runs:read # exit 0 allowed / 1 denied
619
+ openwop users me security
620
+ openwop vault list
621
+ openwop vault set billing:stripe-key --scope host --value-file ./stripe.key
622
+ openwop developer-keys create --name "CI deploy" --scope runs:write
623
+ openwop environments promote --from dev # exit 3 when queued for approval
624
+ openwop billing portal # a Stripe-hosted URL; no card data
625
+ openwop governance egress-rules set --mode allowlist --host api.stripe.com
626
+ openwop toggles admin set crm --status beta # read-modify-write
627
+ openwop admin run-retention hold t_acme --reason "legal hold"
628
+ ```
629
+
630
+ Not driven (browser or server-to-server legs): `POST /auth/saml/sso/acs` (IdP form
631
+ post), `POST /billing/webhook` (Stripe-signed), `POST /vault/secrets/:ref/reveal`
632
+ (returns plaintext). Exit codes: `0` ok · `1` server error · `2` usage error / request
633
+ rejected · `3` pending (approval queued, domain not yet live) · `4` not signed in / not permitted.
634
+
635
+ ## Operations & work management
636
+
637
+ Host-extension groups over the reference host's operations and work surfaces:
638
+ the operator console (`operations` — health, SLO, DLQ, dispatch outbox, webhook
639
+ delivery, saga compensation), the help desk (`service-desk`, plus the anonymous
640
+ `public` widget path), `job-search`, `kicktodo` readiness, your `dashboard`,
641
+ org `bi` metrics, `insights-suite`, a conversation's `intent-ledger`, ambient
642
+ `work-graph` suggestions, `work-selection` ranking, the run `tasks` deck, the
643
+ `model-router` switch, and the demo-only `dev ucp-merchant`. It also fills out
644
+ `strategy` (check-ins, versions, timeline, cadence, decisions, links),
645
+ `priority-matrix` (ideas, scores, intake, evidence, schedules, sessions,
646
+ scenarios, portfolio, federated peers), `projects` (knowledge, memory,
647
+ schedules, visibility, group chat), `goals` (arm / evaluate / record-run),
648
+ `workforces migration set`, `roster activity|check`, `profiles` (pins, avatar,
649
+ personal knowledge), `analytics` (trend, nav telemetry), `marketplace` (feature
650
+ bundles, pack enablement, certify, pack remove/restore) and `connections`
651
+ (delete, inbound webhook binding, provider catalog).
652
+
653
+ Each group's `--help` is generated from its route table and lists the exact
654
+ method + path every command hits. Flags are the host's field names in kebab-case;
655
+ writes also take `--body`/`--body-file`. Routes that REPLACE a whole document on
656
+ write (job-search steering, strategy cadence, bi metric definitions,
657
+ insights-suite config, profile contact) are read-modify-write, so flags you do not
658
+ pass keep their saved values. Secrets (a federated peer's bearer, an inbound
659
+ signing secret) are read from a file and never printed.
660
+
661
+ ```bash
662
+ openwop operations health --json # superadmin
663
+ openwop operations compensation run_42
664
+ openwop service-desk tickets org_1 --status open
665
+ openwop service-desk public send sdk_0123... --text "Hi" # the anonymous widget path
666
+ openwop strategy check-ins add s_1 kr_1 --value 42 --note "on track"
667
+ openwop priority-matrix ideas score l_1 c_1 --score reach=8 --score effort=3
668
+ openwop projects schedules add p_1 --cron-expr "0 9 * * 1" --workflow-id wf.weekly
669
+ openwop job-search steering set org_1 --roles "Staff Engineer" --remote --daily-cap 5
670
+ openwop bi metrics run org_1 open-deals --bucket week
671
+ openwop tasks deck
672
+ ```
673
+
674
+ Destructive commands refuse without `--yes`. Exit codes: `0` ok · `2` usage error /
675
+ not found / rejected · `4` not signed in or not permitted · `1` server error
676
+ (`kicktodo readiness` also exits `1` when the product reports `degraded`).
677
+
678
+ ## Residual host surfaces
679
+
680
+ The last host-extension routes the reference host serves, added as three new
681
+ groups — `capability-firewall` (composition rules, recent decisions, a read-only
682
+ `simulate`, and the super-admin platform baseline), `heartbeat` (the host-wide
683
+ agent heartbeat switch, super-admin) and `settings` (your personal token cap,
684
+ reasoning directive and privacy opt-outs) — and as route tables inside existing
685
+ groups: `cms` (scheduled publish/unpublish, version restore, review status, shared
686
+ sections, language settings, translator locale grants, per-locale publish, AI
687
+ section translation, page A/B experiments, and the page SEO head), `email` (sender
688
+ settings, provider status, bounce-webhook configs, campaign engagement), `kb`
689
+ (retrieval config, media-collection ingest, reindex drain/cancel), `forms`
690
+ (templates), `chat-widget tool-catalog`, `consent` (purpose vocabulary, re-admit an
691
+ erased subject), `approvals teams-pref`, `profiles memory-extraction`, `advisors`
692
+ (strategy context, shared knowledge), `campaigns-orchestration`
693
+ (workspace/versions/dispatches), `notifications preferences`, `workflows budget`,
694
+ `kanban column-limit|work-item-run` and `job-search answers`.
695
+
696
+ Replace-on-write documents (firewall rules, SEO head, heartbeat config,
697
+ notification preferences, personal settings, workflow budget) are
698
+ read-modify-write, so flags you do not pass keep their saved values. The email
699
+ webhook verification secret is read from a file and never printed.
700
+
701
+ ```bash
702
+ openwop capability-firewall simulate --org org_1 --next '{"egress":"safe-fetch"}' --seen '[{"safetyTier":"read"}]'
703
+ openwop cms schedule publish page_1 --org org_1 --at 2026-10-01T09:00:00Z
704
+ openwop cms experiments results page_1 pexp:1 --org org_1
705
+ openwop email webhooks add --org org_1 --provider postmark --verification-secret-file ./secret.txt
706
+ openwop notifications preferences set --quiet-hours --timezone Europe/Oslo
707
+ openwop workflows budget set wf_1 --daily-usd 10 --hard-cap
708
+ openwop settings prefs set --daily-token-cap 200000
709
+ ```
710
+
711
+ Exit codes: `0` ok · `2` usage error / not found / rejected · `4` not signed in or
712
+ not permitted (the super-admin surfaces say so) · `1` server error.
713
+
458
714
  ## Defaults
459
715
 
460
716
  - Host URL: `--base-url` > `OPENWOP_BASE_URL` > **saved config** (`onboard`'s `~/.openwop/config.json`) > `http://localhost:8080`. After `onboard`, everyday commands use the saved host with no flag.