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: P0 audit fixes — resolve contradictions, hand over the keys
Fixes the highest-leverage findings from the full docs audit (110 guide
pages reviewed against a customer-comprehension rubric).
Contradiction fixes (docs said two different things, or taught dead APIs):
- OWD: permissions-matrix table/example/callout now use the canonical four
sharingModel values (ADR-0090 D4) instead of removed legacy aliases
- referenceFilters taught as a positive example while relationships.mdx
documents it as schema-accepted-but-inert — fields.mdx now teaches
structured lookupFilters + dependsOn; property tables mark it Legacy
- percent semantics unified to fraction storage (0.85 = 85%) across
fields/decision-tree (validation-rules already had it right)
- hook input shape unified to the `{ doc }` contract (plugins tutorial
handler + test now match kernel/events.mdx)
- libsql:// removed from self-hosting env table (driver ships in Cloud,
not the open framework); backup page Turso section qualified
- api/index MCP row: actions require the author's ai.exposed opt-in
- permission-metadata: `positions` (not `roles`) is the canonical field
- common-patterns: all pattern objects now declare sharingModel and the
page warns about namespace prefixes — examples pass the gate they teach
Key handovers (previously undocumented dead-ends):
- build-with-claude-code: seeded dev admin credentials at the verify step,
npx os invocations, localhost MCP connect example
- api/index: new Authentication section (session sign-in + API keys)
- self-hosting: "First boot: create the admin" section (first signup =
bootstrap admin); fixed dead examples/docker links (also docker/README)
- vercel: warn that InMemoryDriver loses data on every cold start
- getting-started prerequisites: Node 18+ only for the scaffold path
- kernel/services-checklist: stale-status warning banner
- quick-reference: unlink two non-existent reference pages
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: content/docs/api/index.mdx
+18-1Lines changed: 18 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -15,7 +15,7 @@ ObjectStack exposes a fully typed REST API. All endpoints use JSON request/respo
15
15
| :--- | :--- |
16
16
|**REST**| ✅ Auto-generated from the protocol (`@objectstack/rest`) — CRUD, query, batch, metadata, packages |
17
17
|**Realtime**| ⚠️ In-process pub/sub service (`@objectstack/service-realtime`, single-instance); the `/realtime/*` REST routes and WebSocket/SSE transport are plugin-provided — none ships in the open framework |
18
-
|**MCP**| ✅ Non-system objects and their actions exposed as Model Context Protocol tools, gated by the caller's permissions/RLS rather than a per-action opt-in flag ([AI module](/docs/ai)) |
18
+
|**MCP**| ✅ Non-system objects exposed automatically as Model Context Protocol tools; actions additionally require the author's `ai.exposed` opt-in — every call is gated by the caller's permissions/RLS ([AI module](/docs/ai)) |
19
19
|**GraphQL**| ⚠️ Route is wired but **bring-your-own service**: `/graphql` returns 501 unless an implementation of the `IGraphQLService` contract is registered — none ships in the open framework |
20
20
|**OData**| ⚠️ Vocabulary only: REST list endpoints accept OData-style operators (e.g. `$top`), but there is no standalone OData endpoint |
21
21
@@ -58,6 +58,23 @@ sequenceDiagram
58
58
See [Actions as Tools](/docs/ai/actions-as-tools) for the `run_action` bridge and the
59
59
[MCP reference](/docs/references/ai/mcp) for binding external MCP servers into your agents.
60
60
61
+
## Authentication
62
+
63
+
Every REST call runs as a principal — anonymous requests only see what your
64
+
permission model grants anonymous users. Two ways to authenticate:
65
+
66
+
-**Session cookie** (browsers, quick local tests): `POST /api/v1/auth/sign-in/email`
67
+
with `{ "email": "…", "password": "…" }` sets the session cookie — reuse it with
68
+
`curl -c cookies.txt` / `-b cookies.txt`. On a fresh dev database the seeded
69
+
admin is `admin@objectos.ai` / `admin123`.
70
+
-**API key** (scripts, CI, headless agents): mint one with `POST /api/v1/keys`
71
+
(the key is shown once), or from **Setup → Connect an Agent** in the Console.
72
+
Send it as `x-api-key: osk_…` or `Authorization: Bearer osk_…`.
73
+
74
+
See [Authentication](/docs/permissions/authentication) for the full identity
75
+
surface (OAuth flows, sessions, providers) and
76
+
[Plugin Endpoints](/docs/api/plugin-endpoints) for the auth route catalog.
77
+
61
78
## What's in this module
62
79
63
80
-[Data API](/docs/api/data-api) — CRUD, batch operations, record cloning, and analytics queries
|`referenceFilters`|`string[]`| — |**Legacy** — accepted by the schema but not read by the record-picker (filters nothing). Use structured `lookupFilters` + `dependsOn` instead; see [Relationships](/docs/data-modeling/relationships)|
305
305
|`deleteBehavior`|`'restrict' \| 'cascade' \| 'set_null'`|`'set_null'`| Behavior when referenced record is deleted (a *required* lookup left at the default `set_null` is escalated to `restrict`, since a NOT NULL foreign key cannot be cleared) |
306
306
307
307
```typescript
@@ -323,7 +323,7 @@ Parent-child relationship (cascading delete by default).
323
323
| Property | Type | Default | Description |
324
324
|:---|:---|:---|:---|
325
325
|`reference`|`string`|**required**| Target (master) object name |
|`referenceFilters`|`string[]`| — |**Legacy** — accepted by the schema but not read by the record-picker (filters nothing). Use structured `lookupFilters` + `dependsOn` instead; see [Relationships](/docs/data-modeling/relationships)|
327
327
|`deleteBehavior`|`'restrict' \| 'cascade' \| 'set_null'`|`'cascade'`| Behavior when parent is deleted (master-detail cascades unless set to `restrict`) |
328
328
|`inlineEdit`|`boolean \| 'grid' \| 'form'`| — | Edit child records inline on the parent create/edit form (`true` = auto-pick, `'grid'`, or `'form'`) |
Copy file name to clipboardExpand all lines: content/docs/deployment/self-hosting.mdx
+16-2Lines changed: 16 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -32,7 +32,7 @@ workable default:
32
32
33
33
| Variable | Why it must be set |
34
34
|:---|:---|
35
-
|`OS_DATABASE_URL`| Without it, data lands in a SQLite file under the ObjectStack home directory (`~/.objectstack`, or `<cwd>/.objectstack` next to a project config) — fine for one box, wrong for containers. Use `postgres://…`, `libsql://…`, or a mounted `file:…` path. |
35
+
|`OS_DATABASE_URL`| Without it, data lands in a SQLite file under the ObjectStack home directory (`~/.objectstack`, or `<cwd>/.objectstack` next to a project config) — fine for one box, wrong for containers. Use `postgres://…`, `mongodb://…`, or a mounted `file:…` path (`libsql://` / Turso is **not** supported by the open framework — that driver ships in ObjectStack Cloud). |
36
36
|`OS_AUTH_SECRET`| Session secret for the auth plugin (`AUTH_SECRET` is the legacy alias). Without it, `/api/v1/auth/*` is **silently skipped** — the server runs unauthenticated. |
37
37
|`OS_SECRET_KEY`| 32-byte master key encrypting every stored secret (`openssl rand -hex 32`). On a container's ephemeral filesystem the auto-minted key is **lost on restart**, making previously-encrypted secrets undecryptable. |
38
38
|`OS_PORT`|`os start`**fails loudly** if the port is busy (it never auto-shifts like `os dev`). Pin it and keep your reverse-proxy upstream in sync. |
@@ -117,7 +117,7 @@ straight from release storage instead of a mount.)
117
117
For a self-contained deployable image, extend it. The Dockerfile below (plus
118
118
the compose stack in the next section and a `.dockerignore`) ships
0 commit comments