Echo/Docs

CLI command

roadmap

A product's public roadmap: items the operator publishes, the page where signed-in users vote for them, and the votes they give.

Invocation#

Shell
echo-cli roadmap votes --product <id>
echo-cli roadmap page --product <id>
echo-cli roadmap widget --product <id>
echo-cli roadmap add --product <id> --title <text> --description <text> --by <name>
echo-cli roadmap publish --id <item-id>
echo-cli roadmap withdraw --id <item-id>
echo-cli roadmap ship --id <item-id>
echo-cli roadmap unship --id <item-id>

Inputs and output#

votes writes every item of the product, published or not, newest first: id, product_id, title, description, published_at, shipped_at (each null until set), created_by, created_at and votes, the number of signed-in users who voted for it. page writes url, the product's public roadmap page, and published, how many items it shows now. add, publish, withdraw, ship and unship write the item as it now stands.

State effect#

Every verb calls Echo Web's authenticated /api/analytics/roadmap with ECHO_INTERNAL_BEARER at ECHO_WEB_BASE_URL; the Public roadmap section of the tracking screen and of Echo Desktop's GEO screen call the same operations, open the public page and show the landing widget's snippet, and echo-mcp reads the items with their votes (echo_roadmap_votes), the page's address (echo_roadmap_page) and the widget (echo_roadmap_widget) but cannot change them. An item is written unpublished. publish stamps it, and from then on it appears on the public roadmap: the page /roadmap/<product id> on Echo Web, and GET /api/public/roadmap/<product id>, which anyone may read: only published items, most voted first, with their title, description, votes and stamps. withdraw clears the stamp and takes it off. ship and unship set or clear when it landed. On the page a signed-in user votes for an item with its Vote button (POST /api/public/roadmap/votes { item_id }), the items they already voted for shown as Voted and a refusal shown beside the button; a visitor who is not signed in sees the counts and a sign-in link that returns to the page. Each user votes once per item, and vote counts are read from the stored votes on every read.

Refusals#

  • A wrong invocation is refused before anything is sent: "roadmap takes <every verb's usage, separated by semicolons>; got <word>", "roadmap <verb> does not take <flag>; it takes …", "<flag> needs a value" and "roadmap <verb> needs <flag>" for each flag the verb needs.
  • widget writes { script_url, snippet, script_bytes } after reading the script Echo Web serves at GET /api/public/roadmap/widget: the snippet is the <script data-product> tag and the <div data-echo-roadmap> a product's landing embeds on its own origin. The script reads GET /api/public/roadmap/<product id> (answered with the deployment's CORS headers, so a page on an origin CORS_ALLOWED_ORIGINS declares can read it) and draws each published item's title, votes, description and, once shipped, that it shipped, as text, most voted first, with a link to the voting page on Echo, because a vote needs Echo's session, which a page on another origin does not carry. A product id that is not a UUID is answered not found with "no roadmap: the product id is not a UUID"; the script writes any refusal into the element, or to the console without one.
  • Echo Web answers a bad request with "product_id is required: …", "title is required: what will be built, in words a user reads", "description is required: what it does for the user", "id is required: …" or "created_by is required: an internal caller has no signed-in user, so it names who is acting"; and not found with "no product has id <id>; echo-cli products lists the ones that exist" or "no roadmap item has id <id>; echo-cli roadmap votes --product <id> lists them". The public vote answers "sign in to vote: a vote belongs to a signed-in user" as unauthorized, "no published roadmap item has id <id>" as not found, and "you already voted for \"<title>\" at <time>; each user votes once per item" as a conflict. The command prints Echo Web's sentence and exits non-zero.