diff --git a/apps/docs/redirects.mjs b/apps/docs/redirects.mjs index e9ac6fafec..db689d59d2 100644 --- a/apps/docs/redirects.mjs +++ b/apps/docs/redirects.mjs @@ -109,6 +109,9 @@ export const docsRedirects = [ // folder moves (wildcards — keep after exact entries) ['/docs/guides/runtime-services/:path*', '/docs/kernel/runtime-services/:path*'], ['/docs/guides/contracts/:path*', '/docs/kernel/contracts/:path*'], + // ObjectOS layer-name retirement: the System Protocol section is now "kernel" + // (:path* matches zero or more segments, so this also covers the bare URL) + ['/docs/protocol/objectos/:path*', '/docs/protocol/kernel/:path*'], // safety net for anything else under retired sections — keep last ['/docs/guides/:path*', '/docs'], ]; diff --git a/content/docs/api/data-flow.mdx b/content/docs/api/data-flow.mdx index 1e6ea50e81..1488e3fcc0 100644 --- a/content/docs/api/data-flow.mdx +++ b/content/docs/api/data-flow.mdx @@ -212,7 +212,7 @@ flowchart LR How data changes propagate to connected clients in real time. -**Implementation status:** This diagram (and the `emit(...)` → `EB->>WS` broadcast step in the Write Flow diagram above) shows the target design. The realtime service that ships today is an **in-memory pub/sub adapter** (`InMemoryRealtimeAdapter` in `@objectstack/service-realtime`), delivered to JS clients via **long-polling** (`RealtimeAPI` in `@objectstack/client`) — no WebSocket transport is wired up yet. The adapter also only matches subscriptions by `object` and `eventTypes`; per-field `filter` conditions (e.g. `{ project: 'prj_1' }`) are accepted in the request shape but are not yet enforced server-side. See [Real-Time Protocols](/docs/protocol/objectos/realtime-protocol) for the full implementation-status breakdown. +**Implementation status:** This diagram (and the `emit(...)` → `EB->>WS` broadcast step in the Write Flow diagram above) shows the target design. The realtime service that ships today is an **in-memory pub/sub adapter** (`InMemoryRealtimeAdapter` in `@objectstack/service-realtime`), delivered to JS clients via **long-polling** (`RealtimeAPI` in `@objectstack/client`) — no WebSocket transport is wired up yet. The adapter also only matches subscriptions by `object` and `eventTypes`; per-field `filter` conditions (e.g. `{ project: 'prj_1' }`) are accepted in the request shape but are not yet enforced server-side. See [Real-Time Protocols](/docs/protocol/kernel/realtime-protocol) for the full implementation-status breakdown. ```mermaid diff --git a/content/docs/api/index.mdx b/content/docs/api/index.mdx index d1064fa5a0..ac94174720 100644 --- a/content/docs/api/index.mdx +++ b/content/docs/api/index.mdx @@ -71,7 +71,7 @@ See [Actions as Tools](/docs/ai/actions-as-tools) for the `run_action` bridge an - [Error Catalog](/docs/api/error-catalog) — the full list of error codes - [Wire Format](/docs/api/wire-format) — request/response envelopes on the wire -Spec: [HTTP API](/docs/protocol/objectos/http-protocol), [Real-Time Protocols](/docs/protocol/objectos/realtime-protocol) +Spec: [HTTP API](/docs/protocol/kernel/http-protocol), [Real-Time Protocols](/docs/protocol/kernel/realtime-protocol) Schema reference: [API](/docs/references/api) diff --git a/content/docs/automation/index.mdx b/content/docs/automation/index.mdx index f161b22483..acae7f5e64 100644 --- a/content/docs/automation/index.mdx +++ b/content/docs/automation/index.mdx @@ -49,6 +49,6 @@ Rule of thumb: model *state* with workflows, model *steps* with flows, use hooks ## Related -- **Spec:** [State Machine (Lifecycle)](/docs/protocol/objectql/state-machine), [Runtime Capabilities](/docs/protocol/objectos/runtime-capabilities) +- **Spec:** [State Machine (Lifecycle)](/docs/protocol/objectql/state-machine), [Runtime Capabilities](/docs/protocol/kernel/runtime-capabilities) - **Schema reference:** [Automation](/docs/references/automation) - **Neighbors:** validation rules that block bad data live in [Data Modeling](/docs/data-modeling/validation); who may trigger an automation is governed by [Permissions & Identity](/docs/permissions); the services hooks call (email, queue, storage…) are documented in [Kernel & Services](/docs/kernel/runtime-services). diff --git a/content/docs/concepts/architecture.mdx b/content/docs/concepts/architecture.mdx index ce3a91e8b5..581fc19d4f 100644 --- a/content/docs/concepts/architecture.mdx +++ b/content/docs/concepts/architecture.mdx @@ -561,7 +561,7 @@ The three protocols are **loosely coupled** but **tightly integrated**: - [ObjectQL: Data Protocol](/docs/protocol/objectql) - Full data protocol specification - [ObjectUI: UI Protocol](/docs/protocol/objectui) - Full view protocol specification -- [Kernel: System Protocol](/docs/protocol/objectos) - Full control protocol specification +- [Kernel: System Protocol](/docs/protocol/kernel) - Full control protocol specification - [Developer Guide](/docs/getting-started/quick-start) - Build your first ObjectStack application --- diff --git a/content/docs/kernel/index.mdx b/content/docs/kernel/index.mdx index 1e74f7de56..cfcd09835d 100644 --- a/content/docs/kernel/index.mdx +++ b/content/docs/kernel/index.mdx @@ -5,7 +5,7 @@ description: The ObjectKernel runtime — plugin host, event bus, service regist # Kernel & Services -The kernel is ObjectStack's runtime: it loads your metadata artifact, hosts plugins, wires up services, and enforces the lifecycle that keeps the system stable. This module documents the **ObjectOS layer** in practice — the [System Protocol](/docs/protocol/objectos) is its normative spec. If you write hooks or plugins, this is where the capability surface you call — `ctx.api`, `ctx.getService(...)`, and the `services.*` contract they implement — is documented. +The kernel is ObjectStack's runtime: it loads your metadata artifact, hosts plugins, wires up services, and enforces the lifecycle that keeps the system stable. This module documents the **ObjectOS layer** in practice — the [System Protocol](/docs/protocol/kernel) is its normative spec. If you write hooks or plugins, this is where the capability surface you call — `ctx.api`, `ctx.getService(...)`, and the `services.*` contract they implement — is documented. ## How it fits together @@ -40,6 +40,6 @@ The kernel is ObjectStack's runtime: it loads your metadata artifact, hosts plug ## Related -- **Spec:** [System Lifecycle](/docs/protocol/objectos/lifecycle), [Runtime Capabilities](/docs/protocol/objectos/runtime-capabilities), [Metadata Service](/docs/protocol/objectos/metadata-service) +- **Spec:** [System Lifecycle](/docs/protocol/kernel/lifecycle), [Runtime Capabilities](/docs/protocol/kernel/runtime-capabilities), [Metadata Service](/docs/protocol/kernel/metadata-service) - **Schema reference:** [Kernel](/docs/references/kernel), [System](/docs/references/system), [Contracts](/docs/references/contracts) - **Neighbors:** building and packaging plugins is covered in [Plugins & Packages](/docs/plugins); running the kernel in production is covered in [Deployment & Operations](/docs/deployment). diff --git a/content/docs/plugins/index.mdx b/content/docs/plugins/index.mdx index 6747044f74..11046f80b0 100644 --- a/content/docs/plugins/index.mdx +++ b/content/docs/plugins/index.mdx @@ -18,7 +18,7 @@ ObjectStack is built on a **microkernel architecture** where nearly everything b - **[Package Overview](/docs/plugins/packages)** — All ObjectStack packages, services, drivers, plugins, and adapters - **[Adding a Metadata Type](/docs/plugins/adding-a-metadata-type)** — Register a new metadata type in the Studio Metadata Admin - Schema reference: [Kernel](/docs/references/kernel) -- Spec: [Plugin Package Specification](/docs/protocol/objectos/plugin-spec) +- Spec: [Plugin Package Specification](/docs/protocol/kernel/plugin-spec) --- diff --git a/content/docs/protocol/index.mdx b/content/docs/protocol/index.mdx index 17eee8ea3b..2e35c6c842 100644 --- a/content/docs/protocol/index.mdx +++ b/content/docs/protocol/index.mdx @@ -12,7 +12,7 @@ The ObjectStack Protocol defines three interconnected layers that together descr } title="ObjectQL: Data Protocol" href="/docs/protocol/objectql" description="Schema definitions, field types, state machines, query syntax, and data security." /> } title="ObjectUI: UI Protocol" href="/docs/protocol/objectui" description="Server-driven UI contracts for layouts, widgets, forms, and actions." /> - } title="Kernel: System Protocol" href="/docs/protocol/objectos" description="Runtime lifecycle, HTTP/realtime protocols, plugins, configuration, and i18n." /> + } title="Kernel: System Protocol" href="/docs/protocol/kernel" description="Runtime lifecycle, HTTP/realtime protocols, plugins, configuration, and i18n." /> ## Design Principles diff --git a/content/docs/protocol/objectos/config-resolution.mdx b/content/docs/protocol/kernel/config-resolution.mdx similarity index 99% rename from content/docs/protocol/objectos/config-resolution.mdx rename to content/docs/protocol/kernel/config-resolution.mdx index 182b56d8bc..0737b283b0 100644 --- a/content/docs/protocol/objectos/config-resolution.mdx +++ b/content/docs/protocol/kernel/config-resolution.mdx @@ -898,4 +898,4 @@ ObjectStack configuration resolution: - **Boot-time validation** using Zod schemas - **Inspection tools** for debugging config issues -**Next:** Learn about internationalization in [i18n Standard](/docs/protocol/objectos/i18n-standard). +**Next:** Learn about internationalization in [i18n Standard](/docs/protocol/kernel/i18n-standard). diff --git a/content/docs/protocol/objectos/error-handling.mdx b/content/docs/protocol/kernel/error-handling.mdx similarity index 99% rename from content/docs/protocol/objectos/error-handling.mdx rename to content/docs/protocol/kernel/error-handling.mdx index 80a1b64b8b..67ce28aed4 100644 --- a/content/docs/protocol/objectos/error-handling.mdx +++ b/content/docs/protocol/kernel/error-handling.mdx @@ -1047,12 +1047,12 @@ for (let i = 0; i < 1000000; i++) { icon={} title="HTTP API" description="Learn REST endpoint conventions and CRUD operations" - href="/docs/protocol/objectos/http-protocol" + href="/docs/protocol/kernel/http-protocol" /> } title="Real-Time Protocols" description="Implement WebSocket subscriptions and event streaming" - href="/docs/protocol/objectos/realtime-protocol" + href="/docs/protocol/kernel/realtime-protocol" /> diff --git a/content/docs/protocol/objectos/http-protocol.mdx b/content/docs/protocol/kernel/http-protocol.mdx similarity index 99% rename from content/docs/protocol/objectos/http-protocol.mdx rename to content/docs/protocol/kernel/http-protocol.mdx index d687977e12..261e2ca919 100644 --- a/content/docs/protocol/objectos/http-protocol.mdx +++ b/content/docs/protocol/kernel/http-protocol.mdx @@ -860,7 +860,7 @@ X-RateLimit-Reset: 1705324800 } ``` -See [Error Handling](/docs/protocol/objectos/error-handling) for more details. +See [Error Handling](/docs/protocol/kernel/error-handling) for more details. ## Best Practices @@ -923,12 +923,12 @@ if (!response.ok) { icon={} title="Real-Time Protocols" description="Learn WebSocket subscriptions and event streaming" - href="/docs/protocol/objectos/realtime-protocol" + href="/docs/protocol/kernel/realtime-protocol" /> } title="Error Handling" description="Master error codes and debugging strategies" - href="/docs/protocol/objectos/error-handling" + href="/docs/protocol/kernel/error-handling" /> diff --git a/content/docs/protocol/objectos/i18n-standard.mdx b/content/docs/protocol/kernel/i18n-standard.mdx similarity index 100% rename from content/docs/protocol/objectos/i18n-standard.mdx rename to content/docs/protocol/kernel/i18n-standard.mdx diff --git a/content/docs/protocol/objectos/index.mdx b/content/docs/protocol/kernel/index.mdx similarity index 98% rename from content/docs/protocol/objectos/index.mdx rename to content/docs/protocol/kernel/index.mdx index 3fed08c10f..58cc855045 100644 --- a/content/docs/protocol/objectos/index.mdx +++ b/content/docs/protocol/kernel/index.mdx @@ -85,25 +85,25 @@ Traditional enterprise platforms tightly couple infrastructure concerns with bus } title="Lifecycle Management" - href="/docs/protocol/objectos/lifecycle" + href="/docs/protocol/kernel/lifecycle" description="Boot sequence, plugin installation, zero-downtime upgrades, rollback strategies" /> } title="Plugin Specification" - href="/docs/protocol/objectos/plugin-spec" + href="/docs/protocol/kernel/plugin-spec" description="Manifest structure, dependency graph, versioning semantics, distribution format" /> } title="Configuration Resolution" - href="/docs/protocol/objectos/config-resolution" + href="/docs/protocol/kernel/config-resolution" description="Merge strategies, precedence rules, environment overrides, tenant isolation" /> } title="i18n Standard" - href="/docs/protocol/objectos/i18n-standard" + href="/docs/protocol/kernel/i18n-standard" description="Translation bundles, locale resolution, date/number formatting, dynamic loading" /> @@ -491,25 +491,25 @@ const message = context.i18n.t('slack.button.send'); } title="Learn Lifecycle Management" - href="/docs/protocol/objectos/lifecycle" + href="/docs/protocol/kernel/lifecycle" description="Understand boot sequence, installation, upgrade strategies, and rollback procedures" /> } title="Build Your First Plugin" - href="/docs/protocol/objectos/plugin-spec" + href="/docs/protocol/kernel/plugin-spec" description="Create a plugin manifest, define dependencies, and implement lifecycle hooks" /> } title="Master Configuration" - href="/docs/protocol/objectos/config-resolution" + href="/docs/protocol/kernel/config-resolution" description="Learn merge strategies, environment overrides, and tenant-specific settings" /> } title="Internationalize Your App" - href="/docs/protocol/objectos/i18n-standard" + href="/docs/protocol/kernel/i18n-standard" description="Add multi-language support with translation bundles and locale resolution" /> diff --git a/content/docs/protocol/objectos/lifecycle.mdx b/content/docs/protocol/kernel/lifecycle.mdx similarity index 99% rename from content/docs/protocol/objectos/lifecycle.mdx rename to content/docs/protocol/kernel/lifecycle.mdx index f121723244..db78d364f1 100644 --- a/content/docs/protocol/objectos/lifecycle.mdx +++ b/content/docs/protocol/kernel/lifecycle.mdx @@ -792,4 +792,4 @@ ObjectStack lifecycle management provides: - **Automatic Rollback:** Failed upgrades auto-revert to previous version - **Health Monitoring:** Built-in health checks validate system state -**Next:** Learn how to define plugin manifests in [Plugin Specification](/docs/protocol/objectos/plugin-spec). +**Next:** Learn how to define plugin manifests in [Plugin Specification](/docs/protocol/kernel/plugin-spec). diff --git a/content/docs/protocol/objectos/meta.json b/content/docs/protocol/kernel/meta.json similarity index 100% rename from content/docs/protocol/objectos/meta.json rename to content/docs/protocol/kernel/meta.json diff --git a/content/docs/protocol/objectos/metadata-service.mdx b/content/docs/protocol/kernel/metadata-service.mdx similarity index 100% rename from content/docs/protocol/objectos/metadata-service.mdx rename to content/docs/protocol/kernel/metadata-service.mdx diff --git a/content/docs/protocol/objectos/plugin-spec.mdx b/content/docs/protocol/kernel/plugin-spec.mdx similarity index 99% rename from content/docs/protocol/objectos/plugin-spec.mdx rename to content/docs/protocol/kernel/plugin-spec.mdx index b212414051..a697905197 100644 --- a/content/docs/protocol/objectos/plugin-spec.mdx +++ b/content/docs/protocol/kernel/plugin-spec.mdx @@ -952,4 +952,4 @@ Plugin packages in ObjectStack: - **Lifecycle-aware:** Hooks for install, upgrade, boot, and uninstall - **NPM-compatible:** Distribute via NPM or `.osplugin` archives -**Next:** Learn how configuration is resolved in [Configuration Resolution](/docs/protocol/objectos/config-resolution). +**Next:** Learn how configuration is resolved in [Configuration Resolution](/docs/protocol/kernel/config-resolution). diff --git a/content/docs/protocol/objectos/realtime-protocol.mdx b/content/docs/protocol/kernel/realtime-protocol.mdx similarity index 99% rename from content/docs/protocol/objectos/realtime-protocol.mdx rename to content/docs/protocol/kernel/realtime-protocol.mdx index 1de66e9423..1b9d3d6563 100644 --- a/content/docs/protocol/objectos/realtime-protocol.mdx +++ b/content/docs/protocol/kernel/realtime-protocol.mdx @@ -1026,12 +1026,12 @@ WebSocket messages are rate-limited: icon={} title="HTTP Protocol" description="Learn REST endpoint conventions and CRUD operations" - href="/docs/protocol/objectos/http-protocol" + href="/docs/protocol/kernel/http-protocol" /> } title="Error Handling" description="Master error codes and debugging strategies" - href="/docs/protocol/objectos/error-handling" + href="/docs/protocol/kernel/error-handling" /> diff --git a/content/docs/protocol/objectos/runtime-capabilities.mdx b/content/docs/protocol/kernel/runtime-capabilities.mdx similarity index 99% rename from content/docs/protocol/objectos/runtime-capabilities.mdx rename to content/docs/protocol/kernel/runtime-capabilities.mdx index 6777873b03..f6b577d1c6 100644 --- a/content/docs/protocol/objectos/runtime-capabilities.mdx +++ b/content/docs/protocol/kernel/runtime-capabilities.mdx @@ -529,6 +529,6 @@ export function SemanticSearch() { /* ... */ } - [ObjectQL Reference](/docs/protocol/objectql) - [ObjectUI Reference](/docs/protocol/objectui) -- [ObjectStack Reference](/docs/protocol/objectos) +- [ObjectStack Reference](/docs/protocol/kernel) - [API Discovery](/docs/references/api/discovery) - [Driver Capabilities](/docs/references/data/driver) diff --git a/content/docs/protocol/meta.json b/content/docs/protocol/meta.json index ed07439481..feaa9ac495 100644 --- a/content/docs/protocol/meta.json +++ b/content/docs/protocol/meta.json @@ -6,7 +6,7 @@ "diagram", "objectql", "objectui", - "objectos", + "kernel", "knowledge", "backward-compatibility" ] diff --git a/content/docs/protocol/objectui/index.mdx b/content/docs/protocol/objectui/index.mdx index 946bb1f3e2..265e842ed7 100644 --- a/content/docs/protocol/objectui/index.mdx +++ b/content/docs/protocol/objectui/index.mdx @@ -566,5 +566,5 @@ Using ObjectUI to build applications? ### Related Protocols - **[ObjectQL (Data Protocol)](/docs/protocol/objectql)** - Define objects and queries -- **[ObjectOS (System Protocol)](/docs/protocol/objectos)** - Runtime configuration +- **[ObjectOS (System Protocol)](/docs/protocol/kernel)** - Runtime configuration - **[UI Reference](/docs/references/ui)** - Complete API reference diff --git a/content/docs/references/data/object.mdx b/content/docs/references/data/object.mdx index fe02ea184b..cb52626262 100644 --- a/content/docs/references/data/object.mdx +++ b/content/docs/references/data/object.mdx @@ -14,8 +14,8 @@ API Operations Enum ## TypeScript Usage ```typescript -import { ApiMethod, Index, ObjectAccessConfig, ObjectCapabilities, ObjectExternalBinding, ObjectFieldGroup, ObjectOwnershipEnum, ObjectRequiredPermissions, PerOperationRequiredPermissions, SoftDeleteConfig, TenancyConfig, VersioningConfig } from '@objectstack/spec/data'; -import type { ApiMethod, Index, ObjectAccessConfig, ObjectCapabilities, ObjectExternalBinding, ObjectFieldGroup, ObjectOwnershipEnum, ObjectRequiredPermissions, PerOperationRequiredPermissions, SoftDeleteConfig, TenancyConfig, VersioningConfig } from '@objectstack/spec/data'; +import { ApiMethod, Index, Lifecycle, LifecycleClass, ObjectAccessConfig, ObjectCapabilities, ObjectExternalBinding, ObjectFieldGroup, ObjectOwnershipEnum, ObjectRequiredPermissions, PerOperationRequiredPermissions, SoftDeleteConfig, TenancyConfig, VersioningConfig } from '@objectstack/spec/data'; +import type { ApiMethod, Index, Lifecycle, LifecycleClass, ObjectAccessConfig, ObjectCapabilities, ObjectExternalBinding, ObjectFieldGroup, ObjectOwnershipEnum, ObjectRequiredPermissions, PerOperationRequiredPermissions, SoftDeleteConfig, TenancyConfig, VersioningConfig } from '@objectstack/spec/data'; // Validate data const result = ApiMethod.parse(data); @@ -58,6 +58,35 @@ const result = ApiMethod.parse(data); | **partial** | `string` | optional | Partial index condition (SQL WHERE clause for conditional indexes) | +--- + +## Lifecycle + +### Properties + +| Property | Type | Required | Description | +| :--- | :--- | :--- | :--- | +| **class** | `Enum<'record' \| 'audit' \| 'telemetry' \| 'transient' \| 'event'>` | ✅ | Persistence contract: record (business truth, permanent) | audit (compliance ledger) | telemetry (high-freq log) | transient (ephemeral state) | event (bus messages). | +| **retention** | `Object` | optional | Age-based retention window enforced by the LifecycleService Reaper. | +| **ttl** | `Object` | optional | Per-row TTL auto-expiry (transient/event classes). | +| **storage** | `Object` | optional | Physical storage strategy for high-frequency telemetry (LifecycleService Rotator). | +| **archive** | `Object` | optional | Cold-store archival (LifecycleService Archiver) — audit-class hot→cold hand-off. | +| **reclaim** | `boolean` | optional | Run driver space reclamation (SQLite incremental_vacuum) after sweeping this object. Default true for non-record classes. | + + +--- + +## LifecycleClass + +### Allowed Values + +* `record` +* `audit` +* `telemetry` +* `transient` +* `event` + + --- ## ObjectAccessConfig diff --git a/content/docs/references/identity/position.mdx b/content/docs/references/identity/position.mdx index e25def0720..71bc6d0190 100644 --- a/content/docs/references/identity/position.mdx +++ b/content/docs/references/identity/position.mdx @@ -84,6 +84,7 @@ const result = Position.parse(data); | **name** | `string` | ✅ | Unique position name (lowercase snake_case) | | **label** | `string` | ✅ | Display label (e.g. VP of Sales) | | **description** | `string` | optional | | +| **delegatable** | `boolean` | ✅ | ADR-0091 D3: holders may self-service delegate this position, time-boxed (default false). | --- diff --git a/content/docs/references/kernel/execution-context.mdx b/content/docs/references/kernel/execution-context.mdx index e30cf50ad8..62901fe4d0 100644 --- a/content/docs/references/kernel/execution-context.mdx +++ b/content/docs/references/kernel/execution-context.mdx @@ -57,6 +57,7 @@ const result = ExecutionContext.parse(data); | **positions** | `string[]` | ✅ | | | **principalKind** | `Enum<'human' \| 'agent' \| 'service' \| 'guest' \| 'system'>` | optional | | | **audience** | `Enum<'internal' \| 'external'>` | optional | | +| **posture** | `Enum<'PLATFORM_ADMIN' \| 'TENANT_ADMIN' \| 'MEMBER' \| 'EXTERNAL'>` | optional | ADR-0095 D2 posture rung — PLATFORM_ADMIN crosses the tenant wall where object posture permits; TENANT_ADMIN sees all rows in the org; MEMBER gets business RLS; EXTERNAL sees only explicitly shared rows. | | **onBehalfOf** | `Object` | optional | | | **permissions** | `string[]` | ✅ | | | **systemPermissions** | `string[]` | optional | | @@ -65,6 +66,7 @@ const result = ExecutionContext.parse(data); | **rlsMembership** | `Record` | optional | | | **isSystem** | `boolean` | ✅ | | | **skipTriggers** | `boolean` | optional | | +| **skipAutomations** | `boolean` | optional | | | **oauthScopes** | `string[]` | optional | | | **accessToken** | `string` | optional | | | **transaction** | `any` | optional | | diff --git a/content/docs/references/security/explain.mdx b/content/docs/references/security/explain.mdx index 966c550f19..c9a15c196f 100644 --- a/content/docs/references/security/explain.mdx +++ b/content/docs/references/security/explain.mdx @@ -23,9 +23,31 @@ enforcement, minus the throw. Layer order mirrors the runtime pipeline: -principal → required_permissions → object_crud → fls → owd_baseline → +tenant_isolation → principal → required_permissions → object_crud → fls → -depth → sharing → vama_bypass → rls. +owd_baseline → depth → sharing → vama_bypass → rls. + +[C2 / ADR-0095] Record-grained explanation. The contract carries an optional + +`recordId` on the request and, when present, a per-layer `record` attribution + +plus a top-level `record` verdict on the response — so the sharing / rls / owd + +layers can report the ROW-LEVEL story for one concrete record (which share + +admitted it, which filter excluded it, whether the effective row filter + +matches). Object-level requests (no `recordId`) stay byte-compatible. + +[ADR-0095 D1/D2] The contract also reserves the kernel-chain vocabulary the + +β engine + UI will fill: the always-first tenant wall as `tenant_isolation` + +(Layer 0), a per-layer `kernelTier` marking Layer 0 vs. business RLS + +(Layer 1), and the monotonic posture ladder + +(PLATFORM_ADMIN > TENANT_ADMIN > MEMBER > EXTERNAL) on the resolved principal. **Source:** `packages/spec/src/security/explain.zod.ts` @@ -34,8 +56,8 @@ depth → sharing → vama_bypass → rls. ## TypeScript Usage ```typescript -import { AccessMatrix, AccessMatrixEntry, ExplainDecision, ExplainLayer, ExplainOperation, ExplainRequest } from '@objectstack/spec/security'; -import type { AccessMatrix, AccessMatrixEntry, ExplainDecision, ExplainLayer, ExplainOperation, ExplainRequest } from '@objectstack/spec/security'; +import { AccessMatrix, AccessMatrixEntry, AuthzPosture, ExplainDecision, ExplainLayer, ExplainMatchedRule, ExplainOperation, ExplainRecordAttribution, ExplainRequest } from '@objectstack/spec/security'; +import type { AccessMatrix, AccessMatrixEntry, AuthzPosture, ExplainDecision, ExplainLayer, ExplainMatchedRule, ExplainOperation, ExplainRecordAttribution, ExplainRequest } from '@objectstack/spec/security'; // Validate data const result = AccessMatrix.parse(data); @@ -74,6 +96,20 @@ const result = AccessMatrix.parse(data); | **sharingModel** | `string` | optional | | +--- + +## AuthzPosture + +ADR-0095 D2 posture rung — PLATFORM_ADMIN crosses the tenant wall where object posture permits; TENANT_ADMIN sees all rows in the org; MEMBER gets business RLS; EXTERNAL sees only explicitly shared rows. + +### Allowed Values + +* `PLATFORM_ADMIN` +* `TENANT_ADMIN` +* `MEMBER` +* `EXTERNAL` + + --- ## ExplainDecision @@ -88,6 +124,7 @@ const result = AccessMatrix.parse(data); | **principal** | `Object` | ✅ | | | **layers** | `Object[]` | ✅ | | | **readFilter** | `any` | optional | | +| **record** | `Object` | optional | Row-level verdict for the specific record; set only for record-grained requests. | --- @@ -98,10 +135,28 @@ const result = AccessMatrix.parse(data); | Property | Type | Required | Description | | :--- | :--- | :--- | :--- | -| **layer** | `Enum<'principal' \| 'required_permissions' \| 'object_crud' \| 'fls' \| 'owd_baseline' \| 'depth' \| 'sharing' \| 'vama_bypass' \| 'rls'>` | ✅ | | +| **layer** | `Enum<'tenant_isolation' \| 'principal' \| 'required_permissions' \| 'object_crud' \| 'fls' \| 'owd_baseline' \| 'depth' \| 'sharing' \| 'vama_bypass' \| 'rls'>` | ✅ | | +| **kernelTier** | `Enum<'layer_0_tenant' \| 'layer_1_business'>` | optional | ADR-0095 kernel layer: layer_0_tenant = the always-first org wall; layer_1_business = business RLS/sharing/ownership. | | **verdict** | `Enum<'grants' \| 'denies' \| 'narrows' \| 'widens' \| 'neutral' \| 'not_applicable'>` | ✅ | | | **detail** | `string` | ✅ | | | **contributors** | `Object[]` | ✅ | | +| **record** | `Object` | optional | Row-level determination for the specific record under explanation; set only for record-grained requests. | + + +--- + +## ExplainMatchedRule + +### Properties + +| Property | Type | Required | Description | +| :--- | :--- | :--- | :--- | +| **kind** | `Enum<'tenant_filter' \| 'owd_baseline' \| 'ownership' \| 'record_share' \| 'sharing_rule' \| 'team' \| 'territory' \| 'rls_policy'>` | ✅ | The row-visibility source kind evaluated for this record at this layer. | +| **name** | `string` | ✅ | Stable identifier of the concrete rule, share, or policy that was evaluated. | +| **grants** | `Enum<'read' \| 'edit' \| 'full'>` | optional | Access level a sharing source grants on the record (mirrors SharingLevel). | +| **via** | `string` | optional | How the rule reached the principal — recipient group/position, ownership, or the matching criteria. | +| **predicate** | `any` | optional | The row predicate this rule contributed, when it is filter-shaped (null = unrestricted). | +| **effect** | `Enum<'admits' \| 'excludes' \| 'neutral'>` | ✅ | The rule's effect on THIS record: admits, excludes, or neutral. | --- @@ -119,6 +174,21 @@ const result = AccessMatrix.parse(data); * `purge` +--- + +## ExplainRecordAttribution + +### Properties + +| Property | Type | Required | Description | +| :--- | :--- | :--- | :--- | +| **outcome** | `Enum<'admitted' \| 'excluded' \| 'not_evaluated'>` | ✅ | This layer's row-level outcome for the record: admitted, excluded, or not_evaluated (skipped/not row-scoped). | +| **rowFilter** | `any` | optional | The effective row predicate this layer contributed for the record set (null = unrestricted, __deny_all__ = zero rows). | +| **matchesRecord** | `boolean` | optional | Whether the specific record satisfies rowFilter — the judgement behind outcome. | +| **rules** | `Object[]` | ✅ | Concrete rules, shares, or policies this layer evaluated against the record, in evaluation order. | +| **detail** | `string` | optional | Human-readable, record-specific explanation of this layer's outcome. | + + --- ## ExplainRequest @@ -129,6 +199,7 @@ const result = AccessMatrix.parse(data); | :--- | :--- | :--- | :--- | | **object** | `string` | ✅ | | | **operation** | `Enum<'read' \| 'create' \| 'update' \| 'delete' \| 'transfer' \| 'restore' \| 'purge'>` | ✅ | | +| **recordId** | `string` | optional | Optional id of one concrete record to explain at row granularity; omitted = object-level (pre-C2) request. | | **userId** | `string` | optional | | diff --git a/content/docs/references/security/meta.json b/content/docs/references/security/meta.json index 9d9dcff0cd..c644a9963b 100644 --- a/content/docs/references/security/meta.json +++ b/content/docs/references/security/meta.json @@ -2,6 +2,7 @@ "title": "Security Protocol", "pages": [ "explain", + "misc", "permission", "rls", "sharing", diff --git a/content/docs/references/security/misc.mdx b/content/docs/references/security/misc.mdx new file mode 100644 index 0000000000..b5f2e957ee --- /dev/null +++ b/content/docs/references/security/misc.mdx @@ -0,0 +1,38 @@ +--- +title: Misc +description: Misc protocol schemas +--- + +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} + + +**Source:** `packages/spec/src/security/misc.zod.ts` + + +## TypeScript Usage + +```typescript +import { CapabilityDeclaration } from '@objectstack/spec/security'; +import type { CapabilityDeclaration } from '@objectstack/spec/security'; + +// Validate data +const result = CapabilityDeclaration.parse(data); +``` + +--- + +## CapabilityDeclaration + +### Properties + +| Property | Type | Required | Description | +| :--- | :--- | :--- | :--- | +| **name** | `string` | ✅ | Stable capability key referenced by systemPermissions / requiredPermissions | +| **label** | `string` | optional | Human label shown in Setup | +| **description** | `string` | optional | What holding this capability permits | +| **scope** | `Enum<'platform' \| 'org'>` | ✅ | platform = a platform-wide power; org = scoped to an organization | +| **packageId** | `string` | optional | [ADR-0086 D3] Owning package id (author-declared fallback; absent = registry-stamped) | + + +--- + diff --git a/content/docs/references/ui/action.mdx b/content/docs/references/ui/action.mdx index 86d676c680..a4dc70fb65 100644 --- a/content/docs/references/ui/action.mdx +++ b/content/docs/references/ui/action.mdx @@ -48,8 +48,8 @@ to the field name and is used as the request-body key). ## TypeScript Usage ```typescript -import { ActionAi, ActionLocation, ActionParam, ActionType } from '@objectstack/spec/ui'; -import type { ActionAi, ActionLocation, ActionParam, ActionType } from '@objectstack/spec/ui'; +import { ActionAi, ActionLocation, ActionType } from '@objectstack/spec/ui'; +import type { ActionAi, ActionLocation, ActionType } from '@objectstack/spec/ui'; // Validate data const result = ActionAi.parse(data); @@ -86,27 +86,6 @@ const result = ActionAi.parse(data); * `global_nav` ---- - -## ActionParam - -### Properties - -| Property | Type | Required | Description | -| :--- | :--- | :--- | :--- | -| **name** | `string` | optional | | -| **field** | `string` | optional | Snake case identifier (lowercase with underscores only) | -| **objectOverride** | `string` | optional | Snake case identifier (lowercase with underscores only) | -| **label** | `string` | optional | Display label (plain string; i18n keys are auto-generated by the framework) | -| **type** | `Enum<'text' \| 'textarea' \| 'email' \| 'url' \| 'phone' \| 'password' \| 'secret' \| 'markdown' \| 'html' \| 'richtext' \| 'number' \| 'currency' \| 'percent' \| 'date' \| 'datetime' \| 'time' \| 'boolean' \| 'toggle' \| 'select' \| 'multiselect' \| 'radio' \| 'checkboxes' \| 'lookup' \| 'master_detail' \| 'tree' \| 'user' \| 'image' \| 'file' \| 'avatar' \| 'video' \| 'audio' \| 'formula' \| 'summary' \| 'autonumber' \| 'composite' \| 'repeater' \| 'record' \| 'location' \| 'address' \| 'code' \| 'json' \| 'color' \| 'rating' \| 'slider' \| 'signature' \| 'qrcode' \| 'progress' \| 'tags' \| 'vector'>` | optional | | -| **required** | `boolean` | ✅ | | -| **options** | `Object[]` | optional | | -| **placeholder** | `string` | optional | | -| **helpText** | `string` | optional | | -| **defaultValue** | `any` | optional | | -| **defaultFromRow** | `boolean` | optional | | - - --- ## ActionType diff --git a/packages/metadata/ROADMAP.md b/packages/metadata/ROADMAP.md index ce2690d455..8fa22297ec 100644 --- a/packages/metadata/ROADMAP.md +++ b/packages/metadata/ROADMAP.md @@ -233,5 +233,5 @@ artifact persistence (`artifacts/${projectId}/${commitId}.json`). - [Root ROADMAP](../../ROADMAP.md) — Full platform evolution (v3.0 → v5.0) - [Studio ROADMAP](../../apps/studio/ROADMAP.md) — Visual IDE development phases -- [Metadata Service Protocol](../../content/docs/protocol/objectos/metadata-service.mdx) — Detailed protocol documentation +- [Metadata Service Protocol](../../content/docs/protocol/kernel/metadata-service.mdx) — Detailed protocol documentation - [DX ROADMAP](../../docs/DX_ROADMAP.md) — Developer experience improvements diff --git a/packages/services/service-i18n/README.md b/packages/services/service-i18n/README.md index 898d2a0e11..22fadcfd01 100644 --- a/packages/services/service-i18n/README.md +++ b/packages/services/service-i18n/README.md @@ -372,4 +372,4 @@ Apache-2.0. See [LICENSING.md](../../../LICENSING.md). - [i18next Documentation](https://www.i18next.com/) - [@objectstack/spec/system (Translation schema)](../../spec/src/system/) -- [I18n Best Practices Guide](/content/docs/protocol/objectos/i18n-standard.mdx) +- [I18n Best Practices Guide](/content/docs/protocol/kernel/i18n-standard.mdx) diff --git a/packages/services/service-realtime/README.md b/packages/services/service-realtime/README.md index 827a6b2d49..4359795549 100644 --- a/packages/services/service-realtime/README.md +++ b/packages/services/service-realtime/README.md @@ -435,4 +435,4 @@ Apache-2.0. See [LICENSING.md](../../../LICENSING.md). - [WebSocket API Documentation](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API) - [@objectstack/client](../../client/) - [@objectstack/client-react](../../client-react/) -- [Realtime Features Guide](/content/docs/protocol/objectos/realtime-protocol.mdx) +- [Realtime Features Guide](/content/docs/protocol/kernel/realtime-protocol.mdx) diff --git a/scripts/role-word-baseline.json b/scripts/role-word-baseline.json index f8faf87fbc..ebcfd33018 100644 --- a/scripts/role-word-baseline.json +++ b/scripts/role-word-baseline.json @@ -29,9 +29,9 @@ "content/docs/plugins/anatomy.mdx": 7, "content/docs/plugins/packages.mdx": 2, "content/docs/protocol/diagram.mdx": 4, - "content/docs/protocol/objectos/error-handling.mdx": 1, - "content/docs/protocol/objectos/index.mdx": 1, - "content/docs/protocol/objectos/runtime-capabilities.mdx": 4, + "content/docs/protocol/kernel/error-handling.mdx": 1, + "content/docs/protocol/kernel/index.mdx": 1, + "content/docs/protocol/kernel/runtime-capabilities.mdx": 4, "content/docs/protocol/objectql/security.mdx": 1, "content/docs/protocol/objectui/record-alert.mdx": 1, "content/docs/protocol/objectui/widget-contract.mdx": 3,