Skip to content

Commit 6ceaa4b

Browse files
claude[bot]claude
andauthored
fix(devx): read a published README's import specifier against the packages that exist (#10923)
Nine `@objectstack/` names across seven published documents named a package in no directory of this repo; five sat on import lines inside runnable fences. `check:published-readme-exports` was blind to all of them by construction — it resolves a documented import through the workspace member map, so a specifier that is not a member has no type entry to compare against and the gate reads no further. The gate now makes the member-existence claim before the symbol one, fenced to this repo's own npm scope, and the run header prints the scoped population as N/N. Claude-Session: https://claude.ai/code/session_01DdCnBGcHeufjrq7drTD3wt Co-authored-by: Claude <noreply@anthropic.com>
1 parent bd003d8 commit 6ceaa4b

9 files changed

Lines changed: 555 additions & 45 deletions

File tree

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
---
2+
"@objectstack/plugin-security": patch
3+
"@objectstack/service-package": patch
4+
"@objectstack/trigger-schedule": patch
5+
"@objectstack/trigger-record-change": patch
6+
"@objectstack/embedder-openai": patch
7+
"@objectstack/driver-sqlite-wasm": patch
8+
"@objectstack/spec": patch
9+
---
10+
11+
docs: name packages that exist in seven published documents, and gate the class (#10893)
12+
13+
A published README ships inside the npm tarball, so an install instruction in one
14+
reaches every reader of the package. Nine `@objectstack/` names across seven
15+
published documents named a package that is in **no directory of this repo**, and
16+
five of those sat on `import` lines inside runnable fences.
17+
18+
`check:published-readme-exports` could not see any of it, by construction. It
19+
resolves a documented import against the package's built type surface through the
20+
workspace member map, so a specifier that is not a member has no type entry to
21+
compare against and the gate reads no further — strict about a member that exists,
22+
silent about one that does not. The gate now makes the member-existence claim
23+
first: an `@objectstack/`-scoped specifier that names no workspace member is a
24+
finding, and the run header prints the scoped population as `N/N` so a recogniser
25+
that stops matching shows up as a denominator that fell.
26+
27+
What each dead claim now says, and why:
28+
29+
- **`@objectstack/trigger-schedule`** and **`@objectstack/trigger-record-change`**
30+
each misnamed **themselves**. Both READMEs — including their `# ` titles and
31+
every fenced import — said `@objectstack/plugin-trigger-…`, a name that has
32+
never been published. The exported class names (`ScheduleTriggerPlugin`,
33+
`TimeRelativeTriggerPlugin`, `RecordChangeTriggerPlugin`) were correct all
34+
along; only the package name was wrong, so this is a rename pinned by each
35+
package's own `name` field.
36+
- **`@objectstack/plugin-security`** told readers to `install
37+
@objectstack/plugin-org-scoping` and register an `OrgScopingPlugin` from it. No
38+
such package exists. The organization wall ships as the enterprise
39+
`@objectstack/organizations` runtime, whose `OrganizationsPlugin` registers the
40+
`org-scoping` service this plugin probes — the name `objectstack serve` and
41+
`objectstack doctor` both print. Asking for the wall without it is a refusal to
42+
boot (ADR-0093 D5), not a silent downgrade, and the page now says so. The
43+
tenant-isolation bullet pointed at `@objectstack/service-tenant`, which is the
44+
cloud control-plane runtime from the separate `cloud` repository and not where
45+
the wall comes from either.
46+
- **`@objectstack/service-package`** described packages being "delivered to
47+
runtime kernels that load them through `@objectstack/service-marketplace`". That
48+
package was never built: ADR-0003, ADR-0016 and ADR-0025 all name it as future
49+
work. The loading half that does exist here is
50+
`@objectstack/cloud-connection`'s `MarketplaceInstallLocalPlugin`.
51+
- **`@objectstack/embedder-openai`** had a fenced example importing
52+
`KnowledgeTursoPlugin` from `@objectstack/knowledge-turso` — the worst shape,
53+
because a reader pastes it. No knowledge adapter in this repository consumes an
54+
`IEmbedder` at all: `knowledge-memory` and `knowledge-ragflow` take no embedder
55+
option, and the adapters the contract is written for are not here. The example
56+
is now the `embed()` surface that does exist, with the gap stated rather than
57+
papered over with a substitute package name.
58+
- **`@objectstack/driver-sqlite-wasm`**'s "When to use" table compared it against
59+
`@objectstack/driver-sqlite` and `@objectstack/driver-postgres`. Neither has
60+
ever existed; `@objectstack/driver-sql` covers PostgreSQL, MySQL and SQLite
61+
through Knex, choosing the client from its optional peers.
62+
- **`@objectstack/spec`**'s published `prompts/architecture.md` instructed code
63+
generators to write `import { User } from '@objectstack/protocol'`. The package
64+
is `@objectstack/spec`, which the same sentence names as the path being
65+
replaced.
66+
67+
Four `@objectstack/` names that are **not** in this repo are deliberately left as
68+
they are, because prose may name a package this repo does not build and a runnable
69+
import may not: `@objectstack/security-enterprise` (the enterprise edition, whose
70+
install hint the CLI prints and a CLI test pins), `@objectstack/service-tenant`
71+
(the cloud runtime), `@objectstack/framework` (the umbrella install name), and the
72+
two names `service-datasource`'s README recalls as its own past.

packages/drivers/driver-sqlite-wasm/README.md

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# @objectstack/driver-sqlite-wasm
22

33
SQLite-on-WASM driver for ObjectStack. Runs the same `SqlDriver` codepath as
4-
`@objectstack/driver-sqlite` but swaps the native `better-sqlite3` N-API binding
4+
`@objectstack/driver-sql` but swaps the native `better-sqlite3` N-API binding
55
for [`sql.js`](https://sql.js.org) (SQLite compiled to WebAssembly), so it works
66
in environments where native modules are unavailable — most notably
77
**StackBlitz WebContainer** (Node-in-browser).
@@ -14,14 +14,18 @@ in environments where native modules are unavailable — most notably
1414

1515
| Driver | Backend | Runs in WebContainer | Native binary |
1616
|---|---|---|---|
17-
| `@objectstack/driver-sqlite` | `better-sqlite3` || yes |
17+
| `@objectstack/driver-sql` (SQLite) | `better-sqlite3`, an optional dependency || yes |
1818
| **`@objectstack/driver-sqlite-wasm`** | `sql.js` (WASM) || no |
19-
| `@objectstack/driver-postgres` | `pg` | ✅ (with TCP) | no |
19+
| `@objectstack/driver-sql` (Postgres) | `pg`, an optional peer dependency | ✅ (with TCP) | no |
20+
21+
Two rows name the same package on purpose: `@objectstack/driver-sql` covers
22+
PostgreSQL, MySQL and SQLite through Knex, selecting the client from its optional
23+
peers. There is no separate `driver-sqlite` or `driver-postgres` package.
2024

2125
Pick the WASM driver when you need a zero-binary SQLite that boots in the
2226
browser sandbox, in serverless edge runtimes that expose Node `fs`, or in
2327
CI environments where building `better-sqlite3` against the host Node is
24-
painful. For production servers, prefer the native driver.
28+
painful. For production servers, prefer `@objectstack/driver-sql` with a native client.
2529

2630
## Install
2731

packages/plugins/embedder-openai/README.md

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ OpenAI-compatible embedder for ObjectStack. Works against any endpoint that spea
1414
| Ollama (local) | `http://localhost:11434/v1` | `bge-m3`, `nomic-embed-text` |
1515
| LiteLLM / vLLM / 自建网关 | (your endpoint) | (your model) |
1616

17-
Implements `IEmbedder` from `@objectstack/spec/contracts` — drop directly into any knowledge adapter (e.g. `@objectstack/knowledge-turso`).
17+
Implements `IEmbedder` from `@objectstack/spec/contracts`, so it drops into any knowledge adapter that computes vectors. ⚠️ No adapter in this repository does yet — see [Using the embedder](#using-the-embedder).
1818

1919
## Install
2020

@@ -77,21 +77,28 @@ const embedder = createOpenAIEmbedder({
7777
});
7878
```
7979

80-
## Plug into a knowledge adapter
80+
## Using the embedder
81+
82+
`OpenAIEmbedder` is a plain `IEmbedder`: construct it and hand it to whatever needs
83+
vectors.
8184

8285
```ts
8386
import { OpenAIEmbedder } from '@objectstack/embedder-openai';
84-
import { KnowledgeTursoPlugin } from '@objectstack/knowledge-turso';
8587

8688
const embedder = new OpenAIEmbedder({ apiKey: process.env.OPENAI_API_KEY! });
8789

88-
kernel.use(new KnowledgeTursoPlugin({
89-
url: 'libsql://your-tenant.turso.io',
90-
authToken: env.TURSO_TOKEN,
91-
embedding: embedder,
92-
}));
90+
const [vector] = await embedder.embed(['ObjectStack turns an app into typed metadata']);
91+
console.log(embedder.id, embedder.dimensions, vector.length);
9392
```
9493

94+
⚠️ **No knowledge adapter in this repository consumes an `IEmbedder` yet.** The two this
95+
repo builds — `@objectstack/knowledge-memory` and `@objectstack/knowledge-ragflow` — take
96+
no embedder option. The vector-computing adapters the contract is written for
97+
(`@objectstack/knowledge-turso`, `@objectstack/knowledge-sqlite-vec`, named in
98+
[`embedder.ts`](../../spec/src/contracts/embedder.ts)) are in no directory of this repo,
99+
so an earlier revision of this page showed a `new KnowledgeTursoPlugin({ embedding })`
100+
example that no reader could install or run.
101+
95102
## Options
96103

97104
| Option | Default | Description |

packages/plugins/plugin-security/README.md

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -37,23 +37,31 @@ await kernel.bootstrap();
3737

3838
`SecurityPlugin` is single-tenant by default. It enforces RBAC, owner-based RLS, and Field-Level Security regardless of mode.
3939

40-
For **multi-tenant** (logical row-level Organization scoping) install `@objectstack/plugin-org-scoping` *before* SecurityPlugin:
41-
42-
```typescript
43-
import { OrgScopingPlugin } from '@objectstack/plugin-org-scoping';
44-
45-
await kernel.use(new OrgScopingPlugin()); // MUST be BEFORE SecurityPlugin
46-
await kernel.use(new SecurityPlugin());
47-
```
40+
For **multi-tenant** (logical row-level Organization scoping) the organization wall itself
41+
is **not in this package and not in this repository**. It ships as the enterprise
42+
`@objectstack/organizations` runtime, whose `OrganizationsPlugin` registers the
43+
`org-scoping` service; a host app declares and installs it in its own `package.json`, and
44+
`objectstack serve` resolves it from the app rather than from the framework. It must be
45+
registered **before** `SecurityPlugin`, so the posture probe below finds it.
46+
47+
Asking for the wall without the package is not a silent downgrade: `objectstack serve`
48+
prints `FATAL: tenancy posture '<posture>' was requested but @objectstack/organizations
49+
could not be loaded` and **refuses to boot** (ADR-0093 D5), unless the operator explicitly
50+
sets `OS_ALLOW_DEGRADED_TENANCY=1`. `objectstack doctor` reports the same missing runtime.
51+
52+
> ⚠️ Earlier revisions of this page told readers to install `@objectstack/plugin-org-scoping`
53+
> and register an `OrgScopingPlugin` from it. No such package exists — not on npm, and in no
54+
> directory of this repo. The open edition ships no organization wall; there is nothing to
55+
> install *here* to get one.
4856
4957
SecurityPlugin resolves the tenancy **posture** (`single` | `group` | `isolated`) once at start time — preferring the `tenancy` service, and falling back to probing `getService('org-scoping')` (present ⇒ the historical `isolated` posture). Two consequences:
5058

5159
- **Tenant isolation is not an RLS policy.** Since ADR-0095 D1 the organization wall is **Layer 0** (`tenant-layer.ts`): an independent filter AND-composed ahead of business RLS, so a business-RLS change can never weaken it (W1) and the `viewAllRecords` / `modifyAllRecords` superuser bypass can never cross it (W2 — crossing takes a true `PLATFORM_ADMIN`). Under the `single` posture Layer 0 is inert. Accordingly the default `member_default` / `viewer_readonly` sets ship **no** wildcard `tenant_isolation` policy: `member_default` carries the owner-scoped `owner_only_writes` / `owner_only_deletes` plus per-object `_self` carve-outs on the better-auth identity tables, and `viewer_readonly` carries the `_self` carve-outs only.
5260
- **The platform's own tenant-scoped RLS policies are still stripped when no wall is enforced** (`single`), so single-tenant deployments aren't filtered to zero rows and don't pay the field-existence safety net on every find — e.g. `organization_admin`'s `sys_member_org` / `sys_invitation_org` / `sys_team_org`, and the `sys_organization_self` carve-out. The strip is by **provenance**, not by pattern-matching the predicate: an app-authored tenant policy is never stripped — it reaches the compiler and fails closed there, with a one-time operator warning (ADR-0105 D3).
5361

54-
`organization_id` auto-injection on insert is provided by OrgScopingPlugin; `owner_id` auto-injection always runs in SecurityPlugin regardless.
62+
`organization_id` auto-injection on insert is provided by that organizations runtime; `owner_id` auto-injection always runs in SecurityPlugin regardless.
5563

56-
In CLI / dev-server mode the `OS_MULTI_ORG_ENABLED` environment variable (default `false`) toggles whether the runtime registers `OrgScopingPlugin` alongside `SecurityPlugin`. Set `OS_MULTI_ORG_ENABLED=true` before `objectstack serve` / `pnpm dev` to enable.
64+
In CLI / dev-server mode the `OS_MULTI_ORG_ENABLED` environment variable (default `false`) toggles whether the runtime registers `OrganizationsPlugin` alongside `SecurityPlugin`. Set `OS_MULTI_ORG_ENABLED=true` before `objectstack serve` / `pnpm dev` to enable.
5765

5866
## Key Exports
5967

@@ -92,7 +100,7 @@ Compilation output is a filter AST merged into every query's `where` clause, so
92100
## When to use
93101

94102
- ✅ Any multi-user deployment.
95-
- ✅ Enforcing tenant isolation (combine with `@objectstack/service-tenant`).
103+
- ✅ Enforcing tenant isolation — the wall itself comes from the enterprise organizations runtime described above, not from this package.
96104

97105
## When not to use
98106

packages/services/service-package/README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
## Overview
99

10-
`service-package` persists ObjectStack packages — the unit of metadata distribution consisting of a `manifest` plus its `objects`, `views`, `apps`, `flows`, `agents`, `tools`, and `translations` — into the `sys_packages` system table so they can be published, listed, and delivered to runtime kernels that load them through `@objectstack/service-marketplace`.
10+
`service-package` persists ObjectStack packages — the unit of metadata distribution consisting of a `manifest` plus its `objects`, `views`, `apps`, `flows`, `agents`, `tools`, and `translations` — into the `sys_packages` system table so they can be published, listed, and delivered to runtime kernels that load them. In this repo the loading half is `@objectstack/cloud-connection`, whose `MarketplaceInstallLocalPlugin` installs a marketplace package into the local kernel through the `manifest` service.
1111

1212
Typical consumers:
1313

@@ -105,7 +105,8 @@ CREATE INDEX IF NOT EXISTS idx_packages_latest
105105
## When not to use
106106

107107
- ❌ Not a package manager for npm/TypeScript source packages — use npm.
108-
- ❌ Not a runtime plugin loader — pair with `@objectstack/service-marketplace` or a custom loader for that.
108+
- ❌ Not a runtime plugin loader — pair with `@objectstack/cloud-connection`'s
109+
`MarketplaceInstallLocalPlugin`, or a custom loader, for that.
109110

110111
## Related Packages
111112

packages/spec/prompts/architecture.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ B. Terminology
6767
* ALWAYS emphasize "Polyglot Data". We are not just a SQL wrapper; we handle Redis and Excel native files.
6868
* Studio vs. Cloud: Studio is for "Local Data & Development". Cloud is for "Deployment & Collaboration".
6969
C. Coding Style
70-
* Monorepo: Use generic imports (e.g., import { User } from '@objectstack/protocol') instead of relative paths like ../../packages/spec.
70+
* Monorepo: Use generic imports (e.g., import { User } from '@objectstack/spec') instead of relative paths like ../../packages/spec.
7171
* UI: Use Shadcn UI + Tailwind CSS. Dark mode default for developer tools (Studio/Console).
7272
* Data Fetching: All UI components must be Server-Driven or strongly typed against the Schema.
7373
5. Execution Context

packages/triggers/trigger-record-change/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# @objectstack/plugin-trigger-record-change
1+
# @objectstack/trigger-record-change
22

33
Auto-launch ObjectStack flows on record changes.
44

@@ -74,7 +74,7 @@ update path.
7474
```ts
7575
import { AutomationServicePlugin } from '@objectstack/service-automation';
7676
import { MessagingServicePlugin } from '@objectstack/service-messaging';
77-
import { RecordChangeTriggerPlugin } from '@objectstack/plugin-trigger-record-change';
77+
import { RecordChangeTriggerPlugin } from '@objectstack/trigger-record-change';
7878

7979
kernel
8080
.use(new AutomationServicePlugin()) // engine + flows

packages/triggers/trigger-schedule/README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# @objectstack/plugin-trigger-schedule
1+
# @objectstack/trigger-schedule
22

33
Auto-launch ObjectStack flows on a schedule (cron / interval / once).
44

@@ -9,7 +9,7 @@ platform `IJobService` (the `'job'` service), so it stays adapter-agnostic: the
99
job service selects a cron-capable adapter (e.g. the durable `DbJobAdapter` or
1010
`CronJobAdapter`) for cron schedules and the interval adapter for the rest.
1111

12-
This is the sibling of `@objectstack/plugin-trigger-record-change` — same
12+
This is the sibling of `@objectstack/trigger-record-change` — same
1313
engine baseline, a different event source.
1414

1515
## What it does
@@ -48,7 +48,7 @@ in its context.
4848
```ts
4949
import { AutomationServicePlugin } from '@objectstack/service-automation';
5050
import { JobServicePlugin } from '@objectstack/service-job';
51-
import { ScheduleTriggerPlugin } from '@objectstack/plugin-trigger-schedule';
51+
import { ScheduleTriggerPlugin } from '@objectstack/trigger-schedule';
5252

5353
kernel
5454
.use(new AutomationServicePlugin()) // engine + flows
@@ -110,7 +110,7 @@ It needs both the job service (sweep cadence) **and** the ObjectQL engine (the
110110
date-window query); register it alongside the schedule trigger:
111111

112112
```ts
113-
import { ScheduleTriggerPlugin, TimeRelativeTriggerPlugin } from '@objectstack/plugin-trigger-schedule';
113+
import { ScheduleTriggerPlugin, TimeRelativeTriggerPlugin } from '@objectstack/trigger-schedule';
114114

115115
kernel
116116
.use(new ScheduleTriggerPlugin()) // plain schedule flows

0 commit comments

Comments
 (0)