Skip to content

Commit 5444bb1

Browse files
committed
Merge remote-tracking branch 'origin/main' into claude/issue-20653-plugin-bundle-leaves
2 parents 7f6edd4 + 9a4b2bb commit 5444bb1

60 files changed

Lines changed: 476 additions & 461 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
---
2+
'@objectstack/spec': minor
3+
---
4+
5+
feat(spec): the stored-filter conversion rewrites a filter on a block whose rows are inline, as it does on any other block
6+
7+
The ADR-0087 D2 conversion `page-component-filter-record-to-rule-array` no longer leaves every filter of a page component whose rows are inline (`data: { provider: 'value', … }`, a `data` array, or `staticData`) as stored. Such a filter, the binding's `dataSource.filter` included, is now rewritten to the `[{ field, operator, value }, ...]` rule array exactly as it is on a block that queries an object. What still stays as stored, and is still reported as a TODO, is only a filter with a part that has no lossless rule spelling: a combinator, a null value, or an operator the rule vocabulary does not spell. That holds on any block.
8+
9+
Why the conversion declined, and why it no longer needs to: the `object-map`, `object-tree`, `object-calendar` and `object-gantt` blocks match that filter against their own rows in objectui's in-memory data source (`ValueDataSource.find`). The conversion was written against an objectui version whose `find` excluded every row for a rule array, so it left those filters alone and said so in the TODO. The objectui version this repository pins (`.objectui-sha`, the same pin the previous release shipped) lowers a rule array before it matches, and it selects the rows the stored form selected. That was measured over every operator the conversion maps: 114 filters on eight rows, null and missing values included. The same filters select no row on the objectui build just before that fix. So the decline was already protecting nothing: it only left convertible filters unconverted and reported TODOs that no longer needed to exist.
10+
11+
What an operator sees:
12+
13+
- `os migrate meta --stored` now lists such a page as a pending rewrite. It used to list it as a `skipped` row with a TODO. A preview over a database whose only legacy filters sat on inline-row blocks therefore exits 1 until `os migrate meta --stored --apply` rewrites them.
14+
- Until then, every stored-row read replays the same rewrite, so the block reads the rule array and shows the same rows.
15+
- Nothing an author writes is accepted or refused differently. The conversion stays retired from the authoring path, and no schema changes.
16+
17+
The migration entries `element-data-source-and-object-block-filter-rule-array` and `object-grid-default-filters-rule-array`, and the protocol-18 step rationale, no longer say that inline-row filters are left as stored.
18+
19+
ADR-0087 disposition: already registered. This changes the behaviour of the registered D2 conversion `page-component-filter-record-to-rule-array` and edits its two D3 entries. There is nothing new to register.
20+
21+
Clause-②: no
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
'@objectstack/plugin-security': patch
3+
---
4+
5+
Provenance comments in `plugin-security` were re-anchored
6+
7+
Comment and docblock lines under `src/` that cited tracker numbers which no
8+
longer resolve on GitHub now cite the record in this repository that decided
9+
the matter (an ADR where one exists, otherwise the commit in this repository's
10+
history), and say in their own words what was decided. Comments only: no type,
11+
schema, export, log or refusal text, or runtime behaviour changes.

‎content/docs/automation/connectors.mdx‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,8 @@ Materializes a single **`request`** action accepting
114114
payload per call. Use it when the upstream is "just HTTP" and you don't have a
115115
spec document.
116116

117+
Do not put a credential in `headers` or `defaultHeaders`: both are stored in metadata and served with it. Declare it as `auth.credentialRef` instead — the resolved `auth` is applied to every request — as the `Authorization` header, or for `api-key` as `headerName` (default `X-API-Key`) or the `paramName` query parameter.
118+
117119
### `provider: 'openapi'` — one action per operation
118120

