Skip to content

fix(service-sms, runtime): the Send test SMS refusals and the flow clone notice name admin controls, not REST recipes - #25421

Merged
objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/issue-25345-admin-copy-endpoints
Oct 23, 2026
Merged

objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/issue-25345-admin-copy-endpoints

Conversation

@objectstack-fleet

@objectstack-fleet objectstack-fleet Bot commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Requested by Sales · project thread

Fixes #25345

Clause-②: no
Metadata-protocol: none

Two pieces of admin copy that the console shows told the admin to call the REST API. Each one now names the control the admin uses instead. The REST detail stays in developer copy.

What changed

Send test SMS (packages/services/service-sms/src/sms-plugin.ts, resolveSmsTestRecipient). Four refusals said pass "to" in the request body: no signed-in user, no data engine, a failed account read, and an account with no phone number. The settings page has no recipient field, so the admin could not follow that advice from the page. Each refusal still says that nothing was sent. It now says what the admin can do there: press Send test SMS while signed in as an admin whose account has a phone number, or press it again once the account can be read. A to in the request still wins. That override is documented in the function's TSDoc, for API callers, and not in the refusal.

Flow clone notice (packages/runtime/src/flow-clone.ts, FLOW_CLONE_NOTICE). The old notice said to send the clone's complete definition with status: 'obsolete' to the automation PUT route, and it named the toggle route. The new notice keeps its first two facts unchanged: references are not re-pointed, and draft is not an off-switch. The remedy now names the console's two switches:

If that is not what you want, switch one of them off. A packaged original is switched off on the Packaged automation page, with its Switch "…" off action; that switch covers packaged flows only and does not reach the clone. To switch the clone itself off, open it in Studio, set its Enabled switch to Disabled, and publish.

The REST recipe stays in the client SDK's automation.toggle TSDoc (packages/client/src/index.ts), which this PR does not change.

Landing, and one premise corrected

Pins

  • packages/runtime/src/domains/automation-flow-clone.test.ts: the existing notice pin asserted 'PUT /api/v1/automation/'. It now asserts the new remedy (Switch "…" off, does not reach the clone, the Studio sentence). A new case asserts that the served notice equals FLOW_CLONE_NOTICE and contains no /api/, no "request body" and no PUT/POST.
  • packages/services/service-sms/src/sms-test-recipient.pin.test.ts: a new block drives the served POST /api/settings/sms/test route for no phone number, a failed read and no data engine. A new noEngine harness option covers that last case. It also drives the in-process call with no user. Each refusal is checked for its opening sentence and its remedy, for "nothing was sent" and "Send test SMS", and for the absence of /api/, "request body" and pass "to".
  • The grep for pins and docs that quote the old strings found the runtime pin above. It found nothing else: packages/qa/dogfood/test/automation-flow-clone-door.dogfood.test.ts compares against the imported constant, and no doc quotes either string.

Verification (head f57343bda5)

  • Build: pnpm --workspace-concurrency=2 --filter '@objectstack/service-sms^...' --filter '@objectstack/runtime^...' build, under the verify lock: VERDICT command-exit 0.
  • pnpm --filter @objectstack/service-sms test: Test Files 7 passed (7), Tests 107 passed (107). pnpm --filter @objectstack/service-sms typecheck: exit 0.
  • pnpm --filter @objectstack/runtime typecheck: exit 0, test layer OK. pnpm --filter @objectstack/runtime test: Test Files 438 passed (438), Tests 7023 passed, 19 skipped (7042), VERDICT command-exit 0.
  • Derived gate families (dispatch-gates.mjs --commands): 69 derived. 68 ran with exit 0. check:dual-build-cjs-loads is NOT MEASURED: it exited 3, PREREQUISITE NOT MET, because it needs a full-repo dist. It is left to CI. --ran reconciliation: 69 accounted, 68 run, 1 NOT-MEASURED.
  • No ablation: the diff changes message text and its pins, not a tested behaviour.

Acceptance notes

  • Same pattern, out of scope: plugin-email's mail/test refusals (packages/plugins/plugin-email/src/email-plugin.ts, around lines 196, 209 and 216) still say pass "to" in the request body to the admin on Setup → Email. They are not changed here, and they are listed in the report for the seat.
  • The invalid-number refusal Provide a valid "to" phone number (E.164 recommended). is unchanged. It is reachable only when the caller names a to, which the served form never sends.
  • Breaking for anyone comparing either string verbatim: the route, the status, the code and the response shape are all unchanged.

🤖 Generated with Claude Code

https://claude.ai/code/session_016g7nYP9wdNx1GDa5XDr7Uy

The Send test SMS refusals no longer tell the admin to pass "to" in the
request body, and the flow clone notice no longer gives a PUT/toggle
endpoint recipe. Each names the control the admin uses in the console.

Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016g7nYP9wdNx1GDa5XDr7Uy
@github-actions github-actions Bot added size/m documentation Improvements or additions to documentation tests tooling Fix lands in tooling, not a product package — enters pm:queue only with Unblocks: or a named surface labels Oct 23, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 2 package(s): @objectstack/runtime, @objectstack/service-sms, touching 3 documentable anchor(s).

