Skip to content

Commit 36ec568

Browse files
committed
Merge remote-tracking branch 'origin/main' into claude/issue-14917-driver-mongodb-test-layer-typecheck
2 parents 5fc27e5 + 0db2947 commit 36ec568

20 files changed

Lines changed: 883 additions & 61 deletions
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
---
2+
"@objectstack/spec": patch
3+
---
4+
5+
Reference pages no longer print `@example` and `@category` tag lines as literal text.
6+
7+
A module docblock is JSDoc, so its header carries block tags, and the reference-docs
8+
renderer emitted a tag written on a prose line verbatim — 18 such lines reached 14
9+
customer-facing pages, as `@example Basic field mapping` above a code fence and
10+
`@category Security` at the foot of four `system/` pages. `#13796` removed `@module`
11+
from the page and left these two open, because a blanket `^@\w+` line filter would
12+
have taken reader prose off the page and orphaned the fences below it.
13+
14+
The verdict is per tag, and the axis is the payload rather than the spelling:
15+
16+
- **`@example CAPTION` is REWRITTEN** into that caption, in bold, above the block it
17+
captions — the shape `@see` already had (`See also: …`). 12 lines across 10 pages.
18+
Bold rather than a heading because heading renumbering has already run by then, so
19+
an emitted heading would carry a level chosen blind of the page, add entries to the
20+
pages' tables of contents, and put a caption in reach of `check:docs-single-h1`.
21+
- **A bare `@example` is DROPPED.** With no payload it is the `@module` case exactly,
22+
and the fence beneath it is visibly an example without a line announcing one. 2
23+
lines (`studio/plugin`, `studio/object-designer`), both sitting against the
24+
`check:skill-examples` opt-in marker that was already dropped there.
25+
- **`@category VALUE` is DROPPED.** 4 lines, all reading `Security`, on four pages that
26+
already sit under a `system/` section saying as much — and nothing in the repo reads
27+
the tag: no typedoc or api-extractor (neither is used here), no search index, no
28+
gate. Routing it into page frontmatter instead would publish a field with no
29+
consumer. The tag stays in the source, where it is a legitimate JSDoc tag; only the
30+
rendered page drops it.
31+
32+
No schema behavior changes. The pins assert on the rendered fragment rather than on the
33+
emitted `.mdx`, because `check:docs` compares the artifact against the source and
34+
reproduced all 18 tag lines faithfully.
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
---
2+
'@objectstack/runtime': patch
3+
---
4+
5+
fix(runtime): a sandboxed hook body no longer launders an untouched `readonly` field onto the row
6+
7+
A `beforeUpdate`/`beforeInsert` body running in the sandbox made the engine believe it had
8+
written payload keys it never named, and a `readonly` field the caller supplied then survived
9+
the readonly strip and landed. Measured end to end: with `locked_at` declared
10+
`{ type: 'datetime', readonly: true }` and seeded to `2020-01-01`, a caller sending
11+
`locked_at: new Date('2099-12-31…')` alongside a body whose whole source is
12+
`ctx.input.touched_by = 'hook'` stored the caller's 2099 value — while the same object's
13+
readonly `text` field was correctly stripped in the same request.
14+
15+
The cause was a comparison of unlike things. The write-back decides whether a body wrote
16+
*through* an object-valued key by comparing the host payload value against the VM's exit dump,
17+
and the dump has been through `JSON.stringify`/`JSON.parse` while the host value has not. A
18+
`Date` therefore never compared equal to its own ISO projection, took the documented
19+
"cannot prove equal ⇒ carry it back" path, and was re-asserted onto the proxy that records
20+
which keys a hook wrote. The class was every object-valued value a JSON round-trip cannot
21+
prove equal — an object carrying an `undefined` member included, a `Date` being only its most
22+
reachable member.
23+
24+
The entry value is now normalised through the same round-trip the VM saw before it is
25+
compared. The same change ends a fidelity loss on non-readonly fields: an untouched key is no
26+
longer carried at all, so a host `Date` is no longer replaced by an ISO string on its way to
27+
the driver.
28+
29+
Fail-open behaviour is unchanged for values the round-trip genuinely cannot evaluate: a cyclic
30+
or bigint-bearing payload value is still reported as changed and still carried, per key.