119121
Config: **`spec`** (required) and **`baseUrl`** (optional — overrides the

‎content/docs/automation/flows.mdx‎

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -261,15 +261,19 @@ nothing is assigned or written in its place.
261261
{
262262
id: 'notify_slack',
263263
type: 'http',
264-
label: 'Send Slack Notification',
264+
label: 'Post Order Event',
265265
config: {
266-
url: 'https://hooks.slack.com/services/...',
266+
url: 'https://api.example.com/v1/order-events',
267267
method: 'POST',
268-
body: { text: 'New order: {record.name}' },
268+
body: { event: 'order.created', name: '{record.name}' },
269269
},
270270
}
271271
```
272272

273+
<Callout type="warn" title="Do not put a secret in an http node's url or headers">
274+
A flow definition, including an `http` node's `url` and `headers`, is served to every member who can read flows. A token, API key or signed webhook url written there is readable by all of them. Route an outbound credential to a declarative connector's `auth.credentialRef` and call it with a `connector_action` node instead — see [Connectors](/docs/automation/connectors#authentication). Only `signingSecret` (and a start node's `secret`) is withheld when a definition is served; `url` and `headers` are served as written.
275+
</Callout>
276+
273277
**Script:**
274278

275279
The built-in `script` executor never evaluates an arbitrary JavaScript string —

‎packages/plugins/plugin-security/src/bootstrap-declared-capabilities.test.ts‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,12 @@ function makeQl(declared: any[] = []) {
6060
return (v === null ? r[k] == null : r[k] === v);
6161
}),
6262
);
63-
// [#11518] `limit` is HONOURED, and a paged read is ordered by `id`
63+
// [commit e1d773eb7] `limit` is HONOURED, and a paged read is ordered by `id`
6464
// ascending (#4363's pagination tie-breaker). Both are properties of the
6565
// shipped drivers, measured for the sibling double in
6666
// `bootstrap-system-capabilities.test.ts`; this one ignored `limit`
6767
// entirely, which made the whole class of page-cap defect INEXPRESSIBLE
68-
// here — including #11518's, whose consequence lands on THIS seeder.
68+
// here — including the cap commit e1d773eb7 fixed, whose consequence lands on THIS seeder.
6969
if (q?.limit === undefined) return matched;
7070
return [...matched]
7171
.sort((a, b) => (String(a.id) < String(b.id) ? -1 : String(a.id) > String(b.id) ? 1 : 0))
@@ -434,7 +434,7 @@ describe('unowned-declaration diagnostic (#4967 Part 3)', () => {
434434
});
435435

436436
/**
437-
* [#11518] THE CONSEQUENCE THIS SEEDER PAYS FOR A TRUNCATED EXISTENCE PAGE.
437+
* [commit e1d773eb7] THE CONSEQUENCE THIS SEEDER PAYS FOR A TRUNCATED EXISTENCE PAGE.
438438
*
439439
* This is one of the two callers on `main` that read UNSCOPED (the other is
440440
* `permission-set-projection`'s overlay pass), and `seed-name-lookup.ts` capped

‎packages/plugins/plugin-security/src/bootstrap-platform-admin-existing-holder-scan.test.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.
22

33
/**
4-
* #16861 — whether this deployment ALREADY has a platform admin, and why the
4+
* Commit 1c83ca226 — whether this deployment ALREADY has a platform admin, and why the
55
* answer stopped being a function of how many ORG admins it has.
66
*
77
* ## The defect, re-measured on this branch's base before anything changed
@@ -58,7 +58,7 @@
5858
* ## Why the row ORDER is permuted rather than a second driver package
5959
*
6060
* Same reason as `bootstrap-platform-admin-promotion-selection.test.ts`
61-
* (#16682): `@objectstack/driver-memory` cannot be declared here without a
61+
* (commit 9b9581b11): `@objectstack/driver-memory` cannot be declared here without a
6262
* `scripts/driver-memory-census.ledger.json` disposition, which is a
6363
* maintainer ruling. Each case runs the REAL engine over the REAL
6464
* better-sqlite3 driver behind a facade that permutes a result ONLY when the

‎packages/plugins/plugin-security/src/bootstrap-platform-admin-promotion-selection.test.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.
22

33
/**
4-
* #16682 — WHICH user the `single`-posture bootstrap promotes, and why.
4+
* Commit 9b9581b11 — WHICH user the `single`-posture bootstrap promotes, and why.
55
*
66
* ## The defect, re-measured on this branch's base before anything changed
77
*
@@ -199,7 +199,7 @@ async function seedUser(
199199
email: string,
200200
createdAt: string,
201201
withAccount: boolean,
202-
// [#16682, maintainer ruling batch #100] Absent means UNVERIFIED, which is
202+
// [commit 9b9581b11, maintainer ruling batch #100] Absent means UNVERIFIED, which is
203203
// what `isEmailVerifiedUserRow` reads an absent column as — so every fixture
204204
// that does not say otherwise is a row the declared-owner leg must REFUSE.
205205
emailVerified = false,

‎packages/plugins/plugin-security/src/bootstrap-platform-admin-seeded-provenance.test.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.
22

33
/**
4-
* #8692 — what provenance a REAL `bootstrapPlatformAdmin` run leaves on the
4+
* [commit 712e185db] What provenance a REAL `bootstrapPlatformAdmin` run leaves on the
55
* platform default permission sets, and what `os meta resync` then does with it.
66
*
77
* ## Why this file exists at all
@@ -136,7 +136,7 @@ async function rowViaEngine(engine: ObjectQL, name: string): Promise<any> {
136136
}
137137

138138
/**
139-
* A row exactly as a PRE-#8692 install holds it — written the way the old
139+
* A row exactly as an install before commit 712e185db holds it — written the way the old
140140
* seeder wrote it, which is to say WITHOUT `managed_by`, so the value comes
141141
* from the declaration's `defaultValue: 'admin'` by the very mechanism that
142142
* produced it on every install created before the ruling.

‎packages/plugins/plugin-security/src/bootstrap-platform-admin-walled-owner.test.ts‎

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* History of this surface, because the pins below flip an older family:
77
* - #11184 (framework leg of cloud#1509): walled postures stopped promoting
88
* the first registrant; only the env-declared owner elevated.
9-
* - #11343: the walled match additionally required a VERIFIED email.
9+
* - commit c0714eb5d: the walled match additionally required a VERIFIED email.
1010
* - #13147: `OS_PLATFORM_OWNER_EMAIL` became a comma-separated list through
1111
* the ONE parser in `@objectstack/core`.
1212
* - **#11974 (#11663 L4, maintainer acceptance 2026-08-25, Choice 4A/5A):
@@ -24,7 +24,7 @@
2424
* state, and `single` still PROMOTES (Choice 4A — the over-denial guard:
2525
* retiring the walled write must not retire the `single` one).
2626
*
27-
* - **#16682: the `single` SELECTION is repaired.** That guard used to be
27+
* - **Commit 9b9581b11: the `single` SELECTION is repaired.** That guard used to be
2828
* written as "byte-for-byte", and one case snapshotted the incumbent's
2929
* refusal to read `OS_PLATFORM_OWNER_EMAIL` on this branch. The incumbent
3030
* was the defect: an unordered, cap-50 `sys_user` read sorted client-side,
@@ -460,7 +460,7 @@ describe('single posture — "first user is owner" is ruled reasonable and UNCHA
460460
});
461461

462462
/**
463-
* ⚠️ RE-AUTHORED by #16682. This case used to assert the opposite —
463+
* ⚠️ RE-AUTHORED by commit 9b9581b11. This case used to assert the opposite —
464464
* "never consults the owner-email variable: a declared owner does NOT
465465
* redirect the single-org promotion" — and it is worth being explicit about
466466
* what changed and what did NOT, because the two are easy to confuse.
@@ -479,7 +479,7 @@ describe('single posture — "first user is owner" is ruled reasonable and UNCHA
479479
* only on the walled branch.
480480
*
481481
* The authority for the reversal is a MAINTAINER ruling — 2026-09-08,
482-
* decision batch #100, recorded on #16682 (comment 5587754690), which
482+
* decision batch #100, applied by commit 9b9581b11, which
483483
* supersedes the Choice 4A sentence for this one point and states what
484484
* survives it, verbatim:
485485
*
@@ -490,7 +490,7 @@ describe('single posture — "first user is owner" is ruled reasonable and UNCHA
490490
* > `single` one, and the over-denial invariant (`adminPromoted === true`
491491
* > with a grant row minted) stays pinned.
492492
*
493-
* ⛔ An earlier revision of this comment quoted the #16682 TRIAGE seat's
493+
* ⛔ An earlier revision of this comment quoted the TRIAGE seat's
494494
* ruling instead. That quotation was the reviewer's F3 finding: a pin
495495
* recorded under a maintainer ruling cannot be rewritten under a seat's.
496496
* The quotation above is the record that resolved it.
@@ -518,7 +518,7 @@ describe('single posture — "first user is owner" is ruled reasonable and UNCHA
518518
// #11974's over-denial guard, unchanged: the `single` write still happens.
519519
expect(r.adminPromoted).toBe(true);
520520
expect(ql.grants()).toHaveLength(1);
521-
// #16682: and it goes to the address the operator declared, not to
521+
// Commit 9b9581b11: and it goes to the address the operator declared, not to
522522
// whichever row the driver handed back first.
523523
expect(ql.grants()[0]?.user_id).toBe('u_second');
524524
expect(r.basis).toBe('declared-owner');
@@ -550,8 +550,8 @@ describe('single posture — "first user is owner" is ruled reasonable and UNCHA
550550
});
551551

552552
// ───────────────────────────────────────────────────────────────────────────
553-
// [#11974, amended by #16682] The bootstrap-replay trigger set. #11974
554-
// narrowed it to `single` + create/insert: the #11343 update arm (email /
553+
// [#11974, amended by commit 9b9581b11] The bootstrap-replay trigger set. #11974
554+
// narrowed it to `single` + create/insert: commit c0714eb5d's update arm (email /
555555
// email_verified) fired for the walled verify-then-elevate sequence, which no
556556
// longer exists, and its own rationale was that "`single` promotes the oldest
557557
// authenticable human and never reads `email`/`email_verified`".

0 commit comments

Comments
 (0)