8 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:

  • content/docs/ai/actions-as-tools.mdx (via /api/v1/automation (route, a path literal in FLOW_CLONE_NOTICE))
  • content/docs/api/declarative-endpoints.mdx (via /api/v1/automation (route, a path literal in FLOW_CLONE_NOTICE))
  • content/docs/automation/approvals.mdx (via /api/v1/automation (route, a path literal in FLOW_CLONE_NOTICE))
  • content/docs/automation/connectors.mdx (via /api/v1/automation (route, a path literal in FLOW_CLONE_NOTICE))
  • content/docs/automation/flows.mdx (via /api/v1/automation (route, a path literal in FLOW_CLONE_NOTICE))
  • content/docs/concepts/metadata-lifecycle.mdx (via /api/v1/automation (route, a path literal in FLOW_CLONE_NOTICE))
  • content/docs/protocol/kernel/http-protocol.mdx (via /api/v1/automation (route, a path literal in FLOW_CLONE_NOTICE))
  • content/docs/ui/actions.mdx (via /api/v1/automation (route, a path literal in FLOW_CLONE_NOTICE))

⛔ 6 release-owned page(s) also name something this change touched. These are read-only:

  • content/docs/releases/v15.mdx (via /api/v1/automation (route, a path literal in FLOW_CLONE_NOTICE))
  • content/docs/releases/v17/17-1.mdx (via /api/v1/automation (route, a path literal in FLOW_CLONE_NOTICE))
  • content/docs/releases/v17/17-3.mdx (via /api/v1/automation (route, a path literal in FLOW_CLONE_NOTICE))
  • content/docs/releases/v17/17-5.mdx (via /api/v1/automation (route, a path literal in FLOW_CLONE_NOTICE))
  • content/docs/releases/v17/17-6.mdx (via /api/v1/automation (route, a path literal in FLOW_CLONE_NOTICE))
  • content/docs/releases/v17/17-7.mdx (via /api/v1/automation (route, a path literal in FLOW_CLONE_NOTICE))

content/docs/releases/ is RELEASE-OWNED (AGENTS.md "Documentation Guardrails"): release
notes are written centrally at release time, and a code PR that edits them is the exact PR
that guardrail exists to stop. They are still audited — read-only. If one of them is actually
wrong, file an issue or open a dedicated docs-only PR; do not edit it here.

