Skip to content

docs(rest): map exported tables to their automatic REST endpoints - #650

Merged
Ethan-Arrowood merged 3 commits into
mainfrom
docs/table-rest-endpoint-mapping
Aug 28, 2026
Merged

docs(rest): map exported tables to their automatic REST endpoints#650
Ethan-Arrowood merged 3 commits into
mainfrom
docs/table-rest-endpoint-mapping

Conversation

@Ethan-Arrowood

@Ethan-Arrowood Ethan-Arrowood commented Aug 27, 2026

Copy link
Copy Markdown
Member

What

Adds a canonical Tables and Their Automatic Endpoints section to reference/rest/overview.md, plus a one-sentence pointer from the @export directive in reference/database/schema.md.

Why this shape

The facts already existed but were never joined: @export is documented in the schema reference, rest: true under Configuration in the REST overview, and the per-method behavior in that same file's GET/PUT/POST/PATCH/DELETE sections. Nothing connected "I defined and exported a table" to "here is the HTTP surface I now have." That disconnect is the reported gap.

The new section is a compact endpoint table whose rows link down to the existing per-method sections rather than restating them. Restating PUT/PATCH semantics in two places on the same page would guarantee drift, and PUT/PATCH are exactly the two whose nuance matters most. Each row carries a one-line description and an anchor to the fuller section below.

It lives in rest/overview.md rather than schema.md because rest: true and all per-method nuance are already on that page. schema.md gets a pointer, not a duplicate table.

The rest: true gate

The section states plainly that both halves are required:

  • @table @export in the schema - without it there is no REST route and callers get 404.
  • rest: true in the application's config.yaml - without it the REST handler is never registered for the application, so even an exported table does not respond to HTTP.

With one carve-out, called out in an admonition: a component directory with no configuration file at all falls back to components/DEFAULT_CONFIG.ts, which sets rest: true and loads *.graphql from the component root. componentLoader.ts:602-614 selects a config file or the built-in default verbatim, with no merge, which makes the two cases fully disjoint - so a config.yaml that omits rest turns REST off even though the same directory would have had it with no file present. That is the gotcha the issue centers on, stated without over-claiming.

Verified against harper origin/main (c4dd96237)

  • rest: true gate. rest is a key in TRUSTED_RESOURCE_PLUGINS (components/componentLoader.ts:300) mapping to server/REST.ts; absent config keys are skipped by the loader. static/defaultConfig.yaml has no rest key; components/DEFAULT_CONFIG.ts:2 does set rest: true, and applies only when no config file exists (see carve-out above).
  • Method surface. server/REST.ts dispatches GET/HEAD/POST/PUT/DELETE/PATCH/OPTIONS/CONNECT/TRACE/QUERY/COPY/MOVE, delegating to the matched Resource class's same-named static and returning 405 via missingMethod() when the underlying instance method is absent. A table's working surface is GET, HEAD, PUT, POST, PATCH, DELETE, and QUERY.
  • PUT is create-or-replace, not update. Table.put -> update(..., fullUpdate = true); the fullUpdate branch in _writeUpdate replaces the stored record. Properties absent from the body are removed.
  • PUT's three exceptions to full replacement (Table.ts:2461-2487): @createdTime retains the original record's value, @updatedTime is re-stamped with the write time, and the primary key is forced to the URL {id} even when the body carries a different one. Recorded as a note rather than a table row so the "omitted properties are removed" warning keeps the lede.
  • PATCH merge is shallow. Table.patch -> update(..., fullUpdate = false), a top-level merge. Row links to the existing detailed warning.
  • POST. Responds 201 (REST.ts:319). The new key is returned in Location, and the value is the bare primary key, not a URL - Resource.ts:246 sets context.newLocation = id ?? results?.[primaryKey] and REST.ts:320 emits it verbatim. POST /Table without the trailing slash returns 404 from a purpose-built ClientError during argument normalization (Resource.ts:747); only POST /Table/{id} falls through to missingMethod -> 405.
  • QUERY works on a plain exported table. Resource.ts:347 dispatches method: 'query' to resource.search, which Table.ts:3244 implements. Exercised end-to-end over real HTTP in integrationTests/security/query-row-allowread-checkpermission.test.ts (QUERY /Vault/ -> 200), with unitTests/server/serverHelpers/uwsServer.test.js confirming the server accepts the verb.
  • Trailing slash is load-bearing. RequestTarget sets isCollection = true only for a trailing slash (or a bare query string); an exact resource-path match sets isCollection = false, id = null. Table.get then returns a describe object (table name, database, attributes, and an href to ./) for GET /Table. recordCount/estimatedRecordRange are undefined unless expensive estimates are requested, so the section does not promise a record count.
  • Collection DELETE. Table.delete treats any collection target as a search target and deletes every matching record. With no query parameters that is every record in the table. The row says so accurately without making it sound casual.

