Oko/Docs

Command reference

oko contact most set

Writes the account Most sends asks from (the handle Most's Messages account sends as) for the `most` channel, then shows the channel as `show` does. On the `most` channel an ask goes to the person's own iMessage handle (`oko contact imessage set`) through Most, which Oko finds through Stado's service directory (`stado service directory connect most --consumer oko`), never at a typed address; the person answers by replying in that chat.

Invocation#

Command
oko contact most set --sender ACCOUNT [--json]

Inputs and options#

  • --sender, the account Most sends from. It is an Oko setting (`oko.most.sender`) in Oko Desktop's preferences domain; `OKO_SETTINGS_DOMAIN` names another domain, which a test uses so it never writes the person's own settings.
  • Most's API bearer: the item playing role `most-api` (field `token`) read as consumer `oko-most-client`, or on a machine without Skarbiec the owner-only file `OKO_MOST_TOKEN_FILE` names, the same value Most checks through `MOST_API_TOKEN_FILE`.

Output and state effect#

  • Sending: `POST <Most>/v3/chats` with `from` the sender, `to` the handle, the ask's question, detail, choices and how to answer; the delivery row says `sent through Most at <route> (stado service directory connect most --consumer oko) from <sender> to <handle>: chat <id>, message <id> <status>; a reply in that chat answers the ask through <receiver>`. The chat is kept in `most-chats.json` (`OKO_MOST_CHATS`).
  • The way back: Oko's service (`oko serve`) runs a loopback receiver and records its address, its own signing secret and its pid in `most-receiver.json` (`OKO_MOST_RECEIVER`). Before sending, Oko subscribes Most's `message.received` events to that receiver under that secret (`POST /v3/webhook-subscriptions`), reusing the subscription while Most still lists it. An event is taken only when its `X-Webhook-Signature` is the HMAC-SHA-256 of `<timestamp>.<body>` under the secret, its chat is one an ask went out on, and its sender is the handle that ask went to; its text then answers the ask as `oko asks answer` does, recorded `on` `most`, and Oko writes `Taken: your answer “<text>” is recorded for ask <id>.` or `Not taken: <cause>` back into the chat once Most has its HTTP answer.
  • Real test: `tests/asks/most/journey.rs` (`cargo test --test asks-most -- --ignored`), with a real `most-server` (`OKO_TEST_MOST_SERVER`) in its `dev-remote` composition, the test as its only worker so nothing leaves the machine, the real `stado` on a registry of the run's own, and a disposable local Oko database (`OKO_TEST_MOST_DATABASE`, `OKO_TEST_MOST_ANON_KEY`). It checks that the person's own settings domain is unchanged.

Refusals and safe exits#

  • `oko contact most set requires a non-empty --sender` (exit 2); `oko contact most takes set or show; got <verb>` (exit 2).
  • `the most channel has no account to send from: the Oko setting oko.most.sender is not set in <domain>; set it with `oko contact most set --sender ACCOUNT`…`, and the `imessage` handle refusal when the person's handle is not set.
  • `Most could not be found through Stado's service directory (stado service directory connect most --consumer oko): <Stado's answer>; Most is reached only where the directory places it: place it with `stado service ensure most --host <host>` and admit Oko with `stado service directory consumer add most oko`` — Stado's answer says which: `unknown logical service "most"`, `consumer "oko" is not authorized for service "most"`, or that Most did not answer where it is placed; `… gave <url>, an address Oko does not send Most's bearer to (HTTPS, or HTTP on a loopback host)`.
  • `no reply receiver for Most runs on this machine (<file> names none): Oko's service (`oko serve`) runs it; …` and `the reply receiver for Most that <file> names (<url>) belonged to Oko's service as pid <pid>, which no longer runs; …`: an ask is never sent where its reply could not come back.
  • `OKO_MOST_TOKEN_FILE=<path> is readable by others; make it owner-only (chmod 600) before it is used`, `… cannot be read: <error>`, `… is empty`; `Most's bearer could not be read: role most-api field token as oko-most-client: <cause>; …`.
  • Most's own answer: `Most answered POST <url> with HTTP <status>: <body>` (with `; the bearer is not the one Most checks …` for 401 and `; Most cannot check bearers or has no transport for this now, see its log` for 503), `Most at <url> could not be reached for <request>: <error>; …`, `Most did not send the ask to <handle>: <error> (chat <id>)`, `Most recorded the ask to <handle> as failed and gave no cause (chat <id>)`, `Most took the ask but named no chat for it: <answer>`, `Most sent the ask on chat <id>, but the chat could not be kept for its reply: <cause>`.
  • Each is the `most` delivery's failed row: the ask is queued with it, as every channel's refusal is, and `oko asks deliver <id>` sends it again once the cause is gone.
  • At the receiver, answered to Most (and kept in its webhook outbox) and said on the service's stderr: 401 `the event's signature is not Most's under the secret this receiver subscribed with; it was not taken` or `the event carries no X-Webhook-Timestamp and X-Webhook-Signature, so it is not Most's`; 403 `a message in chat <id> came from "<handle>", not from <handle>, the handle ask <id> was sent to; only the person it was put to answers it`; 400 `the reply in chat <id> carries no text to answer ask <id> with`; 409 `the reply “<text>” in chat <id> did not answer ask <id>: <cause>` (already answered, expired, not one of its choices), which is also written back into the chat as `Not taken: <cause>`.

CLI reference#