content/docs/references/api/automation-api.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ triggering executions, and querying execution history.
1212

1313
Base path: /api/automation
1414

15-
@example Endpoints
15+
**Endpoints**
1616
GET /api/automation — List flows
1717
GET /api/automation/:name — Get flow
1818
POST /api/automation — Create flow

content/docs/references/api/documentation.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ Architecture Alignment:
2222
- Postman: API testing collections
2323
- Redoc: Documentation rendering
2424

25-
@example Documentation Config
25+
**Documentation Config**
2626
```typescript
2727
const docConfig: ApiDocumentationConfig = {
2828
enabled: true,

content/docs/references/api/odata.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ See also: https://www.odata.org/documentation/
4242

4343
See also: https://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part2-url-conventions.html
4444

45-
@example OData Query
45+
**OData Query**
4646
```
4747
GET /api/odata/customers?
4848
$select=name,email&
@@ -54,7 +54,7 @@ GET /api/odata/customers?
5454
$count=true
5555
```
5656

57-
@example Programmatic Use
57+
**Programmatic Use**
5858
```typescript
5959
const query: ODataQuery = {
6060
select: ['name', 'email'],

content/docs/references/api/package-api.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ REST API endpoint schemas for package lifecycle management.
1111

1212
Base path: /api/v1/packages
1313

14-
@example Endpoints
14+
**Endpoints**
1515
POST /api/v1/packages/install — Install a package
1616
POST /api/v1/packages/upgrade — Upgrade a package
1717
POST /api/v1/packages/resolve-dependencies — Resolve dependencies

content/docs/references/api/plugin-rest-api.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ Architecture Alignment:
2828
- Microsoft Dynamics: Web API with entity operations
2929
- Strapi: Auto-generated REST endpoints from schemas
3030

31-
@example Serving routes from a plugin (imperative `http.server` mount)
31+
**Serving routes from a plugin (imperative `http.server` mount)**
3232
```typescript
3333
// Routes are mounted in CODE — resolve the `http.server` service from the
3434
// plugin context and register handlers on `kernel:ready` (the service is

content/docs/references/automation/time-relative-trigger.mdx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ automation context (so `{record.<field>}` interpolation and the start-node
3030
`condition` gate work exactly as they do for record-change flows). The
3131
descriptor is carried on the flow's start node as `config.timeRelative`.
3232

33-
@example T-minus renewal reminders (fires on the day a contract is 60/30/7 days out)
33+
**T-minus renewal reminders (fires on the day a contract is 60/30/7 days out)**
3434
```ts
3535
// flow start node
3636
config: {
@@ -45,14 +45,14 @@ config: {
4545
}
4646
```
4747

48-
@example "Expiring soon" range (fires every day a document is within 30 days of expiry)
48+
**"Expiring soon" range (fires every day a document is within 30 days of expiry)**
4949
```ts
5050
config: {
5151
timeRelative: { object: 'hr_document', dateField: 'expires_on', withinDays: 30 },
5252
}
5353
```
5454

55-
@example Overdue sweep (fires for POs up to 14 days past due)
55+
**Overdue sweep (fires for POs up to 14 days past due)**
5656
```ts
5757
config: {
5858
timeRelative: { object: 'purchase_order', dateField: 'due_date', withinDays: -14, filter: { status: 'open' } },

content/docs/references/shared/mapping.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,15 @@ ObjectStack for data synchronization.
1818
this base too, until the whole external-lookup family was retired in
1919
#8075 — ADR-0049, zero consumers.)
2020

21-
@example Basic field mapping
21+
**Basic field mapping**
2222
```typescript
2323
const mapping: FieldMapping = {
2424
source: 'external_user_id',
2525
target: 'user_id',
2626
};
2727
```
2828

29-
@example With a fallback for missing source values
29+
**With a fallback for missing source values**
3030
```typescript
3131
const mapping: FieldMapping = {
3232
source: 'user_name',

content/docs/references/studio/object-designer.mdx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ The Object Designer is composed of four interconnected panels:
3838
└─────────────────────────────────────────────────────────────────┘
3939
```
4040

41-
@example
4241
```typescript
4342
import {
4443
ObjectDesignerConfigSchema,

0 commit comments

Comments
 (0)