No place where the source contradicted the existing text of rest/overview.md; the page was accurate on every point checked.

Corrections made after initial review

Three problems were found in the first push and are fixed here:

  1. Removed an incorrect HEAD/OPTIONS/405 note. It claimed OPTIONS "reports the resource's supported methods." It does not. allowedMethods() (resources/Resource.ts:1003) iterates KNOWN_METHODS = get, head, put, post, delete, patch, query, move, copy and pushes any typeof resource[method] === 'function' - and REST.ts's OPTIONS case calls it with the Resource class, so it inspects statics rather than instance methods. Resource defines statics for every entry except head, so a table's Allow header over-reports MOVE and COPY (the statics exist and dispatch to instance methods a table does not define, so both 405) and omits HEAD (served, but no static). Rather than document that mismatch, the note now states only what is true: HEAD is GET minus the body (REST.ts:352), and QUERY runs a body-supplied search on the collection path.
  2. Added the no-config-file carve-out described above. The blanket "rest is not enabled by default" would have told a reader with no config.yaml that their exported tables 404 when they actually work.
  3. Corrected the POST status code. No-trailing-slash POST is 404, not 405, and the two cases have different codes for different reasons (see above).

Note for a follow-up skills PR

The hand-authored rule harper-best-practices/rules/adding-tables-with-schemas in @harperfast/skills contains a PUT-semantics error: it says PUT /{Table}/{id} "Updates an existing record." PUT is create-or-replace with upsert semantics, and properties omitted from the body are removed - the difference between an update and silent data loss. The same rule also omits that PATCH's merge is shallow, and omits the Location header on POST. That rule is out of scope here (separate repo, gated work); a follow-up skills PR will correct it, and can then source from this section.

Separately, the Allow mismatch found while checking correction 1 (MOVE/COPY advertised but 405, HEAD served but unadvertised) looks like a harper bug rather than something to document. Not filed here.

