Echo/Docs

CLI command

content case-study

Case studies and customer consent: a blog post marked as a case study is published only while its customer's consent is in force.

Invocation#

Shell
echo-cli content case-study list
echo-cli content case-study consent --customer <name> --granted-by <person> --evidence <text> --by <name>
echo-cli content case-study revoke --customer <name> --by <name>
echo-cli content case-study mark --post <post-id> --customer <name> --by <name>
echo-cli content case-study draft --customer <name> --subject <user|anonymous|revenuecat id> --days <n> --surface <slug> --slug <slug> --by <name>

Inputs and output#

list writes consents, newest first (id, customer, granted_by, evidence, recorded_by, recorded_at, revoked_by and revoked_at, null until revoked), and case_studies (post_id, customer, marked_by, marked_at). consent and revoke write the consent; mark writes the case study. draft writes { post, case_study, usage, route }: usage is the customer's events of the last --days days — every web and mobile event of each identifier the identity edges link to --subject, as tracking identity show resolves them — counted per source and event (table, app_id, event_name, events), most first; route is the deployment's ECHO_CASE_STUDY_ROUTE, which wrote the post through Brama from those counts alone; post is the draft stored at --slug on the blog surface --surface (status draft, with title, description, body_markdown, reading_minutes and keywords) and case_study its mark as the customer's case study, so publishing it stays the blog admin's or an approved publish_blog_post's, and is refused once the consent is revoked.

State effect#

Every verb calls Echo Web's authenticated /api/analytics/case-studies with ECHO_INTERNAL_BEARER at ECHO_WEB_BASE_URL; the Case studies section of the blog admin and of Echo Desktop's GEO screen call the same operation, and echo-mcp reads it as echo_case_studies. Consents are kept in case_study_consents, at most one in force per customer, revoked rather than deleted; marks in case_studies. Before a post is published — by the blog admin's publish button or by an approved publish_blog_post — a post marked as a case study is refused while its customer has no consent in force.

Refusals#

  • A wrong invocation is refused before anything is sent: "content takes evergreen, interactive, case-study, review; got <word>", "content case-study takes <every verb's usage>; got <word>", "content case-study <verb> needs <flag>" and "--days must be a whole number of days; got <value>".
  • Echo Web answers a bad request with "customer is required: …", "granted_by is required: …", "evidence is required: …" or "post_id is required: …"; not found with "<customer> has no consent in force to revoke" or "no blog post has id <id>"; and a conflict with "<customer> has consent <id> in force since <instant>". Publishing a case study without consent is answered as a conflict: "not published: post <id> is a case study of <customer>, who has no consent in force; echo-cli content case-study consent --customer \"<customer>\" records it". The command prints Echo Web's sentence and exits 1.
  • draft is refused before the route is asked: as a bad request with "subject is required: …", "surface_slug is required: …", "slug is required: …" or "days must be a positive whole number: the window to read"; as not found with "<customer> has no case study consent in force, so nothing about them is drafted; echo-cli content case-study consent records it", "no identity edge names <subject>; it was never seen at a sign-in" or "<subject> sent no event in the last <days> days, so there is no usage of <customer> to draw a case study from"; and a deployment without ECHO_CASE_STUDY_ROUTE fails naming the setting. After the route answers, a post citing a number the usage does not hold fails with "the case study cites <numbers>, which the customer's usage does not hold; nothing was stored", a post missing a field with "the route <route> called record_case_study without a title, description and body: …", and a slug the surface already has or a surface that does not exist with "the case study of <customer> could not become a draft post at <slug> on <surface>: <cause>" as a bad request.