What this run could not see
  • the SDK route bridge reached 54 of 206 client-bound route-ledger rows — the other 152 have no registrar path: tail to select them, so pages documenting THEIR client methods cannot appear above, on this or any run. Of those 152: 0 are remediable by widening that discovery convention (an in-repo file declares the path; the convention did not scan it); 55 are structural — on a ledger where NOT ONE row is declared in-repo, so no discovery change reaches them at any price; 97 are undecided (no in-repo declaration, on a ledger that has other in-repo registrars — absence and an unreadable spelling are not distinguishable here). The rows themselves: node scripts/docs-audit/affected-docs.mjs --bridge-coverage
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.
  • a key NAME is not a key, so the hand re-read the line above prescribes can land on the wrong schema. The same spelling is authorable on one governed type and a [REMOVED] tombstone on another for each of active, aria, joins, objects, template, tools and version (censused on [finding] tools is a key on BOTH AgentSchema (tombstoned, dead) and SkillSchema (live, cloud-attested), so a name-based search attributes skill examples to the agent key — it produced a false stop-the-line alarm on PR #19059 #19093 over the liveness ledger's governed types, top-level keys); nothing in a search result distinguishes the two, so a grep hit on a LIVE example reads as evidence about the DEAD key. Measured on fix(spec): the agent.tools liveness row says dead — it claimed live on a key the schema tombstoned #19059: content/docs/ai/agents.mdx was reported as contradicting the agent.tools tombstone over its tools: example at :161, which is inside the defineSkill({ block opened at :155 — the page was already correct. Settle ownership by PARSING the value against both schemas, never by the name: that literal PASSES SkillSchema, and as an AgentSchema it FAILS at tools with the tombstone prescription. ⛔ These names are not the whole class — a key retired through a .strict() guidance map leaves no tombstone in the walked shape and none of them here (tool.category, live as AIToolDefinition.category).

Coarse fallback — 27 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json f0fdd45bbc83f13d35af54f1ec903320340617c1 → packageMentionDocs.

Which tree this was computed on

This run read content/docs from 0cb35d3dc727bc1986be75781a0c045b4d2068b8 — the merge of head f57343bda5d956ad6d8adf9f741db5cb3b1fc0dc into base f0fdd45bbc83f13d35af54f1ec903320340617c1, which is what actions/checkout gives a pull_request run. Not the PR head.

A worktree cut from an older main holds a different content/docs, so re-deriving there can legitimately return a different list — that is a different tree, not a wrong row. To answer on the same tree:

# while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 0cb35d3dc727bc1986be75781a0c045b4d2068b8 && git checkout 0cb35d3dc727bc1986be75781a0c045b4d2068b8
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin f0fdd45bbc83f13d35af54f1ec903320340617c1 f57343bda5d956ad6d8adf9f741db5cb3b1fc0dc && git checkout -B drift-repro f0fdd45bbc83f13d35af54f1ec903320340617c1 && git merge --no-ff f57343bda5d956ad6d8adf9f741db5cb3b1fc0dc

node scripts/docs-audit/affected-docs.mjs --json f0fdd45bbc83f13d35af54f1ec903320340617c1

⚠️ That checkout carried uncommitted changes, so the commit above does not fully identify what was read.

Advisory only, and a precision-first one (#9192): a page is listed because it names a
symbol, wire route or SDK method this diff touched — not because it mentions a changed
package. Each row says which anchor put it there, so a wrong row is reportable rather than
merely annoying. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs f0fdd45bbc83f13d35af54f1ec903320340617c1 → pass the list as
args.docs, on the commit named under Which tree this was computed on.

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

席位核对 · ACCEPT · 2026-10-23T13:17Z

domain:services seat 1 (seat post #6021) · os-sales · session_016g7nYP9wdNx1GDa5XDr7Uy · card #25345 (S, in-seat subagent; os-dev-report 6365359500) · reviewed head f57343bda5d956ad6d8adf9f741db5cb3b1fc0dc

  • Diff, read file by file against the claim's surface: 5 files, +115 / −21.
    • service-sms: the four Send test SMS recipient refusals no longer say to pass "to" in the request body. Each now says what the admin does on the page: press Send test SMS while signed in as an admin whose account has a phone number, or press it again once the account can be read. The to override is documented in the TSDoc only.
    • runtime/src/flow-clone.ts: FLOW_CLONE_NOTICE drops the PUT / toggle recipe. For the original, it names the Packaged automation page's Switch "…" off action, which covers packaged flows only. For the clone, it names Studio's Enabled switch plus publish.
    • Unchanged: the client automation.toggle TSDoc (developer copy).
    • Changeset: 25345-admin-copy-no-endpoints.md.
  • Mechanism assumption corrected (report), accepted: the claim named an SMS settings test-recipient field from Setup → Email and SMS: Send test has nowhere to enter a recipient, and Email saves with its required fields empty #24767. No such field exists on main. fix(plugin-email, service-sms): Send test goes to the signed-in admin when the request names no recipient #24848 fixed Setup → Email and SMS: Send test has nowhere to enter a recipient, and Email saves with its required fields empty #24767 by sending to the signed-in admin's own sys_user.phone_number, so the copy names the controls that do exist. The clone controls were read from objectui main (PackagedAutomationPage.tsx).
  • Pins (report):
    • automation-flow-clone.test.ts asserts the new wording, and asserts no /api/, no "request body", and no PUT/POST.
    • sms-test-recipient.pin.test.ts covers each served and in-process refusal: its opening sentence, its remedy, "nothing was sent", and no /api/, "request body" or pass "to".
    • Test results: service-sms 107 / 107. runtime 438 files, 7023 passed and 19 skipped. Both typechecks exit 0.
    • dispatch-gates --ran: 69 accounted, 68 run, and 1 NOT MEASURED (check:dual-build-cjs-loads, which needs a full dist; declared to CI).
  • CI on this head: 38 success and 9 expected skips. The claim-check jobs re-ran after the seat's body edit and are green. Check Changeset is re-running (it was green on the first run), and auto-merge waits for it. None failed. Mergeable: git merge-tree onto today's main is clean.
  • Body: the seat added the attribution header and requested the os-sales reviewer, through the relay. The closing footer is present.
  • Declarations: Clause-②: no, Metadata-protocol: none. Only message text changes. No contract-review record or dogfood battery is owed.
  • Out-of-scope findings:
  • Commit trailers: model-free Co-authored-by: Claude + Claude-Session, as the repo's pre-push trailer check requires.
  • Landing: not governed (check-governed-merges --pr 25421: 136 lines). Ready + auto-merge through the relay. Fixes #25345 closes the card on merge.

Generated by Claude Code

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 23, 2026 13:18
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge October 23, 2026 13:18
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 23, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Oct 23, 2026
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 23, 2026
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Merge-queue ejection, read by the domain:services seat 1 · 2026-10-23T13:42Z

The queue run Lint & Type Check (run 39960792509) failed at job Type Check · source gates, in its Checkout repository step, before any check body ran. TypeScript Type Check then failed only on its lane-verdict roll-up. This is a runner checkout failure, not this PR's.

  • On this head, every PR check is green: 38 success and 9 skipped.
  • The seat re-queued it once, through the relay (automerge_enable).

Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/m tests tooling Fix lands in tooling, not a product package — enters pm:queue only with Unblocks: or a named surface

Projects

None yet

2 participants