Skip to content

docs(api): add POST /member/notify - #395

Merged
ysyneu merged 9 commits into
mainfrom
feat/member-notify
Sep 14, 2026
Merged

ysyneu merged 9 commits into
mainfrom
feat/member-notify

Conversation

@ysyneu

@ysyneu ysyneu commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

Summary

Documents POST /member/notify (operationId memberNotify, tag Platform / Members) in the en and zh specs, openapi.*.json and platform.openapi.*.json, and adds it to the docs.json navigation.

The endpoint emails account members on the caller's behalf. The message is written by an AI SRE agent inside an AI SRE session; any other credential gets a permission error.

  • Request. subject is 1–200 characters, used as written. html is an HTML fragment of up to 102,400 bytes and must be non-empty after sanitizing; recipients receive it as the whole email body, with nothing added around it — no platform layout, sender line, session link, footer, or subject prefix. The sender display name carries attribution instead: "<caller name> (via AI SRE)". person_ids is optional, up to 20, and defaults to the caller. dry_run (boolean, default false) runs every check — validation, sanitize, membership, email, preference, per-turn duplicate, hourly rate — without sending anything.
  • Sanitizing. Scripts, styles, frames, forms, SVG and event handlers are stripped. Only https image sources survive. Links are limited to http, https and mailto. Inline style attributes are kept as written.
  • Response. One recipients[] entry per recipient, with status accepted or skipped and a reason: not_member, no_email, email_disabled, duplicate, rate_limited or send_failed. With dry_run: true, recipients reflects what a real send would return, and html carries the exact, sanitized email document that would have been sent.
    The outcomes are named recipients, not items: across this API an items array next to scalar fields is a list page, and clients that bound list pages (the CLI's structured output does) would withhold outcomes to make room for a large html.
  • Limits. 20 emails per recipient per hour.

Checks

jq empty passes on all four spec files, and python3 scripts/lint_openapi.py passes.

Document the endpoint that sends an email notification to account
members with a caller-supplied HTML body. Adds the operation to the
platform module spec and the merged spec (en/zh), including request
and response schemas, per-recipient result reasons, and the shared
error responses used by the other /member/* operations. Registers
the new page in the API reference navigation alongside its siblings.
The email body is now exactly the sanitized html with no platform
layout, sender line, session link, footer, or subject prefix.
Attribution moves to the sender display name instead. Inline style
attributes are kept as written; the previous CSS property allowlist
is removed.

Add a dry_run request field: when true, every check runs (validation,
sanitize, membership, email, preference, per-turn duplicate, hourly
rate) without sending, and the response includes the exact email in a
new html field.
The endpoint's gateway route is registered without auditing, so the
usage note claiming every call is recorded in the account audit log
was incorrect.
The sanitizer removes disallowed content without an error, so a dry run is the only way to see the email recipients will get. Say so in the operation description, which is what generated clients show as the command help.
Recipients in every locale see the caller's name followed by (via AI SRE).
An items array beside scalar fields reads as a list page, and the CLI
bounds list pages by withholding rows. A dry run's html sibling made
every realistic email overflow that bound. Naming the per-recipient
outcomes recipients keeps the response a plain object.
@ysyneu
ysyneu merged commit 57f8a22 into main Sep 14, 2026
2 checks passed
@ysyneu
ysyneu deleted the feat/member-notify branch September 22, 2026 09:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant