Skip to content

ActionSchema.method's worked example points a type: 'api' PATCH at /api/v1/sys_api_key/{id} — the shipped data API is /api/v1/data/:object/:id, so copying it 404s #14093

Description

@os-warren

@objectstack/spec 17.2.0, ActionSchema.method doc comment:

HTTP method to use when type: 'api'. Defaults to POST. Use PATCH to call data-API update endpoints (e.g. /api/v1/sys_api_key/{id} with bodyExtra: { revoked: true }).

The path is missing the /data segment the router actually mounts.

Measured

@objectstack/rest 17.2.0 composes the CRUD routes as getApiBasePath() + crud.dataPrefix + /:object/:id:

getApiBasePath() { return api.apiPath ?? `${api.basePath}/${api.version}`; }   // '/api' + '/v1'
dataPrefix: crud.dataPrefix ?? "/data"
registerCrudEndpoints(basePath) {
  const dataPath = `${basePath}${crud.dataPrefix}`;
  ...
  this.routeManager.register({ method: "PATCH", path: `${dataPath}/:object/:id`, ... })
}

So the update endpoint is PATCH /api/v1/data/<object>/<id>. Nothing overrides dataPrefix on the standalone/runtime path, and sys_api_key has no bespoke route of its own — plugin-auth mounts only /api/v1/auth/* and /api/v1/mcp, and sys_api_key is an ordinary platform-objects object served by the generic data API.

Why it is worth fixing rather than leaving as prose

This is the one worked example an author copies when reaching for the only declarative-looking way to set a field from an action (see #14092). Nothing catches the mistake: objectstack validate does not check target, type: 'api' has no author-time route validation, and the action renders, is clickable, and 404s at the click — the same silent shape as an unregistered handler, arriving through a doc example instead of a missing registration.

Suggested

`/api/v1/data/sys_api_key/{id}` with `bodyExtra: { revoked: true }`

and, since target is interpolated by the renderer with ${param.X} / ${ctx.X} (this same schema's target doc) rather than with {id}, spelling the id as ${ctx.recordId} in the example would stop the two conventions in one schema from reading as interchangeable. (newTabUrl is the one key that really does take a bare {recordId} placeholder.)

Found while building objectstack-ai/duly#4.

Activity

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

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions