Skip to content

feat(client): actions surface — the SDK path to server-registered actions (#3563 PR-2) - #3571

Merged
os-zhuang merged 1 commit into
mainfrom
claude/screen-flow-submit-resume-v9dqjx
Jul 27, 2026
Merged

feat(client): actions surface — the SDK path to server-registered actions (#3563 PR-2)#3571
os-zhuang merged 1 commit into
mainfrom
claude/screen-flow-submit-resume-v9dqjx

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

PR-2 of #3563, closing the largest gap the audit found — and the first real exercise of the PR-1 (#3569) guard: the gap ratchet drops 27 → 24.

The gap

The whole /actions domain — the documented way to expose custom server-side operations (engine.registerAction) — had no SDK expression at all. Every console hand-rolls fetch for POST /api/v1/actions/... today.

The surface

const res = await client.actions.invoke('crm_lead', 'convert', {
  recordId,
  params: { create_opportunity: true },
});
if (!res.success) toast(res.error);          // handler business failure — not thrown

await client.actions.invokeGlobal('nightly_cleanup', { params: { dryRun: true } });

Design points, each matching the dispatcher's actual contract (handleActions, http-dispatcher.ts:1946-2150):

  • recordId travels in the body — the server accepts it in the URL or the body; one client shape serves both server shapes.
  • Fixed path, not discovery-routedactions is not in ApiRoutesSchema, so getRoute() cannot resolve it; same precedent as projects/api/v1/cloud, documented at the definition.
  • The inner envelope is surfaced, not thrown — a handler throw comes back HTTP 200 with { success:false, error } (the dispatcher strips the sandbox wrapper to the business message); callers toast it rather than catch it.

Ledger + ratchet

All three /actions rows flip gapsdk; the conformance bound in route-ledger.conformance.test.ts drops to 24. The client half of the guard (route-ledger-coverage.test.ts) verifies actions.invoke / actions.invokeGlobal resolve on a real client instance.

Documentation stops lying (audit findings §6)

  • client README — the six phantom methods are gone (meta.getObject, views.share, views.setDefault, workflow.approve, workflow.reject, ai.chat), replaced with the real calls where one exists (meta.getItem, client.approvals.*); the "all 13 namespaces / 95+ methods" claims now defer to the CI-enforced ledger.
  • CLIENT_SPEC_COMPLIANCE.md — retired to a tombstone. Its "✅ FULLY COMPLIANT" verdict was measured against DEFAULT_DISPATCHER_ROUTES, a table nothing in runtime consumes that omits five of the domains it should have been measuring. The file stays so inbound links don't break.
  • content/docs/api/client-sdk.mdx — documents the new surface (with the inner-envelope semantics); the automation row now reflects the real method count (15, not 1); the compliance callout points at the ledger instead of the retired matrix.

Test plan

  • 5 new unit tests: URL shape, encoding, body defaults, global variant, inner-failure surfacing — all against the mocked-fetch house pattern.
  • Full suites: client 122 passed, runtime 653 passed (both guard halves included).
  • ESLint clean. Pre-existing and untouched: the bare tsc -p TS2741 (routeMap missing graphql) reproduces identically on main; its root is the stale graphql entry in ApiRoutesSchema, already tracked as audit follow-up Remove explicit pnpm version from workflows to fix version conflict #7 (spec-major territory).

🤖 Generated with Claude Code

https://claude.ai/code/session_01LX9ut3MK3KykE11S9bJmv5


Generated by Claude Code

…ions (#3563 PR-2)

Closes the largest gap in the #3563 route audit: the whole /actions domain —
the documented way to expose custom server-side operations
(engine.registerAction) — had no SDK expression at all, so every console
hand-rolled fetch for it.

- client.actions.invoke(object, action, { recordId, params }) — POST
  /api/v1/actions/:object/:action. recordId travels in the body, which both
  server URL shapes honor. The path is fixed (not discovery-routed): actions
  is not in ApiRoutesSchema, same precedent as projects' /api/v1/cloud.
- client.actions.invokeGlobal(action, opts) — the wildcard
  /actions/global/:action shape.
- The handler's own business failure surfaces as { success:false, error }
  (the dispatcher's inner envelope), deliberately not thrown, so callers can
  toast it. Unit tests cover URL shape, encoding, body defaults, the global
  variant, and the inner-failure path.

Ledger: all three /actions rows flip to sdk; the gap ratchet drops 27 → 24 —
first real exercise of the PR-1 guard.

Documentation stops lying (audit findings):
- client README: the six phantom methods are gone (meta.getObject,
  views.share, views.setDefault, workflow.approve/reject, ai.chat — replaced
  with the real calls where one exists), and the hand-written "all 13
  namespaces / FULLY COMPLIANT" claims now defer to the CI-enforced ledger.
- CLIENT_SPEC_COMPLIANCE.md: retired to a tombstone. Its verdict was measured
  against DEFAULT_DISPATCHER_ROUTES — a table nothing in runtime consumes,
  missing five of the domains it should have been measuring.
- content/docs/api/client-sdk.mdx: documents the new actions surface;
  the automation row now reflects the real method count.

Pre-existing, untouched: the bare `tsc -p` TS2741 (routeMap missing graphql)
reproduces identically on main — its root is the stale graphql entry in
ApiRoutesSchema, tracked as audit follow-up #7 (spec-major territory).

Verified: client 122 passed (5 new), runtime 653 passed, both ledger guard
halves green, eslint clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LX9ut3MK3KykE11S9bJmv5
@vercel

vercel Bot commented Jul 27, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
objectstack Ignored Ignored Jul 27, 2026 6:59am

Request Review

@github-actions github-actions Bot added documentation Improvements or additions to documentation tests tooling size/l labels Jul 27, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 2 package(s): @objectstack/client, @objectstack/runtime.

26 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/ai/skills-reference.mdx (via packages/client)
  • content/docs/api/client-sdk.mdx (via @objectstack/client, packages/runtime)
  • content/docs/api/data-flow.mdx (via @objectstack/client)
  • content/docs/api/environment-routing.mdx (via @objectstack/client)
  • content/docs/api/error-catalog.mdx (via @objectstack/client)
  • content/docs/api/index.mdx (via @objectstack/runtime)
  • content/docs/api/wire-format.mdx (via @objectstack/runtime)
  • content/docs/automation/hook-bodies.mdx (via @objectstack/runtime)
  • content/docs/concepts/north-star.mdx (via packages/runtime)
  • content/docs/data-modeling/drivers.mdx (via @objectstack/runtime)
  • content/docs/deployment/index.mdx (via @objectstack/runtime)
  • content/docs/deployment/production-readiness.mdx (via @objectstack/runtime)
  • content/docs/deployment/single-project-mode.mdx (via @objectstack/runtime)
  • content/docs/deployment/vercel.mdx (via @objectstack/runtime)
  • content/docs/getting-started/your-first-project.mdx (via @objectstack/client, @objectstack/runtime)
  • content/docs/kernel/runtime-services/data-service.mdx (via packages/client)
  • content/docs/kernel/runtime-services/index.mdx (via packages/client)
  • content/docs/permissions/authentication.mdx (via @objectstack/client, @objectstack/runtime)
  • content/docs/permissions/authorization.mdx (via packages/runtime)
  • content/docs/plugins/packages.mdx (via @objectstack/client, @objectstack/runtime)
  • content/docs/protocol/kernel/http-protocol.mdx (via @objectstack/runtime)
  • content/docs/protocol/kernel/index.mdx (via @objectstack/runtime)
  • content/docs/protocol/kernel/lifecycle.mdx (via @objectstack/runtime)
  • content/docs/protocol/kernel/realtime-protocol.mdx (via @objectstack/client)
  • content/docs/releases/implementation-status.mdx (via @objectstack/client, @objectstack/runtime)
  • content/docs/releases/v16.mdx (via @objectstack/client)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

@os-zhuang
os-zhuang marked this pull request as ready for review July 27, 2026 07:21
@os-zhuang
os-zhuang merged commit d3f2ff6 into main Jul 27, 2026
16 checks passed
@os-zhuang
os-zhuang deleted the claude/screen-flow-submit-resume-v9dqjx branch July 27, 2026 07:21
os-zhuang added a commit that referenced this pull request Jul 27, 2026
…xture debris (#3586) (#3595)

The const described a route surface that never existed (/workflow,
/realtime listed; eight real prefixes missing) and was consumed by
nothing in the runtime — only its own tests and api-surface.json. Its
one real-world effect was underwriting CLIENT_SPEC_COMPLIANCE.md's false
"FULLY COMPLIANT" verdict (retired in #3571). The maintained,
guard-enforced source of truth is packages/runtime/src/route-ledger.ts.

Since the major train is loading now (#3562, #3581), the removal ships
directly instead of the deprecate-first interim step.

Also swept what #3562 left behind: registry test fixtures renamed from
graphql_api//graphql to honest OData naming, the tautological
config.graphql assertions dropped, the stale '"type": "graphql"'
JSDoc example corrected. Client's bare tsc -p is verified clean (the
TS2741 acceptance item — resolved by #3562's schema change, confirmed
here).

Closes #3586


Claude-Session: https://claude.ai/code/session_01LX9ut3MK3KykE11S9bJmv5

Co-authored-by: Claude <noreply@anthropic.com>
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/l tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants