From f7bc1236f762b08b51c80d2818331d072d47fcfb Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 4 Jul 2026 15:09:43 +0000 Subject: [PATCH 1/3] docs(site): restructure IA into module-first single sidebar Dissolve the six root tabs (Getting Started/Concepts/Guides/Reference/ Protocol/Releases) into one sidebar tree of 14 capability groups aligned with the Reference domains: Get Started, Core Concepts, Data Modeling, Automation, Permissions & Identity, UI Engine, API & SDK, AI, Plugins & Packages, Kernel & Services, Deployment & Operations, Protocol Spec, Reference, Releases. - move ~90 pages out of guides//concepts/ grab-bags into module groups - split 6 oversized multi-topic pages (security, data-modeling, ai-capabilities, business-logic, plugins, api-reference) along H2 boundaries; content moved verbatim and deduplicated - delete diverged duplicate pages (architecture fork, packages, concepts index); merge terminology into glossary - new landing page and five module overview pages - rewrite internal links (absolute + relative) to the new URL space - move internal-facing pages (airtable gap analysis, CRM standards) out of the site to docs/notes/ Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_018r9mjpF7jr9BKdzEmUE4uZ --- content/blog/protocol-first-development.mdx | 2 +- content/docs/ai/actions-as-tools.mdx | 236 +++++ content/docs/ai/agents.mdx | 239 +++++ .../chatbot-integration.mdx} | 2 +- content/docs/ai/index.mdx | 181 ++++ content/docs/ai/knowledge-rag.mdx | 69 ++ content/docs/ai/meta.json | 14 + content/docs/ai/natural-language-queries.mdx | 34 + .../skills.mdx => ai/skills-reference.mdx} | 10 +- content/docs/{concepts => ai}/skills.mdx | 10 +- content/docs/{guides => api}/client-sdk.mdx | 0 content/docs/api/data-api.mdx | 208 ++++ content/docs/{guides => api}/data-flow.mdx | 2 +- .../environment-routing.mdx} | 6 +- .../cheatsheets => api}/error-catalog.mdx | 2 +- .../{guides => api}/error-handling-client.mdx | 4 +- .../{guides => api}/error-handling-server.mdx | 0 content/docs/api/index.mdx | 184 ++++ content/docs/api/meta.json | 17 + content/docs/api/metadata-api.mdx | 98 ++ content/docs/api/plugin-endpoints.mdx | 113 +++ .../cheatsheets => api}/wire-format.mdx | 2 +- .../approvals.mdx} | 71 +- .../flow.mdx => automation/flows.mdx} | 144 ++- .../{guides => automation}/hook-bodies.mdx | 8 +- content/docs/automation/hooks.mdx | 115 +++ content/docs/automation/index.mdx | 35 + content/docs/automation/meta.json | 13 + .../webhooks.mdx} | 0 .../workflow.mdx => automation/workflows.mdx} | 0 content/docs/concepts/architecture.mdx | 104 +- content/docs/concepts/core/index.mdx | 56 -- content/docs/concepts/core/meta.json | 10 - content/docs/concepts/design-principles.mdx | 4 +- content/docs/concepts/index.mdx | 715 +++----------- content/docs/concepts/meta.json | 12 +- content/docs/concepts/metadata-driven.mdx | 2 +- content/docs/concepts/packages.mdx | 890 ------------------ content/docs/concepts/terminology.mdx | 161 ---- .../analytics.mdx} | 0 .../drivers.mdx} | 0 .../external-datasources.mdx | 4 +- .../field-type-decision-tree.mdx | 2 +- .../field-types.mdx} | 0 .../field.mdx => data-modeling/fields.mdx} | 6 +- .../formulas.mdx} | 146 ++- content/docs/data-modeling/index.mdx | 39 + content/docs/data-modeling/indexing.mdx | 45 + content/docs/data-modeling/meta.json | 22 + .../object.mdx => data-modeling/objects.mdx} | 10 +- .../queries.mdx} | 0 content/docs/data-modeling/relationships.mdx | 58 ++ .../schema-design.mdx} | 410 +------- .../{guides => data-modeling}/seed-data.mdx | 2 +- .../validation-rules.mdx} | 0 .../metadata => data-modeling}/validation.mdx | 45 +- .../cloud-artifact-api.mdx | 6 +- .../environment-variables.mdx | 2 +- .../index.mdx} | 6 +- content/docs/deployment/meta.json | 15 + .../migration-from-objectql.mdx} | 2 +- .../production-readiness.mdx | 0 .../publish-and-preview.mdx | 12 +- .../single-project-mode.mdx | 8 +- .../troubleshooting.mdx | 2 +- .../vercel.mdx} | 10 +- content/docs/getting-started/architecture.mdx | 643 ------------- content/docs/getting-started/cli.mdx | 2 +- .../common-patterns.mdx | 6 +- .../docs/getting-started/core-concepts.mdx | 191 ---- content/docs/getting-started/examples.mdx | 2 +- content/docs/getting-started/glossary.mdx | 28 +- content/docs/getting-started/index.mdx | 6 +- content/docs/getting-started/meta.json | 15 +- .../docs/getting-started/quick-reference.mdx | 317 +++++++ content/docs/getting-started/quick-start.mdx | 16 +- .../validating-metadata.mdx | 6 +- content/docs/guides/ai-capabilities.mdx | 712 -------------- content/docs/guides/api-reference.mdx | 540 ----------- content/docs/guides/business-logic.mdx | 675 ------------- content/docs/guides/cheatsheets/meta.json | 15 - .../guides/cheatsheets/quick-reference.mdx | 317 ------- content/docs/guides/index.mdx | 86 -- content/docs/guides/meta.json | 57 -- content/docs/guides/metadata/index.mdx | 127 --- content/docs/guides/metadata/meta.json | 17 - content/docs/guides/security.mdx | 777 --------------- content/docs/guides/solutions/index.mdx | 55 -- content/docs/guides/solutions/meta.json | 13 - content/docs/index.mdx | 62 +- .../core => kernel}/architecture.mdx | 0 .../cluster.mdx} | 0 .../contracts/auth-service.mdx | 0 .../contracts/cache-service.mdx | 0 .../contracts/data-engine.mdx | 0 .../{guides => kernel}/contracts/index.mdx | 0 .../{guides => kernel}/contracts/meta.json | 0 .../contracts/metadata-service.mdx | 0 .../contracts/storage-service.mdx | 0 .../docs/{concepts/core => kernel}/events.mdx | 0 content/docs/kernel/index.mdx | 34 + content/docs/kernel/meta.json | 14 + .../runtime-services/audit-service.mdx | 0 .../runtime-services/data-service.mdx | 0 .../runtime-services/email-service.mdx | 0 .../runtime-services/examples.mdx | 0 .../runtime-services/index.mdx | 0 .../runtime-services/meta.json | 0 .../runtime-services/queue-service.mdx | 0 .../runtime-services/settings-service.mdx | 0 .../runtime-services/sharing-service.mdx | 0 .../runtime-services/storage-service.mdx | 0 .../runtime-services/versioning.mdx | 0 .../services-checklist.mdx} | 0 .../{concepts/core => kernel}/services.mdx | 0 content/docs/meta.json | 12 +- .../access-recipes.mdx} | 4 +- .../authentication.mdx | 10 +- .../authorization.mdx | 0 .../docs/permissions/field-level-security.mdx | 93 ++ content/docs/permissions/index.mdx | 219 +++++ content/docs/permissions/meta.json | 18 + .../permission-metadata.mdx} | 6 +- content/docs/permissions/permission-sets.mdx | 132 +++ .../permissions-matrix.mdx | 0 content/docs/permissions/profiles.mdx | 198 ++++ content/docs/permissions/roles.mdx | 59 ++ content/docs/permissions/sharing-rules.mdx | 135 +++ .../auth-sso.mdx => permissions/sso.mdx} | 0 .../adding-a-metadata-type.mdx | 6 +- .../core/plugins.mdx => plugins/anatomy.mdx} | 93 +- .../development.mdx} | 6 +- .../{guides/plugins.mdx => plugins/index.mdx} | 181 +--- content/docs/plugins/meta.json | 11 + content/docs/{guides => plugins}/packages.mdx | 4 +- .../backward-compatibility.mdx | 0 .../diagram.mdx} | 0 content/docs/protocol/meta.json | 13 +- content/docs/protocol/objectql/index.mdx | 4 +- .../docs/protocol/objectql/state-machine.mdx | 2 +- content/docs/protocol/objectui/actions.mdx | 2 +- .../docs/protocol/objectui/record-alert.mdx | 6 +- .../protocol/objectui/widget-contract.mdx | 2 +- content/docs/references/ai/agent.mdx | 2 +- content/docs/references/ai/conversation.mdx | 2 +- content/docs/references/ai/embedding.mdx | 2 +- .../docs/references/ai/knowledge-document.mdx | 2 +- .../docs/references/ai/knowledge-source.mdx | 2 +- content/docs/references/ai/mcp.mdx | 2 +- content/docs/references/ai/model-registry.mdx | 2 +- content/docs/references/ai/skill.mdx | 2 +- .../docs/references/ai/solution-blueprint.mdx | 9 +- content/docs/references/ai/tool.mdx | 2 +- content/docs/references/ai/usage.mdx | 2 +- content/docs/references/api/analytics.mdx | 2 +- .../docs/references/api/auth-endpoints.mdx | 2 +- content/docs/references/api/auth.mdx | 2 +- .../docs/references/api/automation-api.mdx | 2 +- content/docs/references/api/batch.mdx | 2 +- content/docs/references/api/connector.mdx | 2 +- content/docs/references/api/contract.mdx | 2 +- content/docs/references/api/core-services.mdx | 2 +- content/docs/references/api/discovery.mdx | 2 +- content/docs/references/api/dispatcher.mdx | 2 +- content/docs/references/api/documentation.mdx | 2 +- content/docs/references/api/endpoint.mdx | 2 +- content/docs/references/api/errors.mdx | 2 +- content/docs/references/api/events.mdx | 2 +- content/docs/references/api/export.mdx | 273 +++++- content/docs/references/api/feed-api.mdx | 2 +- content/docs/references/api/graphql.mdx | 2 +- content/docs/references/api/http-cache.mdx | 2 +- content/docs/references/api/http.mdx | 2 +- content/docs/references/api/identity.mdx | 2 +- .../docs/references/api/metadata-plugin.mdx | 2 +- content/docs/references/api/metadata.mdx | 2 +- content/docs/references/api/notification.mdx | 2 +- content/docs/references/api/object.mdx | 2 +- content/docs/references/api/odata.mdx | 2 +- content/docs/references/api/package-api.mdx | 2 +- .../docs/references/api/package-registry.mdx | 2 +- .../docs/references/api/plugin-rest-api.mdx | 2 +- content/docs/references/api/protocol.mdx | 2 +- content/docs/references/api/query-adapter.mdx | 2 +- .../docs/references/api/realtime-shared.mdx | 2 +- content/docs/references/api/realtime.mdx | 2 +- content/docs/references/api/registry.mdx | 2 +- content/docs/references/api/rest-server.mdx | 2 +- content/docs/references/api/router.mdx | 2 +- content/docs/references/api/storage.mdx | 2 +- content/docs/references/api/versioning.mdx | 2 +- content/docs/references/api/websocket.mdx | 2 +- .../docs/references/automation/approval.mdx | 2 +- .../references/automation/bpmn-interop.mdx | 2 +- .../docs/references/automation/connector.mdx | 2 +- content/docs/references/automation/etl.mdx | 2 +- .../docs/references/automation/execution.mdx | 2 +- content/docs/references/automation/flow.mdx | 2 +- content/docs/references/automation/job.mdx | 2 +- .../references/automation/node-executor.mdx | 2 +- .../docs/references/automation/offline.mdx | 2 +- .../references/automation/state-machine.mdx | 2 +- content/docs/references/automation/sync.mdx | 2 +- .../automation/trigger-registry.mdx | 2 +- .../docs/references/automation/webhook.mdx | 2 +- content/docs/references/cloud/app-store.mdx | 2 +- .../references/cloud/developer-portal.mdx | 2 +- .../references/cloud/environment-artifact.mdx | 2 +- .../references/cloud/environment-package.mdx | 2 +- content/docs/references/cloud/environment.mdx | 2 +- .../references/cloud/marketplace-admin.mdx | 2 +- content/docs/references/cloud/marketplace.mdx | 2 +- .../docs/references/cloud/package-version.mdx | 2 +- content/docs/references/cloud/package.mdx | 2 +- .../docs/references/cloud/plugin-security.mdx | 2 +- .../docs/references/cloud/provisioning.mdx | 2 +- .../references/cloud/template-manifest.mdx | 2 +- content/docs/references/cloud/tenant.mdx | 2 +- content/docs/references/data/analytics.mdx | 2 +- content/docs/references/data/data-engine.mdx | 2 +- content/docs/references/data/datasource.mdx | 2 +- content/docs/references/data/date-macros.mdx | 2 +- content/docs/references/data/document.mdx | 2 +- content/docs/references/data/driver-nosql.mdx | 2 +- content/docs/references/data/driver-sql.mdx | 2 +- content/docs/references/data/driver.mdx | 2 +- .../docs/references/data/external-catalog.mdx | 2 +- .../docs/references/data/external-lookup.mdx | 2 +- content/docs/references/data/feed.mdx | 2 +- content/docs/references/data/field.mdx | 2 +- content/docs/references/data/filter.mdx | 2 +- content/docs/references/data/hook-body.mdx | 2 +- content/docs/references/data/hook.mdx | 2 +- content/docs/references/data/mapping.mdx | 2 +- content/docs/references/data/notification.mdx | 2 +- content/docs/references/data/object.mdx | 34 +- content/docs/references/data/query.mdx | 2 +- .../docs/references/data/search-engine.mdx | 2 +- content/docs/references/data/seed-loader.mdx | 2 +- content/docs/references/data/seed.mdx | 2 +- content/docs/references/data/subscription.mdx | 2 +- content/docs/references/data/validation.mdx | 2 +- .../docs/references/identity/eval-user.mdx | 2 +- content/docs/references/identity/identity.mdx | 2 +- .../docs/references/identity/organization.mdx | 2 +- content/docs/references/identity/role.mdx | 2 +- content/docs/references/identity/scim.mdx | 2 +- .../docs/references/integration/connector.mdx | 2 +- content/docs/references/integration/http.mdx | 2 +- .../references/integration/message-queue.mdx | 2 +- content/docs/references/integration/misc.mdx | 2 +- .../references/integration/object-storage.mdx | 2 +- .../docs/references/integration/offline.mdx | 2 +- .../docs/references/integration/tenant.mdx | 2 +- .../references/integration/translation.mdx | 2 +- .../docs/references/kernel/cli-extension.mdx | 2 +- content/docs/references/kernel/cluster.mdx | 4 +- content/docs/references/kernel/context.mdx | 2 +- .../kernel/dependency-resolution.mdx | 2 +- content/docs/references/kernel/dev-plugin.mdx | 2 +- .../references/kernel/execution-context.mdx | 2 +- content/docs/references/kernel/feature.mdx | 2 +- content/docs/references/kernel/manifest.mdx | 2 +- .../kernel/metadata-customization.mdx | 2 +- .../references/kernel/metadata-loader.mdx | 2 +- .../kernel/metadata-persistence.mdx | 2 +- .../references/kernel/metadata-plugin.mdx | 2 +- .../references/kernel/metadata-protection.mdx | 2 +- content/docs/references/kernel/misc.mdx | 2 +- .../references/kernel/package-artifact.mdx | 2 +- .../references/kernel/package-registry.mdx | 2 +- .../references/kernel/package-upgrade.mdx | 2 +- .../references/kernel/plugin-capability.mdx | 2 +- .../kernel/plugin-lifecycle-advanced.mdx | 2 +- .../kernel/plugin-lifecycle-events.mdx | 2 +- .../docs/references/kernel/plugin-loading.mdx | 2 +- .../references/kernel/plugin-registry.mdx | 2 +- .../docs/references/kernel/plugin-runtime.mdx | 2 +- .../kernel/plugin-security-advanced.mdx | 2 +- .../references/kernel/plugin-security.mdx | 2 +- .../references/kernel/plugin-structure.mdx | 2 +- .../references/kernel/plugin-validator.mdx | 2 +- .../references/kernel/plugin-versioning.mdx | 2 +- content/docs/references/kernel/plugin.mdx | 2 +- .../references/kernel/service-registry.mdx | 2 +- .../kernel/startup-orchestrator.mdx | 2 +- .../docs/references/kernel/state-machine.mdx | 2 +- content/docs/references/meta.json | 1 - content/docs/references/qa/testing.mdx | 2 +- .../docs/references/security/permission.mdx | 4 +- content/docs/references/security/rls.mdx | 2 +- content/docs/references/security/sharing.mdx | 2 +- .../docs/references/security/territory.mdx | 2 +- .../docs/references/shared/branded-types.mdx | 2 +- content/docs/references/shared/enums.mdx | 2 +- content/docs/references/shared/expression.mdx | 2 +- content/docs/references/shared/http.mdx | 2 +- .../docs/references/shared/identifiers.mdx | 2 +- .../shared/metadata-persistence.mdx | 2 +- .../docs/references/shared/metadata-types.mdx | 2 +- content/docs/references/shared/protection.mdx | 2 +- content/docs/references/studio/action.mdx | 2 +- .../docs/references/studio/flow-builder.mdx | 2 +- .../references/studio/object-designer.mdx | 2 +- content/docs/references/studio/plugin.mdx | 2 +- .../docs/references/system/app-install.mdx | 2 +- content/docs/references/system/audit.mdx | 2 +- .../docs/references/system/auth-config.mdx | 2 +- content/docs/references/system/book.mdx | 2 +- content/docs/references/system/cache.mdx | 2 +- .../references/system/change-management.mdx | 2 +- .../docs/references/system/collaboration.mdx | 2 +- content/docs/references/system/compliance.mdx | 2 +- .../docs/references/system/core-services.mdx | 2 +- .../docs/references/system/deploy-bundle.mdx | 2 +- .../references/system/disaster-recovery.mdx | 2 +- content/docs/references/system/doc.mdx | 2 +- .../docs/references/system/email-config.mdx | 2 +- .../docs/references/system/email-template.mdx | 2 +- content/docs/references/system/encryption.mdx | 2 +- .../system/environment-artifact.mdx | 2 +- .../docs/references/system/http-server.mdx | 2 +- .../references/system/incident-response.mdx | 2 +- content/docs/references/system/job.mdx | 2 +- content/docs/references/system/license.mdx | 2 +- content/docs/references/system/logging.mdx | 2 +- content/docs/references/system/masking.mdx | 2 +- .../docs/references/system/message-queue.mdx | 2 +- .../references/system/metadata-loader.mdx | 2 +- .../system/metadata-persistence.mdx | 2 +- content/docs/references/system/metrics.mdx | 2 +- content/docs/references/system/migration.mdx | 2 +- .../docs/references/system/notification.mdx | 2 +- .../docs/references/system/object-storage.mdx | 2 +- .../docs/references/system/provisioning.mdx | 2 +- .../references/system/registry-config.mdx | 2 +- .../docs/references/system/search-engine.mdx | 2 +- .../references/system/security-context.mdx | 2 +- .../references/system/settings-client.mdx | 2 +- .../references/system/settings-manifest.mdx | 2 +- .../references/system/supplier-security.mdx | 2 +- content/docs/references/system/tenant.mdx | 2 +- content/docs/references/system/tracing.mdx | 2 +- content/docs/references/system/training.mdx | 2 +- .../docs/references/system/translation.mdx | 2 +- content/docs/references/system/worker.mdx | 2 +- content/docs/references/ui/action.mdx | 2 +- content/docs/references/ui/animation.mdx | 2 +- content/docs/references/ui/app.mdx | 2 +- content/docs/references/ui/chart.mdx | 2 +- content/docs/references/ui/component.mdx | 4 +- content/docs/references/ui/dashboard.mdx | 2 +- content/docs/references/ui/dataset.mdx | 2 +- content/docs/references/ui/dnd.mdx | 2 +- content/docs/references/ui/http.mdx | 2 +- content/docs/references/ui/i18n.mdx | 2 +- content/docs/references/ui/keyboard.mdx | 2 +- content/docs/references/ui/notification.mdx | 2 +- content/docs/references/ui/offline.mdx | 2 +- content/docs/references/ui/page.mdx | 2 +- content/docs/references/ui/portal.mdx | 2 +- content/docs/references/ui/report.mdx | 2 +- content/docs/references/ui/responsive.mdx | 2 +- content/docs/references/ui/sharing.mdx | 2 +- content/docs/references/ui/theme.mdx | 2 +- content/docs/references/ui/touch.mdx | 2 +- content/docs/references/ui/view.mdx | 3 +- content/docs/references/ui/widget.mdx | 2 +- .../implementation-status.mdx | 2 +- content/docs/releases/meta.json | 3 +- content/docs/releases/v9.mdx | 8 +- .../{guides/metadata/app.mdx => ui/apps.mdx} | 8 +- .../solutions => ui}/create-vs-edit-form.mdx | 2 +- .../dashboard.mdx => ui/dashboards.mdx} | 6 +- .../metadata/doc.mdx => ui/doc-pages.mdx} | 0 .../field-grouping-and-order.mdx | 4 +- .../{guides/public-forms.mdx => ui/forms.mdx} | 4 +- content/docs/ui/index.mdx | 43 + content/docs/ui/meta.json | 19 + .../metadata/page.mdx => ui/pages.mdx} | 6 +- .../public-data-collection.mdx | 2 +- .../role-based-interfaces.mdx | 6 +- content/docs/{concepts => ui}/setup-app.mdx | 6 +- .../metadata/view.mdx => ui/views.mdx} | 8 +- .../notes}/airtable-dashboard-analysis.mdx | 2 +- .../notes/crm-development-standards.mdx | 0 386 files changed, 4469 insertions(+), 7000 deletions(-) create mode 100644 content/docs/ai/actions-as-tools.mdx create mode 100644 content/docs/ai/agents.mdx rename content/docs/{guides/plugin-chatbot-integration.mdx => ai/chatbot-integration.mdx} (98%) create mode 100644 content/docs/ai/index.mdx create mode 100644 content/docs/ai/knowledge-rag.mdx create mode 100644 content/docs/ai/meta.json create mode 100644 content/docs/ai/natural-language-queries.mdx rename content/docs/{guides/skills.mdx => ai/skills-reference.mdx} (96%) rename content/docs/{concepts => ai}/skills.mdx (95%) rename content/docs/{guides => api}/client-sdk.mdx (100%) create mode 100644 content/docs/api/data-api.mdx rename content/docs/{guides => api}/data-flow.mdx (99%) rename content/docs/{guides/project-scoping.mdx => api/environment-routing.mdx} (96%) rename content/docs/{guides/cheatsheets => api}/error-catalog.mdx (99%) rename content/docs/{guides => api}/error-handling-client.mdx (98%) rename content/docs/{guides => api}/error-handling-server.mdx (100%) create mode 100644 content/docs/api/index.mdx create mode 100644 content/docs/api/meta.json create mode 100644 content/docs/api/metadata-api.mdx create mode 100644 content/docs/api/plugin-endpoints.mdx rename content/docs/{guides/cheatsheets => api}/wire-format.mdx (98%) rename content/docs/{guides/solutions/approval-workflow.mdx => automation/approvals.mdx} (63%) rename content/docs/{guides/metadata/flow.mdx => automation/flows.mdx} (85%) rename content/docs/{guides => automation}/hook-bodies.mdx (97%) create mode 100644 content/docs/automation/hooks.mdx create mode 100644 content/docs/automation/index.mdx create mode 100644 content/docs/automation/meta.json rename content/docs/{concepts/webhook-delivery.mdx => automation/webhooks.mdx} (100%) rename content/docs/{guides/metadata/workflow.mdx => automation/workflows.mdx} (100%) delete mode 100644 content/docs/concepts/core/index.mdx delete mode 100644 content/docs/concepts/core/meta.json delete mode 100644 content/docs/concepts/packages.mdx delete mode 100644 content/docs/concepts/terminology.mdx rename content/docs/{guides/analytics-datasets.mdx => data-modeling/analytics.mdx} (100%) rename content/docs/{guides/driver-configuration.mdx => data-modeling/drivers.mdx} (100%) rename content/docs/{guides => data-modeling}/external-datasources.mdx (97%) rename content/docs/{guides/cheatsheets => data-modeling}/field-type-decision-tree.mdx (98%) rename content/docs/{guides/cheatsheets/field-type-gallery.mdx => data-modeling/field-types.mdx} (100%) rename content/docs/{guides/metadata/field.mdx => data-modeling/fields.mdx} (97%) rename content/docs/{guides/formula.mdx => data-modeling/formulas.mdx} (78%) create mode 100644 content/docs/data-modeling/index.mdx create mode 100644 content/docs/data-modeling/indexing.mdx create mode 100644 content/docs/data-modeling/meta.json rename content/docs/{guides/metadata/object.mdx => data-modeling/objects.mdx} (95%) rename content/docs/{guides/cheatsheets/query-cheat-sheet.mdx => data-modeling/queries.mdx} (100%) create mode 100644 content/docs/data-modeling/relationships.mdx rename content/docs/{guides/data-modeling.mdx => data-modeling/schema-design.mdx} (56%) rename content/docs/{guides => data-modeling}/seed-data.mdx (99%) rename content/docs/{guides/cheatsheets/field-validation-rules.mdx => data-modeling/validation-rules.mdx} (100%) rename content/docs/{guides/metadata => data-modeling}/validation.mdx (82%) rename content/docs/{concepts => deployment}/cloud-artifact-api.mdx (96%) rename content/docs/{guides => deployment}/environment-variables.mdx (99%) rename content/docs/{guides/cloud-deployment.mdx => deployment/index.mdx} (96%) create mode 100644 content/docs/deployment/meta.json rename content/docs/{guides/objectql-migration.mdx => deployment/migration-from-objectql.mdx} (99%) rename content/docs/{guides => deployment}/production-readiness.mdx (100%) rename content/docs/{guides => deployment}/publish-and-preview.mdx (90%) rename content/docs/{guides => deployment}/single-project-mode.mdx (93%) rename content/docs/{guides => deployment}/troubleshooting.mdx (99%) rename content/docs/{guides/deployment-vercel.mdx => deployment/vercel.mdx} (95%) delete mode 100644 content/docs/getting-started/architecture.mdx rename content/docs/{guides => getting-started}/common-patterns.mdx (97%) delete mode 100644 content/docs/getting-started/core-concepts.mdx create mode 100644 content/docs/getting-started/quick-reference.mdx rename content/docs/{guides => getting-started}/validating-metadata.mdx (94%) delete mode 100644 content/docs/guides/ai-capabilities.mdx delete mode 100644 content/docs/guides/api-reference.mdx delete mode 100644 content/docs/guides/business-logic.mdx delete mode 100644 content/docs/guides/cheatsheets/meta.json delete mode 100644 content/docs/guides/cheatsheets/quick-reference.mdx delete mode 100644 content/docs/guides/index.mdx delete mode 100644 content/docs/guides/meta.json delete mode 100644 content/docs/guides/metadata/index.mdx delete mode 100644 content/docs/guides/metadata/meta.json delete mode 100644 content/docs/guides/security.mdx delete mode 100644 content/docs/guides/solutions/index.mdx delete mode 100644 content/docs/guides/solutions/meta.json rename content/docs/{concepts/core => kernel}/architecture.mdx (100%) rename content/docs/{concepts/cluster-semantics.mdx => kernel/cluster.mdx} (100%) rename content/docs/{guides => kernel}/contracts/auth-service.mdx (100%) rename content/docs/{guides => kernel}/contracts/cache-service.mdx (100%) rename content/docs/{guides => kernel}/contracts/data-engine.mdx (100%) rename content/docs/{guides => kernel}/contracts/index.mdx (100%) rename content/docs/{guides => kernel}/contracts/meta.json (100%) rename content/docs/{guides => kernel}/contracts/metadata-service.mdx (100%) rename content/docs/{guides => kernel}/contracts/storage-service.mdx (100%) rename content/docs/{concepts/core => kernel}/events.mdx (100%) create mode 100644 content/docs/kernel/index.mdx create mode 100644 content/docs/kernel/meta.json rename content/docs/{guides => kernel}/runtime-services/audit-service.mdx (100%) rename content/docs/{guides => kernel}/runtime-services/data-service.mdx (100%) rename content/docs/{guides => kernel}/runtime-services/email-service.mdx (100%) rename content/docs/{guides => kernel}/runtime-services/examples.mdx (100%) rename content/docs/{guides => kernel}/runtime-services/index.mdx (100%) rename content/docs/{guides => kernel}/runtime-services/meta.json (100%) rename content/docs/{guides => kernel}/runtime-services/queue-service.mdx (100%) rename content/docs/{guides => kernel}/runtime-services/settings-service.mdx (100%) rename content/docs/{guides => kernel}/runtime-services/sharing-service.mdx (100%) rename content/docs/{guides => kernel}/runtime-services/storage-service.mdx (100%) rename content/docs/{guides => kernel}/runtime-services/versioning.mdx (100%) rename content/docs/{guides/kernel-services.mdx => kernel/services-checklist.mdx} (100%) rename content/docs/{concepts/core => kernel}/services.mdx (100%) rename content/docs/{guides/solutions/data-automation-interface-access.mdx => permissions/access-recipes.mdx} (95%) rename content/docs/{guides => permissions}/authentication.mdx (98%) rename content/docs/{concepts => permissions}/authorization.mdx (100%) create mode 100644 content/docs/permissions/field-level-security.mdx create mode 100644 content/docs/permissions/index.mdx create mode 100644 content/docs/permissions/meta.json rename content/docs/{guides/metadata/permission.mdx => permissions/permission-metadata.mdx} (96%) create mode 100644 content/docs/permissions/permission-sets.mdx rename content/docs/{guides/cheatsheets => permissions}/permissions-matrix.mdx (100%) create mode 100644 content/docs/permissions/profiles.mdx create mode 100644 content/docs/permissions/roles.mdx create mode 100644 content/docs/permissions/sharing-rules.mdx rename content/docs/{guides/auth-sso.mdx => permissions/sso.mdx} (100%) rename content/docs/{guides => plugins}/adding-a-metadata-type.mdx (96%) rename content/docs/{concepts/core/plugins.mdx => plugins/anatomy.mdx} (57%) rename content/docs/{guides/plugin-development.mdx => plugins/development.mdx} (97%) rename content/docs/{guides/plugins.mdx => plugins/index.mdx} (68%) create mode 100644 content/docs/plugins/meta.json rename content/docs/{guides => plugins}/packages.mdx (99%) rename content/docs/{guides/cheatsheets => protocol}/backward-compatibility.mdx (100%) rename content/docs/{guides/cheatsheets/protocol-diagram.mdx => protocol/diagram.mdx} (100%) rename content/docs/{concepts => releases}/implementation-status.mdx (99%) rename content/docs/{guides/metadata/app.mdx => ui/apps.mdx} (95%) rename content/docs/{guides/solutions => ui}/create-vs-edit-form.mdx (98%) rename content/docs/{guides/metadata/dashboard.mdx => ui/dashboards.mdx} (98%) rename content/docs/{guides/metadata/doc.mdx => ui/doc-pages.mdx} (100%) rename content/docs/{guides/solutions => ui}/field-grouping-and-order.mdx (96%) rename content/docs/{guides/public-forms.mdx => ui/forms.mdx} (98%) create mode 100644 content/docs/ui/index.mdx create mode 100644 content/docs/ui/meta.json rename content/docs/{guides/metadata/page.mdx => ui/pages.mdx} (97%) rename content/docs/{guides/solutions => ui}/public-data-collection.mdx (98%) rename content/docs/{guides/solutions => ui}/role-based-interfaces.mdx (91%) rename content/docs/{concepts => ui}/setup-app.mdx (96%) rename content/docs/{guides/metadata/view.mdx => ui/views.mdx} (96%) rename {content/docs/guides => docs/notes}/airtable-dashboard-analysis.mdx (99%) rename content/docs/guides/standards.mdx => docs/notes/crm-development-standards.mdx (100%) diff --git a/content/blog/protocol-first-development.mdx b/content/blog/protocol-first-development.mdx index da257f9441..4d13d90783 100644 --- a/content/blog/protocol-first-development.mdx +++ b/content/blog/protocol-first-development.mdx @@ -849,4 +849,4 @@ Join us in building it. --- -*Ready to build on ObjectStack? Check out our [Getting Started Guide](/docs/guides/getting-started) or join the conversation on [GitHub Issues](https://github.com/objectstack-ai/spec/issues).* +*Ready to build on ObjectStack? Check out our [Getting Started Guide](/docs/getting-started) or join the conversation on [GitHub Issues](https://github.com/objectstack-ai/spec/issues).* diff --git a/content/docs/ai/actions-as-tools.mdx b/content/docs/ai/actions-as-tools.mdx new file mode 100644 index 0000000000..b3608e55a0 --- /dev/null +++ b/content/docs/ai/actions-as-tools.mdx @@ -0,0 +1,236 @@ +--- +title: Actions as Tools +description: Expose declarative Action metadata as AI-callable tools with explicit opt-in, HITL approval, and permission-aware execution +--- + +# Actions as Tools + +Part of the [AI module](/docs/ai) — how existing Action metadata becomes LLM-callable, and the guardrails around it. + +Declarative `Action` metadata can be exposed as AI-callable tools, named +`action_`, but exposure is **explicit opt-in**. Add an `ai:` block +with `exposed: true` and an LLM-facing `description`; otherwise the action stays +human/UI-only. + +```typescript +export const triageCaseAction = { + name: 'triage_case', + label: 'Triage Case', + objectName: 'case', + type: 'flow', + target: 'case_triage', + ai: { + exposed: true, + description: 'Triage a support case, suggest priority, and assign the next support queue.', + category: 'action', + requiresConfirmation: false, + }, +}; +``` + +When the LLM picks an exposed action, the AI runtime dispatches to the same +handler the Console row toolbar would invoke, so your business logic stays in +one place. + +## What gets exposed + +The AI runtime walks every registered object's `actions[]` and registers only +actions with `ai.exposed === true` that also pass safety and wiring checks. +Three action types are supported: + +| `action.type` | Dispatch path | Wiring needed | +|:---|:---|:---| +| `script` | `IDataEngine.executeAction(object, target, ctx)` — the same call Studio makes | none beyond the metadata service | +| `api` | HTTP call to `action.target` via `ApiActionClient` (default: `fetch`) | `apiBaseUrl` (or a custom `apiClient`) | +| `flow` | `IAutomationService.execute(target, { triggerData })` | `automation` service registered | + +Console-only types (`url`, `modal`, `form`) are always skipped. Dangerous +actions — those with `confirmText`, `mode: 'delete'`, `variant: 'danger'`, or +`ai.requiresConfirmation: true` — are skipped unless the +[HITL approval queue](#human-in-the-loop-approval) is wired. To assert that a +destructive-looking action is safe for autonomous execution, set +`ai.requiresConfirmation: false`. + +## Wiring it up + +```typescript +import { AIServicePlugin } from '@objectstack/service-ai'; + +kernel.use( + new AIServicePlugin({ + // Enables type:'api' action dispatch. Relative `target` paths + // ('/api/v1/...') are resolved against this base URL. + apiActionBaseUrl: process.env.OS_AI_ACTION_API_BASE_URL, + // Forwarded on every api-action HTTP call (auth, environment id, ...). + apiActionHeaders: { Authorization: `Bearer ${process.env.SERVICE_TOKEN}` }, + }), +); +``` + +If `automation` is already registered with the kernel, `type:'flow'` actions are picked up automatically — no extra wiring needed. + +## `type:'api'` body assembly + +For api actions, the request body is built from three sources (last wins): + +1. **User-collected params** (the keys the LLM filled in). +2. **`recordIdParam`** — when row-context, the id is placed flat at `action.recordIdParam`, using `recordIdField` (default `'id'`) to pick the value off the record. +3. **`bodyExtra`** — constant fields that always override. + +`bodyShape: { wrap: 'data' }` nests the user params under `data` while keeping `recordIdParam` flat — matching shapes like better-auth's `organization/update`. + +## Diagnostics + +`registerActionsAsTools()` returns `{ registered, skipped, warnings }`. The +diagnostics include reasons such as `"not AI-exposed"`, +`"no apiClient or apiBaseUrl configured"`, or +`"requires confirmation ... wire HITL approval"` so action authors can see +whether their action will be LLM-callable. + +## Human-In-The-Loop approval + +Destructive actions are too risky to let the LLM execute autonomously, but locking them away entirely defeats agentic UX. The HITL queue strikes the balance: the LLM gets to **propose** the call, a human gets to **approve** it. + +Enable the queue via the plugin option (default: off): + +```typescript +kernel.use( + new AIServicePlugin({ + enableActionApproval: true, + apiActionBaseUrl: process.env.OS_AI_ACTION_API_BASE_URL, + }), +); +``` + +When the LLM picks an approval-gated tool (e.g. `action_delete_task`), the runtime: + +1. Persists an `ai_pending_actions` row with `status:'pending'`, `tool_input`, `proposed_by`, etc. +2. Returns `{ status: 'pending_approval', pendingActionId }` to the model so it can summarise (e.g. "I've requested approval to delete task #42."). +3. The operator sees the proposal in the **AI Pending Actions** Studio inbox. +4. Clicking **Approve** calls `POST /api/v1/ai/pending-actions/:id/approve` (`ai:approve` permission). The service looks up the pre-registered dispatcher and executes the action with HITL routing disabled, so the same code path runs. The row transitions to `executed` (or `failed` if dispatch threw). +5. Clicking **Reject** calls `POST /api/v1/ai/pending-actions/:id/reject` with an optional reason. + +The queue is exposed via four REST endpoints (`GET`, `GET/:id`, `POST/:id/approve`, `POST/:id/reject`) and via `IAIService.{proposePendingAction,approvePendingAction,rejectPendingAction,listPendingActions}` for programmatic use. + +**Why a dedicated queue (not the multi-step `IApprovalService`)?** AI tool-call HITL is ephemeral: subject is the proposed *call*, not a stable record state; there's no predefined process; operators expect single-click yes/no. The pending-action queue is a thin write log + dispatcher map that delivers that UX without dragging in process-engine overhead. + +### End-to-end example + +Two runnable demos live in `examples/app-todo/test/`: + +- **`ai-hitl.test.ts`** — drives the tool registry directly (no LLM dependency). Asserts the full lifecycle: `variant:'danger'` action registered as a tool → invocation returns `pending_approval` without executing → row persisted → `approvePendingAction(id, actor)` re-runs the handler → row transitions to `executed`. Reject path is also covered. + + ```bash + pnpm --filter @example/app-todo test:hitl + ``` + +- **`ai-hitl-llm.test.ts`** — same scenario but with a real model behind Vercel AI Gateway. The LLM is given the auto-generated tool description and asked to "delete all completed tasks"; the framework returns `pending_approval` so the model summarises the wait instead of retrying. After we call approve from the test, the deletion completes. + + ```bash + AI_GATEWAY_API_KEY=vck_... pnpm --filter @example/app-todo test:hitl:llm + ``` + + Gated on `AI_GATEWAY_API_KEY` (or `OPENAI_API_KEY`); exits 0 with a notice if no key is provided, so it can be wired into CI without leaking spend. + +A trimmed view of the integration path: + +```typescript +// 1. Plugin boots with approval gating enabled +new AIServicePlugin({ + adapter: new VercelLLMAdapter({ model }), + enableActionApproval: true, // ← opt-in +}) + +// 2. LLM picks the gated tool — handler short-circuits to pending +const result = await aiService.toolRegistry.execute({ + type: 'tool-call', + toolName: 'action_delete_completed', + input: {}, +} as never); +const envelope = JSON.parse((result.output as { value: string }).value); +// → { ok: true, status: 'pending_approval', pendingActionId: 'pa_...' } + +// 3. Operator approves (REST or programmatic) +const outcome = await ai.approvePendingAction(envelope.pendingActionId, 'alice@example.com'); +// → { status: 'executed', result: } +``` + +## Permission-aware execution (RLS for agents) + +Every AI tool call now runs with the **end-user's** `ExecutionContext`, +so the same row-level-security rules that protect the REST API +automatically scope what an agent can see and do. There is no separate +"agent permission" surface to maintain — if a user can't read account +`acc_42` through ObjectQL, neither can the LLM acting on their behalf. + +**How it works:** + +1. The REST routes for `/api/v1/ai/assistant/chat` and + `/api/v1/ai/agents/:id/chat` pull the authenticated principal out of + `req.user` and forward it to `aiService.chatWithTools(...)` as + `toolExecutionContext: { actor, conversationId, environmentId }`. + Both **cookie session** (`better-auth.session_token`) and **Bearer + token** auth are resolved automatically by the dispatcher — your + browser chats and your scripted API calls land in the same RLS + context as a plain ObjectQL request from the same user. +2. The tool registry threads that context into every handler invocation. +3. Built-in data tools (`query_records`, `get_record`, + `aggregate_data`) and auto-generated `action_*` tools convert the + actor into a `{ userId, roles, permissions, isSystem: false }` + engine context on each `IDataEngine` call. RLS engages exactly as + it would for a hand-rolled API endpoint. +4. Action audit logs attribute the dispatch to the real user instead of + a generic "AI Assistant" principal. + +When you invoke `chatWithTools` from a custom server route, opt in by +passing the actor explicitly: + +```typescript +await aiService.chatWithTools(messages, tools, { + toolExecutionContext: { + actor: { + id: currentUser.id, + name: currentUser.displayName, + roles: currentUser.roles, + permissions: currentUser.permissions, + }, + conversationId, + environmentId, + }, +}); +``` + +Omit `toolExecutionContext` to keep the previous system-level behaviour +(used by cron jobs, internal callers, and the existing test suite). + +## LLM-generated conversation titles + +Auto-titling is **opt-in** (disabled by default; enable it via the `ai` +settings namespace from Console → Settings → AI). Once enabled, after a +conversation has at least one user + assistant exchange (≥ 2 messages) and +still has no title, the AI service fires a short, out-of-band LLM call +(default cap **16 characters**, single-line, no quotes) to summarise what the +user is asking about and writes the result back to `ai_conversations.title`. +The summarise call: + +- Reuses the **active chat provider** (so it works with any + `provider/model` you configured via Console → Settings → AI), and + honours the same `${provider}_base_url` you wired for chat — + including custom OpenAI-compatible endpoints (SiliconFlow, DeepSeek, + a local OpenAI proxy, …). +- Runs as a fire-and-forget task with a short timeout — if the title + call fails, the chat reply is unaffected and the conversation simply + keeps its placeholder name. +- Skips re-titling once `title` is set, so manual edits via the + conversation API are never overwritten. + +The Console sidebar groups conversations by recency and displays the +title; if you ever need to force a regenerate, clear the field via the +`ai_conversations` REST API and send another message. + +--- + +## See also + +- [AI Overview](/docs/ai) +- [AI Agents](/docs/ai/agents) diff --git a/content/docs/ai/agents.mdx b/content/docs/ai/agents.mdx new file mode 100644 index 0000000000..2be563d757 --- /dev/null +++ b/content/docs/ai/agents.mdx @@ -0,0 +1,239 @@ +--- +title: AI Agents +description: The two platform agents (ask and build), how skills extend them, and the shape of an AgentSchema record +--- + +# AI Agents + +Part of the [AI module](/docs/ai) — see the overview for how the cloud / Enterprise in-UI AI runtime differs from the open edition's MCP-only (BYO-AI) approach. + +Per [ADR-0063](https://github.com/objectstack-ai/framework/blob/main/docs/adr/0063-two-kernel-agents-skills-are-the-extension-primitive.md) +the kernel ships **exactly two** platform agents, bound by the *surface* the user +is in — the user never picks from a roster: + +| Agent | Surface | Does | Edition | +|---|---|---|---| +| **`ask`** | data console | Read / query / explore records + run the business **actions** the app exposes. RLS-bounded. | cloud · Enterprise | +| **`build`** | Studio | Author *metadata* (objects, fields, views, flows) via plan → draft → verify → publish. | cloud · Enterprise | + +Both agents are part of the **cloud / Enterprise** in-UI AI runtime (cloud ADR-0025). +The **open edition** ships neither — it uses `@objectstack/mcp` (BYO-AI) for data +query and source-mode authoring instead (see the note above). + +Within the cloud / EE runtime there is no per-turn intent classifier and no agent +dropdown: the surface binds the agent (data console → `ask`, Studio → `build`). A +`build`-shaped request that reaches `ask` is declined and redirected to the +Builder, never silently re-routed. + +## You extend the platform with **skills**, not agents + +`*.agent.ts` is **closed to third parties** — the `agent` metadata type is +`allowRuntimeCreate:false, allowOrgOverride:false`, reserved for the two platform +agents and platform-owned subagents (ADR-0063 §2). To give the `ask` agent a new +capability you author a **skill** (`*.skill.ts`) whose `tools` reference your +Actions / Flows / queries; it then attaches to `ask`. Every skill declares +`surface: 'ask' | 'build' | 'both'`, and an agent's tool set is the **union of its +surface-compatible skills' tools** — there is no global fall-through, so a skill +reaches an agent only when their surfaces match +([ADR-0064](https://github.com/objectstack-ai/framework/blob/main/docs/adr/0064-tool-scoping-to-agent.md)). +Both `surface:'ask'` and `surface:'build'` skills run only where the in-UI AI +runtime exists — the **cloud / Enterprise** distribution. On the open framework +there is no in-product agent to attach them to (cloud ADR-0025); author capability +as Actions / Flows and reach it through `@objectstack/mcp` instead. + +## The shape of an agent + +An agent is metadata validated by `AgentSchema` (the platform's own `ask` / `build` +records use exactly these fields): + +| Field | Meaning | +|------|---------| +| `surface` | `'ask'` \| `'build'` — the product surface this agent binds (ADR-0063 §1) | +| `role` | Free-text **persona** string (e.g. `"Senior Support Engineer"`) — not an enum | +| `instructions` | System prompt / prime directives | +| `model` | Provider + model config (`provider`: `openai` \| `azure_openai` \| `anthropic` \| `local`) | +| `skills` | Skill names to attach (the primary Agent → Skill → Tool capability model) | +| `tools` | Direct tool **references** `{ type, name, description }` — `type` is `action` \| `flow` \| `query` \| `vector_search`; `name` points at an existing Action/Flow/query | +| `knowledge` | RAG access: `{ topics: string[], indexes: string[] }` | + +There is no `type` field and no fixed agent "type" taxonomy — behaviour comes from +persona, instructions, skills, and tools. There are no `triggers` / `schedule` +fields on an agent; drive agents from [Flows/Workflows](/docs/automation) or invoke +them via the chat endpoint. + + +Agent tools are **references** to existing Actions, Flows, or queries — you do +not define ad-hoc tool names with inline parameter schemas here. See +[Actions as Tools](#actions-as-tools-explicit-opt-in) for how an Action becomes +LLM-callable. + + + +The agent definitions below illustrate agent **anatomy** — they show how an +`AgentSchema` record is shaped, *not* a tenant-authoring tutorial. On today's +platform you do not ship your own agents (`*.agent.ts` is platform-internal); you +add capability by authoring a **skill** that attaches to the built-in `ask` agent. +Read the examples for structure, then express your own capability as a skill plus +the Actions/Flows its tools reference. + + +## Sales Assistant Agent + +```typescript +import { defineAgent } from '@objectstack/spec/ai'; + +export const SalesAssistantAgent = defineAgent({ + name: 'sales_assistant', + label: 'Sales Assistant', + role: 'Sales Development Assistant', + + instructions: `You are a sales assistant AI. + +Your responsibilities: +1. Qualify incoming leads (BANT criteria) +2. Suggest next best actions +3. Draft personalized emails +4. Analyze win/loss patterns + +Always be professional and data-driven.`, + + model: { + provider: 'openai', + model: 'gpt-4', + temperature: 0.7, + maxTokens: 2000, + }, + + // References to Actions/Flows exposed as tools (see "Actions as Tools"). + tools: [ + { type: 'flow', name: 'analyze_lead', description: 'Analyze a lead and provide a qualification score' }, + { type: 'flow', name: 'suggest_next_action', description: 'Suggest the next best action for an opportunity' }, + { type: 'action', name: 'generate_email', description: 'Generate a personalized email template' }, + ], + + // RAG access: topics to recruit knowledge from + vector store indexes. + knowledge: { + topics: ['sales-playbook', 'leads', 'opportunities'], + indexes: ['sales_docs'], + }, +}); +``` + +## Customer Service Agent + +```typescript +export const ServiceAgent = defineAgent({ + name: 'service_agent', + label: 'Customer Service Agent', + role: 'Customer Service Specialist', + + instructions: `You are a customer service AI agent. + +Your responsibilities: +1. Triage incoming cases +2. Suggest relevant knowledge articles +3. Draft response templates +4. Escalate critical issues + +Always be empathetic and solution-focused.`, + + model: { + provider: 'openai', + model: 'gpt-4', + temperature: 0.5, + maxTokens: 1500, + }, + + // `search_knowledge` is provided by the Knowledge Protocol tool, not declared inline. + tools: [ + { type: 'flow', name: 'triage_case', description: 'Analyze a case and assign priority' }, + { type: 'action', name: 'generate_response', description: 'Generate a customer response' }, + ], + + knowledge: { + topics: ['support-kb', 'cases'], + indexes: ['support_docs'], + }, +}); +``` + +## Lead Enrichment Agent + +```typescript +export const LeadEnrichmentAgent = defineAgent({ + name: 'lead_enrichment', + label: 'Lead Enrichment Agent', + role: 'Data Enrichment Worker', + + instructions: `You enrich lead records with additional data. + +Tasks: +1. Look up company information +2. Enrich contact details +3. Add firmographic data +4. Research technology stack + +Use reputable data sources.`, + + model: { + provider: 'openai', + model: 'gpt-3.5-turbo', + temperature: 0.3, + maxTokens: 1000, + }, + + tools: [ + { type: 'flow', name: 'lookup_company', description: 'Look up company information' }, + { type: 'flow', name: 'enrich_contact', description: 'Enrich contact information' }, + ], +}); +``` + +To run enrichment when a lead is created or on a schedule, trigger this agent +from a [Flow or Workflow](/docs/automation) — agents themselves carry no +`triggers`/`schedule` fields. + +## Revenue Intelligence Agent + +```typescript +export const RevenueIntelligenceAgent = defineAgent({ + name: 'revenue_intelligence', + label: 'Revenue Intelligence Agent', + role: 'Revenue Operations Analyst', + + instructions: `You analyze sales data and provide insights. + +Responsibilities: +1. Analyze pipeline health +2. Identify at-risk deals +3. Summarize trends +4. Generate executive summaries + +Use the data tools to query records and aggregate metrics.`, + + model: { + provider: 'openai', + model: 'gpt-4', + temperature: 0.2, + maxTokens: 3000, + }, + + // Built-in data tools (query_records / get_record / aggregate_data) are + // available to agents automatically once registered — see "Actions as Tools". + tools: [ + { type: 'flow', name: 'analyze_pipeline', description: 'Analyze sales pipeline health' }, + ], + + knowledge: { + topics: ['opportunities', 'pipeline'], + indexes: ['sales_docs'], + }, +}); +``` + +--- + +## See also + +- [AI Overview](/docs/ai) +- [Actions as Tools](/docs/ai/actions-as-tools) diff --git a/content/docs/guides/plugin-chatbot-integration.mdx b/content/docs/ai/chatbot-integration.mdx similarity index 98% rename from content/docs/guides/plugin-chatbot-integration.mdx rename to content/docs/ai/chatbot-integration.mdx index e276a60508..5953999dfe 100644 --- a/content/docs/guides/plugin-chatbot-integration.mdx +++ b/content/docs/ai/chatbot-integration.mdx @@ -12,7 +12,7 @@ HITL inbox (`@objectstack/service-ai`) — ships in the **cloud / Enterprise** distribution, not the open framework (cloud ADR-0025: `service-ai → cloud; open = MCP-only`). On the **open edition** there is no in-product chat backend; expose the app to your own AI through `@objectstack/mcp` (BYO-AI) instead — see the -[AI Capabilities guide](./ai-capabilities). Follow this guide when you run against +[AI Capabilities guide](/docs/ai). Follow this guide when you run against a cloud / EE host (or a dev server with the AI tier mounted). diff --git a/content/docs/ai/index.mdx b/content/docs/ai/index.mdx new file mode 100644 index 0000000000..47ea0b4291 --- /dev/null +++ b/content/docs/ai/index.mdx @@ -0,0 +1,181 @@ +--- +title: AI Overview +description: Complete guide to leveraging AI agents, RAG pipelines, and intelligent automation in ObjectStack +--- + +# AI Overview + +AI in ObjectStack is a **cross-protocol capability layer**: agents, tools, and knowledge retrieval sit on top of the same objects, actions, permissions, and automation that power the rest of the platform. This module covers the architecture and each of its moving parts. + + +**This guide describes the cloud / Enterprise AI tier. The open edition exposes AI only via MCP (BYO-AI).** + +Per **cloud ADR-0025** (`service-ai → cloud; open = MCP-only` — [`cloud/docs/adr/0025`](https://github.com/objectstack-ai/cloud/blob/main/docs/adr/0025-service-ai-to-cloud-open-mcp-only.md)), the in-UI AI runtime — `@objectstack/service-ai`: both the **`ask`** data-query assistant and the **`build`** Studio authoring assistant, plus all in-product chat — ships in the **cloud / Enterprise** distribution. It is **not** in the open framework, and no open distribution (cloud free tier, Docker, desktop, on-prem) has a built-in `ask` / `build` chat. + +The **open edition** does AI two ways instead — both bring-your-own-AI, zero platform AI cost: + +- **Data query → `@objectstack/mcp`** (BYO-AI). Point your own AI — Claude, Cursor, any MCP client, or a local model — at the app's objects, queries, and business **actions**, governed by the same RLS. With a local model, data *and* inference stay inside your boundary. +- **Metadata authoring → source mode.** Author typed metadata as source (`*.object.ts`, `*.flow.ts`, …) with your own AI coding agent (Claude Code, Cursor), aided by the ObjectStack [skills](/docs/ai/skills-reference) and MCP introspection. There is no in-product Builder chat in the open edition. + +Everything below (agents, the `ask` / `build` personas, `@objectstack/service-ai` wiring, the `/api/v1/ai/*` routes) therefore describes the **cloud / Enterprise** distribution. + + +## What's in this module + +- [AI Agents](/docs/ai/agents) — the two platform agents (`ask` / `build`), skills as the extension primitive, and agent anatomy +- [Actions as Tools](/docs/ai/actions-as-tools) — explicit opt-in exposure of Actions to the LLM, HITL approval, permission-aware execution +- [Knowledge & RAG](/docs/ai/knowledge-rag) — the Knowledge Protocol and its adapter plugins +- [Natural Language Queries](/docs/ai/natural-language-queries) — the built-in data tools that turn questions into ObjectQL +- [AI Skills System](/docs/ai/skills) — structured knowledge modules for AI coding assistants +- [AI Skills Reference](/docs/ai/skills-reference) — the per-skill catalog +- [Chatbot Integration](/docs/ai/chatbot-integration) — wiring `plugin-chatbot` to the framework AI backend +- Spec: [Knowledge Protocol](/docs/protocol/knowledge) +- Schema reference: [AI](/docs/references/ai) + +--- + +## AI Architecture + +ObjectStack provides a comprehensive AI platform: + +``` +┌─────────────────────────────────────┐ +│ AI Agents │ ← Persona + skills/tools +│ Skills & Tools │ ← Actions/Flows exposed to the LLM +├─────────────────────────────────────┤ +│ Knowledge Protocol │ ← search_knowledge via adapters +│ - memory / ragflow / custom │ +│ - Permission-aware retrieval │ +├─────────────────────────────────────┤ +│ Model Registry │ ← LLM management +│ - openai, azure_openai, │ +│ anthropic, local │ +│ - Token accounting / cost │ +└─────────────────────────────────────┘ +``` + +--- + +## Best Practices + +### 1. AI Agent Design + +✅ **DO:** +- Define clear agent roles and responsibilities +- Provide detailed instructions +- Use appropriate temperature settings +- Test with real-world scenarios +- Monitor agent performance + +❌ **DON'T:** +- Give agents conflicting instructions +- Use high temperatures for factual tasks +- Deploy without testing +- Ignore cost implications + +### 2. Knowledge & Data Access + +✅ **DO:** +- Declare knowledge sources via the Knowledge Protocol and pick the adapter (`memory`, `ragflow`, custom) that fits your data +- Rely on the built-in data tools (`query_records` / `get_record` / `aggregate_data`) for live record access +- Let permission-aware retrieval and RLS scope what each user's agent can see +- Keep indexed objects in sync via the protocol's event sync + +❌ **DON'T:** +- Reinvent a vector DB — let the adapter engine handle chunking/embedding/rerank +- Bypass `ExecutionContext`, which would leak rows past row-level security +- Expose objects to agents that the calling user can't read + +### 3. Prompt Engineering + +✅ **DO:** +- Be specific and clear +- Provide examples +- Use role-playing ("You are a...") +- Include constraints +- Test variations + +❌ **DON'T:** +- Be vague or ambiguous +- Assume context +- Use complex jargon +- Write overly long prompts + +### 4. Cost Management + +✅ **DO:** +- Choose appropriate models (GPT-3.5 vs GPT-4) +- Implement caching +- Set token limits +- Monitor usage +- Use cheaper models for simple tasks + +❌ **DON'T:** +- Always use the most expensive model +- Skip caching +- Allow unlimited tokens +- Ignore cost metrics + +### 5. Security & Privacy + +✅ **DO:** +- Implement access controls +- Mask sensitive data +- Log AI interactions +- Review outputs +- Follow data privacy regulations + +❌ **DON'T:** +- Expose PII to external APIs +- Skip output validation +- Ignore audit trails +- Trust AI blindly + +--- + +## Real-World Integration + +### Complete Sales AI Workflow + +Agents are metadata, not classes — there are no `.enrich()` / `.predict()` / +`.query()` methods to call. You invoke an agent over HTTP (the REST chat +endpoint) or, server-side, via `aiService.chatWithTools(...)`. Enrichment, +scoring, and email drafting are implemented as **Actions/Flows exposed as +tools**, and the LLM calls them while reasoning over the conversation. + +```typescript +// Invoke an agent over the REST chat endpoint. +// POST /api/v1/ai/agents/:agentName/chat +const res = await fetch('/api/v1/ai/agents/sales_assistant/chat', { + method: 'POST', + headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` }, + body: JSON.stringify({ + message: `A hot lead just came in (id ${lead.id}). Qualify it, suggest the + next best action, and draft a professional intro email.`, + }), +}); +const { reply } = await res.json(); +// The agent calls its `analyze_lead` / `suggest_next_action` / `generate_email` +// tools (the Actions/Flows you wired) and returns its summary in `reply`. +``` + +Server-side, the same flow runs through `chatWithTools`, threading the +end-user's `ExecutionContext` so tool calls respect row-level security: + +```typescript +const reply = await aiService.chatWithTools(messages, tools, { + toolExecutionContext: { + actor: { id: currentUser.id, name: currentUser.displayName, roles: currentUser.roles, permissions: currentUser.permissions }, + conversationId, + environmentId, + }, +}); +``` + +To run any of this on lead creation or on a schedule, drive the agent from a +[Flow or Workflow](/docs/automation) rather than expecting trigger/schedule fields +on the agent itself. + +--- + +**Next:** [AI Agents →](/docs/ai/agents) diff --git a/content/docs/ai/knowledge-rag.mdx b/content/docs/ai/knowledge-rag.mdx new file mode 100644 index 0000000000..31caee0eb8 --- /dev/null +++ b/content/docs/ai/knowledge-rag.mdx @@ -0,0 +1,69 @@ +--- +title: Knowledge & RAG +description: The Knowledge Protocol — permission-aware RAG for agents via pluggable adapter plugins (memory, RAGFlow, custom) +--- + +# Knowledge & RAG + +Part of the [AI module](/docs/ai) — how agents retrieve knowledge through the Knowledge Protocol and its adapter plugins. + +ObjectStack ships a Knowledge Protocol that lets agents call `search_knowledge(query, sourceIds?, topK?)` against pluggable backends (RAGFlow, LlamaIndex, Dify, custom pgvector, …). The framework defines the contract and runs permission-aware filtering; the adapter plugin does the actual retrieval. See [the protocol design](/docs/protocol/knowledge) for the rationale. + +## Wiring + +```ts +import { ObjectKernel } from '@objectstack/core'; +import { KnowledgeServicePlugin } from '@objectstack/service-knowledge'; +import { KnowledgeMemoryPlugin } from '@objectstack/knowledge-memory'; +// or, for prod: +// import { KnowledgeRagflowPlugin } from '@objectstack/knowledge-ragflow'; + +const kernel = new ObjectKernel(); +kernel.use(new KnowledgeServicePlugin({ + sources: [ + { + id: 'task_notes', + label: 'Task notes', + adapter: 'memory', + source: { kind: 'object', object: 'task', contentFields: ['title', 'notes'] }, + }, + { + id: 'product_docs', + label: 'Product docs', + adapter: 'ragflow', + source: { kind: 'http', urls: ['https://docs.example.com/sitemap.xml'] }, + options: { datasetId: 'rgf_doc_dataset' }, + }, + ], +})); +kernel.use(new KnowledgeMemoryPlugin()); +// kernel.use(new KnowledgeRagflowPlugin({ endpoint, apiKey })); +``` + +Then register the AI tool so agents can call it: + +```ts +import { registerKnowledgeTools } from '@objectstack/service-ai'; + +ctx.hook('ai:ready', async (ai) => { + const knowledge = ctx.getService('knowledge'); + registerKnowledgeTools(ai.toolRegistry, { knowledgeService: knowledge }); +}); +``` + +## What you get for free + +- **Permission-aware retrieval.** Every hit with a `sourceRecordId` is re-checked against the caller's `ExecutionContext` via `IDataEngine` — the same RLS that gates plain ObjectQL queries. A salesperson asking "find proposals about ACME" only sees the proposals they could already read directly. File / HTTP hits pass through (ACL is the adapter's problem). +- **Inline event sync.** When records on indexed objects change, the kernel's `IRealtimeService` events drive `KnowledgeService.handleRecordUpsert/Delete` automatically. No cron, no queue (yet — Phase 2). +- **Adapter swap, zero LLM changes.** Move from `memory` to `ragflow` to a custom adapter without touching the `search_knowledge` tool or any agent prompt. + +## Why we did not build a vector DB + +Mature OSS (RAGFlow, LlamaIndex, Dify) already nail chunking, embedding, hybrid retrieval, rerank, and OCR. ObjectStack's value is **the metadata-native source declaration + the permission-aware filter on top of those engines** — not yet-another-RAG-stack. Customers pick the retrieval engine that matches their data; we make sure it talks to ObjectStack the same way every time. + +--- + +## See also + +- [AI Overview](/docs/ai) +- [Natural Language Queries](/docs/ai/natural-language-queries) diff --git a/content/docs/ai/meta.json b/content/docs/ai/meta.json new file mode 100644 index 0000000000..9da85f00df --- /dev/null +++ b/content/docs/ai/meta.json @@ -0,0 +1,14 @@ +{ + "title": "AI", + "icon": "Bot", + "pages": [ + "index", + "agents", + "actions-as-tools", + "knowledge-rag", + "natural-language-queries", + "skills", + "skills-reference", + "chatbot-integration" + ] +} diff --git a/content/docs/ai/natural-language-queries.mdx b/content/docs/ai/natural-language-queries.mdx new file mode 100644 index 0000000000..101abde7e6 --- /dev/null +++ b/content/docs/ai/natural-language-queries.mdx @@ -0,0 +1,34 @@ +--- +title: Natural Language Queries +description: How agents query live data through the built-in data tools (query_records, get_record, aggregate_data) under RLS +--- + +# Natural Language Queries + +Part of the [AI module](/docs/ai) — how natural-language questions become ObjectQL queries at runtime. + +Agents query your data through the built-in **data tools** — +`query_records`, `get_record`, and `aggregate_data` — which the LLM calls with +structured arguments. These run as ordinary [ObjectQL](/docs/protocol/objectql) queries over +your objects (ObjectStack uses ObjectQL, not SOQL), and they execute under the +caller's `ExecutionContext`, so row-level security applies exactly as it does +for the REST API. + +```typescript +import { registerDataTools } from '@objectstack/service-ai'; + +ctx.hook('ai:ready', async (ai) => { + registerDataTools(ai.toolRegistry, { dataEngine: ctx.getService('data') }); +}); +``` + +There is no separate natural-language-to-query metadata type to author — the +model is prompted with the available objects and translates the user's question +into `query_records` / `aggregate_data` calls at runtime. + +--- + +## See also + +- [AI Overview](/docs/ai) +- [Knowledge & RAG](/docs/ai/knowledge-rag) diff --git a/content/docs/guides/skills.mdx b/content/docs/ai/skills-reference.mdx similarity index 96% rename from content/docs/guides/skills.mdx rename to content/docs/ai/skills-reference.mdx index a3319a76e4..fc134ce29d 100644 --- a/content/docs/guides/skills.mdx +++ b/content/docs/ai/skills-reference.mdx @@ -8,7 +8,7 @@ description: Reference for every ObjectStack AI skill — domain-scoped knowledg ObjectStack ships a set of **domain-specific skills** that teach AI assistants (Claude Code, GitHub Copilot, Cursor, …) the protocol's schemas, patterns, and constraints. This guide is the complete catalog. -**New to skills?** Read [AI Skills System](/docs/concepts/skills) first for the conceptual overview, then return here for the per-skill reference. +**New to skills?** Read [AI Skills System](/docs/ai/skills) first for the conceptual overview, then return here for the per-skill reference. --- @@ -232,7 +232,7 @@ If a skill says "delegate to X for Y", follow it. Skills are deliberately focuse ## Next steps -- [AI Skills System](/docs/concepts/skills) — conceptual overview of the skills architecture -- [AI Capabilities](/docs/guides/ai-capabilities) — AI agents, RAG pipelines, and intelligent automation -- [Plugin Development](/docs/guides/plugin-development) — build custom plugins -- [Development Standards](/docs/guides/standards) — naming conventions and project structure +- [AI Skills System](/docs/ai/skills) — conceptual overview of the skills architecture +- [AI Capabilities](/docs/ai) — AI agents, RAG pipelines, and intelligent automation +- [Plugin Development](/docs/plugins/development) — build custom plugins +- [Development Standards](/docs/concepts/design-principles) — naming conventions and project structure diff --git a/content/docs/concepts/skills.mdx b/content/docs/ai/skills.mdx similarity index 95% rename from content/docs/concepts/skills.mdx rename to content/docs/ai/skills.mdx index e173316623..942c2882e7 100644 --- a/content/docs/concepts/skills.mdx +++ b/content/docs/ai/skills.mdx @@ -27,7 +27,7 @@ npm create objectstack@latest my-app npx skills add objectstack-ai/framework --all ``` -The bundle is versioned and updated as **one unit** — `--all` is idempotent, so you never track skills individually. For the full per-skill catalog and install options, see the [AI Skills Reference](/docs/guides/skills#installing-skills). +The bundle is versioned and updated as **one unit** — `--all` is idempotent, so you never track skills individually. For the full per-skill catalog and install options, see the [AI Skills Reference](/docs/ai/skills-reference#installing-skills). --- @@ -120,7 +120,7 @@ This format ensures AI assistants generate protocol-compliant code. ObjectStack provides **nine domain-specific skills**, one per protocol domain — Platform, Data, Query, UI, Automation, AI, API, i18n, and Formula. -The authoritative list (names, domains, and "use when / do not use" boundaries) is generated from each skill's `SKILL.md` frontmatter. See the **[AI Skills Reference](/docs/guides/skills)** for the full catalog with per-skill detail. +The authoritative list (names, domains, and "use when / do not use" boundaries) is generated from each skill's `SKILL.md` frontmatter. See the **[AI Skills Reference](/docs/ai/skills-reference)** for the full catalog with per-skill detail. Lifecycle hooks, plugin development, and project bootstrap are **not** separate skills — they live in **Data** (record hooks) and **Platform** (plugins, kernel events, `defineStack`). @@ -221,7 +221,7 @@ The `evals/` directory in each skill allows teams to validate that their AI assi ## Next Steps -- [AI Skills Reference](/docs/guides/skills) — Detailed guide to each skill with usage examples -- [AI Capabilities](/docs/guides/ai-capabilities) — AI agents, RAG pipelines, and intelligent automation -- [Plugin Development](/docs/guides/plugin-development) — Build custom plugins +- [AI Skills Reference](/docs/ai/skills-reference) — Detailed guide to each skill with usage examples +- [AI Capabilities](/docs/ai) — AI agents, RAG pipelines, and intelligent automation +- [Plugin Development](/docs/plugins/development) — Build custom plugins - [Quick Start](/docs/getting-started/quick-start) — Build your first ObjectStack app diff --git a/content/docs/guides/client-sdk.mdx b/content/docs/api/client-sdk.mdx similarity index 100% rename from content/docs/guides/client-sdk.mdx rename to content/docs/api/client-sdk.mdx diff --git a/content/docs/api/data-api.mdx b/content/docs/api/data-api.mdx new file mode 100644 index 0000000000..381ab792eb --- /dev/null +++ b/content/docs/api/data-api.mdx @@ -0,0 +1,208 @@ +--- +title: Data API +description: REST endpoints for CRUD, batch operations, record cloning, and analytics queries. +--- + +# Data API + +Record CRUD, batch operations, and analytics queries over REST. All paths are relative to the base URL (defaults to `/api/v1`) — see the [API Overview](/docs/api) for discovery and service availability. + +## Data Operations + +CRUD operations on any object. Always available — provided by the kernel. + +### `GET /data/:object` + +Query records with filtering, sorting, selection, and pagination. + +| Parameter | Location | Description | +|:----------|:---------|:------------| +| `object` | path | Object name | +| `select` | query | Comma-separated field names | +| `filter` | query | Filter expression (JSON). `filters` also accepted for backward compatibility. | +| `sort` | query | Sort expression (e.g. `name asc` or `-created_at`) | +| `top` | query | Limit (default: 20) | +| `skip` | query | Offset | +| `expand` | query | Comma-separated list of relations to eager-load | +| `search` | query | Full-text search query | + +> **Note:** OData-style `$`-prefixed parameters (`$filter`, `$select`, `$orderby`, `$top`, `$skip`) are supported via the [OData endpoint](/docs/references/api/odata). The standard REST API uses unprefixed parameter names. + +**Response**: +```json +{ + "object": "account", + "records": [{ "id": "1", "name": "Acme Corp", ... }], + "total": 42, + "hasMore": true +} +``` + +### `GET /data/:object/:id` + +Get a single record by ID. Only `select` and `expand` query parameters are allowed; all other parameters are discarded. + +| Parameter | Location | Description | +|:----------|:---------|:------------| +| `object` | path | Object name | +| `id` | path | Record ID | +| `select` | query | Comma-separated field names to include | +| `expand` | query | Comma-separated list of relations to eager-load | + +**Response**: `{ object: "account", id: "1", record: { ... } }` + +### `POST /data/:object` + +Create a new record. + +**Body**: `{ name: "Acme Corp", industry: "Technology" }` +**Response**: `{ object: "account", id: "1", record: { ... } }` + +### `PATCH /data/:object/:id` + +Update an existing record (partial update). + +**Body**: `{ industry: "Healthcare" }` +**Response**: `{ object: "account", id: "1", record: { ... } }` + +### `DELETE /data/:object/:id` + +Delete a record. + +**Response**: `{ object: "account", id: "1", success: true }` + +--- + +## Batch Operations + +Efficient bulk operations. Always available. + +### `POST /data/:object/batch` + +Execute a batch operation (create / update / upsert / delete) on multiple records. + +**Body**: +```json +{ + "operation": "update", + "records": [ + { "id": "1", "data": { "status": "active" } }, + { "id": "2", "data": { "status": "active" } } + ], + "options": { + "atomic": true, + "returnRecords": true, + "continueOnError": false, + "validateOnly": false + } +} +``` + +**Response**: `BatchUpdateResponse` with `succeeded`, `failed`, `total`, and a per-record `results` array. Each entry in `results` has `id`, `success`, an optional `errors` array, and optional `data` (the full record, present when `returnRecords` is `true`). + +### `POST /data/:object/createMany` + +Batch create multiple records. + +**Body**: a bare array of records — `[{ name: "A" }, { name: "B" }]`. The REST handler reads the request body directly as the records array, so do **not** wrap it in `{ records: [...] }`. +**Response**: `{ object: "account", records: [...], count: 2 }` + +### `POST /data/:object/updateMany` + +Batch update multiple records. + +**Body**: +```json +{ + "records": [ + { "id": "1", "data": { "status": "active" } }, + { "id": "2", "data": { "status": "closed" } } + ], + "options": { "atomic": false } +} +``` + +### `POST /data/:object/deleteMany` + +Batch delete records by ID list. + +**Body**: `{ ids: ["1", "2", "3"] }` + +--- + +### `POST /data/:object/:id/clone` + +Clone a record. Reads the source, drops engine-owned columns (`id`, the audit +fields, autonumbers, and computed `formula`/`summary` values) so they are +re-derived, applies any caller `overrides`, and inserts the copy. Shallow by +design — it duplicates the record's own fields, not its child records. + +Gated by the object's `enable.clone` capability (default `true`); an object with +`enable.clone: false` returns `403 CLONE_DISABLED`. + +**Body** (optional): `{ "overrides": { "name": "Acme (Copy)" } }` — applied on +top of the copied values (a bare field map is also accepted). The natural place +to set a new name or clear a unique field. + +**Response** `201`: `{ object, id, sourceId, record }` + +--- + +## Analytics + +Semantic BI queries using a cube-style API. Available when the analytics service is enabled. + +### `POST /analytics/query` + +Execute an analytics query. + +**Body**: +```json +{ + "cube": "account", + "measures": ["revenue.sum", "count"], + "dimensions": ["industry"], + "where": { "status": "active" }, + "limit": 100 +} +``` + + +Filtering uses the canonical Query DSL `where` object (the same MongoDB-style `FilterCondition` accepted by `find()`), not a `filters` array. + + +**Response**: the runtime dispatcher wraps the `AnalyticsResult` as `{ success: true, data: { rows, fields, sql?, totals? } }`: +```json +{ + "success": true, + "data": { + "rows": [ + { "industry": "Technology", "revenue.sum": 150000, "count": 5 }, + { "industry": "Healthcare", "revenue.sum": 80000, "count": 3 } + ], + "fields": [ + { "name": "industry", "type": "string", "label": "Industry" }, + { "name": "revenue.sum", "type": "number", "label": "Revenue Sum", "format": "$0,0" }, + { "name": "count", "type": "number", "label": "Count" } + ], + "sql": "SELECT ..." + } +} +``` + +### `GET /analytics/meta` + +Get auto-generated cube metadata for all objects. + +**Response**: Array of cube definitions with measures, dimensions, and time dimensions. + +### `POST /analytics/sql` + +Execute a raw SQL analytics query (if supported by driver). + +--- + +## See also + +- [API Overview](/docs/api) — discovery, error handling, and protocol types +- [Metadata & Package API](/docs/api/metadata-api) — schemas, views, and package management diff --git a/content/docs/guides/data-flow.mdx b/content/docs/api/data-flow.mdx similarity index 99% rename from content/docs/guides/data-flow.mdx rename to content/docs/api/data-flow.mdx index b460c97d24..96c6e9ab58 100644 --- a/content/docs/guides/data-flow.mdx +++ b/content/docs/api/data-flow.mdx @@ -8,7 +8,7 @@ description: How data moves through the ObjectStack system — from defineStack( This guide provides detailed diagrams showing how data moves through every layer of the ObjectStack system — from developer configuration to database operations and back to the client. -**Architecture Overview:** For a high-level view of how protocol layers connect, see the [Protocol Relationship Diagram](/docs/guides/cheatsheets/protocol-diagram). +**Architecture Overview:** For a high-level view of how protocol layers connect, see the [Protocol Relationship Diagram](/docs/protocol/diagram). --- diff --git a/content/docs/guides/project-scoping.mdx b/content/docs/api/environment-routing.mdx similarity index 96% rename from content/docs/guides/project-scoping.mdx rename to content/docs/api/environment-routing.mdx index b0895b72f5..4cc050bb3c 100644 --- a/content/docs/guides/project-scoping.mdx +++ b/content/docs/api/environment-routing.mdx @@ -126,6 +126,6 @@ one, so they are intentionally excluded from data-plane resolution. ## Related -- [Single-Environment Mode](./single-project-mode) -- [Deployment Modes](./cloud-deployment) -- [Client SDK](./client-sdk) +- [Single-Environment Mode](/docs/deployment/single-project-mode) +- [Deployment Modes](/docs/deployment) +- [Client SDK](/docs/api/client-sdk) diff --git a/content/docs/guides/cheatsheets/error-catalog.mdx b/content/docs/api/error-catalog.mdx similarity index 99% rename from content/docs/guides/cheatsheets/error-catalog.mdx rename to content/docs/api/error-catalog.mdx index 87f43a0fc1..25ddd34508 100644 --- a/content/docs/guides/cheatsheets/error-catalog.mdx +++ b/content/docs/api/error-catalog.mdx @@ -103,7 +103,7 @@ ObjectStack uses a structured error system with **9 error categories** and **41+ ### `invalid_query` **Cause:** The query structure is malformed. -**Fix:** Check the query syntax against the [Query Cheat Sheet](/docs/guides/cheatsheets/query-cheat-sheet). +**Fix:** Check the query syntax against the [Query Cheat Sheet](/docs/data-modeling/queries). **Retry:** `no_retry` ### `invalid_filter` diff --git a/content/docs/guides/error-handling-client.mdx b/content/docs/api/error-handling-client.mdx similarity index 98% rename from content/docs/guides/error-handling-client.mdx rename to content/docs/api/error-handling-client.mdx index e7953aa0ee..10051297ff 100644 --- a/content/docs/guides/error-handling-client.mdx +++ b/content/docs/api/error-handling-client.mdx @@ -8,7 +8,7 @@ description: Best practices for handling ObjectStack errors in client applicatio This guide covers best practices for handling ObjectStack API errors in client applications — from parsing error responses to displaying validation errors in forms and implementing retry strategies. -**Error Format:** All ObjectStack API errors follow the `ErrorResponseSchema` structure. See [Wire Format](/docs/guides/cheatsheets/wire-format#7-error-response-format) for the full JSON shape. +**Error Format:** All ObjectStack API errors follow the `ErrorResponseSchema` structure. See [Wire Format](/docs/api/wire-format#7-error-response-format) for the full JSON shape. --- @@ -47,7 +47,7 @@ interface ErrorResponse { ``` -Error `code` values are lowercase snake_case (`validation_error`, `permission_denied`, `rate_limit_exceeded`, `resource_not_found`) — see the [Error Catalog](/docs/guides/cheatsheets/error-catalog) for the full list. +Error `code` values are lowercase snake_case (`validation_error`, `permission_denied`, `rate_limit_exceeded`, `resource_not_found`) — see the [Error Catalog](/docs/api/error-catalog) for the full list. --- diff --git a/content/docs/guides/error-handling-server.mdx b/content/docs/api/error-handling-server.mdx similarity index 100% rename from content/docs/guides/error-handling-server.mdx rename to content/docs/api/error-handling-server.mdx diff --git a/content/docs/api/index.mdx b/content/docs/api/index.mdx new file mode 100644 index 0000000000..5b02446b0a --- /dev/null +++ b/content/docs/api/index.mdx @@ -0,0 +1,184 @@ +--- +title: API Overview +description: How ObjectStack generates its API surface from metadata — discovery, error handling wire formats, protocol types, and a map of the API & SDK docs. +--- + +# API Overview + +ObjectStack generates its entire API surface — REST endpoints, realtime protocols, and the client SDK — from your metadata: define an object once and its endpoints exist. This module documents those surfaces and how to consume them. + +ObjectStack exposes a fully typed REST API. All endpoints use JSON request/response bodies. The API is **service-driven** — routes are only available when the corresponding plugin is installed. Use the [Discovery endpoint](#discovery) to determine what services are available at runtime. + + +**Base URL**: Configurable, defaults to `/api/v1`. All paths below are relative to the base URL. + + +## What's in this module + +- [Data API](/docs/api/data-api) — CRUD, batch operations, record cloning, and analytics queries +- [Metadata & Package API](/docs/api/metadata-api) — object schemas, metadata types, UI views, and package management +- [Plugin Endpoints](/docs/api/plugin-endpoints) — auth, workflow, realtime, and other plugin-provided routes +- [Client SDK](/docs/api/client-sdk) — the official TypeScript client +- [Environment Routing](/docs/api/environment-routing) — routing requests across environments +- [Data Flow](/docs/api/data-flow) — how a request travels through the stack +- [Error Handling (Client)](/docs/api/error-handling-client) — handling API errors in client code +- [Error Handling (Server)](/docs/api/error-handling-server) — raising and shaping errors on the server +- [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) + +Schema reference: [API](/docs/references/api) + +--- + +## Discovery + +The discovery endpoint is the entry point for all clients. It returns the API version, available routes, service capabilities, and per-service status. + +### `GET /api/v1` + +Returns the full discovery manifest. + +**Response**: +```json +{ + "name": "ObjectOS", + "version": "1.0.0", + "environment": "development", + "routes": { + "data": "/api/v1/data", + "metadata": "/api/v1/meta", + "analytics": "/api/v1/analytics", + "auth": null, + "workflow": null + }, + "features": { + "graphql": false, + "search": false, + "websockets": false, + "files": false, + "analytics": true, + "ai": false, + "workflow": false, + "notifications": false, + "i18n": false + }, + "services": { + "metadata": { + "enabled": true, + "status": "degraded", + "route": "/api/v1/meta", + "provider": "kernel", + "message": "In-memory registry; DB persistence pending" + }, + "data": { "enabled": true, "status": "available", "route": "/api/v1/data", "provider": "kernel" }, + "analytics": { "enabled": true, "status": "available", "route": "/api/v1/analytics" }, + "auth": { "enabled": false, "status": "unavailable", "message": "Install an auth plugin to enable" } + }, + "locale": { + "default": "en", + "supported": ["en", "zh-CN"], + "timezone": "UTC" + } +} +``` + +### `GET /.well-known/objectstack` + +Alias for the discovery endpoint used by auto-discovery in the client SDK. + + +**Service Status Values**: `available` (fully operational), `registered` (route declared but handler unverified — may return 501), `degraded` (partial functionality), `unavailable` (not installed), `stub` (placeholder that throws errors) + + +--- + +## Error Handling + +Error responses depend on which HTTP server is in front of the kernel. There are two wire formats in use today. + +**Kernel REST server** (`@objectstack/rest`) emits a string `error` message plus a SCREAMING_SNAKE `code`: + +```json +{ + "error": "Record not found: account/123", + "code": "RECORD_NOT_FOUND" +} +``` + +Validation failures additionally include an `issues` array. Common codes emitted by the kernel REST server: + +| Code | HTTP | Description | +|:-----|:-----|:------------| +| `VALIDATION_FAILED` | 400 | Input validation failed (includes `issues`) | +| `PERMISSION_DENIED` | 403 | Insufficient permissions | +| `RECORD_NOT_FOUND` | 404 | Resource does not exist | +| `CONCURRENT_UPDATE` | 409 | Record was modified by another user | + +**Runtime dispatcher** (`@objectstack/runtime`) wraps errors in the `{ success: false, ... }` envelope, where `code` is the numeric HTTP status: + +```json +{ + "success": false, + "error": { + "message": "Record not found: account/123", + "code": 404, + "details": {} + } +} +``` + + +The richer `ErrorResponseSchema` in `@objectstack/spec/api` (with `category`, `retryable`, etc.) is the aspirational spec envelope, not the current wire format. Its `category` values are drawn from the `ErrorCategory` enum: `validation`, `authentication`, `authorization`, `not_found`, `conflict`, `rate_limit`, `server`, `external`, `maintenance`. + + +--- + +## Protocol Types (Zod) + +All request/response schemas are defined as Zod schemas in `@objectstack/spec/api` and can be used for both runtime validation and TypeScript type inference. + +```typescript +import { + FindDataRequestSchema, + FindDataResponseSchema, + type FindDataRequest, + type FindDataResponse, +} from '@objectstack/spec/api'; + +// Runtime validation +const request = FindDataRequestSchema.parse({ object: 'account', query: { ... } }); + +// TypeScript type +const response: FindDataResponse = await protocol.findData(request); +``` + +See the [Protocol Reference](/docs/references/api/protocol) for the full list of protocol methods and their Zod schemas. + +--- + +## Next Steps + + + + + + + diff --git a/content/docs/api/meta.json b/content/docs/api/meta.json new file mode 100644 index 0000000000..0d3ef025cc --- /dev/null +++ b/content/docs/api/meta.json @@ -0,0 +1,17 @@ +{ + "title": "API & SDK", + "icon": "Plug", + "pages": [ + "index", + "data-api", + "metadata-api", + "plugin-endpoints", + "client-sdk", + "environment-routing", + "data-flow", + "error-handling-client", + "error-handling-server", + "error-catalog", + "wire-format" + ] +} diff --git a/content/docs/api/metadata-api.mdx b/content/docs/api/metadata-api.mdx new file mode 100644 index 0000000000..3d6dbda821 --- /dev/null +++ b/content/docs/api/metadata-api.mdx @@ -0,0 +1,98 @@ +--- +title: Metadata & Package API +description: REST endpoints for object schemas, metadata types, UI views, and package management. +--- + +# Metadata & Package API + +Manage object schemas, metadata types, UI views, and installed packages over REST. All paths are relative to the base URL (defaults to `/api/v1`) — see the [API Overview](/docs/api) for discovery and service availability. + +## Metadata + +Retrieve and manage object schemas, metadata types, and UI views. Always available — provided by the kernel. + +### `GET /meta` + +List all registered metadata types. + +**Response**: `{ types: ["object", "view", "plugin", ...] }` + +### `GET /meta/:type` + +List all items of a metadata type. + +| Parameter | Location | Description | +|:----------|:---------|:------------| +| `type` | path | Metadata type name (e.g. `object`, `view`) | + +**Response**: `{ type: "object", items: [{ name: "account", ... }, ...] }` + +### `GET /meta/:type/:name` + +Get a specific metadata item with optional ETag caching. + +| Parameter | Location | Description | +|:----------|:---------|:------------| +| `type` | path | Metadata type name | +| `name` | path | Item name (snake_case) | +| `If-None-Match` | header | ETag for conditional request | + +**Response**: `{ type: "object", name: "account", item: { ... } }` +**304** if ETag matches (not modified). + +### `PUT /meta/:type/:name` + +Create or update a metadata item. + +**Body**: `{ type: "object", name: "account", item: { ... } }` +**Response**: `{ success: true }` + +### `GET /ui/view/:object/:type` + +Get an auto-generated UI view for an object. + +| Parameter | Location | Description | +|:----------|:---------|:------------| +| `object` | path | Object name (snake_case) | +| `type` | path | `list` or `form` | + +**Response**: Full `ViewSchema` definition with columns/fields derived from the object schema. + +--- + +## Package Management + +Manage installed plugins/packages. + +### `GET /packages` + +List installed packages. + +### `POST /packages` + +Install a package from manifest. + +**Body**: `{ manifest: { name: "plugin-auth", version: "1.0.0", ... } }` + +### `GET /packages/:id` + +Get package details. + +### `DELETE /packages/:id` + +Uninstall a package. + +### `PATCH /packages/:id/enable` + +Enable a disabled package. + +### `PATCH /packages/:id/disable` + +Disable a package without uninstalling. + +--- + +## See also + +- [API Overview](/docs/api) — discovery, error handling, and protocol types +- [Data API](/docs/api/data-api) — CRUD, batch operations, and analytics diff --git a/content/docs/api/plugin-endpoints.mdx b/content/docs/api/plugin-endpoints.mdx new file mode 100644 index 0000000000..f449bad69f --- /dev/null +++ b/content/docs/api/plugin-endpoints.mdx @@ -0,0 +1,113 @@ +--- +title: Plugin Endpoints +description: REST endpoints that become available when the corresponding plugin is installed — auth, workflow, automation, views, realtime, notifications, AI, i18n, GraphQL, and file storage. +--- + +# Plugin Endpoints + +These REST endpoints are only available when the corresponding plugin is installed. Check the [discovery manifest](/docs/api#discovery) `services` map before calling them; all paths are relative to the base URL (defaults to `/api/v1`). + +## Authentication (Plugin Required) + + +These endpoints are only available when an auth plugin is installed. Check `discovery.services.auth.enabled` first. + + +### `POST /auth/login` + +Authenticate and receive a session token. + +**Body**: `{ username: "admin", password: "secret" }` +**Response**: `{ token: "jwt...", expiresAt: "...", user: { ... } }` + +--- + +## Plugin-Provided Service Endpoints + +The following endpoints become available when the corresponding plugin is installed and registered with the kernel. Use the discovery `services` map to check availability. + +### Workflow (`/workflow`) — Plugin Required + +| Method | Endpoint | Description | +|:-------|:---------|:------------| +| GET | `/workflow/:object/config` | Get workflow configuration | +| GET | `/workflow/:object/:recordId/state` | Get record's workflow state | +| POST | `/workflow/:object/:recordId/transition` | Execute state transition | +| POST | `/workflow/:object/:recordId/approve` | Approve workflow step | +| POST | `/workflow/:object/:recordId/reject` | Reject workflow step | + +### Automation (`/automation`) — Plugin Required + +| Method | Endpoint | Description | +|:-------|:---------|:------------| +| POST | `/automation/trigger/:name` | Trigger an automation flow by name | + +### Views (`/ui`) — Plugin Required + +| Method | Endpoint | Description | +|:-------|:---------|:------------| +| GET | `/ui/views?object=:object` | List views for an object | +| GET | `/ui/views/:viewId` | Get a view definition | +| POST | `/ui/views` | Create a new view | +| PATCH | `/ui/views/:viewId` | Update a view | +| DELETE | `/ui/views/:viewId` | Delete a view | + +### Realtime (`/realtime`) — Plugin Required + +| Method | Endpoint | Description | +|:-------|:---------|:------------| +| POST | `/realtime/connect` | Establish WebSocket/SSE connection | +| POST | `/realtime/disconnect` | Close connection | +| POST | `/realtime/subscribe` | Subscribe to channel | +| POST | `/realtime/unsubscribe` | Unsubscribe | +| POST | `/realtime/presence` | Set presence | +| GET | `/realtime/presence/:channel` | Get channel presence | + +### Notifications (`/notifications`) — Plugin Required + +| Method | Endpoint | Description | +|:-------|:---------|:------------| +| GET | `/notifications` | List notifications (inbox) | +| POST | `/notifications/read` | Mark notifications as read (body: `{ ids: string[] }`) | +| POST | `/notifications/read/all` | Mark all as read | + + +The core dispatcher implements only the list / read / read-all routes above. Device-registration and preference endpoints are provided by specific notification plugins, if any. + + +### AI (`/ai`) — Plugin Required + +| Method | Endpoint | Description | +|:-------|:---------|:------------| +| POST | `/ai/nlq` | Natural language → query | +| POST | `/ai/chat` | AI chat conversation | +| POST | `/ai/suggest` | Get value suggestions | +| POST | `/ai/insights` | Get data insights | + +### i18n (`/i18n`) — Plugin Required + +| Method | Endpoint | Description | +|:-------|:---------|:------------| +| GET | `/i18n/locales` | List available locales | +| GET | `/i18n/translations/:locale` | Get translation bundle | +| GET | `/i18n/labels/:object/:locale` | Get field labels | + +### GraphQL (`/graphql`) — Plugin Required + +| Method | Endpoint | Description | +|:-------|:---------|:------------| +| POST | `/graphql` | Execute GraphQL query/mutation | + +### File Storage (`/storage`) — Plugin Required + +| Method | Endpoint | Description | +|:-------|:---------|:------------| +| POST | `/storage/upload` | Upload a file | +| GET | `/storage/file/:id` | Download a file | + +--- + +## See also + +- [API Overview](/docs/api) — discovery, error handling, and protocol types +- [Client SDK](/docs/api/client-sdk) — service-aware TypeScript client that adapts to installed plugins diff --git a/content/docs/guides/cheatsheets/wire-format.mdx b/content/docs/api/wire-format.mdx similarity index 98% rename from content/docs/guides/cheatsheets/wire-format.mdx rename to content/docs/api/wire-format.mdx index 3cc490a868..92b17ab6f5 100644 --- a/content/docs/guides/cheatsheets/wire-format.mdx +++ b/content/docs/api/wire-format.mdx @@ -385,7 +385,7 @@ Returned when an `If-Match` / `expectedVersion` token no longer matches the stor ``` -**Error Codes:** See the [Error Catalog](/docs/guides/cheatsheets/error-catalog) for the complete list of error codes and their meanings. +**Error Codes:** See the [Error Catalog](/docs/api/error-catalog) for the complete list of error codes and their meanings. --- diff --git a/content/docs/guides/solutions/approval-workflow.mdx b/content/docs/automation/approvals.mdx similarity index 63% rename from content/docs/guides/solutions/approval-workflow.mdx rename to content/docs/automation/approvals.mdx index e835089233..175285a35e 100644 --- a/content/docs/guides/solutions/approval-workflow.mdx +++ b/content/docs/automation/approvals.mdx @@ -15,7 +15,7 @@ An approval is a **flow** with an **approval node**. Two access decisions matter ### 1. Who can configure it -Authoring flows/automations is a builder capability — it needs `manage_metadata` (typically Studio users). End users **submit** records and **act on** approval requests, but they do not edit the automation. Keep the automation surfaces out of consumer apps (see [role-based interfaces](/docs/guides/solutions/role-based-interfaces)). +Authoring flows/automations is a builder capability — it needs `manage_metadata` (typically Studio users). End users **submit** records and **act on** approval requests, but they do not edit the automation. Keep the automation surfaces out of consumer apps (see [role-based interfaces](/docs/ui/role-based-interfaces)). ### 2. As whom does it run — the safety decision @@ -45,6 +45,73 @@ defineFlow({ Approving is itself a gated action — model "may approve" as a capability (`approve_invoice`) the approver role holds, and gate the approve action's `requiredPermissions` on it so the gate is enforced on **both** the UI and the server (ADR-0066 D4). +## Approval nodes in practice + +Approvals are authored as Flow nodes with `type: 'approval'`. The +`@objectstack/plugin-approvals` package owns the durable approval state +(`sys_approval_request` and `sys_approval_action`), record locking, approver +resolution, and resume-on-decision behavior. + +```typescript +export const opportunityApproval: Flow = { + name: 'opportunity_approval', + label: 'Opportunity Approval', + type: 'record_change', + status: 'active', + nodes: [ + { + id: 'start', + type: 'start', + label: 'Start', + config: { + triggerType: 'record-after-update', + objectName: 'opportunity', + condition: "record.amount >= 50000 && record.stage == 'proposal'", + }, + }, + { + id: 'manager_approval', + type: 'approval', + label: 'Manager Approval', + config: { + approvers: [{ type: 'user', value: '${record.owner_manager_id}' }], + behavior: 'unanimous', + approvalStatusField: 'approval_status', + lockRecord: true, + }, + }, + { id: 'mark_approved', type: 'update_record', label: 'Mark Approved' }, + { id: 'mark_rejected', type: 'update_record', label: 'Mark Rejected' }, + { id: 'end', type: 'end', label: 'End' }, + ], + edges: [ + { id: 'e1', source: 'start', target: 'manager_approval' }, + { id: 'approved', source: 'manager_approval', target: 'mark_approved', label: 'approve' }, + { id: 'rejected', source: 'manager_approval', target: 'mark_rejected', label: 'reject' }, + { id: 'e4', source: 'mark_approved', target: 'end' }, + { id: 'e5', source: 'mark_rejected', target: 'end' }, + ], +}; +``` + +For multi-step approvals, chain multiple `approval` nodes. For parallel +approvals, see the aggregating-node pattern in [Flow Metadata](/docs/automation/flows). + +### Best practices + +✅ **DO:** +- Define clear entry criteria +- Set reasonable timeout periods +- Allow recall when appropriate +- Notify all stakeholders +- Track approval history + +❌ **DON'T:** +- Create too many approval steps +- Make approvals too complex +- Forget rejection paths +- Hard-code approvers + ## Why Separating *who configures* from *who approves* from *as whom it runs* is the same capability/assignment/requirement decoupling as the rest of authorization (ADR-0066). The `runAs` default of `user` means an approval flow can't silently grant the submitter cross-tenant or cross-owner reach — elevation is opt-in and auditable. That is the safe-by-default posture: the common case respects RLS; the elevated case is explicit. @@ -63,5 +130,5 @@ Separating *who configures* from *who approves* from *as whom it runs* is the sa ## See also - Decision records: **ADR-0049** (`runAs`), **ADR-0066** (unified authorization). -- Guide: [Business Logic](/docs/guides/business-logic) (Flows, Approval Nodes); [Who can see data / automation / interface](/docs/guides/solutions/data-automation-interface-access). +- Guide: [Business Logic](/docs/automation/hooks) (Flows, Approval Nodes); [Who can see data / automation / interface](/docs/permissions/access-recipes). - Reference: [Flow](/docs/references/automation/flow), [Approval](/docs/references/automation/approval). diff --git a/content/docs/guides/metadata/flow.mdx b/content/docs/automation/flows.mdx similarity index 85% rename from content/docs/guides/metadata/flow.mdx rename to content/docs/automation/flows.mdx index 9434ab73e5..e5b83b3ffa 100644 --- a/content/docs/guides/metadata/flow.mdx +++ b/content/docs/automation/flows.mdx @@ -560,8 +560,146 @@ the active project. All three components participate in the Studio authentication / project-scope context, so they work identically in single-project mode and in cloud mode. +## Flows in practice + +Flows automate business processes as explicit node graphs. Use them for field +updates, notifications, record creation, HTTP calls, decisions, waits, screens, +subflows, and approval pauses. The old standalone Workflow Rule authoring model +is retired; model the same logic as a Flow. + +### Record-change flow + +```typescript +import type { Flow } from '@objectstack/spec/automation'; + +export const hotLeadFollowUp: Flow = { + name: 'hot_lead_follow_up', + label: 'Hot Lead Follow Up', + type: 'record_change', + status: 'active', + nodes: [ + { + id: 'start', + type: 'start', + label: 'Start', + config: { + triggerType: 'record-after-create', + objectName: 'lead', + condition: "record.rating == 'hot'", + }, + }, + { + id: 'create_task', + type: 'create_record', + label: 'Create Follow-up Task', + config: { + object: 'task', + data: { + subject: 'Follow up on hot lead', + related_to: '${record.id}', + priority: 'high', + }, + }, + }, + { + id: 'notify_owner', + type: 'notify', + label: 'Notify Owner', + config: { + channel: 'in_app', + template: 'hot_lead_created', + }, + }, + { id: 'end', type: 'end', label: 'End' }, + ], + edges: [ + { id: 'e1', source: 'start', target: 'create_task' }, + { id: 'e2', source: 'create_task', target: 'notify_owner' }, + { id: 'e3', source: 'notify_owner', target: 'end' }, + ], +}; +``` + +### Scheduled flow + +```typescript +export const contractExpirationCheck: Flow = { + name: 'contract_expiration_check', + label: 'Contract Expiration Check', + type: 'schedule', + status: 'active', + nodes: [ + { + id: 'start', + type: 'start', + label: 'Start', + config: { + triggerType: 'schedule', + schedule: { type: 'cron', expression: '0 0 * * *', timezone: 'UTC' }, + }, + }, + { id: 'find_expiring', type: 'get_record', label: 'Find Expiring Contracts' }, + { id: 'notify_owners', type: 'notify', label: 'Notify Owners' }, + { id: 'end', type: 'end', label: 'End' }, + ], + edges: [ + { id: 'e1', source: 'start', target: 'find_expiring' }, + { id: 'e2', source: 'find_expiring', target: 'notify_owners' }, + { id: 'e3', source: 'notify_owners', target: 'end' }, + ], +}; +``` + +### Update-triggered flow + +Trigger on a record update and compare against the previous value: + +```typescript +// Flow: Update probability +flows: [ + { + name: 'update_probability', + label: 'Update Probability', + type: 'record_change', + status: 'active', + nodes: [ + { + id: 'start', + type: 'start', + label: 'Start', + config: { + triggerType: 'record-after-update', + objectName: 'opportunity', + condition: 'record.stage != previous.stage', + }, + }, + { id: 'update_probability', type: 'update_record', label: 'Update Probability' }, + { id: 'end', type: 'end', label: 'End' }, + ], + edges: [ + { id: 'e1', source: 'start', target: 'update_probability' }, + { id: 'e2', source: 'update_probability', target: 'end' }, + ], + }, +], +``` + +### Best practices + +✅ **DO:** +- Keep flows simple and focused +- Document the business logic +- Test recursion and retry behavior +- Use scheduled flows for batch updates + +❌ **DON'T:** +- Create uncontrolled loops +- Update too many fields in one node +- Use triggers when a declarative flow is enough +- Mix unrelated concerns in one flow + ## Related -- [Workflow Metadata](./workflow) — Event-triggered automation rules -- [Object Metadata](./object) — Objects that flows operate on -- [Validation Metadata](./validation) — Data validation rules +- [Workflow Metadata](/docs/automation/workflows) — Event-triggered automation rules +- [Object Metadata](/docs/data-modeling/objects) — Objects that flows operate on +- [Validation Metadata](/docs/data-modeling/validation) — Data validation rules diff --git a/content/docs/guides/hook-bodies.mdx b/content/docs/automation/hook-bodies.mdx similarity index 97% rename from content/docs/guides/hook-bodies.mdx rename to content/docs/automation/hook-bodies.mdx index 27f3c75342..c3c6282ef4 100644 --- a/content/docs/guides/hook-bodies.mdx +++ b/content/docs/automation/hook-bodies.mdx @@ -71,7 +71,7 @@ Pure formula. No IO, no mutation. Used for: { "language": "expression", "source": "input.amount > 1000 && input.status == 'open'" } ``` -Evaluated by the same formula engine that powers field formulas — see [Formula Reference](./formula). +Evaluated by the same formula engine that powers field formulas — see [Formula Reference](/docs/data-modeling/formulas). ## L2 — Sandboxed JS bodies @@ -237,9 +237,9 @@ objectstack.config.ts ## See also -- [Formula Reference](./formula) — the L1 expression engine. -- [Business Logic](./business-logic) — broader patterns for hooks, actions, flows. -- [Cloud Deployment](./cloud-deployment) — how artifacts travel from Studio to objectos. +- [Formula Reference](/docs/data-modeling/formulas) — the L1 expression engine. +- [Business Logic](/docs/automation/hooks) — broader patterns for hooks, actions, flows. +- [Cloud Deployment](/docs/deployment) — how artifacts travel from Studio to objectos. - `packages/spec/src/data/hook-body.zod.ts` — canonical Zod schema. - `packages/runtime/src/sandbox/script-runner.ts` — engine decision rationale. - `packages/cli/src/utils/extract-hook-body.ts` — extractor + capability inference. diff --git a/content/docs/automation/hooks.mdx b/content/docs/automation/hooks.mdx new file mode 100644 index 0000000000..5d11601910 --- /dev/null +++ b/content/docs/automation/hooks.mdx @@ -0,0 +1,115 @@ +--- +title: Hooks +description: Run custom code at interception points in the ObjectQL execution pipeline — before/after insert, update, delete, and find +--- + +# Hooks + +Hooks are the data-layer "logic layer": they run custom code at interception +points in the ObjectQL execution pipeline (before/after insert, update, delete, +find, etc.). The construct is `Hook`, imported from `@objectstack/spec/data`. + +A hook targets one or more `object`s and subscribes to one or more lifecycle +`events`. Each event is a combined timing+action enum value, e.g. +`beforeInsert`, `beforeUpdate`, `afterUpdate`, `afterDelete` (read-side events +such as `beforeFind`/`afterFind` are also available). + +## Before Hook + +Mutate the incoming record before it is saved. The pending record lives on +`ctx.input` (`ctx.input.doc` for insert/update): + +```typescript +import { Hook } from '@objectstack/spec/data'; + +export const AccountBeforeWrite: Hook = { + name: 'account_before_write', + object: 'account', + events: ['beforeInsert', 'beforeUpdate'], + + handler: async (ctx) => { + const record = ctx.input.doc as Record; + + // Normalize phone numbers + if (record.phone) { + record.phone = normalizePhone(record.phone); + } + + // Auto-populate from website + if (!record.industry && record.website) { + record.industry = await lookupIndustry(record.website); + } + }, +}; +``` + +## After Hook + +React after a record is persisted. Use `ctx.previous` for the pre-change +snapshot and `ctx.api.object('x')` for cross-object writes: + +```typescript +export const OpportunityAfterUpdate: Hook = { + name: 'opportunity_after_update', + object: 'opportunity', + events: ['afterUpdate'], + + handler: async (ctx) => { + const opp = ctx.result as Record; + const wasWon = ctx.previous?.stage === 'closed_won'; + + if (opp.stage === 'closed_won' && !wasWon) { + // Create a contract via the scoped cross-object API + await ctx.api.object('contract').insert({ + account: opp.account, + opportunity: opp.id, + contract_value: opp.amount, + start_date: new Date(), + }); + } + }, +}; +``` + +## Hook Context + +`handler` receives a `HookContext` with these fields: + +```typescript +ctx = { + id, // tracing id + object, // target object name + event, // e.g. 'beforeInsert' | 'afterUpdate' + input, // mutable input (e.g. input.doc for insert/update) + result, // mutable operation result (after* events) + previous, // record state before the operation (update/delete) + session, // { userId, tenantId, roles, accessToken, isSystem } + user, // { id, name, email } convenience shortcut + transaction, // active transaction handle, if any + ql, // ObjectQL engine reference + api, // scoped cross-object access: ctx.api.object('x') +} +``` + +## Best Practices + +✅ **DO:** +- Use before hooks to enrich/normalize the incoming record +- Use after hooks for related-record side effects +- Use `ctx.api.object('x')` for cross-object access so writes stay in scope +- Handle errors gracefully + +❌ **DON'T:** +- Query in loops +- Trigger unbounded cascades of writes +- Perform heavy/long-running work inline in a hook +- Mutate `ctx.result` in before hooks (it is only populated for after hooks) + +## Related business logic + +Hooks are one of several business-logic layers. Topics formerly covered on this page now live on their own pages: + +- Validation rules → [/docs/data-modeling/validation](/docs/data-modeling/validation) +- Formula logic → [/docs/data-modeling/formulas](/docs/data-modeling/formulas) +- Flows → [/docs/automation/flows](/docs/automation/flows) +- Approval nodes → [/docs/automation/approvals](/docs/automation/approvals) diff --git a/content/docs/automation/index.mdx b/content/docs/automation/index.mdx new file mode 100644 index 0000000000..fa739732f4 --- /dev/null +++ b/content/docs/automation/index.mdx @@ -0,0 +1,35 @@ +--- +title: Automation +description: Hooks, flows, workflows, approvals, and webhooks — the process engine that reacts to data changes and drives business processes. +--- + +# Automation + +Automation is ObjectStack's process engine: it lets you attach business logic to your data model **declaratively** — as metadata — instead of scattering it through application code. It is a cross-protocol capability: automations are declared in the Automation Protocol namespace and executed by the ObjectOS runtime against ObjectQL data. + +## The building blocks + +- **Hooks** run custom logic before/after record operations (create, update, delete) — the workhorse for validation-with-side-effects, denormalization, and integrations. +- **Flows** are node-based visual logic (screen flows, autolaunched flows, scheduled flows). +- **Workflows** model a record's lifecycle as a **finite state machine**: states, transitions, and guards. +- **Approvals** add human sign-off steps to a process. +- **Webhooks** deliver events to external systems over HTTP with retry semantics. + +Rule of thumb: model *state* with workflows, model *steps* with flows, use hooks for *code-level* reactions, and webhooks to *notify the outside world*. + +## What's in this module + + + + + + + + + + +## Related + +- **Spec:** [State Machine (Lifecycle)](/docs/protocol/objectql/state-machine), [Runtime Capabilities](/docs/protocol/objectos/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/automation/meta.json b/content/docs/automation/meta.json new file mode 100644 index 0000000000..7b9c2678b7 --- /dev/null +++ b/content/docs/automation/meta.json @@ -0,0 +1,13 @@ +{ + "title": "Automation", + "icon": "Workflow", + "pages": [ + "index", + "hooks", + "hook-bodies", + "flows", + "workflows", + "approvals", + "webhooks" + ] +} diff --git a/content/docs/concepts/webhook-delivery.mdx b/content/docs/automation/webhooks.mdx similarity index 100% rename from content/docs/concepts/webhook-delivery.mdx rename to content/docs/automation/webhooks.mdx diff --git a/content/docs/guides/metadata/workflow.mdx b/content/docs/automation/workflows.mdx similarity index 100% rename from content/docs/guides/metadata/workflow.mdx rename to content/docs/automation/workflows.mdx diff --git a/content/docs/concepts/architecture.mdx b/content/docs/concepts/architecture.mdx index c9a6ce769a..665cb8f242 100644 --- a/content/docs/concepts/architecture.mdx +++ b/content/docs/concepts/architecture.mdx @@ -83,7 +83,7 @@ ObjectStack enforces **Separation of Concerns** through protocol boundaries: ### Example: Defining a Customer Object ```typescript -// packages/crm/src/objects/customer.object.ts +// src/objects/customer.object.ts import { ObjectSchema, Field } from '@objectstack/spec/data'; export const Customer = ObjectSchema.create({ @@ -143,14 +143,13 @@ That's the job of the other layers. ### Example: Permission Rules ```typescript -// packages/crm/src/permissions/sales_rep.permission.ts -import { definePermissionSet } from '@objectstack/spec/security'; +// src/permissions/sales_rep.permission.ts +import { definePermissionSet } from '@objectstack/spec'; -// A permission set is keyed by object name. Each object grants the four -// CRUD verbs (allowCreate / allowRead / allowEdit / allowDelete), and -// optional field-level security keyed by "object.field". -export const SalesRep = definePermissionSet({ +// A permission set (here used as a profile) keyed by object and field. +export const SalesRepPermission = definePermissionSet({ name: 'sales_rep', + label: 'Sales Rep', isProfile: true, objects: { customer: { @@ -161,6 +160,7 @@ export const SalesRep = definePermissionSet({ }, }, fields: { + // . -> field-level security 'customer.annual_revenue': { readable: true, editable: false }, // Read-only }, }); @@ -168,26 +168,26 @@ export const SalesRep = definePermissionSet({ ### Example: Workflow Automation -Automations are authored with `defineFlow`. A flow is a **node graph** — -a typed `start`/`end` plus decision and action nodes wired together by -`edges` — driven by a trigger `type` (here `record_change`): - ```typescript -// packages/crm/src/flows/high_value_customer.flow.ts +// src/flows/high_value_customer.flow.ts import { defineFlow } from '@objectstack/spec'; -export const HighValueCustomer = defineFlow({ +// Automation is authored as a Flow: a graph of nodes connected by edges. +// A record_change flow runs when records of its target object change; branch +// edges carry CEL conditions evaluated against the changed record. +export const HighValueCustomerFlow = defineFlow({ name: 'high_value_customer', - label: 'High-Value Customer Routing', - type: 'record_change', // runs when a customer record changes + label: 'High-Value Customer Alert', + type: 'record_change', + status: 'active', nodes: [ { id: 'start', type: 'start', label: 'Customer created' }, - { id: 'assign', type: 'action', label: 'Assign to enterprise team' }, - { id: 'notify', type: 'action', label: 'Alert sales leadership' }, + { id: 'assign', type: 'update_record', label: 'Assign owner' }, + { id: 'notify', type: 'send_email', label: 'Alert leadership' }, { id: 'end', type: 'end', label: 'End' }, ], edges: [ - // Only branch when annual_revenue > 1,000,000 (CEL condition) + // Only continue when annual revenue exceeds $1M. { id: 'e1', source: 'start', target: 'assign', condition: 'record.annual_revenue > 1000000' }, { id: 'e2', source: 'assign', target: 'notify' }, { id: 'e3', source: 'notify', target: 'end' }, @@ -195,12 +195,7 @@ export const HighValueCustomer = defineFlow({ }); ``` - -The node/edge wiring above is illustrative. For the full set of node types, -trigger semantics, and condition syntax, see the -[automation skill](/docs/protocol/objectos) and the `defineFlow` schema in -`@objectstack/spec/automation`. - +See the [Automation Protocol](/docs/protocol/objectos) for the full Flow node and edge reference. ObjectOS **orchestrates** these rules at runtime, independent of the data structure or UI. @@ -220,17 +215,22 @@ ObjectOS **orchestrates** these rules at runtime, independent of the data struct ### Example: List View ```typescript -// packages/crm/src/views/customer.view.ts +// src/views/customer.view.ts import { defineView } from '@objectstack/spec'; -// A view is a container bound to an object; its `list` slot holds the -// list-view config. Columns are field names; sort is { field, order }. +// A view is authored with defineView({ list, form }); the list/form configs +// are nested, and the data source declares which object the view reads. export const CustomerView = defineView({ - object: 'customer', list: { - label: 'All Customers', type: 'grid', - columns: ['name', 'industry', 'annual_revenue', 'primary_contact'], + data: { provider: 'object', object: 'customer' }, + columns: [ + { field: 'name' }, + { field: 'industry' }, + { field: 'annual_revenue' }, + { field: 'primary_contact' }, + ], + filterableFields: ['industry', 'annual_revenue'], sort: [{ field: 'name', order: 'asc' }], }, }); @@ -239,20 +239,18 @@ export const CustomerView = defineView({ ### Example: Form View ```typescript -// packages/crm/src/views/customer.view.ts +// src/views/customer.view.ts import { defineView } from '@objectstack/spec'; -// The same view container can also carry a `form` slot. A form is laid out -// with `sections`, each section listing the fields it renders. +// The same defineView container also carries the form layout. A form is a +// list of sections, each holding fields. export const CustomerView = defineView({ - object: 'customer', form: { - label: 'Customer Details', - type: 'tabbed', + type: 'simple', + data: { provider: 'object', object: 'customer' }, sections: [ { label: 'Company Information', - columns: 2, fields: ['name', 'industry', 'annual_revenue'], }, { @@ -275,10 +273,10 @@ The UI doesn't "know" the field types. It asks ObjectQL for the schema and rende Let's trace a **real-world scenario**: A sales rep creates a new high-value customer. -The snippets in this walkthrough (`Auth.getCurrentUser`, `Permission.check`, -`ObjectQL.getSchema`, `driver.insert`, `Workflow.getTriggersFor`, …) are -**conceptual pseudo-code** that illustrate the control flow between layers. -They are not literal exported APIs — don't search for these exact symbols. +The TypeScript in Steps 2–6 below is **conceptual pseudo-code** illustrating the +flow of control between layers. Calls like `Auth.getCurrentUser()`, +`Permission.check()`, `ObjectQL.getSchema()`, and `Workflow.getTriggersFor()` are +not real exported APIs — they stand in for the kernel's internal orchestration. ### Step 1: User Action (ObjectUI) @@ -424,14 +422,15 @@ export const Opportunity = ObjectSchema.create({ ```typescript import { defineFlow } from '@objectstack/spec'; -export const OpportunityWon = defineFlow({ +export const OpportunityWonFlow = defineFlow({ name: 'opportunity_won', - label: 'On Opportunity Won', + label: 'Opportunity Closed Won', type: 'record_change', + status: 'active', nodes: [ { id: 'start', type: 'start', label: 'Stage changed' }, - { id: 'invoice', type: 'action', label: 'Create invoice' }, - { id: 'notify', type: 'action', label: 'Notify sales team' }, + { id: 'invoice', type: 'create_record', label: 'Create invoice' }, + { id: 'notify', type: 'send_email', label: 'Notify sales team' }, { id: 'end', type: 'end', label: 'End' }, ], edges: [ @@ -447,18 +446,19 @@ export const OpportunityWon = defineFlow({ ```typescript import { defineView } from '@objectstack/spec'; -// For a kanban list, set type: 'kanban' and put the board config under -// `kanban` (groupByField selects the column axis). `columns` is the list -// of card fields. Drag-and-drop between columns is built in. -export const OpportunityBoard = defineView({ - object: 'opportunity', +export const OpportunityKanbanView = defineView({ list: { type: 'kanban', - columns: ['title', 'amount', 'customer'], + data: { provider: 'object', object: 'opportunity' }, + columns: [ + { field: 'title' }, + { field: 'amount' }, + { field: 'customer' }, + ], + // Kanban-specific config: group columns by the stage field. kanban: { groupByField: 'stage', summarizeField: 'amount', - columns: ['title', 'amount'], }, }, }); diff --git a/content/docs/concepts/core/index.mdx b/content/docs/concepts/core/index.mdx deleted file mode 100644 index 7588fdb0b6..0000000000 --- a/content/docs/concepts/core/index.mdx +++ /dev/null @@ -1,56 +0,0 @@ ---- -title: Introduction -description: The Core Microkernel of ObjectStack ---- - -# ObjectStack Core - -The `@objectstack/core` package is the **Microkernel** of the ObjectStack operating system. It provides the minimal runtime environment required to load plugins, manage dependencies, and orchestrate the system lifecycle. - -Similar to how the Linux Kernel manages hardware drivers and processes, the ObjectStack Core manages **Protocol Plugins** and **Services**. - -## Why a Microkernel? - -ObjectStack is designed to be: -1. **Modular**: Every feature, including the API Server, Database Driver, and UI Engine, is a plugin. -2. **Extensible**: You can replace any default component with your own implementation. -3. **Environment Agnostic**: Runs on Node.js, Bun, Edge Runtimes (Cloudflare Workers), or even in the Browser (via Mock Service Worker). - -## Key Responsibilities - -1. **Plugin Lifecycle Management**: Loading, validating, initializing, and starting plugins in the correct dependency order. -2. **Dependency Injection (DI)**: A central registry for services to communicate without tight coupling. -3. **Event Bus**: System-wide hook system for intercepting logic (e.g., `data:beforeInsert`, `kernel:ready`). -4. **Configuration Management**: Standardized configuration loading using Zod validation. - -## Installation - -```bash -pnpm add @objectstack/core -``` - -## Basic Usage - -```typescript -import { ObjectKernel } from '@objectstack/core'; - -// 1. Create the Kernel -const kernel = new ObjectKernel({ - logger: { level: 'info' } -}); - -// 2. Register Plugins -kernel.use({ - name: 'my-custom-plugin', - version: '1.0.0', - async init(ctx) { - ctx.logger.info('Initializing my plugin...'); - }, - async start(ctx) { - ctx.logger.info('Plugin started!'); - } -}); - -// 3. Boot system -await kernel.bootstrap(); -``` diff --git a/content/docs/concepts/core/meta.json b/content/docs/concepts/core/meta.json deleted file mode 100644 index 99dc3aed15..0000000000 --- a/content/docs/concepts/core/meta.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "title": "Core (Microkernel)", - "pages": [ - "index", - "architecture", - "plugins", - "services", - "events" - ] -} diff --git a/content/docs/concepts/design-principles.mdx b/content/docs/concepts/design-principles.mdx index 86963195a3..4b3176b584 100644 --- a/content/docs/concepts/design-principles.mdx +++ b/content/docs/concepts/design-principles.mdx @@ -159,5 +159,5 @@ By adhering to these values, we build software that is **resilient to change**, ## Next Steps - [Architecture](/docs/concepts/architecture) - See how these principles shape the system -- [Glossary](/docs/concepts/terminology) - Understand key terms -- [Core Concepts](/docs/getting-started/core-concepts) - Learn about metadata-driven development +- [Glossary](/docs/getting-started/glossary) - Understand key terms +- [Core Concepts](/docs/concepts) - Learn about metadata-driven development diff --git a/content/docs/concepts/index.mdx b/content/docs/concepts/index.mdx index c403f7ed6a..efd1b465fa 100644 --- a/content/docs/concepts/index.mdx +++ b/content/docs/concepts/index.mdx @@ -1,654 +1,191 @@ --- -title: Protocol Architecture -description: How the Data, System, and UI protocols work together as one cohesive system +title: Core Concepts +description: The foundational ideas behind ObjectStack — metadata-driven development, protocol-first design, and the principles that shape every decision --- -import { Database, Layout, Cpu, ArrowRight, CheckCircle, Workflow, Bot, Cloud } from 'lucide-react'; +import { Scale, Code2, Database, ScrollText, Laptop } from 'lucide-react'; -# The Protocol Stack +# Core Concepts -The architecture is built on foundational protocols that work together as a unified system: +Before diving into code, understanding these foundational ideas will make everything else click. - - } - title="Data Protocol" - description="ObjectQL: Structure, queries, and constraints." - /> - } - title="UI Protocol" - description="ObjectUI: Presentation, interaction, and routing." - /> - } - title="System Protocol" - description="ObjectOS: Control, runtime, and governance." - /> - } - title="Automation Protocol" - description="Business Logic: Flow, Workflow, Triggers." - /> - } - title="AI Protocol" - description="Intelligence: Agents, RAG, Models." - /> - } - title="Cloud Protocol" - description="Management: Multi-tenancy, Marketplace, Licensing." - /> - - -## Why Separated Layers? - -Traditional applications tightly couple data, business logic, and presentation. This creates **Implementation Coupling** — changing one layer forces changes across the entire stack. - -ObjectStack enforces **Separation of Concerns** through protocol boundaries: - -``` -┌───────────────────────────────────────────────────────────┐ -│ UI Protocol & AI Protocol │ -│ Apps, Views, Dashboards, Agents, RAG │ -│ "How do users and agents interact?" │ -└───────────────────────────┬───────────────────────────────┘ - │ Interface -┌───────────────────────────┴───────────────────────────────┐ -│ System Protocol & Automation Protocol & Cloud Protocol │ -│ Auth, Permissions, Orchestration, Multi-tenancy │ -│ "Who/What can do what, when, and where?" │ -└───────────────────────────┬───────────────────────────────┘ - │ Control -┌───────────────────────────┴───────────────────────────────┐ -│ Data Protocol │ -│ Objects, Fields, Queries, Drivers │ -│ "What is the data structure?" │ -└───────────────────────────────────────────────────────────┘ -``` +## Metadata-Driven Development -## Layer 1: ObjectQL (Data Protocol) +Metadata-driven development is a paradigm shift where **application logic is defined by declarative data (metadata), not imperative code.** -**Role:** Define the **Structure** and **Intent** of data. +### The Problem with Code-First -**Responsibilities:** -- Object schema definitions (what is a "Customer"?) -- Field types and validation rules -- Query language (filtering, sorting, aggregation) -- Database drivers (Postgres, MongoDB, SQLite) +In traditional development, the "Intent" (e.g., *"This field is a required email address"*) is scattered across multiple layers: -**Key Principle:** ObjectQL knows **nothing** about users, permissions, or UI. It only cares about data structure and queries. +1. **Database:** SQL constraints (`NOT NULL`, `CHECK`) +2. **Backend:** ORM validation (TypeORM decorators, Prisma schemas) +3. **Frontend:** UI validation (React Hook Form + Zod) +4. **Documentation:** API specs (OpenAPI/Swagger) -### Example: Defining a Customer Object +When a business requirement changes, you must update code in **three or four places**. This is **Implementation Coupling**. -```typescript -// packages/crm/src/objects/customer.object.ts -import { ObjectSchema, Field } from '@objectstack/spec/data'; - -export const Customer = ObjectSchema.create({ - name: 'customer', - label: 'Customer', - icon: 'building', - - fields: { - name: Field.text({ - label: 'Company Name', - required: true, - maxLength: 120, - }), - - industry: Field.select({ - label: 'Industry', - options: [ - { label: 'Technology', value: 'technology' }, - { label: 'Finance', value: 'finance' }, - { label: 'Healthcare', value: 'healthcare' }, - { label: 'Retail', value: 'retail' }, - ], - }), - - annual_revenue: Field.currency({ - label: 'Annual Revenue', - scale: 2, - }), - - primary_contact: Field.lookup('contact', { - label: 'Primary Contact', - }), - }, -}); -``` - - -The object names on this page (`customer`, `opportunity`, `contact`) are illustrative. In a real package, object names carry their domain/package prefix directly in the name (e.g. `crm_customer`, `sys_user`) — there is no separate `namespace` field. - - -This definition is **pure metadata**. It doesn't know: -- Who can see this data -- How to render a form -- When to trigger workflows - -That's the job of the other layers. - -## Layer 2: ObjectOS (Control Protocol) - -**Role:** Manage the **Lifecycle** and **Governance** of requests. +### The ObjectStack Way -**Responsibilities:** -- Authentication (who is this user?) -- Authorization (can they access this field?) -- Workflows and automations (what happens after save?) -- Event processing (audit logs, notifications) -- Multi-tenancy and data isolation - -**Key Principle:** ObjectOS acts as the **Gateway**. No layer can directly access the database; all requests must pass through the OS Kernel. - -### Example: Permission Rules - -Access control is declared as **permission set** metadata (the `PermissionSet` shape from `@objectstack/spec`). A permission set maps each object to its CRUD/lifecycle flags and, optionally, per-field read/edit flags keyed by `.`: +ObjectStack centralizes the "Intent" into a **single Protocol Definition**: + + ```typescript -// packages/crm/src/permissions/sales_rep.permission.ts -import { definePermissionSet } from '@objectstack/spec'; - -export const salesRep = definePermissionSet({ - name: 'sales_rep', - label: 'Sales Rep', - isProfile: true, - objects: { - customer: { - allowCreate: true, - allowRead: true, - allowEdit: true, - allowDelete: false, // Only managers can delete - }, - }, - fields: { - 'customer.annual_revenue': { readable: true, editable: false }, // Read-only - }, -}); - -// packages/crm/src/permissions/sales_manager.permission.ts -export const salesManager = definePermissionSet({ - name: 'sales_manager', - label: 'Sales Manager', - isProfile: true, - objects: { - customer: { - allowCreate: true, - allowRead: true, - allowEdit: true, - allowDelete: true, +// ONE definition — everything else derives from it +import { defineStack } from '@objectstack/spec'; + +export default defineStack({ + objects: [{ + name: 'user', + label: 'User', + fields: { + phone: { label: 'Phone Number', type: 'phone', required: true }, }, - }, + }], }); ``` - -### Example: Flow Automation - -Business logic is authored as a **Flow** — a graph of nodes and edges — via `defineFlow`. A `record_change` flow runs when a record is written; a `decision` node branches on a bare CEL condition (reference fields directly, e.g. `record.annual_revenue`, and do **not** wrap them in `{…}`): - + + ```typescript -// packages/crm/src/flows/high_value_customer.flow.ts -import { defineFlow } from '@objectstack/spec'; - -export const highValueCustomerFlow = defineFlow({ - name: 'high_value_customer', - label: 'High-Value Customer Alert', - type: 'record_change', - status: 'active', - nodes: [ - { id: 'start', type: 'start', label: 'On Create' }, - { id: 'check', type: 'decision', label: 'Is High Value?' }, - { id: 'assign', type: 'update_record', label: 'Assign Enterprise Team' }, - { id: 'notify', type: 'notify', label: 'Email Leadership' }, - { id: 'end', type: 'end', label: 'End' }, - ], - edges: [ - { id: 'e1', source: 'start', target: 'check' }, - { id: 'e2', source: 'check', target: 'assign', condition: 'record.annual_revenue > 1000000' }, - { id: 'e3', source: 'assign', target: 'notify' }, - { id: 'e4', source: 'notify', target: 'end' }, - ], -}); -``` - -ObjectOS **orchestrates** these rules at runtime, independent of the data structure or UI. - -## Layer 3: ObjectUI (View Protocol) - -**Role:** Render the **Presentation** and handle **User Interaction**. - -**Responsibilities:** -- App navigation and branding -- List views (grid, kanban, calendar) -- Form layouts (simple, tabbed, wizard) -- Dashboards and reports -- Actions and buttons - -**Key Principle:** ObjectUI is a **Rendering Engine**, not a hardcoded interface. It asks ObjectQL *"What is the schema?"* and dynamically generates the UI. - -### Example: List View - -Views are authored with `defineView`, which aggregates an object's `list` and `form` views into one document. A list view binds to its data source (`provider: 'object'`), names its columns, and declares any default sort: - -```typescript -// packages/crm/src/views/customer.view.ts -import { defineView } from '@objectstack/spec'; - -export const customerViews = defineView({ - list: { - label: 'All Customers', - type: 'grid', - data: { provider: 'object', object: 'customer' }, - columns: ['name', 'industry', 'annual_revenue', 'primary_contact'], - filter: [ - { field: 'annual_revenue', operator: 'greaterThan', value: 0 }, - ], - sort: [{ field: 'name', order: 'asc' }], - }, -}); -``` - -### Example: Form View - -The same `defineView` document carries the `form` view. A form is laid out as **sections** of fields (each section can span 1-4 columns): +// Map keys become the `name` field automatically +import { defineStack } from '@objectstack/spec'; -```typescript -// packages/crm/src/views/customer.view.ts -import { defineView } from '@objectstack/spec'; - -export const customerViews = defineView({ - form: { - type: 'simple', - data: { provider: 'object', object: 'customer' }, - sections: [ - { - label: 'Company Information', - columns: 2, - fields: ['name', 'industry', 'annual_revenue'], - }, - { - label: 'Contact', - fields: ['primary_contact'], +export default defineStack({ + objects: { + user: { + label: 'User', + fields: { + phone: { label: 'Phone Number', type: 'phone', required: true }, }, - ], + }, }, }); ``` - -The UI doesn't "know" the field types. It asks ObjectQL for the schema and renders accordingly: -- `Field.text` → Text input -- `Field.select` → Dropdown -- `Field.lookup` → Autocomplete lookup -- `Field.currency` → Number input with currency formatting - -## How They Work Together - -Let's trace a **real-world scenario**: A sales rep creates a new high-value customer. + + -The runtime snippets in Steps 3-6 below are **conceptual pseudo-code** — names like `Auth.getCurrentUser()`, `Permission.check()`, `ObjectQL.getSchema()`, and `Workflow.getTriggersFor()` illustrate *what each layer does at runtime*; they are not importable APIs from `@objectstack/spec`. The schema, view, permission-set, and flow snippets elsewhere on this page are the real authoring surface. +**Array or Map?** `defineStack()` accepts both formats for all named metadata collections (`objects`, `apps`, `flows`, etc.). Map keys are injected as the `name` field — pick whichever style you prefer. -### Step 1: User Action (ObjectUI) - -``` -User fills out the "Create Customer" form: -- Name: "Acme Corp" -- Industry: "Technology" -- Annual Revenue: $5,000,000 -- Primary Contact: "John Doe" - -User clicks "Save" -``` - -### Step 2: UI Layer Sends Request - -```typescript -// ObjectUI dispatches an action to ObjectOS -const request = { - action: 'create', - object: 'customer', - data: { - name: 'Acme Corp', - industry: 'technology', - annual_revenue: 5000000, - primary_contact: 'contact_12345', - }, -}; -``` - -### Step 3: ObjectOS Validates Permissions - -```typescript -// Kernel checks: Does this user have permission? -const user = await Auth.getCurrentUser(); -const canCreate = await Permission.check({ - user, - object: 'customer', - operation: 'create', -}); - -if (!canCreate) { - throw new Error('Permission denied'); -} -``` +From this single definition, ObjectStack automatically: -### Step 4: ObjectOS Validates Data +✅ Generates database schema +✅ Creates validation rules +✅ Builds CRUD APIs +✅ Renders form fields +✅ Produces API documentation -```typescript -// Kernel asks ObjectQL: Is this data valid? -const schema = ObjectQL.getSchema('customer'); -const validation = schema.validate(request.data); +### The Three Truths -if (!validation.success) { - throw new ValidationError(validation.errors); -} -``` +1. **The UI is a Projection** — The form is generated from the schema, not hand-coded +2. **The API is a Consequence** — REST/GraphQL endpoints appear automatically from object definitions +3. **The Schema is the Application** — Your entire business logic lives in metadata files -### Step 5: ObjectQL Writes to Database +### When to Use Metadata-Driven -```typescript -// ObjectQL compiles the request into a database operation -const driver = ObjectQL.getDriver(); // Postgres, MongoDB, etc. -const result = await driver.insert('customer', { - name: 'Acme Corp', - industry: 'technology', - annual_revenue: 5000000, - primary_contact_id: 'contact_12345', -}); -``` +✅ **Great for:** CRUD apps, SaaS platforms, admin panels, rapid prototyping, multi-tenant systems -### Step 6: ObjectOS Triggers Workflows +❌ **Not ideal for:** Pixel-perfect custom UIs, real-time 3D/games, highly unique domains -```typescript -// Kernel checks: Are there any workflows for this event? -const workflows = Workflow.getTriggersFor('customer', 'after_create'); - -for (const workflow of workflows) { - if (workflow.conditionsMet(result)) { - await workflow.execute(result); - } -} - -// In this case: -// ✅ Annual revenue > $1M -// → Assign to enterprise sales team -// → Send alert email to leadership -``` +--- -### Step 7: ObjectUI Updates Display +## Design Principles -```typescript -// Kernel returns success response -// UI optimistically updates the screen -// UI shows toast notification: "Customer created successfully" -// UI navigates to the new customer detail page -``` +ObjectStack is governed by four unshakable principles: -## The Full Stack in Action + + } + title="I. Protocol Neutrality" + description="The Protocol is law. The Implementation is merely an opinion." + /> + } + title="II. Mechanism over Policy" + description="Provide the tools to build rules, do not hardcode the rules themselves." + /> + } + title="III. Single Source of Truth" + description="There is no 'Code'. There is only Schema." + /> + } + title="IV. Agent-Ready Boundaries" + description="Agents may act only through typed, permission-aware, auditable surfaces." + /> + -Here's how all three protocols collaborate for a **Kanban Board** feature: +### Protocol Neutrality -### 1. ObjectQL: Define the Data +**"The Protocol is neutral. The Engine is replaceable."** -```typescript -import { ObjectSchema, Field } from '@objectstack/spec/data'; - -export const Opportunity = ObjectSchema.create({ - name: 'opportunity', - label: 'Opportunity', - icon: 'target', - - fields: { - title: Field.text({ - label: 'Title', - required: true, - }), - - stage: Field.select({ - label: 'Stage', - options: [ - { label: 'Prospecting', value: 'prospecting', default: true }, - { label: 'Qualification', value: 'qualification' }, - { label: 'Proposal', value: 'proposal' }, - { label: 'Closed Won', value: 'closed_won' }, - ], - }), - - amount: Field.currency({ - label: 'Amount', - scale: 2, - }), - - customer: Field.lookup('customer', { - label: 'Customer', - }), - }, -}); -``` +- **Spec before Engine:** Features must be defined in the Specification layer before any engine code is written +- **Zero Leakage:** Implementation details (React, SQL, etc.) never leak into Protocol definitions -### 2. ObjectOS: Define Business Rules +This ensures ObjectStack apps can run on Node.js + PostgreSQL today, Python + SQLite tomorrow, or Rust WASM in the browser. -```typescript -import { defineFlow } from '@objectstack/spec'; - -export const opportunityWonFlow = defineFlow({ - name: 'opportunity_won', - label: 'Opportunity Won', - type: 'record_change', - status: 'active', - nodes: [ - { id: 'start', type: 'start', label: 'On Change' }, - { id: 'check', type: 'decision', label: 'Closed Won?' }, - { id: 'invoice', type: 'create_record', label: 'Create Invoice' }, - { id: 'notify', type: 'notify', label: 'Notify Sales Team' }, - { id: 'end', type: 'end', label: 'End' }, - ], - edges: [ - { id: 'e1', source: 'start', target: 'check' }, - { id: 'e2', source: 'check', target: 'invoice', condition: "record.stage == 'closed_won'" }, - { id: 'e3', source: 'invoice', target: 'notify' }, - { id: 'e4', source: 'notify', target: 'end' }, - ], -}); -``` +### Mechanism over Policy -### 3. ObjectUI: Define the Kanban View +**"Give them the physics, not the simulation."** -```typescript -import { defineView } from '@objectstack/spec'; - -export const opportunityViews = defineView({ - list: { - type: 'kanban', - data: { provider: 'object', object: 'opportunity' }, - columns: ['title', 'amount', 'customer'], - kanban: { - groupByField: 'stage', - summarizeField: 'amount', - columns: ['title', 'amount', 'customer'], - }, - }, -}); -``` +| Layer | Responsibility | Example | +| :--- | :--- | :--- | +| **Protocol** | Defines capabilities | A row-level-security policy slot (`operation` + `using` clause) | +| **App** | Defines business logic | `{ operation: 'select', using: "role = 'admin'" }` | +| **Engine** | Enforces the logic | Compiles the `using` condition into a SQL `WHERE` clause | -### The Result + +CRUD permissions (`allowRead`, `allowEdit`, …) are simple booleans — they grant or deny an operation. Record-level *conditional* access is a separate mechanism: [Row-Level Security](/docs/concepts/architecture) policies, whose `using` clause is a SQL-like (PostgreSQL-compatible) predicate over context variables such as `current_user.roles` and `current_user.id`. + -When a user **drags an opportunity card** from "Proposal" to "Closed Won": +### Single Source of Truth -1. **ObjectUI** captures the drag-drop event -2. **ObjectOS** checks if the user has permission to update the `stage` field -3. **ObjectQL** validates that `"closed_won"` is a valid option -4. **ObjectQL** writes the update to the database -5. **ObjectOS** triggers the workflow (create invoice, send notification) -6. **ObjectUI** updates the kanban board to reflect the new state +In ObjectStack, **the Object Protocol is the only truth:** -**All from metadata. Zero hardcoded logic.** +- The Database is a *derivative* of the Protocol +- The UI is a *projection* of the Protocol +- The API is a *consequence* of the Protocol +- The Agent tool surface is a *bounded capability set* derived from the Protocol -## Benefits of the Three-Layer Architecture +Change the Protocol → the entire system adapts automatically. -### 1. Technology Independence +### Agent-Ready Boundaries -Swap implementations without breaking the system: +AI agents should not bypass the application model by calling raw SQL, scraping UI state, or executing arbitrary glue code. They should act through typed, permission-aware capabilities derived from the same metadata artifact that powers the application. ``` -Same Metadata Definitions - ↓ -┌─────────┼─────────┐ -ObjectQL: │ │ -Postgres │ MongoDB - │ -ObjectOS: │ -Node.js │ Python - │ -ObjectUI: │ -React │ Flutter +Traditional AI app: Database schema -> App code -> Custom query -> Hand-written MCP tool +ObjectStack: Zod metadata -> Metadata registry -> ObjectStack runtime -> API / UI / MCP tools ``` -### 2. Parallel Development - -Teams can work independently on each layer: - -- **Data Team:** Define objects in ObjectQL -- **Backend Team:** Build workflows in ObjectOS -- **Frontend Team:** Create views in ObjectUI - -All communicate through **protocol contracts**, not code dependencies. - -### 3. Incremental Migration - -Adopt ObjectStack gradually: - -- **Phase 1:** Use ObjectQL as an ORM replacement -- **Phase 2:** Add ObjectOS for permissions and workflows -- **Phase 3:** Build ObjectUI views to replace custom forms - -Each layer is independently useful. +--- -### 4. Testability +## Naming Conventions -Mock any layer for testing: +ObjectStack enforces strict naming rules for consistency: -```typescript -// Test ObjectOS workflows without a real database -const mockObjectQL = { - getSchema: () => CustomerSchema, - insert: jest.fn(), -}; - -// Test ObjectUI rendering without a real backend -const mockObjectOS = { - checkPermission: () => true, - executeQuery: () => mockData, -}; -``` +| Element | Convention | Examples | +|---------|-----------|----------| +| **Object names** (machine) | `snake_case` | `todo_task`, `user_profile` | +| **Field names** (machine) | `snake_case` | `first_name`, `is_active` | +| **Export names** (constants) | `PascalCase` | `TodoTask`, `UserProfile` | +| **Config keys** (properties) | `camelCase` | `maxLength`, `defaultValue` | ## Summary -| Layer | Role | Knows About | Doesn't Know About | -| :--- | :--- | :--- | :--- | -| **ObjectQL** | Data structure & queries | Schema, fields, drivers | Users, permissions, UI | -| **ObjectOS** | Runtime & governance | Auth, workflows, events | Data structure, UI layout | -| **ObjectUI** | Presentation & interaction | Layout, navigation, actions | Business logic, data storage | - -The three protocols are **loosely coupled** but **tightly integrated**: -- They communicate through **standard contracts** (Zod schemas) -- They can be **swapped or upgraded** independently -- They form a **complete system** when combined +| Aspect | Traditional | Metadata-Driven | +| :--- | :--- | :--- | +| **Definition** | Code in multiple files | Single metadata definition | +| **Changes** | Update 3-4 places | Update once | +| **Type Safety** | Manual synchronization | Automatic from Zod | +| **Flexibility** | Locked to tech stack | Technology agnostic | +| **Boilerplate** | High (300+ lines) | Low (30 lines) | +| **Agent Tools** | Hand-written and drift-prone | Generated from metadata and permissions | ## Next Steps -- [ObjectQL: Data Protocol](/docs/protocol/objectql) - Full data protocol specification -- [ObjectUI: UI Protocol](/docs/protocol/objectui) - Full view protocol specification -- [ObjectOS: System Protocol](/docs/protocol/objectos) - Full control protocol specification -- [Developer Guide](/docs/getting-started/quick-start) - Build your first ObjectStack application - ---- - -## Appendix: Protocol Dependencies - -Understanding the dependency chain helps you design applications correctly. - -### Data Layer (ObjectQL) - -``` -Field Protocol (Core) - ↓ - ├→ Object Protocol (uses Fields) - ├→ Query Protocol (references Fields) - ├→ Filter Protocol (filters on Fields) - └→ Validation Protocol (validates Fields) - ↓ - └→ Hook Protocol (extends validation with code) -``` - -### UI Layer (ObjectUI) - -``` -Theme Protocol (Foundation) - ↓ -View Protocol (uses Object, Query) - ├→ ListView (uses Query, Filter) - ├→ FormView (uses Object, Field) - └→ Dashboard (uses View, Widget) - ↓ - ├→ Page Protocol (composes Views) - └→ App Protocol (organizes Pages) - ↓ - └→ Action Protocol (UI interactions) -``` - -### System Layer (ObjectOS) - -``` -Data Driver Contracts (Database Abstraction) - ↓ -Datasource Protocol (Connection Config) - ↓ - ├→ Context Protocol (Runtime State) - ├→ Events Protocol (Event Bus) - └→ Plugin Protocol (Extensibility) - ↓ - ├→ Security Protocol (Access Control) - ├→ API Protocol (External Access) - └→ Automation Protocol (Workflows) - ↓ - └→ AI Protocol (Intelligence) -``` - -## Appendix: Usage Patterns - -### Pattern 1: Data-Driven UI - -UI auto-generated from data definitions: - -``` -Object → Field → View → Page → App -``` - -### Pattern 2: Custom UI with Data Binding - -Custom UI connected to data: - -``` -Page → Component → View (Custom) → Query → Object -``` - -### Pattern 3: Automation & Integration - -Business logic automation: - -``` -Object → Hook → Flow → Automation → API/Webhook -``` - -### Pattern 4: AI-Enhanced Applications - -AI capabilities on top of data: - -``` -Object → RAG Pipeline → Agent → Conversation → UI -``` +- [Architecture](/docs/concepts/architecture) — How the protocol layers work together +- [Quick Start](/docs/getting-started/quick-start) — Build your first app in 5 minutes +- [Glossary](/docs/getting-started/glossary) — Key terminology diff --git a/content/docs/concepts/meta.json b/content/docs/concepts/meta.json index 95b7dae946..c9bff39747 100644 --- a/content/docs/concepts/meta.json +++ b/content/docs/concepts/meta.json @@ -1,6 +1,12 @@ { - "title": "Concepts", + "title": "Core Concepts", "icon": "Lightbulb", - "root": true, - "pages": ["index", "north-star", "metadata-driven", "metadata-lifecycle", "design-principles", "architecture", "authorization", "cluster-semantics", "webhook-delivery", "skills", "core", "packages", "setup-app", "cloud-artifact-api", "terminology", "implementation-status"] + "pages": [ + "index", + "architecture", + "metadata-driven", + "metadata-lifecycle", + "design-principles", + "north-star" + ] } diff --git a/content/docs/concepts/metadata-driven.mdx b/content/docs/concepts/metadata-driven.mdx index 709a00e5a4..d0eeb92a0e 100644 --- a/content/docs/concepts/metadata-driven.mdx +++ b/content/docs/concepts/metadata-driven.mdx @@ -521,5 +521,5 @@ export const ExampleObject = ObjectSchema.create({ - [Metadata Lifecycle & HMR](/docs/concepts/metadata-lifecycle) - How writes propagate through the Repository / Change Log / Cache / Registry - [Architecture](/docs/concepts/architecture) - How the three protocols work together -- [Core Concepts](/docs/concepts/core) - Deep dive into the kernel, services, and object model +- [Core Concepts](/docs/kernel) - Deep dive into the kernel, services, and object model - [ObjectQL Protocol](/docs/protocol/objectql) - Learn the data protocol specification diff --git a/content/docs/concepts/packages.mdx b/content/docs/concepts/packages.mdx deleted file mode 100644 index 3a14e5a26a..0000000000 --- a/content/docs/concepts/packages.mdx +++ /dev/null @@ -1,890 +0,0 @@ ---- -title: Package Reference -description: Complete reference of all ObjectStack packages in the monorepo ---- - -# Package Reference - -ObjectStack is distributed as a monorepo containing **~75 package manifests** organized into core runtime, client SDKs, framework adapters, drivers, plugins, connectors, triggers, and platform services. - -> **Note for AI Agents**: Each package's `README.md` contains a specific architectural role and usage rules section. - -## Package Overview - -| Category | Count | Description | -| :--- | :---: | :--- | -| Core runtime | 11 | `spec`, `core`, `runtime`, `types`, `metadata`, `metadata-core`, `metadata-fs`, `objectql`, `rest`, `formula`, `platform-objects` | -| Client / DX | 5 | `client`, `client-react`, `cli`, `create-objectstack`, `vscode-objectstack` | -| Framework adapters | 7 | Express, Fastify, Hono, NestJS, Next.js, Nuxt, SvelteKit | -| Drivers | 4 | `driver-memory`, `driver-sql`, `driver-sqlite-wasm`, `driver-mongodb` | -| Plugins | 18 | Auth, security, audit, org-scoping, approvals, sharing, email, webhooks, reports, Hono/MCP servers, MSW/dev, record-change & schedule triggers, knowledge, and embedders | -| Connectors | 4 | `connector-rest`, `connector-mcp`, `connector-openapi`, `connector-slack` | -| Triggers | 3 | `trigger-api`, `trigger-record-change`, `trigger-schedule` | -| Platform services | 17 | AI, Analytics, Automation, Cache, Cluster, Datasource, Feed, I18n, Job, Knowledge, Messaging, Package, Queue, Realtime, Settings, Storage | -| Other | ~6 | `mcp`, `console`, `cloud-connection`, `observability`, app templates, and tooling | - -**Total: ~75 package manifests.** Counts drift as packages are added — run `find packages -name package.json -not -path '*/node_modules/*'` for the exact current set. - ---- - -## Core Packages - -### @objectstack/spec - -**Description:** ObjectStack Protocol & Specification - TypeScript Interfaces, JSON Schemas, and Convention Configurations - -**Purpose:** The foundational package containing all protocol definitions and schemas. This is the "DNA" of ObjectStack. - -**Protocol Domains (subpath imports):** - -The package does **not** export schemas from the root; import the domain you need via its subpath, e.g. `import * as Data from '@objectstack/spec/data'`. - -- `@objectstack/spec/data` - Data protocol schemas (Field, Object, Query, etc.) -- `@objectstack/spec/ui` - UI protocol schemas (View, App, Dashboard, etc.) -- `@objectstack/spec/system` - System protocol schemas (Manifest, Plugin, Events, Auth config, etc.) -- `@objectstack/spec/identity` - Identity & authentication schemas -- `@objectstack/spec/security` - Permission and security schemas -- `@objectstack/spec/ai` - AI protocol schemas (Agent, RAG Pipeline, etc.) -- `@objectstack/spec/api` - API protocol schemas (Contract, Endpoint, etc.) -- `@objectstack/spec/automation` - Automation protocol schemas (Flow, Workflow, etc.) -- `@objectstack/spec/integration` - Integration protocol schemas -- `@objectstack/spec/contracts` - Service contract interfaces -- `@objectstack/spec/kernel` - Kernel protocol schemas -- `@objectstack/spec/shared` - Shared utilities and identifiers -- Additional subpaths: `studio`, `cloud`, `qa` - -**Protocol Count:** Hundreds of Zod schemas across these domains — the set grows over time, so refer to the [Protocol Reference](/docs/references) for the current catalog. - -**Learn more:** [Protocol Reference](/docs/references) - ---- - -### @objectstack/core - -**Description:** Microkernel Core for ObjectStack - -**Purpose:** Provides the runtime foundation for ObjectStack, including the plugin system, service registry, and logging infrastructure. - -**Key Features:** -- **ObjectKernel**: Plugin-based microkernel with dependency injection -- **Plugin Lifecycle**: Init → Start → Destroy with topological dependency resolution -- **Service Registry**: Dependency injection (registerService, getService) -- **Hook/Event System**: Inter-plugin communication (beforeFind, afterInsert, etc.) -- **Security**: PluginConfigValidator, PluginSignatureVerifier, PluginPermissionEnforcer -- **Logging**: Cross-platform logger (browser + server) with multiple formats -- **API Registry**: Central API registry for dynamic endpoint management -- **QA Framework**: Testing framework with HTTP adapter support - -**Use Cases:** -- Building custom ObjectStack runtimes -- Creating plugin-based architectures -- Implementing microkernel patterns - -**Implementation Status:** ✅ **FULLY IMPLEMENTED** - Production ready - ---- - -### @objectstack/runtime - -**Description:** ObjectStack Server Runtime & REST API Engine - -**Purpose:** The main server runtime that provides HTTP endpoints and REST API generation. - -**Key Features:** -- **RestServer**: Auto-generates RESTful CRUD endpoints from object schemas -- **Route Management**: Centralized route registration and middleware chain management -- **HTTP Server**: Implements IHttpServer interface (adapter pattern) -- **Endpoint Generation**: Configuration-driven CRUD API (GET/POST/PATCH/DELETE) -- **Batch Operations**: /createMany, /updateMany, /deleteMany, /batch endpoints -- **Metadata Endpoints**: `/meta`, `/meta/{type}`, `/meta/{type}/{name}` -- **Discovery**: /api/v1 API discovery endpoint -- **HTTP Caching**: ETag, Last-Modified headers support -- **Path Transformations**: plural, kebab-case, camelCase -- **Plugin Adapters**: AppPlugin, DriverPlugin for kernel integration - -**Use Cases:** -- Running ObjectStack server applications -- Auto-generating REST APIs from metadata -- Building production API servers - -**Implementation Status:** ✅ **FULLY IMPLEMENTED** - Production ready - ---- - -### @objectstack/objectql - -**Description:** Isomorphic ObjectQL Engine & Protocol Implementation - -**Purpose:** Standalone ObjectQL query engine that implements the ObjectStack protocol and can run in any JavaScript environment (Node.js, browsers, edge). - -**Key Features:** -- **ObjectQL Engine**: Implements `IDataEngine` interface - - Query operations: find, insert, update, delete, count - - Hook system: beforeFind, afterFind, beforeInsert, afterInsert, etc. - - Driver management: registerDriver, getDriver -- **SchemaRegistry**: Central metadata registry - - registerObject, registerApp, registerMetadata - - getObject, getItem, listItems, getRegisteredTypes -- **ObjectStackProtocolImplementation**: Full `ObjectStackProtocol` implementation - - Discovery: getDiscovery() - - Metadata: getMetaTypes(), getMetaItems(type), getMetaItem(type, name) - - UI Views: getUiView(object, type) - - CRUD operations: findData, getData, createData, updateData, deleteData - - Batch operations: batchUpdate, batchDelete - - HTTP Caching: ETag-based caching with 304 Not Modified support -- **Isomorphic**: Works in Node.js, browsers, and edge environments -- **Driver-agnostic**: Query interface abstraction - -**Use Cases:** -- Client-side data querying -- Edge function data access -- Serverless query execution -- Implementing ObjectStack protocol - -**Implementation Status:** ✅ **FULLY IMPLEMENTED** - Production ready - ---- - -### @objectstack/client - -**Description:** Official TypeScript Client SDK for ObjectStack Protocol - -**Purpose:** Type-safe client library for interacting with ObjectStack REST APIs. - -**Key Features:** -- **Discovery API**: `connect()` → /api/v1 endpoint -- **Metadata API**: - - `meta.getTypes()`, `meta.getItems(type)`, `meta.getItem(type, name)` - - `meta.getObject(name)` - Object definitions - - `meta.getView(object, type)` - UI schemas with ETag caching - - `meta.getCached()` - Conditional 304 Not Modified support -- **Data Operations (CRUD)**: - - `data.query(object, ast)` - Advanced AST queries via POST - - `data.find(object, options)` - Simplified queries with filters/sort/select - - `data.get(id)`, `data.create()`, `data.update()`, `data.delete()` - - `data.createMany()`, `data.updateMany()`, `data.deleteMany()` - - `data.batch()` - Atomic batch operations -- **Query Builder**: `QueryBuilder`, `FilterBuilder`, `createQuery()`, `createFilter()` -- **Error Handling**: StandardError with code, category, httpStatus, retryable flag -- **Authentication**: Bearer token support via `token` config -- **Type Safety**: Full TypeScript types from spec schemas - -**Use Cases:** -- Building frontend applications -- Consuming ObjectStack APIs -- Type-safe data fetching - -**Implementation Status:** ✅ **FULLY IMPLEMENTED** - Production ready - ---- - -### @objectstack/client-react - -**Description:** React hooks for ObjectStack Client SDK - -**Purpose:** React-specific hooks and components for ObjectStack integration. - -**Requirements:** React 18+ - -**Key Features:** -- **Context & Provider**: - - `ObjectStackProvider` - Makes client available to all React components - - `useClient()` - Access ObjectStackClient instance -- **Data Hooks**: - - `useQuery(object, options)` - Query with caching, refetch, enabled flag - - `useMutation(object, options)` - Create/Update/Delete with optimistic updates - - `usePagination(object, options)` - Paginated queries with next/previous helpers - - `useInfiniteQuery(object, options)` - Infinite scroll support -- **Metadata Hooks**: - - `useObject(name)` - Get object schema - - `useView(object, type)` - Get list/form UI schema - - `useFields(object)` - Get field definitions - - `useMetadata(type, name, options)` - Generic metadata access -- **Automatic Caching**: Built-in cache management -- **TypeScript Support**: Full type inference from schemas - -**Use Cases:** -- Building React applications -- Real-time data synchronization -- Form handling with ObjectStack data - -**Implementation Status:** ✅ **FULLY IMPLEMENTED** - Production ready - ---- - -### @objectstack/cli - -**Description:** Command Line Interface for ObjectStack Development - -**Purpose:** Complete developer tools for scaffolding, building, validating, and managing ObjectStack applications. - -**Commands:** - -| Category | Commands | -| :--- | :--- | -| Development | `init`, `dev`, `serve` | -| Build & Validate | `compile`, `validate`, `info` | -| Scaffolding | `generate` (alias: `g`), `create` | -| Quality | `test`, `doctor`, `lint` | -| Publishing & Registry | `build`, `publish`, `register`, `rollback`, `login`, `logout`, `whoami` | -| Inspection | `diff`, `explain` | -| Command groups | `cloud`, `data`, `datasource`, `environments`, `i18n`, `meta`, `package`, `plugin` | - -> This is a representative list; run `os --help` for the authoritative set of commands and subcommands. - -**Key Features:** -- **Project Initialization**: `os init` creates projects from templates (app, plugin, empty) -- **Code Generation**: `os generate` scaffolds objects, views, actions, flows, agents, dashboards, apps -- **Schema Validation**: `os validate` checks config against `ObjectStackDefinitionSchema` with `--strict` and `--json` modes -- **Metadata Introspection**: `os info` displays metadata summary without compilation -- **Config Compilation**: `os compile` bundles config to deployable JSON artifact with metadata stats -- **Development Server**: `os serve --dev` with auto-plugin detection, port conflict resolution -- **CI/CD Integration**: All output commands support `--json` for machine-readable output -- **Shared Utilities**: Unified formatting, config loading, and error handling across all commands -- **Monorepo Support**: pnpm workspace integration via `os dev` -- **Environment Diagnostics**: `os doctor` validates Node.js, pnpm, TypeScript, dependencies - -**Use Cases:** -- Project scaffolding and initialization -- Metadata generation and validation -- Development workflows with hot-reload -- CI/CD pipeline integration -- Environment diagnostics - -**Learn more:** [CLI Guide](/docs/getting-started/cli) - -**Implementation Status:** ✅ **FULLY IMPLEMENTED** - Production ready - ---- - -### @objectstack/metadata - -**Description:** Metadata Management System - -**Purpose:** Provides metadata loading, saving, watching, and caching capabilities for ObjectStack. - -**Key Features:** -- **MetadataManager**: Orchestrates loading, saving, watching, caching metadata -- **MetadataPlugin**: Kernel plugin adapter for metadata system -- **Loaders**: - - `MemoryLoader` - In-memory metadata source - - `RemoteLoader` - Loads metadata from a remote endpoint - - `DatabaseLoader` - Loads metadata persisted in the database -- **Serializers**: - - `JSONSerializer` - `.json` files - - `YAMLSerializer` - `.yaml` files - - `TypeScriptSerializer` - `.ts` files (also handles JavaScript) -- **Watch Mode**: File system notifications with chokidar -- **Auto-detection**: Format auto-detection for load/save -- **Caching**: Metadata caching with statistics -- **Migration**: Metadata migration system - -**Use Cases:** -- Loading metadata from multiple formats -- Hot-reloading metadata during development -- Managing metadata lifecycle - -**Implementation Status:** ✅ **FULLY IMPLEMENTED** - Production ready - ---- - -### @objectstack/metadata-core - -**Description:** Metadata Repository contracts (ADR-0008) — types, canonicalization, errors, and the `MetadataRepository` interface. - -**Purpose:** The shared contract layer the metadata system and its storage backends implement. - -**Use Cases:** Building custom metadata repositories, integrating with the metadata system. - -**Implementation Status:** ✅ **IMPLEMENTED** - ---- - -### @objectstack/metadata-fs - -**Description:** `FileSystemRepository` — a Node-only `MetadataRepository` implementation backed by JSON files and a JSONL change log (ADR-0008). - -**Purpose:** Persists metadata on the filesystem with an append-only change history. - -**Use Cases:** Local development, file-based metadata storage, change auditing. - -**Implementation Status:** ✅ **IMPLEMENTED** - ---- - -### @objectstack/types - -**Description:** Shared Runtime Type Definitions - -**Purpose:** Provides core TypeScript interfaces used across all ObjectStack packages at runtime. - -**Key Exports:** -- `IKernel` - Kernel interface -- `RuntimePlugin` - Plugin base interface -- `RuntimeContext` - Runtime context type -- Other shared runtime types - -**Use Cases:** -- Building plugins that need kernel interfaces -- Implementing custom runtimes -- Type-safe cross-package integration - -**Implementation Status:** ✅ **FULLY IMPLEMENTED** - Production ready - ---- - -## Framework Adapters - -The open edition ships the **Hono** adapter. For another framework, build a thin adapter on the public `HttpDispatcher` API — the previous Express / Fastify / Next.js / NestJS / Nuxt / SvelteKit adapters were removed in 11 and can be vendored out-of-tree. - -### @objectstack/hono - -**Description:** Hono Framework Adapter - -**Purpose:** Converts ObjectStack's standard HTTP dispatch interface to Hono routes. - -**Key Features:** -- Maps standard routes to Hono handlers -- Supports Hono's middleware chain -- Works with Node.js, Bun, Deno, Cloudflare Workers - -**Implementation Status:** ✅ **FULLY IMPLEMENTED** - ---- - -## Plugin Packages - -### @objectstack/driver-memory - -**Description:** In-Memory Driver for ObjectStack (Reference Implementation) - -**Purpose:** A reference in-memory database driver used for testing and development. - -**Key Features:** -- **CRUD & Bulk Operations**: create, read, update, delete, find, plus bulk insert/update/delete -- **Mingo Query Engine**: MongoDB-compatible filtering, projection, and distinct values -- **Aggregation Pipeline**: `$match`, `$group`, `$sort`, `$project`, `$unwind`, and an `IAnalyticsService` implementation (`memory-analytics`) -- **Sorting & Pagination**: `orderBy` sorting with offset-based pagination -- **Snapshot Transactions**: `beginTransaction` / `commit` / `rollback` (capability flag `transactions: true`) -- **Health Checks**: Built-in health monitoring -- **Array & JSON Fields**: Support for complex field types - -**Limitations:** -- ⚠️ Non-persistent — all data is held in memory and lost on restart -- ⚠️ No savepoints within a transaction (`savepoints: false`) - -**Use Cases:** -- Testing ObjectStack applications -- Development without database setup -- Understanding driver implementation patterns -- Quick prototyping - -**Status:** ✅ Reference implementation for driver developers - -**Implementation Status:** ✅ **FULLY IMPLEMENTED** (in-memory) - Mingo-backed filtering, aggregation, sorting, and snapshot transactions; non-persistent - ---- - -### @objectstack/plugin-hono-server - -**Description:** Hono HTTP Server Adapter for ObjectStack Runtime - -**Purpose:** Production HTTP server adapter using the Hono framework. - -**Key Features:** -- **Standard Runtime**: Uses the unified `HttpDispatcher` and standard Hono adapter via `@objectstack/hono` -- **Full Protocol Support**: Automatically provides all ObjectStack Runtime endpoints (Auth, Data, Metadata, Storage) -- **Fast HTTP Server**: Uses Hono framework for high performance -- **Port Configuration**: Configurable port with conflict detection -- **Static File Serving**: Built-in static file support -- **API Registry Integration**: Centralized endpoint management -- **Metadata Caching**: ETag-based caching for metadata endpoints -- **Edge Runtime Compatible**: Can run on edge environments - -**Use Cases:** -- Production REST API deployment -- Edge function hosting (Cloudflare Workers, Deno Deploy, etc.) -- Serverless deployments -- Local development server - -**Implementation Status:** ✅ **FULLY IMPLEMENTED** - Production ready - ---- - -### @objectstack/plugin-auth - -**Description:** Authentication & Identity Plugin for ObjectStack - -**Purpose:** Provides authentication and identity management services for ObjectStack applications with better-auth integration. - -**Key Features:** -- **better-auth Integration**: Wires better-auth's server-side authentication pipeline (sign-up/sign-in, sessions, tokens) -- **Plugin Lifecycle**: Full init/start/destroy lifecycle implementation -- **Service Registration**: Registers `auth` service in ObjectKernel -- **HTTP Routes**: `/api/v1/auth/*` endpoints via IHttpServer, plus a `/set-initial-password` route -- **Configuration Support**: Uses `AuthConfig` schema from `@objectstack/spec/system` -- **OAuth Provider Support**: Configuration for Google, GitHub, Microsoft, etc. -- **ObjectQL Adapter**: Persists users/sessions through ObjectQL (no separate ORM required) -- **Password Hashing**: Cryptographic password hashing via `@noble/hashes` -- **Advanced Features**: Organization/team support, 2FA, passkeys, magic links - -**API Routes:** -- `POST /api/v1/auth/sign-in/email` - Sign in with email and password -- `POST /api/v1/auth/sign-up/email` - Register new user -- `POST /api/v1/auth/sign-out` - Sign out -- `GET /api/v1/auth/get-session` - Get current session - -**Use Cases:** -- Adding authentication to ObjectStack applications -- Multi-tenant applications with organization support -- OAuth social login integration -- Secure session management - -**Implementation Status:** ✅ **FULLY IMPLEMENTED** - Shipped better-auth integration with an ObjectQL persistence adapter, password hashing, and session/token management - -**Learn more:** [Auth Config Reference](/docs/references/system/auth-config) - ---- - -### @objectstack/plugin-security - -**Description:** Security Plugin for ObjectStack — RBAC, RLS, and Field-Level Security Runtime - -**Purpose:** Provides runtime security enforcement for ObjectStack applications, including role-based access control, row-level security, and field-level masking. - -**Key Features:** -- **RBAC Permission Evaluator**: Checks object-level CRUD permissions per user role -- **Row-Level Security (RLS)**: Compiles policy expressions into ObjectQL query filters -- **Field-Level Masking**: Strips non-readable fields from query results -- **ObjectQL Middleware Integration**: Transparent security enforcement on every operation -- **Most-Permissive Merging**: If any role grants access, the operation is allowed - -**Security Chain (4 steps):** -1. Resolve permission sets from user roles -2. Check CRUD permissions on objects -3. Inject RLS filters into queries -4. Mask restricted fields in results - -**Use Cases:** -- Multi-tenant applications with role-based access -- Data isolation between teams/organizations -- Compliance requirements (field masking for sensitive data) - -**Implementation Status:** ✅ **FULLY IMPLEMENTED** - Production ready - ---- - -### @objectstack/plugin-audit - -**Description:** Audit Plugin for ObjectStack — system audit log object and audit trail. - -**Key Features:** Records create/update/delete activity into a system audit-log object for compliance and forensics. - -**Use Cases:** Compliance audit trails, change tracking, security investigations. - -**Implementation Status:** ✅ **IMPLEMENTED** - ---- - -### @objectstack/plugin-org-scoping - -**Description:** Organization-Scoping Plugin for ObjectStack — row-level organization isolation. - -**Key Features:** Per-org row-level isolation, per-org seed replay, default-org bootstrap. - -**Use Cases:** Multi-tenant data isolation, organization-scoped applications. - -**Implementation Status:** ✅ **IMPLEMENTED** - ---- - -### @objectstack/plugin-dev - -**Description:** Development Mode Plugin for ObjectStack - -**Purpose:** Auto-enables all 17+ kernel services with in-memory implementations for a full-featured API development environment. - -**Key Features:** -- **Zero Configuration**: Single plugin enables entire development stack -- **In-Memory Services**: All services use in-memory implementations -- **Full Protocol Support**: Auth, Data, Metadata, Storage, Analytics, and more -- **Hot Reload Compatible**: Works with `os dev` for hot-reload workflows - -**Use Cases:** -- Rapid prototyping without database setup -- Local development and testing -- CI/CD pipeline testing - -**Implementation Status:** ✅ **FULLY IMPLEMENTED** - Development ready - ---- - -### @objectstack/driver-mongodb - -**Description:** MongoDB driver for ObjectQL - -**Purpose:** Persist objects in MongoDB with native document semantics while still going through the ObjectQL protocol. - -**Use Cases:** Existing MongoDB infrastructure, document-shaped data, hybrid relational/document deployments. - -**Implementation Status:** ⚠️ **IN PROGRESS** - ---- - -### @objectstack/plugin-approvals - -**Description:** Contributes the `approval` flow node (ADR-0019) — an approval rides the one automation engine as a durable-pause node, backed by `sys_approval_request` / `sys_approval_action`. There is no separate approval-process engine. - -**Key Features:** Approver resolution, `first_response` / `unanimous` behavior, record lock, status mirror, per-node SLA escalation, audit trail; multi-step review is successive `approval` nodes on the flow graph. - -**Use Cases:** Expense, quote, contract, and any workflow requiring human sign-off. - -**Implementation Status:** ✅ **IMPLEMENTED** - ---- - -### @objectstack/plugin-sharing - -**Description:** Record-level sharing engine for collaborative access. - -**Key Features:** Manual shares, sharing rules, team-based access, `sys_record_share` table, integration with `plugin-security`. - -**Use Cases:** Granting per-record access beyond static RBAC, Salesforce-style sharing. - -**Implementation Status:** ✅ **IMPLEMENTED** - ---- - -### @objectstack/plugin-email - -**Description:** Outbound email channel for ObjectStack flows and notifications. - -**Key Features:** Provider adapters (SMTP, transactional), MJML templates, delivery tracking, retries. - -**Use Cases:** Transactional email, workflow notifications, approval requests. - -**Implementation Status:** ✅ **IMPLEMENTED** - ---- - -### @objectstack/plugin-webhooks - -**Description:** Outbound HTTP webhook delivery for ObjectStack events. - -**Key Features:** Subscriptions, signed payloads, exponential-backoff retries, delivery logs. - -**Use Cases:** Integrating ObjectStack with external systems (Zapier-style, ETL pipelines, customer integrations). - -**Implementation Status:** ✅ **IMPLEMENTED** - ---- - -### @objectstack/plugin-reports - -**Description:** Metadata-driven report rendering and scheduling. - -**Key Features:** Tabular and aggregate reports, scheduled delivery, multi-format export (CSV/XLSX/PDF). - -**Use Cases:** Operational reporting on top of business objects without writing custom queries. - -**Implementation Status:** ✅ **IMPLEMENTED** - ---- - -### @objectstack/service-messaging - -**Description:** Notification and messaging pipeline service. - -**Purpose:** Provides the single notification ingress, delivery outbox, in-app materialization, preferences, templates, quiet-hours, and digest collapse. - -**Use Cases:** Flow `notify` nodes, collaboration mentions, assignment notifications, inbox messages, email delivery, and future channel plugins. - -**Implementation Status:** ✅ **IMPLEMENTED** - ---- - -### @objectstack/service-settings - -**Description:** Hierarchical, validated application settings. - -**Key Features:** Per-org / per-user settings, Zod-validated namespaces, default fallbacks, runtime override. - -**Use Cases:** Feature flags, tenant configuration, user preferences. - -**Implementation Status:** ✅ **IMPLEMENTED** - ---- - -### @objectstack/formula - -**Description:** Shared CEL formula compiler and runtime. - -**Purpose:** One expression language across validation hooks, predicates, formula fields, conditions, and dynamic seed values. See [Formula skill](/docs/guides/formula). - -**Use Cases:** Anywhere metadata references a CEL expression (`F\`\``, `P\`\``, `cel\`\``). - -**Implementation Status:** ✅ **IMPLEMENTED** - ---- - -### @objectstack/platform-objects - -**Description:** Canonical `sys_*` platform objects bundled with every ObjectOS runtime. - -**Purpose:** Standard system tables — users, sessions, audit logs, approvals, sharing, settings — so applications never redefine identity, audit, or governance primitives. - -**Use Cases:** Always loaded by the runtime; apps reference these via lookups. - -**Implementation Status:** ✅ **IMPLEMENTED** - ---- - -## Connectors - -Connectors register concrete `request`/action handlers on the automation engine's connector registry, letting flows call external systems (ADR-0018 Addendum, ADR-0022/0023/0024). - -### @objectstack/connector-rest - -**Description:** Generic REST connector — the reference concrete connector that registers a `request` action on the connector registry. - -**Use Cases:** Calling arbitrary REST APIs from flows. - -**Implementation Status:** ✅ **IMPLEMENTED** - ---- - -### @objectstack/connector-openapi - -**Description:** OpenAPI 3.x connector generator — turns a declarative OpenAPI document into connector actions, with a self-contained static-auth HTTP transport. - -**Use Cases:** Integrating any OpenAPI-described service as flow actions. - -**Implementation Status:** ✅ **IMPLEMENTED** - ---- - -### @objectstack/connector-mcp - -**Description:** Model Context Protocol (MCP) connector — turns any MCP server's tools into a connector's actions on the automation engine. - -**Use Cases:** Exposing MCP-server tools to flows and agents. - -**Implementation Status:** ✅ **IMPLEMENTED** - ---- - -### @objectstack/connector-slack - -**Description:** Slack Web API connector — registers `chat.postMessage` / `chat.update` / `call` actions on the connector registry. - -**Use Cases:** Posting Slack messages and triggering Slack calls from flows. - -**Implementation Status:** ✅ **IMPLEMENTED** - ---- - -## Triggers - -Trigger packages auto-launch flows in response to events (ADR-0018, ADR-0041). - -### @objectstack/trigger-record-change - -**Description:** Record-change flow trigger — auto-launches flows on object insert/update/delete via ObjectQL lifecycle hooks. - -**Use Cases:** Event-driven automation reacting to data changes. - -**Implementation Status:** ✅ **IMPLEMENTED** - ---- - -### @objectstack/trigger-schedule - -**Description:** Schedule flow trigger — auto-launches flows on a cron/interval/once schedule via the `IJobService`. - -**Use Cases:** Scheduled and recurring automation. - -**Implementation Status:** ✅ **IMPLEMENTED** - ---- - -### @objectstack/trigger-api - -**Description:** Inbound HTTP/webhook flow trigger — per-flow HMAC-verified endpoints with queue-backed ingestion. - -**Use Cases:** Launching flows from external webhooks and inbound HTTP calls. - -**Implementation Status:** ✅ **IMPLEMENTED** - ---- - -## Tools - -### @objectstack/mcp - -**Description:** ObjectStack as an MCP server — exposes your app's objects (and AI tools) over the Model Context Protocol (stdio + Streamable HTTP). - -**Purpose:** Lets MCP clients (and AI agents) discover and operate on ObjectStack data and tools. - -**Use Cases:** Exposing an ObjectStack app to AI assistants and MCP-aware tooling. - -**Implementation Status:** ✅ **IMPLEMENTED** - ---- - -### @objectstack/rest - -**Description:** ObjectStack REST API Server — automatic REST endpoint generation from protocol - -**Purpose:** Turns ObjectStack schema definitions into fully functional CRUD endpoints with zero boilerplate. - -**Key Features:** -- **Auto-Generated Endpoints**: CRUD routes from object schemas -- **Batch Operations**: `/createMany`, `/updateMany`, `/deleteMany`, `/batch` endpoints -- **Metadata API**: `/meta`, `/meta/{type}`, `/meta/{type}/{name}` for runtime introspection -- **Discovery Endpoint**: `/api/v1` for API self-documentation -- **Route Manager**: Centralized route registration, grouping, and middleware chain -- **HTTP Caching**: ETag and Last-Modified header support -- **Configurable Paths**: Plural, kebab-case, and camelCase path transformations - -**Use Cases:** -- Auto-generating REST APIs from metadata -- Building production API servers -- Custom route management - -**Implementation Status:** ✅ **FULLY IMPLEMENTED** - Production ready - ---- - -### create-objectstack - -**Description:** Create a new ObjectStack project — `npx create-objectstack` - -**Purpose:** Interactive project scaffolder for quickly creating new ObjectStack projects. - -**Key Features:** -- **Interactive Mode**: Guided project setup with prompts -- **Template Support**: `full-stack`, `api-only`, `plugin` templates -- **Dependency Installation**: Automatic `pnpm install` (skippable) -- **Zero Config**: Works out-of-the-box with sensible defaults - -**Use Cases:** -- Starting new ObjectStack projects -- Creating plugin packages -- Scaffolding from templates - -**Implementation Status:** ✅ **FULLY IMPLEMENTED** - Production ready - ---- - -### objectstack-vscode - -**Description:** ObjectStack Protocol — Autocomplete, validation, and inline diagnostics for `.object.ts`, `.view.ts`, and `objectstack.config.ts` files - -**Purpose:** VSCode extension providing IDE support for ObjectStack protocol development. - -**Key Features:** -- **Autocomplete**: IntelliSense for ObjectStack schemas -- **Validation**: Real-time schema validation with error diagnostics -- **Protocol Awareness**: Understands `.object.ts`, `.view.ts`, and config files - -**Use Cases:** -- ObjectStack development in VSCode -- Real-time feedback on schema definitions -- Productivity improvement - -**Implementation Status:** ✅ **FULLY IMPLEMENTED** - ---- - -## Package Dependencies - -### Dependency Graph - -``` -@objectstack/spec (no dependencies) - ↓ - ├─→ @objectstack/types (shared runtime interfaces) - ├─→ @objectstack/core (uses spec contracts) - ├─→ @objectstack/metadata (uses spec system schemas) - ├─→ @objectstack/objectql (implements spec protocols) - │ ↓ - │ └─→ @objectstack/runtime (uses objectql engine) - │ ↓ - │ ├─→ @objectstack/rest (REST API generation) - │ ├─→ @objectstack/client (consumes runtime APIs) - │ │ ↓ - │ │ └─→ @objectstack/client-react (wraps client) - │ └─→ @objectstack/hono (Hono adapter) - └─→ @objectstack/cli (validates against spec schemas) - -Plugins (depend on core packages): - ├─→ @objectstack/driver-memory (implements driver interface) - ├─→ @objectstack/plugin-hono-server (HTTP server via @objectstack/hono) - ├─→ @objectstack/plugin-auth (authentication via better-auth) - ├─→ @objectstack/plugin-security (RBAC, RLS, field masking) - └─→ @objectstack/plugin-dev (dev mode, all services in-memory) - -Tools: - ├─→ create-objectstack (project scaffolder) - └─→ objectstack-vscode (VSCode extension) -``` - -### Installation - -**For Application Development:** -```bash -pnpm add @objectstack/runtime @objectstack/client @objectstack/plugin-hono-server -``` - -**For React Applications:** -```bash -pnpm add @objectstack/client-react -``` - -**For Plugin Development:** -```bash -pnpm add @objectstack/core @objectstack/spec -``` - -**For CLI Tools:** -```bash -pnpm add -D @objectstack/cli -# Or install globally -pnpm add -g @objectstack/cli -``` - ---- - -## Version Compatibility - -All packages in the monorepo are versioned together and released simultaneously to ensure compatibility. - -**Current Version:** Check [CHANGELOG.md](https://github.com/objectstack-ai/framework/blob/main/CHANGELOG.md) - -**Compatibility Matrix:** - -| Package Version | Node.js | TypeScript | React (for client-react) | -| :--- | :--- | :--- | :--- | -| 1.0.x | ≥18.0.0 | ≥5.3.0 | ≥18.0.0 | - ---- - -## Next Steps - - - - - - diff --git a/content/docs/concepts/terminology.mdx b/content/docs/concepts/terminology.mdx deleted file mode 100644 index 6320d12c1a..0000000000 --- a/content/docs/concepts/terminology.mdx +++ /dev/null @@ -1,161 +0,0 @@ ---- -title: Terminology -description: The Glossary of the ObjectStack Ecosystem. Speaking the same language. ---- - -import { Book, Server, Code, Database } from 'lucide-react'; - -To navigate the ObjectStack ecosystem effectively, it is helpful to understand the specific vocabulary we use. While many terms are standard in computer science, some have specific nuances in our "Protocol-Driven" context. - -## The Ecosystem - -### ObjectStack -The umbrella term for the entire suite of protocols and reference implementations. It is organized into **15 protocol namespaces** grouped into three architectural layers. - -### Protocol Namespace -A logical grouping of related schemas and types defined with Zod. ObjectStack has 15 protocol namespaces: Data, UI, System, Automation, AI, API, Identity, Security, Kernel, Cloud, QA, Contracts, Integration, Studio, and Shared. - ---- - -## The Three Architectural Layers - -The 15 namespaces collapse into three top-level layers that match the public product vocabulary: - -| Layer | Also called | Namespaces it includes | Purpose | -| :--- | :--- | :--- | :--- | -| **ObjectQL** | Data Layer | Data | Objects, fields, queries, relations, validation, data access | -| **ObjectOS** | Control Layer / System Layer | Kernel, System, Automation, AI, API, Identity, Security, Cloud, Integration, Studio, QA, Contracts, Shared | Runtime, permissions, automation, plugins, tenants, agent tools, artifact loading | -| **ObjectUI** | View Layer | UI | Apps, views, dashboards, actions, presentation metadata | - -When external docs or talks refer to ObjectOS as the "Control Layer", they mean the same runtime described by the System/Kernel/AI/API protocol namespaces below. - ---- - -## The 15 Protocol Namespaces - -### Data Protocol -Defines the core business data model. Includes Object schema, Field types, Validation rules, Query AST, and Filter conditions. This is the foundation of ObjectQL. - -### UI Protocol -Server-Driven UI specification for building user interfaces. Includes App structure, Views (List/Form/Kanban/Calendar), Dashboards, Reports, Themes, and Actions. - -### System Protocol -Infrastructure services including Event Bus, Job Scheduling, Translation (i18n), and Audit Logging. Manages system-level concerns. - -### Kernel Protocol -Plugin system and runtime management. Includes Plugin lifecycle, Manifest definition, Logger configuration, and Runtime Context. The core of ObjectOS. - -### AI Protocol -Artificial intelligence capabilities including AI Agents, RAG pipelines, Natural Language Query (NLQ), Predictive models, Cost tracking, and Orchestration. - -### API Protocol -External communication layer including REST contracts, API discovery, Realtime subscriptions (WebSocket/SSE), and Routing configuration. - -### Automation Protocol -Business process automation including Workflows (state machines), Flows (visual logic), and Webhooks (HTTP callbacks). - -### Identity Protocol -User, organization, and profile schemas for identity management. - -### Security Protocol -RBAC, permissions, policy, and access-control schemas. - -### Cloud Protocol -Multi-tenant cloud, deployment, environment, and package distribution schemas. - -### QA Protocol -Test, validation, and quality-assurance schemas. - -### Contracts Protocol -Cross-package interface contracts shared by runtime packages and services. - -### Integration Protocol -External system integration schemas and connection metadata. - -### Studio Protocol -Studio UI metadata and builder-specific schemas. - -### Shared Protocol -Reusable error maps, suggestions, and metadata normalization utilities. - ---- - -## Architecture Concepts - -### Protocol-Driven -A development paradigm where logic is defined in static, declarative data formats (JSON/YAML) with Zod schemas rather than imperative code. The goal is to separate the **Intent** (Business Logic) from the **Implementation** (Tech Stack). - -### Local-First (development) - -In ObjectStack, "local-first" refers to the **development and runtime mode**, not data sovereignty on end-user devices. Every project can boot against local drivers (in-memory, SQLite, Turso embedded replica) with zero cloud dependency, so authoring, testing, and demos work fully offline. Cloud is an enhancement, not a prerequisite. - -### Agent-Ready Boundaries -The architectural commitment that AI agents act only through typed, permission-aware, auditable capabilities derived from the same metadata artifact that powers the application — never via raw SQL, scraped UI state, or hand-written glue tools. RBAC, RLS, and FLS apply to agent actions exactly as they apply to users. - -### Database Compiler -A system that takes a high-level query AST (Abstract Syntax Tree) and compiles it into an optimized database query string (e.g., SQL). This contrasts with an ORM, which typically acts as a runtime wrapper object. - -### Virtual Field -A field defined in the Data Protocol schema that does not exist physically in the database table but is computed on the fly. -* *Example:* A SQL subquery or expression injected into the `SELECT` statement at compile time. - ---- - -## Data & Schema - -### Object (Entity) -The fundamental unit of data modeling in ObjectStack. Roughly equivalent to a "Table" in SQL or a "Collection" in NoSQL. An Object definition includes Fields, Actions, Triggers, and Permissions. - -### Driver -An adapter plugin in the Data Protocol runtime stack that allows the Data Layer to communicate with a specific underlying storage engine. -* *Example:* `@objectstack/driver-sql` (Postgres / MySQL / SQLite via Knex), `@objectstack/driver-mongodb`. `@objectstack/driver-turso` (edge SQLite) ships with ObjectStack Cloud rather than the open-source framework. - -### AST (Abstract Syntax Tree) -The intermediate representation of a query or schema. The Data Protocol parses a JSON request into an AST before the Driver translates it into SQL/NoSQL queries. This allows for security validation and optimization before execution. - -### Manifest -The entry point configuration file (Kernel Protocol) for an ObjectStack Plugin. It declares dependencies, resources, and extensions using the Manifest schema. - -### Source (`objectstack.config.ts`) -The **authoring** form of an ObjectStack app or host: a TypeScript module that calls `defineStack()` (or composes one with `composeStacks()`). Source files reference Zod schemas, helper functions and `import`s — they only run inside the build/dev toolchain. Edit the source when you change *what the app is*. - -### Artifact (`objectstack.json`) -The **distribution** form, produced by `objectstack build`. A single self-contained JSON document — plus an optional `objectstack-runtime..mjs` sidecar for compiled hooks — that includes the manifest, objects, views, flows and `requires: []` capability list. Artifacts are framework-agnostic, deterministic, signable, and the only thing a production runtime actually needs. `objectstack start` (or any host calling `createDefaultHostConfig()`) can boot directly from an artifact, with **no source files on the target machine**. - ---- - -## Interface & Logic - -### Layout -A JSON structure defined in the UI Protocol that describes the visual arrangement of components. Layouts can be nested and dynamic (e.g., Master-Detail, Grid, Kanban). - -### Workflow -A business process (Automation Protocol) defined as a **Finite State Machine (FSM)**. It consists of States (e.g., `draft`, `approved`), Transitions, and Guards. - -### Flow -A visual logic automation tool (Automation Protocol) that allows building business processes using a node-based editor. Supports screen flows, autolaunched flows, and scheduled flows. - -### Action -A discrete unit of logic (UI Protocol) that can be triggered by a user (UI button) or a system event (Workflow transition). Actions define button behaviors and navigation. - -### Component Registry -A map within the UI Runtime that links a string identifier (e.g., `"chart.bar"`) to a real React Component. This allows the UI Protocol to instantiate UI elements dynamically. - ---- - -## Governance - -### Tenant (Space / Workspace) -A logical isolation unit in the Cloud Protocol for multi-tenancy, modeled by the `tenant` schema (`cloud/tenant.zod.ts`). A single ObjectStack instance can host multiple tenants. Data is segregated by tenant isolation strategies. "Space" and "Workspace" are informal aliases for the same concept. - -### FLS (Field-Level Security) -A granular permission model (Security Protocol) where access control is applied to individual fields (columns), not just the whole object (row). - -### OWD (Organization-Wide Defaults) -The default sharing level (Security Protocol) for records in an object. Determines the baseline access level before sharing rules are applied. - -### Territory -A hierarchical access control model (Security Protocol) that grants data access based on geographic or organizational boundaries. - -### TCK (Technology Compatibility Kit) -A suite of tests that validates if a Driver or Renderer complies with the official ObjectStack Protocol. If a new driver passes the TCK, it is certified as compatible. diff --git a/content/docs/guides/analytics-datasets.mdx b/content/docs/data-modeling/analytics.mdx similarity index 100% rename from content/docs/guides/analytics-datasets.mdx rename to content/docs/data-modeling/analytics.mdx diff --git a/content/docs/guides/driver-configuration.mdx b/content/docs/data-modeling/drivers.mdx similarity index 100% rename from content/docs/guides/driver-configuration.mdx rename to content/docs/data-modeling/drivers.mdx diff --git a/content/docs/guides/external-datasources.mdx b/content/docs/data-modeling/external-datasources.mdx similarity index 97% rename from content/docs/guides/external-datasources.mdx rename to content/docs/data-modeling/external-datasources.mdx index 56cc6127dd..3f13c8e8f6 100644 --- a/content/docs/guides/external-datasources.mdx +++ b/content/docs/data-modeling/external-datasources.mdx @@ -18,7 +18,7 @@ auto-connected, validated at boot, and queryable — with no application code.** This guide is about reading/writing the *live* remote tables (federation). To *copy* rows into ObjectStack-owned tables instead, see seed data / data sync. For the plain multi-datasource routing of **managed** databases ObjectStack owns, see -[Database Drivers](/docs/guides/driver-configuration). +[Database Drivers](/docs/data-modeling/drivers). ## 1. Declare the datasource @@ -167,7 +167,7 @@ default allows all connects (subject to the gating above). ## See also -- [Database Drivers](/docs/guides/driver-configuration) — managed multi-datasource routing. +- [Database Drivers](/docs/data-modeling/drivers) — managed multi-datasource routing. - [Datasource reference](/docs/references/data/datasource) — every `defineDatasource` field. - The `examples/app-showcase` `showcase_external` datasource — a runnable end-to-end demo. - ADR-0015 (federation spec) and ADR-0062 (external-datasource runtime). diff --git a/content/docs/guides/cheatsheets/field-type-decision-tree.mdx b/content/docs/data-modeling/field-type-decision-tree.mdx similarity index 98% rename from content/docs/guides/cheatsheets/field-type-decision-tree.mdx rename to content/docs/data-modeling/field-type-decision-tree.mdx index dac9cfaa73..e59215374a 100644 --- a/content/docs/guides/cheatsheets/field-type-decision-tree.mdx +++ b/content/docs/data-modeling/field-type-decision-tree.mdx @@ -8,7 +8,7 @@ description: Interactive guide for choosing the right ObjectStack field type — Not sure which field type to use? Follow this decision tree to find the right type for your data, then check the quick-reference table for details. -**Full Details:** Once you've identified the right type, see the [Field Type Gallery](/docs/guides/cheatsheets/field-type-gallery) for complete configuration properties. +**Full Details:** Once you've identified the right type, see the [Field Type Gallery](/docs/data-modeling/field-types) for complete configuration properties. --- diff --git a/content/docs/guides/cheatsheets/field-type-gallery.mdx b/content/docs/data-modeling/field-types.mdx similarity index 100% rename from content/docs/guides/cheatsheets/field-type-gallery.mdx rename to content/docs/data-modeling/field-types.mdx diff --git a/content/docs/guides/metadata/field.mdx b/content/docs/data-modeling/fields.mdx similarity index 97% rename from content/docs/guides/metadata/field.mdx rename to content/docs/data-modeling/fields.mdx index 9674c180ee..717aa58af1 100644 --- a/content/docs/guides/metadata/field.mdx +++ b/content/docs/data-modeling/fields.mdx @@ -348,6 +348,6 @@ only for older packages that already emitted it. ## Related -- [Object Metadata](./object) — Define business entities -- [Validation Metadata](./validation) — Field-level and cross-field validation rules -- [View Metadata](./view) — Control how fields are displayed in views +- [Object Metadata](/docs/data-modeling/objects) — Define business entities +- [Validation Metadata](/docs/data-modeling/validation) — Field-level and cross-field validation rules +- [View Metadata](/docs/ui/views) — Control how fields are displayed in views diff --git a/content/docs/guides/formula.mdx b/content/docs/data-modeling/formulas.mdx similarity index 78% rename from content/docs/guides/formula.mdx rename to content/docs/data-modeling/formulas.mdx index 52947564ce..323a75dcea 100644 --- a/content/docs/guides/formula.mdx +++ b/content/docs/data-modeling/formulas.mdx @@ -25,7 +25,7 @@ plus the ObjectStack standard library. > emit it natively), AST-first persistence, and sandboxed execution with > bounded cost. ObjectStack does **not** ship a Salesforce-flavor DSL — the > previous custom 22-function engine was deleted in M9. See -> [north-star §8](../concepts/north-star.mdx) "No private expression DSL". +> [north-star §8](/docs/concepts/north-star) "No private expression DSL". --- @@ -281,6 +281,142 @@ invert the test (here `amount <= 0` rejects non-positive amounts). --- +## Formula patterns + +Complex calculations and logic in formula fields. + +### Conditional Logic + +Formula fields are CEL. Use ternary `cond ? a : b` for conditionals and +`&&`/`||`/`!` for boolean logic. Reference fields via `record.`: + +```typescript +// Tiered pricing +Field.formula({ + label: 'Discount Tier', + returnType: 'text', + expression: ` + record.amount > 1000000 ? "Platinum" : + record.amount > 500000 ? "Gold" : + record.amount > 100000 ? "Silver" : "Bronze" + `, +}) + +// Status indicator +Field.formula({ + label: 'Health Score', + returnType: 'text', + expression: ` + record.is_active && record.days_since_contact < 30 ? "Healthy" : + record.days_since_contact < 90 ? "At Risk" : "Critical" + `, +}) +``` + +### Date Calculations + +```typescript +// Days until close +Field.formula({ + label: 'Days to Close', + returnType: 'number', + expression: 'daysBetween(record.close_date, today())', +}) + +// Contract end in 30 days +Field.formula({ + label: 'Expiring Soon', + returnType: 'boolean', + expression: 'record.status == "active" && daysBetween(record.end_date, today()) <= 30', +}) + +// Age in days +Field.formula({ + label: 'Age (Days)', + returnType: 'number', + expression: 'daysBetween(today(), record.created_date)', +}) +``` + +### Financial Calculations + +```typescript +// Gross margin (computes a number; a formula's type is always 'formula' — +// declare the value type with returnType, and decimal places with scale) +Field.formula({ + label: 'Gross Margin %', + returnType: 'number', + expression: 'record.revenue > 0 ? ((record.revenue - record.cost) / record.revenue) * 100 : 0', + scale: 2, +}) + +// Weighted pipeline +Field.formula({ + label: 'Weighted Amount', + returnType: 'number', + expression: 'record.amount * (record.probability / 100)', + scale: 2, +}) + +// Total with tax +Field.formula({ + label: 'Total with Tax', + returnType: 'number', + expression: 'record.subtotal * 1.0825', // 8.25% tax + scale: 2, +}) +``` + +### Text Manipulation + +```typescript +// Uppercase +Field.formula({ + label: 'Code', + returnType: 'text', + expression: 'upper(record.sku)', +}) + +// Has a company email +Field.formula({ + label: 'Internal', + returnType: 'boolean', + expression: 'endsWith(lower(record.email), "@example.com")', +}) +``` + +### Lead scoring + +```typescript +// Formula: Lead score +Field.formula({ + label: 'Lead Score', + returnType: 'number', + expression: ` + (record.rating == "hot" ? 30 : record.rating == "warm" ? 20 : 10) + + (record.annual_revenue > 1000000 ? 25 : 0) + + (record.number_of_employees > 500 ? 20 : 0) + + (record.industry in ["technology", "finance"] ? 15 : 0) + `, +}) +``` + +### Best practices + +✅ **DO:** +- Keep formulas simple and readable +- Add comments for complex logic +- Test edge cases (null, zero, empty) +- Use appropriate data types + +❌ **DON'T:** +- Create circular references +- Use formulas for frequently changing data +- Nest too many IF statements +- Ignore null handling + +--- + ## Determinism contract Two consecutive `objectstack build` runs with no source changes must produce @@ -344,8 +480,8 @@ validator backs `objectstack build` and metadata registration (and a planned ## Related -- [Field Metadata](./metadata/field) — declaring `type: 'formula'` fields -- [Seed Data](./seed-data) — using `cel\`...\`` for dynamic install-time values -- [Hook Bodies](./hook-bodies) — when to use a JS hook vs a CEL `condition` +- [Field Metadata](/docs/data-modeling/fields) — declaring `type: 'formula'` fields +- [Seed Data](/docs/data-modeling/seed-data) — using `cel\`...\`` for dynamic install-time values +- [Hook Bodies](/docs/automation/hook-bodies) — when to use a JS hook vs a CEL `condition` - [`packages/formula/`](https://github.com/objectstack-ai/framework/tree/main/packages/formula) — engine + stdlib source -- [north-star §8](../concepts/north-star.mdx) — anti-pattern: private DSLs +- [north-star §8](/docs/concepts/north-star) — anti-pattern: private DSLs diff --git a/content/docs/data-modeling/index.mdx b/content/docs/data-modeling/index.mdx new file mode 100644 index 0000000000..6db673790a --- /dev/null +++ b/content/docs/data-modeling/index.mdx @@ -0,0 +1,39 @@ +--- +title: Data Modeling +description: Define objects, fields, relationships, validation, formulas, and queries — the ObjectQL layer that every other module builds on. +--- + +# Data Modeling + +Data modeling is where every ObjectStack application starts: you declare **objects** (business entities), their **fields**, **relationships**, and **validation rules** as metadata, and the platform derives the database schema, APIs, permissions surface, and UI from that single definition. This module is the practical documentation for the **ObjectQL layer** — the Data Protocol described normatively in the [ObjectQL spec](/docs/protocol/objectql). + +## How it fits together + +- An **Object** is the unit of modeling (a table/collection with fields, actions, triggers, and permissions attached). +- Queries are expressed as a JSON **AST** that the runtime validates and a **driver** compiles into SQL/NoSQL for the underlying store — the same model runs on Postgres, MySQL, SQLite, or MongoDB. +- Validation and **formula (CEL) expressions** live in the metadata, so they are enforced identically in the API, UI, and automation layers. +- Data that lives outside ObjectStack can join the model through **external datasources** (federation). + +## What's in this module + + + + + + + + + + + + + + + + + +## Related + +- **Spec:** [ObjectQL — Schema](/docs/protocol/objectql/schema), [Query Syntax](/docs/protocol/objectql/query-syntax), [Type System](/docs/protocol/objectql/types) +- **Schema reference:** [Data](/docs/references/data) +- **Neighbors:** record access rules live in [Permissions & Identity](/docs/permissions); reacting to data changes lives in [Automation](/docs/automation); presenting records lives in [UI Engine](/docs/ui). diff --git a/content/docs/data-modeling/indexing.mdx b/content/docs/data-modeling/indexing.mdx new file mode 100644 index 0000000000..7a0e3adf6f --- /dev/null +++ b/content/docs/data-modeling/indexing.mdx @@ -0,0 +1,45 @@ +--- +title: Database Indexing +description: Optimize query performance with single-field, unique, compound, and lookup indexes +--- + +# Database Indexing + +Optimize query performance with indexes: + +```typescript +indexes: [ + // Single field index + { fields: ['name'], unique: false }, + + // Unique index + { fields: ['email'], unique: true }, + + // Compound index + { fields: ['type', 'is_active'], unique: false }, + + // Lookup field index + { fields: ['owner'], unique: false }, +] +``` + +### When to Add Indexes + +✅ **Add indexes for:** +- Lookup/reference fields +- Fields used in filters +- Fields used for sorting +- Fields in WHERE clauses +- High-cardinality fields + +❌ **Avoid indexes for:** +- Low-cardinality fields (e.g., boolean) +- Fields rarely queried +- Frequently updated fields + +--- + +## See also + +- [Data Modeling overview](/docs/data-modeling) +- [Schema Design](/docs/data-modeling/schema-design) diff --git a/content/docs/data-modeling/meta.json b/content/docs/data-modeling/meta.json new file mode 100644 index 0000000000..5e21d6bd09 --- /dev/null +++ b/content/docs/data-modeling/meta.json @@ -0,0 +1,22 @@ +{ + "title": "Data Modeling", + "icon": "Database", + "pages": [ + "index", + "schema-design", + "objects", + "fields", + "field-types", + "field-type-decision-tree", + "relationships", + "validation", + "validation-rules", + "formulas", + "queries", + "indexing", + "seed-data", + "external-datasources", + "drivers", + "analytics" + ] +} diff --git a/content/docs/guides/metadata/object.mdx b/content/docs/data-modeling/objects.mdx similarity index 95% rename from content/docs/guides/metadata/object.mdx rename to content/docs/data-modeling/objects.mdx index b395132424..7aafbd7a7d 100644 --- a/content/docs/guides/metadata/object.mdx +++ b/content/docs/data-modeling/objects.mdx @@ -207,7 +207,7 @@ indexes: [ | `sharingModel` | `enum` | Org-Wide Default record visibility (ADR-0055/0056). Canonical: `'private'`, `'public_read'`, `'public_read_write'`, `'controlled_by_parent'` (detail visibility derived from its master). Legacy aliases: `'read'`=public_read, `'read_write'`/`'full'`=public_read_write | | `keyPrefix` | `string` | Short prefix for record IDs (e.g. `'001'`) | | `recordTypes` | `string[]` | Record type names for this object | -| `validations` | `ValidationRule[]` | Object-level validation rules (see [Validation](./validation)) | +| `validations` | `ValidationRule[]` | Object-level validation rules (see [Validation](/docs/data-modeling/validation)) | ## Naming Conventions @@ -282,7 +282,7 @@ export const ProjectTask = ObjectSchema.create({ ## Related -- [Field Metadata](./field) — All field types and configuration options -- [Validation Metadata](./validation) — Data integrity rules -- [View Metadata](./view) — Customize how objects are displayed -- [Permission Metadata](./permission) — Control access to objects +- [Field Metadata](/docs/data-modeling/fields) — All field types and configuration options +- [Validation Metadata](/docs/data-modeling/validation) — Data integrity rules +- [View Metadata](/docs/ui/views) — Customize how objects are displayed +- [Permission Metadata](/docs/permissions/permission-metadata) — Control access to objects diff --git a/content/docs/guides/cheatsheets/query-cheat-sheet.mdx b/content/docs/data-modeling/queries.mdx similarity index 100% rename from content/docs/guides/cheatsheets/query-cheat-sheet.mdx rename to content/docs/data-modeling/queries.mdx diff --git a/content/docs/data-modeling/relationships.mdx b/content/docs/data-modeling/relationships.mdx new file mode 100644 index 0000000000..19925f8b8f --- /dev/null +++ b/content/docs/data-modeling/relationships.mdx @@ -0,0 +1,58 @@ +--- +title: "Relationships & Lookups" +description: Model relationships between objects — lookups, filtered lookups, self-referencing hierarchies, and related lists +--- + +# Relationships & Lookups + +### Lookup (Many-to-One) + +Creates a reference to another object: + +```typescript +fields: { + account: Field.lookup('account', { + label: 'Account', + required: true, + }), +} +``` + +**Naming Convention:** Use the object name directly (e.g., `account`, not `account_id`) + +### Filtered Lookups + +Reference records that meet criteria: + +```typescript +contact: Field.lookup('contact', { + label: 'Contact', + referenceFilters: ['account = {account}', 'is_active = true'], +}) +``` + +### Self-Referencing Lookups + +Create hierarchies: + +```typescript +parent_account: Field.lookup('account', { + label: 'Parent Account', + description: 'Parent company in hierarchy', +}) +``` + +### Related Lists + +Child records automatically appear in related lists when a lookup points to the parent. + +**Example:** +- Account has many Contacts (Contact.account → Account) +- Account detail page shows "Contacts" related list + +--- + +## See also + +- [Data Modeling overview](/docs/data-modeling) +- [Schema Design](/docs/data-modeling/schema-design) diff --git a/content/docs/guides/data-modeling.mdx b/content/docs/data-modeling/schema-design.mdx similarity index 56% rename from content/docs/guides/data-modeling.mdx rename to content/docs/data-modeling/schema-design.mdx index cd101ea80b..cceddbf273 100644 --- a/content/docs/guides/data-modeling.mdx +++ b/content/docs/data-modeling/schema-design.mdx @@ -1,23 +1,12 @@ --- -title: Data Modeling Guide -description: Complete guide to designing robust data models in ObjectStack following enterprise best practices +title: Schema Design +description: Design robust object schemas in ObjectStack — object metadata, enable flags, field groups, and enterprise best practices --- -# Data Modeling Guide +# Schema Design Complete guide to designing robust data models in ObjectStack following enterprise best practices. -## Table of Contents - -1. [Object Schema Design](#object-schema-design) -2. [Field Types & Configuration](#field-types--configuration) -3. [Relationships & Lookups](#relationships--lookups) -4. [Validation Rules](#validation-rules) -5. [Formula Fields](#formula-fields) -6. [Field Groups](#field-groups) -7. [Database Indexing](#database-indexing) -8. [Best Practices](#best-practices) - --- ## Object Schema Design @@ -121,114 +110,7 @@ name/title field plus short-text fields. ## Field Types & Configuration -### Text Fields - -```typescript -// Simple text field -Field.text({ - label: 'Account Name', - required: true, - maxLength: 255, - searchable: true, -}) - -// Text area (multi-line) -Field.textarea({ - label: 'Description', - maxLength: 5000, - rows: 5, -}) - -// Rich text / Markdown -Field.markdown({ - label: 'Notes', -}) -``` - -### Numeric Fields - -```typescript -// Number -Field.number({ - label: 'Employees', - min: 0, - max: 1000000, - step: 1, -}) - -// Currency -Field.currency({ - label: 'Annual Revenue', - scale: 2, // Decimal places - min: 0, -}) - -// Percent -Field.percent({ - label: 'Discount', - scale: 2, - min: 0, - max: 100, -}) -``` - -### Date & Time Fields - -```typescript -// Date only -Field.date({ - label: 'Close Date', - required: true, - // Dynamic defaults must be a CEL expression envelope; a bare string - // like 'TODAY()' would be stored verbatim. - defaultValue: { dialect: 'cel', source: 'today()' }, -}) - -// Date and time -Field.datetime({ - label: 'Last Modified', - readonly: true, - defaultValue: { dialect: 'cel', source: 'now()' }, -}) - -// Time only (no `Field.time` helper — use the generic form) -{ type: 'time', label: 'Business Hours Start' } -``` - -### Boolean Field - -```typescript -Field.boolean({ - label: 'Active', - defaultValue: true, -}) -``` - -### Select Fields - -```typescript -// Single select (picklist) -Field.select({ - label: 'Status', - options: [ - { label: 'New', value: 'new', color: '#999999', default: true }, - { label: 'In Progress', value: 'in_progress', color: '#FFA500' }, - { label: 'Completed', value: 'completed', color: '#00AA00' }, - ], - required: true, -}) - -// Multi-select -Field.select({ - label: 'Skills', - multiple: true, - options: [ - { label: 'JavaScript', value: 'js' }, - { label: 'Python', value: 'python' }, - { label: 'Go', value: 'go' }, - ], -}) -``` +ObjectStack fields cover text, numeric, date & time, boolean, select, lookup, address, location, and other specialized data, each configured through `Field.*` factory options. See [Field Metadata](/docs/data-modeling/fields) for how to configure fields and their common properties, and the [Field Type Gallery](/docs/data-modeling/field-types) for the complete per-type reference. ### AutoNumber Field @@ -245,24 +127,6 @@ Field.autonumber({ // Date tokens like {YYYY}/{MM}/{DD} are not interpolated. ``` -### Lookup Fields - -Reference other objects: - -```typescript -// Simple lookup -Field.lookup('account', { - label: 'Account', - required: true, -}) - -// Lookup with filters (array of filter strings) -Field.lookup('contact', { - label: 'Primary Contact', - referenceFilters: ['account = {account}', 'is_active = true'], -}) -``` - ### User Fields Pick a person — the equivalent of Airtable's *Collaborator* or Salesforce's @@ -289,241 +153,17 @@ is equivalent at the storage layer — adopt `Field.user()` with no data migration. Record ownership and row-level security continue to use the existing `owner_id` convention. -### Address Field - -Structured address data: - -```typescript -Field.address({ - label: 'Billing Address', - addressFormat: 'international', // or 'us', 'uk', etc. -}) - -// Stores: -// - street -// - city -// - state/province -// - postal_code -// - country -``` - -### Location Field - -Geographic coordinates: - -```typescript -Field.location({ - label: 'Office Location', - displayMap: true, - allowGeocoding: true, -}) - -// Stores: -// - latitude -// - longitude -``` - -### URL Field - -```typescript -Field.url({ - label: 'Website', -}) -``` - -### Email Field - -```typescript -Field.email({ - label: 'Email Address', - unique: true, -}) -``` - -### Phone Field - -```typescript -Field.text({ - label: 'Phone', - format: 'phone', -}) -``` - -### Color Field - -```typescript -Field.color({ - label: 'Brand Color', - colorFormat: 'hex', // 'hex', 'rgb', 'hsl' - presetColors: [ - '#FF0000', - '#00FF00', - '#0000FF', - ], -}) -``` - ---- - -## Relationships & Lookups - -### Lookup (Many-to-One) - -Creates a reference to another object: - -```typescript -fields: { - account: Field.lookup('account', { - label: 'Account', - required: true, - }), -} -``` - -**Naming Convention:** Use the object name directly (e.g., `account`, not `account_id`) - -### Filtered Lookups - -Reference records that meet criteria: - -```typescript -contact: Field.lookup('contact', { - label: 'Contact', - referenceFilters: ['account = {account}', 'is_active = true'], -}) -``` - -### Self-Referencing Lookups - -Create hierarchies: - -```typescript -parent_account: Field.lookup('account', { - label: 'Parent Account', - description: 'Parent company in hierarchy', -}) -``` - -### Related Lists - -Child records automatically appear in related lists when a lookup points to the parent. - -**Example:** -- Account has many Contacts (Contact.account → Account) -- Account detail page shows "Contacts" related list - --- ## Validation Rules -### Script Validations - -`condition` is a CEL predicate that runs against the record. **When the -predicate evaluates to `TRUE`, validation fails** and the configured message is -raised. Reference fields as `record.`. - -```typescript -validations: [ - { - name: 'revenue_positive', - type: 'script', - severity: 'error', - message: 'Annual Revenue must be positive', - condition: 'record.annual_revenue < 0', - }, - { - name: 'close_date_future', - type: 'script', - severity: 'warning', - message: 'Close Date should be in the future', - condition: 'record.close_date < today()', - }, -] -``` - -### Unique Constraints - -There is no `unique` validation type. Enforce uniqueness with a unique index or -a field-level `unique` flag: - -```typescript -// Unique index -indexes: [ - { fields: ['email'], unique: true }, -] - -// or field-level -Field.email({ label: 'Email', unique: true }) -``` - -### Required Field Validations - -Mark fields as required: - -```typescript -Field.text({ - label: 'Name', - required: true, -}) -``` - -### Validation Severity - -- **`error`**: Prevents save -- **`warning`**: Shows warning but allows save -- **`info`**: Informational message +Validation rules are CEL predicates that run against the record on save — when a `script` rule's `condition` evaluates to `TRUE`, validation fails and the configured message is raised at `error`, `warning`, or `info` severity. Uniqueness is enforced with a unique index or a field-level `unique` flag, not a validation type. See [Validation Metadata](/docs/data-modeling/validation) for all validation types and [Field Validation Rules](/docs/data-modeling/validation-rules) for the built-in constraints of each field type. --- ## Formula Fields -Calculate values automatically: - -Formula expressions are written in **CEL** and reference fields as -`record.`. The calculation goes in the `expression` property (not -`formula`); the field type is already `formula`, so don't pass `type`. - -```typescript -// Simple calculation -Field.formula({ - label: 'Total Price', - expression: 'record.subtotal - record.discount + record.tax', - scale: 2, -}) - -// Conditional logic (CEL ternary) -Field.formula({ - label: 'Priority Level', - expression: 'record.amount > 100000 ? "High" : (record.amount > 50000 ? "Medium" : "Low")', -}) - -// Date calculation -Field.formula({ - label: 'Days to Close', - expression: 'record.close_date < today() ? 1 : 0', -}) - -// Percentage calculation -Field.formula({ - label: 'Response Rate', - expression: 'record.num_sent > 0 ? (record.num_responses / record.num_sent) * 100 : 0', - scale: 2, -}) -``` - -### Common CEL Operators & Functions - -| Construct | Description | Example | -|-----------|-------------|---------| -| `cond ? a : b` | Conditional (ternary) | `record.amount > 1000 ? "High" : "Low"` | -| `&&` | Logical AND | `record.is_active && record.amount > 0` | -| `\|\|` | Logical OR | `record.status == "new" \|\| record.status == "pending"` | -| `!` | Logical NOT | `!record.is_deleted` | -| `isBlank(value)` | Check if blank | `isBlank(record.phone)` | -| `coalesce(a, b)` | First non-null value | `coalesce(record.nickname, record.name)` | -| `today()` | Current date | `today()` | -| `now()` | Current datetime | `now()` | -| `daysFromNow(n)` / `daysAgo(n)` | Date offset | `daysFromNow(30)` | +Formula fields calculate values automatically. Expressions are written in CEL, reference fields as `record.`, and go in the `expression` property — the field type is already `formula`, so don't pass `type`. See [Expressions (CEL)](/docs/data-modeling/formulas) for the expression language, standard library, and cookbook. --- @@ -588,42 +228,6 @@ here (ADR-0085). --- -## Database Indexing - -Optimize query performance with indexes: - -```typescript -indexes: [ - // Single field index - { fields: ['name'], unique: false }, - - // Unique index - { fields: ['email'], unique: true }, - - // Compound index - { fields: ['type', 'is_active'], unique: false }, - - // Lookup field index - { fields: ['owner'], unique: false }, -] -``` - -### When to Add Indexes - -✅ **Add indexes for:** -- Lookup/reference fields -- Fields used in filters -- Fields used for sorting -- Fields in WHERE clauses -- High-cardinality fields - -❌ **Avoid indexes for:** -- Low-cardinality fields (e.g., boolean) -- Fields rarely queried -- Frequently updated fields - ---- - ## Best Practices ### 1. Naming Conventions @@ -771,4 +375,4 @@ export const Account = ObjectSchema.create({ --- -**Next:** [Business Logic →](./business-logic) +**Next:** [Automation →](/docs/automation) diff --git a/content/docs/guides/seed-data.mdx b/content/docs/data-modeling/seed-data.mdx similarity index 99% rename from content/docs/guides/seed-data.mdx rename to content/docs/data-modeling/seed-data.mdx index e8fd11735d..f0e9ae1203 100644 --- a/content/docs/guides/seed-data.mdx +++ b/content/docs/data-modeling/seed-data.mdx @@ -387,4 +387,4 @@ stack's seed runner or store it in an export array. --- -**Next:** [Data Modeling Guide](./data-modeling) +**Next:** [Data Modeling Guide](/docs/data-modeling) diff --git a/content/docs/guides/cheatsheets/field-validation-rules.mdx b/content/docs/data-modeling/validation-rules.mdx similarity index 100% rename from content/docs/guides/cheatsheets/field-validation-rules.mdx rename to content/docs/data-modeling/validation-rules.mdx diff --git a/content/docs/guides/metadata/validation.mdx b/content/docs/data-modeling/validation.mdx similarity index 82% rename from content/docs/guides/metadata/validation.mdx rename to content/docs/data-modeling/validation.mdx index b8a241811d..5ea64e470e 100644 --- a/content/docs/guides/metadata/validation.mdx +++ b/content/docs/data-modeling/validation.mdx @@ -303,8 +303,47 @@ validations: [ // indexes: [{ fields: ['order_number'], unique: true }] ``` +## CEL Functions and Operators + +Conditions and formulas use CEL. Logic is expressed with operators (`&&`, `||`, +`!`, `==`, `!=`, ternary `cond ? a : b`) rather than function calls. The current +record is `record`; the pre-change snapshot is `previous`. The CEL stdlib +functions available include: + +| Function | Description | Example | +|----------|-------------|---------| +| `isBlank(x)` | True if null/empty/whitespace | `isBlank(record.phone)` | +| `isEmpty(x)` | True if empty collection/string | `isEmpty(record.tags)` | +| `coalesce(a, b, …)` | First non-blank value | `coalesce(record.nickname, record.name)` | +| `today()` | Current date | `record.close_date <= today()` | +| `now()` | Current datetime | `record.due_at < now()` | +| `daysBetween(a, b)` | Whole days between two dates | `daysBetween(record.end_date, today())` | +| `upper(s)` / `lower(s)` | Case conversion | `upper(record.sku)` | +| `trim(s)` | Strip whitespace | `trim(record.name)` | +| `contains(s, sub)` / `startsWith` / `endsWith` | Substring checks | `contains(record.email, "@")` | +| `matches(s, regex)` | Regex test | `matches(record.email, "^[^@]+@[^@]+$")` | +| `len(x)` / `size(x)` | Length / size | `len(record.code) == 6` | +| `min(a, b)` / `max(a, b)` / `abs(x)` / `round(x)` | Numerics | `max(record.amount, 0)` | + +To compare against a field's previous value, reference `previous.` +(e.g. `record.stage != previous.stage`). + +## Best Practices + +✅ **DO:** +- Validate at the lowest level possible (field > validation rule > trigger) +- Provide clear, actionable error messages +- Use appropriate severity levels +- Test with real-world data + +❌ **DON'T:** +- Duplicate validations +- Create overly complex conditions +- Block legitimate edge cases +- Use triggers for simple validations + ## Related -- [Object Metadata](./object) — Objects contain validation rules -- [Field Metadata](./field) — Field-level constraints (`required`, `unique`, `min`, `max`) -- [Workflow Metadata](./workflow) — Event-driven business automation +- [Object Metadata](/docs/data-modeling/objects) — Objects contain validation rules +- [Field Metadata](/docs/data-modeling/fields) — Field-level constraints (`required`, `unique`, `min`, `max`) +- [Workflow Metadata](/docs/automation/workflows) — Event-driven business automation diff --git a/content/docs/concepts/cloud-artifact-api.mdx b/content/docs/deployment/cloud-artifact-api.mdx similarity index 96% rename from content/docs/concepts/cloud-artifact-api.mdx rename to content/docs/deployment/cloud-artifact-api.mdx index 86372d67c3..8727d5187b 100644 --- a/content/docs/concepts/cloud-artifact-api.mdx +++ b/content/docs/deployment/cloud-artifact-api.mdx @@ -120,6 +120,6 @@ calls, not data-plane calls. ## Related -- [Deployment Modes](../guides/cloud-deployment) -- [Environment-Scoped Routing](../guides/project-scoping) -- [North Star](./north-star) +- [Deployment Modes](/docs/deployment) +- [Environment-Scoped Routing](/docs/api/environment-routing) +- [North Star](/docs/concepts/north-star) diff --git a/content/docs/guides/environment-variables.mdx b/content/docs/deployment/environment-variables.mdx similarity index 99% rename from content/docs/guides/environment-variables.mdx rename to content/docs/deployment/environment-variables.mdx index 436ef18e9d..4e93e18aea 100644 --- a/content/docs/guides/environment-variables.mdx +++ b/content/docs/deployment/environment-variables.mdx @@ -131,7 +131,7 @@ These variables configure the **cloud / Enterprise** in-UI AI runtime ADR-0025 (`service-ai → cloud; open = MCP-only`). The **open edition** has no in-UI AI runtime to configure: it exposes AI through `@objectstack/mcp` (BYO-AI), where the model and provider are configured in your own MCP client (Claude, -Cursor, a local model, …). See the [AI Capabilities guide](./ai-capabilities). +Cursor, a local model, …). See the [AI Capabilities guide](/docs/ai). | Variable | Type | Default | Description | diff --git a/content/docs/guides/cloud-deployment.mdx b/content/docs/deployment/index.mdx similarity index 96% rename from content/docs/guides/cloud-deployment.mdx rename to content/docs/deployment/index.mdx index 8025edf8b9..e68ace4afb 100644 --- a/content/docs/guides/cloud-deployment.mdx +++ b/content/docs/deployment/index.mdx @@ -156,6 +156,6 @@ managed KMS / Vault provider behind the same `ICryptoProvider` seam. ## Related -- [Single-Environment Mode](./single-project-mode) -- [Environment-Scoped Routing](./project-scoping) -- [Publish, Versioning & Preview](./publish-and-preview) +- [Single-Environment Mode](/docs/deployment/single-project-mode) +- [Environment-Scoped Routing](/docs/api/environment-routing) +- [Publish, Versioning & Preview](/docs/deployment/publish-and-preview) diff --git a/content/docs/deployment/meta.json b/content/docs/deployment/meta.json new file mode 100644 index 0000000000..4cd596d944 --- /dev/null +++ b/content/docs/deployment/meta.json @@ -0,0 +1,15 @@ +{ + "title": "Deployment & Operations", + "icon": "Cloud", + "pages": [ + "index", + "vercel", + "production-readiness", + "publish-and-preview", + "environment-variables", + "single-project-mode", + "cloud-artifact-api", + "migration-from-objectql", + "troubleshooting" + ] +} diff --git a/content/docs/guides/objectql-migration.mdx b/content/docs/deployment/migration-from-objectql.mdx similarity index 99% rename from content/docs/guides/objectql-migration.mdx rename to content/docs/deployment/migration-from-objectql.mdx index e4d7a0b6ff..a711717993 100644 --- a/content/docs/guides/objectql-migration.mdx +++ b/content/docs/deployment/migration-from-objectql.mdx @@ -1,5 +1,5 @@ --- -title: "Migrating from @objectql/core" +title: Migrating from @objectql/core description: Step-by-step guide for migrating from @objectql/core to @objectstack/objectql --- diff --git a/content/docs/guides/production-readiness.mdx b/content/docs/deployment/production-readiness.mdx similarity index 100% rename from content/docs/guides/production-readiness.mdx rename to content/docs/deployment/production-readiness.mdx diff --git a/content/docs/guides/publish-and-preview.mdx b/content/docs/deployment/publish-and-preview.mdx similarity index 90% rename from content/docs/guides/publish-and-preview.mdx rename to content/docs/deployment/publish-and-preview.mdx index 2a8198e9dd..504d860be9 100644 --- a/content/docs/guides/publish-and-preview.mdx +++ b/content/docs/deployment/publish-and-preview.mdx @@ -69,8 +69,8 @@ Common flags: | `--install` | — | Auto-install the new version into `--env` after publishing | In user mode the package is owned by your active organization; in service mode -(bearer key) pass `--org`. See [Packages](./packages) for the package model and the -[Cloud Environment Artifact API](../concepts/cloud-artifact-api) for the +(bearer key) pass `--org`. See [Packages](/docs/plugins/packages) for the package model and the +[Cloud Environment Artifact API](/docs/deployment/cloud-artifact-api) for the control-plane endpoints. --- @@ -98,7 +98,7 @@ Use one of these shapes: ## Related -- [Packages](./packages) -- [Deployment Modes](./cloud-deployment) -- [Environment-Scoped Routing](./project-scoping) -- [Cloud Environment Artifact API](../concepts/cloud-artifact-api) +- [Packages](/docs/plugins/packages) +- [Deployment Modes](/docs/deployment) +- [Environment-Scoped Routing](/docs/api/environment-routing) +- [Cloud Environment Artifact API](/docs/deployment/cloud-artifact-api) diff --git a/content/docs/guides/single-project-mode.mdx b/content/docs/deployment/single-project-mode.mdx similarity index 93% rename from content/docs/guides/single-project-mode.mdx rename to content/docs/deployment/single-project-mode.mdx index 2b8c883a91..a36f4560d6 100644 --- a/content/docs/guides/single-project-mode.mdx +++ b/content/docs/deployment/single-project-mode.mdx @@ -17,7 +17,7 @@ This is the mode used by: - `createStandaloneStack()` / `createDefaultHostConfig()` in `@objectstack/runtime` -Use [Deployment Modes](./cloud-deployment) when you need to publish to an +Use [Deployment Modes](/docs/deployment) when you need to publish to an ObjectStack Cloud control plane or test environment-scoped routing. --- @@ -106,6 +106,6 @@ environments, provision databases, or mount a control plane. ## Related -- [Environment-Scoped Routing](./project-scoping) -- [Deployment Modes](./cloud-deployment) -- [CLI reference](../getting-started/cli) +- [Environment-Scoped Routing](/docs/api/environment-routing) +- [Deployment Modes](/docs/deployment) +- [CLI reference](/docs/getting-started/cli) diff --git a/content/docs/guides/troubleshooting.mdx b/content/docs/deployment/troubleshooting.mdx similarity index 99% rename from content/docs/guides/troubleshooting.mdx rename to content/docs/deployment/troubleshooting.mdx index 4df2d9c1e7..c2570180af 100644 --- a/content/docs/guides/troubleshooting.mdx +++ b/content/docs/deployment/troubleshooting.mdx @@ -17,7 +17,7 @@ Solutions to the most common issues encountered when working with ObjectStack. **Cause:** The `type` value has a typo or uses an unsupported type name. -**Fix:** Use exact type names from the [Field Type Gallery](/docs/guides/cheatsheets/field-type-gallery). Common mistakes: +**Fix:** Use exact type names from the [Field Type Gallery](/docs/data-modeling/field-types). Common mistakes: | ❌ Wrong | ✅ Correct | |:---|:---| diff --git a/content/docs/guides/deployment-vercel.mdx b/content/docs/deployment/vercel.mdx similarity index 95% rename from content/docs/guides/deployment-vercel.mdx rename to content/docs/deployment/vercel.mdx index 607ba519d0..3e8cdfd78c 100644 --- a/content/docs/guides/deployment-vercel.mdx +++ b/content/docs/deployment/vercel.mdx @@ -155,7 +155,7 @@ storage for artifacts. | `OS_S3_SECRET_ACCESS_KEY` | optional | Falls back to AWS SDK credential chain | | `OS_S3_FORCE_PATH_STYLE` | optional | `1` for MinIO / self-hosted | -> See [Publish, Versioning & Preview](./publish-and-preview) for the full +> See [Publish, Versioning & Preview](/docs/deployment/publish-and-preview) for the full > storage matrix (native S3, Cloudflare R2, MinIO, etc.) and what the cloud > control plane stores in each bucket. @@ -178,7 +178,7 @@ storage for artifacts. ## Related -- [Plugin System](/docs/guides/plugins) — the Hono server adapter -- [Client SDK](/docs/guides/client-sdk) — Frontend data fetching -- [Driver Configuration](/docs/guides/driver-configuration) — Database setup -- [Architecture](/docs/getting-started/architecture) — Kernel and runtime overview +- [Plugin System](/docs/plugins) — the Hono server adapter +- [Client SDK](/docs/api/client-sdk) — Frontend data fetching +- [Driver Configuration](/docs/data-modeling/drivers) — Database setup +- [Architecture](/docs/concepts/architecture) — Kernel and runtime overview diff --git a/content/docs/getting-started/architecture.mdx b/content/docs/getting-started/architecture.mdx deleted file mode 100644 index 665cb8f242..0000000000 --- a/content/docs/getting-started/architecture.mdx +++ /dev/null @@ -1,643 +0,0 @@ ---- -title: Protocol Architecture -description: How the Data, System, and UI protocols work together as one cohesive system ---- - -import { Database, Layout, Cpu, ArrowRight, CheckCircle, Workflow, Bot, Cloud } from 'lucide-react'; - -# The Protocol Stack - -The architecture is built on foundational protocols that work together as a unified system: - - - } - title="Data Protocol" - description="ObjectQL: Structure, queries, and constraints." - /> - } - title="UI Protocol" - description="ObjectUI: Presentation, interaction, and routing." - /> - } - title="System Protocol" - description="ObjectOS: Control, runtime, and governance." - /> - } - title="Automation Protocol" - description="Business Logic: Flow, Workflow, Triggers." - /> - } - title="AI Protocol" - description="Intelligence: Agents, RAG, Models." - /> - } - title="Cloud Protocol" - description="Management: Multi-tenancy, Marketplace, Licensing." - /> - - -## Why Separated Layers? - -Traditional applications tightly couple data, business logic, and presentation. This creates **Implementation Coupling** — changing one layer forces changes across the entire stack. - -ObjectStack enforces **Separation of Concerns** through protocol boundaries: - -``` -┌───────────────────────────────────────────────────────────┐ -│ UI Protocol & AI Protocol │ -│ Apps, Views, Dashboards, Agents, RAG │ -│ "How do users and agents interact?" │ -└───────────────────────────┬───────────────────────────────┘ - │ Interface -┌───────────────────────────┴───────────────────────────────┐ -│ System Protocol & Automation Protocol & Cloud Protocol │ -│ Auth, Permissions, Orchestration, Multi-tenancy │ -│ "Who/What can do what, when, and where?" │ -└───────────────────────────┬───────────────────────────────┘ - │ Control -┌───────────────────────────┴───────────────────────────────┐ -│ Data Protocol │ -│ Objects, Fields, Queries, Drivers │ -│ "What is the data structure?" │ -└───────────────────────────────────────────────────────────┘ -``` - -## Layer 1: ObjectQL (Data Protocol) - -**Role:** Define the **Structure** and **Intent** of data. - -**Responsibilities:** -- Object schema definitions (what is a "Customer"?) -- Field types and validation rules -- Query language (filtering, sorting, aggregation) -- Database drivers (Postgres, MongoDB, SQLite) - -**Key Principle:** ObjectQL knows **nothing** about users, permissions, or UI. It only cares about data structure and queries. - -### Example: Defining a Customer Object - -```typescript -// src/objects/customer.object.ts -import { ObjectSchema, Field } from '@objectstack/spec/data'; - -export const Customer = ObjectSchema.create({ - name: 'customer', - label: 'Customer', - icon: 'building', - - fields: { - name: Field.text({ - label: 'Company Name', - required: true, - maxLength: 120, - }), - - industry: Field.select({ - label: 'Industry', - options: [ - { label: 'Technology', value: 'technology' }, - { label: 'Finance', value: 'finance' }, - { label: 'Healthcare', value: 'healthcare' }, - { label: 'Retail', value: 'retail' }, - ], - }), - - annual_revenue: Field.currency({ - label: 'Annual Revenue', - scale: 2, - }), - - primary_contact: Field.lookup('contact', { - label: 'Primary Contact', - }), - }, -}); -``` - -This definition is **pure metadata**. It doesn't know: -- Who can see this data -- How to render a form -- When to trigger workflows - -That's the job of the other layers. - -## Layer 2: ObjectOS (Control Protocol) - -**Role:** Manage the **Lifecycle** and **Governance** of requests. - -**Responsibilities:** -- Authentication (who is this user?) -- Authorization (can they access this field?) -- Workflows and automations (what happens after save?) -- Event processing (audit logs, notifications) -- Multi-tenancy and data isolation - -**Key Principle:** ObjectOS acts as the **Gateway**. No layer can directly access the database; all requests must pass through the OS Kernel. - -### Example: Permission Rules - -```typescript -// src/permissions/sales_rep.permission.ts -import { definePermissionSet } from '@objectstack/spec'; - -// A permission set (here used as a profile) keyed by object and field. -export const SalesRepPermission = definePermissionSet({ - name: 'sales_rep', - label: 'Sales Rep', - isProfile: true, - objects: { - customer: { - allowCreate: true, - allowRead: true, - allowEdit: true, - allowDelete: false, // Only managers can delete - }, - }, - fields: { - // . -> field-level security - 'customer.annual_revenue': { readable: true, editable: false }, // Read-only - }, -}); -``` - -### Example: Workflow Automation - -```typescript -// src/flows/high_value_customer.flow.ts -import { defineFlow } from '@objectstack/spec'; - -// Automation is authored as a Flow: a graph of nodes connected by edges. -// A record_change flow runs when records of its target object change; branch -// edges carry CEL conditions evaluated against the changed record. -export const HighValueCustomerFlow = defineFlow({ - name: 'high_value_customer', - label: 'High-Value Customer Alert', - type: 'record_change', - status: 'active', - nodes: [ - { id: 'start', type: 'start', label: 'Customer created' }, - { id: 'assign', type: 'update_record', label: 'Assign owner' }, - { id: 'notify', type: 'send_email', label: 'Alert leadership' }, - { id: 'end', type: 'end', label: 'End' }, - ], - edges: [ - // Only continue when annual revenue exceeds $1M. - { id: 'e1', source: 'start', target: 'assign', condition: 'record.annual_revenue > 1000000' }, - { id: 'e2', source: 'assign', target: 'notify' }, - { id: 'e3', source: 'notify', target: 'end' }, - ], -}); -``` - -See the [Automation Protocol](/docs/protocol/objectos) for the full Flow node and edge reference. - -ObjectOS **orchestrates** these rules at runtime, independent of the data structure or UI. - -## Layer 3: ObjectUI (View Protocol) - -**Role:** Render the **Presentation** and handle **User Interaction**. - -**Responsibilities:** -- App navigation and branding -- List views (grid, kanban, calendar) -- Form layouts (simple, tabbed, wizard) -- Dashboards and reports -- Actions and buttons - -**Key Principle:** ObjectUI is a **Rendering Engine**, not a hardcoded interface. It asks ObjectQL *"What is the schema?"* and dynamically generates the UI. - -### Example: List View - -```typescript -// src/views/customer.view.ts -import { defineView } from '@objectstack/spec'; - -// A view is authored with defineView({ list, form }); the list/form configs -// are nested, and the data source declares which object the view reads. -export const CustomerView = defineView({ - list: { - type: 'grid', - data: { provider: 'object', object: 'customer' }, - columns: [ - { field: 'name' }, - { field: 'industry' }, - { field: 'annual_revenue' }, - { field: 'primary_contact' }, - ], - filterableFields: ['industry', 'annual_revenue'], - sort: [{ field: 'name', order: 'asc' }], - }, -}); -``` - -### Example: Form View - -```typescript -// src/views/customer.view.ts -import { defineView } from '@objectstack/spec'; - -// The same defineView container also carries the form layout. A form is a -// list of sections, each holding fields. -export const CustomerView = defineView({ - form: { - type: 'simple', - data: { provider: 'object', object: 'customer' }, - sections: [ - { - label: 'Company Information', - fields: ['name', 'industry', 'annual_revenue'], - }, - { - label: 'Contact', - fields: ['primary_contact'], - }, - ], - }, -}); -``` - -The UI doesn't "know" the field types. It asks ObjectQL for the schema and renders accordingly: -- `Field.text` → Text input -- `Field.select` → Dropdown -- `Field.lookup` → Autocomplete lookup -- `Field.currency` → Number input with currency formatting - -## How They Work Together - -Let's trace a **real-world scenario**: A sales rep creates a new high-value customer. - - -The TypeScript in Steps 2–6 below is **conceptual pseudo-code** illustrating the -flow of control between layers. Calls like `Auth.getCurrentUser()`, -`Permission.check()`, `ObjectQL.getSchema()`, and `Workflow.getTriggersFor()` are -not real exported APIs — they stand in for the kernel's internal orchestration. - - -### Step 1: User Action (ObjectUI) - -``` -User fills out the "Create Customer" form: -- Name: "Acme Corp" -- Industry: "Technology" -- Annual Revenue: $5,000,000 -- Primary Contact: "John Doe" - -User clicks "Save" -``` - -### Step 2: UI Layer Sends Request - -```typescript -// ObjectUI dispatches an action to ObjectOS -const request = { - action: 'create', - object: 'customer', - data: { - name: 'Acme Corp', - industry: 'technology', - annual_revenue: 5000000, - primary_contact: 'contact_12345', - }, -}; -``` - -### Step 3: ObjectOS Validates Permissions - -```typescript -// Kernel checks: Does this user have permission? -const user = await Auth.getCurrentUser(); -const canCreate = await Permission.check({ - user, - object: 'customer', - operation: 'create', -}); - -if (!canCreate) { - throw new Error('Permission denied'); -} -``` - -### Step 4: ObjectOS Validates Data - -```typescript -// Kernel asks ObjectQL: Is this data valid? -const schema = ObjectQL.getSchema('customer'); -const validation = schema.validate(request.data); - -if (!validation.success) { - throw new ValidationError(validation.errors); -} -``` - -### Step 5: ObjectQL Writes to Database - -```typescript -// ObjectQL compiles the request into a database operation -const driver = ObjectQL.getDriver(); // Postgres, MongoDB, etc. -const result = await driver.insert('customer', { - name: 'Acme Corp', - industry: 'technology', - annual_revenue: 5000000, - primary_contact_id: 'contact_12345', -}); -``` - -### Step 6: ObjectOS Triggers Workflows - -```typescript -// Kernel checks: Are there any workflows for this event? -const workflows = Workflow.getTriggersFor('customer', 'after_create'); - -for (const workflow of workflows) { - if (workflow.conditionsMet(result)) { - await workflow.execute(result); - } -} - -// In this case: -// ✅ Annual revenue > $1M -// → Assign to enterprise sales team -// → Send alert email to leadership -``` - -### Step 7: ObjectUI Updates Display - -```typescript -// Kernel returns success response -// UI optimistically updates the screen -// UI shows toast notification: "Customer created successfully" -// UI navigates to the new customer detail page -``` - -## The Full Stack in Action - -Here's how all three protocols collaborate for a **Kanban Board** feature: - -### 1. ObjectQL: Define the Data - -```typescript -import { ObjectSchema, Field } from '@objectstack/spec/data'; - -export const Opportunity = ObjectSchema.create({ - name: 'opportunity', - label: 'Opportunity', - icon: 'target', - - fields: { - title: Field.text({ - label: 'Title', - required: true, - }), - - stage: Field.select({ - label: 'Stage', - options: [ - { label: 'Prospecting', value: 'prospecting', default: true }, - { label: 'Qualification', value: 'qualification' }, - { label: 'Proposal', value: 'proposal' }, - { label: 'Closed Won', value: 'closed_won' }, - ], - }), - - amount: Field.currency({ - label: 'Amount', - scale: 2, - }), - - customer: Field.lookup('customer', { - label: 'Customer', - }), - }, -}); -``` - -### 2. ObjectOS: Define Business Rules - -```typescript -import { defineFlow } from '@objectstack/spec'; - -export const OpportunityWonFlow = defineFlow({ - name: 'opportunity_won', - label: 'Opportunity Closed Won', - type: 'record_change', - status: 'active', - nodes: [ - { id: 'start', type: 'start', label: 'Stage changed' }, - { id: 'invoice', type: 'create_record', label: 'Create invoice' }, - { id: 'notify', type: 'send_email', label: 'Notify sales team' }, - { id: 'end', type: 'end', label: 'End' }, - ], - edges: [ - { id: 'e1', source: 'start', target: 'invoice', condition: "record.stage == 'closed_won'" }, - { id: 'e2', source: 'invoice', target: 'notify' }, - { id: 'e3', source: 'notify', target: 'end' }, - ], -}); -``` - -### 3. ObjectUI: Define the Kanban View - -```typescript -import { defineView } from '@objectstack/spec'; - -export const OpportunityKanbanView = defineView({ - list: { - type: 'kanban', - data: { provider: 'object', object: 'opportunity' }, - columns: [ - { field: 'title' }, - { field: 'amount' }, - { field: 'customer' }, - ], - // Kanban-specific config: group columns by the stage field. - kanban: { - groupByField: 'stage', - summarizeField: 'amount', - }, - }, -}); -``` - -### The Result - -When a user **drags an opportunity card** from "Proposal" to "Closed Won": - -1. **ObjectUI** captures the drag-drop event -2. **ObjectOS** checks if the user has permission to update the `stage` field -3. **ObjectQL** validates that `"closed_won"` is a valid option -4. **ObjectQL** writes the update to the database -5. **ObjectOS** triggers the workflow (create invoice, send notification) -6. **ObjectUI** updates the kanban board to reflect the new state - -**All from metadata. Zero hardcoded logic.** - -## Benefits of the Three-Layer Architecture - -### 1. Technology Independence - -Swap implementations without breaking the system: - -``` -Same Metadata Definitions - ↓ -┌─────────┼─────────┐ -ObjectQL: │ │ -Postgres │ MongoDB - │ -ObjectOS: │ -Node.js │ Python - │ -ObjectUI: │ -React │ Flutter -``` - -### 2. Parallel Development - -Teams can work independently on each layer: - -- **Data Team:** Define objects in ObjectQL -- **Backend Team:** Build workflows in ObjectOS -- **Frontend Team:** Create views in ObjectUI - -All communicate through **protocol contracts**, not code dependencies. - -### 3. Incremental Migration - -Adopt ObjectStack gradually: - -- **Phase 1:** Use ObjectQL as an ORM replacement -- **Phase 2:** Add ObjectOS for permissions and workflows -- **Phase 3:** Build ObjectUI views to replace custom forms - -Each layer is independently useful. - -### 4. Testability - -Mock any layer for testing: - -```typescript -// Test ObjectOS workflows without a real database -const mockObjectQL = { - getSchema: () => CustomerSchema, - insert: jest.fn(), -}; - -// Test ObjectUI rendering without a real backend -const mockObjectOS = { - checkPermission: () => true, - executeQuery: () => mockData, -}; -``` - -## Summary - -| Layer | Role | Knows About | Doesn't Know About | -| :--- | :--- | :--- | :--- | -| **ObjectQL** | Data structure & queries | Schema, fields, drivers | Users, permissions, UI | -| **ObjectOS** | Runtime & governance | Auth, workflows, events | Data structure, UI layout | -| **ObjectUI** | Presentation & interaction | Layout, navigation, actions | Business logic, data storage | - -The three protocols are **loosely coupled** but **tightly integrated**: -- They communicate through **standard contracts** (Zod schemas) -- They can be **swapped or upgraded** independently -- They form a **complete system** when combined - -## Next Steps - -- [ObjectQL: Data Protocol](/docs/protocol/objectql) - Full data protocol specification -- [ObjectUI: UI Protocol](/docs/protocol/objectui) - Full view protocol specification -- [ObjectOS: System Protocol](/docs/protocol/objectos) - Full control protocol specification -- [Developer Guide](/docs/getting-started/quick-start) - Build your first ObjectStack application - ---- - -## Appendix: Protocol Dependencies - -Understanding the dependency chain helps you design applications correctly. - -### Data Layer (ObjectQL) - -``` -Field Protocol (Core) - ↓ - ├→ Object Protocol (uses Fields) - ├→ Query Protocol (references Fields) - ├→ Filter Protocol (filters on Fields) - └→ Validation Protocol (validates Fields) - ↓ - └→ Hook Protocol (extends validation with code) -``` - -### UI Layer (ObjectUI) - -``` -Theme Protocol (Foundation) - ↓ -View Protocol (uses Object, Query) - ├→ ListView (uses Query, Filter) - ├→ FormView (uses Object, Field) - └→ Dashboard (uses View, Widget) - ↓ - ├→ Page Protocol (composes Views) - └→ App Protocol (organizes Pages) - ↓ - └→ Action Protocol (UI interactions) -``` - -### System Layer (ObjectOS) - -``` -Data Driver Contracts (Database Abstraction) - ↓ -Datasource Protocol (Connection Config) - ↓ - ├→ Context Protocol (Runtime State) - ├→ Events Protocol (Event Bus) - └→ Plugin Protocol (Extensibility) - ↓ - ├→ Security Protocol (Access Control) - ├→ API Protocol (External Access) - └→ Automation Protocol (Workflows) - ↓ - └→ AI Protocol (Intelligence) -``` - -## Appendix: Usage Patterns - -### Pattern 1: Data-Driven UI - -UI auto-generated from data definitions: - -``` -Object → Field → View → Page → App -``` - -### Pattern 2: Custom UI with Data Binding - -Custom UI connected to data: - -``` -Page → Component → View (Custom) → Query → Object -``` - -### Pattern 3: Automation & Integration - -Business logic automation: - -``` -Object → Hook → Flow → Automation → API/Webhook -``` - -### Pattern 4: AI-Enhanced Applications - -AI capabilities on top of data: - -``` -Object → RAG Pipeline → Agent → Conversation → UI -``` diff --git a/content/docs/getting-started/cli.mdx b/content/docs/getting-started/cli.mdx index 23cdaae6b8..01129678fc 100644 --- a/content/docs/getting-started/cli.mdx +++ b/content/docs/getting-started/cli.mdx @@ -385,7 +385,7 @@ os validate path/to/config # Validate specific file `os validate` will not fail the build on schema/predicate/binding grounds. In a scaffolded project these are wired as `npm run validate` and `npm run build`; your `AGENTS.md` tells coding agents to run `npm run validate` after editing -metadata. See [Validating metadata](/docs/guides/validating-metadata). +metadata. See [Validating metadata](/docs/getting-started/validating-metadata). #### `os info` diff --git a/content/docs/guides/common-patterns.mdx b/content/docs/getting-started/common-patterns.mdx similarity index 97% rename from content/docs/guides/common-patterns.mdx rename to content/docs/getting-started/common-patterns.mdx index 61a4b56bc1..cb5b139421 100644 --- a/content/docs/guides/common-patterns.mdx +++ b/content/docs/getting-started/common-patterns.mdx @@ -504,7 +504,7 @@ export default defineStack({ **Next Steps:** -- [Field Type Gallery](/docs/guides/cheatsheets/field-type-gallery) — Choose the right field type -- [Query Cheat Sheet](/docs/guides/cheatsheets/query-cheat-sheet) — Write powerful queries -- [Error Catalog](/docs/guides/cheatsheets/error-catalog) — Handle errors gracefully +- [Field Type Gallery](/docs/data-modeling/field-types) — Choose the right field type +- [Query Cheat Sheet](/docs/data-modeling/queries) — Write powerful queries +- [Error Catalog](/docs/api/error-catalog) — Handle errors gracefully diff --git a/content/docs/getting-started/core-concepts.mdx b/content/docs/getting-started/core-concepts.mdx deleted file mode 100644 index 5ec9a28fcb..0000000000 --- a/content/docs/getting-started/core-concepts.mdx +++ /dev/null @@ -1,191 +0,0 @@ ---- -title: Core Concepts -description: The foundational ideas behind ObjectStack — metadata-driven development, protocol-first design, and the principles that shape every decision ---- - -import { Scale, Code2, Database, ScrollText, Laptop } from 'lucide-react'; - -# Core Concepts - -Before diving into code, understanding these foundational ideas will make everything else click. - -## Metadata-Driven Development - -Metadata-driven development is a paradigm shift where **application logic is defined by declarative data (metadata), not imperative code.** - -### The Problem with Code-First - -In traditional development, the "Intent" (e.g., *"This field is a required email address"*) is scattered across multiple layers: - -1. **Database:** SQL constraints (`NOT NULL`, `CHECK`) -2. **Backend:** ORM validation (TypeORM decorators, Prisma schemas) -3. **Frontend:** UI validation (React Hook Form + Zod) -4. **Documentation:** API specs (OpenAPI/Swagger) - -When a business requirement changes, you must update code in **three or four places**. This is **Implementation Coupling**. - -### The ObjectStack Way - -ObjectStack centralizes the "Intent" into a **single Protocol Definition**: - - - -```typescript -// ONE definition — everything else derives from it -import { defineStack } from '@objectstack/spec'; - -export default defineStack({ - objects: [{ - name: 'user', - label: 'User', - fields: { - phone: { label: 'Phone Number', type: 'phone', required: true }, - }, - }], -}); -``` - - -```typescript -// Map keys become the `name` field automatically -import { defineStack } from '@objectstack/spec'; - -export default defineStack({ - objects: { - user: { - label: 'User', - fields: { - phone: { label: 'Phone Number', type: 'phone', required: true }, - }, - }, - }, -}); -``` - - - - -**Array or Map?** `defineStack()` accepts both formats for all named metadata collections (`objects`, `apps`, `flows`, etc.). Map keys are injected as the `name` field — pick whichever style you prefer. - - -From this single definition, ObjectStack automatically: - -✅ Generates database schema -✅ Creates validation rules -✅ Builds CRUD APIs -✅ Renders form fields -✅ Produces API documentation - -### The Three Truths - -1. **The UI is a Projection** — The form is generated from the schema, not hand-coded -2. **The API is a Consequence** — REST/GraphQL endpoints appear automatically from object definitions -3. **The Schema is the Application** — Your entire business logic lives in metadata files - -### When to Use Metadata-Driven - -✅ **Great for:** CRUD apps, SaaS platforms, admin panels, rapid prototyping, multi-tenant systems - -❌ **Not ideal for:** Pixel-perfect custom UIs, real-time 3D/games, highly unique domains - ---- - -## Design Principles - -ObjectStack is governed by four unshakable principles: - - - } - title="I. Protocol Neutrality" - description="The Protocol is law. The Implementation is merely an opinion." - /> - } - title="II. Mechanism over Policy" - description="Provide the tools to build rules, do not hardcode the rules themselves." - /> - } - title="III. Single Source of Truth" - description="There is no 'Code'. There is only Schema." - /> - } - title="IV. Agent-Ready Boundaries" - description="Agents may act only through typed, permission-aware, auditable surfaces." - /> - - -### Protocol Neutrality - -**"The Protocol is neutral. The Engine is replaceable."** - -- **Spec before Engine:** Features must be defined in the Specification layer before any engine code is written -- **Zero Leakage:** Implementation details (React, SQL, etc.) never leak into Protocol definitions - -This ensures ObjectStack apps can run on Node.js + PostgreSQL today, Python + SQLite tomorrow, or Rust WASM in the browser. - -### Mechanism over Policy - -**"Give them the physics, not the simulation."** - -| Layer | Responsibility | Example | -| :--- | :--- | :--- | -| **Protocol** | Defines capabilities | A row-level-security policy slot (`operation` + `using` clause) | -| **App** | Defines business logic | `{ operation: 'select', using: "role = 'admin'" }` | -| **Engine** | Enforces the logic | Compiles the `using` condition into a SQL `WHERE` clause | - - -CRUD permissions (`allowRead`, `allowEdit`, …) are simple booleans — they grant or deny an operation. Record-level *conditional* access is a separate mechanism: [Row-Level Security](/docs/getting-started/architecture) policies, whose `using` clause is a SQL-like (PostgreSQL-compatible) predicate over context variables such as `current_user.roles` and `current_user.id`. - - -### Single Source of Truth - -In ObjectStack, **the Object Protocol is the only truth:** - -- The Database is a *derivative* of the Protocol -- The UI is a *projection* of the Protocol -- The API is a *consequence* of the Protocol -- The Agent tool surface is a *bounded capability set* derived from the Protocol - -Change the Protocol → the entire system adapts automatically. - -### Agent-Ready Boundaries - -AI agents should not bypass the application model by calling raw SQL, scraping UI state, or executing arbitrary glue code. They should act through typed, permission-aware capabilities derived from the same metadata artifact that powers the application. - -``` -Traditional AI app: Database schema -> App code -> Custom query -> Hand-written MCP tool -ObjectStack: Zod metadata -> Metadata registry -> ObjectStack runtime -> API / UI / MCP tools -``` - ---- - -## Naming Conventions - -ObjectStack enforces strict naming rules for consistency: - -| Element | Convention | Examples | -|---------|-----------|----------| -| **Object names** (machine) | `snake_case` | `todo_task`, `user_profile` | -| **Field names** (machine) | `snake_case` | `first_name`, `is_active` | -| **Export names** (constants) | `PascalCase` | `TodoTask`, `UserProfile` | -| **Config keys** (properties) | `camelCase` | `maxLength`, `defaultValue` | - -## Summary - -| Aspect | Traditional | Metadata-Driven | -| :--- | :--- | :--- | -| **Definition** | Code in multiple files | Single metadata definition | -| **Changes** | Update 3-4 places | Update once | -| **Type Safety** | Manual synchronization | Automatic from Zod | -| **Flexibility** | Locked to tech stack | Technology agnostic | -| **Boilerplate** | High (300+ lines) | Low (30 lines) | -| **Agent Tools** | Hand-written and drift-prone | Generated from metadata and permissions | - -## Next Steps - -- [Architecture](/docs/getting-started/architecture) — How the protocol layers work together -- [Quick Start](/docs/getting-started/quick-start) — Build your first app in 5 minutes -- [Glossary](/docs/getting-started/glossary) — Key terminology diff --git a/content/docs/getting-started/examples.mdx b/content/docs/getting-started/examples.mdx index af2625f9ee..55dc1417df 100644 --- a/content/docs/getting-started/examples.mdx +++ b/content/docs/getting-started/examples.mdx @@ -356,5 +356,5 @@ my-app/ ## What's Next - [CLI Reference](/docs/getting-started/cli) — All available commands -- [Data Modeling Guide](/docs/guides/data-modeling) — Deep dive into objects and fields +- [Data Modeling Guide](/docs/data-modeling) — Deep dive into objects and fields - [Developer Guide](/docs/getting-started/quick-start) — Full learning path from objects to AI agents diff --git a/content/docs/getting-started/glossary.mdx b/content/docs/getting-started/glossary.mdx index dd5ccd8164..29aaf1e7a1 100644 --- a/content/docs/getting-started/glossary.mdx +++ b/content/docs/getting-started/glossary.mdx @@ -3,20 +3,32 @@ title: Glossary description: The Glossary of the ObjectStack Ecosystem. Speaking the same language. --- -import { Book, Server, Code, Database } from 'lucide-react'; - To navigate the ObjectStack ecosystem effectively, it is helpful to understand the specific vocabulary we use. While many terms are standard in computer science, some have specific nuances in our "Protocol-Driven" context. ## The Ecosystem ### ObjectStack -The umbrella term for the entire suite of protocols and reference implementations. It is organized into **15 protocol namespaces** (enumerated below). +The umbrella term for the entire suite of protocols and reference implementations. It is organized into **15 protocol namespaces** grouped into three architectural layers. ### Protocol Namespace A logical grouping of related schemas and types defined with Zod. ObjectStack has 15 protocol namespaces: Data, UI, System, Automation, AI, API, Identity, Security, Kernel, Cloud, QA, Contracts, Integration, Studio, and Shared. --- +## The Three Architectural Layers + +The 15 namespaces collapse into three top-level layers that match the public product vocabulary: + +| Layer | Also called | Namespaces it includes | Purpose | +| :--- | :--- | :--- | :--- | +| **ObjectQL** | Data Layer | Data | Objects, fields, queries, relations, validation, data access | +| **ObjectOS** | Control Layer / System Layer | Kernel, System, Automation, AI, API, Identity, Security, Cloud, Integration, Studio, QA, Contracts, Shared | Runtime, permissions, automation, plugins, tenants, agent tools, artifact loading | +| **ObjectUI** | View Layer | UI | Apps, views, dashboards, actions, presentation metadata | + +When external docs or talks refer to ObjectOS as the "Control Layer", they mean the same runtime described by the System/Kernel/AI/API protocol namespaces below. + +--- + ## The 15 Protocol Namespaces ### Data Protocol @@ -103,6 +115,12 @@ The intermediate representation of a query or schema. The Data Protocol parses a ### Manifest The entry point configuration file (Kernel Protocol) for an ObjectStack Plugin. It declares dependencies, resources, and extensions using the Manifest schema. +### Source (`objectstack.config.ts`) +The **authoring** form of an ObjectStack app or host: a TypeScript module that calls `defineStack()` (or composes one with `composeStacks()`). Source files reference Zod schemas, helper functions and `import`s — they only run inside the build/dev toolchain. Edit the source when you change *what the app is*. + +### Artifact (`objectstack.json`) +The **distribution** form, produced by `objectstack build`. A single self-contained JSON document — plus an optional `objectstack-runtime..mjs` sidecar for compiled hooks — that includes the manifest, objects, views, flows and `requires: []` capability list. Artifacts are framework-agnostic, deterministic, signable, and the only thing a production runtime actually needs. `objectstack start` (or any host calling `createDefaultHostConfig()`) can boot directly from an artifact, with **no source files on the target machine**. + --- ## Interface & Logic @@ -126,8 +144,8 @@ A map within the UI Runtime that links a string identifier (e.g., `"chart.bar"`) ## Governance -### Space (Workspace) -A logical isolation unit in the Cloud Protocol for multi-tenancy. A single ObjectStack instance can host multiple Spaces. Data is physically segregated by tenant isolation strategies. +### Tenant (Space / Workspace) +A logical isolation unit in the Cloud Protocol for multi-tenancy, modeled by the `tenant` schema (`cloud/tenant.zod.ts`). A single ObjectStack instance can host multiple tenants. Data is segregated by tenant isolation strategies. "Space" and "Workspace" are informal aliases for the same concept. ### FLS (Field-Level Security) A granular permission model (Security Protocol) where access control is applied to individual fields (columns), not just the whole object (row). diff --git a/content/docs/getting-started/index.mdx b/content/docs/getting-started/index.mdx index b91a408cbd..eac36f6eaf 100644 --- a/content/docs/getting-started/index.mdx +++ b/content/docs/getting-started/index.mdx @@ -140,11 +140,11 @@ lsof -i :3000 OS_PORT=3001 pnpm dev ``` -For more troubleshooting, see the [Troubleshooting & FAQ](/docs/guides/troubleshooting) guide. +For more troubleshooting, see the [Troubleshooting & FAQ](/docs/deployment/troubleshooting) guide. ## Next Steps -- [Core Concepts](/docs/getting-started/core-concepts) — Metadata-driven development & design principles -- [Architecture](/docs/getting-started/architecture) — The three-layer protocol stack +- [Core Concepts](/docs/concepts) — Metadata-driven development & design principles +- [Architecture](/docs/concepts/architecture) — The three-layer protocol stack - [Glossary](/docs/getting-started/glossary) — Key terminology - [Quick Start](/docs/getting-started/quick-start) — Build your first app in 5 minutes diff --git a/content/docs/getting-started/meta.json b/content/docs/getting-started/meta.json index 549a47e10c..de00dc59e7 100644 --- a/content/docs/getting-started/meta.json +++ b/content/docs/getting-started/meta.json @@ -1,6 +1,15 @@ { - "title": "Getting Started", + "title": "Get Started", "icon": "Rocket", - "root": true, - "pages": ["index", "quick-start", "core-concepts", "architecture", "examples", "cli", "glossary"] + "defaultOpen": true, + "pages": [ + "index", + "quick-start", + "examples", + "cli", + "validating-metadata", + "common-patterns", + "quick-reference", + "glossary" + ] } diff --git a/content/docs/getting-started/quick-reference.mdx b/content/docs/getting-started/quick-reference.mdx new file mode 100644 index 0000000000..419cb87514 --- /dev/null +++ b/content/docs/getting-started/quick-reference.mdx @@ -0,0 +1,317 @@ +--- +title: Quick Reference Guide +description: Fast lookup table for all ObjectStack protocols +--- + + +# Quick Reference Guide + +Fast lookup for all 175 ObjectStack protocols organized by category. + + +Click on any protocol name to view its complete API reference. + + +## Data Protocol (18 schemas) + +Core business logic and data modeling schemas. + +| Protocol | Source File | Key Schemas | Purpose | +|:---------|:-----------|:------------|:--------| +| **[Field](/docs/references/data/field)** | `field.zod.ts` | Field, FieldType, SelectOption | 44 field types for data modeling | +| **[Object](/docs/references/data/object)** | `object.zod.ts` | Object, ObjectCapabilities | Object/table definitions | +| **[Query](/docs/references/data/query)** | `query.zod.ts` | Query, QueryOptions | Query AST with joins, aggregations | +| **[Filter](/docs/references/data/filter)** | `filter.zod.ts` | QueryFilter, FilterCondition | Advanced filtering operators | +| **[Validation](/docs/references/data/validation)** | `validation.zod.ts` | ValidationRule | Business validation rules | +| **[Dataset](./data/dataset)** | `dataset.zod.ts` | Dataset, DatasetMode | Reusable dataset definitions | +| **[Datasource](/docs/references/data/datasource)** | `datasource.zod.ts` | Datasource, DatasourceType | Database connection configs | +| **[Analytics](/docs/references/data/analytics)** | `analytics.zod.ts` | Analytics | Data analytics and aggregation | +| **[Mapping](/docs/references/data/mapping)** | `mapping.zod.ts` | FieldMapping | Field transformation mappings | +| **[Hook](/docs/references/data/hook)** | `hook.zod.ts` | Hook, HookEvent | Lifecycle event hooks | +| **[Data Engine](/docs/references/data/data-engine)** | `data-engine.zod.ts` | DataEngine | Data engine configuration | +| **[Driver](/docs/references/data/driver)** | `driver.zod.ts` | Driver, DriverCapabilities | Database driver interface | +| **[SQL Driver](/docs/references/data/driver-sql)** | `driver-sql.zod.ts` | SQLDriver | SQL-specific driver | +| **[NoSQL Driver](/docs/references/data/driver-nosql)** | `driver-nosql.zod.ts` | NoSQLDriver | NoSQL-specific driver | +| **[Document](/docs/references/data/document)** | `document.zod.ts` | Document | Document-oriented data | +| **[External Lookup](/docs/references/data/external-lookup)** | `external-lookup.zod.ts` | ExternalLookup | External data lookups | +| **[Postgres Driver](./data/driver/postgres)** | `driver/postgres.zod.ts` | PostgresConfig | PostgreSQL configuration | +| **[Mongo Driver](./data/driver/mongo)** | `driver/mongo.zod.ts` | MongoConfig | MongoDB configuration | + +## UI Protocol (10 schemas) + +Presentation layer - views, forms, dashboards, and themes. + +| Protocol | Source File | Key Schemas | Purpose | +|:---------|:-----------|:------------|:--------| +| **[View](/docs/references/ui/view)** | `view.zod.ts` | View, ListView, FormView | List and form view configurations | +| **[Page](/docs/references/ui/page)** | `page.zod.ts` | Page, PageComponent | FlexiPage layouts | +| **[App](/docs/references/ui/app)** | `app.zod.ts` | App, NavigationItem | Application navigation structure | +| **[Dashboard](/docs/references/ui/dashboard)** | `dashboard.zod.ts` | Dashboard, DashboardWidget | Dashboard layouts and widgets | +| **[Report](/docs/references/ui/report)** | `report.zod.ts` | Report, ReportType | Report definitions | +| **[Action](/docs/references/ui/action)** | `action.zod.ts` | Action, ActionType | UI button actions | +| **[Component](/docs/references/ui/component)** | `component.zod.ts` | PageComponent variants | Reusable UI components | +| **[Chart](/docs/references/ui/chart)** | `chart.zod.ts` | Chart, ChartType | Chart definitions | +| **[Theme](/docs/references/ui/theme)** | `theme.zod.ts` | Theme, ColorPalette | Theming and branding | +| **[Widget](/docs/references/ui/widget)** | `widget.zod.ts` | WidgetManifest | Custom widget definitions | + +## Kernel Protocol (17 schemas) + +Plugin architecture, manifests, and kernel runtime. + +| Protocol | Source File | Key Schemas | Purpose | +|:---------|:-----------|:------------|:--------| +| **[Manifest](/docs/references/kernel/manifest)** | `manifest.zod.ts` | Manifest | Package manifest (objectstack.config.ts) | +| **[Context](/docs/references/kernel/context)** | `context.zod.ts` | KernelContext | Runtime execution context | +| **[Plugin](/docs/references/kernel/plugin)** | `plugin.zod.ts` | Plugin, PluginHook | Plugin system interface | +| **[Plugin Capability](/docs/references/kernel/plugin-capability)** | `plugin-capability.zod.ts` | PluginCapability | Plugin capability declarations | +| **[Plugin Lifecycle](/docs/references/kernel/plugin-lifecycle-events)** | `plugin-lifecycle-events.zod.ts` | PluginLifecycleEvents | Plugin lifecycle events | +| **[Plugin Lifecycle Advanced](/docs/references/kernel/plugin-lifecycle-advanced)** | `plugin-lifecycle-advanced.zod.ts` | PluginLifecycleAdvanced | Advanced lifecycle hooks | +| **[Plugin Loading](/docs/references/kernel/plugin-loading)** | `plugin-loading.zod.ts` | PluginLoading | Plugin loading and init | +| **[Plugin Security](/docs/references/kernel/plugin-security-advanced)** | `plugin-security-advanced.zod.ts` | PluginSecurityAdvanced | Plugin sandboxing | +| **[Plugin Structure](/docs/references/kernel/plugin-structure)** | `plugin-structure.zod.ts` | PluginStructure | Plugin file conventions | +| **[Plugin Validator](/docs/references/kernel/plugin-validator)** | `plugin-validator.zod.ts` | PluginValidator | Plugin validation | +| **[Plugin Versioning](/docs/references/kernel/plugin-versioning)** | `plugin-versioning.zod.ts` | PluginVersioning | Version compatibility | +| **[Service Registry](/docs/references/kernel/service-registry)** | `service-registry.zod.ts` | ServiceRegistry | Service discovery | +| **[Startup Orchestrator](/docs/references/kernel/startup-orchestrator)** | `startup-orchestrator.zod.ts` | StartupOrchestrator | System startup | +| **[Events](./kernel/events)** | `events.zod.ts` | Event, EventBus | System event bus | +| **[Feature](/docs/references/kernel/feature)** | `feature.zod.ts` | FeatureFlag | Feature flags | +| **[Metadata Loader](/docs/references/kernel/metadata-loader)** | `metadata-loader.zod.ts` | MetadataLoader | Metadata loading | +| **[Package Registry](/docs/references/kernel/package-registry)** | `package-registry.zod.ts` | PackageRegistry | Package resolution | + +## System Protocol (22 schemas) + +Runtime environment, logging, jobs, caching, and observability. + +| Protocol | Source File | Key Schemas | Purpose | +|:---------|:-----------|:------------|:--------| +| **[Audit](/docs/references/system/audit)** | `audit.zod.ts` | AuditLog, AuditEvent | Audit trail logging | +| **[Auth Config](/docs/references/system/auth-config)** | `auth-config.zod.ts` | AuthConfig | Authentication configuration | +| **[Cache](/docs/references/system/cache)** | `cache.zod.ts` | CacheConfig | Caching layer | +| **[Change Management](/docs/references/system/change-management)** | `change-management.zod.ts` | ChangeManagement | Change tracking | +| **[Collaboration](/docs/references/system/collaboration)** | `collaboration.zod.ts` | Collaboration | Real-time collab | +| **[Compliance](/docs/references/system/compliance)** | `compliance.zod.ts` | Compliance | Regulatory controls | +| **[Encryption](/docs/references/system/encryption)** | `encryption.zod.ts` | Encryption | Encryption & keys | +| **[HTTP Server](/docs/references/system/http-server)** | `http-server.zod.ts` | HTTPServer | HTTP server config | +| **[Job](/docs/references/system/job)** | `job.zod.ts` | Job, JobSchedule | Background job queue | +| **[Logging](/docs/references/system/logging)** | `logging.zod.ts` | LoggingConfig | Structured logging | +| **[Masking](/docs/references/system/masking)** | `masking.zod.ts` | Masking | Data masking | +| **[Message Queue](/docs/references/system/message-queue)** | `message-queue.zod.ts` | MessageQueue | Message queuing | +| **[Metadata Persistence](/docs/references/system/metadata-persistence)** | `metadata-persistence.zod.ts` | MetadataPersistence | Metadata storage | +| **[Metrics](/docs/references/system/metrics)** | `metrics.zod.ts` | Metrics | Application metrics | +| **[Migration](/docs/references/system/migration)** | `migration.zod.ts` | Migration | Schema migration | +| **[Notification](/docs/references/system/notification)** | `notification.zod.ts` | Notification | Notifications | +| **[Object Storage](/docs/references/system/object-storage)** | `object-storage.zod.ts` | ObjectStorage | Object storage | +| **[Search Engine](/docs/references/system/search-engine)** | `search-engine.zod.ts` | SearchEngine | Full-text search | +| **[Service Registry](./system/service-registry)** | `service-registry.zod.ts` | ServiceRegistry | System services | +| **[Tracing](/docs/references/system/tracing)** | `tracing.zod.ts` | Tracing | Distributed tracing | +| **[Translation](/docs/references/system/translation)** | `translation.zod.ts` | Translation | i18n support | +| **[Worker](/docs/references/system/worker)** | `worker.zod.ts` | Worker | Background workers | + +## AI Protocol (13 schemas) + +AI/ML capabilities - agents, models, RAG, and cost tracking. + +| Protocol | Source File | Key Schemas | Purpose | +|:---------|:-----------|:------------|:--------| +| **[Agent](/docs/references/ai/agent)** | `agent.zod.ts` | Agent, AITool | AI agent definitions | +| **[Agent Action](./ai/agent-action)** | `agent-action.zod.ts` | AgentAction | Agent action definitions | +| **[Model Registry](/docs/references/ai/model-registry)** | `model-registry.zod.ts` | ModelRegistry, ModelProvider | LLM model management | +| **[RAG Pipeline](./ai/rag-pipeline)** | `rag-pipeline.zod.ts` | RAGPipelineConfig | Retrieval augmented generation | +| **[NLQ](./ai/nlq)** | `nlq.zod.ts` | NLQRequest, NLQResponse | Natural language to query | +| **[Conversation](/docs/references/ai/conversation)** | `conversation.zod.ts` | ConversationSession | Conversation management | +| **[Cost](./ai/cost)** | `cost.zod.ts` | CostEntry, BudgetLimit | AI cost tracking and budgets | +| **[Predictive](./ai/predictive)** | `predictive.zod.ts` | PredictiveModel | Predictive ML models | +| **[Orchestration](./ai/orchestration)** | `orchestration.zod.ts` | AIOrchestration | Multi-agent orchestration | +| **[Feedback Loop](./ai/feedback-loop)** | `feedback-loop.zod.ts` | FeedbackLoop | AI feedback and learning | +| **[DevOps Agent](./ai/devops-agent)** | `devops-agent.zod.ts` | DevOpsAgent | DevOps automation | +| **[Plugin Development](./ai/plugin-development)** | `plugin-development.zod.ts` | PluginDevelopment | AI-assisted development | +| **[Runtime Ops](./ai/runtime-ops)** | `runtime-ops.zod.ts` | RuntimeOps | AI runtime operations | + +## API Protocol (20 schemas) + +REST/GraphQL endpoints, real-time subscriptions, and discovery. + +| Protocol | Source File | Key Schemas | Purpose | +|:---------|:-----------|:------------|:--------| +| **[Contract](/docs/references/api/contract)** | `contract.zod.ts` | APIContract | API contract definitions | +| **[Endpoint](/docs/references/api/endpoint)** | `endpoint.zod.ts` | Endpoint, EndpointMethod | REST endpoint configuration | +| **[Router](/docs/references/api/router)** | `router.zod.ts` | Router, Route | API routing rules | +| **[OData](/docs/references/api/odata)** | `odata.zod.ts` | ODataQuery | OData protocol support | +| **[GraphQL](/docs/references/api/graphql)** | `graphql.zod.ts` | GraphQLSchema | GraphQL API config | +| **[Realtime](/docs/references/api/realtime)** | `realtime.zod.ts` | Subscription, Channel | WebSocket subscriptions | +| **[WebSocket](/docs/references/api/websocket)** | `websocket.zod.ts` | WebSocketConfig | WebSocket protocol | +| **[Discovery](/docs/references/api/discovery)** | `discovery.zod.ts` | ServiceDiscovery | API discovery and metadata | +| **[Batch](/docs/references/api/batch)** | `batch.zod.ts` | BatchRequest | Batch API processing | +| **[HTTP Cache](/docs/references/api/http-cache)** | `http-cache.zod.ts` | CacheStrategy | HTTP caching | +| **[Errors](/docs/references/api/errors)** | `errors.zod.ts` | ErrorResponse | Error responses | +| **[Protocol](/docs/references/api/protocol)** | `protocol.zod.ts` | ProtocolDefinition | Protocol definitions | +| **[REST Server](/docs/references/api/rest-server)** | `rest-server.zod.ts` | RESTServer | REST server config | +| **[Auth](/docs/references/api/auth)** | `auth.zod.ts` | Auth | API authentication | +| **[Analytics](/docs/references/api/analytics)** | `analytics.zod.ts` | Analytics | API usage analytics | +| **[Documentation](/docs/references/api/documentation)** | `documentation.zod.ts` | Documentation | API docs generation | +| **[Hub](./api/hub)** | `hub.zod.ts` | Hub | API hub integration | +| **[Metadata](/docs/references/api/metadata)** | `metadata.zod.ts` | Metadata | API metadata endpoints | +| **[Registry](/docs/references/api/registry)** | `registry.zod.ts` | Registry | API registry | +| **[Storage](/docs/references/api/storage)** | `storage.zod.ts` | Storage | API storage operations | + +## Automation Protocol (8 schemas) + +Flows, state machines, approvals, and integrations. + +| Protocol | Source File | Key Schemas | Purpose | +|:---------|:-----------|:------------|:--------| +| **[Flow](/docs/references/automation/flow)** | `flow.zod.ts` | Flow, FlowNode | Visual workflow builder | +| **[Workflow](./automation/workflow)** | `state-machine.zod.ts` | StateMachine | Historical route; current workflow semantics are state machines plus Flow | +| **[Approval](/docs/references/automation/approval)** | `approval.zod.ts` | ApprovalNodeConfig | Flow approval-node config | +| **[State Machine](/docs/references/automation/state-machine)** | `state-machine.zod.ts` | StateMachine | State machine definitions | +| **[Webhook](/docs/references/automation/webhook)** | `webhook.zod.ts` | Webhook, WebhookEvent | Outbound webhooks | +| **[ETL](/docs/references/automation/etl)** | `etl.zod.ts` | ETLPipeline | Data transformation pipelines | +| **[Trigger Registry](/docs/references/automation/trigger-registry)** | `trigger-registry.zod.ts` | TriggerRegistry | Event-driven triggers | +| **[Sync](/docs/references/automation/sync)** | `sync.zod.ts` | SyncConfig | Bi-directional data sync | + +## Security Protocol (5 schemas) + +Access control, permissions, and row-level security. + +| Protocol | Source File | Key Schemas | Purpose | +|:---------|:-----------|:------------|:--------| +| **[Permission](/docs/references/security/permission)** | `permission.zod.ts` | ObjectPermission | Object-level permissions | +| **[Policy](./security/policy)** | `policy.zod.ts` | SecurityPolicy | Security policies | +| **[RLS](/docs/references/security/rls)** | `rls.zod.ts` | RowLevelSecurity | Row-level security filters | +| **[Sharing](/docs/references/security/sharing)** | `sharing.zod.ts` | SharingRule | Record sharing rules | +| **[Territory](/docs/references/security/territory)** | `territory.zod.ts` | Territory | Territory-based access | + +## Identity Protocol (4 schemas) + +User identity, organizations, and role management. + +| Protocol | Source File | Key Schemas | Purpose | +|:---------|:-----------|:------------|:--------| +| **[Identity](/docs/references/identity/identity)** | `identity.zod.ts` | Identity, User | User identity management | +| **[Organization](/docs/references/identity/organization)** | `organization.zod.ts` | Organization | Multi-organization support | +| **[Role](/docs/references/identity/role)** | `role.zod.ts` | Role | Role-based access control | +| **[SCIM](/docs/references/identity/scim)** | `scim.zod.ts` | SCIMUser, SCIMGroup | SCIM 2.0 provisioning | + +## Cloud Protocol (9 schemas) + +Marketplace, licensing, and multi-tenancy. + +| Protocol | Source File | Key Schemas | Purpose | +|:---------|:-----------|:------------|:--------| +| **[Marketplace](./hub/marketplace)** | `marketplace.zod.ts` | Package, PackageVersion | Plugin marketplace | +| **[Plugin Registry](./hub/plugin-registry)** | `plugin-registry.zod.ts` | PluginRegistry | Plugin versioning | +| **[Plugin Security](./hub/plugin-security)** | `plugin-security.zod.ts` | PluginSecurity | Plugin security policies | +| **[Composer](./hub/composer)** | `composer.zod.ts` | Dependency | Dependency management | +| **[License](./hub/license)** | `license.zod.ts` | License, LicenseType | Feature licensing | +| **[Tenant](./hub/tenant)** | `tenant.zod.ts` | Tenant | Multi-tenancy isolation | +| **[Space](./hub/space)** | `space.zod.ts` | Space, Workspace | Workspace management | +| **[Hub Federation](./hub/hub-federation)** | `hub-federation.zod.ts` | HubFederation | Cross-instance federation | +| **[Registry Config](./hub/registry-config)** | `registry-config.zod.ts` | RegistryConfig | Registry settings | + +## Integration Protocol (7 schemas) + +External system connectors and adapters. + +| Protocol | Source File | Key Schemas | Purpose | +|:---------|:-----------|:------------|:--------| +| **[Connector](/docs/references/integration/connector)** | `connector.zod.ts` | Connector | Generic connector interface | +| **[SaaS Connector](./integration/connector/saas)** | `connector/saas.zod.ts` | SaaSConnector | SaaS integrations | +| **[Database Connector](./integration/connector/database)** | `connector/database.zod.ts` | DatabaseConnector | Database adapters | +| **[File Storage](./integration/connector/file-storage)** | `connector/file-storage.zod.ts` | FileStorageConnector | Cloud storage | +| **[Message Queue](./integration/connector/message-queue)** | `connector/message-queue.zod.ts` | MessageQueueConnector | Queue integrations | +| **[GitHub](./integration/connector/github)** | `connector/github.zod.ts` | GitHubConnector | GitHub API integration | +| **[Vercel](./integration/connector/vercel)** | `connector/vercel.zod.ts` | VercelConnector | Vercel deployment | + +## Shared Protocol (4 schemas) + +Common utilities used across all protocols. + +| Protocol | Source File | Key Schemas | Purpose | +|:---------|:-----------|:------------|:--------| +| **[HTTP](/docs/references/shared/http)** | `http.zod.ts` | HTTPRequest, HTTPResponse | HTTP utilities | +| **[Identifiers](/docs/references/shared/identifiers)** | `identifiers.zod.ts` | ID formats | Standard ID patterns | +| **[Mapping](./shared/mapping)** | `mapping.zod.ts` | MappingRule | Field mapping utilities | +| **[Connector Auth](./shared/connector-auth)** | `connector-auth.zod.ts` | ConnectorAuth | Connector auth patterns | + +## QA Protocol (1 schema) + +Testing and quality assurance. + +| Protocol | Source File | Key Schemas | Purpose | +|:---------|:-----------|:------------|:--------| +| **[Testing](/docs/references/qa/testing)** | `testing.zod.ts` | TestSuite | Declarative test definitions | + +--- + +## Common Patterns + +### Naming Conventions + + + + ```typescript + // Property names in schemas: camelCase + { + maxLength: 100, + defaultValue: 'example', + referenceFilters: ['active = true'] + } + ``` + + + ```typescript + // Machine identifiers in data: snake_case + { + name: 'project_task', + object: 'customer', + field: 'first_name' + } + ``` + + + ```typescript + // Export names: PascalCase + Schema suffix + export const FieldSchema = z.object({...}); + export type Field = z.infer; + ``` + + + +### Common Imports + +```typescript +// Data protocols +import { FieldSchema, ObjectSchema, QuerySchema } from '@objectstack/spec/data'; + +// UI protocols +import { ViewSchema, AppSchema, DashboardSchema } from '@objectstack/spec/ui'; + +// Kernel protocols +import { ManifestSchema, PluginSchema } from '@objectstack/spec/kernel'; + +// System protocols +import { LoggerConfigSchema, JobSchema } from '@objectstack/spec/system'; + +// AI protocols +import { AgentSchema, RAGPipelineConfigSchema } from '@objectstack/spec/ai'; + +// Types +import type { Field, Object, Query, View } from '@objectstack/spec'; +``` + +## Search Tips + +- **By Feature**: "How do I model relationships?" → [Field Protocol](/docs/references/data/field) → `lookup` or `master_detail` types +- **By Use Case**: "Build a dashboard" → [Dashboard Protocol](/docs/references/ui/dashboard) +- **By Layer**: Data → [Data Protocol](./data), UI → [UI Protocol](./ui), Runtime → [System Protocol](./system) + +## Next Steps + + +**New to ObjectStack?** Start with the [Introduction](../introduction) to learn core concepts before diving into specific protocols. + + +- [Protocol Reference Index](/docs/guides) - Full protocol documentation +- [ObjectQL Guide](../objectql) - Deep dive into data modeling +- [ObjectUI Guide](../objectui) - UI development guide +- [Contributing Guide](https://github.com/objectstack-ai/framework/blob/main/CONTRIBUTING.md) - How to contribute to protocols diff --git a/content/docs/getting-started/quick-start.mdx b/content/docs/getting-started/quick-start.mdx index eef9824a3b..8481546064 100644 --- a/content/docs/getting-started/quick-start.mdx +++ b/content/docs/getting-started/quick-start.mdx @@ -1,5 +1,5 @@ --- -title: Developer Guide +title: Quick Start description: Learn to build enterprise applications with the ObjectStack Protocol --- @@ -30,7 +30,7 @@ Install the ObjectStack skill bundle so your AI assistant (Claude Code, Copilot, npx skills add objectstack-ai/framework --all ``` -Re-run the same command any time to update — the bundle is versioned as one unit. See the [AI Skills Reference](/docs/guides/skills) for the full catalog. +Re-run the same command any time to update — the bundle is versioned as one unit. See the [AI Skills Reference](/docs/ai/skills-reference) for the full catalog. Scaffolding with `npm create objectstack@latest` runs this step automatically. @@ -117,27 +117,27 @@ Follow these guides in order for the best experience: @@ -183,6 +183,6 @@ my-app/ ## Next Steps - [Example Apps](/docs/getting-started/examples) — Run the Todo, CRM, and BI examples -- [Data Modeling Guide](/docs/guides/data-modeling) — Deep dive into objects and fields +- [Data Modeling Guide](/docs/data-modeling) — Deep dive into objects and fields - [CLI Reference](/docs/getting-started/cli) — All available commands - [Protocol Reference](/docs/references) — Complete schema documentation diff --git a/content/docs/guides/validating-metadata.mdx b/content/docs/getting-started/validating-metadata.mdx similarity index 94% rename from content/docs/guides/validating-metadata.mdx rename to content/docs/getting-started/validating-metadata.mdx index 43ef8df25b..2dfe28513f 100644 --- a/content/docs/guides/validating-metadata.mdx +++ b/content/docs/getting-started/validating-metadata.mdx @@ -86,7 +86,7 @@ passes.** In the example apps the equivalent is `pnpm --filter validate` To validate one CEL expression *before* you write it into a file — for example inside an AI build loop — call the `validate_expression` agent tool, which runs the same predicate validator inline. See the -[objectstack-formula skill](/docs/guides/formula). +[objectstack-formula skill](/docs/data-modeling/formulas). ## In CI @@ -100,5 +100,5 @@ Both commands support `--json` and exit non-zero on failure: ## See also - [Command Line Interface](/docs/getting-started/cli) — full `os validate` / `os build` reference -- [Formula & Predicates](/docs/guides/formula) — the CEL surface and `record.` scope -- [Data Modeling](/docs/guides/data-modeling) — objects, fields, validations, sharing +- [Formula & Predicates](/docs/data-modeling/formulas) — the CEL surface and `record.` scope +- [Data Modeling](/docs/data-modeling) — objects, fields, validations, sharing diff --git a/content/docs/guides/ai-capabilities.mdx b/content/docs/guides/ai-capabilities.mdx deleted file mode 100644 index 41fcb24d37..0000000000 --- a/content/docs/guides/ai-capabilities.mdx +++ /dev/null @@ -1,712 +0,0 @@ ---- -title: "AI Capabilities Guide" -description: "Complete guide to leveraging AI agents, RAG pipelines, and intelligent automation in ObjectStack" ---- - -# AI Capabilities Guide - -Complete guide to leveraging AI agents, knowledge retrieval, and intelligent automation in ObjectStack. - - -**This guide describes the cloud / Enterprise AI tier. The open edition exposes AI only via MCP (BYO-AI).** - -Per **cloud ADR-0025** (`service-ai → cloud; open = MCP-only` — [`cloud/docs/adr/0025`](https://github.com/objectstack-ai/cloud/blob/main/docs/adr/0025-service-ai-to-cloud-open-mcp-only.md)), the in-UI AI runtime — `@objectstack/service-ai`: both the **`ask`** data-query assistant and the **`build`** Studio authoring assistant, plus all in-product chat — ships in the **cloud / Enterprise** distribution. It is **not** in the open framework, and no open distribution (cloud free tier, Docker, desktop, on-prem) has a built-in `ask` / `build` chat. - -The **open edition** does AI two ways instead — both bring-your-own-AI, zero platform AI cost: - -- **Data query → `@objectstack/mcp`** (BYO-AI). Point your own AI — Claude, Cursor, any MCP client, or a local model — at the app's objects, queries, and business **actions**, governed by the same RLS. With a local model, data *and* inference stay inside your boundary. -- **Metadata authoring → source mode.** Author typed metadata as source (`*.object.ts`, `*.flow.ts`, …) with your own AI coding agent (Claude Code, Cursor), aided by the ObjectStack [skills](./skills) and MCP introspection. There is no in-product Builder chat in the open edition. - -Everything below (agents, the `ask` / `build` personas, `@objectstack/service-ai` wiring, the `/api/v1/ai/*` routes) therefore describes the **cloud / Enterprise** distribution. - - -## Table of Contents - -1. [AI Architecture](#ai-architecture) -2. [AI Agents](#ai-agents) -3. [Actions as Tools (explicit opt-in)](#actions-as-tools-explicit-opt-in) - - [Human-In-The-Loop approval](#human-in-the-loop-approval) -4. [Knowledge Protocol (RAG via adapter plugins)](#knowledge-protocol-rag-via-adapter-plugins) -5. [Best Practices](#best-practices) - ---- - -## AI Architecture - -ObjectStack provides a comprehensive AI platform: - -``` -┌─────────────────────────────────────┐ -│ AI Agents │ ← Persona + skills/tools -│ Skills & Tools │ ← Actions/Flows exposed to the LLM -├─────────────────────────────────────┤ -│ Knowledge Protocol │ ← search_knowledge via adapters -│ - memory / ragflow / custom │ -│ - Permission-aware retrieval │ -├─────────────────────────────────────┤ -│ Model Registry │ ← LLM management -│ - openai, azure_openai, │ -│ anthropic, local │ -│ - Token accounting / cost │ -└─────────────────────────────────────┘ -``` - ---- - -## AI Agents - -Per [ADR-0063](https://github.com/objectstack-ai/framework/blob/main/docs/adr/0063-two-kernel-agents-skills-are-the-extension-primitive.md) -the kernel ships **exactly two** platform agents, bound by the *surface* the user -is in — the user never picks from a roster: - -| Agent | Surface | Does | Edition | -|---|---|---|---| -| **`ask`** | data console | Read / query / explore records + run the business **actions** the app exposes. RLS-bounded. | cloud · Enterprise | -| **`build`** | Studio | Author *metadata* (objects, fields, views, flows) via plan → draft → verify → publish. | cloud · Enterprise | - -Both agents are part of the **cloud / Enterprise** in-UI AI runtime (cloud ADR-0025). -The **open edition** ships neither — it uses `@objectstack/mcp` (BYO-AI) for data -query and source-mode authoring instead (see the note above). - -Within the cloud / EE runtime there is no per-turn intent classifier and no agent -dropdown: the surface binds the agent (data console → `ask`, Studio → `build`). A -`build`-shaped request that reaches `ask` is declined and redirected to the -Builder, never silently re-routed. - -### You extend the platform with **skills**, not agents - -`*.agent.ts` is **closed to third parties** — the `agent` metadata type is -`allowRuntimeCreate:false, allowOrgOverride:false`, reserved for the two platform -agents and platform-owned subagents (ADR-0063 §2). To give the `ask` agent a new -capability you author a **skill** (`*.skill.ts`) whose `tools` reference your -Actions / Flows / queries; it then attaches to `ask`. Every skill declares -`surface: 'ask' | 'build' | 'both'`, and an agent's tool set is the **union of its -surface-compatible skills' tools** — there is no global fall-through, so a skill -reaches an agent only when their surfaces match -([ADR-0064](https://github.com/objectstack-ai/framework/blob/main/docs/adr/0064-tool-scoping-to-agent.md)). -Both `surface:'ask'` and `surface:'build'` skills run only where the in-UI AI -runtime exists — the **cloud / Enterprise** distribution. On the open framework -there is no in-product agent to attach them to (cloud ADR-0025); author capability -as Actions / Flows and reach it through `@objectstack/mcp` instead. - -### The shape of an agent - -An agent is metadata validated by `AgentSchema` (the platform's own `ask` / `build` -records use exactly these fields): - -| Field | Meaning | -|------|---------| -| `surface` | `'ask'` \| `'build'` — the product surface this agent binds (ADR-0063 §1) | -| `role` | Free-text **persona** string (e.g. `"Senior Support Engineer"`) — not an enum | -| `instructions` | System prompt / prime directives | -| `model` | Provider + model config (`provider`: `openai` \| `azure_openai` \| `anthropic` \| `local`) | -| `skills` | Skill names to attach (the primary Agent → Skill → Tool capability model) | -| `tools` | Direct tool **references** `{ type, name, description }` — `type` is `action` \| `flow` \| `query` \| `vector_search`; `name` points at an existing Action/Flow/query | -| `knowledge` | RAG access: `{ topics: string[], indexes: string[] }` | - -There is no `type` field and no fixed agent "type" taxonomy — behaviour comes from -persona, instructions, skills, and tools. There are no `triggers` / `schedule` -fields on an agent; drive agents from [Flows/Workflows](./automation) or invoke -them via the chat endpoint. - - -Agent tools are **references** to existing Actions, Flows, or queries — you do -not define ad-hoc tool names with inline parameter schemas here. See -[Actions as Tools](#actions-as-tools-explicit-opt-in) for how an Action becomes -LLM-callable. - - - -The agent definitions below illustrate agent **anatomy** — they show how an -`AgentSchema` record is shaped, *not* a tenant-authoring tutorial. On today's -platform you do not ship your own agents (`*.agent.ts` is platform-internal); you -add capability by authoring a **skill** that attaches to the built-in `ask` agent. -Read the examples for structure, then express your own capability as a skill plus -the Actions/Flows its tools reference. - - -### Sales Assistant Agent - -```typescript -import { defineAgent } from '@objectstack/spec/ai'; - -export const SalesAssistantAgent = defineAgent({ - name: 'sales_assistant', - label: 'Sales Assistant', - role: 'Sales Development Assistant', - - instructions: `You are a sales assistant AI. - -Your responsibilities: -1. Qualify incoming leads (BANT criteria) -2. Suggest next best actions -3. Draft personalized emails -4. Analyze win/loss patterns - -Always be professional and data-driven.`, - - model: { - provider: 'openai', - model: 'gpt-4', - temperature: 0.7, - maxTokens: 2000, - }, - - // References to Actions/Flows exposed as tools (see "Actions as Tools"). - tools: [ - { type: 'flow', name: 'analyze_lead', description: 'Analyze a lead and provide a qualification score' }, - { type: 'flow', name: 'suggest_next_action', description: 'Suggest the next best action for an opportunity' }, - { type: 'action', name: 'generate_email', description: 'Generate a personalized email template' }, - ], - - // RAG access: topics to recruit knowledge from + vector store indexes. - knowledge: { - topics: ['sales-playbook', 'leads', 'opportunities'], - indexes: ['sales_docs'], - }, -}); -``` - -### Customer Service Agent - -```typescript -export const ServiceAgent = defineAgent({ - name: 'service_agent', - label: 'Customer Service Agent', - role: 'Customer Service Specialist', - - instructions: `You are a customer service AI agent. - -Your responsibilities: -1. Triage incoming cases -2. Suggest relevant knowledge articles -3. Draft response templates -4. Escalate critical issues - -Always be empathetic and solution-focused.`, - - model: { - provider: 'openai', - model: 'gpt-4', - temperature: 0.5, - maxTokens: 1500, - }, - - // `search_knowledge` is provided by the Knowledge Protocol tool, not declared inline. - tools: [ - { type: 'flow', name: 'triage_case', description: 'Analyze a case and assign priority' }, - { type: 'action', name: 'generate_response', description: 'Generate a customer response' }, - ], - - knowledge: { - topics: ['support-kb', 'cases'], - indexes: ['support_docs'], - }, -}); -``` - -### Lead Enrichment Agent - -```typescript -export const LeadEnrichmentAgent = defineAgent({ - name: 'lead_enrichment', - label: 'Lead Enrichment Agent', - role: 'Data Enrichment Worker', - - instructions: `You enrich lead records with additional data. - -Tasks: -1. Look up company information -2. Enrich contact details -3. Add firmographic data -4. Research technology stack - -Use reputable data sources.`, - - model: { - provider: 'openai', - model: 'gpt-3.5-turbo', - temperature: 0.3, - maxTokens: 1000, - }, - - tools: [ - { type: 'flow', name: 'lookup_company', description: 'Look up company information' }, - { type: 'flow', name: 'enrich_contact', description: 'Enrich contact information' }, - ], -}); -``` - -To run enrichment when a lead is created or on a schedule, trigger this agent -from a [Flow or Workflow](./automation) — agents themselves carry no -`triggers`/`schedule` fields. - -### Revenue Intelligence Agent - -```typescript -export const RevenueIntelligenceAgent = defineAgent({ - name: 'revenue_intelligence', - label: 'Revenue Intelligence Agent', - role: 'Revenue Operations Analyst', - - instructions: `You analyze sales data and provide insights. - -Responsibilities: -1. Analyze pipeline health -2. Identify at-risk deals -3. Summarize trends -4. Generate executive summaries - -Use the data tools to query records and aggregate metrics.`, - - model: { - provider: 'openai', - model: 'gpt-4', - temperature: 0.2, - maxTokens: 3000, - }, - - // Built-in data tools (query_records / get_record / aggregate_data) are - // available to agents automatically once registered — see "Actions as Tools". - tools: [ - { type: 'flow', name: 'analyze_pipeline', description: 'Analyze sales pipeline health' }, - ], - - knowledge: { - topics: ['opportunities', 'pipeline'], - indexes: ['sales_docs'], - }, -}); -``` - ---- - -## Actions as Tools (explicit opt-in) - -Declarative `Action` metadata can be exposed as AI-callable tools, named -`action_`, but exposure is **explicit opt-in**. Add an `ai:` block -with `exposed: true` and an LLM-facing `description`; otherwise the action stays -human/UI-only. - -```typescript -export const triageCaseAction = { - name: 'triage_case', - label: 'Triage Case', - objectName: 'case', - type: 'flow', - target: 'case_triage', - ai: { - exposed: true, - description: 'Triage a support case, suggest priority, and assign the next support queue.', - category: 'action', - requiresConfirmation: false, - }, -}; -``` - -When the LLM picks an exposed action, the AI runtime dispatches to the same -handler the Console row toolbar would invoke, so your business logic stays in -one place. - -### What gets exposed - -The AI runtime walks every registered object's `actions[]` and registers only -actions with `ai.exposed === true` that also pass safety and wiring checks. -Three action types are supported: - -| `action.type` | Dispatch path | Wiring needed | -|:---|:---|:---| -| `script` | `IDataEngine.executeAction(object, target, ctx)` — the same call Studio makes | none beyond the metadata service | -| `api` | HTTP call to `action.target` via `ApiActionClient` (default: `fetch`) | `apiBaseUrl` (or a custom `apiClient`) | -| `flow` | `IAutomationService.execute(target, { triggerData })` | `automation` service registered | - -Console-only types (`url`, `modal`, `form`) are always skipped. Dangerous -actions — those with `confirmText`, `mode: 'delete'`, `variant: 'danger'`, or -`ai.requiresConfirmation: true` — are skipped unless the -[HITL approval queue](#human-in-the-loop-approval) is wired. To assert that a -destructive-looking action is safe for autonomous execution, set -`ai.requiresConfirmation: false`. - -### Wiring it up - -```typescript -import { AIServicePlugin } from '@objectstack/service-ai'; - -kernel.use( - new AIServicePlugin({ - // Enables type:'api' action dispatch. Relative `target` paths - // ('/api/v1/...') are resolved against this base URL. - apiActionBaseUrl: process.env.OS_AI_ACTION_API_BASE_URL, - // Forwarded on every api-action HTTP call (auth, environment id, ...). - apiActionHeaders: { Authorization: `Bearer ${process.env.SERVICE_TOKEN}` }, - }), -); -``` - -If `automation` is already registered with the kernel, `type:'flow'` actions are picked up automatically — no extra wiring needed. - -### `type:'api'` body assembly - -For api actions, the request body is built from three sources (last wins): - -1. **User-collected params** (the keys the LLM filled in). -2. **`recordIdParam`** — when row-context, the id is placed flat at `action.recordIdParam`, using `recordIdField` (default `'id'`) to pick the value off the record. -3. **`bodyExtra`** — constant fields that always override. - -`bodyShape: { wrap: 'data' }` nests the user params under `data` while keeping `recordIdParam` flat — matching shapes like better-auth's `organization/update`. - -### Diagnostics - -`registerActionsAsTools()` returns `{ registered, skipped, warnings }`. The -diagnostics include reasons such as `"not AI-exposed"`, -`"no apiClient or apiBaseUrl configured"`, or -`"requires confirmation ... wire HITL approval"` so action authors can see -whether their action will be LLM-callable. - -### Human-In-The-Loop approval - -Destructive actions are too risky to let the LLM execute autonomously, but locking them away entirely defeats agentic UX. The HITL queue strikes the balance: the LLM gets to **propose** the call, a human gets to **approve** it. - -Enable the queue via the plugin option (default: off): - -```typescript -kernel.use( - new AIServicePlugin({ - enableActionApproval: true, - apiActionBaseUrl: process.env.OS_AI_ACTION_API_BASE_URL, - }), -); -``` - -When the LLM picks an approval-gated tool (e.g. `action_delete_task`), the runtime: - -1. Persists an `ai_pending_actions` row with `status:'pending'`, `tool_input`, `proposed_by`, etc. -2. Returns `{ status: 'pending_approval', pendingActionId }` to the model so it can summarise (e.g. "I've requested approval to delete task #42."). -3. The operator sees the proposal in the **AI Pending Actions** Studio inbox. -4. Clicking **Approve** calls `POST /api/v1/ai/pending-actions/:id/approve` (`ai:approve` permission). The service looks up the pre-registered dispatcher and executes the action with HITL routing disabled, so the same code path runs. The row transitions to `executed` (or `failed` if dispatch threw). -5. Clicking **Reject** calls `POST /api/v1/ai/pending-actions/:id/reject` with an optional reason. - -The queue is exposed via four REST endpoints (`GET`, `GET/:id`, `POST/:id/approve`, `POST/:id/reject`) and via `IAIService.{proposePendingAction,approvePendingAction,rejectPendingAction,listPendingActions}` for programmatic use. - -**Why a dedicated queue (not the multi-step `IApprovalService`)?** AI tool-call HITL is ephemeral: subject is the proposed *call*, not a stable record state; there's no predefined process; operators expect single-click yes/no. The pending-action queue is a thin write log + dispatcher map that delivers that UX without dragging in process-engine overhead. - -#### End-to-end example - -Two runnable demos live in `examples/app-todo/test/`: - -- **`ai-hitl.test.ts`** — drives the tool registry directly (no LLM dependency). Asserts the full lifecycle: `variant:'danger'` action registered as a tool → invocation returns `pending_approval` without executing → row persisted → `approvePendingAction(id, actor)` re-runs the handler → row transitions to `executed`. Reject path is also covered. - - ```bash - pnpm --filter @example/app-todo test:hitl - ``` - -- **`ai-hitl-llm.test.ts`** — same scenario but with a real model behind Vercel AI Gateway. The LLM is given the auto-generated tool description and asked to "delete all completed tasks"; the framework returns `pending_approval` so the model summarises the wait instead of retrying. After we call approve from the test, the deletion completes. - - ```bash - AI_GATEWAY_API_KEY=vck_... pnpm --filter @example/app-todo test:hitl:llm - ``` - - Gated on `AI_GATEWAY_API_KEY` (or `OPENAI_API_KEY`); exits 0 with a notice if no key is provided, so it can be wired into CI without leaking spend. - -A trimmed view of the integration path: - -```typescript -// 1. Plugin boots with approval gating enabled -new AIServicePlugin({ - adapter: new VercelLLMAdapter({ model }), - enableActionApproval: true, // ← opt-in -}) - -// 2. LLM picks the gated tool — handler short-circuits to pending -const result = await aiService.toolRegistry.execute({ - type: 'tool-call', - toolName: 'action_delete_completed', - input: {}, -} as never); -const envelope = JSON.parse((result.output as { value: string }).value); -// → { ok: true, status: 'pending_approval', pendingActionId: 'pa_...' } - -// 3. Operator approves (REST or programmatic) -const outcome = await ai.approvePendingAction(envelope.pendingActionId, 'alice@example.com'); -// → { status: 'executed', result: } -``` - -### Permission-aware execution (RLS for agents) - -Every AI tool call now runs with the **end-user's** `ExecutionContext`, -so the same row-level-security rules that protect the REST API -automatically scope what an agent can see and do. There is no separate -"agent permission" surface to maintain — if a user can't read account -`acc_42` through ObjectQL, neither can the LLM acting on their behalf. - -**How it works:** - -1. The REST routes for `/api/v1/ai/assistant/chat` and - `/api/v1/ai/agents/:id/chat` pull the authenticated principal out of - `req.user` and forward it to `aiService.chatWithTools(...)` as - `toolExecutionContext: { actor, conversationId, environmentId }`. - Both **cookie session** (`better-auth.session_token`) and **Bearer - token** auth are resolved automatically by the dispatcher — your - browser chats and your scripted API calls land in the same RLS - context as a plain ObjectQL request from the same user. -2. The tool registry threads that context into every handler invocation. -3. Built-in data tools (`query_records`, `get_record`, - `aggregate_data`) and auto-generated `action_*` tools convert the - actor into a `{ userId, roles, permissions, isSystem: false }` - engine context on each `IDataEngine` call. RLS engages exactly as - it would for a hand-rolled API endpoint. -4. Action audit logs attribute the dispatch to the real user instead of - a generic "AI Assistant" principal. - -When you invoke `chatWithTools` from a custom server route, opt in by -passing the actor explicitly: - -```typescript -await aiService.chatWithTools(messages, tools, { - toolExecutionContext: { - actor: { - id: currentUser.id, - name: currentUser.displayName, - roles: currentUser.roles, - permissions: currentUser.permissions, - }, - conversationId, - environmentId, - }, -}); -``` - -Omit `toolExecutionContext` to keep the previous system-level behaviour -(used by cron jobs, internal callers, and the existing test suite). - -### LLM-generated conversation titles - -Auto-titling is **opt-in** (disabled by default; enable it via the `ai` -settings namespace from Console → Settings → AI). Once enabled, after a -conversation has at least one user + assistant exchange (≥ 2 messages) and -still has no title, the AI service fires a short, out-of-band LLM call -(default cap **16 characters**, single-line, no quotes) to summarise what the -user is asking about and writes the result back to `ai_conversations.title`. -The summarise call: - -- Reuses the **active chat provider** (so it works with any - `provider/model` you configured via Console → Settings → AI), and - honours the same `${provider}_base_url` you wired for chat — - including custom OpenAI-compatible endpoints (SiliconFlow, DeepSeek, - a local OpenAI proxy, …). -- Runs as a fire-and-forget task with a short timeout — if the title - call fails, the chat reply is unaffected and the conversation simply - keeps its placeholder name. -- Skips re-titling once `title` is set, so manual edits via the - conversation API are never overwritten. - -The Console sidebar groups conversations by recency and displays the -title; if you ever need to force a regenerate, clear the field via the -`ai_conversations` REST API and send another message. - ---- - -## Knowledge Protocol (RAG via adapter plugins) - -ObjectStack ships a Knowledge Protocol that lets agents call `search_knowledge(query, sourceIds?, topK?)` against pluggable backends (RAGFlow, LlamaIndex, Dify, custom pgvector, …). The framework defines the contract and runs permission-aware filtering; the adapter plugin does the actual retrieval. See [the protocol design](../protocol/knowledge.mdx) for the rationale. - -### Wiring - -```ts -import { ObjectKernel } from '@objectstack/core'; -import { KnowledgeServicePlugin } from '@objectstack/service-knowledge'; -import { KnowledgeMemoryPlugin } from '@objectstack/knowledge-memory'; -// or, for prod: -// import { KnowledgeRagflowPlugin } from '@objectstack/knowledge-ragflow'; - -const kernel = new ObjectKernel(); -kernel.use(new KnowledgeServicePlugin({ - sources: [ - { - id: 'task_notes', - label: 'Task notes', - adapter: 'memory', - source: { kind: 'object', object: 'task', contentFields: ['title', 'notes'] }, - }, - { - id: 'product_docs', - label: 'Product docs', - adapter: 'ragflow', - source: { kind: 'http', urls: ['https://docs.example.com/sitemap.xml'] }, - options: { datasetId: 'rgf_doc_dataset' }, - }, - ], -})); -kernel.use(new KnowledgeMemoryPlugin()); -// kernel.use(new KnowledgeRagflowPlugin({ endpoint, apiKey })); -``` - -Then register the AI tool so agents can call it: - -```ts -import { registerKnowledgeTools } from '@objectstack/service-ai'; - -ctx.hook('ai:ready', async (ai) => { - const knowledge = ctx.getService('knowledge'); - registerKnowledgeTools(ai.toolRegistry, { knowledgeService: knowledge }); -}); -``` - -### What you get for free - -- **Permission-aware retrieval.** Every hit with a `sourceRecordId` is re-checked against the caller's `ExecutionContext` via `IDataEngine` — the same RLS that gates plain ObjectQL queries. A salesperson asking "find proposals about ACME" only sees the proposals they could already read directly. File / HTTP hits pass through (ACL is the adapter's problem). -- **Inline event sync.** When records on indexed objects change, the kernel's `IRealtimeService` events drive `KnowledgeService.handleRecordUpsert/Delete` automatically. No cron, no queue (yet — Phase 2). -- **Adapter swap, zero LLM changes.** Move from `memory` to `ragflow` to a custom adapter without touching the `search_knowledge` tool or any agent prompt. - -### Why we did not build a vector DB - -Mature OSS (RAGFlow, LlamaIndex, Dify) already nail chunking, embedding, hybrid retrieval, rerank, and OCR. ObjectStack's value is **the metadata-native source declaration + the permission-aware filter on top of those engines** — not yet-another-RAG-stack. Customers pick the retrieval engine that matches their data; we make sure it talks to ObjectStack the same way every time. - ---- - -## Natural Language Queries - -Agents query your data through the built-in **data tools** — -`query_records`, `get_record`, and `aggregate_data` — which the LLM calls with -structured arguments. These run as ordinary [ObjectQL](./objectql) queries over -your objects (ObjectStack uses ObjectQL, not SOQL), and they execute under the -caller's `ExecutionContext`, so row-level security applies exactly as it does -for the REST API. - -```typescript -import { registerDataTools } from '@objectstack/service-ai'; - -ctx.hook('ai:ready', async (ai) => { - registerDataTools(ai.toolRegistry, { dataEngine: ctx.getService('data') }); -}); -``` - -There is no separate natural-language-to-query metadata type to author — the -model is prompted with the available objects and translates the user's question -into `query_records` / `aggregate_data` calls at runtime. - ---- - -## Best Practices - -### 1. AI Agent Design - -✅ **DO:** -- Define clear agent roles and responsibilities -- Provide detailed instructions -- Use appropriate temperature settings -- Test with real-world scenarios -- Monitor agent performance - -❌ **DON'T:** -- Give agents conflicting instructions -- Use high temperatures for factual tasks -- Deploy without testing -- Ignore cost implications - -### 2. Knowledge & Data Access - -✅ **DO:** -- Declare knowledge sources via the Knowledge Protocol and pick the adapter (`memory`, `ragflow`, custom) that fits your data -- Rely on the built-in data tools (`query_records` / `get_record` / `aggregate_data`) for live record access -- Let permission-aware retrieval and RLS scope what each user's agent can see -- Keep indexed objects in sync via the protocol's event sync - -❌ **DON'T:** -- Reinvent a vector DB — let the adapter engine handle chunking/embedding/rerank -- Bypass `ExecutionContext`, which would leak rows past row-level security -- Expose objects to agents that the calling user can't read - -### 3. Prompt Engineering - -✅ **DO:** -- Be specific and clear -- Provide examples -- Use role-playing ("You are a...") -- Include constraints -- Test variations - -❌ **DON'T:** -- Be vague or ambiguous -- Assume context -- Use complex jargon -- Write overly long prompts - -### 4. Cost Management - -✅ **DO:** -- Choose appropriate models (GPT-3.5 vs GPT-4) -- Implement caching -- Set token limits -- Monitor usage -- Use cheaper models for simple tasks - -❌ **DON'T:** -- Always use the most expensive model -- Skip caching -- Allow unlimited tokens -- Ignore cost metrics - -### 5. Security & Privacy - -✅ **DO:** -- Implement access controls -- Mask sensitive data -- Log AI interactions -- Review outputs -- Follow data privacy regulations - -❌ **DON'T:** -- Expose PII to external APIs -- Skip output validation -- Ignore audit trails -- Trust AI blindly - ---- - -## Real-World Integration - -### Complete Sales AI Workflow - -Agents are metadata, not classes — there are no `.enrich()` / `.predict()` / -`.query()` methods to call. You invoke an agent over HTTP (the REST chat -endpoint) or, server-side, via `aiService.chatWithTools(...)`. Enrichment, -scoring, and email drafting are implemented as **Actions/Flows exposed as -tools**, and the LLM calls them while reasoning over the conversation. - -```typescript -// Invoke an agent over the REST chat endpoint. -// POST /api/v1/ai/agents/:agentName/chat -const res = await fetch('/api/v1/ai/agents/sales_assistant/chat', { - method: 'POST', - headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` }, - body: JSON.stringify({ - message: `A hot lead just came in (id ${lead.id}). Qualify it, suggest the - next best action, and draft a professional intro email.`, - }), -}); -const { reply } = await res.json(); -// The agent calls its `analyze_lead` / `suggest_next_action` / `generate_email` -// tools (the Actions/Flows you wired) and returns its summary in `reply`. -``` - -Server-side, the same flow runs through `chatWithTools`, threading the -end-user's `ExecutionContext` so tool calls respect row-level security: - -```typescript -const reply = await aiService.chatWithTools(messages, tools, { - toolExecutionContext: { - actor: { id: currentUser.id, name: currentUser.displayName, roles: currentUser.roles, permissions: currentUser.permissions }, - conversationId, - environmentId, - }, -}); -``` - -To run any of this on lead creation or on a schedule, drive the agent from a -[Flow or Workflow](./automation) rather than expecting trigger/schedule fields -on the agent itself. - ---- - -**Next:** [Coding Standards →](/docs/guides/standards) diff --git a/content/docs/guides/api-reference.mdx b/content/docs/guides/api-reference.mdx deleted file mode 100644 index 4dc2428267..0000000000 --- a/content/docs/guides/api-reference.mdx +++ /dev/null @@ -1,540 +0,0 @@ ---- -title: API Reference -description: Complete REST API reference for ObjectStack — all endpoints, request/response schemas, and service availability. ---- - -# API Reference - -ObjectStack exposes a fully typed REST API. All endpoints use JSON request/response bodies. The API is **service-driven** — routes are only available when the corresponding plugin is installed. Use the [Discovery endpoint](#discovery) to determine what services are available at runtime. - - -**Base URL**: Configurable, defaults to `/api/v1`. All paths below are relative to the base URL. - - ---- - -## Discovery - -The discovery endpoint is the entry point for all clients. It returns the API version, available routes, service capabilities, and per-service status. - -### `GET /api/v1` - -Returns the full discovery manifest. - -**Response**: -```json -{ - "name": "ObjectOS", - "version": "1.0.0", - "environment": "development", - "routes": { - "data": "/api/v1/data", - "metadata": "/api/v1/meta", - "analytics": "/api/v1/analytics", - "auth": null, - "workflow": null - }, - "features": { - "graphql": false, - "search": false, - "websockets": false, - "files": false, - "analytics": true, - "ai": false, - "workflow": false, - "notifications": false, - "i18n": false - }, - "services": { - "metadata": { - "enabled": true, - "status": "degraded", - "route": "/api/v1/meta", - "provider": "kernel", - "message": "In-memory registry; DB persistence pending" - }, - "data": { "enabled": true, "status": "available", "route": "/api/v1/data", "provider": "kernel" }, - "analytics": { "enabled": true, "status": "available", "route": "/api/v1/analytics" }, - "auth": { "enabled": false, "status": "unavailable", "message": "Install an auth plugin to enable" } - }, - "locale": { - "default": "en", - "supported": ["en", "zh-CN"], - "timezone": "UTC" - } -} -``` - -### `GET /.well-known/objectstack` - -Alias for the discovery endpoint used by auto-discovery in the client SDK. - - -**Service Status Values**: `available` (fully operational), `registered` (route declared but handler unverified — may return 501), `degraded` (partial functionality), `unavailable` (not installed), `stub` (placeholder that throws errors) - - ---- - -## Metadata - -Retrieve and manage object schemas, metadata types, and UI views. Always available — provided by the kernel. - -### `GET /meta` - -List all registered metadata types. - -**Response**: `{ types: ["object", "view", "plugin", ...] }` - -### `GET /meta/:type` - -List all items of a metadata type. - -| Parameter | Location | Description | -|:----------|:---------|:------------| -| `type` | path | Metadata type name (e.g. `object`, `view`) | - -**Response**: `{ type: "object", items: [{ name: "account", ... }, ...] }` - -### `GET /meta/:type/:name` - -Get a specific metadata item with optional ETag caching. - -| Parameter | Location | Description | -|:----------|:---------|:------------| -| `type` | path | Metadata type name | -| `name` | path | Item name (snake_case) | -| `If-None-Match` | header | ETag for conditional request | - -**Response**: `{ type: "object", name: "account", item: { ... } }` -**304** if ETag matches (not modified). - -### `PUT /meta/:type/:name` - -Create or update a metadata item. - -**Body**: `{ type: "object", name: "account", item: { ... } }` -**Response**: `{ success: true }` - -### `GET /ui/view/:object/:type` - -Get an auto-generated UI view for an object. - -| Parameter | Location | Description | -|:----------|:---------|:------------| -| `object` | path | Object name (snake_case) | -| `type` | path | `list` or `form` | - -**Response**: Full `ViewSchema` definition with columns/fields derived from the object schema. - ---- - -## Data Operations - -CRUD operations on any object. Always available — provided by the kernel. - -### `GET /data/:object` - -Query records with filtering, sorting, selection, and pagination. - -| Parameter | Location | Description | -|:----------|:---------|:------------| -| `object` | path | Object name | -| `select` | query | Comma-separated field names | -| `filter` | query | Filter expression (JSON). `filters` also accepted for backward compatibility. | -| `sort` | query | Sort expression (e.g. `name asc` or `-created_at`) | -| `top` | query | Limit (default: 20) | -| `skip` | query | Offset | -| `expand` | query | Comma-separated list of relations to eager-load | -| `search` | query | Full-text search query | - -> **Note:** OData-style `$`-prefixed parameters (`$filter`, `$select`, `$orderby`, `$top`, `$skip`) are supported via the [OData endpoint](/docs/references/api/odata). The standard REST API uses unprefixed parameter names. - -**Response**: -```json -{ - "object": "account", - "records": [{ "id": "1", "name": "Acme Corp", ... }], - "total": 42, - "hasMore": true -} -``` - -### `GET /data/:object/:id` - -Get a single record by ID. Only `select` and `expand` query parameters are allowed; all other parameters are discarded. - -| Parameter | Location | Description | -|:----------|:---------|:------------| -| `object` | path | Object name | -| `id` | path | Record ID | -| `select` | query | Comma-separated field names to include | -| `expand` | query | Comma-separated list of relations to eager-load | - -**Response**: `{ object: "account", id: "1", record: { ... } }` - -### `POST /data/:object` - -Create a new record. - -**Body**: `{ name: "Acme Corp", industry: "Technology" }` -**Response**: `{ object: "account", id: "1", record: { ... } }` - -### `PATCH /data/:object/:id` - -Update an existing record (partial update). - -**Body**: `{ industry: "Healthcare" }` -**Response**: `{ object: "account", id: "1", record: { ... } }` - -### `DELETE /data/:object/:id` - -Delete a record. - -**Response**: `{ object: "account", id: "1", success: true }` - ---- - -## Batch Operations - -Efficient bulk operations. Always available. - -### `POST /data/:object/batch` - -Execute a batch operation (create / update / upsert / delete) on multiple records. - -**Body**: -```json -{ - "operation": "update", - "records": [ - { "id": "1", "data": { "status": "active" } }, - { "id": "2", "data": { "status": "active" } } - ], - "options": { - "atomic": true, - "returnRecords": true, - "continueOnError": false, - "validateOnly": false - } -} -``` - -**Response**: `BatchUpdateResponse` with `succeeded`, `failed`, `total`, and a per-record `results` array. Each entry in `results` has `id`, `success`, an optional `errors` array, and optional `data` (the full record, present when `returnRecords` is `true`). - -### `POST /data/:object/createMany` - -Batch create multiple records. - -**Body**: a bare array of records — `[{ name: "A" }, { name: "B" }]`. The REST handler reads the request body directly as the records array, so do **not** wrap it in `{ records: [...] }`. -**Response**: `{ object: "account", records: [...], count: 2 }` - -### `POST /data/:object/updateMany` - -Batch update multiple records. - -**Body**: -```json -{ - "records": [ - { "id": "1", "data": { "status": "active" } }, - { "id": "2", "data": { "status": "closed" } } - ], - "options": { "atomic": false } -} -``` - -### `POST /data/:object/deleteMany` - -Batch delete records by ID list. - -**Body**: `{ ids: ["1", "2", "3"] }` - ---- - -### `POST /data/:object/:id/clone` - -Clone a record. Reads the source, drops engine-owned columns (`id`, the audit -fields, autonumbers, and computed `formula`/`summary` values) so they are -re-derived, applies any caller `overrides`, and inserts the copy. Shallow by -design — it duplicates the record's own fields, not its child records. - -Gated by the object's `enable.clone` capability (default `true`); an object with -`enable.clone: false` returns `403 CLONE_DISABLED`. - -**Body** (optional): `{ "overrides": { "name": "Acme (Copy)" } }` — applied on -top of the copied values (a bare field map is also accepted). The natural place -to set a new name or clear a unique field. - -**Response** `201`: `{ object, id, sourceId, record }` - ---- - -## Analytics - -Semantic BI queries using a cube-style API. Available when the analytics service is enabled. - -### `POST /analytics/query` - -Execute an analytics query. - -**Body**: -```json -{ - "cube": "account", - "measures": ["revenue.sum", "count"], - "dimensions": ["industry"], - "where": { "status": "active" }, - "limit": 100 -} -``` - - -Filtering uses the canonical Query DSL `where` object (the same MongoDB-style `FilterCondition` accepted by `find()`), not a `filters` array. - - -**Response**: the runtime dispatcher wraps the `AnalyticsResult` as `{ success: true, data: { rows, fields, sql?, totals? } }`: -```json -{ - "success": true, - "data": { - "rows": [ - { "industry": "Technology", "revenue.sum": 150000, "count": 5 }, - { "industry": "Healthcare", "revenue.sum": 80000, "count": 3 } - ], - "fields": [ - { "name": "industry", "type": "string", "label": "Industry" }, - { "name": "revenue.sum", "type": "number", "label": "Revenue Sum", "format": "$0,0" }, - { "name": "count", "type": "number", "label": "Count" } - ], - "sql": "SELECT ..." - } -} -``` - -### `GET /analytics/meta` - -Get auto-generated cube metadata for all objects. - -**Response**: Array of cube definitions with measures, dimensions, and time dimensions. - -### `POST /analytics/sql` - -Execute a raw SQL analytics query (if supported by driver). - ---- - -## Package Management - -Manage installed plugins/packages. - -### `GET /packages` - -List installed packages. - -### `POST /packages` - -Install a package from manifest. - -**Body**: `{ manifest: { name: "plugin-auth", version: "1.0.0", ... } }` - -### `GET /packages/:id` - -Get package details. - -### `DELETE /packages/:id` - -Uninstall a package. - -### `PATCH /packages/:id/enable` - -Enable a disabled package. - -### `PATCH /packages/:id/disable` - -Disable a package without uninstalling. - ---- - -## Authentication (Plugin Required) - - -These endpoints are only available when an auth plugin is installed. Check `discovery.services.auth.enabled` first. - - -### `POST /auth/login` - -Authenticate and receive a session token. - -**Body**: `{ username: "admin", password: "secret" }` -**Response**: `{ token: "jwt...", expiresAt: "...", user: { ... } }` - ---- - -## Plugin-Provided Service Endpoints - -The following endpoints become available when the corresponding plugin is installed and registered with the kernel. Use the discovery `services` map to check availability. - -### Workflow (`/workflow`) — Plugin Required - -| Method | Endpoint | Description | -|:-------|:---------|:------------| -| GET | `/workflow/:object/config` | Get workflow configuration | -| GET | `/workflow/:object/:recordId/state` | Get record's workflow state | -| POST | `/workflow/:object/:recordId/transition` | Execute state transition | -| POST | `/workflow/:object/:recordId/approve` | Approve workflow step | -| POST | `/workflow/:object/:recordId/reject` | Reject workflow step | - -### Automation (`/automation`) — Plugin Required - -| Method | Endpoint | Description | -|:-------|:---------|:------------| -| POST | `/automation/trigger/:name` | Trigger an automation flow by name | - -### Views (`/ui`) — Plugin Required - -| Method | Endpoint | Description | -|:-------|:---------|:------------| -| GET | `/ui/views?object=:object` | List views for an object | -| GET | `/ui/views/:viewId` | Get a view definition | -| POST | `/ui/views` | Create a new view | -| PATCH | `/ui/views/:viewId` | Update a view | -| DELETE | `/ui/views/:viewId` | Delete a view | - -### Realtime (`/realtime`) — Plugin Required - -| Method | Endpoint | Description | -|:-------|:---------|:------------| -| POST | `/realtime/connect` | Establish WebSocket/SSE connection | -| POST | `/realtime/disconnect` | Close connection | -| POST | `/realtime/subscribe` | Subscribe to channel | -| POST | `/realtime/unsubscribe` | Unsubscribe | -| POST | `/realtime/presence` | Set presence | -| GET | `/realtime/presence/:channel` | Get channel presence | - -### Notifications (`/notifications`) — Plugin Required - -| Method | Endpoint | Description | -|:-------|:---------|:------------| -| GET | `/notifications` | List notifications (inbox) | -| POST | `/notifications/read` | Mark notifications as read (body: `{ ids: string[] }`) | -| POST | `/notifications/read/all` | Mark all as read | - - -The core dispatcher implements only the list / read / read-all routes above. Device-registration and preference endpoints are provided by specific notification plugins, if any. - - -### AI (`/ai`) — Plugin Required - -| Method | Endpoint | Description | -|:-------|:---------|:------------| -| POST | `/ai/nlq` | Natural language → query | -| POST | `/ai/chat` | AI chat conversation | -| POST | `/ai/suggest` | Get value suggestions | -| POST | `/ai/insights` | Get data insights | - -### i18n (`/i18n`) — Plugin Required - -| Method | Endpoint | Description | -|:-------|:---------|:------------| -| GET | `/i18n/locales` | List available locales | -| GET | `/i18n/translations/:locale` | Get translation bundle | -| GET | `/i18n/labels/:object/:locale` | Get field labels | - -### GraphQL (`/graphql`) — Plugin Required - -| Method | Endpoint | Description | -|:-------|:---------|:------------| -| POST | `/graphql` | Execute GraphQL query/mutation | - -### File Storage (`/storage`) — Plugin Required - -| Method | Endpoint | Description | -|:-------|:---------|:------------| -| POST | `/storage/upload` | Upload a file | -| GET | `/storage/file/:id` | Download a file | - ---- - -## Error Handling - -Error responses depend on which HTTP server is in front of the kernel. There are two wire formats in use today. - -**Kernel REST server** (`@objectstack/rest`) emits a string `error` message plus a SCREAMING_SNAKE `code`: - -```json -{ - "error": "Record not found: account/123", - "code": "RECORD_NOT_FOUND" -} -``` - -Validation failures additionally include an `issues` array. Common codes emitted by the kernel REST server: - -| Code | HTTP | Description | -|:-----|:-----|:------------| -| `VALIDATION_FAILED` | 400 | Input validation failed (includes `issues`) | -| `PERMISSION_DENIED` | 403 | Insufficient permissions | -| `RECORD_NOT_FOUND` | 404 | Resource does not exist | -| `CONCURRENT_UPDATE` | 409 | Record was modified by another user | - -**Runtime dispatcher** (`@objectstack/runtime`) wraps errors in the `{ success: false, ... }` envelope, where `code` is the numeric HTTP status: - -```json -{ - "success": false, - "error": { - "message": "Record not found: account/123", - "code": 404, - "details": {} - } -} -``` - - -The richer `ErrorResponseSchema` in `@objectstack/spec/api` (with `category`, `retryable`, etc.) is the aspirational spec envelope, not the current wire format. Its `category` values are drawn from the `ErrorCategory` enum: `validation`, `authentication`, `authorization`, `not_found`, `conflict`, `rate_limit`, `server`, `external`, `maintenance`. - - ---- - -## Protocol Types (Zod) - -All request/response schemas are defined as Zod schemas in `@objectstack/spec/api` and can be used for both runtime validation and TypeScript type inference. - -```typescript -import { - FindDataRequestSchema, - FindDataResponseSchema, - type FindDataRequest, - type FindDataResponse, -} from '@objectstack/spec/api'; - -// Runtime validation -const request = FindDataRequestSchema.parse({ object: 'account', query: { ... } }); - -// TypeScript type -const response: FindDataResponse = await protocol.findData(request); -``` - -See the [Protocol Reference](../references/api/protocol) for the full list of protocol methods and their Zod schemas. - ---- - -## Next Steps - - - - - - diff --git a/content/docs/guides/business-logic.mdx b/content/docs/guides/business-logic.mdx deleted file mode 100644 index 0d8c31d8ea..0000000000 --- a/content/docs/guides/business-logic.mdx +++ /dev/null @@ -1,675 +0,0 @@ ---- -title: Business Logic Guide -description: Complete guide to implementing business rules, validations, and automated processes in ObjectStack ---- - -# Business Logic Guide - -Complete guide to implementing business rules, validations, and automated processes in ObjectStack. - -## Table of Contents - -1. [Validation Rules](#validation-rules) -2. [Flows](#flows) -3. [Hooks](#hooks) -4. [Approval Nodes](#approval-nodes) -5. [Formula Logic](#formula-logic) -6. [Best Practices](#best-practices) - ---- - -## Validation Rules - -Validation rules ensure data quality by preventing invalid data from being saved. - -### Script Validation - -Validation conditions are **CEL** expressions evaluated against the record. The -rule **fails** when the condition is `TRUE`, so phrase the condition as the -*invalid* case. Use lowercase CEL stdlib functions (`today()`, `now()`, -`isBlank()`, …) and `==`/`!=` for comparisons: - -```typescript -validations: [ - { - name: 'close_date_future', - type: 'script', - severity: 'error', - message: 'Close Date must be in the future', - condition: 'record.close_date <= today()', - }, - - { - name: 'discount_limit', - type: 'script', - severity: 'warning', - message: 'Discount exceeds 20%', - condition: 'record.discount > 20', - }, -] -``` - -### Unique Constraints - -There is no `unique` validation rule type. Uniqueness is enforced with a unique -index (or field-level `unique: true`), not a validation rule: - -```typescript -// Field-level uniqueness -Field.text({ - label: 'Email', - unique: true, -}) - -// Single-field unique index -indexes: [ - { fields: ['email'], unique: true }, -] - -// Compound unique index -indexes: [ - { fields: ['account', 'product'], unique: true }, -] -``` - -### Required Field Validation - -Mark fields as required at the field level: - -```typescript -Field.text({ - label: 'Name', - required: true, -}) - -// Conditional required (use validation rule) -{ - name: 'contact_required_for_customer', - type: 'script', - severity: 'error', - message: 'Contact is required for customer accounts', - condition: 'record.type == "customer" && isBlank(record.primary_contact)', -} -``` - -### CEL Functions and Operators - -Conditions and formulas use CEL. Logic is expressed with operators (`&&`, `||`, -`!`, `==`, `!=`, ternary `cond ? a : b`) rather than function calls. The current -record is `record`; the pre-change snapshot is `previous`. The CEL stdlib -functions available include: - -| Function | Description | Example | -|----------|-------------|---------| -| `isBlank(x)` | True if null/empty/whitespace | `isBlank(record.phone)` | -| `isEmpty(x)` | True if empty collection/string | `isEmpty(record.tags)` | -| `coalesce(a, b, …)` | First non-blank value | `coalesce(record.nickname, record.name)` | -| `today()` | Current date | `record.close_date <= today()` | -| `now()` | Current datetime | `record.due_at < now()` | -| `daysBetween(a, b)` | Whole days between two dates | `daysBetween(record.end_date, today())` | -| `upper(s)` / `lower(s)` | Case conversion | `upper(record.sku)` | -| `trim(s)` | Strip whitespace | `trim(record.name)` | -| `contains(s, sub)` / `startsWith` / `endsWith` | Substring checks | `contains(record.email, "@")` | -| `matches(s, regex)` | Regex test | `matches(record.email, "^[^@]+@[^@]+$")` | -| `len(x)` / `size(x)` | Length / size | `len(record.code) == 6` | -| `min(a, b)` / `max(a, b)` / `abs(x)` / `round(x)` | Numerics | `max(record.amount, 0)` | - -To compare against a field's previous value, reference `previous.` -(e.g. `record.stage != previous.stage`). - ---- - -## Flows - -Flows automate business processes as explicit node graphs. Use them for field -updates, notifications, record creation, HTTP calls, decisions, waits, screens, -subflows, and approval pauses. The old standalone Workflow Rule authoring model -is retired; model the same logic as a Flow. - -### Record-change flow - -```typescript -import type { Flow } from '@objectstack/spec/automation'; - -export const hotLeadFollowUp: Flow = { - name: 'hot_lead_follow_up', - label: 'Hot Lead Follow Up', - type: 'record_change', - status: 'active', - nodes: [ - { - id: 'start', - type: 'start', - label: 'Start', - config: { - triggerType: 'record-after-create', - objectName: 'lead', - condition: "record.rating == 'hot'", - }, - }, - { - id: 'create_task', - type: 'create_record', - label: 'Create Follow-up Task', - config: { - object: 'task', - data: { - subject: 'Follow up on hot lead', - related_to: '${record.id}', - priority: 'high', - }, - }, - }, - { - id: 'notify_owner', - type: 'notify', - label: 'Notify Owner', - config: { - channel: 'in_app', - template: 'hot_lead_created', - }, - }, - { id: 'end', type: 'end', label: 'End' }, - ], - edges: [ - { id: 'e1', source: 'start', target: 'create_task' }, - { id: 'e2', source: 'create_task', target: 'notify_owner' }, - { id: 'e3', source: 'notify_owner', target: 'end' }, - ], -}; -``` - -### Scheduled flow - -```typescript -export const contractExpirationCheck: Flow = { - name: 'contract_expiration_check', - label: 'Contract Expiration Check', - type: 'schedule', - status: 'active', - nodes: [ - { - id: 'start', - type: 'start', - label: 'Start', - config: { - triggerType: 'schedule', - schedule: { type: 'cron', expression: '0 0 * * *', timezone: 'UTC' }, - }, - }, - { id: 'find_expiring', type: 'get_record', label: 'Find Expiring Contracts' }, - { id: 'notify_owners', type: 'notify', label: 'Notify Owners' }, - { id: 'end', type: 'end', label: 'End' }, - ], - edges: [ - { id: 'e1', source: 'start', target: 'find_expiring' }, - { id: 'e2', source: 'find_expiring', target: 'notify_owners' }, - { id: 'e3', source: 'notify_owners', target: 'end' }, - ], -}; -``` - -### Built-in node types - -| Node | Use case | -|------|----------| -| `start`, `end` | Flow entry (carries the trigger config) and exit | -| `decision` | Branch based on CEL predicates | -| `assignment` | Set variables | -| `script` | Run an inline expression / function | -| `loop`, `map` | Iterate over a collection | -| `create_record`, `update_record`, `delete_record`, `get_record` | CRUD | -| `http` | Outbound HTTP call | -| `connector_action` | Invoke a registered connector action | -| `notify` | In-app/email-style notification dispatch | -| `wait`, `screen`, `approval` | Durable pauses | -| `subflow` | Invoke another flow | -| `parallel_gateway`, `join_gateway`, `boundary_event` | BPMN-style orchestration | - ---- - -## Hooks - -Hooks are the data-layer "logic layer": they run custom code at interception -points in the ObjectQL execution pipeline (before/after insert, update, delete, -find, etc.). The construct is `Hook`, imported from `@objectstack/spec/data`. - -A hook targets one or more `object`s and subscribes to one or more lifecycle -`events`. Each event is a combined timing+action enum value, e.g. -`beforeInsert`, `beforeUpdate`, `afterUpdate`, `afterDelete` (read-side events -such as `beforeFind`/`afterFind` are also available). - -### Before Hook - -Mutate the incoming record before it is saved. The pending record lives on -`ctx.input` (`ctx.input.doc` for insert/update): - -```typescript -import { Hook } from '@objectstack/spec/data'; - -export const AccountBeforeWrite: Hook = { - name: 'account_before_write', - object: 'account', - events: ['beforeInsert', 'beforeUpdate'], - - handler: async (ctx) => { - const record = ctx.input.doc as Record; - - // Normalize phone numbers - if (record.phone) { - record.phone = normalizePhone(record.phone); - } - - // Auto-populate from website - if (!record.industry && record.website) { - record.industry = await lookupIndustry(record.website); - } - }, -}; -``` - -### After Hook - -React after a record is persisted. Use `ctx.previous` for the pre-change -snapshot and `ctx.api.object('x')` for cross-object writes: - -```typescript -export const OpportunityAfterUpdate: Hook = { - name: 'opportunity_after_update', - object: 'opportunity', - events: ['afterUpdate'], - - handler: async (ctx) => { - const opp = ctx.result as Record; - const wasWon = ctx.previous?.stage === 'closed_won'; - - if (opp.stage === 'closed_won' && !wasWon) { - // Create a contract via the scoped cross-object API - await ctx.api.object('contract').insert({ - account: opp.account, - opportunity: opp.id, - contract_value: opp.amount, - start_date: new Date(), - }); - } - }, -}; -``` - -### Hook Context - -`handler` receives a `HookContext` with these fields: - -```typescript -ctx = { - id, // tracing id - object, // target object name - event, // e.g. 'beforeInsert' | 'afterUpdate' - input, // mutable input (e.g. input.doc for insert/update) - result, // mutable operation result (after* events) - previous, // record state before the operation (update/delete) - session, // { userId, tenantId, roles, accessToken, isSystem } - user, // { id, name, email } convenience shortcut - transaction, // active transaction handle, if any - ql, // ObjectQL engine reference - api, // scoped cross-object access: ctx.api.object('x') -} -``` - ---- - -## Approval Nodes - -Approvals are authored as Flow nodes with `type: 'approval'`. The -`@objectstack/plugin-approvals` package owns the durable approval state -(`sys_approval_request` and `sys_approval_action`), record locking, approver -resolution, and resume-on-decision behavior. - -```typescript -export const opportunityApproval: Flow = { - name: 'opportunity_approval', - label: 'Opportunity Approval', - type: 'record_change', - status: 'active', - nodes: [ - { - id: 'start', - type: 'start', - label: 'Start', - config: { - triggerType: 'record-after-update', - objectName: 'opportunity', - condition: "record.amount >= 50000 && record.stage == 'proposal'", - }, - }, - { - id: 'manager_approval', - type: 'approval', - label: 'Manager Approval', - config: { - approvers: [{ type: 'user', value: '${record.owner_manager_id}' }], - behavior: 'unanimous', - approvalStatusField: 'approval_status', - lockRecord: true, - }, - }, - { id: 'mark_approved', type: 'update_record', label: 'Mark Approved' }, - { id: 'mark_rejected', type: 'update_record', label: 'Mark Rejected' }, - { id: 'end', type: 'end', label: 'End' }, - ], - edges: [ - { id: 'e1', source: 'start', target: 'manager_approval' }, - { id: 'approved', source: 'manager_approval', target: 'mark_approved', label: 'approve' }, - { id: 'rejected', source: 'manager_approval', target: 'mark_rejected', label: 'reject' }, - { id: 'e4', source: 'mark_approved', target: 'end' }, - { id: 'e5', source: 'mark_rejected', target: 'end' }, - ], -}; -``` - -For multi-step approvals, chain multiple `approval` nodes. For parallel -approvals, combine `parallel_gateway`, multiple `approval` nodes, and -`join_gateway`. - ---- - -## Formula Logic - -Complex calculations and logic in formula fields. - -### Conditional Logic - -Formula fields are CEL. Use ternary `cond ? a : b` for conditionals and -`&&`/`||`/`!` for boolean logic. Reference fields via `record.`: - -```typescript -// Tiered pricing -Field.formula({ - label: 'Discount Tier', - returnType: 'text', - expression: ` - record.amount > 1000000 ? "Platinum" : - record.amount > 500000 ? "Gold" : - record.amount > 100000 ? "Silver" : "Bronze" - `, -}) - -// Status indicator -Field.formula({ - label: 'Health Score', - returnType: 'text', - expression: ` - record.is_active && record.days_since_contact < 30 ? "Healthy" : - record.days_since_contact < 90 ? "At Risk" : "Critical" - `, -}) -``` - -### Date Calculations - -```typescript -// Days until close -Field.formula({ - label: 'Days to Close', - returnType: 'number', - expression: 'daysBetween(record.close_date, today())', -}) - -// Contract end in 30 days -Field.formula({ - label: 'Expiring Soon', - returnType: 'boolean', - expression: 'record.status == "active" && daysBetween(record.end_date, today()) <= 30', -}) - -// Age in days -Field.formula({ - label: 'Age (Days)', - returnType: 'number', - expression: 'daysBetween(today(), record.created_date)', -}) -``` - -### Financial Calculations - -```typescript -// Gross margin (computes a number; a formula's type is always 'formula' — -// declare the value type with returnType, and decimal places with scale) -Field.formula({ - label: 'Gross Margin %', - returnType: 'number', - expression: 'record.revenue > 0 ? ((record.revenue - record.cost) / record.revenue) * 100 : 0', - scale: 2, -}) - -// Weighted pipeline -Field.formula({ - label: 'Weighted Amount', - returnType: 'number', - expression: 'record.amount * (record.probability / 100)', - scale: 2, -}) - -// Total with tax -Field.formula({ - label: 'Total with Tax', - returnType: 'number', - expression: 'record.subtotal * 1.0825', // 8.25% tax - scale: 2, -}) -``` - -### Text Manipulation - -```typescript -// Full name -Field.formula({ - label: 'Full Name', - returnType: 'text', - expression: 'record.first_name + " " + record.last_name', -}) - -// Uppercase -Field.formula({ - label: 'Code', - returnType: 'text', - expression: 'upper(record.sku)', -}) - -// Has a company email -Field.formula({ - label: 'Internal', - returnType: 'boolean', - expression: 'endsWith(lower(record.email), "@example.com")', -}) -``` - ---- - -## Best Practices - -### 1. Validation Rules - -✅ **DO:** -- Validate at the lowest level possible (field > validation rule > trigger) -- Provide clear, actionable error messages -- Use appropriate severity levels -- Test with real-world data - -❌ **DON'T:** -- Duplicate validations -- Create overly complex conditions -- Block legitimate edge cases -- Use triggers for simple validations - -### 2. Flows - -✅ **DO:** -- Keep flows simple and focused -- Document the business logic -- Test recursion and retry behavior -- Use scheduled flows for batch updates - -❌ **DON'T:** -- Create uncontrolled loops -- Update too many fields in one node -- Use triggers when a declarative flow is enough -- Mix unrelated concerns in one flow - -### 3. Hooks - -✅ **DO:** -- Use before hooks to enrich/normalize the incoming record -- Use after hooks for related-record side effects -- Use `ctx.api.object('x')` for cross-object access so writes stay in scope -- Handle errors gracefully - -❌ **DON'T:** -- Query in loops -- Trigger unbounded cascades of writes -- Perform heavy/long-running work inline in a hook -- Mutate `ctx.result` in before hooks (it is only populated for after hooks) - -### 4. Approval Nodes - -✅ **DO:** -- Define clear entry criteria -- Set reasonable timeout periods -- Allow recall when appropriate -- Notify all stakeholders -- Track approval history - -❌ **DON'T:** -- Create too many approval steps -- Make approvals too complex -- Forget rejection paths -- Hard-code approvers - -### 5. Formula Fields - -✅ **DO:** -- Keep formulas simple and readable -- Add comments for complex logic -- Test edge cases (null, zero, empty) -- Use appropriate data types - -❌ **DON'T:** -- Create circular references -- Use formulas for frequently changing data -- Nest too many IF statements -- Ignore null handling - ---- - -## Real-World Examples - -### Lead Qualification Automation - -```typescript -// Validation: Ensure valid data -validations: [ - { - name: 'valid_email', - type: 'script', - severity: 'error', - message: 'Invalid email address', - condition: 'record.email != null && !matches(record.email, "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$")', - }, -], - -// Flow: Auto-assign hot leads -flows: [ - { - name: 'assign_hot_leads', - label: 'Assign Hot Leads', - type: 'record_change', - status: 'active', - nodes: [ - { - id: 'start', - type: 'start', - label: 'Start', - config: { - triggerType: 'record-after-create', - objectName: 'lead', - condition: "record.rating == 'hot' && record.lead_source == 'web'", - }, - }, - { id: 'assign_owner', type: 'assignment', label: 'Assign Owner' }, - { id: 'create_task', type: 'create_record', label: 'Create Follow-up Task' }, - { id: 'end', type: 'end', label: 'End' }, - ], - edges: [ - { id: 'e1', source: 'start', target: 'assign_owner' }, - { id: 'e2', source: 'assign_owner', target: 'create_task' }, - { id: 'e3', source: 'create_task', target: 'end' }, - ], - }, -], - -// Formula: Lead score -Field.formula({ - label: 'Lead Score', - returnType: 'number', - expression: ` - (record.rating == "hot" ? 30 : record.rating == "warm" ? 20 : 10) + - (record.annual_revenue > 1000000 ? 25 : 0) + - (record.number_of_employees > 500 ? 20 : 0) + - (record.industry in ["technology", "finance"] ? 15 : 0) - `, -}) -``` - -### Opportunity Management - -```typescript -// Validation: Stage progression -validations: [ - { - name: 'valid_stage_change', - type: 'script', - severity: 'error', - message: 'Cannot skip stages', - // Fails when the stage changed to a value not allowed from the previous one. - condition: ` - record.stage != previous.stage && - !(record.stage in validTransitions[previous.stage]) - `, - }, -], - -// Flow: Update probability -flows: [ - { - name: 'update_probability', - label: 'Update Probability', - type: 'record_change', - status: 'active', - nodes: [ - { - id: 'start', - type: 'start', - label: 'Start', - config: { - triggerType: 'record-after-update', - objectName: 'opportunity', - condition: 'record.stage != previous.stage', - }, - }, - { id: 'update_probability', type: 'update_record', label: 'Update Probability' }, - { id: 'end', type: 'end', label: 'End' }, - ], - edges: [ - { id: 'e1', source: 'start', target: 'update_probability' }, - { id: 'e2', source: 'update_probability', target: 'end' }, - ], - }, -], - -// Approval: Large deals -// (See Approval Nodes section above) -``` - ---- - -**Next:** [Security Model →](./security) diff --git a/content/docs/guides/cheatsheets/meta.json b/content/docs/guides/cheatsheets/meta.json deleted file mode 100644 index 092c1573cd..0000000000 --- a/content/docs/guides/cheatsheets/meta.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "title": "Cheatsheets", - "pages": [ - "quick-reference", - "field-type-gallery", - "field-type-decision-tree", - "field-validation-rules", - "query-cheat-sheet", - "error-catalog", - "wire-format", - "protocol-diagram", - "permissions-matrix", - "backward-compatibility" - ] -} diff --git a/content/docs/guides/cheatsheets/quick-reference.mdx b/content/docs/guides/cheatsheets/quick-reference.mdx deleted file mode 100644 index d2ea9b5854..0000000000 --- a/content/docs/guides/cheatsheets/quick-reference.mdx +++ /dev/null @@ -1,317 +0,0 @@ ---- -title: Quick Reference Guide -description: Fast lookup table for all ObjectStack protocols ---- - - -# Quick Reference Guide - -Fast lookup for all 175 ObjectStack protocols organized by category. - - -Click on any protocol name to view its complete API reference. - - -## Data Protocol (18 schemas) - -Core business logic and data modeling schemas. - -| Protocol | Source File | Key Schemas | Purpose | -|:---------|:-----------|:------------|:--------| -| **[Field](./data/field)** | `field.zod.ts` | Field, FieldType, SelectOption | 44 field types for data modeling | -| **[Object](./data/object)** | `object.zod.ts` | Object, ObjectCapabilities | Object/table definitions | -| **[Query](./data/query)** | `query.zod.ts` | Query, QueryOptions | Query AST with joins, aggregations | -| **[Filter](./data/filter)** | `filter.zod.ts` | QueryFilter, FilterCondition | Advanced filtering operators | -| **[Validation](./data/validation)** | `validation.zod.ts` | ValidationRule | Business validation rules | -| **[Dataset](./data/dataset)** | `dataset.zod.ts` | Dataset, DatasetMode | Reusable dataset definitions | -| **[Datasource](./data/datasource)** | `datasource.zod.ts` | Datasource, DatasourceType | Database connection configs | -| **[Analytics](./data/analytics)** | `analytics.zod.ts` | Analytics | Data analytics and aggregation | -| **[Mapping](./data/mapping)** | `mapping.zod.ts` | FieldMapping | Field transformation mappings | -| **[Hook](./data/hook)** | `hook.zod.ts` | Hook, HookEvent | Lifecycle event hooks | -| **[Data Engine](./data/data-engine)** | `data-engine.zod.ts` | DataEngine | Data engine configuration | -| **[Driver](./data/driver)** | `driver.zod.ts` | Driver, DriverCapabilities | Database driver interface | -| **[SQL Driver](./data/driver-sql)** | `driver-sql.zod.ts` | SQLDriver | SQL-specific driver | -| **[NoSQL Driver](./data/driver-nosql)** | `driver-nosql.zod.ts` | NoSQLDriver | NoSQL-specific driver | -| **[Document](./data/document)** | `document.zod.ts` | Document | Document-oriented data | -| **[External Lookup](./data/external-lookup)** | `external-lookup.zod.ts` | ExternalLookup | External data lookups | -| **[Postgres Driver](./data/driver/postgres)** | `driver/postgres.zod.ts` | PostgresConfig | PostgreSQL configuration | -| **[Mongo Driver](./data/driver/mongo)** | `driver/mongo.zod.ts` | MongoConfig | MongoDB configuration | - -## UI Protocol (10 schemas) - -Presentation layer - views, forms, dashboards, and themes. - -| Protocol | Source File | Key Schemas | Purpose | -|:---------|:-----------|:------------|:--------| -| **[View](./ui/view)** | `view.zod.ts` | View, ListView, FormView | List and form view configurations | -| **[Page](./ui/page)** | `page.zod.ts` | Page, PageComponent | FlexiPage layouts | -| **[App](./ui/app)** | `app.zod.ts` | App, NavigationItem | Application navigation structure | -| **[Dashboard](./ui/dashboard)** | `dashboard.zod.ts` | Dashboard, DashboardWidget | Dashboard layouts and widgets | -| **[Report](./ui/report)** | `report.zod.ts` | Report, ReportType | Report definitions | -| **[Action](./ui/action)** | `action.zod.ts` | Action, ActionType | UI button actions | -| **[Component](./ui/component)** | `component.zod.ts` | PageComponent variants | Reusable UI components | -| **[Chart](./ui/chart)** | `chart.zod.ts` | Chart, ChartType | Chart definitions | -| **[Theme](./ui/theme)** | `theme.zod.ts` | Theme, ColorPalette | Theming and branding | -| **[Widget](./ui/widget)** | `widget.zod.ts` | WidgetManifest | Custom widget definitions | - -## Kernel Protocol (17 schemas) - -Plugin architecture, manifests, and kernel runtime. - -| Protocol | Source File | Key Schemas | Purpose | -|:---------|:-----------|:------------|:--------| -| **[Manifest](./kernel/manifest)** | `manifest.zod.ts` | Manifest | Package manifest (objectstack.config.ts) | -| **[Context](./kernel/context)** | `context.zod.ts` | KernelContext | Runtime execution context | -| **[Plugin](./kernel/plugin)** | `plugin.zod.ts` | Plugin, PluginHook | Plugin system interface | -| **[Plugin Capability](./kernel/plugin-capability)** | `plugin-capability.zod.ts` | PluginCapability | Plugin capability declarations | -| **[Plugin Lifecycle](./kernel/plugin-lifecycle-events)** | `plugin-lifecycle-events.zod.ts` | PluginLifecycleEvents | Plugin lifecycle events | -| **[Plugin Lifecycle Advanced](./kernel/plugin-lifecycle-advanced)** | `plugin-lifecycle-advanced.zod.ts` | PluginLifecycleAdvanced | Advanced lifecycle hooks | -| **[Plugin Loading](./kernel/plugin-loading)** | `plugin-loading.zod.ts` | PluginLoading | Plugin loading and init | -| **[Plugin Security](./kernel/plugin-security-advanced)** | `plugin-security-advanced.zod.ts` | PluginSecurityAdvanced | Plugin sandboxing | -| **[Plugin Structure](./kernel/plugin-structure)** | `plugin-structure.zod.ts` | PluginStructure | Plugin file conventions | -| **[Plugin Validator](./kernel/plugin-validator)** | `plugin-validator.zod.ts` | PluginValidator | Plugin validation | -| **[Plugin Versioning](./kernel/plugin-versioning)** | `plugin-versioning.zod.ts` | PluginVersioning | Version compatibility | -| **[Service Registry](./kernel/service-registry)** | `service-registry.zod.ts` | ServiceRegistry | Service discovery | -| **[Startup Orchestrator](./kernel/startup-orchestrator)** | `startup-orchestrator.zod.ts` | StartupOrchestrator | System startup | -| **[Events](./kernel/events)** | `events.zod.ts` | Event, EventBus | System event bus | -| **[Feature](./kernel/feature)** | `feature.zod.ts` | FeatureFlag | Feature flags | -| **[Metadata Loader](./kernel/metadata-loader)** | `metadata-loader.zod.ts` | MetadataLoader | Metadata loading | -| **[Package Registry](./kernel/package-registry)** | `package-registry.zod.ts` | PackageRegistry | Package resolution | - -## System Protocol (22 schemas) - -Runtime environment, logging, jobs, caching, and observability. - -| Protocol | Source File | Key Schemas | Purpose | -|:---------|:-----------|:------------|:--------| -| **[Audit](./system/audit)** | `audit.zod.ts` | AuditLog, AuditEvent | Audit trail logging | -| **[Auth Config](./system/auth-config)** | `auth-config.zod.ts` | AuthConfig | Authentication configuration | -| **[Cache](./system/cache)** | `cache.zod.ts` | CacheConfig | Caching layer | -| **[Change Management](./system/change-management)** | `change-management.zod.ts` | ChangeManagement | Change tracking | -| **[Collaboration](./system/collaboration)** | `collaboration.zod.ts` | Collaboration | Real-time collab | -| **[Compliance](./system/compliance)** | `compliance.zod.ts` | Compliance | Regulatory controls | -| **[Encryption](./system/encryption)** | `encryption.zod.ts` | Encryption | Encryption & keys | -| **[HTTP Server](./system/http-server)** | `http-server.zod.ts` | HTTPServer | HTTP server config | -| **[Job](./system/job)** | `job.zod.ts` | Job, JobSchedule | Background job queue | -| **[Logging](./system/logging)** | `logging.zod.ts` | LoggingConfig | Structured logging | -| **[Masking](./system/masking)** | `masking.zod.ts` | Masking | Data masking | -| **[Message Queue](./system/message-queue)** | `message-queue.zod.ts` | MessageQueue | Message queuing | -| **[Metadata Persistence](./system/metadata-persistence)** | `metadata-persistence.zod.ts` | MetadataPersistence | Metadata storage | -| **[Metrics](./system/metrics)** | `metrics.zod.ts` | Metrics | Application metrics | -| **[Migration](./system/migration)** | `migration.zod.ts` | Migration | Schema migration | -| **[Notification](./system/notification)** | `notification.zod.ts` | Notification | Notifications | -| **[Object Storage](./system/object-storage)** | `object-storage.zod.ts` | ObjectStorage | Object storage | -| **[Search Engine](./system/search-engine)** | `search-engine.zod.ts` | SearchEngine | Full-text search | -| **[Service Registry](./system/service-registry)** | `service-registry.zod.ts` | ServiceRegistry | System services | -| **[Tracing](./system/tracing)** | `tracing.zod.ts` | Tracing | Distributed tracing | -| **[Translation](./system/translation)** | `translation.zod.ts` | Translation | i18n support | -| **[Worker](./system/worker)** | `worker.zod.ts` | Worker | Background workers | - -## AI Protocol (13 schemas) - -AI/ML capabilities - agents, models, RAG, and cost tracking. - -| Protocol | Source File | Key Schemas | Purpose | -|:---------|:-----------|:------------|:--------| -| **[Agent](./ai/agent)** | `agent.zod.ts` | Agent, AITool | AI agent definitions | -| **[Agent Action](./ai/agent-action)** | `agent-action.zod.ts` | AgentAction | Agent action definitions | -| **[Model Registry](./ai/model-registry)** | `model-registry.zod.ts` | ModelRegistry, ModelProvider | LLM model management | -| **[RAG Pipeline](./ai/rag-pipeline)** | `rag-pipeline.zod.ts` | RAGPipelineConfig | Retrieval augmented generation | -| **[NLQ](./ai/nlq)** | `nlq.zod.ts` | NLQRequest, NLQResponse | Natural language to query | -| **[Conversation](./ai/conversation)** | `conversation.zod.ts` | ConversationSession | Conversation management | -| **[Cost](./ai/cost)** | `cost.zod.ts` | CostEntry, BudgetLimit | AI cost tracking and budgets | -| **[Predictive](./ai/predictive)** | `predictive.zod.ts` | PredictiveModel | Predictive ML models | -| **[Orchestration](./ai/orchestration)** | `orchestration.zod.ts` | AIOrchestration | Multi-agent orchestration | -| **[Feedback Loop](./ai/feedback-loop)** | `feedback-loop.zod.ts` | FeedbackLoop | AI feedback and learning | -| **[DevOps Agent](./ai/devops-agent)** | `devops-agent.zod.ts` | DevOpsAgent | DevOps automation | -| **[Plugin Development](./ai/plugin-development)** | `plugin-development.zod.ts` | PluginDevelopment | AI-assisted development | -| **[Runtime Ops](./ai/runtime-ops)** | `runtime-ops.zod.ts` | RuntimeOps | AI runtime operations | - -## API Protocol (20 schemas) - -REST/GraphQL endpoints, real-time subscriptions, and discovery. - -| Protocol | Source File | Key Schemas | Purpose | -|:---------|:-----------|:------------|:--------| -| **[Contract](./api/contract)** | `contract.zod.ts` | APIContract | API contract definitions | -| **[Endpoint](./api/endpoint)** | `endpoint.zod.ts` | Endpoint, EndpointMethod | REST endpoint configuration | -| **[Router](./api/router)** | `router.zod.ts` | Router, Route | API routing rules | -| **[OData](./api/odata)** | `odata.zod.ts` | ODataQuery | OData protocol support | -| **[GraphQL](./api/graphql)** | `graphql.zod.ts` | GraphQLSchema | GraphQL API config | -| **[Realtime](./api/realtime)** | `realtime.zod.ts` | Subscription, Channel | WebSocket subscriptions | -| **[WebSocket](./api/websocket)** | `websocket.zod.ts` | WebSocketConfig | WebSocket protocol | -| **[Discovery](./api/discovery)** | `discovery.zod.ts` | ServiceDiscovery | API discovery and metadata | -| **[Batch](./api/batch)** | `batch.zod.ts` | BatchRequest | Batch API processing | -| **[HTTP Cache](./api/http-cache)** | `http-cache.zod.ts` | CacheStrategy | HTTP caching | -| **[Errors](./api/errors)** | `errors.zod.ts` | ErrorResponse | Error responses | -| **[Protocol](./api/protocol)** | `protocol.zod.ts` | ProtocolDefinition | Protocol definitions | -| **[REST Server](./api/rest-server)** | `rest-server.zod.ts` | RESTServer | REST server config | -| **[Auth](./api/auth)** | `auth.zod.ts` | Auth | API authentication | -| **[Analytics](./api/analytics)** | `analytics.zod.ts` | Analytics | API usage analytics | -| **[Documentation](./api/documentation)** | `documentation.zod.ts` | Documentation | API docs generation | -| **[Hub](./api/hub)** | `hub.zod.ts` | Hub | API hub integration | -| **[Metadata](./api/metadata)** | `metadata.zod.ts` | Metadata | API metadata endpoints | -| **[Registry](./api/registry)** | `registry.zod.ts` | Registry | API registry | -| **[Storage](./api/storage)** | `storage.zod.ts` | Storage | API storage operations | - -## Automation Protocol (8 schemas) - -Flows, state machines, approvals, and integrations. - -| Protocol | Source File | Key Schemas | Purpose | -|:---------|:-----------|:------------|:--------| -| **[Flow](./automation/flow)** | `flow.zod.ts` | Flow, FlowNode | Visual workflow builder | -| **[Workflow](./automation/workflow)** | `state-machine.zod.ts` | StateMachine | Historical route; current workflow semantics are state machines plus Flow | -| **[Approval](./automation/approval)** | `approval.zod.ts` | ApprovalNodeConfig | Flow approval-node config | -| **[State Machine](./automation/state-machine)** | `state-machine.zod.ts` | StateMachine | State machine definitions | -| **[Webhook](./automation/webhook)** | `webhook.zod.ts` | Webhook, WebhookEvent | Outbound webhooks | -| **[ETL](./automation/etl)** | `etl.zod.ts` | ETLPipeline | Data transformation pipelines | -| **[Trigger Registry](./automation/trigger-registry)** | `trigger-registry.zod.ts` | TriggerRegistry | Event-driven triggers | -| **[Sync](./automation/sync)** | `sync.zod.ts` | SyncConfig | Bi-directional data sync | - -## Security Protocol (5 schemas) - -Access control, permissions, and row-level security. - -| Protocol | Source File | Key Schemas | Purpose | -|:---------|:-----------|:------------|:--------| -| **[Permission](./security/permission)** | `permission.zod.ts` | ObjectPermission | Object-level permissions | -| **[Policy](./security/policy)** | `policy.zod.ts` | SecurityPolicy | Security policies | -| **[RLS](./security/rls)** | `rls.zod.ts` | RowLevelSecurity | Row-level security filters | -| **[Sharing](./security/sharing)** | `sharing.zod.ts` | SharingRule | Record sharing rules | -| **[Territory](./security/territory)** | `territory.zod.ts` | Territory | Territory-based access | - -## Identity Protocol (4 schemas) - -User identity, organizations, and role management. - -| Protocol | Source File | Key Schemas | Purpose | -|:---------|:-----------|:------------|:--------| -| **[Identity](./identity/identity)** | `identity.zod.ts` | Identity, User | User identity management | -| **[Organization](./identity/organization)** | `organization.zod.ts` | Organization | Multi-organization support | -| **[Role](./identity/role)** | `role.zod.ts` | Role | Role-based access control | -| **[SCIM](./identity/scim)** | `scim.zod.ts` | SCIMUser, SCIMGroup | SCIM 2.0 provisioning | - -## Cloud Protocol (9 schemas) - -Marketplace, licensing, and multi-tenancy. - -| Protocol | Source File | Key Schemas | Purpose | -|:---------|:-----------|:------------|:--------| -| **[Marketplace](./hub/marketplace)** | `marketplace.zod.ts` | Package, PackageVersion | Plugin marketplace | -| **[Plugin Registry](./hub/plugin-registry)** | `plugin-registry.zod.ts` | PluginRegistry | Plugin versioning | -| **[Plugin Security](./hub/plugin-security)** | `plugin-security.zod.ts` | PluginSecurity | Plugin security policies | -| **[Composer](./hub/composer)** | `composer.zod.ts` | Dependency | Dependency management | -| **[License](./hub/license)** | `license.zod.ts` | License, LicenseType | Feature licensing | -| **[Tenant](./hub/tenant)** | `tenant.zod.ts` | Tenant | Multi-tenancy isolation | -| **[Space](./hub/space)** | `space.zod.ts` | Space, Workspace | Workspace management | -| **[Hub Federation](./hub/hub-federation)** | `hub-federation.zod.ts` | HubFederation | Cross-instance federation | -| **[Registry Config](./hub/registry-config)** | `registry-config.zod.ts` | RegistryConfig | Registry settings | - -## Integration Protocol (7 schemas) - -External system connectors and adapters. - -| Protocol | Source File | Key Schemas | Purpose | -|:---------|:-----------|:------------|:--------| -| **[Connector](./integration/connector)** | `connector.zod.ts` | Connector | Generic connector interface | -| **[SaaS Connector](./integration/connector/saas)** | `connector/saas.zod.ts` | SaaSConnector | SaaS integrations | -| **[Database Connector](./integration/connector/database)** | `connector/database.zod.ts` | DatabaseConnector | Database adapters | -| **[File Storage](./integration/connector/file-storage)** | `connector/file-storage.zod.ts` | FileStorageConnector | Cloud storage | -| **[Message Queue](./integration/connector/message-queue)** | `connector/message-queue.zod.ts` | MessageQueueConnector | Queue integrations | -| **[GitHub](./integration/connector/github)** | `connector/github.zod.ts` | GitHubConnector | GitHub API integration | -| **[Vercel](./integration/connector/vercel)** | `connector/vercel.zod.ts` | VercelConnector | Vercel deployment | - -## Shared Protocol (4 schemas) - -Common utilities used across all protocols. - -| Protocol | Source File | Key Schemas | Purpose | -|:---------|:-----------|:------------|:--------| -| **[HTTP](./shared/http)** | `http.zod.ts` | HTTPRequest, HTTPResponse | HTTP utilities | -| **[Identifiers](./shared/identifiers)** | `identifiers.zod.ts` | ID formats | Standard ID patterns | -| **[Mapping](./shared/mapping)** | `mapping.zod.ts` | MappingRule | Field mapping utilities | -| **[Connector Auth](./shared/connector-auth)** | `connector-auth.zod.ts` | ConnectorAuth | Connector auth patterns | - -## QA Protocol (1 schema) - -Testing and quality assurance. - -| Protocol | Source File | Key Schemas | Purpose | -|:---------|:-----------|:------------|:--------| -| **[Testing](./qa/testing)** | `testing.zod.ts` | TestSuite | Declarative test definitions | - ---- - -## Common Patterns - -### Naming Conventions - - - - ```typescript - // Property names in schemas: camelCase - { - maxLength: 100, - defaultValue: 'example', - referenceFilters: ['active = true'] - } - ``` - - - ```typescript - // Machine identifiers in data: snake_case - { - name: 'project_task', - object: 'customer', - field: 'first_name' - } - ``` - - - ```typescript - // Export names: PascalCase + Schema suffix - export const FieldSchema = z.object({...}); - export type Field = z.infer; - ``` - - - -### Common Imports - -```typescript -// Data protocols -import { FieldSchema, ObjectSchema, QuerySchema } from '@objectstack/spec/data'; - -// UI protocols -import { ViewSchema, AppSchema, DashboardSchema } from '@objectstack/spec/ui'; - -// Kernel protocols -import { ManifestSchema, PluginSchema } from '@objectstack/spec/kernel'; - -// System protocols -import { LoggerConfigSchema, JobSchema } from '@objectstack/spec/system'; - -// AI protocols -import { AgentSchema, RAGPipelineConfigSchema } from '@objectstack/spec/ai'; - -// Types -import type { Field, Object, Query, View } from '@objectstack/spec'; -``` - -## Search Tips - -- **By Feature**: "How do I model relationships?" → [Field Protocol](./data/field) → `lookup` or `master_detail` types -- **By Use Case**: "Build a dashboard" → [Dashboard Protocol](./ui/dashboard) -- **By Layer**: Data → [Data Protocol](./data), UI → [UI Protocol](./ui), Runtime → [System Protocol](./system) - -## Next Steps - - -**New to ObjectStack?** Start with the [Introduction](../introduction) to learn core concepts before diving into specific protocols. - - -- [Protocol Reference Index](./index) - Full protocol documentation -- [ObjectQL Guide](../objectql) - Deep dive into data modeling -- [ObjectUI Guide](../objectui) - UI development guide -- [Contributing Guide](https://github.com/objectstack-ai/framework/blob/main/CONTRIBUTING.md) - How to contribute to protocols diff --git a/content/docs/guides/index.mdx b/content/docs/guides/index.mdx deleted file mode 100644 index a87bdd15c8..0000000000 --- a/content/docs/guides/index.mdx +++ /dev/null @@ -1,86 +0,0 @@ ---- -title: Guides -description: Task-oriented tutorials for building applications with ObjectStack ---- - -import { Database, Workflow, Shield, Bot, Globe, Wrench, BookMarked, FileText, Brain, Lightbulb } from 'lucide-react'; - -# Developer Guides - -Practical, task-oriented guides covering the full development workflow. Each guide is self-contained — jump to whatever you need. - - -**New here?** Complete the [Quick Start](/docs/getting-started/quick-start) first, then return here to go deeper. - - -## Solutions (Scenario Cookbook) - -Goal-oriented recipes: given a concrete business scenario, the recommended way to solve it across objects, fields, forms, views, permissions and automation. The rest of the guides explain *how a feature works*; these explain *how to solve a problem*. - - - } - title="Scenario Cookbook" - href="/docs/guides/solutions" - description="Create-vs-edit forms, field grouping, role-based interfaces, access control, public forms, approvals — each with a runnable example." - /> - - -## Foundations - - - } - title="Metadata Types" - href="/docs/guides/metadata" - description="Every metadata type: Object, Field, View, App, Dashboard, Flow, Workflow, Validation, Permission." - /> - } - title="Data Modeling" - href="/docs/guides/data-modeling" - description="Design objects, fields, relationships, indexes, and validation rules." - /> - } - title="Common Patterns" - href="/docs/guides/common-patterns" - description="Top 10 copy-paste patterns: CRUD, search, auth, realtime, and more." - /> - - -## Building Applications - -| Guide | What You'll Learn | -| :--- | :--- | -| [Plugins](/docs/guides/plugins) | Using and configuring plugins | -| [Plugin Development](/docs/guides/plugin-development) | Building, testing, and publishing plugins | -| [Business Logic](/docs/guides/business-logic) | Workflows, approval flows, triggers, formulas | -| [Authentication](/docs/guides/authentication) | Identity management, OAuth, SAML, sessions | -| [Security](/docs/guides/security) | Profiles, permissions, sharing rules, RLS | -| [AI Capabilities](/docs/guides/ai-capabilities) | AI agents, RAG pipelines, NLQ, models | -| [AI Skills](/docs/guides/skills) | Structured knowledge modules for AI-powered code generation | - -## Integration & Infrastructure - -| Guide | What You'll Learn | -| :--- | :--- | -| [API Reference](/docs/guides/api-reference) | REST, GraphQL, and WebSocket APIs | -| [Client SDK](/docs/guides/client-sdk) | TypeScript client and React hooks | -| [Driver Configuration](/docs/guides/driver-configuration) | Database driver setup (Postgres, MongoDB, SQLite) | -| [Kernel Services](/docs/guides/kernel-services) | Microkernel architecture and service registry | -| [Data Flow](/docs/guides/data-flow) | Request lifecycle and data flow diagrams | - -## Operations - -| Guide | What You'll Learn | -| :--- | :--- | -| [Deploy to Vercel](/docs/guides/deployment-vercel) | MSW mode (static SPA) and Server mode (Serverless) deployment | -| [Error Handling (Client)](/docs/guides/error-handling-client) | Frontend error handling patterns | -| [Error Handling (Server)](/docs/guides/error-handling-server) | Backend error handling and recovery | -| [Development Standards](/docs/guides/standards) | Naming conventions, project structure, testing | -| [Troubleshooting](/docs/guides/troubleshooting) | FAQ and solutions to common issues | - -## Quick Reference - -Need to look something up fast? See the [Cheatsheets](/docs/guides/cheatsheets/quick-reference) — field types, query syntax, error codes, and more. diff --git a/content/docs/guides/meta.json b/content/docs/guides/meta.json deleted file mode 100644 index 586011a75e..0000000000 --- a/content/docs/guides/meta.json +++ /dev/null @@ -1,57 +0,0 @@ -{ - "title": "Guides", - "icon": "BookOpen", - "root": true, - "pages": [ - "index", - "---Solutions---", - "solutions", - "---Foundations---", - "packages", - "metadata", - "adding-a-metadata-type", - "data-modeling", - "seed-data", - "common-patterns", - "formula", - "validating-metadata", - "analytics-datasets", - "airtable-dashboard-analysis", - "---Building---", - "plugins", - "plugin-development", - "business-logic", - "hook-bodies", - "public-forms", - "authentication", - "auth-sso", - "security", - "ai-capabilities", - "plugin-chatbot-integration", - "skills", - "---Integration---", - "api-reference", - "client-sdk", - "contracts", - "project-scoping", - "driver-configuration", - "external-datasources", - "kernel-services", - "runtime-services", - "data-flow", - "---Operations---", - "deployment-vercel", - "cloud-deployment", - "production-readiness", - "publish-and-preview", - "single-project-mode", - "environment-variables", - "objectql-migration", - "error-handling-client", - "error-handling-server", - "standards", - "troubleshooting", - "---Cheatsheets---", - "cheatsheets" - ] -} diff --git a/content/docs/guides/metadata/index.mdx b/content/docs/guides/metadata/index.mdx deleted file mode 100644 index f99532da0f..0000000000 --- a/content/docs/guides/metadata/index.mdx +++ /dev/null @@ -1,127 +0,0 @@ ---- -title: Metadata Types Overview -description: A comprehensive guide to every metadata type used in ObjectStack application development ---- - -# Metadata Types Overview - -In ObjectStack, an application is defined entirely by **metadata** — declarative configurations that describe data models, user interfaces, business logic, and security rules. The Kernel interprets these metadata definitions at runtime to produce a fully functional application. - -This section provides a detailed guide for each metadata type you use when building an application. - -## Metadata Categories - -### Data Layer - -Define your business data model and integrity rules. - -| Metadata Type | Description | File Convention | -| :--- | :--- | :--- | -| [**Object**](./object) | Business entity definitions — tables, fields, capabilities | `*.object.ts` / `*.object.yml` | -| [**Field**](./field) | Individual property definitions within objects — 40+ types | Defined inline within Object | -| [**Validation**](./validation) | Data integrity rules — formula, uniqueness, format, state machine | Defined inline or standalone | - -### UI Layer - -Define how users interact with data. - -| Metadata Type | Description | File Convention | -| :--- | :--- | :--- | -| [**View**](./view) | List views and form views — grid, kanban, calendar, gantt | `*.view.ts` / `*.view.yml` | -| [**Page**](./page) | Custom pages with component-based layouts | `*.page.ts` / `*.page.yml` | -| [**App**](./app) | Application container — navigation, branding, permissions | `*.app.ts` / `*.app.yml` | -| [**Dashboard**](./dashboard) | Analytics dashboards with chart widgets | `*.dashboard.ts` / `*.dashboard.yml` | - -### Automation Layer - -Define business logic and process automation. - -| Metadata Type | Description | File Convention | -| :--- | :--- | :--- | -| [**Flow**](./flow) | Visual automation — decision trees, data operations, screens, approval nodes | `*.flow.ts` / `*.flow.yml` | -| [**Workflow**](./workflow) | Not a standalone metadata type (ADR-0020) — use Flow for automation, or a `state_machine` validation rule for lifecycle transitions | Authored as Flow / Validation | - -### Security Layer - -Define access control and data visibility. - -| Metadata Type | Description | File Convention | -| :--- | :--- | :--- | -| [**Permission**](./permission) | Permission sets — object CRUD, field security, tab visibility | `*.permission.ts` / `*.permission.yml` | - -### Documentation Layer - -Ship package documentation that travels and versions with the package. - -| Metadata Type | Description | File Convention | -| :--- | :--- | :--- | -| [**Doc**](./doc) | Package documentation pages — flat Markdown, rendered at `/docs/` | `src/docs/*.md` | - -## How Metadata Works Together - -``` -┌─────────────────────────────────────────────────┐ -│ App (Container) │ -│ ┌──────────┐ ┌───────────┐ ┌──────────────┐ │ -│ │Navigation│ │ Branding │ │ Permissions │ │ -│ └──────────┘ └───────────┘ └──────────────┘ │ -├─────────────────────────────────────────────────┤ -│ Views / Pages / Dashboards │ -│ ┌─────────┐ ┌──────────┐ ┌───────────────┐ │ -│ │ListView │ │ FormView │ │ Dashboard │ │ -│ │(grid, │ │(sections,│ │ (widgets, │ │ -│ │ kanban) │ │ fields) │ │ charts) │ │ -│ └─────────┘ └──────────┘ └───────────────┘ │ -├─────────────────────────────────────────────────┤ -│ Objects + Fields │ -│ ┌──────────────────────────────────────────┐ │ -│ │ Object: name, fields, capabilities │ │ -│ │ Fields: text, number, select, lookup ... │ │ -│ │ Validations: formula, uniqueness, format │ │ -│ └──────────────────────────────────────────┘ │ -├─────────────────────────────────────────────────┤ -│ Flows + Workflows + Permissions │ -│ ┌───────────┐ ┌───────────┐ ┌────────────┐ │ -│ │ Flow │ │ Workflow │ │ Permission │ │ -│ │(visual │ │(event │ │(CRUD, field│ │ -│ │ logic) │ │ triggers) │ │ security) │ │ -│ └───────────┘ └───────────┘ └────────────┘ │ -└─────────────────────────────────────────────────┘ -``` - -## Quick Example - -A minimal application requires at least an **Object** definition: - -```typescript -import { ObjectSchema, Field } from '@objectstack/spec/data'; - -export const Task = ObjectSchema.create({ - name: 'task', - label: 'Task', - fields: { - title: Field.text({ label: 'Title', required: true }), - status: Field.select({ - label: 'Status', - options: [ - { label: 'To Do', value: 'todo', default: true }, - { label: 'In Progress', value: 'in_progress' }, - { label: 'Done', value: 'done' }, - ], - }), - assignee: Field.lookup('user', { label: 'Assignee' }), - }, - enable: { apiEnabled: true, searchable: true }, -}); -``` - -From this single definition, ObjectStack automatically generates CRUD APIs, form views, and list views. As your application grows, you add **Views**, **Flows**, **Permissions**, and other metadata to customize behavior. - -## Next Steps - -Start with the core building blocks: - -1. [**Object**](./object) — Define your data entities -2. [**Field**](./field) — Configure field types and properties -3. [**View**](./view) — Customize list and form layouts -4. [**Flow**](./flow) — Add business logic and automation diff --git a/content/docs/guides/metadata/meta.json b/content/docs/guides/metadata/meta.json deleted file mode 100644 index 3ea0b9410e..0000000000 --- a/content/docs/guides/metadata/meta.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "title": "Metadata Types", - "pages": [ - "index", - "object", - "field", - "view", - "page", - "app", - "dashboard", - "flow", - "workflow", - "validation", - "permission", - "doc" - ] -} diff --git a/content/docs/guides/security.mdx b/content/docs/guides/security.mdx deleted file mode 100644 index 61337996a8..0000000000 --- a/content/docs/guides/security.mdx +++ /dev/null @@ -1,777 +0,0 @@ ---- -title: "Security Model Guide" -description: "Complete guide to implementing enterprise-grade security in ObjectStack with fine-grained permissions and data access controls" ---- - -# Security Model Guide - -Complete guide to implementing enterprise-grade security in ObjectStack with fine-grained permissions and data access controls. - -> **Implementation status — Phase-1 RBAC is live.** REST → ObjectQL now propagates a populated `ExecutionContext` (userId, tenantId, roles, permissions) into the SecurityPlugin middleware, so CRUD / FLS / RLS checks actually fire on every authenticated request. The default `member_default` permission set ships a wildcard RLS rule `organization_id == current_user.organization_id` plus explicit per-object overrides `sys_organization_self` (`id == current_user.organization_id`) and `sys_user_self` (`id == current_user.id`) for the two global tables that lack an `organization_id` column. RLS expressions, the physical column, and `RLSUserContext.organization_id` all use the same canonical name — there is no `tenantField` rewrite indirection (schemas with a different physical tenant column should fork the defaults). The legacy `objectql.registerTenantMiddleware` has been removed; SecurityPlugin is the sole authority for tenant isolation. Analytics also reuses the same read scope: `@objectstack/service-analytics` auto-bridges to `security.getReadFilter(object, context)` when the security service is registered, so dataset-bound dashboards/reports do not bypass RLS. End-to-end verified on `pnpm dev:crm` across `sys_organization`, `sys_member`, `sys_user`, `sys_user_permission_set`, `sys_role_permission_set`. **Anonymous traffic is denied by default** (the ADR-0056 D2 default-deny flip landed: `requireAuth` defaults to `true`); an explicit `requireAuth: false` opt-out logs a boot-time warning, and public forms self-authorize via a declaration-derived `publicFormGrant` (ADR-0056 Option A — see [Public Forms](./public-forms)). Organization-Wide Defaults (`private` / `public_read` / `public_read_write` / `controlled_by_parent`) and Sharing Rules (owner + criteria, with `role_and_subordinates` hierarchy widening) are live and dogfood-proven (ADR-0056); the Studio RLS visual editor, per-user×org permission cache, and audit UI for denied access are queued. See `CHANGELOG.md` and `concepts/implementation-status.mdx` for the latest matrix. - -## Table of Contents - -1. [Security Architecture](#security-architecture) -2. [Profiles](#profiles) -3. [Permission Sets](#permission-sets) -4. [Role Hierarchy](#role-hierarchy) -5. [Sharing Rules](#sharing-rules) -6. [Field-Level Security](#field-level-security) -7. [Best Practices](#best-practices) - ---- - -## Security Architecture - -> **Authentication is the first layer.** This guide covers *authorization* — -> who can see and do what once signed in (RBAC, RLS, FLS, sharing). Harden -> *authentication* first — password policy, enforced MFA, account lockout, -> session controls, and IP allowlist — in -> [Enterprise Authentication Hardening](./authentication#enterprise-authentication-hardening-adr-0069). - -ObjectStack implements a multi-layered security model: - -``` -┌─────────────────────────────────────┐ -│ Application Visibility │ ← Which apps can users access? -├─────────────────────────────────────┤ -│ Object Permissions │ ← CRUD on objects -├─────────────────────────────────────┤ -│ Record-Level Security │ ← Which records can be accessed? -│ - Organization-Wide Defaults │ -│ - Role Hierarchy │ -│ - Sharing Rules │ -│ - Manual Sharing │ -├─────────────────────────────────────┤ -│ Field-Level Security │ ← Read/Write specific fields -└─────────────────────────────────────┘ -``` - -### Security Layers - -1. **Object Permissions**: Control create, read, update, delete on entire objects -2. **Record-Level Security**: Control access to specific records -3. **Field-Level Security**: Control visibility and editability of fields -4. **Row-Level Security**: Control access based on data values - ---- - -## Profiles - -Profiles define a user's baseline permissions. - -### Profile Structure - -A profile is modelled as a `PermissionSet` with `isProfile: true` (see -`packages/spec/src/security/permission.zod.ts`). There is no distinct -`Profile` type — author it as a `*.profile.ts` metadata entry validated by -`PermissionSetSchema`. - -```typescript -import { definePermissionSet } from '@objectstack/spec/security'; - -export const SalesRepProfile = definePermissionSet({ - name: 'sales_rep', - label: 'Sales Representative', - isProfile: true, - - // Object-level permissions: -> permissions - objects: { - account: { - allowCreate: true, - allowRead: true, - allowEdit: true, - allowDelete: false, - viewAllRecords: false, // See all records regardless of owner - modifyAllRecords: false, // Edit all records regardless of owner - }, - opportunity: { - allowCreate: true, - allowRead: true, - allowEdit: true, - allowDelete: false, - viewAllRecords: false, - modifyAllRecords: false, - }, - }, - - // Field-level security: . -> permissions - fields: { - 'account.annual_revenue': { readable: true, editable: false }, - 'account.description': { readable: true, editable: true }, - }, - - // Tab/app visibility: -> visibility - tabPermissions: { - app_crm: 'default_on', // Shown by default - app_admin: 'hidden', // Not visible - app_sales: 'visible', // Available - }, -}); -``` - -### Object Permission Levels - -| Permission | Description | -|------------|-------------| -| `allowCreate` | Create new records | -| `allowRead` | View records they own or have access to | -| `allowEdit` | Edit records they own or have access to | -| `allowDelete` | Delete records they own or have access to | -| `allowTransfer` | Change record ownership | -| `allowRestore` | Restore soft-deleted records from trash (undelete) | -| `allowPurge` | Permanently delete records (hard delete / GDPR) | -| `viewAllRecords` | View ALL records regardless of ownership | -| `modifyAllRecords` | Edit ALL records regardless of ownership | - -### Access depth — `readScope` / `writeScope` (ADR-0057 D1) - -Beyond the boolean grants above, an owner-scoped object grant can carry a -**`readScope` / `writeScope`** that widens the owner-match *declaratively* — the -ERP "see my own / my reports / my unit / my unit and below / the whole org" axis, -without hand-writing one RLS policy per object: - -| Scope | Owner-match widens to | -|------------|-------------| -| `own` | the caller (baseline; unset = this) | -| `own_and_reports` | the caller + their `sys_user.manager_id` report chain | -| `unit` | owners in the caller's business unit (`sys_business_unit`) | -| `unit_and_below` | the caller's BU + all descendant BUs (BFS) | -| `org` | the whole tenant (≈ `viewAllRecords` / `modifyAllRecords`) | - -```typescript -objects: { - account: { allowRead: true, allowEdit: true, readScope: 'unit_and_below', writeScope: 'own' }, -} -``` - -It resolves to an `owner_id IN (…)` set at request time and AND-injects alongside -RLS (no compiler change; ADR-0055). Sharing rules still widen on top. - -> **Open-core boundary (ADR-0016).** `own` and `org` are open-source. The -> hierarchy-relative scopes (`own_and_reports` / `unit` / `unit_and_below`) require -> the paid `@objectstack/security-enterprise` plugin (BU-subtree + manager-chain -> resolver); without it they **fail closed to `own`** (never fail-open), and -> `defineStack` errors if a grant uses one without `requires: ['hierarchy-security']`. - -### Capabilities & secure-by-default object access (ADR-0066) - -Beyond CRUD grants and scope depth, two newer gates compose with the model above: - -- **Capabilities** are first-class records in the `sys_capability` registry (ADR-0066 D1) — maintainable named privileges such as `manage_metadata`, `manage_users`, `manage_org_users`, `manage_platform_settings`, `setup.access`, and `studio.access`. Grant them through permission sets like any other privilege. -- **Object access posture** — an object may declare `access: { default: 'public' | 'private' }` (ADR-0066 D2). `public` (the default) preserves allow-by-default exposure; `private` makes the object **secure-by-default** (no access unless explicitly granted). -- **Object-level `requiredPermissions`** (ADR-0066 D3) — a string array of capabilities that gate the object as an **AND** alongside CRUD grants (mirrors `App.requiredPermissions`): a user must hold every listed capability *and* the relevant CRUD grant. - -### Built-in identity roles (ADR-0068) - -`current_user.roles` is a **string array** — the only canonical role field (there is no singular `current_user.role`). Four role names are framework-seeded into `sys_role`: - -| Role | Meaning | -|:---|:---| -| `platform_admin` | Platform operator (SaaS admin) — not a tenant role | -| `org_owner` | Organization owner (`sys_member.role = owner`) | -| `org_admin` | Organization administrator (`sys_member.role = admin`) | -| `org_member` | Organization member (`sys_member.role = member`) | - -Test membership in RLS/CEL with `'org_admin' in current_user.roles` or `current_user.roles.exists(r, r == 'sales_manager')`. `current_user.isPlatformAdmin` is a derived, deprecated alias of `'platform_admin' in current_user.roles`. - -### Standard Profiles - -#### Sales Representative - -```typescript -import { definePermissionSet } from '@objectstack/spec/security'; - -export const SalesRepProfile = definePermissionSet({ - name: 'sales_rep', - isProfile: true, - objects: { - lead: { allowCreate: true, allowRead: true, allowEdit: true, allowDelete: false }, - account: { allowCreate: true, allowRead: true, allowEdit: true, allowDelete: false }, - contact: { allowCreate: true, allowRead: true, allowEdit: true, allowDelete: false }, - opportunity: { allowCreate: true, allowRead: true, allowEdit: true, allowDelete: false }, - quote: { allowCreate: true, allowRead: true, allowEdit: true, allowDelete: false }, - product: { allowCreate: false, allowRead: true, allowEdit: false, allowDelete: false }, - }, - fields: { - 'account.annual_revenue': { readable: true, editable: false }, // Read-only - }, -}); -``` - -#### Sales Manager - -```typescript -import { definePermissionSet } from '@objectstack/spec/security'; - -export const SalesManagerProfile = definePermissionSet({ - name: 'sales_manager', - isProfile: true, - objects: { - lead: { - allowCreate: true, allowRead: true, allowEdit: true, allowDelete: true, - viewAllRecords: true, modifyAllRecords: true - }, - account: { - allowCreate: true, allowRead: true, allowEdit: true, allowDelete: true, - viewAllRecords: true, modifyAllRecords: true - }, - // ... full access to sales objects - }, -}); -``` - -#### Service Agent - -```typescript -import { definePermissionSet } from '@objectstack/spec/security'; - -export const ServiceAgentProfile = definePermissionSet({ - name: 'service_agent', - isProfile: true, - objects: { - case: { allowCreate: true, allowRead: true, allowEdit: true, allowDelete: false }, - task: { allowCreate: true, allowRead: true, allowEdit: true, allowDelete: true }, - account: { allowCreate: false, allowRead: true, allowEdit: false, allowDelete: false }, - contact: { allowCreate: false, allowRead: true, allowEdit: true, allowDelete: false }, - }, - fields: { - 'case.is_sla_violated': { readable: true, editable: false }, - 'case.resolution_time_hours': { readable: true, editable: false }, - }, -}); -``` - ---- - -## Permission Sets - -Permission sets extend profile permissions without changing the profile. - -```typescript -import { definePermissionSet } from '@objectstack/spec/security'; - -export const AdvancedReportingPermissionSet = definePermissionSet({ - name: 'advanced_reporting', - label: 'Advanced Reporting', - - objects: { - opportunity: { - viewAllRecords: true, // Override profile restriction - }, - account: { - viewAllRecords: true, - }, - }, - - fields: { - 'opportunity.amount': { readable: true }, - 'opportunity.probability': { readable: true }, - }, - - // System permissions are a flat array of capability strings - systemPermissions: ['run_reports', 'export_reports', 'create_dashboards'], -}); - -export const BulkDataPermissionSet = definePermissionSet({ - name: 'bulk_data_access', - label: 'Bulk Data Access', - - objects: {}, - systemPermissions: ['bulk_api', 'view_all_data'], -}); -``` - -### Built-in Permission Sets - -The framework ships four canonical permission sets that are auto-seeded on -boot by `plugin-security` (see -`packages/plugins/plugin-security/src/objects/default-permission-sets.ts`). Use -these as the baseline for any new org — tier custom sets on top rather -than redefining the basics. - -| Name | Scope | What it unlocks | Notes | -|:--|:--|:--|:--| -| `admin_full_access` | Platform (no RLS) | All objects, all system permissions, Studio + Setup, cross-org reads | Reserved for platform operators. Auto-granted to the bootstrap admin (`bootstrapPlatformAdmin`) — the **first registered human**. The non-loginable seed-data identity `usr_system` (role `system`, provisioned before the first sign-up to own seeded rows) is deliberately skipped, so the real admin wins the promotion. | -| `organization_admin` | Per-org (`tenant_isolation` RLS, only active when `@objectstack/plugin-org-scoping` is loaded) | Wildcard CRUD inside the org, `manage_org_users`, Setup app shell (only org-scoped entries visible), invite members, manage roles assignment | **Read-only** on `sys_role`, `sys_permission_set`, `sys_role_permission_set`, `sys_user_permission_set`, `sys_user_role` to prevent self-elevation. Does **not** see Studio. | -| `member_default` | Per-org | Standard end-user CRUD on org records; **writes are owner-scoped** | Default profile for invited members. | -| `viewer_readonly` | Per-org | Read access only | For auditors / read-only stakeholders. | - -> **Owner-scoped writes.** `member_default` grants read/create on org records but -> restricts **edit and delete to the records the user created** — via the -> `owner_only_writes` / `owner_only_deletes` RLS policies, keyed on `created_by` -> (the ownership column the engine stamps on every row). These are enforced on -> single-id `update`/`delete` by a **pre-image authorization check**: before the -> mutation the middleware re-reads the target row through the write-operation RLS -> filter, and a member attempting to modify another user's record gets `403`. -> A permission set with `modifyAllRecords` (or no RLS, e.g. `admin_full_access`) -> bypasses this. An object that opts out of audit fields (`systemFields.audit: -> false`, no `created_by`) fails **closed** for member writes — grant -> `modifyAllRecords` or a per-object policy, or model transferable ownership with -> a dedicated owner field + custom policy. - -> **Single-org vs. multi-org runtimes.** The wildcard `tenant_isolation` -> RLS row above only takes effect when `@objectstack/plugin-org-scoping` -> is registered (typically via `OS_MULTI_ORG_ENABLED=true`). In single-org -> mode `plugin-security` detects the missing `org-scoping` service and -> strips the wildcard policy so reads / writes aren't accidentally -> filtered by an unset `current_user.organization_id`. See the -> [Org-Scoping Plugin README](https://github.com/objectstack-ai/framework/blob/main/packages/plugins/plugin-org-scoping/README.md) -> for boot order and per-org seed-replay details. - -#### Auto-grant for organization admins - -Any user whose `sys_member.role` is `owner`, `admin`, or comma-set -`"owner,admin"` automatically receives an org-scoped grant of -`organization_admin` (one `sys_user_permission_set` row per `(user, org)` -pair). The grant is reconciled by a lifecycle hook in `plugin-security` -on every `sys_member` insert / update / delete, and a `kernel:ready` -backfill sweep cleans up orphans on boot. Demoting a member to `member` -revokes the grant in the same transaction; you do not manage these rows -by hand. - -#### Setup app gating - -Setup nav items and the corresponding global settings manifests -(`ai`, `knowledge`, `mail`, `storage`) require the new -`manage_platform_settings` system permission, which is granted **only** to -`admin_full_access`. `organization_admin` sees the Setup shell — -Apps, People & Organization, Roles (read-only) — but not platform-wide -configuration. Tenant-scoped settings (`branding`, `feature_flags`) -remain gated by `setup.access` so org admins can manage them. - -### Assigning Permission Sets - -Permission-set grants are plain data rows, not helper-function calls. Assign a -set to a user by inserting a `sys_user_permission_set` row, or to a role by -inserting a `sys_role_permission_set` row: - -```typescript -// Grant a permission set to a single user -await objectql.object('sys_user_permission_set').insert({ - user_id: 'user123', - permission_set: 'advanced_reporting', -}); - -// Grant a permission set to everyone in a role -await objectql.object('sys_role_permission_set').insert({ - role: 'data_analysts', - permission_set: 'bulk_data_access', -}); -``` - -Org-admin grants are reconciled automatically by a `plugin-security` lifecycle -hook (see [Auto-grant for organization admins](#auto-grant-for-organization-admins)) -— you do not insert those rows by hand. - ---- - -## Role Hierarchy - -Roles control record-level access through a hierarchy. - -The hierarchy is derived from the `parent` link on each role — there is no -`RoleHierarchy` container schema. Author roles as individual `*.role.ts` -entries (each matching `RoleSchema`), using `parent` to point at the role they -report to: - -```typescript -import type { Role } from '@objectstack/spec/identity'; - -export const roles: Role[] = [ - // Top level - { name: 'executive', label: 'Executive' }, - - // Sales hierarchy - { name: 'sales_director', label: 'Sales Director', parent: 'executive' }, - { name: 'sales_manager', label: 'Sales Manager', parent: 'sales_director' }, - { name: 'sales_rep', label: 'Sales Representative', parent: 'sales_manager' }, - - // Service hierarchy - { name: 'service_director', label: 'Service Director', parent: 'executive' }, - { name: 'service_manager', label: 'Service Manager', parent: 'service_director' }, - { name: 'service_agent', label: 'Service Agent', parent: 'service_manager' }, -]; -``` - -### How Role Hierarchy Works - -``` - Executive - / \ - Sales Director Service Director - | | - Sales Manager Service Manager - | | - Sales Rep Service Agent -``` - -**Grant Access UP:** Users see records owned by: -- Themselves -- Their subordinates -- Their subordinates' subordinates (all levels down) - -**Example:** Sales Director sees all records owned by Sales Managers and Sales Reps. - ---- - -## Sharing Rules - -Sharing rules extend access beyond the role hierarchy. - -### Organization-Wide Defaults (OWD) - -Set baseline access for all users: - -Each object's OWD is a single value from the `OWDModel` enum (`private`, -`public_read`, `public_read_write`, `controlled_by_parent`): - -```typescript -export const OrganizationDefaults = { - lead: 'private', // Users see only their own records - account: 'private', - contact: 'controlled_by_parent', // Access controlled by parent (Account) - opportunity: 'private', - campaign: 'public_read', // All users can read - product: 'public_read', -}; -``` - -### Access Levels - -| Level | Description | -|-------|-------------| -| `private` | Owner only (+ role hierarchy) | -| `public_read` | All users can read | -| `public_read_write` | All users can read and edit | -| `controlled_by_parent` | Controlled by parent object | - -### Criteria-Based Sharing Rules - -Share records based on field criteria: - -```typescript -import { defineSharingRule } from '@objectstack/spec/security'; - -export const AccountTeamSharingRule = defineSharingRule({ - name: 'account_team_sharing', - label: 'Share Active Customers with Sales Team', - type: 'criteria', - object: 'account', - - // Predicate (CEL): which records to share - condition: P`record.type == "customer" && record.is_active == true`, - - // Who to share with (a single recipient — see the recipient types below) - sharedWith: { - type: 'role', - value: 'sales_manager', - }, - - // Access level granted: read | edit | full - accessLevel: 'edit', -}); -``` - -#### Recipient types - -`sharedWith` (and `ownedBy`) accept a `{ type, value }` recipient. The supported -`type` values are: - -| `type` | Shares with | -|:--|:--| -| `user` | A single user | -| `group` | All members of a public group | -| `role` | Everyone assigned that role | -| `role_and_subordinates` | Everyone in that role **and every role below it** in the hierarchy (ADR-0056 D6) — configurable per rule, so one rule can cascade down a branch of the org chart | - -```typescript -// Share with a sales manager AND everyone reporting up to them. -sharedWith: { type: 'role_and_subordinates', value: 'sales_manager' }, -``` - -The recipient set is expanded by `@objectstack/plugin-sharing` when the rule is -evaluated (`afterInsert` / `afterUpdate`); `role_and_subordinates` walks the -`sys_role.parent` graph (cycle-safe). - -### Owner-Based Sharing Rules - -Share based on record owner characteristics: - -```typescript -import { defineSharingRule } from '@objectstack/spec/security'; - -export const OpportunityOwnerSharingRule = defineSharingRule({ - name: 'opportunity_owner_sharing', - label: 'Share Sales Rep Opportunities with Managers', - type: 'owner', - object: 'opportunity', - - // Share records owned by this group/role - ownedBy: { - type: 'role', - value: 'sales_rep', - }, - - // Share with this recipient - sharedWith: { - type: 'role', - value: 'sales_manager', - }, - - accessLevel: 'read', -}); -``` - -### Analytics and Dataset Read Scope - -Dataset-bound dashboards and reports often execute through the analytics -service, including the NativeSQL strategy. That path still has to honor the -same row-level security rules as ObjectQL. `@objectstack/plugin-security` -therefore registers a public `security` service with -`getReadFilter(object, context)`, and `@objectstack/service-analytics` -auto-bridges to it unless an explicit `getReadScope` option is supplied. - -The bridge is context-aware and may be async because permission-set and RLS -resolution can hit the database. The analytics service applies the returned -filter to the base object and to joined objects declared by a dataset. If read -scope resolution fails or an unsupported predicate would have to be translated -into SQL, the analytics query fails closed instead of dropping the filter. - ---- - -## Field-Level Security - -Control visibility and editability of specific fields. - -### Field Permissions in Profiles - -Field permissions are keyed `.` and use `readable` / `editable`: - -```typescript -fields: { - // Read-only: visible but not editable - 'account.annual_revenue': { readable: true, editable: false }, - 'account.description': { readable: true, editable: true }, - // Hidden: not visible at all - 'account.ssn': { readable: false, editable: false }, - 'opportunity.amount': { readable: true, editable: true }, - 'opportunity.probability': { readable: true, editable: false }, -} -``` - -### Hidden vs. Read-Only - -```typescript -// Hidden: Field not visible at all -{ readable: false, editable: false } - -// Read-Only: Field visible but not editable -{ readable: true, editable: false } - -// Editable: Field visible and editable -{ readable: true, editable: true } -``` - -### Server-side enforcement (fail-closed) - -The client-side ObjectForm / inline grid hides non-editable fields from -the UI — but that is a **UX layer only**. The SecurityPlugin middleware -enforces field-level write rules on the server, regardless of how the -request arrived (REST, GraphQL, raw ObjectQL call). - -**On read** — `find` / `findOne` results have non-readable fields -stripped from every record before the response leaves the engine. - -**On write** — `insert` / `update` requests are checked **before** the -operation reaches the driver. If the payload contains any field the -caller is not permitted to edit, the engine throws -`PermissionDeniedError` (mapped to HTTP 403) with the offending field -names in `details.forbiddenFields`: - -```json -{ - "error": { - "code": "PERMISSION_DENIED", - "message": "[Security] Field write denied: not permitted to edit [salary, ssn] on 'employee'", - "details": { - "operation": "insert", - "object": "employee", - "forbiddenFields": ["salary", "ssn"] - } - } -} -``` - -**Why throw instead of silently stripping?** Silent strip hides the -security boundary from honest clients (their update "doesn't save" and -they cannot tell why) AND gives a probing client no signal that the -field exists. Throwing makes the boundary observable in both directions -— legitimate UIs get an actionable error to fix; probing clients learn -nothing they could not already infer. - -**Allow-list semantics.** Fields without an explicit rule pass through -untouched. Permission sets only constrain fields they explicitly -enumerate. - -**Bulk inserts.** Arrays are checked row-by-row; a single offending -field in any row rejects the whole batch atomically. - -**System operations.** `ExecutionContext { isSystem: true }` bypasses -the check entirely — used for migrations, seed loading, and audit log -writes. - ---- - -## Best Practices - -### 1. Profile Design - -✅ **DO:** -- Create minimal profiles (start restrictive, extend with permission sets) -- Use descriptive names -- Document the purpose of each profile -- Assign one profile per user - -❌ **DON'T:** -- Create too many profiles -- Give excessive permissions "just in case" -- Mix unrelated permissions in one profile - -### 2. Permission Sets - -✅ **DO:** -- Use for temporary or special access -- Group related permissions -- Name clearly (e.g., "Advanced Reporting", "Bulk Data Access") -- Remove when no longer needed - -❌ **DON'T:** -- Use as a replacement for profiles -- Grant system-wide permissions unnecessarily - -### 3. Role Hierarchy - -✅ **DO:** -- Mirror your organizational structure -- Keep hierarchies simple -- Document reporting relationships -- Review regularly - -❌ **DON'T:** -- Create overly deep hierarchies -- Mix different org structures -- Grant too much upward access - -### 4. Sharing Rules - -✅ **DO:** -- Start with most restrictive OWD -- Use sharing rules to open up access -- Document business justification -- Test thoroughly - -❌ **DON'T:** -- Set OWD to Public unless necessary -- Create redundant sharing rules -- Grant more access than needed - -### 5. Field-Level Security - -✅ **DO:** -- Protect sensitive data (SSN, salary, etc.) -- Use read-only for calculated fields -- Document security classifications -- Audit regularly - -❌ **DON'T:** -- Hide required fields -- Restrict access unnecessarily -- Forget about API access - ---- - -## Security Checklist - -### Initial Setup - -- [ ] Harden authentication (password policy, enforced MFA, lockout, session controls, IP allowlist) — see [Authentication Hardening](./authentication#enterprise-authentication-hardening-adr-0069) -- [ ] Define user roles and hierarchies -- [ ] Create profiles for each role -- [ ] Set organization-wide defaults -- [ ] Configure field-level security -- [ ] Create sharing rules - -### Ongoing Maintenance - -- [ ] Review user access quarterly -- [ ] Audit permission changes -- [ ] Remove inactive users promptly -- [ ] Update sharing rules as needed -- [ ] Monitor security health checks - -### Compliance - -- [ ] Document security model -- [ ] Maintain access request process -- [ ] Log security changes -- [ ] Conduct security reviews -- [ ] Train users on security policies - ---- - -## Real-World Example - -Complete security setup for a sales team: - -```typescript -// 1. Organization-Wide Defaults (one OWDModel value per object) -const OrganizationDefaults = { - account: 'private', - opportunity: 'private', - contact: 'controlled_by_parent', -}; - -// 2. Role Hierarchy (flat roles linked by `parent`) -const roles = [ - { name: 'sales_vp', label: 'Sales VP' }, - { name: 'sales_manager', label: 'Sales Manager', parent: 'sales_vp' }, - { name: 'sales_rep', label: 'Sales Rep', parent: 'sales_manager' }, -]; - -// 3. Profile (a PermissionSet with isProfile: true) -const SalesRepProfile = { - name: 'sales_rep', - isProfile: true, - objects: { - account: { allowCreate: true, allowRead: true, allowEdit: true, allowDelete: false }, - opportunity: { allowCreate: true, allowRead: true, allowEdit: true, allowDelete: false }, - }, - fields: { - 'account.annual_revenue': { readable: true, editable: false }, // Read-only - }, -}; - -// 4. Sharing Rule (criteria type with a CEL condition) -const AccountSharingRule = { - name: 'high_value_accounts', - type: 'criteria', - object: 'account', - // Share high-value accounts with sales reps - condition: P`record.annual_revenue >= 1000000`, - sharedWith: { type: 'role', value: 'sales_rep' }, - accessLevel: 'read', -}; - -// 5. Permission Set (systemPermissions is a string array) -const AdvancedReportingPermissionSet = { - name: 'advanced_reporting', - objects: {}, - // For sales analysts - systemPermissions: ['run_reports', 'export_reports', 'view_all_data'], -}; -``` - ---- - -**Next:** [Automation →](./automation) diff --git a/content/docs/guides/solutions/index.mdx b/content/docs/guides/solutions/index.mdx deleted file mode 100644 index 7142bba6d6..0000000000 --- a/content/docs/guides/solutions/index.mdx +++ /dev/null @@ -1,55 +0,0 @@ ---- -title: Solutions (Scenario Cookbook) -description: Goal-oriented recipes — given a concrete business scenario, the recommended way to solve it across objects, fields, forms, views, permissions and automation. Each recipe links to a runnable example and the decision record behind it. ---- - -# Solutions — Scenario Cookbook - -The rest of the guides answer **"how does feature X work"** (Field, View, Flow, Permission…). These recipes answer the other question: **"I have business problem Y — what's the recommended way to solve it?"** — and the answer usually cuts across several metadata types at once. - - -**Why this section exists.** The mechanisms are all documented in the [references](/docs/references) and per-type [metadata guides](/docs/guides/metadata). What was missing is the *connective tissue*: which mechanisms to combine for a given goal, why, and what the anti-patterns are. These recipes are also the **few-shot corpus for AI authoring** — an AI that has seen the recipe generates the right shape (ADR-0047 §3.5: "zero examples is why zero AI generations use these features"). - - -## How each recipe is structured - -1. **Scenario** — the business problem in one sentence. -2. **Recommended solution** — the cross-cutting approach (objects + fields + forms + views + permissions as needed). -3. **Why** — the reasoning, linked to the relevant ADR. -4. **Runnable example** — a link into `examples/app-showcase`. -5. **Anti-patterns** — what *not* to do, and why it bites later. - -## Recipes - - - - - - - - - diff --git a/content/docs/guides/solutions/meta.json b/content/docs/guides/solutions/meta.json deleted file mode 100644 index b8114831f5..0000000000 --- a/content/docs/guides/solutions/meta.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "title": "Solutions", - "icon": "Lightbulb", - "pages": [ - "index", - "create-vs-edit-form", - "field-grouping-and-order", - "role-based-interfaces", - "data-automation-interface-access", - "public-data-collection", - "approval-workflow" - ] -} diff --git a/content/docs/index.mdx b/content/docs/index.mdx index cc8a64b07b..d268a1ee87 100644 --- a/content/docs/index.mdx +++ b/content/docs/index.mdx @@ -5,33 +5,35 @@ description: Technical documentation for ObjectStack. # ObjectStack Documentation -ObjectStack is an AI-native business backend protocol for structured, auditable business applications. -These docs cover the protocol, runtime, metadata model, API surface, and implementation guides. - -## Start Here - -- [Quick Start](/docs/getting-started/quick-start): create an ObjectStack app and run the Console locally. -- [What is ObjectStack?](/docs/getting-started): understand the protocol model and runtime layers. -- [Core Concepts](/docs/getting-started/core-concepts): learn the key terms used across the docs. -- [Architecture](/docs/getting-started/architecture): see how ObjectQL, ObjectOS, and ObjectUI fit together. - -## Build - -- [Data Modeling](/docs/guides/data-modeling): define objects, fields, relationships, and validation rules. -- [Business Logic](/docs/guides/business-logic): model workflows, approvals, triggers, hooks, and formulas. -- [Security](/docs/guides/security): configure permissions, sharing rules, RBAC, RLS, and field-level access. -- [API Reference](/docs/guides/api-reference): work with generated REST, GraphQL, realtime, and SDK surfaces. -- [Plugin Development](/docs/guides/plugin-development): build and register runtime plugins. - -## Protocol - -- [ObjectQL](/docs/protocol/objectql): data schemas, queries, filters, indexes, and object contracts. -- [ObjectOS](/docs/protocol/objectos): kernel runtime, plugins, HTTP protocol, capabilities, and configuration. -- [ObjectUI](/docs/protocol/objectui): UI metadata for apps, views, pages, dashboards, and actions. - -## Reference - -- [Schema Reference](/docs/references): generated Zod schema reference for ObjectStack metadata. -- [Cheatsheets](/docs/guides/cheatsheets/quick-reference): quick lookup tables for common protocol decisions. -- [CLI Reference](/docs/getting-started/cli): commands for creating, building, and validating projects. -- [Glossary](/docs/getting-started/glossary): shared vocabulary across ObjectStack docs. +ObjectStack is an AI-native business backend protocol for structured, auditable business applications. You declare your application — data model, logic, permissions, and UI — as metadata, and the platform derives the database, APIs, automation, and interface from that single artifact. + +## Start here + +- [What is ObjectStack?](/docs/getting-started) — the protocol model and runtime layers +- [Quick Start](/docs/getting-started/quick-start) — create an app and run the Console locally +- [Core Concepts](/docs/concepts) — the ideas behind metadata-driven development +- [Architecture](/docs/concepts/architecture) — how ObjectQL, ObjectOS, and ObjectUI fit together + +## Platform modules + +Each module documents one capability in depth — overview first, then guides, with links to the matching protocol spec and schema reference. + + + + + + + + + + + + + +## Protocol & reference + +- [Protocol Spec](/docs/protocol) — the normative ObjectQL / ObjectOS / ObjectUI specifications for implementers +- [Schema Reference](/docs/references) — generated Zod schema reference for every metadata type +- [Quick Reference](/docs/getting-started/quick-reference) — fast lookup tables across all protocols +- [Glossary](/docs/getting-started/glossary) — the shared vocabulary used across these docs +- [Releases](/docs/releases) — release notes and implementation status diff --git a/content/docs/concepts/core/architecture.mdx b/content/docs/kernel/architecture.mdx similarity index 100% rename from content/docs/concepts/core/architecture.mdx rename to content/docs/kernel/architecture.mdx diff --git a/content/docs/concepts/cluster-semantics.mdx b/content/docs/kernel/cluster.mdx similarity index 100% rename from content/docs/concepts/cluster-semantics.mdx rename to content/docs/kernel/cluster.mdx diff --git a/content/docs/guides/contracts/auth-service.mdx b/content/docs/kernel/contracts/auth-service.mdx similarity index 100% rename from content/docs/guides/contracts/auth-service.mdx rename to content/docs/kernel/contracts/auth-service.mdx diff --git a/content/docs/guides/contracts/cache-service.mdx b/content/docs/kernel/contracts/cache-service.mdx similarity index 100% rename from content/docs/guides/contracts/cache-service.mdx rename to content/docs/kernel/contracts/cache-service.mdx diff --git a/content/docs/guides/contracts/data-engine.mdx b/content/docs/kernel/contracts/data-engine.mdx similarity index 100% rename from content/docs/guides/contracts/data-engine.mdx rename to content/docs/kernel/contracts/data-engine.mdx diff --git a/content/docs/guides/contracts/index.mdx b/content/docs/kernel/contracts/index.mdx similarity index 100% rename from content/docs/guides/contracts/index.mdx rename to content/docs/kernel/contracts/index.mdx diff --git a/content/docs/guides/contracts/meta.json b/content/docs/kernel/contracts/meta.json similarity index 100% rename from content/docs/guides/contracts/meta.json rename to content/docs/kernel/contracts/meta.json diff --git a/content/docs/guides/contracts/metadata-service.mdx b/content/docs/kernel/contracts/metadata-service.mdx similarity index 100% rename from content/docs/guides/contracts/metadata-service.mdx rename to content/docs/kernel/contracts/metadata-service.mdx diff --git a/content/docs/guides/contracts/storage-service.mdx b/content/docs/kernel/contracts/storage-service.mdx similarity index 100% rename from content/docs/guides/contracts/storage-service.mdx rename to content/docs/kernel/contracts/storage-service.mdx diff --git a/content/docs/concepts/core/events.mdx b/content/docs/kernel/events.mdx similarity index 100% rename from content/docs/concepts/core/events.mdx rename to content/docs/kernel/events.mdx diff --git a/content/docs/kernel/index.mdx b/content/docs/kernel/index.mdx new file mode 100644 index 0000000000..0e6d5f807d --- /dev/null +++ b/content/docs/kernel/index.mdx @@ -0,0 +1,34 @@ +--- +title: Kernel & Services +description: The ObjectKernel runtime — plugin host, event bus, service registry, and the services.* APIs your hooks and plugins call. +--- + +# 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 APIs you call (`services.data`, `services.email`, `services.queue`, …) and the contracts they implement are documented. + +## How it fits together + +- The **ObjectKernel** boots through a strict lifecycle and exposes a **service registry**; everything else — data engine, auth, storage — is a service registered by a plugin. +- **Events & hooks** are the kernel-level extension points plugins use to react to system activity. +- **Runtime services** (`services.*`) are the stable, versioned API surface exposed to hook and action bodies. +- **Service contracts** (`IDataEngine`, `IAuthService`, `ICacheService`, `IMetadataService`, `IStorageService`) define what any implementation must provide, so services are swappable. +- **Cluster semantics** describe how the runtime behaves when scaled beyond a single node. + +## What's in this module + + + + + + + + + + + +## Related + +- **Spec:** [System Lifecycle](/docs/protocol/objectos/lifecycle), [Runtime Capabilities](/docs/protocol/objectos/runtime-capabilities), [Metadata Service](/docs/protocol/objectos/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/kernel/meta.json b/content/docs/kernel/meta.json new file mode 100644 index 0000000000..918f4d08f6 --- /dev/null +++ b/content/docs/kernel/meta.json @@ -0,0 +1,14 @@ +{ + "title": "Kernel & Services", + "icon": "Cpu", + "pages": [ + "index", + "architecture", + "events", + "services", + "services-checklist", + "runtime-services", + "contracts", + "cluster" + ] +} diff --git a/content/docs/guides/runtime-services/audit-service.mdx b/content/docs/kernel/runtime-services/audit-service.mdx similarity index 100% rename from content/docs/guides/runtime-services/audit-service.mdx rename to content/docs/kernel/runtime-services/audit-service.mdx diff --git a/content/docs/guides/runtime-services/data-service.mdx b/content/docs/kernel/runtime-services/data-service.mdx similarity index 100% rename from content/docs/guides/runtime-services/data-service.mdx rename to content/docs/kernel/runtime-services/data-service.mdx diff --git a/content/docs/guides/runtime-services/email-service.mdx b/content/docs/kernel/runtime-services/email-service.mdx similarity index 100% rename from content/docs/guides/runtime-services/email-service.mdx rename to content/docs/kernel/runtime-services/email-service.mdx diff --git a/content/docs/guides/runtime-services/examples.mdx b/content/docs/kernel/runtime-services/examples.mdx similarity index 100% rename from content/docs/guides/runtime-services/examples.mdx rename to content/docs/kernel/runtime-services/examples.mdx diff --git a/content/docs/guides/runtime-services/index.mdx b/content/docs/kernel/runtime-services/index.mdx similarity index 100% rename from content/docs/guides/runtime-services/index.mdx rename to content/docs/kernel/runtime-services/index.mdx diff --git a/content/docs/guides/runtime-services/meta.json b/content/docs/kernel/runtime-services/meta.json similarity index 100% rename from content/docs/guides/runtime-services/meta.json rename to content/docs/kernel/runtime-services/meta.json diff --git a/content/docs/guides/runtime-services/queue-service.mdx b/content/docs/kernel/runtime-services/queue-service.mdx similarity index 100% rename from content/docs/guides/runtime-services/queue-service.mdx rename to content/docs/kernel/runtime-services/queue-service.mdx diff --git a/content/docs/guides/runtime-services/settings-service.mdx b/content/docs/kernel/runtime-services/settings-service.mdx similarity index 100% rename from content/docs/guides/runtime-services/settings-service.mdx rename to content/docs/kernel/runtime-services/settings-service.mdx diff --git a/content/docs/guides/runtime-services/sharing-service.mdx b/content/docs/kernel/runtime-services/sharing-service.mdx similarity index 100% rename from content/docs/guides/runtime-services/sharing-service.mdx rename to content/docs/kernel/runtime-services/sharing-service.mdx diff --git a/content/docs/guides/runtime-services/storage-service.mdx b/content/docs/kernel/runtime-services/storage-service.mdx similarity index 100% rename from content/docs/guides/runtime-services/storage-service.mdx rename to content/docs/kernel/runtime-services/storage-service.mdx diff --git a/content/docs/guides/runtime-services/versioning.mdx b/content/docs/kernel/runtime-services/versioning.mdx similarity index 100% rename from content/docs/guides/runtime-services/versioning.mdx rename to content/docs/kernel/runtime-services/versioning.mdx diff --git a/content/docs/guides/kernel-services.mdx b/content/docs/kernel/services-checklist.mdx similarity index 100% rename from content/docs/guides/kernel-services.mdx rename to content/docs/kernel/services-checklist.mdx diff --git a/content/docs/concepts/core/services.mdx b/content/docs/kernel/services.mdx similarity index 100% rename from content/docs/concepts/core/services.mdx rename to content/docs/kernel/services.mdx diff --git a/content/docs/meta.json b/content/docs/meta.json index 040a62b685..685febfa3b 100644 --- a/content/docs/meta.json +++ b/content/docs/meta.json @@ -3,9 +3,17 @@ "pages": [ "getting-started", "concepts", - "guides", - "references", + "data-modeling", + "automation", + "permissions", + "ui", + "api", + "ai", + "plugins", + "kernel", + "deployment", "protocol", + "references", "releases" ] } diff --git a/content/docs/guides/solutions/data-automation-interface-access.mdx b/content/docs/permissions/access-recipes.mdx similarity index 95% rename from content/docs/guides/solutions/data-automation-interface-access.mdx rename to content/docs/permissions/access-recipes.mdx index 5793c24049..1f88eb83e8 100644 --- a/content/docs/guides/solutions/data-automation-interface-access.mdx +++ b/content/docs/permissions/access-recipes.mdx @@ -45,7 +45,7 @@ definePermissionSet({ Two separate questions: -1. **Who can configure it?** Editing flows/automations needs `manage_metadata` (typically Studio users). Don't expose automation config to end users — see [role-based interfaces](/docs/guides/solutions/role-based-interfaces). +1. **Who can configure it?** Editing flows/automations needs `manage_metadata` (typically Studio users). Don't expose automation config to end users — see [role-based interfaces](/docs/ui/role-based-interfaces). 2. **As whom does it run?** A flow's `runAs` (ADR-0049): - `runAs: 'user'` (default) — runs as the triggering user; CRUD nodes respect that user's RLS. **Safer default.** - `runAs: 'system'` — elevated, bypasses RLS. Make elevation *explicit*, and surface it in the UI as "runs as system". @@ -74,5 +74,5 @@ Keeping capability, assignment and requirement decoupled means resources stay st ## See also - Decision records: **ADR-0066** (unified authorization), **ADR-0057** (access depth), **ADR-0049** (`runAs`). -- Cheatsheet: [Permissions matrix](/docs/guides/cheatsheets/permissions-matrix); guide: [Security](/docs/guides/security). +- Cheatsheet: [Permissions matrix](/docs/permissions/permissions-matrix); guide: [Security](/docs/permissions). - Reference: [Permission](/docs/references/security/permission), [RLS](/docs/references/security/rls), [Sharing](/docs/references/security/sharing). diff --git a/content/docs/guides/authentication.mdx b/content/docs/permissions/authentication.mdx similarity index 98% rename from content/docs/guides/authentication.mdx rename to content/docs/permissions/authentication.mdx index 2ee27ec237..5248236f42 100644 --- a/content/docs/guides/authentication.mdx +++ b/content/docs/permissions/authentication.mdx @@ -1,5 +1,5 @@ --- -title: "Authentication Guide" +title: Authentication description: "Complete guide to implementing authentication in ObjectStack using plugin-auth with Better-Auth" --- @@ -45,7 +45,7 @@ The `@objectstack/plugin-auth` package provides enterprise-grade authentication - ✅ **Enforced MFA** - Org-wide `require_mfa` with a configurable grace period; the session is gated from data access until the user enrolls - ✅ **Session controls** - Idle timeout, absolute lifetime cap, and concurrent-session limit per user - ✅ **IP allowlist** - Restrict authenticated access to CIDR ranges -- ✅ **Enterprise SSO** - Admin-managed OIDC and SAML 2.0 trust list (see [Social & Enterprise SSO](/docs/guides/auth-sso)) +- ✅ **Enterprise SSO** - Admin-managed OIDC and SAML 2.0 trust list (see [Social & Enterprise SSO](/docs/permissions/sso)) See [Enterprise Authentication Hardening](#enterprise-authentication-hardening-adr-0069) for the full settings reference. @@ -760,9 +760,9 @@ This ensures that registration and sign-in flows do not return 404 errors in MSW ## Next Steps -- See [Security Guide](/docs/guides/security) for authorization and permissions -- See [Client SDK Guide](/docs/guides/client-sdk) for client-side integration -- See [API Reference](/docs/guides/api-reference) for complete API documentation +- See [Security Guide](/docs/permissions) for authorization and permissions +- See [Client SDK Guide](/docs/api/client-sdk) for client-side integration +- See [API Reference](/docs/api) for complete API documentation - Visit [Better-Auth Documentation](https://www.better-auth.com/docs) for advanced features --- diff --git a/content/docs/concepts/authorization.mdx b/content/docs/permissions/authorization.mdx similarity index 100% rename from content/docs/concepts/authorization.mdx rename to content/docs/permissions/authorization.mdx diff --git a/content/docs/permissions/field-level-security.mdx b/content/docs/permissions/field-level-security.mdx new file mode 100644 index 0000000000..44a422b002 --- /dev/null +++ b/content/docs/permissions/field-level-security.mdx @@ -0,0 +1,93 @@ +--- +title: "Field-Level Security" +description: "Control visibility and editability of specific fields — readable/editable rules, hidden vs. read-only semantics, and fail-closed server-side enforcement." +--- + +# Field-Level Security + +Control visibility and editability of specific fields. + +## Field Permissions in Profiles + +Field permissions are keyed `.` and use `readable` / `editable`: + +```typescript +fields: { + // Read-only: visible but not editable + 'account.annual_revenue': { readable: true, editable: false }, + 'account.description': { readable: true, editable: true }, + // Hidden: not visible at all + 'account.ssn': { readable: false, editable: false }, + 'opportunity.amount': { readable: true, editable: true }, + 'opportunity.probability': { readable: true, editable: false }, +} +``` + +## Hidden vs. Read-Only + +```typescript +// Hidden: Field not visible at all +{ readable: false, editable: false } + +// Read-Only: Field visible but not editable +{ readable: true, editable: false } + +// Editable: Field visible and editable +{ readable: true, editable: true } +``` + +## Server-side enforcement (fail-closed) + +The client-side ObjectForm / inline grid hides non-editable fields from +the UI — but that is a **UX layer only**. The SecurityPlugin middleware +enforces field-level write rules on the server, regardless of how the +request arrived (REST, GraphQL, raw ObjectQL call). + +**On read** — `find` / `findOne` results have non-readable fields +stripped from every record before the response leaves the engine. + +**On write** — `insert` / `update` requests are checked **before** the +operation reaches the driver. If the payload contains any field the +caller is not permitted to edit, the engine throws +`PermissionDeniedError` (mapped to HTTP 403) with the offending field +names in `details.forbiddenFields`: + +```json +{ + "error": { + "code": "PERMISSION_DENIED", + "message": "[Security] Field write denied: not permitted to edit [salary, ssn] on 'employee'", + "details": { + "operation": "insert", + "object": "employee", + "forbiddenFields": ["salary", "ssn"] + } + } +} +``` + +**Why throw instead of silently stripping?** Silent strip hides the +security boundary from honest clients (their update "doesn't save" and +they cannot tell why) AND gives a probing client no signal that the +field exists. Throwing makes the boundary observable in both directions +— legitimate UIs get an actionable error to fix; probing clients learn +nothing they could not already infer. + +**Allow-list semantics.** Fields without an explicit rule pass through +untouched. Permission sets only constrain fields they explicitly +enumerate. + +**Bulk inserts.** Arrays are checked row-by-row; a single offending +field in any row rejects the whole batch atomically. + +**System operations.** `ExecutionContext { isSystem: true }` bypasses +the check entirely — used for migrations, seed loading, and audit log +writes. + +--- + +## See also + +- [Permissions & Identity overview](/docs/permissions) +- [Profiles](/docs/permissions/profiles) +- [Permission Sets](/docs/permissions/permission-sets) diff --git a/content/docs/permissions/index.mdx b/content/docs/permissions/index.mdx new file mode 100644 index 0000000000..6fab4973bf --- /dev/null +++ b/content/docs/permissions/index.mdx @@ -0,0 +1,219 @@ +--- +title: "Permissions & Identity" +description: "Authentication, authorization, and record- and field-level access control in ObjectStack — a cross-protocol capability enforced by the ObjectOS runtime and declared as ObjectQL security metadata." +--- + +# Permissions & Identity + +This module covers authentication, authorization, and record- and field-level +access control. It is a cross-protocol capability: enforced by the ObjectOS +runtime, declared as ObjectQL security metadata. + +> **Implementation status — Phase-1 RBAC is live.** REST → ObjectQL now propagates a populated `ExecutionContext` (userId, tenantId, roles, permissions) into the SecurityPlugin middleware, so CRUD / FLS / RLS checks actually fire on every authenticated request. The default `member_default` permission set ships a wildcard RLS rule `organization_id == current_user.organization_id` plus explicit per-object overrides `sys_organization_self` (`id == current_user.organization_id`) and `sys_user_self` (`id == current_user.id`) for the two global tables that lack an `organization_id` column. RLS expressions, the physical column, and `RLSUserContext.organization_id` all use the same canonical name — there is no `tenantField` rewrite indirection (schemas with a different physical tenant column should fork the defaults). The legacy `objectql.registerTenantMiddleware` has been removed; SecurityPlugin is the sole authority for tenant isolation. Analytics also reuses the same read scope: `@objectstack/service-analytics` auto-bridges to `security.getReadFilter(object, context)` when the security service is registered, so dataset-bound dashboards/reports do not bypass RLS. End-to-end verified on `pnpm dev:crm` across `sys_organization`, `sys_member`, `sys_user`, `sys_user_permission_set`, `sys_role_permission_set`. **Anonymous traffic is denied by default** (the ADR-0056 D2 default-deny flip landed: `requireAuth` defaults to `true`); an explicit `requireAuth: false` opt-out logs a boot-time warning, and public forms self-authorize via a declaration-derived `publicFormGrant` (ADR-0056 Option A — see [Public Forms](/docs/ui/forms)). Organization-Wide Defaults (`private` / `public_read` / `public_read_write` / `controlled_by_parent`) and Sharing Rules (owner + criteria, with `role_and_subordinates` hierarchy widening) are live and dogfood-proven (ADR-0056); the Studio RLS visual editor, per-user×org permission cache, and audit UI for denied access are queued. See `CHANGELOG.md` and `concepts/implementation-status.mdx` for the latest matrix. + +## What's in this module + +- [Authentication](/docs/permissions/authentication) +- [Social & Enterprise SSO](/docs/permissions/sso) +- [Authorization Architecture](/docs/permissions/authorization) +- [Profiles](/docs/permissions/profiles) +- [Permission Sets](/docs/permissions/permission-sets) +- [Role Hierarchy](/docs/permissions/roles) +- [Sharing Rules](/docs/permissions/sharing-rules) +- [Field-Level Security](/docs/permissions/field-level-security) +- [Permission Metadata](/docs/permissions/permission-metadata) +- [Security Permissions Matrix](/docs/permissions/permissions-matrix) +- [Access Recipes](/docs/permissions/access-recipes) + +Spec: [Security & Access Control](/docs/protocol/objectql/security) · +Schema reference: [Security](/docs/references/security), [Identity](/docs/references/identity) + +--- + +## Security Architecture + +> **Authentication is the first layer.** This guide covers *authorization* — +> who can see and do what once signed in (RBAC, RLS, FLS, sharing). Harden +> *authentication* first — password policy, enforced MFA, account lockout, +> session controls, and IP allowlist — in +> [Enterprise Authentication Hardening](/docs/permissions/authentication#enterprise-authentication-hardening-adr-0069). + +ObjectStack implements a multi-layered security model: + +``` +┌─────────────────────────────────────┐ +│ Application Visibility │ ← Which apps can users access? +├─────────────────────────────────────┤ +│ Object Permissions │ ← CRUD on objects +├─────────────────────────────────────┤ +│ Record-Level Security │ ← Which records can be accessed? +│ - Organization-Wide Defaults │ +│ - Role Hierarchy │ +│ - Sharing Rules │ +│ - Manual Sharing │ +├─────────────────────────────────────┤ +│ Field-Level Security │ ← Read/Write specific fields +└─────────────────────────────────────┘ +``` + +### Security Layers + +1. **Object Permissions**: Control create, read, update, delete on entire objects +2. **Record-Level Security**: Control access to specific records +3. **Field-Level Security**: Control visibility and editability of fields +4. **Row-Level Security**: Control access based on data values + +--- + +## Best Practices + +### 1. Profile Design + +✅ **DO:** +- Create minimal profiles (start restrictive, extend with permission sets) +- Use descriptive names +- Document the purpose of each profile +- Assign one profile per user + +❌ **DON'T:** +- Create too many profiles +- Give excessive permissions "just in case" +- Mix unrelated permissions in one profile + +### 2. Permission Sets + +✅ **DO:** +- Use for temporary or special access +- Group related permissions +- Name clearly (e.g., "Advanced Reporting", "Bulk Data Access") +- Remove when no longer needed + +❌ **DON'T:** +- Use as a replacement for profiles +- Grant system-wide permissions unnecessarily + +### 3. Role Hierarchy + +✅ **DO:** +- Mirror your organizational structure +- Keep hierarchies simple +- Document reporting relationships +- Review regularly + +❌ **DON'T:** +- Create overly deep hierarchies +- Mix different org structures +- Grant too much upward access + +### 4. Sharing Rules + +✅ **DO:** +- Start with most restrictive OWD +- Use sharing rules to open up access +- Document business justification +- Test thoroughly + +❌ **DON'T:** +- Set OWD to Public unless necessary +- Create redundant sharing rules +- Grant more access than needed + +### 5. Field-Level Security + +✅ **DO:** +- Protect sensitive data (SSN, salary, etc.) +- Use read-only for calculated fields +- Document security classifications +- Audit regularly + +❌ **DON'T:** +- Hide required fields +- Restrict access unnecessarily +- Forget about API access + +--- + +## Security Checklist + +### Initial Setup + +- [ ] Harden authentication (password policy, enforced MFA, lockout, session controls, IP allowlist) — see [Authentication Hardening](/docs/permissions/authentication#enterprise-authentication-hardening-adr-0069) +- [ ] Define user roles and hierarchies +- [ ] Create profiles for each role +- [ ] Set organization-wide defaults +- [ ] Configure field-level security +- [ ] Create sharing rules + +### Ongoing Maintenance + +- [ ] Review user access quarterly +- [ ] Audit permission changes +- [ ] Remove inactive users promptly +- [ ] Update sharing rules as needed +- [ ] Monitor security health checks + +### Compliance + +- [ ] Document security model +- [ ] Maintain access request process +- [ ] Log security changes +- [ ] Conduct security reviews +- [ ] Train users on security policies + +--- + +## Real-World Example + +Complete security setup for a sales team: + +```typescript +// 1. Organization-Wide Defaults (one OWDModel value per object) +const OrganizationDefaults = { + account: 'private', + opportunity: 'private', + contact: 'controlled_by_parent', +}; + +// 2. Role Hierarchy (flat roles linked by `parent`) +const roles = [ + { name: 'sales_vp', label: 'Sales VP' }, + { name: 'sales_manager', label: 'Sales Manager', parent: 'sales_vp' }, + { name: 'sales_rep', label: 'Sales Rep', parent: 'sales_manager' }, +]; + +// 3. Profile (a PermissionSet with isProfile: true) +const SalesRepProfile = { + name: 'sales_rep', + isProfile: true, + objects: { + account: { allowCreate: true, allowRead: true, allowEdit: true, allowDelete: false }, + opportunity: { allowCreate: true, allowRead: true, allowEdit: true, allowDelete: false }, + }, + fields: { + 'account.annual_revenue': { readable: true, editable: false }, // Read-only + }, +}; + +// 4. Sharing Rule (criteria type with a CEL condition) +const AccountSharingRule = { + name: 'high_value_accounts', + type: 'criteria', + object: 'account', + // Share high-value accounts with sales reps + condition: P`record.annual_revenue >= 1000000`, + sharedWith: { type: 'role', value: 'sales_rep' }, + accessLevel: 'read', +}; + +// 5. Permission Set (systemPermissions is a string array) +const AdvancedReportingPermissionSet = { + name: 'advanced_reporting', + objects: {}, + // For sales analysts + systemPermissions: ['run_reports', 'export_reports', 'view_all_data'], +}; +``` + +--- + +**Next:** [Automation →](/docs/automation) diff --git a/content/docs/permissions/meta.json b/content/docs/permissions/meta.json new file mode 100644 index 0000000000..d9eae56249 --- /dev/null +++ b/content/docs/permissions/meta.json @@ -0,0 +1,18 @@ +{ + "title": "Permissions & Identity", + "icon": "Shield", + "pages": [ + "index", + "authentication", + "sso", + "authorization", + "profiles", + "permission-sets", + "roles", + "sharing-rules", + "field-level-security", + "permission-metadata", + "permissions-matrix", + "access-recipes" + ] +} diff --git a/content/docs/guides/metadata/permission.mdx b/content/docs/permissions/permission-metadata.mdx similarity index 96% rename from content/docs/guides/metadata/permission.mdx rename to content/docs/permissions/permission-metadata.mdx index c602b86e22..674661ce11 100644 --- a/content/docs/guides/metadata/permission.mdx +++ b/content/docs/permissions/permission-metadata.mdx @@ -284,6 +284,6 @@ const salesManagerPermission = { ## Related -- [Object Metadata](./object) — Objects that permissions control access to -- [Field Metadata](./field) — Fields that field permissions control -- [App Metadata](./app) — Apps that tab permissions control visibility for +- [Object Metadata](/docs/data-modeling/objects) — Objects that permissions control access to +- [Field Metadata](/docs/data-modeling/fields) — Fields that field permissions control +- [App Metadata](/docs/ui/apps) — Apps that tab permissions control visibility for diff --git a/content/docs/permissions/permission-sets.mdx b/content/docs/permissions/permission-sets.mdx new file mode 100644 index 0000000000..266521b290 --- /dev/null +++ b/content/docs/permissions/permission-sets.mdx @@ -0,0 +1,132 @@ +--- +title: "Permission Sets" +description: "Extend profile permissions without changing the profile — custom sets, the four built-in permission sets, auto-granting for org admins, and how grants are assigned as data rows." +--- + +# Permission Sets + +Permission sets extend profile permissions without changing the profile. + +```typescript +import { definePermissionSet } from '@objectstack/spec/security'; + +export const AdvancedReportingPermissionSet = definePermissionSet({ + name: 'advanced_reporting', + label: 'Advanced Reporting', + + objects: { + opportunity: { + viewAllRecords: true, // Override profile restriction + }, + account: { + viewAllRecords: true, + }, + }, + + fields: { + 'opportunity.amount': { readable: true }, + 'opportunity.probability': { readable: true }, + }, + + // System permissions are a flat array of capability strings + systemPermissions: ['run_reports', 'export_reports', 'create_dashboards'], +}); + +export const BulkDataPermissionSet = definePermissionSet({ + name: 'bulk_data_access', + label: 'Bulk Data Access', + + objects: {}, + systemPermissions: ['bulk_api', 'view_all_data'], +}); +``` + +## Built-in Permission Sets + +The framework ships four canonical permission sets that are auto-seeded on +boot by `plugin-security` (see +`packages/plugins/plugin-security/src/objects/default-permission-sets.ts`). Use +these as the baseline for any new org — tier custom sets on top rather +than redefining the basics. + +| Name | Scope | What it unlocks | Notes | +|:--|:--|:--|:--| +| `admin_full_access` | Platform (no RLS) | All objects, all system permissions, Studio + Setup, cross-org reads | Reserved for platform operators. Auto-granted to the bootstrap admin (`bootstrapPlatformAdmin`) — the **first registered human**. The non-loginable seed-data identity `usr_system` (role `system`, provisioned before the first sign-up to own seeded rows) is deliberately skipped, so the real admin wins the promotion. | +| `organization_admin` | Per-org (`tenant_isolation` RLS, only active when `@objectstack/plugin-org-scoping` is loaded) | Wildcard CRUD inside the org, `manage_org_users`, Setup app shell (only org-scoped entries visible), invite members, manage roles assignment | **Read-only** on `sys_role`, `sys_permission_set`, `sys_role_permission_set`, `sys_user_permission_set`, `sys_user_role` to prevent self-elevation. Does **not** see Studio. | +| `member_default` | Per-org | Standard end-user CRUD on org records; **writes are owner-scoped** | Default profile for invited members. | +| `viewer_readonly` | Per-org | Read access only | For auditors / read-only stakeholders. | + +> **Owner-scoped writes.** `member_default` grants read/create on org records but +> restricts **edit and delete to the records the user created** — via the +> `owner_only_writes` / `owner_only_deletes` RLS policies, keyed on `created_by` +> (the ownership column the engine stamps on every row). These are enforced on +> single-id `update`/`delete` by a **pre-image authorization check**: before the +> mutation the middleware re-reads the target row through the write-operation RLS +> filter, and a member attempting to modify another user's record gets `403`. +> A permission set with `modifyAllRecords` (or no RLS, e.g. `admin_full_access`) +> bypasses this. An object that opts out of audit fields (`systemFields.audit: +> false`, no `created_by`) fails **closed** for member writes — grant +> `modifyAllRecords` or a per-object policy, or model transferable ownership with +> a dedicated owner field + custom policy. + +> **Single-org vs. multi-org runtimes.** The wildcard `tenant_isolation` +> RLS row above only takes effect when `@objectstack/plugin-org-scoping` +> is registered (typically via `OS_MULTI_ORG_ENABLED=true`). In single-org +> mode `plugin-security` detects the missing `org-scoping` service and +> strips the wildcard policy so reads / writes aren't accidentally +> filtered by an unset `current_user.organization_id`. See the +> [Org-Scoping Plugin README](https://github.com/objectstack-ai/framework/blob/main/packages/plugins/plugin-org-scoping/README.md) +> for boot order and per-org seed-replay details. + +### Auto-grant for organization admins + +Any user whose `sys_member.role` is `owner`, `admin`, or comma-set +`"owner,admin"` automatically receives an org-scoped grant of +`organization_admin` (one `sys_user_permission_set` row per `(user, org)` +pair). The grant is reconciled by a lifecycle hook in `plugin-security` +on every `sys_member` insert / update / delete, and a `kernel:ready` +backfill sweep cleans up orphans on boot. Demoting a member to `member` +revokes the grant in the same transaction; you do not manage these rows +by hand. + +### Setup app gating + +Setup nav items and the corresponding global settings manifests +(`ai`, `knowledge`, `mail`, `storage`) require the new +`manage_platform_settings` system permission, which is granted **only** to +`admin_full_access`. `organization_admin` sees the Setup shell — +Apps, People & Organization, Roles (read-only) — but not platform-wide +configuration. Tenant-scoped settings (`branding`, `feature_flags`) +remain gated by `setup.access` so org admins can manage them. + +## Assigning Permission Sets + +Permission-set grants are plain data rows, not helper-function calls. Assign a +set to a user by inserting a `sys_user_permission_set` row, or to a role by +inserting a `sys_role_permission_set` row: + +```typescript +// Grant a permission set to a single user +await objectql.object('sys_user_permission_set').insert({ + user_id: 'user123', + permission_set: 'advanced_reporting', +}); + +// Grant a permission set to everyone in a role +await objectql.object('sys_role_permission_set').insert({ + role: 'data_analysts', + permission_set: 'bulk_data_access', +}); +``` + +Org-admin grants are reconciled automatically by a `plugin-security` lifecycle +hook (see [Auto-grant for organization admins](#auto-grant-for-organization-admins)) +— you do not insert those rows by hand. + +--- + +## See also + +- [Permissions & Identity overview](/docs/permissions) +- [Profiles](/docs/permissions/profiles) +- [Security Permissions Matrix](/docs/permissions/permissions-matrix) diff --git a/content/docs/guides/cheatsheets/permissions-matrix.mdx b/content/docs/permissions/permissions-matrix.mdx similarity index 100% rename from content/docs/guides/cheatsheets/permissions-matrix.mdx rename to content/docs/permissions/permissions-matrix.mdx diff --git a/content/docs/permissions/profiles.mdx b/content/docs/permissions/profiles.mdx new file mode 100644 index 0000000000..23398c5c63 --- /dev/null +++ b/content/docs/permissions/profiles.mdx @@ -0,0 +1,198 @@ +--- +title: "Profiles" +description: "Profiles define a user's baseline permissions — object CRUD grants, field-level security, tab visibility, access scopes, capabilities, and built-in identity roles." +--- + +# Profiles + +Profiles define a user's baseline permissions. + +## Profile Structure + +A profile is modelled as a `PermissionSet` with `isProfile: true` (see +`packages/spec/src/security/permission.zod.ts`). There is no distinct +`Profile` type — author it as a `*.profile.ts` metadata entry validated by +`PermissionSetSchema`. + +```typescript +import { definePermissionSet } from '@objectstack/spec/security'; + +export const SalesRepProfile = definePermissionSet({ + name: 'sales_rep', + label: 'Sales Representative', + isProfile: true, + + // Object-level permissions: -> permissions + objects: { + account: { + allowCreate: true, + allowRead: true, + allowEdit: true, + allowDelete: false, + viewAllRecords: false, // See all records regardless of owner + modifyAllRecords: false, // Edit all records regardless of owner + }, + opportunity: { + allowCreate: true, + allowRead: true, + allowEdit: true, + allowDelete: false, + viewAllRecords: false, + modifyAllRecords: false, + }, + }, + + // Field-level security: . -> permissions + fields: { + 'account.annual_revenue': { readable: true, editable: false }, + 'account.description': { readable: true, editable: true }, + }, + + // Tab/app visibility: -> visibility + tabPermissions: { + app_crm: 'default_on', // Shown by default + app_admin: 'hidden', // Not visible + app_sales: 'visible', // Available + }, +}); +``` + +## Object Permission Levels + +| Permission | Description | +|------------|-------------| +| `allowCreate` | Create new records | +| `allowRead` | View records they own or have access to | +| `allowEdit` | Edit records they own or have access to | +| `allowDelete` | Delete records they own or have access to | +| `allowTransfer` | Change record ownership | +| `allowRestore` | Restore soft-deleted records from trash (undelete) | +| `allowPurge` | Permanently delete records (hard delete / GDPR) | +| `viewAllRecords` | View ALL records regardless of ownership | +| `modifyAllRecords` | Edit ALL records regardless of ownership | + +## Access depth — `readScope` / `writeScope` (ADR-0057 D1) + +Beyond the boolean grants above, an owner-scoped object grant can carry a +**`readScope` / `writeScope`** that widens the owner-match *declaratively* — the +ERP "see my own / my reports / my unit / my unit and below / the whole org" axis, +without hand-writing one RLS policy per object: + +| Scope | Owner-match widens to | +|------------|-------------| +| `own` | the caller (baseline; unset = this) | +| `own_and_reports` | the caller + their `sys_user.manager_id` report chain | +| `unit` | owners in the caller's business unit (`sys_business_unit`) | +| `unit_and_below` | the caller's BU + all descendant BUs (BFS) | +| `org` | the whole tenant (≈ `viewAllRecords` / `modifyAllRecords`) | + +```typescript +objects: { + account: { allowRead: true, allowEdit: true, readScope: 'unit_and_below', writeScope: 'own' }, +} +``` + +It resolves to an `owner_id IN (…)` set at request time and AND-injects alongside +RLS (no compiler change; ADR-0055). Sharing rules still widen on top. + +> **Open-core boundary (ADR-0016).** `own` and `org` are open-source. The +> hierarchy-relative scopes (`own_and_reports` / `unit` / `unit_and_below`) require +> the paid `@objectstack/security-enterprise` plugin (BU-subtree + manager-chain +> resolver); without it they **fail closed to `own`** (never fail-open), and +> `defineStack` errors if a grant uses one without `requires: ['hierarchy-security']`. + +## Capabilities & secure-by-default object access (ADR-0066) + +Beyond CRUD grants and scope depth, two newer gates compose with the model above: + +- **Capabilities** are first-class records in the `sys_capability` registry (ADR-0066 D1) — maintainable named privileges such as `manage_metadata`, `manage_users`, `manage_org_users`, `manage_platform_settings`, `setup.access`, and `studio.access`. Grant them through permission sets like any other privilege. +- **Object access posture** — an object may declare `access: { default: 'public' | 'private' }` (ADR-0066 D2). `public` (the default) preserves allow-by-default exposure; `private` makes the object **secure-by-default** (no access unless explicitly granted). +- **Object-level `requiredPermissions`** (ADR-0066 D3) — a string array of capabilities that gate the object as an **AND** alongside CRUD grants (mirrors `App.requiredPermissions`): a user must hold every listed capability *and* the relevant CRUD grant. + +## Built-in identity roles (ADR-0068) + +`current_user.roles` is a **string array** — the only canonical role field (there is no singular `current_user.role`). Four role names are framework-seeded into `sys_role`: + +| Role | Meaning | +|:---|:---| +| `platform_admin` | Platform operator (SaaS admin) — not a tenant role | +| `org_owner` | Organization owner (`sys_member.role = owner`) | +| `org_admin` | Organization administrator (`sys_member.role = admin`) | +| `org_member` | Organization member (`sys_member.role = member`) | + +Test membership in RLS/CEL with `'org_admin' in current_user.roles` or `current_user.roles.exists(r, r == 'sales_manager')`. `current_user.isPlatformAdmin` is a derived, deprecated alias of `'platform_admin' in current_user.roles`. + +## Standard Profiles + +### Sales Representative + +```typescript +import { definePermissionSet } from '@objectstack/spec/security'; + +export const SalesRepProfile = definePermissionSet({ + name: 'sales_rep', + isProfile: true, + objects: { + lead: { allowCreate: true, allowRead: true, allowEdit: true, allowDelete: false }, + account: { allowCreate: true, allowRead: true, allowEdit: true, allowDelete: false }, + contact: { allowCreate: true, allowRead: true, allowEdit: true, allowDelete: false }, + opportunity: { allowCreate: true, allowRead: true, allowEdit: true, allowDelete: false }, + quote: { allowCreate: true, allowRead: true, allowEdit: true, allowDelete: false }, + product: { allowCreate: false, allowRead: true, allowEdit: false, allowDelete: false }, + }, + fields: { + 'account.annual_revenue': { readable: true, editable: false }, // Read-only + }, +}); +``` + +### Sales Manager + +```typescript +import { definePermissionSet } from '@objectstack/spec/security'; + +export const SalesManagerProfile = definePermissionSet({ + name: 'sales_manager', + isProfile: true, + objects: { + lead: { + allowCreate: true, allowRead: true, allowEdit: true, allowDelete: true, + viewAllRecords: true, modifyAllRecords: true + }, + account: { + allowCreate: true, allowRead: true, allowEdit: true, allowDelete: true, + viewAllRecords: true, modifyAllRecords: true + }, + // ... full access to sales objects + }, +}); +``` + +### Service Agent + +```typescript +import { definePermissionSet } from '@objectstack/spec/security'; + +export const ServiceAgentProfile = definePermissionSet({ + name: 'service_agent', + isProfile: true, + objects: { + case: { allowCreate: true, allowRead: true, allowEdit: true, allowDelete: false }, + task: { allowCreate: true, allowRead: true, allowEdit: true, allowDelete: true }, + account: { allowCreate: false, allowRead: true, allowEdit: false, allowDelete: false }, + contact: { allowCreate: false, allowRead: true, allowEdit: true, allowDelete: false }, + }, + fields: { + 'case.is_sla_violated': { readable: true, editable: false }, + 'case.resolution_time_hours': { readable: true, editable: false }, + }, +}); +``` + +--- + +## See also + +- [Permissions & Identity overview](/docs/permissions) +- [Permission Sets](/docs/permissions/permission-sets) +- [Role Hierarchy](/docs/permissions/roles) diff --git a/content/docs/permissions/roles.mdx b/content/docs/permissions/roles.mdx new file mode 100644 index 0000000000..fb79ea1ba1 --- /dev/null +++ b/content/docs/permissions/roles.mdx @@ -0,0 +1,59 @@ +--- +title: "Role Hierarchy" +description: "Roles control record-level access through a hierarchy derived from each role's parent link — access is granted upward to managers over their subordinates' records." +--- + +# Role Hierarchy + +Roles control record-level access through a hierarchy. + +The hierarchy is derived from the `parent` link on each role — there is no +`RoleHierarchy` container schema. Author roles as individual `*.role.ts` +entries (each matching `RoleSchema`), using `parent` to point at the role they +report to: + +```typescript +import type { Role } from '@objectstack/spec/identity'; + +export const roles: Role[] = [ + // Top level + { name: 'executive', label: 'Executive' }, + + // Sales hierarchy + { name: 'sales_director', label: 'Sales Director', parent: 'executive' }, + { name: 'sales_manager', label: 'Sales Manager', parent: 'sales_director' }, + { name: 'sales_rep', label: 'Sales Representative', parent: 'sales_manager' }, + + // Service hierarchy + { name: 'service_director', label: 'Service Director', parent: 'executive' }, + { name: 'service_manager', label: 'Service Manager', parent: 'service_director' }, + { name: 'service_agent', label: 'Service Agent', parent: 'service_manager' }, +]; +``` + +## How Role Hierarchy Works + +``` + Executive + / \ + Sales Director Service Director + | | + Sales Manager Service Manager + | | + Sales Rep Service Agent +``` + +**Grant Access UP:** Users see records owned by: +- Themselves +- Their subordinates +- Their subordinates' subordinates (all levels down) + +**Example:** Sales Director sees all records owned by Sales Managers and Sales Reps. + +--- + +## See also + +- [Permissions & Identity overview](/docs/permissions) +- [Sharing Rules](/docs/permissions/sharing-rules) +- [Profiles](/docs/permissions/profiles) diff --git a/content/docs/permissions/sharing-rules.mdx b/content/docs/permissions/sharing-rules.mdx new file mode 100644 index 0000000000..2db72a9e54 --- /dev/null +++ b/content/docs/permissions/sharing-rules.mdx @@ -0,0 +1,135 @@ +--- +title: "Sharing Rules" +description: "Extend record access beyond the role hierarchy — organization-wide defaults, criteria- and owner-based sharing rules, recipient types, and RLS-safe analytics read scope." +--- + +# Sharing Rules + +Sharing rules extend access beyond the role hierarchy. + +## Organization-Wide Defaults (OWD) + +Set baseline access for all users: + +Each object's OWD is a single value from the `OWDModel` enum (`private`, +`public_read`, `public_read_write`, `controlled_by_parent`): + +```typescript +export const OrganizationDefaults = { + lead: 'private', // Users see only their own records + account: 'private', + contact: 'controlled_by_parent', // Access controlled by parent (Account) + opportunity: 'private', + campaign: 'public_read', // All users can read + product: 'public_read', +}; +``` + +## Access Levels + +| Level | Description | +|-------|-------------| +| `private` | Owner only (+ role hierarchy) | +| `public_read` | All users can read | +| `public_read_write` | All users can read and edit | +| `controlled_by_parent` | Controlled by parent object | + +## Criteria-Based Sharing Rules + +Share records based on field criteria: + +```typescript +import { defineSharingRule } from '@objectstack/spec/security'; + +export const AccountTeamSharingRule = defineSharingRule({ + name: 'account_team_sharing', + label: 'Share Active Customers with Sales Team', + type: 'criteria', + object: 'account', + + // Predicate (CEL): which records to share + condition: P`record.type == "customer" && record.is_active == true`, + + // Who to share with (a single recipient — see the recipient types below) + sharedWith: { + type: 'role', + value: 'sales_manager', + }, + + // Access level granted: read | edit | full + accessLevel: 'edit', +}); +``` + +### Recipient types + +`sharedWith` (and `ownedBy`) accept a `{ type, value }` recipient. The supported +`type` values are: + +| `type` | Shares with | +|:--|:--| +| `user` | A single user | +| `group` | All members of a public group | +| `role` | Everyone assigned that role | +| `role_and_subordinates` | Everyone in that role **and every role below it** in the hierarchy (ADR-0056 D6) — configurable per rule, so one rule can cascade down a branch of the org chart | + +```typescript +// Share with a sales manager AND everyone reporting up to them. +sharedWith: { type: 'role_and_subordinates', value: 'sales_manager' }, +``` + +The recipient set is expanded by `@objectstack/plugin-sharing` when the rule is +evaluated (`afterInsert` / `afterUpdate`); `role_and_subordinates` walks the +`sys_role.parent` graph (cycle-safe). + +## Owner-Based Sharing Rules + +Share based on record owner characteristics: + +```typescript +import { defineSharingRule } from '@objectstack/spec/security'; + +export const OpportunityOwnerSharingRule = defineSharingRule({ + name: 'opportunity_owner_sharing', + label: 'Share Sales Rep Opportunities with Managers', + type: 'owner', + object: 'opportunity', + + // Share records owned by this group/role + ownedBy: { + type: 'role', + value: 'sales_rep', + }, + + // Share with this recipient + sharedWith: { + type: 'role', + value: 'sales_manager', + }, + + accessLevel: 'read', +}); +``` + +## Analytics and Dataset Read Scope + +Dataset-bound dashboards and reports often execute through the analytics +service, including the NativeSQL strategy. That path still has to honor the +same row-level security rules as ObjectQL. `@objectstack/plugin-security` +therefore registers a public `security` service with +`getReadFilter(object, context)`, and `@objectstack/service-analytics` +auto-bridges to it unless an explicit `getReadScope` option is supplied. + +The bridge is context-aware and may be async because permission-set and RLS +resolution can hit the database. The analytics service applies the returned +filter to the base object and to joined objects declared by a dataset. If read +scope resolution fails or an unsupported predicate would have to be translated +into SQL, the analytics query fails closed instead of dropping the filter. + +--- + +## See also + +- [Permissions & Identity overview](/docs/permissions) +- [Role Hierarchy](/docs/permissions/roles) +- [Field-Level Security](/docs/permissions/field-level-security) diff --git a/content/docs/guides/auth-sso.mdx b/content/docs/permissions/sso.mdx similarity index 100% rename from content/docs/guides/auth-sso.mdx rename to content/docs/permissions/sso.mdx diff --git a/content/docs/guides/adding-a-metadata-type.mdx b/content/docs/plugins/adding-a-metadata-type.mdx similarity index 96% rename from content/docs/guides/adding-a-metadata-type.mdx rename to content/docs/plugins/adding-a-metadata-type.mdx index 7de9f45be2..584c17b97e 100644 --- a/content/docs/guides/adding-a-metadata-type.mdx +++ b/content/docs/plugins/adding-a-metadata-type.mdx @@ -226,6 +226,6 @@ If you omit them, the directory falls back to the registry `label`. ## Related -- [`GET /api/v1/meta`](./api-reference.mdx) — lists every registered metadata type; per-type items at `GET /api/v1/meta/:type`, history at `GET /api/v1/meta/:type/:name/history` -- [Object & Field design](./data-modeling.mdx) — the canonical example of a writable metadata type -- [Plugin lifecycle](./plugin-development.mdx) — how third-party packages contribute types +- [`GET /api/v1/meta`](/docs/api) — lists every registered metadata type; per-type items at `GET /api/v1/meta/:type`, history at `GET /api/v1/meta/:type/:name/history` +- [Object & Field design](/docs/data-modeling) — the canonical example of a writable metadata type +- [Plugin lifecycle](/docs/plugins/development) — how third-party packages contribute types diff --git a/content/docs/concepts/core/plugins.mdx b/content/docs/plugins/anatomy.mdx similarity index 57% rename from content/docs/concepts/core/plugins.mdx rename to content/docs/plugins/anatomy.mdx index 1ffe8e70f5..8e65a5c5a1 100644 --- a/content/docs/concepts/core/plugins.mdx +++ b/content/docs/plugins/anatomy.mdx @@ -1,9 +1,9 @@ --- -title: Plugin Development -description: How to build extensions for ObjectStack +title: Plugin Anatomy +description: The Plugin contract — interface, context, and lifecycle phases every ObjectStack plugin implements --- -# Plugin Development +# Plugin Anatomy Plugins are the building blocks of ObjectStack. A plugin is a plain JavaScript/TypeScript object (or class) that conforms to the `Plugin` interface. @@ -159,3 +159,90 @@ export interface Plugin { destroy?(): Promise | void; } ``` + +## Plugin Context + +The `PluginContext` provides access to kernel capabilities: + +```typescript +interface PluginContext { + /** Register a service for other plugins to consume */ + registerService(name: string, service: any): void; + + /** Register a lifecycle-managed service factory (e.g. SCOPED per-project services) */ + registerServiceFactory( + name: string, + factory: (ctx: PluginContext, scopeId?: string) => any, + lifecycle?: ServiceLifecycle, + dependencies?: string[], + ): void; + + /** Get a service registered by another plugin */ + getService(name: string): T; + + /** Get a per-scope service instance (e.g. per-project / per-environment) */ + getServiceScoped(name: string, scopeId: string): Promise; + + /** Replace an existing service implementation */ + replaceService(name: string, implementation: T): void; + + /** Get all registered services */ + getServices(): Map; + + /** Register a hook handler */ + hook(name: string, handler: (...args: any[]) => void | Promise): void; + + /** Trigger a hook */ + trigger(name: string, ...args: any[]): Promise; + + /** Logger instance */ + logger: Logger; + + /** Access the kernel instance */ + getKernel(): ObjectKernel; +} +``` + +## Plugin Lifecycle + +Plugins follow a strict three-phase lifecycle managed by the kernel: + +``` + ┌──────────────────────┐ + │ kernel.use() │ + │ Register plugin │ + └──────────┬───────────┘ + │ + ┌──────────▼───────────┐ + │ Phase 1: init() │ + │ Register services │ + │ Set up hooks │ + └──────────┬───────────┘ + │ + ┌──────────▼───────────┐ + │ Phase 2: start() │ + │ Start servers │ + │ Connect databases │ + │ Execute logic │ + └──────────┬───────────┘ + │ + ┌──────────▼───────────┐ + │ kernel:ready hook │ + │ System operational │ + └──────────┬───────────┘ + │ + ┌──────────▼───────────┐ + │ Phase 3: destroy() │ + │ Cleanup resources │ + │ (reverse order) │ + └──────────────────────┘ +``` + +1. **init()** — Called during kernel initialization. Register services that other plugins may depend on. +2. **start()** — Called after *all* plugins have initialized. Start servers, connect to databases, or execute main logic. +3. **destroy()** — Called during shutdown, in reverse order. Clean up connections, timers, and resources. + +## Next Steps + +- **[Plugin System](/docs/plugins)** — Module overview: architecture, configuration, and built-in plugins +- **[Plugin Development](/docs/plugins/development)** — Step-by-step tutorial: build, test, and register a plugin diff --git a/content/docs/guides/plugin-development.mdx b/content/docs/plugins/development.mdx similarity index 97% rename from content/docs/guides/plugin-development.mdx rename to content/docs/plugins/development.mdx index d5e4f52c1e..88caf129c7 100644 --- a/content/docs/guides/plugin-development.mdx +++ b/content/docs/plugins/development.mdx @@ -442,6 +442,6 @@ Metadata viewers declare which modes they support: ## Next Steps -- [Common Patterns](/docs/guides/common-patterns) — See how plugins fit into the application architecture -- [Error Catalog](/docs/guides/cheatsheets/error-catalog) — Return proper error codes from your plugin -- [Field Type Gallery](/docs/guides/cheatsheets/field-type-gallery) — Define custom objects with the right field types +- [Common Patterns](/docs/getting-started/common-patterns) — See how plugins fit into the application architecture +- [Error Catalog](/docs/api/error-catalog) — Return proper error codes from your plugin +- [Field Type Gallery](/docs/data-modeling/field-types) — Define custom objects with the right field types diff --git a/content/docs/guides/plugins.mdx b/content/docs/plugins/index.mdx similarity index 68% rename from content/docs/guides/plugins.mdx rename to content/docs/plugins/index.mdx index 941a291129..3fc97005ab 100644 --- a/content/docs/guides/plugins.mdx +++ b/content/docs/plugins/index.mdx @@ -1,6 +1,6 @@ --- title: Plugin System -description: Complete guide to the ObjectStack plugin architecture — creating, configuring, and managing plugins with the CLI. +description: Overview of the ObjectStack plugin architecture — plugin types, configuration, management, and built-in plugins. --- # Plugin System @@ -11,6 +11,15 @@ ObjectStack is built on a **microkernel architecture** where nearly everything b **Key Principle**: In ObjectStack, the concept of "Project" and "Plugin" is fluid. A **Project** is simply a Stack that is currently being executed. A **Plugin** is a Stack loaded by another Stack. Any project can be imported as a plugin without code changes. +## What's in this module + +- **[Plugin Anatomy](/docs/plugins/anatomy)** — The `Plugin` contract: interface, `PluginContext`, and lifecycle phases +- **[Plugin Development](/docs/plugins/development)** — Step-by-step tutorial: build, test, and register a plugin +- **[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) + --- ## Architecture Overview @@ -56,123 +65,18 @@ ObjectStack defines several specialized plugin types: ## Plugin Interface -Every plugin implements the `Plugin` interface from `@objectstack/core`: - -```typescript -interface Plugin { - /** Unique plugin name (e.g., 'com.objectstack.engine.objectql') */ - name: string; - - /** Plugin version */ - version?: string; - - /** Plugin type */ - type?: 'standard' | 'ui' | 'driver' | 'server' | 'app' | 'theme' | 'agent' | 'objectql'; - - /** Plugin dependencies (loaded before this plugin) */ - dependencies?: string[]; - - /** Phase 1: Register services */ - init(ctx: PluginContext): Promise | void; - - /** Phase 2: Execute business logic (after all plugins initialized) */ - start?(ctx: PluginContext): Promise | void; - - /** Phase 3: Cleanup on shutdown */ - destroy?(): Promise | void; -} -``` - -### Plugin Context - -The `PluginContext` provides access to kernel capabilities: - -```typescript -interface PluginContext { - /** Register a service for other plugins to consume */ - registerService(name: string, service: any): void; - - /** Register a lifecycle-managed service factory (e.g. SCOPED per-project services) */ - registerServiceFactory( - name: string, - factory: (ctx: PluginContext, scopeId?: string) => any, - lifecycle?: ServiceLifecycle, - dependencies?: string[], - ): void; - - /** Get a service registered by another plugin */ - getService(name: string): T; - - /** Get a per-scope service instance (e.g. per-project / per-environment) */ - getServiceScoped(name: string, scopeId: string): Promise; - - /** Replace an existing service implementation */ - replaceService(name: string, implementation: T): void; - - /** Get all registered services */ - getServices(): Map; - - /** Register a hook handler */ - hook(name: string, handler: (...args: any[]) => void | Promise): void; - - /** Trigger a hook */ - trigger(name: string, ...args: any[]): Promise; - - /** Logger instance */ - logger: Logger; - - /** Access the kernel instance */ - getKernel(): ObjectKernel; -} -``` +Every plugin implements the `Plugin` interface from `@objectstack/core` — see [Plugin Anatomy](/docs/plugins/anatomy) for the full contract and the `PluginContext` reference. --- ## Plugin Lifecycle -Plugins follow a strict three-phase lifecycle managed by the kernel: - -``` - ┌──────────────────────┐ - │ kernel.use() │ - │ Register plugin │ - └──────────┬───────────┘ - │ - ┌──────────▼───────────┐ - │ Phase 1: init() │ - │ Register services │ - │ Set up hooks │ - └──────────┬───────────┘ - │ - ┌──────────▼───────────┐ - │ Phase 2: start() │ - │ Start servers │ - │ Connect databases │ - │ Execute logic │ - └──────────┬───────────┘ - │ - ┌──────────▼───────────┐ - │ kernel:ready hook │ - │ System operational │ - └──────────┬───────────┘ - │ - ┌──────────▼───────────┐ - │ Phase 3: destroy() │ - │ Cleanup resources │ - │ (reverse order) │ - └──────────────────────┘ -``` - -1. **init()** — Called during kernel initialization. Register services that other plugins may depend on. -2. **start()** — Called after *all* plugins have initialized. Start servers, connect to databases, or execute main logic. -3. **destroy()** — Called during shutdown, in reverse order. Clean up connections, timers, and resources. +Plugins follow a strict three-phase lifecycle (`init()` → `start()` → `destroy()`) managed by the kernel — see [Plugin Anatomy](/docs/plugins/anatomy#plugin-lifecycle) for the phase model. --- ## Creating a Plugin -### Using the CLI - The fastest way to create a plugin is with the CLI scaffolding: ```bash @@ -188,58 +92,7 @@ os create plugin my-feature # └── index.ts ``` -### Manual Plugin Creation - -```typescript -import type { Plugin } from '@objectstack/core'; - -export const myFeaturePlugin: Plugin = { - name: 'com.example.my-feature', - version: '1.0.0', - type: 'standard', - - async init(ctx) { - // Register a service that other plugins can consume - const myService = { greet: (name: string) => `Hello, ${name}!` }; - ctx.registerService('my-feature', myService); - - // Listen for kernel hooks (e.g. run logic once the system is operational). - // Note: object lifecycle hooks like beforeInsert/afterInsert are defined on - // the object itself (L2 hooks), not subscribed via ctx.hook. - ctx.hook('kernel:ready', async () => { - ctx.logger.info('Kernel is ready'); - }); - }, - - async start(ctx) { - // Access services registered by other plugins - const data = ctx.getService('data'); - ctx.logger.info('My feature plugin started'); - }, - - async destroy() { - // Cleanup resources - }, -}; - -export default myFeaturePlugin; -``` - -### Plugin with Dependencies - -```typescript -export const analyticsPlugin: Plugin = { - name: 'com.example.analytics', - version: '1.0.0', - dependencies: ['com.objectstack.server.hono'], // Loaded after Hono - - async init(ctx) { - // Safe to access Hono server because of dependency declaration - const server = ctx.getService('http.server'); - ctx.registerService('analytics', new AnalyticsService()); - }, -}; -``` +For the full walkthrough — implementing the `Plugin` interface, registering services and hooks, testing, and registering with the kernel — see the [Plugin Development](/docs/plugins/development) tutorial. --- @@ -566,7 +419,7 @@ plugin-my-feature/ ## Next Steps -- **[Data Modeling](/docs/guides/data-modeling)** — Define business objects and fields -- **[Authentication](/docs/guides/authentication)** — Set up auth with the auth plugin -- **[Kernel Services](/docs/guides/kernel-services)** — Understand the service registry -- **[Security](/docs/guides/security)** — Configure field and row-level security +- **[Data Modeling](/docs/data-modeling)** — Define business objects and fields +- **[Authentication](/docs/permissions/authentication)** — Set up auth with the auth plugin +- **[Kernel Services](/docs/kernel/services-checklist)** — Understand the service registry +- **[Security](/docs/permissions)** — Configure field and row-level security diff --git a/content/docs/plugins/meta.json b/content/docs/plugins/meta.json new file mode 100644 index 0000000000..b126a898e0 --- /dev/null +++ b/content/docs/plugins/meta.json @@ -0,0 +1,11 @@ +{ + "title": "Plugins & Packages", + "icon": "Puzzle", + "pages": [ + "index", + "anatomy", + "development", + "packages", + "adding-a-metadata-type" + ] +} diff --git a/content/docs/guides/packages.mdx b/content/docs/plugins/packages.mdx similarity index 99% rename from content/docs/guides/packages.mdx rename to content/docs/plugins/packages.mdx index b9394d47d4..01454514d5 100644 --- a/content/docs/guides/packages.mdx +++ b/content/docs/plugins/packages.mdx @@ -93,7 +93,7 @@ const kernel = new ObjectKernel(); - **Purpose**: One expression language across hooks, predicates, formula fields, and seed templates - **When to use**: Anywhere you write a CEL expression in metadata -- **Learn more**: [Formula skill](/docs/guides/formula) +- **Learn more**: [Formula skill](/docs/data-modeling/formulas) ### @objectstack/platform-objects @@ -494,7 +494,7 @@ await kernel.use(createServiceAnalyticsPlugin({ /* … */ })); ## Next Steps -- **Architecture Overview**: [Learn the architecture](/docs/getting-started/architecture) +- **Architecture Overview**: [Learn the architecture](/docs/concepts/architecture) - **Quick Start**: [Build your first app](/docs/getting-started/quick-start) - **API Reference**: [Explore the API](/docs/references) - **Examples**: [Browse examples](/docs/getting-started/examples) diff --git a/content/docs/guides/cheatsheets/backward-compatibility.mdx b/content/docs/protocol/backward-compatibility.mdx similarity index 100% rename from content/docs/guides/cheatsheets/backward-compatibility.mdx rename to content/docs/protocol/backward-compatibility.mdx diff --git a/content/docs/guides/cheatsheets/protocol-diagram.mdx b/content/docs/protocol/diagram.mdx similarity index 100% rename from content/docs/guides/cheatsheets/protocol-diagram.mdx rename to content/docs/protocol/diagram.mdx diff --git a/content/docs/protocol/meta.json b/content/docs/protocol/meta.json index 185065ed99..ed07439481 100644 --- a/content/docs/protocol/meta.json +++ b/content/docs/protocol/meta.json @@ -1,6 +1,13 @@ { - "title": "Protocol", + "title": "Protocol Spec", "icon": "Network", - "root": true, - "pages": ["index", "objectql", "objectui", "objectos", "knowledge"] + "pages": [ + "index", + "diagram", + "objectql", + "objectui", + "objectos", + "knowledge", + "backward-compatibility" + ] } diff --git a/content/docs/protocol/objectql/index.mdx b/content/docs/protocol/objectql/index.mdx index 89004b19ce..1ef7fce36f 100644 --- a/content/docs/protocol/objectql/index.mdx +++ b/content/docs/protocol/objectql/index.mdx @@ -369,8 +369,8 @@ See [Security Protocol](/docs/protocol/objectql/security) for details. 4. [Security](/docs/protocol/objectql/security) - Implement access control **Advanced:** -5. [Data Engine contract](/docs/guides/contracts/data-engine) - Build custom database drivers -6. [Analytics Datasets](/docs/guides/analytics-datasets) - OLAP queries +5. [Data Engine contract](/docs/kernel/contracts/data-engine) - Build custom database drivers +6. [Analytics Datasets](/docs/data-modeling/analytics) - OLAP queries ## Technical References diff --git a/content/docs/protocol/objectql/state-machine.mdx b/content/docs/protocol/objectql/state-machine.mdx index 7fb173a9a6..52bc4aec6c 100644 --- a/content/docs/protocol/objectql/state-machine.mdx +++ b/content/docs/protocol/objectql/state-machine.mdx @@ -203,5 +203,5 @@ export const Order = ObjectSchema.create({ ``` - "Do something when the state changes" (emails, webhooks, downstream record updates) is **not** part of the transition table. Express side effects as a record-triggered [Flow](/docs/guides/metadata/flow) — the state machine only locks the legal edges. + "Do something when the state changes" (emails, webhooks, downstream record updates) is **not** part of the transition table. Express side effects as a record-triggered [Flow](/docs/automation/flows) — the state machine only locks the legal edges. diff --git a/content/docs/protocol/objectui/actions.mdx b/content/docs/protocol/objectui/actions.mdx index 7d5ab48c0b..fa289922eb 100644 --- a/content/docs/protocol/objectui/actions.mdx +++ b/content/docs/protocol/objectui/actions.mdx @@ -435,5 +435,5 @@ ai: - [Action Reference](/docs/references/ui/action) - Auto-generated `ActionSchema` reference - [View Reference](/docs/references/ui/view) - List and form view metadata -- [Hook Bodies](/docs/guides/hook-bodies) - Authoring `body` expressions and sandboxed JS +- [Hook Bodies](/docs/automation/hook-bodies) - Authoring `body` expressions and sandboxed JS - [Flow Builder](/docs/references/studio/flow-builder) - Build multi-step flows diff --git a/content/docs/protocol/objectui/record-alert.mdx b/content/docs/protocol/objectui/record-alert.mdx index e2d0bd7ef2..c42e9554ed 100644 --- a/content/docs/protocol/objectui/record-alert.mdx +++ b/content/docs/protocol/objectui/record-alert.mdx @@ -102,7 +102,7 @@ Rules: ## CTA wiring -The optional `action.actionName` resolves against the object's `actions[]` (the same array that backs `record:quick_actions`). When clicked, the renderer dispatches the resolved action, which means it inherits the action's declared behavior from the [action schema](../../references/ui/action): +The optional `action.actionName` resolves against the object's `actions[]` (the same array that backs `record:quick_actions`). When clicked, the renderer dispatches the resolved action, which means it inherits the action's declared behavior from the [action schema](/docs/references/ui/action): - Confirm dialog (`confirmText`) - Param collection (`params: [...]`) @@ -150,5 +150,5 @@ Pick a stable `dismissKey` when the title is i18n'd — otherwise translation ch ## Related -- [`record:quick_actions`](./actions) — action toolbar that pairs naturally with `record:alert` (the alert nudges the user; the toolbar lets them act). -- [`ui/page.zod.ts`](../../references/ui/page) — the slotted page schema definition, including the `alerts` slot. +- [`record:quick_actions`](/docs/protocol/objectui/actions) — action toolbar that pairs naturally with `record:alert` (the alert nudges the user; the toolbar lets them act). +- [`ui/page.zod.ts`](/docs/references/ui/page) — the slotted page schema definition, including the `alerts` slot. diff --git a/content/docs/protocol/objectui/widget-contract.mdx b/content/docs/protocol/objectui/widget-contract.mdx index c78c4f1e78..f07a7d654b 100644 --- a/content/docs/protocol/objectui/widget-contract.mdx +++ b/content/docs/protocol/objectui/widget-contract.mdx @@ -334,7 +334,7 @@ Widgets inherit the active theme automatically; they do not each carry a full se } title="Plugin Development" - href="/docs/guides/plugin-development" + href="/docs/plugins/development" description="Build and register your own widgets and extensions" /> diff --git a/content/docs/references/ai/agent.mdx b/content/docs/references/ai/agent.mdx index 2f0c530656..820ea3651e 100644 --- a/content/docs/references/ai/agent.mdx +++ b/content/docs/references/ai/agent.mdx @@ -3,7 +3,7 @@ title: Agent description: Agent protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} AI Model Configuration diff --git a/content/docs/references/ai/conversation.mdx b/content/docs/references/ai/conversation.mdx index e4d0723d5d..be7c66c117 100644 --- a/content/docs/references/ai/conversation.mdx +++ b/content/docs/references/ai/conversation.mdx @@ -3,7 +3,7 @@ title: Conversation description: Conversation protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} AI Conversation Memory Protocol diff --git a/content/docs/references/ai/embedding.mdx b/content/docs/references/ai/embedding.mdx index 591a5359eb..63c4a99124 100644 --- a/content/docs/references/ai/embedding.mdx +++ b/content/docs/references/ai/embedding.mdx @@ -3,7 +3,7 @@ title: Embedding description: Embedding protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Embedding & Vector Store Primitives diff --git a/content/docs/references/ai/knowledge-document.mdx b/content/docs/references/ai/knowledge-document.mdx index 6f4d6ec24c..f0e39e1f10 100644 --- a/content/docs/references/ai/knowledge-document.mdx +++ b/content/docs/references/ai/knowledge-document.mdx @@ -3,7 +3,7 @@ title: Knowledge Document description: Knowledge Document protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Knowledge Document / Chunk / Hit — canonical shapes shared by every diff --git a/content/docs/references/ai/knowledge-source.mdx b/content/docs/references/ai/knowledge-source.mdx index 8eeec35c30..072db25b1d 100644 --- a/content/docs/references/ai/knowledge-source.mdx +++ b/content/docs/references/ai/knowledge-source.mdx @@ -3,7 +3,7 @@ title: Knowledge Source description: Knowledge Source protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Knowledge Source — declarative metadata describing what to index and diff --git a/content/docs/references/ai/mcp.mdx b/content/docs/references/ai/mcp.mdx index 25df571a74..7ceef85de9 100644 --- a/content/docs/references/ai/mcp.mdx +++ b/content/docs/references/ai/mcp.mdx @@ -3,7 +3,7 @@ title: Mcp description: Mcp protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Model Context Protocol (MCP) — Reference & Binding Primitives diff --git a/content/docs/references/ai/model-registry.mdx b/content/docs/references/ai/model-registry.mdx index c988b5f73b..b0212ca298 100644 --- a/content/docs/references/ai/model-registry.mdx +++ b/content/docs/references/ai/model-registry.mdx @@ -3,7 +3,7 @@ title: Model Registry description: Model Registry protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} AI Model Registry Protocol diff --git a/content/docs/references/ai/skill.mdx b/content/docs/references/ai/skill.mdx index 39039601a0..aeffbb6c92 100644 --- a/content/docs/references/ai/skill.mdx +++ b/content/docs/references/ai/skill.mdx @@ -3,7 +3,7 @@ title: Skill description: Skill protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Skill Trigger Condition Schema diff --git a/content/docs/references/ai/solution-blueprint.mdx b/content/docs/references/ai/solution-blueprint.mdx index 2fd1d00bf5..5a4870b29f 100644 --- a/content/docs/references/ai/solution-blueprint.mdx +++ b/content/docs/references/ai/solution-blueprint.mdx @@ -3,7 +3,7 @@ title: Solution Blueprint description: Solution Blueprint protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Solution Blueprint Schema (ADR-0033 §4 — plan-first authoring) @@ -110,6 +110,7 @@ const result = BlueprintApp.parse(data); | **label** | `string` | optional | Human-readable singular label | | **description** | `string` | optional | What this object represents | | **fields** | `Object[]` | ✅ | Fields to create on the object | +| **nameField** | `string` | optional | The record title field — which field holds the human-readable name shown on cards, lookup chips, breadcrumbs and search (ADR-0079). Set it to the object's text label field (e.g. "product_name"). For a numbered entity (invoice/ticket), set it to a formula field that composes number + name (e.g. "`{order_no}` · `{customer}`"). Omitting it lets the platform auto-pick a text field, but declaring it is strongly preferred. | --- @@ -135,9 +136,9 @@ const result = BlueprintApp.parse(data); | **object** | `string` | ✅ | Object this view displays (snake_case) | | **name** | `string` | ✅ | View machine name (snake_case) | | **label** | `string` | optional | Human-readable view label | -| **type** | `Enum<'list' \| 'form' \| 'kanban' \| 'calendar'>` | ✅ | View kind | -| **columns** | `string[]` | optional | Field names shown as columns (in order) | -| **groupBy** | `string` | optional | REQUIRED for kanban views: the select/status field whose options become the board columns (e.g. "stage", "status"). Without it a kanban renders as a plain list. | +| **type** | `Enum<'list' \| 'form' \| 'kanban' \| 'calendar' \| 'gallery' \| 'gantt'>` | ✅ | View kind. Pick the surface that fits the data: "gallery" for a visual card/cover browse when the user asks for a 画廊/相册/卡片墙/封面/海报/图集 (a gallery / card wall / cover / poster grid) or the object has an image/avatar/file field worth showing as a card cover; "gantt" for a 甘特图/时间线/排期 (timeline / schedule) when the object has BOTH a start and an end date field; "kanban" for a board grouped by a status/select field; "calendar" for a single-date schedule; "form" for a record editor; else "list". | +| **columns** | `string[]` | optional | Field names shown as columns (in order). For a gallery, INCLUDE the image/avatar/file field (it becomes the card cover); for a gantt, INCLUDE the start date column before the end date column. | +| **groupBy** | `string` | optional | REQUIRED for kanban views: the select/status field whose options become the board columns (e.g. "stage", "status"). Without it a kanban renders as a plain list. Optional for gantt (groups leaf tasks into summary rows). | --- diff --git a/content/docs/references/ai/tool.mdx b/content/docs/references/ai/tool.mdx index 4cdf1baad0..a3451dd650 100644 --- a/content/docs/references/ai/tool.mdx +++ b/content/docs/references/ai/tool.mdx @@ -3,7 +3,7 @@ title: Tool description: Tool protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Tool Category diff --git a/content/docs/references/ai/usage.mdx b/content/docs/references/ai/usage.mdx index f14aac8261..65480e83a9 100644 --- a/content/docs/references/ai/usage.mdx +++ b/content/docs/references/ai/usage.mdx @@ -3,7 +3,7 @@ title: Usage description: Usage protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} AI Usage Primitives diff --git a/content/docs/references/api/analytics.mdx b/content/docs/references/api/analytics.mdx index c8adadc256..3101ae43a2 100644 --- a/content/docs/references/api/analytics.mdx +++ b/content/docs/references/api/analytics.mdx @@ -3,7 +3,7 @@ title: Analytics description: Analytics protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Analytics API Protocol diff --git a/content/docs/references/api/auth-endpoints.mdx b/content/docs/references/api/auth-endpoints.mdx index 0976978246..f51d92ffbd 100644 --- a/content/docs/references/api/auth-endpoints.mdx +++ b/content/docs/references/api/auth-endpoints.mdx @@ -3,7 +3,7 @@ title: Auth Endpoints description: Auth Endpoints protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Authentication Endpoint Specification diff --git a/content/docs/references/api/auth.mdx b/content/docs/references/api/auth.mdx index cc3d1b813f..e24aca6ef3 100644 --- a/content/docs/references/api/auth.mdx +++ b/content/docs/references/api/auth.mdx @@ -3,7 +3,7 @@ title: Auth description: Auth protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Authentication Service Protocol diff --git a/content/docs/references/api/automation-api.mdx b/content/docs/references/api/automation-api.mdx index b1b194d228..19291864fd 100644 --- a/content/docs/references/api/automation-api.mdx +++ b/content/docs/references/api/automation-api.mdx @@ -3,7 +3,7 @@ title: Automation Api description: Automation Api protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Automation API Protocol diff --git a/content/docs/references/api/batch.mdx b/content/docs/references/api/batch.mdx index 287180499a..1bf7c47e20 100644 --- a/content/docs/references/api/batch.mdx +++ b/content/docs/references/api/batch.mdx @@ -3,7 +3,7 @@ title: Batch description: Batch protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Batch Operations API diff --git a/content/docs/references/api/connector.mdx b/content/docs/references/api/connector.mdx index 4894914a0c..990bc65596 100644 --- a/content/docs/references/api/connector.mdx +++ b/content/docs/references/api/connector.mdx @@ -3,7 +3,7 @@ title: Connector description: Connector protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ 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/api/connector.zod.ts` diff --git a/content/docs/references/api/contract.mdx b/content/docs/references/api/contract.mdx index 835c34ae63..f36baedb1b 100644 --- a/content/docs/references/api/contract.mdx +++ b/content/docs/references/api/contract.mdx @@ -3,7 +3,7 @@ title: Contract description: Contract protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Standard Create Request diff --git a/content/docs/references/api/core-services.mdx b/content/docs/references/api/core-services.mdx index 2f93693bdb..1583948a79 100644 --- a/content/docs/references/api/core-services.mdx +++ b/content/docs/references/api/core-services.mdx @@ -3,7 +3,7 @@ title: Core Services description: Core Services protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ 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/api/core-services.zod.ts` diff --git a/content/docs/references/api/discovery.mdx b/content/docs/references/api/discovery.mdx index 2ac0fafa5d..8fb5631485 100644 --- a/content/docs/references/api/discovery.mdx +++ b/content/docs/references/api/discovery.mdx @@ -3,7 +3,7 @@ title: Discovery description: Discovery protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Service Status Enum diff --git a/content/docs/references/api/dispatcher.mdx b/content/docs/references/api/dispatcher.mdx index 666b568d3d..83a039512c 100644 --- a/content/docs/references/api/dispatcher.mdx +++ b/content/docs/references/api/dispatcher.mdx @@ -3,7 +3,7 @@ title: Dispatcher description: Dispatcher protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} # HttpDispatcher Protocol diff --git a/content/docs/references/api/documentation.mdx b/content/docs/references/api/documentation.mdx index 82e2d6d287..1e8fbe7b75 100644 --- a/content/docs/references/api/documentation.mdx +++ b/content/docs/references/api/documentation.mdx @@ -3,7 +3,7 @@ title: Documentation description: Documentation protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} API Documentation & Testing Interface Protocol diff --git a/content/docs/references/api/endpoint.mdx b/content/docs/references/api/endpoint.mdx index 69bed94f65..128e13ecd9 100644 --- a/content/docs/references/api/endpoint.mdx +++ b/content/docs/references/api/endpoint.mdx @@ -3,7 +3,7 @@ title: Endpoint description: Endpoint protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} API Mapping Schema diff --git a/content/docs/references/api/errors.mdx b/content/docs/references/api/errors.mdx index 9897362fce..eafb2dd374 100644 --- a/content/docs/references/api/errors.mdx +++ b/content/docs/references/api/errors.mdx @@ -3,7 +3,7 @@ title: Errors description: Errors protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Standardized Error Codes Protocol diff --git a/content/docs/references/api/events.mdx b/content/docs/references/api/events.mdx index e4e0d2cc30..56d3e9879a 100644 --- a/content/docs/references/api/events.mdx +++ b/content/docs/references/api/events.mdx @@ -3,7 +3,7 @@ title: Events description: Events protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Metadata Event Types diff --git a/content/docs/references/api/export.mdx b/content/docs/references/api/export.mdx index 8ecdeeb9d8..71a28d82f2 100644 --- a/content/docs/references/api/export.mdx +++ b/content/docs/references/api/export.mdx @@ -3,7 +3,7 @@ title: Export description: Export protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Data Export & Import Protocol @@ -24,8 +24,8 @@ Base path: /api/v1/data/\{object\}/export ## TypeScript Usage ```typescript -import { CreateExportJobRequest, CreateExportJobResponse, DeduplicationStrategy, ExportFormat, ExportImportTemplate, ExportJobProgress, ExportJobStatus, ExportJobSummary, FieldMappingEntry, GetExportJobDownloadRequest, GetExportJobDownloadResponse, ImportValidationConfig, ImportValidationMode, ImportValidationResult, ListExportJobsRequest, ListExportJobsResponse, ScheduleExportResponse } from '@objectstack/spec/api'; -import type { CreateExportJobRequest, CreateExportJobResponse, DeduplicationStrategy, ExportFormat, ExportImportTemplate, ExportJobProgress, ExportJobStatus, ExportJobSummary, FieldMappingEntry, GetExportJobDownloadRequest, GetExportJobDownloadResponse, ImportValidationConfig, ImportValidationMode, ImportValidationResult, ListExportJobsRequest, ListExportJobsResponse, ScheduleExportResponse } from '@objectstack/spec/api'; +import { CreateExportJobRequest, CreateExportJobResponse, CreateImportJobRequest, CreateImportJobResponse, DeduplicationStrategy, ExportFormat, ExportImportTemplate, ExportJobProgress, ExportJobStatus, ExportJobSummary, FieldMappingEntry, GetExportJobDownloadRequest, GetExportJobDownloadResponse, ImportJobProgress, ImportJobResults, ImportJobStatus, ImportJobSummary, ImportMapping, ImportRequest, ImportResponse, ImportRowResult, ImportValidationConfig, ImportValidationMode, ImportValidationResult, ImportWriteMode, ListExportJobsRequest, ListExportJobsResponse, ListImportJobsRequest, ListImportJobsResponse, ScheduleExportResponse, UndoImportJobResponse } from '@objectstack/spec/api'; +import type { CreateExportJobRequest, CreateExportJobResponse, CreateImportJobRequest, CreateImportJobResponse, DeduplicationStrategy, ExportFormat, ExportImportTemplate, ExportJobProgress, ExportJobStatus, ExportJobSummary, FieldMappingEntry, GetExportJobDownloadRequest, GetExportJobDownloadResponse, ImportJobProgress, ImportJobResults, ImportJobStatus, ImportJobSummary, ImportMapping, ImportRequest, ImportResponse, ImportRowResult, ImportValidationConfig, ImportValidationMode, ImportValidationResult, ImportWriteMode, ListExportJobsRequest, ListExportJobsResponse, ListImportJobsRequest, ListImportJobsResponse, ScheduleExportResponse, UndoImportJobResponse } from '@objectstack/spec/api'; // Validate data const result = CreateExportJobRequest.parse(data); @@ -64,6 +64,45 @@ const result = CreateExportJobRequest.parse(data); | **data** | `Object` | ✅ | | +--- + +## CreateImportJobRequest + +### Properties + +| Property | Type | Required | Description | +| :--- | :--- | :--- | :--- | +| **format** | `Enum<'csv' \| 'json' \| 'xlsx'>` | optional | Payload shape: csv text, a rows[] array, or a base64 xlsx (inferred when omitted) | +| **csv** | `string` | optional | CSV text (when format = csv) | +| **rows** | `Record[]` | optional | Row objects (when format = json) | +| **xlsxBase64** | `string` | optional | Base64-encoded .xlsx workbook bytes (when format = xlsx); parsed server-side | +| **sheet** | `string \| integer` | optional | Worksheet name or 1-based index to read (xlsx; defaults to the first sheet) | +| **mapping** | `Record \| Object[]` | optional | Source column → target field mapping | +| **dryRun** | `boolean` | ✅ | Validate + coerce every row without persisting | +| **writeMode** | `Enum<'insert' \| 'update' \| 'upsert'>` | ✅ | insert / update / upsert semantics | +| **matchFields** | `string[]` | optional | Fields that identify an existing record (required for update/upsert) | +| **runAutomations** | `boolean` | ✅ | Fire triggers/hooks for each imported row (off by default for bulk) | +| **trimWhitespace** | `boolean` | ✅ | Trim leading/trailing whitespace from string cells | +| **nullValues** | `string[]` | optional | Strings treated as null/blank (besides empty string) | +| **createMissingOptions** | `boolean` | ✅ | Keep unmatched select values instead of failing the row | +| **skipBlankMatchKey** | `boolean` | ✅ | Skip rows whose matchFields are blank (default: upsert creates them, update skips them) | + + +--- + +## CreateImportJobResponse + +### Properties + +| Property | Type | Required | Description | +| :--- | :--- | :--- | :--- | +| **jobId** | `string` | ✅ | Import job id — poll progress/results with this | +| **object** | `string` | ✅ | Target object name | +| **status** | `Enum<'pending' \| 'running' \| 'succeeded' \| 'failed' \| 'cancelled'>` | ✅ | Initial job status (usually "pending") | +| **total** | `integer` | ✅ | Rows accepted for processing | +| **createdAt** | `string` | ✅ | Job creation timestamp (ISO 8601) | + + --- ## DeduplicationStrategy @@ -198,6 +237,182 @@ const result = CreateExportJobRequest.parse(data); | **data** | `Object` | ✅ | | +--- + +## ImportJobProgress + +### Properties + +| Property | Type | Required | Description | +| :--- | :--- | :--- | :--- | +| **jobId** | `string` | ✅ | Import job id | +| **object** | `string` | ✅ | Target object name | +| **status** | `Enum<'pending' \| 'running' \| 'succeeded' \| 'failed' \| 'cancelled'>` | ✅ | Current job status | +| **dryRun** | `boolean` | ✅ | Whether this is a validate-only pass | +| **writeMode** | `Enum<'insert' \| 'update' \| 'upsert'>` | ✅ | Write mode used | +| **total** | `integer` | ✅ | Total rows to process | +| **processed** | `integer` | ✅ | Rows processed so far | +| **created** | `integer` | ✅ | Rows that created a new record | +| **updated** | `integer` | ✅ | Rows that updated an existing record | +| **skipped** | `integer` | ✅ | Rows skipped | +| **errors** | `integer` | ✅ | Rows that failed | +| **percentComplete** | `number` | ✅ | processed / total as a percentage | +| **undoable** | `boolean` | ✅ | Whether this job can still be logically rolled back (undo log captured, terminal state, not yet reverted) | +| **revertedAt** | `string` | optional | When the job was undone / rolled back (ISO 8601) | +| **error** | `string` | optional | Fatal error message (when status = failed) | +| **startedAt** | `string` | optional | Processing start timestamp (ISO 8601) | +| **completedAt** | `string` | optional | Completion timestamp (ISO 8601) | +| **createdAt** | `string` | ✅ | Job creation timestamp (ISO 8601) | + + +--- + +## ImportJobResults + +### Properties + +| Property | Type | Required | Description | +| :--- | :--- | :--- | :--- | +| **jobId** | `string` | ✅ | Import job id | +| **object** | `string` | ✅ | Target object name | +| **status** | `Enum<'pending' \| 'running' \| 'succeeded' \| 'failed' \| 'cancelled'>` | ✅ | Current job status | +| **dryRun** | `boolean` | ✅ | Whether this is a validate-only pass | +| **writeMode** | `Enum<'insert' \| 'update' \| 'upsert'>` | ✅ | Write mode used | +| **total** | `integer` | ✅ | Total rows to process | +| **processed** | `integer` | ✅ | Rows processed so far | +| **created** | `integer` | ✅ | Rows that created a new record | +| **updated** | `integer` | ✅ | Rows that updated an existing record | +| **skipped** | `integer` | ✅ | Rows skipped | +| **errors** | `integer` | ✅ | Rows that failed | +| **percentComplete** | `number` | ✅ | processed / total as a percentage | +| **undoable** | `boolean` | ✅ | Whether this job can still be logically rolled back (undo log captured, terminal state, not yet reverted) | +| **revertedAt** | `string` | optional | When the job was undone / rolled back (ISO 8601) | +| **error** | `string` | optional | Fatal error message (when status = failed) | +| **startedAt** | `string` | optional | Processing start timestamp (ISO 8601) | +| **completedAt** | `string` | optional | Completion timestamp (ISO 8601) | +| **createdAt** | `string` | ✅ | Job creation timestamp (ISO 8601) | +| **results** | `Object[]` | ✅ | Capped sample of per-row outcomes (failures first) | +| **resultsTruncated** | `boolean` | ✅ | Whether `results` is a capped sample of a larger set | + + +--- + +## ImportJobStatus + +### Allowed Values + +* `pending` +* `running` +* `succeeded` +* `failed` +* `cancelled` + + +--- + +## ImportJobSummary + +### Properties + +| Property | Type | Required | Description | +| :--- | :--- | :--- | :--- | +| **jobId** | `string` | ✅ | Import job id | +| **object** | `string` | ✅ | Target object name | +| **status** | `Enum<'pending' \| 'running' \| 'succeeded' \| 'failed' \| 'cancelled'>` | ✅ | Job status | +| **total** | `integer` | ✅ | Total rows | +| **processed** | `integer` | ✅ | Rows processed | +| **created** | `integer` | ✅ | Rows created | +| **updated** | `integer` | ✅ | Rows updated | +| **skipped** | `integer` | ✅ | Rows skipped | +| **errors** | `integer` | ✅ | Rows failed | +| **createdAt** | `string` | ✅ | Job creation timestamp (ISO 8601) | +| **completedAt** | `string` | optional | Completion timestamp (ISO 8601) | +| **undoable** | `boolean` | ✅ | Whether this job can still be logically rolled back | +| **revertedAt** | `string` | optional | When the job was undone / rolled back (ISO 8601) | + + +--- + +## ImportMapping + +### Union Options + +This schema accepts one of the following structures: + +#### Option 1 + +Type: `Record` + +--- + +#### Option 2 + +Type: `Object[]` + +--- + + +--- + +## ImportRequest + +### Properties + +| Property | Type | Required | Description | +| :--- | :--- | :--- | :--- | +| **format** | `Enum<'csv' \| 'json' \| 'xlsx'>` | optional | Payload shape: csv text, a rows[] array, or a base64 xlsx (inferred when omitted) | +| **csv** | `string` | optional | CSV text (when format = csv) | +| **rows** | `Record[]` | optional | Row objects (when format = json) | +| **xlsxBase64** | `string` | optional | Base64-encoded .xlsx workbook bytes (when format = xlsx); parsed server-side | +| **sheet** | `string \| integer` | optional | Worksheet name or 1-based index to read (xlsx; defaults to the first sheet) | +| **mapping** | `Record \| Object[]` | optional | Source column → target field mapping | +| **dryRun** | `boolean` | ✅ | Validate + coerce every row without persisting | +| **writeMode** | `Enum<'insert' \| 'update' \| 'upsert'>` | ✅ | insert / update / upsert semantics | +| **matchFields** | `string[]` | optional | Fields that identify an existing record (required for update/upsert) | +| **runAutomations** | `boolean` | ✅ | Fire triggers/hooks for each imported row (off by default for bulk) | +| **trimWhitespace** | `boolean` | ✅ | Trim leading/trailing whitespace from string cells | +| **nullValues** | `string[]` | optional | Strings treated as null/blank (besides empty string) | +| **createMissingOptions** | `boolean` | ✅ | Keep unmatched select values instead of failing the row | +| **skipBlankMatchKey** | `boolean` | ✅ | Skip rows whose matchFields are blank (default: upsert creates them, update skips them) | + + +--- + +## ImportResponse + +### Properties + +| Property | Type | Required | Description | +| :--- | :--- | :--- | :--- | +| **object** | `string` | ✅ | Target object name | +| **dryRun** | `boolean` | ✅ | Whether this was a validate-only pass | +| **writeMode** | `Enum<'insert' \| 'update' \| 'upsert'>` | ✅ | Write mode used | +| **total** | `integer` | ✅ | Rows processed | +| **ok** | `integer` | ✅ | Rows that succeeded | +| **errors** | `integer` | ✅ | Rows that failed | +| **created** | `integer` | ✅ | Rows that created a new record | +| **updated** | `integer` | ✅ | Rows that updated an existing record | +| **skipped** | `integer` | ✅ | Rows skipped (no match in update mode, etc.) | +| **results** | `Object[]` | ✅ | Per-row outcomes | + + +--- + +## ImportRowResult + +### Properties + +| Property | Type | Required | Description | +| :--- | :--- | :--- | :--- | +| **row** | `integer` | ✅ | 1-based row number in the source data | +| **ok** | `boolean` | ✅ | Whether the row succeeded | +| **action** | `Enum<'created' \| 'updated' \| 'skipped' \| 'failed'>` | ✅ | What happened to the row | +| **id** | `string` | optional | Record id (created/updated rows) | +| **field** | `string` | optional | Field that caused a coercion/validation error | +| **code** | `string` | optional | Error code (failed rows) | +| **error** | `string` | optional | Human-readable error message (failed rows) | + + --- ## ImportValidationConfig @@ -239,6 +454,17 @@ const result = CreateExportJobRequest.parse(data); | **data** | `Object` | ✅ | | +--- + +## ImportWriteMode + +### Allowed Values + +* `insert` +* `update` +* `upsert` + + --- ## ListExportJobsRequest @@ -267,6 +493,31 @@ const result = CreateExportJobRequest.parse(data); | **data** | `Object` | ✅ | | +--- + +## ListImportJobsRequest + +### Properties + +| Property | Type | Required | Description | +| :--- | :--- | :--- | :--- | +| **object** | `string` | optional | Filter to one target object | +| **status** | `Enum<'pending' \| 'running' \| 'succeeded' \| 'failed' \| 'cancelled'>` | optional | Filter by job status | +| **limit** | `integer` | ✅ | Max rows to return | +| **offset** | `integer` | ✅ | Pagination offset | + + +--- + +## ListImportJobsResponse + +### Properties + +| Property | Type | Required | Description | +| :--- | :--- | :--- | :--- | +| **jobs** | `Object[]` | ✅ | Import jobs, newest first | + + --- ## ScheduleExportResponse @@ -283,3 +534,19 @@ const result = CreateExportJobRequest.parse(data); --- +## UndoImportJobResponse + +### Properties + +| Property | Type | Required | Description | +| :--- | :--- | :--- | :--- | +| **success** | `boolean` | ✅ | Whether the undo completed | +| **jobId** | `string` | ✅ | Import job id | +| **object** | `string` | ✅ | Target object name | +| **deleted** | `integer` | ✅ | Created records deleted | +| **restored** | `integer` | ✅ | Updated records restored to pre-import values | +| **failed** | `integer` | ✅ | Reversal operations that failed | + + +--- + diff --git a/content/docs/references/api/feed-api.mdx b/content/docs/references/api/feed-api.mdx index 167be6201a..47560d3e8e 100644 --- a/content/docs/references/api/feed-api.mdx +++ b/content/docs/references/api/feed-api.mdx @@ -3,7 +3,7 @@ title: Feed Api description: Feed Api protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Feed / Chatter API Protocol diff --git a/content/docs/references/api/graphql.mdx b/content/docs/references/api/graphql.mdx index c16e2e7a20..e70a165010 100644 --- a/content/docs/references/api/graphql.mdx +++ b/content/docs/references/api/graphql.mdx @@ -3,7 +3,7 @@ title: Graphql description: Graphql protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} GraphQL Protocol Support diff --git a/content/docs/references/api/http-cache.mdx b/content/docs/references/api/http-cache.mdx index c360dd6f73..a4e1d6145b 100644 --- a/content/docs/references/api/http-cache.mdx +++ b/content/docs/references/api/http-cache.mdx @@ -3,7 +3,7 @@ title: Http Cache description: Http Cache protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} HTTP Metadata Cache Protocol diff --git a/content/docs/references/api/http.mdx b/content/docs/references/api/http.mdx index 38f4500e39..bbbd7be6ef 100644 --- a/content/docs/references/api/http.mdx +++ b/content/docs/references/api/http.mdx @@ -3,7 +3,7 @@ title: Http description: Http protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ 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/api/http.zod.ts` diff --git a/content/docs/references/api/identity.mdx b/content/docs/references/api/identity.mdx index e3ed895405..f57cb9f9af 100644 --- a/content/docs/references/api/identity.mdx +++ b/content/docs/references/api/identity.mdx @@ -3,7 +3,7 @@ title: Identity description: Identity protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ 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/api/identity.zod.ts` diff --git a/content/docs/references/api/metadata-plugin.mdx b/content/docs/references/api/metadata-plugin.mdx index 6c49baf1f2..60b07ddd2d 100644 --- a/content/docs/references/api/metadata-plugin.mdx +++ b/content/docs/references/api/metadata-plugin.mdx @@ -3,7 +3,7 @@ title: Metadata Plugin description: Metadata Plugin protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ 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/api/metadata-plugin.zod.ts` diff --git a/content/docs/references/api/metadata.mdx b/content/docs/references/api/metadata.mdx index f6b9158387..ddba1f6c7f 100644 --- a/content/docs/references/api/metadata.mdx +++ b/content/docs/references/api/metadata.mdx @@ -3,7 +3,7 @@ title: Metadata description: Metadata protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Metadata Service Protocol diff --git a/content/docs/references/api/notification.mdx b/content/docs/references/api/notification.mdx index 3bee5250d6..063d3d6f18 100644 --- a/content/docs/references/api/notification.mdx +++ b/content/docs/references/api/notification.mdx @@ -3,7 +3,7 @@ title: Notification description: Notification protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ 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/api/notification.zod.ts` diff --git a/content/docs/references/api/object.mdx b/content/docs/references/api/object.mdx index c0f45cd70e..0b7d48412a 100644 --- a/content/docs/references/api/object.mdx +++ b/content/docs/references/api/object.mdx @@ -3,7 +3,7 @@ title: Object description: Object protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ 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/api/object.zod.ts` diff --git a/content/docs/references/api/odata.mdx b/content/docs/references/api/odata.mdx index 7a1da70a8e..f7855bb355 100644 --- a/content/docs/references/api/odata.mdx +++ b/content/docs/references/api/odata.mdx @@ -3,7 +3,7 @@ title: Odata description: Odata protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} OData v4 Protocol Support diff --git a/content/docs/references/api/package-api.mdx b/content/docs/references/api/package-api.mdx index a83b7d196b..55501ca0e3 100644 --- a/content/docs/references/api/package-api.mdx +++ b/content/docs/references/api/package-api.mdx @@ -3,7 +3,7 @@ title: Package Api description: Package Api protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} # Package API Protocol diff --git a/content/docs/references/api/package-registry.mdx b/content/docs/references/api/package-registry.mdx index fb6757a231..1c8834813a 100644 --- a/content/docs/references/api/package-registry.mdx +++ b/content/docs/references/api/package-registry.mdx @@ -3,7 +3,7 @@ title: Package Registry description: Package Registry protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ 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/api/package-registry.zod.ts` diff --git a/content/docs/references/api/plugin-rest-api.mdx b/content/docs/references/api/plugin-rest-api.mdx index 0ae63cec90..45aee6497d 100644 --- a/content/docs/references/api/plugin-rest-api.mdx +++ b/content/docs/references/api/plugin-rest-api.mdx @@ -3,7 +3,7 @@ title: Plugin Rest Api description: Plugin Rest Api protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} REST API Plugin Protocol diff --git a/content/docs/references/api/protocol.mdx b/content/docs/references/api/protocol.mdx index 94d2d35ae6..437b8d010e 100644 --- a/content/docs/references/api/protocol.mdx +++ b/content/docs/references/api/protocol.mdx @@ -3,7 +3,7 @@ title: Protocol description: Protocol protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Response for `GET /api/v1/automation/actions` (ADR-0018). diff --git a/content/docs/references/api/query-adapter.mdx b/content/docs/references/api/query-adapter.mdx index 54db49bea5..4d966b6768 100644 --- a/content/docs/references/api/query-adapter.mdx +++ b/content/docs/references/api/query-adapter.mdx @@ -3,7 +3,7 @@ title: Query Adapter description: Query Adapter protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} API Query DSL Adapter Protocol diff --git a/content/docs/references/api/realtime-shared.mdx b/content/docs/references/api/realtime-shared.mdx index b06586a391..60dd9fc9df 100644 --- a/content/docs/references/api/realtime-shared.mdx +++ b/content/docs/references/api/realtime-shared.mdx @@ -3,7 +3,7 @@ title: Realtime Shared description: Realtime Shared protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Realtime Shared Protocol diff --git a/content/docs/references/api/realtime.mdx b/content/docs/references/api/realtime.mdx index b9621db62b..e58285ef7e 100644 --- a/content/docs/references/api/realtime.mdx +++ b/content/docs/references/api/realtime.mdx @@ -3,7 +3,7 @@ title: Realtime description: Realtime protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Transport Protocol Enum diff --git a/content/docs/references/api/registry.mdx b/content/docs/references/api/registry.mdx index 0f3272baf8..4d0bd6587e 100644 --- a/content/docs/references/api/registry.mdx +++ b/content/docs/references/api/registry.mdx @@ -3,7 +3,7 @@ title: Registry description: Registry protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Unified API Registry Protocol diff --git a/content/docs/references/api/rest-server.mdx b/content/docs/references/api/rest-server.mdx index 923420de3a..c6f37442aa 100644 --- a/content/docs/references/api/rest-server.mdx +++ b/content/docs/references/api/rest-server.mdx @@ -3,7 +3,7 @@ title: Rest Server description: Rest Server protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} REST API Server Protocol diff --git a/content/docs/references/api/router.mdx b/content/docs/references/api/router.mdx index 86a3bab2f8..f81caad0ca 100644 --- a/content/docs/references/api/router.mdx +++ b/content/docs/references/api/router.mdx @@ -3,7 +3,7 @@ title: Router description: Router protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Route Category Enum diff --git a/content/docs/references/api/storage.mdx b/content/docs/references/api/storage.mdx index c76d161293..070532a186 100644 --- a/content/docs/references/api/storage.mdx +++ b/content/docs/references/api/storage.mdx @@ -3,7 +3,7 @@ title: Storage description: Storage protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Storage Service Protocol diff --git a/content/docs/references/api/versioning.mdx b/content/docs/references/api/versioning.mdx index 50c31545ed..c380786c40 100644 --- a/content/docs/references/api/versioning.mdx +++ b/content/docs/references/api/versioning.mdx @@ -3,7 +3,7 @@ title: Versioning description: Versioning protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} # API Versioning Protocol diff --git a/content/docs/references/api/websocket.mdx b/content/docs/references/api/websocket.mdx index b4b0cd61e9..1ad71725c0 100644 --- a/content/docs/references/api/websocket.mdx +++ b/content/docs/references/api/websocket.mdx @@ -3,7 +3,7 @@ title: Websocket description: Websocket protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} WebSocket Event Protocol diff --git a/content/docs/references/automation/approval.mdx b/content/docs/references/automation/approval.mdx index b3023f4baf..1ebd2ec5ac 100644 --- a/content/docs/references/automation/approval.mdx +++ b/content/docs/references/automation/approval.mdx @@ -3,7 +3,7 @@ title: Approval description: Approval protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Approval Step Approver Type diff --git a/content/docs/references/automation/bpmn-interop.mdx b/content/docs/references/automation/bpmn-interop.mdx index 2be04223a1..31fe954a61 100644 --- a/content/docs/references/automation/bpmn-interop.mdx +++ b/content/docs/references/automation/bpmn-interop.mdx @@ -3,7 +3,7 @@ title: Bpmn Interop description: Bpmn Interop protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} @module automation/bpmn-interop diff --git a/content/docs/references/automation/connector.mdx b/content/docs/references/automation/connector.mdx index 2606917346..59bea827bf 100644 --- a/content/docs/references/automation/connector.mdx +++ b/content/docs/references/automation/connector.mdx @@ -3,7 +3,7 @@ title: Connector description: Connector protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ 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/automation/connector.zod.ts` diff --git a/content/docs/references/automation/etl.mdx b/content/docs/references/automation/etl.mdx index 2facfe99ff..d28a6ed67d 100644 --- a/content/docs/references/automation/etl.mdx +++ b/content/docs/references/automation/etl.mdx @@ -3,7 +3,7 @@ title: Etl description: Etl protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} ETL (Extract, Transform, Load) Pipeline Protocol - LEVEL 2: Data Engineering diff --git a/content/docs/references/automation/execution.mdx b/content/docs/references/automation/execution.mdx index 34e1a43664..4c46580a2c 100644 --- a/content/docs/references/automation/execution.mdx +++ b/content/docs/references/automation/execution.mdx @@ -3,7 +3,7 @@ title: Execution description: Execution protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Automation Execution Protocol diff --git a/content/docs/references/automation/flow.mdx b/content/docs/references/automation/flow.mdx index 443ab3f4a6..7ca4b3d70f 100644 --- a/content/docs/references/automation/flow.mdx +++ b/content/docs/references/automation/flow.mdx @@ -3,7 +3,7 @@ title: Flow description: Flow protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Flow Node Types — **built-in seed set** (ADR-0018). diff --git a/content/docs/references/automation/job.mdx b/content/docs/references/automation/job.mdx index 86804cc9a6..8f79ea972b 100644 --- a/content/docs/references/automation/job.mdx +++ b/content/docs/references/automation/job.mdx @@ -3,7 +3,7 @@ title: Job description: Job protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ 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/automation/job.zod.ts` diff --git a/content/docs/references/automation/node-executor.mdx b/content/docs/references/automation/node-executor.mdx index 2f76b92b79..a501e949d1 100644 --- a/content/docs/references/automation/node-executor.mdx +++ b/content/docs/references/automation/node-executor.mdx @@ -3,7 +3,7 @@ title: Node Executor description: Node Executor protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} @module automation/node-executor diff --git a/content/docs/references/automation/offline.mdx b/content/docs/references/automation/offline.mdx index e0ea2e55e5..00fb908d98 100644 --- a/content/docs/references/automation/offline.mdx +++ b/content/docs/references/automation/offline.mdx @@ -3,7 +3,7 @@ title: Offline description: Offline protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ 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/automation/offline.zod.ts` diff --git a/content/docs/references/automation/state-machine.mdx b/content/docs/references/automation/state-machine.mdx index fa52e8421e..264d16daae 100644 --- a/content/docs/references/automation/state-machine.mdx +++ b/content/docs/references/automation/state-machine.mdx @@ -3,7 +3,7 @@ title: State Machine description: State Machine protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} XState-inspired State Machine Protocol diff --git a/content/docs/references/automation/sync.mdx b/content/docs/references/automation/sync.mdx index 0a3f187ad3..589c4b9ca6 100644 --- a/content/docs/references/automation/sync.mdx +++ b/content/docs/references/automation/sync.mdx @@ -3,7 +3,7 @@ title: Sync description: Sync protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Data Sync Protocol - LEVEL 1: Simple Synchronization diff --git a/content/docs/references/automation/trigger-registry.mdx b/content/docs/references/automation/trigger-registry.mdx index be7f2b1c7d..07d8c539f1 100644 --- a/content/docs/references/automation/trigger-registry.mdx +++ b/content/docs/references/automation/trigger-registry.mdx @@ -3,7 +3,7 @@ title: Trigger Registry description: Trigger Registry protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Trigger Registry Protocol diff --git a/content/docs/references/automation/webhook.mdx b/content/docs/references/automation/webhook.mdx index 66cd92062a..da84d21f92 100644 --- a/content/docs/references/automation/webhook.mdx +++ b/content/docs/references/automation/webhook.mdx @@ -3,7 +3,7 @@ title: Webhook description: Webhook protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Webhook Trigger Event diff --git a/content/docs/references/cloud/app-store.mdx b/content/docs/references/cloud/app-store.mdx index 2a6d7c80b4..0077cbc064 100644 --- a/content/docs/references/cloud/app-store.mdx +++ b/content/docs/references/cloud/app-store.mdx @@ -3,7 +3,7 @@ title: App Store description: App Store protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} # App Store Protocol (Customer Experience) diff --git a/content/docs/references/cloud/developer-portal.mdx b/content/docs/references/cloud/developer-portal.mdx index f4cc43d9f5..6dd328f84e 100644 --- a/content/docs/references/cloud/developer-portal.mdx +++ b/content/docs/references/cloud/developer-portal.mdx @@ -3,7 +3,7 @@ title: Developer Portal description: Developer Portal protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} # Developer Portal Protocol diff --git a/content/docs/references/cloud/environment-artifact.mdx b/content/docs/references/cloud/environment-artifact.mdx index 016f27efca..0bd05bb982 100644 --- a/content/docs/references/cloud/environment-artifact.mdx +++ b/content/docs/references/cloud/environment-artifact.mdx @@ -3,7 +3,7 @@ title: Environment Artifact description: Environment Artifact protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} # Environment Artifact Envelope (M1) diff --git a/content/docs/references/cloud/environment-package.mdx b/content/docs/references/cloud/environment-package.mdx index ab6279a1ca..ae3c578c32 100644 --- a/content/docs/references/cloud/environment-package.mdx +++ b/content/docs/references/cloud/environment-package.mdx @@ -3,7 +3,7 @@ title: Environment Package description: Environment Package protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} # Environment Package Installation Protocol diff --git a/content/docs/references/cloud/environment.mdx b/content/docs/references/cloud/environment.mdx index fa06b627c2..752b493fa2 100644 --- a/content/docs/references/cloud/environment.mdx +++ b/content/docs/references/cloud/environment.mdx @@ -3,7 +3,7 @@ title: Environment description: Environment protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} # Environment Protocol (runtime container) diff --git a/content/docs/references/cloud/marketplace-admin.mdx b/content/docs/references/cloud/marketplace-admin.mdx index e3974223ed..a6ca5b4da3 100644 --- a/content/docs/references/cloud/marketplace-admin.mdx +++ b/content/docs/references/cloud/marketplace-admin.mdx @@ -3,7 +3,7 @@ title: Marketplace Admin description: Marketplace Admin protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} # Marketplace Administration Protocol diff --git a/content/docs/references/cloud/marketplace.mdx b/content/docs/references/cloud/marketplace.mdx index 9e8f3d4faa..025b13d553 100644 --- a/content/docs/references/cloud/marketplace.mdx +++ b/content/docs/references/cloud/marketplace.mdx @@ -3,7 +3,7 @@ title: Marketplace description: Marketplace protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} # Marketplace Protocol diff --git a/content/docs/references/cloud/package-version.mdx b/content/docs/references/cloud/package-version.mdx index 059324cbd7..46086489ef 100644 --- a/content/docs/references/cloud/package-version.mdx +++ b/content/docs/references/cloud/package-version.mdx @@ -3,7 +3,7 @@ title: Package Version description: Package Version protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Package Version Protocol diff --git a/content/docs/references/cloud/package.mdx b/content/docs/references/cloud/package.mdx index c923d0e268..23b883252a 100644 --- a/content/docs/references/cloud/package.mdx +++ b/content/docs/references/cloud/package.mdx @@ -3,7 +3,7 @@ title: Package description: Package protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Package Identity Protocol diff --git a/content/docs/references/cloud/plugin-security.mdx b/content/docs/references/cloud/plugin-security.mdx index 1de82dab26..877edc19be 100644 --- a/content/docs/references/cloud/plugin-security.mdx +++ b/content/docs/references/cloud/plugin-security.mdx @@ -3,7 +3,7 @@ title: Plugin Security description: Plugin Security protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ 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/cloud/plugin-security.zod.ts` diff --git a/content/docs/references/cloud/provisioning.mdx b/content/docs/references/cloud/provisioning.mdx index d1634cc5de..126b63717c 100644 --- a/content/docs/references/cloud/provisioning.mdx +++ b/content/docs/references/cloud/provisioning.mdx @@ -3,7 +3,7 @@ title: Provisioning description: Provisioning protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ 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/cloud/provisioning.zod.ts` diff --git a/content/docs/references/cloud/template-manifest.mdx b/content/docs/references/cloud/template-manifest.mdx index f532919bb6..4fcaa942df 100644 --- a/content/docs/references/cloud/template-manifest.mdx +++ b/content/docs/references/cloud/template-manifest.mdx @@ -3,7 +3,7 @@ title: Template Manifest description: Template Manifest protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} `objectstack.manifest.json` — on-disk descriptor for a template / package diff --git a/content/docs/references/cloud/tenant.mdx b/content/docs/references/cloud/tenant.mdx index bafa1b6763..45eac0602f 100644 --- a/content/docs/references/cloud/tenant.mdx +++ b/content/docs/references/cloud/tenant.mdx @@ -3,7 +3,7 @@ title: Tenant description: Tenant protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Multi-Tenant Architecture Schema diff --git a/content/docs/references/data/analytics.mdx b/content/docs/references/data/analytics.mdx index bdd46a8c26..682bb2959d 100644 --- a/content/docs/references/data/analytics.mdx +++ b/content/docs/references/data/analytics.mdx @@ -3,7 +3,7 @@ title: Analytics description: Analytics protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Analytics/Semantic Layer Protocol diff --git a/content/docs/references/data/data-engine.mdx b/content/docs/references/data/data-engine.mdx index dfc16767fd..c4e6bfae52 100644 --- a/content/docs/references/data/data-engine.mdx +++ b/content/docs/references/data/data-engine.mdx @@ -3,7 +3,7 @@ title: Data Engine description: Data Engine protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Data Engine Protocol diff --git a/content/docs/references/data/datasource.mdx b/content/docs/references/data/datasource.mdx index 1ce8de7212..6d3df13f0f 100644 --- a/content/docs/references/data/datasource.mdx +++ b/content/docs/references/data/datasource.mdx @@ -3,7 +3,7 @@ title: Datasource description: Datasource protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Driver Identifier diff --git a/content/docs/references/data/date-macros.mdx b/content/docs/references/data/date-macros.mdx index 3850c072a2..410cbf97d4 100644 --- a/content/docs/references/data/date-macros.mdx +++ b/content/docs/references/data/date-macros.mdx @@ -3,7 +3,7 @@ title: Date Macros description: Date Macros protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Date Macro Tokens — the declarative placeholders the UI substitutes diff --git a/content/docs/references/data/document.mdx b/content/docs/references/data/document.mdx index 4fe2957228..fe53ddd393 100644 --- a/content/docs/references/data/document.mdx +++ b/content/docs/references/data/document.mdx @@ -3,7 +3,7 @@ title: Document description: Document protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Document Version Schema diff --git a/content/docs/references/data/driver-nosql.mdx b/content/docs/references/data/driver-nosql.mdx index d3f9dafbe4..1bd6e6ec6c 100644 --- a/content/docs/references/data/driver-nosql.mdx +++ b/content/docs/references/data/driver-nosql.mdx @@ -3,7 +3,7 @@ title: Driver Nosql description: Driver Nosql protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} NoSQL Database Type Enumeration diff --git a/content/docs/references/data/driver-sql.mdx b/content/docs/references/data/driver-sql.mdx index d8770266aa..37d288249d 100644 --- a/content/docs/references/data/driver-sql.mdx +++ b/content/docs/references/data/driver-sql.mdx @@ -3,7 +3,7 @@ title: Driver Sql description: Driver Sql protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} SQL Dialect Enumeration diff --git a/content/docs/references/data/driver.mdx b/content/docs/references/data/driver.mdx index d2037791fa..9a43861b08 100644 --- a/content/docs/references/data/driver.mdx +++ b/content/docs/references/data/driver.mdx @@ -3,7 +3,7 @@ title: Driver description: Driver protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Common Driver Options diff --git a/content/docs/references/data/external-catalog.mdx b/content/docs/references/data/external-catalog.mdx index 810b8a2674..b663340618 100644 --- a/content/docs/references/data/external-catalog.mdx +++ b/content/docs/references/data/external-catalog.mdx @@ -3,7 +3,7 @@ title: External Catalog description: External Catalog protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} ExternalCatalog — cached remote-schema snapshot for a federated datasource diff --git a/content/docs/references/data/external-lookup.mdx b/content/docs/references/data/external-lookup.mdx index 0112c12743..88a1dd9385 100644 --- a/content/docs/references/data/external-lookup.mdx +++ b/content/docs/references/data/external-lookup.mdx @@ -3,7 +3,7 @@ title: External Lookup description: External Lookup protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} External Data Source Schema diff --git a/content/docs/references/data/feed.mdx b/content/docs/references/data/feed.mdx index 6dcdf1cee5..21e9ee58ef 100644 --- a/content/docs/references/data/feed.mdx +++ b/content/docs/references/data/feed.mdx @@ -3,7 +3,7 @@ title: Feed description: Feed protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Feed Item Type diff --git a/content/docs/references/data/field.mdx b/content/docs/references/data/field.mdx index 1b901ec805..cab5a45d7f 100644 --- a/content/docs/references/data/field.mdx +++ b/content/docs/references/data/field.mdx @@ -3,7 +3,7 @@ title: Field description: Field protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Field Type Enum diff --git a/content/docs/references/data/filter.mdx b/content/docs/references/data/filter.mdx index 84853b5245..aaef8677e8 100644 --- a/content/docs/references/data/filter.mdx +++ b/content/docs/references/data/filter.mdx @@ -3,7 +3,7 @@ title: Filter description: Filter protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Unified Query DSL Specification diff --git a/content/docs/references/data/hook-body.mdx b/content/docs/references/data/hook-body.mdx index c9e4b466ee..85b6bc2e21 100644 --- a/content/docs/references/data/hook-body.mdx +++ b/content/docs/references/data/hook-body.mdx @@ -3,7 +3,7 @@ title: Hook Body description: Hook Body protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Capability tokens a script body may request. diff --git a/content/docs/references/data/hook.mdx b/content/docs/references/data/hook.mdx index 32ab4ec379..eb505018ed 100644 --- a/content/docs/references/data/hook.mdx +++ b/content/docs/references/data/hook.mdx @@ -3,7 +3,7 @@ title: Hook description: Hook protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Hook Lifecycle Events diff --git a/content/docs/references/data/mapping.mdx b/content/docs/references/data/mapping.mdx index d7e7992cb4..58357da0d8 100644 --- a/content/docs/references/data/mapping.mdx +++ b/content/docs/references/data/mapping.mdx @@ -3,7 +3,7 @@ title: Mapping description: Mapping protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Transformation Logic diff --git a/content/docs/references/data/notification.mdx b/content/docs/references/data/notification.mdx index 4c908e8532..57613fe7e9 100644 --- a/content/docs/references/data/notification.mdx +++ b/content/docs/references/data/notification.mdx @@ -3,7 +3,7 @@ title: Notification description: Notification protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ 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/data/notification.zod.ts` diff --git a/content/docs/references/data/object.mdx b/content/docs/references/data/object.mdx index d1b8afc858..66549bf583 100644 --- a/content/docs/references/data/object.mdx +++ b/content/docs/references/data/object.mdx @@ -3,7 +3,7 @@ title: Object description: Object protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} API Operations Enum @@ -14,8 +14,8 @@ API Operations Enum ## TypeScript Usage ```typescript -import { ApiMethod, Index, ObjectAccessConfig, ObjectCapabilities, ObjectExternalBinding, ObjectOwnershipEnum, PartitioningConfig, SoftDeleteConfig, TenancyConfig, VersioningConfig } from '@objectstack/spec/data'; -import type { ApiMethod, Index, ObjectAccessConfig, ObjectCapabilities, ObjectExternalBinding, ObjectOwnershipEnum, PartitioningConfig, SoftDeleteConfig, TenancyConfig, VersioningConfig } from '@objectstack/spec/data'; +import { ApiMethod, Index, ObjectAccessConfig, ObjectCapabilities, ObjectExternalBinding, ObjectFieldGroup, ObjectOwnershipEnum, SoftDeleteConfig, TenancyConfig, VersioningConfig } from '@objectstack/spec/data'; +import type { ApiMethod, Index, ObjectAccessConfig, ObjectCapabilities, ObjectExternalBinding, ObjectFieldGroup, ObjectOwnershipEnum, SoftDeleteConfig, TenancyConfig, VersioningConfig } from '@objectstack/spec/data'; // Validate data const result = ApiMethod.parse(data); @@ -109,26 +109,30 @@ External datasource binding (ADR-0015) --- -## ObjectOwnershipEnum +## ObjectFieldGroup -### Allowed Values +### Properties -* `own` -* `extend` +| Property | Type | Required | Description | +| :--- | :--- | :--- | :--- | +| **key** | `string` | ✅ | Group machine key (snake_case). Referenced by Field.group. | +| **label** | `string` | ✅ | Group display label | +| **icon** | `string` | optional | Icon name (Lucide/Material) for the group header | +| **description** | `string` | optional | Optional description shown under the group header | +| **collapse** | `Enum<'none' \| 'expanded' \| 'collapsed'>` | ✅ | [ADR-0085] Section collapse behaviour: 'none' (always open, no toggle), 'expanded' (collapsible, starts open), 'collapsed' (collapsible, starts closed). | +| **defaultExpanded** | `boolean` | optional | [DEPRECATED → collapse] true → 'expanded', false → 'collapsed'. | +| **collapsible** | `boolean` | optional | [DEPRECATED → collapse] Boolean pair with `collapsed`; use the `collapse` enum. | +| **collapsed** | `boolean` | optional | [DEPRECATED → collapse] Boolean pair with `collapsible`; use the `collapse` enum. | --- -## PartitioningConfig +## ObjectOwnershipEnum -### Properties +### Allowed Values -| Property | Type | Required | Description | -| :--- | :--- | :--- | :--- | -| **enabled** | `boolean` | ✅ | Enable table partitioning | -| **strategy** | `Enum<'range' \| 'hash' \| 'list'>` | ✅ | Partitioning strategy: range (date ranges), hash (consistent hashing), list (predefined values) | -| **key** | `string` | ✅ | Field name to partition by | -| **interval** | `string` | optional | Partition interval for range strategy (e.g., "1 month", "1 year") | +* `own` +* `extend` --- diff --git a/content/docs/references/data/query.mdx b/content/docs/references/data/query.mdx index 68ba187d3f..2724050baa 100644 --- a/content/docs/references/data/query.mdx +++ b/content/docs/references/data/query.mdx @@ -3,7 +3,7 @@ title: Query description: Query protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Sort Node diff --git a/content/docs/references/data/search-engine.mdx b/content/docs/references/data/search-engine.mdx index 3602f9bd9b..3c57784739 100644 --- a/content/docs/references/data/search-engine.mdx +++ b/content/docs/references/data/search-engine.mdx @@ -3,7 +3,7 @@ title: Search Engine description: Search Engine protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ 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/data/search-engine.zod.ts` diff --git a/content/docs/references/data/seed-loader.mdx b/content/docs/references/data/seed-loader.mdx index 7809f223ad..6986738a48 100644 --- a/content/docs/references/data/seed-loader.mdx +++ b/content/docs/references/data/seed-loader.mdx @@ -3,7 +3,7 @@ title: Seed Loader description: Seed Loader protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} # Seed Loader Protocol diff --git a/content/docs/references/data/seed.mdx b/content/docs/references/data/seed.mdx index 954d889839..950561afbd 100644 --- a/content/docs/references/data/seed.mdx +++ b/content/docs/references/data/seed.mdx @@ -3,7 +3,7 @@ title: Seed description: Seed protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Seed Import Strategy diff --git a/content/docs/references/data/subscription.mdx b/content/docs/references/data/subscription.mdx index 368f4cb15a..2f4a516461 100644 --- a/content/docs/references/data/subscription.mdx +++ b/content/docs/references/data/subscription.mdx @@ -3,7 +3,7 @@ title: Subscription description: Subscription protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Subscription Event Type diff --git a/content/docs/references/data/validation.mdx b/content/docs/references/data/validation.mdx index 9f6f1728a7..378cb14a6e 100644 --- a/content/docs/references/data/validation.mdx +++ b/content/docs/references/data/validation.mdx @@ -3,7 +3,7 @@ title: Validation description: Validation protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} # ObjectStack Validation Protocol diff --git a/content/docs/references/identity/eval-user.mdx b/content/docs/references/identity/eval-user.mdx index bef6604d4f..8874d893f8 100644 --- a/content/docs/references/identity/eval-user.mdx +++ b/content/docs/references/identity/eval-user.mdx @@ -3,7 +3,7 @@ title: Eval User description: Eval User protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} EvalUser — the one user-context contract (ADR-0068 D1). diff --git a/content/docs/references/identity/identity.mdx b/content/docs/references/identity/identity.mdx index c092f4af21..877741a416 100644 --- a/content/docs/references/identity/identity.mdx +++ b/content/docs/references/identity/identity.mdx @@ -3,7 +3,7 @@ title: Identity description: Identity protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Identity & User Model Specification diff --git a/content/docs/references/identity/organization.mdx b/content/docs/references/identity/organization.mdx index 02ea493dfd..173b2ee57a 100644 --- a/content/docs/references/identity/organization.mdx +++ b/content/docs/references/identity/organization.mdx @@ -3,7 +3,7 @@ title: Organization description: Organization protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Organization Schema (Multi-Tenant Architecture) diff --git a/content/docs/references/identity/role.mdx b/content/docs/references/identity/role.mdx index 34519e3d66..30b4c75cf5 100644 --- a/content/docs/references/identity/role.mdx +++ b/content/docs/references/identity/role.mdx @@ -3,7 +3,7 @@ title: Role description: Role protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Role Schema (aka Business Unit / Org Unit) diff --git a/content/docs/references/identity/scim.mdx b/content/docs/references/identity/scim.mdx index b745d1edfd..6103f4d46d 100644 --- a/content/docs/references/identity/scim.mdx +++ b/content/docs/references/identity/scim.mdx @@ -3,7 +3,7 @@ title: Scim description: Scim protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} # SCIM 2.0 Protocol Implementation diff --git a/content/docs/references/integration/connector.mdx b/content/docs/references/integration/connector.mdx index c36d0115c0..49016c4042 100644 --- a/content/docs/references/integration/connector.mdx +++ b/content/docs/references/integration/connector.mdx @@ -3,7 +3,7 @@ title: Connector description: Connector protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Connector Protocol - LEVEL 3: Enterprise Connector diff --git a/content/docs/references/integration/http.mdx b/content/docs/references/integration/http.mdx index 18296372d9..d9ae601891 100644 --- a/content/docs/references/integration/http.mdx +++ b/content/docs/references/integration/http.mdx @@ -3,7 +3,7 @@ title: Http description: Http protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ 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/integration/http.zod.ts` diff --git a/content/docs/references/integration/message-queue.mdx b/content/docs/references/integration/message-queue.mdx index ee32170d1c..4e9df76ec0 100644 --- a/content/docs/references/integration/message-queue.mdx +++ b/content/docs/references/integration/message-queue.mdx @@ -3,7 +3,7 @@ title: Message Queue description: Message Queue protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ 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/integration/message-queue.zod.ts` diff --git a/content/docs/references/integration/misc.mdx b/content/docs/references/integration/misc.mdx index 1970cf881e..4b83166daa 100644 --- a/content/docs/references/integration/misc.mdx +++ b/content/docs/references/integration/misc.mdx @@ -3,7 +3,7 @@ title: Misc description: Misc protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ 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/integration/misc.zod.ts` diff --git a/content/docs/references/integration/object-storage.mdx b/content/docs/references/integration/object-storage.mdx index 1bd476d75d..c2f2e95aca 100644 --- a/content/docs/references/integration/object-storage.mdx +++ b/content/docs/references/integration/object-storage.mdx @@ -3,7 +3,7 @@ title: Object Storage description: Object Storage protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ 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/integration/object-storage.zod.ts` diff --git a/content/docs/references/integration/offline.mdx b/content/docs/references/integration/offline.mdx index 13aa95db99..75736d3b07 100644 --- a/content/docs/references/integration/offline.mdx +++ b/content/docs/references/integration/offline.mdx @@ -3,7 +3,7 @@ title: Offline description: Offline protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ 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/integration/offline.zod.ts` diff --git a/content/docs/references/integration/tenant.mdx b/content/docs/references/integration/tenant.mdx index 76cd59e6f7..d7a420d1ff 100644 --- a/content/docs/references/integration/tenant.mdx +++ b/content/docs/references/integration/tenant.mdx @@ -3,7 +3,7 @@ title: Tenant description: Tenant protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ 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/integration/tenant.zod.ts` diff --git a/content/docs/references/integration/translation.mdx b/content/docs/references/integration/translation.mdx index 5fd774b916..44014d67bd 100644 --- a/content/docs/references/integration/translation.mdx +++ b/content/docs/references/integration/translation.mdx @@ -3,7 +3,7 @@ title: Translation description: Translation protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ 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/integration/translation.zod.ts` diff --git a/content/docs/references/kernel/cli-extension.mdx b/content/docs/references/kernel/cli-extension.mdx index cb4f2442a3..91eb9d47d7 100644 --- a/content/docs/references/kernel/cli-extension.mdx +++ b/content/docs/references/kernel/cli-extension.mdx @@ -3,7 +3,7 @@ title: Cli Extension description: Cli Extension protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} # CLI Extension Protocol diff --git a/content/docs/references/kernel/cluster.mdx b/content/docs/references/kernel/cluster.mdx index 08e0ffc977..1fd983ba0c 100644 --- a/content/docs/references/kernel/cluster.mdx +++ b/content/docs/references/kernel/cluster.mdx @@ -3,7 +3,7 @@ title: Cluster description: Cluster protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} # Cluster Protocol @@ -17,7 +17,7 @@ when more than one Node.js process is involved. The protocol layer codifies The full design rationale is in -`content/docs/concepts/cluster-semantics.mdx`. Read it before changing +`content/docs/kernel/cluster.mdx`. Read it before changing any of the enums here — every value has a precise contract that other diff --git a/content/docs/references/kernel/context.mdx b/content/docs/references/kernel/context.mdx index 38415c68d9..1ad09aa2d6 100644 --- a/content/docs/references/kernel/context.mdx +++ b/content/docs/references/kernel/context.mdx @@ -3,7 +3,7 @@ title: Context description: Context protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Runtime Mode Enum diff --git a/content/docs/references/kernel/dependency-resolution.mdx b/content/docs/references/kernel/dependency-resolution.mdx index 5ea50748b7..fe99584503 100644 --- a/content/docs/references/kernel/dependency-resolution.mdx +++ b/content/docs/references/kernel/dependency-resolution.mdx @@ -3,7 +3,7 @@ title: Dependency Resolution description: Dependency Resolution protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} # Dependency Resolution Protocol diff --git a/content/docs/references/kernel/dev-plugin.mdx b/content/docs/references/kernel/dev-plugin.mdx index 0fdf2af57f..7fd5a7c007 100644 --- a/content/docs/references/kernel/dev-plugin.mdx +++ b/content/docs/references/kernel/dev-plugin.mdx @@ -3,7 +3,7 @@ title: Dev Plugin description: Dev Plugin protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} # Dev Mode Plugin Protocol diff --git a/content/docs/references/kernel/execution-context.mdx b/content/docs/references/kernel/execution-context.mdx index aac3ec6025..578058afdf 100644 --- a/content/docs/references/kernel/execution-context.mdx +++ b/content/docs/references/kernel/execution-context.mdx @@ -3,7 +3,7 @@ title: Execution Context description: Execution Context protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Execution Context Schema diff --git a/content/docs/references/kernel/feature.mdx b/content/docs/references/kernel/feature.mdx index 9db726d054..acefce45ca 100644 --- a/content/docs/references/kernel/feature.mdx +++ b/content/docs/references/kernel/feature.mdx @@ -3,7 +3,7 @@ title: Feature description: Feature protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Feature Rollout Strategy diff --git a/content/docs/references/kernel/manifest.mdx b/content/docs/references/kernel/manifest.mdx index 0a5173d0d8..bfb745871a 100644 --- a/content/docs/references/kernel/manifest.mdx +++ b/content/docs/references/kernel/manifest.mdx @@ -3,7 +3,7 @@ title: Manifest description: Manifest protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Structured permission grants requested by a plugin (ADR-0025 §3.2). diff --git a/content/docs/references/kernel/metadata-customization.mdx b/content/docs/references/kernel/metadata-customization.mdx index 74e0126491..939358b4f8 100644 --- a/content/docs/references/kernel/metadata-customization.mdx +++ b/content/docs/references/kernel/metadata-customization.mdx @@ -3,7 +3,7 @@ title: Metadata Customization description: Metadata Customization protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} # Metadata Customization Layer Protocol diff --git a/content/docs/references/kernel/metadata-loader.mdx b/content/docs/references/kernel/metadata-loader.mdx index 5986a82a0a..10e82a6ffd 100644 --- a/content/docs/references/kernel/metadata-loader.mdx +++ b/content/docs/references/kernel/metadata-loader.mdx @@ -3,7 +3,7 @@ title: Metadata Loader description: Metadata Loader protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} # Metadata Loader Protocol diff --git a/content/docs/references/kernel/metadata-persistence.mdx b/content/docs/references/kernel/metadata-persistence.mdx index 9a4d512259..119ae25ebd 100644 --- a/content/docs/references/kernel/metadata-persistence.mdx +++ b/content/docs/references/kernel/metadata-persistence.mdx @@ -3,7 +3,7 @@ title: Metadata Persistence description: Metadata Persistence protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ 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/kernel/metadata-persistence.zod.ts` diff --git a/content/docs/references/kernel/metadata-plugin.mdx b/content/docs/references/kernel/metadata-plugin.mdx index 7af8f75030..14ddc15375 100644 --- a/content/docs/references/kernel/metadata-plugin.mdx +++ b/content/docs/references/kernel/metadata-plugin.mdx @@ -3,7 +3,7 @@ title: Metadata Plugin description: Metadata Plugin protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} # Metadata Plugin Protocol diff --git a/content/docs/references/kernel/metadata-protection.mdx b/content/docs/references/kernel/metadata-protection.mdx index fe52d72382..80ac089abb 100644 --- a/content/docs/references/kernel/metadata-protection.mdx +++ b/content/docs/references/kernel/metadata-protection.mdx @@ -3,7 +3,7 @@ title: Metadata Protection description: Metadata Protection protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} # Metadata Protection Model — Phase 1 (ADR-0010) diff --git a/content/docs/references/kernel/misc.mdx b/content/docs/references/kernel/misc.mdx index ac1c388efc..0ae6456abf 100644 --- a/content/docs/references/kernel/misc.mdx +++ b/content/docs/references/kernel/misc.mdx @@ -3,7 +3,7 @@ title: Misc description: Misc protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ 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/kernel/misc.zod.ts` diff --git a/content/docs/references/kernel/package-artifact.mdx b/content/docs/references/kernel/package-artifact.mdx index e3228453c8..95974896bd 100644 --- a/content/docs/references/kernel/package-artifact.mdx +++ b/content/docs/references/kernel/package-artifact.mdx @@ -3,7 +3,7 @@ title: Package Artifact description: Package Artifact protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} # Package Artifact Format Protocol diff --git a/content/docs/references/kernel/package-registry.mdx b/content/docs/references/kernel/package-registry.mdx index e19d55e9b0..f6c8e63929 100644 --- a/content/docs/references/kernel/package-registry.mdx +++ b/content/docs/references/kernel/package-registry.mdx @@ -3,7 +3,7 @@ title: Package Registry description: Package Registry protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} # Package Registry Protocol diff --git a/content/docs/references/kernel/package-upgrade.mdx b/content/docs/references/kernel/package-upgrade.mdx index 4d998b3b9f..f1d3ca6423 100644 --- a/content/docs/references/kernel/package-upgrade.mdx +++ b/content/docs/references/kernel/package-upgrade.mdx @@ -3,7 +3,7 @@ title: Package Upgrade description: Package Upgrade protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} # Package Upgrade Protocol diff --git a/content/docs/references/kernel/plugin-capability.mdx b/content/docs/references/kernel/plugin-capability.mdx index e949e28b3d..58cfc7b4bd 100644 --- a/content/docs/references/kernel/plugin-capability.mdx +++ b/content/docs/references/kernel/plugin-capability.mdx @@ -3,7 +3,7 @@ title: Plugin Capability description: Plugin Capability protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} # Plugin Capability Protocol diff --git a/content/docs/references/kernel/plugin-lifecycle-advanced.mdx b/content/docs/references/kernel/plugin-lifecycle-advanced.mdx index d9d82edc2c..43216f1bc6 100644 --- a/content/docs/references/kernel/plugin-lifecycle-advanced.mdx +++ b/content/docs/references/kernel/plugin-lifecycle-advanced.mdx @@ -3,7 +3,7 @@ title: Plugin Lifecycle Advanced description: Plugin Lifecycle Advanced protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} # Advanced Plugin Lifecycle Protocol diff --git a/content/docs/references/kernel/plugin-lifecycle-events.mdx b/content/docs/references/kernel/plugin-lifecycle-events.mdx index 2cc36c5682..73495ffa53 100644 --- a/content/docs/references/kernel/plugin-lifecycle-events.mdx +++ b/content/docs/references/kernel/plugin-lifecycle-events.mdx @@ -3,7 +3,7 @@ title: Plugin Lifecycle Events description: Plugin Lifecycle Events protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Plugin Lifecycle Events Protocol diff --git a/content/docs/references/kernel/plugin-loading.mdx b/content/docs/references/kernel/plugin-loading.mdx index cf351359cc..f4c35538a6 100644 --- a/content/docs/references/kernel/plugin-loading.mdx +++ b/content/docs/references/kernel/plugin-loading.mdx @@ -3,7 +3,7 @@ title: Plugin Loading description: Plugin Loading protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} # Plugin Loading Protocol diff --git a/content/docs/references/kernel/plugin-registry.mdx b/content/docs/references/kernel/plugin-registry.mdx index fe0673496e..d94d39714b 100644 --- a/content/docs/references/kernel/plugin-registry.mdx +++ b/content/docs/references/kernel/plugin-registry.mdx @@ -3,7 +3,7 @@ title: Plugin Registry description: Plugin Registry protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} # Plugin Registry Protocol diff --git a/content/docs/references/kernel/plugin-runtime.mdx b/content/docs/references/kernel/plugin-runtime.mdx index dddf488fe8..ee0ec896fb 100644 --- a/content/docs/references/kernel/plugin-runtime.mdx +++ b/content/docs/references/kernel/plugin-runtime.mdx @@ -3,7 +3,7 @@ title: Plugin Runtime description: Plugin Runtime protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} # Plugin Runtime Management Protocol diff --git a/content/docs/references/kernel/plugin-security-advanced.mdx b/content/docs/references/kernel/plugin-security-advanced.mdx index 0b7271d94b..9553b82af2 100644 --- a/content/docs/references/kernel/plugin-security-advanced.mdx +++ b/content/docs/references/kernel/plugin-security-advanced.mdx @@ -3,7 +3,7 @@ title: Plugin Security Advanced description: Plugin Security Advanced protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} # Plugin Security and Sandboxing Protocol diff --git a/content/docs/references/kernel/plugin-security.mdx b/content/docs/references/kernel/plugin-security.mdx index c11565cde8..02d24a8e1d 100644 --- a/content/docs/references/kernel/plugin-security.mdx +++ b/content/docs/references/kernel/plugin-security.mdx @@ -3,7 +3,7 @@ title: Plugin Security description: Plugin Security protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} # Plugin Security & Dependency Resolution Protocol diff --git a/content/docs/references/kernel/plugin-structure.mdx b/content/docs/references/kernel/plugin-structure.mdx index 9a0ed0779f..6f1c7e4b71 100644 --- a/content/docs/references/kernel/plugin-structure.mdx +++ b/content/docs/references/kernel/plugin-structure.mdx @@ -3,7 +3,7 @@ title: Plugin Structure description: Plugin Structure protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} ObjectStack Plugin Structure Standards (OPS) diff --git a/content/docs/references/kernel/plugin-validator.mdx b/content/docs/references/kernel/plugin-validator.mdx index 5a617b59c7..331b726596 100644 --- a/content/docs/references/kernel/plugin-validator.mdx +++ b/content/docs/references/kernel/plugin-validator.mdx @@ -3,7 +3,7 @@ title: Plugin Validator description: Plugin Validator protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Plugin Validator Protocol diff --git a/content/docs/references/kernel/plugin-versioning.mdx b/content/docs/references/kernel/plugin-versioning.mdx index cbab702a87..2226c315a2 100644 --- a/content/docs/references/kernel/plugin-versioning.mdx +++ b/content/docs/references/kernel/plugin-versioning.mdx @@ -3,7 +3,7 @@ title: Plugin Versioning description: Plugin Versioning protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} # Plugin Versioning and Compatibility Protocol diff --git a/content/docs/references/kernel/plugin.mdx b/content/docs/references/kernel/plugin.mdx index 60e1f214ba..615ce1ee1d 100644 --- a/content/docs/references/kernel/plugin.mdx +++ b/content/docs/references/kernel/plugin.mdx @@ -3,7 +3,7 @@ title: Plugin description: Plugin protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Upgrade Context Schema diff --git a/content/docs/references/kernel/service-registry.mdx b/content/docs/references/kernel/service-registry.mdx index 482d076962..19aa53513a 100644 --- a/content/docs/references/kernel/service-registry.mdx +++ b/content/docs/references/kernel/service-registry.mdx @@ -3,7 +3,7 @@ title: Service Registry description: Service Registry protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Service Registry Protocol diff --git a/content/docs/references/kernel/startup-orchestrator.mdx b/content/docs/references/kernel/startup-orchestrator.mdx index c784123170..b1d558007a 100644 --- a/content/docs/references/kernel/startup-orchestrator.mdx +++ b/content/docs/references/kernel/startup-orchestrator.mdx @@ -3,7 +3,7 @@ title: Startup Orchestrator description: Startup Orchestrator protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Startup Orchestrator Protocol diff --git a/content/docs/references/kernel/state-machine.mdx b/content/docs/references/kernel/state-machine.mdx index 5259c87d42..e47f220ac5 100644 --- a/content/docs/references/kernel/state-machine.mdx +++ b/content/docs/references/kernel/state-machine.mdx @@ -3,7 +3,7 @@ title: State Machine description: State Machine protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ 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/kernel/state-machine.zod.ts` diff --git a/content/docs/references/meta.json b/content/docs/references/meta.json index e42fcada24..357008a34a 100644 --- a/content/docs/references/meta.json +++ b/content/docs/references/meta.json @@ -1,7 +1,6 @@ { "title": "Reference", "icon": "FileCode", - "root": true, "pages": [ "ai", "api", diff --git a/content/docs/references/qa/testing.mdx b/content/docs/references/qa/testing.mdx index 9817bff68b..9a3fac99c4 100644 --- a/content/docs/references/qa/testing.mdx +++ b/content/docs/references/qa/testing.mdx @@ -3,7 +3,7 @@ title: Testing description: Testing protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ 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/qa/testing.zod.ts` diff --git a/content/docs/references/security/permission.mdx b/content/docs/references/security/permission.mdx index 2544554b34..8a39477531 100644 --- a/content/docs/references/security/permission.mdx +++ b/content/docs/references/security/permission.mdx @@ -3,7 +3,7 @@ title: Permission description: Permission protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Entity (Object) Level Permissions @@ -87,6 +87,8 @@ const result = FieldPermission.parse(data); | :--- | :--- | :--- | :--- | | **name** | `string` | ✅ | Permission set unique name (lowercase snake_case) | | **label** | `string` | optional | Display label | +| **packageId** | `string` | optional | [ADR-0086 D3] Owning package id for a package-shipped set (absent = env-authored) | +| **managedBy** | `Enum<'package' \| 'platform' \| 'user'>` | optional | [ADR-0086 D3] Record provenance: package (upgrade-owned metadata) vs platform/user (env config) | | **isProfile** | `boolean` | ✅ | Whether this is a user profile | | **isDefault** | `boolean` | ✅ | [ADR-0056 D7] When true, this profile is the FALLBACK assigned to authenticated users who have no explicit grants — an app declares its default access posture here instead of relying on the built-in member_default. Foundation for SSO/JIT provisioning. | | **objects** | `Record` | ✅ | Entity permissions | diff --git a/content/docs/references/security/rls.mdx b/content/docs/references/security/rls.mdx index a0e8a5f277..0bba7d4c77 100644 --- a/content/docs/references/security/rls.mdx +++ b/content/docs/references/security/rls.mdx @@ -3,7 +3,7 @@ title: Rls description: Rls protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} # Row-Level Security (RLS) Protocol diff --git a/content/docs/references/security/sharing.mdx b/content/docs/references/security/sharing.mdx index f8212aefcf..8f616ef87a 100644 --- a/content/docs/references/security/sharing.mdx +++ b/content/docs/references/security/sharing.mdx @@ -3,7 +3,7 @@ title: Sharing description: Sharing protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Organization-Wide Defaults (OWD) diff --git a/content/docs/references/security/territory.mdx b/content/docs/references/security/territory.mdx index 10d3d51cb9..e32d75ea37 100644 --- a/content/docs/references/security/territory.mdx +++ b/content/docs/references/security/territory.mdx @@ -3,7 +3,7 @@ title: Territory description: Territory protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Territory Management Protocol diff --git a/content/docs/references/shared/branded-types.mdx b/content/docs/references/shared/branded-types.mdx index 9ed69eb6ff..ec76d2c183 100644 --- a/content/docs/references/shared/branded-types.mdx +++ b/content/docs/references/shared/branded-types.mdx @@ -3,7 +3,7 @@ title: Branded Types description: Branded Types protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Branded Types for ObjectStack Identifiers diff --git a/content/docs/references/shared/enums.mdx b/content/docs/references/shared/enums.mdx index 68ce7cd481..596bc11adf 100644 --- a/content/docs/references/shared/enums.mdx +++ b/content/docs/references/shared/enums.mdx @@ -3,7 +3,7 @@ title: Enums description: Enums protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Aggregation functions used across query, data-engine, analytics, field diff --git a/content/docs/references/shared/expression.mdx b/content/docs/references/shared/expression.mdx index 197af6ede0..c3edf67907 100644 --- a/content/docs/references/shared/expression.mdx +++ b/content/docs/references/shared/expression.mdx @@ -3,7 +3,7 @@ title: Expression description: Expression protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} # Expression Protocol diff --git a/content/docs/references/shared/http.mdx b/content/docs/references/shared/http.mdx index 787aa99960..0de1470b5a 100644 --- a/content/docs/references/shared/http.mdx +++ b/content/docs/references/shared/http.mdx @@ -3,7 +3,7 @@ title: Http description: Http protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Shared HTTP Schemas diff --git a/content/docs/references/shared/identifiers.mdx b/content/docs/references/shared/identifiers.mdx index 5627e4d1c9..44feb495db 100644 --- a/content/docs/references/shared/identifiers.mdx +++ b/content/docs/references/shared/identifiers.mdx @@ -3,7 +3,7 @@ title: Identifiers description: Identifiers protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} System Identifier Schema diff --git a/content/docs/references/shared/metadata-persistence.mdx b/content/docs/references/shared/metadata-persistence.mdx index 4dc0894db5..184a882589 100644 --- a/content/docs/references/shared/metadata-persistence.mdx +++ b/content/docs/references/shared/metadata-persistence.mdx @@ -3,7 +3,7 @@ title: Metadata Persistence description: Metadata Persistence protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ 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/shared/metadata-persistence.zod.ts` diff --git a/content/docs/references/shared/metadata-types.mdx b/content/docs/references/shared/metadata-types.mdx index 1d91fcd05e..864682673e 100644 --- a/content/docs/references/shared/metadata-types.mdx +++ b/content/docs/references/shared/metadata-types.mdx @@ -3,7 +3,7 @@ title: Metadata Types description: Metadata Types protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Supported metadata file formats diff --git a/content/docs/references/shared/protection.mdx b/content/docs/references/shared/protection.mdx index 9ac16de2b7..800148c09c 100644 --- a/content/docs/references/shared/protection.mdx +++ b/content/docs/references/shared/protection.mdx @@ -3,7 +3,7 @@ title: Protection description: Protection protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} # Package-level metadata protection (ADR-0010 §3.7 — Phase 4.3) diff --git a/content/docs/references/studio/action.mdx b/content/docs/references/studio/action.mdx index 317617147f..492761a89f 100644 --- a/content/docs/references/studio/action.mdx +++ b/content/docs/references/studio/action.mdx @@ -3,7 +3,7 @@ title: Action description: Action protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ 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/studio/action.zod.ts` diff --git a/content/docs/references/studio/flow-builder.mdx b/content/docs/references/studio/flow-builder.mdx index fce617ddd8..0f7c71f5b9 100644 --- a/content/docs/references/studio/flow-builder.mdx +++ b/content/docs/references/studio/flow-builder.mdx @@ -3,7 +3,7 @@ title: Flow Builder description: Flow Builder protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} @module studio/flow-builder diff --git a/content/docs/references/studio/object-designer.mdx b/content/docs/references/studio/object-designer.mdx index 2f392d1dcd..f79eacab2c 100644 --- a/content/docs/references/studio/object-designer.mdx +++ b/content/docs/references/studio/object-designer.mdx @@ -3,7 +3,7 @@ title: Object Designer description: Object Designer protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} @module studio/object-designer diff --git a/content/docs/references/studio/plugin.mdx b/content/docs/references/studio/plugin.mdx index e0b4d16166..7b17afff77 100644 --- a/content/docs/references/studio/plugin.mdx +++ b/content/docs/references/studio/plugin.mdx @@ -3,7 +3,7 @@ title: Plugin description: Plugin protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} @module studio/plugin diff --git a/content/docs/references/system/app-install.mdx b/content/docs/references/system/app-install.mdx index 46c854b7ae..a1acedbe86 100644 --- a/content/docs/references/system/app-install.mdx +++ b/content/docs/references/system/app-install.mdx @@ -3,7 +3,7 @@ title: App Install description: App Install protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} App Installation Protocol diff --git a/content/docs/references/system/audit.mdx b/content/docs/references/system/audit.mdx index 6ecc14c71a..ebf291c9e7 100644 --- a/content/docs/references/system/audit.mdx +++ b/content/docs/references/system/audit.mdx @@ -3,7 +3,7 @@ title: Audit description: Audit protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Audit Log Architecture diff --git a/content/docs/references/system/auth-config.mdx b/content/docs/references/system/auth-config.mdx index 57f2d8241c..e34f85d4dc 100644 --- a/content/docs/references/system/auth-config.mdx +++ b/content/docs/references/system/auth-config.mdx @@ -3,7 +3,7 @@ title: Auth Config description: Auth Config protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Better-Auth Configuration Protocol diff --git a/content/docs/references/system/book.mdx b/content/docs/references/system/book.mdx index fd4c25c7f9..c4c9f321b8 100644 --- a/content/docs/references/system/book.mdx +++ b/content/docs/references/system/book.mdx @@ -3,7 +3,7 @@ title: Book description: Book protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Package Documentation Navigation — the `book` element (ADR-0046 §6). diff --git a/content/docs/references/system/cache.mdx b/content/docs/references/system/cache.mdx index a0f674edc4..cc11346266 100644 --- a/content/docs/references/system/cache.mdx +++ b/content/docs/references/system/cache.mdx @@ -3,7 +3,7 @@ title: Cache description: Cache protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Application-Level Cache Protocol diff --git a/content/docs/references/system/change-management.mdx b/content/docs/references/system/change-management.mdx index 3c42c19468..34b7e9e0ad 100644 --- a/content/docs/references/system/change-management.mdx +++ b/content/docs/references/system/change-management.mdx @@ -3,7 +3,7 @@ title: Change Management description: Change Management protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Change Type Enum diff --git a/content/docs/references/system/collaboration.mdx b/content/docs/references/system/collaboration.mdx index 58d2a86294..2b0c946b21 100644 --- a/content/docs/references/system/collaboration.mdx +++ b/content/docs/references/system/collaboration.mdx @@ -3,7 +3,7 @@ title: Collaboration description: Collaboration protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Real-Time Collaboration Protocol diff --git a/content/docs/references/system/compliance.mdx b/content/docs/references/system/compliance.mdx index 2dbfa64d4f..9a25838179 100644 --- a/content/docs/references/system/compliance.mdx +++ b/content/docs/references/system/compliance.mdx @@ -3,7 +3,7 @@ title: Compliance description: Compliance protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Compliance protocol for GDPR, CCPA, HIPAA, SOX, PCI-DSS diff --git a/content/docs/references/system/core-services.mdx b/content/docs/references/system/core-services.mdx index 097555c0a2..98a1707459 100644 --- a/content/docs/references/system/core-services.mdx +++ b/content/docs/references/system/core-services.mdx @@ -3,7 +3,7 @@ title: Core Services description: Core Services protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} # Service Registry Protocol diff --git a/content/docs/references/system/deploy-bundle.mdx b/content/docs/references/system/deploy-bundle.mdx index 1dd08ca723..9b3e142221 100644 --- a/content/docs/references/system/deploy-bundle.mdx +++ b/content/docs/references/system/deploy-bundle.mdx @@ -3,7 +3,7 @@ title: Deploy Bundle description: Deploy Bundle protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Deploy Bundle Protocol diff --git a/content/docs/references/system/disaster-recovery.mdx b/content/docs/references/system/disaster-recovery.mdx index 0b1d0f3308..e61d13021d 100644 --- a/content/docs/references/system/disaster-recovery.mdx +++ b/content/docs/references/system/disaster-recovery.mdx @@ -3,7 +3,7 @@ title: Disaster Recovery description: Disaster Recovery protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Backup Strategy Schema diff --git a/content/docs/references/system/doc.mdx b/content/docs/references/system/doc.mdx index e07857e682..4cb22838e2 100644 --- a/content/docs/references/system/doc.mdx +++ b/content/docs/references/system/doc.mdx @@ -3,7 +3,7 @@ title: Doc description: Doc protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Package Documentation Metadata Protocol (ADR-0046) diff --git a/content/docs/references/system/email-config.mdx b/content/docs/references/system/email-config.mdx index 18634825dc..d7954735f5 100644 --- a/content/docs/references/system/email-config.mdx +++ b/content/docs/references/system/email-config.mdx @@ -3,7 +3,7 @@ title: Email Config description: Email Config protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Email Service Configuration Protocol diff --git a/content/docs/references/system/email-template.mdx b/content/docs/references/system/email-template.mdx index 41f90d3a10..3a4ccd7538 100644 --- a/content/docs/references/system/email-template.mdx +++ b/content/docs/references/system/email-template.mdx @@ -3,7 +3,7 @@ title: Email Template description: Email Template protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Email Template Metadata Protocol diff --git a/content/docs/references/system/encryption.mdx b/content/docs/references/system/encryption.mdx index 98682a25ed..093ce24325 100644 --- a/content/docs/references/system/encryption.mdx +++ b/content/docs/references/system/encryption.mdx @@ -3,7 +3,7 @@ title: Encryption description: Encryption protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Field-level encryption protocol diff --git a/content/docs/references/system/environment-artifact.mdx b/content/docs/references/system/environment-artifact.mdx index c8fa40e31f..5297955ba0 100644 --- a/content/docs/references/system/environment-artifact.mdx +++ b/content/docs/references/system/environment-artifact.mdx @@ -3,7 +3,7 @@ title: Environment Artifact description: Environment Artifact protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} # Environment Artifact Format Protocol (v0) diff --git a/content/docs/references/system/http-server.mdx b/content/docs/references/system/http-server.mdx index 2c2397b343..60e98c9fd9 100644 --- a/content/docs/references/system/http-server.mdx +++ b/content/docs/references/system/http-server.mdx @@ -3,7 +3,7 @@ title: Http Server description: Http Server protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} HTTP Server Protocol diff --git a/content/docs/references/system/incident-response.mdx b/content/docs/references/system/incident-response.mdx index 6e63dd52e3..2fb53ac205 100644 --- a/content/docs/references/system/incident-response.mdx +++ b/content/docs/references/system/incident-response.mdx @@ -3,7 +3,7 @@ title: Incident Response description: Incident Response protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Incident Response Protocol — ISO 27001:2022 (A.5.24–A.5.28) diff --git a/content/docs/references/system/job.mdx b/content/docs/references/system/job.mdx index 83f114d739..1dbd6d5b32 100644 --- a/content/docs/references/system/job.mdx +++ b/content/docs/references/system/job.mdx @@ -3,7 +3,7 @@ title: Job description: Job protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Cron Schedule Schema diff --git a/content/docs/references/system/license.mdx b/content/docs/references/system/license.mdx index fa4f09aea1..2ce838f6f0 100644 --- a/content/docs/references/system/license.mdx +++ b/content/docs/references/system/license.mdx @@ -3,7 +3,7 @@ title: License description: License protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Metric Type Classification diff --git a/content/docs/references/system/logging.mdx b/content/docs/references/system/logging.mdx index 183ceb0e42..3e03bb6ac0 100644 --- a/content/docs/references/system/logging.mdx +++ b/content/docs/references/system/logging.mdx @@ -3,7 +3,7 @@ title: Logging description: Logging protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Logging Protocol - Comprehensive Observability Logging diff --git a/content/docs/references/system/masking.mdx b/content/docs/references/system/masking.mdx index d3825a3ed3..c3efcb2d36 100644 --- a/content/docs/references/system/masking.mdx +++ b/content/docs/references/system/masking.mdx @@ -3,7 +3,7 @@ title: Masking description: Masking protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Data masking protocol for PII protection diff --git a/content/docs/references/system/message-queue.mdx b/content/docs/references/system/message-queue.mdx index 0f89b5bf99..a3356c408a 100644 --- a/content/docs/references/system/message-queue.mdx +++ b/content/docs/references/system/message-queue.mdx @@ -3,7 +3,7 @@ title: Message Queue description: Message Queue protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Message queue protocol for async communication diff --git a/content/docs/references/system/metadata-loader.mdx b/content/docs/references/system/metadata-loader.mdx index 822ae942f8..41d4550607 100644 --- a/content/docs/references/system/metadata-loader.mdx +++ b/content/docs/references/system/metadata-loader.mdx @@ -3,7 +3,7 @@ title: Metadata Loader description: Metadata Loader protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ 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/system/metadata-loader.zod.ts` diff --git a/content/docs/references/system/metadata-persistence.mdx b/content/docs/references/system/metadata-persistence.mdx index 2567ea3e32..d6d77def4b 100644 --- a/content/docs/references/system/metadata-persistence.mdx +++ b/content/docs/references/system/metadata-persistence.mdx @@ -3,7 +3,7 @@ title: Metadata Persistence description: Metadata Persistence protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Metadata Scope Enum diff --git a/content/docs/references/system/metrics.mdx b/content/docs/references/system/metrics.mdx index 390e6caf2e..ad9d8a2515 100644 --- a/content/docs/references/system/metrics.mdx +++ b/content/docs/references/system/metrics.mdx @@ -3,7 +3,7 @@ title: Metrics description: Metrics protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Metrics Protocol - Performance and Operational Metrics diff --git a/content/docs/references/system/migration.mdx b/content/docs/references/system/migration.mdx index 729b6a67ab..c669c8db80 100644 --- a/content/docs/references/system/migration.mdx +++ b/content/docs/references/system/migration.mdx @@ -3,7 +3,7 @@ title: Migration description: Migration protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ 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/system/migration.zod.ts` diff --git a/content/docs/references/system/notification.mdx b/content/docs/references/system/notification.mdx index 350510141c..d6aadf3a1e 100644 --- a/content/docs/references/system/notification.mdx +++ b/content/docs/references/system/notification.mdx @@ -3,7 +3,7 @@ title: Notification description: Notification protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Email Template Schema diff --git a/content/docs/references/system/object-storage.mdx b/content/docs/references/system/object-storage.mdx index 4a9f30720f..3eb99bd5c4 100644 --- a/content/docs/references/system/object-storage.mdx +++ b/content/docs/references/system/object-storage.mdx @@ -3,7 +3,7 @@ title: Object Storage description: Object Storage protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Object Storage Protocol diff --git a/content/docs/references/system/provisioning.mdx b/content/docs/references/system/provisioning.mdx index dad34f06f2..74fa57ff71 100644 --- a/content/docs/references/system/provisioning.mdx +++ b/content/docs/references/system/provisioning.mdx @@ -3,7 +3,7 @@ title: Provisioning description: Provisioning protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Tenant Provisioning Protocol diff --git a/content/docs/references/system/registry-config.mdx b/content/docs/references/system/registry-config.mdx index fdec5b9db4..aa04382f5d 100644 --- a/content/docs/references/system/registry-config.mdx +++ b/content/docs/references/system/registry-config.mdx @@ -3,7 +3,7 @@ title: Registry Config description: Registry Config protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} # Registry Configuration Protocol diff --git a/content/docs/references/system/search-engine.mdx b/content/docs/references/system/search-engine.mdx index 4e7becc698..27abe86f63 100644 --- a/content/docs/references/system/search-engine.mdx +++ b/content/docs/references/system/search-engine.mdx @@ -3,7 +3,7 @@ title: Search Engine description: Search Engine protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Full-text search protocol diff --git a/content/docs/references/system/security-context.mdx b/content/docs/references/system/security-context.mdx index 0b7616332b..e8c11f0a00 100644 --- a/content/docs/references/system/security-context.mdx +++ b/content/docs/references/system/security-context.mdx @@ -3,7 +3,7 @@ title: Security Context description: Security Context protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Unified Security Context Protocol diff --git a/content/docs/references/system/settings-client.mdx b/content/docs/references/system/settings-client.mdx index 91546e49c1..92b8f76609 100644 --- a/content/docs/references/system/settings-client.mdx +++ b/content/docs/references/system/settings-client.mdx @@ -3,7 +3,7 @@ title: Settings Client description: Settings Client protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} SettingsClient — reactive consumer contract for runtime settings. diff --git a/content/docs/references/system/settings-manifest.mdx b/content/docs/references/system/settings-manifest.mdx index 39c26fddf3..cc5d0a34fa 100644 --- a/content/docs/references/system/settings-manifest.mdx +++ b/content/docs/references/system/settings-manifest.mdx @@ -3,7 +3,7 @@ title: Settings Manifest description: Settings Manifest protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Settings Manifest Protocol diff --git a/content/docs/references/system/supplier-security.mdx b/content/docs/references/system/supplier-security.mdx index 0ab688926d..89fb5665b7 100644 --- a/content/docs/references/system/supplier-security.mdx +++ b/content/docs/references/system/supplier-security.mdx @@ -3,7 +3,7 @@ title: Supplier Security description: Supplier Security protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Supplier Security Protocol — ISO 27001:2022 (A.5.19–A.5.22) diff --git a/content/docs/references/system/tenant.mdx b/content/docs/references/system/tenant.mdx index add7d871ef..3506e63e67 100644 --- a/content/docs/references/system/tenant.mdx +++ b/content/docs/references/system/tenant.mdx @@ -3,7 +3,7 @@ title: Tenant description: Tenant protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Tenant Schema (Multi-Tenant Architecture) diff --git a/content/docs/references/system/tracing.mdx b/content/docs/references/system/tracing.mdx index 3379620c38..bd185e56b2 100644 --- a/content/docs/references/system/tracing.mdx +++ b/content/docs/references/system/tracing.mdx @@ -3,7 +3,7 @@ title: Tracing description: Tracing protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Tracing Protocol - Distributed Tracing & Observability diff --git a/content/docs/references/system/training.mdx b/content/docs/references/system/training.mdx index d59192e5c6..31ddc49cf9 100644 --- a/content/docs/references/system/training.mdx +++ b/content/docs/references/system/training.mdx @@ -3,7 +3,7 @@ title: Training description: Training protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Information Security Training Protocol — ISO 27001:2022 (A.6.3) diff --git a/content/docs/references/system/translation.mdx b/content/docs/references/system/translation.mdx index 1aefe92dfa..81d5f348f9 100644 --- a/content/docs/references/system/translation.mdx +++ b/content/docs/references/system/translation.mdx @@ -3,7 +3,7 @@ title: Translation description: Translation protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Field Translation Schema diff --git a/content/docs/references/system/worker.mdx b/content/docs/references/system/worker.mdx index d26bfa9584..85c521be41 100644 --- a/content/docs/references/system/worker.mdx +++ b/content/docs/references/system/worker.mdx @@ -3,7 +3,7 @@ title: Worker description: Worker protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Worker System Protocol diff --git a/content/docs/references/ui/action.mdx b/content/docs/references/ui/action.mdx index ca09b79647..86d676c680 100644 --- a/content/docs/references/ui/action.mdx +++ b/content/docs/references/ui/action.mdx @@ -3,7 +3,7 @@ title: Action description: Action protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Action Parameter Schema diff --git a/content/docs/references/ui/animation.mdx b/content/docs/references/ui/animation.mdx index d01dd2a667..adf61c0a3b 100644 --- a/content/docs/references/ui/animation.mdx +++ b/content/docs/references/ui/animation.mdx @@ -3,7 +3,7 @@ title: Animation description: Animation protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Transition Preset Schema diff --git a/content/docs/references/ui/app.mdx b/content/docs/references/ui/app.mdx index c84f1de3b1..106aff2f00 100644 --- a/content/docs/references/ui/app.mdx +++ b/content/docs/references/ui/app.mdx @@ -3,7 +3,7 @@ title: App description: App protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Base Navigation Item Schema diff --git a/content/docs/references/ui/chart.mdx b/content/docs/references/ui/chart.mdx index 9653c391d5..8d2f2555e9 100644 --- a/content/docs/references/ui/chart.mdx +++ b/content/docs/references/ui/chart.mdx @@ -3,7 +3,7 @@ title: Chart description: Chart protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Unified Chart Type Taxonomy diff --git a/content/docs/references/ui/component.mdx b/content/docs/references/ui/component.mdx index 8e6b17a972..71d6bf9f3c 100644 --- a/content/docs/references/ui/component.mdx +++ b/content/docs/references/ui/component.mdx @@ -3,7 +3,7 @@ title: Component description: Component protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Empty Properties Schema @@ -274,7 +274,7 @@ const result = AIChatWindowProps.parse(data); | Property | Type | Required | Description | | :--- | :--- | :--- | :--- | | **columns** | `Enum<'1' \| '2' \| '3' \| '4'>` | ✅ | Number of columns for field layout (1-4) | -| **layout** | `Enum<'auto' \| 'custom'>` | ✅ | Layout mode: auto uses object highlightFields (formerly compactLayout), custom uses explicit sections | +| **layout** | `Enum<'auto' \| 'custom'>` | ✅ | Layout mode: auto uses object highlightFields, custom uses explicit sections | | **sections** | `string[]` | optional | Section IDs to show (required when layout is "custom") | | **fields** | `string[]` | optional | Explicit field list to display (optional, overrides highlightFields) | | **aria** | `Object` | optional | ARIA accessibility attributes | diff --git a/content/docs/references/ui/dashboard.mdx b/content/docs/references/ui/dashboard.mdx index 2a9095db14..32f968a405 100644 --- a/content/docs/references/ui/dashboard.mdx +++ b/content/docs/references/ui/dashboard.mdx @@ -3,7 +3,7 @@ title: Dashboard description: Dashboard protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Color variant for dashboard widgets (e.g., KPI cards). diff --git a/content/docs/references/ui/dataset.mdx b/content/docs/references/ui/dataset.mdx index c3731c0d44..fb98a3b0bf 100644 --- a/content/docs/references/ui/dataset.mdx +++ b/content/docs/references/ui/dataset.mdx @@ -3,7 +3,7 @@ title: Dataset description: Dataset protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Analytics Dataset — the one semantic layer (ADR-0021). diff --git a/content/docs/references/ui/dnd.mdx b/content/docs/references/ui/dnd.mdx index 4869e20016..05fc8eb4d2 100644 --- a/content/docs/references/ui/dnd.mdx +++ b/content/docs/references/ui/dnd.mdx @@ -3,7 +3,7 @@ title: Dnd description: Dnd protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Drag Handle Schema diff --git a/content/docs/references/ui/http.mdx b/content/docs/references/ui/http.mdx index 7d7b891031..5d5b81ce53 100644 --- a/content/docs/references/ui/http.mdx +++ b/content/docs/references/ui/http.mdx @@ -3,7 +3,7 @@ title: Http description: Http protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ 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/ui/http.zod.ts` diff --git a/content/docs/references/ui/i18n.mdx b/content/docs/references/ui/i18n.mdx index 9c3748c85b..3a79b31caf 100644 --- a/content/docs/references/ui/i18n.mdx +++ b/content/docs/references/ui/i18n.mdx @@ -3,7 +3,7 @@ title: I18n description: I18n protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} I18n Object Schema diff --git a/content/docs/references/ui/keyboard.mdx b/content/docs/references/ui/keyboard.mdx index 497e42a0d2..b090fe6679 100644 --- a/content/docs/references/ui/keyboard.mdx +++ b/content/docs/references/ui/keyboard.mdx @@ -3,7 +3,7 @@ title: Keyboard description: Keyboard protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Focus Trap Configuration Schema diff --git a/content/docs/references/ui/notification.mdx b/content/docs/references/ui/notification.mdx index 3ad62625a4..6fa16f4e17 100644 --- a/content/docs/references/ui/notification.mdx +++ b/content/docs/references/ui/notification.mdx @@ -3,7 +3,7 @@ title: Notification description: Notification protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Notification Type Schema diff --git a/content/docs/references/ui/offline.mdx b/content/docs/references/ui/offline.mdx index 833db7a313..8db809406a 100644 --- a/content/docs/references/ui/offline.mdx +++ b/content/docs/references/ui/offline.mdx @@ -3,7 +3,7 @@ title: Offline description: Offline protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Offline Strategy Schema diff --git a/content/docs/references/ui/page.mdx b/content/docs/references/ui/page.mdx index c1ef342941..d96ee68eec 100644 --- a/content/docs/references/ui/page.mdx +++ b/content/docs/references/ui/page.mdx @@ -3,7 +3,7 @@ title: Page description: Page protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Page Region Schema diff --git a/content/docs/references/ui/portal.mdx b/content/docs/references/ui/portal.mdx index 0ef5c0d041..71ec42d035 100644 --- a/content/docs/references/ui/portal.mdx +++ b/content/docs/references/ui/portal.mdx @@ -3,7 +3,7 @@ title: Portal description: Portal protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} @module ui/portal diff --git a/content/docs/references/ui/report.mdx b/content/docs/references/ui/report.mdx index 73dd784409..619a47ba07 100644 --- a/content/docs/references/ui/report.mdx +++ b/content/docs/references/ui/report.mdx @@ -3,7 +3,7 @@ title: Report description: Report protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Report Type Enum diff --git a/content/docs/references/ui/responsive.mdx b/content/docs/references/ui/responsive.mdx index 93e133351e..6ff01d2bd6 100644 --- a/content/docs/references/ui/responsive.mdx +++ b/content/docs/references/ui/responsive.mdx @@ -3,7 +3,7 @@ title: Responsive description: Responsive protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Breakpoint Name Enum diff --git a/content/docs/references/ui/sharing.mdx b/content/docs/references/ui/sharing.mdx index 6e293cda38..2eaf5999ac 100644 --- a/content/docs/references/ui/sharing.mdx +++ b/content/docs/references/ui/sharing.mdx @@ -3,7 +3,7 @@ title: Sharing description: Sharing protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} @module ui/sharing diff --git a/content/docs/references/ui/theme.mdx b/content/docs/references/ui/theme.mdx index 1f0f3bf25e..9ebe78fce0 100644 --- a/content/docs/references/ui/theme.mdx +++ b/content/docs/references/ui/theme.mdx @@ -3,7 +3,7 @@ title: Theme description: Theme protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Color Palette Schema diff --git a/content/docs/references/ui/touch.mdx b/content/docs/references/ui/touch.mdx index d787cd8582..9f20c191bd 100644 --- a/content/docs/references/ui/touch.mdx +++ b/content/docs/references/ui/touch.mdx @@ -3,7 +3,7 @@ title: Touch description: Touch protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Touch Target Configuration Schema diff --git a/content/docs/references/ui/view.mdx b/content/docs/references/ui/view.mdx index 78d87ea58b..ab507dcefc 100644 --- a/content/docs/references/ui/view.mdx +++ b/content/docs/references/ui/view.mdx @@ -3,7 +3,7 @@ title: View description: View protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} HTTP Method Enum & HTTP Request Schema @@ -353,6 +353,7 @@ User action toggles for the view toolbar | **filter** | `boolean` | ✅ | Allow users to filter records | | **rowHeight** | `boolean` | ✅ | Allow users to toggle row height/density | | **addRecordForm** | `boolean` | ✅ | Add records through a form instead of inline | +| **editInline** | `boolean` | ✅ | Allow users to edit records inline — click a cell to edit it with the field's type-aware widget (the same control the form uses). Off by default: the list is read-only unless the author opts in. | | **buttons** | `string[]` | optional | Custom action button IDs to show in the toolbar | diff --git a/content/docs/references/ui/widget.mdx b/content/docs/references/ui/widget.mdx index 1c96e0fee9..9b4a8439ce 100644 --- a/content/docs/references/ui/widget.mdx +++ b/content/docs/references/ui/widget.mdx @@ -3,7 +3,7 @@ title: Widget description: Widget protocol schemas --- -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} Widget Lifecycle Hooks Schema diff --git a/content/docs/concepts/implementation-status.mdx b/content/docs/releases/implementation-status.mdx similarity index 99% rename from content/docs/concepts/implementation-status.mdx rename to content/docs/releases/implementation-status.mdx index ab683a9f99..91e41a9db4 100644 --- a/content/docs/concepts/implementation-status.mdx +++ b/content/docs/releases/implementation-status.mdx @@ -298,7 +298,7 @@ The `auth` service in `CoreServiceName` covers both **authentication** (identity The in-UI AI **runtime** below (`@objectstack/service-ai`) moved to the **cloud / Enterprise** distribution — see cloud ADR-0025 (`service-ai → cloud; open = MCP-only`). The agent / skill / tool **schemas** stay open in `@objectstack/spec/ai`; -the **open edition** exposes AI via [`@objectstack/mcp`](../guides/ai-capabilities) +the **open edition** exposes AI via [`@objectstack/mcp`](/docs/ai) (BYO-AI). The Implementation / Status columns describe the runtime as it ships in cloud / EE. diff --git a/content/docs/releases/meta.json b/content/docs/releases/meta.json index 2e16742ada..4df96025f5 100644 --- a/content/docs/releases/meta.json +++ b/content/docs/releases/meta.json @@ -1,6 +1,5 @@ { "title": "Releases", "icon": "Tag", - "root": true, - "pages": ["index", "v9"] + "pages": ["index", "v9", "implementation-status"] } diff --git a/content/docs/releases/v9.mdx b/content/docs/releases/v9.mdx index 1128cde5f6..74393c7b90 100644 --- a/content/docs/releases/v9.mdx +++ b/content/docs/releases/v9.mdx @@ -34,7 +34,7 @@ Removed from the spec: 1. For each inline query, create a dataset with `defineDataset(...)` declaring its dimensions and measures. See the - [Analytics Datasets guide](/docs/guides/analytics-datasets). + [Analytics Datasets guide](/docs/data-modeling/analytics). 2. Point the widget/report/chart at it: `dataset: ""`, pick `values` (measure names) and `dimensions`/`rows` (dimension names). 3. Presentation-scope filtering goes through the widget's `filter`, which is @@ -75,7 +75,7 @@ settings-namespace environment overrides. Rename your deployment variables: | `FEATURE_FLAGS_AI_ENABLED` | `OS_FEATURE_FLAGS_AI_ENABLED` | The general rule: `OS_` + namespace + key, upper-snake-cased. See the -[Environment Variables guide](/docs/guides/environment-variables). +[Environment Variables guide](/docs/deployment/environment-variables). ### 4. `@object-ui/plugin-workflow` removed @@ -141,7 +141,7 @@ Existing tools that never emit behave exactly as before. runtime configuration and exposes an extension hook for provider packages. Google sign-in works out of the box — configure it in **Setup → Authentication** or via deployment-level `GOOGLE_CLIENT_ID` / -`GOOGLE_CLIENT_SECRET`. See [Auth & SSO](/docs/guides/auth-sso). +`GOOGLE_CLIENT_SECRET`. See [Auth & SSO](/docs/permissions/sso). ### CLI: AI provider SDKs bundled @@ -212,7 +212,7 @@ distribution. 1. Update all `@objectstack/*` dependencies to `^9.0.0` (they are version-locked — upgrade them together). 2. Migrate inline dashboard widgets, reports, and list charts to named - datasets ([guide](/docs/guides/analytics-datasets)). + datasets ([guide](/docs/data-modeling/analytics)). 3. Replace removed chart types with their base family (table above). 4. Rename settings env vars to the `OS__` form. 5. Re-run your app's spec validation (`os validate`) — it will flag any diff --git a/content/docs/guides/metadata/app.mdx b/content/docs/ui/apps.mdx similarity index 95% rename from content/docs/guides/metadata/app.mdx rename to content/docs/ui/apps.mdx index 6369a62c81..126c14b83f 100644 --- a/content/docs/guides/metadata/app.mdx +++ b/content/docs/ui/apps.mdx @@ -219,7 +219,7 @@ const projectApp = { ## Related -- [Page Metadata](./page) — Custom pages referenced from navigation -- [Dashboard Metadata](./dashboard) — Dashboards referenced from navigation -- [View Metadata](./view) — Views displayed within navigation items -- [Permission Metadata](./permission) — Access control for apps +- [Page Metadata](/docs/ui/pages) — Custom pages referenced from navigation +- [Dashboard Metadata](/docs/ui/dashboards) — Dashboards referenced from navigation +- [View Metadata](/docs/ui/views) — Views displayed within navigation items +- [Permission Metadata](/docs/permissions/permission-metadata) — Access control for apps diff --git a/content/docs/guides/solutions/create-vs-edit-form.mdx b/content/docs/ui/create-vs-edit-form.mdx similarity index 98% rename from content/docs/guides/solutions/create-vs-edit-form.mdx rename to content/docs/ui/create-vs-edit-form.mdx index 3f28f6628c..164abc3154 100644 --- a/content/docs/guides/solutions/create-vs-edit-form.mdx +++ b/content/docs/ui/create-vs-edit-form.mdx @@ -113,5 +113,5 @@ Rule of thumb: **"different field subset" → derive. "different layout or flow" ## See also - Decision record: **ADR-0047** (object UI run modes — derive-default + override). -- [Field grouping & order](/docs/guides/solutions/field-grouping-and-order) — the three different meanings of "group". +- [Field grouping & order](/docs/ui/field-grouping-and-order) — the three different meanings of "group". - Reference: [View / FormView schema](/docs/references/ui/view), [Field schema](/docs/references/data/field). diff --git a/content/docs/guides/metadata/dashboard.mdx b/content/docs/ui/dashboards.mdx similarity index 98% rename from content/docs/guides/metadata/dashboard.mdx rename to content/docs/ui/dashboards.mdx index 2a81ade42d..c22c9c47e9 100644 --- a/content/docs/guides/metadata/dashboard.mdx +++ b/content/docs/ui/dashboards.mdx @@ -401,6 +401,6 @@ const projectDashboard = { ## Related -- [App Metadata](./app) — Reference dashboards in app navigation -- [View Metadata](./view) — List views for record browsing -- [Page Metadata](./page) — Custom pages with component layouts +- [App Metadata](/docs/ui/apps) — Reference dashboards in app navigation +- [View Metadata](/docs/ui/views) — List views for record browsing +- [Page Metadata](/docs/ui/pages) — Custom pages with component layouts diff --git a/content/docs/guides/metadata/doc.mdx b/content/docs/ui/doc-pages.mdx similarity index 100% rename from content/docs/guides/metadata/doc.mdx rename to content/docs/ui/doc-pages.mdx diff --git a/content/docs/guides/solutions/field-grouping-and-order.mdx b/content/docs/ui/field-grouping-and-order.mdx similarity index 96% rename from content/docs/guides/solutions/field-grouping-and-order.mdx rename to content/docs/ui/field-grouping-and-order.mdx index 028b25f643..20569a6df7 100644 --- a/content/docs/guides/solutions/field-grouping-and-order.mdx +++ b/content/docs/ui/field-grouping-and-order.mdx @@ -49,7 +49,7 @@ form: { ### Order is the order you author in -There is **no `field.order`**. The order you declare fields in the object **is** the default display order everywhere — and form `sections` (and the fields within them) are themselves an ordered list, so group order and intra-group order are captured at authoring time. Both the create and edit projections inherit that order, which keeps "quick-create subset" and "full form" visually continuous (see [Create form ≠ edit form](/docs/guides/solutions/create-vs-edit-form)). +There is **no `field.order`**. The order you declare fields in the object **is** the default display order everywhere — and form `sections` (and the fields within them) are themselves an ordered list, so group order and intra-group order are captured at authoring time. Both the create and edit projections inherit that order, which keeps "quick-create subset" and "full form" visually continuous (see [Create form ≠ edit form](/docs/ui/create-vs-edit-form)). ## The trap: a table's "group" is a *different thing* @@ -79,6 +79,6 @@ Keeping grouping off the field (beyond an optional semantic hint) is what lets * ## See also -- [Create form ≠ edit form](/docs/guides/solutions/create-vs-edit-form). +- [Create form ≠ edit form](/docs/ui/create-vs-edit-form). - Reference: [Field schema](/docs/references/data/field) (`group`), [View schema](/docs/references/ui/view) (`sections`, `grouping`). - Studio: [Object Designer](/docs/references/studio/object-designer) — field editor groups by `field.group`. diff --git a/content/docs/guides/public-forms.mdx b/content/docs/ui/forms.mdx similarity index 98% rename from content/docs/guides/public-forms.mdx rename to content/docs/ui/forms.mdx index 99841477f9..32b9b099b2 100644 --- a/content/docs/guides/public-forms.mdx +++ b/content/docs/ui/forms.mdx @@ -393,5 +393,5 @@ entry (`/forms/:name`). - [`skills/objectstack-ui/SKILL.md`](https://github.com/objectstack-ai/framework/tree/main/skills/objectstack-ui) — full FormView schema reference. - [`skills/objectstack-data/SKILL.md`](https://github.com/objectstack-ai/framework/tree/main/skills/objectstack-data) — object, hook + permission-set authoring patterns. -- [Hook & Action Bodies](./hook-bodies) — what runs in the sandbox vs. the host. -- [Security](./security) — RBAC, profiles, and the `anonymous` execution context. +- [Hook & Action Bodies](/docs/automation/hook-bodies) — what runs in the sandbox vs. the host. +- [Security](/docs/permissions) — RBAC, profiles, and the `anonymous` execution context. diff --git a/content/docs/ui/index.mdx b/content/docs/ui/index.mdx new file mode 100644 index 0000000000..b512e1951e --- /dev/null +++ b/content/docs/ui/index.mdx @@ -0,0 +1,43 @@ +--- +title: UI Engine +description: Apps, pages, views, dashboards, and forms — server-driven UI declared as metadata and rendered by the ObjectUI runtime. +--- + +# UI Engine + +The UI engine turns metadata into user interfaces: you declare **apps**, **pages**, **views**, and **dashboards** as data, and any compliant renderer draws them. This module is the practical documentation for the **ObjectUI layer** — the UI Protocol described normatively in the [ObjectUI spec](/docs/protocol/objectui). Because the UI is data, it ships inside the same artifact as your schema, respects the same permissions, and can be generated or modified by AI agents through the same typed surface. + +## The building blocks + +- An **App** groups navigation, branding, and entry points for one audience. +- **Views** present object records as list, form, kanban, or calendar; **Pages** compose free-form layouts from widgets. +- **Dashboards** combine charts and datasets for analytics. +- **Forms** capture data — both internal record forms and public, unauthenticated collection forms. +- The **Setup App** is the platform's built-in administration UI, itself rendered from the same protocol. + +## What's in this module + + + + + + + + + + + +### Recipes + + + + + + + + +## Related + +- **Spec:** [UI as Data Concept](/docs/protocol/objectui/concept), [Layout DSL](/docs/protocol/objectui/layout-dsl), [Action Protocol](/docs/protocol/objectui/actions), [Widget Contract](/docs/protocol/objectui/widget-contract) +- **Schema reference:** [UI](/docs/references/ui), [Studio](/docs/references/studio) +- **Neighbors:** the records a view shows come from [Data Modeling](/docs/data-modeling); what a user is allowed to see is decided by [Permissions & Identity](/docs/permissions); buttons that run logic call into [Automation](/docs/automation). diff --git a/content/docs/ui/meta.json b/content/docs/ui/meta.json new file mode 100644 index 0000000000..24ee2654d9 --- /dev/null +++ b/content/docs/ui/meta.json @@ -0,0 +1,19 @@ +{ + "title": "UI Engine", + "icon": "Layout", + "pages": [ + "index", + "apps", + "pages", + "views", + "dashboards", + "forms", + "doc-pages", + "setup-app", + "---Recipes---", + "create-vs-edit-form", + "field-grouping-and-order", + "role-based-interfaces", + "public-data-collection" + ] +} diff --git a/content/docs/guides/metadata/page.mdx b/content/docs/ui/pages.mdx similarity index 97% rename from content/docs/guides/metadata/page.mdx rename to content/docs/ui/pages.mdx index 138f3f365b..832e68be21 100644 --- a/content/docs/guides/metadata/page.mdx +++ b/content/docs/ui/pages.mdx @@ -240,6 +240,6 @@ const accountRecordPage = { ## Related -- [View Metadata](./view) — List views and form views for record display -- [Dashboard Metadata](./dashboard) — Analytics-focused page layout -- [App Metadata](./app) — Organize pages into applications +- [View Metadata](/docs/ui/views) — List views and form views for record display +- [Dashboard Metadata](/docs/ui/dashboards) — Analytics-focused page layout +- [App Metadata](/docs/ui/apps) — Organize pages into applications diff --git a/content/docs/guides/solutions/public-data-collection.mdx b/content/docs/ui/public-data-collection.mdx similarity index 98% rename from content/docs/guides/solutions/public-data-collection.mdx rename to content/docs/ui/public-data-collection.mdx index 43b9bf60df..15833ff1e3 100644 --- a/content/docs/guides/solutions/public-data-collection.mdx +++ b/content/docs/ui/public-data-collection.mdx @@ -67,5 +67,5 @@ Authorization is **derived from the declaration**, not configured separately — ## See also - Decision record: **ADR-0056** (public forms — Option A). -- Guide: [Forms (Public + Internal)](/docs/guides/public-forms). +- Guide: [Forms (Public + Internal)](/docs/ui/forms). - Reference: [Sharing](/docs/references/ui/sharing), [View / FormView schema](/docs/references/ui/view). diff --git a/content/docs/guides/solutions/role-based-interfaces.mdx b/content/docs/ui/role-based-interfaces.mdx similarity index 91% rename from content/docs/guides/solutions/role-based-interfaces.mdx rename to content/docs/ui/role-based-interfaces.mdx index 38d58d1aa7..d55f020f8b 100644 --- a/content/docs/guides/solutions/role-based-interfaces.mdx +++ b/content/docs/ui/role-based-interfaces.mdx @@ -51,7 +51,7 @@ In **data mode** (`navigation → object`) users get the permissive grid: switch ### 3. Curate the data surface itself -Use a [curated view](/docs/guides/solutions/field-grouping-and-order) (selected fields, progressive disclosure) rather than granting read on the raw object and dropping users onto a 40-column grid. +Use a [curated view](/docs/ui/field-grouping-and-order) (selected fields, progressive disclosure) rather than granting read on the raw object and dropping users onto a 40-column grid. ## Why @@ -71,5 +71,5 @@ This is the lesson from Airtable's surfaces: the **Automations tab is visible to ## See also - Decision records: **ADR-0047** (run modes), **ADR-0066** (unified authorization, dual-surface gates). -- [Who can see data / automation / interface](/docs/guides/solutions/data-automation-interface-access). -- Guide: [Security](/docs/guides/security); reference: [App schema](/docs/references/ui/app), [Permission schema](/docs/references/security/permission). +- [Who can see data / automation / interface](/docs/permissions/access-recipes). +- Guide: [Security](/docs/permissions); reference: [App schema](/docs/references/ui/app), [Permission schema](/docs/references/security/permission). diff --git a/content/docs/concepts/setup-app.mdx b/content/docs/ui/setup-app.mdx similarity index 96% rename from content/docs/concepts/setup-app.mdx rename to content/docs/ui/setup-app.mdx index b1d33d1609..47f1c1241f 100644 --- a/content/docs/concepts/setup-app.mdx +++ b/content/docs/ui/setup-app.mdx @@ -111,6 +111,6 @@ project — Setup is reserved for platform-level administration. ## Related -- [App Metadata](../guides/metadata/app) — `App` schema reference -- [Authentication](../guides/authentication) — where `setup.access` is granted -- [Cloud Deployment](../guides/cloud-deployment) — how Setup behaves in cloud mode +- [App Metadata](/docs/ui/apps) — `App` schema reference +- [Authentication](/docs/permissions/authentication) — where `setup.access` is granted +- [Cloud Deployment](/docs/deployment) — how Setup behaves in cloud mode diff --git a/content/docs/guides/metadata/view.mdx b/content/docs/ui/views.mdx similarity index 96% rename from content/docs/guides/metadata/view.mdx rename to content/docs/ui/views.mdx index 23c3f55a6e..71ea1e4c1c 100644 --- a/content/docs/guides/metadata/view.mdx +++ b/content/docs/ui/views.mdx @@ -315,7 +315,7 @@ const taskForm = { ## Related -- [Object Metadata](./object) — Define the data behind views -- [Field Metadata](./field) — Field types that views display -- [Page Metadata](./page) — Custom pages with component layouts -- [Dashboard Metadata](./dashboard) — Analytics dashboards with charts +- [Object Metadata](/docs/data-modeling/objects) — Define the data behind views +- [Field Metadata](/docs/data-modeling/fields) — Field types that views display +- [Page Metadata](/docs/ui/pages) — Custom pages with component layouts +- [Dashboard Metadata](/docs/ui/dashboards) — Analytics dashboards with charts diff --git a/content/docs/guides/airtable-dashboard-analysis.mdx b/docs/notes/airtable-dashboard-analysis.mdx similarity index 99% rename from content/docs/guides/airtable-dashboard-analysis.mdx rename to docs/notes/airtable-dashboard-analysis.mdx index 86d96a5a17..d5b9249c15 100644 --- a/content/docs/guides/airtable-dashboard-analysis.mdx +++ b/docs/notes/airtable-dashboard-analysis.mdx @@ -1066,7 +1066,7 @@ For reference, here's the same dashboard definition in pure JSON format: ### Internal Documentation -- [Dashboard Metadata Guide](/docs/guides/metadata/dashboard) — Current dashboard protocol documentation +- [Dashboard Metadata Guide](/docs/ui/dashboards) — Current dashboard protocol documentation - [Chart Configuration Reference](/docs/references/ui/chart) — Chart type taxonomy and configuration --- diff --git a/content/docs/guides/standards.mdx b/docs/notes/crm-development-standards.mdx similarity index 100% rename from content/docs/guides/standards.mdx rename to docs/notes/crm-development-standards.mdx From 5f42c8e1fb7aeb1df8768e196e8ba3b2f729ab24 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 4 Jul 2026 15:09:57 +0000 Subject: [PATCH 2/3] docs(site): add redirects and repoint doc tooling to the new IA - apps/docs/redirects.mjs: permanent redirects for every moved URL (exact entries + folder wildcards + /docs/guides/:path* safety net), wired into next.config.mjs - build-docs.ts: references group is no longer a root sidebar tab; banner wording updated (guides/ no longer exists) - build-skill-docs.ts now emits content/docs/ai/skills-reference.mdx; check-doc-authoring.mjs SKIP_FILES follows - docs-accuracy-audit workflow page list regenerated (146 pages) - update stale content/docs paths in spec JSDoc (source of generated reference prose), skills corpus, package READMEs, ADRs, roadmaps Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_018r9mjpF7jr9BKdzEmUE4uZ --- .claude/workflows/docs-accuracy-audit.js | 2 +- RELEASE_NOTES.md | 4 +- ROADMAP.md | 2 +- apps/docs/next.config.mjs | 4 + apps/docs/redirects.mjs | 123 ++++++++++++++++++ docs/HARDENING.md | 2 +- docs/PLATFORM_GAPS_FROM_TEMPLATES.md | 4 +- docs/adr/0004-cloud-multi-kernel.md | 2 +- ...6-permission-model-landing-verification.md | 2 +- ...-06-handwritten-docs-accuracy-followups.md | 8 +- packages/mcp/README.md | 2 +- packages/metadata/ROADMAP.md | 2 +- packages/objectql/README.md | 2 +- packages/plugins/plugin-audit/README.md | 2 +- packages/runtime/src/runtime.ts | 2 +- packages/services/service-analytics/README.md | 2 +- .../services/service-automation/README.md | 2 +- packages/services/service-cache/README.md | 2 +- .../services/service-cluster/src/cluster.ts | 2 +- .../services/service-cluster/src/index.ts | 2 +- .../src/metadata-cluster-bridge-plugin.ts | 2 +- packages/services/service-i18n/README.md | 2 +- packages/services/service-job/README.md | 2 +- packages/services/service-realtime/README.md | 2 +- packages/spec/scripts/build-docs.ts | 10 +- packages/spec/scripts/build-skill-docs.ts | 4 +- .../spec/src/contracts/cluster-service.ts | 2 +- packages/spec/src/kernel/cluster.zod.ts | 14 +- packages/spec/src/kernel/events/core.zod.ts | 2 +- .../spec/src/kernel/service-registry.zod.ts | 2 +- packages/spec/src/stack.zod.ts | 2 +- scripts/check-doc-authoring.mjs | 2 +- skills/objectstack-api/SKILL.md | 2 +- skills/objectstack-data/rules/datasources.md | 2 +- skills/objectstack-formula/SKILL.md | 2 +- skills/objectstack-ui/SKILL.md | 2 +- 36 files changed, 177 insertions(+), 50 deletions(-) create mode 100644 apps/docs/redirects.mjs diff --git a/.claude/workflows/docs-accuracy-audit.js b/.claude/workflows/docs-accuracy-audit.js index eecd00d47c..05e35e08f6 100644 --- a/.claude/workflows/docs-accuracy-audit.js +++ b/.claude/workflows/docs-accuracy-audit.js @@ -11,7 +11,7 @@ export const meta = { // Default scope = every hand-written doc (content/docs/** minus references/). Keep in // sync with `node scripts/docs-audit/affected-docs.mjs --all`. Callers normally pass a // scoped subset via args.docs (e.g. only docs whose backing packages/ code changed). -const ALL_HANDWRITTEN = ["content/docs/concepts/architecture.mdx","content/docs/concepts/cloud-artifact-api.mdx","content/docs/concepts/cluster-semantics.mdx","content/docs/concepts/core/architecture.mdx","content/docs/concepts/core/events.mdx","content/docs/concepts/core/index.mdx","content/docs/concepts/core/plugins.mdx","content/docs/concepts/core/services.mdx","content/docs/concepts/design-principles.mdx","content/docs/concepts/implementation-status.mdx","content/docs/concepts/index.mdx","content/docs/concepts/metadata-driven.mdx","content/docs/concepts/metadata-lifecycle.mdx","content/docs/concepts/north-star.mdx","content/docs/concepts/packages.mdx","content/docs/concepts/setup-app.mdx","content/docs/concepts/skills.mdx","content/docs/concepts/terminology.mdx","content/docs/concepts/webhook-delivery.mdx","content/docs/getting-started/architecture.mdx","content/docs/getting-started/cli.mdx","content/docs/getting-started/core-concepts.mdx","content/docs/getting-started/examples.mdx","content/docs/getting-started/glossary.mdx","content/docs/getting-started/index.mdx","content/docs/getting-started/quick-start.mdx","content/docs/guides/adding-a-metadata-type.mdx","content/docs/guides/ai-capabilities.mdx","content/docs/guides/airtable-dashboard-analysis.mdx","content/docs/guides/analytics-datasets.mdx","content/docs/guides/api-reference.mdx","content/docs/guides/auth-sso.mdx","content/docs/guides/authentication.mdx","content/docs/guides/business-logic.mdx","content/docs/guides/cheatsheets/backward-compatibility.mdx","content/docs/guides/cheatsheets/error-catalog.mdx","content/docs/guides/cheatsheets/field-type-decision-tree.mdx","content/docs/guides/cheatsheets/field-type-gallery.mdx","content/docs/guides/cheatsheets/field-validation-rules.mdx","content/docs/guides/cheatsheets/permissions-matrix.mdx","content/docs/guides/cheatsheets/protocol-diagram.mdx","content/docs/guides/cheatsheets/query-cheat-sheet.mdx","content/docs/guides/cheatsheets/quick-reference.mdx","content/docs/guides/cheatsheets/wire-format.mdx","content/docs/guides/client-sdk.mdx","content/docs/guides/cloud-deployment.mdx","content/docs/guides/common-patterns.mdx","content/docs/guides/contracts/auth-service.mdx","content/docs/guides/contracts/cache-service.mdx","content/docs/guides/contracts/data-engine.mdx","content/docs/guides/contracts/index.mdx","content/docs/guides/contracts/metadata-service.mdx","content/docs/guides/contracts/storage-service.mdx","content/docs/guides/data-flow.mdx","content/docs/guides/data-modeling.mdx","content/docs/guides/deployment-vercel.mdx","content/docs/guides/driver-configuration.mdx","content/docs/guides/environment-variables.mdx","content/docs/guides/error-handling-client.mdx","content/docs/guides/error-handling-server.mdx","content/docs/guides/formula.mdx","content/docs/guides/hook-bodies.mdx","content/docs/guides/index.mdx","content/docs/guides/kernel-services.mdx","content/docs/guides/metadata/app.mdx","content/docs/guides/metadata/dashboard.mdx","content/docs/guides/metadata/doc.mdx","content/docs/guides/metadata/field.mdx","content/docs/guides/metadata/flow.mdx","content/docs/guides/metadata/index.mdx","content/docs/guides/metadata/object.mdx","content/docs/guides/metadata/page.mdx","content/docs/guides/metadata/permission.mdx","content/docs/guides/metadata/validation.mdx","content/docs/guides/metadata/view.mdx","content/docs/guides/metadata/workflow.mdx","content/docs/guides/objectql-migration.mdx","content/docs/guides/packages.mdx","content/docs/guides/plugin-chatbot-integration.mdx","content/docs/guides/plugin-development.mdx","content/docs/guides/plugins.mdx","content/docs/guides/production-readiness.mdx","content/docs/guides/project-scoping.mdx","content/docs/guides/public-forms.mdx","content/docs/guides/publish-and-preview.mdx","content/docs/guides/runtime-services/audit-service.mdx","content/docs/guides/runtime-services/data-service.mdx","content/docs/guides/runtime-services/email-service.mdx","content/docs/guides/runtime-services/examples.mdx","content/docs/guides/runtime-services/index.mdx","content/docs/guides/runtime-services/queue-service.mdx","content/docs/guides/runtime-services/settings-service.mdx","content/docs/guides/runtime-services/sharing-service.mdx","content/docs/guides/runtime-services/storage-service.mdx","content/docs/guides/runtime-services/versioning.mdx","content/docs/guides/security.mdx","content/docs/guides/seed-data.mdx","content/docs/guides/single-project-mode.mdx","content/docs/guides/skills.mdx","content/docs/guides/standards.mdx","content/docs/guides/troubleshooting.mdx","content/docs/index.mdx","content/docs/protocol/index.mdx","content/docs/protocol/knowledge.mdx","content/docs/protocol/objectos/config-resolution.mdx","content/docs/protocol/objectos/error-handling.mdx","content/docs/protocol/objectos/http-protocol.mdx","content/docs/protocol/objectos/i18n-standard.mdx","content/docs/protocol/objectos/index.mdx","content/docs/protocol/objectos/lifecycle.mdx","content/docs/protocol/objectos/metadata-service.mdx","content/docs/protocol/objectos/plugin-spec.mdx","content/docs/protocol/objectos/realtime-protocol.mdx","content/docs/protocol/objectos/runtime-capabilities.mdx","content/docs/protocol/objectql/index.mdx","content/docs/protocol/objectql/query-syntax.mdx","content/docs/protocol/objectql/schema.mdx","content/docs/protocol/objectql/security.mdx","content/docs/protocol/objectql/state-machine.mdx","content/docs/protocol/objectql/types.mdx","content/docs/protocol/objectui/actions.mdx","content/docs/protocol/objectui/concept.mdx","content/docs/protocol/objectui/index.mdx","content/docs/protocol/objectui/layout-dsl.mdx","content/docs/protocol/objectui/record-alert.mdx","content/docs/protocol/objectui/widget-contract.mdx","content/docs/releases/index.mdx","content/docs/releases/v9.mdx"] +const ALL_HANDWRITTEN = ["content/docs/ai/actions-as-tools.mdx","content/docs/ai/agents.mdx","content/docs/ai/chatbot-integration.mdx","content/docs/ai/index.mdx","content/docs/ai/knowledge-rag.mdx","content/docs/ai/natural-language-queries.mdx","content/docs/ai/skills-reference.mdx","content/docs/ai/skills.mdx","content/docs/api/client-sdk.mdx","content/docs/api/data-api.mdx","content/docs/api/data-flow.mdx","content/docs/api/environment-routing.mdx","content/docs/api/error-catalog.mdx","content/docs/api/error-handling-client.mdx","content/docs/api/error-handling-server.mdx","content/docs/api/index.mdx","content/docs/api/metadata-api.mdx","content/docs/api/plugin-endpoints.mdx","content/docs/api/wire-format.mdx","content/docs/automation/approvals.mdx","content/docs/automation/flows.mdx","content/docs/automation/hook-bodies.mdx","content/docs/automation/hooks.mdx","content/docs/automation/index.mdx","content/docs/automation/webhooks.mdx","content/docs/automation/workflows.mdx","content/docs/concepts/architecture.mdx","content/docs/concepts/design-principles.mdx","content/docs/concepts/index.mdx","content/docs/concepts/metadata-driven.mdx","content/docs/concepts/metadata-lifecycle.mdx","content/docs/concepts/north-star.mdx","content/docs/data-modeling/analytics.mdx","content/docs/data-modeling/drivers.mdx","content/docs/data-modeling/external-datasources.mdx","content/docs/data-modeling/field-type-decision-tree.mdx","content/docs/data-modeling/field-types.mdx","content/docs/data-modeling/fields.mdx","content/docs/data-modeling/formulas.mdx","content/docs/data-modeling/index.mdx","content/docs/data-modeling/indexing.mdx","content/docs/data-modeling/objects.mdx","content/docs/data-modeling/queries.mdx","content/docs/data-modeling/relationships.mdx","content/docs/data-modeling/schema-design.mdx","content/docs/data-modeling/seed-data.mdx","content/docs/data-modeling/validation-rules.mdx","content/docs/data-modeling/validation.mdx","content/docs/deployment/cloud-artifact-api.mdx","content/docs/deployment/environment-variables.mdx","content/docs/deployment/index.mdx","content/docs/deployment/migration-from-objectql.mdx","content/docs/deployment/production-readiness.mdx","content/docs/deployment/publish-and-preview.mdx","content/docs/deployment/single-project-mode.mdx","content/docs/deployment/troubleshooting.mdx","content/docs/deployment/vercel.mdx","content/docs/getting-started/cli.mdx","content/docs/getting-started/common-patterns.mdx","content/docs/getting-started/examples.mdx","content/docs/getting-started/glossary.mdx","content/docs/getting-started/index.mdx","content/docs/getting-started/quick-reference.mdx","content/docs/getting-started/quick-start.mdx","content/docs/getting-started/validating-metadata.mdx","content/docs/index.mdx","content/docs/kernel/architecture.mdx","content/docs/kernel/cluster.mdx","content/docs/kernel/contracts/auth-service.mdx","content/docs/kernel/contracts/cache-service.mdx","content/docs/kernel/contracts/data-engine.mdx","content/docs/kernel/contracts/index.mdx","content/docs/kernel/contracts/metadata-service.mdx","content/docs/kernel/contracts/storage-service.mdx","content/docs/kernel/events.mdx","content/docs/kernel/index.mdx","content/docs/kernel/runtime-services/audit-service.mdx","content/docs/kernel/runtime-services/data-service.mdx","content/docs/kernel/runtime-services/email-service.mdx","content/docs/kernel/runtime-services/examples.mdx","content/docs/kernel/runtime-services/index.mdx","content/docs/kernel/runtime-services/queue-service.mdx","content/docs/kernel/runtime-services/settings-service.mdx","content/docs/kernel/runtime-services/sharing-service.mdx","content/docs/kernel/runtime-services/storage-service.mdx","content/docs/kernel/runtime-services/versioning.mdx","content/docs/kernel/services-checklist.mdx","content/docs/kernel/services.mdx","content/docs/permissions/access-recipes.mdx","content/docs/permissions/authentication.mdx","content/docs/permissions/authorization.mdx","content/docs/permissions/field-level-security.mdx","content/docs/permissions/index.mdx","content/docs/permissions/permission-metadata.mdx","content/docs/permissions/permission-sets.mdx","content/docs/permissions/permissions-matrix.mdx","content/docs/permissions/profiles.mdx","content/docs/permissions/roles.mdx","content/docs/permissions/sharing-rules.mdx","content/docs/permissions/sso.mdx","content/docs/plugins/adding-a-metadata-type.mdx","content/docs/plugins/anatomy.mdx","content/docs/plugins/development.mdx","content/docs/plugins/index.mdx","content/docs/plugins/packages.mdx","content/docs/protocol/backward-compatibility.mdx","content/docs/protocol/diagram.mdx","content/docs/protocol/index.mdx","content/docs/protocol/knowledge.mdx","content/docs/protocol/objectos/config-resolution.mdx","content/docs/protocol/objectos/error-handling.mdx","content/docs/protocol/objectos/http-protocol.mdx","content/docs/protocol/objectos/i18n-standard.mdx","content/docs/protocol/objectos/index.mdx","content/docs/protocol/objectos/lifecycle.mdx","content/docs/protocol/objectos/metadata-service.mdx","content/docs/protocol/objectos/plugin-spec.mdx","content/docs/protocol/objectos/realtime-protocol.mdx","content/docs/protocol/objectos/runtime-capabilities.mdx","content/docs/protocol/objectql/index.mdx","content/docs/protocol/objectql/query-syntax.mdx","content/docs/protocol/objectql/schema.mdx","content/docs/protocol/objectql/security.mdx","content/docs/protocol/objectql/state-machine.mdx","content/docs/protocol/objectql/types.mdx","content/docs/protocol/objectui/actions.mdx","content/docs/protocol/objectui/concept.mdx","content/docs/protocol/objectui/index.mdx","content/docs/protocol/objectui/layout-dsl.mdx","content/docs/protocol/objectui/record-alert.mdx","content/docs/protocol/objectui/widget-contract.mdx","content/docs/releases/implementation-status.mdx","content/docs/releases/index.mdx","content/docs/releases/v9.mdx","content/docs/ui/apps.mdx","content/docs/ui/create-vs-edit-form.mdx","content/docs/ui/dashboards.mdx","content/docs/ui/doc-pages.mdx","content/docs/ui/field-grouping-and-order.mdx","content/docs/ui/forms.mdx","content/docs/ui/index.mdx","content/docs/ui/pages.mdx","content/docs/ui/public-data-collection.mdx","content/docs/ui/role-based-interfaces.mdx","content/docs/ui/setup-app.mdx","content/docs/ui/views.mdx"] const DOCS = (args && Array.isArray(args.docs) && args.docs.length) ? args.docs : ALL_HANDWRITTEN diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 6fcea496fa..df4ab2a260 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -32,8 +32,8 @@ Prepare all 42 packages under `@objectstack/*` for formal public release on npm - [x] `service-tenant` and `service-package` version-aligned to `4.0.4`. - [x] `packages/services/service-package/README.md` authored. - [x] Thin READMEs rewritten: `core`, `rest`, `driver-memory`, `plugin-security`, all 7 adapters. -- [x] `content/docs/guides/packages.mdx` updated to 42-package inventory including `service-package` and `service-tenant`. -- [x] `content/docs/concepts/packages.mdx` updated to 42-package inventory. +- [x] `content/docs/plugins/packages.mdx` updated to 42-package inventory including `service-package` and `service-tenant`. +- [x] `content/docs/plugins/packages.mdx` updated to 42-package inventory. - [x] `CHANGELOG.md` carries a release-prep entry. - [ ] `pnpm build` passes for every publishable package. - [ ] `pnpm test` passes. diff --git a/ROADMAP.md b/ROADMAP.md index 19c2bc5508..7df7e8a903 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -39,7 +39,7 @@ docs, adapters, services, plugins, and the bundled console integration. | P0 | Keep public docs aligned with the environment rename. | Prevent users from copying stale `project` route/header/env examples. | | P0 | Keep CLI/docs/examples aligned with actual scripts: `pnpm dev`, `pnpm dev:crm`, `os dev`, `os start`, `os serve`, `os publish`. | Avoid broken onboarding. | | P0 | Remove references to deleted app/service packages from current docs. | `apps/cloud`, `apps/objectos`, `apps/studio`, and `service-tenant` no longer exist in this repo. | -| ~~P1~~ done | ~~Document Flow-first automation and workflow state-machine semantics.~~ Flow automation is documented in [guides/metadata/flow](content/docs/guides/metadata/flow.mdx) (triggers, nodes, structured control flow, durable pause/resume, parallel + batch approval, run observability) and the ADR-0019/0031/0039 series; state-machine semantics in [guides/metadata/workflow](content/docs/guides/metadata/workflow.mdx) + [validation](content/docs/guides/metadata/validation.mdx). | Old Workflow Rule docs implied a retired Salesforce-style rule engine. | +| ~~P1~~ done | ~~Document Flow-first automation and workflow state-machine semantics.~~ Flow automation is documented in [guides/metadata/flow](content/docs/automation/flows.mdx) (triggers, nodes, structured control flow, durable pause/resume, parallel + batch approval, run observability) and the ADR-0019/0031/0039 series; state-machine semantics in [guides/metadata/workflow](content/docs/automation/workflows.mdx) + [validation](content/docs/data-modeling/validation.mdx). | Old Workflow Rule docs implied a retired Salesforce-style rule engine. | | P1 | Document explicit AI action opt-in via action metadata. | AI tool exposure is no longer automatic for every action. | | P1 | Document implemented formula, summary, autonumber, notifications, and master-detail behavior. | Recent runtime work is under-documented and older status pages still mark it missing. | | P2 | Regenerate reference docs after Zod description updates. | Keeps generated schema pages consistent without hand-editing them. | diff --git a/apps/docs/next.config.mjs b/apps/docs/next.config.mjs index 44d31efc57..f4bbe7630b 100644 --- a/apps/docs/next.config.mjs +++ b/apps/docs/next.config.mjs @@ -1,4 +1,5 @@ import { createMDX } from 'fumadocs-mdx/next'; +import { toNextRedirects } from './redirects.mjs'; const withMDX = createMDX(); @@ -26,6 +27,9 @@ const config = { }, ], }, + async redirects() { + return toNextRedirects(); + }, async rewrites() { return [ { diff --git a/apps/docs/redirects.mjs b/apps/docs/redirects.mjs new file mode 100644 index 0000000000..e9ac6fafec --- /dev/null +++ b/apps/docs/redirects.mjs @@ -0,0 +1,123 @@ +/** + * Permanent redirects from the pre-2026-07 docs IA (type-based: guides/concepts/ + * getting-started grab-bags) to the module-based IA (data-modeling, automation, + * permissions, ui, api, ai, plugins, kernel, deployment, ...). + * + * This table is the single source of truth for the migration: next.config.mjs + * serves it as HTTP redirects, and scripts used during the migration rewrote + * in-content links from the same pairs. Exact entries come first; wildcard + * catch-alls for retired sections must stay last (first match wins). + */ +export const docsRedirects = [ + // getting-started + ['/docs/guides/cheatsheets/quick-reference', '/docs/getting-started/quick-reference'], + ['/docs/guides/common-patterns', '/docs/getting-started/common-patterns'], + ['/docs/guides/validating-metadata', '/docs/getting-started/validating-metadata'], + // concepts + ['/docs/getting-started/core-concepts', '/docs/concepts'], + ['/docs/getting-started/architecture', '/docs/concepts/architecture'], + ['/docs/concepts/terminology', '/docs/getting-started/glossary'], + // data-modeling + ['/docs/guides/data-modeling', '/docs/data-modeling'], + ['/docs/guides/metadata/object', '/docs/data-modeling/objects'], + ['/docs/guides/metadata/field', '/docs/data-modeling/fields'], + ['/docs/guides/cheatsheets/field-type-gallery', '/docs/data-modeling/field-types'], + ['/docs/guides/cheatsheets/field-type-decision-tree', '/docs/data-modeling/field-type-decision-tree'], + ['/docs/guides/metadata/validation', '/docs/data-modeling/validation'], + ['/docs/guides/cheatsheets/field-validation-rules', '/docs/data-modeling/validation-rules'], + ['/docs/guides/formula', '/docs/data-modeling/formulas'], + ['/docs/guides/cheatsheets/query-cheat-sheet', '/docs/data-modeling/queries'], + ['/docs/guides/seed-data', '/docs/data-modeling/seed-data'], + ['/docs/guides/external-datasources', '/docs/data-modeling/external-datasources'], + ['/docs/guides/driver-configuration', '/docs/data-modeling/drivers'], + ['/docs/guides/analytics-datasets', '/docs/data-modeling/analytics'], + ['/docs/guides/airtable-dashboard-analysis', '/docs/data-modeling/analytics'], + // automation + ['/docs/guides/business-logic', '/docs/automation/hooks'], + ['/docs/guides/hook-bodies', '/docs/automation/hook-bodies'], + ['/docs/guides/metadata/flow', '/docs/automation/flows'], + ['/docs/guides/metadata/workflow', '/docs/automation/workflows'], + ['/docs/guides/solutions/approval-workflow', '/docs/automation/approvals'], + ['/docs/concepts/webhook-delivery', '/docs/automation/webhooks'], + // permissions + ['/docs/guides/security', '/docs/permissions'], + ['/docs/guides/authentication', '/docs/permissions/authentication'], + ['/docs/guides/auth-sso', '/docs/permissions/sso'], + ['/docs/concepts/authorization', '/docs/permissions/authorization'], + ['/docs/guides/metadata/permission', '/docs/permissions/permission-metadata'], + ['/docs/guides/cheatsheets/permissions-matrix', '/docs/permissions/permissions-matrix'], + ['/docs/guides/solutions/data-automation-interface-access', '/docs/permissions/access-recipes'], + // ui + ['/docs/guides/metadata/app', '/docs/ui/apps'], + ['/docs/guides/metadata/page', '/docs/ui/pages'], + ['/docs/guides/metadata/view', '/docs/ui/views'], + ['/docs/guides/metadata/dashboard', '/docs/ui/dashboards'], + ['/docs/guides/public-forms', '/docs/ui/forms'], + ['/docs/guides/metadata/doc', '/docs/ui/doc-pages'], + ['/docs/concepts/setup-app', '/docs/ui/setup-app'], + ['/docs/guides/solutions/create-vs-edit-form', '/docs/ui/create-vs-edit-form'], + ['/docs/guides/solutions/field-grouping-and-order', '/docs/ui/field-grouping-and-order'], + ['/docs/guides/solutions/role-based-interfaces', '/docs/ui/role-based-interfaces'], + ['/docs/guides/solutions/public-data-collection', '/docs/ui/public-data-collection'], + // api + ['/docs/guides/api-reference', '/docs/api'], + ['/docs/guides/client-sdk', '/docs/api/client-sdk'], + ['/docs/guides/project-scoping', '/docs/api/environment-routing'], + ['/docs/guides/data-flow', '/docs/api/data-flow'], + ['/docs/guides/error-handling-client', '/docs/api/error-handling-client'], + ['/docs/guides/error-handling-server', '/docs/api/error-handling-server'], + ['/docs/guides/cheatsheets/error-catalog', '/docs/api/error-catalog'], + ['/docs/guides/cheatsheets/wire-format', '/docs/api/wire-format'], + // ai + ['/docs/guides/ai-capabilities', '/docs/ai'], + ['/docs/concepts/skills', '/docs/ai/skills'], + ['/docs/guides/skills', '/docs/ai/skills-reference'], + ['/docs/guides/plugin-chatbot-integration', '/docs/ai/chatbot-integration'], + // plugins + ['/docs/guides/plugins', '/docs/plugins'], + ['/docs/guides/plugin-development', '/docs/plugins/development'], + ['/docs/guides/packages', '/docs/plugins/packages'], + ['/docs/concepts/packages', '/docs/plugins/packages'], + ['/docs/guides/adding-a-metadata-type', '/docs/plugins/adding-a-metadata-type'], + ['/docs/concepts/core/plugins', '/docs/plugins/anatomy'], + // kernel + ['/docs/concepts/core/architecture', '/docs/kernel/architecture'], + ['/docs/concepts/core/events', '/docs/kernel/events'], + ['/docs/concepts/core/services', '/docs/kernel/services'], + ['/docs/concepts/core', '/docs/kernel'], + ['/docs/guides/kernel-services', '/docs/kernel/services-checklist'], + ['/docs/concepts/cluster-semantics', '/docs/kernel/cluster'], + // deployment + ['/docs/guides/cloud-deployment', '/docs/deployment'], + ['/docs/guides/deployment-vercel', '/docs/deployment/vercel'], + ['/docs/guides/production-readiness', '/docs/deployment/production-readiness'], + ['/docs/guides/publish-and-preview', '/docs/deployment/publish-and-preview'], + ['/docs/guides/environment-variables', '/docs/deployment/environment-variables'], + ['/docs/guides/single-project-mode', '/docs/deployment/single-project-mode'], + ['/docs/concepts/cloud-artifact-api', '/docs/deployment/cloud-artifact-api'], + ['/docs/guides/objectql-migration', '/docs/deployment/migration-from-objectql'], + ['/docs/guides/troubleshooting', '/docs/deployment/troubleshooting'], + // protocol / releases + ['/docs/guides/cheatsheets/protocol-diagram', '/docs/protocol/diagram'], + ['/docs/guides/cheatsheets/backward-compatibility', '/docs/protocol/backward-compatibility'], + ['/docs/concepts/implementation-status', '/docs/releases/implementation-status'], + // retired pages / sections + ['/docs/guides/standards', '/docs/concepts/design-principles'], + ['/docs/guides/metadata', '/docs/concepts/metadata-driven'], + ['/docs/guides/solutions', '/docs'], + ['/docs/guides/cheatsheets', '/docs/getting-started/quick-reference'], + // 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*'], + // safety net for anything else under retired sections — keep last + ['/docs/guides/:path*', '/docs'], +]; + +/** Next.js redirects() entries derived from the table above. */ +export function toNextRedirects() { + return docsRedirects.map(([source, destination]) => ({ + source, + destination, + permanent: true, + })); +} diff --git a/docs/HARDENING.md b/docs/HARDENING.md index 976d32e7b2..5b6667a2a8 100644 --- a/docs/HARDENING.md +++ b/docs/HARDENING.md @@ -157,7 +157,7 @@ Password expiry and enforced MFA share a *session-validation gate*: a non-compliant session can authenticate but is blocked from data access (auth + health + a remediation allowlist still pass) until the user rotates the password or enrols MFA. See the -[Authentication guide](../content/docs/guides/authentication.mdx#enterprise-authentication-hardening-adr-0069) +[Authentication guide](../content/docs/permissions/authentication.mdx#enterprise-authentication-hardening-adr-0069) for the full per-setting reference. ## JWT / session lifecycle diff --git a/docs/PLATFORM_GAPS_FROM_TEMPLATES.md b/docs/PLATFORM_GAPS_FROM_TEMPLATES.md index 53fe4f872c..5821e681e2 100644 --- a/docs/PLATFORM_GAPS_FROM_TEMPLATES.md +++ b/docs/PLATFORM_GAPS_FROM_TEMPLATES.md @@ -32,7 +32,7 @@ | 20 | 🟢 P3 | 企业 | 多步审批、委派、不在岗代理缺失 | 同上 | | 21 | 🟢 P3 | 企业 | 外部审计员 / 只读访客门户缺失 | 合规类应用刚需 | | 22 | 🟢 P3 | 移动 | 移动端响应式未验证 | 审批走手机是基本盘 | -| 23 | 🟢 P3 | 文档 | ~~`services.data.{get,update}` 等 API 未文档化~~ | Fixed in Unreleased: 新增 `content/docs/guides/runtime-services/*` | +| 23 | 🟢 P3 | 文档 | ~~`services.data.{get,update}` 等 API 未文档化~~ | Fixed in Unreleased: 新增 `content/docs/kernel/runtime-services/*` | | 24 | 🟢 P3 | 发布 | 模板包发布/版本升级流程不明 | 模板生态化卡点 | | 25 | 🟢 P3 | 审计 | 平台内置审计日志的可见性 / 配置入口不清 | 合规模板无法引用 | @@ -290,7 +290,7 @@ ### 23. ~~`services.data.{get,update}` 等 API 未文档化~~ 模板代码中调用 `services?.data?.get(object, id)` / `services?.data?.update(object, id, values)`,靠读源码发现,签名/错误语义无文档。建议补 SDK 参考。 -**Fixed in Unreleased:** 已新增独立章节 `content/docs/guides/runtime-services/`,覆盖 `services.data/sharing/audit/queue/email/settings/storage` 方法签名、参数、返回、错误语义、示例与稳定性标记。 +**Fixed in Unreleased:** 已新增独立章节 `content/docs/kernel/runtime-services/`,覆盖 `services.data/sharing/audit/queue/email/settings/storage` 方法签名、参数、返回、错误语义、示例与稳定性标记。 ### 24. 模板包发布 / 版本升级流程不明 diff --git a/docs/adr/0004-cloud-multi-kernel.md b/docs/adr/0004-cloud-multi-kernel.md index ca11ec3a15..fd23126710 100644 --- a/docs/adr/0004-cloud-multi-kernel.md +++ b/docs/adr/0004-cloud-multi-kernel.md @@ -130,4 +130,4 @@ Custom domains and multi-hostname binding (ACME certificates, `sys_domain` table - Plan: `apps-server-sleepy-newell` (the plan this ADR crystallizes). - Code: `packages/runtime/src/kernel-manager.ts`, `packages/runtime/src/project-kernel-factory.ts`, `packages/runtime/src/http-dispatcher.ts`, `apps/objectos/server/bootstrap.ts`, `apps/cloud/objectstack.config.ts`. -- Related guide: [Cloud vs Self-Hosted deployment](../../content/docs/guides/cloud-deployment.mdx). +- Related guide: [Cloud vs Self-Hosted deployment](../../content/docs/deployment/index.mdx). diff --git a/docs/adr/0056-permission-model-landing-verification.md b/docs/adr/0056-permission-model-landing-verification.md index d141b85ce6..6b6a3235b4 100644 --- a/docs/adr/0056-permission-model-landing-verification.md +++ b/docs/adr/0056-permission-model-landing-verification.md @@ -187,7 +187,7 @@ The one-time table above rots. Make it a **living ledger**: extend the ADR-0054 - ADR-0049 (no unenforced security properties), ADR-0054 (runtime proof), ADR-0055 (controlled-by-parent), ADR-0010 (metadata protection), ADR-0029 (kernel object ownership). - Audit evidence: `plugin-security/src/security-plugin.ts`, `rls-compiler.ts`; `plugin-sharing/src/sharing-service.ts`, `sharing-rule-service.ts`; `rest/src/rest-server.ts`; `runtime/src/security/resolve-execution-context.ts`; `spec/src/security/{permission,rls,sharing}.zod.ts`, `spec/src/data/object.zod.ts`. -- Liveness ledger: `packages/spec/scripts/liveness/proof-registry.mts`. Implementation status: `content/docs/concepts/implementation-status.mdx`, `content/docs/guides/security.mdx`. +- Liveness ledger: `packages/spec/scripts/liveness/proof-registry.mts`. Implementation status: `content/docs/releases/implementation-status.mdx`, `content/docs/permissions/index.mdx`. --- diff --git a/docs/audits/2026-06-handwritten-docs-accuracy-followups.md b/docs/audits/2026-06-handwritten-docs-accuracy-followups.md index 5f3d88f05a..a57780440c 100644 --- a/docs/audits/2026-06-handwritten-docs-accuracy-followups.md +++ b/docs/audits/2026-06-handwritten-docs-accuracy-followups.md @@ -137,7 +137,7 @@ Out of scope here (generated, DO-NOT-EDIT); fix by regenerating from spec in a d ### `guides/error-handling-client.mdx` - Section 2 ObjectStackError constructor is typed against the REAL `import type { ErrorResponse } from '@objectstack/spec/api'`, whose `error.code` is the strict `StandardErrorCode` enum (errors.zod.ts:221), NOT `string`. Sections 4 and 7 use the client-synthesized literal 'NETWORK_ERROR', which is not a member of that enum (grep for NETWORK_ERROR in packages/ is empty). So `new ObjectStackError({ error: { code: 'NETWORK_ERROR', ... } })` and the `case 'NETWORK_ERROR':` switch arm would be TS type errors against the imported type. The audit added a clarifying comment ('client-synthesized') but did not reconcile the type. Not a regression (pre-existing pedagogy choice flagged by the audit). Honest fixes: either (a) widen the doc's own Section-1 `ErrorResponse.error.code` to `StandardErrorCode | 'NETWORK_ERROR'` / `string` and have the class accept that local interface rather than the imported type, or (b) drop NETWORK_ERROR in favor of a real server code. Left in place per minimal-edit rule. - Section 1 standalone `ErrorResponse` interface declares `meta.traceId` and `error.retryStrategy`, which DO exist in the schema (errors.zod.ts:226,232,265) — correct. But note the JSDoc example in the spec (errors.zod.ts:182-198) nests `fieldErrors` INSIDE `details`, contradicting the actual `EnhancedApiErrorSchema` where `fieldErrors` is a top-level sibling of `details` (line 229). The doc correctly follows the SCHEMA (top-level), so the doc is right and the spec's own JSDoc example is the stale one. No doc change needed; flagging that the spec example at errors.zod.ts:182-198 is internally inconsistent with its schema. -- Out of scope (carried from audit's unresolved): content/docs/guides/cheatsheets/wire-format.mdx section 7 (## 7. Error Response Format at line 331) still documents the OLD shape (UPPERCASE codes, error.status, error.details[] arrays). The cross-reference link/anchor #7-error-response-format from this doc (line 11) is still VALID (target heading exists), but the cheatsheet content it points to now contradicts this corrected doc. Should be reconciled in a follow-up. +- Out of scope (carried from audit's unresolved): content/docs/api/wire-format.mdx section 7 (## 7. Error Response Format at line 331) still documents the OLD shape (UPPERCASE codes, error.status, error.details[] arrays). The cross-reference link/anchor #7-error-response-format from this doc (line 11) is still VALID (target heading exists), but the cheatsheet content it points to now contradicts this corrected doc. Should be reconciled in a follow-up. - Out of scope (carried from audit's unresolved): the actual REST runtime envelope from mapDataError (packages/rest/src/rest-server.ts) is reportedly a flatter third shape than ErrorResponseSchema. This doc documents the spec/ErrorResponseSchema shape, which is a defensible source-of-truth choice, but the divergence between spec schema and REST runtime output is worth a dedicated reconciliation pass. ### `guides/error-handling-server.mdx` @@ -157,7 +157,7 @@ Out of scope here (generated, DO-NOT-EDIT); fix by regenerating from spec in a d - The `visible` type label was changed to `Expression`. Strictly, ExpressionInputSchema (packages/spec/src/shared/expression.zod.ts:83-86) accepts either a bare CEL string OR a canonical Expression envelope at input time; the doc's `Expression` label + 'CEL expression' description is accurate enough, but a reader might not realize a raw string shorthand is also accepted. Minor; not an inaccuracy. ### `guides/metadata/dashboard.mdx` -- Descriptive prose at /Users/oszhuang/Documents/GitHub/framework/content/docs/guides/metadata/dashboard.mdx:165-169 ('ObjectUI currently renders dataset-backed metric, chart, table/list, pivot, funnel, and gauge-style widgets ... drill-down affordances') is a runtime-renderer capability claim not directly backed by the spec schemas I read. It is not false on its face (all named chart types are in ChartTypeSchema) but the specific rendering/drill-down feature claims live in ObjectUI (objectui repo / client-react), which is outside packages/spec — not independently verified here. Low priority, no evidence it is wrong. +- Descriptive prose at /Users/oszhuang/Documents/GitHub/framework/content/docs/ui/dashboards.mdx:165-169 ('ObjectUI currently renders dataset-backed metric, chart, table/list, pivot, funnel, and gauge-style widgets ... drill-down affordances') is a runtime-renderer capability claim not directly backed by the spec schemas I read. It is not false on its face (all named chart types are in ChartTypeSchema) but the specific rendering/drill-down feature claims live in ObjectUI (objectui repo / client-react), which is outside packages/spec — not independently verified here. Low priority, no evidence it is wrong. - Line 102: filter is documented as type `FilterCondition` with note '(runtimeFilter)'. Schema (dashboard.zod.ts:121-122) confirms widget.filter is FilterConditionSchema applied as runtimeFilter — accurate. No action needed; noting only that the parenthetical 'runtimeFilter' is internal naming that may confuse authors but is faithful to the schema describe() text. ### `guides/metadata/doc.mdx` @@ -232,7 +232,7 @@ Out of scope here (generated, DO-NOT-EDIT); fix by regenerating from spec in a d ### `guides/runtime-services/email-service.mdx` - NONE in the doc — doc is accurate. Note for code-side follow-up (NOT a doc issue): the contract comment at packages/spec/src/contracts/email-service.ts:11 claims 'Aligned with CoreServiceName email in core-services.zod.ts', but the CoreServiceName enum (packages/spec/src/system/core-services.zod.ts:20-43) has NO 'email' member — email is subsumed under 'notification' (line 38). The doc does not reference CoreServiceName, so the doc itself is correct; the stale code comment is out of scope here. -- Audit's two 'unresolved' items are actually resolvable and benign: (1) services.email accessor IS genuine — plugin-email registers the service under key 'email' via ctx.registerService('email', this.service) at packages/plugins/plugin-email/src/email-plugin.ts:117, and the accessor matches the chapter-wide convention in content/docs/guides/runtime-services/index.mdx. (2) Stability 'stable' is a curation claim consistent with every sibling runtime-services doc (storage-service.mdx etc.); no code marker exists, correctly left unchanged. +- Audit's two 'unresolved' items are actually resolvable and benign: (1) services.email accessor IS genuine — plugin-email registers the service under key 'email' via ctx.registerService('email', this.service) at packages/plugins/plugin-email/src/email-plugin.ts:117, and the accessor matches the chapter-wide convention in content/docs/kernel/runtime-services/index.mdx. (2) Stability 'stable' is a curation claim consistent with every sibling runtime-services doc (storage-service.mdx etc.); no code marker exists, correctly left unchanged. ### `guides/runtime-services/examples.mdx` - Example #2 registers a data hook by exporting a top-level function named after the event (`export async function beforeUpdate(ctx)`). This convention is NOT confirmed in code: grep for `export ... beforeUpdate` across packages/ and examples/ returned no matches. The flow-node `export async function run` convention (Example #1) DOES appear in code (packages/objectql/src/build-probes.ts, packages/cli/src/lint/metadata-eval.ts), but the analogous hook-by-function-name registration is unverified. The audit agent correctly flagged this as unresolved and left it loosely-typed (ctx: any) — recommend a human confirm the actual hook-registration convention (top-level export vs. ctx.hook registration). `ctx.input.id`, `ctx.session.{userId,tenantId,roles}` match HookSchema per the audit's cited hook.zod.ts lines (not independently re-read here, but consistent with SharingExecutionContext which I did confirm). @@ -240,7 +240,7 @@ Out of scope here (generated, DO-NOT-EDIT); fix by regenerating from spec in a d ### `guides/runtime-services/index.mdx` - Conceptual-only: the page lists service categories as `services.data`, `services.sharing`, etc. The core service registry (packages/core/src/kernel.ts:455, kernel-base.ts:76) resolves services via getService(name)/registerService(name, service), not property access on a `services` object. However, this is a bulleted category listing with NO executable code sample, and `.data` property access does in fact exist on the scoped client surface (packages/client/src/index.ts:1052 `scoped.data.find(...)`), so the shorthand is defensible. Correctly left unchanged by the audit; changing it to `services.get('data')` would risk introducing an unsupported convention. No evidence-backed fix warranted. -- The `description` frontmatter and body both reference per-service sub-pages ('Each page links the canonical TypeScript source'). I did not verify that sibling pages under content/docs/guides/runtime-services/ actually exist; if they are missing the cross-reference prose would be aspirational, but this is out of scope for verifying the index page's factual claims and was not flagged as a fix. +- The `description` frontmatter and body both reference per-service sub-pages ('Each page links the canonical TypeScript source'). I did not verify that sibling pages under content/docs/kernel/runtime-services/ actually exist; if they are missing the cross-reference prose would be aspirational, but this is out of scope for verifying the index page's factual claims and was not flagged as a fix. ### `guides/runtime-services/queue-service.mdx` - Not a doc inaccuracy, but a code/doc-comment mismatch for awareness: the IQueueService.replay JSDoc at packages/spec/src/contracts/queue-service.ts:144 says it throws if the message 'is not in dlq status', whereas db-queue-adapter.ts:201 actually accepts both 'dlq' and 'failed'. The doc's INVALID_STATE description (non-dlq/failed) correctly matches the adapter, so the doc is fine. diff --git a/packages/mcp/README.md b/packages/mcp/README.md index c7eaa5b1e7..741b29ef48 100644 --- a/packages/mcp/README.md +++ b/packages/mcp/README.md @@ -555,4 +555,4 @@ Apache-2.0. See [LICENSING.md](../../LICENSING.md). - [Model Context Protocol Specification](https://modelcontextprotocol.io/) - [MCP TypeScript SDK](https://github.com/modelcontextprotocol/typescript-sdk) - [@objectstack/spec/ai](../../spec/src/ai/) -- [Building MCP Servers Guide](/content/docs/guides/mcp/) +- [Building MCP Servers Guide](/content/docs/ai/) diff --git a/packages/metadata/ROADMAP.md b/packages/metadata/ROADMAP.md index a144e90954..ce2690d455 100644 --- a/packages/metadata/ROADMAP.md +++ b/packages/metadata/ROADMAP.md @@ -196,7 +196,7 @@ artifact persistence (`artifacts/${projectId}/${commitId}.json`). - [x] `MetadataPlugin` consumes published artifacts via the `artifactSource: { mode: 'artifact-api' }` source — no direct S3 coupling needed in the metadata layer. -- See [Publish, Versioning & Preview](../../content/docs/guides/publish-and-preview.mdx). +- See [Publish, Versioning & Preview](../../content/docs/deployment/publish-and-preview.mdx). --- diff --git a/packages/objectql/README.md b/packages/objectql/README.md index f9b5749eb4..b177ea2334 100644 --- a/packages/objectql/README.md +++ b/packages/objectql/README.md @@ -97,7 +97,7 @@ computeFQN('base', 'user'); // => 'user' (reserved namespace) ## Migrating from `@objectql/core` If you are migrating from the downstream `@objectql/core` package, see the -[Migration Guide](../../content/docs/guides/objectql-migration.mdx) for +[Migration Guide](../../content/docs/deployment/migration-from-objectql.mdx) for step-by-step instructions. **Quick summary:** diff --git a/packages/plugins/plugin-audit/README.md b/packages/plugins/plugin-audit/README.md index 5852b69e96..8a53665800 100644 --- a/packages/plugins/plugin-audit/README.md +++ b/packages/plugins/plugin-audit/README.md @@ -411,4 +411,4 @@ Apache-2.0. See [LICENSING.md](../../../LICENSING.md). - [GDPR Requirements](https://gdpr.eu/) - [HIPAA Compliance](https://www.hhs.gov/hipaa/) - [@objectstack/plugin-security](../plugin-security/) -- [Audit Logging Best Practices](/content/docs/guides/audit/) +- [Audit Logging Best Practices](/content/docs/kernel/runtime-services/audit-service.mdx) diff --git a/packages/runtime/src/runtime.ts b/packages/runtime/src/runtime.ts index 32e84560a1..2a25a2c04d 100644 --- a/packages/runtime/src/runtime.ts +++ b/packages/runtime/src/runtime.ts @@ -30,7 +30,7 @@ export interface RuntimeConfig { * - `ClusterCapabilityConfigInput`: forwarded to `defineCluster()`. * - `{ cluster: IClusterService }`: bring your own instance. * - * See `content/docs/concepts/cluster-semantics.mdx` for driver options. + * See `content/docs/kernel/cluster.mdx` for driver options. */ cluster?: false | ClusterCapabilityConfigInput | ClusterServicePluginOptions; } diff --git a/packages/services/service-analytics/README.md b/packages/services/service-analytics/README.md index e132a94a24..6d3d783353 100644 --- a/packages/services/service-analytics/README.md +++ b/packages/services/service-analytics/README.md @@ -392,4 +392,4 @@ Apache-2.0. See [LICENSING.md](../../../LICENSING.md). - [@objectstack/objectql](../../objectql/) - [@objectstack/spec/contracts](../../spec/src/contracts/) -- [Analytics Guide](/content/docs/guides/analytics/) +- [Analytics Guide](/content/docs/data-modeling/analytics.mdx) diff --git a/packages/services/service-automation/README.md b/packages/services/service-automation/README.md index ab5b8f6e66..ea143c31ee 100644 --- a/packages/services/service-automation/README.md +++ b/packages/services/service-automation/README.md @@ -433,5 +433,5 @@ Apache-2.0. See [LICENSING.md](../../../LICENSING.md). ## See Also - [@objectstack/spec/automation](../../spec/src/automation/) -- [Flow Builder Guide](/content/docs/guides/automation/) +- [Flow Builder Guide](/content/docs/automation/) - [Trigger Reference](/content/docs/references/automation/) diff --git a/packages/services/service-cache/README.md b/packages/services/service-cache/README.md index 63fac9a359..48cb38d6f0 100644 --- a/packages/services/service-cache/README.md +++ b/packages/services/service-cache/README.md @@ -291,4 +291,4 @@ Apache-2.0. See [LICENSING.md](../../../LICENSING.md). - [Redis Documentation](https://redis.io/documentation) - [@objectstack/spec/contracts](../../spec/src/contracts/) -- [Caching Best Practices](/content/docs/guides/caching/) +- [Caching Best Practices](/content/docs/kernel/contracts/cache-service.mdx) diff --git a/packages/services/service-cluster/src/cluster.ts b/packages/services/service-cluster/src/cluster.ts index 3e22a1aec8..9cb58d9f6f 100644 --- a/packages/services/service-cluster/src/cluster.ts +++ b/packages/services/service-cluster/src/cluster.ts @@ -76,7 +76,7 @@ export function defineCluster( `Cluster driver "${parsed.driver}" is not registered. ` + `Did you forget to import @objectstack/service-cluster-${parsed.driver} ` + `or call registerClusterDriver()? ` + - `See content/docs/concepts/cluster-semantics.mdx §6.`, + `See content/docs/kernel/cluster.mdx §6.`, ); } return factory({ ...parsed, nodeId }); diff --git a/packages/services/service-cluster/src/index.ts b/packages/services/service-cluster/src/index.ts index 11fd22f486..c8c9bd07e7 100644 --- a/packages/services/service-cluster/src/index.ts +++ b/packages/services/service-cluster/src/index.ts @@ -18,7 +18,7 @@ * locks/counters; pub/sub does not fan out across processes). Use a * remote driver for any multi-replica deployment. * - * See `content/docs/concepts/cluster-semantics.mdx` for the protocol. + * See `content/docs/kernel/cluster.mdx` for the protocol. */ export { diff --git a/packages/services/service-cluster/src/metadata-cluster-bridge-plugin.ts b/packages/services/service-cluster/src/metadata-cluster-bridge-plugin.ts index 405d18966b..4e427c1c32 100644 --- a/packages/services/service-cluster/src/metadata-cluster-bridge-plugin.ts +++ b/packages/services/service-cluster/src/metadata-cluster-bridge-plugin.ts @@ -20,7 +20,7 @@ import type { IClusterService } from '@objectstack/spec/contracts'; * Channel: `metadata.changed` — payload shape defined by * `ClusterMetadataChangedPayload` in `@objectstack/metadata`. * - * See `content/docs/concepts/cluster-semantics.mdx` §5. + * See `content/docs/kernel/cluster.mdx` §5. */ export class MetadataClusterBridgePlugin implements Plugin { name = 'com.objectstack.service.metadata-cluster-bridge'; diff --git a/packages/services/service-i18n/README.md b/packages/services/service-i18n/README.md index 28ee6bdb17..898d2a0e11 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/guides/i18n/) +- [I18n Best Practices Guide](/content/docs/protocol/objectos/i18n-standard.mdx) diff --git a/packages/services/service-job/README.md b/packages/services/service-job/README.md index 4b5b3f908a..6fbbd796d5 100644 --- a/packages/services/service-job/README.md +++ b/packages/services/service-job/README.md @@ -368,4 +368,4 @@ Apache-2.0. See [LICENSING.md](../../../LICENSING.md). - [Cron Expression Generator](https://crontab.guru/) - [@objectstack/spec/contracts](../../spec/src/contracts/) -- [Job Scheduling Guide](/content/docs/guides/jobs/) +- [Job Scheduling Guide](/content/docs/kernel/runtime-services/queue-service.mdx) diff --git a/packages/services/service-realtime/README.md b/packages/services/service-realtime/README.md index 980f3ec307..827a6b2d49 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/guides/realtime/) +- [Realtime Features Guide](/content/docs/protocol/objectos/realtime-protocol.mdx) diff --git a/packages/spec/scripts/build-docs.ts b/packages/spec/scripts/build-docs.ts index 1259460e7f..36207a02d5 100644 --- a/packages/spec/scripts/build-docs.ts +++ b/packages/spec/scripts/build-docs.ts @@ -8,7 +8,8 @@ // DO NOT place hand-written content in content/docs/references/ — it WILL be // overwritten or deleted on the next build. // -// Hand-written documentation belongs in content/docs/guides/ instead. +// Hand-written documentation lives in the module folders under content/docs/ +// (data-modeling/, automation/, permissions/, ui/, api/, ai/, plugins/, kernel/, ...). // See DX_ROADMAP.md and .cursorrules for details. import fs from 'fs'; @@ -268,7 +269,7 @@ function generateZodFileMarkdown(zodFile: string, schemas: Array<{name: string, md += `title: ${zodTitle}\n`; md += `description: ${zodTitle} protocol schemas\n`; md += `---\n\n`; - md += `{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */}\n\n`; + md += `{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */}\n\n`; if (fileDesc) { md += `${fileDesc}\n\n`; @@ -444,9 +445,8 @@ const pages = [ const meta = { title: "Reference", icon: "FileCode", - // Render the (large, generated) reference as its own sidebar tab so it does not - // crowd the hand-written docs. Keep in sync with the other root sections' meta.json. - root: true, + // One collapsible group in the single-tree sidebar (module-based IA); it must + // NOT be a root tab — the whole docs tree renders as one sidebar. pages: pages }; fs.writeFileSync(path.join(DOCS_ROOT, 'meta.json'), JSON.stringify(meta, null, 2)); diff --git a/packages/spec/scripts/build-skill-docs.ts b/packages/spec/scripts/build-skill-docs.ts index 51f42b7ada..b063fda7cb 100644 --- a/packages/spec/scripts/build-skill-docs.ts +++ b/packages/spec/scripts/build-skill-docs.ts @@ -12,7 +12,7 @@ * Derived listings (rewritten between `` * markers; prose outside the markers is preserved): * - skills/README.md → the Index table - * - content/docs/guides/skills.mdx → Quick Reference table + per-skill cards + * - content/docs/ai/skills-reference.mdx → Quick Reference table + per-skill cards * * Usage: * tsx scripts/build-skill-docs.ts # write @@ -27,7 +27,7 @@ import path from 'path'; const REPO_ROOT = path.resolve(__dirname, '../../..'); const SKILLS_DIR = path.resolve(REPO_ROOT, 'skills'); const README = path.resolve(SKILLS_DIR, 'README.md'); -const GUIDE = path.resolve(REPO_ROOT, 'content/docs/guides/skills.mdx'); +const GUIDE = path.resolve(REPO_ROOT, 'content/docs/ai/skills-reference.mdx'); // Marker comments delimit the generated region. MDX does not support HTML // comments (``) — it needs `{/* */}` — so the syntax is per file type. diff --git a/packages/spec/src/contracts/cluster-service.ts b/packages/spec/src/contracts/cluster-service.ts index 3b4ec2833b..01d7b3883b 100644 --- a/packages/spec/src/contracts/cluster-service.ts +++ b/packages/spec/src/contracts/cluster-service.ts @@ -4,7 +4,7 @@ * Cluster Service Contracts * * Runtime interfaces for the four cluster primitives defined in - * `content/docs/concepts/cluster-semantics.mdx` §3: + * `content/docs/kernel/cluster.mdx` §3: * * - IPubSub — fan-out messaging across nodes * - ILock — distributed mutual exclusion with TTL fencing diff --git a/packages/spec/src/kernel/cluster.zod.ts b/packages/spec/src/kernel/cluster.zod.ts index 4484a95d19..774093302e 100644 --- a/packages/spec/src/kernel/cluster.zod.ts +++ b/packages/spec/src/kernel/cluster.zod.ts @@ -12,7 +12,7 @@ import { lazySchema } from '../shared/lazy-schema'; * (`memory`, `redis`, `postgres`, `nats`) live in `@objectstack/service-cluster`. * * The full design rationale is in - * `content/docs/concepts/cluster-semantics.mdx`. Read it before changing + * `content/docs/kernel/cluster.mdx`. Read it before changing * any of the enums here — every value has a precise contract that other * subsystems depend on. */ @@ -37,7 +37,7 @@ import { lazySchema } from '../shared/lazy-schema'; * by tenant id so only nodes currently serving the tenant * receive it. * - * @see content/docs/concepts/cluster-semantics.mdx §4.1 + * @see content/docs/kernel/cluster.mdx §4.1 */ export const EventScopeSchema = z.enum(['local', 'cluster', 'tenant']) .describe('Where the event must be delivered: local process, whole cluster, or tenant-scoped.'); @@ -60,7 +60,7 @@ export type EventScope = z.infer; * clear error. Accepted in the schema so future * runtimes can add it without a breaking change. * - * @see content/docs/concepts/cluster-semantics.mdx §4.2 + * @see content/docs/kernel/cluster.mdx §4.2 */ export const EventDeliverySemanticsSchema = z.enum([ 'best-effort', @@ -122,7 +122,7 @@ export type EventClusterOptions = z.infer; * - `cluster` — Logically one instance across the whole cluster. Must * declare a `leaderStrategy` for how the invariant is held. * - * @see content/docs/concepts/cluster-semantics.mdx §5 + * @see content/docs/kernel/cluster.mdx §5 */ export const ServiceClusterScopeSchema = z.enum(['node', 'cluster']) .describe('Whether this service runs on every node or as a cluster singleton.'); @@ -145,7 +145,7 @@ export type ServiceClusterScope = z.infer; * and the work itself is idempotent. Use for * cache invalidation and projection rebuilders. * - * @see content/docs/concepts/cluster-semantics.mdx §5 + * @see content/docs/kernel/cluster.mdx §5 */ export const ServiceLeaderStrategySchema = z.enum([ 'leader-elected', @@ -201,7 +201,7 @@ export type ServiceClusterAnnotations = z.infer z.object({ /** diff --git a/packages/spec/src/kernel/events/core.zod.ts b/packages/spec/src/kernel/events/core.zod.ts index 42068345e1..748b231faa 100644 --- a/packages/spec/src/kernel/events/core.zod.ts +++ b/packages/spec/src/kernel/events/core.zod.ts @@ -62,7 +62,7 @@ export const EventMetadataSchema = lazySchema(() => z.object({ * cross-node delivery, ordering, or persisted at-least-once semantics * MUST set the relevant fields. * - * @see content/docs/concepts/cluster-semantics.mdx §4 + * @see content/docs/kernel/cluster.mdx §4 */ cluster: EventClusterOptionsSchema.optional() .describe('Per-emit cluster routing & delivery options. See cluster-semantics.mdx §4.'), diff --git a/packages/spec/src/kernel/service-registry.zod.ts b/packages/spec/src/kernel/service-registry.zod.ts index d041c96301..b7698ad3e8 100644 --- a/packages/spec/src/kernel/service-registry.zod.ts +++ b/packages/spec/src/kernel/service-registry.zod.ts @@ -80,7 +80,7 @@ export const ServiceMetadataSchema = lazySchema(() => z.object({ * multi-node deployment. Optional — omitting it is equivalent to * `{ clusterScope: 'node' }`, which is correct on a single machine. * - * @see content/docs/concepts/cluster-semantics.mdx §5 + * @see content/docs/kernel/cluster.mdx §5 */ cluster: ServiceClusterAnnotationsSchema.optional() .describe('Cluster scope & leader strategy. See cluster-semantics.mdx §5.'), diff --git a/packages/spec/src/stack.zod.ts b/packages/spec/src/stack.zod.ts index c2cc612290..615ee01e92 100644 --- a/packages/spec/src/stack.zod.ts +++ b/packages/spec/src/stack.zod.ts @@ -1281,7 +1281,7 @@ export const ObjectOSCapabilitiesSchema = lazySchema(() => z.object({ * event scope & delivery semantics; service leader election. Optional; * when absent the kernel uses the in-memory driver (single-process). * - * @see content/docs/concepts/cluster-semantics.mdx + * @see content/docs/kernel/cluster.mdx */ cluster: ClusterCapabilityConfigSchema.optional() .describe('Cluster transport & semantics configuration.'), diff --git a/scripts/check-doc-authoring.mjs b/scripts/check-doc-authoring.mjs index 479c085b54..ba51eea827 100644 --- a/scripts/check-doc-authoring.mjs +++ b/scripts/check-doc-authoring.mjs @@ -19,7 +19,7 @@ import { join } from 'node:path'; const ROOTS = ['skills', 'content']; const SKIP_DIRS = new Set(['node_modules', '.git', 'dist', 'references']); // Generated from spec/frontmatter — not hand-authored, don't police. -const SKIP_FILES = new Set(['content/docs/guides/skills.mdx']); +const SKIP_FILES = new Set(['content/docs/ai/skills-reference.mdx']); const DOMAINS = [ 'Datasource', 'Connector', 'Policy', 'SharingRule', 'Role', 'PermissionSet', diff --git a/skills/objectstack-api/SKILL.md b/skills/objectstack-api/SKILL.md index f76aaeb531..2a5a5049fb 100644 --- a/skills/objectstack-api/SKILL.md +++ b/skills/objectstack-api/SKILL.md @@ -98,7 +98,7 @@ are intended for Web-to-Lead / Web-to-Case style flows. The framework strips fields outside the form's `sections[].fields[]` list; a `beforeInsert` hook on the target object should stamp safe defaults (`status='new'`, `lead_source='web'`, …) and `delete` privileged keys -(`owner`, `internal_notes`, …). See `content/docs/guides/public-forms.mdx` +(`owner`, `internal_notes`, …). See `content/docs/ui/forms.mdx` for the full contract. ### Custom Endpoints diff --git a/skills/objectstack-data/rules/datasources.md b/skills/objectstack-data/rules/datasources.md index a0d13b1c9a..9eced69291 100644 --- a/skills/objectstack-data/rules/datasources.md +++ b/skills/objectstack-data/rules/datasources.md @@ -6,7 +6,7 @@ connection to a data store. Objects route to one via their `datasource` field to read/write a **separate** or **external** database. Full field reference: `node_modules/@objectstack/spec/src/data/datasource.zod.ts`. -Narrative guide: `content/docs/guides/external-datasources.mdx`. +Narrative guide: `content/docs/data-modeling/external-datasources.mdx`. ## `schemaMode` — who owns the schema diff --git a/skills/objectstack-formula/SKILL.md b/skills/objectstack-formula/SKILL.md index 820904d839..51b2aa55a6 100644 --- a/skills/objectstack-formula/SKILL.md +++ b/skills/objectstack-formula/SKILL.md @@ -435,7 +435,7 @@ validator inline. ## See also -- [`content/docs/guides/formula.mdx`](../../content/docs/guides/formula.mdx) — human-facing guide +- [`content/docs/data-modeling/formulas.mdx`](../../content/docs/data-modeling/formulas.mdx) — human-facing guide - [`packages/formula/`](../../packages/formula/) — engine + stdlib - [`packages/spec/src/shared/expression.zod.ts`](../../packages/spec/src/shared/expression.zod.ts) — `Expression`, `ExpressionInput`, `cel` / `F` / `P` - ROADMAP M9 — Expression Unification milestone diff --git a/skills/objectstack-ui/SKILL.md b/skills/objectstack-ui/SKILL.md index 532340da52..97acc01521 100644 --- a/skills/objectstack-ui/SKILL.md +++ b/skills/objectstack-ui/SKILL.md @@ -492,7 +492,7 @@ queries. A widget binds to `dataset` and selects named `dimensions` and `values`; the dataset owns the base object, allowed joins, intrinsic filter, dimensions, and certified measures. Reports bind the same way (`dataset` + `rows` + `values` + `runtimeFilter`). Full guide: **Guides → Analytics Datasets** -(`content/docs/guides/analytics-datasets.mdx`). +(`content/docs/data-modeling/analytics.mdx`). A widget's presentation-scope `filter` flows into the query as the runtime filter; keep `filter` on the widget when binding a dataset. From 0017a38ed5e7b3bc72a053ca99fba9fa12f1a7c0 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 4 Jul 2026 15:19:23 +0000 Subject: [PATCH 3/3] docs(site): purge broken links from quick-reference and mcp README quick-reference had drifted from the generated reference tree: - delete 18 table rows whose schemas do not exist anywhere in packages/spec/src (fictional ai/hub/policy entries, plus a Workflow row duplicating State Machine) - relink 13 rows to the real generated pages (dataset lives in ui/, marketplace/tenant/plugin-security in cloud/, service-registry and plugin-registry in kernel/, connectors in integration/) - unlink 4 rows whose schema exists but has no generated page (driver/postgres, driver/mongo, shared mapping, connector-auth) - recount section headers; resolve the last relative links - drop the mcp README bullet advertising a guide that never existed Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_018r9mjpF7jr9BKdzEmUE4uZ --- .../docs/getting-started/quick-reference.mdx | 70 +++++++------------ packages/mcp/README.md | 1 - 2 files changed, 26 insertions(+), 45 deletions(-) diff --git a/content/docs/getting-started/quick-reference.mdx b/content/docs/getting-started/quick-reference.mdx index 419cb87514..a826f54e0c 100644 --- a/content/docs/getting-started/quick-reference.mdx +++ b/content/docs/getting-started/quick-reference.mdx @@ -23,7 +23,7 @@ Core business logic and data modeling schemas. | **[Query](/docs/references/data/query)** | `query.zod.ts` | Query, QueryOptions | Query AST with joins, aggregations | | **[Filter](/docs/references/data/filter)** | `filter.zod.ts` | QueryFilter, FilterCondition | Advanced filtering operators | | **[Validation](/docs/references/data/validation)** | `validation.zod.ts` | ValidationRule | Business validation rules | -| **[Dataset](./data/dataset)** | `dataset.zod.ts` | Dataset, DatasetMode | Reusable dataset definitions | +| **[Dataset](/docs/references/ui/dataset)** | `dataset.zod.ts` | Dataset, DatasetMode | Reusable dataset definitions | | **[Datasource](/docs/references/data/datasource)** | `datasource.zod.ts` | Datasource, DatasourceType | Database connection configs | | **[Analytics](/docs/references/data/analytics)** | `analytics.zod.ts` | Analytics | Data analytics and aggregation | | **[Mapping](/docs/references/data/mapping)** | `mapping.zod.ts` | FieldMapping | Field transformation mappings | @@ -34,8 +34,8 @@ Core business logic and data modeling schemas. | **[NoSQL Driver](/docs/references/data/driver-nosql)** | `driver-nosql.zod.ts` | NoSQLDriver | NoSQL-specific driver | | **[Document](/docs/references/data/document)** | `document.zod.ts` | Document | Document-oriented data | | **[External Lookup](/docs/references/data/external-lookup)** | `external-lookup.zod.ts` | ExternalLookup | External data lookups | -| **[Postgres Driver](./data/driver/postgres)** | `driver/postgres.zod.ts` | PostgresConfig | PostgreSQL configuration | -| **[Mongo Driver](./data/driver/mongo)** | `driver/mongo.zod.ts` | MongoConfig | MongoDB configuration | +| **Postgres Driver** | `driver/postgres.zod.ts` | PostgresConfig | PostgreSQL configuration | +| **Mongo Driver** | `driver/mongo.zod.ts` | MongoConfig | MongoDB configuration | ## UI Protocol (10 schemas) @@ -73,7 +73,7 @@ Plugin architecture, manifests, and kernel runtime. | **[Plugin Versioning](/docs/references/kernel/plugin-versioning)** | `plugin-versioning.zod.ts` | PluginVersioning | Version compatibility | | **[Service Registry](/docs/references/kernel/service-registry)** | `service-registry.zod.ts` | ServiceRegistry | Service discovery | | **[Startup Orchestrator](/docs/references/kernel/startup-orchestrator)** | `startup-orchestrator.zod.ts` | StartupOrchestrator | System startup | -| **[Events](./kernel/events)** | `events.zod.ts` | Event, EventBus | System event bus | +| **[Events](/docs/kernel/events)** | `events.zod.ts` | Event, EventBus | System event bus | | **[Feature](/docs/references/kernel/feature)** | `feature.zod.ts` | FeatureFlag | Feature flags | | **[Metadata Loader](/docs/references/kernel/metadata-loader)** | `metadata-loader.zod.ts` | MetadataLoader | Metadata loading | | **[Package Registry](/docs/references/kernel/package-registry)** | `package-registry.zod.ts` | PackageRegistry | Package resolution | @@ -102,32 +102,22 @@ Runtime environment, logging, jobs, caching, and observability. | **[Notification](/docs/references/system/notification)** | `notification.zod.ts` | Notification | Notifications | | **[Object Storage](/docs/references/system/object-storage)** | `object-storage.zod.ts` | ObjectStorage | Object storage | | **[Search Engine](/docs/references/system/search-engine)** | `search-engine.zod.ts` | SearchEngine | Full-text search | -| **[Service Registry](./system/service-registry)** | `service-registry.zod.ts` | ServiceRegistry | System services | +| **[Service Registry](/docs/references/kernel/service-registry)** | `service-registry.zod.ts` | ServiceRegistry | System services | | **[Tracing](/docs/references/system/tracing)** | `tracing.zod.ts` | Tracing | Distributed tracing | | **[Translation](/docs/references/system/translation)** | `translation.zod.ts` | Translation | i18n support | | **[Worker](/docs/references/system/worker)** | `worker.zod.ts` | Worker | Background workers | -## AI Protocol (13 schemas) +## AI Protocol (3 schemas) AI/ML capabilities - agents, models, RAG, and cost tracking. | Protocol | Source File | Key Schemas | Purpose | |:---------|:-----------|:------------|:--------| | **[Agent](/docs/references/ai/agent)** | `agent.zod.ts` | Agent, AITool | AI agent definitions | -| **[Agent Action](./ai/agent-action)** | `agent-action.zod.ts` | AgentAction | Agent action definitions | | **[Model Registry](/docs/references/ai/model-registry)** | `model-registry.zod.ts` | ModelRegistry, ModelProvider | LLM model management | -| **[RAG Pipeline](./ai/rag-pipeline)** | `rag-pipeline.zod.ts` | RAGPipelineConfig | Retrieval augmented generation | -| **[NLQ](./ai/nlq)** | `nlq.zod.ts` | NLQRequest, NLQResponse | Natural language to query | | **[Conversation](/docs/references/ai/conversation)** | `conversation.zod.ts` | ConversationSession | Conversation management | -| **[Cost](./ai/cost)** | `cost.zod.ts` | CostEntry, BudgetLimit | AI cost tracking and budgets | -| **[Predictive](./ai/predictive)** | `predictive.zod.ts` | PredictiveModel | Predictive ML models | -| **[Orchestration](./ai/orchestration)** | `orchestration.zod.ts` | AIOrchestration | Multi-agent orchestration | -| **[Feedback Loop](./ai/feedback-loop)** | `feedback-loop.zod.ts` | FeedbackLoop | AI feedback and learning | -| **[DevOps Agent](./ai/devops-agent)** | `devops-agent.zod.ts` | DevOpsAgent | DevOps automation | -| **[Plugin Development](./ai/plugin-development)** | `plugin-development.zod.ts` | PluginDevelopment | AI-assisted development | -| **[Runtime Ops](./ai/runtime-ops)** | `runtime-ops.zod.ts` | RuntimeOps | AI runtime operations | -## API Protocol (20 schemas) +## API Protocol (19 schemas) REST/GraphQL endpoints, real-time subscriptions, and discovery. @@ -149,19 +139,17 @@ REST/GraphQL endpoints, real-time subscriptions, and discovery. | **[Auth](/docs/references/api/auth)** | `auth.zod.ts` | Auth | API authentication | | **[Analytics](/docs/references/api/analytics)** | `analytics.zod.ts` | Analytics | API usage analytics | | **[Documentation](/docs/references/api/documentation)** | `documentation.zod.ts` | Documentation | API docs generation | -| **[Hub](./api/hub)** | `hub.zod.ts` | Hub | API hub integration | | **[Metadata](/docs/references/api/metadata)** | `metadata.zod.ts` | Metadata | API metadata endpoints | | **[Registry](/docs/references/api/registry)** | `registry.zod.ts` | Registry | API registry | | **[Storage](/docs/references/api/storage)** | `storage.zod.ts` | Storage | API storage operations | -## Automation Protocol (8 schemas) +## Automation Protocol (7 schemas) Flows, state machines, approvals, and integrations. | Protocol | Source File | Key Schemas | Purpose | |:---------|:-----------|:------------|:--------| | **[Flow](/docs/references/automation/flow)** | `flow.zod.ts` | Flow, FlowNode | Visual workflow builder | -| **[Workflow](./automation/workflow)** | `state-machine.zod.ts` | StateMachine | Historical route; current workflow semantics are state machines plus Flow | | **[Approval](/docs/references/automation/approval)** | `approval.zod.ts` | ApprovalNodeConfig | Flow approval-node config | | **[State Machine](/docs/references/automation/state-machine)** | `state-machine.zod.ts` | StateMachine | State machine definitions | | **[Webhook](/docs/references/automation/webhook)** | `webhook.zod.ts` | Webhook, WebhookEvent | Outbound webhooks | @@ -169,14 +157,13 @@ Flows, state machines, approvals, and integrations. | **[Trigger Registry](/docs/references/automation/trigger-registry)** | `trigger-registry.zod.ts` | TriggerRegistry | Event-driven triggers | | **[Sync](/docs/references/automation/sync)** | `sync.zod.ts` | SyncConfig | Bi-directional data sync | -## Security Protocol (5 schemas) +## Security Protocol (4 schemas) Access control, permissions, and row-level security. | Protocol | Source File | Key Schemas | Purpose | |:---------|:-----------|:------------|:--------| | **[Permission](/docs/references/security/permission)** | `permission.zod.ts` | ObjectPermission | Object-level permissions | -| **[Policy](./security/policy)** | `policy.zod.ts` | SecurityPolicy | Security policies | | **[RLS](/docs/references/security/rls)** | `rls.zod.ts` | RowLevelSecurity | Row-level security filters | | **[Sharing](/docs/references/security/sharing)** | `sharing.zod.ts` | SharingRule | Record sharing rules | | **[Territory](/docs/references/security/territory)** | `territory.zod.ts` | Territory | Territory-based access | @@ -192,21 +179,16 @@ User identity, organizations, and role management. | **[Role](/docs/references/identity/role)** | `role.zod.ts` | Role | Role-based access control | | **[SCIM](/docs/references/identity/scim)** | `scim.zod.ts` | SCIMUser, SCIMGroup | SCIM 2.0 provisioning | -## Cloud Protocol (9 schemas) +## Cloud Protocol (4 schemas) Marketplace, licensing, and multi-tenancy. | Protocol | Source File | Key Schemas | Purpose | |:---------|:-----------|:------------|:--------| -| **[Marketplace](./hub/marketplace)** | `marketplace.zod.ts` | Package, PackageVersion | Plugin marketplace | -| **[Plugin Registry](./hub/plugin-registry)** | `plugin-registry.zod.ts` | PluginRegistry | Plugin versioning | -| **[Plugin Security](./hub/plugin-security)** | `plugin-security.zod.ts` | PluginSecurity | Plugin security policies | -| **[Composer](./hub/composer)** | `composer.zod.ts` | Dependency | Dependency management | -| **[License](./hub/license)** | `license.zod.ts` | License, LicenseType | Feature licensing | -| **[Tenant](./hub/tenant)** | `tenant.zod.ts` | Tenant | Multi-tenancy isolation | -| **[Space](./hub/space)** | `space.zod.ts` | Space, Workspace | Workspace management | -| **[Hub Federation](./hub/hub-federation)** | `hub-federation.zod.ts` | HubFederation | Cross-instance federation | -| **[Registry Config](./hub/registry-config)** | `registry-config.zod.ts` | RegistryConfig | Registry settings | +| **[Marketplace](/docs/references/cloud/marketplace)** | `marketplace.zod.ts` | Package, PackageVersion | Plugin marketplace | +| **[Plugin Registry](/docs/references/kernel/plugin-registry)** | `plugin-registry.zod.ts` | PluginRegistry | Plugin versioning | +| **[Plugin Security](/docs/references/cloud/plugin-security)** | `plugin-security.zod.ts` | PluginSecurity | Plugin security policies | +| **[Tenant](/docs/references/cloud/tenant)** | `tenant.zod.ts` | Tenant | Multi-tenancy isolation | ## Integration Protocol (7 schemas) @@ -215,12 +197,12 @@ External system connectors and adapters. | Protocol | Source File | Key Schemas | Purpose | |:---------|:-----------|:------------|:--------| | **[Connector](/docs/references/integration/connector)** | `connector.zod.ts` | Connector | Generic connector interface | -| **[SaaS Connector](./integration/connector/saas)** | `connector/saas.zod.ts` | SaaSConnector | SaaS integrations | -| **[Database Connector](./integration/connector/database)** | `connector/database.zod.ts` | DatabaseConnector | Database adapters | -| **[File Storage](./integration/connector/file-storage)** | `connector/file-storage.zod.ts` | FileStorageConnector | Cloud storage | -| **[Message Queue](./integration/connector/message-queue)** | `connector/message-queue.zod.ts` | MessageQueueConnector | Queue integrations | -| **[GitHub](./integration/connector/github)** | `connector/github.zod.ts` | GitHubConnector | GitHub API integration | -| **[Vercel](./integration/connector/vercel)** | `connector/vercel.zod.ts` | VercelConnector | Vercel deployment | +| **[SaaS Connector](/docs/references/integration/connector)** | `connector/saas.zod.ts` | SaaSConnector | SaaS integrations | +| **[Database Connector](/docs/references/integration/connector)** | `connector/database.zod.ts` | DatabaseConnector | Database adapters | +| **[File Storage](/docs/references/integration/connector)** | `connector/file-storage.zod.ts` | FileStorageConnector | Cloud storage | +| **[Message Queue](/docs/references/integration/message-queue)** | `connector/message-queue.zod.ts` | MessageQueueConnector | Queue integrations | +| **[GitHub](/docs/references/integration/connector)** | `connector/github.zod.ts` | GitHubConnector | GitHub API integration | +| **[Vercel](/docs/references/integration/connector)** | `connector/vercel.zod.ts` | VercelConnector | Vercel deployment | ## Shared Protocol (4 schemas) @@ -230,8 +212,8 @@ Common utilities used across all protocols. |:---------|:-----------|:------------|:--------| | **[HTTP](/docs/references/shared/http)** | `http.zod.ts` | HTTPRequest, HTTPResponse | HTTP utilities | | **[Identifiers](/docs/references/shared/identifiers)** | `identifiers.zod.ts` | ID formats | Standard ID patterns | -| **[Mapping](./shared/mapping)** | `mapping.zod.ts` | MappingRule | Field mapping utilities | -| **[Connector Auth](./shared/connector-auth)** | `connector-auth.zod.ts` | ConnectorAuth | Connector auth patterns | +| **Mapping** | `mapping.zod.ts` | MappingRule | Field mapping utilities | +| **Connector Auth** | `connector-auth.zod.ts` | ConnectorAuth | Connector auth patterns | ## QA Protocol (1 schema) @@ -303,15 +285,15 @@ import type { Field, Object, Query, View } from '@objectstack/spec'; - **By Feature**: "How do I model relationships?" → [Field Protocol](/docs/references/data/field) → `lookup` or `master_detail` types - **By Use Case**: "Build a dashboard" → [Dashboard Protocol](/docs/references/ui/dashboard) -- **By Layer**: Data → [Data Protocol](./data), UI → [UI Protocol](./ui), Runtime → [System Protocol](./system) +- **By Layer**: Data → [Data Protocol](/docs/references/data), UI → [UI Protocol](/docs/references/ui), Runtime → [System Protocol](/docs/references/system) ## Next Steps -**New to ObjectStack?** Start with the [Introduction](../introduction) to learn core concepts before diving into specific protocols. +**New to ObjectStack?** Start with the [Introduction](/docs/getting-started) to learn core concepts before diving into specific protocols. - [Protocol Reference Index](/docs/guides) - Full protocol documentation -- [ObjectQL Guide](../objectql) - Deep dive into data modeling -- [ObjectUI Guide](../objectui) - UI development guide +- [Data Modeling](/docs/data-modeling) - Deep dive into data modeling +- [UI Engine](/docs/ui) - UI development guide - [Contributing Guide](https://github.com/objectstack-ai/framework/blob/main/CONTRIBUTING.md) - How to contribute to protocols diff --git a/packages/mcp/README.md b/packages/mcp/README.md index 741b29ef48..60398b1607 100644 --- a/packages/mcp/README.md +++ b/packages/mcp/README.md @@ -555,4 +555,3 @@ Apache-2.0. See [LICENSING.md](../../LICENSING.md). - [Model Context Protocol Specification](https://modelcontextprotocol.io/) - [MCP TypeScript SDK](https://github.com/modelcontextprotocol/typescript-sdk) - [@objectstack/spec/ai](../../spec/src/ai/) -- [Building MCP Servers Guide](/content/docs/ai/)