You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
docs(releases,nav): v17 follow-up — Console gap backfill, sidebar restore, first docs sweep
Three related closures on the just-merged v17 release page (#3906):
1. The Console section was missing 25 objectui commits. The v17 frontend window
is cf2d56e32a11 → 4a4829d0ef39 = 128 commits, but the pending console-*.md
changesets covered only 103: the range 2cb8d78e24ad...c6cfdf1288b6 landed with
no changeset — exactly the "SHA bump leaves no trace" failure
scripts/bump-objectui.sh exists to prevent. Two of the missing commits are
breaking and each is the frontend half of a backend change the page already
documented (useClientNotifications delegates ↔ #3612 SDK removal;
@object-ui/types Capabilities re-exports ↔ the retired capabilities cluster).
Both now sit beside their backend halves and in the upgrade checklist, with the
other eight substantive commits folded into the Console section and
.changeset/console-c6cfdf1288b6-backfill.md recording the range itself.
2. "releases" returns to the root sidebar. #3423 unlisted References and
Releases together ("lookup content ... the docs home page links both"); that
trade holds for References (22 generated pages) but not for Releases in a
release window, when the upgrade notes are what people open the docs for.
References stays out. check-release-notes now enforces what its success line
already claimed: the section must be reachable via the root nav OR a
/docs/releases link on the docs home — either satisfies it (preserving #3423's
option), losing both fails the build. Negative-tested both directions.
3. First v17 docs sweep (docs/v17-docs-sweep.md — playbook + append-only run
log with a watermark, built to re-run while the RC train iterates). Run 1
fixed the drift v17 left in hand-written prose: services-checklist (17→16
services, graphql rows, the dissolved ObjectStackProtocol), the anonymous-deny
matrix still listing /graphql + handleGraphQL, sharing docs describing
owner/group shapes as "declared but not enforced" (they no longer parse),
http-protocol claiming enable.trash exists, REST/GraphQL in objectql
diagrams/prose, and the objectstack-api skill description (mirrors regenerated
via gen:skill-docs). False positives and out-of-scope findings (spec comment
drift, implementation-status.mdx staleness) are logged for the next run.
Verified: pnpm docs:build passes; check:release-notes / doc-authoring /
role-word / org-identifier / nul-bytes / skill-docs-sync all green; the new
guard branch fails when both entry points are removed and passes with either.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LXvaYR7TiJBCxYwjn51owH
Design the server-side API surface that an ObjectStack runtime exposes — REST/GraphQL endpoints, auth providers, realtime channels, error envelopes, batch/versioning contracts.
148
+
Design the server-side API surface that an ObjectStack runtime exposes — REST endpoints, auth providers, realtime channels, error envelopes, batch/versioning contracts.
149
149
150
-
Use when the user is adding `*.endpoint.ts`, configuring auth providers, defining custom routes, or extending the REST/GraphQL generator.
150
+
Use when the user is adding `*.endpoint.ts`, configuring auth providers, defining custom routes, or extending the REST generator.
151
151
152
152
Do not use for: consuming an ObjectStack API from a client (that is just standard HTTP — no skill needed); the auto-generated CRUD endpoints (those follow from objectstack-data); request-side query syntax (see objectstack-query). CEL expressions in route guards or auth predicates: load objectstack-formula alongside.
Copy file name to clipboardExpand all lines: content/docs/kernel/services-checklist.mdx
+6-9Lines changed: 6 additions & 9 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -13,7 +13,7 @@ for the protocol-method inventory; treat the per-service status columns as
13
13
historical until this page is regenerated.
14
14
</Callout>
15
15
16
-
The ObjectStack protocol defines **17 kernel services** registered via the `CoreServiceName` enum. Each service maps to a set of protocol methods (57 total), governed by the `ObjectStackProtocol`interface.
16
+
The ObjectStack protocol defines **16 kernel services** registered via the `CoreServiceName` enum (the never-implemented `graphql` entry was removed in v17). Each service maps to a set of protocol methods governed by its per-domain contract (`DataProtocol`, `MetadataProtocol`, ...) — the transitional `ObjectStackProtocol`composition alias was dissolved in v17 (ADR-0076 D9); capability availability comes from the runtime discovery `services` registry.
17
17
18
18
**Key architecture principle**: The kernel itself only provides **data** and **metadata** (framework). Everything else — including **auth** and **automation** — is delivered by **plugins**. The current `@objectstack/objectql` package is an example kernel implementation to get the basic API running; production kernels will be rebuilt as new plugins.
19
19
@@ -42,7 +42,7 @@ The ObjectStack protocol defines **17 kernel services** registered via the `Core
// Development (automatic — DevPlugin registers i18n stub for all 17 core services)
284
+
// Development (automatic — DevPlugin registers i18n stub for all 16 core services)
286
285
kernel.use(newDevPlugin());
287
286
288
287
// No plugin required — kernel auto-injects in-memory fallback if none registered
@@ -331,9 +330,9 @@ AppPlugin will:
331
330
332
331
---
333
332
334
-
## 12–17. Infrastructure Services
333
+
## 12–16. Infrastructure Services
335
334
336
-
`cache`, `queue`, and `job` are `core` services: like `i18n`, the kernel auto-injects an in-memory fallback when no plugin registers them (see `CORE_FALLBACK_FACTORIES` in `packages/core/src/fallbacks/`). The `optional` services (`file-storage`, `search`, `graphql`) stay disabled until a plugin provides them.
335
+
`cache`, `queue`, and `job` are `core` services: like `i18n`, the kernel auto-injects an in-memory fallback when no plugin registers them (see `CORE_FALLBACK_FACTORIES` in `packages/core/src/fallbacks/`). The `optional` services (`file-storage`, `search`) stay disabled until a plugin provides them.
337
336
338
337
| Service | Description |
339
338
|:--------|:------------|
@@ -342,7 +341,6 @@ AppPlugin will:
342
341
|**cache**| General-purpose cache. In-memory fallback; Redis via `@objectstack/service-cache`. |
Copy file name to clipboardExpand all lines: content/docs/permissions/authorization.mdx
+2-2Lines changed: 2 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -48,10 +48,10 @@ site — the file you read when behavior surprises you.
48
48
49
49
| # | Gate | What it decides | Enforcement site | Failure direction |
50
50
|---|---|---|---|---|
51
-
| 1 |**Anonymous deny**| No identity → HTTP 401. **Uniform across every HTTP surface that reaches object data** (#2567): REST `/data`, the metadata endpoints (`/meta`), the dispatcher GraphQL endpoint (`/graphql`), and the raw-hono standard `/data` routes — one shared decision, so a caller denied on `/data` can't read the same rows through a sibling door. **Default-on** (ADR-0056 D2): public serving requires an explicit `api.requireAuth: false` opt-out, which logs a boot warning. Control plane (`/auth`, `/health`, `/discovery`) is exempt; share-links validate their token then read as SYSTEM. |`packages/core/src/security/anonymous-deny.ts``shouldDenyAnonymous` — called by `rest-server.ts``enforceAuth`, the dispatcher `handleGraphQL`/`handleMetadata`/`handleAI`, and `plugin-hono-server``denyAnonymous` (default in `packages/spec/src/api/rest-server.zod.ts`); a source-enumerating ratchet in `authz-conformance.test.ts` fails CI if a new surface ships ungated | fail-closed |
51
+
| 1 | **Anonymous deny** | No identity → HTTP 401. **Uniform across every HTTP surface that reaches object data** (#2567): REST `/data`, the metadata endpoints (`/meta`), and the raw-hono standard `/data` routes (the dispatcher GraphQL endpoint left the matrix when the GraphQL surface was removed in v17 — `/graphql` now 404s) — one shared decision, so a caller denied on `/data` can't read the same rows through a sibling door. **Default-on** (ADR-0056 D2): public serving requires an explicit `api.requireAuth: false` opt-out, which logs a boot warning. Control plane (`/auth`, `/health`, `/discovery`) is exempt; share-links validate their token then read as SYSTEM. | `packages/core/src/security/anonymous-deny.ts` `shouldDenyAnonymous` — called by `rest-server.ts` `enforceAuth`, the dispatcher `handleMetadata`/`handleAI`, and `plugin-hono-server` `denyAnonymous` (default in `packages/spec/src/api/rest-server.zod.ts`); a source-enumerating ratchet in `authz-conformance.test.ts` fails CI if a new surface ships ungated | fail-closed |
52
52
| 2 |**Public-form grant**| An anonymous form submission carries a declaration-derived `publicFormGrant` authorizing ONLY create + read-back on the form's declared target object — never anything else (ADR-0056 Option A). No guest-portal configuration needed (anonymous principals hold the `guest` position). |`packages/plugins/plugin-security/src/security-plugin.ts` (ObjectQL middleware) | scope-limited allow |
53
53
| 3 |**Object CRUD**|`allowRead/Create/Edit/Delete` (+ the destructive lifecycle class `allowTransfer/Restore/Purge`, gated ahead of the M2 operations — #1883) resolved across the caller's permission sets. |`packages/plugins/plugin-security/src/permission-evaluator.ts``checkObjectPermission`| fail-closed 403 |
54
-
| 4 |**OWD / sharing**| Org-wide default (`private` / `public_read` / `public_read_write` / `controlled_by_parent`; **unset or unknown ⇒ `private`, fail-closed** — ADR-0090 D1) plus the external dial (`externalSharingModel`, ADR-0090 D11), manual record shares, criteria sharing rules (owner-type rules are declared but seed-skipped — [not enforced](/docs/permissions/sharing-rules#owner-based-sharing-rules)), business-unit hierarchy widening (ADR-0057 D5: scope-depth hierarchy lives on `sys_business_unit`, not positions). |`packages/plugins/plugin-sharing/src/sharing-service.ts` + `sharing-rule-service.ts`| fail-closed to owner-only |
54
+
| 4 |**OWD / sharing**| Org-wide default (`private` / `public_read` / `public_read_write` / `controlled_by_parent`; **unset or unknown ⇒ `private`, fail-closed** — ADR-0090 D1) plus the external dial (`externalSharingModel`, ADR-0090 D11), manual record shares, criteria sharing rules (owner-type rules were removed from the authoring surface in v17 rather than left declared-but-skipped — [Sharing Rules](/docs/permissions/sharing-rules#recipient-types)), business-unit hierarchy widening (ADR-0057 D5: scope-depth hierarchy lives on `sys_business_unit`, not positions). |`packages/plugins/plugin-sharing/src/sharing-service.ts` + `sharing-rule-service.ts`| fail-closed to owner-only |
55
55
| 5 |**Row-level security**| CEL predicates (`using` read filter, `check` write post-image) compiled into the query. If **no** applicable policy compiles, the result is a deny-all sentinel (fail-closed); an uncompilable policy alongside compilable ones is excluded from the OR-union **with a logged warning** — exclusion can only narrow access, never widen it. Tenant isolation is a wildcard RLS rule AND-ed on top. |`packages/plugins/plugin-security/src/rls-compiler.ts` + `security-plugin.ts`| fail-closed |
56
56
| 6 |**Field-level security**| Read mask (strip non-readable fields) + write deny per `fields` rules. Caller queries that **filter, sort, group, or aggregate by** a non-readable field are rejected outright (HTTP 403, `field_predicate_denied`) — masking only the output would leave row presence as a value oracle. RLS-injected predicates are exempt (they run after the guard and may reference hidden fields like `owner_id`). |`packages/plugins/plugin-security/src/field-masker.ts` + `predicate-guard.ts`| fail-closed on predicates; see posture note below |
0 commit comments