Verification

  • Rebased on main at ca6143ef.
  • npm run format:write clean, npm run format:check passes.
  • npm run build succeeds. Every anchor added was verified by grepping the generated build/reference/v5/**.html for the target id (rather than trusting the exit code, since onBrokenAnchors only warns): #export, #createdtime, #updatedtime, #configuration, #get, #post, #put, #patch, #delete, #url-structure, #openapi, #tables-and-their-automatic-endpoints, plus the four cross-page targets. The only broken anchors reported are the two known pre-existing ones (backups/overview and release-notes/v5-lincoln/5.1), owned elsewhere.

Closes #538

🤖 Generated with Claude Code

@Ethan-Arrowood
Ethan-Arrowood requested a review from a team as a code owner August 27, 2026 20:57

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the documentation to clarify the requirements for serving tables over REST, specifically noting that both the @export directive and the rest plugin must be enabled. It also introduces a comprehensive section detailing the automatic REST endpoints generated for exported tables. The feedback suggests replacing em dashes with hyphens in the newly added Markdown text to maintain consistency with the repository's style guidelines.

Comment thread reference/database/schema.md Outdated

The optional `name` parameter specifies the URL path segment (e.g., `/my-table/`). Without `name`, the type name is used.

`@export` alone does not serve HTTP traffic — the `rest` plugin must also be enabled in the application's `config.yaml`. See [REST Overview / Tables and Their Automatic Endpoints](../rest/overview.md#tables-and-their-automatic-endpoints) for the endpoints an exported table produces and the `rest: true` requirement.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Per the repository's general rules, please use a hyphen (-) instead of an em dash () for consistency. The rule states to use hyphens even if there are pre-existing inconsistencies in the file.

Suggested change
`@export` alone does not serve HTTP traffic the `rest` plugin must also be enabled in the application's `config.yaml`. See [REST Overview / Tables and Their Automatic Endpoints](../rest/overview.md#tables-and-their-automatic-endpoints) for the endpoints an exported table produces and the `rest: true` requirement.
`@export` alone does not serve HTTP traffic - the `rest` plugin must also be enabled in the application's `config.yaml`. See [REST Overview / Tables and Their Automatic Endpoints](../rest/overview.md#tables-and-their-automatic-endpoints) for the endpoints an exported table produces and the `rest: true` requirement.
References
  1. In Markdown documentation, use hyphens ('-') instead of em dashes ('—') as field separators to adhere to the style guide, even if the file has pre-existing inconsistencies using em dashes.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not taking this one. The em-dash rule is being over-generalized here.

AGENTS.md says em dashes "are fine for parenthetical asides and match existing prose; do not use them as field separators." The field-separator prohibition refers to the bullet immediately above it - Type: / Default: reference blocks, where each field goes on its own line. It is not a ban on - **term** — description in prose lists.

Two checks: the docs tree has 633 em-dash list-item lines across 63 reference files, and AGENTS.md itself uses this exact pattern - including in the rule being quoted (- **Hyphens vs. dashes** — em dashes...).

So these are the established convention, not "pre-existing inconsistencies." Applying the suggestion would leave the touched lines inconsistent with every sibling line in the same list.

sent with Claude Opus 5

Comment thread reference/rest/overview.md Outdated
rest: true
```

Neither half is sufficient on its own. Without `@export` the table has no REST route and callers get `404`. Without `rest: true` the REST handler is never registered for the application, so exported tables do not respond to HTTP requests at all — `rest` is not enabled by default.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Per the repository's general rules, please use a hyphen (-) instead of an em dash (). This change should be applied consistently throughout the new content in this file where em dashes are used (e.g., on lines 67, 72, 73, and 75).

Suggested change
Neither half is sufficient on its own. Without `@export` the table has no REST route and callers get `404`. Without `rest: true` the REST handler is never registered for the application, so exported tables do not respond to HTTP requests at all `rest` is not enabled by default.
Neither half is sufficient on its own. Without `@export` the table has no REST route and callers get `404`. Without `rest: true` the REST handler is never registered for the application, so exported tables do not respond to HTTP requests at all - `rest` is not enabled by default.
References
  1. In Markdown documentation, use hyphens ('-') instead of em dashes ('—') as field separators to adhere to the style guide, even if the file has pre-existing inconsistencies using em dashes.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not taking this one. The em-dash rule is being over-generalized here.

AGENTS.md says em dashes "are fine for parenthetical asides and match existing prose; do not use them as field separators." The field-separator prohibition refers to the bullet immediately above it - Type: / Default: reference blocks, where each field goes on its own line. It is not a ban on - **term** — description in prose lists.

Two checks: the docs tree has 633 em-dash list-item lines across 63 reference files, and AGENTS.md itself uses this exact pattern - including in the rule being quoted (- **Hyphens vs. dashes** — em dashes...).

So these are the established convention, not "pre-existing inconsistencies." Applying the suggestion would leave the touched lines inconsistent with every sibling line in the same list.

sent with Claude Opus 5

@github-actions
github-actions Bot temporarily deployed to pr-650 August 27, 2026 21:01 Inactive
@github-actions

Copy link
Copy Markdown

🚀 Preview Deployment

Your preview deployment is ready!

🔗 Preview URL: https://preview.harper-documentation.harperfabric.com/pr-650

This preview will update automatically when you push new commits.

@Ethan-Arrowood
Ethan-Arrowood force-pushed the docs/table-rest-endpoint-mapping branch from dd9bc32 to d4687e6 Compare August 27, 2026 21:13
@github-actions
github-actions Bot temporarily deployed to pr-650 August 27, 2026 21:16 Inactive
@github-actions

Copy link
Copy Markdown

🚀 Preview Deployment

Your preview deployment is ready!

🔗 Preview URL: https://preview.harper-documentation.harperfabric.com/pr-650

This preview will update automatically when you push new commits.

@kriszyp kriszyp left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good overview/intro, I like it.
🤖 Reviewed with Codex

Comment thread reference/rest/overview.md Outdated

## Tables and Their Automatic Endpoints

A table is served over REST only when **both** of the following are true:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is too absolute for the documented table-extension path: reference/resources/overview.md:32-42 explicitly tells users to omit @export when a JavaScript subclass of tables.MyTable owns the route, with rest: true at reference/resources/overview.md:74-82. Following this new rule can make those users add both exports and create the conflicting endpoints that the existing guide warns about. Could we scope this sentence and reference/rest/overview.md:61 to the automatically registered/default table Resource?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch — scoped it. The section now opens by saying it describes the default table Resource that Harper registers automatically, and the "neither half is sufficient" paragraph is worded the same way. I also added a paragraph pointing at reference/resources/overview.md "Extending a Table": @export is how the table itself claims the URL, so when a tables.MyTable subclass should own it you omit @export and export the class instead.

sent with Claude Opus 5

Comment thread reference/rest/overview.md Outdated
| `GET /Product/` | The record collection. Append query parameters to search, filter, sort, and page. | [GET](#get), [Querying](./querying.md) |
| `GET /Product/{id}` | A single record by primary key; `404` when no such record exists. | [GET](#get) |
| `GET /Product/{id}.property` | A single property of one record. Only properties declared in the schema. | [GET](#get) |
| `POST /Product/` | Creates a record with a Harper-assigned primary key and responds `201`. Requires the trailing slash — `POST /Product` returns `404`. | [POST](#post) |

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A collection POST does not always use a Harper-assigned key. If the request body supplies the table's primary-key property, Harper preserves that value and returns it in Location; a key is generated only when the property is omitted. Could this say “with a Harper-assigned primary key when one is not supplied” so clients do not expect their explicit key to be replaced?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirmed and fixed. Table.create does let id = requestTargetToId(target) ?? record[primaryKey] and only calls getNewId() when that is undefined, so the row now reads "Creates a record and responds 201, with a Harper-assigned primary key when the body does not supply one." I added a note that a supplied key is preserved and echoed in Location, and that posting an existing key returns 409 rather than overwriting — and updated the ### POST prose below, which had the same "without specifying a primary key" claim.

sent with Claude Opus 5

Comment thread reference/rest/overview.md Outdated
- `HEAD` is served exactly as `GET` with the response body omitted. `QUERY` is accepted on the collection path (`QUERY /Product/`) and runs a search taken from the request body rather than the URL.
- On a successful `POST`, the new record's primary key is returned in the `Location` response header. The header carries the bare key value, not a URL — it is not a link to follow.
- `PUT` replaces the stored record, with three exceptions that Harper always applies: a [`@createdTime`](../database/schema.md#createdtime) attribute keeps the original record's value, an [`@updatedTime`](../database/schema.md#updatedtime) attribute is re-stamped with the time of the write, and the primary key is forced to match the `{id}` in the URL even if the body carries a different one.
- Enabling `rest` also enables [WebSocket](./websockets.md) and [Server-Sent Events](./server-sent-events.md) subscriptions on these same resource paths.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not unconditional for WebSockets: the configuration example at reference/rest/overview.md:33-35 explicitly supports webSocket: false, which leaves REST enabled while suppressing WebSocket registration. Could this say that REST enables WebSocket subscriptions by default, unless webSocket is disabled, while describing SSE separately?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed, and split into two bullets. WebSocket is now "by default", with webSocket: false under rest suppressing the registration while REST keeps serving — that matches server/REST.ts, where the early return sits after the HTTP handler is registered and before scope.server.ws(...). SSE gets its own bullet: it is negotiated per request via Accept: text/event-stream inside the HTTP handler, so the webSocket option does not affect it.

sent with Claude Opus 5

Comment thread reference/rest/overview.md Outdated
- On a successful `POST`, the new record's primary key is returned in the `Location` response header. The header carries the bare key value, not a URL — it is not a link to follow.
- `PUT` replaces the stored record, with three exceptions that Harper always applies: a [`@createdTime`](../database/schema.md#createdtime) attribute keeps the original record's value, an [`@updatedTime`](../database/schema.md#updatedtime) attribute is re-stamped with the time of the write, and the primary key is forced to match the `{id}` in the URL even if the body carries a different one.
- Enabling `rest` also enables [WebSocket](./websockets.md) and [Server-Sent Events](./server-sent-events.md) subscriptions on these same resource paths.
- Every exported resource is included in the generated [OpenAPI](#openapi) document.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

static hidden = true drops a programmatic Resource from OpenAPI (reference/resources/resource-api.md:612-614), and type-level @hidden likewise suppresses table resources from the OpenAPI document (reference/database/schema.md:244-246). Please qualify this as “Every non-hidden exported resource” or otherwise call out the exception.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Qualified it. The bullet now reads "Every non-hidden exported resource is included in the generated OpenAPI document" and calls out both exceptions explicitly, linking @hidden on the type and static hidden = true on a programmatic Resource.

sent with Claude Opus 5

Comment thread reference/database/schema.md Outdated

The optional `name` parameter specifies the URL path segment (e.g., `/my-table/`). Without `name`, the type name is used.

`@export` alone does not serve HTTP traffic — the `rest` plugin must also be enabled in the application's `config.yaml`. See [REST Overview / Tables and Their Automatic Endpoints](../rest/overview.md#tables-and-their-automatic-endpoints) for the endpoints an exported table produces and the `rest: true` requirement.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The no-configuration-file exception documented at reference/rest/overview.md:63-66 makes this statement false for a bare component directory: Harper's built-in default enables both rest and *.graphql, so the user does not need a config.yaml. Could this say that REST must be enabled either explicitly or by the built-in no-config default?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, that contradicted the carve-out I added on the other page. It now says REST must be enabled for the application "either explicitly with rest: true in its config.yaml or by Harper's built-in default for a component directory that has no configuration file at all." I made the matching change to requirement 2 in the REST overview so the two pages agree.

sent with Claude Opus 5

Ethan-Arrowood and others added 3 commits August 28, 2026 11:24
Adds a "Tables and Their Automatic Endpoints" section to the REST
overview that joins the two facts a reader currently has to assemble
from separate pages: a table needs `@table @export` in the schema AND
`rest: true` in the application's config.yaml before it answers any HTTP
request. `rest` is not in defaultConfig.yaml, so without it the REST
handler is never registered and exported tables 404.

The section is a compact endpoint table whose rows link down to the
existing per-method sections rather than restating them, so PUT/PATCH
semantics stay defined in exactly one place.

Also adds a one-sentence pointer from the schema reference's `@export`
directive to the new section.

Closes #538

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…T status

Three corrections to the endpoints section, each re-verified against
harper origin/main c4dd96237:

- Remove the incorrect HEAD/OPTIONS/405 note. `allowedMethods()`
  (resources/Resource.ts:1003) is called with the Resource *class* in
  server/REST.ts's OPTIONS case, so it inspects statics, not instance
  methods: it over-reports MOVE and COPY (statics exist and dispatch to
  instance methods a table does not define, so both 405) and omits HEAD
  (no static). "OPTIONS reports the supported methods" overstated it.
  Replaced with what is actually true: HEAD is GET minus the body
  (REST.ts:352), and QUERY works on the collection path, dispatching
  through `Resource.query` to the table's `search` (Resource.ts:347).

- Add a carve-out for components with no configuration file.
  static/defaultConfig.yaml has no `rest` key, but
  components/DEFAULT_CONFIG.ts sets `rest: true`, and
  componentLoader.ts:602-614 selects one or the other verbatim with no
  merge. The two cases are disjoint, so the blanket "not enabled by
  default" told a reader with no config.yaml their exported tables would
  404 when they work.

- Correct the POST row: `POST /Table` without the trailing slash returns
  404 from a purpose-built ClientError during argument normalization
  (Resource.ts:747), not 405; only `POST /Table/{id}` reaches
  missingMethod. Also note the response is 201 and that `Location`
  carries the bare primary key rather than a URL (Resource.ts:246,
  REST.ts:319-320).

Also folds in PUT's three always-applied exceptions to full replacement
(Table.ts:2461-2487) as a note rather than a table row, so the
"omitted properties are removed" warning keeps the lede.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ptions

Addresses review feedback on the "Tables and Their Automatic Endpoints"
section:

- Scope the "@export + rest" requirement to the default table Resource that
  Harper registers automatically, and point at Extending a Table for the case
  where a tables.MyTable subclass owns the route instead (omit @export). The
  previous absolute wording contradicted reference/resources/overview.md and
  could lead users into the conflicting-endpoints trap it warns about.
- A collection POST only generates a primary key when the body omits the
  primary-key property. A supplied key is preserved and echoed in Location; a
  POST to an existing key returns 409 rather than overwriting.
- REST enables WebSocket subscriptions by default, not unconditionally:
  rest.webSocket: false suppresses WS registration while REST keeps serving.
  SSE is described separately, since it is negotiated per request via Accept
  and is not gated by that option.
- Qualify OpenAPI inclusion as every non-hidden exported resource, naming both
  @hidden on the type and static hidden = true on a programmatic Resource.
- reference/database/schema.md no longer claims config.yaml is required; it
  now matches the no-configuration-file carve-out documented on the REST page.

Verified against harper origin/main: Table.create (resources/Table.ts),
Resource.create/post (resources/Resource.ts), the webSocket early return and
the SSE branch (server/REST.ts), and the hidden filters (resources/openApi.ts).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@Ethan-Arrowood
Ethan-Arrowood force-pushed the docs/table-rest-endpoint-mapping branch from d4687e6 to 3baf519 Compare August 28, 2026 17:29
@github-actions
github-actions Bot temporarily deployed to pr-650 August 28, 2026 17:32 Inactive
@github-actions

Copy link
Copy Markdown

🚀 Preview Deployment

Your preview deployment is ready!

🔗 Preview URL: https://preview.harper-documentation.harperfabric.com/pr-650

This preview will update automatically when you push new commits.

@Ethan-Arrowood
Ethan-Arrowood enabled auto-merge (squash) August 28, 2026 19:00
@Ethan-Arrowood
Ethan-Arrowood merged commit 5cda815 into main Aug 28, 2026
10 checks passed
@Ethan-Arrowood
Ethan-Arrowood deleted the docs/table-rest-endpoint-mapping branch August 28, 2026 19:00
@github-actions

Copy link
Copy Markdown

🧹 Preview Cleanup

The preview deployment for this PR has been removed.

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.

Document the table → automatic REST endpoint mapping (and rest: true requirement)

3 participants