diff --git a/.claude/launch.json b/.claude/launch.json new file mode 100644 index 0000000..4ddbeef --- /dev/null +++ b/.claude/launch.json @@ -0,0 +1,23 @@ +{ + "version": "0.0.1", + "configurations": [ + { + "name": "Docs site (@objectos/docs)", + "runtimeExecutable": "pnpm", + "runtimeArgs": ["--filter", "@objectos/docs", "dev"], + "port": 3000, + "autoPort": true + }, + { + "name": "ObjectStack server (@objectos/server)", + "runtimeExecutable": "pnpm", + "runtimeArgs": ["--filter", "@objectos/server", "dev"], + "port": 3001 + }, + { + "name": "Desktop app (@objectos/one, Tauri)", + "runtimeExecutable": "pnpm", + "runtimeArgs": ["--filter", "@objectos/one", "dev"] + } + ] +} diff --git a/apps/docs/app/[lang]/layout.tsx b/apps/docs/app/[lang]/layout.tsx index f1c6ad4..391a282 100644 --- a/apps/docs/app/[lang]/layout.tsx +++ b/apps/docs/app/[lang]/layout.tsx @@ -5,7 +5,11 @@ import { i18n } from '@/lib/i18n'; // Language display names mapping const LANGUAGE_NAMES: Record = { en: 'English', - cn: '中文', + 'zh-Hans': '简体中文', + ja: '日本語', + de: 'Deutsch', + es: 'Español', + fr: 'Français', }; export default async function LanguageLayout({ diff --git a/apps/docs/app/[lang]/privacy/page.tsx b/apps/docs/app/[lang]/privacy/page.tsx index ddec0c2..de564e9 100644 --- a/apps/docs/app/[lang]/privacy/page.tsx +++ b/apps/docs/app/[lang]/privacy/page.tsx @@ -26,7 +26,7 @@ const content = { ], back: '← Back to home', }, - cn: { + 'zh-Hans': { title: '隐私政策', updated: '最近更新:2026 年 5 月 27 日', body: [ @@ -57,7 +57,7 @@ export default async function PrivacyPage({ params: Promise<{ lang: string }>; }) { const { lang } = await params; - const t = content[lang === 'cn' ? 'cn' : 'en']; + const t = content[lang as keyof typeof content] ?? content.en; return ( diff --git a/apps/docs/app/[lang]/terms/page.tsx b/apps/docs/app/[lang]/terms/page.tsx index ae9fa22..6327754 100644 --- a/apps/docs/app/[lang]/terms/page.tsx +++ b/apps/docs/app/[lang]/terms/page.tsx @@ -30,7 +30,7 @@ const content = { ], back: '← Back to home', }, - cn: { + 'zh-Hans': { title: '服务条款', updated: '最近更新:2026 年 5 月 27 日', body: [ @@ -65,7 +65,7 @@ export default async function TermsPage({ params: Promise<{ lang: string }>; }) { const { lang } = await params; - const t = content[lang === 'cn' ? 'cn' : 'en']; + const t = content[lang as keyof typeof content] ?? content.en; return ( diff --git a/apps/docs/lib/download-i18n.ts b/apps/docs/lib/download-i18n.ts index b2a9c47..b6129b6 100644 --- a/apps/docs/lib/download-i18n.ts +++ b/apps/docs/lib/download-i18n.ts @@ -1,7 +1,7 @@ /** * Download page translations + static install data. * - * English is the source of truth — edit `en` first, then sync `cn`. + * English is the source of truth — edit `en` first, then sync `zhHans`. * * Only include install methods that have a real, published artifact: * - Docker image: ghcr.io/objectstack-ai/objectos:latest (docker.yml) @@ -198,7 +198,7 @@ export const en: DownloadTranslations = { copy: { copy: 'Copy', copied: 'Copied' }, }; -export const cn: DownloadTranslations = { +export const zhHans: DownloadTranslations = { badge: `最新发布 · v${ONE_VERSION}`, hero: { title: '下载 ObjectOS', @@ -313,8 +313,17 @@ export const cn: DownloadTranslations = { copy: { copy: '复制', copied: '已复制' }, }; +/** + * Registry of available download-page translations. Locales absent + * here (ja, de, es, fr until translated) resolve to English. + */ +const DOWNLOAD_TRANSLATIONS: Partial> = { + en, + 'zh-Hans': zhHans, +}; + export function getDownloadTranslations(lang: string): DownloadTranslations { - return lang === 'cn' ? cn : en; + return DOWNLOAD_TRANSLATIONS[lang] ?? en; } /* ------------------------------------------------------------------ */ diff --git a/apps/docs/lib/homepage-i18n.ts b/apps/docs/lib/homepage-i18n.ts index b81ad23..fab7000 100644 --- a/apps/docs/lib/homepage-i18n.ts +++ b/apps/docs/lib/homepage-i18n.ts @@ -7,7 +7,8 @@ * evaluating a customer-hosted runtime for ObjectStack applications — * NOT framework developers. * - * Supports: en (English), cn (Chinese / 中文) + * Supports: en (English), zh-Hans (简体中文). Additional locales + * (ja, de, es, fr) fall back to English until their objects are added. */ import { SPEC_VERSION, OBJECTOS_VERSION } from './version'; @@ -332,9 +333,9 @@ export const en: HomepageTranslations = { }; /** - * Chinese Translations (中文翻译) + * Chinese (Simplified) Translations (简体中文翻译) */ -export const cn: HomepageTranslations = { +export const zhHans: HomepageTranslations = { badge: { status: 'AI 原生业务平台', version: SPEC_VERSION, @@ -487,14 +488,17 @@ export const cn: HomepageTranslations = { }; /** - * Get translations for a specific language + * Registry of available homepage translations. Locales absent here + * (ja, de, es, fr until translated) resolve to English via the getter. + */ +const HOMEPAGE_TRANSLATIONS: Partial> = { + en, + 'zh-Hans': zhHans, +}; + +/** + * Get translations for a specific language, falling back to English. */ export function getHomepageTranslations(lang: string): HomepageTranslations { - switch (lang) { - case 'cn': - return cn; - case 'en': - default: - return en; - } + return HOMEPAGE_TRANSLATIONS[lang] ?? en; } diff --git a/apps/docs/lib/i18n.ts b/apps/docs/lib/i18n.ts index 9657059..c7be422 100644 --- a/apps/docs/lib/i18n.ts +++ b/apps/docs/lib/i18n.ts @@ -2,14 +2,18 @@ import { defineI18n } from 'fumadocs-core/i18n'; /** * i18n Configuration for ObjectStack Documentation - * - * Supported Languages: - * - en: English (Default) - * - cn: Chinese (中文) + * + * Supported Languages (BCP 47 tags): + * - en: English (Default) + * - zh-Hans: Chinese, Simplified (简体中文) + * - ja: Japanese (日本語) + * - de: German (Deutsch) + * - es: Spanish (Español) + * - fr: French (Français) */ export const i18n = defineI18n({ defaultLanguage: 'en', - languages: ['en', 'cn'], + languages: ['en', 'zh-Hans', 'ja', 'de', 'es', 'fr'], // Hide locale prefix for default language (e.g., /docs instead of /en/docs) hideLocale: 'default-locale', }); diff --git a/apps/docs/lib/layout.shared.tsx b/apps/docs/lib/layout.shared.tsx index b0d00f9..d808146 100644 --- a/apps/docs/lib/layout.shared.tsx +++ b/apps/docs/lib/layout.shared.tsx @@ -9,7 +9,11 @@ export const gitConfig = { const NAV_LABELS: Record = { en: { docs: 'Docs', download: 'Download', changelog: 'Changelog' }, - cn: { docs: '文档', download: '下载', changelog: '更新日志' }, + 'zh-Hans': { docs: '文档', download: '下载', changelog: '更新日志' }, + ja: { docs: 'ドキュメント', download: 'ダウンロード', changelog: '変更履歴' }, + de: { docs: 'Dokumentation', download: 'Download', changelog: 'Änderungen' }, + es: { docs: 'Documentación', download: 'Descargar', changelog: 'Cambios' }, + fr: { docs: 'Documentation', download: 'Télécharger', changelog: 'Journal' }, }; const RELEASES_URL = 'https://github.com/objectstack-ai/objectos/releases'; diff --git a/apps/docs/middleware.ts b/apps/docs/middleware.ts index 51da12e..bd162dc 100644 --- a/apps/docs/middleware.ts +++ b/apps/docs/middleware.ts @@ -24,10 +24,21 @@ function setLocaleCookie(response: NextResponse, locale: string): void { * Maps browser language codes to our supported language codes */ const LANGUAGE_MAPPING: Record = { - 'zh': 'cn', // Chinese -> cn - 'zh-CN': 'cn', // Chinese (China) -> cn - 'zh-TW': 'cn', // Chinese (Taiwan) -> cn - 'zh-HK': 'cn', // Chinese (Hong Kong) -> cn + 'zh': 'zh-Hans', // Chinese -> Simplified + 'zh-CN': 'zh-Hans', // Chinese (China) -> Simplified + 'zh-SG': 'zh-Hans', // Chinese (Singapore) -> Simplified + 'zh-Hans': 'zh-Hans', // already Simplified + // Traditional variants fall back to Simplified until zh-Hant ships + 'zh-TW': 'zh-Hans', + 'zh-HK': 'zh-Hans', +}; + +/** + * Legacy locale redirects: old locale code -> current BCP 47 tag. + * Permanent (308) so search engines transfer ranking to the new path. + */ +const LEGACY_LOCALE_REDIRECTS: Record = { + cn: 'zh-Hans', }; /** @@ -83,7 +94,8 @@ function getPreferredLanguage(request: NextRequest): string { * - Detects the user's preferred language from browser settings or cookies * - Redirects users to the appropriate localized version * - For default language (en): keeps URL as "/" (with internal rewrite) - * - For other languages (cn): redirects to "/cn/" + * - For other languages (e.g. zh-Hans): redirects to "/zh-Hans/" + * - Redirects legacy locale paths (e.g. /cn/*) to their new tag * - Stores language preference as a cookie */ export default function middleware(request: NextRequest) { @@ -99,6 +111,20 @@ export default function middleware(request: NextRequest) { const { pathname } = request.nextUrl; + // Legacy locale redirect (e.g. /cn/... -> /zh-Hans/...), permanent for SEO. + const legacySeg = pathname.split('/')[1]; + if (legacySeg && LEGACY_LOCALE_REDIRECTS[legacySeg]) { + const target = LEGACY_LOCALE_REDIRECTS[legacySeg]; + const url = new URL(request.url); + url.pathname = pathname.replace( + new RegExp(`^/${legacySeg}(/|$)`), + `/${target}$1`, + ); + const response = NextResponse.redirect(url, 308); + setLocaleCookie(response, target); + return response; + } + // Check if the pathname already has a locale const pathnameHasLocale = i18n.languages.some( (locale) => pathname.startsWith(`/${locale}/`) || pathname === `/${locale}` diff --git a/content/docs/architecture.de.mdx b/content/docs/architecture.de.mdx new file mode 100644 index 0000000..63a351f --- /dev/null +++ b/content/docs/architecture.de.mdx @@ -0,0 +1,139 @@ +--- +title: Architektur +description: Was tatsächlich auf Ihren Systemen läuft — für die Engineers, die abwägen, ob sie dies einführen sollen. +--- + +# Architektur + +Eine praxisnahe Sicht darauf, was auf Ihren Maschinen läuft, wenn Sie +ObjectOS bereitstellen, welche Daten Ihr Netzwerk verlassen und welche nicht. + +Das mentale Modell besteht aus zwei dünnen Schichten: + +1. **Metadaten** — Pakete aus Objekten / Views / Actions / Flows / + Agents. Größtenteils vom [AI Builder](/docs/build/ai-builder) + gegen eine sandboxed Tool-API geschrieben; teils von Hand bearbeitet, stets + versionskontrolliert und auditiert. +2. **Eine einzige Node.js-Laufzeit**, die diese Metadaten in eine + funktionierende Anwendung interpretiert — REST-API, Console-UI, Berechtigungen, Jobs, AI-Tools — alles in einem Prozess, der mit Ihrer Datenbank kommuniziert. + +Kein Codegenerierungsschritt, keine Deploy-Pipeline zwischen „Benutzer hat +beschrieben, was er möchte" und „es ist live". Die Laufzeit lädt die neuen +Metadaten nach einer HITL-Freigabe per Hot-Reload. + +## Was Sie bereitstellen + +Ein Node.js-Prozess pro ObjectOS-Instanz. Das ist alles. + +```text +┌─────────────────────────────────────────────────────┐ +│ ObjectOS process │ +│ ┌───────────────────────────────────────────────┐ │ +│ │ HTTP dispatcher (/ · /api · /_console …) │ │ +│ ├───────────────────────────────────────────────┤ │ +│ │ Per-project ObjectKernel (LRU cached) │ │ +│ │ ├─ Auth (Better Auth) │ │ +│ │ ├─ Security (RBAC + row-level + field) │ │ +│ │ ├─ ObjectQL (data engine, generates SQL) │ │ +│ │ ├─ REST API generator │ │ +│ │ └─ Capabilities loaded per artifact │ │ +│ │ (audit, storage, jobs, queue, AI …) │ │ +│ └───────────────────────────────────────────────┘ │ +└──────────┬──────────────────────────────────────────┘ + │ + ▼ + Your business database + (Postgres / MySQL / SQLite / Turso / MongoDB) +``` + +Es hat die Komplexität einer einzigen statisch gelinkten Binärdatei. Kein +Sidecar, kein Kafka, keine separate Cache-Schicht erforderlich. Fügen Sie diese hinzu, wenn Sie +sie brauchen; zahlen Sie nicht am ersten Tag dafür. + +## Wo Ihre Daten liegen + +| Daten | Liegen in | Verlassen Ihr Netzwerk? | +|---|---|---| +| Geschäftsdatensätze | Ihrer Datenbank | **Nein** | +| Benutzerkonten, Sitzungen, OAuth-Tokens | Ihrer Datenbank | **Nein** | +| Audit-Log | Ihrer Datenbank | **Nein** | +| Einstellungen, API-Schlüssel, Secrets | Ihrer Datenbank / Secret-Manager | **Nein** | +| Hochgeladene Dateien | Ihrer Festplatte oder Ihrem S3/R2-Bucket | **Nein** | +| Die kompilierte App-Definition (`objectstack.json`) | Einer Datei auf der Festplatte oder abgerufen von Ihrer Control Plane | Optional | + +ObjectOS telefoniert nicht nach Hause. Keine Telemetrie. Keine Lizenzprüfung. Wenn Sie den +Internetzugang vollständig kappen, läuft es unbegrenzt weiter. Siehe +[Air-gapped](/docs/deploy/air-gapped). + +## Wie eine Anfrage bedient wird + +```text +1. Ingress / TLS termination (your load balancer) +2. HTTP dispatcher (security headers, request id) +3. Hostname → project resolution (cached, TTL configurable) +4. Get or build per-project kernel from LRU +5. AuthPlugin — session cookie, bearer token, or API key +6. SecurityPlugin — RBAC + row-level + field-level checks +7. Route handler — generated REST, declarative action, or custom +8. Data driver — ObjectQL compiles to SQL / Mongo query +9. Response with X-Request-Id propagated +``` + +Die Schritte 4–8 werden typischerweise in < 5 ms ausgeführt, sobald der Kernel warm ist. + +## Die drei Schichten (nur relevant, wenn Sie integrieren) + +Die meisten Kunden stellen nur **ObjectOS** bereit. Die anderen beiden Schichten existieren, falls +Sie wissen möchten, woher das Artefakt stammt: + +| Schicht | Was es ist | Wo es läuft | +|---|---|---| +| **Framework** (`@objectstack/*`) | Open-Source-Kernel, ObjectQL, Plugins, Treiber | npm — zur Build-Zeit eingebunden | +| **Control Plane** (optional) | Veröffentlicht kompilierte `objectstack.json`-Artefakte; Sie können die gehostete ObjectStack Cloud nutzen, eine eigene betreiben oder sie ganz weglassen | Ihre CI, unsere Cloud oder Ihr Laptop | +| **ObjectOS** | Die Laufzeit, die Sie betreiben | **Ihre Infrastruktur** | + +Wenn Sie eine einzelne App ausliefern, benötigen Sie keine Control Plane — +kompilieren Sie `objectstack.config.ts → dist/objectstack.json` in Ihrer CI und +liefern Sie das JSON im Image aus. Wenn Sie einen internen App-Marketplace +mit vielen Tenants und Apps betreiben, ist die Control Plane der Ort, an dem der +Katalog liegt. + +## Boot-Modi + +| Modus | Wann | Wie | +|---|---|---| +| **Standalone** | Einzelne App, Entwicklung, Evaluierung, Air-gapped, die meisten Produktionsbereitstellungen | `pnpm dev` oder `dist/objectstack.json` von der Festplatte ausführen | +| **File-backed** | Produktion mit extern verwalteten Artefakten | `OS_ARTIFACT_PATH=/path/to/objectstack.json` setzen | +| **Cloud-connected** | Multi-Tenant- / Multi-App-Bereitstellungen, gespeist von einer Control Plane | `OS_CLOUD_URL` + `OS_CLOUD_API_KEY` setzen | + +Der Modus wird automatisch anhand von Umgebungsvariablen erkannt. + +## Performance-Eigenschaften + +| Metrik | Wert | +|---|---| +| Kaltstart (Prozess hochgefahren, bereit für Traffic) | ~1 Sekunde | +| Kernel-Warmup (erste Anfrage an ein Projekt) | 50–300 ms je nach Capabilities | +| Latenz bei warmer Anfrage (CRUD via REST) | typischerweise < 10 ms + Datenbanklatenz | +| Speicherbedarf | ~150 MB Basis; ~10–30 MB pro aktivem Projekt-Kernel | +| Gleichzeitige Projekte pro Instanz | Begrenzt durch `OS_KERNEL_CACHE_SIZE` (Standard 32) | + +## Warum diese Form + +- **Ein Node-Prozess, keine Sidecars** → passt in ein `docker run`, passt in eine + systemd-Unit, passt in eine Lambda-ähnliche Umgebung. +- **Per-Projekt-Kernel, LRU-gecacht** → eine Instanz kann viele + kleine Apps bedienen, ohne bei jeder Anfrage die Warmup-Kosten zu tragen. +- **Generierte APIs auf Basis deklarierter Metadaten** → es gibt keinen Codegen- + Schritt in Ihrer CI, kein Client-SDK zum Veröffentlichen; die API entspricht Ihrem Datenmodell konstruktionsbedingt. +- **Alle Capabilities sind optionale Plugins** → die Image-Größe skaliert mit dem, + was Sie tatsächlich nutzen. + +## Wie es weitergeht + +- [Production Readiness](/docs/operate/production) — Checkliste, bevor + Sie es echtem Traffic aussetzen. +- [Runtime Configuration](/docs/configure/runtime) — Verdrahtung von Datenbanken, + Caches und Secrets. +- [Runtime Capabilities](/docs/reference/runtime-capabilities) — + welche optionalen Pakete existieren und was sie ermöglichen. diff --git a/content/docs/architecture.es.mdx b/content/docs/architecture.es.mdx new file mode 100644 index 0000000..d2f9cd0 --- /dev/null +++ b/content/docs/architecture.es.mdx @@ -0,0 +1,142 @@ +--- +title: Arquitectura +description: Lo que realmente estás ejecutando — para el ingeniero que evalúa si vale la pena adoptar esto. +--- + +# Arquitectura + +Una visión práctica de lo que se ejecuta en tus máquinas cuando despliegas +ObjectOS, qué datos salen de tu red y cuáles no. + +El modelo mental son dos capas delgadas: + +1. **Metadatos** — paquetes de objetos / vistas / acciones / flujos / + agentes. En su mayoría escritos por el [AI Builder](/docs/build/ai-builder) + contra una API de herramientas en un entorno aislado (sandbox); a veces + editados a mano, siempre con control de versiones y auditados. +2. **Un único runtime de Node.js** que interpreta esos metadatos en una + aplicación funcional — REST API, Console UI, permisos, trabajos, herramientas + de IA — todo en un solo proceso, comunicándose con tu base de datos. + +Sin paso de generación de código, sin pipeline de despliegue entre "el usuario +describió lo que quería" y "está en producción". El runtime carga en caliente los +nuevos metadatos tras una aprobación HITL. + +## Lo que despliegas + +Un proceso de Node.js por instancia de ObjectOS. Eso es todo. + +```text +┌─────────────────────────────────────────────────────┐ +│ ObjectOS process │ +│ ┌───────────────────────────────────────────────┐ │ +│ │ HTTP dispatcher (/ · /api · /_console …) │ │ +│ ├───────────────────────────────────────────────┤ │ +│ │ Per-project ObjectKernel (LRU cached) │ │ +│ │ ├─ Auth (Better Auth) │ │ +│ │ ├─ Security (RBAC + row-level + field) │ │ +│ │ ├─ ObjectQL (data engine, generates SQL) │ │ +│ │ ├─ REST API generator │ │ +│ │ └─ Capabilities loaded per artifact │ │ +│ │ (audit, storage, jobs, queue, AI …) │ │ +│ └───────────────────────────────────────────────┘ │ +└──────────┬──────────────────────────────────────────┘ + │ + ▼ + Your business database + (Postgres / MySQL / SQLite / Turso / MongoDB) +``` + +Equivale a la complejidad de un único binario enlazado estáticamente. Sin +sidecar, sin Kafka, sin necesidad de una capa de caché separada. Añade esas +cosas cuando las necesites; no pagues por ellas desde el primer día. + +## Dónde viven tus datos + +| Datos | Viven en | ¿Salen de tu red? | +|---|---|---| +| Registros de negocio | Tu base de datos | **No** | +| Cuentas de usuario, sesiones, tokens OAuth | Tu base de datos | **No** | +| Registro de auditoría | Tu base de datos | **No** | +| Configuraciones, claves API, secretos | Tu base de datos / gestor de secretos | **No** | +| Archivos subidos | Tu disco o tu bucket S3/R2 | **No** | +| La definición compilada de la app (`objectstack.json`) | Un archivo en disco u obtenido desde tu plano de control | Opcional | + +ObjectOS no se comunica con el exterior. Sin telemetría. Sin verificación de +licencia. Si cortas el acceso a internet por completo, sigue funcionando +indefinidamente. Consulta [Air-gapped](/docs/deploy/air-gapped). + +## Cómo se atiende una solicitud + +```text +1. Ingress / TLS termination (your load balancer) +2. HTTP dispatcher (security headers, request id) +3. Hostname → project resolution (cached, TTL configurable) +4. Get or build per-project kernel from LRU +5. AuthPlugin — session cookie, bearer token, or API key +6. SecurityPlugin — RBAC + row-level + field-level checks +7. Route handler — generated REST, declarative action, or custom +8. Data driver — ObjectQL compiles to SQL / Mongo query +9. Response with X-Request-Id propagated +``` + +Los pasos 4-8 normalmente se ejecutan en < 5ms una vez que el kernel está +caliente. + +## Las tres capas (solo importa si estás integrando) + +La mayoría de los clientes despliegan únicamente **ObjectOS**. Las otras dos +capas existen por si quieres saber de dónde viene el artefacto: + +| Capa | Qué es | Dónde se ejecuta | +|---|---|---| +| **Framework** (`@objectstack/*`) | Kernel de código abierto, ObjectQL, plugins, drivers | npm — incorporado en tiempo de compilación | +| **Plano de control** (opcional) | Publica artefactos `objectstack.json` compilados; puedes usar el ObjectStack Cloud alojado, ejecutar el tuyo propio u omitirlo por completo | Tu CI, nuestra nube o tu portátil | +| **ObjectOS** | El runtime que operas | **Tu infraestructura** | + +Si estás distribuyendo una sola app, no necesitas un plano de control — +compila `objectstack.config.ts → dist/objectstack.json` en tu CI y +distribuye el JSON en la imagen. Si estás ejecutando un marketplace interno de +apps con muchos inquilinos y aplicaciones, el plano de control es donde reside +el catálogo. + +## Modos de arranque + +| Modo | Cuándo | Cómo | +|---|---|---| +| **Standalone** | App única, desarrollo, evaluación, air-gapped, la mayoría de despliegues de producción | `pnpm dev` o ejecuta `dist/objectstack.json` desde disco | +| **File-backed** | Producción con artefactos gestionados externamente | Define `OS_ARTIFACT_PATH=/path/to/objectstack.json` | +| **Cloud-connected** | Despliegues multi-inquilino / multi-app alimentados por un plano de control | Define `OS_CLOUD_URL` + `OS_CLOUD_API_KEY` | + +El modo se detecta automáticamente a partir de las variables de entorno. + +## Características de rendimiento + +| Métrica | Número | +|---|---| +| Arranque en frío (proceso activo, listo para tráfico) | ~1 segundo | +| Calentamiento por kernel (primera solicitud a un proyecto) | 50-300ms según las capacidades | +| Latencia de solicitud en caliente (CRUD vía REST) | normalmente < 10ms + latencia de base de datos | +| Huella de memoria | ~150MB base; ~10-30MB por kernel de proyecto activo | +| Proyectos concurrentes por instancia | Limitado por `OS_KERNEL_CACHE_SIZE` (32 por defecto) | + +## Por qué esta forma + +- **Un proceso de Node, sin sidecars** → cabe en un `docker run`, cabe en una + unidad systemd, cabe en un entorno tipo Lambda. +- **Kernel por proyecto, con caché LRU** → una instancia puede atender muchas + apps pequeñas sin pagar el coste de calentamiento en cada solicitud. +- **APIs generadas sobre metadatos declarados** → no hay paso de codegen + en tu CI, ni SDK de cliente que publicar; la API coincide con tu modelo de + datos por construcción. +- **Todas las capacidades son plugins opcionales** → el tamaño de la imagen + escala con lo que realmente usas. + +## A dónde ir después + +- [Production Readiness](/docs/operate/production) — checklist antes de + exponerlo a tráfico real. +- [Runtime Configuration](/docs/configure/runtime) — conexión de bases de + datos, cachés y secretos. +- [Runtime Capabilities](/docs/reference/runtime-capabilities) — + qué paquetes opcionales existen y qué habilitan. diff --git a/content/docs/architecture.fr.mdx b/content/docs/architecture.fr.mdx new file mode 100644 index 0000000..8bfb5f6 --- /dev/null +++ b/content/docs/architecture.fr.mdx @@ -0,0 +1,141 @@ +--- +title: Architecture +description: Ce que vous exécutez réellement — pour l'ingénieur qui évalue s'il faut adopter cette solution. +--- + +# Architecture + +Une vision pratique de ce qui s'exécute sur vos machines lorsque vous déployez +ObjectOS, des données qui quittent votre réseau et de celles qui n'en sortent pas. + +Le modèle mental repose sur deux couches légères : + +1. **Métadonnées** — des packages d'objets / vues / actions / flows / + agents. Écrits pour l'essentiel par l'[AI Builder](/docs/build/ai-builder) + via une API d'outils en bac à sable ; parfois édités à la main, toujours + versionnés et audités. +2. **Un unique runtime Node.js** qui interprète ces métadonnées pour en faire une + application fonctionnelle — API REST, interface Console, permissions, jobs, outils + d'IA — le tout dans un seul processus, communiquant avec votre base de données. + +Aucune étape de génération de code, aucun pipeline de déploiement entre « l'utilisateur a décrit +ce qu'il voulait » et « c'est en ligne ». Le runtime charge à chaud les nouvelles +métadonnées après une approbation HITL. + +## Ce que vous déployez + +Un seul processus Node.js par instance ObjectOS. C'est tout. + +```text +┌─────────────────────────────────────────────────────┐ +│ ObjectOS process │ +│ ┌───────────────────────────────────────────────┐ │ +│ │ HTTP dispatcher (/ · /api · /_console …) │ │ +│ ├───────────────────────────────────────────────┤ │ +│ │ Per-project ObjectKernel (LRU cached) │ │ +│ │ ├─ Auth (Better Auth) │ │ +│ │ ├─ Security (RBAC + row-level + field) │ │ +│ │ ├─ ObjectQL (data engine, generates SQL) │ │ +│ │ ├─ REST API generator │ │ +│ │ └─ Capabilities loaded per artifact │ │ +│ │ (audit, storage, jobs, queue, AI …) │ │ +│ └───────────────────────────────────────────────┘ │ +└──────────┬──────────────────────────────────────────┘ + │ + ▼ + Your business database + (Postgres / MySQL / SQLite / Turso / MongoDB) +``` + +Cela représente la complexité d'un unique binaire lié statiquement. Aucun +sidecar, aucun Kafka, aucune couche de cache distincte requise. Ajoutez-les quand vous en +avez besoin ; ne les payez pas dès le premier jour. + +## Où résident vos données + +| Données | Résident dans | Quittent votre réseau ? | +|---|---|---| +| Enregistrements métier | Votre base de données | **Non** | +| Comptes utilisateurs, sessions, tokens OAuth | Votre base de données | **Non** | +| Journal d'audit | Votre base de données | **Non** | +| Paramètres, clés API, secrets | Votre base de données / gestionnaire de secrets | **Non** | +| Fichiers téléversés | Votre disque ou votre bucket S3/R2 | **Non** | +| La définition compilée de l'application (`objectstack.json`) | Un fichier sur disque ou récupéré depuis votre control plane | Optionnel | + +ObjectOS ne « rappelle pas la maison ». Aucune télémétrie. Aucune vérification de licence. Si vous coupez +totalement l'accès à Internet, il continue de fonctionner indéfiniment. Voir +[Air-gapped](/docs/deploy/air-gapped). + +## Comment une requête est traitée + +```text +1. Ingress / TLS termination (your load balancer) +2. HTTP dispatcher (security headers, request id) +3. Hostname → project resolution (cached, TTL configurable) +4. Get or build per-project kernel from LRU +5. AuthPlugin — session cookie, bearer token, or API key +6. SecurityPlugin — RBAC + row-level + field-level checks +7. Route handler — generated REST, declarative action, or custom +8. Data driver — ObjectQL compiles to SQL / Mongo query +9. Response with X-Request-Id propagated +``` + +Les étapes 4 à 8 s'exécutent généralement en moins de 5 ms une fois le kernel à chaud. + +## Les trois couches (utile uniquement si vous intégrez) + +La plupart des clients ne déploient que **ObjectOS**. Les deux autres couches existent si +vous voulez savoir d'où provient l'artefact : + +| Couche | Ce que c'est | Où elle s'exécute | +|---|---|---| +| **Framework** (`@objectstack/*`) | Kernel open-source, ObjectQL, plugins, drivers | npm — récupéré au moment du build | +| **Control plane** (optionnel) | Publie des artefacts `objectstack.json` compilés ; vous pouvez utiliser le service hébergé ObjectStack Cloud, exécuter le vôtre ou vous en passer entièrement | Votre CI, notre cloud ou votre ordinateur portable | +| **ObjectOS** | Le runtime que vous exploitez | **Votre infrastructure** | + +Si vous livrez une application unique, vous n'avez pas besoin d'un control plane — +compilez `objectstack.config.ts → dist/objectstack.json` dans votre CI et +livrez le JSON dans l'image. Si vous exploitez un marketplace d'applications +internes avec de nombreux tenants et applications, le control plane est l'endroit où réside le +catalogue. + +## Modes de démarrage + +| Mode | Quand | Comment | +|---|---|---| +| **Standalone** | Application unique, dev, évaluation, air-gapped, la plupart des déploiements en production | `pnpm dev` ou exécuter `dist/objectstack.json` depuis le disque | +| **File-backed** | Production avec des artefacts gérés en externe | Définir `OS_ARTIFACT_PATH=/path/to/objectstack.json` | +| **Cloud-connected** | Déploiements multi-tenant / multi-app alimentés par un control plane | Définir `OS_CLOUD_URL` + `OS_CLOUD_API_KEY` | + +Le mode est détecté automatiquement à partir des variables d'environnement. + +## Caractéristiques de performance + +| Métrique | Valeur | +|---|---| +| Démarrage à froid (processus lancé, prêt à recevoir du trafic) | ~1 seconde | +| Préchauffage par kernel (première requête vers un projet) | 50-300 ms selon les capabilities | +| Latence des requêtes à chaud (CRUD via REST) | typiquement < 10 ms + latence de la base de données | +| Empreinte mémoire | ~150 Mo de base ; ~10-30 Mo par kernel de projet actif | +| Projets concurrents par instance | Limité par `OS_KERNEL_CACHE_SIZE` (32 par défaut) | + +## Pourquoi cette forme + +- **Un seul processus Node, sans sidecars** → tient dans un `docker run`, tient dans une + unité systemd, tient dans un environnement de type Lambda. +- **Kernel par projet, mis en cache LRU** → une instance peut servir de nombreuses + petites applications sans payer le coût de préchauffage à chaque requête. +- **APIs générées au-dessus de métadonnées déclarées** → il n'y a pas d'étape de codegen + dans votre CI, pas de SDK client à publier ; l'API correspond à votre modèle de + données par construction. +- **Toutes les capabilities sont des plugins optionnels** → la taille de l'image évolue selon + ce que vous utilisez réellement. + +## Pour aller plus loin + +- [Production Readiness](/docs/operate/production) — checklist avant + d'exposer le tout à du trafic réel. +- [Runtime Configuration](/docs/configure/runtime) — câblage des bases de données, + des caches et des secrets. +- [Runtime Capabilities](/docs/reference/runtime-capabilities) — + quels packages optionnels existent et ce qu'ils activent. diff --git a/content/docs/architecture.ja.mdx b/content/docs/architecture.ja.mdx new file mode 100644 index 0000000..642c8ac --- /dev/null +++ b/content/docs/architecture.ja.mdx @@ -0,0 +1,120 @@ +--- +title: アーキテクチャ +description: 実際に何が動いているのか — 導入を検討しているエンジニアのために。 +--- + +# アーキテクチャ + +ObjectOS をデプロイしたときにマシン上で何が動くのか、どのデータがネットワークの外へ出て、どのデータが出ないのかを実践的な視点で解説します。 + +メンタルモデルは、薄い 2 つのレイヤーです。 + +1. **メタデータ** — objects / views / actions / flows / + agents のパッケージ。多くは [AI Builder](/docs/build/ai-builder) + がサンドボックス化されたツール API に対して記述します。手作業で編集される場合もありますが、常にバージョン管理され監査されます。 +2. **単一の Node.js ランタイム** が、そのメタデータを解釈して動作するアプリケーション + — REST API、Console UI、権限、ジョブ、AI + ツール — に変換します。これらはすべて 1 つのプロセス内で、あなたのデータベースと通信しながら動作します。 + +コード生成のステップはなく、「ユーザーが望むものを記述した」状態と「それが稼働している」状態の間にデプロイパイプラインはありません。ランタイムは HITL の承認後に新しいメタデータをホットロードします。 + +## デプロイするもの + +ObjectOS インスタンスごとに 1 つの Node.js プロセス。それだけです。 + +```text +┌─────────────────────────────────────────────────────┐ +│ ObjectOS process │ +│ ┌───────────────────────────────────────────────┐ │ +│ │ HTTP dispatcher (/ · /api · /_console …) │ │ +│ ├───────────────────────────────────────────────┤ │ +│ │ Per-project ObjectKernel (LRU cached) │ │ +│ │ ├─ Auth (Better Auth) │ │ +│ │ ├─ Security (RBAC + row-level + field) │ │ +│ │ ├─ ObjectQL (data engine, generates SQL) │ │ +│ │ ├─ REST API generator │ │ +│ │ └─ Capabilities loaded per artifact │ │ +│ │ (audit, storage, jobs, queue, AI …) │ │ +│ └───────────────────────────────────────────────┘ │ +└──────────┬──────────────────────────────────────────┘ + │ + ▼ + Your business database + (Postgres / MySQL / SQLite / Turso / MongoDB) +``` + +複雑さの度合いは、静的リンクされた単一バイナリ程度です。サイドカーも、Kafka も、別途のキャッシュレイヤーも必要ありません。必要になったときに追加すればよく、初日からそのコストを払う必要はありません。 + +## データはどこにあるのか + +| データ | 保管場所 | ネットワークの外へ出るか? | +|---|---|---| +| 業務レコード | あなたのデータベース | **いいえ** | +| ユーザーアカウント、セッション、OAuth トークン | あなたのデータベース | **いいえ** | +| 監査ログ | あなたのデータベース | **いいえ** | +| 設定、API キー、シークレット | あなたのデータベース / シークレットマネージャー | **いいえ** | +| アップロードされたファイル | あなたのディスク、または S3/R2 バケット | **いいえ** | +| コンパイル済みアプリ定義(`objectstack.json`) | ディスク上のファイル、またはコントロールプレーンから取得 | 任意 | + +ObjectOS はホームへ通信しません。テレメトリーもライセンスチェックもありません。インターネットアクセスを完全に遮断しても、無期限に動作し続けます。[Air-gapped](/docs/deploy/air-gapped) を参照してください。 + +## リクエストはどのように処理されるか + +```text +1. Ingress / TLS termination (your load balancer) +2. HTTP dispatcher (security headers, request id) +3. Hostname → project resolution (cached, TTL configurable) +4. Get or build per-project kernel from LRU +5. AuthPlugin — session cookie, bearer token, or API key +6. SecurityPlugin — RBAC + row-level + field-level checks +7. Route handler — generated REST, declarative action, or custom +8. Data driver — ObjectQL compiles to SQL / Mongo query +9. Response with X-Request-Id propagated +``` + +ステップ 4〜8 は、カーネルがウォームな状態であれば通常 5ms 未満で実行されます。 + +## 3 つのレイヤー(統合する場合のみ重要) + +ほとんどの顧客は **ObjectOS** のみをデプロイします。残りの 2 つのレイヤーは、アーティファクトがどこから来るのかを知りたい場合に存在します。 + +| レイヤー | 内容 | 実行される場所 | +|---|---|---| +| **Framework**(`@objectstack/*`) | オープンソースのカーネル、ObjectQL、プラグイン、ドライバー | npm — ビルド時に取り込まれる | +| **Control plane**(任意) | コンパイル済み `objectstack.json` アーティファクトを公開する。ホスティングされた ObjectStack Cloud を利用するか、自前で運用するか、まったく使わないかを選べる | あなたの CI、当社のクラウド、またはあなたのノート PC | +| **ObjectOS** | あなたが運用するランタイム | **あなたのインフラ** | + +単一のアプリを出荷するだけなら、コントロールプレーンは不要です。CI で `objectstack.config.ts → dist/objectstack.json` をコンパイルし、その JSON をイメージに含めて出荷します。多数のテナントやアプリを抱える社内アプリ marketplace を運用する場合は、コントロールプレーンがカタログの置き場所になります。 + +## ブートモード + +| モード | 利用シーン | 方法 | +|---|---|---| +| **Standalone** | 単一アプリ、開発、評価、エアギャップ環境、ほとんどの本番デプロイ | `pnpm dev`、またはディスク上の `dist/objectstack.json` を実行 | +| **File-backed** | 外部管理のアーティファクトを使う本番環境 | `OS_ARTIFACT_PATH=/path/to/objectstack.json` を設定 | +| **Cloud-connected** | コントロールプレーンから供給されるマルチテナント / マルチアプリのデプロイ | `OS_CLOUD_URL` + `OS_CLOUD_API_KEY` を設定 | + +モードは環境変数から自動検出されます。 + +## パフォーマンス特性 + +| 指標 | 数値 | +|---|---| +| コールドスタート(プロセス起動からトラフィック受付可能まで) | 約 1 秒 | +| カーネルごとのウォームアップ(プロジェクトへの最初のリクエスト) | capabilities に応じて 50〜300ms | +| ウォームリクエストのレイテンシ(REST 経由の CRUD) | 通常 10ms 未満 + データベースのレイテンシ | +| メモリフットプリント | ベース約 150MB、アクティブなプロジェクトカーネルごとに約 10〜30MB | +| インスタンスあたりの同時プロジェクト数 | `OS_KERNEL_CACHE_SIZE`(デフォルト 32)によって制限される | + +## なぜこの形なのか + +- **サイドカーなしの単一 Node プロセス** → `docker run` に収まり、systemd ユニットに収まり、Lambda のような環境に収まる。 +- **プロジェクトごとのカーネル、LRU キャッシュ** → 1 つのインスタンスで多数の小さなアプリを、リクエストごとにウォームアップコストを払うことなく処理できる。 +- **宣言されたメタデータの上に生成される API** → CI にコード生成のステップはなく、公開すべきクライアント SDK もない。API は構造的にあなたのデータモデルと一致する。 +- **すべての capabilities は任意のプラグイン** → イメージサイズは実際に使うものに応じてスケールする。 + +## 次に読むもの + +- [Production Readiness](/docs/operate/production) — 実トラフィックにさらす前のチェックリスト。 +- [Runtime Configuration](/docs/configure/runtime) — データベース、キャッシュ、シークレットの接続。 +- [Runtime Capabilities](/docs/reference/runtime-capabilities) — どの任意パッケージが存在し、何を有効にするか。 diff --git a/content/docs/architecture.mdx b/content/docs/architecture.mdx index 9c78312..9f66281 100644 --- a/content/docs/architecture.mdx +++ b/content/docs/architecture.mdx @@ -104,7 +104,7 @@ catalog lives. | Mode | When | How | |---|---|---| | **Standalone** | Single app, dev, evaluation, air-gapped, most production deployments | `pnpm dev` or run `dist/objectstack.json` from disk | -| **File-backed** | Production with externally-managed artifacts | Set `OS_ARTIFACT_FILE=/path/to/objectstack.json` | +| **File-backed** | Production with externally-managed artifacts | Set `OS_ARTIFACT_PATH=/path/to/objectstack.json` | | **Cloud-connected** | Multi-tenant / multi-app deployments fed by a control plane | Set `OS_CLOUD_URL` + `OS_CLOUD_API_KEY` | Mode is auto-detected from environment variables. diff --git a/content/docs/architecture.cn.mdx b/content/docs/architecture.zh-Hans.mdx similarity index 100% rename from content/docs/architecture.cn.mdx rename to content/docs/architecture.zh-Hans.mdx diff --git a/content/docs/build/actions.cn.mdx b/content/docs/build/actions.cn.mdx deleted file mode 100644 index 28af00b..0000000 --- a/content/docs/build/actions.cn.mdx +++ /dev/null @@ -1,176 +0,0 @@ ---- -title: Actions -description: 平台以 REST 端点、Console 按钮、流程步骤和 AI 工具的形式暴露的命名操作 —— 一处声明即可。 ---- - -# Actions - -**Action** 是对象上的一个命名操作。声明一次,它就会作为: - -- 一个 **REST 端点** `/api/v1/data//actions/` -- Console 记录详情页上的一个 **按钮** -- 一个 **流程步骤**(`type: 'action'`)用于自动化 -- 一个 **AI 工具**(`action_`)供 Agent 和 AI Builder 调用 - -你不必在四种表面之间重复自己。一处声明;四种调用方式。 - -## 声明一个 Action - -```ts -// src/actions/approve_invoice.action.ts -import { defineAction, Field } from '@objectstack/spec'; - -export const approveInvoice = defineAction({ - name: 'approve_invoice', - label: 'Approve Invoice', - object: 'invoice', - description: 'Mark the invoice approved and stamp the approver.', - icon: 'check', - - inputs: { - note: Field.textarea({ label: 'Approval note' }), - }, - - // 谁能调用 - permissions: { - requires: ['allowEdit'], // 对象级 - condition: 'record.status == "pending"', - }, - - // 它做什么 —— 声明式,不需要 JS - steps: [ - { - type: 'update', - record: '{!record.id}', - fields: { - status: 'approved', - approved_by: '{!user.id}', - approved_at: '{!now()}', - approval_note: '{!inputs.note}', - }, - }, - ], -}); -``` - -整个文件就这些。`os dev` 重编译之后: - -- `POST /api/v1/data/invoice/actions/approve_invoice` 可用 -- Console 里 Invoice 记录页出现一个 **Approve Invoice** 按钮 -- 流程可以包含 `{ type: 'action', action: 'approve_invoice', inputs: { note: '…' } }` -- 若 Skill 允许,AI 助手可以调用 `action_approve_invoice` - -## 三种风味 - -| 风味 | 跑什么 | 用于 | -|---|---|---| -| **声明式**(`steps:`) | DSL —— update/create/delete/query/action/condition/foreach | 多数场景 —— 可审计 + AI 可调 | -| **脚本**(`script:`) | TypeScript 函数,服务端执行 | 跨系统逻辑、复杂变换 | -| **外部**(`webhook:`) | HTTP POST 到你的端点 | 委托给你自己的服务 | - -```ts -// 脚本风味 -defineAction({ - name: 'archive_old_orders', - object: 'order', - script: async ({ ctx, record, inputs }) => { - await ctx.data.update('order', record.id, { archived_at: new Date() }); - return { ok: true }; - }, -}); -``` - -不论哪种风味,Action 在所有表面都是同样的一等公民。 - -## 调用一个 Action - -### REST - -```bash -curl -X POST https://app.example.com/api/v1/data/invoice/actions/approve_invoice \ - -H 'Authorization: Bearer ' \ - -H 'Content-Type: application/json' \ - -d '{"recordId": "inv_123", "inputs": {"note": "LGTM"}}' -``` - -返回更新后的记录(声明式 Action)或你的处理函数的返回值(脚本 Action)。 - -### Console - -默认情况下,Console 把 Action 显示为记录详情页上的按钮,按 Action 的 `permissions.condition` 过滤。在视图配置中覆盖位置: - -```ts -defineView({ - name: 'invoice_detail', - object: 'invoice', - actions: ['approve_invoice', 'reject_invoice', 'send_to_customer'], -}); -``` - -### 从流程 - -```ts -{ - type: 'action', - action: 'approve_invoice', - inputs: { note: 'Auto-approved by SLA flow' }, - record: '{!trigger.record.id}', -} -``` - -### 从 AI Agent - -如果 `approve_invoice` 在 Agent 的某个 Skill 里,LLM 就能调它。输入来自对话;权限照样按用户本人直接调用来执行。 - -> *"批准发票 INV-2042,备注 'verified by phone.'"* - -## 权限 - -每个 Action 以发起调用的用户身份运行 —— 永远不是服务账号。平台检查: - -1. **对象权限** —— 用户权限集上的 `requires:` 标志(`allowEdit`、`allowCreate`…)。 -2. **Action 闸门** —— Action 的 `permissions.condition`(针对记录、用户、输入求值的 CEL 表达式)。 -3. **字段权限** —— Action 写入的任何字段,用户必须有写权限。 - -校验失败返回 `403 Forbidden` 及结构化错误,说明哪个检查失败。 - -## 内置 Action - -每个对象天生就有: - -| Action | 作用 | -|---|---| -| `create` | 插入一条记录 | -| `update` | 更新一条记录 | -| `delete` | 删除(或软删除)一条记录 | -| `restore` | 恢复软删除 | -| `clone` | 深拷贝一条记录 | -| `share` | 直接与用户/角色分享 | - -不要重复声明这些 —— 通过 [Hook](/docs/build/data-model#field-types) 扩展行为。 - -## 审计 - -每次 Action 调用都落到 `sys_audit_log`,含: - -- 发起用户 -- Action 名称 + 输入(敏感字段脱敏) -- 记录 id(如有) -- 成功 / 失败 + 错误 -- 时序 -- 发起表面(`rest` / `studio` / `flow` / `ai`) - -这是"谁按了按钮?"这类问题的首要查询入口。 - -## 用 AI Builder 生成 Action - -> *"在 `support_ticket` 上创建一个 `escalate_ticket` Action,把优先级设为紧急,并指派给值班工程师。"* - -AI 会调 `create_action`(元数据工具)并把变更入审批队列。批准后,该 Action 可从 REST、Console、流程,以及——递归地——AI 自己调用。 - -## 下一步 - -- [Flows](/docs/build/flows) —— 把多个 Action 组合为业务逻辑 -- [Agents](/docs/build/agents) —— 把 Action 作为 AI 工具暴露 -- [API Access](/docs/configure/api-access) —— 从外部系统调用 Action -- [Permissions](/docs/configure/permissions) —— 控制谁能调用什么 diff --git a/content/docs/build/actions.de.mdx b/content/docs/build/actions.de.mdx new file mode 100644 index 0000000..9cfd877 --- /dev/null +++ b/content/docs/build/actions.de.mdx @@ -0,0 +1,204 @@ +--- +title: Actions +description: Benannte Operationen, die die Plattform als REST-Endpunkte, Console-Schaltflächen, Flow-Schritte und AI-Tools bereitstellt — aus einer einzigen Deklaration. +--- + +# Actions + +Eine **Action** ist eine benannte Operation auf einem Objekt. Deklarieren Sie sie einmal und +sie erscheint als: + +- ein **REST-Endpunkt** unter `/api/v1/actions//` +- eine **Schaltfläche** in der Datensatzdetailansicht der Console +- ein **Flow-Schritt** (`type: 'action'`) für die Automatisierung +- ein **AI-Tool** (`action_`) für Agents und den AI Builder + +Sie wiederholen sich nicht über vier Oberflächen hinweg. Eine Deklaration; vier +Möglichkeiten zum Aufruf. + +## Eine Action deklarieren + +```ts +// src/actions/approve_invoice.action.ts +import { Action } from '@objectstack/spec'; + +export const approveInvoice = Action.create({ + name: 'approve_invoice', // lowercase snake_case (machine id) + label: 'Approve Invoice', + objectName: 'invoice', // attaches to the invoice object + icon: 'check', + variant: 'primary', + locations: ['record_header'], // where the button shows + confirmText: 'Approve this invoice?', + successMessage: 'Invoice approved', + refreshAfter: true, + + // collect input before running + params: [ + { name: 'note', label: 'Approval note', type: 'textarea' }, + ], + + // only show the button when the record is still pending + visible: 'record.status == "pending"', + + // what it does — a sandboxed script body + type: 'script', + body: { + language: 'js', + source: ` + await ctx.data.update('invoice', input.id, { + status: 'approved', + approved_by: ctx.user.id, + approved_at: now(), + approval_note: input.note, + }); + `, + }, +}); +``` + +Nach der erneuten Kompilierung durch `os dev`: + +- `POST /api/v1/actions/invoice/approve_invoice` funktioniert +- Die Invoice-Datensatzseite in der Console zeigt eine **Approve Invoice**-Schaltfläche +- Ein Flow kann `{ type: 'action', action: 'approve_invoice', inputs: { note: '…' } }` enthalten +- Der AI-Assistent kann `action_approve_invoice` aufrufen, wenn seine Skills es erlauben + +## Action-Typen + +Das Feld `type` entscheidet, was die Action tut: + +| `type` | Was ausgeführt wird | Verwendung für | +|---|---|---| +| `script` | Ein `body` — ein L1-Formelausdruck oder Sandbox-L2-JavaScript | Die meisten Fälle — serverseitige Logik, auditierbar + AI-aufrufbar | +| `api` | Ein HTTP-Aufruf an einen `target`-Endpunkt (`method`, `bodyExtra`) | Wiederverwendung von Daten-API- oder Plattform-Endpunkten | +| `flow` | Führt den in `target` benannten Flow aus | Mehrstufige Geschäftsprozesse | +| `url` | Navigiert zur `target`-URL | Deep Links, Weiterleitungs-Actions | +| `modal` | Öffnet die in `target` benannte Seite/das Modal | Benutzerdefinierte Dialoge | +| `form` | Öffnet die in `target` benannte FormView | Geführte Dateneingabe | + +```ts +// api type — reuse a data-API endpoint +Action.create({ + name: 'archive_order', + objectName: 'order', + label: 'Archive', + locations: ['list_item'], + type: 'api', + method: 'PATCH', + target: '/api/v1/data/order/{id}', + bodyExtra: { archived: true }, +}); +``` + +Andere Typen als `script` erfordern ein `target`. Welchen Typ auch immer, die Action +ist auf jeder Oberfläche derselbe vollwertige Bürger. + +## Eine Action aufrufen + +### REST + +```bash +# the record id can go in the body, or in the path +curl -X POST https://app.example.com/api/v1/actions/invoice/approve_invoice/inv_123 \ + -H 'Authorization: Bearer ' \ + -H 'Content-Type: application/json' \ + -d '{"note": "LGTM"}' +``` + +Params werden flach im Anfragetext gesendet. Die Datensatz-ID kann +entweder als abschließendes Pfadsegment (`.../approve_invoice/:recordId`) oder im +Anfragetext angegeben werden. Die Antwort ist der Rückgabewert Ihres Skript-Bodys (oder das Aufrufergebnis +bei Actions vom Typ `api`). + +### Console + +Standardmäßig zeigt die Console Actions als Schaltflächen auf der Datensatzdetailseite an, +gefiltert durch das `visible`-Prädikat der Action. Überschreiben Sie die Platzierung +in Ihrer View-Konfiguration: + +```ts +defineView({ + name: 'invoice_detail', + object: 'invoice', + actions: ['approve_invoice', 'reject_invoice', 'send_to_customer'], +}); +``` + +### Aus einem Flow + +```ts +{ + type: 'action', + action: 'approve_invoice', + inputs: { note: 'Auto-approved by SLA flow' }, + record: '{!trigger.record.id}', +} +``` + +### Von einem AI-Agent + +Wenn `approve_invoice` in einem Skill enthalten ist, das der Agent besitzt, kann das LLM es +aufrufen. Die Eingaben stammen aus der Konversation; die Berechtigungen werden so durchgesetzt, als ob +der Benutzer sie direkt aufgerufen hätte. + +> *"Approve invoice INV-2042 with note 'verified by phone.'"* + +## Berechtigungen + +Actions laufen mit den Berechtigungen des aufrufenden Benutzers. Die Plattform prüft: + +1. **Objektberechtigungen** — die [Berechtigungssätze](/docs/configure/permissions/permission-sets) des Benutzers + müssen den objektbezogenen Zugriff gewähren, den die Action benötigt (z. B. Aktualisieren). +2. **Feldberechtigungen** — für jedes Feld, das die Action schreibt, muss der Benutzer + über Schreibzugriff verfügen (FLS). +3. **UI-Gating** — die Prädikate `visible` und `disabled` (CEL, + ausgewertet gegen `record`, `os.user` und Params) steuern, ob die + Schaltfläche in der Console gerendert oder ausgegraut wird. + +Fehlgeschlagene Berechtigungsprüfungen geben `403` mit einem `PERMISSION_DENIED`-Fehler zurück. + +## Integrierte Actions + +Jedes Objekt erhält diese kostenlos: + +| Action | Was sie tut | +|---|---| +| `create` | Einen Datensatz einfügen | +| `update` | Einen Datensatz aktualisieren | +| `delete` | Einen Datensatz löschen (oder soft-löschen) | +| `restore` | Ein Soft-Delete rückgängig machen | +| `clone` | Einen Datensatz tief kopieren | +| `share` | Direkt mit einem Benutzer / einer Rolle teilen | + +Deklarieren Sie diese nicht erneut — sie folgen den [Lebenszyklus- & Capability-Flags](/docs/build/data-model) des Objekts. + +## Auditing + +Plattformereignisse landen in `sys_audit_log`, einem unveränderlichen Verlauf mit Feldern +wie unter anderem: + +- `user_id` — der auslösende Benutzer +- `action` — der Name der Action +- `object_name` und `record_id` — was berührt wurde +- `old_value` / `new_value` — die Änderung +- `ip_address` / `user_agent` — Ursprung der Anfrage +- `created_at` — wann es geschah + +Dies ist Ihre erste Anlaufstelle für Fragen wie *"Wer hat die Schaltfläche gedrückt?"*. + +## Actions mit dem AI Builder generieren + +> *"Create an action `escalate_ticket` on `support_ticket` that sets +> priority to urgent and assigns it to the on-call engineer."* + +Der [AI Builder](/docs/build/ai-builder) generiert die Action-Metadaten und +stellt die Änderung zur Genehmigung in die Warteschlange. Nach der Genehmigung ist die Action aufrufbar über +REST, Console, Flows und — rekursiv — die AI selbst. + +## Wie es weitergeht + +- [Flows](/docs/build/flows) — mehrere Actions zu Geschäftslogik zusammensetzen +- [Agents](/docs/build/agents) — Actions als AI-Tools bereitstellen +- [API Access](/docs/configure/api-access) — Actions aus externen Systemen aufrufen +- [Permissions](/docs/configure/permissions) — steuern, wer was aufrufen darf diff --git a/content/docs/build/actions.es.mdx b/content/docs/build/actions.es.mdx new file mode 100644 index 0000000..7fb4881 --- /dev/null +++ b/content/docs/build/actions.es.mdx @@ -0,0 +1,204 @@ +--- +title: Acciones +description: Operaciones con nombre que la plataforma expone como endpoints REST, botones de Console, pasos de flujo y herramientas de IA, a partir de una sola declaración. +--- + +# Acciones + +Una **Acción** es una operación con nombre sobre un objeto. Decláralo una vez y +aparece como: + +- un **endpoint REST** en `/api/v1/actions//` +- un **botón** en el detalle de registro de Console +- un **paso de flujo** (`type: 'action'`) para automatización +- una **herramienta de IA** (`action_`) para Agents y el AI Builder + +No te repites en cuatro superficies. Una declaración; cuatro +formas de invocarla. + +## Declarar una acción + +```ts +// src/actions/approve_invoice.action.ts +import { Action } from '@objectstack/spec'; + +export const approveInvoice = Action.create({ + name: 'approve_invoice', // lowercase snake_case (machine id) + label: 'Approve Invoice', + objectName: 'invoice', // attaches to the invoice object + icon: 'check', + variant: 'primary', + locations: ['record_header'], // where the button shows + confirmText: 'Approve this invoice?', + successMessage: 'Invoice approved', + refreshAfter: true, + + // collect input before running + params: [ + { name: 'note', label: 'Approval note', type: 'textarea' }, + ], + + // only show the button when the record is still pending + visible: 'record.status == "pending"', + + // what it does — a sandboxed script body + type: 'script', + body: { + language: 'js', + source: ` + await ctx.data.update('invoice', input.id, { + status: 'approved', + approved_by: ctx.user.id, + approved_at: now(), + approval_note: input.note, + }); + `, + }, +}); +``` + +Después de que `os dev` recompile: + +- `POST /api/v1/actions/invoice/approve_invoice` funciona +- La página de registro de Invoice en Console muestra un botón **Approve Invoice** +- Un flujo puede incluir `{ type: 'action', action: 'approve_invoice', inputs: { note: '…' } }` +- El asistente de IA puede llamar a `action_approve_invoice` si sus skills lo permiten + +## Tipos de acción + +El campo `type` decide qué hace la acción: + +| `type` | Qué se ejecuta | Úsalo para | +|---|---|---| +| `script` | Un `body` — una expresión de fórmula L1 o JavaScript L2 en sandbox | La mayoría de los casos — lógica del lado del servidor, auditable y llamable por IA | +| `api` | Una llamada HTTP a un endpoint `target` (`method`, `bodyExtra`) | Reutilizar endpoints de la data-API o de la plataforma | +| `flow` | Ejecuta el flujo indicado en `target` | Procesos de negocio de varios pasos | +| `url` | Navega a la URL de `target` | Enlaces directos, acciones de tipo redirección | +| `modal` | Abre la página/modal indicada en `target` | Diálogos personalizados | +| `form` | Abre la FormView indicada en `target` | Entrada de datos guiada | + +```ts +// api type — reuse a data-API endpoint +Action.create({ + name: 'archive_order', + objectName: 'order', + label: 'Archive', + locations: ['list_item'], + type: 'api', + method: 'PATCH', + target: '/api/v1/data/order/{id}', + bodyExtra: { archived: true }, +}); +``` + +Los tipos distintos de `script` requieren un `target`. Sea cual sea el tipo, la acción +es el mismo ciudadano de primera clase en todas las superficies. + +## Llamar a una acción + +### REST + +```bash +# the record id can go in the body, or in the path +curl -X POST https://app.example.com/api/v1/actions/invoice/approve_invoice/inv_123 \ + -H 'Authorization: Bearer ' \ + -H 'Content-Type: application/json' \ + -d '{"note": "LGTM"}' +``` + +Los parámetros se envían planos en el cuerpo de la solicitud. El id del registro puede suministrarse +como un segmento final de la ruta (`.../approve_invoice/:recordId`) o en +el cuerpo. La respuesta es el valor de retorno del cuerpo de tu script (o el resultado +de la llamada en el caso de las acciones de tipo `api`). + +### Console + +Por defecto, Console muestra las acciones como botones en la página de detalle del registro, +filtradas por el predicado `visible` de la acción. Anula la ubicación +en la configuración de tu vista: + +```ts +defineView({ + name: 'invoice_detail', + object: 'invoice', + actions: ['approve_invoice', 'reject_invoice', 'send_to_customer'], +}); +``` + +### Desde un flujo + +```ts +{ + type: 'action', + action: 'approve_invoice', + inputs: { note: 'Auto-approved by SLA flow' }, + record: '{!trigger.record.id}', +} +``` + +### Desde un AI Agent + +Si `approve_invoice` está en alguna skill que tenga el agente, el LLM puede llamarla. +Las entradas provienen de la conversación; los permisos se aplican como si +el usuario la hubiera invocado directamente. + +> *"Aprueba la factura INV-2042 con la nota 'verificado por teléfono'."* + +## Permisos + +Las acciones se ejecutan con los permisos del usuario que las invoca. La plataforma comprueba: + +1. **Permisos de objeto** — los [conjuntos de permisos](/docs/configure/permissions/permission-sets) + del usuario deben otorgar el acceso a nivel de objeto que necesita la acción (p. ej. actualizar). +2. **Permisos de campo** — para cualquier campo que la acción escriba, el usuario + debe tener acceso de escritura (FLS). +3. **Control de UI** — los predicados `visible` y `disabled` (CEL, + evaluados contra `record`, `os.user` y los parámetros) controlan si el + botón se renderiza o aparece atenuado en Console. + +Las comprobaciones de permisos fallidas devuelven `403` con un error `PERMISSION_DENIED`. + +## Acciones integradas + +Cada objeto obtiene estas de forma gratuita: + +| Acción | Qué hace | +|---|---| +| `create` | Inserta un registro | +| `update` | Actualiza un registro | +| `delete` | Elimina (o elimina de forma reversible) un registro | +| `restore` | Deshace una eliminación reversible | +| `clone` | Copia en profundidad un registro | +| `share` | Comparte directamente con un usuario / rol | + +No vuelvas a declarar estas — siguen los [indicadores de ciclo de vida y capacidad](/docs/build/data-model) del objeto. + +## Auditoría + +Los eventos de la plataforma se registran en `sys_audit_log`, un rastro inmutable con campos +que incluyen: + +- `user_id` — el usuario originario +- `action` — el nombre de la acción +- `object_name` y `record_id` — qué se modificó +- `old_value` / `new_value` — el cambio +- `ip_address` / `user_agent` — origen de la solicitud +- `created_at` — cuándo ocurrió + +Este es tu primer recurso para preguntas del tipo *"¿quién pulsó el botón?"*. + +## Generar acciones con el AI Builder + +> *"Crea una acción `escalate_ticket` en `support_ticket` que establezca +> la prioridad en urgente y la asigne al ingeniero de guardia."* + +El [AI Builder](/docs/build/ai-builder) genera los metadatos de la acción y +pone en cola el cambio para su aprobación. Tras la aprobación, la acción puede invocarse desde +REST, Console, flujos y — recursivamente — la propia IA. + +## Adónde ir después + +- [Flows](/docs/build/flows) — compón varias acciones en lógica de negocio +- [Agents](/docs/build/agents) — expón acciones como herramientas de IA +- [API Access](/docs/configure/api-access) — llama a acciones desde sistemas externos +- [Permissions](/docs/configure/permissions) — controla quién puede llamar a qué diff --git a/content/docs/build/actions.fr.mdx b/content/docs/build/actions.fr.mdx new file mode 100644 index 0000000..48d05ff --- /dev/null +++ b/content/docs/build/actions.fr.mdx @@ -0,0 +1,204 @@ +--- +title: Actions +description: Opérations nommées que la plateforme expose en tant qu'endpoints REST, boutons Console, étapes de flow et outils IA — à partir d'une seule déclaration. +--- + +# Actions + +Une **Action** est une opération nommée sur un objet. Déclarez-la une seule fois et +elle apparaît comme : + +- un **endpoint REST** à `/api/v1/actions//` +- un **bouton** dans le détail d'enregistrement de Console +- une **étape de flow** (`type: 'action'`) pour l'automatisation +- un **outil IA** (`action_`) pour les Agents et l'AI Builder + +Vous ne vous répétez pas sur quatre surfaces. Une seule déclaration ; quatre +façons de l'appeler. + +## Déclarer une action + +```ts +// src/actions/approve_invoice.action.ts +import { Action } from '@objectstack/spec'; + +export const approveInvoice = Action.create({ + name: 'approve_invoice', // lowercase snake_case (machine id) + label: 'Approve Invoice', + objectName: 'invoice', // attaches to the invoice object + icon: 'check', + variant: 'primary', + locations: ['record_header'], // where the button shows + confirmText: 'Approve this invoice?', + successMessage: 'Invoice approved', + refreshAfter: true, + + // collect input before running + params: [ + { name: 'note', label: 'Approval note', type: 'textarea' }, + ], + + // only show the button when the record is still pending + visible: 'record.status == "pending"', + + // what it does — a sandboxed script body + type: 'script', + body: { + language: 'js', + source: ` + await ctx.data.update('invoice', input.id, { + status: 'approved', + approved_by: ctx.user.id, + approved_at: now(), + approval_note: input.note, + }); + `, + }, +}); +``` + +Après la recompilation par `os dev` : + +- `POST /api/v1/actions/invoice/approve_invoice` fonctionne +- La page d'enregistrement Invoice dans Console affiche un bouton **Approve Invoice** +- Un flow peut inclure `{ type: 'action', action: 'approve_invoice', inputs: { note: '…' } }` +- L'assistant IA peut appeler `action_approve_invoice` si ses skills le permettent + +## Types d'action + +Le champ `type` décide de ce que fait l'action : + +| `type` | Ce qui s'exécute | À utiliser pour | +|---|---|---| +| `script` | Un `body` — une expression de formule L1 ou du JavaScript L2 en sandbox | La plupart des cas — logique côté serveur, auditable + appelable par l'IA | +| `api` | Un appel HTTP vers un endpoint `target` (`method`, `bodyExtra`) | Réutiliser des endpoints data-API ou de la plateforme | +| `flow` | Exécute le flow nommé dans `target` | Processus métier multi-étapes | +| `url` | Navigue vers l'URL `target` | Liens profonds, actions de type redirection | +| `modal` | Ouvre la page/modale nommée dans `target` | Boîtes de dialogue personnalisées | +| `form` | Ouvre la FormView nommée dans `target` | Saisie de données guidée | + +```ts +// api type — reuse a data-API endpoint +Action.create({ + name: 'archive_order', + objectName: 'order', + label: 'Archive', + locations: ['list_item'], + type: 'api', + method: 'PATCH', + target: '/api/v1/data/order/{id}', + bodyExtra: { archived: true }, +}); +``` + +Les types autres que `script` nécessitent un `target`. Quel que soit le type, l'action +est le même citoyen de première classe sur chaque surface. + +## Appeler une action + +### REST + +```bash +# the record id can go in the body, or in the path +curl -X POST https://app.example.com/api/v1/actions/invoice/approve_invoice/inv_123 \ + -H 'Authorization: Bearer ' \ + -H 'Content-Type: application/json' \ + -d '{"note": "LGTM"}' +``` + +Les params sont envoyés à plat dans le corps de la requête. L'identifiant de l'enregistrement peut être fourni +soit comme segment de chemin final (`.../approve_invoice/:recordId`), soit dans +le corps. La réponse est la valeur de retour du corps de votre script (ou le résultat de l'appel +pour les actions de type `api`). + +### Console + +Par défaut, Console affiche les actions sous forme de boutons sur la page de détail de l'enregistrement, +filtrés par le prédicat `visible` de l'action. Remplacez le placement +dans la configuration de votre vue : + +```ts +defineView({ + name: 'invoice_detail', + object: 'invoice', + actions: ['approve_invoice', 'reject_invoice', 'send_to_customer'], +}); +``` + +### Depuis un flow + +```ts +{ + type: 'action', + action: 'approve_invoice', + inputs: { note: 'Auto-approved by SLA flow' }, + record: '{!trigger.record.id}', +} +``` + +### Depuis un Agent IA + +Si `approve_invoice` se trouve dans l'un des skills dont dispose l'agent, le LLM peut l'appeler. +Les entrées proviennent de la conversation ; les permissions sont appliquées comme si +l'utilisateur l'avait invoquée directement. + +> *"Approve invoice INV-2042 with note 'verified by phone.'"* + +## Permissions + +Les actions s'exécutent avec les permissions de l'utilisateur appelant. La plateforme vérifie : + +1. **Permissions d'objet** — les [permission sets](/docs/configure/permissions/permission-sets) de l'utilisateur + doivent accorder l'accès au niveau de l'objet dont l'action a besoin (par exemple update). +2. **Permissions de champ** — pour chaque champ que l'action écrit, l'utilisateur + doit avoir un accès en écriture (FLS). +3. **Contrôle UI** — les prédicats `visible` et `disabled` (CEL, + évalués par rapport à `record`, `os.user` et aux params) déterminent si le + bouton s'affiche ou est grisé dans Console. + +Les vérifications de permission échouées renvoient un `403` avec une erreur `PERMISSION_DENIED`. + +## Actions intégrées + +Chaque objet dispose gratuitement de celles-ci : + +| Action | Ce qu'elle fait | +|---|---| +| `create` | Insère un enregistrement | +| `update` | Met à jour un enregistrement | +| `delete` | Supprime (ou supprime en douceur) un enregistrement | +| `restore` | Annule une suppression douce | +| `clone` | Copie en profondeur un enregistrement | +| `share` | Partage direct avec un utilisateur / rôle | + +Ne redéclarez pas celles-ci — elles suivent les [drapeaux de cycle de vie et de capacité](/docs/build/data-model) de l'objet. + +## Audit + +Les événements de la plateforme aboutissent dans `sys_audit_log`, une piste immuable avec des champs +notamment : + +- `user_id` — l'utilisateur à l'origine de l'action +- `action` — le nom de l'action +- `object_name` et `record_id` — ce qui a été touché +- `old_value` / `new_value` — le changement +- `ip_address` / `user_agent` — l'origine de la requête +- `created_at` — quand cela s'est produit + +C'est votre premier point d'arrêt pour les questions du type *"qui a appuyé sur le bouton ?"*. + +## Générer des actions avec l'AI Builder + +> *"Create an action `escalate_ticket` on `support_ticket` that sets +> priority to urgent and assigns it to the on-call engineer."* + +L'[AI Builder](/docs/build/ai-builder) génère les métadonnées de l'action et +met le changement en file d'attente pour approbation. Après approbation, l'action est appelable depuis +REST, Console, les flows et — de manière récursive — l'IA elle-même. + +## Où aller ensuite + +- [Flows](/docs/build/flows) — composez plusieurs actions en logique métier +- [Agents](/docs/build/agents) — exposez les actions en tant qu'outils IA +- [API Access](/docs/configure/api-access) — appelez les actions depuis des systèmes externes +- [Permissions](/docs/configure/permissions) — contrôlez qui peut appeler quoi diff --git a/content/docs/build/actions.ja.mdx b/content/docs/build/actions.ja.mdx new file mode 100644 index 0000000..e08aaeb --- /dev/null +++ b/content/docs/build/actions.ja.mdx @@ -0,0 +1,205 @@ +--- +title: アクション +description: プラットフォームが REST エンドポイント、Console のボタン、フローのステップ、AI ツールとして公開する名前付きの操作 — 1 つの宣言から。 +--- + +# アクション + +**アクション**とは、オブジェクトに対する名前付きの操作です。一度宣言すれば、 +次のように表れます。 + +- `/api/v1/actions//` の **REST エンドポイント** +- Console のレコード詳細にある**ボタン** +- 自動化のための**フローステップ**(`type: 'action'`) +- Agents と AI Builder のための **AI ツール**(`action_`) + +4 つのサーフェスにわたって同じことを繰り返す必要はありません。宣言は 1 つ、 +呼び出し方は 4 通りです。 + +## アクションを宣言する + +```ts +// src/actions/approve_invoice.action.ts +import { Action } from '@objectstack/spec'; + +export const approveInvoice = Action.create({ + name: 'approve_invoice', // lowercase snake_case (machine id) + label: 'Approve Invoice', + objectName: 'invoice', // attaches to the invoice object + icon: 'check', + variant: 'primary', + locations: ['record_header'], // where the button shows + confirmText: 'Approve this invoice?', + successMessage: 'Invoice approved', + refreshAfter: true, + + // collect input before running + params: [ + { name: 'note', label: 'Approval note', type: 'textarea' }, + ], + + // only show the button when the record is still pending + visible: 'record.status == "pending"', + + // what it does — a sandboxed script body + type: 'script', + body: { + language: 'js', + source: ` + await ctx.data.update('invoice', input.id, { + status: 'approved', + approved_by: ctx.user.id, + approved_at: now(), + approval_note: input.note, + }); + `, + }, +}); +``` + +`os dev` による再コンパイル後: + +- `POST /api/v1/actions/invoice/approve_invoice` が機能する +- Console の Invoice レコードページに **Approve Invoice** ボタンが表示される +- フローに `{ type: 'action', action: 'approve_invoice', inputs: { note: '…' } }` を含められる +- AI アシスタントは、スキルが許可していれば `action_approve_invoice` を呼び出せる + +## アクションの種類 + +`type` フィールドがアクションの動作を決定します。 + +| `type` | 実行される内容 | 用途 | +|---|---|---| +| `script` | `body` — L1 の formula 式、またはサンドボックス化された L2 の JavaScript | ほとんどのケース — サーバーサイドのロジック、監査可能かつ AI から呼び出し可能 | +| `api` | `target` エンドポイントへの HTTP 呼び出し(`method`、`bodyExtra`) | data-API またはプラットフォームのエンドポイントの再利用 | +| `flow` | `target` で指定した名前のフローを実行 | 複数ステップのビジネスプロセス | +| `url` | `target` の URL へ遷移 | ディープリンク、リダイレクト形式のアクション | +| `modal` | `target` で指定した名前のページ/モーダルを開く | カスタムダイアログ | +| `form` | `target` で指定した名前の FormView を開く | ガイド付きのデータ入力 | + +```ts +// api type — reuse a data-API endpoint +Action.create({ + name: 'archive_order', + objectName: 'order', + label: 'Archive', + locations: ['list_item'], + type: 'api', + method: 'PATCH', + target: '/api/v1/data/order/{id}', + bodyExtra: { archived: true }, +}); +``` + +`script` 以外の種類には `target` が必要です。どの種類であっても、アクションは +すべてのサーフェスで同じファーストクラスの存在です。 + +## アクションを呼び出す + +### REST + +```bash +# the record id can go in the body, or in the path +curl -X POST https://app.example.com/api/v1/actions/invoice/approve_invoice/inv_123 \ + -H 'Authorization: Bearer ' \ + -H 'Content-Type: application/json' \ + -d '{"note": "LGTM"}' +``` + +パラメータはリクエストボディにフラットな形で送信されます。レコード id は、 +末尾のパスセグメント(`.../approve_invoice/:recordId`)として、またはボディで +渡せます。レスポンスはスクリプトボディの戻り値(または `api` 種類のアクションでは +呼び出し結果)です。 + +### Console + +デフォルトでは、Console はアクションをレコード詳細ページのボタンとして表示し、 +アクションの `visible` 述語でフィルタリングします。配置を上書きするには、 +ビュー設定で指定します。 + +```ts +defineView({ + name: 'invoice_detail', + object: 'invoice', + actions: ['approve_invoice', 'reject_invoice', 'send_to_customer'], +}); +``` + +### フローから + +```ts +{ + type: 'action', + action: 'approve_invoice', + inputs: { note: 'Auto-approved by SLA flow' }, + record: '{!trigger.record.id}', +} +``` + +### AI Agent から + +`approve_invoice` がエージェントの持ついずれかのスキルに含まれていれば、LLM は +それを呼び出せます。入力は会話から取得され、権限はユーザーが直接呼び出した場合と +同じように適用されます。 + +> *「INV-2042 の請求書を、メモ『電話で確認済み』を付けて承認して。」* + +## 権限 + +アクションは呼び出したユーザーの権限で実行されます。プラットフォームは次を +チェックします。 + +1. **オブジェクト権限** — ユーザーの[権限セット](/docs/configure/permissions/permission-sets)が、 + アクションに必要なオブジェクトレベルのアクセス(例: update)を付与している必要があります。 +2. **フィールド権限** — アクションが書き込む任意のフィールドについて、ユーザーは + 書き込みアクセス(FLS)を持っている必要があります。 +3. **UI ゲーティング** — `visible` と `disabled` の述語(CEL、`record`、`os.user`、 + およびパラメータに対して評価される)が、Console でボタンを描画するか、 + グレーアウトするかを制御します。 + +権限チェックに失敗すると、`PERMISSION_DENIED` エラーとともに `403` を返します。 + +## 組み込みアクション + +すべてのオブジェクトには、これらが標準で備わっています。 + +| アクション | 動作 | +|---|---| +| `create` | レコードを挿入 | +| `update` | レコードを更新 | +| `delete` | レコードを削除(またはソフト削除) | +| `restore` | ソフト削除を取り消し | +| `clone` | レコードをディープコピー | +| `share` | ユーザー / ロールと直接共有 | + +これらを再宣言しないでください — これらはオブジェクトの[ライフサイクルと機能フラグ](/docs/build/data-model)に従います。 + +## 監査 + +プラットフォームのイベントは、次のフィールドを含む不変の証跡である +`sys_audit_log` に記録されます。 + +- `user_id` — 発生元のユーザー +- `action` — アクション名 +- `object_name` と `record_id` — 操作対象 +- `old_value` / `new_value` — 変更内容 +- `ip_address` / `user_agent` — リクエストの発信元 +- `created_at` — 発生日時 + +これは*「誰がボタンを押したのか?」*という疑問の最初の手がかりです。 + +## AI Builder でアクションを生成する + +> *「`support_ticket` に `escalate_ticket` というアクションを作成し、優先度を +> urgent に設定して、オンコールのエンジニアに割り当てて。」* + +[AI Builder](/docs/build/ai-builder) はアクションのメタデータを生成し、その変更を +承認待ちのキューに入れます。承認後、アクションは REST、Console、フロー、そして +再帰的に AI 自身からも呼び出せるようになります。 + +## 次に読むもの + +- [フロー](/docs/build/flows) — 複数のアクションを組み合わせてビジネスロジックを構成する +- [Agents](/docs/build/agents) — アクションを AI ツールとして公開する +- [API アクセス](/docs/configure/api-access) — 外部システムからアクションを呼び出す +- [権限](/docs/configure/permissions) — 誰が何を呼び出せるかを制御する diff --git a/content/docs/build/actions.mdx b/content/docs/build/actions.mdx index dc6136c..ba4a6cd 100644 --- a/content/docs/build/actions.mdx +++ b/content/docs/build/actions.mdx @@ -8,7 +8,7 @@ description: Named operations the platform exposes as REST endpoints, Console bu An **Action** is a named operation on an object. Declare it once and it appears as: -- a **REST endpoint** at `/api/v1/data//actions/` +- a **REST endpoint** at `/api/v1/actions//` - a **button** in Console's record detail - a **flow step** (`type: 'action'`) for automation - an **AI tool** (`action_`) for Agents and the AI Builder @@ -20,89 +20,101 @@ ways to call it. ```ts // src/actions/approve_invoice.action.ts -import { defineAction, Field } from '@objectstack/spec'; +import { Action } from '@objectstack/spec'; -export const approveInvoice = defineAction({ - name: 'approve_invoice', +export const approveInvoice = Action.create({ + name: 'approve_invoice', // lowercase snake_case (machine id) label: 'Approve Invoice', - object: 'invoice', - description: 'Mark the invoice approved and stamp the approver.', + objectName: 'invoice', // attaches to the invoice object icon: 'check', + variant: 'primary', + locations: ['record_header'], // where the button shows + confirmText: 'Approve this invoice?', + successMessage: 'Invoice approved', + refreshAfter: true, + + // collect input before running + params: [ + { name: 'note', label: 'Approval note', type: 'textarea' }, + ], - inputs: { - note: Field.textarea({ label: 'Approval note' }), - }, - - // who can invoke this - permissions: { - requires: ['allowEdit'], // object-level - condition: 'record.status == "pending"', + // only show the button when the record is still pending + visible: 'record.status == "pending"', + + // what it does — a sandboxed script body + type: 'script', + body: { + language: 'js', + source: ` + await ctx.data.update('invoice', input.id, { + status: 'approved', + approved_by: ctx.user.id, + approved_at: now(), + approval_note: input.note, + }); + `, }, - - // what it does — declarative, no JS required - steps: [ - { - type: 'update', - record: '{!record.id}', - fields: { - status: 'approved', - approved_by: '{!user.id}', - approved_at: '{!now()}', - approval_note: '{!inputs.note}', - }, - }, - ], }); ``` -That's the whole file. After `os dev` recompiles: +After `os dev` recompiles: -- `POST /api/v1/data/invoice/actions/approve_invoice` works +- `POST /api/v1/actions/invoice/approve_invoice` works - The Invoice record page in Console shows an **Approve Invoice** button - A flow can include `{ type: 'action', action: 'approve_invoice', inputs: { note: '…' } }` - The AI assistant can call `action_approve_invoice` if its skills allow -## Three flavors +## Action types -| Flavor | What runs | Use for | +The `type` field decides what the action does: + +| `type` | What runs | Use for | |---|---|---| -| **Declarative** (`steps:`) | DSL — update/create/delete/query/action/condition/foreach | Most cases — auditable + AI-callable | -| **Script** (`script:`) | TypeScript function, executes server-side | Cross-system logic, complex transforms | -| **External** (`webhook:`) | HTTP POST to your endpoint | Delegating to your own service | +| `script` | A `body` — an L1 formula expression or sandboxed L2 JavaScript | Most cases — server-side logic, auditable + AI-callable | +| `api` | An HTTP call to a `target` endpoint (`method`, `bodyExtra`) | Reusing data-API or platform endpoints | +| `flow` | Runs the flow named in `target` | Multi-step business processes | +| `url` | Navigates to the `target` URL | Deep links, redirect-style actions | +| `modal` | Opens the page/modal named in `target` | Custom dialogs | +| `form` | Opens the FormView named in `target` | Guided data entry | ```ts -// script flavor -defineAction({ - name: 'archive_old_orders', - object: 'order', - script: async ({ ctx, record, inputs }) => { - await ctx.data.update('order', record.id, { archived_at: new Date() }); - return { ok: true }; - }, +// api type — reuse a data-API endpoint +Action.create({ + name: 'archive_order', + objectName: 'order', + label: 'Archive', + locations: ['list_item'], + type: 'api', + method: 'PATCH', + target: '/api/v1/data/order/{id}', + bodyExtra: { archived: true }, }); ``` -Whichever flavor, the action is the same first-class citizen on every -surface. +Types other than `script` require a `target`. Whichever type, the action +is the same first-class citizen on every surface. ## Calling an action ### REST ```bash -curl -X POST https://app.example.com/api/v1/data/invoice/actions/approve_invoice \ +# the record id can go in the body, or in the path +curl -X POST https://app.example.com/api/v1/actions/invoice/approve_invoice/inv_123 \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ - -d '{"recordId": "inv_123", "inputs": {"note": "LGTM"}}' + -d '{"note": "LGTM"}' ``` -Returns the updated record (for declarative actions) or your handler's -return value (for script actions). +Params are sent flat in the request body. The record id can be supplied +either as a trailing path segment (`.../approve_invoice/:recordId`) or in +the body. The response is your script body's return value (or the call +result for `api`-type actions). ### Console By default, Console shows actions as buttons on the record detail page, -filtered by the action's `permissions.condition`. Override placement +filtered by the action's `visible` predicate. Override placement in your view config: ```ts @@ -134,18 +146,17 @@ the user invoked it directly. ## Permissions -Every action runs as the calling user — never as a service account. -The platform checks: +Actions run with the calling user's permissions. The platform checks: -1. **Object permission** — the `requires:` flags (`allowEdit`, - `allowCreate`, …) on the user's permission set. -2. **Action gate** — the action's `permissions.condition` (a CEL - expression evaluated against the record, the user, and inputs). -3. **Field permissions** — for any field the action writes, the user - must have write access. +1. **Object permissions** — the user's [permission sets](/docs/configure/permissions/permission-sets) + must grant the object-level access the action needs (e.g. update). +2. **Field permissions** — for any field the action writes, the user + must have write access (FLS). +3. **UI gating** — the `visible` and `disabled` predicates (CEL, + evaluated against `record`, `os.user`, and params) control whether the + button renders or is greyed out in Console. -Failed checks return `403 Forbidden` with a structured error explaining -which check failed. +Failed permission checks return `403` with a `PERMISSION_DENIED` error. ## Built-in actions @@ -160,18 +171,19 @@ Every object gets these for free: | `clone` | Deep-copy a record | | `share` | Direct share with a user / role | -Don't redeclare these — extend behavior via [hooks](/docs/build/data-model#field-types). +Don't redeclare these — they follow the object's [lifecycle & capability flags](/docs/build/data-model). ## Auditing -Every action invocation lands in `sys_audit_log` with: +Platform events land in `sys_audit_log`, an immutable trail with fields +including: -- the originating user -- the action name + inputs (with secret fields redacted) -- the record id (if any) -- success / failure + error -- timing -- the originating surface (`rest` / `studio` / `flow` / `ai`) +- `user_id` — the originating user +- `action` — the action name +- `object_name` and `record_id` — what was touched +- `old_value` / `new_value` — the change +- `ip_address` / `user_agent` — request origin +- `created_at` — when it happened This is your first stop for *"who pushed the button?"* questions. @@ -180,9 +192,9 @@ This is your first stop for *"who pushed the button?"* questions. > *"Create an action `escalate_ticket` on `support_ticket` that sets > priority to urgent and assigns it to the on-call engineer."* -The AI calls `create_action` (a metadata tool) and queues the change -for approval. After approval, the action is callable from REST, -Console, flows, and — recursively — the AI itself. +The [AI Builder](/docs/build/ai-builder) generates the action metadata and +queues the change for approval. After approval, the action is callable from +REST, Console, flows, and — recursively — the AI itself. ## Where to go next diff --git a/content/docs/build/actions.zh-Hans.mdx b/content/docs/build/actions.zh-Hans.mdx new file mode 100644 index 0000000..01e6311 --- /dev/null +++ b/content/docs/build/actions.zh-Hans.mdx @@ -0,0 +1,187 @@ +--- +title: Actions +description: 平台从单一声明出发,将命名操作同时暴露为 REST 端点、Console 按钮、流程步骤和 AI 工具。 +--- + +# Actions + +**Action** 是对象上的一个命名操作。只需声明一次,它就会以以下形式出现: + +- 一个位于 `/api/v1/actions//` 的 **REST 端点** +- Console 记录详情中的一个**按钮** +- 用于自动化的一个**流程步骤**(`type: 'action'`) +- 供 Agents 和 AI Builder 使用的一个 **AI 工具**(`action_`) + +你无需在四个界面上重复定义。一次声明,四种调用方式。 + +## 声明一个 action + +```ts +// src/actions/approve_invoice.action.ts +import { Action } from '@objectstack/spec'; + +export const approveInvoice = Action.create({ + name: 'approve_invoice', // lowercase snake_case (machine id) + label: 'Approve Invoice', + objectName: 'invoice', // attaches to the invoice object + icon: 'check', + variant: 'primary', + locations: ['record_header'], // where the button shows + confirmText: 'Approve this invoice?', + successMessage: 'Invoice approved', + refreshAfter: true, + + // collect input before running + params: [ + { name: 'note', label: 'Approval note', type: 'textarea' }, + ], + + // only show the button when the record is still pending + visible: 'record.status == "pending"', + + // what it does — a sandboxed script body + type: 'script', + body: { + language: 'js', + source: ` + await ctx.data.update('invoice', input.id, { + status: 'approved', + approved_by: ctx.user.id, + approved_at: now(), + approval_note: input.note, + }); + `, + }, +}); +``` + +在 `os dev` 重新编译之后: + +- `POST /api/v1/actions/invoice/approve_invoice` 可用 +- Console 中的 Invoice 记录页面会显示一个 **Approve Invoice** 按钮 +- 流程可以包含 `{ type: 'action', action: 'approve_invoice', inputs: { note: '…' } }` +- 如果 AI 助手的技能允许,它可以调用 `action_approve_invoice` + +## Action 类型 + +`type` 字段决定 action 执行什么: + +| `type` | 执行内容 | 适用场景 | +|---|---|---| +| `script` | 一个 `body` —— 一个 L1 formula 表达式或沙箱化的 L2 JavaScript | 大多数场景 —— 服务端逻辑,可审计且可被 AI 调用 | +| `api` | 对某个 `target` 端点发起的 HTTP 调用(`method`、`bodyExtra`) | 复用数据 API 或平台端点 | +| `flow` | 运行 `target` 中指定名称的流程 | 多步骤业务流程 | +| `url` | 跳转到 `target` URL | 深度链接、重定向式操作 | +| `modal` | 打开 `target` 中指定名称的页面/模态框 | 自定义对话框 | +| `form` | 打开 `target` 中指定名称的 FormView | 引导式数据录入 | + +```ts +// api type — reuse a data-API endpoint +Action.create({ + name: 'archive_order', + objectName: 'order', + label: 'Archive', + locations: ['list_item'], + type: 'api', + method: 'PATCH', + target: '/api/v1/data/order/{id}', + bodyExtra: { archived: true }, +}); +``` + +除 `script` 之外的类型都需要一个 `target`。无论哪种类型,该 action 在每个界面上都是同等的一级公民。 + +## 调用一个 action + +### REST + +```bash +# the record id can go in the body, or in the path +curl -X POST https://app.example.com/api/v1/actions/invoice/approve_invoice/inv_123 \ + -H 'Authorization: Bearer ' \ + -H 'Content-Type: application/json' \ + -d '{"note": "LGTM"}' +``` + +参数以扁平形式放在请求体中发送。记录 id 既可以作为路径末尾的片段提供(`.../approve_invoice/:recordId`),也可以放在请求体中。响应是你的脚本 body 的返回值(对于 `api` 类型的 action 则是调用结果)。 + +### Console + +默认情况下,Console 会将 action 显示为记录详情页面上的按钮,并按 action 的 `visible` 谓词进行过滤。你可以在视图配置中覆盖其位置: + +```ts +defineView({ + name: 'invoice_detail', + object: 'invoice', + actions: ['approve_invoice', 'reject_invoice', 'send_to_customer'], +}); +``` + +### 来自流程 + +```ts +{ + type: 'action', + action: 'approve_invoice', + inputs: { note: 'Auto-approved by SLA flow' }, + record: '{!trigger.record.id}', +} +``` + +### 来自 AI Agent + +如果 `approve_invoice` 包含在该 agent 拥有的任意技能中,LLM 就可以调用它。输入来自对话内容;权限的执行方式与用户直接调用时完全一致。 + +> *"Approve invoice INV-2042 with note 'verified by phone.'"* + +## 权限 + +Action 以发起调用的用户的权限运行。平台会检查: + +1. **对象权限** —— 用户的[权限集](/docs/configure/permissions/permission-sets)必须授予该 action 所需的对象级访问权限(例如 update)。 +2. **字段权限** —— 对于该 action 写入的任何字段,用户必须拥有写入访问权限(FLS)。 +3. **UI 控制** —— `visible` 和 `disabled` 谓词(CEL,针对 `record`、`os.user` 和参数求值)控制按钮在 Console 中是渲染还是置灰。 + +未通过的权限检查会返回 `403`,并附带一个 `PERMISSION_DENIED` 错误。 + +## 内置 action + +每个对象都会免费获得以下 action: + +| Action | 作用 | +|---|---| +| `create` | 插入一条记录 | +| `update` | 更新一条记录 | +| `delete` | 删除(或软删除)一条记录 | +| `restore` | 撤销软删除 | +| `clone` | 深拷贝一条记录 | +| `share` | 直接与某个用户/角色共享 | + +不要重新声明这些 —— 它们遵循对象的[生命周期与能力标志](/docs/build/data-model)。 + +## 审计 + +平台事件会落入 `sys_audit_log`,这是一条不可变的轨迹,其字段包括: + +- `user_id` —— 发起操作的用户 +- `action` —— action 名称 +- `object_name` 和 `record_id` —— 被操作的对象 +- `old_value` / `new_value` —— 变更内容 +- `ip_address` / `user_agent` —— 请求来源 +- `created_at` —— 发生时间 + +当你需要回答*"是谁按下了这个按钮?"*之类的问题时,这里是首选的查证之处。 + +## 使用 AI Builder 生成 action + +> *"Create an action `escalate_ticket` on `support_ticket` that sets +> priority to urgent and assigns it to the on-call engineer."* + +[AI Builder](/docs/build/ai-builder) 会生成该 action 的元数据,并将变更排队等待审批。审批通过后,该 action 即可从 REST、Console、流程,以及 —— 递归地 —— AI 自身进行调用。 + +## 后续去向 + +- [Flows](/docs/build/flows) —— 将多个 action 组合成业务逻辑 +- [Agents](/docs/build/agents) —— 将 action 暴露为 AI 工具 +- [API Access](/docs/configure/api-access) —— 从外部系统调用 action +- [Permissions](/docs/configure/permissions) —— 控制谁可以调用什么 diff --git a/content/docs/build/agents.cn.mdx b/content/docs/build/agents.cn.mdx deleted file mode 100644 index 832623e..0000000 --- a/content/docs/build/agents.cn.mdx +++ /dev/null @@ -1,155 +0,0 @@ ---- -title: Agents -description: 终端用户的 AI 助手 —— Agent → Skill → Tool —— 直接由你的数据和 Action 接线而成。 ---- - -# Agents - -Agent 是你的**终端用户**对话的 AI 助手 —— 工单台副驾、销售 BDR、内部 HR 问答机器人。它们坐在你已经定义好的数据和 Action 之上;你不必再写新代码,只需把已有原语组合成一个角色人设。 - -三层架构,对齐 Salesforce Agentforce、Microsoft Copilot Console 与 ServiceNow Now Assist: - -```text -Agent ──→ Skill ──→ Tool -(persona) (capability) (callable function) -``` - -| 层级 | 是什么 | 例子 | -|---|---|---| -| **Tool** | 单个可调用函数(action、查询、知识搜索、MCP 方法) | `create_ticket`、`get_order_status`、`search_kb` | -| **Skill** | 一组相关工具的命名集合,共享 LLM 指令 | `ticket_management` = create + update + close + escalate | -| **Agent** | 带角色、系统提示、所附 Skill 和知识的人设 | `tier1_support` = 有同理心、会核验身份、拥有 `ticket_management` + `kb_search` | - -## 定义一个 Agent(一个文件) - -```ts -// src/agents/tier1_support.agent.ts -import { defineAgent } from '@objectstack/spec/ai'; - -export const tier1Support = defineAgent({ - name: 'tier1_support', - label: 'First Line Support', - role: 'Help Desk Assistant', - instructions: ` - You are a friendly first-line support agent. - Always verify the user's identity before discussing account specifics. - Escalate to tier 2 if the issue involves billing or security. - `, - skills: ['ticket_management', 'knowledge_search'], - knowledge: { - topics: ['faq', 'policies'], - indexes: ['support_docs'], - }, - model: 'smart', // 在 AI 服务的模型映射中解析 - memory: { strategy: 'rolling', maxMessages: 30 }, -}); -``` - -或者在 Console 中:**Console → Agents → New Agent**。 - -又或者 —— 这才是重点 —— 对 AI Builder 说: - -> *"创建一个一线支持 Agent,处理工单管理并搜索 FAQ。讨论账户细节前应核验身份。"* - -## 定义一个 Skill - -```ts -// src/skills/ticket_management.skill.ts -import { defineSkill } from '@objectstack/spec/ai'; - -export const ticketManagement = defineSkill({ - name: 'ticket_management', - label: 'Ticket Management', - instructions: ` - Always confirm the ticket subject and priority before creating one. - Use 'urgent' priority sparingly — only for outages or security incidents. - `, - tools: [ - 'create_ticket', - 'update_ticket', - 'close_ticket', - 'escalate_ticket', - 'action_*', // 通配符:获取当前对象上未来任何 Action - ], -}); -``` - -Skill 是**最适合复用的单元**。一个 Skill 可服务多个 Agent。 - -## Tool 来自你声明的元数据 - -你声明的每个 `*.action.ts` 都会自动物化为一个 `action_` 工具 —— 无需另外接线。所以如果你已经在 `support_ticket` 对象上定义了 `escalate_ticket` Action,AI Builder 和你的 Agent 都能调用它。权限仍然生效:Agent **以用户身份**调用该 Action,能否成功由用户的权限集决定。 - -你还可以暴露: - -| 工具类型 | 来源 | -|---|---| -| **Action** | 已安装任何包中的任何 `*.action.ts` | -| **Flow** | 任何手动流程(`type: 'manual'`) | -| **Query** | 保存的 ObjectQL 查询(`*.query.ts`) | -| **Knowledge search** | 附加到 Agent 的任意知识索引 | -| **MCP 方法** | 接入的 MCP 服务器所暴露的任何方法 | -| **内置元数据工具** | `create_object`、`add_field`…—— 仅对管理员 Agent 开放 | - -## 环境助手模式 - -如果你想要**整个应用一个聊天框**(Claude Code / Agentforce 风格),而不是强迫用户挑选 Agent,使用 assistant 端点: - -```text -GET /api/v1/ai/assistant 为当前上下文解析默认 Agent -GET /api/v1/ai/assistant/skills 列出当前上下文激活的 Skill -POST /api/v1/ai/assistant/chat 发消息 —— 由 LLM 挑工具 -``` - -Console 内置的 AI 面板用的就是这些。运行时会解析: - -1. 当前 App 的**默认 Agent**(声明在 App 元数据上),否则是用户能访问的第一个 Agent。 -2. **激活的 Skill** —— 按用户权限集、当前对象/记录上下文、Agent 的 `skills:` 列表过滤。 -3. 附加到该 Agent 的**知识**。 - -你不必接线"哪里展示哪个 Agent"。声明一个 App,把其中一个 Agent 标为默认,它就会出现。 - -## 权限 - -| 能力 | 权限 | -|---|---| -| 与 Agent 对话 | `ai:chat`(并对该 Agent 的 Skill 所含工具有权限) | -| 审批元数据变更 | `ai:approve` | -| 定义 / 编辑 Agent 和 Skill | `ai:author`(通常是 Setup Administrator) | -| 读取 AI 对话(审计) | `ai:read` | - -对话以用户为粒度作用域 —— 用户之间互相看不见对话记录,除非有委托授权。 - -## 记忆与会话状态 - -| 策略 | 作用 | -|---|---| -| `rolling`(默认) | 在提示中保留最近 N 条消息 | -| `summary` | 把更早的轮次摘要为一条系统注释 | -| `none` | 无状态 —— 每轮都从零开始 | -| `custom` | 提供你自己的记忆插件 | - -会话记录存于 `sys_ai_conversation`。工具调用结果与待执行的 Action 都反向引用其原始会话以便审计。 - -## 可观测性 - -每次 Agent 运行都会发出: - -- `audit:ai:chat` 事件(每轮一条) -- `audit:ai:tool` 事件(每次工具调用,含输入 + 输出) -- `audit:ai:pending_action` 事件(变更入队时) -- token 计数指标(按模型、按供应商)进入审计日志,用于成本分摊 - -你可以把这些接入你常用的可观测性栈 —— 见 [Observability](/docs/operate/observability)。 - -## 多租户说明 - -Agent 是 Environment 级的。租户 A 的 `tier1_support` Agent 永远看不到租户 B 的数据、对话或知识 —— 即便你在应用市场包里发的是同一份 Agent 定义。 - -## 下一步 - -- [AI Builder](/docs/build/ai-builder) —— 构建期助手 -- [IDE Skills](/docs/build/ai-skills) —— `npx skills add objectstack-ai/framework`,让你的 IDE Agent 正确编写元数据 -- [Actions](/docs/build/actions) —— 声明你的 Agent 将使用的工具 -- [AI Service](/docs/configure/ai) —— 供应商、嵌入器、MCP 配置 -- [`@objectstack/spec/ai`](https://github.com/objectstack-ai/framework/tree/main/packages/spec/src/ai) —— 完整 Schema diff --git a/content/docs/build/agents.de.mdx b/content/docs/build/agents.de.mdx new file mode 100644 index 0000000..332bcc6 --- /dev/null +++ b/content/docs/build/agents.de.mdx @@ -0,0 +1,190 @@ +--- +title: Agents +description: KI-Assistenten für Endnutzer — Agent → Skill → Tool — verdrahtet aus Ihren Daten und Aktionen. +--- + +# Agents + +Agents sind die KI-Assistenten, mit denen Ihre **Endnutzer** chatten — ein +Helpdesk-Co-Pilot, ein Vertriebs-BDR, ein interner HR-Q&A-Bot. Sie setzen auf +den Daten und Aktionen auf, die Sie bereits definiert haben; Sie schreiben +keinen neuen Code, sondern komponieren vorhandene Primitive zu einer Persona. + +Dreistufige Architektur, abgestimmt auf Salesforce Agentforce, Microsoft +Copilot Studio und ServiceNow Now Assist: + +```text +Agent ──→ Skill ──→ Tool +(persona) (capability) (callable function) +``` + +| Stufe | Was es ist | Beispiel | +|---|---|---| +| **Tool** | Eine aufrufbare Funktion (Aktion, Abfrage, Wissenssuche, MCP-Methode) | `create_ticket`, `get_order_status`, `search_kb` | +| **Skill** | Ein benanntes Bündel verwandter Tools mit gemeinsamen LLM-Anweisungen | `ticket_management` = create + update + close + escalate | +| **Agent** | Eine Persona mit einer Rolle, einem System-Prompt, angehängten Skills und Wissen | `tier1_support` = empathisch, verifiziert die Identität, verfügt über `ticket_management` + `kb_search` | + +## Einen Agent definieren (eine Datei) + +```ts +// src/agents/tier1_support.agent.ts +import { defineAgent } from '@objectstack/spec/ai'; + +export const tier1Support = defineAgent({ + name: 'tier1_support', + label: 'First Line Support', + role: 'Help Desk Assistant', + instructions: ` + You are a friendly first-line support agent. + Always verify the user's identity before discussing account specifics. + Escalate to tier 2 if the issue involves billing or security. + `, + skills: ['ticket_management', 'knowledge_search'], + knowledge: { + topics: ['faq', 'policies'], + indexes: ['support_docs'], + }, + model: { provider: 'openai', model: 'gpt-4o', temperature: 0.3 }, + memory: { shortTerm: { maxMessages: 30 } }, +}); +``` + +Oder in der Console: **Console → Agents → New Agent**. + +Oder — und das ist der entscheidende Punkt — sagen Sie zum AI Builder: + +> *„Erstelle einen Tier-1-Support-Agent, der das Ticket-Management übernimmt +> und die FAQ durchsucht. Er soll die Identität verifizieren, bevor er über +> Kontodetails spricht."* + +## Einen Skill definieren + +```ts +// src/skills/ticket_management.skill.ts +import { defineSkill } from '@objectstack/spec/ai'; + +export const ticketManagement = defineSkill({ + name: 'ticket_management', + label: 'Ticket Management', + instructions: ` + Always confirm the ticket subject and priority before creating one. + Use 'urgent' priority sparingly — only for outages or security incidents. + `, + tools: [ + 'create_ticket', + 'update_ticket', + 'close_ticket', + 'escalate_ticket', + 'action_*', // wildcard: pick up any future actions on the active object + ], +}); +``` + +Skills sind **die richtige Einheit für die Wiederverwendung**. Ein Skill +funktioniert über viele Agents hinweg. + +## Tools stammen aus Ihren deklarierten Metadaten + +Jede `*.action.ts`, die Sie deklarieren, materialisiert sich automatisch als +`action_`-Tool — ohne separate Verdrahtung. Wenn Sie also bereits +`escalate_ticket` als Aktion auf dem Objekt `support_ticket` definiert haben, +können sowohl der AI Builder als auch Ihre Agents sie aufrufen. Berechtigungen +gelten weiterhin: Der Agent ruft die Aktion **als der Nutzer** auf, sodass das +Berechtigungsset des Nutzers entscheidet, ob sie erfolgreich ist. + +Sie können außerdem Folgendes bereitstellen: + +| Tool-Typ | Quelle | +|---|---| +| **Action** | Jede `*.action.ts` in jedem installierten Paket | +| **Flow** | Jeder manuelle Flow (`type: 'manual'`) | +| **Query** | Gespeicherte ObjectQL-Abfragen (`*.query.ts`) | +| **Wissenssuche** | Jeder Wissensindex, der dem Agent angehängt ist | +| **MCP-Methode** | Alles, was von einem angehängten MCP-Server bereitgestellt wird | +| **Integrierte Metadaten-Tools** | `create_object`, `add_field`, … — jedoch nur für Admin-Agents | + +## Muster für Ambient-Assistenten + +Wenn Sie **eine Chatbox für die gesamte App** wollen (im Stil von Claude Code / +Agentforce), anstatt den Nutzer zur Auswahl eines Agents zu zwingen, +deklarieren Sie einen `defaultAgent` in den App-Metadaten und rufen den +Ambient-Chat-Endpunkt mit dem App-Kontext auf: + +```text +POST /api/v1/ai/chat { context: { appName: 'crm' }, ... } +``` + +Wenn `context.appName` zu einer App aufgelöst wird, die einen `defaultAgent` +deklariert, wählt die Laufzeitumgebung diesen Agent automatisch aus — der +Nutzer wählt nie aus einer Liste. Das integrierte KI-Panel der Console nutzt +dies. Die Laufzeitumgebung löst auf: + +1. Den **Standard-Agent** für die aktive App (der `defaultAgent` der App) + oder den ersten Agent, auf den der Nutzer Zugriff hat. +2. Die **aktiven Skills** — die `skills:`-Liste des Agents, geladen aus der + Skill Registry, gefiltert nach dem Berechtigungsset des Nutzers und dem + aktuellen Objekt-/Datensatzkontext. +3. Das **Wissen**, das dem Agent angehängt ist. + +Sie müssen nicht verdrahten, welcher Agent wo angezeigt wird. Deklarieren Sie +eine App, legen Sie ihren `defaultAgent` fest, und er erscheint. + +## Berechtigungen + +| Fähigkeit | Berechtigung | +|---|---| +| Mit einem Agent chatten | `ai:chat` (und Zugriff auf die Tools der Skills des Agents) | +| Metadatenänderungen genehmigen | `ai:approve` | +| Agents und Skills definieren / bearbeiten | `ai:author` (typischerweise Setup Administrator) | +| KI-Konversationen lesen (Audit) | `ai:read` | + +Konversationen sind auf den Nutzer beschränkt — ein Nutzer kann den +Chatverlauf eines anderen nicht sehen, es sei denn, er verfügt über eine +delegierte Berechtigung. + +## Speicher und Konversationsstatus + +Der `memory`-Block des Agents hat zwei Stufen: + +| Feld | Was es tut | +|---|---| +| `shortTerm.maxMessages` | Aktuelle Nachrichten, die im Arbeitsspeicher gehalten werden (Standard `50`) | +| `shortTerm.maxTokens` | Optionales Token-Budget für das Kurzzeit-Kontextfenster | +| `longTerm.enabled` | Speicher über Sitzungen hinweg persistieren (Standard `false`) | +| `longTerm.store` | Backend für persistierten Speicher: `vector` (Standard), `database` oder `redis` | +| `reflectionInterval` | Alle N Interaktionen reflektieren, um das Verhalten zu verfeinern | + +Das Beschneiden des Live-Kontextfensters wird durch die +Token-Budget-Strategie der Konversation gesteuert — `sliding_window` +(Standard), `fifo`, `importance`, `semantic` oder `summary`. + +Konversationszeilen liegen in `ai_conversations`. Tool-Aufruf-Ergebnisse und +ausstehende Aktionen verweisen zur Auditierung auf die zugehörige Konversation +zurück. + +## Observability + +Jeder Agent-Lauf gibt aus: + +- `audit:ai:chat`-Ereignisse (pro Runde) +- `audit:ai:tool`-Ereignisse (pro Tool-Aufruf, mit Eingaben + Ausgaben) +- `audit:ai:pending_action`-Ereignisse (wenn eine Mutation in die Warteschlange gestellt wird) +- Token-Zählmetriken (pro Modell, pro Anbieter) in das Audit-Log für die + Kostenzuordnung + +Sie können diese in Ihren üblichen Observability-Stack einbinden — siehe +[Observability](/docs/operate/observability). + +## Hinweis zur Mandantenfähigkeit + +Agents sind pro Environment. Der `tier1_support`-Agent von Mandant A sieht +niemals die Daten, Konversationen oder das Wissen von Mandant B — selbst wenn +Sie dieselbe Agent-Definition in einem Marketplace-Paket ausliefern. + +## Wie es weitergeht + +- [AI Builder](/docs/build/ai-builder) — der Assistent zur Build-Zeit +- [IDE Skills](/docs/build/ai-skills) — `npx skills add objectstack-ai/framework`, damit Ihr IDE-Agent Metadaten korrekt erstellt +- [Actions](/docs/build/actions) — deklarieren Sie die Tools, die Ihre Agents verwenden werden +- [AI Service](/docs/configure/ai) — Anbieter-, Embedder- und MCP-Einrichtung +- [`@objectstack/spec/ai`](https://github.com/objectstack-ai/framework/tree/main/packages/spec/src/ai) — vollständige Schemas diff --git a/content/docs/build/agents.es.mdx b/content/docs/build/agents.es.mdx new file mode 100644 index 0000000..b0699b3 --- /dev/null +++ b/content/docs/build/agents.es.mdx @@ -0,0 +1,190 @@ +--- +title: Agentes +description: Asistentes de IA para usuarios finales — Agente → Skill → Tool — conectados desde tus datos y acciones. +--- + +# Agentes + +Los agentes son los asistentes de IA con los que conversan tus **usuarios +finales** — un copiloto de mesa de ayuda, un BDR de ventas, un bot interno +de preguntas y respuestas de RR. HH. Se apoyan en los datos y las acciones +que ya has definido; no escribes código nuevo, compones primitivas +existentes para formar una persona. + +Arquitectura de tres niveles, alineada con Salesforce Agentforce, Microsoft +Copilot Studio y ServiceNow Now Assist: + +```text +Agent ──→ Skill ──→ Tool +(persona) (capability) (callable function) +``` + +| Nivel | Qué es | Ejemplo | +|---|---|---| +| **Tool** | Una función invocable (acción, consulta, búsqueda de conocimiento, método MCP) | `create_ticket`, `get_order_status`, `search_kb` | +| **Skill** | Un paquete con nombre de tools relacionadas con instrucciones de LLM compartidas | `ticket_management` = create + update + close + escalate | +| **Agent** | Una persona con un rol, prompt de sistema, skills adjuntas y conocimiento | `tier1_support` = empático, verifica identidad, tiene `ticket_management` + `kb_search` | + +## Definir un agente (un archivo) + +```ts +// src/agents/tier1_support.agent.ts +import { defineAgent } from '@objectstack/spec/ai'; + +export const tier1Support = defineAgent({ + name: 'tier1_support', + label: 'First Line Support', + role: 'Help Desk Assistant', + instructions: ` + You are a friendly first-line support agent. + Always verify the user's identity before discussing account specifics. + Escalate to tier 2 if the issue involves billing or security. + `, + skills: ['ticket_management', 'knowledge_search'], + knowledge: { + topics: ['faq', 'policies'], + indexes: ['support_docs'], + }, + model: { provider: 'openai', model: 'gpt-4o', temperature: 0.3 }, + memory: { shortTerm: { maxMessages: 30 } }, +}); +``` + +O en Console: **Console → Agents → New Agent**. + +O — y este es el punto clave — dile al AI Builder: + +> *"Crea un agente de soporte de nivel 1 que gestione la administración de +> tickets y busque en las preguntas frecuentes. Debe verificar la identidad +> antes de hablar de los detalles de la cuenta."* + +## Definir una Skill + +```ts +// src/skills/ticket_management.skill.ts +import { defineSkill } from '@objectstack/spec/ai'; + +export const ticketManagement = defineSkill({ + name: 'ticket_management', + label: 'Ticket Management', + instructions: ` + Always confirm the ticket subject and priority before creating one. + Use 'urgent' priority sparingly — only for outages or security incidents. + `, + tools: [ + 'create_ticket', + 'update_ticket', + 'close_ticket', + 'escalate_ticket', + 'action_*', // wildcard: pick up any future actions on the active object + ], +}); +``` + +Las skills son **la unidad correcta para la reutilización**. Una skill +funciona en muchos agentes. + +## Las tools provienen de tus metadatos declarados + +Cada `*.action.ts` que declaras se materializa automáticamente como una +tool `action_` — sin conexiones por separado. Por lo tanto, si ya has +definido `escalate_ticket` como una Action en el objeto `support_ticket`, +tanto el AI Builder como tus agentes pueden invocarla. Los permisos siguen +aplicándose: el agente invoca la acción **como el usuario**, por lo que el +conjunto de permisos del usuario decide si tiene éxito. + +También puedes exponer: + +| Tipo de tool | Origen | +|---|---| +| **Action** | Cualquier `*.action.ts` en cualquier paquete instalado | +| **Flow** | Cualquier flujo manual (`type: 'manual'`) | +| **Query** | Consultas ObjectQL guardadas (`*.query.ts`) | +| **Knowledge search** | Cualquier índice de conocimiento adjunto al agente | +| **MCP method** | Cualquier cosa expuesta por un servidor MCP adjunto | +| **Built-in metadata tools** | `create_object`, `add_field`, … — pero solo para agentes administradores | + +## Patrón de asistente ambiental + +Si quieres **un solo cuadro de chat para toda la app** (estilo Claude Code / +Agentforce) en lugar de obligar al usuario a elegir un agente, declara un +`defaultAgent` en los metadatos de la App y llama al endpoint de chat +ambiental con el contexto de la app: + +```text +POST /api/v1/ai/chat { context: { appName: 'crm' }, ... } +``` + +Cuando `context.appName` se resuelve a una app que declara un +`defaultAgent`, el runtime selecciona automáticamente ese agente — el +usuario nunca elige de una lista. El panel de IA integrado de Console usa +esto. El runtime resuelve: + +1. El **agente predeterminado** para la app activa (el `defaultAgent` de la + app), o el primer agente al que el usuario tenga acceso. +2. Las **skills activas** — la lista `skills:` del agente cargada desde el + Skill Registry, filtrada por el conjunto de permisos del usuario y el + contexto actual de objeto/registro. +3. El **conocimiento** adjunto al agente. + +No tienes que conectar qué agente se muestra dónde. Declara una app, +configura su `defaultAgent` y aparece. + +## Permisos + +| Capacidad | Permiso | +|---|---| +| Conversar con un agente | `ai:chat` (y acceso a las tools de las skills del agente) | +| Aprobar cambios de metadatos | `ai:approve` | +| Definir / editar agentes y skills | `ai:author` (normalmente Setup Administrator) | +| Leer conversaciones de IA (auditoría) | `ai:read` | + +Las conversaciones tienen alcance por usuario — un usuario no puede ver el +historial de chat de otro a menos que tenga una concesión delegada. + +## Memoria y estado de la conversación + +El bloque `memory` del agente tiene dos niveles: + +| Campo | Qué hace | +|---|---| +| `shortTerm.maxMessages` | Mensajes recientes guardados en la memoria de trabajo (predeterminado `50`) | +| `shortTerm.maxTokens` | Presupuesto opcional de tokens para la ventana de contexto a corto plazo | +| `longTerm.enabled` | Persiste la memoria entre sesiones (predeterminado `false`) | +| `longTerm.store` | Backend para la memoria persistida: `vector` (predeterminado), `database` o `redis` | +| `reflectionInterval` | Reflexiona cada N interacciones para refinar el comportamiento | + +La poda de la ventana de contexto en vivo se rige por la estrategia de +presupuesto de tokens de la conversación — `sliding_window` (predeterminado), +`fifo`, `importance`, `semantic` o `summary`. + +Las filas de conversación viven en `ai_conversations`. Los resultados de las +llamadas a tools y las acciones pendientes hacen referencia cruzada a la +conversación de origen para la auditoría. + +## Observabilidad + +Cada ejecución de un agente emite: + +- eventos `audit:ai:chat` (por turno) +- eventos `audit:ai:tool` (por llamada a tool, con entradas + salidas) +- eventos `audit:ai:pending_action` (cuando se pone en cola una mutación) +- métricas de recuento de tokens (por modelo, por proveedor) en el registro + de auditoría para la facturación interna + +Puedes conectarlas a tu pila de observabilidad habitual — consulta +[Observability](/docs/operate/observability). + +## Nota sobre multi-tenant + +Los agentes son por Environment. El agente `tier1_support` del tenant A +nunca ve los datos, conversaciones ni conocimiento del tenant B — incluso si +distribuyes la misma definición de agente en un paquete del marketplace. + +## A dónde ir después + +- [AI Builder](/docs/build/ai-builder) — el asistente de tiempo de build +- [IDE Skills](/docs/build/ai-skills) — `npx skills add objectstack-ai/framework` para que el agente de tu IDE genere los metadatos correctamente +- [Actions](/docs/build/actions) — declara las tools que usarán tus agentes +- [AI Service](/docs/configure/ai) — configuración de proveedor, embedder y MCP +- [`@objectstack/spec/ai`](https://github.com/objectstack-ai/framework/tree/main/packages/spec/src/ai) — esquemas completos diff --git a/content/docs/build/agents.fr.mdx b/content/docs/build/agents.fr.mdx new file mode 100644 index 0000000..ea9fe13 --- /dev/null +++ b/content/docs/build/agents.fr.mdx @@ -0,0 +1,195 @@ +--- +title: Agents +description: Assistants IA pour utilisateurs finaux — Agent → Skill → Tool — câblés à partir de vos données et de vos actions. +--- + +# Agents + +Les agents sont les assistants IA avec lesquels vos **utilisateurs +finaux** dialoguent — un copilote de service d'assistance, un BDR +commercial, un bot de questions-réponses RH interne. Ils s'appuient sur +les données et les actions que vous avez déjà définies ; vous n'écrivez +pas de nouveau code, vous composez des primitives existantes en une +persona. + +Architecture à trois niveaux, alignée sur Salesforce Agentforce, +Microsoft Copilot Studio et ServiceNow Now Assist : + +```text +Agent ──→ Skill ──→ Tool +(persona) (capability) (callable function) +``` + +| Niveau | Ce que c'est | Exemple | +|---|---|---| +| **Tool** | Une fonction appelable (action, requête, recherche de connaissances, méthode MCP) | `create_ticket`, `get_order_status`, `search_kb` | +| **Skill** | Un ensemble nommé d'outils connexes partageant des instructions LLM communes | `ticket_management` = create + update + close + escalate | +| **Agent** | Une persona dotée d'un rôle, d'un prompt système, de compétences rattachées et de connaissances | `tier1_support` = empathique, vérifie l'identité, possède `ticket_management` + `kb_search` | + +## Définir un agent (un seul fichier) + +```ts +// src/agents/tier1_support.agent.ts +import { defineAgent } from '@objectstack/spec/ai'; + +export const tier1Support = defineAgent({ + name: 'tier1_support', + label: 'First Line Support', + role: 'Help Desk Assistant', + instructions: ` + You are a friendly first-line support agent. + Always verify the user's identity before discussing account specifics. + Escalate to tier 2 if the issue involves billing or security. + `, + skills: ['ticket_management', 'knowledge_search'], + knowledge: { + topics: ['faq', 'policies'], + indexes: ['support_docs'], + }, + model: { provider: 'openai', model: 'gpt-4o', temperature: 0.3 }, + memory: { shortTerm: { maxMessages: 30 } }, +}); +``` + +Ou dans la Console : **Console → Agents → New Agent**. + +Ou — et c'est tout l'intérêt — dites à l'AI Builder : + +> *"Create a tier-1 support agent that handles ticket management and +> searches the FAQ. It should verify identity before discussing +> account details."* + +## Définir une compétence (Skill) + +```ts +// src/skills/ticket_management.skill.ts +import { defineSkill } from '@objectstack/spec/ai'; + +export const ticketManagement = defineSkill({ + name: 'ticket_management', + label: 'Ticket Management', + instructions: ` + Always confirm the ticket subject and priority before creating one. + Use 'urgent' priority sparingly — only for outages or security incidents. + `, + tools: [ + 'create_ticket', + 'update_ticket', + 'close_ticket', + 'escalate_ticket', + 'action_*', // wildcard: pick up any future actions on the active object + ], +}); +``` + +Les compétences sont **la bonne unité de réutilisation**. Une seule +compétence fonctionne avec de nombreux agents. + +## Les outils proviennent de vos métadonnées déclarées + +Chaque `*.action.ts` que vous déclarez se matérialise automatiquement +en un outil `action_` — aucun câblage séparé. Ainsi, si vous avez +déjà défini `escalate_ticket` comme une Action sur l'objet +`support_ticket`, à la fois l'AI Builder et vos agents peuvent +l'appeler. Les permissions continuent de s'appliquer : l'agent appelle +l'action **en tant qu'utilisateur**, c'est donc l'ensemble de +permissions de l'utilisateur qui détermine si elle aboutit. + +Vous pouvez aussi exposer : + +| Type d'outil | Source | +|---|---| +| **Action** | N'importe quel `*.action.ts` dans n'importe quel package installé | +| **Flow** | N'importe quel flow manuel (`type: 'manual'`) | +| **Query** | Requêtes ObjectQL enregistrées (`*.query.ts`) | +| **Knowledge search** | N'importe quel index de connaissances rattaché à l'agent | +| **MCP method** | Tout ce qui est exposé par un serveur MCP rattaché | +| **Built-in metadata tools** | `create_object`, `add_field`, … — mais uniquement pour les agents administrateurs | + +## Modèle d'assistant ambiant + +Si vous souhaitez **une seule zone de chat pour toute l'application** +(à la manière de Claude Code / Agentforce) plutôt que de forcer +l'utilisateur à choisir un agent, déclarez un `defaultAgent` dans les +métadonnées de l'App et appelez le point de terminaison de chat ambiant +avec le contexte de l'application : + +```text +POST /api/v1/ai/chat { context: { appName: 'crm' }, ... } +``` + +Lorsque `context.appName` correspond à une application qui déclare un +`defaultAgent`, le runtime sélectionne automatiquement cet agent — +l'utilisateur ne choisit jamais dans une liste. Le panneau IA intégré +de la Console utilise ce mécanisme. Le runtime résout : + +1. L'**agent par défaut** pour l'application active (le `defaultAgent` + de l'application), ou le premier agent auquel l'utilisateur a accès. +2. Les **compétences actives** — la liste `skills:` de l'agent chargée + depuis le Skill Registry, filtrée par l'ensemble de permissions de + l'utilisateur et par le contexte objet/enregistrement courant. +3. Les **connaissances** rattachées à l'agent. + +Vous n'avez pas à câbler quel agent s'affiche où. Déclarez une +application, définissez son `defaultAgent`, et il apparaît. + +## Permissions + +| Capacité | Permission | +|---|---| +| Dialoguer avec un agent | `ai:chat` (et accès aux outils des compétences de l'agent) | +| Approuver les modifications de métadonnées | `ai:approve` | +| Définir / modifier des agents et des compétences | `ai:author` (généralement Setup Administrator) | +| Lire les conversations IA (audit) | `ai:read` | + +Les conversations sont cantonnées à l'utilisateur — un utilisateur ne +peut pas voir l'historique de chat d'un autre, sauf s'il dispose d'une +autorisation déléguée. + +## Mémoire et état de la conversation + +Le bloc `memory` de l'agent comporte deux niveaux : + +| Champ | Ce qu'il fait | +|---|---| +| `shortTerm.maxMessages` | Messages récents conservés en mémoire de travail (par défaut `50`) | +| `shortTerm.maxTokens` | Budget de tokens facultatif pour la fenêtre de contexte à court terme | +| `longTerm.enabled` | Persister la mémoire entre les sessions (par défaut `false`) | +| `longTerm.store` | Backend pour la mémoire persistée : `vector` (par défaut), `database` ou `redis` | +| `reflectionInterval` | Réfléchir toutes les N interactions pour affiner le comportement | + +L'élagage de la fenêtre de contexte active est régi par la stratégie de +budget de tokens de la conversation — `sliding_window` (par défaut), +`fifo`, `importance`, `semantic` ou `summary`. + +Les lignes de conversation résident dans `ai_conversations`. Les +résultats des appels d'outils et les actions en attente sont +référencés en retour vers la conversation d'origine à des fins d'audit. + +## Observabilité + +Chaque exécution d'agent émet : + +- des événements `audit:ai:chat` (par tour) +- des événements `audit:ai:tool` (par appel d'outil, avec entrées + sorties) +- des événements `audit:ai:pending_action` (lorsqu'une mutation est mise en file d'attente) +- des métriques de comptage de tokens (par modèle, par fournisseur) dans + le journal d'audit pour la refacturation + +Vous pouvez intégrer ces données à votre pile d'observabilité +habituelle — voir [Observability](/docs/operate/observability). + +## Note multi-tenant + +Les agents sont propres à chaque environnement. L'agent `tier1_support` +du tenant A ne voit jamais les données, les conversations ni les +connaissances du tenant B — même si vous livrez la même définition +d'agent dans un package du marketplace. + +## Pour aller plus loin + +- [AI Builder](/docs/build/ai-builder) — l'assistant au moment du build +- [IDE Skills](/docs/build/ai-skills) — `npx skills add objectstack-ai/framework` pour que votre agent d'IDE rédige correctement les métadonnées +- [Actions](/docs/build/actions) — déclarez les outils que vos agents utiliseront +- [AI Service](/docs/configure/ai) — configuration du fournisseur, de l'embedder et de MCP +- [`@objectstack/spec/ai`](https://github.com/objectstack-ai/framework/tree/main/packages/spec/src/ai) — schémas complets diff --git a/content/docs/build/agents.ja.mdx b/content/docs/build/agents.ja.mdx new file mode 100644 index 0000000..6aaeccc --- /dev/null +++ b/content/docs/build/agents.ja.mdx @@ -0,0 +1,186 @@ +--- +title: エージェント +description: エンドユーザー向けの AI アシスタント — Agent → Skill → Tool — あなたのデータとアクションから組み立てます。 +--- + +# エージェント + +エージェントは、**エンドユーザー**が対話する AI アシスタントです — ヘルプ +デスクの副操縦士、営業の BDR、社内向け HR Q&A ボットなど。これらは、 +すでに定義済みのデータとアクションの上に構築されます。新しいコードを書く +必要はなく、既存のプリミティブを組み合わせて 1 つのペルソナを作り上げます。 + +Salesforce Agentforce、Microsoft Copilot Studio、ServiceNow Now Assist +と整合する 3 階層アーキテクチャ: + +```text +Agent ──→ Skill ──→ Tool +(persona) (capability) (callable function) +``` + +| 階層 | 概要 | 例 | +|---|---|---| +| **Tool** | 1 つの呼び出し可能な関数(アクション、クエリ、ナレッジ検索、MCP メソッド) | `create_ticket`, `get_order_status`, `search_kb` | +| **Skill** | 共有 LLM 指示を持つ、関連するツールの名前付きバンドル | `ticket_management` = create + update + close + escalate | +| **Agent** | ロール、システムプロンプト、付属スキル、ナレッジを備えたペルソナ | `tier1_support` = 共感的、本人確認を行い、`ticket_management` + `kb_search` を持つ | + +## エージェントを定義する(1 ファイル) + +```ts +// src/agents/tier1_support.agent.ts +import { defineAgent } from '@objectstack/spec/ai'; + +export const tier1Support = defineAgent({ + name: 'tier1_support', + label: 'First Line Support', + role: 'Help Desk Assistant', + instructions: ` + You are a friendly first-line support agent. + Always verify the user's identity before discussing account specifics. + Escalate to tier 2 if the issue involves billing or security. + `, + skills: ['ticket_management', 'knowledge_search'], + knowledge: { + topics: ['faq', 'policies'], + indexes: ['support_docs'], + }, + model: { provider: 'openai', model: 'gpt-4o', temperature: 0.3 }, + memory: { shortTerm: { maxMessages: 30 } }, +}); +``` + +または Console から: **Console → Agents → New Agent**。 + +あるいは — そしてこれが本質ですが — AI Builder にこう伝えます: + +> *「チケット管理を扱い、FAQ を検索する tier-1 サポートエージェントを作成して。 +> アカウントの詳細を話す前に本人確認を行うようにして。」* + +## スキルを定義する + +```ts +// src/skills/ticket_management.skill.ts +import { defineSkill } from '@objectstack/spec/ai'; + +export const ticketManagement = defineSkill({ + name: 'ticket_management', + label: 'Ticket Management', + instructions: ` + Always confirm the ticket subject and priority before creating one. + Use 'urgent' priority sparingly — only for outages or security incidents. + `, + tools: [ + 'create_ticket', + 'update_ticket', + 'close_ticket', + 'escalate_ticket', + 'action_*', // wildcard: pick up any future actions on the active object + ], +}); +``` + +スキルは**再利用に適した単位**です。1 つのスキルは多くのエージェントにまたがって +機能します。 + +## ツールは宣言したメタデータから生成される + +宣言したすべての `*.action.ts` は、自動的に `action_` ツールとして +具現化されます — 個別の配線は不要です。したがって、`support_ticket` オブジェクト +上のアクションとして `escalate_ticket` をすでに定義していれば、AI Builder と +あなたのエージェントの両方がそれを呼び出せます。権限は引き続き適用されます。 +エージェントは**ユーザーとして**アクションを呼び出すため、それが成功するかどうかは +ユーザーの権限セットが決定します。 + +次のものも公開できます: + +| ツールの種類 | ソース | +|---|---| +| **Action** | インストール済みパッケージ内の任意の `*.action.ts` | +| **Flow** | 任意の手動フロー(`type: 'manual'`) | +| **Query** | 保存済みの ObjectQL クエリ(`*.query.ts`) | +| **Knowledge search** | エージェントに付属する任意のナレッジインデックス | +| **MCP method** | 付属の MCP サーバーが公開する任意のもの | +| **組み込みメタデータツール** | `create_object`, `add_field`, … — ただし管理者エージェントのみ | + +## アンビエントアシスタントパターン + +ユーザーにエージェントを選ばせる代わりに、**アプリ全体で 1 つのチャットボックス** +(Claude Code / Agentforce スタイル)を使いたい場合は、App メタデータに +`defaultAgent` を宣言し、アプリのコンテキストとともにアンビエントチャット +エンドポイントを呼び出します: + +```text +POST /api/v1/ai/chat { context: { appName: 'crm' }, ... } +``` + +`context.appName` が `defaultAgent` を宣言するアプリに解決されると、ランタイムは +そのエージェントを自動選択します — ユーザーがリストから選ぶことはありません。 +Console の組み込み AI パネルはこれを使用しています。ランタイムは次を解決します: + +1. アクティブなアプリの**デフォルトエージェント**(アプリの `defaultAgent`)、 + またはユーザーがアクセスできる最初のエージェント。 +2. **アクティブなスキル** — Skill Registry から読み込まれたエージェントの + `skills:` リストで、ユーザーの権限セットと現在のオブジェクト/レコードの + コンテキストでフィルタリングされたもの。 +3. エージェントに付属する**ナレッジ**。 + +どのエージェントをどこに表示するかを配線する必要はありません。アプリを宣言し、 +その `defaultAgent` を設定すれば、表示されます。 + +## 権限 + +| 機能 | 権限 | +|---|---| +| エージェントとチャットする | `ai:chat`(およびエージェントのスキルのツールへのアクセス) | +| メタデータの変更を承認する | `ai:approve` | +| エージェントとスキルを定義/編集する | `ai:author`(通常は Setup Administrator) | +| AI 会話を読む(監査) | `ai:read` | + +会話はユーザー単位にスコープされます — あるユーザーは、委任された付与がない限り、 +別のユーザーのチャット履歴を見ることはできません。 + +## メモリと会話の状態 + +エージェントの `memory` ブロックには 2 つの階層があります: + +| フィールド | 役割 | +|---|---| +| `shortTerm.maxMessages` | ワーキングメモリに保持する直近のメッセージ数(デフォルト `50`) | +| `shortTerm.maxTokens` | 短期コンテキストウィンドウの任意のトークン予算 | +| `longTerm.enabled` | セッションをまたいでメモリを永続化する(デフォルト `false`) | +| `longTerm.store` | 永続メモリのバックエンド: `vector`(デフォルト)、`database`、または `redis` | +| `reflectionInterval` | N 回のインタラクションごとに振り返り、挙動を改善する | + +ライブコンテキストウィンドウのプルーニングは、会話のトークン予算戦略によって +管理されます — `sliding_window`(デフォルト)、`fifo`、`importance`、`semantic`、 +または `summary`。 + +会話の行は `ai_conversations` に存在します。ツール呼び出しの結果と保留中の +アクションは、監査のために発生元の会話への相互参照を保持します。 + +## オブザーバビリティ + +すべてのエージェント実行は次を発行します: + +- `audit:ai:chat` イベント(ターンごと) +- `audit:ai:tool` イベント(ツール呼び出しごと、入力 + 出力付き) +- `audit:ai:pending_action` イベント(ミューテーションがキューに入ったとき) +- トークン数のメトリクス(モデルごと、プロバイダーごと)をチャージバックのために + 監査ログへ + +これらは通常のオブザーバビリティスタックに配線できます — +[Observability](/docs/operate/observability) を参照してください。 + +## マルチテナントに関する注意 + +エージェントは Environment 単位です。テナント A の `tier1_support` エージェントは、 +marketplace パッケージで同じエージェント定義を出荷していても、テナント B の +データ、会話、ナレッジを決して見ることはありません。 + +## 次に進む先 + +- [AI Builder](/docs/build/ai-builder) — ビルド時のアシスタント +- [IDE Skills](/docs/build/ai-skills) — `npx skills add objectstack-ai/framework` で、IDE エージェントがメタデータを正しく作成できるようにします +- [Actions](/docs/build/actions) — エージェントが使用するツールを宣言します +- [AI Service](/docs/configure/ai) — プロバイダー、エンベッダー、MCP のセットアップ +- [`@objectstack/spec/ai`](https://github.com/objectstack-ai/framework/tree/main/packages/spec/src/ai) — 完全なスキーマ diff --git a/content/docs/build/agents.mdx b/content/docs/build/agents.mdx index 20793a8..17232d1 100644 --- a/content/docs/build/agents.mdx +++ b/content/docs/build/agents.mdx @@ -11,7 +11,7 @@ the data and actions you've already defined; you don't write new code, you compose existing primitives into a persona. Three-tier architecture, aligned with Salesforce Agentforce, Microsoft -Copilot Console, and ServiceNow Now Assist: +Copilot Studio, and ServiceNow Now Assist: ```text Agent ──→ Skill ──→ Tool @@ -44,8 +44,8 @@ export const tier1Support = defineAgent({ topics: ['faq', 'policies'], indexes: ['support_docs'], }, - model: 'smart', // resolved against the AI service's model map - memory: { strategy: 'rolling', maxMessages: 30 }, + model: { provider: 'openai', model: 'gpt-4o', temperature: 0.3 }, + memory: { shortTerm: { maxMessages: 30 } }, }); ``` @@ -106,25 +106,28 @@ You can also expose: ## Ambient assistant pattern If you want **one chat box for the whole app** (Claude Code / -Agentforce style) instead of forcing the user to pick an agent, use -the assistant endpoints: +Agentforce style) instead of forcing the user to pick an agent, +declare a `defaultAgent` on the App metadata and call the ambient +chat endpoint with the app context: ```text -GET /api/v1/ai/assistant resolve the default agent for the current context -GET /api/v1/ai/assistant/skills list skills active for the current context -POST /api/v1/ai/assistant/chat send a message — the LLM picks the tool +POST /api/v1/ai/chat { context: { appName: 'crm' }, ... } ``` -Console's built-in AI panel uses these. The runtime resolves: +When `context.appName` resolves to an app that declares a +`defaultAgent`, the runtime auto-selects that agent — the user never +picks from a list. Console's built-in AI panel uses this. The runtime +resolves: -1. The **default agent** for the active app (declared on the App - metadata), or the first agent the user has access to. -2. The **active skills** — filtered by user permission set, current - object/record context, and the agent's `skills:` list. +1. The **default agent** for the active app (the app's `defaultAgent`), + or the first agent the user has access to. +2. The **active skills** — the agent's `skills:` list loaded from the + Skill Registry, filtered by user permission set and the current + object/record context. 3. The **knowledge** attached to the agent. -You don't have to wire which agent is shown where. Declare an app, -mark one of its agents as default, and it appears. +You don't have to wire which agent is shown where. Declare an app, set +its `defaultAgent`, and it appears. ## Permissions @@ -140,14 +143,21 @@ chat history unless they have a delegated grant. ## Memory and conversation state -| Strategy | What it does | +The agent's `memory` block has two tiers: + +| Field | What it does | |---|---| -| `rolling` (default) | Keep last N messages in the prompt | -| `summary` | Summarize older turns into a system note | -| `none` | Stateless — every turn starts fresh | -| `custom` | Provide your own memory plugin | +| `shortTerm.maxMessages` | Recent messages kept in working memory (default `50`) | +| `shortTerm.maxTokens` | Optional token budget for the short-term context window | +| `longTerm.enabled` | Persist memory across sessions (default `false`) | +| `longTerm.store` | Backend for persisted memory: `vector` (default), `database`, or `redis` | +| `reflectionInterval` | Reflect every N interactions to refine behavior | + +Pruning of the live context window is governed by the conversation's +token-budget strategy — `sliding_window` (default), `fifo`, +`importance`, `semantic`, or `summary`. -Conversation rows live in `sys_ai_conversation`. Tool-call results +Conversation rows live in `ai_conversations`. Tool-call results and pending actions cross-reference back to the originating conversation for audit. diff --git a/content/docs/build/agents.zh-Hans.mdx b/content/docs/build/agents.zh-Hans.mdx new file mode 100644 index 0000000..62588d1 --- /dev/null +++ b/content/docs/build/agents.zh-Hans.mdx @@ -0,0 +1,158 @@ +--- +title: Agents +description: 面向终端用户的 AI 助手 —— Agent → Skill → Tool —— 由你的数据和操作连接而成。 +--- + +# Agents + +Agents 是供你的**终端用户**对话的 AI 助手 —— 服务台副驾、销售 BDR、内部 HR 问答机器人。它们构建在你已经定义好的数据和操作之上;你无需编写新代码,只需将现有的基本要素组合成一个角色。 + +三层架构,与 Salesforce Agentforce、Microsoft Copilot Studio 和 ServiceNow Now Assist 保持一致: + +```text +Agent ──→ Skill ──→ Tool +(persona) (capability) (callable function) +``` + +| 层级 | 它是什么 | 示例 | +|---|---|---| +| **Tool** | 单个可调用函数(操作、查询、知识搜索、MCP 方法) | `create_ticket`、`get_order_status`、`search_kb` | +| **Skill** | 一组相关 tool 的命名集合,带有共享的 LLM 指令 | `ticket_management` = create + update + close + escalate | +| **Agent** | 一个角色,具有职责、系统提示、所附 skill 和知识 | `tier1_support` = 富有同理心、会验证身份、拥有 `ticket_management` + `kb_search` | + +## 定义一个 Agent(单个文件) + +```ts +// src/agents/tier1_support.agent.ts +import { defineAgent } from '@objectstack/spec/ai'; + +export const tier1Support = defineAgent({ + name: 'tier1_support', + label: 'First Line Support', + role: 'Help Desk Assistant', + instructions: ` + You are a friendly first-line support agent. + Always verify the user's identity before discussing account specifics. + Escalate to tier 2 if the issue involves billing or security. + `, + skills: ['ticket_management', 'knowledge_search'], + knowledge: { + topics: ['faq', 'policies'], + indexes: ['support_docs'], + }, + model: { provider: 'openai', model: 'gpt-4o', temperature: 0.3 }, + memory: { shortTerm: { maxMessages: 30 } }, +}); +``` + +或者在 Console 中:**Console → Agents → New Agent**。 + +又或者 —— 这才是重点 —— 对 AI Builder 说: + +> *"创建一个一线支持 agent,处理工单管理并搜索 FAQ。在讨论账户细节之前,它应当先验证身份。"* + +## 定义一个 Skill + +```ts +// src/skills/ticket_management.skill.ts +import { defineSkill } from '@objectstack/spec/ai'; + +export const ticketManagement = defineSkill({ + name: 'ticket_management', + label: 'Ticket Management', + instructions: ` + Always confirm the ticket subject and priority before creating one. + Use 'urgent' priority sparingly — only for outages or security incidents. + `, + tools: [ + 'create_ticket', + 'update_ticket', + 'close_ticket', + 'escalate_ticket', + 'action_*', // wildcard: pick up any future actions on the active object + ], +}); +``` + +Skill 是**最适合复用的单元**。一个 skill 可以服务多个 agent。 + +## Tool 来自你声明的元数据 + +你声明的每个 `*.action.ts` 都会自动具现为一个 `action_` tool —— 无需另外连接。因此,如果你已经在 `support_ticket` 对象上将 `escalate_ticket` 定义为一个 Action,那么 AI Builder 和你的 Agents 都能调用它。权限仍然生效:agent **以用户身份**调用该操作,因此能否成功由该用户的权限集决定。 + +你还可以暴露: + +| Tool 类型 | 来源 | +|---|---| +| **Action** | 已安装的任何包中的任意 `*.action.ts` | +| **Flow** | 任意手动 flow(`type: 'manual'`) | +| **Query** | 已保存的 ObjectQL 查询(`*.query.ts`) | +| **Knowledge search** | 附加到 agent 的任意知识索引 | +| **MCP method** | 接入的 MCP 服务器所暴露的任意内容 | +| **内置元数据 tool** | `create_object`、`add_field`…… —— 但仅对管理员 agent 开放 | + +## 环境助手模式 + +如果你想要**整个应用只有一个聊天框**(Claude Code / Agentforce 风格),而不是强迫用户去挑选某个 agent,那就在 App 元数据上声明一个 `defaultAgent`,并带上 app 上下文调用环境聊天端点: + +```text +POST /api/v1/ai/chat { context: { appName: 'crm' }, ... } +``` + +当 `context.appName` 解析到一个声明了 `defaultAgent` 的 app 时,运行时会自动选择该 agent —— 用户永远无需从列表中挑选。Console 内置的 AI 面板正是这样工作的。运行时会解析: + +1. 当前 app 的**默认 agent**(即 app 的 `defaultAgent`),或用户有权访问的第一个 agent。 +2. **激活的 skill** —— 从 Skill Registry 加载的 agent `skills:` 列表,并按用户权限集以及当前对象/记录上下文进行过滤。 +3. 附加到该 agent 的**知识**。 + +你不必去连接哪个 agent 显示在哪里。声明一个 app,设置它的 `defaultAgent`,它便会出现。 + +## 权限 + +| 能力 | 权限 | +|---|---| +| 与 agent 对话 | `ai:chat`(以及对该 agent 各 skill 所含 tool 的访问权) | +| 审批元数据变更 | `ai:approve` | +| 定义 / 编辑 agent 和 skill | `ai:author`(通常是 Setup Administrator) | +| 读取 AI 对话(审计) | `ai:read` | + +对话以用户为范围 —— 除非有委派授权,否则一个用户无法看到另一个用户的聊天记录。 + +## 记忆与会话状态 + +agent 的 `memory` 块有两个层级: + +| 字段 | 作用 | +|---|---| +| `shortTerm.maxMessages` | 保留在工作记忆中的近期消息数(默认 `50`) | +| `shortTerm.maxTokens` | 短期上下文窗口的可选 token 预算 | +| `longTerm.enabled` | 跨会话持久化记忆(默认 `false`) | +| `longTerm.store` | 持久化记忆的后端:`vector`(默认)、`database` 或 `redis` | +| `reflectionInterval` | 每 N 次交互反思一次,以优化行为 | + +实时上下文窗口的裁剪由会话的 token 预算策略决定 —— `sliding_window`(默认)、`fifo`、`importance`、`semantic` 或 `summary`。 + +会话记录存于 `ai_conversations`。Tool 调用结果与待执行的操作都会反向引用其原始会话以便审计。 + +## 可观测性 + +每次 agent 运行都会发出: + +- `audit:ai:chat` 事件(每轮一条) +- `audit:ai:tool` 事件(每次 tool 调用,含输入 + 输出) +- `audit:ai:pending_action` 事件(变更入队时) +- token 计数指标(按模型、按 provider)进入审计日志,用于成本分摊 + +你可以把这些接入你常用的可观测性技术栈 —— 见 [Observability](/docs/operate/observability)。 + +## 多租户说明 + +Agents 是按 Environment 划分的。租户 A 的 `tier1_support` agent 永远看不到租户 B 的数据、对话或知识 —— 即便你在某个 marketplace 包里分发的是同一份 agent 定义。 + +## 下一步去哪里 + +- [AI Builder](/docs/build/ai-builder) —— 构建期助手 +- [IDE Skills](/docs/build/ai-skills) —— `npx skills add objectstack-ai/framework`,让你的 IDE agent 正确地编写元数据 +- [Actions](/docs/build/actions) —— 声明你的 agent 将使用的 tool +- [AI Service](/docs/configure/ai) —— provider、embedder、MCP 设置 +- [`@objectstack/spec/ai`](https://github.com/objectstack-ai/framework/tree/main/packages/spec/src/ai) —— 完整 schema diff --git a/content/docs/build/ai-builder.cn.mdx b/content/docs/build/ai-builder.cn.mdx deleted file mode 100644 index 44b02d1..0000000 --- a/content/docs/build/ai-builder.cn.mdx +++ /dev/null @@ -1,150 +0,0 @@ ---- -title: AI Builder -description: Console 内的对话,把自然语言需求变成运行中的元数据。 ---- - -# AI Builder - -AI Builder 是**客户扩展 ObjectOS 的主要方式**。打开 Console,用自然语言跟助手对话,它为你构建元数据 —— 包、对象、字段、Action、流程。每次变更先进入 Human-in-the-Loop (HITL) 审批队列,然后才上线。 - -## 30 秒试一下 - -``` -你:我需要跟踪客户支持工单。 - 每个工单有主题、描述、优先级(low/medium/high/urgent)、 - 状态(new/open/pending/resolved/closed)和负责人。 - -AI:我会为你创建。这是计划: - • 创建包 `com.you.support` (v0.1.0) - • 创建对象 `support_ticket`,含 5 个字段 - • 添加按状态分组的看板视图 - • 添加 3 个权限集:agent、manager、viewer - - 批准?[是] [修改] [取消] - -你:[是] - -AI:✓ 包已创建 - ✓ 对象已创建,含 5 字段、12 个索引 - ✓ 看板视图已注册 - ✓ 权限集已创建 - 完成。试试看:/support_ticket -``` - -你现在拥有一个能跑的工单应用 —— REST 端点、Console 视图、审计日志条目、权限检查点,全都有。没编辑任何文件;没有重启。 - -## AI 能做什么 - -助手可访问 **11 个内置元数据工具**,全部带命名空间、并通过 `@objectstack/spec` 校验: - -| 类别 | 工具 | 作用 | -|---|---|---| -| **包** | `create_package` | 新建容器,附带 manifest + 版本 | -| | `list_packages` | 浏览现有包 | -| | `get_package` / `get_active_package` | 查看内容 | -| | `set_active_package` | 选择本次对话的工作包 | -| **对象** | `create_object` | 新建对象及初始字段 | -| | `list_objects` | 浏览活动包内的对象 | -| | `describe_object` | 打印 schema、字段、关系 | -| **字段** | `add_field` | 添加类型化字段(支持 25 种类型) | -| | `modify_field` | 修改标签、下拉选项、校验 | -| | `delete_field` | 删除字段(带安全检查) | -| **数据** | `query_data` | 通过 ObjectQL 读取记录 | -| **Action / 知识** | `*_action`、`search_knowledge` | 调用 Action、对文档做 RAG | - -加上从每个声明的 `*.action.ts` 实化出来的 Action 工具 —— 命名为 `action_<名称>` —— 一旦 Action 在包里存在,AI 就能像调用任何内置工具一样调用它。 - -运行时查看完整工具目录:`GET /api/v1/ai/tools`。 - -## Human-in-the-Loop 审批 - -**修改元数据的**工具调用会路由进待审批队列。审批操作员看到改动 diff 后再点击*批准*。 - -| 端点 | 用途 | -|---|---| -| `GET /api/v1/ai/pending-actions` | 列出排队中的 Action(可按状态过滤) | -| `GET /api/v1/ai/pending-actions/:id` | 单条提议变更的 diff | -| `POST /api/v1/ai/pending-actions/:id/approve` | 应用变更 | -| `POST /api/v1/ai/pending-actions/:id/reject` | 带理由丢弃 | - -所需权限: - -| 操作 | 权限 | -|---|---| -| 读取队列 | `ai:read` | -| 批准 / 拒绝 | `ai:approve` | - -默认只有 **Setup Administrator** 成员拥有 `ai:approve`。可在 [Permission Sets](/docs/configure/permissions/permission-sets) 中拆得更细 —— 例如"产品负责人可批准 `com.acme.crm`,其他人不行"。 - -队列可审计:每次批准/拒绝都会落到 `sys_audit_log`,带上发起对话的 id。 - -## 对话与上下文 - -每次聊天是一条 `sys_ai_conversation` 记录。平台跟踪: - -- **活动包** —— 由 `set_active_package` 设置。新对象/字段在这里落地。 -- **Skills** —— 当前上下文可用的工具切片(例如在 `support_ticket` 详情页内,AI 可能开启 `support_ticket` 范围的 Skill)。 -- **知识** —— 绑定在对话上的 RAG 主题 + 索引。 - -```text -POST /api/v1/ai/assistant/chat -{ - "messages": [{ "role": "user", "content": "Add a tags field to support_ticket" }], - "context": { "objectName": "support_ticket", "recordId": "tkt_123" } -} -``` - -平台为当前应用解析默认 Agent,按上下文过滤 Skill 集合,让 LLM 自己挑工具调用。你不需要把 Agent 预先接到特定 UI —— Agent 会基于元数据自动附着。 - -## 你可以这样问 - -经过验证的模式,附带一句话提示词: - -| 目标 | 提示词 | -|---|---| -| 新对象 | *"创建 `product` 对象,含 name、sku、price、category。"* | -| 加字段 | *"在 `order` 上加一个 `discount` 小数字段,最大 50。"* | -| 修改下拉 | *"在 `task.status` 上,把 'blocked' 加到 'open' 和 'done' 之间。"* | -| 索引 | *"为仪表盘按 status + created_at 给 `order` 加索引。"* | -| 关系 | *"把 `order_line` 设为 `order` 的主从关系。"* | -| 校验 | *"在 `invoice` 上,折扣不能超过小计金额。"* | -| 流程 | *"高优先级工单在 'new' 停留 30 分钟时,通知经理。"* | -| Action | *"创建一个 `approve_invoice` Action,把状态设为已批准。"* | -| 权限集 | *"创建 `agent` 权限集,对 support_ticket 读/建/改,对 customer 仅读。"* | -| 翻译 | *"把 support_ticket 的标签和下拉选项翻译成西班牙语。"* | - -如果 AI 做不到,它会直说 —— 并指向手动路径(通常是一个 30 行的 `*.ts` 文件或一个 Console 表单)。 - -## 实时预览 - -每次批准后,Console 就地重渲染受影响的视图。无需重载。内核缓存使被改的包失效;后续请求用新元数据。 - -## 回滚 - -待审批 Action 记录保留了**变更前状态**。如果一次改动出问题,拒绝任何在途条目,然后让 AI: - -``` -你:把 support_ticket 最后 3 次改动回滚。 -AI:找到来自对话 conv_abc 的 3 次变更(3 分钟前)。 - 将 'support_ticket' 恢复到 13:42:11 的状态。 - 批准?[是] -``` - -需要更大规模回滚时,用 [`os diff`](/docs/reference/cli) 对比你上一个已知良好的产物,并应用反向 diff。 - -## 当下的限制 - -- **助手对客户数据默认是只读的。**它能查询记录,但不能插入/更新/删除,除非赋予 `ai:write_data` 权限。多数客户保持关闭。 -- **跨包变更需要显式确认。**让 AI 修改系统包(`sys_*`)会返回拒绝消息 —— 平台原则上拒绝。 -- **长时间多步计划**(比如"从零搭一个完整 HR 应用")能跑,但更建议拆成一系列较小的对话,每次落地一两个对象。 - -## 超越构建期 AI - -同一套 AI 管道也驱动面向终端用户的**运行时 Agent** —— 支持助理、销售副驾、内部问答机器人 —— 建在同样的 Agent → Skill → Tool 架构上。见 [Agents](/docs/build/agents)。 - -## 下一步 - -- [Agents](/docs/build/agents) —— 建在你数据之上的终端用户助手 -- [Data Model](/docs/build/data-model) —— AI 实际在生成什么 -- [Actions](/docs/build/actions) —— AI 以运行时工具暴露的单元 -- [AI Service](/docs/configure/ai) —— Provider 配置(OpenAI / Anthropic / Doubao / …) diff --git a/content/docs/build/ai-builder.de.mdx b/content/docs/build/ai-builder.de.mdx new file mode 100644 index 0000000..fb9184f --- /dev/null +++ b/content/docs/build/ai-builder.de.mdx @@ -0,0 +1,185 @@ +--- +title: AI Builder +description: Der Chat in der Console, der Anforderungen in einfacher Sprache in laufende Metadaten verwandelt. +--- + +# AI Builder + +Der AI Builder ist die **primäre Methode, mit der Kunden ObjectOS erweitern**. Öffne +die Console, sprich mit dem Assistenten in einfacher Sprache, und er erstellt die +Metadaten für dich — Pakete, Objekte, Felder, Aktionen, Flows. Jede +Änderung wird in einer Human-in-the-Loop (HITL) Genehmigungsliste eingereiht, bevor sie +live geht. + +## Probiere es in 30 Sekunden + +``` +You: I need to track customer support tickets. + Each ticket has a subject, description, priority (low/medium/high/urgent), + status (new/open/pending/resolved/closed), and assignee. + +AI: I'll create that for you. Here's the plan: + • Create package `com.you.support` (v0.1.0) + • Create object `support_ticket` with 5 fields + • Add a kanban view grouped by status + • Add 3 permission sets: agent, manager, viewer + + Approve? [Yes] [Modify] [Cancel] + +You: [Yes] + +AI: ✓ Package created + ✓ Object created with 5 fields and 12 indexes + ✓ Kanban view registered + ✓ Permission sets created + Done. Try it: /support_ticket +``` + +Du hast jetzt eine funktionierende Ticketing-App — REST-Endpunkte, Console-Ansichten, +Audit-Log-Einträge, Berechtigungskontrollen, alles inklusive. Es wurde keine Datei +bearbeitet; es fand kein Neustart statt. + +## Was die AI kann + +Der Assistent hat Zugriff auf eine Reihe **integrierter Metadaten-Tools**, die alle +mit Namespace versehen und gegen `@objectstack/spec` validiert sind: + +| Kategorie | Tool | Was es tut | +|---|---|---| +| **Pakete** | `create_package` | Neuer Container mit Manifest + Version | +| | `list_packages` | Vorhandene Pakete durchsuchen | +| | `get_package` / `get_active_package` | Inhalte inspizieren | +| | `set_active_package` | Das Arbeitspaket für die Konversation auswählen | +| **Objekte** | `create_object` | Neues Objekt mit anfänglichen Feldern | +| | `list_objects` | Objekte im aktiven Paket durchsuchen | +| | `describe_object` | Schema, Felder, Beziehungen ausgeben | +| **Felder** | `add_field` | Ein typisiertes Feld hinzufügen (gängige [Feldtypen](/docs/reference/field-types)) | +| | `modify_field` | Label, Picklist-Optionen, Validierung ändern | +| | `delete_field` | Ein Feld entfernen (mit Sicherheitsprüfung) | +| **Daten** | `query_data` | Datensätze über ObjectQL lesen | +| **Aktionen / Wissen** | `action_`, `search_knowledge` | Aktionen aufrufen, RAG über Dokumente | + +Hinzu kommen Action-Tools, die aus jedem deklarierten `*.action.ts` materialisiert werden — +benannt `action_` — sodass die AI eine Aktion, sobald sie im Paket existiert, +wie jedes integrierte Tool aufrufen kann. + +Den vollständigen Tool-Katalog zur Laufzeit ansehen: `GET /api/v1/ai/tools`. + +## Human-in-the-Loop Genehmigung + +Tool-Aufrufe, die **Metadaten verändern**, werden über eine Warteschlange für +ausstehende Aktionen geleitet. Genehmigende Operatoren sehen den vorgeschlagenen Änderungs-Diff, +bevor sie auf *Genehmigen* klicken. + +| Endpunkt | Zweck | +|---|---| +| `GET /api/v1/ai/pending-actions` | Eingereihte Aktionen auflisten (nach Status filtern) | +| `GET /api/v1/ai/pending-actions/:id` | Diff für eine einzelne vorgeschlagene Aktion | +| `POST /api/v1/ai/pending-actions/:id/approve` | Die Änderung anwenden | +| `POST /api/v1/ai/pending-actions/:id/reject` | Mit Begründung verwerfen | + +Erforderliche Berechtigungen: + +| Aktion | Berechtigung | +|---|---| +| Warteschlange lesen | `ai:read` | +| Genehmigen / ablehnen | `ai:approve` | + +Standard: Nur Mitglieder von **Setup Administrator** haben `ai:approve`. +Du kannst feiner unterteilen in [Permission Sets](/docs/configure/permissions/permission-sets) — z. B. +„Product Owner können in `com.acme.crm` genehmigen, sonst niemand.“ + +Die Warteschlange ist auditierbar: Jede Genehmigung/Ablehnung landet in +`sys_audit_log` mit der ID der ursprünglichen Konversation. + +## Konversationen und Kontext + +Jeder Chat ist ein `ai_conversations`-Datensatz. Die Plattform verfolgt: + +- **Aktives Paket** — gesetzt durch `set_active_package`. Neue Objekte / + Felder landen hier. +- **Skills** — der Ausschnitt der Tools, die für den aktuellen Kontext verfügbar sind + (z. B. innerhalb der `support_ticket`-Detailseite kann die AI + `support_ticket`-bezogene Skills aktiviert haben). +- **Wissen** — RAG-Themen + Indizes, die der Konversation angehängt sind. + +```text +POST /api/v1/ai/assistant/chat +{ + "messages": [{ "role": "user", "content": "Add a tags field to support_ticket" }], + "context": { "objectName": "support_ticket", "recordId": "tkt_123" } +} +``` + +Die Plattform ermittelt den Standard-Agent für die aktive Anwendung, +filtert die Skill-Menge nach Kontext und lässt das LLM auswählen, welches Tool +aufgerufen werden soll. Du verdrahtest Agents nicht vorab fest in bestimmte UIs — der Agent hängt +sich basierend auf den Metadaten selbst an. + +## Was du anfragen kannst + +Verifizierte Muster, mit Einzeiler-Prompts: + +| Ziel | Prompt | +|---|---| +| Neues Objekt | *„Erstelle ein `product`-Objekt mit name, sku, price, category.“* | +| Feld hinzufügen | *„Füge `order` ein `discount` Dezimalfeld hinzu, max 50.“* | +| Picklist ändern | *„Füge bei `task.status` 'blocked' zwischen 'open' und 'done' ein.“* | +| Index | *„Indiziere `order` nach status + created_at für das Dashboard.“* | +| Beziehung | *„Mache `order_line` zu Master-Detail von `order`.“* | +| Validierung | *„Bei `invoice` darf der Rabatt die Zwischensumme nicht überschreiten.“* | +| Flow | *„Wenn ein Ticket mit hoher Priorität 30 Minuten in 'new' verbleibt, benachrichtige den Manager.“* | +| Aktion | *„Erstelle eine Aktion `approve_invoice`, die den Status auf approved setzt.“* | +| Permission Set | *„Erstelle ein `agent` Permission Set mit read/create/edit auf support_ticket und read auf customer.“* | +| Übersetzung | *„Übersetze die support_ticket-Labels und Picklists ins Spanische.“* | + +Wenn die AI etwas nicht kann, sagt sie es — und verweist dich auf den manuellen Weg +(meist eine 30-zeilige `*.ts`-Datei oder ein Console-Formular). + +## Live-Vorschau + +Nach jeder genehmigten Änderung rendert die Console die betroffenen Ansichten an +Ort und Stelle neu. Kein Neuladen erforderlich. Der Kernel-Cache invalidiert das berührte +Paket; nachfolgende Anfragen verwenden die neuen Metadaten. + +## Zurückrollen + +Datensätze ausstehender Aktionen behalten den **Vorher-Zustand**. Wenn eine Änderung +schiefgeht, lehne alle laufenden Elemente ab und frage die AI: + +``` +You: Roll back the last 3 changes to support_ticket. +AI: Found 3 mutations from conversation conv_abc (3 minutes ago). + Restoring 'support_ticket' to its state at 13:42:11. + Approve? [Yes] +``` + +Für größere Rollbacks verwende [`os diff`](/docs/reference/cli) gegen +dein letztes als funktionierend bekanntes Artefakt und wende den umgekehrten Diff an. + +## Einschränkungen (heute) + +- **Der Datenzugriff folgt den eigenen Berechtigungen des Operators.** Der + Assistent läuft als der angemeldete Benutzer, sodass er nur Datensätze lesen oder schreiben + kann, die dieser Benutzer bereits bearbeiten darf. Die meisten Teams halten den + Assistenten auf Metadaten fokussiert und lassen ihn Kundendaten abfragen — nicht + verändern. +- **Paketübergreifende Mutationen erfordern eine ausdrückliche Bestätigung.** Die AI zu + bitten, ein Systempaket (`sys_*`) zu modifizieren, gibt eine Ablehnungs- + meldung zurück — die Plattform verweigert dies aus Prinzip. +- **Langlaufende mehrstufige Pläne** (z. B. „eine komplette HR-App von + Grund auf bauen“) funktionieren, werden aber am besten als eine Reihe kleinerer + Konversationen durchgeführt, von denen jede ein oder zwei Objekte umsetzt. + +## Über die Build-Time-AI hinaus + +Dieselbe AI-Infrastruktur betreibt **Runtime-Agents** für deine Endbenutzer — +Support-Assistenten, Sales-Co-Piloten, interne Q&A-Bots — aufgebaut auf +derselben Agent → Skill → Tool Architektur. Siehe [Agents](/docs/build/agents). + +## Wie es weitergeht + +- [Agents](/docs/build/agents) — Endbenutzer-Assistenten auf Basis deiner Daten +- [Data Model](/docs/build/data-model) — was die AI tatsächlich generiert +- [Actions](/docs/build/actions) — die Einheit, die die AI als Runtime-Tools bereitstellt +- [AI Service](/docs/configure/ai) — Provider-Konfiguration (OpenAI / Anthropic / Doubao / …) diff --git a/content/docs/build/ai-builder.es.mdx b/content/docs/build/ai-builder.es.mdx new file mode 100644 index 0000000..dae84f9 --- /dev/null +++ b/content/docs/build/ai-builder.es.mdx @@ -0,0 +1,185 @@ +--- +title: AI Builder +description: El chat dentro de Console que convierte requisitos en lenguaje natural en metadatos en ejecución. +--- + +# AI Builder + +El AI Builder es la **forma principal en que los clientes extienden ObjectOS**. Abre +Console, habla con el asistente en lenguaje natural y él construye los +metadatos por ti: paquetes, objetos, campos, acciones, flujos. Cada +cambio se encola en una lista de aprobación Human-in-the-Loop (HITL) antes de +ponerse en marcha. + +## Pruébalo en 30 segundos + +``` +You: I need to track customer support tickets. + Each ticket has a subject, description, priority (low/medium/high/urgent), + status (new/open/pending/resolved/closed), and assignee. + +AI: I'll create that for you. Here's the plan: + • Create package `com.you.support` (v0.1.0) + • Create object `support_ticket` with 5 fields + • Add a kanban view grouped by status + • Add 3 permission sets: agent, manager, viewer + + Approve? [Yes] [Modify] [Cancel] + +You: [Yes] + +AI: ✓ Package created + ✓ Object created with 5 fields and 12 indexes + ✓ Kanban view registered + ✓ Permission sets created + Done. Try it: /support_ticket +``` + +Ahora tienes una aplicación de tickets en funcionamiento: endpoints REST, vistas en Console, +entradas de registro de auditoría, puntos de control de permisos, todo. No se editó ningún +archivo; no hubo ningún reinicio. + +## Qué puede hacer la IA + +El asistente tiene acceso a un conjunto de **herramientas de metadatos integradas**, todas +con espacio de nombres y validadas contra `@objectstack/spec`: + +| Categoría | Herramienta | Qué hace | +|---|---|---| +| **Paquetes** | `create_package` | Nuevo contenedor con manifiesto + versión | +| | `list_packages` | Explora los paquetes existentes | +| | `get_package` / `get_active_package` | Inspecciona el contenido | +| | `set_active_package` | Elige el paquete de trabajo para la conversación | +| **Objetos** | `create_object` | Nuevo objeto con campos iniciales | +| | `list_objects` | Explora los objetos del paquete activo | +| | `describe_object` | Imprime esquema, campos, relaciones | +| **Campos** | `add_field` | Añade un campo tipado (tipos de campo comunes [field types](/docs/reference/field-types)) | +| | `modify_field` | Cambia etiqueta, opciones de lista de selección, validación | +| | `delete_field` | Elimina un campo (con comprobación de seguridad) | +| **Datos** | `query_data` | Lee registros mediante ObjectQL | +| **Acciones / Conocimiento** | `action_`, `search_knowledge` | Invoca acciones, RAG sobre la documentación | + +Además de herramientas de acción materializadas a partir de cada `*.action.ts` declarado, +nombradas `action_`, de modo que una vez que una acción existe en el paquete, +la IA puede llamarla como cualquier herramienta integrada. + +Consulta el catálogo completo de herramientas en tiempo de ejecución: `GET /api/v1/ai/tools`. + +## Aprobación Human-in-the-Loop + +Las llamadas a herramientas que **modifican metadatos** se enrutan a través de una cola de +acciones pendientes. Los operadores que aprueban ven el diff del cambio propuesto antes de +hacer clic en *Approve*. + +| Endpoint | Propósito | +|---|---| +| `GET /api/v1/ai/pending-actions` | Lista las acciones en cola (filtra por estado) | +| `GET /api/v1/ai/pending-actions/:id` | Diff de una única acción propuesta | +| `POST /api/v1/ai/pending-actions/:id/approve` | Aplica el cambio | +| `POST /api/v1/ai/pending-actions/:id/reject` | Descarta con un motivo | + +Permisos necesarios: + +| Acción | Permiso | +|---|---| +| Leer la cola | `ai:read` | +| Aprobar / rechazar | `ai:approve` | + +Por defecto: solo los miembros de **Setup Administrator** tienen `ai:approve`. +Puedes descomponerlo con mayor granularidad en [Permission Sets](/docs/configure/permissions/permission-sets) — p. ej. +"los product owners pueden aprobar en `com.acme.crm`, nadie más". + +La cola es auditable: cada aprobación/rechazo queda registrado en +`sys_audit_log` con el id de la conversación de origen. + +## Conversaciones y contexto + +Cada chat es un registro `ai_conversations`. La plataforma rastrea: + +- **Paquete activo** — establecido por `set_active_package`. Los nuevos objetos / + campos van aquí. +- **Skills** — el subconjunto de herramientas disponibles para el contexto actual + (p. ej. dentro de la página de detalle de `support_ticket`, la IA puede tener + habilitadas skills con alcance de `support_ticket`). +- **Conocimiento** — temas e índices de RAG asociados a la conversación. + +```text +POST /api/v1/ai/assistant/chat +{ + "messages": [{ "role": "user", "content": "Add a tags field to support_ticket" }], + "context": { "objectName": "support_ticket", "recordId": "tkt_123" } +} +``` + +La plataforma resuelve el Agent por defecto para la aplicación activa, +filtra el conjunto de skills según el contexto y deja que el LLM elija qué herramienta +llamar. No conectas previamente los agentes a interfaces específicas: el agente se asocia +a sí mismo en función de los metadatos. + +## Qué puedes pedir + +Patrones verificados, con prompts de una sola línea: + +| Objetivo | Prompt | +|---|---| +| Nuevo objeto | *"Create a `product` object with name, sku, price, category."* | +| Añadir campo | *"Add a `discount` decimal field to `order`, max 50."* | +| Cambio de lista de selección | *"On `task.status`, add 'blocked' between 'open' and 'done'."* | +| Índice | *"Index `order` by status + created_at for the dashboard."* | +| Relación | *"Make `order_line` master-detail to `order`."* | +| Validación | *"On `invoice`, the discount can't exceed the subtotal."* | +| Flujo | *"When a high-priority ticket sits in 'new' for 30 minutes, notify the manager."* | +| Acción | *"Create an action `approve_invoice` that sets status to approved."* | +| Permission set | *"Create `agent` permission set with read/create/edit on support_ticket and read on customer."* | +| Traducción | *"Translate the support_ticket labels and picklists to Spanish."* | + +Si la IA no puede hacerlo, lo dice, y te indica el camino manual +(normalmente un archivo `*.ts` de 30 líneas o un formulario de Console). + +## Vista previa en vivo + +Tras cada cambio aprobado, Console vuelve a renderizar las vistas afectadas en +el lugar. No es necesario recargar. La caché del kernel se invalida para el paquete +modificado; las solicitudes posteriores usan los nuevos metadatos. + +## Revertir + +Los registros de acciones pendientes conservan el **estado anterior**. Si un cambio sale +mal, rechaza cualquier elemento en curso y pídeselo a la IA: + +``` +You: Roll back the last 3 changes to support_ticket. +AI: Found 3 mutations from conversation conv_abc (3 minutes ago). + Restoring 'support_ticket' to its state at 13:42:11. + Approve? [Yes] +``` + +Para reversiones más grandes, usa [`os diff`](/docs/reference/cli) contra +tu último artefacto correcto conocido y aplica el diff inverso. + +## Limitaciones (por ahora) + +- **El acceso a los datos sigue los propios permisos del operador.** El + asistente se ejecuta como el usuario que ha iniciado sesión, por lo que solo puede leer o escribir + registros que ese usuario ya tiene permitido tocar. La mayoría de los equipos mantienen al + asistente centrado en los metadatos y le dejan consultar —no modificar— + los datos de los clientes. +- **Las mutaciones entre paquetes requieren confirmación explícita.** Pedirle + a la IA que modifique un paquete del sistema (`sys_*`) devuelve un mensaje de + rechazo: la plataforma se niega por principio. +- **Los planes largos de varios pasos** (p. ej. "construye una aplicación de RR. HH. completa desde + cero") funcionan, pero es mejor hacerlos como una serie de conversaciones más pequeñas, + cada una creando uno o dos objetos. + +## Más allá de la IA en tiempo de construcción + +La misma infraestructura de IA impulsa **agentes en tiempo de ejecución** para tus usuarios finales: +asistentes de soporte, copilotos de ventas, bots internos de preguntas y respuestas, construidos sobre +la misma arquitectura Agent → Skill → Tool. Consulta [Agents](/docs/build/agents). + +## Hacia dónde ir después + +- [Agents](/docs/build/agents) — asistentes para usuarios finales sobre tus datos +- [Data Model](/docs/build/data-model) — lo que la IA está generando realmente +- [Actions](/docs/build/actions) — la unidad que la IA expone como herramientas en tiempo de ejecución +- [AI Service](/docs/configure/ai) — configuración del proveedor (OpenAI / Anthropic / Doubao / …) diff --git a/content/docs/build/ai-builder.fr.mdx b/content/docs/build/ai-builder.fr.mdx new file mode 100644 index 0000000..2ec7a5b --- /dev/null +++ b/content/docs/build/ai-builder.fr.mdx @@ -0,0 +1,185 @@ +--- +title: AI Builder +description: Le chat intégré à la Console qui transforme des exigences exprimées en langage courant en métadonnées opérationnelles. +--- + +# AI Builder + +L'AI Builder est le **principal moyen pour les clients d'étendre ObjectOS**. Ouvrez +la Console, parlez à l'assistant en langage courant, et il construit les +métadonnées pour vous — packages, objets, champs, actions, flux. Chaque +modification est placée dans une file d'approbation Human-in-the-Loop (HITL) avant +sa mise en production. + +## Essayez-le en 30 secondes + +``` +You: I need to track customer support tickets. + Each ticket has a subject, description, priority (low/medium/high/urgent), + status (new/open/pending/resolved/closed), and assignee. + +AI: I'll create that for you. Here's the plan: + • Create package `com.you.support` (v0.1.0) + • Create object `support_ticket` with 5 fields + • Add a kanban view grouped by status + • Add 3 permission sets: agent, manager, viewer + + Approve? [Yes] [Modify] [Cancel] + +You: [Yes] + +AI: ✓ Package created + ✓ Object created with 5 fields and 12 indexes + ✓ Kanban view registered + ✓ Permission sets created + Done. Try it: /support_ticket +``` + +Vous disposez désormais d'une application de gestion de tickets fonctionnelle — points de terminaison REST, vues Console, +entrées de journal d'audit, points de contrôle de permissions, tout y est. Aucun fichier n'a été +modifié ; aucun redémarrage n'a eu lieu. + +## Ce que l'IA peut faire + +L'assistant a accès à un ensemble d'**outils de métadonnées intégrés**, tous +regroupés dans un espace de noms et validés par rapport à `@objectstack/spec` : + +| Catégorie | Outil | Ce qu'il fait | +|---|---|---| +| **Packages** | `create_package` | Nouveau conteneur avec manifeste + version | +| | `list_packages` | Parcourir les packages existants | +| | `get_package` / `get_active_package` | Inspecter le contenu | +| | `set_active_package` | Choisir le package de travail pour la conversation | +| **Objects** | `create_object` | Nouvel objet avec champs initiaux | +| | `list_objects` | Parcourir les objets du package actif | +| | `describe_object` | Afficher le schéma, les champs, les relations | +| **Fields** | `add_field` | Ajouter un champ typé (les [types de champs](/docs/reference/field-types) courants) | +| | `modify_field` | Modifier le libellé, les options de liste de sélection, la validation | +| | `delete_field` | Supprimer un champ (avec contrôle de sécurité) | +| **Data** | `query_data` | Lire des enregistrements via ObjectQL | +| **Actions / Knowledge** | `action_`, `search_knowledge` | Invoquer des actions, RAG sur la documentation | + +Auxquels s'ajoutent des outils d'action matérialisés à partir de chaque `*.action.ts` déclaré — +nommés `action_` — de sorte qu'une fois qu'une action existe dans le package, +l'IA peut l'appeler comme n'importe quel outil intégré. + +Consultez le catalogue complet des outils à l'exécution : `GET /api/v1/ai/tools`. + +## Approbation Human-in-the-Loop + +Les appels d'outils qui **modifient les métadonnées** transitent par une file +d'attente d'actions en attente. Les opérateurs chargés de l'approbation voient le diff de la +modification proposée avant de cliquer sur *Approve*. + +| Point de terminaison | Objet | +|---|---| +| `GET /api/v1/ai/pending-actions` | Lister les actions en file d'attente (filtrer par statut) | +| `GET /api/v1/ai/pending-actions/:id` | Diff d'une seule action proposée | +| `POST /api/v1/ai/pending-actions/:id/approve` | Appliquer la modification | +| `POST /api/v1/ai/pending-actions/:id/reject` | Rejeter avec un motif | + +Permissions requises : + +| Action | Permission | +|---|---| +| Lire la file d'attente | `ai:read` | +| Approuver / rejeter | `ai:approve` | + +Par défaut : seuls les membres de **Setup Administrator** disposent de `ai:approve`. +Vous pouvez affiner ce découpage dans les [Permission Sets](/docs/configure/permissions/permission-sets) — par exemple +« les product owners peuvent approuver dans `com.acme.crm`, personne d'autre ». + +La file d'attente est auditable : chaque approbation/rejet est enregistré dans +`sys_audit_log` avec l'identifiant de la conversation d'origine. + +## Conversations et contexte + +Chaque chat correspond à un enregistrement `ai_conversations`. La plateforme suit : + +- **Package actif** — défini par `set_active_package`. Les nouveaux objets / + champs y sont créés. +- **Skills** — l'ensemble des outils disponibles pour le contexte courant + (par exemple, dans la page de détail de `support_ticket`, l'IA peut disposer de + skills limités à `support_ticket`). +- **Knowledge** — les sujets RAG + index rattachés à la conversation. + +```text +POST /api/v1/ai/assistant/chat +{ + "messages": [{ "role": "user", "content": "Add a tags field to support_ticket" }], + "context": { "objectName": "support_ticket", "recordId": "tkt_123" } +} +``` + +La plateforme résout l'Agent par défaut de l'application active, +filtre l'ensemble des skills selon le contexte, et laisse le LLM choisir quel outil +appeler. Vous ne câblez pas à l'avance les agents dans des interfaces spécifiques — l'agent se rattache +de lui-même en fonction des métadonnées. + +## Ce que vous pouvez demander + +Modèles vérifiés, avec des prompts en une ligne : + +| Objectif | Prompt | +|---|---| +| Nouvel objet | *"Create a `product` object with name, sku, price, category."* | +| Ajouter un champ | *"Add a `discount` decimal field to `order`, max 50."* | +| Modification de liste de sélection | *"On `task.status`, add 'blocked' between 'open' and 'done'."* | +| Index | *"Index `order` by status + created_at for the dashboard."* | +| Relation | *"Make `order_line` master-detail to `order`."* | +| Validation | *"On `invoice`, the discount can't exceed the subtotal."* | +| Flux | *"When a high-priority ticket sits in 'new' for 30 minutes, notify the manager."* | +| Action | *"Create an action `approve_invoice` that sets status to approved."* | +| Permission set | *"Create `agent` permission set with read/create/edit on support_ticket and read on customer."* | +| Traduction | *"Translate the support_ticket labels and picklists to Spanish."* | + +Si l'IA ne peut pas le faire, elle vous le dit — et vous oriente vers la voie manuelle +(généralement un fichier `*.ts` de 30 lignes ou un formulaire Console). + +## Aperçu en direct + +Après chaque modification approuvée, la Console restitue à nouveau les vues affectées sur +place. Aucun rechargement nécessaire. Le cache du noyau invalide le package touché ; +les requêtes suivantes utilisent les nouvelles métadonnées. + +## Annuler les modifications + +Les enregistrements d'actions en attente conservent l'**état antérieur**. Si une modification tourne +mal, rejetez les éléments en cours et demandez à l'IA : + +``` +You: Roll back the last 3 changes to support_ticket. +AI: Found 3 mutations from conversation conv_abc (3 minutes ago). + Restoring 'support_ticket' to its state at 13:42:11. + Approve? [Yes] +``` + +Pour des annulations plus importantes, utilisez [`os diff`](/docs/reference/cli) par rapport à +votre dernier artefact connu comme fiable et appliquez le diff inverse. + +## Limitations (aujourd'hui) + +- **L'accès aux données suit les permissions propres de l'opérateur.** L'assistant + s'exécute en tant qu'utilisateur connecté, il ne peut donc lire ou écrire que les + enregistrements que cet utilisateur est déjà autorisé à manipuler. La plupart des équipes + maintiennent l'assistant centré sur les métadonnées et le laissent interroger — et non modifier — + les données client. +- **Les modifications inter-packages nécessitent une confirmation explicite.** Demander + à l'IA de modifier un package système (`sys_*`) renvoie un message de rejet — + la plateforme refuse par principe. +- **Les plans multi-étapes de longue durée** (par exemple « construire une application RH complète à partir + de zéro ») fonctionnent, mais il est préférable de les réaliser sous forme d'une série de + conversations plus courtes, chacune aboutissant à un ou deux objets. + +## Aller au-delà de l'IA au moment de la construction + +La même tuyauterie d'IA alimente les **agents d'exécution** destinés à vos utilisateurs finaux — +assistants de support, copilotes commerciaux, bots de questions-réponses internes — construits sur +la même architecture Agent → Skill → Tool. Voir [Agents](/docs/build/agents). + +## Pour aller plus loin + +- [Agents](/docs/build/agents) — des assistants pour utilisateurs finaux au-dessus de vos données +- [Data Model](/docs/build/data-model) — ce que l'IA génère réellement +- [Actions](/docs/build/actions) — l'unité que l'IA expose en tant qu'outils d'exécution +- [AI Service](/docs/configure/ai) — configuration des fournisseurs (OpenAI / Anthropic / Doubao / …) diff --git a/content/docs/build/ai-builder.ja.mdx b/content/docs/build/ai-builder.ja.mdx new file mode 100644 index 0000000..e0c0649 --- /dev/null +++ b/content/docs/build/ai-builder.ja.mdx @@ -0,0 +1,188 @@ +--- +title: AI Builder +description: 自然言語の要件を実行可能なメタデータに変換する Console 内チャット。 +--- + +# AI Builder + +AI Builder は、**顧客が ObjectOS を拡張するための主要な手段**です。Console +を開き、アシスタントに自然言語で話しかければ、アシスタントがメタデータ +(パッケージ、オブジェクト、フィールド、アクション、フロー)を構築して +くれます。すべての変更は、本番反映前に Human-in-the-Loop (HITL) の承認 +リストにキューイングされます。 + +## 30 秒で試す + +``` +You: I need to track customer support tickets. + Each ticket has a subject, description, priority (low/medium/high/urgent), + status (new/open/pending/resolved/closed), and assignee. + +AI: I'll create that for you. Here's the plan: + • Create package `com.you.support` (v0.1.0) + • Create object `support_ticket` with 5 fields + • Add a kanban view grouped by status + • Add 3 permission sets: agent, manager, viewer + + Approve? [Yes] [Modify] [Cancel] + +You: [Yes] + +AI: ✓ Package created + ✓ Object created with 5 fields and 12 indexes + ✓ Kanban view registered + ✓ Permission sets created + Done. Try it: /support_ticket +``` + +これで動作するチケット管理アプリが完成します。REST エンドポイント、 +Console ビュー、監査ログのエントリ、権限チェックポイントまで一式そろって +います。ファイルは一切編集されず、再起動も発生していません。 + +## AI ができること + +アシスタントは、すべて名前空間化され `@objectstack/spec` に対して検証された +**組み込みメタデータツール**のセットにアクセスできます。 + +| カテゴリ | ツール | 機能 | +|---|---|---| +| **Packages** | `create_package` | マニフェスト + バージョン付きの新しいコンテナ | +| | `list_packages` | 既存のパッケージを閲覧 | +| | `get_package` / `get_active_package` | 内容を確認 | +| | `set_active_package` | 会話で作業対象とするパッケージを選択 | +| **Objects** | `create_object` | 初期フィールド付きの新しいオブジェクト | +| | `list_objects` | アクティブなパッケージ内のオブジェクトを閲覧 | +| | `describe_object` | スキーマ、フィールド、リレーションを出力 | +| **Fields** | `add_field` | 型付きフィールドを追加(一般的な[フィールドタイプ](/docs/reference/field-types)) | +| | `modify_field` | ラベル、選択リストのオプション、検証を変更 | +| | `delete_field` | フィールドを削除(安全チェック付き) | +| **Data** | `query_data` | ObjectQL でレコードを読み取り | +| **Actions / Knowledge** | `action_`, `search_knowledge` | アクションの呼び出し、ドキュメントに対する RAG | + +さらに、宣言されたすべての `*.action.ts` から具体化されたアクション +ツール(`action_` という名前)が利用できます。そのため、パッケージ +にアクションが存在すれば、AI は組み込みツールと同じように呼び出せます。 + +実行時にツールの完全なカタログを確認するには: `GET /api/v1/ai/tools`。 + +## Human-in-the-Loop の承認 + +**メタデータを変更する**ツール呼び出しは、保留中アクションのキューを経由 +します。承認担当のオペレーターは、*Approve* をクリックする前に、提案され +た変更の差分を確認できます。 + +| エンドポイント | 目的 | +|---|---| +| `GET /api/v1/ai/pending-actions` | キューイングされたアクションの一覧(ステータスでフィルタ) | +| `GET /api/v1/ai/pending-actions/:id` | 単一の提案アクションの差分 | +| `POST /api/v1/ai/pending-actions/:id/approve` | 変更を適用 | +| `POST /api/v1/ai/pending-actions/:id/reject` | 理由を付けて破棄 | + +必要な権限: + +| アクション | 権限 | +|---|---| +| キューの読み取り | `ai:read` | +| 承認 / 却下 | `ai:approve` | + +デフォルトでは、**Setup Administrator** のメンバーのみが `ai:approve` を +持ちます。[Permission Sets](/docs/configure/permissions/permission-sets) で +さらに細かく分割できます。たとえば「プロダクトオーナーは `com.acme.crm` +で承認できるが、それ以外は誰も承認できない」といった設定が可能です。 + +このキューは監査可能で、すべての承認 / 却下は、発生元の会話 ID とともに +`sys_audit_log` に記録されます。 + +## 会話とコンテキスト + +各チャットは `ai_conversations` レコードです。プラットフォームは次を追跡 +します。 + +- **アクティブなパッケージ** — `set_active_package` で設定します。新しい + オブジェクト / フィールドはここに配置されます。 +- **Skills** — 現在のコンテキストで利用可能なツールのスライス(たとえば + `support_ticket` の詳細ページ内では、AI が `support_ticket` スコープの + スキルを有効にできる場合があります)。 +- **Knowledge** — 会話にアタッチされた RAG トピック + インデックス。 + +```text +POST /api/v1/ai/assistant/chat +{ + "messages": [{ "role": "user", "content": "Add a tags field to support_ticket" }], + "context": { "objectName": "support_ticket", "recordId": "tkt_123" } +} +``` + +プラットフォームはアクティブなアプリケーションのデフォルト Agent を解決し、 +コンテキストでスキルセットをフィルタし、どのツールを呼び出すかを LLM に +選ばせます。エージェントを特定の UI に事前配線する必要はありません。 +エージェントはメタデータに基づいて自身をアタッチします。 + +## 依頼できること + +検証済みのパターンと、ワンライナーのプロンプト: + +| 目的 | プロンプト | +|---|---| +| 新しいオブジェクト | *"Create a `product` object with name, sku, price, category."* | +| フィールドの追加 | *"Add a `discount` decimal field to `order`, max 50."* | +| 選択リストの変更 | *"On `task.status`, add 'blocked' between 'open' and 'done'."* | +| インデックス | *"Index `order` by status + created_at for the dashboard."* | +| リレーション | *"Make `order_line` master-detail to `order`."* | +| 検証 | *"On `invoice`, the discount can't exceed the subtotal."* | +| フロー | *"When a high-priority ticket sits in 'new' for 30 minutes, notify the manager."* | +| アクション | *"Create an action `approve_invoice` that sets status to approved."* | +| 権限セット | *"Create `agent` permission set with read/create/edit on support_ticket and read on customer."* | +| 翻訳 | *"Translate the support_ticket labels and picklists to Spanish."* | + +AI が対応できない場合はそう伝え、手動の方法(通常は 30 行程度の `*.ts` +ファイルか Console フォーム)を案内します。 + +## ライブプレビュー + +承認された変更ごとに、Console は影響を受けるビューをその場で再レンダリング +します。リロードは不要です。カーネルキャッシュは変更されたパッケージを +無効化し、以降のリクエストは新しいメタデータを使用します。 + +## ロールバック + +保留中アクションのレコードは**変更前の状態**を保持します。変更がうまく +いかなかった場合は、処理中のアイテムを却下し、AI に依頼します。 + +``` +You: Roll back the last 3 changes to support_ticket. +AI: Found 3 mutations from conversation conv_abc (3 minutes ago). + Restoring 'support_ticket' to its state at 13:42:11. + Approve? [Yes] +``` + +より大規模なロールバックには、最後に正常だったアーティファクトに対して +[`os diff`](/docs/reference/cli) を使用し、逆方向の差分を適用してください。 + +## 制限事項(現時点) + +- **データアクセスはオペレーター自身の権限に従います。** アシスタントは + サインインしたユーザーとして動作するため、そのユーザーがすでに操作を + 許可されているレコードのみを読み取り / 書き込みできます。多くのチームは、 + アシスタントをメタデータに集中させ、顧客データについては変更ではなく + クエリのみを行わせています。 +- **パッケージをまたぐ変更には明示的な確認が必要です。** システム + パッケージ(`sys_*`)の変更を AI に依頼すると、却下メッセージが返され + ます。プラットフォームは原則としてこれを拒否します。 +- **長時間にわたる複数ステップの計画**(たとえば「ゼロから完全な HR アプリ + を構築する」)も動作しますが、それぞれが 1〜2 個のオブジェクトを配置する + 一連の小さな会話に分けて行うのが最適です。 + +## ビルド時 AI のその先へ + +同じ AI の仕組みは、エンドユーザー向けの**ランタイムエージェント** +(サポートアシスタント、セールスコパイロット、社内 Q&A ボットなど)も +動かします。これらは同じ Agent → Skill → Tool アーキテクチャの上に構築 +されています。[Agents](/docs/build/agents) を参照してください。 + +## 次に読むべきページ + +- [Agents](/docs/build/agents) — あなたのデータの上に構築するエンドユーザー向けアシスタント +- [Data Model](/docs/build/data-model) — AI が実際に生成しているもの +- [Actions](/docs/build/actions) — AI がランタイムツールとして公開する単位 +- [AI Service](/docs/configure/ai) — プロバイダー設定(OpenAI / Anthropic / Doubao / …) diff --git a/content/docs/build/ai-builder.mdx b/content/docs/build/ai-builder.mdx index 97ba65c..bae792e 100644 --- a/content/docs/build/ai-builder.mdx +++ b/content/docs/build/ai-builder.mdx @@ -41,7 +41,7 @@ edited; no restart happened. ## What the AI can do -The assistant has access to **11 built-in metadata tools**, all +The assistant has access to a set of **built-in metadata tools**, all namespaced and validated against `@objectstack/spec`: | Category | Tool | What it does | @@ -53,11 +53,11 @@ namespaced and validated against `@objectstack/spec`: | **Objects** | `create_object` | New object with initial fields | | | `list_objects` | Browse objects in active package | | | `describe_object` | Print schema, fields, relationships | -| **Fields** | `add_field` | Add a typed field (25 types supported) | +| **Fields** | `add_field` | Add a typed field (common [field types](/docs/reference/field-types)) | | | `modify_field` | Change label, picklist options, validation | | | `delete_field` | Remove a field (with safety check) | | **Data** | `query_data` | Read records via ObjectQL | -| **Actions / Knowledge** | `*_action`, `search_knowledge` | Invoke actions, RAG over docs | +| **Actions / Knowledge** | `action_`, `search_knowledge` | Invoke actions, RAG over docs | Plus action tools materialized from every declared `*.action.ts` — named `action_` — so once an action exists in the package, @@ -94,7 +94,7 @@ The queue is auditable: every approve/reject lands in ## Conversations and context -Each chat is a `sys_ai_conversation` record. The platform tracks: +Each chat is an `ai_conversations` record. The platform tracks: - **Active package** — set by `set_active_package`. New objects / fields land here. @@ -159,9 +159,11 @@ your last known-good artifact and apply the reverse diff. ## Limitations (today) -- **The assistant is read-only on customer data by default.** It can - query records but cannot insert/update/delete unless given the - `ai:write_data` permission. Most customers leave this off. +- **Data access follows the operator's own permissions.** The + assistant runs as the signed-in user, so it can only read or write + records that user is already allowed to touch. Most teams keep the + assistant focused on metadata and let it query — not mutate — + customer data. - **Cross-package mutations require explicit confirmation.** Asking the AI to modify a system package (`sys_*`) returns a rejection message — the platform refuses on principle. diff --git a/content/docs/build/ai-builder.zh-Hans.mdx b/content/docs/build/ai-builder.zh-Hans.mdx new file mode 100644 index 0000000..bc325b8 --- /dev/null +++ b/content/docs/build/ai-builder.zh-Hans.mdx @@ -0,0 +1,185 @@ +--- +title: AI Builder +description: Console 内置的对话功能,将自然语言需求转化为可运行的元数据。 +--- + +# AI Builder + +AI Builder 是**客户扩展 ObjectOS 的主要方式**。打开 +Console,用自然语言与助手对话,它就会为你构建 +元数据——包、对象、字段、动作、流程。每一次 +变更都会先进入人机协作(HITL)审批列表,然后才会 +正式生效。 + +## 30 秒快速体验 + +``` +You: I need to track customer support tickets. + Each ticket has a subject, description, priority (low/medium/high/urgent), + status (new/open/pending/resolved/closed), and assignee. + +AI: I'll create that for you. Here's the plan: + • Create package `com.you.support` (v0.1.0) + • Create object `support_ticket` with 5 fields + • Add a kanban view grouped by status + • Add 3 permission sets: agent, manager, viewer + + Approve? [Yes] [Modify] [Cancel] + +You: [Yes] + +AI: ✓ Package created + ✓ Object created with 5 fields and 12 indexes + ✓ Kanban view registered + ✓ Permission sets created + Done. Try it: /support_ticket +``` + +现在你就拥有了一个可用的工单应用——REST 端点、Console 视图、 +审计日志条目、权限检查点,一应俱全。没有编辑任何 +文件,也没有发生重启。 + +## AI 能做什么 + +助手可以访问一组**内置的元数据工具**,它们都 +带有命名空间,并依据 `@objectstack/spec` 进行校验: + +| 类别 | 工具 | 功能 | +|---|---|---| +| **Packages** | `create_package` | 创建带有 manifest + 版本的新容器 | +| | `list_packages` | 浏览已有的包 | +| | `get_package` / `get_active_package` | 查看内容 | +| | `set_active_package` | 为当前对话选定工作包 | +| **Objects** | `create_object` | 创建带有初始字段的新对象 | +| | `list_objects` | 浏览当前活动包中的对象 | +| | `describe_object` | 输出 schema、字段、关系 | +| **Fields** | `add_field` | 添加一个有类型的字段(常见[字段类型](/docs/reference/field-types)) | +| | `modify_field` | 修改标签、选项列表选项、校验规则 | +| | `delete_field` | 删除字段(带安全检查) | +| **Data** | `query_data` | 通过 ObjectQL 读取记录 | +| **Actions / Knowledge** | `action_`、`search_knowledge` | 调用动作,对文档进行 RAG 检索 | + +此外,每一个声明的 `*.action.ts` 都会物化为动作工具—— +命名为 `action_`——因此一旦某个动作存在于包中, +AI 就可以像调用任何内置工具一样调用它。 + +在运行时查看完整的工具目录:`GET /api/v1/ai/tools`。 + +## 人机协作审批 + +**会变更元数据**的工具调用会路由进一个待处理动作 +队列。审批操作员在点击*批准*之前,会看到所提议 +变更的差异(diff)。 + +| 端点 | 用途 | +|---|---| +| `GET /api/v1/ai/pending-actions` | 列出排队中的动作(可按状态过滤) | +| `GET /api/v1/ai/pending-actions/:id` | 查看单个所提议动作的差异 | +| `POST /api/v1/ai/pending-actions/:id/approve` | 应用变更 | +| `POST /api/v1/ai/pending-actions/:id/reject` | 带原因丢弃 | + +所需权限: + +| 操作 | 权限 | +|---|---| +| 读取队列 | `ai:read` | +| 批准 / 拒绝 | `ai:approve` | + +默认情况下,只有 **Setup Administrator** 的成员才拥有 `ai:approve`。 +你可以在[权限集](/docs/configure/permissions/permission-sets)中进行更细粒度的拆分——例如 +“产品负责人可以在 `com.acme.crm` 中批准,其他人都不行。” + +该队列可审计:每一次批准/拒绝都会记录到 +`sys_audit_log`,并附带发起对话的 id。 + +## 对话与上下文 + +每一次聊天都是一条 `ai_conversations` 记录。平台会跟踪: + +- **活动包(Active package)**——由 `set_active_package` 设定。新建的对象/ + 字段会落到这里。 +- **技能(Skills)**——当前上下文中可用的工具子集 + (例如在 `support_ticket` 详情页内,AI 可能启用了 + `support_ticket` 范围的技能)。 +- **知识(Knowledge)**——附加到该对话的 RAG 主题 + 索引。 + +```text +POST /api/v1/ai/assistant/chat +{ + "messages": [{ "role": "user", "content": "Add a tags field to support_ticket" }], + "context": { "objectName": "support_ticket", "recordId": "tkt_123" } +} +``` + +平台会为当前活动应用解析出默认的 Agent, +根据上下文过滤技能集,然后让 LLM 选择要调用哪个工具。 +你无需把 agent 预先绑定到特定的 UI 上——agent 会 +根据元数据自动挂载。 + +## 你可以请求什么 + +经过验证的模式,附带一行提示词: + +| 目标 | 提示词 | +|---|---| +| 新对象 | *"Create a `product` object with name, sku, price, category."* | +| 添加字段 | *"Add a `discount` decimal field to `order`, max 50."* | +| 选项列表变更 | *"On `task.status`, add 'blocked' between 'open' and 'done'."* | +| 索引 | *"Index `order` by status + created_at for the dashboard."* | +| 关系 | *"Make `order_line` master-detail to `order`."* | +| 校验 | *"On `invoice`, the discount can't exceed the subtotal."* | +| 流程 | *"When a high-priority ticket sits in 'new' for 30 minutes, notify the manager."* | +| 动作 | *"Create an action `approve_invoice` that sets status to approved."* | +| 权限集 | *"Create `agent` permission set with read/create/edit on support_ticket and read on customer."* | +| 翻译 | *"Translate the support_ticket labels and picklists to Spanish."* | + +如果 AI 无法完成,它会明确告知——并为你指出 +手动操作的途径(通常是一个 30 行的 `*.ts` 文件,或一个 Console 表单)。 + +## 实时预览 + +每次变更获批后,Console 会就地重新渲染受影响的视图。 +无需重新加载。内核缓存会使被改动的包失效; +后续请求将使用新的元数据。 + +## 回滚 + +待处理动作记录会保留**变更前的状态**。如果某次变更出错, +拒绝所有在途的条目,然后请 AI: + +``` +You: Roll back the last 3 changes to support_ticket. +AI: Found 3 mutations from conversation conv_abc (3 minutes ago). + Restoring 'support_ticket' to its state at 13:42:11. + Approve? [Yes] +``` + +对于规模更大的回滚,请使用 [`os diff`](/docs/reference/cli) +对比你上一个已知良好的产物,并应用反向 diff。 + +## 当前的限制 + +- **数据访问遵循操作员自身的权限。** + 助手以登录用户的身份运行,因此它只能读取或写入 + 该用户本就有权限操作的记录。大多数团队会让 + 助手专注于元数据,并让它查询——而非变更—— + 客户数据。 +- **跨包变更需要显式确认。** 请求 + AI 修改系统包(`sys_*`)会返回拒绝 + 消息——平台在原则上拒绝这类操作。 +- **长时间运行的多步骤计划**(例如“从零构建一个完整的 HR 应用”) + 是可行的,但最好拆分成一系列较小的 + 对话来完成,每次落地一两个对象。 + +## 超越构建期 AI + +同样的 AI 底层能力也为你的终端用户驱动**运行时 agent**—— +支持助手、销售副驾、内部问答机器人——它们构建于 +同一套 Agent → Skill → Tool 架构之上。参见 [Agents](/docs/build/agents)。 + +## 下一步去哪里 + +- [Agents](/docs/build/agents) —— 基于你的数据构建的终端用户助手 +- [Data Model](/docs/build/data-model) —— AI 实际生成的内容 +- [Actions](/docs/build/actions) —— AI 作为运行时工具暴露的单元 +- [AI Service](/docs/configure/ai) —— 提供商配置(OpenAI / Anthropic / Doubao / …) diff --git a/content/docs/build/ai-skills.de.mdx b/content/docs/build/ai-skills.de.mdx new file mode 100644 index 0000000..81c03d3 --- /dev/null +++ b/content/docs/build/ai-skills.de.mdx @@ -0,0 +1,115 @@ +--- +title: IDE-Skills (Claude Code / Cursor / Copilot) +description: Installieren Sie ObjectOS-Skills in Ihren Coding-Agent, damit Claude Code, Cursor, Copilot, Codex und Co. wissen, wie man ObjectOS-Metadaten korrekt erstellt. +--- + +# IDE-Skills + +Der [AI Builder](./ai-builder) lebt innerhalb der Console und kommuniziert mit der +Datenbank Ihres Mandanten. Aber manchmal möchten Sie dasselbe Domänenwissen +direkt in Ihrer IDE — wenn Sie `*.object.ts` von Hand bearbeiten, einen +Flow entwerfen oder Cursor bitten, ein CEL-Prädikat zu schreiben. + +ObjectOS liefert **9 First-Party-Agent-Skills** mit, die Coding-Assistenten +beibringen, wie man jede Art von ObjectOS-Metadaten erstellt. Sie werden +über das offene [`skills`](https://www.npmjs.com/package/skills)-Ökosystem +(Vercel Labs) verteilt und funktionieren mit **Claude Code, Cursor, Copilot, +Codex, Gemini CLI, Windsurf, Cline, Continue, Roo, Goose, Kiro, +opencode** und etwa 50 weiteren Agents. + +## Installation + +In jedem Projekt, das `@objectstack/*`-Pakete verwendet: + +```bash +npx skills add objectstack-ai/framework +``` + +Die CLI erkennt, welche Agents Sie konfiguriert haben (`.claude/`, +`.cursor/`, `.github/copilot/`, `AGENTS.md` usw.) und schreibt die +Skills an die richtige Stelle. Führen Sie den Befehl jederzeit erneut aus, +um die neuesten Versionen zu beziehen. + +> Keine Änderung an `package.json`, keine globale Installation. Skills sind +> reine Markdown-Dateien, die in Ihr Repository committet werden, sodass das +> gesamte Team — und CI-Agents — dieselben Anweisungen teilen. + +## Was Sie erhalten + +| Skill | Laden, wenn Sie an … arbeiten | +|:------|:-----------------------------| +| `objectstack-platform` | `defineStack`, Drivern, Adaptern, Plugins, Services, der `os`-CLI, Deployment | +| `objectstack-data` | `*.object.ts`, `*.seed.ts`, Feldern, Beziehungen, Validierungen, Indizes, Lifecycle-Hooks, RLS | +| `objectstack-query` | ObjectQL — Filter, Sortierung, Pagination, Aggregation, Joins, Window-Funktionen, Volltextsuche | +| `objectstack-ui` | Views, Apps, Pages, Dashboards, Reports, Charts, Actions | +| `objectstack-automation` | Flows, Workflows, Triggers, Approvals, Zeitplänen, Webhooks | +| `objectstack-ai` | Agents, Tools, Skills, Conversations, Model Registry, MCP | +| `objectstack-api` | REST/GraphQL-Endpunkten, Auth, Realtime, Error-Envelopes | +| `objectstack-i18n` | Übersetzungs-Bundles, Locale-Fallback, Abdeckung | +| `objectstack-formula` | CEL-Ausdrücken — Formelfeldern, Validierungs-/Sharing-/Sichtbarkeits-Prädikaten, Bedingungen | + +Jeder Skill ist **scope-aware** — er teilt dem Agent mit, wann er sich +selbst laden und wann er an einen verwandten Skill verweisen soll, sodass +Claude nicht versucht, ein Objekt mit dem Platform-Skill zu modellieren oder +einen CEL-Ausdruck mit dem Data-Skill zu schreiben. + +## Wie es funktioniert + +Jeder Skill ist ein Ordner unter `skills/` im +[Framework-Repo](https://github.com/objectstack-ai/framework/tree/main/skills): + +``` +skills/objectstack-data/ +├── SKILL.md # YAML frontmatter + prose guide +├── references/ +│ └── _index.md # pointers into @objectstack/spec Zod sources +└── rules/ # optional deep-dive rules +``` + +Das Frontmatter in `SKILL.md` ist das, was `skills add` liest, um den +Skill an die richtige Agent-Oberfläche zu leiten: + +```yaml +--- +name: objectstack-data +description: Design ObjectStack data schemas — objects, fields, ... +license: Apache-2.0 +compatibility: Requires @objectstack/spec Zod schemas (v4+) +metadata: + domain: data + tags: object, field, validation, relationship, hook, permission, rls +--- +``` + +Eine zentrale Regel über alle Skills hinweg: **Die Zod-Schemas in +`@objectstack/spec` sind die Wahrheit**. Skills vermitteln die Absicht; +Agents lesen die Schemas in `node_modules/@objectstack/spec/src/**/*.zod.ts` +für die exakten Feldformen. Deshalb verschwinden halluzinierte Felder +praktisch, sobald die Skills installiert sind. + +## Skills vs. AI Builder + +| | [AI Builder](./ai-builder) | IDE-Skills | +|:--|:--|:--| +| Wo es läuft | Console (Browser) | Ihre IDE / Ihr Coding-Agent | +| Was es ändert | Live-Metadaten in Ihrem Mandanten | Dateien in Ihrem Repository | +| Handelt im Namen von | Ihren Endnutzern / Admins | Ihren Entwicklern | +| Genehmigungsmodell | HITL-Warteschlange (`ai:approve`) | Pull-Request-Review | +| Am besten für | Tägliche Erweiterungen, No-Code-Nutzer | Templates, Pakete, komplexe Flows, Bibliothekscode | + +Die beiden ergänzen sich. Die meisten Teams nutzen den AI Builder für die +Mandantenanpassung und IDE-Skills bei der Arbeit an **Paketen, die sie +veröffentlichen wollen** (siehe [Templates](./templates) und [Marketplace](./marketplace)). + +## Aktualisieren + +Die Skills folgen den `@objectstack/spec`-Versionen. Führen Sie +`npx skills add objectstack-ai/framework` nach dem Upgrade des Spec-Pakets +erneut aus, um Ihren Agent mit den neuesten Zod-Schemas, CEL-Helfern und +dem Metadaten-Vokabular synchron zu halten. + +## Verwandt + +- [AI Builder](./ai-builder) — das Gegenstück innerhalb der Console +- [Agents](./agents) — deklarieren Sie serverseitige Agents, die *innerhalb* von ObjectOS laufen +- [Templates](./templates) — jedes offizielle Template wird mit diesen geladenen Skills erstellt diff --git a/content/docs/build/ai-skills.es.mdx b/content/docs/build/ai-skills.es.mdx new file mode 100644 index 0000000..815b082 --- /dev/null +++ b/content/docs/build/ai-skills.es.mdx @@ -0,0 +1,117 @@ +--- +title: AI Skills para IDE (Claude Code / Cursor / Copilot) +description: Instala las skills de ObjectOS en tu agente de programación para que Claude Code, Cursor, Copilot, Codex y similares sepan cómo crear correctamente metadatos de ObjectOS. +--- + +# AI Skills para IDE + +El [AI Builder](./ai-builder) vive dentro de Console y se comunica con la +base de datos de tu tenant. Pero a veces quieres ese mismo conocimiento +de dominio dentro de tu IDE — cuando editas a mano `*.object.ts`, diseñas +un flow o le pides a Cursor que escriba un predicado CEL. + +ObjectOS incluye **9 AI Skills de agente de primera categoría** que enseñan +a los asistentes de programación cómo crear todo tipo de metadatos de +ObjectOS. Se distribuyen a través del ecosistema abierto +[`skills`](https://www.npmjs.com/package/skills) (Vercel Labs) y funcionan +con **Claude Code, Cursor, Copilot, Codex, Gemini CLI, Windsurf, Cline, +Continue, Roo, Goose, Kiro, opencode** y ~50 agentes más. + +## Instalación + +En cualquier proyecto que use paquetes `@objectstack/*`: + +```bash +npx skills add objectstack-ai/framework +``` + +El CLI detecta qué agentes tienes configurados (`.claude/`, +`.cursor/`, `.github/copilot/`, `AGENTS.md`, etc.) y escribe las +skills en el lugar correcto. Vuelve a ejecutarlo en cualquier momento +para obtener las últimas versiones. + +> No hay cambios en `package.json` ni instalación global. Las skills son +> simples archivos markdown incluidos en tu repositorio, de modo que todo +> el equipo — y los agentes de CI — comparten las mismas instrucciones. + +## Qué obtienes + +| Skill | Cárgala cuando trabajes en… | +|:------|:-----------------------------| +| `objectstack-platform` | `defineStack`, drivers, adaptadores, plugins, servicios, el CLI `os`, despliegue | +| `objectstack-data` | `*.object.ts`, `*.seed.ts`, campos, relaciones, validaciones, índices, hooks de ciclo de vida, RLS | +| `objectstack-query` | ObjectQL — filtros, ordenación, paginación, agregación, joins, funciones de ventana, búsqueda de texto completo | +| `objectstack-ui` | Views, Apps, Pages, Dashboards, Reports, Charts, Actions | +| `objectstack-automation` | Flows, Workflows, Triggers, Approvals, programaciones, webhooks | +| `objectstack-ai` | Agents, Tools, Skills, Conversations, Model Registry, MCP | +| `objectstack-api` | Endpoints REST/GraphQL, autenticación, tiempo real, envelopes de error | +| `objectstack-i18n` | Paquetes de traducción, fallback de locales, cobertura | +| `objectstack-formula` | Expresiones CEL — campos de fórmula, predicados de validación/compartición/visibilidad, condiciones | + +Cada skill **conoce su alcance** — le indica al agente cuándo cargarse y +cuándo delegar en una skill hermana, de modo que Claude no intente modelar +un objeto con la skill de plataforma ni escribir una expresión CEL con la +skill de datos. + +## Cómo funciona + +Cada skill es una carpeta dentro de `skills/` en el +[repositorio del framework](https://github.com/objectstack-ai/framework/tree/main/skills): + +``` +skills/objectstack-data/ +├── SKILL.md # YAML frontmatter + prose guide +├── references/ +│ └── _index.md # pointers into @objectstack/spec Zod sources +└── rules/ # optional deep-dive rules +``` + +El frontmatter de `SKILL.md` es lo que lee `skills add` para enrutar la +skill a la superficie de agente correcta: + +```yaml +--- +name: objectstack-data +description: Design ObjectStack data schemas — objects, fields, ... +license: Apache-2.0 +compatibility: Requires @objectstack/spec Zod schemas (v4+) +metadata: + domain: data + tags: object, field, validation, relationship, hook, permission, rls +--- +``` + +Una regla fundamental en todas las skills: **los esquemas Zod en +`@objectstack/spec` son la fuente de verdad**. Las skills aportan la +intención; los agentes leen los esquemas en +`node_modules/@objectstack/spec/src/**/*.zod.ts` para conocer las formas +exactas de los campos. Por eso los campos alucinados desaparecen +efectivamente una vez instaladas las skills. + +## Skills frente a AI Builder + +| | [AI Builder](./ai-builder) | AI Skills para IDE | +|:--|:--|:--| +| Dónde se ejecuta | Console (navegador) | Tu IDE / agente de programación | +| Qué modifica | Metadatos en vivo en tu tenant | Archivos en tu repositorio | +| Actúa en nombre de | Tus usuarios finales / administradores | Tus desarrolladores | +| Modelo de aprobación | Cola HITL (`ai:approve`) | Revisión de pull request | +| Ideal para | Extensiones del día a día, usuarios no-code | Plantillas, paquetes, flows complejos, código de librería | + +Ambos son complementarios. La mayoría de los equipos usan el AI Builder +para la personalización del tenant y las AI Skills para IDE al trabajar en +**paquetes que pretenden publicar** (consulta [Templates](./templates) y +[Marketplace](./marketplace)). + +## Actualización + +Las skills siguen las versiones de `@objectstack/spec`. Vuelve a ejecutar +`npx skills add objectstack-ai/framework` tras actualizar el paquete spec +para mantener tu agente sincronizado con los últimos esquemas Zod, +helpers de CEL y vocabulario de metadatos. + +## Relacionado + +- [AI Builder](./ai-builder) — la contraparte dentro de Console +- [Agents](./agents) — declara agentes del lado del servidor que se ejecutan *dentro* de ObjectOS +- [Templates](./templates) — cada plantilla oficial se construye con estas skills cargadas diff --git a/content/docs/build/ai-skills.fr.mdx b/content/docs/build/ai-skills.fr.mdx new file mode 100644 index 0000000..27e3e1a --- /dev/null +++ b/content/docs/build/ai-skills.fr.mdx @@ -0,0 +1,120 @@ +--- +title: Skills IDE (Claude Code / Cursor / Copilot) +description: Installez les skills ObjectOS dans votre agent de codage afin que Claude Code, Cursor, Copilot, Codex et compagnie sachent rédiger correctement les métadonnées ObjectOS. +--- + +# Skills IDE + +L'[AI Builder](./ai-builder) vit dans Console et communique avec la +base de données de votre tenant. Mais il arrive que vous vouliez les +mêmes connaissances métier directement dans votre IDE — lorsque vous +éditez à la main des `*.object.ts`, concevez un flow ou demandez à +Cursor d'écrire un prédicat CEL. + +ObjectOS fournit **9 agent skills first-party** qui apprennent aux +assistants de codage à rédiger tous les types de métadonnées ObjectOS. +Ils sont distribués via l'écosystème ouvert +[`skills`](https://www.npmjs.com/package/skills) (Vercel Labs) et +fonctionnent avec **Claude Code, Cursor, Copilot, Codex, Gemini CLI, +Windsurf, Cline, Continue, Roo, Goose, Kiro, opencode** et une +cinquantaine d'autres agents. + +## Installation + +Dans n'importe quel projet utilisant les packages `@objectstack/*` : + +```bash +npx skills add objectstack-ai/framework +``` + +La CLI détecte les agents que vous avez configurés (`.claude/`, +`.cursor/`, `.github/copilot/`, `AGENTS.md`, etc.) et écrit les skills +au bon endroit. Relancez-la à tout moment pour récupérer les dernières +versions. + +> Aucune modification de `package.json`, aucune installation globale. +> Les skills sont de simples fichiers markdown commités dans votre dépôt +> afin que toute l'équipe — ainsi que les agents de CI — partagent les +> mêmes instructions. + +## Ce que vous obtenez + +| Skill | À charger quand vous travaillez sur… | +|:------|:-----------------------------| +| `objectstack-platform` | `defineStack`, drivers, adaptateurs, plugins, services, la CLI `os`, le déploiement | +| `objectstack-data` | `*.object.ts`, `*.seed.ts`, champs, relations, validations, index, hooks de cycle de vie, RLS | +| `objectstack-query` | ObjectQL — filtres, tri, pagination, agrégation, jointures, fonctions de fenêtrage, recherche plein texte | +| `objectstack-ui` | Views, Apps, Pages, Dashboards, Reports, Charts, Actions | +| `objectstack-automation` | Flows, Workflows, Triggers, Approvals, planifications, webhooks | +| `objectstack-ai` | Agents, Tools, Skills, Conversations, Model Registry, MCP | +| `objectstack-api` | endpoints REST/GraphQL, authentification, temps réel, enveloppes d'erreur | +| `objectstack-i18n` | bundles de traduction, repli de locale, couverture | +| `objectstack-formula` | expressions CEL — champs de formule, prédicats de validation/partage/visibilité, conditions | + +Chaque skill est **conscient de son périmètre** — il indique à l'agent +quand se charger lui-même et quand déléguer à un skill voisin, afin que +Claude n'essaie pas de modéliser un objet avec le skill platform ni +d'écrire une expression CEL avec le skill data. + +## Comment ça fonctionne + +Chaque skill est un dossier sous `skills/` dans le +[dépôt framework](https://github.com/objectstack-ai/framework/tree/main/skills) : + +``` +skills/objectstack-data/ +├── SKILL.md # YAML frontmatter + prose guide +├── references/ +│ └── _index.md # pointers into @objectstack/spec Zod sources +└── rules/ # optional deep-dive rules +``` + +Le frontmatter du `SKILL.md` est ce que `skills add` lit pour router +le skill vers la bonne surface d'agent : + +```yaml +--- +name: objectstack-data +description: Design ObjectStack data schemas — objects, fields, ... +license: Apache-2.0 +compatibility: Requires @objectstack/spec Zod schemas (v4+) +metadata: + domain: data + tags: object, field, validation, relationship, hook, permission, rls +--- +``` + +Une règle fondamentale dans tous les skills : **les schémas Zod de +`@objectstack/spec` font foi**. Les skills donnent l'intention ; les +agents lisent les schémas dans +`node_modules/@objectstack/spec/src/**/*.zod.ts` pour connaître la +forme exacte des champs. C'est pourquoi les champs hallucinés +disparaissent de fait une fois les skills installés. + +## Skills vs. AI Builder + +| | [AI Builder](./ai-builder) | Skills IDE | +|:--|:--|:--| +| Où ça s'exécute | Console (navigateur) | Votre IDE / agent de codage | +| Ce que ça modifie | Métadonnées en direct dans votre tenant | Fichiers de votre dépôt | +| Agit pour le compte de | Vos utilisateurs finaux / admins | Vos développeurs | +| Modèle d'approbation | File HITL (`ai:approve`) | Revue de pull request | +| Idéal pour | Extensions du quotidien, utilisateurs no-code | Templates, packages, flows complexes, code de bibliothèque | + +Les deux sont complémentaires. La plupart des équipes utilisent l'AI +Builder pour la personnalisation du tenant et les skills IDE lorsqu'elles +travaillent sur des **packages qu'elles comptent publier** (voir +[Templates](./templates) et [Marketplace](./marketplace)). + +## Mise à jour + +Les skills suivent les versions de `@objectstack/spec`. Relancez +`npx skills add objectstack-ai/framework` après avoir mis à niveau le +package spec pour garder votre agent synchronisé avec les derniers +schémas Zod, helpers CEL et vocabulaire de métadonnées. + +## Voir aussi + +- [AI Builder](./ai-builder) — l'équivalent intégré à Console +- [Agents](./agents) — déclarez des agents côté serveur qui s'exécutent *à l'intérieur* d'ObjectOS +- [Templates](./templates) — chaque template officiel est conçu avec ces skills chargés diff --git a/content/docs/build/ai-skills.ja.mdx b/content/docs/build/ai-skills.ja.mdx new file mode 100644 index 0000000..6b156b9 --- /dev/null +++ b/content/docs/build/ai-skills.ja.mdx @@ -0,0 +1,114 @@ +--- +title: IDE スキル (Claude Code / Cursor / Copilot) +description: ObjectOS スキルをコーディングエージェントにインストールして、Claude Code、Cursor、Copilot、Codex などが ObjectOS メタデータを正しく作成できるようにします。 +--- + +# IDE スキル + +[AI Builder](./ai-builder) は Console の内部に存在し、テナントの +データベースとやり取りします。しかし、IDE の中で同じドメイン知識が +欲しい場面もあります。たとえば `*.object.ts` を手作業で編集したり、 +フローを設計したり、Cursor に CEL 述語を書かせたりするときです。 + +ObjectOS は **9 個のファーストパーティ製エージェントスキル** を提供しており、 +あらゆる種類の ObjectOS メタデータの作成方法をコーディングアシスタントに教えます。 +これらはオープンな [`skills`](https://www.npmjs.com/package/skills) +エコシステム (Vercel Labs) を通じて配布され、**Claude Code、Cursor、Copilot、 +Codex、Gemini CLI、Windsurf、Cline、Continue、Roo、Goose、Kiro、 +opencode** およびその他約 50 種類のエージェントで動作します。 + +## インストール + +`@objectstack/*` パッケージを使用しているプロジェクトであればどこでも: + +```bash +npx skills add objectstack-ai/framework +``` + +CLI は構成済みのエージェント (`.claude/`、`.cursor/`、`.github/copilot/`、 +`AGENTS.md` など) を検出し、スキルを適切な場所に書き込みます。 +最新バージョンを取得するには、いつでも再実行してください。 + +> `package.json` の変更も、グローバルインストールも不要です。スキルは +> リポジトリにコミットされるプレーンな Markdown ファイルなので、チーム全体 — +> そして CI エージェント — が同じ指示を共有できます。 + +## 得られるもの + +| スキル | 読み込むタイミング(作業対象) | +|:------|:-----------------------------| +| `objectstack-platform` | `defineStack`、ドライバー、アダプター、プラグイン、サービス、`os` CLI、デプロイ | +| `objectstack-data` | `*.object.ts`、`*.seed.ts`、フィールド、リレーションシップ、バリデーション、インデックス、ライフサイクルフック、RLS | +| `objectstack-query` | ObjectQL — フィルター、ソート、ページネーション、集計、結合、ウィンドウ関数、全文検索 | +| `objectstack-ui` | Views、Apps、Pages、Dashboards、Reports、Charts、Actions | +| `objectstack-automation` | Flows、Workflows、Triggers、Approvals、スケジュール、Webhook | +| `objectstack-ai` | Agents、Tools、Skills、Conversations、Model Registry、MCP | +| `objectstack-api` | REST/GraphQL エンドポイント、認証、リアルタイム、エラーエンベロープ | +| `objectstack-i18n` | 翻訳バンドル、ロケールフォールバック、カバレッジ | +| `objectstack-formula` | CEL 式 — 数式フィールド、バリデーション/共有/可視性の述語、条件 | + +各スキルは **スコープを認識** しており、いつ自身を読み込み、いつ兄弟スキルに +委譲すべきかをエージェントに伝えます。そのため Claude が platform スキルで +オブジェクトをモデリングしようとしたり、data スキルで CEL 式を書こうとしたりすることはありません。 + +## 仕組み + +すべてのスキルは +[framework リポジトリ](https://github.com/objectstack-ai/framework/tree/main/skills) +の `skills/` 配下にあるフォルダーです: + +``` +skills/objectstack-data/ +├── SKILL.md # YAML frontmatter + prose guide +├── references/ +│ └── _index.md # pointers into @objectstack/spec Zod sources +└── rules/ # optional deep-dive rules +``` + +`SKILL.md` の frontmatter は、`skills add` がスキルを適切なエージェント +サーフェスへルーティングするために読み取るものです: + +```yaml +--- +name: objectstack-data +description: Design ObjectStack data schemas — objects, fields, ... +license: Apache-2.0 +compatibility: Requires @objectstack/spec Zod schemas (v4+) +metadata: + domain: data + tags: object, field, validation, relationship, hook, permission, rls +--- +``` + +すべてのスキルに共通する中核的なルール: **`@objectstack/spec` 内の Zod +スキーマが真実です**。スキルは意図を与え、エージェントは正確なフィールドの +形状を得るために `node_modules/@objectstack/spec/src/**/*.zod.ts` の +スキーマを読み取ります。これが、スキルをインストールすると幻覚的な +フィールドが事実上消える理由です。 + +## スキル vs. AI Builder + +| | [AI Builder](./ai-builder) | IDE スキル | +|:--|:--|:--| +| 実行される場所 | Console (ブラウザー) | あなたの IDE / コーディングエージェント | +| 変更対象 | テナント内のライブメタデータ | リポジトリ内のファイル | +| 代理する対象 | エンドユーザー / 管理者 | 開発者 | +| 承認モデル | HITL キュー (`ai:approve`) | プルリクエストレビュー | +| 最適な用途 | 日常的な拡張、ノーコードユーザー | テンプレート、パッケージ、複雑なフロー、ライブラリコード | + +両者は補完的な関係です。多くのチームは、テナントのカスタマイズには +AI Builder を使い、**公開を意図したパッケージ** を扱う際には IDE スキルを +使います ([Templates](./templates) と [Marketplace](./marketplace) を参照)。 + +## 更新 + +スキルは `@objectstack/spec` のバージョンに追従します。spec パッケージを +アップグレードした後に `npx skills add objectstack-ai/framework` を再実行して、 +エージェントを最新の Zod スキーマ、CEL ヘルパー、メタデータ語彙と +同期させてください。 + +## 関連項目 + +- [AI Builder](./ai-builder) — Console 内のカウンターパート +- [Agents](./agents) — ObjectOS の *内部* で実行されるサーバーサイドエージェントを宣言する +- [Templates](./templates) — すべての公式テンプレートはこれらのスキルを読み込んで構築されている diff --git a/content/docs/build/ai-skills.cn.mdx b/content/docs/build/ai-skills.zh-Hans.mdx similarity index 100% rename from content/docs/build/ai-skills.cn.mdx rename to content/docs/build/ai-skills.zh-Hans.mdx diff --git a/content/docs/build/data-model.de.mdx b/content/docs/build/data-model.de.mdx new file mode 100644 index 0000000..1c34dd1 --- /dev/null +++ b/content/docs/build/data-model.de.mdx @@ -0,0 +1,262 @@ +--- +title: Datenmodell +description: Objekte, Felder, Beziehungen, Validierung, Indizes — der KI beschrieben oder in TypeScript geschrieben. +--- + +# Datenmodell + +Das Datenmodell ist die zentrale Quelle der Wahrheit für Ihre App. Sobald +ein Objekt existiert, stellt Ihnen ObjectOS REST-APIs, eine Console-Ansicht, +RBAC-Checkpoints, Audit-Log-Einträge und KI-Tool-Bereitstellung zur +Verfügung — kostenlos. + +**Die meisten Kunden schreiben das Schema nie von Hand.** Sie beschreiben, +was sie benötigen, im [AI Builder](/docs/build/ai-builder), und die +Plattform erstellt die Objekte, Felder, Indizes und Übersetzungen. Diese +Seite beschreibt die zugrunde liegende Struktur — damit Sie verstehen, was +die KI generiert, und sie bei Bedarf direkt bearbeiten können. + +## Autorenpfade + +| Pfad | Sieht aus wie | +|---|---| +| **AI Builder** (primär) | *„Erstelle ein `support_ticket`-Objekt mit subject, description, priority, status, assignee."* | +| **Console-Klick-Erstellung** | Console → Objects → New Object → Formulare | +| **TypeScript (`*.object.ts`)** | Das unten gezeigte TS — typischerweise innerhalb einer geforkten [Vorlage](/docs/build/templates) | + +Alle drei erzeugen dasselbe Schema. Das Schema ist kanonisch; alles +andere wird daraus abgeleitet. + +## Aufbau eines Objekts + +```ts +// src/objects/task.ts +import { ObjectSchema, Field } from '@objectstack/spec/data'; + +export const Task = ObjectSchema.create({ + name: 'todo_task', + label: 'Task', + pluralLabel: 'Tasks', + icon: 'check-square', + description: 'A single unit of work.', + + fields: { + subject: Field.text({ label: 'Subject', required: true, maxLength: 200 }), + description: Field.markdown({ label: 'Description' }), + status: Field.select({ + label: 'Status', + options: [ + { label: 'To Do', value: 'todo', default: true }, + { label: 'In Progress', value: 'in_progress' }, + { label: 'Done', value: 'done' }, + ], + }), + due: Field.date({ label: 'Due' }), + assignee: Field.lookup('sys_user', { label: 'Assignee' }), + }, + + enable: { + trackHistory: true, // record field changes in audit log + apiEnabled: true, // expose REST endpoints (default true) + feeds: true, // chatter / comments / @mentions + }, +}); +``` + +Registrieren Sie es in Ihrem Stack: + +```ts +// objectstack.config.ts +import { defineStack } from '@objectstack/spec'; +import * as objects from './src/objects'; + +export default defineStack({ + manifest: { id: 'my.app', namespace: 'myapp', version: '0.1.0', type: 'app', name: 'My App' }, + objects: Object.values(objects), +}); +``` + +Das ist alles, was Sie brauchen. `os dev` kompiliert neu, und +`/api/v1/data/todo_task`, die Console-Task-Ansicht und die +Console-Berechtigungszeile erscheinen allesamt. + +## Feldtypen + +ObjectStack liefert ~25 Feldtypen. Die am häufigsten verwendeten: + +### Skalare + +| Typ | Was es speichert | Helfer | +|---|---|---| +| `text` | Kurze Zeichenkette | `Field.text({ maxLength, required })` | +| `textarea` | Lange Zeichenkette | `Field.textarea(...)` | +| `markdown` | Rich-Text mit Markdown | `Field.markdown(...)` | +| `number` | Ganzzahl | `Field.number({ min, max })` | +| `decimal` | Exakte Dezimalzahl (Geld usw.) | `Field.decimal({ precision, scale })` | +| `boolean` | Wahr/Falsch | `Field.boolean({ defaultValue })` | +| `date` | Kalenderdatum | `Field.date(...)` | +| `datetime` | Zeitstempel | `Field.datetime(...)` | +| `email` | Validierte E-Mail | `Field.email(...)` | +| `url` | Validierte URL | `Field.url(...)` | +| `phone` | Validierte Telefonnummer | `Field.phone(...)` | +| `json` | Beliebiges JSON | `Field.json(...)` | + +### Auswahlmöglichkeiten + +| Typ | Verwendung für | +|---|---| +| `select` | Einzelauswahl (Enum) | +| `multiselect` | Mehrfachauswahl | + +### Beziehungen + +| Typ | Kardinalität | Helfer | +|---|---|---| +| `lookup` | Eins-zu-viele (FK) | `Field.lookup({ reference: 'sys_user' })` | +| `masterDetail` | Eins-zu-viele mit kaskadierendem Löschen | `Field.masterDetail({ reference: 'order' })` | + +### Dateien & Medien + +| Typ | Was es speichert | +|---|---| +| `attachment` | Eine Datei über den Speicherdienst | +| `image` | Bildanhang mit Vorschau | + +### Berechnet / abgeleitet + +| Typ | Verhalten | +|---|---| +| `formula` | Beim Lesen aus einem CEL-Ausdruck berechnet | +| `rollup` | Aggregat verknüpfter Datensätze (Summe/Anzahl/Durchschnitt) | +| `autoNumber` | Sequenz (`INV-{000001}`) | +| `created`, `lastModified` | Systemgepflegte Zeitstempel | +| `createdBy`, `lastModifiedBy` | Systemgepflegte Benutzerreferenzen | + +## Erforderlich / eindeutig / Standard + +Gängige Modifikatoren für jedes skalare Feld: + +```ts +Field.text({ + label: 'Code', + required: true, + unique: true, // unique constraint enforced at DB level + defaultValue: '', + helpText: 'Internal short code', +}) +``` + +## Validierung + +Inline: + +```ts +Field.number({ label: 'Quantity', min: 1, max: 9999 }) +Field.text({ label: 'SKU', pattern: '^[A-Z]{3}-[0-9]{4}$' }) +``` + +Objektebene-Regeln (feldübergreifend): + +```ts +ObjectSchema.create({ + name: 'order', + fields: { /* ... */ }, + validations: [ + { + name: 'discount_lt_total', + message: 'Discount cannot exceed total', + condition: 'discount < total', + }, + ], +}); +``` + +Die Validierung läuft bei jedem Schreibvorgang — REST, Console, ObjectQL — +sodass es keine „Hintertür" gibt. + +## Indizes & Performance + +```ts +ObjectSchema.create({ + name: 'order', + fields: { /* ... */ }, + indexes: [ + { fields: ['status', 'created_at'] }, + { fields: ['account', 'created_at'], unique: false }, + ], +}); +``` + +Der Treiber erstellt beim Schema-Sync echte DB-Indizes. + +## Feldgruppen + +Für lange Formulare gruppieren Sie Felder in der Console: + +```ts +ObjectSchema.create({ + name: 'task', + fieldGroups: [ + { key: 'core', label: 'Task', icon: 'check-square' }, + { key: 'planning', label: 'Planning', icon: 'calendar' }, + { key: 'meta', label: 'Metadata', icon: 'info', defaultExpanded: false }, + ], + fields: { + subject: Field.text({ label: 'Subject', group: 'core' }), + due: Field.date({ label: 'Due', group: 'planning' }), + }, +}); +``` + +## Lebenszyklus & Eigentümerschaft + +```ts +ObjectSchema.create({ + name: 'task', + ownership: 'own', // 'own' | 'shared' | 'system' + enable: { + apiEnabled: true, // generated REST endpoints + trackHistory: true, // audit log of field changes + feeds: true, // sys_comment / sys_activity / @mentions + softDelete: true, // tombstone instead of hard delete + }, +}); +``` + +## Systemobjekte (kostenlos bei jedem Projekt) + +Sie müssen diese nicht deklarieren — sie sind immer vorhanden: + +| Objekt | Was | +|---|---| +| `sys_user` | Benutzerkonten | +| `sys_org` | Organisationen / Mandanten | +| `sys_member` | Org-Mitgliedschaft | +| `sys_role`, `sys_permission_set` | RBAC-Primitive | +| `sys_audit_log` | Audit-Trail (wenn Audit-Fähigkeit geladen) | +| `sys_file`, `sys_attachment` | Datei-Metadaten (wenn Speicher geladen) | +| `sys_comment`, `sys_activity` | Feed / Chatter (wenn Feed geladen) | +| `sys_session`, `sys_api_key` | Auth-Artefakte | +| `sys_webhook`, `sys_webhook_delivery` | Webhook-Abonnements (wenn aktiviert) | + +Referenzieren Sie sie in `lookup`-Feldern über den Namen — z. B. `Field.lookup({ reference: 'sys_user' })`. + +## Polymorphe Plattformfunktionen + +Wenn Sie `feeds: true` und `trackHistory: true` aktivieren, nimmt Ihr Objekt +automatisch teil an: + +- `sys_comment` (thread_id = `:`) +- `sys_attachment` (parent_object = ``, parent_id = ``) +- `sys_activity` (Timeline) +- `sys_audit_log` (Diffs auf Feldebene) + +Sie verdrahten diese nicht pro Objekt — sie sind auf der Plattform polymorph. + +## Wie es weitergeht + +- [Berechtigungen](/docs/configure/permissions) — Zugriff auf Ihre Objekte steuern +- [Flows / Automatisierung](/docs/build/flows) — auf Datensatzänderungen reagieren +- [API-Zugriff](/docs/configure/api-access) — Ihre generierte REST aufrufen +- [`os explain`](/docs/reference/cli) — das gerenderte Schema ausgeben +- [`@objectstack/spec`-Quelle](https://github.com/objectstack-ai/framework/tree/main/packages/spec) — das Schema ist der Vertrag; alles hier wird daraus abgeleitet diff --git a/content/docs/build/data-model.es.mdx b/content/docs/build/data-model.es.mdx new file mode 100644 index 0000000..c7032a9 --- /dev/null +++ b/content/docs/build/data-model.es.mdx @@ -0,0 +1,261 @@ +--- +title: Modelo de datos +description: Objetos, campos, relaciones, validación, índices — descritos a la IA o escritos en TypeScript. +--- + +# Modelo de datos + +El modelo de datos es la única fuente de verdad de tu aplicación. Una vez +que existe un objeto, ObjectOS te ofrece APIs REST, una vista en Console, puntos +de control de RBAC, entradas en el registro de auditoría y exposición de +herramientas de IA — de forma gratuita. + +**La mayoría de los clientes nunca escriben el esquema a mano.** Describen lo +que necesitan en el [AI Builder](/docs/build/ai-builder) y la +plataforma crea los objetos, campos, índices y traducciones. Esta +página describe la forma subyacente — para que entiendas lo que la IA +está generando y puedas editarlo directamente cuando quieras. + +## Vías de creación + +| Vía | Cómo se ve | +|---|---| +| **AI Builder** (principal) | *"Crea un objeto `support_ticket` con asunto, descripción, prioridad, estado y responsable."* | +| **Construcción con clics en Console** | Console → Objects → New Object → formularios | +| **TypeScript (`*.object.ts`)** | El TS que se muestra a continuación — normalmente dentro de una [plantilla](/docs/build/templates) bifurcada | + +Las tres producen el mismo esquema. El esquema es canónico; todo lo +demás se deriva de él. + +## Anatomía de un objeto + +```ts +// src/objects/task.ts +import { ObjectSchema, Field } from '@objectstack/spec/data'; + +export const Task = ObjectSchema.create({ + name: 'todo_task', + label: 'Task', + pluralLabel: 'Tasks', + icon: 'check-square', + description: 'A single unit of work.', + + fields: { + subject: Field.text({ label: 'Subject', required: true, maxLength: 200 }), + description: Field.markdown({ label: 'Description' }), + status: Field.select({ + label: 'Status', + options: [ + { label: 'To Do', value: 'todo', default: true }, + { label: 'In Progress', value: 'in_progress' }, + { label: 'Done', value: 'done' }, + ], + }), + due: Field.date({ label: 'Due' }), + assignee: Field.lookup('sys_user', { label: 'Assignee' }), + }, + + enable: { + trackHistory: true, // record field changes in audit log + apiEnabled: true, // expose REST endpoints (default true) + feeds: true, // chatter / comments / @mentions + }, +}); +``` + +Regístralo en tu stack: + +```ts +// objectstack.config.ts +import { defineStack } from '@objectstack/spec'; +import * as objects from './src/objects'; + +export default defineStack({ + manifest: { id: 'my.app', namespace: 'myapp', version: '0.1.0', type: 'app', name: 'My App' }, + objects: Object.values(objects), +}); +``` + +Eso es todo lo que necesitas. `os dev` recompila, y `/api/v1/data/todo_task`, +la vista Task de Console y la fila de permisos de Console aparecen todas. + +## Tipos de campo + +ObjectStack incluye unos 25 tipos de campo. Los más usados: + +### Escalares + +| Tipo | Qué almacena | Helper | +|---|---|---| +| `text` | Cadena corta | `Field.text({ maxLength, required })` | +| `textarea` | Cadena larga | `Field.textarea(...)` | +| `markdown` | Texto enriquecido con markdown | `Field.markdown(...)` | +| `number` | Entero | `Field.number({ min, max })` | +| `decimal` | Decimal exacto (dinero, etc.) | `Field.decimal({ precision, scale })` | +| `boolean` | Verdadero/falso | `Field.boolean({ defaultValue })` | +| `date` | Fecha de calendario | `Field.date(...)` | +| `datetime` | Marca de tiempo | `Field.datetime(...)` | +| `email` | Correo electrónico validado | `Field.email(...)` | +| `url` | URL validada | `Field.url(...)` | +| `phone` | Teléfono validado | `Field.phone(...)` | +| `json` | JSON arbitrario | `Field.json(...)` | + +### Opciones + +| Tipo | Se usa para | +|---|---| +| `select` | Opción única (enum) | +| `multiselect` | Varias opciones | + +### Relaciones + +| Tipo | Cardinalidad | Helper | +|---|---|---| +| `lookup` | Uno a muchos (FK) | `Field.lookup({ reference: 'sys_user' })` | +| `masterDetail` | Uno a muchos con eliminación en cascada | `Field.masterDetail({ reference: 'order' })` | + +### Archivos y multimedia + +| Tipo | Qué almacena | +|---|---| +| `attachment` | Un archivo mediante el servicio de almacenamiento | +| `image` | Adjunto de imagen con vista previa | + +### Calculados / derivados + +| Tipo | Comportamiento | +|---|---| +| `formula` | Calculado en el momento de la lectura a partir de una expresión CEL | +| `rollup` | Agregado de registros relacionados (suma/recuento/promedio) | +| `autoNumber` | Secuencia (`INV-{000001}`) | +| `created`, `lastModified` | Marcas de tiempo mantenidas por el sistema | +| `createdBy`, `lastModifiedBy` | Referencias de usuario mantenidas por el sistema | + +## Required / unique / default + +Modificadores comunes en cada campo escalar: + +```ts +Field.text({ + label: 'Code', + required: true, + unique: true, // unique constraint enforced at DB level + defaultValue: '', + helpText: 'Internal short code', +}) +``` + +## Validación + +En línea: + +```ts +Field.number({ label: 'Quantity', min: 1, max: 9999 }) +Field.text({ label: 'SKU', pattern: '^[A-Z]{3}-[0-9]{4}$' }) +``` + +Reglas a nivel de objeto (entre campos): + +```ts +ObjectSchema.create({ + name: 'order', + fields: { /* ... */ }, + validations: [ + { + name: 'discount_lt_total', + message: 'Discount cannot exceed total', + condition: 'discount < total', + }, + ], +}); +``` + +La validación se ejecuta en cada escritura — REST, Console, ObjectQL — por lo que +no hay "puerta trasera". + +## Índices y rendimiento + +```ts +ObjectSchema.create({ + name: 'order', + fields: { /* ... */ }, + indexes: [ + { fields: ['status', 'created_at'] }, + { fields: ['account', 'created_at'], unique: false }, + ], +}); +``` + +El controlador crea índices reales en la base de datos al sincronizar el esquema. + +## Grupos de campos + +Para formularios largos, agrupa los campos en Console: + +```ts +ObjectSchema.create({ + name: 'task', + fieldGroups: [ + { key: 'core', label: 'Task', icon: 'check-square' }, + { key: 'planning', label: 'Planning', icon: 'calendar' }, + { key: 'meta', label: 'Metadata', icon: 'info', defaultExpanded: false }, + ], + fields: { + subject: Field.text({ label: 'Subject', group: 'core' }), + due: Field.date({ label: 'Due', group: 'planning' }), + }, +}); +``` + +## Ciclo de vida y propiedad + +```ts +ObjectSchema.create({ + name: 'task', + ownership: 'own', // 'own' | 'shared' | 'system' + enable: { + apiEnabled: true, // generated REST endpoints + trackHistory: true, // audit log of field changes + feeds: true, // sys_comment / sys_activity / @mentions + softDelete: true, // tombstone instead of hard delete + }, +}); +``` + +## Objetos del sistema (gratuitos con cada proyecto) + +No tienes que declararlos — siempre están ahí: + +| Objeto | Qué | +|---|---| +| `sys_user` | Cuentas de usuario | +| `sys_org` | Organizaciones / tenants | +| `sys_member` | Pertenencia a una organización | +| `sys_role`, `sys_permission_set` | Primitivas de RBAC | +| `sys_audit_log` | Rastro de auditoría (cuando se carga la capacidad de auditoría) | +| `sys_file`, `sys_attachment` | Metadatos de archivos (cuando se carga el almacenamiento) | +| `sys_comment`, `sys_activity` | Feed / chatter (cuando se carga el feed) | +| `sys_session`, `sys_api_key` | Artefactos de autenticación | +| `sys_webhook`, `sys_webhook_delivery` | Suscripciones de webhook (cuando están habilitadas) | + +Haz referencia a ellos en los campos `lookup` por su nombre — p. ej. `Field.lookup({ reference: 'sys_user' })`. + +## Funciones polimórficas de la plataforma + +Cuando habilitas `feeds: true` y `trackHistory: true`, tu objeto +participa automáticamente en: + +- `sys_comment` (thread_id = `:`) +- `sys_attachment` (parent_object = ``, parent_id = ``) +- `sys_activity` (cronología) +- `sys_audit_log` (diferencias a nivel de campo) + +No conectas esto por cada objeto — es polimórfico en la plataforma. + +## Adónde ir a continuación + +- [Permisos](/docs/configure/permissions) — controla el acceso a tus objetos +- [Flujos / Automatización](/docs/build/flows) — reacciona a los cambios en los registros +- [Acceso a la API](/docs/configure/api-access) — llama a tu REST generado +- [`os explain`](/docs/reference/cli) — imprime el esquema renderizado +- [Código fuente de `@objectstack/spec`](https://github.com/objectstack-ai/framework/tree/main/packages/spec) — el esquema es el contrato; todo lo aquí descrito se deriva de él diff --git a/content/docs/build/data-model.fr.mdx b/content/docs/build/data-model.fr.mdx new file mode 100644 index 0000000..ad7abb2 --- /dev/null +++ b/content/docs/build/data-model.fr.mdx @@ -0,0 +1,263 @@ +--- +title: Modèle de données +description: Objets, champs, relations, validation, index — décrits à l'IA ou écrits en TypeScript. +--- + +# Modèle de données + +Le modèle de données est la source de vérité unique de votre application. Dès +qu'un objet existe, ObjectOS vous fournit des API REST, une vue Console, des +points de contrôle RBAC, des entrées de journal d'audit et une exposition aux +outils d'IA — gratuitement. + +**La plupart des clients n'écrivent jamais le schéma à la main.** Ils décrivent +ce dont ils ont besoin dans l'[AI Builder](/docs/build/ai-builder) et la +plateforme crée les objets, les champs, les index et les traductions. Cette +page décrit la structure sous-jacente — afin que vous compreniez ce que l'IA +génère et que vous puissiez la modifier directement quand vous le souhaitez. + +## Méthodes de création + +| Méthode | À quoi cela ressemble | +|---|---| +| **AI Builder** (principale) | *« Créer un objet `support_ticket` avec sujet, description, priorité, statut, responsable. »* | +| **Construction par clic dans la Console** | Console → Objects → New Object → formulaires | +| **TypeScript (`*.object.ts`)** | Le TS présenté ci-dessous — généralement à l'intérieur d'un [template](/docs/build/templates) forké | + +Les trois produisent le même schéma. Le schéma est canonique ; tout le reste en +est dérivé. + +## Anatomie d'un objet + +```ts +// src/objects/task.ts +import { ObjectSchema, Field } from '@objectstack/spec/data'; + +export const Task = ObjectSchema.create({ + name: 'todo_task', + label: 'Task', + pluralLabel: 'Tasks', + icon: 'check-square', + description: 'A single unit of work.', + + fields: { + subject: Field.text({ label: 'Subject', required: true, maxLength: 200 }), + description: Field.markdown({ label: 'Description' }), + status: Field.select({ + label: 'Status', + options: [ + { label: 'To Do', value: 'todo', default: true }, + { label: 'In Progress', value: 'in_progress' }, + { label: 'Done', value: 'done' }, + ], + }), + due: Field.date({ label: 'Due' }), + assignee: Field.lookup('sys_user', { label: 'Assignee' }), + }, + + enable: { + trackHistory: true, // record field changes in audit log + apiEnabled: true, // expose REST endpoints (default true) + feeds: true, // chatter / comments / @mentions + }, +}); +``` + +Enregistrez-le dans votre stack : + +```ts +// objectstack.config.ts +import { defineStack } from '@objectstack/spec'; +import * as objects from './src/objects'; + +export default defineStack({ + manifest: { id: 'my.app', namespace: 'myapp', version: '0.1.0', type: 'app', name: 'My App' }, + objects: Object.values(objects), +}); +``` + +C'est tout ce dont vous avez besoin. `os dev` recompile, et +`/api/v1/data/todo_task`, la vue Task de la Console et la ligne d'autorisation +de la Console apparaissent tous. + +## Types de champs + +ObjectStack fournit environ 25 types de champs. Les plus utilisés : + +### Scalaires + +| Type | Ce qu'il stocke | Helper | +|---|---|---| +| `text` | Chaîne courte | `Field.text({ maxLength, required })` | +| `textarea` | Chaîne longue | `Field.textarea(...)` | +| `markdown` | Texte enrichi avec markdown | `Field.markdown(...)` | +| `number` | Entier | `Field.number({ min, max })` | +| `decimal` | Décimal exact (monnaie, etc.) | `Field.decimal({ precision, scale })` | +| `boolean` | Vrai/faux | `Field.boolean({ defaultValue })` | +| `date` | Date du calendrier | `Field.date(...)` | +| `datetime` | Horodatage | `Field.datetime(...)` | +| `email` | E-mail validé | `Field.email(...)` | +| `url` | URL validée | `Field.url(...)` | +| `phone` | Téléphone validé | `Field.phone(...)` | +| `json` | JSON arbitraire | `Field.json(...)` | + +### Choix + +| Type | À utiliser pour | +|---|---| +| `select` | Choix unique (enum) | +| `multiselect` | Choix multiples | + +### Relations + +| Type | Cardinalité | Helper | +|---|---|---| +| `lookup` | Un-à-plusieurs (FK) | `Field.lookup({ reference: 'sys_user' })` | +| `masterDetail` | Un-à-plusieurs avec suppression en cascade | `Field.masterDetail({ reference: 'order' })` | + +### Fichiers et médias + +| Type | Ce qu'il stocke | +|---|---| +| `attachment` | Un fichier via le service de stockage | +| `image` | Pièce jointe image avec aperçu | + +### Calculé / dérivé + +| Type | Comportement | +|---|---| +| `formula` | Calculé à la lecture à partir d'une expression CEL | +| `rollup` | Agrégat d'enregistrements liés (somme/nombre/moyenne) | +| `autoNumber` | Séquence (`INV-{000001}`) | +| `created`, `lastModified` | Horodatages gérés par le système | +| `createdBy`, `lastModifiedBy` | Références utilisateur gérées par le système | + +## Requis / unique / par défaut + +Modificateurs courants sur chaque champ scalaire : + +```ts +Field.text({ + label: 'Code', + required: true, + unique: true, // unique constraint enforced at DB level + defaultValue: '', + helpText: 'Internal short code', +}) +``` + +## Validation + +En ligne : + +```ts +Field.number({ label: 'Quantity', min: 1, max: 9999 }) +Field.text({ label: 'SKU', pattern: '^[A-Z]{3}-[0-9]{4}$' }) +``` + +Règles au niveau de l'objet (entre champs) : + +```ts +ObjectSchema.create({ + name: 'order', + fields: { /* ... */ }, + validations: [ + { + name: 'discount_lt_total', + message: 'Discount cannot exceed total', + condition: 'discount < total', + }, + ], +}); +``` + +La validation s'exécute à chaque écriture — REST, Console, ObjectQL — il n'y a +donc aucune « porte dérobée ». + +## Index et performance + +```ts +ObjectSchema.create({ + name: 'order', + fields: { /* ... */ }, + indexes: [ + { fields: ['status', 'created_at'] }, + { fields: ['account', 'created_at'], unique: false }, + ], +}); +``` + +Le driver crée de vrais index de base de données lors de la synchronisation du +schéma. + +## Groupes de champs + +Pour les formulaires longs, regroupez les champs dans la Console : + +```ts +ObjectSchema.create({ + name: 'task', + fieldGroups: [ + { key: 'core', label: 'Task', icon: 'check-square' }, + { key: 'planning', label: 'Planning', icon: 'calendar' }, + { key: 'meta', label: 'Metadata', icon: 'info', defaultExpanded: false }, + ], + fields: { + subject: Field.text({ label: 'Subject', group: 'core' }), + due: Field.date({ label: 'Due', group: 'planning' }), + }, +}); +``` + +## Cycle de vie et propriété + +```ts +ObjectSchema.create({ + name: 'task', + ownership: 'own', // 'own' | 'shared' | 'system' + enable: { + apiEnabled: true, // generated REST endpoints + trackHistory: true, // audit log of field changes + feeds: true, // sys_comment / sys_activity / @mentions + softDelete: true, // tombstone instead of hard delete + }, +}); +``` + +## Objets système (gratuits avec chaque projet) + +Vous n'avez pas à les déclarer — ils sont toujours présents : + +| Objet | Quoi | +|---|---| +| `sys_user` | Comptes utilisateurs | +| `sys_org` | Organisations / locataires | +| `sys_member` | Appartenance à une organisation | +| `sys_role`, `sys_permission_set` | Primitives RBAC | +| `sys_audit_log` | Piste d'audit (lorsque la capacité d'audit est chargée) | +| `sys_file`, `sys_attachment` | Métadonnées de fichier (lorsque le stockage est chargé) | +| `sys_comment`, `sys_activity` | Fil / chatter (lorsque le fil est chargé) | +| `sys_session`, `sys_api_key` | Artefacts d'authentification | +| `sys_webhook`, `sys_webhook_delivery` | Abonnements webhook (lorsqu'ils sont activés) | + +Référencez-les dans les champs `lookup` par leur nom — par exemple `Field.lookup({ reference: 'sys_user' })`. + +## Fonctionnalités polymorphes de la plateforme + +Lorsque vous activez `feeds: true` et `trackHistory: true`, votre objet +participe automatiquement à : + +- `sys_comment` (thread_id = `:`) +- `sys_attachment` (parent_object = ``, parent_id = ``) +- `sys_activity` (chronologie) +- `sys_audit_log` (différences au niveau des champs) + +Vous ne câblez pas cela par objet — c'est polymorphe sur la plateforme. + +## Pour aller plus loin + +- [Permissions](/docs/configure/permissions) — contrôlez l'accès à vos objets +- [Flows / Automation](/docs/build/flows) — réagissez aux modifications d'enregistrements +- [API Access](/docs/configure/api-access) — appelez vos API REST générées +- [`os explain`](/docs/reference/cli) — affichez le schéma rendu +- [Source de `@objectstack/spec`](https://github.com/objectstack-ai/framework/tree/main/packages/spec) — le schéma est le contrat ; tout ce qui est ici en est dérivé diff --git a/content/docs/build/data-model.ja.mdx b/content/docs/build/data-model.ja.mdx new file mode 100644 index 0000000..81d23cb --- /dev/null +++ b/content/docs/build/data-model.ja.mdx @@ -0,0 +1,263 @@ +--- +title: データモデル +description: オブジェクト、フィールド、リレーションシップ、バリデーション、インデックス — AI に説明するか、TypeScript で記述します。 +--- + +# データモデル + +データモデルは、アプリにとって唯一の信頼できる情報源です。オブジェクトが +存在するようになると、ObjectOS は REST API、Console ビュー、RBAC の +チェックポイント、監査ログのエントリ、そして AI ツールへの公開を — 無償で +提供します。 + +**ほとんどのお客様はスキーマを手書きすることはありません。**必要なものを +[AI Builder](/docs/build/ai-builder) で説明すると、プラットフォームが +オブジェクト、フィールド、インデックス、翻訳を作成します。このページでは +その基盤となる構造を説明します — AI が生成しているものを理解し、必要に +応じて直接編集できるようにするためです。 + +## オーサリングのパス + +| パス | 具体例 | +|---|---| +| **AI Builder**(推奨) | *「subject、description、priority、status、assignee を持つ `support_ticket` オブジェクトを作成して。」* | +| **Console のクリックビルド** | Console → Objects → New Object → フォーム | +| **TypeScript(`*.object.ts`)** | 下に示す TS — 通常はフォークした[テンプレート](/docs/build/templates)の中で記述 | + +この 3 つはいずれも同じスキーマを生成します。スキーマが正規のものであり、 +それ以外はすべて派生物です。 + +## オブジェクトの構造 + +```ts +// src/objects/task.ts +import { ObjectSchema, Field } from '@objectstack/spec/data'; + +export const Task = ObjectSchema.create({ + name: 'todo_task', + label: 'Task', + pluralLabel: 'Tasks', + icon: 'check-square', + description: 'A single unit of work.', + + fields: { + subject: Field.text({ label: 'Subject', required: true, maxLength: 200 }), + description: Field.markdown({ label: 'Description' }), + status: Field.select({ + label: 'Status', + options: [ + { label: 'To Do', value: 'todo', default: true }, + { label: 'In Progress', value: 'in_progress' }, + { label: 'Done', value: 'done' }, + ], + }), + due: Field.date({ label: 'Due' }), + assignee: Field.lookup('sys_user', { label: 'Assignee' }), + }, + + enable: { + trackHistory: true, // record field changes in audit log + apiEnabled: true, // expose REST endpoints (default true) + feeds: true, // chatter / comments / @mentions + }, +}); +``` + +スタックに登録します: + +```ts +// objectstack.config.ts +import { defineStack } from '@objectstack/spec'; +import * as objects from './src/objects'; + +export default defineStack({ + manifest: { id: 'my.app', namespace: 'myapp', version: '0.1.0', type: 'app', name: 'My App' }, + objects: Object.values(objects), +}); +``` + +必要なのはこれだけです。`os dev` が再コンパイルを行い、`/api/v1/data/todo_task`、 +Console の Task ビュー、そして Console のパーミッション行がすべて表示されます。 + +## フィールドタイプ + +ObjectStack には約 25 種類のフィールドタイプが付属します。よく使われるものは +次のとおりです: + +### スカラー + +| タイプ | 格納する内容 | ヘルパー | +|---|---|---| +| `text` | 短い文字列 | `Field.text({ maxLength, required })` | +| `textarea` | 長い文字列 | `Field.textarea(...)` | +| `markdown` | markdown 形式のリッチテキスト | `Field.markdown(...)` | +| `number` | 整数 | `Field.number({ min, max })` | +| `decimal` | 正確な小数(金額など) | `Field.decimal({ precision, scale })` | +| `boolean` | 真偽値 | `Field.boolean({ defaultValue })` | +| `date` | カレンダー日付 | `Field.date(...)` | +| `datetime` | タイムスタンプ | `Field.datetime(...)` | +| `email` | バリデーション済みメールアドレス | `Field.email(...)` | +| `url` | バリデーション済み URL | `Field.url(...)` | +| `phone` | バリデーション済み電話番号 | `Field.phone(...)` | +| `json` | 任意の JSON | `Field.json(...)` | + +### 選択肢 + +| タイプ | 用途 | +|---|---| +| `select` | 単一選択(列挙) | +| `multiselect` | 複数選択 | + +### リレーションシップ + +| タイプ | カーディナリティ | ヘルパー | +|---|---|---| +| `lookup` | 一対多(FK) | `Field.lookup({ reference: 'sys_user' })` | +| `masterDetail` | カスケード削除付きの一対多 | `Field.masterDetail({ reference: 'order' })` | + +### ファイルとメディア + +| タイプ | 格納する内容 | +|---|---| +| `attachment` | ストレージサービス経由の単一ファイル | +| `image` | プレビュー付きの画像添付 | + +### 計算 / 派生 + +| タイプ | 動作 | +|---|---| +| `formula` | CEL 式から読み取り時に計算 | +| `rollup` | 関連レコードの集計(sum/count/avg) | +| `autoNumber` | シーケンス(`INV-{000001}`) | +| `created`, `lastModified` | システムが保守するタイムスタンプ | +| `createdBy`, `lastModifiedBy` | システムが保守するユーザー参照 | + +## 必須 / 一意 / デフォルト + +すべてのスカラーフィールドで共通の修飾子: + +```ts +Field.text({ + label: 'Code', + required: true, + unique: true, // unique constraint enforced at DB level + defaultValue: '', + helpText: 'Internal short code', +}) +``` + +## バリデーション + +インライン: + +```ts +Field.number({ label: 'Quantity', min: 1, max: 9999 }) +Field.text({ label: 'SKU', pattern: '^[A-Z]{3}-[0-9]{4}$' }) +``` + +オブジェクトレベルのルール(フィールド間): + +```ts +ObjectSchema.create({ + name: 'order', + fields: { /* ... */ }, + validations: [ + { + name: 'discount_lt_total', + message: 'Discount cannot exceed total', + condition: 'discount < total', + }, + ], +}); +``` + +バリデーションはあらゆる書き込み時に実行されます — REST、Console、ObjectQL のいずれでも — +そのため「裏口」は存在しません。 + +## インデックスとパフォーマンス + +```ts +ObjectSchema.create({ + name: 'order', + fields: { /* ... */ }, + indexes: [ + { fields: ['status', 'created_at'] }, + { fields: ['account', 'created_at'], unique: false }, + ], +}); +``` + +ドライバーはスキーマ同期時に実際の DB インデックスを作成します。 + +## フィールドグループ + +長いフォームでは、Console 内でフィールドをグループ化します: + +```ts +ObjectSchema.create({ + name: 'task', + fieldGroups: [ + { key: 'core', label: 'Task', icon: 'check-square' }, + { key: 'planning', label: 'Planning', icon: 'calendar' }, + { key: 'meta', label: 'Metadata', icon: 'info', defaultExpanded: false }, + ], + fields: { + subject: Field.text({ label: 'Subject', group: 'core' }), + due: Field.date({ label: 'Due', group: 'planning' }), + }, +}); +``` + +## ライフサイクルと所有権 + +```ts +ObjectSchema.create({ + name: 'task', + ownership: 'own', // 'own' | 'shared' | 'system' + enable: { + apiEnabled: true, // generated REST endpoints + trackHistory: true, // audit log of field changes + feeds: true, // sys_comment / sys_activity / @mentions + softDelete: true, // tombstone instead of hard delete + }, +}); +``` + +## システムオブジェクト(すべてのプロジェクトで無償) + +これらを宣言する必要はありません — 常に存在します: + +| オブジェクト | 内容 | +|---|---| +| `sys_user` | ユーザーアカウント | +| `sys_org` | 組織 / テナント | +| `sys_member` | 組織のメンバーシップ | +| `sys_role`, `sys_permission_set` | RBAC のプリミティブ | +| `sys_audit_log` | 監査証跡(監査機能がロードされている場合) | +| `sys_file`, `sys_attachment` | ファイルのメタデータ(ストレージがロードされている場合) | +| `sys_comment`, `sys_activity` | フィード / chatter(フィードがロードされている場合) | +| `sys_session`, `sys_api_key` | 認証アーティファクト | +| `sys_webhook`, `sys_webhook_delivery` | Webhook サブスクリプション(有効化されている場合) | + +`lookup` フィールドでは名前で参照します — 例: `Field.lookup({ reference: 'sys_user' })`。 + +## ポリモーフィックなプラットフォーム機能 + +`feeds: true` と `trackHistory: true` を有効にすると、オブジェクトは +自動的に次の機能に参加します: + +- `sys_comment`(thread_id = `:`) +- `sys_attachment`(parent_object = ``、parent_id = ``) +- `sys_activity`(タイムライン) +- `sys_audit_log`(フィールドレベルの差分) + +これらをオブジェクトごとに配線する必要はありません — プラットフォーム上で +ポリモーフィックに動作します。 + +## 次に読むべきもの + +- [パーミッション](/docs/configure/permissions) — オブジェクトへのアクセスを制御 +- [フロー / 自動化](/docs/build/flows) — レコードの変更に反応 +- [API アクセス](/docs/configure/api-access) — 生成された REST を呼び出す +- [`os explain`](/docs/reference/cli) — レンダリングされたスキーマを出力 +- [`@objectstack/spec` ソース](https://github.com/objectstack-ai/framework/tree/main/packages/spec) — スキーマが契約であり、ここに記載されているものはすべてそこから派生します diff --git a/content/docs/build/data-model.mdx b/content/docs/build/data-model.mdx index 3354dc0..c4b03d2 100644 --- a/content/docs/build/data-model.mdx +++ b/content/docs/build/data-model.mdx @@ -51,7 +51,7 @@ export const Task = ObjectSchema.create({ ], }), due: Field.date({ label: 'Due' }), - assignee: Field.lookup({ label: 'Assignee', reference: 'sys_user' }), + assignee: Field.lookup('sys_user', { label: 'Assignee' }), }, enable: { diff --git a/content/docs/build/data-model.cn.mdx b/content/docs/build/data-model.zh-Hans.mdx similarity index 98% rename from content/docs/build/data-model.cn.mdx rename to content/docs/build/data-model.zh-Hans.mdx index 704bf58..be1ea48 100644 --- a/content/docs/build/data-model.cn.mdx +++ b/content/docs/build/data-model.zh-Hans.mdx @@ -44,7 +44,7 @@ export const Task = ObjectSchema.create({ ], }), due: Field.date({ label: 'Due' }), - assignee: Field.lookup({ label: 'Assignee', reference: 'sys_user' }), + assignee: Field.lookup('sys_user', { label: 'Assignee' }), }, enable: { diff --git a/content/docs/build/flows.de.mdx b/content/docs/build/flows.de.mdx new file mode 100644 index 0000000..9d31255 --- /dev/null +++ b/content/docs/build/flows.de.mdx @@ -0,0 +1,237 @@ +--- +title: Flows & Automatisierung +description: Deklarative Geschäftslogik — der KI beschrieben oder in TypeScript geschrieben, die Runtime führt in beiden Fällen dasselbe Artefakt aus. +--- + +# Flows & Automatisierung + +Flows sind die Art, wie Sie Geschäftslogik ausdrücken, ohne einen Server zu schreiben. +Jeder Flow ist deklarative Metadaten, die die Runtime ausführt — genau so +wie Objekte und Views. Das bedeutet, dass Flows in `os diff`, im +Audit-Log, im Flow-Builder der Console und im [AI Builder](/docs/build/ai-builder) +gleichzeitig erscheinen. + +Die meisten Kunden erstellen Flows, indem sie die KI fragen: + +> *„Wenn ein Ticket mit hoher Priorität 30 Minuten lang im Status ‚new‘ +> bleibt, benachrichtige den Manager auf Slack."* + +Die KI generiert den unten stehenden Flow. Diese Seite beschreibt die Struktur, damit Sie +ihn lesen und bearbeiten können. + +Aktivieren Sie die Funktion in Ihrem Stack: + +```ts +export default defineStack({ + // ... + requires: ['automation'], +}); +``` + +## Drei Flow-Typen + +| Typ | Ausgelöst durch | Verwendung für | +|---|---|---| +| **Autolaunched** | Eine Datensatzänderung (insert/update/delete) | „Willkommens-E-Mail senden, wenn sich ein Benutzer registriert" | +| **Scheduled** | Cron-Ausdruck oder Intervall | „Veraltete Aufgaben jede Nacht um 2 Uhr markieren" | +| **Manual** | Benutzer klickt einen Button in der Console oder einen API-Aufruf | „Rechnung genehmigen"-Aktionen | + +## Autolaunched: auf eine Datensatzänderung reagieren + +```ts +// src/flows/welcome_email.ts +import { defineFlow } from '@objectstack/spec'; + +export const welcomeEmail = defineFlow({ + name: 'welcome_email', + type: 'autolaunched', + trigger: { + object: 'sys_user', + when: 'after_insert', + }, + steps: [ + { + type: 'action', + action: 'send_email', + inputs: { + to: '{!trigger.record.email}', + subject: 'Welcome to {!org.name}', + body: 'Hi {!trigger.record.name}, welcome aboard.', + }, + }, + ], +}); +``` + +Variableninterpolation: `{!trigger.record.}`, `{!org.}`, +`{!user.}`, `{!step..output}`. Verwenden Sie CEL-Ausdrücke in +`condition:`-Blöcken. + +Trigger-Zeitpunkt: + +| `when` | Wird ausgelöst | +|---|---| +| `before_insert` | Innerhalb der Schreibtransaktion, vor INSERT | +| `after_insert` | Nach dem Commit | +| `before_update` | Innerhalb der Schreibtransaktion, vor UPDATE | +| `after_update` | Nach dem Commit | +| `before_delete` | Innerhalb der Schreibtransaktion, vor DELETE | +| `after_delete` | Nach dem Commit | + +`before_*`-Flows können den zu schreibenden Datensatz verändern (Felder berechnen, +Daten normalisieren). `after_*`-Flows laufen asynchron und können langsame externe +Dienste aufrufen. + +## Scheduled: nach der Uhr ausführen + +```ts +export const nightlyCleanup = defineFlow({ + name: 'nightly_cleanup', + type: 'scheduled', + schedule: { cron: '0 2 * * *', timezone: 'America/New_York' }, + steps: [ + { + type: 'query', + query: { object: 'task', filter: 'status:open AND due_lt:now()' }, + output: 'stale', + }, + { + type: 'foreach', + items: '{!step.stale}', + do: [ + { type: 'update', record: '{!item.id}', fields: { status: 'overdue' } }, + ], + }, + ], +}); +``` + +Unterstützt durch die `@objectstack/service-job`-Funktion — siehe +[Runtime Capabilities](/docs/reference/runtime-capabilities). + +## Manual: Aktionen und Genehmigungen + +```ts +export const approveInvoice = defineFlow({ + name: 'approve_invoice', + type: 'manual', + inputs: { + invoice_id: { type: 'lookup', reference: 'invoice', required: true }, + note: { type: 'textarea' }, + }, + steps: [ + { + type: 'update', + record: '{!inputs.invoice_id}', + fields: { status: 'approved', approved_by: '{!user.id}' }, + }, + ], +}); +``` + +Stellen Sie ihn in der Console als Button in der Invoice-View bereit oder rufen Sie ihn per +REST auf: + +```bash +curl -X POST https://app.example.com/api/v1/actions/invoice/approve_invoice \ + -H 'Authorization: Bearer ' \ + -d '{"inputs": {"invoice_id": "inv_123", "note": "OK"}}' +``` + +## Step-Typen + +| Step | Zweck | +|---|---| +| `query` | Datensätze über ObjectQL lesen | +| `create` / `update` / `delete` | In Objekte schreiben | +| `action` | Eine integrierte oder über ein Plugin registrierte Aktion aufrufen (E-Mail, Webhook, KI-Aufruf, …) | +| `condition` | Anhand eines CEL-Ausdrucks verzweigen | +| `foreach` | Über eine Sammlung iterieren | +| `parallel` | Sub-Steps gleichzeitig ausführen | +| `wait` | Pausieren für eine Dauer / bis zu einem Zeitstempel / bis eine Bedingung erfüllt ist | +| `subflow` | Einen anderen Flow aufrufen | +| `approval` | Blockieren, bis ein Benutzer genehmigt (erfordert `@objectstack/plugin-approvals`) | + +## Bedingungen und Verzweigungen + +```ts +{ + type: 'condition', + when: 'trigger.record.amount > 10000', + then: [ + { type: 'action', action: 'send_slack', inputs: { /* ... */ } }, + ], + else: [ + { type: 'update', record: '{!trigger.record.id}', fields: { status: 'auto_approved' } }, + ], +} +``` + +## Fehlerbehandlung + +Jeder Step akzeptiert: + +```ts +{ + type: 'action', + action: 'send_email', + inputs: { /* ... */ }, + retry: { attempts: 3, backoffMs: 1000, multiplier: 2 }, + onError: 'continue' | 'fail' | 'rollback', +} +``` + +Bei autolaunched `before_*`-Flows bricht `onError: 'fail'` (Standard) die +ursprüngliche Schreibtransaktion ab. Bei `after_*`-Flows ist der ursprüngliche +Schreibvorgang bereits committet; fehlgeschlagene Flow-Läufe landen in der Job-Retry- +Warteschlange. + +## Formeln und Ausdrücke (CEL) + +Bedingungen, dynamische Feldwerte und Filterausdrücke akzeptieren alle +**CEL** (Common Expression Language) — Googles Sprache für die sichere +Auswertung von Ausdrücken: + +```ts +'amount > 10000 && account.tier == "enterprise"' +'duration(now() - created_at) > duration("30d")' +'has(record.notes) && record.notes != ""' +``` + +CEL ist sandboxed (keine Seiteneffekte, kein I/O), wird serverseitig ausgewertet und +ist im Flow-Builder auditierbar. + +## Visueller Builder + +Die Console bringt einen visuellen Flow-Builder mit, der sich verlustfrei mit den +deklarativen Metadaten austauscht — Nicht-Ingenieure können einen Flow bearbeiten, und er serialisiert +sich zurück in dieselbe Struktur wie das TypeScript, das Sie von Hand schreiben würden. + +## Flows testen + +```bash +os test --scenario "welcome email fires on signup" +``` + +## Grenzen & Best Practices + +- **Halten Sie Before-Hooks klein.** Sie blockieren die Schreibtransaktion. +- **Verwenden Sie `wait` statt langlaufender Steps.** Ein Flow, der schläft, + blockiert einen Worker; ein `wait until` gibt den Worker an den Pool zurück. +- **Verwenden Sie `parallel` für unabhängige Steps.** Die sequentielle Ausführung ist + der Standard. +- **Idempotenz ist wichtig.** Retries können denselben Step zweimal ausführen; + externe Seiteneffekte sollten dedupliziert werden (verwenden Sie die Flow-Run-ID als Schlüssel). +- **Audit-sensible Aktionen.** Flows, die Berechtigungen ändern oder + Datensätze löschen, sollten selbst in `sys_audit_log` protokollieren. + +## Wie es weitergeht + +- [Webhooks](/docs/configure/webhooks) — ausgehende Benachrichtigungen, oft + von Flows ausgelöst +- [Email](/docs/configure/email) — das Transportmittel der `send_email`-Aktion +- [AI Service](/docs/configure/ai) — `ai_call`-Aktion für LLM-Steps +- [API Access](/docs/configure/api-access) — manuelle Flows von + externen Systemen aufrufen +- [@objectstack/service-automation](https://github.com/objectstack-ai/framework/tree/main/packages/services/service-automation) + — Quellcode der Ausführungs-Engine diff --git a/content/docs/build/flows.es.mdx b/content/docs/build/flows.es.mdx new file mode 100644 index 0000000..1e92666 --- /dev/null +++ b/content/docs/build/flows.es.mdx @@ -0,0 +1,237 @@ +--- +title: Flujos y Automatización +description: Lógica de negocio declarativa — descrita a la IA o escrita en TypeScript, el runtime ejecuta el mismo artefacto en cualquiera de los dos casos. +--- + +# Flujos y Automatización + +Los flujos son la forma de expresar lógica de negocio sin escribir un servidor. +Cada flujo es metadato declarativo que el runtime ejecuta — igual +que los objetos y las vistas. Eso significa que los flujos aparecen en `os diff`, el +registro de auditoría, el constructor de flujos de Console y el [AI Builder](/docs/build/ai-builder) +todo a la vez. + +La mayoría de los clientes crean flujos pidiéndoselo a la IA: + +> *"Cuando un ticket de alta prioridad permanezca en 'new' durante 30 minutos, notifica +> al responsable por Slack."* + +La IA genera el flujo de abajo. Esta página describe su estructura para que puedas +leerlo y editarlo. + +Habilita la capacidad en tu stack: + +```ts +export default defineStack({ + // ... + requires: ['automation'], +}); +``` + +## Tres tipos de flujo + +| Tipo | Activado por | Úsalo para | +|---|---|---| +| **Autolaunched** | Un cambio en un registro (insert/update/delete) | "Enviar correo de bienvenida cuando un usuario se registra" | +| **Scheduled** | Expresión cron o intervalo | "Marcar tareas obsoletas cada noche a las 2am" | +| **Manual** | El usuario hace clic en un botón en Console, o una llamada a la API | Acciones de "Aprobar factura" | + +## Autolaunched: reaccionar a un cambio en un registro + +```ts +// src/flows/welcome_email.ts +import { defineFlow } from '@objectstack/spec'; + +export const welcomeEmail = defineFlow({ + name: 'welcome_email', + type: 'autolaunched', + trigger: { + object: 'sys_user', + when: 'after_insert', + }, + steps: [ + { + type: 'action', + action: 'send_email', + inputs: { + to: '{!trigger.record.email}', + subject: 'Welcome to {!org.name}', + body: 'Hi {!trigger.record.name}, welcome aboard.', + }, + }, + ], +}); +``` + +Interpolación de variables: `{!trigger.record.}`, `{!org.}`, +`{!user.}`, `{!step..output}`. Usa expresiones CEL en +los bloques `condition:`. + +Momento del trigger: + +| `when` | Se dispara | +|---|---| +| `before_insert` | Dentro de la transacción de escritura, antes del INSERT | +| `after_insert` | Después del commit | +| `before_update` | Dentro de la transacción de escritura, antes del UPDATE | +| `after_update` | Después del commit | +| `before_delete` | Dentro de la transacción de escritura, antes del DELETE | +| `after_delete` | Después del commit | + +Los flujos `before_*` pueden mutar el registro que se está escribiendo (calcular campos, +normalizar datos). Los flujos `after_*` se ejecutan de forma asíncrona y pueden llamar a servicios +externos lentos. + +## Scheduled: ejecutar según un reloj + +```ts +export const nightlyCleanup = defineFlow({ + name: 'nightly_cleanup', + type: 'scheduled', + schedule: { cron: '0 2 * * *', timezone: 'America/New_York' }, + steps: [ + { + type: 'query', + query: { object: 'task', filter: 'status:open AND due_lt:now()' }, + output: 'stale', + }, + { + type: 'foreach', + items: '{!step.stale}', + do: [ + { type: 'update', record: '{!item.id}', fields: { status: 'overdue' } }, + ], + }, + ], +}); +``` + +Respaldado por la capacidad `@objectstack/service-job` — consulta +[Runtime Capabilities](/docs/reference/runtime-capabilities). + +## Manual: acciones y aprobaciones + +```ts +export const approveInvoice = defineFlow({ + name: 'approve_invoice', + type: 'manual', + inputs: { + invoice_id: { type: 'lookup', reference: 'invoice', required: true }, + note: { type: 'textarea' }, + }, + steps: [ + { + type: 'update', + record: '{!inputs.invoice_id}', + fields: { status: 'approved', approved_by: '{!user.id}' }, + }, + ], +}); +``` + +Muéstralo en Console como un botón en la vista de Invoice, o invócalo mediante +REST: + +```bash +curl -X POST https://app.example.com/api/v1/actions/invoice/approve_invoice \ + -H 'Authorization: Bearer ' \ + -d '{"inputs": {"invoice_id": "inv_123", "note": "OK"}}' +``` + +## Tipos de paso + +| Paso | Propósito | +|---|---| +| `query` | Leer registros mediante ObjectQL | +| `create` / `update` / `delete` | Escribir en objetos | +| `action` | Invocar una acción integrada o registrada por un plugin (email, webhook, llamada a IA, …) | +| `condition` | Ramificar según una expresión CEL | +| `foreach` | Iterar sobre una colección | +| `parallel` | Ejecutar sub-pasos de forma concurrente | +| `wait` | Pausar durante una duración / hasta un timestamp / hasta una condición | +| `subflow` | Llamar a otro flujo | +| `approval` | Bloquear hasta que un usuario apruebe (requiere `@objectstack/plugin-approvals`) | + +## Condiciones y ramificaciones + +```ts +{ + type: 'condition', + when: 'trigger.record.amount > 10000', + then: [ + { type: 'action', action: 'send_slack', inputs: { /* ... */ } }, + ], + else: [ + { type: 'update', record: '{!trigger.record.id}', fields: { status: 'auto_approved' } }, + ], +} +``` + +## Manejo de errores + +Cada paso acepta: + +```ts +{ + type: 'action', + action: 'send_email', + inputs: { /* ... */ }, + retry: { attempts: 3, backoffMs: 1000, multiplier: 2 }, + onError: 'continue' | 'fail' | 'rollback', +} +``` + +Para los flujos autolaunched `before_*`, `onError: 'fail'` (por defecto) aborta +la transacción de escritura de origen. Para los flujos `after_*`, la escritura de origen +ya está confirmada; las ejecuciones de flujo fallidas pasan a la cola de reintentos +de jobs. + +## Fórmulas y expresiones (CEL) + +Las condiciones, los valores de campo dinámicos y las expresiones de filtro aceptan +todas **CEL** (Common Expression Language) — el lenguaje de Google para la evaluación +segura de expresiones: + +```ts +'amount > 10000 && account.tier == "enterprise"' +'duration(now() - created_at) > duration("30d")' +'has(record.notes) && record.notes != ""' +``` + +CEL está aislado en un sandbox (sin efectos secundarios, sin E/S), se evalúa en el servidor y +es auditable en el constructor de flujos. + +## Constructor visual + +Console incluye un constructor visual de flujos que va y vuelve con el +metadato declarativo — quienes no son ingenieros pueden editar un flujo, y este se serializa +de vuelta a la misma estructura que el TypeScript que escribirías a mano. + +## Probar flujos + +```bash +os test --scenario "welcome email fires on signup" +``` + +## Límites y buenas prácticas + +- **Mantén pequeños los before-hooks.** Bloquean la transacción de escritura. +- **Usa `wait` en lugar de pasos de larga duración.** Un flujo que duerme + bloquea un worker; un `wait until` devuelve el worker al pool. +- **Usa `parallel` para pasos independientes.** La ejecución secuencial es + la opción por defecto. +- **La idempotencia importa.** Los reintentos pueden ejecutar el mismo paso dos veces; + los efectos secundarios externos deben deduplicarse (usa el id de ejecución del flujo como clave). +- **Acciones sensibles para auditoría.** Los flujos que cambian permisos o + eliminan registros deberían registrar ellos mismos en `sys_audit_log`. + +## A dónde ir después + +- [Webhooks](/docs/configure/webhooks) — notificaciones salientes, a menudo + activadas desde flujos +- [Email](/docs/configure/email) — el transporte de la acción `send_email` +- [AI Service](/docs/configure/ai) — la acción `ai_call` para pasos con LLM +- [API Access](/docs/configure/api-access) — invocar flujos manuales desde + sistemas externos +- [@objectstack/service-automation](https://github.com/objectstack-ai/framework/tree/main/packages/services/service-automation) + — código fuente del motor de ejecución diff --git a/content/docs/build/flows.fr.mdx b/content/docs/build/flows.fr.mdx new file mode 100644 index 0000000..80ee2f3 --- /dev/null +++ b/content/docs/build/flows.fr.mdx @@ -0,0 +1,237 @@ +--- +title: Flux & Automatisation +description: Logique métier déclarative — décrite à l'IA ou écrite en TypeScript, le runtime exécute le même artefact dans les deux cas. +--- + +# Flux & Automatisation + +Les flux sont la façon d'exprimer la logique métier sans écrire de serveur. +Chaque flux est une métadonnée déclarative que le runtime exécute — au même +titre que les objets et les vues. Cela signifie que les flux apparaissent dans `os diff`, le +journal d'audit, le générateur de flux de la Console et l'[AI Builder](/docs/build/ai-builder) +tout à la fois. + +La plupart des clients créent des flux en demandant à l'IA : + +> *« Lorsqu'un ticket à haute priorité reste en statut « new » pendant 30 minutes, notifier +> le manager sur Slack. »* + +L'IA génère le flux ci-dessous. Cette page décrit sa structure afin que vous puissiez +le lire et le modifier. + +Activez la capacité dans votre stack : + +```ts +export default defineStack({ + // ... + requires: ['automation'], +}); +``` + +## Trois types de flux + +| Type | Déclenché par | À utiliser pour | +|---|---|---| +| **Autolaunched** | Une modification d'enregistrement (insertion/mise à jour/suppression) | « Envoyer un e-mail de bienvenue à l'inscription d'un utilisateur » | +| **Scheduled** | Expression cron ou intervalle | « Marquer les tâches obsolètes chaque nuit à 2h » | +| **Manual** | L'utilisateur clique sur un bouton dans la Console, ou un appel d'API | Actions « Approuver la facture » | + +## Autolaunched : réagir à une modification d'enregistrement + +```ts +// src/flows/welcome_email.ts +import { defineFlow } from '@objectstack/spec'; + +export const welcomeEmail = defineFlow({ + name: 'welcome_email', + type: 'autolaunched', + trigger: { + object: 'sys_user', + when: 'after_insert', + }, + steps: [ + { + type: 'action', + action: 'send_email', + inputs: { + to: '{!trigger.record.email}', + subject: 'Welcome to {!org.name}', + body: 'Hi {!trigger.record.name}, welcome aboard.', + }, + }, + ], +}); +``` + +Interpolation de variables : `{!trigger.record.}`, `{!org.}`, +`{!user.}`, `{!step..output}`. Utilisez des expressions CEL dans +les blocs `condition:`. + +Moment de déclenchement : + +| `when` | Se déclenche | +|---|---| +| `before_insert` | À l'intérieur de la transaction d'écriture, avant l'INSERT | +| `after_insert` | Après le commit | +| `before_update` | À l'intérieur de la transaction d'écriture, avant l'UPDATE | +| `after_update` | Après le commit | +| `before_delete` | À l'intérieur de la transaction d'écriture, avant le DELETE | +| `after_delete` | Après le commit | + +Les flux `before_*` peuvent modifier l'enregistrement en cours d'écriture (calculer des champs, +normaliser des données). Les flux `after_*` s'exécutent de manière asynchrone et peuvent appeler des services externes +lents. + +## Scheduled : s'exécuter selon une horloge + +```ts +export const nightlyCleanup = defineFlow({ + name: 'nightly_cleanup', + type: 'scheduled', + schedule: { cron: '0 2 * * *', timezone: 'America/New_York' }, + steps: [ + { + type: 'query', + query: { object: 'task', filter: 'status:open AND due_lt:now()' }, + output: 'stale', + }, + { + type: 'foreach', + items: '{!step.stale}', + do: [ + { type: 'update', record: '{!item.id}', fields: { status: 'overdue' } }, + ], + }, + ], +}); +``` + +Reposant sur la capacité `@objectstack/service-job` — voir +[Runtime Capabilities](/docs/reference/runtime-capabilities). + +## Manual : actions et approbations + +```ts +export const approveInvoice = defineFlow({ + name: 'approve_invoice', + type: 'manual', + inputs: { + invoice_id: { type: 'lookup', reference: 'invoice', required: true }, + note: { type: 'textarea' }, + }, + steps: [ + { + type: 'update', + record: '{!inputs.invoice_id}', + fields: { status: 'approved', approved_by: '{!user.id}' }, + }, + ], +}); +``` + +Affichez-le dans la Console sous forme de bouton sur la vue Invoice, ou appelez-le via +REST : + +```bash +curl -X POST https://app.example.com/api/v1/actions/invoice/approve_invoice \ + -H 'Authorization: Bearer ' \ + -d '{"inputs": {"invoice_id": "inv_123", "note": "OK"}}' +``` + +## Types d'étapes + +| Étape | Objectif | +|---|---| +| `query` | Lire des enregistrements via ObjectQL | +| `create` / `update` / `delete` | Écrire dans les objets | +| `action` | Invoquer une action intégrée ou enregistrée par un plugin (e-mail, webhook, appel IA, …) | +| `condition` | Brancher selon une expression CEL | +| `foreach` | Itérer sur une collection | +| `parallel` | Exécuter des sous-étapes en parallèle | +| `wait` | Mettre en pause pendant une durée / jusqu'à un horodatage / jusqu'à une condition | +| `subflow` | Appeler un autre flux | +| `approval` | Bloquer jusqu'à ce qu'un utilisateur approuve (nécessite `@objectstack/plugin-approvals`) | + +## Conditions et branchements + +```ts +{ + type: 'condition', + when: 'trigger.record.amount > 10000', + then: [ + { type: 'action', action: 'send_slack', inputs: { /* ... */ } }, + ], + else: [ + { type: 'update', record: '{!trigger.record.id}', fields: { status: 'auto_approved' } }, + ], +} +``` + +## Gestion des erreurs + +Chaque étape accepte : + +```ts +{ + type: 'action', + action: 'send_email', + inputs: { /* ... */ }, + retry: { attempts: 3, backoffMs: 1000, multiplier: 2 }, + onError: 'continue' | 'fail' | 'rollback', +} +``` + +Pour les flux `before_*` de type autolaunched, `onError: 'fail'` (par défaut) interrompt +la transaction d'écriture d'origine. Pour les flux `after_*`, l'écriture d'origine +est déjà validée ; les exécutions de flux échouées sont placées dans la file d'attente de +nouvelle tentative des jobs. + +## Formules et expressions (CEL) + +Les conditions, valeurs de champ dynamiques et expressions de filtre acceptent toutes le +**CEL** (Common Expression Language) — le langage de Google pour l'évaluation sécurisée +d'expressions : + +```ts +'amount > 10000 && account.tier == "enterprise"' +'duration(now() - created_at) > duration("30d")' +'has(record.notes) && record.notes != ""' +``` + +Le CEL est isolé (sans effets de bord, sans I/O), évalué côté serveur, et +auditable dans le générateur de flux. + +## Générateur visuel + +La Console est livrée avec un générateur de flux visuel qui fait l'aller-retour avec la +métadonnée déclarative — les non-ingénieurs peuvent modifier un flux, et celui-ci se sérialise +de nouveau dans la même structure que le TypeScript que vous écririez à la main. + +## Tester les flux + +```bash +os test --scenario "welcome email fires on signup" +``` + +## Limites & bonnes pratiques + +- **Gardez les before-hooks petits.** Ils bloquent la transaction d'écriture. +- **Utilisez `wait` plutôt que des étapes de longue durée.** Un flux qui se met en veille + bloque un worker ; un `wait until` rend le worker au pool. +- **Utilisez `parallel` pour les étapes indépendantes.** L'exécution séquentielle est + le comportement par défaut. +- **L'idempotence est importante.** Les nouvelles tentatives peuvent exécuter la même étape deux fois ; + les effets de bord externes doivent dédupliquer (utilisez l'identifiant d'exécution du flux comme clé). +- **Actions sensibles à l'audit.** Les flux qui modifient des permissions ou + suppriment des enregistrements doivent eux-mêmes consigner dans `sys_audit_log`. + +## Où aller ensuite + +- [Webhooks](/docs/configure/webhooks) — notifications sortantes, souvent + déclenchées depuis les flux +- [Email](/docs/configure/email) — le transport de l'action `send_email` +- [AI Service](/docs/configure/ai) — l'action `ai_call` pour les étapes LLM +- [API Access](/docs/configure/api-access) — invoquer des flux manuels depuis des + systèmes externes +- [@objectstack/service-automation](https://github.com/objectstack-ai/framework/tree/main/packages/services/service-automation) + — code source du moteur d'exécution diff --git a/content/docs/build/flows.ja.mdx b/content/docs/build/flows.ja.mdx new file mode 100644 index 0000000..8e415dd --- /dev/null +++ b/content/docs/build/flows.ja.mdx @@ -0,0 +1,213 @@ +--- +title: フローと自動化 +description: 宣言的なビジネスロジック — AI に記述してもらうか TypeScript で記述するかにかかわらず、ランタイムはどちらの場合も同じアーティファクトを実行します。 +--- + +# フローと自動化 + +フローは、サーバーを書くことなくビジネスロジックを表現する方法です。 +すべてのフローは、ランタイムが実行する宣言的なメタデータであり、これはオブジェクトやビューと同じです。つまり、フローは `os diff`、監査ログ、Console のフロービルダー、そして [AI Builder](/docs/build/ai-builder) のすべてに一度に表示されます。 + +ほとんどのお客様は、AI に依頼してフローを作成します。 + +> *「優先度の高いチケットが 30 分間「new」のままになっていたら、Slack でマネージャーに通知して。」* + +AI は以下のフローを生成します。このページでは、その構造を読んで編集できるように説明します。 + +スタックでこの機能を有効にします。 + +```ts +export default defineStack({ + // ... + requires: ['automation'], +}); +``` + +## 3 つのフロータイプ + +| タイプ | トリガー元 | 用途 | +|---|---|---| +| **Autolaunched** | レコードの変更(挿入/更新/削除) | 「ユーザー登録時にウェルカムメールを送信する」 | +| **Scheduled** | Cron 式または間隔 | 「毎晩 2 時に古いタスクをマークする」 | +| **Manual** | ユーザーが Console でボタンをクリック、または API 呼び出し | 「請求書を承認する」アクション | + +## Autolaunched: レコードの変更に反応する + +```ts +// src/flows/welcome_email.ts +import { defineFlow } from '@objectstack/spec'; + +export const welcomeEmail = defineFlow({ + name: 'welcome_email', + type: 'autolaunched', + trigger: { + object: 'sys_user', + when: 'after_insert', + }, + steps: [ + { + type: 'action', + action: 'send_email', + inputs: { + to: '{!trigger.record.email}', + subject: 'Welcome to {!org.name}', + body: 'Hi {!trigger.record.name}, welcome aboard.', + }, + }, + ], +}); +``` + +変数の補間: `{!trigger.record.}`、`{!org.}`、 +`{!user.}`、`{!step..output}`。`condition:` ブロックでは CEL 式を使用します。 + +トリガーのタイミング: + +| `when` | 発火 | +|---|---| +| `before_insert` | 書き込みトランザクション内、INSERT の前 | +| `after_insert` | コミット後 | +| `before_update` | 書き込みトランザクション内、UPDATE の前 | +| `after_update` | コミット後 | +| `before_delete` | 書き込みトランザクション内、DELETE の前 | +| `after_delete` | コミット後 | + +`before_*` フローは、書き込まれるレコードを変更できます(フィールドの計算、データの正規化)。`after_*` フローは非同期で実行され、低速な外部サービスを呼び出すことができます。 + +## Scheduled: 時刻に従って実行する + +```ts +export const nightlyCleanup = defineFlow({ + name: 'nightly_cleanup', + type: 'scheduled', + schedule: { cron: '0 2 * * *', timezone: 'America/New_York' }, + steps: [ + { + type: 'query', + query: { object: 'task', filter: 'status:open AND due_lt:now()' }, + output: 'stale', + }, + { + type: 'foreach', + items: '{!step.stale}', + do: [ + { type: 'update', record: '{!item.id}', fields: { status: 'overdue' } }, + ], + }, + ], +}); +``` + +`@objectstack/service-job` 機能に支えられています。詳しくは [Runtime Capabilities](/docs/reference/runtime-capabilities) を参照してください。 + +## Manual: アクションと承認 + +```ts +export const approveInvoice = defineFlow({ + name: 'approve_invoice', + type: 'manual', + inputs: { + invoice_id: { type: 'lookup', reference: 'invoice', required: true }, + note: { type: 'textarea' }, + }, + steps: [ + { + type: 'update', + record: '{!inputs.invoice_id}', + fields: { status: 'approved', approved_by: '{!user.id}' }, + }, + ], +}); +``` + +Console で Invoice ビューのボタンとして表示するか、REST 経由で呼び出します。 + +```bash +curl -X POST https://app.example.com/api/v1/actions/invoice/approve_invoice \ + -H 'Authorization: Bearer ' \ + -d '{"inputs": {"invoice_id": "inv_123", "note": "OK"}}' +``` + +## ステップタイプ + +| ステップ | 目的 | +|---|---| +| `query` | ObjectQL でレコードを読み取る | +| `create` / `update` / `delete` | オブジェクトに書き込む | +| `action` | 組み込みアクションまたはプラグイン登録アクションを呼び出す(メール、Webhook、AI 呼び出し、…) | +| `condition` | CEL 式で分岐する | +| `foreach` | コレクションを反復処理する | +| `parallel` | サブステップを並行して実行する | +| `wait` | 一定時間 / タイムスタンプまで / 条件が満たされるまで一時停止する | +| `subflow` | 別のフローを呼び出す | +| `approval` | ユーザーが承認するまでブロックする(`@objectstack/plugin-approvals` が必要) | + +## 条件と分岐 + +```ts +{ + type: 'condition', + when: 'trigger.record.amount > 10000', + then: [ + { type: 'action', action: 'send_slack', inputs: { /* ... */ } }, + ], + else: [ + { type: 'update', record: '{!trigger.record.id}', fields: { status: 'auto_approved' } }, + ], +} +``` + +## エラー処理 + +各ステップは以下を受け付けます。 + +```ts +{ + type: 'action', + action: 'send_email', + inputs: { /* ... */ }, + retry: { attempts: 3, backoffMs: 1000, multiplier: 2 }, + onError: 'continue' | 'fail' | 'rollback', +} +``` + +autolaunched の `before_*` フローでは、`onError: 'fail'`(デフォルト)は元の書き込みトランザクションを中止します。`after_*` フローでは、元の書き込みはすでにコミットされており、失敗したフロー実行はジョブの再試行キューに入ります。 + +## 数式と式(CEL) + +条件、動的なフィールド値、フィルター式はすべて **CEL**(Common Expression Language)を受け付けます。これは、安全な式評価のための Google の言語です。 + +```ts +'amount > 10000 && account.tier == "enterprise"' +'duration(now() - created_at) > duration("30d")' +'has(record.notes) && record.notes != ""' +``` + +CEL はサンドボックス化されており(副作用なし、I/O なし)、サーバー側で評価され、フロービルダーで監査可能です。 + +## ビジュアルビルダー + +Console には、宣言的なメタデータとラウンドトリップするビジュアルフロービルダーが付属しています。エンジニアでない人でもフローを編集でき、手作業で記述する TypeScript と同じ構造にシリアライズされます。 + +## フローのテスト + +```bash +os test --scenario "welcome email fires on signup" +``` + +## 制限とベストプラクティス + +- **before フックは小さく保ちます。** 書き込みトランザクションをブロックします。 +- **長時間実行されるステップの代わりに `wait` を使用します。** スリープするフローはワーカーをブロックしますが、`wait until` はワーカーをプールに返します。 +- **独立したステップには `parallel` を使用します。** デフォルトは順次実行です。 +- **冪等性が重要です。** 再試行では同じステップが 2 回実行されることがあります。外部の副作用は重複排除する必要があります(フロー実行 ID をキーとして使用します)。 +- **監査が必要なアクション。** 権限を変更したりレコードを削除したりするフローは、それ自体を `sys_audit_log` に記録する必要があります。 + +## 次のステップ + +- [Webhooks](/docs/configure/webhooks) — アウトバウンド通知。多くの場合フローからトリガーされます +- [Email](/docs/configure/email) — `send_email` アクションのトランスポート +- [AI Service](/docs/configure/ai) — LLM ステップ用の `ai_call` アクション +- [API Access](/docs/configure/api-access) — 外部システムから手動フローを呼び出す +- [@objectstack/service-automation](https://github.com/objectstack-ai/framework/tree/main/packages/services/service-automation) + — 実行エンジンのソース diff --git a/content/docs/build/flows.mdx b/content/docs/build/flows.mdx index da596c1..cee7252 100644 --- a/content/docs/build/flows.mdx +++ b/content/docs/build/flows.mdx @@ -133,7 +133,7 @@ Surface it in Console as a button on the Invoice view, or call it via REST: ```bash -curl -X POST https://app.example.com/api/v1/data/invoice/actions/approve_invoice \ +curl -X POST https://app.example.com/api/v1/actions/invoice/approve_invoice \ -H 'Authorization: Bearer ' \ -d '{"inputs": {"invoice_id": "inv_123", "note": "OK"}}' ``` diff --git a/content/docs/build/flows.cn.mdx b/content/docs/build/flows.zh-Hans.mdx similarity index 79% rename from content/docs/build/flows.cn.mdx rename to content/docs/build/flows.zh-Hans.mdx index 6c8388a..2fe059e 100644 --- a/content/docs/build/flows.cn.mdx +++ b/content/docs/build/flows.zh-Hans.mdx @@ -1,17 +1,17 @@ --- title: 流程与自动化 -description: 声明式业务逻辑 —— 描述给 AI,或者用 TypeScript 写,运行时执行同一份产物。 +description: 声明式业务逻辑 —— 无论是描述给 AI 还是用 TypeScript 编写,运行时执行的都是同一份产物。 --- # 流程与自动化 -Flow 是你不写服务端就能表达业务逻辑的方式。每个 Flow 都是声明式元数据,由运行时执行 —— 与对象、视图一样。这意味着 Flow 会同时出现在 `os diff`、审计日志、Console 的流程构建器以及 [AI Builder](/docs/build/ai-builder) 中。 +Flow 是你不写服务端就能表达业务逻辑的方式。每个 Flow 都是声明式元数据,由运行时执行 —— 与对象、视图一样。这意味着 Flow 会同时出现在 `os diff`、审计日志、Console 的流程构建器以及 [AI Builder](/docs/build/ai-builder) 中。 多数客户通过对 AI 提问来创建 Flow: > *"当一个高优先级工单在 'new' 状态停留 30 分钟时,在 Slack 上通知经理。"* -AI 会生成下面的 Flow。本页描述其结构,以便你阅读和编辑。 +AI 会生成下面的 Flow。本页描述其结构,以便你阅读和编辑。 在 stack 中启用该能力: @@ -28,7 +28,7 @@ export default defineStack({ |---|---|---| | **Autolaunched** | 记录变更(insert/update/delete) | "用户注册时发欢迎邮件" | | **Scheduled** | Cron 表达式或间隔 | "每晚 2 点标记过期任务" | -| **Manual** | 用户在 Console 点按钮,或 API 调用 | "审批发票"等 Action | +| **Manual** | 用户在 Console 点按钮,或 API 调用 | "审批发票"等 Action | ## Autolaunched:对记录变更做出反应 @@ -70,7 +70,7 @@ export const welcomeEmail = defineFlow({ | `before_delete` | 写事务内、DELETE 之前 | | `after_delete` | 提交之后 | -`before_*` 流程可以修改正在写入的记录(计算字段、归一化数据)。`after_*` 流程异步运行,可以调用慢的外部服务。 +`before_*` 流程可以修改正在写入的记录(计算字段、归一化数据)。`after_*` 流程异步运行,可以调用慢的外部服务。 ## Scheduled:按时钟运行 @@ -118,10 +118,10 @@ export const approveInvoice = defineFlow({ }); ``` -在 Console 中作为 Invoice 视图上的按钮暴露,或通过 REST 调用: +在 Console 中作为 Invoice 视图上的按钮暴露,或通过 REST 调用: ```bash -curl -X POST https://app.example.com/api/v1/data/invoice/actions/approve_invoice \ +curl -X POST https://app.example.com/api/v1/actions/invoice/approve_invoice \ -H 'Authorization: Bearer ' \ -d '{"inputs": {"invoice_id": "inv_123", "note": "OK"}}' ``` @@ -169,7 +169,7 @@ curl -X POST https://app.example.com/api/v1/data/invoice/actions/approve_invoice } ``` -对于 autolaunched 的 `before_*` 流程,`onError: 'fail'`(默认)会终止原始写事务。对 `after_*` 流程,原始写已经提交,失败的流程运行会落到任务重试队列。 +对于 autolaunched 的 `before_*` 流程,`onError: 'fail'`(默认)会终止原始写事务。对 `after_*` 流程,原始写已经提交,失败的流程运行会落到任务重试队列。 ## 公式与表达式(CEL) @@ -185,7 +185,7 @@ CEL 是沙盒化的(无副作用、无 I/O)、服务端求值、并可在流程 ## 可视化构建器 -Console 自带一个可视化流程构建器,它与声明式元数据来回往返 —— 非工程师可以编辑流程,序列化结果与你手写的 TypeScript 同形。 +Console 自带一个可视化流程构建器,它与声明式元数据来回往返 —— 非工程师可以编辑流程,序列化结果与你手写的 TypeScript 同形。 ## 测试流程 @@ -196,14 +196,14 @@ os test --scenario "welcome email fires on signup" ## 限制与最佳实践 - **保持 before-hook 简短。**它们会阻塞写事务。 -- **用 `wait` 代替长时运行的步骤。**休眠的流程会占用 worker;`wait until` 会把 worker 还回池里。 +- **用 `wait` 代替长时运行的步骤。**休眠的流程会占用 worker;`wait until` 会把 worker 还回池里。 - **用 `parallel` 跑独立步骤。**默认是顺序执行。 -- **幂等很重要。**重试可能让同一步骤跑两次;外部副作用应去重(用流程运行 id 作为键)。 +- **幂等很重要。**重试可能让同一步骤跑两次;外部副作用应去重(用流程运行 id 作为键)。 - **审计敏感的 Action。**改权限或删记录的流程自身也应记录到 `sys_audit_log`。 ## 下一步 -- [Webhooks](/docs/configure/webhooks) —— 出站通知,常由流程触发 +- [Webhooks](/docs/configure/webhooks) —— 出站通知,常由流程触发 - [Email](/docs/configure/email) —— `send_email` Action 的传输层 - [AI Service](/docs/configure/ai) —— 用于 LLM 步骤的 `ai_call` Action - [API Access](/docs/configure/api-access) —— 从外部系统调用手动流程 diff --git a/content/docs/build/index.de.mdx b/content/docs/build/index.de.mdx new file mode 100644 index 0000000..514219b --- /dev/null +++ b/content/docs/build/index.de.mdx @@ -0,0 +1,61 @@ +--- +title: Erstellen +description: Wie Apps in ObjectOS zum Leben erwachen — durch Chatten mit der KI, durch Klicken in der Console oder durch das Forken einer Vorlage. +--- + +# Erstellen + +In ObjectOS schreibt der Kunde keine Metadaten. **Er beschreibt, was +er möchte, und die KI erstellt es.** Es gibt drei Wege, geordnet danach, +wie die meisten Menschen die Plattform tatsächlich nutzen: + +| Weg | Für wen | Ergebnis | +|---|---|---| +| **[AI Builder](/docs/build/ai-builder)** (primär) | Business-Anwender, Product Owner, jeder | Live-Metadaten in Ihrem Tenant, zur Genehmigung in der Warteschlange | +| **Console-Klickerstellung** (Fallback) | Admins, die Formulare bevorzugen | Dieselben Live-Metadaten | +| **[Vorlagen-Fork](/docs/build/templates)** (Entwicklerweg) | Ingenieure, die Code unter Versionskontrolle wollen | Ein TypeScript-Paket, ausgeliefert über den marketplace | + +Alle drei Wege erzeugen **dieselbe Artefaktform** — Pakete aus +Objekten, Feldern, Ansichten, Aktionen, Flows, Berechtigungen. Die Plattform +kümmert sich nicht darum, wie die Metadaten dorthin gelangt sind. + +## Das Plattform-Vokabular + +Jede App ist aus denselben Grundbausteinen zusammengesetzt. Lernen Sie diese einmal. + +| Konzept | Was es ist | Dokumentation | +|---|---|---| +| **[Package](/docs/build/packages)** | Die Organisationseinheit — `com.acme.crm`, versioniert, installierbar | Packages | +| **[Datenmodell](/docs/build/data-model)** | Objekte + Felder + Beziehungen + Zustandsautomaten | Data Model | +| **[Aktionen](/docs/build/actions)** | Benannte Operationen, aufrufbar über REST, Console-Schaltflächen, Flows oder KI-Agenten | Actions | +| **[Flows](/docs/build/flows)** | Deklarative Geschäftslogik (automatisch gestartet / geplant / manuell) | Flows | +| **[Agenten](/docs/build/agents)** | KI-Assistenten für Endanwender — Agent → Skill → Tool | Agents | +| **[Marketplace](/docs/build/marketplace)** | Fertige Pakete, die jeder mit einem Klick installieren kann | Marketplace | + +## Wo Sie beginnen sollten + +1. **Nur am Erkunden?** → Öffnen Sie die Console, starten Sie den [AI Builder](/docs/build/ai-builder), + sagen Sie *„Ich muss Kundensupport-Tickets mit Priorität, Status und Bearbeiter verfolgen."* + In weniger als 30 Sekunden haben Sie ein funktionierendes Objekt. + +2. **Ein echtes Produkt darauf aufbauen?** → Lesen Sie [Packages](/docs/build/packages) + und [Data Model](/docs/build/data-model), damit Sie verstehen, was die + KI generiert. Nutzen Sie die KI zum Entwerfen, verfeinern Sie von Hand oder per Chat + und committen Sie das Ergebnis. + +3. **Eine Salesforce-/Retool-App ablösen?** → Forken Sie die am besten passende + [marketplace-Vorlage](/docs/build/marketplace), entfernen Sie, was Sie + nicht brauchen, und bitten Sie die KI, die Lücken zu füllen. + +## Was Sie nie tun müssen + +- Einen REST-Endpunkt schreiben. Die Plattform generiert einen pro Objekt. +- Ein Console-Formular verdrahten. Das Formular wird aus dem Schema gerendert. +- RBAC-Prüfungen schreiben. Berechtigungen werden deklariert, nicht codiert. +- Eine Admin-Oberfläche bauen. Console + Account decken sowohl System- als auch Business-Administration ab. +- Typen generieren. `@objectstack/spec` leitet sie aus dem Schema ab. + +ObjectOS ist hierin bewusst meinungsstark: **Sobald Metadaten +existieren, erscheint jede Oberfläche (REST, Console, ObjectQL, Audit, KI-Tools) +kostenlos.** Deshalb funktioniert der AI Builder — er muss nur +Metadaten erzeugen, und die Plattform erledigt den Rest. diff --git a/content/docs/build/index.es.mdx b/content/docs/build/index.es.mdx new file mode 100644 index 0000000..bc8c756 --- /dev/null +++ b/content/docs/build/index.es.mdx @@ -0,0 +1,61 @@ +--- +title: Construir +description: Cómo cobran vida las aplicaciones en ObjectOS — conversando con la IA, haciendo clic en la Console o bifurcando una plantilla. +--- + +# Construir + +En ObjectOS el cliente no escribe metadatos. **Describe lo que +quiere y la IA lo construye.** Existen tres caminos, ordenados según +cómo la mayoría de la gente usa realmente la plataforma: + +| Camino | Para quién es | Resultado | +|---|---|---| +| **[AI Builder](/docs/build/ai-builder)** (principal) | Usuarios de negocio, responsables de producto, cualquiera | Metadatos en vivo en tu tenant, en cola para aprobación | +| **Construcción por clics en Console** (alternativa) | Administradores que prefieren formularios | Los mismos metadatos en vivo | +| **[Bifurcación de plantilla](/docs/build/templates)** (camino para desarrolladores) | Ingenieros que quieren código bajo control de versiones | Un paquete de TypeScript distribuido a través del marketplace | + +Los tres caminos producen **la misma forma de artefacto** — paquetes de +objetos, campos, vistas, acciones, flujos y permisos. A la plataforma +no le importa cómo llegaron los metadatos hasta allí. + +## El vocabulario de la plataforma + +Toda aplicación se compone de las mismas primitivas. Apréndelas una vez. + +| Concepto | Qué es | Documentación | +|---|---|---| +| **[Package](/docs/build/packages)** | La unidad de organización — `com.acme.crm`, versionada e instalable | Packages | +| **[Data model](/docs/build/data-model)** | Objetos + campos + relaciones + máquinas de estado | Data Model | +| **[Actions](/docs/build/actions)** | Operaciones con nombre invocables desde REST, botones de Console, flujos o agentes de IA | Actions | +| **[Flows](/docs/build/flows)** | Lógica de negocio declarativa (autolanzada / programada / manual) | Flows | +| **[Agents](/docs/build/agents)** | Asistentes de IA para usuarios finales — Agent → Skill → Tool | Agents | +| **[Marketplace](/docs/build/marketplace)** | Paquetes ya hechos que cualquiera puede instalar con un solo clic | Marketplace | + +## Por dónde empezar + +1. **¿Solo estás explorando?** → Abre Console, inicia el [AI Builder](/docs/build/ai-builder), + di *"Necesito hacer seguimiento de tickets de soporte al cliente con prioridad, estado y responsable asignado."* + Tendrás un objeto funcional en menos de 30 segundos. + +2. **¿Construyendo un producto real sobre la plataforma?** → Lee [Packages](/docs/build/packages) + y [Data Model](/docs/build/data-model) para entender lo que la + IA está generando. Usa la IA para crear un borrador, refínalo a mano o por chat, + y confirma el resultado. + +3. **¿Reemplazando una aplicación de Salesforce/Retool?** → Bifurca la + [plantilla del marketplace](/docs/build/marketplace) más parecida, elimina lo + que no necesites y pídele a la IA que rellene los huecos. + +## Lo que nunca tendrás que hacer + +- Escribir un endpoint REST. La plataforma genera uno por objeto. +- Conectar un formulario de Console. El formulario se renderiza a partir del esquema. +- Escribir comprobaciones de RBAC. Los permisos se declaran, no se programan. +- Construir una interfaz de administración. Console + Account cubren tanto la administración del sistema como la de negocio. +- Generar tipos. `@objectstack/spec` los deriva del esquema. + +ObjectOS es deliberadamente firme en esto: **una vez que los metadatos +existen, cada superficie (REST, Console, ObjectQL, auditoría, herramientas de IA) +aparece de forma gratuita.** Por eso funciona el AI Builder — solo necesita +producir metadatos, y la plataforma se encarga del resto. diff --git a/content/docs/build/index.fr.mdx b/content/docs/build/index.fr.mdx new file mode 100644 index 0000000..e436510 --- /dev/null +++ b/content/docs/build/index.fr.mdx @@ -0,0 +1,65 @@ +--- +title: Créer +description: Comment les applications prennent vie dans ObjectOS — en discutant avec l'IA, en cliquant dans Console ou en forkant un modèle. +--- + +# Créer + +Dans ObjectOS, le client n'écrit pas de métadonnées. **Il décrit ce +qu'il veut et l'IA le construit.** Trois approches existent, classées +selon la manière dont la plupart des gens utilisent réellement la +plateforme : + +| Approche | Pour qui | Résultat | +|---|---|---| +| **[AI Builder](/docs/build/ai-builder)** (principale) | Utilisateurs métier, product owners, tout le monde | Métadonnées en direct dans votre tenant, en attente d'approbation | +| **Construction par clic dans Console** (alternative) | Administrateurs qui préfèrent les formulaires | Les mêmes métadonnées en direct | +| **[Fork de modèle](/docs/build/templates)** (voie développeur) | Ingénieurs qui veulent du code sous contrôle de version | Un package TypeScript livré via le marketplace | + +Les trois approches produisent **la même forme d'artefact** — des +packages d'objets, de champs, de vues, d'actions, de flows et de +permissions. La plateforme se moque de la manière dont les métadonnées +ont été créées. + +## Le vocabulaire de la plateforme + +Chaque application est composée des mêmes primitives. Apprenez-les une +bonne fois. + +| Concept | Ce que c'est | Doc | +|---|---|---| +| **[Package](/docs/build/packages)** | L'unité d'organisation — `com.acme.crm`, versionné, installable | Packages | +| **[Data model](/docs/build/data-model)** | Objets + champs + relations + machines à états | Data Model | +| **[Actions](/docs/build/actions)** | Opérations nommées appelables depuis REST, boutons Console, flows ou agents IA | Actions | +| **[Flows](/docs/build/flows)** | Logique métier déclarative (autolancée / planifiée / manuelle) | Flows | +| **[Agents](/docs/build/agents)** | Assistants IA pour l'utilisateur final — Agent → Skill → Tool | Agents | +| **[Marketplace](/docs/build/marketplace)** | Packages prêts à l'emploi installables par tous en un clic | Marketplace | + +## Par où commencer + +1. **Vous explorez simplement ?** → Ouvrez Console, lancez l'[AI Builder](/docs/build/ai-builder), + dites *« J'ai besoin de suivre les tickets de support client avec priorité, statut et assigné. »* + Vous aurez un objet fonctionnel en moins de 30 secondes. + +2. **Vous construisez un véritable produit par-dessus ?** → Lisez [Packages](/docs/build/packages) + et [Data Model](/docs/build/data-model) pour comprendre ce que + l'IA génère. Utilisez l'IA pour ébaucher, affinez à la main ou par + chat, puis validez le résultat. + +3. **Vous remplacez une application Salesforce/Retool ?** → Forkez le + [modèle marketplace](/docs/build/marketplace) le plus proche, retirez ce + dont vous n'avez pas besoin et demandez à l'IA de combler les manques. + +## Ce que vous n'aurez jamais à faire + +- Écrire un endpoint REST. La plateforme en génère un par objet. +- Câbler un formulaire Console. Le formulaire est rendu à partir du schéma. +- Écrire des vérifications RBAC. Les permissions sont déclarées, pas codées. +- Construire une interface d'administration. Console + Account couvrent à la fois l'administration système et métier. +- Générer des types. `@objectstack/spec` les dérive à partir du schéma. + +ObjectOS est volontairement opinionné sur ce point : **dès lors que les +métadonnées existent, chaque surface (REST, Console, ObjectQL, audit, +outils IA) apparaît gratuitement.** C'est pourquoi l'AI Builder +fonctionne — il lui suffit de produire des métadonnées, et la +plateforme s'occupe du reste. diff --git a/content/docs/build/index.ja.mdx b/content/docs/build/index.ja.mdx new file mode 100644 index 0000000..f6ff3a4 --- /dev/null +++ b/content/docs/build/index.ja.mdx @@ -0,0 +1,53 @@ +--- +title: 構築 +description: ObjectOS でアプリが生まれる仕組み — AI とチャットする、Console でクリックする、あるいはテンプレートをフォークする。 +--- + +# 構築 + +ObjectOS では顧客がメタデータを記述することはありません。**やりたいことを説明すれば、AI がそれを構築します。** 多くの人が実際にプラットフォームを利用する順に、3 つの方法があります。 + +| 方法 | 対象ユーザー | 成果物 | +|---|---|---| +| **[AI Builder](/docs/build/ai-builder)**(メイン) | ビジネスユーザー、プロダクトオーナー、誰でも | テナント内のライブメタデータ。承認待ちのキューに入る | +| **Console によるクリック構築**(代替手段) | フォーム操作を好む管理者 | 同じライブメタデータ | +| **[テンプレートのフォーク](/docs/build/templates)**(開発者向け) | コードをソース管理下に置きたいエンジニア | marketplace 経由で配布される TypeScript パッケージ | + +3 つの方法はいずれも **同じ成果物の形** を生み出します — オブジェクト、フィールド、ビュー、アクション、フロー、権限のパッケージです。プラットフォームはメタデータがどのように作られたかを問いません。 + +## プラットフォームの語彙 + +すべてのアプリは同じプリミティブから構成されます。これらを一度学んでおきましょう。 + +| 概念 | 内容 | ドキュメント | +|---|---|---| +| **[Package](/docs/build/packages)** | 編成の単位 — `com.acme.crm`、バージョン管理され、インストール可能 | Packages | +| **[Data model](/docs/build/data-model)** | オブジェクト + フィールド + リレーションシップ + ステートマシン | Data Model | +| **[Actions](/docs/build/actions)** | REST、Console のボタン、フロー、AI エージェントから呼び出せる名前付きの操作 | Actions | +| **[Flows](/docs/build/flows)** | 宣言的なビジネスロジック(自動起動 / スケジュール / 手動) | Flows | +| **[Agents](/docs/build/agents)** | エンドユーザー向けの AI アシスタント — Agent → Skill → Tool | Agents | +| **[Marketplace](/docs/build/marketplace)** | 誰でもワンクリックでインストールできる既製のパッケージ | Marketplace | + +## どこから始めるか + +1. **まずは試してみたい?** → Console を開き、[AI Builder](/docs/build/ai-builder) を起動して、 + *「優先度、ステータス、担当者を持つカスタマーサポートのチケットを管理したい」* と言ってみましょう。 + 30 秒もかからずに動作するオブジェクトが手に入ります。 + +2. **本格的なプロダクトをその上に構築する?** → [Packages](/docs/build/packages) + と [Data Model](/docs/build/data-model) を読んで、AI が生成している内容を理解しましょう。 + AI で下書きを作り、手作業やチャットで調整し、結果をコミットします。 + +3. **Salesforce / Retool のアプリを置き換える?** → 最も近い + [marketplace テンプレート](/docs/build/marketplace) をフォークし、不要なものを削ぎ落とし、 + 足りない部分を AI に埋めてもらいましょう。 + +## 一切やらなくてよいこと + +- REST エンドポイントの記述。プラットフォームがオブジェクトごとに 1 つ生成します。 +- Console フォームの配線。フォームはスキーマからレンダリングされます。 +- RBAC チェックの記述。権限はコードではなく宣言されます。 +- 管理 UI の構築。Console + Account がシステム管理とビジネス管理の両方をカバーします。 +- 型の生成。`@objectstack/spec` がスキーマから型を導出します。 + +ObjectOS は意図的にこの点について方針を明確にしています。**メタデータが存在すれば、あらゆる接点(REST、Console、ObjectQL、監査、AI ツール)が自動的に現れます。** だからこそ AI Builder が機能するのです — AI はメタデータを生成しさえすればよく、残りはプラットフォームが処理します。 diff --git a/content/docs/build/index.mdx b/content/docs/build/index.mdx index 5ef22c2..a038cea 100644 --- a/content/docs/build/index.mdx +++ b/content/docs/build/index.mdx @@ -52,7 +52,7 @@ Every app is composed from the same primitives. Learn these once. - Write a REST endpoint. The platform generates one per object. - Wire a Console form. The form renders from the schema. - Write RBAC checks. Permissions are declared, not coded. -- Build an admin UI. Console + Console cover both system and business admin. +- Build an admin UI. Console + Account cover both system and business admin. - Generate types. `@objectstack/spec` derives them from the schema. ObjectOS is opinionated about this on purpose: **once metadata diff --git a/content/docs/build/index.cn.mdx b/content/docs/build/index.zh-Hans.mdx similarity index 88% rename from content/docs/build/index.cn.mdx rename to content/docs/build/index.zh-Hans.mdx index d7cd98b..abf6c9b 100644 --- a/content/docs/build/index.cn.mdx +++ b/content/docs/build/index.zh-Hans.mdx @@ -11,7 +11,7 @@ description: 在 ObjectOS 里应用是怎么诞生的 —— 跟 AI 对话、在 |---|---|---| | **[AI Builder](/docs/build/ai-builder)**(主路径) | 业务用户、产品负责人、任何人 | 你租户内的实时元数据,等待审批 | | **Console 点击构建**(兜底) | 偏好表单的管理员 | 同样的实时元数据 | -| **[模板 Fork](/docs/build/templates)**(开发者路径) | 想要代码进版本管理的工程师 | 通过应用市场分发的一个 TypeScript 包 | +| **[模板 Fork](/docs/build/templates)**(开发者路径) | 想要代码进版本管理的工程师 | 通过 marketplace 分发的一个 TypeScript 包 | 三条路径产出**同一种产物形态** —— 对象、字段、视图、Action、流程、权限的打包。平台不关心元数据是怎么来的。 @@ -26,7 +26,7 @@ description: 在 ObjectOS 里应用是怎么诞生的 —— 跟 AI 对话、在 | **[Actions](/docs/build/actions)** | 命名操作,可被 REST、Console 按钮、流程或 AI Agent 调用 | Actions | | **[流程](/docs/build/flows)** | 声明式业务逻辑(自动启动 / 定时 / 手动) | Flows | | **[Agents](/docs/build/agents)** | 面向终端用户的 AI 助手 —— Agent → Skill → Tool | Agents | -| **[应用市场](/docs/build/marketplace)** | 一键安装的现成包 | Marketplace | +| **[marketplace](/docs/build/marketplace)** | 一键安装的现成包 | Marketplace | ## 从哪里开始 @@ -39,7 +39,7 @@ description: 在 ObjectOS 里应用是怎么诞生的 —— 跟 AI 对话、在 用 AI 起草,手动或对话方式打磨,提交结果。 3. **替换 Salesforce/Retool 应用?** → Fork 最接近的 - [市场模板](/docs/build/marketplace),去掉不需要的部分, + [marketplace 模板](/docs/build/marketplace),去掉不需要的部分, 让 AI 补上空缺。 ## 你永远不需要做的事 @@ -47,7 +47,7 @@ description: 在 ObjectOS 里应用是怎么诞生的 —— 跟 AI 对话、在 - 写 REST 端点。平台为每个对象自动生成一个。 - 接 Console 表单。表单从 schema 渲染。 - 写 RBAC 检查。权限是声明的,不是写代码。 -- 构建管理 UI。Console + Console 覆盖系统和业务两类管理。 +- 构建管理 UI。Console + Account 覆盖系统和业务两类管理。 - 生成类型。`@objectstack/spec` 从 schema 派生它们。 ObjectOS 在这点上是有意为之的:**一旦元数据存在,所有界面(REST、Console、ObjectQL、审计、AI 工具)就自动出现。**这就是 AI Builder 能跑通的原因 —— 它只需要产出元数据,剩下的平台全包了。 diff --git a/content/docs/build/marketplace.cn.mdx b/content/docs/build/marketplace.cn.mdx deleted file mode 100644 index 376743c..0000000 --- a/content/docs/build/marketplace.cn.mdx +++ /dev/null @@ -1,97 +0,0 @@ ---- -title: 应用市场 -description: 把现成的应用安装到运行中的 ObjectOS,无需写代码。 ---- - -# 应用市场 - -ObjectOS 的应用市场让你把预构建的应用安装到运行中的 runtime —— 无需构建、无需重启、无需源码 checkout。这是上线第一天就把真实软件交付给用户的最快方式。 - -## 工作原理 - -每个 ObjectOS runtime 都默认启用 `MarketplaceProxy` 与 `MarketplaceInstallLocal` 插件。当你打开 Console(`/_console/`)时,Marketplace 标签会查询所配置的应用目录,并展示可安装的应用。 - -```text -你 ─→ Console ─→ Marketplace 标签 ─→ 选择应用 ─→ Install - ↓ - 产物合并进 kernel - ↓ - Console 重新渲染,带上新的 - 对象 / 视图 / 权限 - ↓ - 完成 —— 无需重启 -``` - -## 目录 - -| 目录 | 来源 | 何时使用 | -|---|---|---| -| **默认** | 随 runtime 镜像预打包 | 首次评估、演示、离线 | -| **ObjectStack 公共目录** | 公共应用注册表 | 最新的社区与第一方应用 | -| **私有目录** | 你自己发布的产物 | 不想公开的内部应用 | -| **本地** | 挂载到 runtime 的文件 | 气隙、定制构建 | - -目录来源通过 Marketplace 插件或环境变量配置;见 [Runtime Configuration](/docs/configure/runtime)。 - -## 默认目录里有什么 - -这些应用在 Console 里一键即可安装: - -| 应用 | 提供什么 | -|---|---| -| **Todo** | 通用任务与项目追踪 | -| **Contracts** | 合同生命周期(CLM),含 AI 条款抽取 | -| **Procurement** | 供应商、采购订单、三方匹配 | -| **Compliance** | SOC 2 / ISO 27001 控制项 + 证据收集 | -| **Helpdesk** | AI 优先的客户支持工单系统 | -| **Content** | 编辑日历 + 渠道 ROI | -| **HR** | 通讯录、组织架构、休假 | -| **Project** | 项目 / 任务 / 里程碑追踪 | - -源码在 [github.com/objectstack-ai/templates](https://github.com/objectstack-ai/templates) —— 克隆任一个作为定制应用的起点。 - -## 安装流程 - -1. **打开 Console** —— http://localhost:3000/_console/ -2. **登录** —— 若没有账号,在 `/_account/register` 注册 -3. **进入 Marketplace 标签** -4. **挑应用,点击 Install** -5. **刷新 Console** —— 新应用的对象、视图与 App 都出现了 - -幕后,Marketplace 拉取应用的编译产物,合并进运行中的 kernel,并把对象注册到 ObjectQL。如果应用定义了种子数据,会在首次安装时插入。 - -## 卸载 - -Console → Marketplace → 已安装应用 → Uninstall。该应用的对象从 kernel 中移除,其表被标记为待清理(数据默认保留;你选择是否删表)。 - -## 发布你自己的应用 - -任何用 `os init` 构建的项目都可以成为 Marketplace 应用。 - -```bash -os init my-app -t app --install -cd my-app -# ... 写对象、视图等 ... -os compile # → dist/objectstack.json -os package publish # 发布到目录 -``` - -要发布到公共目录,你需要一个注册表账号(`os login`)。要发布到私有目录,把 `OS_PACKAGE_REGISTRY` 指向你自己的注册表。 - -## 版本管理 - -每个已发布的应用都是不可变的。更新产生新版本。Runtime 按应用追踪 `installed_version` 与可用更新。当你订阅的目录有新版发布时,用户会在 Console 里看到一个 *"Update available"* 标记。 - -## 权限 - -安装应用需要 `manage_marketplace` 系统权限 —— 默认只有 **Setup Administrator** 权限集的成员拥有。普通用户看到的 Marketplace 是只读的。 - -## 气隙应用市场 - -对于无公网出口的部署,在你自己的网络中运行本地目录服务器,并把 ObjectOS 指向它。拓扑见 [Air-gapped](/docs/deploy/air-gapped)。 - -## 应用市场不是什么 - -- **不是代码分发渠道。**已发布的应用是编译产物 —— 它们以声明方式描述数据 + UI + 流程,不分发任意 JavaScript。 -- **不是沙盒。**已安装的应用对你的数据库拥有与 kernel 中任何东西同样的访问权 —— 安装来自不可信来源的应用前请先审阅产物。 -- **不是支付平台**(暂时)。公共目录里的应用都是免费的 Apache-2.0。商用 / 付费分发在路线图上。 diff --git a/content/docs/build/marketplace.de.mdx b/content/docs/build/marketplace.de.mdx new file mode 100644 index 0000000..1159a2f --- /dev/null +++ b/content/docs/build/marketplace.de.mdx @@ -0,0 +1,128 @@ +--- +title: Marketplace +description: Installieren Sie fertige Apps in eine laufende ObjectOS, ohne Code zu schreiben. +--- + +# Marketplace + +Der ObjectOS marketplace ermöglicht es Ihnen, vorgefertigte Apps in eine +laufende Runtime zu installieren — kein Build-Schritt, kein Neustart, +kein Source-Checkout. Es ist der schnellste Weg, um Benutzern bereits am +ersten Tag echte Software zur Verfügung zu stellen. + +## Funktionsweise + +Jede ObjectOS-Runtime wird standardmäßig mit aktivierten Plugins +`MarketplaceProxy` und `MarketplaceInstallLocal` ausgeliefert. Wenn Sie +die Console (`/_console/`) öffnen, fragt der Marketplace-Tab den +konfigurierten App-Katalog ab und zeigt installierbare Apps an. + +```text +You ─→ Console ─→ Marketplace tab ─→ pick app ─→ Install + ↓ + Artifact merged into kernel + ↓ + Console re-renders with new + objects / views / permissions + ↓ + Done — no restart +``` + +## Kataloge + +| Katalog | Quelle | Wann zu verwenden | +|---|---|---| +| **Default** | Vorgebündelt mit dem Runtime-Image | Erste Evaluierung, Demos, offline | +| **ObjectStack public catalog** | Öffentliche App-Registry | Neueste Community- + Erstanbieter-Apps | +| **Private catalog** | Ihre eigenen veröffentlichten Artefakte | Interne Apps, die nicht öffentlich sein sollen | +| **Local** | In die Runtime eingebundene Dateien | Air-Gapped, benutzerdefinierte Builds | + +Die Katalogquelle wird über das Marketplace-Plugin oder Umgebungsvariablen +konfiguriert; siehe [Runtime Configuration](/docs/configure/runtime). + +## Was im Standardkatalog enthalten ist + +Diese Apps lassen sich mit einem Klick in der Console installieren: + +| App | Was Sie damit erhalten | +|---|---| +| **Todo** | Universeller Aufgaben- und Projekt-Tracker | +| **Contracts** | Vertragslebenszyklus (CLM) mit KI-basierter Klauselextraktion | +| **Procurement** | Lieferanten, Bestellungen, 3-Wege-Abgleich | +| **Compliance** | SOC 2 / ISO 27001 Kontrollen + Nachweissammlung | +| **Helpdesk** | KI-first Kundensupport-Ticketing | +| **Content** | Redaktionskalender + Kanal-ROI | +| **HR** | Verzeichnis, Organigramm, Abwesenheiten | +| **Project** | Projekt-/Aufgaben-/Meilenstein-Tracking | + +Der Quellcode befindet sich unter +[github.com/objectstack-ai/templates](https://github.com/objectstack-ai/templates) — +klonen Sie eine davon als Ausgangspunkt für eine benutzerdefinierte App. + +## Installationsablauf + +1. **Console öffnen** — http://localhost:3000/_console/ +2. **Anmelden** — falls noch kein Konto existiert, registrieren Sie eines unter `/_account/register` +3. **Zum Marketplace-Tab navigieren** +4. **Eine App auswählen und auf Install klicken** +5. **Console neu laden** — die Objekte, Ansichten und Flows der neuen App erscheinen + +Im Hintergrund holt der Marketplace das kompilierte Artefakt der App, +führt es in den laufenden Kernel zusammen und registriert dessen Objekte +bei ObjectQL. Seed-Daten (falls die App welche definiert) werden bei der +ersten Installation eingefügt. + +## Deinstallation + +Über Console → Marketplace → installierte App → Uninstall. Die Objekte der +App werden aus dem Kernel entfernt und ihre Tabellen werden zur Bereinigung +markiert (Daten werden standardmäßig beibehalten; Sie entscheiden, ob +Tabellen gelöscht werden). + +## Eigene App veröffentlichen + +Alles, was Sie mit `os init` erstellen, kann zu einer Marketplace-App werden. + +```bash +os init my-app -t app --install +cd my-app +# ... write objects, views, etc. ... +os compile # → dist/objectstack.json +os package publish # publish to a catalog +``` + +Um im öffentlichen Katalog zu veröffentlichen, benötigen Sie ein +Registry-Konto (`os login`). Um in einem privaten Katalog zu +veröffentlichen, richten Sie `OS_PACKAGE_REGISTRY` auf Ihren eigenen aus. + +## Versionierung + +Jede veröffentlichte App ist unveränderlich. Updates erzeugen eine neue +Version. Die Runtime verfolgt die installierte Version + verfügbare Updates +pro App. Benutzer sehen ein Badge "Update available" in der Console, wenn +eine neue Version in einem Katalog veröffentlicht wird, den sie verfolgen. + +## Berechtigungen + +Die Installation von Apps erfordert die Systemberechtigung +`manage_marketplace` — standardmäßig besitzen nur Mitglieder des +Berechtigungssatzes **Setup Administrator** diese. Normale Benutzer sehen +den Marketplace schreibgeschützt. + +## Air-Gapped-Marketplaces + +Für Bereitstellungen ohne Internet-Zugang betreiben Sie einen lokalen +Katalogserver innerhalb Ihres Netzwerks und richten ObjectOS darauf aus. +Siehe [Air-gapped](/docs/deploy/air-gapped) für die Topologie. + +## Was der Marketplace nicht ist + +- **Kein Code-Distributionskanal.** Veröffentlichte Apps sind kompilierte + Artefakte — sie beschreiben Daten + UI + Flows deklarativ. Sie liefern + keinen beliebigen JavaScript-Code aus. +- **Keine Sandbox.** Eine installierte App hat denselben Zugriff auf Ihre + Datenbank wie alles andere im Kernel — prüfen Sie das Artefakt, bevor Sie + Apps aus nicht vertrauenswürdigen Quellen installieren. +- **Keine Zahlungsplattform** (noch nicht). Apps im öffentlichen Katalog sind + kostenlos unter Apache-2.0. Kommerzielle / kostenpflichtige Distribution + steht auf der Roadmap. diff --git a/content/docs/build/marketplace.es.mdx b/content/docs/build/marketplace.es.mdx new file mode 100644 index 0000000..68a4274 --- /dev/null +++ b/content/docs/build/marketplace.es.mdx @@ -0,0 +1,129 @@ +--- +title: Marketplace +description: Instala aplicaciones listas para usar en un ObjectOS en ejecución sin escribir código. +--- + +# Marketplace + +El marketplace de ObjectOS te permite instalar aplicaciones preconstruidas en un +runtime en ejecución: sin paso de compilación, sin reinicios, sin descargar el +código fuente. Es la forma más rápida de poner software real frente a los +usuarios desde el primer día. + +## Cómo funciona + +Cada runtime de ObjectOS incluye los plugins `MarketplaceProxy` y +`MarketplaceInstallLocal` habilitados de forma predeterminada. Cuando abres +Console (`/_console/`), la pestaña del marketplace consulta el catálogo de +aplicaciones configurado y muestra las aplicaciones instalables. + +```text +You ─→ Console ─→ Marketplace tab ─→ pick app ─→ Install + ↓ + Artifact merged into kernel + ↓ + Console re-renders with new + objects / views / permissions + ↓ + Done — no restart +``` + +## Catálogos + +| Catálogo | Origen | Cuándo usarlo | +|---|---|---| +| **Default** | Preempaquetado con la imagen del runtime | Primera evaluación, demos, sin conexión | +| **ObjectStack public catalog** | Registro público de aplicaciones | Las aplicaciones más recientes de la comunidad y oficiales | +| **Private catalog** | Tus propios artefactos publicados | Aplicaciones internas que no quieres hacer públicas | +| **Local** | Archivos montados en el runtime | Entornos aislados, compilaciones personalizadas | + +El origen del catálogo se configura a través del plugin del marketplace o de +variables de entorno; consulta [Runtime Configuration](/docs/configure/runtime). + +## Qué incluye el catálogo predeterminado + +Estas aplicaciones están listas para instalarse con un clic en Console: + +| Aplicación | Lo que te ofrece | +|---|---| +| **Todo** | Seguimiento universal de tareas y proyectos | +| **Contracts** | Ciclo de vida de contratos (CLM) con extracción de cláusulas mediante IA | +| **Procurement** | Proveedores, órdenes de compra, conciliación de 3 vías | +| **Compliance** | Controles SOC 2 / ISO 27001 + recopilación de evidencias | +| **Helpdesk** | Gestión de tickets de soporte al cliente con IA como prioridad | +| **Content** | Calendario editorial + ROI por canal | +| **HR** | Directorio, organigrama, ausencias | +| **Project** | Seguimiento de proyectos / tareas / hitos | + +El código fuente está en +[github.com/objectstack-ai/templates](https://github.com/objectstack-ai/templates): +clona cualquiera de ellos como punto de partida para una aplicación personalizada. + +## Flujo de instalación + +1. **Abre Console** — http://localhost:3000/_console/ +2. **Inicia sesión** — si aún no existe ninguna cuenta, regístrate en `/_account/register` +3. **Navega a la pestaña del marketplace** +4. **Elige una aplicación y haz clic en Install** +5. **Recarga Console** — aparecen los objetos, las vistas y los flujos de la nueva aplicación + +Entre bastidores, el marketplace obtiene el artefacto compilado de la aplicación, +lo fusiona en el kernel en ejecución y registra sus objetos con ObjectQL. Los +datos de inicialización (si la aplicación los define) se insertan en la primera +instalación. + +## Desinstalación + +Desde Console → Marketplace → aplicación instalada → Uninstall. Los objetos de +la aplicación se eliminan del kernel y sus tablas se marcan para limpieza (los +datos se conservan de forma predeterminada; tú decides si eliminar las tablas). + +## Publicar tu propia aplicación + +Cualquier cosa que construyas con `os init` puede convertirse en una aplicación +del marketplace. + +```bash +os init my-app -t app --install +cd my-app +# ... write objects, views, etc. ... +os compile # → dist/objectstack.json +os package publish # publish to a catalog +``` + +Para publicar en el catálogo público necesitarás una cuenta de registro +(`os login`). Para publicar en un catálogo privado, apunta `OS_PACKAGE_REGISTRY` +al tuyo propio. + +## Versionado + +Cada aplicación publicada es inmutable. Las actualizaciones generan una nueva +versión. El runtime hace seguimiento de la versión instalada y de las +actualizaciones disponibles por aplicación. Los usuarios ven una insignia +"Update available" en Console cuando se publica una nueva versión en un catálogo +que están siguiendo. + +## Permisos + +La instalación de aplicaciones requiere el permiso de sistema +`manage_marketplace`: de forma predeterminada, solo los miembros del conjunto de +permisos **Setup Administrator** lo tienen. Los usuarios normales ven el +marketplace en modo de solo lectura. + +## Marketplaces en entornos aislados + +Para despliegues sin salida a internet, ejecuta un servidor de catálogo local +dentro de tu red y apunta ObjectOS hacia él. Consulta +[Air-gapped](/docs/deploy/air-gapped) para conocer la topología. + +## Qué no es el marketplace + +- **No es un canal de distribución de código.** Las aplicaciones publicadas son + artefactos compilados: describen datos + interfaz de usuario + flujos de forma + declarativa. No distribuyen JavaScript arbitrario. +- **No es un sandbox.** Una aplicación instalada tiene el mismo acceso a tu base + de datos que cualquier otro elemento del kernel: revisa el artefacto antes de + instalar aplicaciones de fuentes no confiables. +- **No es una plataforma de pagos** (todavía). Las aplicaciones del catálogo + público son gratuitas con licencia Apache-2.0. La distribución comercial / de + pago está en la hoja de ruta. diff --git a/content/docs/build/marketplace.fr.mdx b/content/docs/build/marketplace.fr.mdx new file mode 100644 index 0000000..baa4949 --- /dev/null +++ b/content/docs/build/marketplace.fr.mdx @@ -0,0 +1,134 @@ +--- +title: Marketplace +description: Installez des applications prêtes à l'emploi dans un ObjectOS en cours d'exécution, sans écrire de code. +--- + +# Marketplace + +Le marketplace ObjectOS vous permet d'installer des applications +préconstruites dans un runtime en cours d'exécution — sans étape de +build, sans redémarrage, sans récupération du code source. C'est le +moyen le plus rapide de mettre un vrai logiciel entre les mains des +utilisateurs dès le premier jour. + +## Comment ça fonctionne + +Chaque runtime ObjectOS est livré avec les plugins `MarketplaceProxy` et +`MarketplaceInstallLocal` activés par défaut. Lorsque vous ouvrez la +Console (`/_console/`), l'onglet marketplace interroge le catalogue +d'applications configuré et affiche les applications installables. + +```text +You ─→ Console ─→ Marketplace tab ─→ pick app ─→ Install + ↓ + Artifact merged into kernel + ↓ + Console re-renders with new + objects / views / permissions + ↓ + Done — no restart +``` + +## Catalogues + +| Catalogue | Source | Quand l'utiliser | +|---|---|---| +| **Default** | Préfourni avec l'image du runtime | Première évaluation, démos, hors ligne | +| **Catalogue public ObjectStack** | Registre public d'applications | Dernières applications de la communauté et propriétaires | +| **Catalogue privé** | Vos propres artefacts publiés | Applications internes que vous ne souhaitez pas rendre publiques | +| **Local** | Fichiers montés dans le runtime | Environnements isolés, builds personnalisés | + +La source du catalogue est configurée via le plugin marketplace ou des +variables d'environnement ; voir [Runtime Configuration](/docs/configure/runtime). + +## Ce que contient le catalogue par défaut + +Ces applications sont prêtes à être installées en un clic dans la Console : + +| Application | Ce qu'elle vous apporte | +|---|---| +| **Todo** | Suivi universel des tâches et des projets | +| **Contracts** | Cycle de vie des contrats (CLM) avec extraction de clauses par IA | +| **Procurement** | Fournisseurs, bons de commande, rapprochement à trois voies | +| **Compliance** | Contrôles SOC 2 / ISO 27001 + collecte de preuves | +| **Helpdesk** | Gestion de tickets de support client orientée IA | +| **Content** | Calendrier éditorial + ROI par canal | +| **HR** | Annuaire, organigramme, congés | +| **Project** | Suivi des projets / tâches / jalons | + +Le code source se trouve sur +[github.com/objectstack-ai/templates](https://github.com/objectstack-ai/templates) — +clonez l'un d'entre eux comme point de départ pour une application personnalisée. + +## Flux d'installation + +1. **Ouvrez la Console** — http://localhost:3000/_console/ +2. **Connectez-vous** — si aucun compte n'existe encore, créez-en un sur `/_account/register` +3. **Accédez à l'onglet marketplace** +4. **Choisissez une application, cliquez sur Install** +5. **Rechargez la Console** — les objets, vues et flux de la nouvelle application apparaissent + +En coulisses, le marketplace récupère l'artefact compilé de +l'application, le fusionne dans le kernel en cours d'exécution et +enregistre ses objets auprès d'ObjectQL. Les données initiales (si +l'application en définit) sont insérées lors de la première +installation. + +## Désinstallation + +Depuis Console → Marketplace → application installée → Uninstall. Les +objets de l'application sont supprimés du kernel et ses tables sont +marquées pour nettoyage (les données sont conservées par défaut ; vous +choisissez de supprimer ou non les tables). + +## Publier votre propre application + +Tout ce que vous construisez avec `os init` peut devenir une application +de marketplace. + +```bash +os init my-app -t app --install +cd my-app +# ... write objects, views, etc. ... +os compile # → dist/objectstack.json +os package publish # publish to a catalog +``` + +Pour publier sur le catalogue public, vous aurez besoin d'un compte de +registre (`os login`). Pour publier sur un catalogue privé, pointez +`OS_PACKAGE_REGISTRY` vers le vôtre. + +## Gestion des versions + +Chaque application publiée est immuable. Les mises à jour produisent une +nouvelle version. Le runtime suit la version installée et les mises à +jour disponibles pour chaque application. Les utilisateurs voient un +badge « Update available » dans la Console lorsqu'une nouvelle version +est publiée dans un catalogue qu'ils suivent. + +## Permissions + +L'installation d'applications nécessite la permission système +`manage_marketplace` — par défaut, seuls les membres de l'ensemble de +permissions **Setup Administrator** la possèdent. Les utilisateurs +ordinaires voient le marketplace en lecture seule. + +## Marketplaces en environnement isolé + +Pour les déploiements sans accès Internet sortant, exécutez un serveur +de catalogue local au sein de votre réseau et pointez ObjectOS vers +celui-ci. Voir [Air-gapped](/docs/deploy/air-gapped) pour la topologie. + +## Ce que le marketplace n'est pas + +- **Ce n'est pas un canal de distribution de code.** Les applications + publiées sont des artefacts compilés — elles décrivent données + UI + + flux de manière déclarative. Elles ne livrent pas de JavaScript + arbitraire. +- **Ce n'est pas un bac à sable.** Une application installée dispose du + même accès à votre base de données que tout le reste dans le kernel — + examinez l'artefact avant d'installer des applications provenant de + sources non fiables. +- **Ce n'est pas (encore) une plateforme de paiement.** Les applications + du catalogue public sont gratuites et sous licence Apache-2.0. La + distribution commerciale / payante figure sur la feuille de route. diff --git a/content/docs/build/marketplace.ja.mdx b/content/docs/build/marketplace.ja.mdx new file mode 100644 index 0000000..6a038ba --- /dev/null +++ b/content/docs/build/marketplace.ja.mdx @@ -0,0 +1,126 @@ +--- +title: marketplace +description: コードを書かずに、稼働中の ObjectOS に既製のアプリをインストールします。 +--- + +# marketplace + +ObjectOS の marketplace を使うと、ビルド手順もリスタートもソースのチェックアウトも不要で、 +稼働中のランタイムに構築済みのアプリをインストールできます。初日からユーザーに +実用的なソフトウェアを届ける最速の方法です。 + +## 仕組み + +すべての ObjectOS ランタイムには、デフォルトで `MarketplaceProxy` と +`MarketplaceInstallLocal` プラグインが有効化された状態で同梱されています。Console +(`/_console/`)を開くと、marketplace タブが設定済みのアプリ +カタログに問い合わせ、インストール可能なアプリを表示します。 + +```text +You ─→ Console ─→ Marketplace tab ─→ pick app ─→ Install + ↓ + Artifact merged into kernel + ↓ + Console re-renders with new + objects / views / permissions + ↓ + Done — no restart +``` + +## カタログ + +| カタログ | ソース | 使いどころ | +|---|---|---| +| **デフォルト** | ランタイムイメージにあらかじめ同梱 | 初回評価、デモ、オフライン | +| **ObjectStack 公開カタログ** | 公開アプリレジストリ | 最新のコミュニティ製 + ファーストパーティ製アプリ | +| **プライベートカタログ** | 自分で公開したアーティファクト | 公開したくない社内向けアプリ | +| **ローカル** | ランタイムにマウントしたファイル | エアギャップ環境、カスタムビルド | + +カタログのソースは marketplace プラグインまたは環境変数で設定します。 +詳しくは [Runtime Configuration](/docs/configure/runtime) を参照してください。 + +## デフォルトカタログに含まれるもの + +これらのアプリは Console でワンクリックですぐにインストールできます。 + +| アプリ | 提供される機能 | +|---|---| +| **Todo** | 汎用のタスク・プロジェクト管理ツール | +| **Contracts** | AI 条項抽出を備えた契約ライフサイクル管理(CLM) | +| **Procurement** | ベンダー、発注書、3-way マッチング | +| **Compliance** | SOC 2 / ISO 27001 統制 + エビデンス収集 | +| **Helpdesk** | AI ファーストのカスタマーサポートチケット管理 | +| **Content** | 編集カレンダー + チャネル ROI | +| **HR** | ディレクトリ、組織図、休暇管理 | +| **Project** | プロジェクト / タスク / マイルストーン管理 | + +ソースは +[github.com/objectstack-ai/templates](https://github.com/objectstack-ai/templates) +にあります。いずれかをクローンして、カスタムアプリの出発点として利用できます。 + +## インストールの流れ + +1. **Console を開く** — http://localhost:3000/_console/ +2. **サインインする** — まだアカウントがない場合は `/_account/register` で登録します +3. **marketplace タブに移動する** +4. **アプリを選び、Install をクリックする** +5. **Console をリロードする** — 新しいアプリのオブジェクト、ビュー、フローが表示されます + +裏側では、marketplace がアプリのコンパイル済みアーティファクトを取得し、 +稼働中の kernel にマージし、そのオブジェクトを ObjectQL に登録します。 +シードデータは(アプリが定義していれば)初回インストール時に挿入されます。 + +## アンインストール + +Console → Marketplace → インストール済みアプリ → Uninstall から行います。アプリの +オブジェクトは kernel から削除され、そのテーブルはクリーンアップ対象として +マークされます(データはデフォルトで保持され、テーブルを削除するかどうかは +ユーザーが選択します)。 + +## 自分のアプリを公開する + +`os init` で構築したものはすべて marketplace アプリにできます。 + +```bash +os init my-app -t app --install +cd my-app +# ... write objects, views, etc. ... +os compile # → dist/objectstack.json +os package publish # publish to a catalog +``` + +公開カタログに公開するにはレジストリアカウント(`os login`)が必要です。 +プライベートカタログに公開するには、`OS_PACKAGE_REGISTRY` を自分の +レジストリに向けてください。 + +## バージョニング + +公開されたアプリはすべてイミュータブルです。更新すると新しいバージョンが +生成されます。ランタイムはアプリごとにインストール済みバージョンと利用可能な +更新を追跡します。追跡対象のカタログに新しいバージョンが公開されると、 +ユーザーには Console に「Update available」バッジが表示されます。 + +## 権限 + +アプリのインストールには `manage_marketplace` システム権限が必要です。 +デフォルトでは **Setup Administrator** 権限セットのメンバーのみがこの権限を +持ちます。一般ユーザーには marketplace が読み取り専用で表示されます。 + +## エアギャップ環境の marketplace + +インターネット egress のないデプロイメントでは、ネットワーク内でローカルの +カタログサーバーを実行し、そこへ ObjectOS を向けます。トポロジーについては +[Air-gapped](/docs/deploy/air-gapped) を参照してください。 + +## marketplace ではないもの + +- **コード配布チャネルではありません。** 公開されるアプリはコンパイル済みの + アーティファクトであり、データ + UI + フローを宣言的に記述したものです。 + 任意の JavaScript を配布するものではありません。 +- **サンドボックスではありません。** インストールされたアプリは、kernel 内の + 他のあらゆるものと同じように、あなたのデータベースにアクセスできます。 + 信頼できないソースのアプリをインストールする前に、アーティファクトを確認して + ください。 +- **(まだ)決済プラットフォームではありません。** 公開カタログのアプリは + Apache-2.0 で無償提供されます。商用 / 有償の配布はロードマップに含まれて + います。 diff --git a/content/docs/build/marketplace.mdx b/content/docs/build/marketplace.mdx index 1c3d2bf..7700c46 100644 --- a/content/docs/build/marketplace.mdx +++ b/content/docs/build/marketplace.mdx @@ -64,7 +64,7 @@ clone any of them as a starting point for a custom app. 2. **Sign in** — if no account exists yet, register one at `/_account/register` 3. **Navigate to the marketplace tab** 4. **Pick an app, click Install** -5. **Reload Console** — the new app's objects, views, and apps appear +5. **Reload Console** — the new app's objects, views, and flows appear Behind the scenes, the marketplace fetches the app's compiled artifact, merges it into the running kernel, and registers its objects with diff --git a/content/docs/build/marketplace.zh-Hans.mdx b/content/docs/build/marketplace.zh-Hans.mdx new file mode 100644 index 0000000..56d8a6b --- /dev/null +++ b/content/docs/build/marketplace.zh-Hans.mdx @@ -0,0 +1,97 @@ +--- +title: Marketplace +description: 无需编写代码,即可将现成应用安装到运行中的 ObjectOS。 +--- + +# Marketplace + +ObjectOS marketplace 让你能够将预构建的应用安装到运行中的运行时——无需构建步骤、无需重启、无需检出源代码。这是在第一天就将真正的软件交付到用户面前的最快方式。 + +## 工作原理 + +每个 ObjectOS 运行时默认都启用了 `MarketplaceProxy` 和 `MarketplaceInstallLocal` 插件。当你打开 Console(`/_console/`)时,marketplace 标签页会查询已配置的应用目录,并展示可安装的应用。 + +```text +You ─→ Console ─→ Marketplace tab ─→ pick app ─→ Install + ↓ + Artifact merged into kernel + ↓ + Console re-renders with new + objects / views / permissions + ↓ + Done — no restart +``` + +## 目录 + +| 目录 | 来源 | 适用场景 | +|---|---|---| +| **Default** | 与运行时镜像预先打包 | 首次评估、演示、离线 | +| **ObjectStack public catalog** | 公共应用注册表 | 最新的社区应用与第一方应用 | +| **Private catalog** | 你自己发布的制品 | 不想公开的内部应用 | +| **Local** | 挂载到运行时中的文件 | 隔离网络环境、自定义构建 | + +目录来源通过 marketplace 插件或环境变量配置;参见[运行时配置](/docs/configure/runtime)。 + +## 默认目录中包含的内容 + +这些应用可以在 Console 中一键安装: + +| 应用 | 提供的能力 | +|---|---| +| **Todo** | 通用任务与项目跟踪器 | +| **Contracts** | 带 AI 条款提取的合同生命周期管理(CLM) | +| **Procurement** | 供应商、采购订单、三方匹配 | +| **Compliance** | SOC 2 / ISO 27001 控制项 + 证据收集 | +| **Helpdesk** | AI 优先的客户支持工单系统 | +| **Content** | 编辑日历 + 渠道 ROI | +| **HR** | 通讯录、组织架构图、休假 | +| **Project** | 项目 / 任务 / 里程碑跟踪 | + +源代码位于 [github.com/objectstack-ai/templates](https://github.com/objectstack-ai/templates)——可以克隆其中任意一个作为自定义应用的起点。 + +## 安装流程 + +1. **打开 Console**——http://localhost:3000/_console/ +2. **登录**——如果尚不存在账户,请在 `/_account/register` 注册一个 +3. **进入 marketplace 标签页** +4. **选择一个应用,点击 Install** +5. **重新加载 Console**——新应用的对象、视图和流程将会出现 + +在幕后,marketplace 会获取应用编译后的制品,将其合并到运行中的内核,并通过 ObjectQL 注册其对象。种子数据(如果应用定义了)会在首次安装时插入。 + +## 卸载 + +在 Console → Marketplace → 已安装的应用 → Uninstall。该应用的对象会从内核中移除,其数据表会被标记为待清理(默认情况下数据会被保留;你可以选择是否删除数据表)。 + +## 发布你自己的应用 + +任何通过 `os init` 构建的内容都可以成为一个 marketplace 应用。 + +```bash +os init my-app -t app --install +cd my-app +# ... write objects, views, etc. ... +os compile # → dist/objectstack.json +os package publish # publish to a catalog +``` + +要发布到公共目录,你需要一个注册表账户(`os login`)。要发布到私有目录,请将 `OS_PACKAGE_REGISTRY` 指向你自己的注册表。 + +## 版本管理 + +每个已发布的应用都是不可变的。更新会产生一个新版本。运行时会按应用跟踪已安装的版本以及可用的更新。当某个应用在用户所跟踪的目录中发布了新版本时,用户会在 Console 中看到一个 "Update available" 徽标。 + +## 权限 + +安装应用需要 `manage_marketplace` 系统权限——默认情况下只有 **Setup Administrator** 权限集的成员拥有该权限。普通用户看到的 marketplace 是只读的。 + +## 隔离网络环境下的 marketplace + +对于没有公网出口的部署环境,可在你的网络内运行一个本地目录服务器,并将 ObjectOS 指向它。拓扑结构请参见[隔离网络](/docs/deploy/air-gapped)。 + +## marketplace 不是什么 + +- **不是代码分发渠道。** 已发布的应用是编译后的制品——它们以声明式方式描述数据 + UI + 流程,不会分发任意 JavaScript。 +- **不是沙箱。** 已安装的应用对你数据库的访问权限与内核中的其他任何内容相同——在安装来自不可信来源的应用之前,请先审查制品。 +- **(暂时)不是支付平台。** 公共目录中的应用都是免费的 Apache-2.0 应用。商业 / 付费分发已列入路线图。 diff --git a/content/docs/build/meta.de.json b/content/docs/build/meta.de.json new file mode 100644 index 0000000..e9bf7cc --- /dev/null +++ b/content/docs/build/meta.de.json @@ -0,0 +1,17 @@ +{ + "title": "Erstellen", + "defaultOpen": false, + "pages": [ + "index", + "ai-builder", + "ai-skills", + "packages", + "data-model", + "views", + "actions", + "flows", + "agents", + "templates", + "marketplace" + ] +} diff --git a/content/docs/build/meta.es.json b/content/docs/build/meta.es.json new file mode 100644 index 0000000..163ab66 --- /dev/null +++ b/content/docs/build/meta.es.json @@ -0,0 +1,17 @@ +{ + "title": "Construir", + "defaultOpen": false, + "pages": [ + "index", + "ai-builder", + "ai-skills", + "packages", + "data-model", + "views", + "actions", + "flows", + "agents", + "templates", + "marketplace" + ] +} diff --git a/content/docs/build/meta.fr.json b/content/docs/build/meta.fr.json new file mode 100644 index 0000000..3bf62cd --- /dev/null +++ b/content/docs/build/meta.fr.json @@ -0,0 +1,17 @@ +{ + "title": "Construire", + "defaultOpen": false, + "pages": [ + "index", + "ai-builder", + "ai-skills", + "packages", + "data-model", + "views", + "actions", + "flows", + "agents", + "templates", + "marketplace" + ] +} diff --git a/content/docs/build/meta.ja.json b/content/docs/build/meta.ja.json new file mode 100644 index 0000000..0c5c4e0 --- /dev/null +++ b/content/docs/build/meta.ja.json @@ -0,0 +1,17 @@ +{ + "title": "構築", + "defaultOpen": false, + "pages": [ + "index", + "ai-builder", + "ai-skills", + "packages", + "data-model", + "views", + "actions", + "flows", + "agents", + "templates", + "marketplace" + ] +} diff --git a/content/docs/build/meta.cn.json b/content/docs/build/meta.zh-Hans.json similarity index 100% rename from content/docs/build/meta.cn.json rename to content/docs/build/meta.zh-Hans.json diff --git a/content/docs/build/packages.cn.mdx b/content/docs/build/packages.cn.mdx deleted file mode 100644 index 0052359..0000000 --- a/content/docs/build/packages.cn.mdx +++ /dev/null @@ -1,144 +0,0 @@ ---- -title: Packages -description: ObjectOS 的组织单元 —— 带版本、可安装、可分享。 ---- - -# Packages - -你在 ObjectOS 里构建的一切都活在一个 **package** 里:一个带版本、自包含的元数据包。Package 是 AI Builder 工作的单元、是 Marketplace 分发的单元、也是 ObjectOS 跟踪更新的单元。 - -## Package 里有什么 - -```text -com.acme.crm@1.2.0 -├── manifest id、version、namespace、dependencies -├── objects/ *.object.ts、*.state.ts、*.hook.ts -├── views/ *.view.ts、*.page.ts、*.form.ts -├── actions/ *.action.ts -├── flows/ *.flow.ts、*.approval.ts -├── agents/ *.agent.ts、*.skill.ts -├── permissions/ *.profile.ts -├── sharing/ *.sharing.ts -├── translations/ en.ts、zh-CN.ts、... -├── apps/ *.app.ts (navigation) -└── data/ defineDataset(...) 种子数据 -``` - -每个元数据产物(对象、Action、Flow……)都精确属于一个 package。Package id 用**反向 DNS**(`com.acme.crm`、`org.mycompany.helpdesk`),命名空间前缀(`crm_`、`hd_`)防止安装在同一租户里的多个 package 之间表名/对象名冲突。 - -## 创建 package - -### 通过 AI Builder - -> *"为我们的内部 CRM 起一个新 package,命名空间 `crm`。"* - -AI 会调用 `create_package` 与 `set_active_package`。从那以后,你描述的每个对象 / 字段 / Action 都落在 `crm` 里。 - -### 通过 CLI - -```bash -os init my-crm -t app --install -cd my-crm -# manifest 在 ./objectstack.manifest.json -pnpm dev -``` - -### 通过 Console - -**Console → Packages → New Package** —— 名称、id、版本、命名空间。 - -## 当前 package - -一次会话、一次 CLI 会话、一个 Console 管理视图各自携带一个**当前 package** —— 新元数据的默认容器。切换方式: - -| 表面 | 怎么切 | -|---|---| -| AI Builder | *"切到 `com.acme.helpdesk`。"*(工具 `set_active_package`) | -| CLI | `os package use com.acme.helpdesk` | -| Console | 顶栏 package 切换器 | -| REST | `X-Package-Id: com.acme.helpdesk` 请求头 | - -## 版本管理 - -Package 遵循 **semver**。规则与 runtime 相同 —— 见 [Changelog & Versioning](/docs/resources/changelog)。 - -升一个版本号在发布之前什么都不会改变。Runtime 按租户、按 package 跟踪 `installed_version`,当目录中有更新版本时,Marketplace 会展示 *"Update available"* 标记。 - -## 依赖 - -Package 可以依赖其他 package: - -```json -{ - "id": "com.acme.helpdesk", - "version": "0.3.0", - "dependencies": { - "com.acme.crm": "^1.0.0", - "sys.feeds": "*" - } -} -``` - -Runtime 在安装时解析依赖。如果 `com.acme.crm` 没装,helpdesk 的安装会以清晰错误失败。 - -系统 package(`sys.*`)永远存在 —— feeds、attachments、audit、identity 等等。 - -## 发布 - -```bash -os compile # → dist/objectstack.json -os package publish # → 配置好的注册表 -``` - -发布到 `OS_PACKAGE_REGISTRY` 指向的注册表(默认是 ObjectStack 公共目录)。私有 / 气隙场景,自己跑一个注册表,把这个环境变量指过去。见 [Marketplace](/docs/build/marketplace)。 - -## 安装 - -| 路径 | 方式 | -|---|---| -| Console | Marketplace 标签 → 选 package → Install | -| CLI | `os package install com.acme.helpdesk@^0.3.0` | -| REST | `POST /api/v1/marketplace/install` | -| 气隙 | 把 `dist/objectstack.json` 丢进本地目录 | - -安装会把 package 的元数据合并进运行中的 kernel,把对象注册到 ObjectQL,并在首次安装时灌入初始数据。无需重启。 - -## 卸载 - -卸载会把 package 标记为已移除,并反注册其对象。默认数据是**保留**的(可重装继续用)。传 `--drop-data` 删掉表。 - -## 跨 package 约定 - -为了避免多个 package 共存时碰撞: - -| 产物 | 约定 | -|---|---| -| 对象名 | 一律加前缀:`crm_account`、`hd_ticket` | -| Action 名 | 加前缀:`crm_assign_owner`、`hd_close_ticket` | -| Flow 名 | 加前缀:`hd_overdue_alert` | -| 翻译键 | 按命名空间作域:`crm.account.label` | -| 种子 `externalId` | `:`,如 `crm:demo-account-1` | -| 系统名 | 保留:`sys_*`(自定义 package 中绝不可用) | - -CLI 和 AI Builder 在创建时都会强制执行这些约定。 - -## 系统 packages - -Runtime 自带少量始终存在的 package,提供多态服务: - -| Package | 提供 | -|---|---| -| `sys.identity` | `sys_user`、`sys_org`、`sys_member`、session、API key | -| `sys.feeds` | `sys_comment`、`sys_activity`、`sys_attachment` | -| `sys.audit` | `sys_audit_log` | -| `sys.files` | `sys_file` | -| `sys.ai` | `sys_ai_conversation`、`sys_ai_pending_action` | -| `sys.settings` | `sys_setting` | - -你通过对象上的 `enable: { feeds: true, trackHistory: true, … }` 启用 —— 见 [Data Model](/docs/build/data-model)。 - -## 下一步 - -- [Marketplace](/docs/build/marketplace) —— 把 package 分发到其他租户 -- [Data Model](/docs/build/data-model) —— package 里面装什么 -- [`os package` 命令](/docs/reference/cli) —— 完整 CLI 参考 diff --git a/content/docs/build/packages.de.mdx b/content/docs/build/packages.de.mdx new file mode 100644 index 0000000..96a065e --- /dev/null +++ b/content/docs/build/packages.de.mdx @@ -0,0 +1,171 @@ +--- +title: Pakete +description: Die Organisationseinheit in ObjectOS — versioniert, installierbar, teilbar. +--- + +# Pakete + +Alles, was Sie in ObjectOS erstellen, lebt in einem **Paket**: einem +versionierten, in sich geschlossenen Bündel von Metadaten. Pakete sind die +Einheit, an der der AI Builder arbeitet, die Einheit, die der marketplace +ausliefert, und die Einheit, gegen die ObjectOS Updates verfolgt. + +## Was in einem Paket steckt + +```text +com.acme.crm@1.2.0 +├── manifest id, version, namespace, dependencies +├── objects/ *.object.ts, *.state.ts, *.hook.ts +├── views/ *.view.ts, *.page.ts, *.form.ts +├── actions/ *.action.ts +├── flows/ *.flow.ts, *.approval.ts +├── agents/ *.agent.ts, *.skill.ts +├── permissions/ *.permission.ts +├── sharing/ *.sharing.ts +├── translations/ en.ts, zh-CN.ts, ... +├── apps/ *.app.ts (navigation) +└── data/ defineDataset(...) seed +``` + +Jedes Metadaten-Artefakt (Objekt, Aktion, Flow, …) gehört zu genau einem +Paket. Die Paket-id ist **reverse-DNS** (`com.acme.crm`, +`org.mycompany.helpdesk`), und das Namespace-Präfix (`crm_`, `hd_`) verhindert, +dass Tabellen- / Objektnamen über mehrere im selben Tenant installierte Pakete +hinweg kollidieren. + +## Ein Paket erstellen + +### Über den AI Builder + +> *"Starte ein neues Paket für unser internes CRM, namespace `crm`."* + +Die KI ruft `create_package` und `set_active_package` auf. Von da an landet +jedes Objekt / Feld / jede Aktion, die Sie beschreiben, in `crm`. + +### Über die CLI + +```bash +os init my-crm -t app +cd my-crm +# manifest lives in the `manifest:` block of ./objectstack.config.ts +pnpm dev +``` + +### Über die Console + +**Console → Packages → New Package** — Name, id, Version, namespace. + +## Aktives Paket + +Im AI Builder trägt eine Konversation ein **aktives Paket** — den Standard- +Container für neue Metadaten. Die KI setzt es mit dem Tool +`set_active_package`, wenn Sie etwas sagen wie *"Wechsle zu +`com.acme.helpdesk`."* Über die CLI ist das aktive Paket einfach dasjenige, +das in der `objectstack.config.ts` des Projekts deklariert ist (der +`manifest:`-Block). + +## Versionierung + +Pakete verwenden **semver**. Dieselben Regeln wie die Runtime — siehe +[Changelog & Versioning](/docs/resources/changelog). + +Das Anheben einer Version ändert nichts, bis Sie veröffentlichen. Die Runtime +verfolgt `installed_version` pro Tenant pro Paket, und der marketplace zeigt +ein *"Update available"*-Badge an, wenn der Katalog eine neuere Version hat. + +## Abhängigkeiten + +Pakete können von anderen Paketen abhängen: + +```json +{ + "id": "com.acme.helpdesk", + "version": "0.3.0", + "dependencies": { + "com.acme.crm": "^1.0.0", + "sys.feeds": "*" + } +} +``` + +Die Runtime löst Abhängigkeiten bei der Installation auf. Wenn +`com.acme.crm` nicht installiert ist, schlägt die Helpdesk-Installation mit +einem klaren Fehler fehl. + +Systempakete (`sys.*`) sind immer vorhanden — feeds, attachments, audit, +identity usw. + +## Veröffentlichen + +```bash +os compile # → dist/objectstack.json +os package publish # → ObjectStack cloud catalog +``` + +`os package publish` lädt das kompilierte manifest in die Cloud-Control-Plane +hoch, die durch `OS_CLOUD_URL` konfiguriert und mit `OS_CLOUD_API_KEY` +authentifiziert wird. Für private / luftgekapselte Distribution überspringen +Sie das Veröffentlichen und übergeben das kompilierte `dist/objectstack.json` +direkt an die Zielinstallation (siehe Installieren weiter unten). Siehe +[Marketplace](/docs/build/marketplace). + +## Installieren + +| Pfad | Wie | +|---|---| +| Console | Marketplace-Tab → Paket auswählen → Install | +| REST | `POST /api/v1/marketplace/install-local` (Body: `{ packageId, versionId? }`) | +| Luftgekapselt | Das kompilierte `dist/objectstack.json`-Artefakt einhängen (siehe [Air-gapped](/docs/deploy/air-gapped)) | + +Die Installation führt die Metadaten des Pakets in den laufenden Kernel +zusammen, registriert seine Objekte bei ObjectQL und sät bei der ersten +Installation initiale Daten — kein Neustart nötig. Zwischengespeicherte +Installationen werden beim nächsten Boot erneut registriert und überstehen so +Prozess-Neustarts. + +## Deinstallieren + +Beim Deinstallieren wird das zwischengespeicherte manifest des Pakets +entfernt, sodass es beim nächsten Boot nicht mehr erneut registriert wird. Da +die Objektregistrierung additiv ist, ist ein **Kernel-Neustart** erforderlich, +um die Objekte eines bereits laufenden Pakets vollständig zu entladen. Daten +werden standardmäßig **behalten**, sodass Sie erneut installieren und +fortfahren können. + +## Paketübergreifende Konventionen + +Um Kollisionen zu vermeiden, wenn viele Pakete koexistieren: + +| Artefakt | Konvention | +|---|---| +| Objektnamen | Immer mit Präfix: `crm_account`, `hd_ticket` | +| Aktionsnamen | Mit Präfix: `crm_assign_owner`, `hd_close_ticket` | +| Flow-Namen | Mit Präfix: `hd_overdue_alert` | +| Übersetzungsschlüssel | Unter dem namespace eingeordnet: `crm.account.label` | +| Seed-`externalId` | `:`, z. B. `crm:demo-account-1` | +| Systemnamen | Reserviert: `sys_*` (niemals in benutzerdefinierten Paketen verwenden) | + +Sowohl die CLI als auch der AI Builder erzwingen dies bei der Erstellung. + +## Systempakete + +Die Runtime liefert eine kleine Reihe stets vorhandener Pakete mit, die +polymorphe Dienste bereitstellen: + +| Paket | Stellt bereit | +|---|---| +| `sys.identity` | `sys_user`, `sys_organization`, `sys_member`, Sessions, API-Keys | +| `sys.feeds` | `sys_comment`, `sys_activity`, `sys_attachment` | +| `sys.audit` | `sys_audit_log` | +| `sys.files` | `sys_file` | +| `sys.ai` | `ai_conversations`, `ai_pending_actions` | +| `sys.settings` | `sys_setting` | + +Sie aktivieren sie über `enable: { feeds: true, trackHistory: true, … }` an +Ihren Objekten — siehe [Data Model](/docs/build/data-model). + +## Wie es weitergeht + +- [Marketplace](/docs/build/marketplace) — Pakete an andere Tenants verteilen +- [Data Model](/docs/build/data-model) — was in ein Paket gehört +- [`os package` commands](/docs/reference/cli) — vollständige CLI-Referenz diff --git a/content/docs/build/packages.es.mdx b/content/docs/build/packages.es.mdx new file mode 100644 index 0000000..962bf35 --- /dev/null +++ b/content/docs/build/packages.es.mdx @@ -0,0 +1,173 @@ +--- +title: Paquetes +description: "La unidad de organización en ObjectOS: versionada, instalable y compartible." +--- + +# Paquetes + +Todo lo que construyes en ObjectOS reside en un **paquete**: un conjunto +de metadatos versionado y autocontenido. Los paquetes son la unidad +sobre la que trabaja el AI Builder, la unidad que distribuye el +marketplace y la unidad respecto a la que ObjectOS rastrea las +actualizaciones. + +## Qué contiene un paquete + +```text +com.acme.crm@1.2.0 +├── manifest id, version, namespace, dependencies +├── objects/ *.object.ts, *.state.ts, *.hook.ts +├── views/ *.view.ts, *.page.ts, *.form.ts +├── actions/ *.action.ts +├── flows/ *.flow.ts, *.approval.ts +├── agents/ *.agent.ts, *.skill.ts +├── permissions/ *.permission.ts +├── sharing/ *.sharing.ts +├── translations/ en.ts, zh-CN.ts, ... +├── apps/ *.app.ts (navigation) +└── data/ defineDataset(...) seed +``` + +Cada artefacto de metadatos (objeto, acción, flujo, …) pertenece a +exactamente un paquete. El id del paquete sigue el formato **DNS +inverso** (`com.acme.crm`, `org.mycompany.helpdesk`) y el prefijo del +namespace (`crm_`, `hd_`) evita que los nombres de tablas / objetos +colisionen entre paquetes instalados en el mismo tenant. + +## Crear un paquete + +### Desde el AI Builder + +> *"Inicia un nuevo paquete para nuestro CRM interno, con el namespace `crm`."* + +La IA invoca `create_package` y `set_active_package`. A partir de ese +momento, cada objeto / campo / acción que describas se ubica en `crm`. + +### Desde la CLI + +```bash +os init my-crm -t app +cd my-crm +# manifest lives in the `manifest:` block of ./objectstack.config.ts +pnpm dev +``` + +### Desde Console + +**Console → Packages → New Package** — nombre, id, versión, namespace. + +## Paquete activo + +En el AI Builder, una conversación lleva asociado un **paquete activo**: +el contenedor predeterminado para los nuevos metadatos. La IA lo +establece con la herramienta `set_active_package` cuando dices algo como +*"Cambia a `com.acme.helpdesk`."* Desde la CLI, el paquete activo es +simplemente el declarado en el `objectstack.config.ts` del proyecto (el +bloque `manifest:`). + +## Versionado + +Los paquetes usan **semver**. Las mismas reglas que el runtime — consulta +[Changelog & Versioning](/docs/resources/changelog). + +Incrementar una versión no cambia nada hasta que publicas. El runtime +rastrea `installed_version` por tenant y por paquete, y el marketplace +muestra una insignia de *"Update available"* cuando el catálogo tiene una +versión más reciente. + +## Dependencias + +Los paquetes pueden depender de otros paquetes: + +```json +{ + "id": "com.acme.helpdesk", + "version": "0.3.0", + "dependencies": { + "com.acme.crm": "^1.0.0", + "sys.feeds": "*" + } +} +``` + +El runtime resuelve las dependencias durante la instalación. Si +`com.acme.crm` no está instalado, la instalación del helpdesk falla con +un error claro. + +Los paquetes de sistema (`sys.*`) siempre están presentes — feeds, +adjuntos, auditoría, identidad, etc. + +## Publicar + +```bash +os compile # → dist/objectstack.json +os package publish # → ObjectStack cloud catalog +``` + +`os package publish` sube el manifiesto compilado al plano de control en +la nube configurado por `OS_CLOUD_URL`, autenticado con +`OS_CLOUD_API_KEY`. Para distribución privada / sin conexión (air-gapped), +omite la publicación y entrega el `dist/objectstack.json` compilado +directamente a la instalación de destino (consulta Instalación más +abajo). Consulta [Marketplace](/docs/build/marketplace). + +## Instalar + +| Ruta | Cómo | +|---|---| +| Console | Pestaña Marketplace → elige el paquete → Install | +| REST | `POST /api/v1/marketplace/install-local` (body: `{ packageId, versionId? }`) | +| Air-gapped | Monta el artefacto compilado `dist/objectstack.json` (consulta [Air-gapped](/docs/deploy/air-gapped)) | + +La instalación fusiona los metadatos del paquete en el kernel en vivo, +registra sus objetos con ObjectQL y carga los datos iniciales en la +primera instalación — sin necesidad de reiniciar. Las instalaciones en +caché se vuelven a registrar en el siguiente arranque, por lo que +sobreviven a los reinicios del proceso. + +## Desinstalar + +Desinstalar elimina el manifiesto en caché del paquete para que ya no se +vuelva a registrar en el siguiente arranque. Como el registro de objetos +es aditivo, se requiere un **reinicio del kernel** para descargar por +completo los objetos de un paquete ya en ejecución. Los datos se +**conservan** de forma predeterminada, por lo que puedes reinstalar y +continuar. + +## Convenciones entre paquetes + +Para evitar colisiones cuando coexisten muchos paquetes: + +| Artefacto | Convención | +|---|---| +| Nombres de objetos | Siempre con prefijo: `crm_account`, `hd_ticket` | +| Nombres de acciones | Con prefijo: `crm_assign_owner`, `hd_close_ticket` | +| Nombres de flujos | Con prefijo: `hd_overdue_alert` | +| Claves de traducción | Acotadas bajo el namespace: `crm.account.label` | +| `externalId` de seed | `:`, p. ej. `crm:demo-account-1` | +| Nombres de sistema | Reservados: `sys_*` (nunca los uses en paquetes personalizados) | + +Tanto la CLI como el AI Builder aplican esto al momento de la creación. + +## Paquetes de sistema + +El runtime incluye un pequeño conjunto de paquetes siempre presentes que +proporcionan servicios polimórficos: + +| Paquete | Proporciona | +|---|---| +| `sys.identity` | `sys_user`, `sys_organization`, `sys_member`, sesiones, claves de API | +| `sys.feeds` | `sys_comment`, `sys_activity`, `sys_attachment` | +| `sys.audit` | `sys_audit_log` | +| `sys.files` | `sys_file` | +| `sys.ai` | `ai_conversations`, `ai_pending_actions` | +| `sys.settings` | `sys_setting` | + +Los habilitas mediante `enable: { feeds: true, trackHistory: true, … }` +en tus objetos — consulta [Data Model](/docs/build/data-model). + +## A dónde ir después + +- [Marketplace](/docs/build/marketplace) — distribuye paquetes a otros tenants +- [Data Model](/docs/build/data-model) — qué va dentro de un paquete +- [`os package` commands](/docs/reference/cli) — referencia completa de la CLI diff --git a/content/docs/build/packages.fr.mdx b/content/docs/build/packages.fr.mdx new file mode 100644 index 0000000..8202dae --- /dev/null +++ b/content/docs/build/packages.fr.mdx @@ -0,0 +1,171 @@ +--- +title: Packages +description: L'unité d'organisation dans ObjectOS — versionnée, installable, partageable. +--- + +# Packages + +Tout ce que vous construisez dans ObjectOS réside dans un **package** : +un ensemble de métadonnées autonome et versionné. Le package est l'unité +sur laquelle travaille l'AI Builder, l'unité que distribue le marketplace, +et l'unité dont ObjectOS suit les mises à jour. + +## Contenu d'un package + +```text +com.acme.crm@1.2.0 +├── manifest id, version, namespace, dependencies +├── objects/ *.object.ts, *.state.ts, *.hook.ts +├── views/ *.view.ts, *.page.ts, *.form.ts +├── actions/ *.action.ts +├── flows/ *.flow.ts, *.approval.ts +├── agents/ *.agent.ts, *.skill.ts +├── permissions/ *.permission.ts +├── sharing/ *.sharing.ts +├── translations/ en.ts, zh-CN.ts, ... +├── apps/ *.app.ts (navigation) +└── data/ defineDataset(...) seed +``` + +Chaque artefact de métadonnées (object, action, flow, …) appartient à +exactement un package. L'id du package est en **reverse-DNS** (`com.acme.crm`, +`org.mycompany.helpdesk`) et le préfixe de namespace (`crm_`, `hd_`) +empêche les noms de tables / d'objets d'entrer en collision entre les +packages installés dans le même tenant. + +## Créer un package + +### Depuis l'AI Builder + +> *« Démarre un nouveau package pour notre CRM interne, namespace `crm`. »* + +L'IA appelle `create_package` et `set_active_package`. À partir de là, +chaque object / champ / action que vous décrivez est placé dans `crm`. + +### Depuis la CLI + +```bash +os init my-crm -t app +cd my-crm +# manifest lives in the `manifest:` block of ./objectstack.config.ts +pnpm dev +``` + +### Depuis la Console + +**Console → Packages → New Package** — nom, id, version, namespace. + +## Package actif + +Dans l'AI Builder, une conversation porte un **package actif** — le +conteneur par défaut pour les nouvelles métadonnées. L'IA le définit avec +l'outil `set_active_package` lorsque vous dites par exemple *« Bascule vers +`com.acme.helpdesk`. »* Depuis la CLI, le package actif est simplement +celui déclaré dans le fichier `objectstack.config.ts` du projet (le bloc +`manifest:`). + +## Versionnement + +Les packages utilisent le **semver**. Mêmes règles que le runtime — voir +[Changelog & Versioning](/docs/resources/changelog). + +Incrémenter une version ne change rien tant que vous ne publiez pas. Le +runtime suit `installed_version` par tenant et par package, et le +marketplace affiche un badge *« Update available »* lorsque le catalogue +contient une version plus récente. + +## Dépendances + +Les packages peuvent dépendre d'autres packages : + +```json +{ + "id": "com.acme.helpdesk", + "version": "0.3.0", + "dependencies": { + "com.acme.crm": "^1.0.0", + "sys.feeds": "*" + } +} +``` + +Le runtime résout les dépendances à l'installation. Si `com.acme.crm` +n'est pas installé, l'installation du helpdesk échoue avec une erreur +explicite. + +Les packages système (`sys.*`) sont toujours présents — feeds, pièces +jointes, audit, identité, etc. + +## Publication + +```bash +os compile # → dist/objectstack.json +os package publish # → ObjectStack cloud catalog +``` + +`os package publish` téléverse le manifeste compilé vers le plan de +contrôle cloud configuré par `OS_CLOUD_URL`, authentifié avec +`OS_CLOUD_API_KEY`. Pour une distribution privée / air-gapped, ignorez la +publication et transmettez directement le `dist/objectstack.json` compilé +à l'installation cible (voir Installation ci-dessous). Voir [Marketplace](/docs/build/marketplace). + +## Installation + +| Méthode | Comment | +|---|---| +| Console | Onglet Marketplace → choisir le package → Install | +| REST | `POST /api/v1/marketplace/install-local` (corps : `{ packageId, versionId? }`) | +| Air-gapped | Monter l'artefact `dist/objectstack.json` compilé (voir [Air-gapped](/docs/deploy/air-gapped)) | + +L'installation fusionne les métadonnées du package dans le kernel en +service, enregistre ses objects auprès d'ObjectQL et amorce les données +initiales lors de la première installation — aucun redémarrage requis. Les +installations en cache sont réenregistrées au prochain démarrage, ce qui +leur permet de survivre aux redémarrages de processus. + +## Désinstallation + +La désinstallation supprime le manifeste mis en cache du package afin qu'il +ne soit plus réenregistré au prochain démarrage. Comme l'enregistrement des +objects est additif, un **redémarrage du kernel** est nécessaire pour +décharger complètement les objects d'un package déjà en cours d'exécution. +Les données sont **conservées** par défaut, ce qui vous permet de +réinstaller et de reprendre. + +## Conventions inter-packages + +Pour éviter les collisions lorsque de nombreux packages coexistent : + +| Artefact | Convention | +|---|---| +| Noms d'objects | Toujours préfixés : `crm_account`, `hd_ticket` | +| Noms d'actions | Préfixés : `crm_assign_owner`, `hd_close_ticket` | +| Noms de flows | Préfixés : `hd_overdue_alert` | +| Clés de traduction | Cadrées sous le namespace : `crm.account.label` | +| `externalId` des seeds | `:`, ex. `crm:demo-account-1` | +| Noms système | Réservés : `sys_*` (à ne jamais utiliser dans les packages personnalisés) | + +La CLI et l'AI Builder appliquent tous deux ces règles à la création. + +## Packages système + +Le runtime fournit un petit ensemble de packages toujours présents qui +offrent des services polymorphes : + +| Package | Fournit | +|---|---| +| `sys.identity` | `sys_user`, `sys_organization`, `sys_member`, sessions, clés API | +| `sys.feeds` | `sys_comment`, `sys_activity`, `sys_attachment` | +| `sys.audit` | `sys_audit_log` | +| `sys.files` | `sys_file` | +| `sys.ai` | `ai_conversations`, `ai_pending_actions` | +| `sys.settings` | `sys_setting` | + +Vous les activez via `enable: { feeds: true, trackHistory: true, … }` +sur vos objects — voir [Data Model](/docs/build/data-model). + +## Pour aller plus loin + +- [Marketplace](/docs/build/marketplace) — distribuer des packages à d'autres tenants +- [Data Model](/docs/build/data-model) — ce qui réside à l'intérieur d'un package +- [Commandes `os package`](/docs/reference/cli) — référence CLI complète diff --git a/content/docs/build/packages.ja.mdx b/content/docs/build/packages.ja.mdx new file mode 100644 index 0000000..7d92bfc --- /dev/null +++ b/content/docs/build/packages.ja.mdx @@ -0,0 +1,136 @@ +--- +title: パッケージ +description: ObjectOS における組織化の単位 — バージョン管理され、インストール可能で、共有可能。 +--- + +# パッケージ + +ObjectOS で構築するものはすべて **パッケージ** の中に存在します。パッケージとは、バージョン管理された、自己完結型のメタデータのまとまりです。パッケージは AI Builder が作業する単位であり、marketplace が配布する単位であり、ObjectOS が更新を追跡する単位でもあります。 + +## パッケージの中身 + +```text +com.acme.crm@1.2.0 +├── manifest id, version, namespace, dependencies +├── objects/ *.object.ts, *.state.ts, *.hook.ts +├── views/ *.view.ts, *.page.ts, *.form.ts +├── actions/ *.action.ts +├── flows/ *.flow.ts, *.approval.ts +├── agents/ *.agent.ts, *.skill.ts +├── permissions/ *.permission.ts +├── sharing/ *.sharing.ts +├── translations/ en.ts, zh-CN.ts, ... +├── apps/ *.app.ts (navigation) +└── data/ defineDataset(...) seed +``` + +すべてのメタデータ成果物(object、action、flow、…)は、ちょうど 1 つのパッケージに属します。パッケージ id は **逆 DNS** 形式(`com.acme.crm`、`org.mycompany.helpdesk`)であり、namespace のプレフィックス(`crm_`、`hd_`)によって、同一テナントにインストールされたパッケージ間でテーブル名 / object 名が衝突しないようにします。 + +## パッケージの作成 + +### AI Builder から + +> *「社内 CRM 用の新しいパッケージを namespace `crm` で開始して。」* + +AI は `create_package` と `set_active_package` を呼び出します。それ以降、記述したすべての object / field / action は `crm` に格納されます。 + +### CLI から + +```bash +os init my-crm -t app +cd my-crm +# manifest lives in the `manifest:` block of ./objectstack.config.ts +pnpm dev +``` + +### Console から + +**Console → Packages → New Package** — name、id、version、namespace を指定します。 + +## アクティブパッケージ + +AI Builder では、会話は **アクティブパッケージ**(新しいメタデータのデフォルトのコンテナ)を保持します。*「`com.acme.helpdesk` に切り替えて。」* のように指示すると、AI は `set_active_package` ツールでこれを設定します。CLI では、アクティブパッケージは単にプロジェクトの `objectstack.config.ts`(`manifest:` ブロック)で宣言されているものになります。 + +## バージョニング + +パッケージは **semver** に従います。ランタイムと同じルールです。詳しくは [Changelog & Versioning](/docs/resources/changelog) を参照してください。 + +バージョンを上げても、公開するまでは何も変わりません。ランタイムはテナントごと・パッケージごとに `installed_version` を追跡し、カタログにより新しいバージョンがある場合、marketplace には *「Update available」* バッジが表示されます。 + +## 依存関係 + +パッケージは他のパッケージに依存できます。 + +```json +{ + "id": "com.acme.helpdesk", + "version": "0.3.0", + "dependencies": { + "com.acme.crm": "^1.0.0", + "sys.feeds": "*" + } +} +``` + +ランタイムはインストール時に依存関係を解決します。`com.acme.crm` がインストールされていない場合、helpdesk のインストールは明確なエラーとともに失敗します。 + +システムパッケージ(`sys.*`)は常に存在します。feeds、attachments、audit、identity などです。 + +## 公開 + +```bash +os compile # → dist/objectstack.json +os package publish # → ObjectStack cloud catalog +``` + +`os package publish` は、コンパイル済みの manifest を、`OS_CLOUD_URL` で設定されたクラウドコントロールプレーンにアップロードし、`OS_CLOUD_API_KEY` で認証します。プライベートな / エアギャップ環境での配布の場合は、公開をスキップし、コンパイル済みの `dist/objectstack.json` を直接インストール先に渡します(後述の「インストール」を参照)。[Marketplace](/docs/build/marketplace) も参照してください。 + +## インストール + +| 経路 | 方法 | +|---|---| +| Console | Marketplace タブ → パッケージを選択 → Install | +| REST | `POST /api/v1/marketplace/install-local`(body: `{ packageId, versionId? }`) | +| エアギャップ | コンパイル済みの `dist/objectstack.json` 成果物をマウント([Air-gapped](/docs/deploy/air-gapped) を参照) | + +インストールは、パッケージのメタデータを稼働中のカーネルにマージし、その object を ObjectQL に登録し、初回インストール時には初期データをシードします。再起動は不要です。キャッシュされたインストールは次回のブート時に再登録されるため、プロセスの再起動後も維持されます。 + +## アンインストール + +アンインストールはパッケージのキャッシュされた manifest を削除するため、次回のブート時に再登録されなくなります。object の登録は追加的に行われるため、すでに稼働中のパッケージの object を完全にアンロードするには **カーネルの再起動** が必要です。データはデフォルトで **保持** されるため、再インストールして再開できます。 + +## パッケージ横断の規約 + +多数のパッケージが共存する際の衝突を防ぐために: + +| 成果物 | 規約 | +|---|---| +| Object 名 | 常にプレフィックス付き: `crm_account`、`hd_ticket` | +| Action 名 | プレフィックス付き: `crm_assign_owner`、`hd_close_ticket` | +| Flow 名 | プレフィックス付き: `hd_overdue_alert` | +| 翻訳キー | namespace 配下にスコープ: `crm.account.label` | +| シードの `externalId` | `:`、例: `crm:demo-account-1` | +| システム名 | 予約済み: `sys_*`(カスタムパッケージでは使用しない) | + +CLI と AI Builder はどちらも、作成時にこの規約を強制します。 + +## システムパッケージ + +ランタイムには、ポリモーフィックなサービスを提供する、常に存在する小さなパッケージ群が同梱されています。 + +| パッケージ | 提供するもの | +|---|---| +| `sys.identity` | `sys_user`、`sys_organization`、`sys_member`、セッション、API キー | +| `sys.feeds` | `sys_comment`、`sys_activity`、`sys_attachment` | +| `sys.audit` | `sys_audit_log` | +| `sys.files` | `sys_file` | +| `sys.ai` | `ai_conversations`、`ai_pending_actions` | +| `sys.settings` | `sys_setting` | + +これらは object 上で `enable: { feeds: true, trackHistory: true, … }` を指定することで有効化します。[Data Model](/docs/build/data-model) を参照してください。 + +## 次に読むべきもの + +- [Marketplace](/docs/build/marketplace) — パッケージを他のテナントに配布する +- [Data Model](/docs/build/data-model) — パッケージの中に入るもの +- [`os package` commands](/docs/reference/cli) — CLI の完全なリファレンス diff --git a/content/docs/build/packages.mdx b/content/docs/build/packages.mdx index 8ad4d71..7e56675 100644 --- a/content/docs/build/packages.mdx +++ b/content/docs/build/packages.mdx @@ -20,7 +20,7 @@ com.acme.crm@1.2.0 ├── actions/ *.action.ts ├── flows/ *.flow.ts, *.approval.ts ├── agents/ *.agent.ts, *.skill.ts -├── permissions/ *.profile.ts +├── permissions/ *.permission.ts ├── sharing/ *.sharing.ts ├── translations/ en.ts, zh-CN.ts, ... ├── apps/ *.app.ts (navigation) @@ -45,9 +45,9 @@ every object / field / action you describe lands in `crm`. ### From the CLI ```bash -os init my-crm -t app --install +os init my-crm -t app cd my-crm -# manifest is at ./objectstack.manifest.json +# manifest lives in the `manifest:` block of ./objectstack.config.ts pnpm dev ``` @@ -57,16 +57,12 @@ pnpm dev ## Active package -A conversation, a CLI session, and a Console admin view each carry an -**active package** — the default container for new metadata. Switch -with: - -| Surface | How | -|---|---| -| AI Builder | *"Switch to `com.acme.helpdesk`."* (tool `set_active_package`) | -| CLI | `os package use com.acme.helpdesk` | -| Console | Top-bar package switcher | -| REST | `X-Package-Id: com.acme.helpdesk` header | +In the AI Builder, a conversation carries an **active package** — the +default container for new metadata. The AI sets it with the +`set_active_package` tool when you say something like *"Switch to +`com.acme.helpdesk`."* From the CLI, the active package is simply the +one declared in the project's `objectstack.config.ts` (the `manifest:` +block). ## Versioning @@ -103,31 +99,35 @@ audit, identity, etc. ```bash os compile # → dist/objectstack.json -os package publish # → configured registry +os package publish # → ObjectStack cloud catalog ``` -Publishes to the registry at `OS_PACKAGE_REGISTRY` (default: the -ObjectStack public catalog). For private / air-gapped, run your own -registry and point that env var at it. See [Marketplace](/docs/build/marketplace). +`os package publish` uploads the compiled manifest to the cloud +control plane configured by `OS_CLOUD_URL`, authenticated with +`OS_CLOUD_API_KEY`. For private / air-gapped distribution, skip +publishing and hand the compiled `dist/objectstack.json` directly to +the target install (see Installing below). See [Marketplace](/docs/build/marketplace). ## Installing | Path | How | |---|---| | Console | Marketplace tab → pick package → Install | -| CLI | `os package install com.acme.helpdesk@^0.3.0` | -| REST | `POST /api/v1/marketplace/install` | -| Air-gapped | Drop `dist/objectstack.json` in the local catalog dir | +| REST | `POST /api/v1/marketplace/install-local` (body: `{ packageId, versionId? }`) | +| Air-gapped | Mount the compiled `dist/objectstack.json` artifact (see [Air-gapped](/docs/deploy/air-gapped)) | Install merges the package's metadata into the live kernel, registers -its objects with ObjectQL, and seeds initial data on first install. -No restart. +its objects with ObjectQL, and seeds initial data on first install — +no restart needed. Cached installs are re-registered on the next boot, +so they survive process restarts. ## Uninstalling -Uninstalling marks the package as removed and unregisters its -objects. By default, data is **kept** (you can re-install and resume). -Pass `--drop-data` to drop the tables. +Uninstalling removes the package's cached manifest so it is no longer +re-registered on the next boot. Because object registration is +additive, a **kernel restart** is required to fully unload an +already-running package's objects. Data is **kept** by default, so you +can re-install and resume. ## Cross-package conventions @@ -151,11 +151,11 @@ polymorphic services: | Package | Provides | |---|---| -| `sys.identity` | `sys_user`, `sys_org`, `sys_member`, sessions, API keys | +| `sys.identity` | `sys_user`, `sys_organization`, `sys_member`, sessions, API keys | | `sys.feeds` | `sys_comment`, `sys_activity`, `sys_attachment` | | `sys.audit` | `sys_audit_log` | | `sys.files` | `sys_file` | -| `sys.ai` | `sys_ai_conversation`, `sys_ai_pending_action` | +| `sys.ai` | `ai_conversations`, `ai_pending_actions` | | `sys.settings` | `sys_setting` | You enable them via `enable: { feeds: true, trackHistory: true, … }` diff --git a/content/docs/build/packages.zh-Hans.mdx b/content/docs/build/packages.zh-Hans.mdx new file mode 100644 index 0000000..d436145 --- /dev/null +++ b/content/docs/build/packages.zh-Hans.mdx @@ -0,0 +1,156 @@ +--- +title: Packages +description: ObjectOS 中的组织单元 —— 可版本化、可安装、可共享。 +--- + +# Packages + +你在 ObjectOS 中构建的一切都存放于一个**包(package)**中:一个可版本化、 +自包含的元数据捆绑体。包是 AI Builder 操作的单元,是 marketplace 分发的单元, +也是 ObjectOS 追踪更新所依据的单元。 + +## 包里有什么 + +```text +com.acme.crm@1.2.0 +├── manifest id, version, namespace, dependencies +├── objects/ *.object.ts, *.state.ts, *.hook.ts +├── views/ *.view.ts, *.page.ts, *.form.ts +├── actions/ *.action.ts +├── flows/ *.flow.ts, *.approval.ts +├── agents/ *.agent.ts, *.skill.ts +├── permissions/ *.permission.ts +├── sharing/ *.sharing.ts +├── translations/ en.ts, zh-CN.ts, ... +├── apps/ *.app.ts (navigation) +└── data/ defineDataset(...) seed +``` + +每一个元数据制品(对象、操作、流程……)都恰好归属于一个包。包 id 采用 +**反向 DNS**(`com.acme.crm`、`org.mycompany.helpdesk`),而命名空间前缀 +(`crm_`、`hd_`)能避免在同一租户中安装的不同包之间,表名 / 对象名发生冲突。 + +## 创建一个包 + +### 从 AI Builder 创建 + +> *"为我们的内部 CRM 新建一个包,命名空间为 `crm`。"* + +AI 会调用 `create_package` 和 `set_active_package`。从此之后, +你所描述的每一个对象 / 字段 / 操作都会落入 `crm`。 + +### 从 CLI 创建 + +```bash +os init my-crm -t app +cd my-crm +# manifest lives in the `manifest:` block of ./objectstack.config.ts +pnpm dev +``` + +### 从 Console 创建 + +**Console → Packages → New Package** —— 填写名称、id、版本、命名空间。 + +## 活动包(Active package) + +在 AI Builder 中,一段对话会携带一个**活动包**—— 即新元数据的默认容器。 +当你说类似 *"切换到 `com.acme.helpdesk`。"* 这样的话时,AI 会通过 +`set_active_package` 工具来设置它。从 CLI 来看,活动包就是项目的 +`objectstack.config.ts` 中声明的那个包(即 `manifest:` 块)。 + +## 版本管理 + +包采用 **semver**。规则与运行时相同 —— 参见 +[Changelog & Versioning](/docs/resources/changelog)。 + +在你发布之前,提升版本号不会改变任何东西。运行时会按租户、按包追踪 +`installed_version`,当目录中存在更新版本时,marketplace 会显示一个 +*"Update available"* 徽标。 + +## 依赖 + +包可以依赖其他包: + +```json +{ + "id": "com.acme.helpdesk", + "version": "0.3.0", + "dependencies": { + "com.acme.crm": "^1.0.0", + "sys.feeds": "*" + } +} +``` + +运行时会在安装时解析依赖。如果 `com.acme.crm` 未安装,helpdesk 的安装会 +带着清晰的错误信息失败。 + +系统包(`sys.*`)始终存在 —— feeds、附件、审计、身份等。 + +## 发布 + +```bash +os compile # → dist/objectstack.json +os package publish # → ObjectStack cloud catalog +``` + +`os package publish` 会将编译后的 manifest 上传到由 `OS_CLOUD_URL` 配置的 +云端控制平面,并使用 `OS_CLOUD_API_KEY` 进行认证。对于私有 / 隔离网络 +(air-gapped)分发,可跳过发布,直接将编译好的 `dist/objectstack.json` +交给目标安装方(参见下方的「安装」)。参见 [Marketplace](/docs/build/marketplace)。 + +## 安装 + +| 路径 | 方式 | +|---|---| +| Console | Marketplace 标签页 → 选择包 → Install | +| REST | `POST /api/v1/marketplace/install-local`(请求体:`{ packageId, versionId? }`) | +| 隔离网络(Air-gapped) | 挂载编译后的 `dist/objectstack.json` 制品(参见 [Air-gapped](/docs/deploy/air-gapped)) | + +安装会将包的元数据合并进运行中的内核,将其对象注册到 ObjectQL,并在首次安装时 +注入初始数据 —— 无需重启。已缓存的安装会在下次启动时重新注册,因此能够在进程 +重启后依然保留。 + +## 卸载 + +卸载会移除包已缓存的 manifest,使其不再在下次启动时被重新注册。由于对象注册是 +增量式的,要彻底卸载一个已在运行中的包的对象,需要进行一次**内核重启**。 +数据默认会被**保留**,因此你可以重新安装并继续使用。 + +## 跨包约定 + +为防止多个包共存时发生冲突: + +| 制品 | 约定 | +|---|---| +| 对象名 | 始终带前缀:`crm_account`、`hd_ticket` | +| 操作名 | 带前缀:`crm_assign_owner`、`hd_close_ticket` | +| 流程名 | 带前缀:`hd_overdue_alert` | +| 翻译键 | 限定在命名空间下:`crm.account.label` | +| 种子数据 `externalId` | `:`,例如 `crm:demo-account-1` | +| 系统名 | 保留:`sys_*`(切勿在自定义包中使用) | + +CLI 和 AI Builder 在创建时都会强制执行这些约定。 + +## 系统包 + +运行时自带一小组始终存在的包,提供多态服务: + +| 包 | 提供内容 | +|---|---| +| `sys.identity` | `sys_user`、`sys_organization`、`sys_member`、会话、API keys | +| `sys.feeds` | `sys_comment`、`sys_activity`、`sys_attachment` | +| `sys.audit` | `sys_audit_log` | +| `sys.files` | `sys_file` | +| `sys.ai` | `ai_conversations`、`ai_pending_actions` | +| `sys.settings` | `sys_setting` | + +你可以在对象上通过 `enable: { feeds: true, trackHistory: true, … }` 来启用它们 —— +参见 [Data Model](/docs/build/data-model)。 + +## 下一步去哪 + +- [Marketplace](/docs/build/marketplace) —— 将包分发到其他租户 +- [Data Model](/docs/build/data-model) —— 包里都放些什么 +- [`os package` 命令](/docs/reference/cli) —— 完整 CLI 参考 diff --git a/content/docs/build/templates.de.mdx b/content/docs/build/templates.de.mdx new file mode 100644 index 0000000..1516af0 --- /dev/null +++ b/content/docs/build/templates.de.mdx @@ -0,0 +1,109 @@ +--- +title: Vorlagen +description: Forkbare Starterpakete — `todo`, `contracts`, `procurement`, `helpdesk` und mehr. +--- + +# Vorlagen + +Vorlagen sind **forkbare Starterpakete**. Jede einzelne ist eine echte, +ausgeformte App, die du mit einem Klick aus dem marketplace installieren +oder mit der CLI klonen kannst, um eine TypeScript-Codebasis zum Erweitern +zu erhalten. + +Vorlagen existieren aus zwei Gründen: + +1. **Zeigen statt erzählen** — eine funktionierende App mit mehreren + Objekten liest sich schneller als Dokumentation. +2. **Engineering-Teams einen Ausgangspunkt geben** — wenn du Code unter + Versionskontrolle haben möchtest und nicht nur KI-generierte Metadaten + in deiner DB. + +## Was im Standardkatalog enthalten ist + +| Vorlage | Domäne | Forkbarer Starter für… | +|---|---|---| +| **`todo`** | Aufgaben & Projekte | Jedes „zu erledigende Dinge, irgendwie gruppiert"-Tool | +| **`contracts`** | CLM mit KI-Klauselextraktion | Genehmigungen + Dokument-KI | +| **`procurement`** | Lieferanten, Bestellungen, 3-Wege-Abgleich | Genehmigungsketten + Wareneingang | +| **`compliance`** | SOC 2 / ISO 27001 Controls | Workflows zur Nachweissammlung | +| **`helpdesk`** | KI-zentrierter Kundensupport | Tickets + SLAs + KI-Co-Pilot | +| **`content`** | Redaktionskalender + Kanal-ROI | Lebenszyklus + Kennzahlen | +| **`hr`** | Verzeichnis, Organigramm, Abwesenheit | Personenzentrierte Apps | +| **`project`** | Projekt- / Aufgaben- / Meilenstein-Tracking | PM-Tools | + +Quelle: [github.com/objectstack-ai/templates](https://github.com/objectstack-ai/templates). +Apache-2.0. Forke ohne zu fragen. + +## In 30 Sekunden installieren (kein Code) + +In der Console: + +1. Öffne **Marketplace** → suche nach der Vorlage. +2. Klicke auf **Install**. +3. Aktualisiere die Seite — die neue App erscheint in deiner Navigation. + +Fertig. Datensätze, Ansichten, Flows, Berechtigungen — alles live. + +## Als Codebasis forken (für Engineers) + +```bash +pnpm dlx @objectstack/cli create my-app --template todo +cd my-app +pnpm install +pnpm dev # http://localhost:4002 +``` + +Der Klon ist ein eigenständiges pnpm-Paket — `*.object.ts`-, +`*.view.ts`-, `*.flow.ts`-Dateien, die du bearbeiten, linten, testen und +committen kannst. Wenn du zufrieden bist: + +```bash +pnpm build +os package publish # → dein marketplace +``` + +Kunden, die deinen Fork installieren, erhalten **deine** Marke und +**deine** Anpassungen. + +## Vorlagen-Charta (der soziale Vertrag) + +Jede Vorlage bringt eine `CHARTER.md` mit, die ihren Umfang und ihre +harten Grenzen deklariert — typischerweise: ≤ 6 Geschäftsobjekte, +≤ 2.500 LOC unter `src/`, eine App, ein Standard-Locale. Die Charta +existiert, damit Vorlagen **Vorlagen** bleiben und keine halbfertigen +Produkte werden. Wenn ein Fork über diese Grenzen hinauswächst, liefere +ihn als neue Vorlage aus und blähe keine bestehende auf. + +Siehe die vorgelagerte [TEMPLATE_GUIDE.md](https://github.com/objectstack-ai/templates/blob/main/TEMPLATE_GUIDE.md) +für das Dateisuffix-Protokoll (`*.object.ts`, `*.state.ts`, `*.hook.ts`, …), +die Erstellungsreihenfolge (Objekte → State → Hooks → Ansichten → Flows → …) +und die polymorphen Plattformdienste (`sys_comment`, `sys_attachment`, +`sys_audit_log`), die du wiederverwenden solltest, anstatt sie neu zu erfinden. + +## Wähle einen Ausgangspunkt + +| Wenn du Folgendes baust… | Forke dies | Warum | +|---|---|---| +| Jedes interne Tool, das „Sachen" trackt | `todo` | Kleinste, sauberste Demonstration aller Primitive | +| Alles mit Genehmigungsketten | `procurement` oder `contracts` | Echte Genehmigungsprozesse verdrahtet | +| Alles Kundenorientierte mit KI | `helpdesk` | Agent- + Ticket-Co-Pilot-Muster | +| Einen Workflow für regulierte Branchen | `compliance` | Audit + Nachweise + Control-Mapping | +| Eine Personen- / Organigramm-App | `hr` | Verzeichnis + Berichtsstruktur | + +## AI Builder + Vorlagen zusammen + +Du kannst eine Vorlage forken und **trotzdem** den AI Builder darauf +anwenden. Installiere `helpdesk` und sage dann: + +> *„Füge ein `csat_score`-Integer-Feld zu `hd_ticket` hinzu, Bereich 1–5, +> frage beim Schließen danach."* + +Der AI Builder erweitert das installierte Paket direkt vor Ort. Pushe die +Änderung mit `os package export` ins Quell-Repository. + +## Wie es weitergeht + +- [AI Builder](/docs/build/ai-builder) — erweitere jede Vorlage per Chat +- [Packages](/docs/build/packages) — was eine Vorlage tatsächlich ist +- [Marketplace](/docs/build/marketplace) — verteile deinen Fork +- [Quickstart](/docs/quickstart) — vollständiger End-to-End-Durchlauf des Entwicklerpfads diff --git a/content/docs/build/templates.es.mdx b/content/docs/build/templates.es.mdx new file mode 100644 index 0000000..2fc1c06 --- /dev/null +++ b/content/docs/build/templates.es.mdx @@ -0,0 +1,109 @@ +--- +title: Plantillas +description: Paquetes de inicio bifurcables — `todo`, `contracts`, `procurement`, `helpdesk` y más. +--- + +# Plantillas + +Las plantillas son **paquetes de inicio bifurcables**. Cada una es una +aplicación real y bien definida que puedes instalar desde el marketplace con un +clic, o clonar con la CLI para obtener una base de código en TypeScript que +puedes ampliar. + +Las plantillas existen por dos razones: + +1. **Mostrar, no contar** — una aplicación funcional de varios objetos se lee + más rápido que la documentación. +2. **Dar a los equipos de ingeniería un punto de partida** — cuando quieres + código bajo control de versiones, no solo metadatos generados por IA en tu + base de datos. + +## Qué incluye el catálogo predeterminado + +| Plantilla | Dominio | Punto de partida bifurcable para… | +|---|---|---| +| **`todo`** | Tareas y proyectos | Cualquier herramienta de "cosas por hacer, agrupadas de algún modo" | +| **`contracts`** | CLM con extracción de cláusulas por IA | Aprobaciones + IA de documentos | +| **`procurement`** | Proveedores, OC, conciliación a tres bandas | Cadenas de aprobación + recepción | +| **`compliance`** | Controles SOC 2 / ISO 27001 | Flujos de recopilación de evidencias | +| **`helpdesk`** | Soporte al cliente con IA en primer lugar | Tickets + SLA + copiloto de IA | +| **`content`** | Calendario editorial + ROI por canal | Ciclo de vida + métricas | +| **`hr`** | Directorio, organigrama, ausencias | Aplicaciones centradas en las personas | +| **`project`** | Seguimiento de proyectos / tareas / hitos | Herramientas de gestión de proyectos | + +Fuente: [github.com/objectstack-ai/templates](https://github.com/objectstack-ai/templates). +Apache-2.0. Bifurca sin pedir permiso. + +## Instala en 30 segundos (sin código) + +En Console: + +1. Abre **Marketplace** → busca la plantilla. +2. Haz clic en **Install**. +3. Actualiza — la nueva aplicación aparece en tu navegación. + +Listo. Registros, vistas, flujos, permisos — todo activo. + +## Bifurca como base de código (para ingenieros) + +```bash +pnpm dlx @objectstack/cli create my-app --template todo +cd my-app +pnpm install +pnpm dev # http://localhost:4002 +``` + +El clon es un paquete pnpm autónomo — archivos `*.object.ts`, +`*.view.ts`, `*.flow.ts` que puedes editar, lintear, probar y confirmar. Cuando +estés conforme: + +```bash +pnpm build +os package publish # → tu marketplace +``` + +Los clientes que instalen tu bifurcación obtienen **tu** marca y **tus** +modificaciones. + +## Estatuto de la plantilla (el contrato social) + +Cada plantilla incluye un `CHARTER.md` que declara su alcance y sus límites +estrictos — normalmente: ≤ 6 objetos de negocio, ≤ 2.500 líneas de código bajo +`src/`, una aplicación, una configuración regional predeterminada. El estatuto +existe para que las plantillas sigan siendo **plantillas**, no productos a medio +terminar. Si una bifurcación supera estos límites, publícala como una plantilla +nueva; no infles una existente. + +Consulta el [TEMPLATE_GUIDE.md](https://github.com/objectstack-ai/templates/blob/main/TEMPLATE_GUIDE.md) +original para conocer el protocolo de sufijos de archivo (`*.object.ts`, `*.state.ts`, `*.hook.ts`, …), +la secuencia de creación (objects → state → hooks → views → flows → …), +y los servicios polimórficos de la plataforma (`sys_comment`, `sys_attachment`, +`sys_audit_log`) que deberías reutilizar en lugar de reinventar. + +## Elige un punto de partida + +| Si estás creando… | Bifurca esto | Por qué | +|---|---|---| +| Cualquier herramienta interna que registre "cosas" | `todo` | La demostración más pequeña y limpia de todos los primitivos | +| Cualquier cosa con cadenas de aprobación | `procurement` o `contracts` | Procesos de aprobación reales ya conectados | +| Cualquier cosa de cara al cliente con IA | `helpdesk` | Patrón de agente + copiloto de tickets | +| Un flujo de trabajo de un sector regulado | `compliance` | Auditoría + evidencias + mapeo de controles | +| Una aplicación de personas / organigrama | `hr` | Directorio + estructura jerárquica | + +## AI Builder + plantillas juntos + +Puedes bifurcar una plantilla y **aun así** usar el AI Builder sobre ella. +Instala `helpdesk` y luego di: + +> *"Añade un campo entero `csat_score` a `hd_ticket`, rango 1–5, pídelo al +> cerrar."* + +La IA amplía el paquete instalado en el mismo lugar. Sube el cambio al +repositorio de origen con `os package export`. + +## Adónde ir a continuación + +- [AI Builder](/docs/build/ai-builder) — amplía cualquier plantilla por chat +- [Packages](/docs/build/packages) — qué es realmente una plantilla +- [Marketplace](/docs/build/marketplace) — distribuye tu bifurcación +- [Quickstart](/docs/quickstart) — recorrido completo de extremo a extremo de la ruta del desarrollador diff --git a/content/docs/build/templates.fr.mdx b/content/docs/build/templates.fr.mdx new file mode 100644 index 0000000..509663b --- /dev/null +++ b/content/docs/build/templates.fr.mdx @@ -0,0 +1,109 @@ +--- +title: Modèles +description: Packages de démarrage clonables — `todo`, `contracts`, `procurement`, `helpdesk`, et plus encore. +--- + +# Modèles + +Les modèles sont des **packages de démarrage clonables**. Chacun est une +véritable application structurée que vous pouvez installer depuis le +marketplace en un clic, ou cloner avec la CLI pour obtenir une base de +code TypeScript à étendre. + +Les modèles existent pour deux raisons : + +1. **Montrer plutôt que décrire** — une application multi-objets + fonctionnelle se lit plus vite que la documentation. +2. **Donner aux équipes d'ingénierie un point de départ** — lorsque vous + voulez du code sous contrôle de version, et pas seulement des + métadonnées générées par l'IA dans votre base de données. + +## Ce que contient le catalogue par défaut + +| Modèle | Domaine | Démarrage clonable pour… | +|---|---|---| +| **`todo`** | Tâches et projets | Tout outil de type « choses à faire, regroupées d'une manière ou d'une autre » | +| **`contracts`** | CLM avec extraction de clauses par IA | Approbations + IA documentaire | +| **`procurement`** | Fournisseurs, bons de commande, rapprochement à 3 voies | Chaînes d'approbation + réception | +| **`compliance`** | Contrôles SOC 2 / ISO 27001 | Flux de collecte de preuves | +| **`helpdesk`** | Support client orienté IA | Tickets + SLA + copilote IA | +| **`content`** | Calendrier éditorial + ROI par canal | Cycle de vie + métriques | +| **`hr`** | Annuaire, organigramme, congés | Applications centrées sur les personnes | +| **`project`** | Suivi de projets / tâches / jalons | Outils de gestion de projet | + +Source : [github.com/objectstack-ai/templates](https://github.com/objectstack-ai/templates). +Apache-2.0. Clonez sans demander. + +## Installer en 30 secondes (sans code) + +Dans Console : + +1. Ouvrez **Marketplace** → recherchez le modèle. +2. Cliquez sur **Install**. +3. Actualisez — la nouvelle application apparaît dans votre navigation. + +C'est fait. Enregistrements, vues, flows, permissions — tout est en ligne. + +## Cloner comme base de code (pour les ingénieurs) + +```bash +pnpm dlx @objectstack/cli create my-app --template todo +cd my-app +pnpm install +pnpm dev # http://localhost:4002 +``` + +Le clone est un package pnpm autonome — des fichiers `*.object.ts`, +`*.view.ts`, `*.flow.ts` que vous pouvez éditer, analyser, tester, +committer. Lorsque vous êtes satisfait : + +```bash +pnpm build +os package publish # → votre marketplace +``` + +Les clients qui installent votre fork obtiennent **votre** marque et +**vos** modifications. + +## Charte du modèle (le contrat social) + +Chaque modèle est livré avec un fichier `CHARTER.md` qui déclare sa +portée et ses limites strictes — généralement : ≤ 6 objets métier, +≤ 2 500 lignes de code sous `src/`, une application, une locale par +défaut. La charte existe pour que les modèles restent des **modèles**, +et non des produits à moitié finis. Si un fork dépasse ces limites, +publiez-le comme un nouveau modèle, ne surchargez pas un modèle existant. + +Consultez le [TEMPLATE_GUIDE.md](https://github.com/objectstack-ai/templates/blob/main/TEMPLATE_GUIDE.md) +en amont pour le protocole des suffixes de fichiers (`*.object.ts`, `*.state.ts`, `*.hook.ts`, …), +la séquence d'écriture (objects → state → hooks → views → flows → …), +et les services de plateforme polymorphes (`sys_comment`, `sys_attachment`, +`sys_audit_log`) que vous devriez réutiliser plutôt que de réinventer. + +## Choisir un point de départ + +| Si vous construisez… | Clonez ceci | Pourquoi | +|---|---|---| +| Tout outil interne qui suit des « choses » | `todo` | La démonstration la plus simple et la plus propre de toutes les primitives | +| Tout ce qui implique des chaînes d'approbation | `procurement` ou `contracts` | De véritables processus d'approbation déjà câblés | +| Tout ce qui est orienté client avec de l'IA | `helpdesk` | Modèle agent + copilote de ticket | +| Un flux de travail en secteur réglementé | `compliance` | Audit + preuves + cartographie des contrôles | +| Une application annuaire / organigramme | `hr` | Annuaire + structure hiérarchique | + +## AI Builder + modèles ensemble + +Vous pouvez cloner un modèle et **continuer** à utiliser l'AI Builder +par-dessus. Installez `helpdesk`, puis dites : + +> *« Ajoute un champ entier `csat_score` à `hd_ticket`, plage 1–5, +> demande-le à la clôture. »* + +L'IA étend le package installé sur place. Renvoyez la modification vers +le dépôt source avec `os package export`. + +## Pour aller plus loin + +- [AI Builder](/docs/build/ai-builder) — étendez n'importe quel modèle par chat +- [Packages](/docs/build/packages) — ce qu'est réellement un modèle +- [Marketplace](/docs/build/marketplace) — distribuez votre fork +- [Quickstart](/docs/quickstart) — le parcours développeur complet de bout en bout diff --git a/content/docs/build/templates.ja.mdx b/content/docs/build/templates.ja.mdx new file mode 100644 index 0000000..0181dbc --- /dev/null +++ b/content/docs/build/templates.ja.mdx @@ -0,0 +1,108 @@ +--- +title: テンプレート +description: フォーク可能なスターターパッケージ — `todo`、`contracts`、`procurement`、`helpdesk` など。 +--- + +# テンプレート + +テンプレートは**フォーク可能なスターターパッケージ**です。それぞれが実際に +形になったアプリであり、marketplace からワンクリックでインストールするか、 +CLI でクローンして拡張可能な TypeScript コードベースを取得できます。 + +テンプレートが存在する理由は 2 つあります。 + +1. **語るより見せる** — 動作するマルチオブジェクトのアプリは、ドキュメントよりも + 素早く理解できます。 +2. **エンジニアリングチームに出発点を提供する** — DB に AI 生成のメタデータがある + だけでなく、ソース管理下にコードを置きたい場合に役立ちます。 + +## デフォルトカタログに含まれるもの + +| テンプレート | ドメイン | フォーク向けのスターター対象… | +|---|---|---| +| **`todo`** | タスクとプロジェクト | 「何らかの方法でグループ化された、やるべきこと」を扱うあらゆるツール | +| **`contracts`** | AI 条項抽出付きの CLM | 承認 + ドキュメント AI | +| **`procurement`** | ベンダー、発注書、3-way マッチ | 承認チェーン + 受領 | +| **`compliance`** | SOC 2 / ISO 27001 統制 | エビデンス収集ワークフロー | +| **`helpdesk`** | AI ファーストのカスタマーサポート | チケット + SLA + AI コパイロット | +| **`content`** | 編集カレンダー + チャネル ROI | ライフサイクル + メトリクス | +| **`hr`** | ディレクトリ、組織図、休暇 | 人材中心のアプリ | +| **`project`** | プロジェクト / タスク / マイルストーン追跡 | PM ツール | + +ソース: [github.com/objectstack-ai/templates](https://github.com/objectstack-ai/templates)。 +Apache-2.0。許可なくフォークしてください。 + +## 30 秒でインストール(コード不要) + +Console で: + +1. **Marketplace** を開く → テンプレートを検索する。 +2. **Install** をクリックする。 +3. 更新する — 新しいアプリがナビゲーションに表示されます。 + +完了です。レコード、ビュー、フロー、権限 — すべて稼働しています。 + +## コードベースとしてフォークする(エンジニア向け) + +```bash +pnpm dlx @objectstack/cli create my-app --template todo +cd my-app +pnpm install +pnpm dev # http://localhost:4002 +``` + +クローンは自己完結型の pnpm パッケージで、編集、lint、テスト、コミットが可能な +`*.object.ts`、`*.view.ts`、`*.flow.ts` ファイルで構成されています。準備が +できたら: + +```bash +pnpm build +os package publish # → your marketplace +``` + +あなたのフォークをインストールした顧客は、**あなたの**ブランドと**あなたの** +変更内容を受け取ります。 + +## テンプレート憲章(ソーシャルコントラクト) + +すべてのテンプレートは、そのスコープと厳格な制限を宣言する `CHARTER.md` を +備えています。典型的には、ビジネスオブジェクト 6 個以下、`src/` 配下のコード +2,500 行以下、アプリ 1 つ、デフォルトロケール 1 つです。憲章が存在するのは、 +テンプレートが未完成の製品ではなく、**テンプレート**であり続けるためです。 +フォークがこれらの制限を超えて成長した場合は、新しいテンプレートとして公開し、 +既存のものを肥大化させないでください。 + +ファイルサフィックスのプロトコル(`*.object.ts`、`*.state.ts`、`*.hook.ts` など)、 +オーサリングの順序(objects → state → hooks → views → flows → …)、および +再発明せずに再利用すべきポリモーフィックなプラットフォームサービス +(`sys_comment`、`sys_attachment`、`sys_audit_log`)については、上流の +[TEMPLATE_GUIDE.md](https://github.com/objectstack-ai/templates/blob/main/TEMPLATE_GUIDE.md) +を参照してください。 + +## 出発点を選ぶ + +| 構築するものが… | これをフォーク | 理由 | +|---|---|---| +| 「何か」を追跡する社内ツール全般 | `todo` | すべてのプリミティブを最小かつ最もクリーンに示すデモ | +| 承認チェーンを伴うもの | `procurement` または `contracts` | 実際の承認プロセスが組み込まれている | +| AI を備えた顧客向けのもの | `helpdesk` | エージェント + チケットコパイロットのパターン | +| 規制業界のワークフロー | `compliance` | 監査 + エビデンス + 統制マッピング | +| 人材 / 組織図アプリ | `hr` | ディレクトリ + レポートライン構造 | + +## AI Builder とテンプレートを組み合わせる + +テンプレートをフォークしても、その上で **引き続き** AI Builder を使用できます。 +`helpdesk` をインストールしてから、次のように指示します。 + +> *「`hd_ticket` に範囲 1〜5 の `csat_score` 整数フィールドを追加し、クローズ時に +> 入力を求めて。」* + +AI はインストール済みのパッケージをその場で拡張します。`os package export` で +変更をソースリポジトリにプッシュしてください。 + +## 次に進む先 + +- [AI Builder](/docs/build/ai-builder) — チャットで任意のテンプレートを拡張する +- [Packages](/docs/build/packages) — テンプレートとは実際には何か +- [Marketplace](/docs/build/marketplace) — あなたのフォークを配布する +- [Quickstart](/docs/quickstart) — 開発者パスのエンドツーエンド全体 diff --git a/content/docs/build/templates.cn.mdx b/content/docs/build/templates.zh-Hans.mdx similarity index 100% rename from content/docs/build/templates.cn.mdx rename to content/docs/build/templates.zh-Hans.mdx diff --git a/content/docs/build/views.de.mdx b/content/docs/build/views.de.mdx new file mode 100644 index 0000000..65b4a4c --- /dev/null +++ b/content/docs/build/views.de.mdx @@ -0,0 +1,246 @@ +--- +title: Views +description: List, Form, Kanban, Calendar, Gantt und mehr — wie jede Objektoberfläche in der Console deklariert wird. +--- + +# Views + +Eine **View** ist die Art und Weise, wie ein Benutzer Datensätze in der +Console sieht und bearbeitet. Views sind deklarative Metadaten — mit +demselben Lebenszyklus wie Objekte: einmal deklarieren, mit Ihrem Paket +ausliefern, überall rendern. + +Zwei Arten: + +- **List Views** — viele Datensätze visualisieren (Grid, Kanban, Calendar, …) +- **Form Views** — einen einzelnen Datensatz ansehen / bearbeiten (simple, tabbed, + wizard, …) + +Schema-Quelle: +[`packages/spec/src/ui/view.zod.ts`](https://github.com/objectstack-ai/framework/blob/main/packages/spec/src/ui/view.zod.ts). + +## Die kürzestmögliche Deklaration + +Jedes Objekt erhält automatisch eine Standard-Grid-Liste + ein einfaches +Formular, selbst wenn Sie keine Views deklarieren. Fügen Sie `view` hinzu, +um zu überschreiben oder zu erweitern: + +```ts +import { defineObject, F, P } from '@objectstack/spec' + +export default defineObject({ + name: 'support_ticket', + fields: [ /* ... */ ], + + view: { + list: { type: 'grid', columns: ['subject', 'status', 'priority', 'assignee'] }, + form: { sections: [ { label: 'Details', fields: ['subject','description','priority','status','assignee'] } ] } + } +}) +``` + +Für Objekte mit mehreren Views (z. B. ein Kanban *und* ein Calendar über +denselben Daten) verwenden Sie die benannten Varianten: + +```ts +view: { + listViews: { + by_status: { type: 'kanban', kanban: { groupByField: 'status' }, columns: ['subject','priority'] }, + schedule: { type: 'calendar', calendar: { startDateField: 'due_at', titleField: 'subject' } }, + by_owner: { type: 'grid', columns: ['subject','status','priority'], filterableFields: ['assignee'] } + }, + formViews: { + quick: { type: 'modal', sections: [ /* ... */ ] }, + full: { type: 'tabbed', sections: [ /* ... */ ] } + } +} +``` + +## List-View-Typen + +| `type` | Rendert | Erforderliche Konfiguration | +|:--|:--|:--| +| `grid` | Datentabelle (Standard) | `columns` | +| `kanban` | Board mit Spalten | `kanban: { groupByField }` | +| `gallery` | Kartenstapel | `gallery: { coverField, titleField }` | +| `calendar` | Monat / Woche / Tag | `calendar: { startDateField, titleField }` | +| `timeline` | Chronologischer Feed | `timeline: { startDateField, titleField }` | +| `gantt` | Projektzeitachse + Abhängigkeiten | `gantt: { startDateField, endDateField, titleField }` | +| `map` | Geografische Pins | `map: { locationField }` | +| `chart` | Eingebettetes Diagramm | `chart: { chartType, xAxisField, yAxisFields }` | + +### Allgemeine List-Optionen + +```ts +{ + type: 'grid', + columns: ['subject','status','priority','assignee','created_at'], + + filter: [ { field: 'archived', operator: 'equals', value: false } ], + sort: [ { field: 'created_at', order: 'desc' } ], + pagination: { pageSize: 25 }, + searchableFields: ['subject','description'], + filterableFields: ['status','priority','assignee'], + + navigation: { mode: 'drawer' }, // 'page' | 'drawer' | 'modal' | 'split' | 'popover' | 'new_window' | 'none' + selection: { type: 'multiple' }, // 'none' | 'single' | 'multiple' + + rowActions: ['close_ticket','assign_to_me'], + bulkActions: ['bulk_close','bulk_export'], + + conditionalFormatting: [ + { condition: P`record.priority == 'urgent'`, style: { background: '#fef2f2', fontWeight: 600 } } + ], + + exportOptions: ['csv','xlsx'], + emptyState: { title: 'No tickets yet', message: 'Create one to get started', icon: 'inbox' } +} +``` + +`filter` und `sort` werden zu [ObjectQL](/docs/reference/objectql) +kompiliert; `rowActions` und `bulkActions` verweisen per Name auf +[Actions](./actions). + +### Kanban + +```ts +{ + type: 'kanban', + kanban: { + groupByField: 'status', // discrete field — usually a select + summarizeField: 'amount', // optional total per column + columns: ['subject', 'priority', 'assignee'] // fields shown on each card + } +} +``` + +Die Spalten des Boards stammen aus den Werten des `groupByField`; ihre +Reihenfolge und Farbe werden den `select`-Optionsdefinitionen dieses +Feldes entnommen. + +Drag & Drop zwischen Spalten löst ein Update aus, das das gruppierte Feld +setzt — mit denselben Berechtigungsregeln wie bei einer manuellen +Bearbeitung. + +### Calendar + +```ts +{ + type: 'calendar', + calendar: { + startDateField: 'start_at', + endDateField: 'end_at', // optional — single-point if omitted + titleField: 'subject', + colorField: 'priority' // optional — colours events by value + } +} +``` + +### Gantt + +```ts +{ + type: 'gantt', + gantt: { + startDateField: 'start_at', + endDateField: 'due_at', + titleField: 'name', + progressField: 'percent_complete', // optional, drives the progress bar + dependenciesField: 'depends_on' // optional — multiselect lookup to same object + } +} +``` + +### Chart (inline) + +```ts +{ + type: 'chart', + chart: { + chartType: 'bar', // 'bar' | 'line' | 'pie' | 'area' | 'scatter' + xAxisField: 'created_at', + yAxisFields: ['amount'], + aggregation: 'sum', + groupByField: 'status' + } +} +``` + +Chart-Views sind für eingebettete Dashboards auf einem einzelnen Objekt +gedacht — für umfangreichere, objektübergreifende Analysen verwenden Sie +die dedizierte Reports-Oberfläche. + +## Form-View-Typen + +| `type` | Layout | +|:--|:--| +| `simple` | Einzelne Spalte oder Abschnitte (Standard) | +| `tabbed` | Abschnitte mit Tabs | +| `wizard` | Schritt-für-Schritt-Ablauf | +| `split` | Master-Detail mit zwei Bereichen | +| `drawer` | Formular im Seitenbereich | +| `modal` | Formular im Dialog | + +```ts +{ + type: 'tabbed', + sections: [ + { label: 'Overview', fields: ['subject','status','priority','assignee'] }, + { label: 'Customer', fields: ['customer','contact','email','phone'] }, + { label: 'Resolution', fields: ['resolution_notes','resolved_at'] } + ], + submitBehavior: { kind: 'next-record' } // 'thank-you' | 'redirect' | 'continue' | 'next-record' +} +``` + +### Öffentliche Formulare + +Formulare können anonym zugänglich gemacht werden: + +```ts +{ + type: 'simple', + sections: [ { fields: ['name','email','message'] } ], + sharing: { + enabled: true, + publicLink: 'contact-us', // slug under /forms/ + allowAnonymous: true + }, + submitBehavior: { kind: 'thank-you' } +} +``` + +Dadurch werden automatisch `GET /api/v1/forms/contact-us` und +`POST /api/v1/forms/contact-us/submit` bereitgestellt — öffentliche +Formularrouten, die keine Authentifizierung erfordern. Siehe +[REST API → Public forms](/docs/reference/rest-api#public-forms). + +## Sichtbarkeit, ARIA, Theming + +- `visibleOn: P\`...\`` — auf Formular-**Abschnitten** und **Feldern**, + blendet sie basierend auf Benutzer / Datensatz / Umgebung aus (CEL-Prädikat) +- `aria: { label, description, ... }` — ARIA-Attribute für Screenreader + (List- und Form-Views) +- `appearance: { showDescription, allowedVisualizations: [...] }` — auf + List-Views, schränkt ein, zu welchen List-Typen Endbenutzer wechseln können + +## Per Chat erstellen + +Normalerweise schreiben Sie View-Metadaten nicht von Hand. Weisen Sie den +AI Builder an: + +> *"Add a kanban view of the support_ticket object grouped by status, +> with cards showing subject and priority. Colour the columns red / +> amber / green by status."* + +Er ruft die Metadaten-Tools auf, stellt den Diff in die Warteschlange, +und sobald Sie ihn genehmigen, erscheint die View in der Console. Siehe +[AI Builder](./ai-builder). + +## Siehe auch + +- [Data model](./data-model) — die Objekte, aus denen Views lesen +- [Actions](./actions) — worauf `rowActions` / `bulkActions` verweisen +- [ObjectQL](/docs/reference/objectql) — wozu `filter` / `sort` kompiliert werden +- [CEL](/docs/reference/cel) — `conditionalFormatting`, `visibleOn` +- [`@objectstack/spec/ui/view.zod.ts`](https://github.com/objectstack-ai/framework/blob/main/packages/spec/src/ui/view.zod.ts) — Schema diff --git a/content/docs/build/views.es.mdx b/content/docs/build/views.es.mdx new file mode 100644 index 0000000..2a357ea --- /dev/null +++ b/content/docs/build/views.es.mdx @@ -0,0 +1,238 @@ +--- +title: Vistas +description: List, Form, Kanban, Calendar, Gantt y más — cómo se declara cada superficie de objeto en Console. +--- + +# Vistas + +Una **vista** es la forma en que un usuario ve y edita registros en Console. Las +vistas son metadatos declarativos — con el mismo ciclo de vida que los objetos: +decláralas una vez, distribúyelas con tu paquete y renderízalas en cualquier lugar. + +Dos tipos: + +- **Vistas de lista** — visualizan muchos registros (grid, kanban, calendar, …) +- **Vistas de formulario** — ver / editar un único registro (simple, con pestañas, + asistente, …) + +Fuente del esquema: +[`packages/spec/src/ui/view.zod.ts`](https://github.com/objectstack-ai/framework/blob/main/packages/spec/src/ui/view.zod.ts). + +## La declaración más corta posible + +Cada objeto obtiene automáticamente una lista en grid + un formulario simple por +defecto, incluso si no declaras ninguna vista. Añade `view` para sobrescribir o +ampliar: + +```ts +import { defineObject, F, P } from '@objectstack/spec' + +export default defineObject({ + name: 'support_ticket', + fields: [ /* ... */ ], + + view: { + list: { type: 'grid', columns: ['subject', 'status', 'priority', 'assignee'] }, + form: { sections: [ { label: 'Details', fields: ['subject','description','priority','status','assignee'] } ] } + } +}) +``` + +Para objetos con varias vistas (p. ej. un Kanban *y* un calendario sobre los +mismos datos) usa las variantes con nombre: + +```ts +view: { + listViews: { + by_status: { type: 'kanban', kanban: { groupByField: 'status' }, columns: ['subject','priority'] }, + schedule: { type: 'calendar', calendar: { startDateField: 'due_at', titleField: 'subject' } }, + by_owner: { type: 'grid', columns: ['subject','status','priority'], filterableFields: ['assignee'] } + }, + formViews: { + quick: { type: 'modal', sections: [ /* ... */ ] }, + full: { type: 'tabbed', sections: [ /* ... */ ] } + } +} +``` + +## Tipos de vista de lista + +| `type` | Renderiza | Configuración requerida | +|:--|:--|:--| +| `grid` | Tabla de datos (por defecto) | `columns` | +| `kanban` | Tablero con columnas | `kanban: { groupByField }` | +| `gallery` | Baraja de tarjetas | `gallery: { coverField, titleField }` | +| `calendar` | Mes / semana / día | `calendar: { startDateField, titleField }` | +| `timeline` | Feed cronológico | `timeline: { startDateField, titleField }` | +| `gantt` | Cronograma de proyecto + dependencias | `gantt: { startDateField, endDateField, titleField }` | +| `map` | Pines geoespaciales | `map: { locationField }` | +| `chart` | Gráfico incrustado | `chart: { chartType, xAxisField, yAxisFields }` | + +### Opciones comunes de lista + +```ts +{ + type: 'grid', + columns: ['subject','status','priority','assignee','created_at'], + + filter: [ { field: 'archived', operator: 'equals', value: false } ], + sort: [ { field: 'created_at', order: 'desc' } ], + pagination: { pageSize: 25 }, + searchableFields: ['subject','description'], + filterableFields: ['status','priority','assignee'], + + navigation: { mode: 'drawer' }, // 'page' | 'drawer' | 'modal' | 'split' | 'popover' | 'new_window' | 'none' + selection: { type: 'multiple' }, // 'none' | 'single' | 'multiple' + + rowActions: ['close_ticket','assign_to_me'], + bulkActions: ['bulk_close','bulk_export'], + + conditionalFormatting: [ + { condition: P`record.priority == 'urgent'`, style: { background: '#fef2f2', fontWeight: 600 } } + ], + + exportOptions: ['csv','xlsx'], + emptyState: { title: 'No tickets yet', message: 'Create one to get started', icon: 'inbox' } +} +``` + +`filter` y `sort` se compilan a [ObjectQL](/docs/reference/objectql); +`rowActions` y `bulkActions` referencian [actions](./actions) por nombre. + +### Kanban + +```ts +{ + type: 'kanban', + kanban: { + groupByField: 'status', // discrete field — usually a select + summarizeField: 'amount', // optional total per column + columns: ['subject', 'priority', 'assignee'] // fields shown on each card + } +} +``` + +Las columnas del tablero provienen de los valores del `groupByField`; su orden +y color se toman de las definiciones de opciones `select` de ese campo. + +Arrastrar y soltar entre columnas emite una actualización que establece el campo +agrupado — con las mismas reglas de permisos que una edición manual. + +### Calendar + +```ts +{ + type: 'calendar', + calendar: { + startDateField: 'start_at', + endDateField: 'end_at', // optional — single-point if omitted + titleField: 'subject', + colorField: 'priority' // optional — colours events by value + } +} +``` + +### Gantt + +```ts +{ + type: 'gantt', + gantt: { + startDateField: 'start_at', + endDateField: 'due_at', + titleField: 'name', + progressField: 'percent_complete', // optional, drives the progress bar + dependenciesField: 'depends_on' // optional — multiselect lookup to same object + } +} +``` + +### Chart (en línea) + +```ts +{ + type: 'chart', + chart: { + chartType: 'bar', // 'bar' | 'line' | 'pie' | 'area' | 'scatter' + xAxisField: 'created_at', + yAxisFields: ['amount'], + aggregation: 'sum', + groupByField: 'status' + } +} +``` + +Las vistas de gráfico son para paneles en línea sobre un único objeto — para +analíticas más ricas y entre objetos, usa la superficie dedicada de informes. + +## Tipos de vista de formulario + +| `type` | Diseño | +|:--|:--| +| `simple` | Columna única o secciones (por defecto) | +| `tabbed` | Secciones con pestañas | +| `wizard` | Flujo paso a paso | +| `split` | Maestro-detalle de dos paneles | +| `drawer` | Formulario en panel lateral | +| `modal` | Formulario en diálogo | + +```ts +{ + type: 'tabbed', + sections: [ + { label: 'Overview', fields: ['subject','status','priority','assignee'] }, + { label: 'Customer', fields: ['customer','contact','email','phone'] }, + { label: 'Resolution', fields: ['resolution_notes','resolved_at'] } + ], + submitBehavior: { kind: 'next-record' } // 'thank-you' | 'redirect' | 'continue' | 'next-record' +} +``` + +### Formularios públicos + +Los formularios pueden hacerse accesibles de forma anónima: + +```ts +{ + type: 'simple', + sections: [ { fields: ['name','email','message'] } ], + sharing: { + enabled: true, + publicLink: 'contact-us', // slug under /forms/ + allowAnonymous: true + }, + submitBehavior: { kind: 'thank-you' } +} +``` + +Esto expone automáticamente `GET /api/v1/forms/contact-us` y +`POST /api/v1/forms/contact-us/submit` — rutas de formulario público que +no requieren autenticación. Consulta [REST API → Public forms](/docs/reference/rest-api#public-forms). + +## Visibilidad, ARIA, temas + +- `visibleOn: P\`...\`` — en **secciones** y **campos** de formulario, ocúltalos + según el usuario / registro / entorno (predicado CEL) +- `aria: { label, description, ... }` — atributos ARIA para lectores de pantalla + (vistas de lista y de formulario) +- `appearance: { showDescription, allowedVisualizations: [...] }` — en vistas de + lista, restringe a qué tipos de lista pueden cambiar los usuarios finales + +## Construye por chat + +Normalmente no escribes los metadatos de vista a mano. Dile al AI Builder: + +> *"Añade una vista kanban del objeto support_ticket agrupada por status, +> con tarjetas que muestren subject y priority. Colorea las columnas en rojo / +> ámbar / verde según el status."* + +Este llama a las herramientas de metadatos, pone en cola el diff y, una vez que +lo apruebas, la vista aparece en Console. Consulta [AI Builder](./ai-builder). + +## Consulta también + +- [Data model](./data-model) — los objetos de los que leen las vistas +- [Actions](./actions) — a qué referencian `rowActions` / `bulkActions` +- [ObjectQL](/docs/reference/objectql) — a qué se compilan `filter` / `sort` +- [CEL](/docs/reference/cel) — `conditionalFormatting`, `visibleOn` +- [`@objectstack/spec/ui/view.zod.ts`](https://github.com/objectstack-ai/framework/blob/main/packages/spec/src/ui/view.zod.ts) — esquema diff --git a/content/docs/build/views.fr.mdx b/content/docs/build/views.fr.mdx new file mode 100644 index 0000000..9c99f21 --- /dev/null +++ b/content/docs/build/views.fr.mdx @@ -0,0 +1,238 @@ +--- +title: Vues +description: Liste, Formulaire, Kanban, Calendrier, Gantt et plus encore — comment chaque surface d'objet dans Console est déclarée. +--- + +# Vues + +Une **vue** correspond à la manière dont un utilisateur consulte et modifie +des enregistrements dans Console. Les vues sont des métadonnées +déclaratives — même cycle de vie que les objets : déclarez-les une fois, +livrez-les avec votre package, affichez-les n'importe où. + +Deux types : + +- **Vues de liste** — visualiser de nombreux enregistrements (grille, kanban, calendrier, …) +- **Vues de formulaire** — consulter / modifier un seul enregistrement (simple, à onglets, + assistant, …) + +Source du schéma : +[`packages/spec/src/ui/view.zod.ts`](https://github.com/objectstack-ai/framework/blob/main/packages/spec/src/ui/view.zod.ts). + +## La déclaration la plus courte possible + +Chaque objet obtient automatiquement une grille de liste par défaut et un formulaire +simple, même si vous ne déclarez aucune vue. Ajoutez `view` pour remplacer ou étendre : + +```ts +import { defineObject, F, P } from '@objectstack/spec' + +export default defineObject({ + name: 'support_ticket', + fields: [ /* ... */ ], + + view: { + list: { type: 'grid', columns: ['subject', 'status', 'priority', 'assignee'] }, + form: { sections: [ { label: 'Details', fields: ['subject','description','priority','status','assignee'] } ] } + } +}) +``` + +Pour les objets à vues multiples (par exemple un Kanban *et* un calendrier sur les +mêmes données), utilisez les variantes nommées : + +```ts +view: { + listViews: { + by_status: { type: 'kanban', kanban: { groupByField: 'status' }, columns: ['subject','priority'] }, + schedule: { type: 'calendar', calendar: { startDateField: 'due_at', titleField: 'subject' } }, + by_owner: { type: 'grid', columns: ['subject','status','priority'], filterableFields: ['assignee'] } + }, + formViews: { + quick: { type: 'modal', sections: [ /* ... */ ] }, + full: { type: 'tabbed', sections: [ /* ... */ ] } + } +} +``` + +## Types de vues de liste + +| `type` | Affiche | Configuration requise | +|:--|:--|:--| +| `grid` | Tableau de données (par défaut) | `columns` | +| `kanban` | Tableau avec colonnes | `kanban: { groupByField }` | +| `gallery` | Jeu de cartes | `gallery: { coverField, titleField }` | +| `calendar` | Mois / semaine / jour | `calendar: { startDateField, titleField }` | +| `timeline` | Flux chronologique | `timeline: { startDateField, titleField }` | +| `gantt` | Échéancier de projet + dépendances | `gantt: { startDateField, endDateField, titleField }` | +| `map` | Repères géospatiaux | `map: { locationField }` | +| `chart` | Graphique intégré | `chart: { chartType, xAxisField, yAxisFields }` | + +### Options de liste courantes + +```ts +{ + type: 'grid', + columns: ['subject','status','priority','assignee','created_at'], + + filter: [ { field: 'archived', operator: 'equals', value: false } ], + sort: [ { field: 'created_at', order: 'desc' } ], + pagination: { pageSize: 25 }, + searchableFields: ['subject','description'], + filterableFields: ['status','priority','assignee'], + + navigation: { mode: 'drawer' }, // 'page' | 'drawer' | 'modal' | 'split' | 'popover' | 'new_window' | 'none' + selection: { type: 'multiple' }, // 'none' | 'single' | 'multiple' + + rowActions: ['close_ticket','assign_to_me'], + bulkActions: ['bulk_close','bulk_export'], + + conditionalFormatting: [ + { condition: P`record.priority == 'urgent'`, style: { background: '#fef2f2', fontWeight: 600 } } + ], + + exportOptions: ['csv','xlsx'], + emptyState: { title: 'No tickets yet', message: 'Create one to get started', icon: 'inbox' } +} +``` + +`filter` et `sort` se compilent en [ObjectQL](/docs/reference/objectql) ; +`rowActions` et `bulkActions` référencent des [actions](./actions) par leur nom. + +### Kanban + +```ts +{ + type: 'kanban', + kanban: { + groupByField: 'status', // discrete field — usually a select + summarizeField: 'amount', // optional total per column + columns: ['subject', 'priority', 'assignee'] // fields shown on each card + } +} +``` + +Les colonnes du tableau proviennent des valeurs du `groupByField` ; leur ordre +et leur couleur sont repris des définitions d'options `select` de ce champ. + +Le glisser-déposer entre colonnes déclenche une mise à jour qui définit le +champ de regroupement — mêmes règles d'autorisation qu'une modification manuelle. + +### Calendrier + +```ts +{ + type: 'calendar', + calendar: { + startDateField: 'start_at', + endDateField: 'end_at', // optional — single-point if omitted + titleField: 'subject', + colorField: 'priority' // optional — colours events by value + } +} +``` + +### Gantt + +```ts +{ + type: 'gantt', + gantt: { + startDateField: 'start_at', + endDateField: 'due_at', + titleField: 'name', + progressField: 'percent_complete', // optional, drives the progress bar + dependenciesField: 'depends_on' // optional — multiselect lookup to same object + } +} +``` + +### Graphique (intégré) + +```ts +{ + type: 'chart', + chart: { + chartType: 'bar', // 'bar' | 'line' | 'pie' | 'area' | 'scatter' + xAxisField: 'created_at', + yAxisFields: ['amount'], + aggregation: 'sum', + groupByField: 'status' + } +} +``` + +Les vues de graphique servent aux tableaux de bord intégrés sur un seul objet — +pour des analyses plus riches et inter-objets, utilisez la surface de rapports dédiée. + +## Types de vues de formulaire + +| `type` | Mise en page | +|:--|:--| +| `simple` | Colonne unique ou sections (par défaut) | +| `tabbed` | Sections à onglets | +| `wizard` | Flux étape par étape | +| `split` | Maître-détail à deux volets | +| `drawer` | Formulaire en panneau latéral | +| `modal` | Formulaire en boîte de dialogue | + +```ts +{ + type: 'tabbed', + sections: [ + { label: 'Overview', fields: ['subject','status','priority','assignee'] }, + { label: 'Customer', fields: ['customer','contact','email','phone'] }, + { label: 'Resolution', fields: ['resolution_notes','resolved_at'] } + ], + submitBehavior: { kind: 'next-record' } // 'thank-you' | 'redirect' | 'continue' | 'next-record' +} +``` + +### Formulaires publics + +Les formulaires peuvent être rendus accessibles de manière anonyme : + +```ts +{ + type: 'simple', + sections: [ { fields: ['name','email','message'] } ], + sharing: { + enabled: true, + publicLink: 'contact-us', // slug under /forms/ + allowAnonymous: true + }, + submitBehavior: { kind: 'thank-you' } +} +``` + +Cela expose automatiquement `GET /api/v1/forms/contact-us` et +`POST /api/v1/forms/contact-us/submit` — des routes de formulaire publiques qui +ne nécessitent pas d'authentification. Voir [REST API → Public forms](/docs/reference/rest-api#public-forms). + +## Visibilité, ARIA, thématisation + +- `visibleOn: P\`...\`` — sur les **sections** et **champs** de formulaire, les masquer + selon l'utilisateur / l'enregistrement / l'environnement (prédicat CEL) +- `aria: { label, description, ... }` — attributs ARIA pour les lecteurs d'écran + (vues de liste et de formulaire) +- `appearance: { showDescription, allowedVisualizations: [...] }` — sur les vues de + liste, restreint les types de liste vers lesquels les utilisateurs finaux peuvent basculer + +## Construire par conversation + +En général, vous n'écrivez pas les métadonnées de vue à la main. Dites-le à l'AI Builder : + +> *"Ajoute une vue kanban de l'objet support_ticket regroupée par statut, +> avec des cartes affichant le sujet et la priorité. Colore les colonnes en rouge / +> ambre / vert selon le statut."* + +Il appelle les outils de métadonnées, met en file d'attente le diff, et une fois que +vous l'approuvez, la vue apparaît dans Console. Voir [AI Builder](./ai-builder). + +## Voir aussi + +- [Modèle de données](./data-model) — les objets que les vues lisent +- [Actions](./actions) — ce que référencent `rowActions` / `bulkActions` +- [ObjectQL](/docs/reference/objectql) — ce en quoi se compilent `filter` / `sort` +- [CEL](/docs/reference/cel) — `conditionalFormatting`, `visibleOn` +- [`@objectstack/spec/ui/view.zod.ts`](https://github.com/objectstack-ai/framework/blob/main/packages/spec/src/ui/view.zod.ts) — schéma diff --git a/content/docs/build/views.ja.mdx b/content/docs/build/views.ja.mdx new file mode 100644 index 0000000..2cc2d0f --- /dev/null +++ b/content/docs/build/views.ja.mdx @@ -0,0 +1,237 @@ +--- +title: ビュー +description: リスト、フォーム、カンバン、カレンダー、ガントなど — Console におけるすべてのオブジェクト画面の宣言方法。 +--- + +# ビュー + +**ビュー** とは、ユーザーが Console でレコードを閲覧・編集する方法です。ビューは +宣言的メタデータであり、オブジェクトと同じライフサイクルを持ちます。一度宣言すれば、 +パッケージとともに配布し、どこでもレンダリングできます。 + +2 種類あります。 + +- **リストビュー** — 多数のレコードを可視化(グリッド、カンバン、カレンダーなど) +- **フォームビュー** — 単一レコードの閲覧・編集(シンプル、タブ、 + ウィザードなど) + +スキーマソース: +[`packages/spec/src/ui/view.zod.ts`](https://github.com/objectstack-ai/framework/blob/main/packages/spec/src/ui/view.zod.ts)。 + +## 最小限の宣言 + +すべてのオブジェクトは、ビューを宣言しなくても自動的にデフォルトのグリッドリスト +とシンプルフォームを取得します。`view` を追加してオーバーライドまたは拡張できます。 + +```ts +import { defineObject, F, P } from '@objectstack/spec' + +export default defineObject({ + name: 'support_ticket', + fields: [ /* ... */ ], + + view: { + list: { type: 'grid', columns: ['subject', 'status', 'priority', 'assignee'] }, + form: { sections: [ { label: 'Details', fields: ['subject','description','priority','status','assignee'] } ] } + } +}) +``` + +マルチビューオブジェクト(例えば同じデータに対するカンバン *と* カレンダー)の場合は、 +名前付きバリアントを使用します。 + +```ts +view: { + listViews: { + by_status: { type: 'kanban', kanban: { groupByField: 'status' }, columns: ['subject','priority'] }, + schedule: { type: 'calendar', calendar: { startDateField: 'due_at', titleField: 'subject' } }, + by_owner: { type: 'grid', columns: ['subject','status','priority'], filterableFields: ['assignee'] } + }, + formViews: { + quick: { type: 'modal', sections: [ /* ... */ ] }, + full: { type: 'tabbed', sections: [ /* ... */ ] } + } +} +``` + +## リストビューの種類 + +| `type` | レンダリング | 必須の設定 | +|:--|:--|:--| +| `grid` | データテーブル(デフォルト) | `columns` | +| `kanban` | 列を持つボード | `kanban: { groupByField }` | +| `gallery` | カードデッキ | `gallery: { coverField, titleField }` | +| `calendar` | 月 / 週 / 日 | `calendar: { startDateField, titleField }` | +| `timeline` | 時系列フィード | `timeline: { startDateField, titleField }` | +| `gantt` | プロジェクトタイムライン + 依存関係 | `gantt: { startDateField, endDateField, titleField }` | +| `map` | 地理空間ピン | `map: { locationField }` | +| `chart` | 埋め込みチャート | `chart: { chartType, xAxisField, yAxisFields }` | + +### 共通のリストオプション + +```ts +{ + type: 'grid', + columns: ['subject','status','priority','assignee','created_at'], + + filter: [ { field: 'archived', operator: 'equals', value: false } ], + sort: [ { field: 'created_at', order: 'desc' } ], + pagination: { pageSize: 25 }, + searchableFields: ['subject','description'], + filterableFields: ['status','priority','assignee'], + + navigation: { mode: 'drawer' }, // 'page' | 'drawer' | 'modal' | 'split' | 'popover' | 'new_window' | 'none' + selection: { type: 'multiple' }, // 'none' | 'single' | 'multiple' + + rowActions: ['close_ticket','assign_to_me'], + bulkActions: ['bulk_close','bulk_export'], + + conditionalFormatting: [ + { condition: P`record.priority == 'urgent'`, style: { background: '#fef2f2', fontWeight: 600 } } + ], + + exportOptions: ['csv','xlsx'], + emptyState: { title: 'No tickets yet', message: 'Create one to get started', icon: 'inbox' } +} +``` + +`filter` と `sort` は [ObjectQL](/docs/reference/objectql) にコンパイルされます。 +`rowActions` と `bulkActions` は [actions](./actions) を名前で参照します。 + +### カンバン + +```ts +{ + type: 'kanban', + kanban: { + groupByField: 'status', // discrete field — usually a select + summarizeField: 'amount', // optional total per column + columns: ['subject', 'priority', 'assignee'] // fields shown on each card + } +} +``` + +ボードの列は `groupByField` の値から生成され、その順序と色は当該フィールドの +`select` オプション定義から取得されます。 + +列間でのドラッグ&ドロップは、グループ化されたフィールドを設定する更新を発行します。 +手動編集と同じ権限ルールが適用されます。 + +### カレンダー + +```ts +{ + type: 'calendar', + calendar: { + startDateField: 'start_at', + endDateField: 'end_at', // optional — single-point if omitted + titleField: 'subject', + colorField: 'priority' // optional — colours events by value + } +} +``` + +### ガント + +```ts +{ + type: 'gantt', + gantt: { + startDateField: 'start_at', + endDateField: 'due_at', + titleField: 'name', + progressField: 'percent_complete', // optional, drives the progress bar + dependenciesField: 'depends_on' // optional — multiselect lookup to same object + } +} +``` + +### チャート(インライン) + +```ts +{ + type: 'chart', + chart: { + chartType: 'bar', // 'bar' | 'line' | 'pie' | 'area' | 'scatter' + xAxisField: 'created_at', + yAxisFields: ['amount'], + aggregation: 'sum', + groupByField: 'status' + } +} +``` + +チャートビューは、単一オブジェクト上のインラインダッシュボード向けです。より高度な +オブジェクト横断分析には、専用のレポート画面を使用してください。 + +## フォームビューの種類 + +| `type` | レイアウト | +|:--|:--| +| `simple` | 単一カラムまたはセクション(デフォルト) | +| `tabbed` | タブ付きセクション | +| `wizard` | ステップバイステップのフロー | +| `split` | マスター・ディテールの 2 ペイン | +| `drawer` | サイドパネルフォーム | +| `modal` | ダイアログフォーム | + +```ts +{ + type: 'tabbed', + sections: [ + { label: 'Overview', fields: ['subject','status','priority','assignee'] }, + { label: 'Customer', fields: ['customer','contact','email','phone'] }, + { label: 'Resolution', fields: ['resolution_notes','resolved_at'] } + ], + submitBehavior: { kind: 'next-record' } // 'thank-you' | 'redirect' | 'continue' | 'next-record' +} +``` + +### 公開フォーム + +フォームは匿名アクセス可能にできます。 + +```ts +{ + type: 'simple', + sections: [ { fields: ['name','email','message'] } ], + sharing: { + enabled: true, + publicLink: 'contact-us', // slug under /forms/ + allowAnonymous: true + }, + submitBehavior: { kind: 'thank-you' } +} +``` + +これにより、`GET /api/v1/forms/contact-us` と +`POST /api/v1/forms/contact-us/submit` が自動的に公開されます。これらは +認証を必要としない公開フォームルートです。[REST API → Public forms](/docs/reference/rest-api#public-forms) を参照してください。 + +## 可視性、ARIA、テーマ + +- `visibleOn: P\`...\`` — フォームの **セクション** と **フィールド** に対して、 + ユーザー / レコード / 環境に基づいて非表示にします(CEL 述語) +- `aria: { label, description, ... }` — スクリーンリーダー向けの ARIA 属性 + (リストビューとフォームビュー) +- `appearance: { showDescription, allowedVisualizations: [...] }` — リスト + ビューにおいて、エンドユーザーが切り替えられるリストタイプを制限します + +## チャットで構築する + +通常、ビューのメタデータを手作業で書くことはありません。AI Builder に伝えましょう。 + +> *「support_ticket オブジェクトのカンバンビューを status でグループ化して追加し、 +> カードに subject と priority を表示してください。列を status に応じて +> 赤 / 黄 / 緑で色分けしてください。」* + +AI Builder はメタデータツールを呼び出し、差分をキューに入れます。承認すると、 +ビューが Console に表示されます。[AI Builder](./ai-builder) を参照してください。 + +## 関連項目 + +- [Data model](./data-model) — ビューが読み取るオブジェクト +- [Actions](./actions) — `rowActions` / `bulkActions` が参照するもの +- [ObjectQL](/docs/reference/objectql) — `filter` / `sort` のコンパイル先 +- [CEL](/docs/reference/cel) — `conditionalFormatting`、`visibleOn` +- [`@objectstack/spec/ui/view.zod.ts`](https://github.com/objectstack-ai/framework/blob/main/packages/spec/src/ui/view.zod.ts) — スキーマ diff --git a/content/docs/build/views.mdx b/content/docs/build/views.mdx index c4b44c2..5ec535c 100644 --- a/content/docs/build/views.mdx +++ b/content/docs/build/views.mdx @@ -60,9 +60,9 @@ view: { |:--|:--|:--| | `grid` | Data table (default) | `columns` | | `kanban` | Board with columns | `kanban: { groupByField }` | -| `gallery` | Card deck | `gallery: { imageField, titleField }` | +| `gallery` | Card deck | `gallery: { coverField, titleField }` | | `calendar` | Month / week / day | `calendar: { startDateField, titleField }` | -| `timeline` | Chronological feed | `timeline: { dateField, titleField }` | +| `timeline` | Chronological feed | `timeline: { startDateField, titleField }` | | `gantt` | Project timeline + dependencies | `gantt: { startDateField, endDateField, titleField }` | | `map` | Geospatial pins | `map: { locationField }` | | `chart` | Embedded chart | `chart: { chartType, xAxisField, yAxisFields }` | @@ -74,10 +74,9 @@ view: { type: 'grid', columns: ['subject','status','priority','assignee','created_at'], - filter: [ { field: 'archived', operator: '$eq', value: false } ], + filter: [ { field: 'archived', operator: 'equals', value: false } ], sort: [ { field: 'created_at', order: 'desc' } ], - pagination: { pageSize: 25, mode: 'cursor' }, // 'cursor' | 'offset' - expand: ['assignee'], + pagination: { pageSize: 25 }, searchableFields: ['subject','description'], filterableFields: ['status','priority','assignee'], @@ -104,20 +103,18 @@ view: { ```ts { type: 'kanban', - columns: ['subject','priority','assignee'], kanban: { - groupByField: 'status', // discrete field — usually a select + groupByField: 'status', // discrete field — usually a select summarizeField: 'amount', // optional total per column - columns: [ // explicit order + colour - { value: 'new', label: 'New', color: '#3b82f6' }, - { value: 'open', label: 'Open', color: '#f59e0b' }, - { value: 'resolved', label: 'Resolved', color: '#10b981' } - ] + columns: ['subject', 'priority', 'assignee'] // fields shown on each card } } ``` -Drag-drop between columns issues an `UPDATE` setting the grouped +The board's columns come from the `groupByField`'s values; their order +and colour are taken from that field's `select` option definitions. + +Drag-drop between columns issues an update setting the grouped field — same permission rules as a manual edit. ### Calendar @@ -164,8 +161,8 @@ field — same permission rules as a manual edit. } ``` -For full reports use the [Reports](/docs/build/reports) surface — chart -views are for inline dashboards on an object. +Chart views are for inline dashboards on a single object — for richer, +cross-object analytics use the dedicated reports surface. ## Form view types @@ -199,8 +196,8 @@ Forms can be made anonymous-accessible: type: 'simple', sections: [ { fields: ['name','email','message'] } ], sharing: { - type: 'collaborative', - publicSlug: 'contact-us', + enabled: true, + publicLink: 'contact-us', // slug under /forms/ allowAnonymous: true }, submitBehavior: { kind: 'thank-you' } @@ -208,16 +205,17 @@ Forms can be made anonymous-accessible: ``` This automatically exposes `GET /api/v1/forms/contact-us` and -`POST /api/v1/forms/contact-us/submit` — the only two REST routes that +`POST /api/v1/forms/contact-us/submit` — public form routes that don't require authentication. See [REST API → Public forms](/docs/reference/rest-api#public-forms). ## Visibility, ARIA, theming -Every view supports: - -- `visibleIf: P\`...\`` — hide the view based on user / record / env +- `visibleOn: P\`...\`` — on form **sections** and **fields**, hide them + based on user / record / env (CEL predicate) - `aria: { label, description, ... }` — ARIA attributes for screen readers -- `appearance: { showDescription, allowedVisualizations: [...] }` — restrict which list types end users can flip to + (list and form views) +- `appearance: { showDescription, allowedVisualizations: [...] }` — on list + views, restrict which list types end users can flip to ## Build by chat @@ -235,5 +233,5 @@ view shows up in Console. See [AI Builder](./ai-builder). - [Data model](./data-model) — the objects views read from - [Actions](./actions) — what `rowActions` / `bulkActions` reference - [ObjectQL](/docs/reference/objectql) — what `filter` / `sort` compile to -- [CEL](/docs/reference/cel) — `conditionalFormatting`, `visibleIf` +- [CEL](/docs/reference/cel) — `conditionalFormatting`, `visibleOn` - [`@objectstack/spec/ui/view.zod.ts`](https://github.com/objectstack-ai/framework/blob/main/packages/spec/src/ui/view.zod.ts) — schema diff --git a/content/docs/build/views.cn.mdx b/content/docs/build/views.zh-Hans.mdx similarity index 100% rename from content/docs/build/views.cn.mdx rename to content/docs/build/views.zh-Hans.mdx diff --git a/content/docs/configure/ai.de.mdx b/content/docs/configure/ai.de.mdx new file mode 100644 index 0000000..8122740 --- /dev/null +++ b/content/docs/configure/ai.de.mdx @@ -0,0 +1,205 @@ +--- +title: AI-Service +description: LLMs, Embedder, RAG und MCP — providerübergreifend einsteckbar, zur Laufzeit austauschbar. +--- + +# AI-Service + +ObjectOS behandelt AI als erstklassige Fähigkeit mit **drei einsteckbaren +Schichten**: + +| Schicht | Paket | Funktion | +|---|---|---| +| **Chat / Generierung** | `@objectstack/service-ai` | Konversationen, Tool-Calls, Streaming | +| **Embeddings** | `@objectstack/embedder-openai` (OpenAI-kompatibel) | Text → Vektoren für semantische Suche und RAG | +| **Wissen / RAG** | `@objectstack/service-knowledge` + Adapter | Dokumente → indizierte Wissensdatenbanken | + +Alle drei sind optional, alle drei sind providerunabhängig, und alle drei +lassen sich zur Laufzeit über **Console → Configuration** neu konfigurieren +— ohne Neustart. + +## Chat / Generierung + +Angetrieben vom [Vercel AI SDK](https://ai-sdk.dev). Installieren Sie den +oder die gewünschten Provider als Peer-Dependencies: + +```bash +pnpm add @ai-sdk/openai # OpenAI +pnpm add @ai-sdk/anthropic # Claude +pnpm add @ai-sdk/google # Gemini +pnpm add @ai-sdk/gateway # AI gateway / OpenRouter / proxies +``` + +Registrieren Sie dann das AI-Service-Plugin mit einem Vercel-SDK-Adapter: + +```ts +import { AIServicePlugin, VercelLLMAdapter } from '@objectstack/service-ai'; +import { openai } from '@ai-sdk/openai'; + +kernel.use(new AIServicePlugin({ + adapter: new VercelLLMAdapter({ model: openai('gpt-4o') }), + models: [ + { id: 'fast', provider: 'openai', model: 'gpt-4o-mini' }, + { id: 'smart', provider: 'openai', model: 'gpt-4o' }, + ], + defaultModelId: 'fast', +})); +``` + +Die `models`-Liste speist die Laufzeit-Modellregistry — sie steuert die +Auflösung des Standardmodells und die Kostenzuordnung in Traces. +Standardmäßig bindet sich das Plugin außerdem an den `ai`-Settings-Namespace +und baut den Adapter live neu auf, wenn ein Operator Provider/Anmeldedaten/Modell +in Console bearbeitet, sodass kein Neustart erforderlich ist. + +Die Provider-API-Schlüssel stammen aus den üblichen Umgebungsvariablen des +jeweiligen SDK: + +| Provider | Umgebungsvariable | +|---|---| +| OpenAI | `OPENAI_API_KEY` | +| Anthropic | `ANTHROPIC_API_KEY` | +| Google | `GOOGLE_GENERATIVE_AI_API_KEY` | +| AI Gateway | `AI_GATEWAY_API_KEY` | + +In Console können Sie diese stattdessen als Laufzeiteinstellungen einfügen — +sie durchlaufen dieselbe Rangfolge (env > settings), aber durch die +Live-Bearbeitung ist kein Neustart nötig. + +### Den AI-Service aus dem Code verwenden + +```ts +const ai = kernel.getService('ai'); + +// One-shot chat +const result = await ai.chat( + [{ role: 'user', content: 'Summarize ObjectStack in two sentences.' }], + { model: 'smart' }, +); + +// Structured output +const { object } = await ai.generateObject( + [{ role: 'user', content: 'Classify this ticket: ...' }], + { schema, model: 'fast' }, +); +``` + +Der Service stellt außerdem `complete()`, `streamChat()`, `embed()` und +`listModels()` bereit. Konversationen werden als `ai_conversations` / +`ai_messages` Datensätze persistiert und über die REST-API verwaltet +(`POST /api/v1/ai/chat`, `POST /api/v1/ai/conversations`). + +### Verwendung aus Agents und Flows + +Für deklarative AI — Agents, Skills und Tools — siehe +[AI Agents](/docs/build/agents). Flows können jede registrierte Aktion +aufrufen (einschließlich Aktionen, die einen `ai.chat()`- / `ai.generateObject()`-Aufruf +kapseln) als `action`-Knoten; siehe [Flows & Automation](/docs/build/flows) +für den umgebenden Kontext. + +## Embedder + +Der Embedder wandelt Text in dichte Vektoren um. Ein einziger +OpenAI-kompatibler Adapter, `@objectstack/embedder-openai`, deckt OpenAI +sowie jeden Provider ab, der einen OpenAI-kompatiblen `/v1/embeddings`-Endpunkt +bereitstellt — wählen Sie einen mit einem **Preset** (das die Basis-URL für +Sie setzt) oder verweisen Sie `baseUrl` auf einen eigenen Endpunkt. + +| Provider | `preset` | Hinweise | +|---|---|---| +| OpenAI | `openai` | `text-embedding-3-small`/`-large` | +| Azure OpenAI | `azure` | Vollständige Deployment-URL über `baseUrl` angeben | +| 阿里通义 DashScope | `dashscope` | `text-embedding-v3` | +| 智谱 GLM | `zhipu` | `embedding-2` | +| 硅基流动 SiliconFlow | `siliconflow` | Aggregator von OSS-Modellen | +| 火山 Doubao | `doubao` | ByteDance | +| MiniMax | `minimax` | — | +| Ollama (selbst gehostet) | `ollama` | Air-Gap-freundlich (`http://localhost:11434/v1`) | +| Custom | _(weglassen; `baseUrl` setzen)_ | Eigenen OpenAI-kompatiblen Endpunkt mitbringen | + +Im Code konfigurieren: + +```ts +import { createOpenAIEmbedder } from '@objectstack/embedder-openai'; + +const embedder = createOpenAIEmbedder({ + preset: 'openai', + model: 'text-embedding-3-small', + // apiKey from OPENAI_API_KEY env if omitted +}); +``` + +Oder zur Laufzeit über **Console → Configuration → AI → Embedder** auswählen. +Wechseln Sie Provider ohne Neustart; vorhandene Vektoren bleiben durchsuchbar +(Sie können im Hintergrund neu indizieren). + +## Wissen / RAG + +Der Knowledge-Service orchestriert die Dokumentenaufnahme, das Chunking, +das Embedding (über den Embedder-Service) und die Abfrage. Das eigentliche +Speicher- und Such-Backend ist einsteckbar: + +| Adapter | Backend | Geeignet für | +|---|---|---| +| `@objectstack/knowledge-memory` | In-Process | Entwicklung, Demos, kleine KBs | +| `@objectstack/knowledge-ragflow` | [RAGFlow](https://github.com/infiniflow/ragflow) | Hochwertiges OSS-RAG mit Chunking + Reranking | + +```ts +import { KnowledgeServicePlugin } from '@objectstack/service-knowledge'; +import { KnowledgeRagflowPlugin } from '@objectstack/knowledge-ragflow'; + +kernel.use(new KnowledgeServicePlugin({ defaultTopK: 10 })); +kernel.use(new KnowledgeRagflowPlugin({ + endpoint: process.env.RAGFLOW_ENDPOINT, // e.g. http://localhost:9380 + apiKey: process.env.RAGFLOW_API_KEY, +})); +``` + +Indizierte Wissensdatenbanken werden zu erstklassigen Objekten — fragen Sie +sie aus Flows ab, machen Sie sie in Console sichtbar, hängen Sie sie als +Retrieval-Kontext an AI-Assistenten an. + +## MCP — Model Context Protocol + +ObjectOS kann sich selbst als Tool-Server für AI-Agents (Claude Desktop, +IDEs, eigene Agents) über das offene [Model Context +Protocol](https://modelcontextprotocol.io) bereitstellen. + +```ts +import { MCPServerPlugin } from '@objectstack/plugin-mcp-server'; + +kernel.use(new MCPServerPlugin({ + transport: 'stdio', // or 'http' + autoStart: true, +})); +``` + +Agents entdecken und rufen ObjectOS-Tools über MCP auf — abhängig von den +Berechtigungen des aufrufenden Benutzers. Der Server überbrückt die +Tool-Registry des AI-Service, einschließlich universeller Tools wie +`list_objects`, `describe_object`, `query_records`, `get_record` und +`aggregate_data`. + +## Betriebsgarantien + +- **Keine zwingende Cloud-Abhängigkeit.** Verwenden Sie Ollama für Chat + + Ollama-Embedder + Memory-Knowledge — vollständig air-gapped. +- **Live austauschbar.** Ändern Sie den Provider in Console; neue Anfragen + nutzen den neuen Provider beim nächsten Aufruf. Kein Neustart. +- **Konfiguration pro Mandant.** Jede Environment hat ihre eigenen + AI-Einstellungen. Mandant A auf OpenAI, Mandant B auf Anthropic — dieselbe + Laufzeit. +- **Audit-Log-Einträge.** Jede Konversation, jeder Tool-Call und jede + Embedder-Anfrage kann auditiert werden (`@objectstack/plugin-audit`). +- **Kostenbewusst.** Token-Zahlen und Provider-IDs fließen in das Audit-Log + für Chargeback / Kostenanalyse. + +## Wie es weitergeht + +- [AI Agents](/docs/build/agents) — deklarative Agents, Skills und Tools +- [Flows & Automation](/docs/build/flows) — AI aus deklarativer Geschäftslogik aufrufen +- [Marketplace](/docs/build/marketplace) — AI-gestützte Apps im Standardkatalog +- [Security & Compliance](/docs/reference/security) — wie AI-Datenflüsse isoliert werden +- [`@objectstack/service-ai` Quellcode](https://github.com/objectstack-ai/framework/tree/main/packages/services/service-ai) +- [`@objectstack/embedder-openai` Quellcode](https://github.com/objectstack-ai/framework/tree/main/packages/plugins/embedder-openai) +- [`@objectstack/service-knowledge` Quellcode](https://github.com/objectstack-ai/framework/tree/main/packages/services/service-knowledge) diff --git a/content/docs/configure/ai.es.mdx b/content/docs/configure/ai.es.mdx new file mode 100644 index 0000000..e51b3c7 --- /dev/null +++ b/content/docs/configure/ai.es.mdx @@ -0,0 +1,207 @@ +--- +title: Servicio de IA +description: LLMs, generadores de embeddings, RAG y MCP — conectables entre proveedores, intercambiables en tiempo de ejecución. +--- + +# Servicio de IA + +ObjectOS trata la IA como una capacidad de primera clase con **tres capas +conectables**: + +| Capa | Paquete | Qué hace | +|---|---|---| +| **Chat / generación** | `@objectstack/service-ai` | Conversaciones, llamadas a herramientas, streaming | +| **Embeddings** | `@objectstack/embedder-openai` (compatible con OpenAI) | Texto → vectores para búsqueda semántica y RAG | +| **Conocimiento / RAG** | `@objectstack/service-knowledge` + adaptador | Documentos → bases de conocimiento indexadas | + +Las tres son opcionales, las tres son independientes del proveedor y las +tres pueden reconfigurarse en tiempo de ejecución desde **Console → +Configuration** sin necesidad de reiniciar. + +## Chat / generación + +Impulsado por el [Vercel AI SDK](https://ai-sdk.dev). Instala el o los +proveedores que quieras como peer deps: + +```bash +pnpm add @ai-sdk/openai # OpenAI +pnpm add @ai-sdk/anthropic # Claude +pnpm add @ai-sdk/google # Gemini +pnpm add @ai-sdk/gateway # AI gateway / OpenRouter / proxies +``` + +Luego registra el plugin del servicio de IA con un adaptador del Vercel-SDK: + +```ts +import { AIServicePlugin, VercelLLMAdapter } from '@objectstack/service-ai'; +import { openai } from '@ai-sdk/openai'; + +kernel.use(new AIServicePlugin({ + adapter: new VercelLLMAdapter({ model: openai('gpt-4o') }), + models: [ + { id: 'fast', provider: 'openai', model: 'gpt-4o-mini' }, + { id: 'smart', provider: 'openai', model: 'gpt-4o' }, + ], + defaultModelId: 'fast', +})); +``` + +La lista `models` alimenta el registro de modelos en tiempo de ejecución — +impulsa la resolución del modelo predeterminado y la atribución de costos +en las trazas. De forma predeterminada, el plugin también se vincula al +espacio de nombres de configuración `ai` y reconstruye el adaptador en vivo +cuando un operador edita el proveedor/credenciales/modelo en Console, por lo +que no se necesita reiniciar. + +Las claves de API de cada proveedor provienen de las variables de entorno +habituales de cada SDK: + +| Proveedor | Variable de entorno | +|---|---| +| OpenAI | `OPENAI_API_KEY` | +| Anthropic | `ANTHROPIC_API_KEY` | +| Google | `GOOGLE_GENERATIVE_AI_API_KEY` | +| AI Gateway | `AI_GATEWAY_API_KEY` | + +En Console puedes pegarlas como ajustes en tiempo de ejecución en su lugar — +pasan por la misma precedencia (env > settings), pero la edición en vivo +significa que no hay reinicio. + +### Uso del servicio de IA desde el código + +```ts +const ai = kernel.getService('ai'); + +// One-shot chat +const result = await ai.chat( + [{ role: 'user', content: 'Summarize ObjectStack in two sentences.' }], + { model: 'smart' }, +); + +// Structured output +const { object } = await ai.generateObject( + [{ role: 'user', content: 'Classify this ticket: ...' }], + { schema, model: 'fast' }, +); +``` + +El servicio también expone `complete()`, `streamChat()`, `embed()` y +`listModels()`. Las conversaciones se persisten como registros +`ai_conversations` / `ai_messages` y se gestionan a través de la API REST +(`POST /api/v1/ai/chat`, `POST /api/v1/ai/conversations`). + +### Uso desde agents y flows + +Para IA declarativa — agents, skills y herramientas — consulta +[AI Agents](/docs/build/agents). Los flows pueden invocar cualquier acción +registrada (incluidas las acciones que envuelven una llamada a +`ai.chat()` / `ai.generateObject()`) como un nodo `action`; consulta +[Flows & Automation](/docs/build/flows) para el contexto que lo rodea. + +## Embedders + +El embedder convierte texto en vectores densos. Un único adaptador +compatible con OpenAI, `@objectstack/embedder-openai`, cubre OpenAI más +cualquier proveedor que exponga un endpoint `/v1/embeddings` compatible con +OpenAI — elige uno con un **preset** (que establece la URL base por ti) o +apunta `baseUrl` a un endpoint personalizado. + +| Proveedor | `preset` | Notas | +|---|---|---| +| OpenAI | `openai` | `text-embedding-3-small`/`-large` | +| Azure OpenAI | `azure` | Proporciona la URL de despliegue completa mediante `baseUrl` | +| 阿里通义 DashScope | `dashscope` | `text-embedding-v3` | +| 智谱 GLM | `zhipu` | `embedding-2` | +| 硅基流动 SiliconFlow | `siliconflow` | Agregador de modelos OSS | +| 火山 Doubao | `doubao` | ByteDance | +| MiniMax | `minimax` | — | +| Ollama (autoalojado) | `ollama` | Apto para entornos aislados (`http://localhost:11434/v1`) | +| Personalizado | _(omítelo; establece `baseUrl`)_ | Usa tu propio endpoint compatible con OpenAI | + +Configurar en código: + +```ts +import { createOpenAIEmbedder } from '@objectstack/embedder-openai'; + +const embedder = createOpenAIEmbedder({ + preset: 'openai', + model: 'text-embedding-3-small', + // apiKey from OPENAI_API_KEY env if omitted +}); +``` + +O elige en tiempo de ejecución desde **Console → Configuration → AI → +Embedder**. Cambia de proveedor sin reiniciar; los vectores existentes +siguen siendo consultables (puedes reindexar en segundo plano). + +## Conocimiento / RAG + +El servicio de conocimiento orquesta la ingesta de documentos, el chunking, +la generación de embeddings (a través del servicio de embedder) y la +recuperación. El backend real de almacenamiento y búsqueda es conectable: + +| Adaptador | Backend | Adecuado para | +|---|---|---| +| `@objectstack/knowledge-memory` | En proceso | Desarrollo, demos, KBs pequeñas | +| `@objectstack/knowledge-ragflow` | [RAGFlow](https://github.com/infiniflow/ragflow) | RAG OSS de alta calidad con chunking + reranking | + +```ts +import { KnowledgeServicePlugin } from '@objectstack/service-knowledge'; +import { KnowledgeRagflowPlugin } from '@objectstack/knowledge-ragflow'; + +kernel.use(new KnowledgeServicePlugin({ defaultTopK: 10 })); +kernel.use(new KnowledgeRagflowPlugin({ + endpoint: process.env.RAGFLOW_ENDPOINT, // e.g. http://localhost:9380 + apiKey: process.env.RAGFLOW_API_KEY, +})); +``` + +Las bases de conocimiento indexadas se convierten en objetos de primera +clase — consúltalas desde flows, muéstralas en Console, adjúntalas a +asistentes de IA como contexto de recuperación. + +## MCP — Model Context Protocol + +ObjectOS puede exponerse a sí mismo como un servidor de herramientas para +agentes de IA (Claude Desktop, IDEs, agentes personalizados) a través del +[Model Context Protocol](https://modelcontextprotocol.io) abierto. + +```ts +import { MCPServerPlugin } from '@objectstack/plugin-mcp-server'; + +kernel.use(new MCPServerPlugin({ + transport: 'stdio', // or 'http' + autoStart: true, +})); +``` + +Los agentes descubren e invocan las herramientas de ObjectOS a través de MCP +— sujeto a los permisos del usuario que las llama. El servidor conecta el +registro de herramientas del servicio de IA, incluidas herramientas +universales como `list_objects`, `describe_object`, `query_records`, +`get_record` y `aggregate_data`. + +## Garantías operativas + +- **Sin dependencia obligatoria de la nube.** Usa Ollama para chat + el + embedder de Ollama + conocimiento en memoria — totalmente aislado. +- **Intercambiable en vivo.** Cambia de proveedor en Console; las nuevas + solicitudes usan el nuevo proveedor en la siguiente llamada. Sin reinicio. +- **Configuración por tenant.** Cada Environment tiene sus propios ajustes + de IA. Tenant A en OpenAI, tenant B en Anthropic — el mismo runtime. +- **Entradas en el registro de auditoría.** Cada conversación, llamada a + herramienta y solicitud al embedder puede auditarse + (`@objectstack/plugin-audit`). +- **Consciente del costo.** Los recuentos de tokens y los IDs de proveedor + fluyen hacia el registro de auditoría para el chargeback / análisis de + costos. + +## Adónde ir después + +- [AI Agents](/docs/build/agents) — agents, skills y herramientas declarativos +- [Flows & Automation](/docs/build/flows) — invoca la IA desde lógica de negocio declarativa +- [Marketplace](/docs/build/marketplace) — aplicaciones impulsadas por IA en el catálogo predeterminado +- [Security & Compliance](/docs/reference/security) — cómo se aíslan los flujos de datos de IA +- [Código fuente de `@objectstack/service-ai`](https://github.com/objectstack-ai/framework/tree/main/packages/services/service-ai) +- [Código fuente de `@objectstack/embedder-openai`](https://github.com/objectstack-ai/framework/tree/main/packages/plugins/embedder-openai) +- [Código fuente de `@objectstack/service-knowledge`](https://github.com/objectstack-ai/framework/tree/main/packages/services/service-knowledge) diff --git a/content/docs/configure/ai.fr.mdx b/content/docs/configure/ai.fr.mdx new file mode 100644 index 0000000..23c8507 --- /dev/null +++ b/content/docs/configure/ai.fr.mdx @@ -0,0 +1,210 @@ +--- +title: Service IA +description: LLM, embedders, RAG et MCP — enfichables selon les fournisseurs, interchangeables à l'exécution. +--- + +# Service IA + +ObjectOS traite l'IA comme une capacité de première classe avec **trois +couches enfichables** : + +| Couche | Package | Rôle | +|---|---|---| +| **Chat / génération** | `@objectstack/service-ai` | Conversations, appels d'outils, streaming | +| **Embeddings** | `@objectstack/embedder-openai` (compatible OpenAI) | Texte → vecteurs pour la recherche sémantique et le RAG | +| **Connaissance / RAG** | `@objectstack/service-knowledge` + adaptateur | Documents → bases de connaissances indexées | + +Les trois couches sont optionnelles, toutes les trois sont agnostiques +vis-à-vis du fournisseur, et toutes les trois peuvent être reconfigurées +à l'exécution depuis **Console → Configuration** sans redémarrage. + +## Chat / génération + +Propulsé par le [Vercel AI SDK](https://ai-sdk.dev). Installez le ou les +fournisseurs souhaités en tant que peer deps : + +```bash +pnpm add @ai-sdk/openai # OpenAI +pnpm add @ai-sdk/anthropic # Claude +pnpm add @ai-sdk/google # Gemini +pnpm add @ai-sdk/gateway # AI gateway / OpenRouter / proxies +``` + +Enregistrez ensuite le plugin du service IA avec un adaptateur Vercel-SDK : + +```ts +import { AIServicePlugin, VercelLLMAdapter } from '@objectstack/service-ai'; +import { openai } from '@ai-sdk/openai'; + +kernel.use(new AIServicePlugin({ + adapter: new VercelLLMAdapter({ model: openai('gpt-4o') }), + models: [ + { id: 'fast', provider: 'openai', model: 'gpt-4o-mini' }, + { id: 'smart', provider: 'openai', model: 'gpt-4o' }, + ], + defaultModelId: 'fast', +})); +``` + +La liste `models` alimente le registre de modèles à l'exécution — elle +pilote la résolution du modèle par défaut et l'attribution des coûts dans +les traces. Par défaut, le plugin se lie également à l'espace de noms de +paramètres `ai` et reconstruit l'adaptateur en direct lorsqu'un opérateur +modifie le fournisseur, les identifiants ou le modèle dans la Console, +de sorte qu'aucun redémarrage n'est nécessaire. + +Les clés d'API des fournisseurs proviennent des variables d'environnement +habituelles de chaque SDK : + +| Fournisseur | Variable d'env | +|---|---| +| OpenAI | `OPENAI_API_KEY` | +| Anthropic | `ANTHROPIC_API_KEY` | +| Google | `GOOGLE_GENERATIVE_AI_API_KEY` | +| AI Gateway | `AI_GATEWAY_API_KEY` | + +Dans la Console, vous pouvez plutôt les coller en tant que paramètres +d'exécution — ils suivent la même priorité (env > paramètres), mais +l'édition en direct évite tout redémarrage. + +### Utiliser le service IA depuis le code + +```ts +const ai = kernel.getService('ai'); + +// One-shot chat +const result = await ai.chat( + [{ role: 'user', content: 'Summarize ObjectStack in two sentences.' }], + { model: 'smart' }, +); + +// Structured output +const { object } = await ai.generateObject( + [{ role: 'user', content: 'Classify this ticket: ...' }], + { schema, model: 'fast' }, +); +``` + +Le service expose également `complete()`, `streamChat()`, `embed()` et +`listModels()`. Les conversations sont persistées sous forme +d'enregistrements `ai_conversations` / `ai_messages` et gérées via l'API +REST (`POST /api/v1/ai/chat`, `POST /api/v1/ai/conversations`). + +### L'utiliser depuis les agents et les flux + +Pour l'IA déclarative — agents, skills et outils — consultez +[AI Agents](/docs/build/agents). Les flux peuvent invoquer n'importe +quelle action enregistrée (y compris les actions qui encapsulent un appel +`ai.chat()` / `ai.generateObject()`) en tant que nœud `action` ; voir +[Flows & Automation](/docs/build/flows) pour le contexte environnant. + +## Embedders + +L'embedder convertit le texte en vecteurs denses. Un unique adaptateur +compatible OpenAI, `@objectstack/embedder-openai`, couvre OpenAI ainsi que +tout fournisseur exposant un point de terminaison `/v1/embeddings` +compatible OpenAI — choisissez-en un avec un **preset** (qui définit +l'URL de base pour vous) ou pointez `baseUrl` vers un point de terminaison +personnalisé. + +| Fournisseur | `preset` | Notes | +|---|---|---| +| OpenAI | `openai` | `text-embedding-3-small`/`-large` | +| Azure OpenAI | `azure` | Fournir l'URL de déploiement complète via `baseUrl` | +| 阿里通义 DashScope | `dashscope` | `text-embedding-v3` | +| 智谱 GLM | `zhipu` | `embedding-2` | +| 硅基流动 SiliconFlow | `siliconflow` | Agrégateur de modèles OSS | +| 火山 Doubao | `doubao` | ByteDance | +| MiniMax | `minimax` | — | +| Ollama (auto-hébergé) | `ollama` | Adapté aux environnements isolés (`http://localhost:11434/v1`) | +| Personnalisé | _(omettre ; définir `baseUrl`)_ | Apportez votre propre point de terminaison compatible OpenAI | + +Configurer dans le code : + +```ts +import { createOpenAIEmbedder } from '@objectstack/embedder-openai'; + +const embedder = createOpenAIEmbedder({ + preset: 'openai', + model: 'text-embedding-3-small', + // apiKey from OPENAI_API_KEY env if omitted +}); +``` + +Ou choisissez à l'exécution depuis **Console → Configuration → AI → +Embedder**. Changez de fournisseur sans redémarrage ; les vecteurs +existants restent interrogeables (vous pouvez réindexer en arrière-plan). + +## Connaissance / RAG + +Le service de connaissance orchestre l'ingestion de documents, le +découpage en chunks, l'embedding (via le service d'embedder) et la +récupération. Le backend réel de stockage et de recherche est enfichable : + +| Adaptateur | Backend | Idéal pour | +|---|---|---| +| `@objectstack/knowledge-memory` | En mémoire (in-process) | Développement, démos, petites bases de connaissances | +| `@objectstack/knowledge-ragflow` | [RAGFlow](https://github.com/infiniflow/ragflow) | RAG OSS de haute qualité avec chunking + reranking | + +```ts +import { KnowledgeServicePlugin } from '@objectstack/service-knowledge'; +import { KnowledgeRagflowPlugin } from '@objectstack/knowledge-ragflow'; + +kernel.use(new KnowledgeServicePlugin({ defaultTopK: 10 })); +kernel.use(new KnowledgeRagflowPlugin({ + endpoint: process.env.RAGFLOW_ENDPOINT, // e.g. http://localhost:9380 + apiKey: process.env.RAGFLOW_API_KEY, +})); +``` + +Les bases de connaissances indexées deviennent des objets de première +classe — interrogez-les depuis les flux, exposez-les dans la Console, +attachez-les aux assistants IA en tant que contexte de récupération. + +## MCP — Model Context Protocol + +ObjectOS peut s'exposer comme serveur d'outils aux agents IA (Claude +Desktop, IDE, agents personnalisés) via le [Model Context +Protocol](https://modelcontextprotocol.io) ouvert. + +```ts +import { MCPServerPlugin } from '@objectstack/plugin-mcp-server'; + +kernel.use(new MCPServerPlugin({ + transport: 'stdio', // or 'http' + autoStart: true, +})); +``` + +Les agents découvrent et invoquent les outils ObjectOS via MCP — sous +réserve des permissions de l'utilisateur appelant. Le serveur fait le pont +avec le registre d'outils du service IA, y compris les outils universels +tels que `list_objects`, `describe_object`, `query_records`, `get_record` +et `aggregate_data`. + +## Garanties opérationnelles + +- **Aucune dépendance cloud obligatoire.** Utilisez Ollama pour le chat + + l'embedder Ollama + la connaissance en mémoire — entièrement isolé du + réseau. +- **Interchangeable en direct.** Changez de fournisseur dans la Console ; + les nouvelles requêtes utilisent le nouveau fournisseur au prochain + appel. Aucun redémarrage. +- **Configuration par locataire.** Chaque Environment possède ses propres + paramètres IA. Le locataire A sur OpenAI, le locataire B sur Anthropic — + même runtime. +- **Entrées de journal d'audit.** Chaque conversation, appel d'outil et + requête d'embedder peut être audité (`@objectstack/plugin-audit`). +- **Conscient des coûts.** Le nombre de tokens et les identifiants de + fournisseur remontent jusqu'au journal d'audit pour la refacturation et + l'analyse des coûts. + +## Pour aller plus loin + +- [AI Agents](/docs/build/agents) — agents, skills et outils déclaratifs +- [Flows & Automation](/docs/build/flows) — appeler l'IA depuis une logique métier déclarative +- [Marketplace](/docs/build/marketplace) — applications propulsées par l'IA dans le catalogue par défaut +- [Security & Compliance](/docs/reference/security) — comment les flux de données IA sont isolés +- [Source de `@objectstack/service-ai`](https://github.com/objectstack-ai/framework/tree/main/packages/services/service-ai) +- [Source de `@objectstack/embedder-openai`](https://github.com/objectstack-ai/framework/tree/main/packages/plugins/embedder-openai) +- [Source de `@objectstack/service-knowledge`](https://github.com/objectstack-ai/framework/tree/main/packages/services/service-knowledge) diff --git a/content/docs/configure/ai.ja.mdx b/content/docs/configure/ai.ja.mdx new file mode 100644 index 0000000..413c67a --- /dev/null +++ b/content/docs/configure/ai.ja.mdx @@ -0,0 +1,165 @@ +--- +title: AI サービス +description: LLM、埋め込み、RAG、MCP — プロバイダーをまたいでプラグイン化でき、実行時に差し替え可能。 +--- + +# AI サービス + +ObjectOS は AI を第一級の機能として扱い、**3 つのプラグイン可能なレイヤー**を提供します。 + +| レイヤー | パッケージ | 役割 | +|---|---|---| +| **チャット / 生成** | `@objectstack/service-ai` | 会話、ツール呼び出し、ストリーミング | +| **埋め込み** | `@objectstack/embedder-openai`(OpenAI 互換) | テキスト → ベクトル(セマンティック検索と RAG 用) | +| **ナレッジ / RAG** | `@objectstack/service-knowledge` + アダプター | ドキュメント → インデックス化されたナレッジベース | + +3 つとも任意であり、3 つともプロバイダー非依存で、3 つとも再起動なしに **Console → Configuration** から実行時に再設定できます。 + +## チャット / 生成 + +[Vercel AI SDK](https://ai-sdk.dev) を基盤としています。必要なプロバイダーをピア依存としてインストールしてください。 + +```bash +pnpm add @ai-sdk/openai # OpenAI +pnpm add @ai-sdk/anthropic # Claude +pnpm add @ai-sdk/google # Gemini +pnpm add @ai-sdk/gateway # AI gateway / OpenRouter / proxies +``` + +次に、Vercel SDK アダプターを指定して AI サービスプラグインを登録します。 + +```ts +import { AIServicePlugin, VercelLLMAdapter } from '@objectstack/service-ai'; +import { openai } from '@ai-sdk/openai'; + +kernel.use(new AIServicePlugin({ + adapter: new VercelLLMAdapter({ model: openai('gpt-4o') }), + models: [ + { id: 'fast', provider: 'openai', model: 'gpt-4o-mini' }, + { id: 'smart', provider: 'openai', model: 'gpt-4o' }, + ], + defaultModelId: 'fast', +})); +``` + +`models` リストは実行時のモデルレジストリに渡され、デフォルトモデルの解決やトレースにおけるコスト按分を駆動します。デフォルトでは、プラグインは `ai` 設定ネームスペースにもバインドされ、オペレーターが Console でプロバイダー / 認証情報 / モデルを編集すると、アダプターをライブで再構築します。そのため再起動は不要です。 + +プロバイダーの API キーは、各 SDK の通常の環境変数から取得されます。 + +| プロバイダー | 環境変数 | +|---|---| +| OpenAI | `OPENAI_API_KEY` | +| Anthropic | `ANTHROPIC_API_KEY` | +| Google | `GOOGLE_GENERATIVE_AI_API_KEY` | +| AI Gateway | `AI_GATEWAY_API_KEY` | + +Console ではこれらを実行時設定として貼り付けることもできます。同じ優先順位(env > settings)に従いますが、ライブ編集なので再起動は不要です。 + +### コードから AI サービスを使う + +```ts +const ai = kernel.getService('ai'); + +// One-shot chat +const result = await ai.chat( + [{ role: 'user', content: 'Summarize ObjectStack in two sentences.' }], + { model: 'smart' }, +); + +// Structured output +const { object } = await ai.generateObject( + [{ role: 'user', content: 'Classify this ticket: ...' }], + { schema, model: 'fast' }, +); +``` + +このサービスは `complete()`、`streamChat()`、`embed()`、`listModels()` も公開しています。会話は `ai_conversations` / `ai_messages` レコードとして永続化され、REST API(`POST /api/v1/ai/chat`、`POST /api/v1/ai/conversations`)経由で管理されます。 + +### エージェントとフローから使う + +宣言的な AI — エージェント、スキル、ツール — については [AI Agents](/docs/build/agents) を参照してください。フローは、登録済みの任意のアクション(`ai.chat()` / `ai.generateObject()` 呼び出しをラップするアクションを含む)を `action` ノードとして呼び出せます。周辺の文脈については [Flows & Automation](/docs/build/flows) を参照してください。 + +## 埋め込み(Embedders) + +埋め込みはテキストを密ベクトルに変換します。単一の OpenAI 互換アダプター `@objectstack/embedder-openai` は、OpenAI に加えて、OpenAI 互換の `/v1/embeddings` エンドポイントを公開するあらゆるプロバイダーをカバーします。**プリセット**(ベースURLを自動設定します)を選ぶか、`baseUrl` をカスタムエンドポイントに向けてください。 + +| プロバイダー | `preset` | 備考 | +|---|---|---| +| OpenAI | `openai` | `text-embedding-3-small`/`-large` | +| Azure OpenAI | `azure` | `baseUrl` で完全なデプロイメント URL を指定 | +| 阿里通义 DashScope | `dashscope` | `text-embedding-v3` | +| 智谱 GLM | `zhipu` | `embedding-2` | +| 硅基流动 SiliconFlow | `siliconflow` | OSS モデルのアグリゲーター | +| 火山 Doubao | `doubao` | ByteDance | +| MiniMax | `minimax` | — | +| Ollama(セルフホスト) | `ollama` | エアギャップ環境に対応(`http://localhost:11434/v1`) | +| カスタム | _(省略し、`baseUrl` を設定)_ | 独自の OpenAI 互換エンドポイントを使用 | + +コードでの設定: + +```ts +import { createOpenAIEmbedder } from '@objectstack/embedder-openai'; + +const embedder = createOpenAIEmbedder({ + preset: 'openai', + model: 'text-embedding-3-small', + // apiKey from OPENAI_API_KEY env if omitted +}); +``` + +または **Console → Configuration → AI → Embedder** から実行時に選択します。再起動なしでプロバイダーを切り替えても、既存のベクトルは検索可能なまま残ります(バックグラウンドで再インデックスできます)。 + +## ナレッジ / RAG + +ナレッジサービスは、ドキュメントの取り込み、チャンク分割、埋め込み(embedder サービス経由)、検索をオーケストレーションします。実際のストレージと検索のバックエンドはプラグイン可能です。 + +| アダプター | バックエンド | 適した用途 | +|---|---|---| +| `@objectstack/knowledge-memory` | インプロセス | 開発、デモ、小規模な KB | +| `@objectstack/knowledge-ragflow` | [RAGFlow](https://github.com/infiniflow/ragflow) | チャンク分割 + リランキングを備えた高品質な OSS RAG | + +```ts +import { KnowledgeServicePlugin } from '@objectstack/service-knowledge'; +import { KnowledgeRagflowPlugin } from '@objectstack/knowledge-ragflow'; + +kernel.use(new KnowledgeServicePlugin({ defaultTopK: 10 })); +kernel.use(new KnowledgeRagflowPlugin({ + endpoint: process.env.RAGFLOW_ENDPOINT, // e.g. http://localhost:9380 + apiKey: process.env.RAGFLOW_API_KEY, +})); +``` + +インデックス化されたナレッジベースは第一級のオブジェクトになります。フローからクエリしたり、Console に表示したり、検索コンテキストとして AI アシスタントに紐付けたりできます。 + +## MCP — Model Context Protocol + +ObjectOS は、オープンな [Model Context Protocol](https://modelcontextprotocol.io) を介して、AI エージェント(Claude Desktop、IDE、カスタムエージェント)に対してツールサーバーとして自身を公開できます。 + +```ts +import { MCPServerPlugin } from '@objectstack/plugin-mcp-server'; + +kernel.use(new MCPServerPlugin({ + transport: 'stdio', // or 'http' + autoStart: true, +})); +``` + +エージェントは MCP を通じて ObjectOS のツールを検出し呼び出します — 呼び出しユーザーの権限に従います。サーバーは AI サービスのツールレジストリをブリッジし、`list_objects`、`describe_object`、`query_records`、`get_record`、`aggregate_data` などの汎用ツールを含みます。 + +## 運用上の保証 + +- **クラウド依存を必須としない。** チャットに Ollama、埋め込みに Ollama embedder、ナレッジに memory を使えば、完全なエアギャップ運用が可能です。 +- **ライブで差し替え可能。** Console でプロバイダーを変更すると、次の呼び出しから新しいリクエストが新しいプロバイダーを使用します。再起動は不要です。 +- **テナントごとの設定。** 各 Environment は独自の AI 設定を持ちます。テナント A は OpenAI、テナント B は Anthropic — 同一ランタイムで実現できます。 +- **監査ログの記録。** すべての会話、ツール呼び出し、embedder リクエストを監査できます(`@objectstack/plugin-audit`)。 +- **コストを意識。** トークン数とプロバイダー ID は監査ログに流れ、チャージバックやコスト分析に利用できます。 + +## 次に読むべきもの + +- [AI Agents](/docs/build/agents) — 宣言的なエージェント、スキル、ツール +- [Flows & Automation](/docs/build/flows) — 宣言的なビジネスロジックから AI を呼び出す +- [Marketplace](/docs/build/marketplace) — デフォルトカタログに含まれる AI 搭載アプリ +- [Security & Compliance](/docs/reference/security) — AI のデータフローがどのように隔離されるか +- [`@objectstack/service-ai` source](https://github.com/objectstack-ai/framework/tree/main/packages/services/service-ai) +- [`@objectstack/embedder-openai` source](https://github.com/objectstack-ai/framework/tree/main/packages/plugins/embedder-openai) +- [`@objectstack/service-knowledge` source](https://github.com/objectstack-ai/framework/tree/main/packages/services/service-knowledge) diff --git a/content/docs/configure/ai.mdx b/content/docs/configure/ai.mdx index a0e346a..e3953a4 100644 --- a/content/docs/configure/ai.mdx +++ b/content/docs/configure/ai.mdx @@ -11,7 +11,7 @@ layers**: | Layer | Package | What it does | |---|---|---| | **Chat / generation** | `@objectstack/service-ai` | Conversations, tool calls, streaming | -| **Embeddings** | `@objectstack/service-embedder` + adapter | Text → vectors for semantic search and RAG | +| **Embeddings** | `@objectstack/embedder-openai` (OpenAI-compatible) | Text → vectors for semantic search and RAG | | **Knowledge / RAG** | `@objectstack/service-knowledge` + adapter | Documents → indexed knowledge bases | All three are optional, all three are provider-agnostic, and all three @@ -30,25 +30,28 @@ pnpm add @ai-sdk/google # Gemini pnpm add @ai-sdk/gateway # AI gateway / OpenRouter / proxies ``` -Then register the service with one or more models: +Then register the AI service plugin with a Vercel-SDK adapter: ```ts -import { ServiceAI } from '@objectstack/service-ai'; -import { openai } from '@ai-sdk/openai'; -import { anthropic } from '@ai-sdk/anthropic'; - -ServiceAI.configure({ - defaultModel: 'fast', - models: { - fast: openai('gpt-4o-mini'), - smart: openai('gpt-4o'), - claude: anthropic('claude-3-5-sonnet-latest'), - }, - enableStreaming: true, - maxHistoryLength: 50, -}); +import { AIServicePlugin, VercelLLMAdapter } from '@objectstack/service-ai'; +import { openai } from '@ai-sdk/openai'; + +kernel.use(new AIServicePlugin({ + adapter: new VercelLLMAdapter({ model: openai('gpt-4o') }), + models: [ + { id: 'fast', provider: 'openai', model: 'gpt-4o-mini' }, + { id: 'smart', provider: 'openai', model: 'gpt-4o' }, + ], + defaultModelId: 'fast', +})); ``` +The `models` list feeds the runtime model registry — it drives +default-model resolution and cost attribution in traces. By default the +plugin also binds to the `ai` settings namespace and rebuilds the +adapter live when an operator edits the provider/credentials/model in +Console, so no restart is needed. + Provider API keys come from each SDK's normal env vars: | Provider | Env var | @@ -67,68 +70,61 @@ no restart. ```ts const ai = kernel.getService('ai'); -const convo = await ai.createConversation({ - model: 'smart', - systemPrompt: 'You are a helpful assistant.', -}); - -const reply = await ai.sendMessage({ - conversationId: convo.id, - message: 'Summarize ObjectStack in two sentences.', -}); +// One-shot chat +const result = await ai.chat( + [{ role: 'user', content: 'Summarize ObjectStack in two sentences.' }], + { model: 'smart' }, +); + +// Structured output +const { object } = await ai.generateObject( + [{ role: 'user', content: 'Classify this ticket: ...' }], + { schema, model: 'fast' }, +); ``` -### Using it from a flow +The service also exposes `complete()`, `streamChat()`, `embed()`, and +`listModels()`. Conversations are persisted as `ai_conversations` / +`ai_messages` records and managed over the REST API +(`POST /api/v1/ai/chat`, `POST /api/v1/ai/conversations`). -The `automation` capability exposes an `ai_call` step type: +### Using it from agents and flows -```ts -{ - type: 'action', - action: 'ai_call', - inputs: { - model: 'fast', - prompt: 'Categorize this ticket: {!trigger.record.subject}', - schema: { category: 'string', priority: 'string' }, - }, - output: 'classified', -} -``` - -See [Flows & Automation](/docs/build/flows) for the surrounding -context. +For declarative AI — agents, skills, and tools — see +[AI Agents](/docs/build/agents). Flows can invoke any registered action +(including actions that wrap an `ai.chat()` / `ai.generateObject()` +call) as an `action` node; see [Flows & Automation](/docs/build/flows) +for the surrounding context. ## Embedders -The embedder service converts text to dense vectors. ObjectStack -ships adapters for many providers — chosen because the embedding -landscape moves fast and your "best" choice depends on cost, latency, -and language. +The embedder converts text to dense vectors. A single OpenAI-compatible +adapter, `@objectstack/embedder-openai`, covers OpenAI plus any provider +that exposes an OpenAI-compatible `/v1/embeddings` endpoint — pick one +with a **preset** (which sets the base URL for you) or point `baseUrl` +at a custom endpoint. -| Provider | Adapter | Notes | +| Provider | `preset` | Notes | |---|---|---| -| OpenAI | `@objectstack/embedder-openai` | `text-embedding-3-small`/`-large` | -| Azure OpenAI | `@objectstack/embedder-openai` (Azure config) | Enterprise, regional | -| 阿里通义 DashScope | `@objectstack/embedder-dashscope` | `text-embedding-v3` | -| 智谱 GLM | `@objectstack/embedder-zhipu` | `embedding-2` | -| 硅基流动 SiliconFlow | `@objectstack/embedder-siliconflow` | Aggregator of OSS models | -| 火山 Doubao | `@objectstack/embedder-doubao` | ByteDance | -| MiniMax | `@objectstack/embedder-minimax` | — | -| Ollama (self-hosted) | `@objectstack/embedder-ollama` | Air-gapped friendly | -| Custom | `@objectstack/embedder-custom` | Bring your own HTTP endpoint | -| None | _builtin_ | Disable embeddings entirely | +| OpenAI | `openai` | `text-embedding-3-small`/`-large` | +| Azure OpenAI | `azure` | Provide full deployment URL via `baseUrl` | +| 阿里通义 DashScope | `dashscope` | `text-embedding-v3` | +| 智谱 GLM | `zhipu` | `embedding-2` | +| 硅基流动 SiliconFlow | `siliconflow` | Aggregator of OSS models | +| 火山 Doubao | `doubao` | ByteDance | +| MiniMax | `minimax` | — | +| Ollama (self-hosted) | `ollama` | Air-gapped friendly (`http://localhost:11434/v1`) | +| Custom | _(omit; set `baseUrl`)_ | Bring your own OpenAI-compatible endpoint | Configure in code: ```ts -import { ServiceEmbedder } from '@objectstack/service-embedder'; -import { OpenAIEmbedderPlugin } from '@objectstack/embedder-openai'; +import { createOpenAIEmbedder } from '@objectstack/embedder-openai'; -ServiceEmbedder.configure({ defaultModel: 'small' }); -// then register the adapter plugin: -new OpenAIEmbedderPlugin({ +const embedder = createOpenAIEmbedder({ + preset: 'openai', model: 'text-embedding-3-small', - // OPENAI_API_KEY from env + // apiKey from OPENAI_API_KEY env if omitted }); ``` @@ -145,18 +141,17 @@ storage and search backend is pluggable: | Adapter | Backend | Good for | |---|---|---| | `@objectstack/knowledge-memory` | In-process | Dev, demos, small KBs | -| `@objectstack/knowledge-turso` | Turso/libSQL + sqlite-vss | Single-region production, embedded vectors | | `@objectstack/knowledge-ragflow` | [RAGFlow](https://github.com/infiniflow/ragflow) | High-quality OSS RAG with chunking + reranking | ```ts -import { ServiceKnowledge } from '@objectstack/service-knowledge'; -import { TursoKnowledgePlugin } from '@objectstack/knowledge-turso'; - -ServiceKnowledge.configure(); -new TursoKnowledgePlugin({ - databaseUrl: process.env.TURSO_DATABASE_URL, - authToken: process.env.TURSO_AUTH_TOKEN, -}); +import { KnowledgeServicePlugin } from '@objectstack/service-knowledge'; +import { KnowledgeRagflowPlugin } from '@objectstack/knowledge-ragflow'; + +kernel.use(new KnowledgeServicePlugin({ defaultTopK: 10 })); +kernel.use(new KnowledgeRagflowPlugin({ + endpoint: process.env.RAGFLOW_ENDPOINT, // e.g. http://localhost:9380 + apiKey: process.env.RAGFLOW_API_KEY, +})); ``` Indexed knowledge bases become first-class objects — query them from @@ -170,18 +165,18 @@ Desktop, IDEs, custom agents) via the open [Model Context Protocol](https://modelcontextprotocol.io). ```ts -import { McpServerPlugin } from '@objectstack/plugin-mcp-server'; +import { MCPServerPlugin } from '@objectstack/plugin-mcp-server'; -new McpServerPlugin({ - // expose specific objects + actions as MCP tools - expose: ['todo_task', 'support_ticket'], -}); +kernel.use(new MCPServerPlugin({ + transport: 'stdio', // or 'http' + autoStart: true, +})); ``` -Agents discover and invoke ObjectOS actions through MCP — subject to -the calling user's permission set. The MCP server also exposes a -small set of universal tools: `search_records`, `get_record`, -`create_record`, `invoke_action`. +Agents discover and invoke ObjectOS tools through MCP — subject to the +calling user's permissions. The server bridges the AI service's tool +registry, including universal tools such as `list_objects`, +`describe_object`, `query_records`, `get_record`, and `aggregate_data`. ## Operational guarantees @@ -198,9 +193,10 @@ small set of universal tools: `search_records`, `get_record`, ## Where to go next +- [AI Agents](/docs/build/agents) — declarative agents, skills, and tools - [Flows & Automation](/docs/build/flows) — call AI from declarative business logic - [Marketplace](/docs/build/marketplace) — AI-powered apps in the default catalog - [Security & Compliance](/docs/reference/security) — how AI data flows are isolated - [`@objectstack/service-ai` source](https://github.com/objectstack-ai/framework/tree/main/packages/services/service-ai) -- [`@objectstack/service-embedder` source](https://github.com/objectstack-ai/framework/tree/main/packages/services/service-embedder) +- [`@objectstack/embedder-openai` source](https://github.com/objectstack-ai/framework/tree/main/packages/plugins/embedder-openai) - [`@objectstack/service-knowledge` source](https://github.com/objectstack-ai/framework/tree/main/packages/services/service-knowledge) diff --git a/content/docs/configure/ai.cn.mdx b/content/docs/configure/ai.zh-Hans.mdx similarity index 100% rename from content/docs/configure/ai.cn.mdx rename to content/docs/configure/ai.zh-Hans.mdx diff --git a/content/docs/configure/api-access.cn.mdx b/content/docs/configure/api-access.cn.mdx deleted file mode 100644 index 693fb89..0000000 --- a/content/docs/configure/api-access.cn.mdx +++ /dev/null @@ -1,85 +0,0 @@ ---- -title: API 访问 -description: 自动生成的 REST API、认证以及用于集成的 API Key。 ---- - -# API 访问 - -每个在 artifact 中声明的对象都会通过自动生成的 REST API 暴露。同一套端点同时驱动 UI、集成和客户的 ETL 脚本——无需另外维护一套"集成 API"。 - -## Base URL - -```text -https:///api/v1 -``` - -主要入口: - -| 路径 | 用途 | -|---|---| -| `/api/v1/data/` | 每个对象自动生成的 CRUD(例如 `/api/v1/data/account`) | -| `/api/v1/data//{id}` | 读取/更新/删除单条记录 | -| `/api/v1/data//actions/` | 调用声明式 Action | -| `/api/v1/auth/*` | 认证(登录、会话、OAuth、OIDC) | -| `/api/v1/meta/*` | 元数据 API(对象、字段、视图),需开启 | -| `/health` | 存活/就绪探针(无需认证) | - -`apiPrefix` 默认为 `/api/v1`,可以在 ObjectOS stack 上配置。 - -## 认证方式 - -调用方有三种认证方式: - -| 方式 | 适用场景 | 做法 | -|---|---|---| -| Session cookie | 浏览器/UI 流量 | 通过 `/api/v1/auth/*` 登录;Cookie 限定到项目主机名 | -| Bearer access token | 移动端、SPA、短时服务端任务 | 通过 `/api/v1/auth/sign-in/email` 换取,并以 `Authorization: Bearer ` 传递 | -| API Key | 服务器到服务器、ETL、长期集成 | 创建 `sys_api_key` 记录,作为 bearer token 使用 | - -三种方式都经过同一个 `AuthPlugin`,最终都解析为 `sys_user` 上下文,由 `SecurityPlugin` 用以评估权限和记录访问。 - -## API Key - -API Key 是一等的 `sys_api_key` 记录。Key 值本身以哈希存储——只有 `prefix` 和元数据保持可查询,因此泄漏的 Key 无法通过数据库还原。 - -签发一个 Key: - -1. 以管理员身份登录 **Console → API Keys**。 -2. 选择所属用户(API 调用继承该用户的权限和记录访问)。 -3. 可选地设置过期时间。 -4. **仅这一次**复制显示的密钥 —— 之后不会再显示。 - -把 Key 作为 bearer token 使用: - -```bash -curl https://app.example.com/api/v1/data/account \ - -H "Authorization: Bearer os_pk_live_…" -``` - -要撤销一个 Key,在对应的 `sys_api_key` 记录上执行 `revoke_api_key` Action(Console UI 中也有)。撤销在下一次请求时立即生效。 - -## 分页、过滤与排序 - -自动生成的列表端点接受标准的 ObjectStack 查询参数: - -| 参数 | 含义 | -|---|---| -| `?limit=` | 页大小(受对象 `maxPageSize` 限制) | -| `?offset=` 或 `?cursor=` | 分页 | -| `?filter=` | 使用 ObjectQL 过滤语法的服务端过滤 | -| `?sort=` | 排序表达式(例如 `-created_at`) | -| `?fields=` | 稀疏字段选择 | - -完整的过滤语法以框架文档为准——运行时语法是 source of truth。 - -## 限流 - -使用框架的 `RateLimiter` 原语(或 ingress / API 网关)应用按 IP 和按身份的限制。推荐的初始配额参见 [Production readiness](/docs/operate/production)。 - -## CORS - -如果调用方在不同源的浏览器上运行,请在 ingress 或运行时中间件中配置 CORS。**不要**把通配符 origin 和带凭据的请求结合使用。 - -## OpenAPI / 发现 - -当镜像中包含相应能力时,运行时可以为生成的 REST API 提供 OpenAPI 文档。客户的集成应基于每个部署的 OpenAPI 文档生成客户端,而不是手写 URL,因为对象名称和生成路由会跟随已部署的 artifact 而变化。 diff --git a/content/docs/configure/api-access.de.mdx b/content/docs/configure/api-access.de.mdx new file mode 100644 index 0000000..e98ca8d --- /dev/null +++ b/content/docs/configure/api-access.de.mdx @@ -0,0 +1,110 @@ +--- +title: API-Zugriff +description: Generierte REST-APIs, Authentifizierung und API-Schlüssel für Integrationen. +--- + +# API-Zugriff + +Jedes im Artefakt deklarierte Objekt wird über eine generierte +REST-API bereitgestellt. Dieselben Endpunkte versorgen die UI, Integrationen +und Kunden-ETL-Skripte — es gibt keine separate „Integrations-API", die +gepflegt werden müsste. + +## Basis-URL + +```text +https:///api/v1 +``` + +Wichtige Schnittstellen: + +| Pfad | Zweck | +|---|---| +| `/api/v1/data/` | Generiertes CRUD für jedes Objekt (z. B. `/api/v1/data/account`) | +| `/api/v1/data//{id}` | Einzelnen Datensatz lesen/aktualisieren/löschen | +| `/api/v1/actions//` | Eine deklarative Aktion aufrufen (POST) | +| `/api/v1/auth/*` | Authentifizierung (Anmeldung, Sitzungen, OAuth, OIDC) | +| `/api/v1/meta/*` | Metadaten-APIs (Objekte, Felder, Ansichten), sofern aktiviert | +| `/api/v1/health` | Liveness-/Readiness-Probe (keine Authentifizierung) | + +Das Präfix lautet standardmäßig `/api/v1` (der API-`basePath` von `/api` plus +die `version` `v1`) und ist im ObjectOS-Stack konfigurierbar. + +## Authentifizierungsoptionen + +Aufrufer können sich auf drei Arten authentifizieren: + +| Methode | Am besten geeignet für | Wie | +|---|---|---| +| Sitzungs-Cookie | Browser-/UI-Verkehr | Anmeldung über `/api/v1/auth/*`; Cookies sind auf den Projekt-Hostnamen beschränkt | +| Bearer-Zugriffstoken | Mobile, SPA, kurzlebige Server-Jobs | Anmeldedaten unter `/api/v1/auth/sign-in/email` austauschen und `Authorization: Bearer ` übergeben | +| API-Schlüssel | Server-zu-Server, ETL, langlebige Integrationen | Einen `sys_api_key` erstellen und als Bearer-Token übergeben | + +Alle drei durchlaufen dasselbe `AuthPlugin` und werden zu einem +`sys_user`-Kontext aufgelöst, den das `SecurityPlugin` anhand von +Berechtigungen und Datensatzzugriff auswertet. + +## API-Schlüssel + +API-Schlüssel sind erstklassige `sys_api_key`-Datensätze. Der Schlüsselwert +selbst wird gehasht gespeichert — nur das `prefix` und Metadaten bleiben +abfragbar, sodass ein durchgesickerter Schlüssel nicht aus der Datenbank +rekonstruiert werden kann. + +So stellen Sie einen Schlüssel aus: + +1. Melden Sie sich als Administrator bei **Console → API Keys** an. +2. Wählen Sie den besitzenden Benutzer (der API-Aufruf erbt die + Berechtigungen und den Datensatzzugriff dieses Benutzers). +3. Legen Sie optional ein Ablaufdatum fest. +4. Kopieren Sie das angezeigte Geheimnis **einmalig** — es wird nicht erneut + angezeigt. + +Verwenden Sie den Schlüssel als Bearer-Token: + +```bash +curl https://app.example.com/api/v1/data/account \ + -H "Authorization: Bearer os_pk_live_…" +``` + +Um einen Schlüssel zu widerrufen, führen Sie die Aktion `revoke_api_key` für +den entsprechenden `sys_api_key`-Datensatz aus (auch in der Console-UI +verfügbar). Der Widerruf wird ab der nächsten Anfrage sofort wirksam. + +## Paginierung, Filterung und Sortierung + +Generierte Listen-Endpunkte akzeptieren die standardmäßigen +ObjectStack-Abfrageparameter: + +| Parameter | Bedeutung | +|---|---| +| `?limit=` | Seitengröße (unterliegt einer serverseitigen Obergrenze) | +| `?offset=` oder `?cursor=` | Paginierung | +| `?filter=` | Serverseitige Filterung mit der ObjectQL-Filtersyntax | +| `?sort=` | Sortierausdruck (z. B. `-created_at`) | +| `?fields=` | Sparse-Feldauswahl | + +Die vollständige Filtergrammatik finden Sie in der Framework-Dokumentation — +die Laufzeitgrammatik ist die maßgebliche Quelle. + +## Ratenbegrenzung + +Verwenden Sie das `RateLimiter`-Primitiv des Frameworks (oder Ihr Ingress / +API-Gateway), um Limits pro IP und pro Identität anzuwenden. Empfohlene +Ausgangswerte sind unter [Production readiness](/docs/operate/production) +dokumentiert. + +## CORS + +Wenn Aufrufer in einem Browser mit einem anderen Origin ausgeführt werden, +konfigurieren Sie CORS am Ingress oder über die Middleware der Laufzeit. +Kombinieren Sie Wildcard-Origins **nicht** mit Anfragen, die Anmeldedaten +enthalten. + +## OpenAPI / Discovery + +Die Laufzeit kann ein OpenAPI-Dokument für die generierte REST-API +bereitstellen, wenn die entsprechende Funktion im Image enthalten ist. +Kundenintegrationen sollten Clients aus dem OpenAPI-Dokument pro Deployment +generieren, anstatt URLs von Hand zu erstellen, da Objektnamen und generierte +Routen dem bereitgestellten Artefakt folgen. diff --git a/content/docs/configure/api-access.es.mdx b/content/docs/configure/api-access.es.mdx new file mode 100644 index 0000000..705d55d --- /dev/null +++ b/content/docs/configure/api-access.es.mdx @@ -0,0 +1,108 @@ +--- +title: Acceso a la API +description: APIs REST generadas, autenticación y claves de API para integraciones. +--- + +# Acceso a la API + +Cada objeto declarado en el artefacto se expone a través de una API +REST generada. Los mismos endpoints alimentan la UI, las integraciones y +los scripts ETL de los clientes — no hay una "API de integración" separada +que mantener. + +## URL base + +```text +https:///api/v1 +``` + +Superficies destacadas: + +| Ruta | Propósito | +|---|---| +| `/api/v1/data/` | CRUD generado para cada objeto (p. ej. `/api/v1/data/account`) | +| `/api/v1/data//{id}` | Leer/actualizar/eliminar un registro individual | +| `/api/v1/actions//` | Invocar una acción declarativa (POST) | +| `/api/v1/auth/*` | Autenticación (inicio de sesión, sesiones, OAuth, OIDC) | +| `/api/v1/meta/*` | APIs de metadatos (objetos, campos, vistas) cuando está habilitado | +| `/api/v1/health` | Sonda de liveness/readiness (sin autenticación) | + +El prefijo es `/api/v1` de forma predeterminada (el `basePath` de la API, +`/api`, más la `version`, `v1`) y es configurable en el stack de ObjectOS. + +## Opciones de autenticación + +Los clientes pueden autenticarse de tres maneras: + +| Método | Ideal para | Cómo | +|---|---|---| +| Cookie de sesión | Tráfico de navegador/UI | Inicia sesión a través de `/api/v1/auth/*`; las cookies se limitan al nombre de host del proyecto | +| Token de acceso Bearer | Móvil, SPA, trabajos de servidor de corta duración | Intercambia credenciales en `/api/v1/auth/sign-in/email` y pasa `Authorization: Bearer ` | +| Clave de API | Servidor a servidor, ETL, integraciones de larga duración | Crea un `sys_api_key` y pásalo como token bearer | + +Las tres pasan por el mismo `AuthPlugin` y se resuelven en un contexto +`sys_user` que el `SecurityPlugin` evalúa frente a los permisos y el +acceso a registros. + +## Claves de API + +Las claves de API son registros `sys_api_key` de primera clase. El valor +de la clave en sí se almacena cifrado (hash) — solo el `prefix` y los +metadatos permanecen consultables, de modo que una clave filtrada no puede +reconstruirse a partir de la base de datos. + +Para emitir una clave: + +1. Inicia sesión en **Console → API Keys** como administrador. +2. Elige el usuario propietario (la llamada a la API hereda los permisos + y el acceso a registros de ese usuario). +3. Opcionalmente, establece una fecha de expiración. +4. Copia el secreto mostrado **una sola vez** — no se vuelve a mostrar. + +Usa la clave como token bearer: + +```bash +curl https://app.example.com/api/v1/data/account \ + -H "Authorization: Bearer os_pk_live_…" +``` + +Para revocar una clave, ejecuta la acción `revoke_api_key` en el registro +`sys_api_key` correspondiente (también disponible en la UI de Console). La +revocación surte efecto de inmediato en la siguiente solicitud. + +## Paginación, filtrado y ordenación + +Los endpoints de listado generados aceptan los parámetros de consulta +estándar de ObjectStack: + +| Parámetro | Significado | +|---|---| +| `?limit=` | Tamaño de página (sujeto a un límite máximo en el servidor) | +| `?offset=` o `?cursor=` | Paginación | +| `?filter=` | Filtrado en el servidor usando la sintaxis de filtros de ObjectQL | +| `?sort=` | Expresión de ordenación (p. ej. `-created_at`) | +| `?fields=` | Selección dispersa de campos | + +Consulta la documentación del framework para conocer la gramática completa +de filtros — la gramática del runtime es la fuente de verdad. + +## Limitación de tasa + +Usa la primitiva `RateLimiter` del framework (o tu ingress / gateway de +API) para aplicar límites por IP y por identidad. Los buckets iniciales +recomendados están documentados en [Production readiness](/docs/operate/production). + +## CORS + +Si los clientes se ejecutan en un navegador desde un origen diferente, +configura CORS en el ingress o mediante el middleware del runtime. **No** +combines orígenes con comodín con solicitudes que incluyan credenciales. + +## OpenAPI / descubrimiento + +El runtime puede servir un documento OpenAPI para la API REST generada +cuando la capacidad correspondiente está incluida en la imagen. Las +integraciones de los clientes deberían generar clientes a partir del +documento OpenAPI por despliegue en lugar de construir URLs a mano, +porque los nombres de los objetos y las rutas generadas siguen el +artefacto desplegado. diff --git a/content/docs/configure/api-access.fr.mdx b/content/docs/configure/api-access.fr.mdx new file mode 100644 index 0000000..3bc10c1 --- /dev/null +++ b/content/docs/configure/api-access.fr.mdx @@ -0,0 +1,110 @@ +--- +title: Accès API +description: API REST générées, authentification et clés API pour les intégrations. +--- + +# Accès API + +Chaque objet déclaré dans l'artefact est exposé via une API REST générée. +Les mêmes points de terminaison alimentent l'interface utilisateur, les +intégrations et les scripts ETL des clients — il n'y a aucune « API +d'intégration » distincte à maintenir. + +## URL de base + +```text +https:///api/v1 +``` + +Surfaces notables : + +| Chemin | Objectif | +|---|---| +| `/api/v1/data/` | CRUD généré pour chaque objet (par ex. `/api/v1/data/account`) | +| `/api/v1/data//{id}` | Lire/mettre à jour/supprimer un enregistrement unique | +| `/api/v1/actions//` | Invoquer une action déclarative (POST) | +| `/api/v1/auth/*` | Authentification (connexion, sessions, OAuth, OIDC) | +| `/api/v1/meta/*` | API de métadonnées (objets, champs, vues) lorsqu'elles sont activées | +| `/api/v1/health` | Sonde de vivacité/disponibilité (sans authentification) | + +Le préfixe est `/api/v1` par défaut (le `basePath` de l'API `/api` plus la +`version` `v1`) et il est configurable sur la stack ObjectOS. + +## Options d'authentification + +Les appelants peuvent s'authentifier de trois façons : + +| Méthode | Idéale pour | Comment | +|---|---|---| +| Cookie de session | Trafic navigateur/UI | Connectez-vous via `/api/v1/auth/*` ; les cookies sont limités au nom d'hôte du projet | +| Jeton d'accès Bearer | Mobile, SPA, tâches serveur à courte durée de vie | Échangez les identifiants à `/api/v1/auth/sign-in/email` et passez `Authorization: Bearer ` | +| Clé API | Serveur à serveur, ETL, intégrations à longue durée de vie | Créez une `sys_api_key` et passez-la comme jeton bearer | + +Les trois passent par le même `AuthPlugin` et se résolvent en un contexte +`sys_user` que le `SecurityPlugin` évalue par rapport aux permissions et à +l'accès aux enregistrements. + +## Clés API + +Les clés API sont des enregistrements `sys_api_key` de première classe. La +valeur de la clé elle-même est stockée hachée — seuls le `prefix` et les +métadonnées restent interrogeables, de sorte qu'une clé divulguée ne peut +pas être reconstituée à partir de la base de données. + +Pour émettre une clé : + +1. Connectez-vous à **Console → API Keys** en tant qu'administrateur. +2. Choisissez l'utilisateur propriétaire (l'appel API hérite des + permissions et de l'accès aux enregistrements de cet utilisateur). +3. Définissez éventuellement une date d'expiration. +4. Copiez le secret affiché **une seule fois** — il n'est plus affiché par + la suite. + +Utilisez la clé comme jeton bearer : + +```bash +curl https://app.example.com/api/v1/data/account \ + -H "Authorization: Bearer os_pk_live_…" +``` + +Pour révoquer une clé, exécutez l'action `revoke_api_key` sur +l'enregistrement `sys_api_key` correspondant (également disponible dans +l'interface de la Console). La révocation prend effet immédiatement lors de +la requête suivante. + +## Pagination, filtrage et tri + +Les points de terminaison de liste générés acceptent les paramètres de +requête ObjectStack standard : + +| Paramètre | Signification | +|---|---| +| `?limit=` | Taille de page (soumise à un plafond côté serveur) | +| `?offset=` ou `?cursor=` | Pagination | +| `?filter=` | Filtrage côté serveur utilisant la syntaxe de filtre ObjectQL | +| `?sort=` | Expression de tri (par ex. `-created_at`) | +| `?fields=` | Sélection partielle de champs | + +Reportez-vous à la documentation du framework pour la grammaire de filtre +complète — la grammaire d'exécution fait foi. + +## Limitation de débit + +Utilisez la primitive `RateLimiter` du framework (ou votre ingress / API +gateway) pour appliquer des limites par IP et par identité. Les compartiments +de départ recommandés sont documentés dans [Préparation à la production](/docs/operate/production). + +## CORS + +Si les appelants s'exécutent dans un navigateur sur une origine différente, +configurez CORS au niveau de l'ingress ou via le middleware du runtime. Ne +combinez **pas** les origines génériques avec des requêtes avec +identifiants. + +## OpenAPI / découverte + +Le runtime peut servir un document OpenAPI pour l'API REST générée lorsque +la capacité correspondante est incluse dans l'image. Les intégrations +clients devraient générer leurs clients à partir du document OpenAPI propre +à chaque déploiement plutôt que de construire les URL à la main, car les +noms d'objets et les routes générées suivent l'artefact déployé. diff --git a/content/docs/configure/api-access.ja.mdx b/content/docs/configure/api-access.ja.mdx new file mode 100644 index 0000000..e427d0b --- /dev/null +++ b/content/docs/configure/api-access.ja.mdx @@ -0,0 +1,105 @@ +--- +title: API アクセス +description: 統合のために生成される REST API、認証、API キーについて。 +--- + +# API アクセス + +アーティファクトで宣言されたすべてのオブジェクトは、生成された REST API +を通じて公開されます。同じエンドポイントが UI、統合、顧客の ETL +スクリプトを支えており、別途維持すべき「統合用 API」は存在しません。 + +## ベース URL + +```text +https:///api/v1 +``` + +主なエンドポイント: + +| Path | 用途 | +|---|---| +| `/api/v1/data/` | 各オブジェクトに対して生成される CRUD(例: `/api/v1/data/account`) | +| `/api/v1/data//{id}` | 単一レコードの読み取り/更新/削除 | +| `/api/v1/actions//` | 宣言的アクションの呼び出し(POST) | +| `/api/v1/auth/*` | 認証(サインイン、セッション、OAuth、OIDC) | +| `/api/v1/meta/*` | 有効化されている場合のメタデータ API(オブジェクト、フィールド、ビュー) | +| `/api/v1/health` | 死活/準備状態のプローブ(認証不要) | + +プレフィックスのデフォルトは `/api/v1`(API の `basePath` である `/api` と +`version` である `v1` の組み合わせ)で、ObjectOS スタック上で構成可能です。 + +## 認証オプション + +呼び出し元は次の 3 つの方法で認証できます: + +| 方法 | 適した用途 | やり方 | +|---|---|---| +| セッション Cookie | ブラウザ/UI のトラフィック | `/api/v1/auth/*` を通じてサインインします。Cookie はプロジェクトのホスト名にスコープされます | +| Bearer アクセストークン | モバイル、SPA、短命のサーバージョブ | `/api/v1/auth/sign-in/email` で資格情報を交換し、`Authorization: Bearer ` を渡します | +| API キー | サーバー間連携、ETL、長期間の統合 | `sys_api_key` を作成し、bearer トークンとして渡します | + +3 つの方法はいずれも同じ `AuthPlugin` を通過し、`SecurityPlugin` が権限と +レコードアクセスに対して評価する `sys_user` コンテキストに解決されます。 + +## API キー + +API キーはファーストクラスの `sys_api_key` レコードです。キーの値自体は +ハッシュ化して保存され、クエリ可能なのは `prefix` とメタデータのみです。 +そのため、漏洩したキーをデータベースから復元することはできません。 + +キーを発行するには: + +1. 管理者として **Console → API Keys** にサインインします。 +2. 所有ユーザーを選択します(API 呼び出しはそのユーザーの権限と + レコードアクセスを継承します)。 +3. 必要に応じて有効期限を設定します。 +4. 表示されたシークレットを**一度だけ**コピーします。再表示はされません。 + +キーは bearer トークンとして使用します: + +```bash +curl https://app.example.com/api/v1/data/account \ + -H "Authorization: Bearer os_pk_live_…" +``` + +キーを失効させるには、対応する `sys_api_key` レコードに対して +`revoke_api_key` アクションを実行します(Console UI でも利用可能)。 +失効は次のリクエストから即座に有効になります。 + +## ページネーション、フィルタリング、ソート + +生成されるリストエンドポイントは、標準の ObjectStack +クエリパラメーターを受け付けます: + +| パラメーター | 意味 | +|---|---| +| `?limit=` | ページサイズ(サーバー側の上限が適用されます) | +| `?offset=` または `?cursor=` | ページネーション | +| `?filter=` | ObjectQL のフィルター構文を使用したサーバー側フィルタリング | +| `?sort=` | ソート式(例: `-created_at`) | +| `?fields=` | スパースなフィールド選択 | + +完全なフィルター文法についてはフレームワークのドキュメントを参照してください。 +ランタイムの文法が信頼できる情報源です。 + +## レート制限 + +フレームワークの `RateLimiter` プリミティブ(または ingress / API +ゲートウェイ)を使用して、IP ごと・アイデンティティごとの制限を適用します。 +推奨される初期バケットは [本番環境への準備](/docs/operate/production) +に記載されています。 + +## CORS + +呼び出し元が異なるオリジンのブラウザで動作する場合は、ingress または +ランタイムのミドルウェアで CORS を構成します。ワイルドカードオリジンと +資格情報付きリクエストを**組み合わせないでください**。 + +## OpenAPI / ディスカバリー + +該当する機能がイメージに含まれている場合、ランタイムは生成された REST API +の OpenAPI ドキュメントを提供できます。オブジェクト名や生成されたルートは +デプロイされたアーティファクトに従うため、顧客の統合では URL を手作業で +組み立てるのではなく、デプロイごとの OpenAPI ドキュメントからクライアントを +生成してください。 diff --git a/content/docs/configure/api-access.mdx b/content/docs/configure/api-access.mdx index 787e96e..c98688a 100644 --- a/content/docs/configure/api-access.mdx +++ b/content/docs/configure/api-access.mdx @@ -21,13 +21,13 @@ Notable surfaces: |---|---| | `/api/v1/data/` | Generated CRUD for each object (e.g. `/api/v1/data/account`) | | `/api/v1/data//{id}` | Read/update/delete a single record | -| `/api/v1/data//actions/` | Invoke a declarative action | +| `/api/v1/actions//` | Invoke a declarative action (POST) | | `/api/v1/auth/*` | Authentication (sign-in, sessions, OAuth, OIDC) | | `/api/v1/meta/*` | Metadata APIs (objects, fields, views) when enabled | -| `/health` | Liveness/readiness probe (no auth) | +| `/api/v1/health` | Liveness/readiness probe (no auth) | -The `apiPrefix` defaults to `/api/v1` and is configurable on the -ObjectOS stack. +The prefix defaults to `/api/v1` (the API `basePath` of `/api` plus the +`version` of `v1`) and is configurable on the ObjectOS stack. ## Authentication options @@ -75,7 +75,7 @@ parameters: | Parameter | Meaning | |---|---| -| `?limit=` | Page size (capped by the object's `maxPageSize`) | +| `?limit=` | Page size (subject to a server-side ceiling) | | `?offset=` or `?cursor=` | Pagination | | `?filter=` | Server-side filtering using the ObjectQL filter syntax | | `?sort=` | Sort expression (e.g. `-created_at`) | diff --git a/content/docs/configure/api-access.zh-Hans.mdx b/content/docs/configure/api-access.zh-Hans.mdx new file mode 100644 index 0000000..ffc53d2 --- /dev/null +++ b/content/docs/configure/api-access.zh-Hans.mdx @@ -0,0 +1,85 @@ +--- +title: API 访问 +description: 用于集成的自动生成 REST API、身份验证和 API 密钥。 +--- + +# API 访问 + +artifact 中声明的每个对象都会通过自动生成的 REST API 对外暴露。同一套端点同时驱动 UI、集成和客户的 ETL 脚本——无需另外维护一套“集成 API”。 + +## Base URL + +```text +https:///api/v1 +``` + +主要入口: + +| Path | 用途 | +|---|---| +| `/api/v1/data/` | 每个对象自动生成的 CRUD(例如 `/api/v1/data/account`) | +| `/api/v1/data//{id}` | 读取/更新/删除单条记录 | +| `/api/v1/actions//` | 调用声明式 action(POST) | +| `/api/v1/auth/*` | 身份验证(登录、会话、OAuth、OIDC) | +| `/api/v1/meta/*` | 元数据 API(对象、字段、视图),在启用时可用 | +| `/api/v1/health` | 存活/就绪探针(无需身份验证) | + +前缀默认为 `/api/v1`(即 API 的 `basePath` `/api` 加上 `version` `v1`),并且可在 ObjectOS stack 上配置。 + +## 身份验证方式 + +调用方可以通过三种方式进行身份验证: + +| 方式 | 适用场景 | 做法 | +|---|---|---| +| Session cookie | 浏览器/UI 流量 | 通过 `/api/v1/auth/*` 登录;cookie 的作用域限定在项目主机名 | +| Bearer 访问令牌 | 移动端、SPA、短时服务端任务 | 在 `/api/v1/auth/sign-in/email` 用凭据换取令牌,并以 `Authorization: Bearer ` 传递 | +| API 密钥 | 服务器到服务器、ETL、长期存续的集成 | 创建一条 `sys_api_key` 记录,作为 bearer 令牌使用 | + +这三种方式都会经过同一个 `AuthPlugin`,并最终解析为 `sys_user` 上下文,由 `SecurityPlugin` 据此评估权限和记录访问。 + +## API 密钥 + +API 密钥是一等公民 `sys_api_key` 记录。密钥值本身以哈希形式存储——只有 `prefix` 和元数据保持可查询,因此即便密钥泄露也无法从数据库中还原。 + +签发一个密钥: + +1. 以管理员身份登录 **Console → API Keys**。 +2. 选择所属用户(API 调用会继承该用户的权限和记录访问)。 +3. 可选地设置过期日期。 +4. **仅这一次**复制显示出的密钥——之后不会再显示。 + +将密钥作为 bearer 令牌使用: + +```bash +curl https://app.example.com/api/v1/data/account \ + -H "Authorization: Bearer os_pk_live_…" +``` + +要撤销某个密钥,请在对应的 `sys_api_key` 记录上运行 `revoke_api_key` action(Console UI 中也提供)。撤销会在下一次请求时立即生效。 + +## 分页、过滤与排序 + +自动生成的列表端点接受标准的 ObjectStack 查询参数: + +| 参数 | 含义 | +|---|---| +| `?limit=` | 页大小(受服务端上限约束) | +| `?offset=` 或 `?cursor=` | 分页 | +| `?filter=` | 使用 ObjectQL 过滤语法进行服务端过滤 | +| `?sort=` | 排序表达式(例如 `-created_at`) | +| `?fields=` | 稀疏字段选择 | + +完整的过滤语法请参阅框架文档——运行时语法才是权威依据。 + +## 限流 + +使用框架的 `RateLimiter` 原语(或 ingress / API 网关)应用按 IP 和按身份的限制。推荐的初始配额桶参见 [Production readiness](/docs/operate/production)。 + +## CORS + +如果调用方在不同源的浏览器上运行,请在 ingress 或运行时中间件中配置 CORS。**不要**将通配符 origin 与携带凭据的请求结合使用。 + +## OpenAPI / 发现 + +当镜像中包含相应能力时,运行时可以为自动生成的 REST API 提供 OpenAPI 文档。客户的集成应基于每个部署的 OpenAPI 文档生成客户端,而不是手写 URL,因为对象名称和生成的路由会跟随已部署的 artifact 而变化。 diff --git a/content/docs/configure/authentication.de.mdx b/content/docs/configure/authentication.de.mdx new file mode 100644 index 0000000..5b7c148 --- /dev/null +++ b/content/docs/configure/authentication.de.mdx @@ -0,0 +1,125 @@ +--- +title: Authentifizierung +description: Konfigurieren Sie Anmeldung, Sitzungen, OAuth, OIDC/SSO und Device Flow. +--- + +# Authentifizierung + +ObjectOS verwendet das ObjectStack-Authentifizierungs-Plugin, das auf +Better Auth basiert. Die Authentifizierung ist projektlokal: Jedes Projekt hat +seine eigenen Identitätstabellen und seinen eigenen Sitzungsbereich. + +## Was wird unterstützt + +Abhängig von der paketierten Anwendung und den aktivierten Einstellungen kann +ObjectOS Folgendes unterstützen: + +- Anmeldung per E-Mail/Passwort; +- Sitzungsverwaltung; +- Passwortzurücksetzung und E-Mail-Verifizierung; +- soziale OAuth-Anbieter wie Google, GitHub, Microsoft und Apple; +- Enterprise-OIDC/SSO wie Okta, Entra ID, Keycloak und Ping; +- Zwei-Faktor-Authentifizierung; +- Passkeys/WebAuthn; +- Magic Links; +- CLI-/Browser-Device-Flow. + +## Erforderliches Geheimnis + +Legen Sie fest: + +```bash +OS_AUTH_SECRET=replace-with-a-strong-random-secret +``` + +ObjectOS leitet aus diesem Wert und der Projektumgebungs-ID ein stabiles +projektspezifisches Geheimnis ab. Das bedeutet: + +- Sitzungen überstehen Container-Neustarts; +- Tokens aus einem Projekt können nicht in einem anderen Projekt wiederverwendet werden; +- das Rotieren von `OS_AUTH_SECRET` macht Sitzungen ungültig. + +Siehe [Environment variables](/docs/reference/environment-variables) für die +vollständige Liste der authentifizierungsbezogenen Einstellungen, einschließlich +des veralteten `AUTH_SECRET`-Alias. + +## Sitzungsisolierung + +In Bereitstellungen mit mehreren Projekten sind Cookies auf den Projekt-Hostnamen +beschränkt. ObjectOS vermeidet bewusst weitreichende Root-Domain-Cookies für +Projektsitzungen. Dadurch wird verhindert, dass eine Sitzung über Kundenprojekte +hinweg durchsickert. + +## Soziale Anmeldung + +Konfigurieren Sie die Anbieter-Anmeldedaten über Umgebungsvariablen oder +Systemeinstellungen, je nachdem, wie das Anwendungspaket die +Authentifizierungskonfiguration bereitstellt. + +Die Callback-URLs der Anbieter hängen vom Anbietertyp ab. ObjectStack stellt +zwei unterschiedliche Callback-Pfade bereit, die **nicht** austauschbar sind: + +| Anbietertyp | Callback-Pfad | +|---|---| +| Integrierte soziale Anbieter (Google, GitHub, Microsoft, Apple, …) | `/api/v1/auth/callback/` | +| Generisches OIDC / OAuth2 (Okta, Entra ID, Keycloak, Ping, …) | `/api/v1/auth/oauth2/callback/` | + +Beispiele: + +```text +https://crm.example.com/api/v1/auth/callback/google +https://crm.example.com/api/v1/auth/callback/microsoft +https://crm.example.com/api/v1/auth/oauth2/callback/okta +https://crm.example.com/api/v1/auth/oauth2/callback/entra +``` + +Konfigurieren Sie die passende Redirect-URI in der Anwendungsregistrierung des +Identitätsanbieters, bevor Sie den Anbieter in ObjectOS aktivieren. + +## Enterprise-OIDC/SSO + +OIDC-Anbieter werden als generische OAuth2-Anbieter registriert und verwenden den +Pfad `/api/v1/auth/oauth2/callback/`. Eine typische Konfiguration +erfordert: + +| Feld | Beschreibung | +|---|---| +| Provider id | Stabile ID wie `okta` oder `entra` (in der Callback-URL verwendet) | +| Display name | Schaltflächenbeschriftung, die Benutzern angezeigt wird | +| Discovery URL | `.well-known/openid-configuration`-Endpunkt | +| Client id | Anwendungs-Client-ID vom Identitätsanbieter | +| Client secret | Geheimnis, das in Umgebung oder verschlüsselten Einstellungen gespeichert ist | +| Scopes | Üblicherweise `openid email profile` | + +Bevorzugen Sie für Kundenbereitstellungen OIDC-Discovery-URLs gegenüber manuell +konfigurierten Authorization-/Token-/Userinfo-Endpunkten. + +## Plattform-SSO + +In cloud-verbundenen Bereitstellungen kann ObjectOS die Control-Plane-Anmeldung +als Plattform-SSO-Anbieter verwenden. Ein Builder, der bereits an der +Control Plane angemeldet ist, kann in eine Projektlaufzeit bereitgestellt werden, +ohne ein separates projektlokales Konto zu erstellen. + +Dies erfordert, dass die Control Plane und ObjectOS dasselbe +`OS_AUTH_SECRET`-Basisgeheimnis teilen. Deaktivieren Sie Plattform-SSO nur, wenn +der Kunde möchte, dass jedes Projekt eine vollständig separate Anmeldegrenze +besitzt. + +## Betriebsprüfungen + +Vor der Produktion: + +- bestätigen Sie, dass abgelaufene Tokens `401` zurückgeben; +- bestätigen Sie, dass die Abmeldung die aktive Sitzung widerruft; +- bestätigen Sie, dass die Passwortzurücksetzung andere Sitzungen widerruft, falls die Richtlinie dies erfordert; +- bestätigen Sie, dass die Callback-URLs mit der öffentlichen Projektdomäne übereinstimmen; +- bestätigen Sie, dass vertrauenswürdige Ursprünge nur genehmigte Domänen enthalten; +- bestätigen Sie, dass `OS_AUTH_SECRET` in einem Secret Manager gespeichert ist und nicht im Quellcode. + +## Nächste Schritte + +Die Authentifizierung legt fest, *wer* ein Benutzer ist. Um zu steuern, *worauf* +ein Benutzer nach der Anmeldung zugreifen kann, siehe +[Permissions](/docs/configure/permissions). Für Nicht-Browser-Clients und +Machine-to-Machine-Zugriff siehe [API access](/docs/configure/api-access). diff --git a/content/docs/configure/authentication.es.mdx b/content/docs/configure/authentication.es.mdx new file mode 100644 index 0000000..0e985f7 --- /dev/null +++ b/content/docs/configure/authentication.es.mdx @@ -0,0 +1,122 @@ +--- +title: Autenticación +description: Configura el inicio de sesión, las sesiones, OAuth, OIDC/SSO y el flujo de dispositivos. +--- + +# Autenticación + +ObjectOS utiliza el complemento de autenticación de ObjectStack, basado en +Better Auth. La autenticación es local al proyecto: cada proyecto tiene sus propias +tablas de identidad y su propio alcance de sesión. + +## Qué se admite + +Según la aplicación empaquetada y los ajustes habilitados, ObjectOS puede +admitir: + +- inicio de sesión con correo electrónico y contraseña; +- gestión de sesiones; +- restablecimiento de contraseña y verificación de correo electrónico; +- proveedores de OAuth social como Google, GitHub, Microsoft y Apple; +- OIDC/SSO empresarial como Okta, Entra ID, Keycloak y Ping; +- autenticación de dos factores; +- passkeys/WebAuthn; +- enlaces mágicos; +- flujo de dispositivos CLI/navegador. + +## Secreto requerido + +Configura: + +```bash +OS_AUTH_SECRET=replace-with-a-strong-random-secret +``` + +ObjectOS deriva un secreto estable por proyecto a partir de este valor y del +id del entorno del proyecto. Esto significa que: + +- las sesiones sobreviven a los reinicios de contenedores; +- los tokens de un proyecto no se pueden reutilizar en otro proyecto; +- rotar `OS_AUTH_SECRET` invalida las sesiones. + +Consulta [Environment variables](/docs/reference/environment-variables) para ver la +lista completa de ajustes relacionados con la autenticación, incluido el alias heredado `AUTH_SECRET`. + +## Aislamiento de sesiones + +En despliegues con varios proyectos, las cookies tienen su alcance limitado al nombre de host del proyecto. +ObjectOS evita intencionadamente las cookies amplias de dominio raíz para las sesiones +de proyecto. Esto impide que una sesión se filtre entre proyectos de distintos clientes. + +## Inicio de sesión social + +Configura las credenciales del proveedor mediante variables de entorno o ajustes +del sistema, según cómo el paquete de la aplicación exponga la configuración +de autenticación. + +Las URL de devolución de llamada del proveedor dependen del tipo de proveedor. ObjectStack expone +dos rutas de devolución de llamada distintas y **no** son intercambiables: + +| Tipo de proveedor | Ruta de devolución de llamada | +|---|---| +| Social integrado (Google, GitHub, Microsoft, Apple, …) | `/api/v1/auth/callback/` | +| OIDC / OAuth2 genérico (Okta, Entra ID, Keycloak, Ping, …) | `/api/v1/auth/oauth2/callback/` | + +Ejemplos: + +```text +https://crm.example.com/api/v1/auth/callback/google +https://crm.example.com/api/v1/auth/callback/microsoft +https://crm.example.com/api/v1/auth/oauth2/callback/okta +https://crm.example.com/api/v1/auth/oauth2/callback/entra +``` + +Configura la URI de redirección correspondiente en el registro de aplicación del +proveedor de identidad antes de habilitar el proveedor en ObjectOS. + +## OIDC/SSO empresarial + +Los proveedores OIDC se registran como proveedores OAuth2 genéricos y usan la +ruta `/api/v1/auth/oauth2/callback/`. Una configuración típica +requiere: + +| Campo | Descripción | +|---|---| +| Provider id | Id estable como `okta` o `entra` (usado en la URL de devolución de llamada) | +| Display name | Etiqueta del botón que se muestra a los usuarios | +| Discovery URL | Endpoint `.well-known/openid-configuration` | +| Client id | Id de cliente de la aplicación del proveedor de identidad | +| Client secret | Secreto almacenado en el entorno o en ajustes cifrados | +| Scopes | Normalmente `openid email profile` | + +Para los despliegues de clientes, prefiere las URL de descubrimiento OIDC en lugar de +endpoints de autorización/token/userinfo configurados manualmente. + +## SSO de plataforma + +En despliegues conectados a la nube, ObjectOS puede usar el inicio de sesión del plano +de control como proveedor de SSO de plataforma. Un creador que ya haya iniciado sesión en el +plano de control puede aprovisionarse en el entorno de ejecución de un proyecto sin crear +una cuenta local del proyecto independiente. + +Esto requiere que el plano de control y ObjectOS compartan el mismo secreto base +`OS_AUTH_SECRET`. Deshabilita el SSO de plataforma solo cuando el cliente +quiera que cada proyecto tenga un límite de inicio de sesión completamente independiente. + +## Comprobaciones operativas + +Antes de producción: + +- confirma que los tokens caducados devuelven `401`; +- confirma que el cierre de sesión revoca la sesión activa; +- confirma que el restablecimiento de contraseña revoca otras sesiones si la política lo requiere; +- confirma que las URL de devolución de llamada coinciden con el dominio público del proyecto; +- confirma que los orígenes de confianza incluyen solo dominios aprobados; +- confirma que `OS_AUTH_SECRET` se almacena en un gestor de secretos, no en el código fuente. + +## Próximos pasos + +La autenticación establece *quién* es un usuario. Para controlar *a qué* puede +acceder una vez que ha iniciado sesión, consulta [Permissions](/docs/configure/permissions). Para +clientes que no son navegadores y para el acceso de máquina a máquina, consulta +[API access](/docs/configure/api-access). diff --git a/content/docs/configure/authentication.fr.mdx b/content/docs/configure/authentication.fr.mdx new file mode 100644 index 0000000..c8d7628 --- /dev/null +++ b/content/docs/configure/authentication.fr.mdx @@ -0,0 +1,122 @@ +--- +title: Authentification +description: Configurez la connexion, les sessions, OAuth, OIDC/SSO et le flux d'appareil. +--- + +# Authentification + +ObjectOS utilise le plugin d'authentification ObjectStack, propulsé par +Better Auth. L'authentification est locale au projet : chaque projet possède ses propres +tables d'identité et sa propre portée de session. + +## Ce qui est pris en charge + +Selon l'application packagée et les paramètres activés, ObjectOS peut +prendre en charge : + +- la connexion par e-mail/mot de passe ; +- la gestion des sessions ; +- la réinitialisation du mot de passe et la vérification de l'e-mail ; +- les fournisseurs OAuth sociaux tels que Google, GitHub, Microsoft et Apple ; +- l'OIDC/SSO d'entreprise tel qu'Okta, Entra ID, Keycloak et Ping ; +- l'authentification à deux facteurs ; +- les passkeys/WebAuthn ; +- les liens magiques ; +- le flux d'appareil CLI/navigateur. + +## Secret requis + +Définissez : + +```bash +OS_AUTH_SECRET=replace-with-a-strong-random-secret +``` + +ObjectOS dérive un secret stable propre au projet à partir de cette valeur et de +l'identifiant d'environnement du projet. Cela signifie que : + +- les sessions survivent aux redémarrages de conteneurs ; +- les jetons d'un projet ne peuvent pas être réutilisés sur un autre projet ; +- la rotation de `OS_AUTH_SECRET` invalide les sessions. + +Consultez [Environment variables](/docs/reference/environment-variables) pour la +liste complète des paramètres liés à l'authentification, y compris l'alias hérité `AUTH_SECRET`. + +## Isolation des sessions + +Dans les déploiements multi-projets, les cookies sont limités au nom d'hôte du projet. +ObjectOS évite intentionnellement les cookies de domaine racine larges pour les sessions +de projet. Cela empêche une session de fuiter d'un projet client à l'autre. + +## Connexion sociale + +Configurez les identifiants des fournisseurs via des variables d'environnement ou des +paramètres système, selon la manière dont le package applicatif expose la +configuration de l'authentification. + +Les URL de rappel des fournisseurs dépendent du type de fournisseur. ObjectStack expose +deux chemins de rappel distincts et ils ne sont **pas** interchangeables : + +| Type de fournisseur | Chemin de rappel | +|---|---| +| Social intégré (Google, GitHub, Microsoft, Apple, …) | `/api/v1/auth/callback/` | +| OIDC / OAuth2 générique (Okta, Entra ID, Keycloak, Ping, …) | `/api/v1/auth/oauth2/callback/` | + +Exemples : + +```text +https://crm.example.com/api/v1/auth/callback/google +https://crm.example.com/api/v1/auth/callback/microsoft +https://crm.example.com/api/v1/auth/oauth2/callback/okta +https://crm.example.com/api/v1/auth/oauth2/callback/entra +``` + +Configurez l'URI de redirection correspondante dans l'enregistrement de l'application +du fournisseur d'identité avant d'activer le fournisseur dans ObjectOS. + +## OIDC/SSO d'entreprise + +Les fournisseurs OIDC sont enregistrés comme des fournisseurs OAuth2 génériques et utilisent le +chemin `/api/v1/auth/oauth2/callback/`. Une configuration typique +requiert : + +| Champ | Description | +|---|---| +| Provider id | Identifiant stable tel que `okta` ou `entra` (utilisé dans l'URL de rappel) | +| Display name | Libellé du bouton affiché aux utilisateurs | +| Discovery URL | Point de terminaison `.well-known/openid-configuration` | +| Client id | Identifiant client de l'application provenant du fournisseur d'identité | +| Client secret | Secret stocké dans l'environnement ou dans des paramètres chiffrés | +| Scopes | Généralement `openid email profile` | + +Pour les déploiements clients, préférez les URL de découverte OIDC aux points de +terminaison authorization/token/userinfo configurés manuellement. + +## SSO de plateforme + +Dans les déploiements connectés au cloud, ObjectOS peut utiliser la connexion du +plan de contrôle comme fournisseur SSO de plateforme. Un constructeur déjà connecté au +plan de contrôle peut être provisionné dans le runtime d'un projet sans créer +un compte distinct local au projet. + +Cela nécessite que le plan de contrôle et ObjectOS partagent le même +secret de base `OS_AUTH_SECRET`. Désactivez le SSO de plateforme uniquement lorsque le client +souhaite que chaque projet possède une frontière de connexion complètement distincte. + +## Vérifications opérationnelles + +Avant la mise en production : + +- confirmez que les jetons expirés renvoient `401` ; +- confirmez que la déconnexion révoque la session active ; +- confirmez que la réinitialisation du mot de passe révoque les autres sessions si la politique l'exige ; +- confirmez que les URL de rappel correspondent au domaine public du projet ; +- confirmez que les origines de confiance n'incluent que des domaines approuvés ; +- confirmez que `OS_AUTH_SECRET` est stocké dans un gestionnaire de secrets, et non dans le code source. + +## Étapes suivantes + +L'authentification établit *qui* est un utilisateur. Pour contrôler *ce* à quoi il peut +accéder une fois connecté, consultez [Permissions](/docs/configure/permissions). Pour +les clients non navigateur et l'accès de machine à machine, consultez +[API access](/docs/configure/api-access). diff --git a/content/docs/configure/authentication.ja.mdx b/content/docs/configure/authentication.ja.mdx new file mode 100644 index 0000000..892b5fa --- /dev/null +++ b/content/docs/configure/authentication.ja.mdx @@ -0,0 +1,100 @@ +--- +title: 認証 +description: サインイン、セッション、OAuth、OIDC/SSO、デバイスフローを設定します。 +--- + +# 認証 + +ObjectOS は、Better Auth を基盤とする ObjectStack 認証プラグインを使用します。認証はプロジェクトローカルであり、各プロジェクトは独自のアイデンティティテーブルとセッションスコープを持ちます。 + +## サポートされる機能 + +パッケージ化されたアプリケーションと有効化された設定に応じて、ObjectOS は以下をサポートできます。 + +- メール/パスワードによるサインイン +- セッション管理 +- パスワードリセットとメール検証 +- Google、GitHub、Microsoft、Apple などのソーシャル OAuth プロバイダー +- Okta、Entra ID、Keycloak、Ping などのエンタープライズ OIDC/SSO +- 二要素認証 +- パスキー/WebAuthn +- マジックリンク +- CLI/ブラウザのデバイスフロー + +## 必須のシークレット + +次を設定します。 + +```bash +OS_AUTH_SECRET=replace-with-a-strong-random-secret +``` + +ObjectOS は、この値とプロジェクト環境 id から、安定したプロジェクトごとのシークレットを導出します。これにより以下が実現されます。 + +- セッションがコンテナの再起動後も維持される +- あるプロジェクトのトークンを別のプロジェクトで再利用できない +- `OS_AUTH_SECRET` をローテーションするとセッションが無効化される + +レガシーの `AUTH_SECRET` エイリアスを含む、認証関連の設定の完全な一覧については、[Environment variables](/docs/reference/environment-variables) を参照してください。 + +## セッションの分離 + +マルチプロジェクト構成のデプロイでは、Cookie はプロジェクトのホスト名にスコープされます。ObjectOS は、プロジェクトセッションに対して広範なルートドメイン Cookie を意図的に使用しません。これにより、セッションが顧客プロジェクト間で漏えいすることを防ぎます。 + +## ソーシャルログイン + +アプリケーションパッケージが認証設定をどのように公開するかに応じて、プロバイダーの認証情報を環境変数またはシステム設定を通じて設定します。 + +プロバイダーのコールバック URL はプロバイダーの種類によって異なります。ObjectStack は 2 つの異なるコールバックパスを公開しており、これらは互いに**入れ替えできません**。 + +| プロバイダーの種類 | コールバックパス | +|---|---| +| 組み込みソーシャル(Google、GitHub、Microsoft、Apple、…) | `/api/v1/auth/callback/` | +| 汎用 OIDC / OAuth2(Okta、Entra ID、Keycloak、Ping、…) | `/api/v1/auth/oauth2/callback/` | + +例: + +```text +https://crm.example.com/api/v1/auth/callback/google +https://crm.example.com/api/v1/auth/callback/microsoft +https://crm.example.com/api/v1/auth/oauth2/callback/okta +https://crm.example.com/api/v1/auth/oauth2/callback/entra +``` + +ObjectOS でプロバイダーを有効化する前に、アイデンティティプロバイダーのアプリケーション登録で、対応するリダイレクト URI を設定してください。 + +## エンタープライズ OIDC/SSO + +OIDC プロバイダーは汎用 OAuth2 プロバイダーとして登録され、`/api/v1/auth/oauth2/callback/` パスを使用します。一般的な設定には次が必要です。 + +| フィールド | 説明 | +|---|---| +| Provider id | `okta` や `entra` などの安定した id(コールバック URL で使用) | +| Display name | ユーザーに表示されるボタンのラベル | +| Discovery URL | `.well-known/openid-configuration` エンドポイント | +| Client id | アイデンティティプロバイダーのアプリケーション client id | +| Client secret | 環境変数または暗号化された設定に保存されるシークレット | +| Scopes | 通常は `openid email profile` | + +顧客向けのデプロイでは、手動で設定する authorization/token/userinfo エンドポイントよりも、OIDC ディスカバリ URL を優先してください。 + +## プラットフォーム SSO + +クラウド接続されたデプロイでは、ObjectOS はコントロールプレーンのログインをプラットフォーム SSO プロバイダーとして使用できます。すでにコントロールプレーンにサインインしているビルダーは、別のプロジェクトローカルアカウントを作成することなく、プロジェクトランタイムにプロビジョニングできます。 + +これには、コントロールプレーンと ObjectOS が同じ `OS_AUTH_SECRET` のベースシークレットを共有している必要があります。すべてのプロジェクトが完全に独立したログイン境界を持つことを顧客が望む場合にのみ、プラットフォーム SSO を無効化してください。 + +## 運用上のチェック + +本番環境に移行する前に、以下を確認します。 + +- 期限切れトークンが `401` を返すことを確認する +- ログアウトでアクティブなセッションが取り消されることを確認する +- ポリシーで必要とされる場合、パスワードリセットが他のセッションを取り消すことを確認する +- コールバック URL が公開プロジェクトドメインと一致することを確認する +- 信頼されたオリジンに承認済みのドメインのみが含まれることを確認する +- `OS_AUTH_SECRET` がソースコードではなくシークレットマネージャーに保存されていることを確認する + +## 次のステップ + +認証は、ユーザーが*誰*であるかを確立します。サインイン後に*何*にアクセスできるかを制御するには、[Permissions](/docs/configure/permissions) を参照してください。ブラウザ以外のクライアントやマシン間アクセスについては、[API access](/docs/configure/api-access) を参照してください。 diff --git a/content/docs/configure/authentication.mdx b/content/docs/configure/authentication.mdx index 49c5134..528817e 100644 --- a/content/docs/configure/authentication.mdx +++ b/content/docs/configure/authentication.mdx @@ -39,6 +39,10 @@ project environment id. This means: - tokens from one project cannot be reused on another project; - rotating `OS_AUTH_SECRET` invalidates sessions. +See [Environment variables](/docs/reference/environment-variables) for the +full list of auth-related settings, including the legacy `AUTH_SECRET` +alias. + ## Session isolation In multi-project deployments, cookies are scoped to the project hostname. @@ -74,7 +78,8 @@ application registration before enabling the provider in ObjectOS. ## Enterprise OIDC/SSO OIDC providers are registered as generic OAuth2 providers and use the -`/oauth2/callback/` path. A typical configuration requires: +`/api/v1/auth/oauth2/callback/` path. A typical configuration +requires: | Field | Description | |---|---| @@ -109,3 +114,10 @@ Before production: - confirm callback URLs match the public project domain; - confirm trusted origins include only approved domains; - confirm `OS_AUTH_SECRET` is stored in a secret manager, not in source. + +## Next steps + +Authentication establishes *who* a user is. To control *what* they can +access once signed in, see [Permissions](/docs/configure/permissions). For +non-browser clients and machine-to-machine access, see +[API access](/docs/configure/api-access). diff --git a/content/docs/configure/authentication.cn.mdx b/content/docs/configure/authentication.zh-Hans.mdx similarity index 85% rename from content/docs/configure/authentication.cn.mdx rename to content/docs/configure/authentication.zh-Hans.mdx index ad426c8..f111af4 100644 --- a/content/docs/configure/authentication.cn.mdx +++ b/content/docs/configure/authentication.zh-Hans.mdx @@ -35,6 +35,8 @@ ObjectOS 基于该值和项目环境 id 派生稳定的项目级 secret。这意 - 一个项目的 token 不能在另一个项目中复用; - 轮换 `OS_AUTH_SECRET` 会使会话失效。 +完整的认证相关设置列表(包括旧版 `AUTH_SECRET` 别名)请参阅 [Environment variables](/docs/reference/environment-variables)。 + ## 会话隔离 在多项目部署中,Cookie 限定到项目主机名。ObjectOS 故意避免使用宽泛的根域 Cookie 作为项目会话——以防止会话跨客户项目泄漏。 @@ -63,7 +65,7 @@ https://crm.example.com/api/v1/auth/oauth2/callback/entra ## 企业级 OIDC/SSO -OIDC Provider 注册为通用 OAuth2 Provider,使用 `/oauth2/callback/` 路径。典型配置需要: +OIDC Provider 注册为通用 OAuth2 Provider,使用 `/api/v1/auth/oauth2/callback/` 路径。典型配置需要: | 字段 | 说明 | |---|---| @@ -92,3 +94,7 @@ OIDC Provider 注册为通用 OAuth2 Provider,使用 `/oauth2/callback/` | +| `OS_EMAIL_RETRIES` | Anzahl der Transport-Wiederholungsversuche bei Sendefehlern (Standard `0`) | + +Umgebungsvariablen überschreiben übereinstimmende Werte im +`email`-Konfigurationsblock des Artefakts, sodass Betreiber die +Zustellung umleiten können, ohne das Artefakt neu zu erstellen. + +## Vorlagen + +Wiederverwendbare Vorlagen werden in `sys_email_template` gespeichert. +Vorlagen unterstützen die Variableninterpolation, die von der +Template-Engine des Frameworks ausgewertet wird. Anwendungscode (oder +ein Flow) ruft den E-Mail-Dienst mit einer Vorlagen-ID und einem +Variablenbündel auf; der Dienst materialisiert Betreff/Inhalt und +übergibt ihn an den konfigurierten Transport. + +## Zustellung überprüfen + +Stellen Sie für Resend / Postmark sicher, dass die sendende Domain im +Dashboard des Anbieters konfiguriert ist (SPF, DKIM, optional DMARC). +Die schnellste End-to-End-Prüfung ist die Aktion **Test-E-Mail senden** +in der Console auf der Seite der E-Mail-Einstellungen — sie verwendet den +Live-Transport und zeigt Transportfehler direkt an. + +## Betriebshinweise + +- Behandeln Sie den API-Schlüssel als Geheimnis. Speichern Sie ihn im + Secret-Manager des Kunden, niemals im Artefakt. +- Beobachten Sie die Transportfehler-Protokolle: Ratenbegrenzungen des + Anbieters, Unterdrückungen und Bounces erscheinen alle dort. +- Audit-relevante Transaktions-E-Mails (Passwort-Zurücksetzung, + MFA-Challenge) sollten gemäß der Richtlinie des Kunden aufbewahrt + werden — legen Sie die Aufbewahrung im Audit-Log fest, nicht im + Transport. +- Ausgehende E-Mails blockieren keine Geschäftstransaktionen: + Sendefehler werden als Fehler angezeigt, machen aber die ursprüngliche + Datensatzänderung nicht rückgängig. diff --git a/content/docs/configure/email.es.mdx b/content/docs/configure/email.es.mdx new file mode 100644 index 0000000..003c272 --- /dev/null +++ b/content/docs/configure/email.es.mdx @@ -0,0 +1,85 @@ +--- +title: Email +description: Configura proveedores de entrega de correo transaccional y plantillas. +--- + +# Email + +ObjectOS envía correo transaccional a través del plugin de email del framework +cuando la aplicación lo requiere (restablecimiento de contraseña, invitaciones, +notificaciones de aprobación, informes programados). El plugin incluye tres +transportes. + +## Transportes + +| Proveedor | Cuándo usarlo | Variables de entorno requeridas | +|---|---|---| +| `log` | Desarrollo local; registra el correo en stdout en lugar de enviarlo | ninguna | +| `resend` | Capacidad de entrega SaaS mediante Resend | `OS_EMAIL_API_KEY` | +| `postmark` | Capacidad de entrega SaaS mediante Postmark | `OS_EMAIL_API_KEY` | + +El valor por defecto es `log`. ObjectOS recurre al transporte log cuando se +configura un proveedor real pero no se suministra una clave de API — útil para +evitar que los entornos no productivos envíen correo de forma accidental. + +### ¿Qué pasa con SMTP? + +El transporte SMTP nativo **no** está integrado en el runtime actualmente. Si tu +entorno requiere SMTP (relay corporativo, correo on-premise, despliegue aislado) +tienes dos opciones de nivel producción: + +1. **Ejecuta un relay de SMTP a API** delante de ObjectOS. Resend, Postmark + y las alternativas autoalojadas (Postal, Cuttlefish) aceptan ingreso por + SMTP y reenvían a través de su API HTTP — ObjectOS se comunica con ellas + sobre HTTPS de forma normal. +2. **Ejecuta el runtime con un plugin de email personalizado.** La API del + plugin de email es pequeña (una sola función `send(message)`); un plugin del + proyecto que envuelva `nodemailer` se conecta a través de la lista `requires`. + Consulta la [guía de creación de plugins](https://github.com/objectstack-ai/spec) + en el repositorio de la especificación. + +El transporte SMTP nativo está en la hoja de ruta; sigue el progreso en +[github.com/objectstack-ai/objectos/issues](https://github.com/objectstack-ai/objectos/issues). + +## Variables de entorno + +| Variable | Propósito | +|---|---| +| `OS_EMAIL_PROVIDER` | `log`, `resend` o `postmark` | +| `OS_EMAIL_API_KEY` | Clave de API del proveedor (Resend o Postmark) | +| `OS_EMAIL_FROM` | Dirección de remitente por defecto. Admite los formatos `addr@x` y `Name ` | +| `OS_EMAIL_RETRIES` | Número de reintentos del transporte ante un fallo de envío (por defecto `0`) | + +Las variables de entorno anulan los valores correspondientes del bloque de +configuración `email` del artefacto, de modo que los operadores pueden +redirigir la entrega sin reconstruir el artefacto. + +## Plantillas + +Las plantillas reutilizables residen en `sys_email_template`. Las plantillas +admiten interpolación de variables evaluada por el motor de plantillas del +framework. El código de la aplicación (o un flujo) invoca el servicio de email +con un id de plantilla y un conjunto de variables; el servicio materializa el +asunto/cuerpo y lo entrega al transporte configurado. + +## Verificación de la entrega + +Para Resend / Postmark, verifica que el dominio de envío esté configurado en el +panel del proveedor (SPF, DKIM y, opcionalmente, DMARC). La comprobación +extremo a extremo más rápida es la acción **Send test email** de la Console en la +página de configuración de email — utiliza el transporte real y muestra los +errores de transporte en línea. + +## Recomendaciones operativas + +- Trata la clave de API como un secreto. Almacénala en el gestor de secretos del + cliente, nunca en el artefacto. +- Vigila los registros de errores de transporte: los límites de tasa del + proveedor, las supresiones y los rebotes aparecen todos ahí. +- El correo transaccional sensible para auditoría (restablecimiento de + contraseña, desafío MFA) debe conservarse de acuerdo con la política del + cliente — establece la retención en el registro de auditoría, no en el + transporte. +- El correo saliente no bloquea las transacciones de negocio: los fallos de + envío se muestran como errores pero no revierten el cambio del registro que + los originó. diff --git a/content/docs/configure/email.fr.mdx b/content/docs/configure/email.fr.mdx new file mode 100644 index 0000000..550c744 --- /dev/null +++ b/content/docs/configure/email.fr.mdx @@ -0,0 +1,91 @@ +--- +title: Email +description: Configurez les fournisseurs et les modèles de livraison d'e-mails transactionnels. +--- + +# Email + +ObjectOS envoie des e-mails transactionnels via le plugin email du +framework lorsque l'application le requiert (réinitialisation de mot de +passe, invitations, notifications d'approbation, rapports planifiés). Le +plugin est fourni avec trois transports. + +## Transports + +| Fournisseur | À utiliser quand | Variables d'env requises | +|---|---|---| +| `log` | Développement local ; consigne l'e-mail dans stdout au lieu de l'envoyer | aucune | +| `resend` | Délivrabilité SaaS via Resend | `OS_EMAIL_API_KEY` | +| `postmark` | Délivrabilité SaaS via Postmark | `OS_EMAIL_API_KEY` | + +La valeur par défaut est `log`. ObjectOS bascule vers le transport log +lorsqu'un véritable fournisseur est configuré mais qu'aucune clé API +n'est fournie — utile pour empêcher les environnements non productifs +d'envoyer accidentellement des e-mails. + +### Qu'en est-il de SMTP ? + +Le transport SMTP natif n'est **pas** intégré au runtime aujourd'hui. Si +votre environnement requiert SMTP (relais d'entreprise, messagerie +on-prem, déploiement isolé du réseau), vous disposez de deux options de +qualité production : + +1. **Exécutez un relais SMTP-vers-API** devant ObjectOS. Resend, + Postmark et les alternatives auto-hébergées (Postal, Cuttlefish) + acceptent tous l'entrée SMTP et la réémettent via leur API HTTP — + ObjectOS communique avec eux en HTTPS comme d'habitude. +2. **Exécutez le runtime avec un plugin email personnalisé.** L'API du + plugin email est réduite (une seule fonction `send(message)`) ; un + plugin de projet qui encapsule `nodemailer` s'intègre via la liste + `requires`. Consultez le + [guide de création de plugins](https://github.com/objectstack-ai/spec) + dans le dépôt spec. + +Le transport SMTP natif figure sur la feuille de route ; suivez +l'avancement sur +[github.com/objectstack-ai/objectos/issues](https://github.com/objectstack-ai/objectos/issues). + +## Variables d'environnement + +| Variable | Rôle | +|---|---| +| `OS_EMAIL_PROVIDER` | `log`, `resend` ou `postmark` | +| `OS_EMAIL_API_KEY` | Clé API du fournisseur (Resend ou Postmark) | +| `OS_EMAIL_FROM` | Adresse d'expéditeur par défaut. Prend en charge les formats `addr@x` et `Name ` | +| `OS_EMAIL_RETRIES` | Nombre de tentatives de réessai du transport en cas d'échec d'envoi (par défaut `0`) | + +Les variables d'environnement remplacent les valeurs correspondantes du +bloc de configuration `email` de l'artefact, ce qui permet aux opérateurs +de rediriger la livraison sans reconstruire l'artefact. + +## Modèles + +Les modèles réutilisables résident dans `sys_email_template`. Les modèles +prennent en charge l'interpolation de variables évaluée par le moteur de +modèles du framework. Le code de l'application (ou un flow) appelle le +service email avec un identifiant de modèle et un ensemble de variables ; +le service matérialise le sujet/corps et le transmet au transport +configuré. + +## Vérifier la livraison + +Pour Resend / Postmark, vérifiez que le domaine d'envoi est configuré +dans le tableau de bord du fournisseur (SPF, DKIM, et éventuellement +DMARC). La vérification de bout en bout la plus rapide est l'action +**Send test email** de la Console sur la page des paramètres email — elle +utilise le transport en direct et fait remonter les erreurs de transport +de manière intégrée. + +## Conseils opérationnels + +- Traitez la clé API comme un secret. Stockez-la dans le gestionnaire de + secrets du client, jamais dans l'artefact. +- Surveillez les journaux d'erreurs de transport : les limites de débit + des fournisseurs, les suppressions et les rebonds y apparaissent tous. +- Les e-mails transactionnels sensibles aux audits (réinitialisation de + mot de passe, défi MFA) doivent être conservés conformément à la + politique du client — définissez la rétention sur le journal d'audit, + pas sur le transport. +- Les e-mails sortants ne bloquent pas les transactions métier : les + échecs d'envoi sont signalés comme des erreurs mais n'annulent pas la + modification de l'enregistrement à l'origine. diff --git a/content/docs/configure/email.ja.mdx b/content/docs/configure/email.ja.mdx new file mode 100644 index 0000000..5cc1149 --- /dev/null +++ b/content/docs/configure/email.ja.mdx @@ -0,0 +1,53 @@ +--- +title: メール +description: トランザクションメールの配信プロバイダーとテンプレートを設定します。 +--- + +# メール + +ObjectOS は、アプリケーションが必要とする場面(パスワードリセット、招待、承認通知、スケジュールされたレポート)で、フレームワークのメールプラグインを通じてトランザクションメールを送信します。このプラグインには 3 つのトランスポートが同梱されています。 + +## トランスポート + +| プロバイダー | 使用する場面 | 必要な環境変数 | +|---|---|---| +| `log` | ローカル開発。メールを送信する代わりに stdout に出力します | なし | +| `resend` | Resend による SaaS 配信 | `OS_EMAIL_API_KEY` | +| `postmark` | Postmark による SaaS 配信 | `OS_EMAIL_API_KEY` | + +デフォルトは `log` です。実際のプロバイダーが設定されていても API キーが指定されていない場合、ObjectOS は log トランスポートにフォールバックします。これは非本番環境が誤ってメールを送信してしまうのを防ぐのに役立ちます。 + +### SMTP については? + +ネイティブの SMTP トランスポートは、現時点ではランタイムに**組み込まれていません**。環境で SMTP が必要な場合(企業のリレー、オンプレミスのメール、エアギャップ環境へのデプロイ)には、本番グレードの選択肢が 2 つあります。 + +1. **SMTP-to-API リレーを ObjectOS の前段で実行する。** Resend、Postmark、およびセルフホスト型の代替手段(Postal、Cuttlefish)はいずれも SMTP の受信を受け付け、HTTP API 経由で再送信します。ObjectOS は通常どおり HTTPS でこれらと通信します。 +2. **カスタムメールプラグインでランタイムを実行する。** メールプラグインの API は小さく(`send(message)` 関数が 1 つ)、`nodemailer` をラップするプロジェクトプラグインを `requires` リスト経由で組み込めます。spec リポジトリの[プラグイン作成ガイド](https://github.com/objectstack-ai/spec)を参照してください。 + +ネイティブの SMTP トランスポートはロードマップに含まれています。進捗は [github.com/objectstack-ai/objectos/issues](https://github.com/objectstack-ai/objectos/issues) で確認できます。 + +## 環境変数 + +| 変数 | 目的 | +|---|---| +| `OS_EMAIL_PROVIDER` | `log`、`resend`、または `postmark` | +| `OS_EMAIL_API_KEY` | プロバイダーの API キー(Resend または Postmark) | +| `OS_EMAIL_FROM` | デフォルトの送信元アドレス。`addr@x` と `Name ` の両方の形式をサポートします | +| `OS_EMAIL_RETRIES` | 送信失敗時のトランスポート再試行回数(デフォルトは `0`) | + +環境変数はアーティファクトの `email` 設定ブロック内の対応する値を上書きするため、運用担当者はアーティファクトを再ビルドすることなく配信先を変更できます。 + +## テンプレート + +再利用可能なテンプレートは `sys_email_template` に格納されます。テンプレートは、フレームワークのテンプレートエンジンによって評価される変数の補間をサポートします。アプリケーションコード(またはフロー)は、テンプレート ID と変数バンドルを指定してメールサービスを呼び出します。サービスは件名と本文を生成し、設定されたトランスポートに引き渡します。 + +## 配信の検証 + +Resend / Postmark の場合は、送信ドメインがプロバイダーのダッシュボードで設定されていること(SPF、DKIM、必要に応じて DMARC)を確認してください。最も手早いエンドツーエンドの確認方法は、メール設定ページにある Console の**テストメール送信**アクションです。これはライブのトランスポートを使用し、トランスポートエラーをインラインで表示します。 + +## 運用上のガイダンス + +- API キーはシークレットとして扱ってください。顧客のシークレットマネージャーに保存し、アーティファクトには決して含めないでください。 +- トランスポートエラーのログを監視してください。プロバイダーのレート制限、抑制(suppression)、バウンスはすべてそこに表示されます。 +- 監査上重要なトランザクションメール(パスワードリセット、MFA チャレンジ)は、顧客のポリシーに従って保持する必要があります。保持期間はトランスポートではなく監査ログに設定してください。 +- 送信メールは業務トランザクションをブロックしません。送信失敗はエラーとして表示されますが、発端となったレコードの変更をロールバックすることはありません。 diff --git a/content/docs/configure/email.cn.mdx b/content/docs/configure/email.zh-Hans.mdx similarity index 100% rename from content/docs/configure/email.cn.mdx rename to content/docs/configure/email.zh-Hans.mdx diff --git a/content/docs/configure/meta.de.json b/content/docs/configure/meta.de.json new file mode 100644 index 0000000..b898a36 --- /dev/null +++ b/content/docs/configure/meta.de.json @@ -0,0 +1,15 @@ +{ + "title": "Konfigurieren", + "defaultOpen": false, + "pages": [ + "runtime", + "authentication", + "permissions", + "storage", + "ai", + "system-settings", + "api-access", + "webhooks", + "email" + ] +} diff --git a/content/docs/configure/meta.es.json b/content/docs/configure/meta.es.json new file mode 100644 index 0000000..a5bd209 --- /dev/null +++ b/content/docs/configure/meta.es.json @@ -0,0 +1,15 @@ +{ + "title": "Configurar", + "defaultOpen": false, + "pages": [ + "runtime", + "authentication", + "permissions", + "storage", + "ai", + "system-settings", + "api-access", + "webhooks", + "email" + ] +} diff --git a/content/docs/configure/meta.fr.json b/content/docs/configure/meta.fr.json new file mode 100644 index 0000000..0882fb9 --- /dev/null +++ b/content/docs/configure/meta.fr.json @@ -0,0 +1,15 @@ +{ + "title": "Configurer", + "defaultOpen": false, + "pages": [ + "runtime", + "authentication", + "permissions", + "storage", + "ai", + "system-settings", + "api-access", + "webhooks", + "email" + ] +} diff --git a/content/docs/configure/meta.ja.json b/content/docs/configure/meta.ja.json new file mode 100644 index 0000000..35e1060 --- /dev/null +++ b/content/docs/configure/meta.ja.json @@ -0,0 +1,15 @@ +{ + "title": "設定", + "defaultOpen": false, + "pages": [ + "runtime", + "authentication", + "permissions", + "storage", + "ai", + "system-settings", + "api-access", + "webhooks", + "email" + ] +} diff --git a/content/docs/configure/meta.cn.json b/content/docs/configure/meta.zh-Hans.json similarity index 100% rename from content/docs/configure/meta.cn.json rename to content/docs/configure/meta.zh-Hans.json diff --git a/content/docs/configure/permissions/index.de.mdx b/content/docs/configure/permissions/index.de.mdx new file mode 100644 index 0000000..6cc4360 --- /dev/null +++ b/content/docs/configure/permissions/index.de.mdx @@ -0,0 +1,159 @@ +--- +title: Berechtigungen +description: Identität, Rollen, Berechtigungssätze, Datensatzzugriff und Feldsicherheit — das gesamte Zugriffsmodell auf einer Seite. +--- + +# Berechtigungen + +ObjectOS verfügt über ein mehrschichtiges Zugriffsmodell, das aus dem +Vorgehen übernommen wurde, das sich in Unternehmenssoftware seit zwei +Jahrzehnten bewährt hat: Identität → Rollen → Berechtigungssätze → +Datensatzzugriff → Feldsicherheit. Jede Schicht beantwortet eine +andere Frage, und Sie können diejenigen ignorieren, die Sie nicht +benötigen. + +## Das Modell in einem Diagramm + +```text +Authentication Who is the caller? + ↓ +Identity Which user/org/membership is active? + ↓ +Roles Where do they sit in the hierarchy? + ↓ +Permission sets What CAN they do — apps, objects, fields, system? + ↓ +Record access WHICH records can they touch? + ↓ +Field security For those records, which FIELDS are readable / writable? +``` + +Jede Schicht wird vom Security-Plugin durchgesetzt. Für einfache Apps +können Sie ausschließlich Berechtigungssätze verwenden (keine Rollen, +keine Freigaberegeln) und den Rest hinzufügen, sobald die Anforderung +auftaucht. + +## Schicht 1 — Identität + +Identitätsobjekte befinden sich in Ihrer Projektdatenbank. Die +wichtigsten davon: + +| Objekt | Was es repräsentiert | +|---|---| +| `sys_user` | Eine Person oder ein Dienstkonto, das sich authentifizieren kann | +| `sys_organization` | Mandanten-/Workspace-Grenze (mandantenfähige Apps) | +| `sys_member` | Die Mitgliedschaft eines Benutzers in einer Organisation (Rolle pro Mitgliedschaft zugewiesen) | +| `sys_department`, `sys_team` | Optionale Organisationsstruktur für Freigaberegeln | +| `sys_invitation` | Ausstehende Einladung, die auf Annahme wartet | +| `sys_session` | Aktive authentifizierte Sitzung | +| `sys_api_key` | Langlebige programmatische Anmeldeinformationen, die an einen Benutzer gebunden sind | + +In einer mandantenfähigen Bereitstellung: + +- Benutzer sind auf die Projektdatenbank beschränkt. +- Sitzungen sind auf den Projekt-Hostnamen beschränkt. +- Prüfungen auf Zeilenebene verwenden die Organisation und die Berechtigungen des aktuellen Benutzers. +- Control-Plane-Benutzer sind **nicht** automatisch Geschäftsbenutzer — sie + müssen über Plattform-SSO oder explizite Bereitstellung zugeordnet werden. + +Sie erstellen/verwalten diese zur Laufzeit über die **Console** +(`/_console/`) oder seeden sie in `objectstack.config.ts` für neue +Umgebungen. + +## Schicht 2 — Rollen + +Rollen modellieren das Organigramm (CFO → Finance Manager → Analyst). +Sie existieren in erster Linie, damit Freigaberegeln und Berichte Dinge +ausdrücken können wie "der Vorgesetzte des Datensatzeigentümers". +Verwenden Sie Rollen, wenn Sie hierarchischen Zugriff benötigen; +verzichten Sie auf sie bei flachen Teams. + +Siehe [Roles](/docs/configure/permissions/roles). + +## Schicht 3 — Berechtigungssätze + +Berechtigungssätze sind die primäre Methode, um Fähigkeiten zu +gewähren. Sie werden Benutzern direkt oder über Rollen zugewiesen. + +### Was sie gewähren + +| Typ | Beispiele | +|---|---| +| Anwendungszugriff | CRM öffnen, das Support-Portal öffnen | +| Objektberechtigungen | Datensätze eines Objekts erstellen / lesen / aktualisieren / löschen | +| Feldberechtigungen | Bestimmte Felder lesen oder aktualisieren | +| Systemberechtigungen | Auf Console zugreifen, Berichte ausführen, Daten exportieren, Audit-Log anzeigen | +| Integrationsberechtigungen | API-Schlüssel verwenden, Webhooks konfigurieren, Admin-Aktionen ausführen | + +### Flags für Objektberechtigungen + +Dies sind die exakten Flag-Namen, die das Security-Plugin prüft: + +| Flag | Bedeutung | +|---|---| +| `allowRead` | Datensätze lesen, die der Benutzer über den Datensatzzugriff sehen kann | +| `allowCreate` | Neue Datensätze erstellen | +| `allowEdit` | Datensätze aktualisieren, die der Benutzer sehen kann | +| `allowDelete` | Datensätze löschen, die der Benutzer sehen kann | +| `viewAllRecords` | **Jeden** Datensatz des Objekts lesen, unter Missachtung der Datensatzzugriffsregeln | +| `modifyAllRecords` | **Jeden** Datensatz aktualisieren/löschen; impliziert `viewAllRecords` | + +`viewAllRecords` und `modifyAllRecords` sind mandantenweite +Superuser-Berechtigungen für das jeweilige Objekt. Reservieren Sie sie +für explizite administrative Berechtigungssätze und halten Sie sie aus +jeder benutzerseitigen Rolle heraus. + +Siehe [Permission Sets](/docs/configure/permissions/permission-sets). + +## Schicht 4 — Datensatzzugriff + +Für Benutzer **ohne** `viewAllRecords`: Welche Zeilen können sie sehen? + +Das Modell unterstützt: + +- Implizites Eigentum (Zeilen, die der Benutzer erstellt hat oder besitzt) +- Freigaberegeln (deklarativ — "Team A sieht die Datensätze von Team A") +- Explizite Freigaben (`sys_record_share`-Zeilen — einmalige Freigaben) +- Organisationsbereich (das `organization_id` der Zeile stimmt mit der + Organisation des Benutzers überein) + +Siehe [Record Access](/docs/configure/permissions/record-access). + +## Schicht 5 — Feldsicherheit + +Selbst wenn ein Benutzer einen Datensatz sehen kann, können einzelne +Felder sein: + +- **Ausgeblendet** — das Feld wird aus API- und UI-Antworten entfernt. +- **Schreibgeschützt** — das Feld wird zurückgegeben, aber beim Schreiben abgelehnt. + +Feldsicherheit gilt pro Objekt + pro Berechtigungssatz. Typische +Verwendung: + +- `salary` auf `sys_user` für alle außerhalb der Personalabteilung ausblenden. +- `external_account_id` für Support-Mitarbeiter lesbar, aber nicht bearbeitbar machen. + +Sie wird im selben Evaluator wie die Objektberechtigungen durchgesetzt, +sodass sie einheitlich über REST, ObjectQL und Console hinweg gilt. + +## Wo Sie anfangen sollten + +| Wenn Sie etwas erstellen … | Verwenden Sie | +|---|---| +| Ein internes Tool für ein einzelnes Team | Nur Berechtigungssätze | +| Eine teamübergreifende App, in der Manager Berichte sehen | Rollen + Berechtigungssätze | +| Eine mandantenfähige SaaS-artige App | Organisationsbereich + Berechtigungssätze | +| Eine regulierte App mit PII | Feldsicherheit obendrauf hinzufügen | +| Eine komplexe App im CRM-Stil | Der vollständige Stack | + +## Diagnose & Audit + +- `/_console/` zeigt die effektiven Berechtigungen eines beliebigen + Benutzers, so wie sie ausgewertet werden. +- Das Audit-Log (`sys_audit_log`) erfasst berechtigungsrelevante + Änderungen — Gewährungen, Rollenzuweisungen, Bearbeitungen von + Berechtigungssätzen. +- Abgelehnte Anfragen protokollieren die fehlgeschlagene Regel + (Objektberechtigung vs. Datensatzzugriff vs. Feldsicherheit), sodass + der Support schnell die Frage "Warum kann ich das nicht sehen?" + beantworten kann. diff --git a/content/docs/configure/permissions/index.es.mdx b/content/docs/configure/permissions/index.es.mdx new file mode 100644 index 0000000..b508a6f --- /dev/null +++ b/content/docs/configure/permissions/index.es.mdx @@ -0,0 +1,148 @@ +--- +title: Permisos +description: Identidad, roles, conjuntos de permisos, acceso a registros y seguridad de campos — todo el modelo de acceso en una sola página. +--- + +# Permisos + +ObjectOS tiene un modelo de acceso en capas tomado del manual que ha +funcionado en el software empresarial durante dos décadas: identidad → roles → +conjuntos de permisos → acceso a registros → seguridad de campos. Cada capa responde a +una pregunta diferente, y puedes ignorar las que no necesites. + +## El modelo en un solo diagrama + +```text +Authentication Who is the caller? + ↓ +Identity Which user/org/membership is active? + ↓ +Roles Where do they sit in the hierarchy? + ↓ +Permission sets What CAN they do — apps, objects, fields, system? + ↓ +Record access WHICH records can they touch? + ↓ +Field security For those records, which FIELDS are readable / writable? +``` + +Cada capa es aplicada por el plugin de seguridad. Puedes usar solo +conjuntos de permisos (sin roles, sin reglas de uso compartido) para aplicaciones simples y añadir +el resto a medida que aparezca el requisito. + +## Capa 1 — Identidad + +Los objetos de identidad residen en la base de datos de tu proyecto. Los más importantes: + +| Objeto | Qué representa | +|---|---| +| `sys_user` | Una persona o cuenta de servicio que puede autenticarse | +| `sys_organization` | Límite de inquilino / espacio de trabajo (aplicaciones multiinquilino) | +| `sys_member` | La pertenencia de un usuario a una organización (rol asignado por pertenencia) | +| `sys_department`, `sys_team` | Estructura organizativa opcional para las reglas de uso compartido | +| `sys_invitation` | Invitación pendiente a la espera de ser aceptada | +| `sys_session` | Sesión autenticada activa | +| `sys_api_key` | Credencial programática de larga duración vinculada a un usuario | + +En un despliegue multiinquilino: + +- Los usuarios están delimitados a la base de datos del proyecto. +- Las sesiones están delimitadas al nombre de host del proyecto. +- Las comprobaciones a nivel de fila usan la organización y los permisos del usuario actual. +- Los usuarios del plano de control **no** son automáticamente usuarios de negocio — + deben mapearse mediante SSO de la plataforma o aprovisionamiento explícito. + +Creas/gestionas estos desde la **Console** (`/_console/`) en tiempo de ejecución, o +los precargas en `objectstack.config.ts` para entornos nuevos. + +## Capa 2 — Roles + +Los roles modelan el organigrama (CFO → Gerente de Finanzas → Analista). Existen +principalmente para que las reglas de uso compartido y los informes puedan decir cosas como "el +gerente del propietario del registro". Usa roles cuando necesites acceso +jerárquico; omítelos para equipos planos. + +Consulta [Roles](/docs/configure/permissions/roles). + +## Capa 3 — Conjuntos de permisos + +Los conjuntos de permisos son la forma principal de otorgar capacidades. Se adjuntan +a los usuarios directamente o a través de roles. + +### Qué otorgan + +| Tipo | Ejemplos | +|---|---| +| Acceso a aplicaciones | Abrir CRM, abrir el portal de soporte | +| Permisos de objeto | Crear / leer / actualizar / eliminar registros de un objeto | +| Permisos de campo | Leer o actualizar campos específicos | +| Permisos de sistema | Acceder a Console, ejecutar informes, exportar datos, ver el registro de auditoría | +| Permisos de integración | Usar claves de API, configurar webhooks, ejecutar acciones de administrador | + +### Indicadores de permisos de objeto + +Estos son los nombres exactos de los indicadores que comprueba el plugin de seguridad: + +| Indicador | Significado | +|---|---| +| `allowRead` | Leer registros que el usuario puede ver mediante el acceso a registros | +| `allowCreate` | Crear nuevos registros | +| `allowEdit` | Actualizar registros que el usuario puede ver | +| `allowDelete` | Eliminar registros que el usuario puede ver | +| `viewAllRecords` | Leer **todos** los registros del objeto, ignorando las reglas de acceso a registros | +| `modifyAllRecords` | Actualizar/eliminar **todos** los registros; implica `viewAllRecords` | + +`viewAllRecords` y `modifyAllRecords` son concesiones de superusuario a nivel de +inquilino para ese objeto. Resérvalas para conjuntos de permisos administrativos +explícitos y mantenlas fuera de cualquier rol orientado al usuario. + +Consulta [Permission Sets](/docs/configure/permissions/permission-sets). + +## Capa 4 — Acceso a registros + +Para los usuarios **sin** `viewAllRecords`, ¿qué filas pueden ver? + +El modelo admite: + +- Propiedad implícita (filas que el usuario creó o posee) +- Reglas de uso compartido (declarativas — "el equipo A ve los registros del equipo A") +- Compartidos explícitos (filas `sys_record_share` — compartidos puntuales) +- Delimitación por organización (el `organization_id` de la fila coincide con la + organización del usuario) + +Consulta [Record Access](/docs/configure/permissions/record-access). + +## Capa 5 — Seguridad de campos + +Incluso cuando un usuario puede ver un registro, los campos individuales pueden ser: + +- **Ocultos** — el campo se elimina de las respuestas de la API y la UI. +- **De solo lectura** — el campo se devuelve pero se rechaza al escribir. + +La seguridad de campos es por objeto + por conjunto de permisos. Uso típico: + +- Ocultar `salary` en `sys_user` a cualquiera fuera de RR. HH. +- Hacer que `external_account_id` sea legible pero no editable para los representantes de soporte. + +Se aplica en el mismo evaluador que los permisos de objeto, por lo que +se aplica de manera uniforme en REST, ObjectQL y Console. + +## Por dónde empezar + +| Si estás construyendo … | Usa | +|---|---| +| Una herramienta interna de un solo equipo | Solo conjuntos de permisos | +| Una aplicación multiequipo con gerentes que ven informes | Roles + conjuntos de permisos | +| Una aplicación con forma de SaaS multiinquilino | Delimitación por organización + conjuntos de permisos | +| Una aplicación regulada con PII | Añade seguridad de campos por encima | +| Una aplicación compleja estilo CRM | La pila completa | + +## Diagnosticar y auditar + +- `/_console/` muestra los permisos efectivos de cualquier usuario tal como se + evalúan. +- El registro de auditoría (`sys_audit_log`) registra los cambios sensibles a permisos — + concesiones, asignaciones de roles, ediciones de conjuntos de permisos. +- Las solicitudes denegadas registran la regla que falló (permiso de objeto vs acceso a + registros vs seguridad de campos) para que el soporte pueda responder rápidamente "¿por qué no puedo ver + esto?". diff --git a/content/docs/configure/permissions/index.fr.mdx b/content/docs/configure/permissions/index.fr.mdx new file mode 100644 index 0000000..4bdf96c --- /dev/null +++ b/content/docs/configure/permissions/index.fr.mdx @@ -0,0 +1,171 @@ +--- +title: Permissions +description: Identité, rôles, ensembles d'autorisations, accès aux enregistrements et sécurité des champs — l'intégralité du modèle d'accès sur une seule page. +--- + +# Permissions + +ObjectOS dispose d'un modèle d'accès en couches inspiré des principes qui +ont fait leurs preuves dans les logiciels d'entreprise depuis deux +décennies : identité → rôles → ensembles d'autorisations → accès aux +enregistrements → sécurité des champs. Chaque couche répond à une +question différente, et vous pouvez ignorer celles dont vous n'avez pas +besoin. + +## Le modèle en un seul diagramme + +```text +Authentication Who is the caller? + ↓ +Identity Which user/org/membership is active? + ↓ +Roles Where do they sit in the hierarchy? + ↓ +Permission sets What CAN they do — apps, objects, fields, system? + ↓ +Record access WHICH records can they touch? + ↓ +Field security For those records, which FIELDS are readable / writable? +``` + +Chaque couche est appliquée par le plugin de sécurité. Vous pouvez +utiliser uniquement les ensembles d'autorisations (sans rôles, sans +règles de partage) pour des applications simples et ajouter le reste à +mesure que le besoin apparaît. + +## Couche 1 — Identité + +Les objets d'identité résident dans la base de données de votre projet. +Les plus importants : + +| Objet | Ce qu'il représente | +|---|---| +| `sys_user` | Une personne ou un compte de service pouvant s'authentifier | +| `sys_organization` | Limite de locataire / espace de travail (applications multi-locataires) | +| `sys_member` | L'appartenance d'un utilisateur à une organisation (rôle attribué par appartenance) | +| `sys_department`, `sys_team` | Structure organisationnelle facultative pour les règles de partage | +| `sys_invitation` | Invitation en attente d'acceptation | +| `sys_session` | Session authentifiée active | +| `sys_api_key` | Identifiant programmatique de longue durée lié à un utilisateur | + +Dans un déploiement multi-locataire : + +- Les utilisateurs sont délimités à la base de données du projet. +- Les sessions sont délimitées au nom d'hôte du projet. +- Les vérifications au niveau des lignes utilisent l'organisation et les + autorisations de l'utilisateur courant. +- Les utilisateurs du plan de contrôle ne sont **pas** automatiquement + des utilisateurs métier — ils doivent être mappés via le SSO de la + plateforme ou un provisionnement explicite. + +Vous créez/gérez ces éléments depuis la **Console** (`/_console/`) à +l'exécution, ou vous les initialisez dans `objectstack.config.ts` pour +les nouveaux environnements. + +## Couche 2 — Rôles + +Les rôles modélisent l'organigramme (CFO → Responsable financier → +Analyste). Ils existent principalement pour que les règles de partage et +les rapports puissent exprimer des choses comme « le responsable du +propriétaire de l'enregistrement ». Utilisez les rôles lorsque vous avez +besoin d'un accès hiérarchique ; ignorez-les pour les équipes à +structure plate. + +Voir [Rôles](/docs/configure/permissions/roles). + +## Couche 3 — Ensembles d'autorisations + +Les ensembles d'autorisations constituent le principal moyen d'accorder +des capacités. Ils s'attachent aux utilisateurs directement ou via les +rôles. + +### Ce qu'ils accordent + +| Type | Exemples | +|---|---| +| Accès aux applications | Ouvrir le CRM, ouvrir le portail de support | +| Permissions sur les objets | Créer / lire / mettre à jour / supprimer les enregistrements d'un objet | +| Permissions sur les champs | Lire ou mettre à jour des champs spécifiques | +| Permissions système | Accéder à la Console, exécuter des rapports, exporter des données, consulter le journal d'audit | +| Permissions d'intégration | Utiliser des clés API, configurer des webhooks, exécuter des actions d'administration | + +### Indicateurs de permission sur les objets + +Voici les noms exacts des indicateurs vérifiés par le plugin de +sécurité : + +| Indicateur | Signification | +|---|---| +| `allowRead` | Lire les enregistrements que l'utilisateur peut voir via l'accès aux enregistrements | +| `allowCreate` | Créer de nouveaux enregistrements | +| `allowEdit` | Mettre à jour les enregistrements que l'utilisateur peut voir | +| `allowDelete` | Supprimer les enregistrements que l'utilisateur peut voir | +| `viewAllRecords` | Lire **chaque** enregistrement de l'objet, en ignorant les règles d'accès aux enregistrements | +| `modifyAllRecords` | Mettre à jour/supprimer **chaque** enregistrement ; implique `viewAllRecords` | + +`viewAllRecords` et `modifyAllRecords` sont des privilèges de +super-utilisateur à l'échelle du locataire pour cet objet. Réservez-les à +des ensembles d'autorisations administratifs explicites et tenez-les à +l'écart de tout rôle destiné aux utilisateurs. + +Voir [Ensembles d'autorisations](/docs/configure/permissions/permission-sets). + +## Couche 4 — Accès aux enregistrements + +Pour les utilisateurs **sans** `viewAllRecords`, quelles lignes +peuvent-ils voir ? + +Le modèle prend en charge : + +- La propriété implicite (les lignes que l'utilisateur a créées ou + possède) +- Les règles de partage (déclaratives — « l'équipe A voit les + enregistrements de l'équipe A ») +- Les partages explicites (lignes `sys_record_share` — partages + ponctuels) +- La délimitation par organisation (l'`organization_id` de la ligne + correspond à l'organisation de l'utilisateur) + +Voir [Accès aux enregistrements](/docs/configure/permissions/record-access). + +## Couche 5 — Sécurité des champs + +Même lorsqu'un utilisateur peut voir un enregistrement, des champs +individuels peuvent être : + +- **Masqués** — le champ est retiré des réponses de l'API et de + l'interface. +- **En lecture seule** — le champ est renvoyé mais rejeté en écriture. + +La sécurité des champs s'applique par objet + par ensemble +d'autorisations. Usage typique : + +- Masquer `salary` sur `sys_user` pour toute personne en dehors des RH. +- Rendre `external_account_id` lisible mais non modifiable pour les + commerciaux du support. + +Elle est appliquée par le même évaluateur que les permissions sur les +objets, de sorte qu'elle s'applique uniformément à REST, ObjectQL et la +Console. + +## Par où commencer + +| Si vous construisez … | Utilisez | +|---|---| +| Un outil interne pour une seule équipe | Uniquement des ensembles d'autorisations | +| Une application multi-équipes où les responsables consultent des rapports | Rôles + ensembles d'autorisations | +| Une application de type SaaS multi-locataire | Délimitation par organisation + ensembles d'autorisations | +| Une application réglementée avec des données personnelles (PII) | Ajouter la sécurité des champs par-dessus | +| Une application complexe de type CRM | L'ensemble complet de la pile | + +## Diagnostiquer et auditer + +- `/_console/` affiche les permissions effectives de tout utilisateur + telles qu'elles sont évaluées. +- Le journal d'audit (`sys_audit_log`) enregistre les modifications + sensibles aux permissions — octrois, attributions de rôles, modifications + d'ensembles d'autorisations. +- Les requêtes refusées consignent la règle qui a échoué (permission sur + l'objet, accès à l'enregistrement ou sécurité des champs), afin que le + support puisse répondre rapidement à la question « pourquoi ne puis-je + pas voir ceci ? ». diff --git a/content/docs/configure/permissions/index.ja.mdx b/content/docs/configure/permissions/index.ja.mdx new file mode 100644 index 0000000..5b39922 --- /dev/null +++ b/content/docs/configure/permissions/index.ja.mdx @@ -0,0 +1,129 @@ +--- +title: 権限 +description: アイデンティティ、ロール、権限セット、レコードアクセス、フィールドセキュリティ — アクセスモデル全体を1ページにまとめて解説します。 +--- + +# 権限 + +ObjectOS は、エンタープライズソフトウェアで20年間にわたり実績を重ねてきた手法を取り入れた、階層型のアクセスモデルを備えています。アイデンティティ → ロール → 権限セット → レコードアクセス → フィールドセキュリティという構成です。各レイヤーはそれぞれ異なる問いに答えるものであり、必要のないレイヤーは無視して構いません。 + +## モデルを1つの図で + +```text +Authentication Who is the caller? + ↓ +Identity Which user/org/membership is active? + ↓ +Roles Where do they sit in the hierarchy? + ↓ +Permission sets What CAN they do — apps, objects, fields, system? + ↓ +Record access WHICH records can they touch? + ↓ +Field security For those records, which FIELDS are readable / writable? +``` + +各レイヤーは security プラグインによって適用されます。シンプルなアプリでは権限セットだけ(ロールやシェアルールなし)を使い、必要が生じた時点で残りを追加できます。 + +## レイヤー 1 — アイデンティティ + +アイデンティティオブジェクトは、プロジェクトのデータベースに存在します。最も重要なものは次のとおりです。 + +| オブジェクト | 表すもの | +|---|---| +| `sys_user` | 認証可能な個人またはサービスアカウント | +| `sys_organization` | テナント / ワークスペースの境界(マルチテナントアプリ向け) | +| `sys_member` | 組織におけるユーザーのメンバーシップ(ロールはメンバーシップごとに割り当てられる) | +| `sys_department`、`sys_team` | シェアルール向けの任意の組織構造 | +| `sys_invitation` | 承諾待ちの保留中の招待 | +| `sys_session` | アクティブな認証済みセッション | +| `sys_api_key` | ユーザーに紐づく長期間有効なプログラム用の認証情報 | + +マルチテナントのデプロイメントでは次のようになります。 + +- ユーザーはプロジェクトのデータベースにスコープされます。 +- セッションはプロジェクトのホスト名にスコープされます。 +- 行レベルのチェックには、現在のユーザーの組織と権限が使用されます。 +- コントロールプレーンのユーザーは自動的にビジネスユーザーには**なりません**。プラットフォームの SSO 経由でマッピングするか、明示的にプロビジョニングする必要があります。 + +これらは実行時に **Console**(`/_console/`)から作成・管理するか、新しい環境向けに `objectstack.config.ts` でシードします。 + +## レイヤー 2 — ロール + +ロールは組織図(CFO → 財務マネージャー → アナリスト)をモデル化します。これらが存在する主な目的は、シェアルールやレポートで「レコード所有者のマネージャー」といった表現を可能にすることです。階層的なアクセスが必要な場合はロールを使い、フラットなチームでは省略してください。 + +[ロール](/docs/configure/permissions/roles)を参照してください。 + +## レイヤー 3 — 権限セット + +権限セットは、機能を付与するための主要な手段です。ユーザーに直接、またはロール経由でアタッチされます。 + +### 付与する内容 + +| 種類 | 例 | +|---|---| +| アプリケーションアクセス | CRM を開く、サポートポータルを開く | +| オブジェクト権限 | オブジェクトのレコードの作成 / 読み取り / 更新 / 削除 | +| フィールド権限 | 特定のフィールドの読み取りまたは更新 | +| システム権限 | Console へのアクセス、レポートの実行、データのエクスポート、監査ログの閲覧 | +| 連携権限 | API キーの使用、Webhook の設定、管理アクションの実行 | + +### オブジェクト権限フラグ + +これらは security プラグインがチェックする正確なフラグ名です。 + +| フラグ | 意味 | +|---|---| +| `allowRead` | レコードアクセスを通じてユーザーが閲覧できるレコードを読み取る | +| `allowCreate` | 新しいレコードを作成する | +| `allowEdit` | ユーザーが閲覧できるレコードを更新する | +| `allowDelete` | ユーザーが閲覧できるレコードを削除する | +| `viewAllRecords` | レコードアクセスルールを無視して、そのオブジェクトの**すべて**のレコードを読み取る | +| `modifyAllRecords` | **すべて**のレコードを更新 / 削除する。`viewAllRecords` を含意する | + +`viewAllRecords` と `modifyAllRecords` は、そのオブジェクトに対するテナント全体のスーパーユーザー権限です。明示的な管理用の権限セットに限定し、ユーザー向けのロールには含めないでください。 + +[権限セット](/docs/configure/permissions/permission-sets)を参照してください。 + +## レイヤー 4 — レコードアクセス + +`viewAllRecords` を**持たない**ユーザーが閲覧できる行はどれでしょうか。 + +このモデルは次をサポートします。 + +- 暗黙的な所有権(ユーザーが作成または所有する行) +- シェアルール(宣言的 — 「チーム A はチーム A のレコードを閲覧できる」) +- 明示的な共有(`sys_record_share` の行 — 個別の共有) +- 組織スコープ(行の `organization_id` がユーザーの組織に一致する) + +[レコードアクセス](/docs/configure/permissions/record-access)を参照してください。 + +## レイヤー 5 — フィールドセキュリティ + +ユーザーがレコードを閲覧できる場合でも、個々のフィールドは次のように設定できます。 + +- **非表示** — フィールドは API および UI のレスポンスから除外されます。 +- **読み取り専用** — フィールドは返されますが、書き込みは拒否されます。 + +フィールドセキュリティは、オブジェクトごと + 権限セットごとに設定します。代表的な用途は次のとおりです。 + +- HR 以外のユーザーから `sys_user` の `salary` を非表示にする。 +- サポート担当者に対して `external_account_id` を読み取り可能だが編集不可にする。 + +これはオブジェクト権限と同じエバリュエーターで適用されるため、REST、ObjectQL、Console 全体に一貫して適用されます。 + +## どこから始めるか + +| 構築しているのが … | 使うもの | +|---|---| +| 単一チームの社内ツール | 権限セットのみ | +| マネージャーがレポートを閲覧するマルチチームアプリ | ロール + 権限セット | +| マルチテナントの SaaS 型アプリ | 組織スコープ + 権限セット | +| PII を扱う規制対象アプリ | 上記にフィールドセキュリティを追加 | +| 複雑な CRM 型アプリ | フルスタック | + +## 診断と監査 + +- `/_console/` は、任意のユーザーの実効権限を評価された状態で表示します。 +- 監査ログ(`sys_audit_log`)は、権限に関わる変更 — 付与、ロールの割り当て、権限セットの編集 — を記録します。 +- 拒否されたリクエストは、失敗したルール(オブジェクト権限 / レコードアクセス / フィールドセキュリティ)をログに残すため、サポートは「なぜこれが見えないのか」という問い合わせに迅速に答えられます。 diff --git a/content/docs/configure/permissions/index.mdx b/content/docs/configure/permissions/index.mdx index 78d5087..3e4163a 100644 --- a/content/docs/configure/permissions/index.mdx +++ b/content/docs/configure/permissions/index.mdx @@ -37,7 +37,7 @@ Identity objects live in your project database. The most important ones: | Object | What it represents | |---|---| | `sys_user` | A person or service account that can authenticate | -| `sys_org` | Tenant / workspace boundary (multi-tenant apps) | +| `sys_organization` | Tenant / workspace boundary (multi-tenant apps) | | `sys_member` | A user's membership in an organization (role assigned per membership) | | `sys_department`, `sys_team` | Optional org structure for sharing rules | | `sys_invitation` | Pending invite waiting to be accepted | @@ -107,7 +107,7 @@ The model supports: - Implicit ownership (rows the user created or owns) - Sharing rules (declarative — "team A sees team A's records") - Explicit shares (`sys_record_share` rows — one-off shares) -- Organization scoping (the row's `org_id` matches the user's +- Organization scoping (the row's `organization_id` matches the user's organization) See [Record Access](/docs/configure/permissions/record-access). diff --git a/content/docs/configure/permissions/index.cn.mdx b/content/docs/configure/permissions/index.zh-Hans.mdx similarity index 100% rename from content/docs/configure/permissions/index.cn.mdx rename to content/docs/configure/permissions/index.zh-Hans.mdx diff --git a/content/docs/configure/permissions/meta.de.json b/content/docs/configure/permissions/meta.de.json new file mode 100644 index 0000000..2dfb8cb --- /dev/null +++ b/content/docs/configure/permissions/meta.de.json @@ -0,0 +1,9 @@ +{ + "title": "Berechtigungen", + "pages": [ + "index", + "roles", + "permission-sets", + "record-access" + ] +} diff --git a/content/docs/configure/permissions/meta.es.json b/content/docs/configure/permissions/meta.es.json new file mode 100644 index 0000000..de91f14 --- /dev/null +++ b/content/docs/configure/permissions/meta.es.json @@ -0,0 +1,9 @@ +{ + "title": "Permisos", + "pages": [ + "index", + "roles", + "permission-sets", + "record-access" + ] +} diff --git a/content/docs/configure/permissions/meta.fr.json b/content/docs/configure/permissions/meta.fr.json new file mode 100644 index 0000000..0c9223c --- /dev/null +++ b/content/docs/configure/permissions/meta.fr.json @@ -0,0 +1,9 @@ +{ + "title": "Permissions", + "pages": [ + "index", + "roles", + "permission-sets", + "record-access" + ] +} diff --git a/content/docs/configure/permissions/meta.ja.json b/content/docs/configure/permissions/meta.ja.json new file mode 100644 index 0000000..689ed95 --- /dev/null +++ b/content/docs/configure/permissions/meta.ja.json @@ -0,0 +1,9 @@ +{ + "title": "権限", + "pages": [ + "index", + "roles", + "permission-sets", + "record-access" + ] +} diff --git a/content/docs/configure/permissions/meta.cn.json b/content/docs/configure/permissions/meta.zh-Hans.json similarity index 100% rename from content/docs/configure/permissions/meta.cn.json rename to content/docs/configure/permissions/meta.zh-Hans.json diff --git a/content/docs/configure/permissions/permission-sets.de.mdx b/content/docs/configure/permissions/permission-sets.de.mdx new file mode 100644 index 0000000..ad6aef9 --- /dev/null +++ b/content/docs/configure/permissions/permission-sets.de.mdx @@ -0,0 +1,112 @@ +--- +title: Berechtigungssätze +description: Anwendungs-, Objekt-, Feld- und Systemberechtigungen erteilen. +--- + +# Berechtigungssätze + +Berechtigungssätze sind die wichtigste Möglichkeit, um Funktionen zu erteilen. Sie können +Benutzern direkt oder indirekt über [Rollen](/docs/configure/permissions/roles) zugewiesen werden. + +## Was Berechtigungssätze steuern + +| Berechtigungstyp | Beispiele | +|---|---| +| Anwendungszugriff | Benutzer kann CRM oder Console öffnen | +| Objektberechtigungen | Datensätze erstellen, lesen, aktualisieren, löschen | +| Feldberechtigungen | Ausgewählte Felder lesen oder aktualisieren | +| Systemberechtigungen | Auf Console zugreifen, Berichte ausführen, Daten exportieren | +| Integrationsberechtigungen | API-Schlüssel, Webhooks oder Admin-Aktionen verwenden | + +## Objektberechtigungen + +Objektberechtigungen beantworten: + +```text +Can this user perform this operation on this object at all? +``` + +Berechtigungssatz-Grants verwenden diese Flag-Namen (so wie sie vom +Berechtigungs-Evaluator des Security-Plugins durchgesetzt werden): + +| Flag | Bedeutung | +|---|---| +| `allowRead` | Lesen von Datensätzen, die durch Datensatzzugriffsregeln erlaubt sind | +| `allowCreate` | Datensätze erstellen | +| `allowEdit` | Aktualisieren von Datensätzen, die durch Datensatzzugriffsregeln erlaubt sind | +| `allowDelete` | Löschen von Datensätzen, die durch Datensatzzugriffsregeln erlaubt sind | +| `viewAllRecords` | Jeden Datensatz des Objekts lesen, unter Umgehung des Datensatzzugriffs | +| `modifyAllRecords` | Jeden Datensatz des Objekts aktualisieren oder löschen, unter Umgehung des Datensatzzugriffs; impliziert `viewAllRecords` für Lesevorgänge | + +[Datensatzzugriff](/docs/configure/permissions/record-access) ist weiterhin relevant, +sofern nicht `viewAllRecords` oder `modifyAllRecords` die normale +zeilenbasierte Grenze umgeht. Reservieren Sie diese Flags für +administrative Berechtigungssätze – sie stellen praktisch einen +mandantenweiten Superuser-Grant für dieses Objekt dar. + +## Systemberechtigungen + +Systemberechtigungen sind für Plattformaktionen wie: + +- Console-Zugriff; +- Benutzer verwalten; +- Rollen und Berechtigungssätze verwalten; +- Berichte ausführen; +- Berichte exportieren; +- Integrationen verwalten; +- Audit-Protokolle anzeigen. + +Halten Sie Systemberechtigungen von Berechtigungen für Geschäftsobjekte getrennt, damit +Administratoren sie einfach prüfen können. + +## Empfohlene Sätze + +Beginnen Sie mit einigen benannten Berechtigungssätzen: + +| Berechtigungssatz | Zweck | +|---|---| +| Basic User | Anmelden und auf die Hauptanwendung zugreifen | +| Setup Administrator | Benutzer, Rollen, Einstellungen und Diagnose verwalten | +| Report Viewer | Berichte und Dashboards anzeigen | +| Integration Operator | Webhooks/API-Schlüssel verwalten | +| Support User | Support-Objekte lesen/aktualisieren | + +Fügen Sie dann domänenspezifische Sätze für die Anwendung des Kunden hinzu. + +## Feldsicherheit (Anhang) + +Berechtigungssätze enthalten auch Grants auf Feldebene. Selbst wenn ein Benutzer +einen Datensatz lesen kann, können einzelne Felder ausgeblendet oder schreibgeschützt werden. + +### Zwei Modi + +| Modus | Wirkung | +|---|---| +| **Ausgeblendet** | Feld wird vollständig aus API-Antworten und Console-Ansichten entfernt | +| **Schreibgeschützt** | Feld wird zurückgegeben, aber Schreibvorgänge werden abgelehnt | + +### Wo es durchgesetzt wird + +Derselbe Evaluator, der Objektberechtigungen prüft, wendet Feldregeln +auf jedem Pfad an – REST, ObjectQL, generierte Console-Formulare, Exporte. Es +gibt keine „Hintertür“ über eine API auf niedrigerer Ebene. + +### Typische Muster + +| Anwendungsfall | Empfehlung | +|---|---| +| HR-Daten in `sys_user` (Gehalt, SSN) | Für alle ausblenden, außer für einen `HR`-Berechtigungssatz | +| Kennungen externer Systeme | Schreibgeschützt für Support, beschreibbar für Integrationsoperatoren | +| Interne Kosten vs. Kundenpreis in `product` | `cost` für den Vertrieb ausblenden, für die Finanzabteilung sichtbar machen | +| Notizfeld mit PHI | Ausblenden, sofern der Berechtigungssatz nicht die entsprechende klinische Rolle umfasst | + +### Hinweise zur Erstellung + +- Wählen Sie standardmäßig **Ausblenden** statt Schreibgeschützt, wenn das Feld + sensible Daten enthält – Schreibgeschützt gibt den Wert weiterhin in + Antworten und Protokollen preis. +- Bündeln Sie Feldregeln in Berechtigungssätzen, die einer realen Rolle entsprechen + (`HR Manager`, `Finance Read-only`), anstatt einen Satz pro + Feld zu erfinden – das erleichtert die Prüfung. +- Kombinieren Sie für Compliance-Anwendungsfälle Feldsicherheit mit der Aufbewahrung + von Audit-Protokollen, damit Sie im Nachhinein die Frage „Wer hat diese Zeile gesehen?“ beantworten können. diff --git a/content/docs/configure/permissions/permission-sets.es.mdx b/content/docs/configure/permissions/permission-sets.es.mdx new file mode 100644 index 0000000..0b9c04e --- /dev/null +++ b/content/docs/configure/permissions/permission-sets.es.mdx @@ -0,0 +1,112 @@ +--- +title: Conjuntos de permisos +description: Otorga permisos de aplicación, objeto, campo y sistema. +--- + +# Conjuntos de permisos + +Los conjuntos de permisos son la forma principal de otorgar capacidades. Pueden +asignarse directamente a los usuarios o indirectamente a través de [roles](/docs/configure/permissions/roles). + +## Qué controlan los conjuntos de permisos + +| Tipo de permiso | Ejemplos | +|---|---| +| Acceso a la aplicación | El usuario puede abrir CRM o Console | +| Permisos de objeto | Crear, leer, actualizar, eliminar registros | +| Permisos de campo | Leer o actualizar campos seleccionados | +| Permisos de sistema | Acceder a Console, ejecutar informes, exportar datos | +| Permisos de integración | Usar claves de API, webhooks o acciones de administrador | + +## Permisos de objeto + +Los permisos de objeto responden: + +```text +Can this user perform this operation on this object at all? +``` + +Las concesiones de los conjuntos de permisos usan estos nombres de marca (tal como los aplica +el evaluador de permisos del plugin de seguridad): + +| Marca | Significado | +|---|---| +| `allowRead` | Leer los registros permitidos por las reglas de acceso a registros | +| `allowCreate` | Crear registros | +| `allowEdit` | Actualizar los registros permitidos por las reglas de acceso a registros | +| `allowDelete` | Eliminar los registros permitidos por las reglas de acceso a registros | +| `viewAllRecords` | Leer todos los registros del objeto, omitiendo el acceso a registros | +| `modifyAllRecords` | Actualizar o eliminar todos los registros del objeto, omitiendo el acceso a registros; implica `viewAllRecords` para las lecturas | + +El [acceso a registros](/docs/configure/permissions/record-access) sigue siendo relevante +a menos que `viewAllRecords` o `modifyAllRecords` omitan el límite normal +a nivel de fila. Reserva esas marcas para +conjuntos de permisos administrativos: son efectivamente una concesión de superusuario +para todo el tenant sobre ese objeto. + +## Permisos de sistema + +Los permisos de sistema son para acciones de la plataforma como: + +- acceso a Console; +- gestionar usuarios; +- gestionar roles y conjuntos de permisos; +- ejecutar informes; +- exportar informes; +- gestionar integraciones; +- ver registros de auditoría. + +Mantén los permisos de sistema separados de los permisos de objetos de negocio para que +los administradores puedan auditarlos fácilmente. + +## Conjuntos recomendados + +Comienza con algunos conjuntos de permisos con nombre: + +| Conjunto de permisos | Propósito | +|---|---| +| Basic User | Iniciar sesión y acceder a la aplicación principal | +| Setup Administrator | Gestionar usuarios, roles, configuraciones y diagnósticos | +| Report Viewer | Ver informes y paneles | +| Integration Operator | Gestionar webhooks/claves de API | +| Support User | Leer/actualizar objetos de soporte | + +Luego agrega conjuntos específicos del dominio para la aplicación del cliente. + +## Seguridad de campos (apéndice) + +Los conjuntos de permisos también incluyen concesiones a nivel de campo. Incluso cuando un usuario puede +leer un registro, ciertos campos pueden ocultarse o hacerse de solo lectura. + +### Dos modos + +| Modo | Efecto | +|---|---| +| **Oculto** | El campo se elimina por completo de las respuestas de la API y de las vistas de Console | +| **Solo lectura** | El campo se devuelve, pero se rechazan las escrituras | + +### Dónde se aplica + +El mismo evaluador que verifica los permisos de objeto aplica las reglas de campo +en cada ruta: REST, ObjectQL, formularios de Console generados, exportaciones. No +existe ninguna "puerta trasera" a través de una API de nivel inferior. + +### Patrones típicos + +| Caso de uso | Recomendación | +|---|---| +| Datos de RR. HH. en `sys_user` (salario, SSN) | Ocultar para todos excepto para un conjunto de permisos `HR` | +| Identificadores de sistemas externos | Solo lectura para soporte, modificables para operadores de integración | +| Costo interno frente a precio para el cliente en `product` | Ocultar `cost` a ventas, mostrarlo a finanzas | +| Campo de notas con PHI | Ocultar a menos que el conjunto de permisos incluya el rol clínico correspondiente | + +### Guía de autoría + +- Prefiere **ocultar** en lugar de solo lectura cuando el campo contenga + datos sensibles: el modo solo lectura aún filtra el valor en las respuestas y + los registros. +- Agrupa las reglas de campo en conjuntos de permisos que correspondan a un rol real + (`HR Manager`, `Finance Read-only`) en lugar de inventar un conjunto por + campo: es más fácil de auditar. +- Para casos de uso de cumplimiento, combina la seguridad de campos con la retención + de registros de auditoría para poder responder "¿quién vio esta fila?" después del hecho. diff --git a/content/docs/configure/permissions/permission-sets.fr.mdx b/content/docs/configure/permissions/permission-sets.fr.mdx new file mode 100644 index 0000000..efbeda9 --- /dev/null +++ b/content/docs/configure/permissions/permission-sets.fr.mdx @@ -0,0 +1,112 @@ +--- +title: Ensembles d'autorisations +description: Accorder des autorisations d'application, d'objet, de champ et système. +--- + +# Ensembles d'autorisations + +Les ensembles d'autorisations constituent le principal moyen d'accorder des capacités. Ils peuvent être +attribués directement aux utilisateurs ou indirectement via des [rôles](/docs/configure/permissions/roles). + +## Ce que contrôlent les ensembles d'autorisations + +| Type d'autorisation | Exemples | +|---|---| +| Accès aux applications | L'utilisateur peut ouvrir le CRM ou Console | +| Autorisations d'objet | Créer, lire, mettre à jour, supprimer des enregistrements | +| Autorisations de champ | Lire ou mettre à jour des champs sélectionnés | +| Autorisations système | Accéder à Console, exécuter des rapports, exporter des données | +| Autorisations d'intégration | Utiliser des clés API, des webhooks ou des actions d'administration | + +## Autorisations d'objet + +Les autorisations d'objet répondent à la question : + +```text +Can this user perform this operation on this object at all? +``` + +Les attributions d'ensembles d'autorisations utilisent ces noms d'indicateurs (tels qu'appliqués par +l'évaluateur d'autorisations du plugin de sécurité) : + +| Indicateur | Signification | +|---|---| +| `allowRead` | Lire les enregistrements autorisés par les règles d'accès aux enregistrements | +| `allowCreate` | Créer des enregistrements | +| `allowEdit` | Mettre à jour les enregistrements autorisés par les règles d'accès aux enregistrements | +| `allowDelete` | Supprimer les enregistrements autorisés par les règles d'accès aux enregistrements | +| `viewAllRecords` | Lire tous les enregistrements de l'objet, en contournant l'accès aux enregistrements | +| `modifyAllRecords` | Mettre à jour ou supprimer tous les enregistrements de l'objet, en contournant l'accès aux enregistrements ; implique `viewAllRecords` pour les lectures | + +L'[accès aux enregistrements](/docs/configure/permissions/record-access) reste pertinent +sauf si `viewAllRecords` ou `modifyAllRecords` contourne la +limite normale au niveau des lignes. Réservez ces indicateurs aux +ensembles d'autorisations administratifs — ils constituent en pratique une attribution de super-utilisateur +à l'échelle du locataire pour cet objet. + +## Autorisations système + +Les autorisations système concernent les actions de plateforme telles que : + +- l'accès à Console ; +- la gestion des utilisateurs ; +- la gestion des rôles et des ensembles d'autorisations ; +- l'exécution de rapports ; +- l'exportation de rapports ; +- la gestion des intégrations ; +- la consultation des journaux d'audit. + +Séparez les autorisations système des autorisations d'objet métier afin que +les administrateurs puissent les auditer facilement. + +## Ensembles recommandés + +Commencez avec quelques ensembles d'autorisations nommés : + +| Ensemble d'autorisations | Objectif | +|---|---| +| Utilisateur de base | Se connecter et accéder à l'application principale | +| Administrateur de configuration | Gérer les utilisateurs, les rôles, les paramètres et les diagnostics | +| Lecteur de rapports | Consulter les rapports et les tableaux de bord | +| Opérateur d'intégration | Gérer les webhooks et les clés API | +| Utilisateur du support | Lire/mettre à jour les objets de support | + +Ajoutez ensuite des ensembles spécifiques au domaine pour l'application du client. + +## Sécurité des champs (annexe) + +Les ensembles d'autorisations portent également des attributions au niveau des champs. Même lorsqu'un utilisateur peut +lire un enregistrement, des champs individuels peuvent être masqués ou rendus en lecture seule. + +### Deux modes + +| Mode | Effet | +|---|---| +| **Masqué** | Le champ est entièrement supprimé des réponses de l'API et des vues de Console | +| **Lecture seule** | Le champ est renvoyé mais les écritures sont rejetées | + +### Où il est appliqué + +Le même évaluateur qui vérifie les autorisations d'objet applique les règles de champ +sur chaque chemin — REST, ObjectQL, formulaires Console générés, exportations. Il +n'existe aucune « porte dérobée » via une API de plus bas niveau. + +### Schémas typiques + +| Cas d'usage | Recommandation | +|---|---| +| Données RH sur `sys_user` (salaire, numéro de sécurité sociale) | Masquer pour tout le monde sauf un ensemble d'autorisations `HR` | +| Identifiants de systèmes externes | Lecture seule pour le support, modifiable pour les opérateurs d'intégration | +| Coût interne vs. prix client sur `product` | Masquer `cost` aux commerciaux, le rendre visible aux équipes financières | +| Champ de notes contenant des RPS | Masquer sauf si l'ensemble d'autorisations inclut le rôle clinique pertinent | + +### Conseils de rédaction + +- Privilégiez par défaut le **masquage** plutôt que la lecture seule lorsque le champ contient + des données sensibles — la lecture seule laisse tout de même fuiter la valeur dans les réponses et + les journaux. +- Regroupez les règles de champ dans des ensembles d'autorisations qui correspondent à un rôle réel + (`HR Manager`, `Finance Read-only`) au lieu d'inventer un ensemble par + champ — c'est plus facile à auditer. +- Pour les cas d'usage de conformité, associez la sécurité des champs à la + rétention des journaux d'audit afin de pouvoir répondre après coup à la question « qui a vu cette ligne ? ». diff --git a/content/docs/configure/permissions/permission-sets.ja.mdx b/content/docs/configure/permissions/permission-sets.ja.mdx new file mode 100644 index 0000000..23271be --- /dev/null +++ b/content/docs/configure/permissions/permission-sets.ja.mdx @@ -0,0 +1,97 @@ +--- +title: 権限セット +description: アプリケーション、オブジェクト、フィールド、システムの権限を付与します。 +--- + +# 権限セット + +権限セットは、機能を付与するための主要な方法です。ユーザーに直接割り当てることも、[ロール](/docs/configure/permissions/roles)を介して間接的に割り当てることもできます。 + +## 権限セットが制御するもの + +| 権限タイプ | 例 | +|---|---| +| アプリケーションアクセス | ユーザーが CRM または Console を開ける | +| オブジェクト権限 | レコードの作成、読み取り、更新、削除 | +| フィールド権限 | 選択したフィールドの読み取りまたは更新 | +| システム権限 | Console へのアクセス、レポートの実行、データのエクスポート | +| 統合権限 | API キー、Webhook、または管理操作の使用 | + +## オブジェクト権限 + +オブジェクト権限は次の問いに答えます。 + +```text +Can this user perform this operation on this object at all? +``` + +権限セットの付与では、次のフラグ名を使用します(セキュリティプラグインの権限評価エンジンによって適用されます)。 + +| フラグ | 意味 | +|---|---| +| `allowRead` | レコードアクセスルールで許可されたレコードを読み取る | +| `allowCreate` | レコードを作成する | +| `allowEdit` | レコードアクセスルールで許可されたレコードを更新する | +| `allowDelete` | レコードアクセスルールで許可されたレコードを削除する | +| `viewAllRecords` | レコードアクセスをバイパスして、オブジェクトのすべてのレコードを読み取る | +| `modifyAllRecords` | レコードアクセスをバイパスして、オブジェクトのすべてのレコードを更新または削除する。読み取りに対しては `viewAllRecords` を含む | + +`viewAllRecords` または `modifyAllRecords` が通常の行レベルの境界をバイパスしない限り、[レコードアクセス](/docs/configure/permissions/record-access)は依然として重要です。これらのフラグは管理用の権限セットに限定してください。これらは、そのオブジェクトに対するテナント全体のスーパーユーザー付与に相当します。 + +## システム権限 + +システム権限は、次のようなプラットフォーム操作のためのものです。 + +- Console アクセス。 +- ユーザーの管理。 +- ロールおよび権限セットの管理。 +- レポートの実行。 +- レポートのエクスポート。 +- 統合の管理。 +- 監査ログの表示。 + +管理者が容易に監査できるよう、システム権限はビジネスオブジェクトの権限とは分けておきましょう。 + +## 推奨セット + +まず、いくつかの名前付き権限セットから始めましょう。 + +| 権限セット | 目的 | +|---|---| +| Basic User | ログインしてメインアプリケーションにアクセスする | +| Setup Administrator | ユーザー、ロール、設定、診断を管理する | +| Report Viewer | レポートとダッシュボードを表示する | +| Integration Operator | Webhook / API キーを管理する | +| Support User | サポートオブジェクトの読み取り/更新 | + +その後、顧客のアプリケーション向けにドメイン固有のセットを追加します。 + +## フィールドセキュリティ(付録) + +権限セットには、フィールドレベルの付与も含まれます。ユーザーがレコードを読み取れる場合でも、個々のフィールドを非表示にしたり読み取り専用にしたりできます。 + +### 2 つのモード + +| モード | 効果 | +|---|---| +| **非表示** | フィールドは API レスポンスや Console ビューから完全に除外される | +| **読み取り専用** | フィールドは返されるが、書き込みは拒否される | + +### 適用される場所 + +オブジェクト権限をチェックするのと同じ評価エンジンが、すべての経路(REST、ObjectQL、生成された Console フォーム、エクスポート)でフィールドルールを適用します。低レベルの API を経由した「裏口」は存在しません。 + +### 一般的なパターン + +| ユースケース | 推奨事項 | +|---|---| +| `sys_user` 上の HR データ(給与、SSN) | `HR` 権限セットを除くすべての人に対して非表示にする | +| 外部システムの識別子 | サポートには読み取り専用、統合オペレーターには書き込み可能にする | +| `product` 上の社内コストと顧客価格 | `cost` を営業には非表示にし、財務には表示する | +| PHI を含むメモフィールド | 権限セットに該当する臨床ロールが含まれない限り非表示にする | + +### 作成時のガイダンス + +- フィールドが機微なデータを保持する場合は、読み取り専用ではなく**非表示**をデフォルトにしてください。読み取り専用でも、値がレスポンスやログに漏れてしまいます。 +- フィールドごとに 1 つのセットを作成するのではなく、実際のロール(`HR Manager`、`Finance Read-only`)に合致する権限セットにフィールドルールをまとめてください。監査が容易になります。 +- コンプライアンスのユースケースでは、フィールドセキュリティと監査ログの保持を組み合わせることで、事後に「誰がこの行を見たか」という問いに答えられるようにしてください。 diff --git a/content/docs/configure/permissions/permission-sets.mdx b/content/docs/configure/permissions/permission-sets.mdx index 7173bdb..0d1c631 100644 --- a/content/docs/configure/permissions/permission-sets.mdx +++ b/content/docs/configure/permissions/permission-sets.mdx @@ -6,7 +6,7 @@ description: Grant application, object, field, and system permissions. # Permission Sets Permission sets are the primary way to grant capabilities. They can be -assigned directly to users or indirectly through roles. +assigned directly to users or indirectly through [roles](/docs/configure/permissions/roles). ## What permission sets control @@ -38,8 +38,9 @@ plugin's permission evaluator): | `viewAllRecords` | Read every record for the object, bypassing record access | | `modifyAllRecords` | Update or delete every record for the object, bypassing record access; implies `viewAllRecords` for reads | -Record access still matters unless `viewAllRecords` or `modifyAllRecords` -bypasses the normal row-level boundary. Reserve those flags for +[Record access](/docs/configure/permissions/record-access) still matters +unless `viewAllRecords` or `modifyAllRecords` bypasses the normal +row-level boundary. Reserve those flags for administrative permission sets — they are effectively a tenant-wide super-user grant for that object. diff --git a/content/docs/configure/permissions/permission-sets.cn.mdx b/content/docs/configure/permissions/permission-sets.zh-Hans.mdx similarity index 100% rename from content/docs/configure/permissions/permission-sets.cn.mdx rename to content/docs/configure/permissions/permission-sets.zh-Hans.mdx diff --git a/content/docs/configure/permissions/record-access.de.mdx b/content/docs/configure/permissions/record-access.de.mdx new file mode 100644 index 0000000..ca5323f --- /dev/null +++ b/content/docs/configure/permissions/record-access.de.mdx @@ -0,0 +1,62 @@ +--- +title: Datensatzzugriff +description: Steuern Sie, welche Datensätze ein Benutzer sehen oder ändern kann. +--- + +# Datensatzzugriff + +Der Datensatzzugriff steuert, welche Zeilen ein Benutzer sehen oder ändern +kann, nachdem die Objektberechtigungen den Vorgang erlaubt haben. + +## Mechanismen + +| Mechanismus | Zweck | +|---|---| +| Sicherheit auf Zeilenebene | Mandanten- oder Organisationsisolation durchsetzen | +| Freigaberegeln | Zugriff anhand deklarativer Kriterien gewähren | +| Datensatzfreigaben | Zugriff für einen bestimmten Benutzer, eine Rolle oder eine Gruppe gewähren | +| Eigentümer/Hierarchie | Zugriff über Eigentümer- oder Vorgesetztenstruktur gewähren | + +## Standardmäßige Mandantenisolation + +Das Sicherheits-Plugin setzt die Mandantenisolation über den Kontext des +aktuellen Benutzers durch. Für Standard-Plattformobjekte schützen +Standardregeln globale Tabellen, die das normale Organisationsfeld nicht +enthalten. + +Die praktische Erwartung des Kunden lautet: + +```text +Users only see records that belong to their organization or records +explicitly shared with them. +``` + +## Freigaberegeln + +Verwenden Sie Freigaberegeln für wiederkehrende Geschäftsrichtlinien: + +- alle Regionalmanager können Accounts in ihrer Region lesen; +- Support-Manager können eskalierte Fälle sehen; +- die Finanzabteilung kann genehmigte Rechnungen lesen; +- Auditoren können Datensätze lesen, die zur Prüfung markiert sind. + +## Datensatzfreigaben + +Verwenden Sie Datensatzfreigaben für Ausnahmen: + +- eine Opportunity mit einem Spezialisten teilen; +- temporären Zugriff während einer Eskalation gewähren; +- einer externen Integration Zugriff auf einen bestimmten Datensatz geben. + +## Fehlerbehebung bei der Sichtbarkeit + +Wenn ein Benutzer einen Datensatz nicht sehen kann, prüfen Sie in dieser +Reihenfolge: + +1. Ist der Benutzer authentifiziert und in der erwarteten Organisation? +2. Verfügt der Benutzer über die Objektberechtigung `read`? +3. Erlaubt die Sicherheit auf Zeilenebene den Datensatz? +4. Gibt es eine Freigaberegel, die gelten sollte? +5. Gibt es eine direkte Datensatzfreigabe? +6. Gehört der Datensatz einem Benutzer oder einer Rolle in der erwarteten Hierarchie? +7. Betrachtet der Benutzer das korrekte Projekt bzw. den korrekten Hostnamen? diff --git a/content/docs/configure/permissions/record-access.es.mdx b/content/docs/configure/permissions/record-access.es.mdx new file mode 100644 index 0000000..a52fc9e --- /dev/null +++ b/content/docs/configure/permissions/record-access.es.mdx @@ -0,0 +1,61 @@ +--- +title: Acceso a registros +description: Controla qué registros puede ver o modificar un usuario. +--- + +# Acceso a registros + +El acceso a registros controla qué filas puede ver o modificar un usuario una vez +que los permisos de objeto permiten la operación. + +## Mecanismos + +| Mecanismo | Propósito | +|---|---| +| Seguridad a nivel de fila | Aplicar el aislamiento por inquilino u organización | +| Reglas de uso compartido | Conceder acceso según criterios declarativos | +| Comparticiones de registros | Conceder acceso a un usuario, rol o grupo específico | +| Propiedad/jerarquía | Conceder acceso a través de la estructura de propietario o responsable | + +## Aislamiento por inquilino predeterminado + +El complemento de seguridad aplica el aislamiento por inquilino a través del +contexto del usuario actual. Para los objetos estándar de la plataforma, las +reglas predeterminadas protegen las tablas globales que no contienen el campo de +organización habitual. + +La expectativa práctica del cliente es: + +```text +Users only see records that belong to their organization or records +explicitly shared with them. +``` + +## Reglas de uso compartido + +Usa las reglas de uso compartido para políticas de negocio repetibles: + +- todos los responsables regionales pueden leer las cuentas de su región; +- los responsables de soporte pueden ver los casos escalados; +- finanzas puede leer las facturas aprobadas; +- los auditores pueden leer los registros marcados para revisión de auditoría. + +## Comparticiones de registros + +Usa las comparticiones de registros para excepciones: + +- compartir una oportunidad con un especialista; +- conceder acceso temporal durante una escalación; +- dar acceso a una integración externa a un registro específico. + +## Resolución de problemas de visibilidad + +Cuando un usuario no puede ver un registro, comprueba en este orden: + +1. ¿El usuario está autenticado y en la organización esperada? +2. ¿El usuario tiene permiso de `read` sobre el objeto? +3. ¿La seguridad a nivel de fila permite el registro? +4. ¿Hay una regla de uso compartido que debería aplicarse? +5. ¿Hay una compartición directa del registro? +6. ¿El registro pertenece a un usuario o rol dentro de la jerarquía esperada? +7. ¿El usuario está viendo el proyecto/nombre de host correcto? diff --git a/content/docs/configure/permissions/record-access.fr.mdx b/content/docs/configure/permissions/record-access.fr.mdx new file mode 100644 index 0000000..4e5c3f4 --- /dev/null +++ b/content/docs/configure/permissions/record-access.fr.mdx @@ -0,0 +1,61 @@ +--- +title: Accès aux enregistrements +description: Contrôlez quels enregistrements un utilisateur peut voir ou modifier. +--- + +# Accès aux enregistrements + +L'accès aux enregistrements contrôle quelles lignes un utilisateur peut voir ou +modifier une fois que les permissions d'objet autorisent l'opération. + +## Mécanismes + +| Mécanisme | Objectif | +|---|---| +| Sécurité au niveau des lignes | Imposer l'isolation par locataire ou organisation | +| Règles de partage | Accorder l'accès selon des critères déclaratifs | +| Partages d'enregistrement | Accorder l'accès à un utilisateur, un rôle ou un groupe spécifique | +| Propriété/hiérarchie | Accorder l'accès via la structure du propriétaire ou du responsable | + +## Isolation par locataire par défaut + +Le plugin de sécurité impose l'isolation par locataire à travers le contexte de +l'utilisateur actuel. Pour les objets standard de la plateforme, des règles par +défaut protègent les tables globales qui ne comportent pas le champ +d'organisation habituel. + +L'attente concrète du client est la suivante : + +```text +Users only see records that belong to their organization or records +explicitly shared with them. +``` + +## Règles de partage + +Utilisez les règles de partage pour les politiques métier récurrentes : + +- tous les responsables régionaux peuvent lire les comptes de leur région ; +- les responsables du support peuvent voir les cas escaladés ; +- la finance peut lire les factures approuvées ; +- les auditeurs peuvent lire les enregistrements marqués pour révision d'audit. + +## Partages d'enregistrement + +Utilisez les partages d'enregistrement pour les exceptions : + +- partager une opportunité avec un spécialiste ; +- accorder un accès temporaire lors d'une escalade ; +- donner à une intégration externe l'accès à un enregistrement spécifique. + +## Dépannage de la visibilité + +Lorsqu'un utilisateur ne peut pas voir un enregistrement, vérifiez dans cet ordre : + +1. L'utilisateur est-il authentifié et dans l'organisation attendue ? +2. L'utilisateur dispose-t-il de la permission `read` sur l'objet ? +3. La sécurité au niveau des lignes autorise-t-elle l'enregistrement ? +4. Existe-t-il une règle de partage qui devrait s'appliquer ? +5. Existe-t-il un partage d'enregistrement direct ? +6. L'enregistrement appartient-il à un utilisateur ou à un rôle dans la hiérarchie attendue ? +7. L'utilisateur consulte-t-il le bon projet/nom d'hôte ? diff --git a/content/docs/configure/permissions/record-access.ja.mdx b/content/docs/configure/permissions/record-access.ja.mdx new file mode 100644 index 0000000..95771a6 --- /dev/null +++ b/content/docs/configure/permissions/record-access.ja.mdx @@ -0,0 +1,57 @@ +--- +title: レコードアクセス +description: ユーザーが閲覧または変更できるレコードを制御します。 +--- + +# レコードアクセス + +レコードアクセスは、オブジェクト権限によって操作が許可された後に、ユーザーがどの行を閲覧または変更できるかを制御します。 + +## 仕組み + +| 仕組み | 目的 | +|---|---| +| 行レベルセキュリティ | テナントまたは組織の分離を強制する | +| 共有ルール | 宣言的な条件に基づいてアクセスを付与する | +| レコード共有 | 特定のユーザー、ロール、またはグループにアクセスを付与する | +| 所有権/階層 | 所有者またはマネージャー構造を通じてアクセスを付与する | + +## デフォルトのテナント分離 + +セキュリティプラグインは、現在のユーザーのコンテキストを通じてテナント分離を強制します。標準のプラットフォームオブジェクトでは、通常の組織フィールドを持たないグローバルテーブルをデフォルトルールが保護します。 + +実際の顧客の期待は次のとおりです。 + +```text +Users only see records that belong to their organization or records +explicitly shared with them. +``` + +## 共有ルール + +繰り返し適用されるビジネスポリシーには共有ルールを使用します。 + +- すべての地域マネージャーは自分の地域のアカウントを読み取ることができる。 +- サポートマネージャーはエスカレーションされたケースを閲覧できる。 +- 財務部門は承認済みの請求書を読み取ることができる。 +- 監査担当者は監査レビュー用にタグ付けされたレコードを読み取ることができる。 + +## レコード共有 + +例外的なケースにはレコード共有を使用します。 + +- 1つの商談をスペシャリストと共有する。 +- エスカレーション中に一時的なアクセスを付与する。 +- 外部連携に特定のレコードへのアクセスを与える。 + +## 表示に関するトラブルシューティング + +ユーザーがレコードを閲覧できない場合は、次の順序で確認します。 + +1. ユーザーは認証されており、想定された組織に所属していますか? +2. ユーザーはオブジェクトの `read` 権限を持っていますか? +3. 行レベルセキュリティはそのレコードを許可していますか? +4. 適用されるべき共有ルールはありますか? +5. 直接のレコード共有はありますか? +6. レコードは想定された階層内のユーザーまたはロールによって所有されていますか? +7. ユーザーは正しいプロジェクト/ホスト名を見ていますか? diff --git a/content/docs/configure/permissions/record-access.cn.mdx b/content/docs/configure/permissions/record-access.zh-Hans.mdx similarity index 100% rename from content/docs/configure/permissions/record-access.cn.mdx rename to content/docs/configure/permissions/record-access.zh-Hans.mdx diff --git a/content/docs/configure/permissions/roles.cn.mdx b/content/docs/configure/permissions/roles.cn.mdx deleted file mode 100644 index 49d6ec6..0000000 --- a/content/docs/configure/permissions/roles.cn.mdx +++ /dev/null @@ -1,59 +0,0 @@ ---- -title: 角色 -description: 用角色为层级与管理责任建模。 ---- - -# 角色 - -角色描述用户在组织中的位置。它们对层级与管理责任很有用,但不应成为授予权限的唯一方式。 - -## 角色的职责 - -把角色用于建模: - -- 上下级关系; -- 部门或团队层级; -- 基于所有权层级的记录可见性; -- 审批职责; -- 报告结构。 - -把权限集用于授予具体的对象、字段与系统能力。 - -## 系统对象 - -| 对象 | 用途 | -|---|---| -| `sys_role` | 角色定义与层级 | -| `sys_role_permission_set` | 通过角色分配的权限集 | -| `sys_member` | 用户的组织成员资格与角色上下文 | - -## 推荐模式 - -从一个小的角色层级开始: - -```text -System Administrator -Sales Director -Sales Manager -Sales Representative -Support Manager -Support Agent -``` - -然后挂接权限集以授予能力: - -```text -Sales Manager role - -> CRM User - -> Sales Manager Access - -> Report Viewer -``` - -这样可以让角色树保持稳定,同时允许权限演进。 - -## 避免 - -- 为每个用户单独建一个角色; -- 在每个角色内重复每一项权限; -- 把角色名作为业务逻辑判断; -- 在记录共享更精确的情况下,通过 manager 角色授予宽泛访问。 diff --git a/content/docs/configure/permissions/roles.de.mdx b/content/docs/configure/permissions/roles.de.mdx new file mode 100644 index 0000000..81f8b52 --- /dev/null +++ b/content/docs/configure/permissions/roles.de.mdx @@ -0,0 +1,65 @@ +--- +title: Rollen +description: Modellhierarchie und Verantwortung im Management mit Rollen. +--- + +# Rollen + +Rollen beschreiben die Position eines Benutzers in der Organisation. Sie sind +nützlich für Hierarchie und Verantwortung im Management, sollten aber nicht +zur einzigen Möglichkeit werden, Berechtigungen zu vergeben. + +## Rollenverantwortlichkeiten + +Verwenden Sie Rollen, um Folgendes zu modellieren: + +- Beziehungen zwischen Vorgesetzten und Untergebenen; +- Abteilungs- oder Teamhierarchie; +- Datensatzsichtbarkeit basierend auf der Eigentümerhierarchie; +- Genehmigungsverantwortung; +- Berichtsstruktur. + +Verwenden Sie [Berechtigungssätze](/docs/configure/permissions/permission-sets), +um konkrete Objekt-, Feld- und Systemfunktionen zu vergeben. + +## Systemobjekte + +| Objekt | Zweck | +|---|---| +| `sys_role` | Rollendefinition und Hierarchie | +| `sys_role_permission_set` | Über eine Rolle zugewiesene Berechtigungssätze | +| `sys_member` | Organisationszugehörigkeit und Rollenkontext des Benutzers | + +## Empfohlenes Muster + +Beginnen Sie mit einer kleinen Rollenhierarchie: + +```text +System Administrator +Sales Director +Sales Manager +Sales Representative +Support Manager +Support Agent +``` + +Hängen Sie dann Berechtigungssätze für Funktionen an: + +```text +Sales Manager role + -> CRM User + -> Sales Manager Access + -> Report Viewer +``` + +Dadurch bleibt der Rollenbaum stabil, während sich die Berechtigungen +weiterentwickeln können. + +## Vermeiden + +- eine Rolle pro einzelnem Benutzer; +- das Duplizieren jeder Berechtigung in jeder Rolle; +- die Verwendung von Rollennamen als Prüfungen in der Geschäftslogik; +- das Gewähren von weitreichendem Zugriff über Manager-Rollen, wenn + [Datensatzfreigabe](/docs/configure/permissions/record-access) präziser + wäre. diff --git a/content/docs/configure/permissions/roles.es.mdx b/content/docs/configure/permissions/roles.es.mdx new file mode 100644 index 0000000..2e15d95 --- /dev/null +++ b/content/docs/configure/permissions/roles.es.mdx @@ -0,0 +1,65 @@ +--- +title: Roles +description: Jerarquía del modelo y responsabilidad de gestión con roles. +--- + +# Roles + +Los roles describen la posición de un usuario en la organización. Resultan +útiles para la jerarquía y la responsabilidad de gestión, pero no deberían +convertirse en la única forma de otorgar permisos. + +## Responsabilidades de los roles + +Usa los roles para modelar: + +- relaciones entre responsable y subordinado; +- jerarquía de departamentos o equipos; +- visibilidad de registros según la jerarquía de propiedad; +- responsabilidad de aprobación; +- estructura de informes. + +Usa los [conjuntos de permisos](/docs/configure/permissions/permission-sets) +para otorgar capacidades concretas de objetos, campos y sistema. + +## Objetos del sistema + +| Objeto | Propósito | +|---|---| +| `sys_role` | Definición y jerarquía de roles | +| `sys_role_permission_set` | Conjuntos de permisos asignados a través de un rol | +| `sys_member` | Pertenencia del usuario a la organización y contexto de rol | + +## Patrón recomendado + +Comienza con una pequeña jerarquía de roles: + +```text +System Administrator +Sales Director +Sales Manager +Sales Representative +Support Manager +Support Agent +``` + +Luego adjunta conjuntos de permisos para las capacidades: + +```text +Sales Manager role + -> CRM User + -> Sales Manager Access + -> Report Viewer +``` + +Esto mantiene estable el árbol de roles mientras permite que los permisos +evolucionen. + +## Evita + +- un rol por cada usuario individual; +- duplicar cada permiso dentro de cada rol; +- usar los nombres de los roles como comprobaciones de lógica de negocio; +- otorgar acceso amplio a través de roles de responsable cuando el + [uso compartido de registros](/docs/configure/permissions/record-access) + sería más preciso. diff --git a/content/docs/configure/permissions/roles.fr.mdx b/content/docs/configure/permissions/roles.fr.mdx new file mode 100644 index 0000000..90f75e0 --- /dev/null +++ b/content/docs/configure/permissions/roles.fr.mdx @@ -0,0 +1,65 @@ +--- +title: Rôles +description: Hiérarchie du modèle et responsabilité de gestion grâce aux rôles. +--- + +# Rôles + +Les rôles décrivent la position d'un utilisateur dans l'organisation. Ils sont +utiles pour la hiérarchie et la responsabilité de gestion, mais ils ne doivent +pas devenir le seul moyen d'accorder des permissions. + +## Responsabilités des rôles + +Utilisez les rôles pour modéliser : + +- les relations responsable/subordonné ; +- la hiérarchie des départements ou des équipes ; +- la visibilité des enregistrements selon la hiérarchie de propriété ; +- la responsabilité d'approbation ; +- la structure hiérarchique de reporting. + +Utilisez les [ensembles de permissions](/docs/configure/permissions/permission-sets) +pour accorder des capacités concrètes sur les objets, les champs et le système. + +## Objets système + +| Objet | Finalité | +|---|---| +| `sys_role` | Définition et hiérarchie des rôles | +| `sys_role_permission_set` | Ensembles de permissions attribués via un rôle | +| `sys_member` | Appartenance à l'organisation et contexte de rôle de l'utilisateur | + +## Modèle recommandé + +Commencez par une petite hiérarchie de rôles : + +```text +System Administrator +Sales Director +Sales Manager +Sales Representative +Support Manager +Support Agent +``` + +Attachez ensuite des ensembles de permissions pour les capacités : + +```text +Sales Manager role + -> CRM User + -> Sales Manager Access + -> Report Viewer +``` + +Cela maintient la stabilité de l'arborescence des rôles tout en permettant aux +permissions d'évoluer. + +## À éviter + +- un rôle par utilisateur individuel ; +- la duplication de chaque permission à l'intérieur de chaque rôle ; +- l'utilisation des noms de rôles comme contrôles de logique métier ; +- l'octroi d'un accès étendu via les rôles de responsable alors que le + [partage d'enregistrements](/docs/configure/permissions/record-access) serait + plus précis. diff --git a/content/docs/configure/permissions/roles.ja.mdx b/content/docs/configure/permissions/roles.ja.mdx new file mode 100644 index 0000000..873a73e --- /dev/null +++ b/content/docs/configure/permissions/roles.ja.mdx @@ -0,0 +1,64 @@ +--- +title: ロール +description: ロールによる階層構造と管理責任のモデリング。 +--- + +# ロール + +ロールは、組織におけるユーザーの位置づけを表します。階層構造や管理責任を +モデリングするのに役立ちますが、権限を付与する唯一の手段にすべきでは +ありません。 + +## ロールの責務 + +ロールは次のようなモデリングに使用します。 + +- 上司/部下の関係。 +- 部門やチームの階層構造。 +- 所有権の階層に基づくレコードの可視性。 +- 承認責任。 +- 報告体系。 + +具体的なオブジェクト、フィールド、システム機能の権限を付与するには、 +[権限セット](/docs/configure/permissions/permission-sets)を使用してください。 + +## システムオブジェクト + +| オブジェクト | 目的 | +|---|---| +| `sys_role` | ロールの定義と階層 | +| `sys_role_permission_set` | ロールを通じて割り当てられる権限セット | +| `sys_member` | ユーザーの組織メンバーシップとロールのコンテキスト | + +## 推奨パターン + +まずは小さなロール階層から始めます。 + +```text +System Administrator +Sales Director +Sales Manager +Sales Representative +Support Manager +Support Agent +``` + +次に、機能を付与するための権限セットを割り当てます。 + +```text +Sales Manager role + -> CRM User + -> Sales Manager Access + -> Report Viewer +``` + +これにより、権限を進化させながらロールツリーを安定して保つことができます。 + +## 避けるべきこと + +- ユーザー個人ごとに1つのロールを作成すること。 +- すべての権限を各ロール内で重複して定義すること。 +- ロール名をビジネスロジックの判定に使用すること。 +- [レコード共有](/docs/configure/permissions/record-access)の方がより + 精密に制御できる場面で、マネージャーロールを通じて広範なアクセスを + 付与すること。 diff --git a/content/docs/configure/permissions/roles.mdx b/content/docs/configure/permissions/roles.mdx index 8e7d968..cf92dfb 100644 --- a/content/docs/configure/permissions/roles.mdx +++ b/content/docs/configure/permissions/roles.mdx @@ -19,8 +19,8 @@ Use roles to model: - approval responsibility; - reporting structure. -Use permission sets to grant concrete object, field, and system -capabilities. +Use [permission sets](/docs/configure/permissions/permission-sets) to grant +concrete object, field, and system capabilities. ## System objects @@ -59,5 +59,6 @@ This keeps the role tree stable while allowing permissions to evolve. - one role per individual user; - duplicating every permission inside every role; - using role names as business logic checks; -- granting broad access through manager roles when record sharing would - be more precise. +- granting broad access through manager roles when + [record sharing](/docs/configure/permissions/record-access) would be more + precise. diff --git a/content/docs/configure/permissions/roles.zh-Hans.mdx b/content/docs/configure/permissions/roles.zh-Hans.mdx new file mode 100644 index 0000000..f0f7311 --- /dev/null +++ b/content/docs/configure/permissions/roles.zh-Hans.mdx @@ -0,0 +1,59 @@ +--- +title: 角色 +description: 使用角色对层级结构和管理职责进行建模。 +--- + +# 角色 + +角色描述用户在组织中的位置。它们对于表达层级结构和管理职责很有用,但不应成为授予权限的唯一方式。 + +## 角色职责 + +使用角色来建模: + +- 上下级(经理/下属)关系; +- 部门或团队层级结构; +- 基于所有权层级的记录可见性; +- 审批职责; +- 汇报结构。 + +使用[权限集](/docs/configure/permissions/permission-sets)来授予具体的对象、字段和系统能力。 + +## 系统对象 + +| 对象 | 用途 | +|---|---| +| `sys_role` | 角色定义与层级结构 | +| `sys_role_permission_set` | 通过角色分配的权限集 | +| `sys_member` | 用户的组织成员身份与角色上下文 | + +## 推荐模式 + +从一个精简的角色层级开始: + +```text +System Administrator +Sales Director +Sales Manager +Sales Representative +Support Manager +Support Agent +``` + +然后为各项能力附加权限集: + +```text +Sales Manager role + -> CRM User + -> Sales Manager Access + -> Report Viewer +``` + +这样可以保持角色树的稳定,同时允许权限不断演进。 + +## 应避免 + +- 为每个用户单独创建一个角色; +- 在每个角色中重复定义所有权限; +- 将角色名称用作业务逻辑判断条件; +- 在[记录共享](/docs/configure/permissions/record-access)能更精确实现需求时,却通过经理角色授予宽泛的访问权限。 diff --git a/content/docs/configure/runtime.de.mdx b/content/docs/configure/runtime.de.mdx new file mode 100644 index 0000000..7fa7d8c --- /dev/null +++ b/content/docs/configure/runtime.de.mdx @@ -0,0 +1,125 @@ +--- +title: Laufzeitkonfiguration +description: Konfigurieren Sie das Laden von Artefakten, die Projektauflösung, die Datenbank, den Cache und Laufzeit-Secrets. +--- + +# Laufzeitkonfiguration + +Die ObjectOS-Laufzeitkonfiguration beantwortet drei Fragen: + +1. Welches Projekt soll diese Anfrage bedienen? +2. Wo befindet sich das kompilierte Artefakt? +3. Welche Datenbank und welche Laufzeitdienste soll das Projekt verwenden? + +## Boot-Modi + +| Modus | Verwenden, wenn | Wichtige Konfiguration | +|---|---|---| +| Standalone | `os start` ohne Konfiguration — schnelle Demo, leerer Kernel, ~23 Plugins, lokales SQLite unter `~/.objectstack/data/standalone.db` | _keine_ (Standardwerte) | +| File-backed | Einzelnes Projekt, Demo, Offline-Bundle für Kunden, Air-Gapped-Bereitstellung | `OS_ARTIFACT_FILE` | +| Cloud-connected | Eine gehostete oder private Control Plane veröffentlicht Projektartefakte | `OS_CLOUD_URL`, `OS_PROJECT_ID` oder Hostnamen-Auflösung | + +### Standalone-Modus + +Der Standard, wenn Sie `os start` ohne Konfiguration oder Artefakt ausführen. +ObjectOS startet einen leeren Kernel mit geladenen Plattform-Plugins +(`auth`, `security`, `audit`, `storage`, `webhooks`, `mcp-server`, +`marketplace-proxy`, `marketplace-install-local`, …), öffnet lokales +SQLite unter `~/.objectstack/data/standalone.db` und stellt die Console- +und Account-UIs bereit. + +Installieren Sie Apps über den marketplace-Tab in der Console, um den Kernel +mit Objekten, Ansichten und Flows zu füllen — kein Rebuild, kein Neustart. Am besten geeignet für +Demos, Evaluierung und die Erkundung im Sinne von "Zeig mir, was das Ding kann". + +`os start` eskaliert automatisch: + +| Erkannt | Verhalten | +|---|---| +| Nichts | Standalone-Modus (siehe oben) | +| `objectstack.config.ts` im cwd | Projektmodus — automatische Kompilierung, `HOME=/.objectstack` | +| Kompiliertes Artefakt im cwd | Artefaktmodus — dieses Artefakt laden | +| Explizites `--artifact ` oder `OS_CLOUD_URL` | File-backed- / Cloud-connected-Modus | + +## File-backed-Modus + +Festlegen: + +```bash +OS_ARTIFACT_FILE=/artifacts/objectstack.json +``` + +ObjectOS verwendet einen lokalen Artifact-API-Client. Jeder Hostname wird auf +dasselbe Projekt aufgelöst. Die Laufzeitkonfiguration wird aus dem Artefakt gelesen, sofern vorhanden, +oder fällt für die Evaluierung auf einen lokalen Laufzeit-Standard zurück. + +`OS_ARTIFACT_FILE` ist die Konvention des ObjectOS-App-Wrappers. Die zugrunde liegende +Laufzeit akzeptiert auch `OS_ARTIFACT_PATH` direkt (verwendet von den +Befehlen `dev` und `start` der `@objectstack/cli` und vom Standalone-Stack des +Frameworks). Legen Sie eines von beiden fest — nicht beide. + +Optional: + +```bash +OS_ENVIRONMENT_ID=env_prod # or the legacy alias OS_PROJECT_ID +OS_WATCH_ARTIFACT=1 +``` + +Verwenden Sie den Watch-Modus nur für die Entwicklung oder für Smoke-Tests. + +## Cloud-connected-Modus + +Festlegen: + +```bash +OS_CLOUD_URL=https://cloud.example.com +OS_CLOUD_API_KEY=replace-with-deployment-token +``` + +ObjectOS fordert die Control Plane auf: + +- den Hostnamen zu Projekt/Umgebung aufzulösen; +- das aktuelle Artefakt abzurufen; +- die Laufzeit-Datenbankkonfiguration für dieses Projekt zu empfangen. + +ObjectOS sollte sich nicht direkt mit der Datenbank der Control Plane verbinden. + +## Authentifizierungs-Secret + +Legen Sie ein starkes Basis-Secret fest: + +```bash +OS_AUTH_SECRET=replace-with-a-strong-random-secret +``` + +ObjectOS leitet projektspezifische Auth-Secrets aus diesem Wert ab. Das hält +die Sitzungssignierung pro Projekt isoliert und ermöglicht gleichzeitig deterministische +Neustarts. Das Rotieren dieses Werts macht bestehende Sitzungen ungültig. + +## Kernel- und Artefakt-Caches + +ObjectOS cacht aufgelöste Umgebungen und Projekt-Kernel, um zu vermeiden, +dass für jede Anfrage ein Kernel neu erstellt wird. + +| Variable | Standard | Zweck | +|---|---:|---| +| `OS_KERNEL_CACHE_SIZE` | `32` | Maximale Anzahl zwischengespeicherter Projekt-Kernel | +| `OS_KERNEL_TTL_MS` | `900000` | Leerlauf-TTL für zwischengespeicherte Kernel | +| `OS_ENV_CACHE_TTL_MS` | `300000` | Cache für Hostnamen-/Umgebungsauflösung | +| `OS_ARTIFACT_CACHE_TTL_MS` | `300000` | Cache für Artefaktantworten | + +Niedrigere TTLs machen Änderungen schneller sichtbar. Höhere TTLs reduzieren den Datenverkehr +zur Control Plane und Kaltstarts. + +## Datenbankkonfiguration + +Im Cloud-connected-Modus gibt die Control Plane die projektspezifische +Laufzeit-Datenbankkonfiguration mit der Artefaktantwort zurück. + +Im File-backed-Modus kann ObjectOS die Datenbankeinstellungen aus den +Datasource-Deklarationen des Artefakts ableiten. Zu den unterstützten Framework-Treibern gehören +SQLite, PostgreSQL, MySQL, MongoDB und speicherbasierte Evaluierungstreiber. + +Verwenden Sie für die Produktion eine kundenverwaltete Datenbank. Verlassen Sie sich für +Geschäftsdaten nicht auf containerlokalen Speicher, es sei denn, die Bereitstellung ist +ausdrücklich eine Single-Node-Evaluierung. diff --git a/content/docs/configure/runtime.es.mdx b/content/docs/configure/runtime.es.mdx new file mode 100644 index 0000000..bcb297f --- /dev/null +++ b/content/docs/configure/runtime.es.mdx @@ -0,0 +1,126 @@ +--- +title: Configuración del entorno de ejecución +description: Configura la carga de artefactos, la resolución de proyectos, la base de datos, la caché y los secretos del entorno de ejecución. +--- + +# Configuración del entorno de ejecución + +La configuración del entorno de ejecución de ObjectOS responde a tres preguntas: + +1. ¿Qué proyecto debe atender esta solicitud? +2. ¿Dónde está el artefacto compilado? +3. ¿Qué base de datos y servicios de ejecución debe usar el proyecto? + +## Modos de arranque + +| Modo | Úsalo cuando | Configuración clave | +|---|---|---| +| Standalone | `os start` sin configuración — demo rápida, kernel vacío, ~23 plugins, SQLite local en `~/.objectstack/data/standalone.db` | _ninguna_ (valores por defecto) | +| File-backed | Proyecto único, demo, paquete offline del cliente, despliegue aislado de la red | `OS_ARTIFACT_FILE` | +| Cloud-connected | Un plano de control alojado o privado publica los artefactos del proyecto | `OS_CLOUD_URL`, `OS_PROJECT_ID` o resolución por nombre de host | + +### Modo standalone + +El modo por defecto cuando ejecutas `os start` sin configuración ni artefacto. +ObjectOS arranca un kernel vacío con los plugins de plataforma cargados +(`auth`, `security`, `audit`, `storage`, `webhooks`, `mcp-server`, +`marketplace-proxy`, `marketplace-install-local`, …), abre SQLite local +en `~/.objectstack/data/standalone.db` y sirve las interfaces de Console +y Account. + +Instala apps desde la pestaña del marketplace en Console para poblar el kernel +con objetos, vistas y flujos — sin recompilar ni reiniciar. Ideal para +demos, evaluación y exploraciones del tipo "muéstrame qué hace esto". + +`os start` escala automáticamente: + +| Detectado | Comportamiento | +|---|---| +| Nada | Modo standalone (arriba) | +| `objectstack.config.ts` en el cwd | Modo proyecto — compilación automática, `HOME=/.objectstack` | +| Artefacto compilado en el cwd | Modo artefacto — carga ese artefacto | +| `--artifact ` explícito u `OS_CLOUD_URL` | Modos file-backed / cloud-connected | + +## Modo file-backed + +Configura: + +```bash +OS_ARTIFACT_FILE=/artifacts/objectstack.json +``` + +ObjectOS usa un cliente local de la Artifact API. Cada nombre de host se resuelve +al mismo proyecto. La configuración del entorno de ejecución se lee del artefacto cuando está presente, +o recurre a un valor por defecto de ejecución local para evaluación. + +`OS_ARTIFACT_FILE` es la convención del app-wrapper de ObjectOS. El entorno de +ejecución subyacente también acepta `OS_ARTIFACT_PATH` directamente (usado por los +comandos `dev` y `start` de `@objectstack/cli` y por el stack standalone del +framework). Configura uno u otro — no ambos. + +Opcional: + +```bash +OS_ENVIRONMENT_ID=env_prod # o el alias heredado OS_PROJECT_ID +OS_WATCH_ARTIFACT=1 +``` + +Usa el modo watch solo para desarrollo o pruebas de humo. + +## Modo cloud-connected + +Configura: + +```bash +OS_CLOUD_URL=https://cloud.example.com +OS_CLOUD_API_KEY=replace-with-deployment-token +``` + +ObjectOS le pide al plano de control que: + +- resuelva el nombre de host a proyecto/entorno; +- obtenga el artefacto actual; +- reciba la configuración de la base de datos de ejecución para ese proyecto. + +ObjectOS no debe conectarse directamente a la base de datos del plano de control. + +## Secreto de autenticación + +Configura un secreto base robusto: + +```bash +OS_AUTH_SECRET=replace-with-a-strong-random-secret +``` + +ObjectOS deriva secretos de autenticación por proyecto a partir de este valor. Esto mantiene +la firma de sesiones aislada por proyecto, sin dejar de permitir reinicios +deterministas. Rotar este valor invalida las sesiones existentes. + +## Cachés de kernel y artefactos + +ObjectOS almacena en caché los entornos resueltos y los kernels de proyecto para evitar +reconstruir un kernel en cada solicitud. + +| Variable | Por defecto | Propósito | +|---|---:|---| +| `OS_KERNEL_CACHE_SIZE` | `32` | Número máximo de kernels de proyecto en caché | +| `OS_KERNEL_TTL_MS` | `900000` | TTL de inactividad para los kernels en caché | +| `OS_ENV_CACHE_TTL_MS` | `300000` | Caché de resolución de nombre de host/entorno | +| `OS_ARTIFACT_CACHE_TTL_MS` | `300000` | Caché de respuestas de artefactos | + +Los TTL más bajos hacen que los cambios sean visibles más rápido. Los TTL más altos reducen el +tráfico al plano de control y los arranques en frío. + +## Configuración de la base de datos + +En el modo cloud-connected, el plano de control devuelve la configuración de la base de datos +de ejecución por proyecto junto con la respuesta del artefacto. + +En el modo file-backed, ObjectOS puede derivar la configuración de la base de datos a partir de las +declaraciones de datasource del artefacto. Los drivers del framework compatibles incluyen +SQLite, PostgreSQL, MySQL, MongoDB y drivers de evaluación respaldados por +memoria. + +Para producción, usa una base de datos gestionada por el cliente. No dependas del +almacenamiento local del contenedor para los datos de negocio, a menos que el despliegue sea +explícitamente una evaluación de un solo nodo. diff --git a/content/docs/configure/runtime.fr.mdx b/content/docs/configure/runtime.fr.mdx new file mode 100644 index 0000000..e8fea76 --- /dev/null +++ b/content/docs/configure/runtime.fr.mdx @@ -0,0 +1,125 @@ +--- +title: Configuration de l'environnement d'exécution +description: Configurez le chargement des artefacts, la résolution des projets, la base de données, le cache et les secrets d'exécution. +--- + +# Configuration de l'environnement d'exécution + +La configuration de l'environnement d'exécution d'ObjectOS répond à trois questions : + +1. Quel projet cette requête doit-elle servir ? +2. Où se trouve l'artefact compilé ? +3. Quelle base de données et quels services d'exécution le projet doit-il utiliser ? + +## Modes de démarrage + +| Mode | À utiliser quand | Configuration clé | +|---|---|---| +| Standalone | `os start` sans configuration — démo rapide, kernel vide, environ 23 plugins, SQLite local à `~/.objectstack/data/standalone.db` | _aucune_ (valeurs par défaut) | +| Adossé à un fichier | Projet unique, démo, offre hors ligne client, déploiement isolé du réseau | `OS_ARTIFACT_FILE` | +| Connecté au cloud | Un plan de contrôle hébergé ou privé publie les artefacts du projet | `OS_CLOUD_URL`, `OS_PROJECT_ID` ou résolution par nom d'hôte | + +### Mode Standalone + +Mode par défaut lorsque vous exécutez `os start` sans configuration ni artefact. +ObjectOS démarre un kernel vide avec les plugins de la plateforme chargés +(`auth`, `security`, `audit`, `storage`, `webhooks`, `mcp-server`, +`marketplace-proxy`, `marketplace-install-local`, …), ouvre une base +SQLite locale à `~/.objectstack/data/standalone.db`, et sert les interfaces +Console et Account. + +Installez des applications depuis l'onglet marketplace dans Console pour peupler le kernel +avec des objets, des vues et des flux — sans recompilation, sans redémarrage. Idéal pour +les démos, l'évaluation et l'exploration de type « montre-moi ce que fait cette chose ». + +`os start` monte automatiquement en puissance : + +| Détecté | Comportement | +|---|---| +| Rien | Mode Standalone (ci-dessus) | +| `objectstack.config.ts` dans le répertoire courant | Mode projet — compilation automatique, `HOME=/.objectstack` | +| Artefact compilé dans le répertoire courant | Mode artefact — charge cet artefact | +| `--artifact ` explicite ou `OS_CLOUD_URL` | Modes adossé à un fichier / connecté au cloud | + +## Mode adossé à un fichier + +Définissez : + +```bash +OS_ARTIFACT_FILE=/artifacts/objectstack.json +``` + +ObjectOS utilise un client local de l'API Artifact. Chaque nom d'hôte se résout vers le +même projet. La configuration d'exécution est lue depuis l'artefact lorsqu'elle est présente, +ou repli sur une valeur d'exécution locale par défaut pour l'évaluation. + +`OS_ARTIFACT_FILE` est la convention de l'enveloppe applicative d'ObjectOS. L'environnement +d'exécution sous-jacent accepte aussi directement `OS_ARTIFACT_PATH` (utilisé par les +commandes `dev` et `start` de `@objectstack/cli` ainsi que par la stack +standalone du framework). Définissez l'une ou l'autre — pas les deux. + +Optionnel : + +```bash +OS_ENVIRONMENT_ID=env_prod # or the legacy alias OS_PROJECT_ID +OS_WATCH_ARTIFACT=1 +``` + +N'utilisez le mode surveillance que pour le développement ou les tests de fumée. + +## Mode connecté au cloud + +Définissez : + +```bash +OS_CLOUD_URL=https://cloud.example.com +OS_CLOUD_API_KEY=replace-with-deployment-token +``` + +ObjectOS demande au plan de contrôle de : + +- résoudre le nom d'hôte vers un projet/environnement ; +- récupérer l'artefact courant ; +- recevoir la configuration de la base de données d'exécution pour ce projet. + +ObjectOS ne doit pas se connecter directement à la base de données du plan de contrôle. + +## Secret d'authentification + +Définissez un secret de base robuste : + +```bash +OS_AUTH_SECRET=replace-with-a-strong-random-secret +``` + +ObjectOS dérive de cette valeur les secrets d'authentification propres à chaque projet. Cela +maintient la signature des sessions isolée par projet tout en permettant des redémarrages +déterministes. Faire pivoter cette valeur invalide les sessions existantes. + +## Caches du kernel et des artefacts + +ObjectOS met en cache les environnements résolus et les kernels de projet afin d'éviter +de reconstruire un kernel à chaque requête. + +| Variable | Valeur par défaut | Objet | +|---|---:|---| +| `OS_KERNEL_CACHE_SIZE` | `32` | Nombre maximum de kernels de projet mis en cache | +| `OS_KERNEL_TTL_MS` | `900000` | TTL d'inactivité pour les kernels mis en cache | +| `OS_ENV_CACHE_TTL_MS` | `300000` | Cache de résolution nom d'hôte/environnement | +| `OS_ARTIFACT_CACHE_TTL_MS` | `300000` | Cache des réponses d'artefacts | + +Des TTL plus faibles rendent les changements visibles plus rapidement. Des TTL plus élevés réduisent le +trafic vers le plan de contrôle et les démarrages à froid. + +## Configuration de la base de données + +En mode connecté au cloud, le plan de contrôle renvoie la configuration de la base de données +d'exécution propre au projet avec la réponse d'artefact. + +En mode adossé à un fichier, ObjectOS peut dériver les paramètres de la base de données à partir des +déclarations de sources de données de l'artefact. Les pilotes du framework pris en charge incluent +SQLite, PostgreSQL, MySQL, MongoDB et des pilotes d'évaluation en mémoire. + +Pour la production, utilisez une base de données gérée par le client. Ne vous appuyez pas sur le +stockage local du conteneur pour les données métier, sauf si le déploiement est +explicitement une évaluation mononœud. diff --git a/content/docs/configure/runtime.ja.mdx b/content/docs/configure/runtime.ja.mdx new file mode 100644 index 0000000..9189ac7 --- /dev/null +++ b/content/docs/configure/runtime.ja.mdx @@ -0,0 +1,122 @@ +--- +title: ランタイム構成 +description: アーティファクトの読み込み、プロジェクトの解決、データベース、キャッシュ、ランタイムシークレットを構成します。 +--- + +# ランタイム構成 + +ObjectOS のランタイム構成は、次の 3 つの問いに答えます。 + +1. このリクエストはどのプロジェクトを処理すべきか? +2. コンパイル済みアーティファクトはどこにあるか? +3. プロジェクトはどのデータベースとランタイムサービスを使用すべきか? + +## ブートモード + +| モード | 使用する場面 | 主な構成 | +|---|---|---| +| Standalone | 設定なしの `os start` — クイックデモ、空のカーネル、約 23 個のプラグイン、`~/.objectstack/data/standalone.db` のローカル SQLite | _なし_(デフォルト) | +| File-backed | 単一プロジェクト、デモ、顧客向けオフラインバンドル、エアギャップ環境へのデプロイ | `OS_ARTIFACT_FILE` | +| Cloud-connected | ホスト型またはプライベートのコントロールプレーンがプロジェクトアーティファクトを公開 | `OS_CLOUD_URL`、`OS_PROJECT_ID` またはホスト名解決 | + +### Standalone モード + +設定やアーティファクトなしで `os start` を実行したときのデフォルトです。 +ObjectOS はプラットフォームプラグイン(`auth`、`security`、`audit`、`storage`、`webhooks`、`mcp-server`、 +`marketplace-proxy`、`marketplace-install-local` など)を読み込んだ空のカーネルをブートし、 +`~/.objectstack/data/standalone.db` のローカル SQLite を開いて、Console と Account の UI を提供します。 + +Console の marketplace タブからアプリをインストールして、オブジェクト、ビュー、フローでカーネルを +構築できます。リビルドも再起動も不要です。デモ、評価、そして「これが何をするものか見せて」という +探索に最適です。 + +`os start` は自動的にエスカレートします。 + +| 検出された内容 | 動作 | +|---|---| +| なし | Standalone モード(上記) | +| cwd に `objectstack.config.ts` | プロジェクトモード — 自動コンパイル、`HOME=/.objectstack` | +| cwd にコンパイル済みアーティファクト | アーティファクトモード — そのアーティファクトを読み込む | +| 明示的な `--artifact ` または `OS_CLOUD_URL` | File-backed / cloud-connected モード | + +## File-backed モード + +設定します。 + +```bash +OS_ARTIFACT_FILE=/artifacts/objectstack.json +``` + +ObjectOS はローカルの Artifact API クライアントを使用します。すべてのホスト名が同じプロジェクトに +解決されます。ランタイム構成はアーティファクトが存在する場合はそこから読み込まれ、存在しない場合は +評価用のローカルランタイムデフォルトにフォールバックします。 + +`OS_ARTIFACT_FILE` は ObjectOS アプリラッパーの慣例です。基盤となるランタイムは +`OS_ARTIFACT_PATH` を直接受け付けることもできます(`@objectstack/cli` の `dev` および `start` +コマンド、ならびにフレームワークの standalone スタックで使用されます)。どちらか一方を設定します — +両方ではありません。 + +オプション: + +```bash +OS_ENVIRONMENT_ID=env_prod # or the legacy alias OS_PROJECT_ID +OS_WATCH_ARTIFACT=1 +``` + +ウォッチモードは開発またはスモークテストでのみ使用してください。 + +## Cloud-connected モード + +設定します。 + +```bash +OS_CLOUD_URL=https://cloud.example.com +OS_CLOUD_API_KEY=replace-with-deployment-token +``` + +ObjectOS はコントロールプレーンに次のことを要求します。 + +- ホスト名をプロジェクト/環境に解決する。 +- 現在のアーティファクトを取得する。 +- そのプロジェクトのランタイムデータベース構成を受け取る。 + +ObjectOS はコントロールプレーンのデータベースに直接接続すべきではありません。 + +## 認証シークレット + +強力なベースシークレットを設定します。 + +```bash +OS_AUTH_SECRET=replace-with-a-strong-random-secret +``` + +ObjectOS はこの値からプロジェクトごとの認証シークレットを導出します。これにより、セッション署名が +プロジェクトごとに分離されつつ、決定論的な再起動も可能になります。この値をローテーションすると、 +既存のセッションは無効になります。 + +## カーネルとアーティファクトのキャッシュ + +ObjectOS は、リクエストごとにカーネルを再構築するのを避けるため、解決済みの環境とプロジェクト +カーネルをキャッシュします。 + +| 変数 | デフォルト | 目的 | +|---|---:|---| +| `OS_KERNEL_CACHE_SIZE` | `32` | キャッシュするプロジェクトカーネルの最大数 | +| `OS_KERNEL_TTL_MS` | `900000` | キャッシュ済みカーネルのアイドル TTL | +| `OS_ENV_CACHE_TTL_MS` | `300000` | ホスト名/環境の解決キャッシュ | +| `OS_ARTIFACT_CACHE_TTL_MS` | `300000` | アーティファクトレスポンスのキャッシュ | + +TTL を低くすると変更がより速く反映されます。TTL を高くするとコントロールプレーンへのトラフィックと +コールドスタートが減少します。 + +## データベース構成 + +cloud-connected モードでは、コントロールプレーンがアーティファクトレスポンスとともにプロジェクト +ごとのランタイムデータベース構成を返します。 + +file-backed モードでは、ObjectOS はアーティファクトのデータソース宣言からデータベース設定を導出 +できます。サポートされるフレームワークドライバには、SQLite、PostgreSQL、MySQL、MongoDB、および +メモリベースの評価用ドライバが含まれます。 + +本番環境では、顧客が管理するデータベースを使用してください。デプロイが明示的に単一ノードの評価用で +ない限り、業務データをコンテナローカルのストレージに依存させないでください。 diff --git a/content/docs/configure/runtime.mdx b/content/docs/configure/runtime.mdx index 1061949..ebfcbfa 100644 --- a/content/docs/configure/runtime.mdx +++ b/content/docs/configure/runtime.mdx @@ -25,8 +25,8 @@ The default when you run `os start` without a config or artifact. ObjectOS boots an empty kernel with the platform plugins loaded (`auth`, `security`, `audit`, `storage`, `webhooks`, `mcp-server`, `marketplace-proxy`, `marketplace-install-local`, …), opens local -SQLite at `~/.objectstack/data/standalone.db`, and serves Console, -Account, and Console. +SQLite at `~/.objectstack/data/standalone.db`, and serves the Console +and Account UIs. Install apps from the marketplace tab in Console to populate the kernel with objects, views, and flows — no rebuild, no restart. Best for @@ -118,7 +118,7 @@ runtime database configuration with the artifact response. In file-backed mode, ObjectOS can derive database settings from the artifact's datasource declarations. Supported framework drivers include -SQLite, PostgreSQL, Turso/libSQL, MongoDB, and memory-backed evaluation +SQLite, PostgreSQL, MySQL, MongoDB, and memory-backed evaluation drivers. For production, use a customer-managed database. Do not rely on diff --git a/content/docs/configure/runtime.cn.mdx b/content/docs/configure/runtime.zh-Hans.mdx similarity index 98% rename from content/docs/configure/runtime.cn.mdx rename to content/docs/configure/runtime.zh-Hans.mdx index 0004dc3..780a3f4 100644 --- a/content/docs/configure/runtime.cn.mdx +++ b/content/docs/configure/runtime.zh-Hans.mdx @@ -99,6 +99,6 @@ ObjectOS 缓存已解析的环境和项目 kernel,避免每次请求都重建 在 cloud-connected 模式下,控制面把每个项目的运行时数据库配置随 artifact 响应一起返回。 -在 file-backed 模式下,ObjectOS 可以根据 artifact 的数据源声明派生数据库设置。支持的框架驱动包括 SQLite、PostgreSQL、Turso/libSQL、MongoDB 以及内存评估驱动。 +在 file-backed 模式下,ObjectOS 可以根据 artifact 的数据源声明派生数据库设置。支持的框架驱动包括 SQLite、PostgreSQL、MySQL、MongoDB 以及内存评估驱动。 生产环境请使用客户托管的数据库。不要把业务数据放在容器本地存储中,除非该部署明确是单节点评估。 diff --git a/content/docs/configure/storage.de.mdx b/content/docs/configure/storage.de.mdx new file mode 100644 index 0000000..5d6fdf3 --- /dev/null +++ b/content/docs/configure/storage.de.mdx @@ -0,0 +1,191 @@ +--- +title: Speicher +description: Wo ObjectOS Dateien ablegt — lokale Festplatte, S3, R2, MinIO, Spaces. +--- + +# Speicher + +ObjectOS-Dateien (Anhänge, Uploads, generierte Dokumente) laufen durch +den **Speicherdienst** — eine austauschbare Abstraktion mit zwei Adaptern: +**lokales Dateisystem** (Standard) und **S3-kompatibel** (Produktion). + +Der Dienst wird von `@objectstack/service-storage` bereitgestellt und ist +in Standalone- und Projekt-Boots standardmäßig aktiviert. + +## Wie Benutzer damit interagieren + +| Oberfläche | Verhalten | +|---|---| +| Console Datei-/Bildfelder | Der Browser lädt über vorab signierte URLs direkt in den Speicher hoch | +| REST `/api/v1/storage/*` | Programmatische Upload-/Download-Endpunkte | +| Objektfelder `attachment` / `image` | Werden als Upload-Widgets gerendert; Metadaten bleiben in `sys_file` erhalten | + +Dateien werden im Systemobjekt `sys_file` nachverfolgt — niemals als +rohe Pfade in Ihren Datensätzen. Das entkoppelt Ihr Datenmodell vom +Speicher-Backend. + +## Lokales Dateisystem (Standard) + +Geeignet für: Entwicklung, Single-Node-Deployments, Demos. + +```ts +// objectstack.config.ts (or wherever you assemble plugins) +import { StorageServicePlugin } from '@objectstack/service-storage'; + +new StorageServicePlugin({ + adapter: 'local', + local: { + rootDir: './uploads', + baseUrl: 'http://localhost:3000', // for presigned URLs + signingSecret: process.env.OS_STORAGE_SIGNING_SECRET, // optional; auto-generated if omitted + }, + presignedTtl: 3600, // seconds — TTL for presigned URLs + sessionTtl: 86400, // seconds — TTL for chunked upload sessions +}); +``` + +Im Standalone-Modus (`os start` ohne Projekt) konfiguriert die Laufzeitumgebung +den lokalen Speicher automatisch unter `.objectstack/data/uploads/`. Überschreiben +Sie das Stammverzeichnis mit der Umgebungsvariable `OS_STORAGE_ROOT`. + +**Die Produktionstauglichkeit hängt von der Form des Deployments ab:** + +- ✅ Desktop-Apps, interne Single-Node-Tools, Edge-/On-Prem-Appliances — + lokaler Speicher ist in Ordnung, solange das Verzeichnis `uploads/` + in Ihr Dateisystem-Backup einbezogen wird (oder bei Desktop-Apps in + einem vom Benutzer kontrollierten Sync-Ordner liegt). +- ❌ Multi-Node, Multi-AZ oder alles, was regionsübergreifende + Beständigkeit benötigt — verwenden Sie S3-kompatiblen Speicher. + +## S3-kompatibel (Produktion) + +Geeignet für: Produktion, Multi-Node, Beständigkeit + Lifecycle-Management. + +```bash +pnpm add @aws-sdk/client-s3 @aws-sdk/s3-request-presigner +``` + +```ts +import { StorageServicePlugin } from '@objectstack/service-storage'; + +new StorageServicePlugin({ + adapter: 's3', + s3: { + bucket: 'my-bucket', + region: 'us-east-1', + // omit credentials to use the AWS SDK's default chain + // (env, ~/.aws, IAM role) + }, +}); +``` + +Das AWS SDK liest Anmeldedaten aus seiner üblichen Kette: + +| Quelle | Umgebungsvariable | +|---|---| +| Standard-Umgebung | `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `AWS_REGION` | +| Session-Token | `AWS_SESSION_TOKEN` | +| Gemeinsame Konfiguration | `~/.aws/credentials`, `AWS_PROFILE` | +| IAM-Rolle | Automatisch auf EC2 / ECS / EKS / Lambda — keine Konfiguration | + +### Cloudflare R2 + +```ts +new StorageServicePlugin({ + adapter: 's3', + s3: { + bucket: 'my-bucket', + region: 'auto', + endpoint: 'https://.r2.cloudflarestorage.com', + forcePathStyle: false, + }, +}); +``` + +Anmeldedaten: R2 Access Key ID + Secret, übergeben über die Standard- +`AWS_*`-Umgebungsvariablen oder Ihren Secret Manager. + +### MinIO (selbst gehostet) + +```ts +new StorageServicePlugin({ + adapter: 's3', + s3: { + bucket: 'my-bucket', + region: 'us-east-1', + endpoint: 'http://minio.internal:9000', + forcePathStyle: true, + }, +}); +``` + +### DigitalOcean Spaces + +```ts +new StorageServicePlugin({ + adapter: 's3', + s3: { + bucket: 'my-bucket', + region: 'nyc3', + endpoint: 'https://nyc3.digitaloceanspaces.com', + forcePathStyle: false, + }, +}); +``` + +### S3-Bucket-Policy + +Der Speicher verwendet vorab signierte PUT-/GET-URLs. Empfohlene Bucket-Policy: + +- Jeglichen öffentlichen Zugriff blockieren. +- CORS: `PUT`/`GET` von Ihren ObjectOS-Hostnamen erlauben. +- Lifecycle: unvollständige Multipart-Uploads nach 1–7 Tagen ablaufen lassen; + mit `temp=true` markierte Objekte nach 24 Stunden ablaufen lassen. +- Versioning + Object Lock: optional, empfohlen für Compliance-Deployments. + +## REST-Oberfläche + +`@objectstack/client` ruft diese auf — normalerweise greifen Sie nicht direkt darauf zu: + +| Methode | Pfad | Zweck | +|---|---|---| +| POST | `/api/v1/storage/upload/presigned` | Eine vorab signierte Upload-URL abrufen | +| POST | `/api/v1/storage/upload/complete` | Einen abgeschlossenen Upload festschreiben | +| POST | `/api/v1/storage/upload/chunked` | Chunked-Upload beginnen | +| PUT | `/api/v1/storage/upload/chunked/:uploadId/chunk/:i` | Einen Chunk hochladen | +| POST | `/api/v1/storage/upload/chunked/:uploadId/complete` | Chunked-Upload abschließen | +| GET | `/api/v1/storage/upload/chunked/:uploadId/progress` | Fortschritt abfragen | +| GET | `/api/v1/storage/files/:fileId/url` | Eine vorab signierte Download-URL abrufen | + +Die Autorisierung pro Datei wird vom Permission-Evaluator des Security-Plugins +gegen das Objekt `sys_file` abgewickelt — Sie benötigen keine separaten +ACLs auf Speicherebene. + +## Live-Konfiguration + +Wenn der Settings-Dienst aktiviert ist (standardmäßig der Fall), kann ein +Administrator den Speicheradapter in **Console → Configuration → Storage** +ohne Neustart austauschen: + +- Adapter, Bucket, Region, Endpunkt auswählen; +- Anmeldedaten einfügen (im Ruhezustand verschlüsselt in `sys_setting`); +- vor dem Speichern auf **Test connection** klicken. + +Die Änderung gilt ab der nächsten Anfrage — kein Neustart erforderlich. + +## Dimensionierung + +| Ressource | Standard | Anpassbar | +|---|---|---| +| TTL für vorab signierte URLs | 1 Stunde | Plugin-Option `presignedTtl` | +| TTL für Chunked-Upload-Sitzungen | 24 Stunden | Plugin-Option `sessionTtl` | +| Maximaler Single-Part-Upload | Vom Backend vorgegeben (S3 = 5 GB) | — | +| Maximaler Chunked-Upload | Vom Backend vorgegeben (S3 = 5 TB) | — | + +## Wie es weitergeht + +- [System settings](/docs/configure/system-settings) — Live-Konfiguration + und der Settings-Dienst, der bei Speicher-Wechseln verwendet wird +- [Production Readiness](/docs/operate/production) — Checkliste, die die + Beständigkeit von Objektspeicher und Backups umfasst +- [`@objectstack/service-storage` on GitHub](https://github.com/objectstack-ai/framework/tree/main/packages/services/service-storage) — Quellcode und vollständige Optionsreferenz diff --git a/content/docs/configure/storage.es.mdx b/content/docs/configure/storage.es.mdx new file mode 100644 index 0000000..c52a81d --- /dev/null +++ b/content/docs/configure/storage.es.mdx @@ -0,0 +1,192 @@ +--- +title: Almacenamiento +description: Dónde coloca ObjectOS los archivos — disco local, S3, R2, MinIO, Spaces. +--- + +# Almacenamiento + +Los archivos de ObjectOS (adjuntos, cargas, documentos generados) fluyen a través +del **servicio de almacenamiento** — una abstracción conectable con dos adaptadores: +**sistema de archivos local** (predeterminado) y **compatible con S3** (producción). + +El servicio lo proporciona `@objectstack/service-storage` y está +habilitado de forma predeterminada en los arranques standalone y de proyecto. + +## Cómo interactúan los usuarios con él + +| Superficie | Comportamiento | +|---|---| +| Campos de archivo/imagen de Console | El navegador carga directamente al almacenamiento mediante URLs prefirmadas | +| REST `/api/v1/storage/*` | Endpoints de carga/descarga programáticos | +| Campos `attachment` / `image` de objetos | Se renderizan como widgets de carga; los metadatos persisten en `sys_file` | + +Los archivos se rastrean en el objeto de sistema `sys_file` — nunca como rutas +sin procesar en tus registros. Eso desacopla tu modelo de datos del +backend de almacenamiento. + +## Sistema de archivos local (predeterminado) + +Ideal para: desarrollo, despliegues de un solo nodo, demostraciones. + +```ts +// objectstack.config.ts (or wherever you assemble plugins) +import { StorageServicePlugin } from '@objectstack/service-storage'; + +new StorageServicePlugin({ + adapter: 'local', + local: { + rootDir: './uploads', + baseUrl: 'http://localhost:3000', // for presigned URLs + signingSecret: process.env.OS_STORAGE_SIGNING_SECRET, // optional; auto-generated if omitted + }, + presignedTtl: 3600, // seconds — TTL for presigned URLs + sessionTtl: 86400, // seconds — TTL for chunked upload sessions +}); +``` + +En modo standalone (`os start` sin proyecto), el runtime configura +el almacenamiento local automáticamente en `.objectstack/data/uploads/`. Anula +el directorio raíz con la variable de entorno `OS_STORAGE_ROOT`. + +**La idoneidad para producción depende de la forma del despliegue:** + +- ✅ Aplicaciones de escritorio, herramientas internas de un solo nodo, dispositivos + edge / on-prem — el almacenamiento local funciona bien, siempre que el directorio + `uploads/` esté incluido en tu copia de seguridad del sistema de archivos (o resida + en una carpeta de sincronización controlada por el usuario en aplicaciones de escritorio). +- ❌ Multinodo, multi-AZ, o cualquier cosa que requiera durabilidad + entre regiones — usa almacenamiento compatible con S3. + +## Compatible con S3 (producción) + +Ideal para: producción, multinodo, durabilidad + gestión del ciclo de vida. + +```bash +pnpm add @aws-sdk/client-s3 @aws-sdk/s3-request-presigner +``` + +```ts +import { StorageServicePlugin } from '@objectstack/service-storage'; + +new StorageServicePlugin({ + adapter: 's3', + s3: { + bucket: 'my-bucket', + region: 'us-east-1', + // omit credentials to use the AWS SDK's default chain + // (env, ~/.aws, IAM role) + }, +}); +``` + +El AWS SDK lee las credenciales de su cadena habitual: + +| Origen | Variable de entorno | +|---|---| +| Entorno estándar | `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `AWS_REGION` | +| Token de sesión | `AWS_SESSION_TOKEN` | +| Configuración compartida | `~/.aws/credentials`, `AWS_PROFILE` | +| Rol de IAM | Automático en EC2 / ECS / EKS / Lambda — sin configuración | + +### Cloudflare R2 + +```ts +new StorageServicePlugin({ + adapter: 's3', + s3: { + bucket: 'my-bucket', + region: 'auto', + endpoint: 'https://.r2.cloudflarestorage.com', + forcePathStyle: false, + }, +}); +``` + +Credenciales: ID de clave de acceso de R2 + secreto, pasados mediante las +variables de entorno estándar `AWS_*` o tu gestor de secretos. + +### MinIO (autoalojado) + +```ts +new StorageServicePlugin({ + adapter: 's3', + s3: { + bucket: 'my-bucket', + region: 'us-east-1', + endpoint: 'http://minio.internal:9000', + forcePathStyle: true, + }, +}); +``` + +### DigitalOcean Spaces + +```ts +new StorageServicePlugin({ + adapter: 's3', + s3: { + bucket: 'my-bucket', + region: 'nyc3', + endpoint: 'https://nyc3.digitaloceanspaces.com', + forcePathStyle: false, + }, +}); +``` + +### Política de bucket de S3 + +El almacenamiento usa URLs prefirmadas PUT/GET. Política de bucket recomendada: + +- Bloquea todo el acceso público. +- CORS: permite `PUT`/`GET` desde tus nombres de host de ObjectOS. +- Ciclo de vida: caduca las cargas multiparte incompletas tras 1–7 días; caduca los + objetos etiquetados con `temp=true` tras 24 horas. +- Versionado + Object Lock: opcional, recomendado para despliegues + de cumplimiento normativo. + +## Superficie REST + +`@objectstack/client` llama a estos — normalmente no los invocas directamente: + +| Método | Ruta | Propósito | +|---|---|---| +| POST | `/api/v1/storage/upload/presigned` | Obtener una URL de carga prefirmada | +| POST | `/api/v1/storage/upload/complete` | Confirmar una carga finalizada | +| POST | `/api/v1/storage/upload/chunked` | Iniciar una carga por fragmentos | +| PUT | `/api/v1/storage/upload/chunked/:uploadId/chunk/:i` | Cargar un fragmento | +| POST | `/api/v1/storage/upload/chunked/:uploadId/complete` | Finalizar la carga por fragmentos | +| GET | `/api/v1/storage/upload/chunked/:uploadId/progress` | Consultar el progreso | +| GET | `/api/v1/storage/files/:fileId/url` | Obtener una URL de descarga prefirmada | + +La autorización por archivo la gestiona el evaluador de permisos del plugin de +seguridad contra el objeto `sys_file` — no necesitas ACLs separadas en la capa +de almacenamiento. + +## Configuración en vivo + +Cuando el servicio de settings está habilitado (lo está de forma predeterminada), un administrador puede +cambiar el adaptador de almacenamiento en **Console → Configuration → Storage** sin +reiniciar: + +- elige adaptador, bucket, región, endpoint; +- pega las credenciales (cifradas en reposo en `sys_setting`); +- haz clic en **Test connection** antes de guardar. + +El cambio se aplica en la siguiente petición — sin necesidad de reiniciar. + +## Dimensionamiento + +| Recurso | Predeterminado | Ajustable | +|---|---|---| +| TTL de URL prefirmada | 1 hora | Opción del plugin `presignedTtl` | +| TTL de sesión de carga por fragmentos | 24 horas | Opción del plugin `sessionTtl` | +| Carga máxima de una sola parte | Impuesta por el backend (S3 = 5 GB) | — | +| Carga máxima por fragmentos | Impuesta por el backend (S3 = 5 TB) | — | + +## A dónde ir después + +- [Configuración del sistema](/docs/configure/system-settings) — configuración + en vivo y el servicio de settings que utilizan los cambios de almacenamiento +- [Preparación para producción](/docs/operate/production) — lista de verificación que + incluye la durabilidad y la copia de seguridad del almacenamiento de objetos +- [`@objectstack/service-storage` en GitHub](https://github.com/objectstack-ai/framework/tree/main/packages/services/service-storage) — código fuente y referencia completa de opciones diff --git a/content/docs/configure/storage.fr.mdx b/content/docs/configure/storage.fr.mdx new file mode 100644 index 0000000..6a3ced4 --- /dev/null +++ b/content/docs/configure/storage.fr.mdx @@ -0,0 +1,198 @@ +--- +title: Stockage +description: Où ObjectOS place les fichiers — disque local, S3, R2, MinIO, Spaces. +--- + +# Stockage + +Les fichiers ObjectOS (pièces jointes, téléversements, documents générés) +transitent par le **service de stockage** — une abstraction modulaire dotée +de deux adaptateurs : le **système de fichiers local** (par défaut) et le +mode **compatible S3** (production). + +Le service est fourni par `@objectstack/service-storage` et est activé par +défaut lors des démarrages autonomes et de projet. + +## Comment les utilisateurs interagissent avec lui + +| Surface | Comportement | +|---|---| +| Champs de fichier/image de la Console | Le navigateur téléverse directement vers le stockage via des URL présignées | +| REST `/api/v1/storage/*` | Points de terminaison programmatiques de téléversement/téléchargement | +| Champs `attachment` / `image` d'objet | Rendus sous forme de widgets de téléversement ; les métadonnées sont conservées dans `sys_file` | + +Les fichiers sont suivis dans l'objet système `sys_file` — jamais sous forme +de chemins bruts dans vos enregistrements. Cela découple votre modèle de +données du backend de stockage. + +## Système de fichiers local (par défaut) + +Adapté à : le développement, les déploiements mononœuds, les démos. + +```ts +// objectstack.config.ts (or wherever you assemble plugins) +import { StorageServicePlugin } from '@objectstack/service-storage'; + +new StorageServicePlugin({ + adapter: 'local', + local: { + rootDir: './uploads', + baseUrl: 'http://localhost:3000', // for presigned URLs + signingSecret: process.env.OS_STORAGE_SIGNING_SECRET, // optional; auto-generated if omitted + }, + presignedTtl: 3600, // seconds — TTL for presigned URLs + sessionTtl: 86400, // seconds — TTL for chunked upload sessions +}); +``` + +En mode autonome (`os start` sans projet), le runtime configure +automatiquement le stockage local sous `.objectstack/data/uploads/`. +Remplacez le répertoire racine avec la variable d'environnement +`OS_STORAGE_ROOT`. + +**L'adéquation à la production dépend de la forme du déploiement :** + +- ✅ Applications de bureau, outils internes mononœuds, équipements + edge / on-premise — le stockage local convient, tant que le répertoire + `uploads/` est inclus dans la sauvegarde de votre système de fichiers + (ou réside dans un dossier de synchronisation contrôlé par l'utilisateur + pour les applications de bureau). +- ❌ Multinœuds, multi-AZ, ou tout ce qui nécessite une durabilité + inter-régions — utilisez un stockage compatible S3. + +## Compatible S3 (production) + +Adapté à : la production, le multinœuds, la durabilité + la gestion du +cycle de vie. + +```bash +pnpm add @aws-sdk/client-s3 @aws-sdk/s3-request-presigner +``` + +```ts +import { StorageServicePlugin } from '@objectstack/service-storage'; + +new StorageServicePlugin({ + adapter: 's3', + s3: { + bucket: 'my-bucket', + region: 'us-east-1', + // omit credentials to use the AWS SDK's default chain + // (env, ~/.aws, IAM role) + }, +}); +``` + +Le SDK AWS lit les identifiants depuis sa chaîne habituelle : + +| Source | Variable d'environnement | +|---|---| +| Env standard | `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `AWS_REGION` | +| Jeton de session | `AWS_SESSION_TOKEN` | +| Config partagée | `~/.aws/credentials`, `AWS_PROFILE` | +| Rôle IAM | Automatique sur EC2 / ECS / EKS / Lambda — aucune configuration | + +### Cloudflare R2 + +```ts +new StorageServicePlugin({ + adapter: 's3', + s3: { + bucket: 'my-bucket', + region: 'auto', + endpoint: 'https://.r2.cloudflarestorage.com', + forcePathStyle: false, + }, +}); +``` + +Identifiants : ID de clé d'accès R2 + secret, transmis via les variables +d'environnement standard `AWS_*` ou votre gestionnaire de secrets. + +### MinIO (auto-hébergé) + +```ts +new StorageServicePlugin({ + adapter: 's3', + s3: { + bucket: 'my-bucket', + region: 'us-east-1', + endpoint: 'http://minio.internal:9000', + forcePathStyle: true, + }, +}); +``` + +### DigitalOcean Spaces + +```ts +new StorageServicePlugin({ + adapter: 's3', + s3: { + bucket: 'my-bucket', + region: 'nyc3', + endpoint: 'https://nyc3.digitaloceanspaces.com', + forcePathStyle: false, + }, +}); +``` + +### Politique de bucket S3 + +Le stockage utilise des URL présignées PUT/GET. Politique de bucket +recommandée : + +- Bloquer tout accès public. +- CORS : autoriser `PUT`/`GET` depuis le(s) nom(s) d'hôte de votre ObjectOS. +- Cycle de vie : expirer les téléversements multipart incomplets après + 1 à 7 jours ; expirer les objets étiquetés `temp=true` après 24 heures. +- Versioning + Object Lock : optionnel, recommandé pour les déploiements + soumis à des exigences de conformité. + +## Surface REST + +`@objectstack/client` appelle ces points de terminaison — vous ne les +sollicitez généralement pas directement : + +| Méthode | Chemin | Objectif | +|---|---|---| +| POST | `/api/v1/storage/upload/presigned` | Obtenir une URL de téléversement présignée | +| POST | `/api/v1/storage/upload/complete` | Valider un téléversement terminé | +| POST | `/api/v1/storage/upload/chunked` | Démarrer un téléversement fragmenté | +| PUT | `/api/v1/storage/upload/chunked/:uploadId/chunk/:i` | Téléverser un fragment | +| POST | `/api/v1/storage/upload/chunked/:uploadId/complete` | Terminer un téléversement fragmenté | +| GET | `/api/v1/storage/upload/chunked/:uploadId/progress` | Suivre la progression | +| GET | `/api/v1/storage/files/:fileId/url` | Obtenir une URL de téléchargement présignée | + +L'autorisation par fichier est gérée par l'évaluateur de permissions du +plugin de sécurité sur l'objet `sys_file` — vous n'avez pas besoin d'ACL +distinctes au niveau de la couche de stockage. + +## Configuration en direct + +Lorsque le service de paramètres est activé (c'est le cas par défaut), un +administrateur peut changer d'adaptateur de stockage dans +**Console → Configuration → Storage** sans redémarrer : + +- choisir l'adaptateur, le bucket, la région, l'endpoint ; +- coller les identifiants (chiffrés au repos dans `sys_setting`) ; +- cliquer sur **Test connection** avant d'enregistrer. + +Le changement s'applique à la requête suivante — aucun redémarrage requis. + +## Dimensionnement + +| Ressource | Par défaut | Ajustable | +|---|---|---| +| TTL d'URL présignée | 1 heure | Option de plugin `presignedTtl` | +| TTL de session de téléversement fragmenté | 24 heures | Option de plugin `sessionTtl` | +| Téléversement single-part max | Imposé par le backend (S3 = 5 Go) | — | +| Téléversement fragmenté max | Imposé par le backend (S3 = 5 To) | — | + +## Pour aller plus loin + +- [Paramètres système](/docs/configure/system-settings) — configuration en + direct et service de paramètres utilisé par les changements de stockage +- [Préparation à la production](/docs/operate/production) — liste de + contrôle incluant la durabilité et la sauvegarde du stockage d'objets +- [`@objectstack/service-storage` sur GitHub](https://github.com/objectstack-ai/framework/tree/main/packages/services/service-storage) — source et référence complète des options diff --git a/content/docs/configure/storage.ja.mdx b/content/docs/configure/storage.ja.mdx new file mode 100644 index 0000000..42a15b7 --- /dev/null +++ b/content/docs/configure/storage.ja.mdx @@ -0,0 +1,192 @@ +--- +title: ストレージ +description: ObjectOS がファイルを保存する場所 — ローカルディスク、S3、R2、MinIO、Spaces。 +--- + +# ストレージ + +ObjectOS のファイル(添付ファイル、アップロード、生成されたドキュメント)は +**ストレージサービス** を経由します。これは 2 つのアダプターを備えた +プラガブルな抽象化レイヤーです。**ローカルファイルシステム**(デフォルト)と +**S3 互換**(本番環境)です。 + +このサービスは `@objectstack/service-storage` によって提供され、 +スタンドアロンおよびプロジェクトの起動時にデフォルトで有効になります。 + +## ユーザーはどのように操作するか + +| 操作面 | 動作 | +|---|---| +| Console のファイル / 画像フィールド | ブラウザが署名付き URL を介してストレージへ直接アップロード | +| REST `/api/v1/storage/*` | プログラムによるアップロード / ダウンロードのエンドポイント | +| オブジェクトの `attachment` / `image` フィールド | アップロードウィジェットとして描画され、メタデータは `sys_file` に永続化される | + +ファイルは `sys_file` システムオブジェクトで追跡されます。レコード内に +生のパスとして保存されることはありません。これにより、データモデルが +ストレージバックエンドから切り離されます。 + +## ローカルファイルシステム(デフォルト) + +適した用途: 開発、シングルノードのデプロイ、デモ。 + +```ts +// objectstack.config.ts (or wherever you assemble plugins) +import { StorageServicePlugin } from '@objectstack/service-storage'; + +new StorageServicePlugin({ + adapter: 'local', + local: { + rootDir: './uploads', + baseUrl: 'http://localhost:3000', // for presigned URLs + signingSecret: process.env.OS_STORAGE_SIGNING_SECRET, // optional; auto-generated if omitted + }, + presignedTtl: 3600, // seconds — TTL for presigned URLs + sessionTtl: 86400, // seconds — TTL for chunked upload sessions +}); +``` + +スタンドアロンモード(プロジェクトなしの `os start`)では、ランタイムが +`.objectstack/data/uploads/` 配下にローカルストレージを自動的に構成します。 +ルートディレクトリは `OS_STORAGE_ROOT` 環境変数で上書きできます。 + +**本番環境での適合性はデプロイの形態によって決まります:** + +- ✅ デスクトップアプリ、シングルノードの社内ツール、エッジ / オンプレミスの + アプライアンス — `uploads/` ディレクトリがファイルシステムのバックアップに + 含まれている(またはデスクトップアプリの場合はユーザー管理の同期フォルダー上に + 存在する)限り、ローカルストレージで問題ありません。 +- ❌ マルチノード、マルチ AZ、またはクロスリージョンの耐久性を必要とするもの — + S3 互換ストレージを使用してください。 + +## S3 互換(本番環境) + +適した用途: 本番環境、マルチノード、耐久性 + ライフサイクル管理。 + +```bash +pnpm add @aws-sdk/client-s3 @aws-sdk/s3-request-presigner +``` + +```ts +import { StorageServicePlugin } from '@objectstack/service-storage'; + +new StorageServicePlugin({ + adapter: 's3', + s3: { + bucket: 'my-bucket', + region: 'us-east-1', + // omit credentials to use the AWS SDK's default chain + // (env, ~/.aws, IAM role) + }, +}); +``` + +AWS SDK は通常のチェーンから認証情報を読み取ります: + +| ソース | 環境変数 | +|---|---| +| 標準の環境変数 | `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `AWS_REGION` | +| セッショントークン | `AWS_SESSION_TOKEN` | +| 共有設定 | `~/.aws/credentials`, `AWS_PROFILE` | +| IAM ロール | EC2 / ECS / EKS / Lambda 上では自動 — 設定不要 | + +### Cloudflare R2 + +```ts +new StorageServicePlugin({ + adapter: 's3', + s3: { + bucket: 'my-bucket', + region: 'auto', + endpoint: 'https://.r2.cloudflarestorage.com', + forcePathStyle: false, + }, +}); +``` + +認証情報: R2 のアクセスキー ID + シークレットを、標準の `AWS_*` 環境変数 +またはシークレットマネージャー経由で渡します。 + +### MinIO(セルフホスト) + +```ts +new StorageServicePlugin({ + adapter: 's3', + s3: { + bucket: 'my-bucket', + region: 'us-east-1', + endpoint: 'http://minio.internal:9000', + forcePathStyle: true, + }, +}); +``` + +### DigitalOcean Spaces + +```ts +new StorageServicePlugin({ + adapter: 's3', + s3: { + bucket: 'my-bucket', + region: 'nyc3', + endpoint: 'https://nyc3.digitaloceanspaces.com', + forcePathStyle: false, + }, +}); +``` + +### S3 バケットポリシー + +ストレージは署名付きの PUT/GET URL を使用します。推奨されるバケットポリシー: + +- すべてのパブリックアクセスをブロックする。 +- CORS: ObjectOS のホスト名から `PUT`/`GET` を許可する。 +- ライフサイクル: 未完了のマルチパートアップロードを 1〜7 日後に期限切れにする。 + `temp=true` のタグが付いたオブジェクトを 24 時間後に期限切れにする。 +- バージョニング + Object Lock: 任意。コンプライアンス対応のデプロイでは推奨。 + +## REST インターフェイス + +`@objectstack/client` がこれらを呼び出します。通常は直接アクセスする必要はありません: + +| メソッド | パス | 目的 | +|---|---|---| +| POST | `/api/v1/storage/upload/presigned` | 署名付きアップロード URL を取得する | +| POST | `/api/v1/storage/upload/complete` | 完了したアップロードをコミットする | +| POST | `/api/v1/storage/upload/chunked` | チャンクアップロードを開始する | +| PUT | `/api/v1/storage/upload/chunked/:uploadId/chunk/:i` | チャンクをアップロードする | +| POST | `/api/v1/storage/upload/chunked/:uploadId/complete` | チャンクアップロードを完了する | +| GET | `/api/v1/storage/upload/chunked/:uploadId/progress` | 進捗をポーリングする | +| GET | `/api/v1/storage/files/:fileId/url` | 署名付きダウンロード URL を取得する | + +ファイルごとの認可は、`sys_file` オブジェクトに対するセキュリティプラグインの +権限エバリュエーターによって処理されます。ストレージ層に個別の ACL を +用意する必要はありません。 + +## ライブ構成 + +設定サービスが有効になっている場合(デフォルトで有効です)、管理者は +**Console → Configuration → Storage** からストレージアダプターを再起動せずに +切り替えることができます: + +- アダプター、バケット、リージョン、エンドポイントを選択する。 +- 認証情報を貼り付ける(`sys_setting` 内で保存時に暗号化される)。 +- 保存する前に **Test connection** をクリックする。 + +変更は次のリクエストから適用されます。再起動は不要です。 + +## サイジング + +| リソース | デフォルト | 調整可能 | +|---|---|---| +| 署名付き URL の TTL | 1 時間 | `presignedTtl` プラグインオプション | +| チャンクアップロードセッションの TTL | 24 時間 | `sessionTtl` プラグインオプション | +| 単一パートアップロードの最大サイズ | バックエンドによる制限(S3 = 5 GB) | — | +| チャンクアップロードの最大サイズ | バックエンドによる制限(S3 = 5 TB) | — | + +## 次に読むべきもの + +- [システム設定](/docs/configure/system-settings) — ライブ構成と、 + ストレージの切り替えで使用される設定サービス +- [本番環境への準備](/docs/operate/production) — オブジェクトストレージの + 耐久性とバックアップを含むチェックリスト +- [GitHub 上の `@objectstack/service-storage`](https://github.com/objectstack-ai/framework/tree/main/packages/services/service-storage) — ソースとすべてのオプションのリファレンス diff --git a/content/docs/configure/storage.mdx b/content/docs/configure/storage.mdx index e78f2e3..d892eaf 100644 --- a/content/docs/configure/storage.mdx +++ b/content/docs/configure/storage.mdx @@ -45,7 +45,8 @@ new StorageServicePlugin({ ``` In standalone mode (`os start` with no project), the runtime configures -local storage automatically under `~/.objectstack/data/uploads/`. +local storage automatically under `.objectstack/data/uploads/`. Override +the root directory with the `OS_STORAGE_ROOT` environment variable. **Production fit depends on the deployment shape:** @@ -184,8 +185,8 @@ The change applies to the next request — no restart needed. ## Where to go next -- [Configuration overview](/docs/configure) — the rest of the - Configure section +- [System settings](/docs/configure/system-settings) — live + configuration and the settings service used by storage swaps - [Production Readiness](/docs/operate/production) — checklist that includes object storage durability and backup - [`@objectstack/service-storage` on GitHub](https://github.com/objectstack-ai/framework/tree/main/packages/services/service-storage) — source and full option reference diff --git a/content/docs/configure/storage.cn.mdx b/content/docs/configure/storage.zh-Hans.mdx similarity index 78% rename from content/docs/configure/storage.cn.mdx rename to content/docs/configure/storage.zh-Hans.mdx index be7f8ce..5dd3cb4 100644 --- a/content/docs/configure/storage.cn.mdx +++ b/content/docs/configure/storage.zh-Hans.mdx @@ -5,7 +5,7 @@ description: ObjectOS 把文件放在哪里 —— 本地磁盘、S3、R2、MinI # 存储 -ObjectOS 的文件(附件、上传、生成的文档)经过**存储服务**——一个可插拔的抽象,包含两类适配器:**本地文件系统**(默认)和 **S3 兼容**(生产)。 +ObjectOS 的文件(附件、上传内容、生成的文档)会经过**存储服务**——一个可插拔的抽象层,包含两类适配器:**本地文件系统**(默认)和 **S3 兼容存储**(生产)。 该服务由 `@objectstack/service-storage` 提供,在 standalone 和 project 启动时默认启用。 @@ -17,7 +17,7 @@ ObjectOS 的文件(附件、上传、生成的文档)经过**存储服务** | REST `/api/v1/storage/*` | 编程式上传/下载端点 | | 对象 `attachment` / `image` 字段 | 渲染为上传控件;元数据持久化在 `sys_file` | -文件以 `sys_file` 系统对象追踪,而非以原始路径出现在你的记录中。这让你的数据模型与存储后端解耦。 +文件以 `sys_file` 系统对象进行追踪,而非以原始路径出现在你的记录中。这让你的数据模型与存储后端解耦。 ## 本地文件系统(默认) @@ -39,7 +39,7 @@ new StorageServicePlugin({ }); ``` -在 standalone 模式(无项目执行 `os start`)下,运行时会在 `~/.objectstack/data/uploads/` 下自动配置本地存储。 +在 standalone 模式(无项目执行 `os start`)下,运行时会自动在 `.objectstack/data/uploads/` 下配置本地存储。可通过 `OS_STORAGE_ROOT` 环境变量覆盖根目录。 **是否适合生产取决于部署形态:** @@ -49,7 +49,7 @@ new StorageServicePlugin({ - ❌ 多节点、多可用区,或者任何需要跨区域持久化的场景 —— 请使用 S3 兼容存储。 -## S3 兼容(生产) +## S3 兼容存储(生产) 适用于:生产、多节点、持久化 + 生命周期管理。 @@ -71,7 +71,7 @@ new StorageServicePlugin({ }); ``` -AWS SDK 按其默认链读取凭据: +AWS SDK 按其正常的凭据链读取凭据: | 来源 | 环境变量 | |---|---| @@ -94,7 +94,7 @@ new StorageServicePlugin({ }); ``` -凭据:R2 access key id + secret,通过标准 `AWS_*` 环境变量或你的 secret manager 传入。 +凭据:R2 access key ID + secret,通过标准 `AWS_*` 环境变量或你的 secret manager 传入。 ### MinIO(自托管) @@ -129,8 +129,8 @@ new StorageServicePlugin({ 存储使用预签名 PUT/GET URL。推荐的 bucket 策略: - 阻止所有公共访问。 -- CORS:允许来自 ObjectOS 主机名的 `PUT`/`GET`。 -- 生命周期:1–7 天后过期未完成的 multipart 上传;24 小时后过期带 `temp=true` 标签的对象。 +- CORS:允许来自你的 ObjectOS 主机名的 `PUT`/`GET`。 +- 生命周期:1–7 天后让未完成的 multipart 上传过期;24 小时后让带 `temp=true` 标签的对象过期。 - Versioning + Object Lock:可选,在合规部署中推荐启用。 ## REST 接口 @@ -147,19 +147,19 @@ new StorageServicePlugin({ | GET | `/api/v1/storage/upload/chunked/:uploadId/progress` | 轮询进度 | | GET | `/api/v1/storage/files/:fileId/url` | 获取预签名下载 URL | -每个文件的鉴权由 security 插件的权限求值器针对 `sys_file` 对象处理 —— 无需独立的存储层 ACL。 +每个文件的鉴权由 security 插件的权限求值器针对 `sys_file` 对象处理 —— 你无需独立的存储层 ACL。 ## 实时配置 -settings 服务启用时(默认启用),管理员可以在 **Console → Configuration → Storage** 中切换存储适配器而无需重启: +当 settings 服务启用时(默认即启用),管理员可以在 **Console → Configuration → Storage** 中切换存储适配器而无需重启: - 选择适配器、bucket、region、endpoint; -- 粘贴凭据(在 `sys_setting` 中加密存储); +- 粘贴凭据(在 `sys_setting` 中静态加密存储); - 保存前点击 **Test connection**。 变更在下一次请求时生效——无需重启。 -## 容量 +## 容量规划 | 资源 | 默认值 | 可调项 | |---|---|---| @@ -170,6 +170,6 @@ settings 服务启用时(默认启用),管理员可以在 **Console → Co ## 下一步 -- [Configuration overview](/docs/configure) —— Configure 章节的其余内容 -- [Production Readiness](/docs/operate/production) —— 包含对象存储持久化和备份的清单 +- [系统设置](/docs/configure/system-settings) —— 实时配置以及存储切换所使用的设置服务 +- [Production Readiness](/docs/operate/production) —— 包含对象存储持久化与备份的清单 - [GitHub 上的 `@objectstack/service-storage`](https://github.com/objectstack-ai/framework/tree/main/packages/services/service-storage) —— 源码与完整选项参考 diff --git a/content/docs/configure/system-settings.cn.mdx b/content/docs/configure/system-settings.cn.mdx deleted file mode 100644 index e92baf5..0000000 --- a/content/docs/configure/system-settings.cn.mdx +++ /dev/null @@ -1,62 +0,0 @@ ---- -title: 系统设置 -description: 通过 manifest 和共享 K/V 存储配置租户与用户设置。 ---- - -# 系统设置 - -ObjectStack 内置了用于运行时与插件设置的 settings 服务。当应用 artifact 需要 settings 能力时,ObjectOS 通过 Console 暴露这些设置。 - -## 设置模型 - -设置由代码声明,并以值的形式存储: - -| 层 | 用途 | -|---|---| -| Settings Manifest | 定义字段、标签、默认值、校验、可见性和操作 | -| `sys_setting` | 存储租户/用户的 K/V 值 | -| Resolver | 读取生效值 | -| Console UI | 渲染标准设置页 | - -对于普通配置,插件不应自建一次性的设置表。它们应声明设置 manifest,让 ObjectOS 统一渲染和存储。 - -## 解析顺序 - -生效值按以下顺序解析: - -```text -Environment override -Tenant setting -User setting -Manifest default -``` - -环境覆盖是锁定的。如果某个值由环境变量设置,Console UI 应将其显示为由宿主托管,并拒绝运行时编辑。 - -## 常见设置类别 - -面向客户的设置通常包括: - -| 类别 | 示例 | -|---|---| -| Email | SMTP 主机、Provider API Key、发件人地址、测试邮件 | -| 品牌 | 产品名称、Logo URL、强调色、默认主题 | -| Feature flag | 租户级特性开关 | -| Storage | 本地文件系统或对象存储凭据 | -| AI Provider | 模型 Provider、API Key、预算上限 | -| SSO | OIDC Provider 设置和连接测试 | - -## Secret - -密码和凭据字段应由 settings 服务加密存储,或以环境托管值的形式提供。不要把 secret 存于 artifact、compose 文件或 Git 中。 - -## 测试操作 - -设置 manifest 可以声明标准操作按钮,例如: - -- 发送测试邮件; -- 测试 SSO discovery; -- 验证对象存储凭据; -- 校验 webhook 目标。 - -在客户初始化流程中使用这些操作,而不是让运维先去翻日志。 diff --git a/content/docs/configure/system-settings.de.mdx b/content/docs/configure/system-settings.de.mdx new file mode 100644 index 0000000..0387979 --- /dev/null +++ b/content/docs/configure/system-settings.de.mdx @@ -0,0 +1,89 @@ +--- +title: Systemeinstellungen +description: Konfigurieren Sie Mandanten- und Benutzereinstellungen über Manifeste und einen gemeinsamen K/V-Speicher. +--- + +# Systemeinstellungen + +ObjectStack enthält einen Einstellungsdienst für Laufzeit- und Plugin-Einstellungen. +ObjectOS stellt diese Einstellungen über die Console bereit, wenn das +Anwendungsartefakt die Einstellungsfähigkeit erfordert. + +## Einstellungsmodell + +Einstellungen werden per Code deklariert und als Werte gespeichert: + +| Ebene | Zweck | +|---|---| +| Settings Manifest | Definiert Felder, Beschriftungen, Standardwerte, Validierung, Sichtbarkeit und Aktionen | +| `sys_setting` | Speichert Mandanten-/Benutzer-K/V-Werte | +| Resolver | Liest den effektiven Wert | +| Console UI | Rendert standardisierte Einstellungsseiten | + +Plugins sollten für die übliche Konfiguration keine einmaligen +Einstellungstabellen erstellen. Sie sollten Einstellungsmanifeste deklarieren +und ObjectOS die Werte konsistent rendern und speichern lassen. + +## Auflösungsreihenfolge + +Jede Einstellung deklariert einen Geltungsbereich (`global`, `tenant` oder +`user`). Der Resolver durchläuft die Kaskade von der höchsten zur niedrigsten +Priorität, und der erste gesetzte Wert gewinnt: + +```text +Environment override (locked) +Global setting +Tenant setting +User setting +Manifest default +``` + +Umgebungs-Overrides sind gesperrt. Wird ein Wert über eine Umgebungsvariable +gesetzt, zeigt die Console UI ihn als vom Host verwaltet an und lehnt +Laufzeitänderungen ab. Ein gesperrter Wert an einer beliebigen Stelle weiter +oben in der Kette sperrt auch den effektiven Wert, sodass niedrigere +Geltungsbereiche ihn nicht überschreiben können. + +## Häufige Einstellungsbereiche + +Kundenseitige Einstellungen umfassen üblicherweise: + +| Bereich | Beispiele | +|---|---| +| E-Mail | SMTP-Host, Anbieter-API-Schlüssel, Absenderadresse, Test-E-Mail | +| Branding | Produktname, Logo-URL, Akzentfarbe, Standardthema | +| Feature-Flags | Funktionsschalter auf Mandantenebene | +| Speicher | Lokales Dateisystem oder Objektspeicher-Anmeldedaten | +| KI-Anbieter | Modellanbieter, API-Schlüssel, Budgetgrenzen | +| SSO | OIDC-Anbietereinstellungen und Verbindungstest | + +## Geheimnisse + +Passwort- und Anmeldedatenfelder sollten vom Einstellungsdienst verschlüsselt +oder als umgebungsverwaltete Werte bereitgestellt werden. Wenn ein +Secret-Provider konfiguriert ist, speichert der Einstellungsdienst den +Chiffretext in `sys_secret` und behält nur einen Handle in `sys_setting`. +Speichern Sie keine Geheimnisse in Artefakten, Compose-Dateien oder Git. + +## Testaktionen + +Einstellungsmanifeste können standardisierte Aktionsschaltflächen deklarieren, +zum Beispiel: + +- Test-E-Mail senden; +- SSO-Discovery testen; +- Objektspeicher-Anmeldedaten überprüfen; +- Webhook-Ziel validieren. + +Verwenden Sie diese Aktionen für Kunden-Setup-Abläufe, anstatt Betreiber +zu bitten, zuerst die Logs zu prüfen. + +## Verwandt + +Mehrere Einstellungsbereiche verfügen über eigene Konfigurationsanleitungen: + +- [E-Mail](/docs/configure/email) +- [Speicher](/docs/configure/storage) +- [KI-Anbieter](/docs/configure/ai) +- [Authentifizierung und SSO](/docs/configure/authentication) +- [Laufzeit](/docs/configure/runtime) diff --git a/content/docs/configure/system-settings.es.mdx b/content/docs/configure/system-settings.es.mdx new file mode 100644 index 0000000..42c2cc0 --- /dev/null +++ b/content/docs/configure/system-settings.es.mdx @@ -0,0 +1,87 @@ +--- +title: Configuración del sistema +description: Configura los ajustes de tenant y de usuario mediante manifiestos y un almacén K/V compartido. +--- + +# Configuración del sistema + +ObjectStack incluye un servicio de configuración para los ajustes de runtime y de plugins. +ObjectOS expone esos ajustes a través de la Console cuando el artefacto de la +aplicación requiere la capacidad de configuración. + +## Modelo de configuración + +Los ajustes se declaran mediante código y se almacenan como valores: + +| Capa | Propósito | +|---|---| +| Manifiesto de configuración | Define campos, etiquetas, valores predeterminados, validación, visibilidad y acciones | +| `sys_setting` | Almacena los valores K/V de tenant/usuario | +| Resolver | Lee el valor efectivo | +| Console UI | Renderiza las páginas de configuración estándar | + +Los plugins no deben crear tablas de configuración puntuales para +ajustes ordinarios. Deben declarar manifiestos de configuración y dejar que ObjectOS +renderice y almacene los valores de forma coherente. + +## Orden de resolución + +Cada ajuste declara un alcance (`global`, `tenant` o `user`). El +resolver recorre la cascada desde la mayor hasta la menor precedencia y el +primer valor establecido prevalece: + +```text +Environment override (locked) +Global setting +Tenant setting +User setting +Manifest default +``` + +Las anulaciones de entorno están bloqueadas. Si un valor se establece mediante una +variable de entorno, la Console UI lo muestra como gestionado por el host +y rechaza las ediciones en runtime. Un valor bloqueado en cualquier punto superior de la cadena también +bloquea el valor efectivo, de modo que los alcances inferiores no pueden ocultarlo. + +## Áreas de configuración comunes + +Los ajustes orientados al cliente suelen incluir: + +| Área | Ejemplos | +|---|---| +| Email | Host SMTP, clave de API del proveedor, dirección de remitente, correo de prueba | +| Branding | Nombre del producto, URL del logotipo, color de acento, tema predeterminado | +| Feature flags | Interruptores de funcionalidades a nivel de tenant | +| Storage | Credenciales de sistema de archivos local o de almacenamiento de objetos | +| Proveedores de IA | Proveedor del modelo, clave de API, límites de presupuesto | +| SSO | Ajustes del proveedor OIDC y prueba de conexión | + +## Secretos + +Los campos de contraseñas y credenciales deben cifrarse mediante el servicio de +configuración o proporcionarse como valores gestionados por el entorno. Cuando se configura un +proveedor de secretos, el servicio de configuración almacena el texto cifrado en +`sys_secret` y conserva únicamente un identificador en `sys_setting`. No almacenes +secretos en artefactos, archivos de compose ni Git. + +## Acciones de prueba + +Los manifiestos de configuración pueden declarar botones de acción estándar, como: + +- enviar correo de prueba; +- probar el descubrimiento de SSO; +- verificar las credenciales de almacenamiento de objetos; +- validar el destino de un webhook. + +Utiliza estas acciones para los flujos de configuración del cliente en lugar de pedir a los operadores +que inspeccionen primero los logs. + +## Relacionado + +Varias áreas de configuración tienen guías de configuración dedicadas: + +- [Email](/docs/configure/email) +- [Storage](/docs/configure/storage) +- [Proveedores de IA](/docs/configure/ai) +- [Autenticación y SSO](/docs/configure/authentication) +- [Runtime](/docs/configure/runtime) diff --git a/content/docs/configure/system-settings.fr.mdx b/content/docs/configure/system-settings.fr.mdx new file mode 100644 index 0000000..3aff0c2 --- /dev/null +++ b/content/docs/configure/system-settings.fr.mdx @@ -0,0 +1,87 @@ +--- +title: Paramètres système +description: Configurez les paramètres de tenant et d'utilisateur à l'aide de manifestes et d'un magasin clé/valeur partagé. +--- + +# Paramètres système + +ObjectStack inclut un service de paramètres pour les paramètres d'exécution et de plugins. +ObjectOS expose ces paramètres via la Console lorsque l'artefact +applicatif requiert la capacité de paramètres. + +## Modèle de paramètres + +Les paramètres sont déclarés par le code et stockés sous forme de valeurs : + +| Couche | Objectif | +|---|---| +| Manifeste de paramètres | Définit les champs, libellés, valeurs par défaut, validations, visibilité et actions | +| `sys_setting` | Stocke les valeurs K/V de tenant/utilisateur | +| Résolveur | Lit la valeur effective | +| Interface de la Console | Affiche les pages de paramètres standard | + +Les plugins ne devraient pas créer de tables de paramètres ponctuelles pour +la configuration ordinaire. Ils devraient déclarer des manifestes de paramètres et laisser ObjectOS +afficher et stocker les valeurs de manière cohérente. + +## Ordre de résolution + +Chaque paramètre déclare une portée (`global`, `tenant` ou `user`). Le +résolveur parcourt la cascade de la priorité la plus élevée à la plus basse, et la +première valeur définie l'emporte : + +```text +Environment override (locked) +Global setting +Tenant setting +User setting +Manifest default +``` + +Les surcharges d'environnement sont verrouillées. Si une valeur est définie via une +variable d'environnement, l'interface de la Console l'affiche comme gérée par l'hôte +et rejette les modifications à l'exécution. Une valeur verrouillée à n'importe quel niveau supérieur de la chaîne +verrouille également la valeur effective, de sorte que les portées inférieures ne peuvent pas la masquer. + +## Domaines de paramètres courants + +Les paramètres destinés aux clients incluent généralement : + +| Domaine | Exemples | +|---|---| +| Email | Hôte SMTP, clé API du fournisseur, adresse d'expéditeur, email de test | +| Image de marque | Nom du produit, URL du logo, couleur d'accentuation, thème par défaut | +| Indicateurs de fonctionnalités | Commutateurs de fonctionnalités au niveau du tenant | +| Stockage | Système de fichiers local ou identifiants de stockage d'objets | +| Fournisseurs d'IA | Fournisseur de modèle, clé API, limites de budget | +| SSO | Paramètres du fournisseur OIDC et test de connexion | + +## Secrets + +Les champs de mot de passe et d'identifiants devraient être chiffrés par le service +de paramètres ou fournis sous forme de valeurs gérées par l'environnement. Lorsqu'un fournisseur +de secrets est configuré, le service de paramètres stocke le texte chiffré dans +`sys_secret` et ne conserve qu'une référence dans `sys_setting`. Ne stockez pas +de secrets dans des artefacts, des fichiers compose ou Git. + +## Actions de test + +Les manifestes de paramètres peuvent déclarer des boutons d'action standard, tels que : + +- envoyer un email de test ; +- tester la découverte SSO ; +- vérifier les identifiants de stockage d'objets ; +- valider la cible d'un webhook. + +Utilisez ces actions pour les flux de configuration des clients plutôt que de demander aux opérateurs +d'inspecter d'abord les journaux. + +## Connexes + +Plusieurs domaines de paramètres disposent de guides de configuration dédiés : + +- [Email](/docs/configure/email) +- [Stockage](/docs/configure/storage) +- [Fournisseurs d'IA](/docs/configure/ai) +- [Authentification et SSO](/docs/configure/authentication) +- [Exécution](/docs/configure/runtime) diff --git a/content/docs/configure/system-settings.ja.mdx b/content/docs/configure/system-settings.ja.mdx new file mode 100644 index 0000000..7d0c4f1 --- /dev/null +++ b/content/docs/configure/system-settings.ja.mdx @@ -0,0 +1,87 @@ +--- +title: システム設定 +description: マニフェストと共有 K/V ストアを通じて、テナントおよびユーザーの設定を構成します。 +--- + +# システム設定 + +ObjectStack には、ランタイムおよびプラグインの設定を扱う設定サービスが含まれています。 +ObjectOS は、アプリケーションアーティファクトが設定機能を必要とする場合に、 +それらの設定を Console を通じて公開します。 + +## 設定モデル + +設定はコードによって宣言され、値として保存されます。 + +| レイヤー | 目的 | +|---|---| +| Settings Manifest | フィールド、ラベル、デフォルト値、検証、表示/非表示、アクションを定義します | +| `sys_setting` | テナント/ユーザーの K/V 値を保存します | +| Resolver | 有効な値を読み取ります | +| Console UI | 標準の設定ページをレンダリングします | + +プラグインは、通常の構成のために一回限りの設定テーブルを作成すべきではありません。 +設定マニフェストを宣言し、ObjectOS に値のレンダリングと保存を +一貫して任せるべきです。 + +## 解決順序 + +各設定はスコープ(`global`、`tenant`、または `user`)を宣言します。 +リゾルバは優先度の高いものから低いものへとカスケードをたどり、 +最初に設定されている値が採用されます。 + +```text +Environment override (locked) +Global setting +Tenant setting +User setting +Manifest default +``` + +環境オーバーライドはロックされています。値が環境変数を通じて設定されている場合、 +Console UI はそれをホストによって管理されていると表示し、ランタイムでの編集を +拒否します。チェーンの上位のいずれかでロックされた値があると、有効な値も +ロックされるため、下位のスコープはそれを上書きできません。 + +## 一般的な設定領域 + +顧客向けの設定には通常、以下が含まれます。 + +| 領域 | 例 | +|---|---| +| Email | SMTP ホスト、プロバイダー API キー、送信元アドレス、テストメール | +| Branding | 製品名、ロゴ URL、アクセントカラー、デフォルトテーマ | +| Feature flags | テナントレベルの機能スイッチ | +| Storage | ローカルファイルシステムまたはオブジェクトストレージの認証情報 | +| AI providers | モデルプロバイダー、API キー、予算上限 | +| SSO | OIDC プロバイダー設定および接続テスト | + +## シークレット + +パスワードや認証情報のフィールドは、設定サービスによって暗号化されるか、 +環境管理された値として提供されるべきです。シークレットプロバイダーが構成されている場合、 +設定サービスは暗号文を `sys_secret` に保存し、`sys_setting` にはハンドルのみを +保持します。シークレットをアーティファクト、compose ファイル、または Git に +保存しないでください。 + +## テストアクション + +設定マニフェストでは、次のような標準のアクションボタンを宣言できます。 + +- テストメールを送信する +- SSO ディスカバリをテストする +- オブジェクトストレージの認証情報を検証する +- webhook ターゲットを検証する + +オペレーターに最初にログを確認させるのではなく、顧客のセットアップフローには +これらのアクションを使用してください。 + +## 関連項目 + +いくつかの設定領域には専用の構成ガイドがあります。 + +- [Email](/docs/configure/email) +- [Storage](/docs/configure/storage) +- [AI providers](/docs/configure/ai) +- [Authentication and SSO](/docs/configure/authentication) +- [Runtime](/docs/configure/runtime) diff --git a/content/docs/configure/system-settings.mdx b/content/docs/configure/system-settings.mdx index e26a5d5..4259c9a 100644 --- a/content/docs/configure/system-settings.mdx +++ b/content/docs/configure/system-settings.mdx @@ -26,18 +26,22 @@ render and store values consistently. ## Resolution order -Effective values resolve in this order: +Each setting declares a scope (`global`, `tenant`, or `user`). The +resolver walks the cascade from highest to lowest precedence and the +first value that is set wins: ```text -Environment override +Environment override (locked) +Global setting Tenant setting User setting Manifest default ``` Environment overrides are locked. If a value is set through an -environment variable, the Console UI should show it as managed by the host -and reject runtime edits. +environment variable, the Console UI shows it as managed by the host +and rejects runtime edits. A locked value anywhere up the chain also +locks the effective value, so lower scopes cannot shadow it. ## Common settings areas @@ -55,8 +59,10 @@ Customer-facing settings usually include: ## Secrets Password and credential fields should be encrypted by the settings -service or provided as environment-managed values. Do not store secrets -in artifacts, compose files, or Git. +service or provided as environment-managed values. When a secret +provider is configured, the settings service stores the ciphertext in +`sys_secret` and keeps only a handle in `sys_setting`. Do not store +secrets in artifacts, compose files, or Git. ## Test actions @@ -69,3 +75,13 @@ Settings manifests can declare standard action buttons, such as: Use these actions for customer setup flows instead of asking operators to inspect logs first. + +## Related + +Several settings areas have dedicated configuration guides: + +- [Email](/docs/configure/email) +- [Storage](/docs/configure/storage) +- [AI providers](/docs/configure/ai) +- [Authentication and SSO](/docs/configure/authentication) +- [Runtime](/docs/configure/runtime) diff --git a/content/docs/configure/system-settings.zh-Hans.mdx b/content/docs/configure/system-settings.zh-Hans.mdx new file mode 100644 index 0000000..b392ce9 --- /dev/null +++ b/content/docs/configure/system-settings.zh-Hans.mdx @@ -0,0 +1,80 @@ +--- +title: 系统设置 +description: 通过清单(manifest)和共享的 K/V 存储配置租户与用户设置。 +--- + +# 系统设置 + +ObjectStack 包含一个用于运行时和插件设置的设置服务。 +当应用工件需要设置能力时,ObjectOS 会通过 Console 暴露这些设置。 + +## 设置模型 + +设置由代码声明,并以值的形式存储: + +| 层级 | 用途 | +|---|---| +| Settings Manifest | 定义字段、标签、默认值、校验、可见性以及操作 | +| `sys_setting` | 存储租户/用户的 K/V 值 | +| Resolver | 读取生效的值 | +| Console UI | 渲染标准的设置页面 | + +对于普通配置,插件不应创建一次性的设置表。 +它们应当声明设置清单,并让 ObjectOS 一致地渲染和存储这些值。 + +## 解析顺序 + +每项设置都声明一个作用域(`global`、`tenant` 或 `user`)。 +解析器按从最高到最低的优先级遍历这个层叠结构,第一个已设置的值生效: + +```text +Environment override (locked) +Global setting +Tenant setting +User setting +Manifest default +``` + +环境覆盖是锁定的。如果某个值是通过环境变量设置的,Console UI 会将其 +显示为由主机托管,并拒绝运行时编辑。链路中更上层的任何锁定值也会锁定 +生效的值,因此更低层的作用域无法将其遮盖。 + +## 常见设置领域 + +面向客户的设置通常包括: + +| 领域 | 示例 | +|---|---| +| Email | SMTP 主机、提供商 API key、发件地址、测试邮件 | +| Branding | 产品名称、Logo URL、强调色、默认主题 | +| Feature flags | 租户级功能开关 | +| Storage | 本地文件系统或对象存储凭据 | +| AI providers | 模型提供商、API key、预算上限 | +| SSO | OIDC 提供商设置以及测试连接 | + +## 机密信息 + +密码和凭据字段应由设置服务加密,或以环境托管的值提供。当配置了机密提供商时, +设置服务会将密文存储在 `sys_secret` 中,并在 `sys_setting` 中只保留一个句柄。 +不要将机密信息存储在工件、compose 文件或 Git 中。 + +## 测试操作 + +设置清单可以声明标准的操作按钮,例如: + +- 发送测试邮件; +- 测试 SSO discovery; +- 验证对象存储凭据; +- 校验 webhook 目标。 + +在客户配置流程中使用这些操作,而不是要求运维人员先去翻查日志。 + +## 相关内容 + +若干设置领域有专门的配置指南: + +- [Email](/docs/configure/email) +- [Storage](/docs/configure/storage) +- [AI providers](/docs/configure/ai) +- [Authentication and SSO](/docs/configure/authentication) +- [Runtime](/docs/configure/runtime) diff --git a/content/docs/configure/webhooks.cn.mdx b/content/docs/configure/webhooks.cn.mdx deleted file mode 100644 index cc98eee..0000000 --- a/content/docs/configure/webhooks.cn.mdx +++ /dev/null @@ -1,68 +0,0 @@ ---- -title: Webhook -description: 出站 Webhook 投递、签名与重试。 ---- - -# Webhook - -ObjectOS 对出站 Webhook 使用持久化的 **outbox** 模型。当 webhook 插件启用时,业务变更会入队一条投递行,由后台 dispatcher 带重试地投递——因此即便接收方缓慢或不可用,也不会阻塞触发业务的事务。 - -## 启用 Webhook - -Webhook 是可选能力。部署的 ObjectOS 镜像必须包含 `@objectstack/plugin-webhooks`,并且应用 artifact 必须注册 Webhook 订阅(通常作为 `sys_webhook` 对象的记录)。 - -启用后,Console 会出现两个对象: - -| 对象 | 用途 | -|---|---| -| `sys_webhook` | Webhook 订阅(目标 URL、事件过滤、secret、状态) | -| `sys_webhook_delivery` | 投递日志(URL、响应码、尝试次数、重试时间) | - -## 投递语义 - -- **至少一次。** 瞬时失败后可能重试;接收方必须幂等。 -- **持久化。** 投递记录存于业务数据库,因此在 ObjectOS 重启后仍然保留。 -- **分区。** 每个 dispatcher worker 认领 outbox 的一个分区,部署可以水平扩展投递而不会重复投递。 -- **有界重试。** 失败的投递按退避重试,直到可配置的上限;耗尽的行保留在 `sys_webhook_delivery` 供检查。 - -## 签名 - -当 Webhook 订阅设置了 `secret` 时,ObjectOS 会为每个请求签名: - -```text -X-Objectstack-Signature: sha256= -``` - -签名为 `HMAC-SHA256(secret, body)`,基于原始请求体计算。在接收端信任载荷前先验证它: - -```js -import { createHmac, timingSafeEqual } from 'node:crypto'; - -function verify(body, signatureHeader, secret) { - const expected = 'sha256=' + createHmac('sha256', secret).update(body).digest('hex'); - return timingSafeEqual(Buffer.from(signatureHeader), Buffer.from(expected)); -} -``` - -轮换 secret 的方式:使用新 secret 创建新订阅,过渡期同时运行两个订阅,然后停用旧的。 - -## 对接收方的要求 - -- 在数秒内返回 `2xx`。其他都视作失败并重试。 -- 任何非 2xx 都视为"不要提交"。dispatcher **不会**在你 ack 之前消费该行。 -- 幂等——基于 delivery id 头或你载荷中的 event id 去重。 - -## 失败处理 - -出错时: - -1. 检查 `sys_webhook_delivery` 中的行 —— 记录了 `response_code`、`response_body` 与 `attempt`。 -2. 确认从 ObjectOS 到接收方的出站网络可达。 -3. 如果接收方永久变更了,更新订阅 URL 并从 Console 重新投递该行。 -4. 用于事件复盘:审计日志(`sys_audit_log`)记录订阅编辑,但不记录载荷 —— 载荷保留在 outbox 中。 - -## 运维建议 - -- 不要把 secret 放进 Webhook URL(query string 会被记录)。 -- 使用独立的接收方主机名,便于在边缘屏蔽以减压时不影响主应用。 -- 关注 dispatcher 滞后——outbox 增长通常意味着接收方降级。 diff --git a/content/docs/configure/webhooks.de.mdx b/content/docs/configure/webhooks.de.mdx new file mode 100644 index 0000000..b416a11 --- /dev/null +++ b/content/docs/configure/webhooks.de.mdx @@ -0,0 +1,113 @@ +--- +title: Webhooks +description: Ausgehende Webhook-Zustellung, Signierung und erneute Zustellversuche. +--- + +# Webhooks + +ObjectOS verwendet ein persistentes **Outbox**-Modell für ausgehende +Webhooks. Wenn das Webhook-Plugin aktiviert ist, reihen +Geschäftsänderungen eine Zustellungszeile in die Warteschlange ein, und +ein Hintergrund-Dispatcher stellt sie mit erneuten Versuchen zu — sodass +ein langsamer oder nicht verfügbarer Empfänger niemals die auslösende +Transaktion blockiert. + +## Webhooks aktivieren + +Webhooks sind eine optionale Funktion. Das bereitgestellte ObjectOS-Image +muss `@objectstack/plugin-webhooks` enthalten, und das Anwendungsartefakt +muss Webhook-Abonnements registrieren (typischerweise als Datensätze +eines `sys_webhook`-Objekts). + +Wenn aktiviert, erscheinen zwei Objekte in der Console: + +| Objekt | Zweck | +|---|---| +| `sys_webhook` | Webhook-Abonnement (Ziel-URL, Ereignisfilter, Secret, Status) | +| `sys_webhook_delivery` | Zustellungsprotokoll (URL, Antwortcode, Anzahl der Versuche, Zeitstempel des erneuten Versuchs) | + +## Zustellungssemantik + +- **At-least-once.** Eine Zustellung kann nach einem vorübergehenden + Fehler erneut versucht werden; Empfänger müssen idempotent sein. +- **Persistent.** Zustellungen überstehen ObjectOS-Neustarts, da sie in + der Geschäftsdatenbank gespeichert sind. +- **Partitioniert.** Jeder Dispatcher-Worker beansprucht eine Partition + der Outbox, sodass Deployments den Versand horizontal skalieren können, + ohne doppelte Zustellung. +- **Begrenzte erneute Versuche.** Fehlgeschlagene Zustellungen werden mit + Backoff bis zu einer konfigurierbaren Obergrenze erneut versucht; + erschöpfte Zeilen verbleiben zur Inspektion in `sys_webhook_delivery`. + +## Signierung + +Jede Zustellung trägt identifizierende Header, damit Empfänger sie +weiterleiten, deduplizieren und verifizieren können: + +```text +X-Objectstack-Event: +X-Objectstack-Delivery: +X-Objectstack-Attempt: +``` + +Wenn ein Webhook-Abonnement über ein `secret` verfügt, signiert ObjectOS +außerdem jede Anfrage: + +```text +X-Objectstack-Signature: sha256= +``` + +Die Signatur ist `HMAC-SHA256(secret, body)`, berechnet über den rohen +Anfragetext. Verifizieren Sie sie auf dem Empfänger, bevor Sie der +Nutzlast vertrauen: + +```js +import { createHmac, timingSafeEqual } from 'node:crypto'; + +function verify(body, signatureHeader, secret) { + const expected = 'sha256=' + createHmac('sha256', secret).update(body).digest('hex'); + return timingSafeEqual(Buffer.from(signatureHeader), Buffer.from(expected)); +} +``` + +Rotieren Sie Secrets, indem Sie ein neues Abonnement mit dem neuen Secret +ausstellen, beide für ein Übergangsfenster betreiben und dann das alte +deaktivieren. + +## Erwartungen an den Empfänger + +- Antworten Sie innerhalb weniger Sekunden mit `2xx`. Eine Antwort mit + `408`, `429` oder `5xx` (oder ein Timeout-/Transportfehler) ist erneut + versuchbar und wird mit Backoff erneut versucht. Jedes andere `4xx` + wird als dauerhafter Fehler behandelt und ohne weitere erneute Versuche + auf `dead` gesetzt. +- Der Dispatcher markiert eine Zustellung erst dann als erfolgreich, wenn + er ein `2xx` sieht, sodass ein fehlgeschlagener Empfänger die Zeile zur + Inspektion oder erneuten Zustellung in `sys_webhook_delivery` behält. +- Seien Sie idempotent — deduplizieren Sie anhand des + `X-Objectstack-Delivery`-Headers (der Zustellungs-ID) oder Ihrer eigenen + Ereignis-ID in der Nutzlast. + +## Fehlerbehandlung + +Wenn etwas fehlschlägt: + +1. Prüfen Sie `sys_webhook_delivery` auf die Zeile — `status`, + `response_code`, `response_body` und `attempts` werden aufgezeichnet. +2. Bestätigen Sie den ausgehenden Netzwerkzugriff von ObjectOS zum + Empfänger. +3. Wenn der Empfänger dauerhaft geändert wurde, aktualisieren Sie die + Abonnement-URL und stellen Sie die Zeile aus der Console erneut zu. +4. Für die Vorfallüberprüfung erfassen Audit-Logs (`sys_audit_log`) + Abonnementbearbeitungen, aber keine Nutzlasten — Nutzlasten verbleiben + in der Outbox. + +## Betriebstipps + +- Platzieren Sie keine Secrets in Webhook-URLs (Query-Strings werden + protokolliert). +- Verwenden Sie einen dedizierten Empfänger-Hostnamen, damit Sie Last + abwerfen können, indem Sie ihn am Edge blockieren, ohne die + Hauptanwendung zu beeinträchtigen. +- Beobachten Sie die Dispatcher-Latenz — eine wachsende Outbox bedeutet + in der Regel, dass der Empfänger beeinträchtigt ist. diff --git a/content/docs/configure/webhooks.es.mdx b/content/docs/configure/webhooks.es.mdx new file mode 100644 index 0000000..84f1570 --- /dev/null +++ b/content/docs/configure/webhooks.es.mdx @@ -0,0 +1,108 @@ +--- +title: Webhooks +description: Entrega, firma y reintentos de webhooks salientes. +--- + +# Webhooks + +ObjectOS utiliza un modelo de **outbox** persistente para los webhooks +salientes. Cuando el plugin de webhooks está habilitado, los cambios de +negocio encolan una fila de entrega y un despachador en segundo plano la +entrega con reintentos, de modo que un receptor lento o no disponible +nunca bloquea la transacción de origen. + +## Habilitar webhooks + +Los webhooks son una capacidad opcional. La imagen de ObjectOS desplegada +debe incluir `@objectstack/plugin-webhooks`, y el artefacto de la +aplicación debe registrar las suscripciones de webhook (normalmente como +registros de un objeto `sys_webhook`). + +Cuando están habilitados, aparecen dos objetos en la Console: + +| Objeto | Propósito | +|---|---| +| `sys_webhook` | Suscripción de webhook (URL de destino, filtro de eventos, secreto, estado) | +| `sys_webhook_delivery` | Registro de entrega (URL, código de respuesta, número de intentos, marca de tiempo de reintento) | + +## Semántica de entrega + +- **Al menos una vez.** Una entrega puede reintentarse tras un fallo + transitorio; los receptores deben ser idempotentes. +- **Persistente.** Las entregas sobreviven a los reinicios de ObjectOS + porque se almacenan en la base de datos de negocio. +- **Particionada.** Cada worker del despachador reclama una partición del + outbox para que los despliegues puedan escalar horizontalmente el + despacho sin entregas duplicadas. +- **Reintentos acotados.** Las entregas fallidas se reintentan con backoff + hasta un límite configurable; las filas agotadas permanecen en + `sys_webhook_delivery` para su inspección. + +## Firma + +Cada entrega lleva cabeceras de identificación para que los receptores +puedan enrutarla, deduplicarla y verificarla: + +```text +X-Objectstack-Event: +X-Objectstack-Delivery: +X-Objectstack-Attempt: +``` + +Cuando una suscripción de webhook tiene un `secret`, ObjectOS también +firma cada solicitud: + +```text +X-Objectstack-Signature: sha256= +``` + +La firma es `HMAC-SHA256(secret, body)` calculada sobre el cuerpo crudo de +la solicitud. Verifícala en el receptor antes de confiar en el payload: + +```js +import { createHmac, timingSafeEqual } from 'node:crypto'; + +function verify(body, signatureHeader, secret) { + const expected = 'sha256=' + createHmac('sha256', secret).update(body).digest('hex'); + return timingSafeEqual(Buffer.from(signatureHeader), Buffer.from(expected)); +} +``` + +Rota los secretos emitiendo una nueva suscripción con el nuevo secreto, +ejecutando ambas durante una ventana de transición y deshabilitando luego +la antigua. + +## Expectativas del receptor + +- Responde con `2xx` en unos pocos segundos. Una respuesta `408`, `429` o + `5xx` (o un timeout/error de transporte) es reintentable y se reintenta + con backoff. Cualquier otro `4xx` se trata como un fallo permanente y se + mueve a `dead` sin más reintentos. +- El despachador **no** marca una entrega como exitosa hasta que ve un + `2xx`, por lo que un receptor fallido mantiene la fila en + `sys_webhook_delivery` para su inspección o reentrega. +- Sé idempotente: deduplica usando la cabecera `X-Objectstack-Delivery` (el + identificador de entrega) o tu propio identificador de evento en el + payload. + +## Manejo de fallos + +Cuando algo falla: + +1. Revisa la fila en `sys_webhook_delivery`: se registran `status`, + `response_code`, `response_body` y `attempts`. +2. Confirma el acceso de red saliente desde ObjectOS al receptor. +3. Si el receptor cambió de forma permanente, actualiza la URL de la + suscripción y reentrega la fila desde la Console. +4. Para la revisión de incidentes, los registros de auditoría + (`sys_audit_log`) capturan las ediciones de las suscripciones, pero no + los payloads; los payloads permanecen en el outbox. + +## Consejos operativos + +- No pongas secretos en las URLs de los webhooks (las cadenas de consulta + quedan registradas). +- Usa un nombre de host de receptor dedicado para poder descargar tráfico + bloqueándolo en el borde sin afectar a la aplicación principal. +- Vigila el retraso del despachador: un outbox que crece normalmente + significa que el receptor está degradado. diff --git a/content/docs/configure/webhooks.fr.mdx b/content/docs/configure/webhooks.fr.mdx new file mode 100644 index 0000000..7acda6d --- /dev/null +++ b/content/docs/configure/webhooks.fr.mdx @@ -0,0 +1,114 @@ +--- +title: Webhooks +description: Livraison, signature et nouvelles tentatives des webhooks sortants. +--- + +# Webhooks + +ObjectOS utilise un modèle d'**outbox** persistant pour les webhooks +sortants. Lorsque le plugin de webhooks est activé, les changements +métier mettent en file d'attente une ligne de livraison, et un +distributeur en arrière-plan la livre avec des nouvelles tentatives — +de sorte qu'un récepteur lent ou indisponible ne bloque jamais la +transaction d'origine. + +## Activer les webhooks + +Les webhooks sont une capacité optionnelle. L'image ObjectOS déployée +doit inclure `@objectstack/plugin-webhooks`, et l'artefact applicatif +doit enregistrer des abonnements de webhooks (généralement sous forme +d'enregistrements d'un objet `sys_webhook`). + +Une fois activés, deux objets apparaissent dans la Console : + +| Objet | Rôle | +|---|---| +| `sys_webhook` | Abonnement au webhook (URL cible, filtre d'événements, secret, statut) | +| `sys_webhook_delivery` | Journal de livraison (URL, code de réponse, nombre de tentatives, horodatage de la nouvelle tentative) | + +## Sémantique de livraison + +- **Au moins une fois.** Une livraison peut être retentée après un + échec transitoire ; les récepteurs doivent être idempotents. +- **Persistante.** Les livraisons survivent aux redémarrages d'ObjectOS + car elles sont stockées dans la base de données métier. +- **Partitionnée.** Chaque worker du distributeur revendique une + partition de l'outbox, de sorte que les déploiements peuvent mettre à + l'échelle horizontalement la distribution sans double livraison. +- **Nouvelles tentatives bornées.** Les livraisons échouées sont + retentées avec un délai progressif jusqu'à un plafond configurable ; + les lignes épuisées restent dans `sys_webhook_delivery` pour + inspection. + +## Signature + +Chaque livraison comporte des en-têtes d'identification afin que les +récepteurs puissent l'acheminer, la dédupliquer et la vérifier : + +```text +X-Objectstack-Event: +X-Objectstack-Delivery: +X-Objectstack-Attempt: +``` + +Lorsqu'un abonnement de webhook possède un `secret`, ObjectOS signe +également chaque requête : + +```text +X-Objectstack-Signature: sha256= +``` + +La signature est `HMAC-SHA256(secret, body)`, calculée sur le corps brut +de la requête. Vérifiez-la côté récepteur avant de faire confiance à la +charge utile : + +```js +import { createHmac, timingSafeEqual } from 'node:crypto'; + +function verify(body, signatureHeader, secret) { + const expected = 'sha256=' + createHmac('sha256', secret).update(body).digest('hex'); + return timingSafeEqual(Buffer.from(signatureHeader), Buffer.from(expected)); +} +``` + +Faites tourner les secrets en créant un nouvel abonnement avec le +nouveau secret, en exécutant les deux pendant une fenêtre de transition, +puis en désactivant l'ancien. + +## Attentes côté récepteur + +- Répondez avec un `2xx` en quelques secondes. Une réponse `408`, `429` + ou `5xx` (ou un délai d'attente / une erreur de transport) est + retentable et donne lieu à une nouvelle tentative avec délai + progressif. Tout autre `4xx` est traité comme un échec permanent et + déplacé vers `dead` sans nouvelle tentative. +- Le distributeur ne marque **pas** une livraison comme réussie tant + qu'il ne reçoit pas un `2xx` ; ainsi, un récepteur défaillant conserve + la ligne dans `sys_webhook_delivery` pour inspection ou nouvelle + livraison. +- Soyez idempotent — dédupliquez sur l'en-tête `X-Objectstack-Delivery` + (l'identifiant de livraison) ou sur votre propre identifiant + d'événement dans la charge utile. + +## Gestion des échecs + +Lorsqu'une erreur survient : + +1. Consultez la ligne dans `sys_webhook_delivery` — `status`, + `response_code`, `response_body` et `attempts` y sont enregistrés. +2. Vérifiez l'accès réseau sortant d'ObjectOS vers le récepteur. +3. Si le récepteur a été modifié de façon permanente, mettez à jour + l'URL de l'abonnement et relivrez la ligne depuis la Console. +4. Pour l'analyse des incidents, les journaux d'audit + (`sys_audit_log`) capturent les modifications d'abonnement mais pas + les charges utiles — celles-ci restent dans l'outbox. + +## Conseils opérationnels + +- Ne placez pas de secrets dans les URL de webhook (les chaînes de + requête sont journalisées). +- Utilisez un nom d'hôte de récepteur dédié afin de pouvoir délester la + charge en le bloquant en périphérie sans affecter l'application + principale. +- Surveillez le retard du distributeur — un outbox qui grossit signifie + généralement que le récepteur est dégradé. diff --git a/content/docs/configure/webhooks.ja.mdx b/content/docs/configure/webhooks.ja.mdx new file mode 100644 index 0000000..87eed79 --- /dev/null +++ b/content/docs/configure/webhooks.ja.mdx @@ -0,0 +1,108 @@ +--- +title: Webhooks +description: アウトバウンド Webhook の配信、署名、リトライ。 +--- + +# Webhooks + +ObjectOS はアウトバウンド Webhook に永続的な **アウトボックス** モデルを +使用します。Webhook プラグインが有効になっている場合、業務上の変更によって +配信行がキューに追加され、バックグラウンドのディスパッチャーがリトライ付きで +配信します。これにより、受信側が遅延したり利用できなかったりしても、元の +トランザクションがブロックされることはありません。 + +## Webhook の有効化 + +Webhook はオプションの機能です。デプロイされた ObjectOS イメージに +`@objectstack/plugin-webhooks` が含まれている必要があり、アプリケーション +アーティファクトが Webhook サブスクリプション(通常は `sys_webhook` +オブジェクトのレコードとして)を登録する必要があります。 + +有効化すると、Console に 2 つのオブジェクトが表示されます。 + +| オブジェクト | 目的 | +|---|---| +| `sys_webhook` | Webhook サブスクリプション(ターゲット URL、イベントフィルター、シークレット、ステータス) | +| `sys_webhook_delivery` | 配信ログ(URL、レスポンスコード、試行回数、リトライのタイムスタンプ) | + +## 配信のセマンティクス + +- **At-least-once(最低 1 回)。** 一時的な障害の後に配信がリトライされる + ことがあります。受信側は冪等である必要があります。 +- **永続的。** 配信は業務データベースに保存されるため、ObjectOS の再起動後も + 保持されます。 +- **パーティション化。** 各ディスパッチャーワーカーはアウトボックスの + パーティションを取得するため、デプロイメントは二重配信なしで配信を水平 + スケールできます。 +- **リトライ回数の上限あり。** 失敗した配信は設定可能な上限までバックオフ + 付きでリトライされます。リトライを使い切った行は調査のために + `sys_webhook_delivery` に残ります。 + +## 署名 + +すべての配信には、受信側がルーティング、重複排除、検証できるように識別用の +ヘッダーが含まれます。 + +```text +X-Objectstack-Event: +X-Objectstack-Delivery: +X-Objectstack-Attempt: +``` + +Webhook サブスクリプションに `secret` が設定されている場合、ObjectOS は +すべてのリクエストにも署名します。 + +```text +X-Objectstack-Signature: sha256= +``` + +署名は、生のリクエストボディに対して計算された +`HMAC-SHA256(secret, body)` です。ペイロードを信頼する前に、受信側で検証 +してください。 + +```js +import { createHmac, timingSafeEqual } from 'node:crypto'; + +function verify(body, signatureHeader, secret) { + const expected = 'sha256=' + createHmac('sha256', secret).update(body).digest('hex'); + return timingSafeEqual(Buffer.from(signatureHeader), Buffer.from(expected)); +} +``` + +シークレットをローテーションするには、新しいシークレットで新しい +サブスクリプションを発行し、移行期間中は両方を稼働させてから、古いものを +無効化します。 + +## 受信側に求められること + +- 数秒以内に `2xx` で応答してください。`408`、`429`、`5xx` のレスポンス + (またはタイムアウト/トランスポートエラー)はリトライ可能で、バックオフ + 付きでリトライされます。その他の `4xx` は永続的な障害として扱われ、 + それ以上のリトライなしで `dead` に移されます。 +- ディスパッチャーは `2xx` を確認するまで配信を成功とマークしません。 + そのため、受信に失敗すると、その行は調査または再配信のために + `sys_webhook_delivery` に残ります。 +- 冪等にしてください。`X-Objectstack-Delivery` ヘッダー(配信 ID)または + ペイロード内の独自のイベント ID で重複排除します。 + +## 障害への対処 + +何かが失敗した場合は次のとおりです。 + +1. `sys_webhook_delivery` で該当の行を確認します。`status`、 + `response_code`、`response_body`、`attempts` が記録されています。 +2. ObjectOS から受信側へのアウトバウンドネットワークアクセスを確認します。 +3. 受信側が恒久的に変更された場合は、サブスクリプションの URL を更新し、 + Console から行を再配信します。 +4. インシデントレビューのために、監査ログ(`sys_audit_log`)には + サブスクリプションの編集は記録されますが、ペイロードは記録されません。 + ペイロードはアウトボックスに残ります。 + +## 運用のヒント + +- Webhook URL にシークレットを入れないでください(クエリ文字列はログに + 記録されます)。 +- 専用の受信側ホスト名を使用すると、メインアプリに影響を与えることなく、 + エッジでブロックして負荷を切り離すことができます。 +- ディスパッチャーの遅延を監視してください。アウトボックスが増加し続ける + 場合、通常は受信側が劣化していることを意味します。 diff --git a/content/docs/configure/webhooks.mdx b/content/docs/configure/webhooks.mdx index de0030d..5826ed8 100644 --- a/content/docs/configure/webhooks.mdx +++ b/content/docs/configure/webhooks.mdx @@ -39,7 +39,16 @@ When enabled, two objects show up in the Console: ## Signing -When a webhook subscription has a `secret`, ObjectOS signs every +Every delivery carries identifying headers so receivers can route, +deduplicate, and verify it: + +```text +X-Objectstack-Event: +X-Objectstack-Delivery: +X-Objectstack-Attempt: +``` + +When a webhook subscription has a `secret`, ObjectOS also signs every request: ```text @@ -63,19 +72,22 @@ running both for a transition window, then disabling the old one. ## Receiver expectations -- Respond with `2xx` within a few seconds. Anything else is treated as - a failure and retried. -- Treat any non-2xx as "do not commit." The dispatcher does **not** - consume the row until you ack. -- Be idempotent — deduplicate on the delivery id header or your own - event id in the payload. +- Respond with `2xx` within a few seconds. A `408`, `429`, or `5xx` + response (or a timeout/transport error) is retriable and gets retried + with backoff. Any other `4xx` is treated as a permanent failure and + moved to `dead` without further retries. +- The dispatcher does **not** mark a delivery successful until it sees a + `2xx`, so a failed receiver keeps the row in `sys_webhook_delivery` for + inspection or redelivery. +- Be idempotent — deduplicate on the `X-Objectstack-Delivery` header (the + delivery id) or your own event id in the payload. ## Failure handling When something fails: -1. Check `sys_webhook_delivery` for the row — `response_code`, - `response_body`, and `attempt` are recorded. +1. Check `sys_webhook_delivery` for the row — `status`, `response_code`, + `response_body`, and `attempts` are recorded. 2. Confirm outbound network access from ObjectOS to the receiver. 3. If the receiver was permanently changed, update the subscription URL and re-deliver the row from the Console. diff --git a/content/docs/configure/webhooks.zh-Hans.mdx b/content/docs/configure/webhooks.zh-Hans.mdx new file mode 100644 index 0000000..41c444a --- /dev/null +++ b/content/docs/configure/webhooks.zh-Hans.mdx @@ -0,0 +1,76 @@ +--- +title: Webhooks +description: 出站 webhook 投递、签名与重试。 +--- + +# Webhooks + +ObjectOS 为出站 webhook 采用持久化的 **outbox** 模型。当 webhook 插件启用时,业务变更会将一条投递记录入队,由后台 dispatcher 带重试地完成投递——因此响应缓慢或不可用的接收方永远不会阻塞发起方事务。 + +## 启用 webhooks + +Webhooks 是一项可选能力。部署的 ObjectOS 镜像必须包含 `@objectstack/plugin-webhooks`,并且应用 artifact 必须注册 webhook 订阅(通常作为 `sys_webhook` 对象的记录)。 + +启用后,Console 中会出现两个对象: + +| 对象 | 用途 | +|---|---| +| `sys_webhook` | Webhook 订阅(目标 URL、事件过滤器、secret、状态) | +| `sys_webhook_delivery` | 投递日志(URL、响应码、尝试次数、重试时间戳) | + +## 投递语义 + +- **至少一次。** 投递在发生瞬时失败后可能被重试;接收方必须是幂等的。 +- **持久化。** 投递记录会在 ObjectOS 重启后保留,因为它们存储在业务数据库中。 +- **分区。** 每个 dispatcher worker 认领 outbox 的一个分区,使部署能够横向扩展投递而不会重复投递。 +- **有界重试。** 失败的投递会以退避策略重试,直至达到可配置的上限;耗尽重试的记录会保留在 `sys_webhook_delivery` 中以供检查。 + +## 签名 + +每次投递都携带标识性请求头,使接收方能够路由、去重并校验它: + +```text +X-Objectstack-Event: +X-Objectstack-Delivery: +X-Objectstack-Attempt: +``` + +当 webhook 订阅设置了 `secret` 时,ObjectOS 还会为每个请求签名: + +```text +X-Objectstack-Signature: sha256= +``` + +签名为 `HMAC-SHA256(secret, body)`,基于原始请求体计算。在接收端信任载荷前先校验它: + +```js +import { createHmac, timingSafeEqual } from 'node:crypto'; + +function verify(body, signatureHeader, secret) { + const expected = 'sha256=' + createHmac('sha256', secret).update(body).digest('hex'); + return timingSafeEqual(Buffer.from(signatureHeader), Buffer.from(expected)); +} +``` + +轮换 secret 的方式:使用新 secret 创建一个新订阅,在过渡期同时运行两者,然后停用旧订阅。 + +## 对接收方的要求 + +- 在数秒内返回 `2xx`。`408`、`429` 或 `5xx` 响应(或超时/传输错误)是可重试的,会以退避策略重试。任何其他 `4xx` 都被视为永久性失败,并在不再重试的情况下转入 `dead`。 +- 在看到 `2xx` 之前,dispatcher **不会**将投递标记为成功,因此失败的接收方会使该记录保留在 `sys_webhook_delivery` 中,以供检查或重新投递。 +- 保持幂等——基于 `X-Objectstack-Delivery` 请求头(delivery id)或你自己在载荷中的 event id 去重。 + +## 失败处理 + +出错时: + +1. 检查 `sys_webhook_delivery` 中的记录——`status`、`response_code`、`response_body` 与 `attempts` 均有记录。 +2. 确认从 ObjectOS 到接收方的出站网络可达。 +3. 如果接收方永久变更了,更新订阅 URL 并从 Console 重新投递该记录。 +4. 用于事件复盘:审计日志(`sys_audit_log`)记录订阅编辑,但不记录载荷——载荷保留在 outbox 中。 + +## 运维建议 + +- 不要把 secret 放进 webhook URL(query string 会被记录)。 +- 使用独立的接收方主机名,便于在边缘屏蔽以卸载流量时不影响主应用。 +- 关注 dispatcher 滞后——outbox 不断增长通常意味着接收方降级。 diff --git a/content/docs/deploy/air-gapped.cn.mdx b/content/docs/deploy/air-gapped.cn.mdx deleted file mode 100644 index f175d09..0000000 --- a/content/docs/deploy/air-gapped.cn.mdx +++ /dev/null @@ -1,52 +0,0 @@ ---- -title: 气隙部署 -description: 在无公网访问的环境下运行 ObjectOS。 ---- - -# 气隙部署 - -气隙部署面向那些 ObjectOS 在运行时不能访问托管控制面或公共包仓库的客户网络。 - -## 需要打包发布什么 - -一个离线发布包应包含: - -| 项 | 用途 | -|---|---| -| ObjectOS 容器镜像 | 运行时二进制与依赖 | -| `objectstack.json` 产物 | 不可变应用定义 | -| 数据库迁移/初始化指南 | 客户业务数据库初始化 | -| 环境模板 | 必需的密钥与运行时变量 | -| 运维清单 | 升级、回滚、备份与诊断 | - -## 运行时模式 - -使用文件支持模式: - -```bash -OS_ARTIFACT_FILE=/artifacts/objectstack.json -``` - -ObjectOS 把每个请求解析到打包好的项目,并从磁盘加载产物。 - -## 网络预期 - -在此模式下 ObjectOS 不需要公网访问。客户网络规则应只允许: - -- 来自经批准的 Ingress 或负载均衡器的入站 HTTP/HTTPS; -- 到客户自管业务数据库的出站数据库流量; -- 到显式配置集成(如 SMTP、对象存储、Webhook 目标或身份提供方)的出站流量。 - -## 认证 - -如果客户使用 OIDC/SSO,身份提供方必须从气隙网络可达。否则使用本地邮箱/密码认证,或在同一网络内托管的身份提供方。 - -## 升级流程 - -把产物视为不可变: - -1. 导入新的 ObjectOS 镜像。 -2. 把新产物放在旧产物旁边。 -3. 更新挂载或环境变量,指向新产物。 -4. 重启 ObjectOS。 -5. 回滚时恢复上一个镜像 tag 或产物路径。 diff --git a/content/docs/deploy/air-gapped.de.mdx b/content/docs/deploy/air-gapped.de.mdx new file mode 100644 index 0000000..5863695 --- /dev/null +++ b/content/docs/deploy/air-gapped.de.mdx @@ -0,0 +1,72 @@ +--- +title: Air-Gapped-Deployment +description: ObjectOS ohne Zugang zum öffentlichen Internet betreiben. +--- + +# Air-Gapped-Deployment + +Air-Gapped-Deployment ist für Kundennetzwerke gedacht, in denen ObjectOS zur +Laufzeit keine gehostete Control Plane oder öffentliche Paket-Registries +aufrufen kann. + +## Was ausgeliefert werden muss + +Ein Offline-Release-Bundle sollte Folgendes enthalten: + +| Element | Zweck | +|---|---| +| ObjectOS-Container-Image | Laufzeitbinärdatei und Abhängigkeiten | +| `objectstack.json`-Artefakt | Unveränderliche Anwendungsdefinition | +| Anleitung zur Datenbankmigration/-initialisierung | Einrichtung der Kunden-Geschäftsdatenbank | +| Umgebungsvorlage | Erforderliche Secrets und Laufzeitvariablen | +| Betriebs-Checkliste | Upgrade, Rollback, Backup und Diagnose | + +Das Container-Image und das Einbinden des Artefakts folgen denselben +Konventionen wie ein standardmäßiges [Docker-Deployment](/docs/deploy/docker); +nur die Netzwerkkonfiguration unterscheidet sich. + +## Laufzeitmodus + +Verwenden Sie den dateibasierten Modus: Verweisen Sie ObjectOS auf ein lokales +Artefakt und eine vom Kunden verwaltete Geschäftsdatenbank und lassen Sie die +Cloud-Control-Plane nicht gesetzt. + +```bash +OS_ARTIFACT_FILE=/artifacts/objectstack.json +OS_BUSINESS_DB_URL=file:/var/lib/objectos/data.db +# Leave OS_CLOUD_URL unset to run fully offline +``` + +ObjectOS löst jede Anfrage zum gebündelten Projekt auf und lädt das Artefakt +von der Festplatte. Wenn `OS_CLOUD_URL` nicht gesetzt ist, werden keine Aufrufe +an eine gehostete Control Plane getätigt. + +## Netzwerkanforderungen + +In diesem Modus benötigt ObjectOS keinen Zugang zum öffentlichen Internet. Die +Netzwerkregeln des Kunden sollten nur Folgendes zulassen: + +- eingehenden HTTP/HTTPS-Verkehr vom genehmigten Ingress oder Load Balancer; +- ausgehenden Datenbankverkehr zur vom Kunden verwalteten Geschäftsdatenbank; +- ausgehenden Verkehr zu explizit konfigurierten Integrationen wie SMTP, + Object Storage, Webhook-Zielen oder Identity-Providern. + +## Authentifizierung + +Wenn der Kunde OIDC/SSO verwendet, muss der Identity-Provider aus dem +Air-Gapped-Netzwerk erreichbar sein. Andernfalls verwenden Sie eine lokale +E-Mail/Passwort-Authentifizierung oder einen innerhalb desselben Netzwerks +gehosteten Identity-Provider. + +## Upgrade-Prozess + +Behandeln Sie Artefakte als unveränderlich: + +1. Importieren Sie das neue ObjectOS-Image. +2. Legen Sie das neue Artefakt neben das vorherige Artefakt. +3. Aktualisieren Sie den Mount oder die Umgebungsvariable, sodass sie auf das neue Artefakt verweisen. +4. Starten Sie ObjectOS neu. +5. Führen Sie ein Rollback durch, indem Sie das vorherige Image-Tag oder den vorherigen Artefaktpfad wiederherstellen. + +Vollständige Anleitungen zu diesen zusammengefassten Schritten finden Sie unter +[Upgrade](/docs/operate/upgrade) und [Backup](/docs/operate/backup). diff --git a/content/docs/deploy/air-gapped.es.mdx b/content/docs/deploy/air-gapped.es.mdx new file mode 100644 index 0000000..0ebf9c3 --- /dev/null +++ b/content/docs/deploy/air-gapped.es.mdx @@ -0,0 +1,71 @@ +--- +title: Despliegue air-gapped +description: Ejecuta ObjectOS sin acceso a la red pública de internet. +--- + +# Despliegue air-gapped + +El despliegue air-gapped está pensado para redes de clientes donde ObjectOS no +puede llamar a un plano de control alojado ni a registros de paquetes públicos en +tiempo de ejecución. + +## Qué entregar + +Un paquete de versión sin conexión debe contener: + +| Elemento | Propósito | +|---|---| +| Imagen de contenedor de ObjectOS | Binario de runtime y dependencias | +| Artefacto `objectstack.json` | Definición de aplicación inmutable | +| Guía de migración/inicialización de la base de datos | Configuración de la base de datos de negocio del cliente | +| Plantilla de entorno | Secretos requeridos y variables de runtime | +| Lista de verificación de operaciones | Actualización, reversión, respaldo y diagnóstico | + +La imagen de contenedor y el montaje del artefacto siguen las mismas convenciones +que un [despliegue con Docker](/docs/deploy/docker) estándar; solo difiere la +postura de red. + +## Modo de runtime + +Usa el modo respaldado por archivos: apunta ObjectOS a un artefacto local y a una +base de datos de negocio gestionada por el cliente, y deja el plano de control en la +nube sin configurar. + +```bash +OS_ARTIFACT_FILE=/artifacts/objectstack.json +OS_BUSINESS_DB_URL=file:/var/lib/objectos/data.db +# Leave OS_CLOUD_URL unset to run fully offline +``` + +ObjectOS resuelve cada solicitud hacia el proyecto empaquetado y carga el artefacto +desde el disco. Con `OS_CLOUD_URL` sin configurar, no se realizan llamadas a un +plano de control alojado. + +## Expectativas de red + +ObjectOS no necesita acceso a internet público en este modo. Las reglas de red del +cliente solo deberían permitir: + +- tráfico HTTP/HTTPS entrante desde el ingress o balanceador de carga aprobado; +- tráfico saliente de base de datos hacia la base de datos de negocio gestionada por el cliente; +- tráfico saliente hacia integraciones configuradas explícitamente, como SMTP, + almacenamiento de objetos, destinos de webhook o proveedores de identidad. + +## Autenticación + +Si el cliente usa OIDC/SSO, el proveedor de identidad debe ser accesible desde la +red air-gapped. De lo contrario, usa autenticación local con correo/contraseña o un +proveedor de identidad alojado dentro de la misma red. + +## Proceso de actualización + +Trata los artefactos como inmutables: + +1. Importa la nueva imagen de ObjectOS. +2. Coloca el nuevo artefacto junto al artefacto anterior. +3. Actualiza el montaje o la variable de entorno para que apunte al nuevo artefacto. +4. Reinicia ObjectOS. +5. Revierte restaurando la etiqueta de imagen anterior o la ruta del artefacto anterior. + +Consulta [Actualización](/docs/operate/upgrade) y [Respaldo](/docs/operate/backup) +para los procedimientos completos que estos pasos resumen. diff --git a/content/docs/deploy/air-gapped.fr.mdx b/content/docs/deploy/air-gapped.fr.mdx new file mode 100644 index 0000000..cd07314 --- /dev/null +++ b/content/docs/deploy/air-gapped.fr.mdx @@ -0,0 +1,70 @@ +--- +title: Déploiement en réseau isolé +description: Exécuter ObjectOS sans accès à l'internet public. +--- + +# Déploiement en réseau isolé + +Le déploiement en réseau isolé (air-gapped) est destiné aux réseaux clients où ObjectOS ne peut pas +appeler un plan de contrôle hébergé ou des registres de paquets publics à l'exécution. + +## Ce qu'il faut livrer + +Un ensemble de release hors ligne doit contenir : + +| Élément | Objectif | +|---|---| +| Image de conteneur ObjectOS | Binaire d'exécution et dépendances | +| Artefact `objectstack.json` | Définition d'application immuable | +| Guide de migration/initialisation de la base de données | Configuration de la base de données métier du client | +| Modèle d'environnement | Secrets et variables d'exécution requis | +| Liste de contrôle des opérations | Mise à niveau, restauration, sauvegarde et diagnostics | + +L'image de conteneur et le montage de l'artefact suivent les mêmes conventions qu'un +[déploiement Docker](/docs/deploy/docker) standard ; seule la +posture réseau diffère. + +## Mode d'exécution + +Utilisez le mode adossé à des fichiers : pointez ObjectOS vers un artefact local et une +base de données métier gérée par le client, et laissez le plan de contrôle cloud +non défini. + +```bash +OS_ARTIFACT_FILE=/artifacts/objectstack.json +OS_BUSINESS_DB_URL=file:/var/lib/objectos/data.db +# Leave OS_CLOUD_URL unset to run fully offline +``` + +ObjectOS résout chaque requête vers le projet empaqueté et charge +l'artefact depuis le disque. Avec `OS_CLOUD_URL` non défini, aucun appel n'est effectué vers un +plan de contrôle hébergé. + +## Attentes réseau + +ObjectOS n'a pas besoin d'accès à l'internet public dans ce mode. Les règles du réseau +client ne doivent autoriser que : + +- le trafic HTTP/HTTPS entrant provenant de l'ingress ou de l'équilibreur de charge approuvé ; +- le trafic de base de données sortant vers la base de données métier gérée par le client ; +- le trafic sortant vers les intégrations explicitement configurées telles que SMTP, + le stockage objet, les cibles de webhook ou les fournisseurs d'identité. + +## Authentification + +Si le client utilise OIDC/SSO, le fournisseur d'identité doit être accessible +depuis le réseau isolé. Sinon, utilisez l'authentification locale par e-mail/mot de passe ou un +fournisseur d'identité hébergé à l'intérieur du même réseau. + +## Processus de mise à niveau + +Traitez les artefacts comme immuables : + +1. Importez la nouvelle image ObjectOS. +2. Placez le nouvel artefact à côté de l'artefact précédent. +3. Mettez à jour le montage ou la variable d'environnement pour qu'il pointe vers le nouvel artefact. +4. Redémarrez ObjectOS. +5. Effectuez une restauration en rétablissant le tag d'image précédent ou le chemin de l'artefact. + +Consultez [Mise à niveau](/docs/operate/upgrade) et [Sauvegarde](/docs/operate/backup) +pour les procédures complètes que ces étapes résument. diff --git a/content/docs/deploy/air-gapped.ja.mdx b/content/docs/deploy/air-gapped.ja.mdx new file mode 100644 index 0000000..125be0a --- /dev/null +++ b/content/docs/deploy/air-gapped.ja.mdx @@ -0,0 +1,71 @@ +--- +title: エアギャップ環境へのデプロイ +description: パブリックインターネットにアクセスせずに ObjectOS を実行します。 +--- + +# エアギャップ環境へのデプロイ + +エアギャップ環境へのデプロイは、ObjectOS が実行時にホスト型のコントロール +プレーンやパブリックなパッケージレジストリを呼び出せない顧客ネットワーク向けです。 + +## 何を配布するか + +オフラインのリリースバンドルには次のものを含めるべきです。 + +| 項目 | 目的 | +|---|---| +| ObjectOS コンテナイメージ | ランタイムバイナリと依存関係 | +| `objectstack.json` アーティファクト | 不変のアプリケーション定義 | +| データベースのマイグレーション/初期化ガイダンス | 顧客の業務データベースのセットアップ | +| 環境テンプレート | 必要なシークレットとランタイム変数 | +| 運用チェックリスト | アップグレード、ロールバック、バックアップ、診断 | + +コンテナイメージとアーティファクトのマウントは、標準的な +[Docker デプロイ](/docs/deploy/docker)と同じ規約に従います。異なるのは +ネットワークの構成だけです。 + +## ランタイムモード + +ファイルバックドモードを使用します。ObjectOS をローカルのアーティファクトと +顧客が管理する業務データベースに向け、クラウドのコントロールプレーンは +未設定のままにします。 + +```bash +OS_ARTIFACT_FILE=/artifacts/objectstack.json +OS_BUSINESS_DB_URL=file:/var/lib/objectos/data.db +# Leave OS_CLOUD_URL unset to run fully offline +``` + +ObjectOS はすべてのリクエストをパッケージ化されたプロジェクトに解決し、 +アーティファクトをディスクから読み込みます。`OS_CLOUD_URL` が未設定の場合、 +ホスト型のコントロールプレーンへの呼び出しは行われません。 + +## ネットワークの前提条件 + +このモードでは ObjectOS にパブリックインターネットへのアクセスは不要です。 +顧客のネットワークルールでは、以下のみを許可するべきです。 + +- 承認されたイングレスまたはロードバランサーからのインバウンド HTTP/HTTPS +- 顧客が管理する業務データベースへのアウトバウンドのデータベーストラフィック +- SMTP、オブジェクトストレージ、Webhook の宛先、ID プロバイダーなど、明示的に + 構成された連携先へのアウトバウンドトラフィック + +## 認証 + +顧客が OIDC/SSO を使用する場合、ID プロバイダーがエアギャップ環境の +ネットワークから到達可能でなければなりません。到達できない場合は、ローカルの +メール/パスワード認証、または同じネットワーク内でホストされている ID +プロバイダーを使用します。 + +## アップグレード手順 + +アーティファクトは不変なものとして扱います。 + +1. 新しい ObjectOS イメージをインポートします。 +2. 新しいアーティファクトを以前のアーティファクトと並べて配置します。 +3. マウントまたは環境変数を更新して、新しいアーティファクトを指すようにします。 +4. ObjectOS を再起動します。 +5. 以前のイメージタグまたはアーティファクトのパスを復元してロールバックします。 + +これらの手順がまとめている完全な手順については、[アップグレード](/docs/operate/upgrade) +および[バックアップ](/docs/operate/backup)を参照してください。 diff --git a/content/docs/deploy/air-gapped.mdx b/content/docs/deploy/air-gapped.mdx index 2e06fd5..eab8139 100644 --- a/content/docs/deploy/air-gapped.mdx +++ b/content/docs/deploy/air-gapped.mdx @@ -20,16 +20,25 @@ An offline release bundle should contain: | Environment template | Required secrets and runtime variables | | Operations checklist | Upgrade, rollback, backup, and diagnostics | +The container image and artifact mount follow the same conventions as a +standard [Docker deployment](/docs/deploy/docker); only the network +posture differs. + ## Runtime mode -Use file-backed mode: +Use file-backed mode: point ObjectOS at a local artifact and a +customer-managed business database, and leave the cloud control plane +unset. ```bash OS_ARTIFACT_FILE=/artifacts/objectstack.json +OS_BUSINESS_DB_URL=file:/var/lib/objectos/data.db +# Leave OS_CLOUD_URL unset to run fully offline ``` ObjectOS resolves every request to the packaged project and loads the -artifact from disk. +artifact from disk. With `OS_CLOUD_URL` unset, no calls are made to a +hosted control plane. ## Network expectations @@ -56,3 +65,6 @@ Treat artifacts as immutable: 3. Update the mount or environment variable to point at the new artifact. 4. Restart ObjectOS. 5. Roll back by restoring the previous image tag or artifact path. + +See [Upgrade](/docs/operate/upgrade) and [Backup](/docs/operate/backup) +for the full procedures these steps summarize. diff --git a/content/docs/deploy/air-gapped.zh-Hans.mdx b/content/docs/deploy/air-gapped.zh-Hans.mdx new file mode 100644 index 0000000..bb9c4ca --- /dev/null +++ b/content/docs/deploy/air-gapped.zh-Hans.mdx @@ -0,0 +1,65 @@ +--- +title: 隔离网络部署 +description: 在无法访问公共互联网的环境中运行 ObjectOS。 +--- + +# 隔离网络部署 + +隔离网络(air-gapped)部署适用于这样的客户网络:ObjectOS 在运行时无法 +调用托管的控制平面或公共软件包注册表。 + +## 需要交付的内容 + +离线发布包应包含: + +| 项目 | 用途 | +|---|---| +| ObjectOS 容器镜像 | 运行时二进制文件及依赖 | +| `objectstack.json` 制品 | 不可变的应用定义 | +| 数据库迁移/初始化指南 | 客户业务数据库的搭建 | +| 环境模板 | 必需的密钥与运行时变量 | +| 运维清单 | 升级、回滚、备份与诊断 | + +容器镜像与制品挂载遵循与标准 [Docker 部署](/docs/deploy/docker) 相同的 +约定;唯一的区别在于网络形态。 + +## 运行模式 + +使用基于文件的模式:将 ObjectOS 指向本地制品和由客户管理的业务数据库, +并保持云端控制平面未设置。 + +```bash +OS_ARTIFACT_FILE=/artifacts/objectstack.json +OS_BUSINESS_DB_URL=file:/var/lib/objectos/data.db +# Leave OS_CLOUD_URL unset to run fully offline +``` + +ObjectOS 会将每个请求解析到打包的项目,并从磁盘加载制品。当 +`OS_CLOUD_URL` 未设置时,不会向托管的控制平面发起任何调用。 + +## 网络要求 + +在此模式下,ObjectOS 不需要访问公共互联网。客户的网络规则应仅允许: + +- 来自已批准入口或负载均衡器的入站 HTTP/HTTPS; +- 流向客户管理的业务数据库的出站数据库流量; +- 流向明确配置的集成的出站流量,例如 SMTP、对象存储、webhook 目标 + 或身份提供方。 + +## 身份验证 + +如果客户使用 OIDC/SSO,身份提供方必须能从隔离网络中访问。如果无法访问, +请使用本地的邮箱/密码身份验证,或在同一网络内托管的身份提供方。 + +## 升级流程 + +将制品视为不可变: + +1. 导入新的 ObjectOS 镜像。 +2. 将新制品放置在旧制品旁边。 +3. 更新挂载或环境变量,使其指向新制品。 +4. 重启 ObjectOS。 +5. 通过恢复上一个镜像标签或制品路径进行回滚。 + +完整流程请参阅 [升级](/docs/operate/upgrade) 与 [备份](/docs/operate/backup), +本节中的步骤即为对它们的概括。 diff --git a/content/docs/deploy/docker.cn.mdx b/content/docs/deploy/docker.cn.mdx deleted file mode 100644 index 9e3c551..0000000 --- a/content/docs/deploy/docker.cn.mdx +++ /dev/null @@ -1,136 +0,0 @@ ---- -title: Docker -description: 在容器中运行 ObjectOS —— 用于评估、Staging 或生产。 ---- - -# Docker - -Docker 是大多数团队走向生产的路径。它与运行时本应被运维的方式吻合:每个实例一个无状态容器、一个外部数据库、一个外部对象存储用于文件、运行时注入密钥。 - -## 拉取预构建镜像 - -我们在每次推到 `main` 和打标签发布时把运行时镜像发布到 GitHub Container Registry: - -```bash -docker pull ghcr.io/objectstack-ai/objectos:latest -``` - -可用 tag: - -| Tag | 通道 | -|---|---| -| `latest` | `main` 的最新构建(推荐首次评估使用) | -| `main` | 与 `latest` 相同,但显式标识 | -| `sha-` | 锁定到具体 commit(推荐生产使用) | -| `vX.Y.Z`、`X.Y`、`X` | 已发布的标签 | - -生产环境请固定到 `sha-` 或 semver tag —— `latest` 会漂移。 - -## 用内置示例运行 - -```bash -docker run --rm -p 3000:3000 \ - -e OS_AUTH_SECRET="$(openssl rand -hex 32)" \ - ghcr.io/objectstack-ai/objectos:latest -``` - -然后打开 http://localhost:3000。镜像内置一个空示例应用,便于你在指向自己产物前先验证运行时能启动、Console/Account 能渲染。 - -`OS_AUTH_SECRET` 是启动必需项。轮换它会让现有会话失效。 - -## 用你自己的产物运行 - -你的应用定义就是一个文件:`dist/objectstack.json`。它的产生方式: - -| 来源 | 方法 | -|---|---| -| 你自己的项目 | 编辑 `objectstack.config.ts` 后运行 `pnpm exec objectstack compile` | -| 模板 | 从 [templates 仓库](https://github.com/objectstack-ai/templates)克隆,执行 `pnpm install && pnpm exec objectstack compile` | -| 应用市场 | 作为发布应用的一部分提供 | - -把文件挂载到 `/artifacts/objectstack.json` 并让运行时指向它: - -```bash -docker run --rm -p 3000:3000 \ - -e OS_AUTH_SECRET="$(openssl rand -hex 32)" \ - -e OS_ARTIFACT_FILE=/artifacts/objectstack.json \ - -v "$PWD/dist:/artifacts:ro" \ - -v objectos-data:/var/lib/objectos \ - ghcr.io/objectstack-ai/objectos:latest -``` - -`objectos-data` 卷保存 SQLite 数据库(当未配置外部数据库时)以及任何本地存储的上传文件。 - -## 用 Postgres 替代 SQLite - -```bash -docker run --rm -p 3000:3000 \ - -e OS_AUTH_SECRET="$(openssl rand -hex 32)" \ - -e OS_ARTIFACT_FILE=/artifacts/objectstack.json \ - -e OS_DATA_DRIVER=postgres \ - -e OS_DATA_URL='postgres://user:pass@db.internal:5432/myapp' \ - -v "$PWD/dist:/artifacts:ro" \ - ghcr.io/objectstack-ai/objectos:latest -``` - -完整驱动和连接选项矩阵见 [Runtime Configuration](/docs/configure/runtime)。 - -## Docker Compose - -参考的 `docker-compose.yml` 在仓库 `docker/` 目录下: - -```bash -git clone https://github.com/objectstack-ai/objectos.git -cd objectos -mkdir -p docker/artifacts -cp /path/to/your/objectstack.json docker/artifacts/ -export OS_AUTH_SECRET="$(openssl rand -hex 32)" -docker compose -f docker/docker-compose.yml up -``` - -默认端口 `3000`;用 `OBJECTOS_PORT=3200 docker compose ...` 覆盖。 - -## 构建你自己的镜像 - -如果你需要嵌入产物、自定义插件,或自己的 SSL/CA 包: - -```bash -git clone https://github.com/objectstack-ai/objectos.git -cd objectos -docker build -f docker/Dockerfile -t myorg/objectos:custom . -``` - -仓库自带的 Dockerfile 是多阶段构建,基于 Node 22 Alpine 产出一个精简运行时镜像(约 150 MB)。 - -## 应该分开存放的资产 - -| 资产 | 应该放在 | -|---|---| -| 产物 (`objectstack.json`) | 镜像(不可变)或挂载卷 | -| 业务数据库 | 外部托管的 Postgres / MySQL / Mongo | -| 身份与会话 | 同一数据库 | -| 上传的文件 | 外部托管的 S3 / R2 / 磁盘卷 | -| 密钥 (`OS_AUTH_SECRET`, DB URL, API Key) | 你的密钥管理器,作为环境变量注入 | -| 日志 | stdout —— 由你的日志驱动收集 | - -## 验证 - -启动后: - -```bash -curl -fsS http://localhost:3000/health -# {"status":"ok",...} -``` - -然后在 http://localhost:3000/_account/register 登录,确认 API 有响应: - -```bash -curl http://localhost:3000/api/v1/data/ -``` - -## 下一步 - -- [Kubernetes](/docs/deploy/kubernetes) —— 生产级编排 -- [Air-gapped](/docs/deploy/air-gapped) —— 在无出网环境运行 -- [Production Readiness](/docs/operate/production) —— 起飞前清单 -- [Observability](/docs/operate/observability) —— 日志、指标、审计 diff --git a/content/docs/deploy/docker.de.mdx b/content/docs/deploy/docker.de.mdx new file mode 100644 index 0000000..b2fac16 --- /dev/null +++ b/content/docs/deploy/docker.de.mdx @@ -0,0 +1,154 @@ +--- +title: Docker +description: ObjectOS in einem Container ausführen — zur Evaluierung, für Staging oder Produktion. +--- + +# Docker + +Docker ist der Weg, den die meisten Teams in die Produktion nehmen. Er +entspricht der Art und Weise, wie die Laufzeitumgebung betrieben werden +soll: ein zustandsloser Container pro Instanz, eine externe Datenbank, +ein externer Objektspeicher für Dateien, zur Laufzeit eingespeiste +Secrets. + +## Das vorgefertigte Image abrufen + +Wir veröffentlichen das Laufzeit-Image bei jedem Push auf `main` sowie +bei getaggten Releases in der GitHub Container Registry: + +```bash +docker pull ghcr.io/objectstack-ai/objectos:latest +``` + +Verfügbare Tags: + +| Tag | Channel | +|---|---| +| `latest` | Neuester Build von `main` (empfohlen für die erste Evaluierung) | +| `main` | Identisch mit `latest`, aber explizit | +| `sha-` | Auf einen bestimmten Commit fixiert (empfohlen für die Produktion) | +| `vX.Y.Z`, `X.Y`, `X` | Getaggte Releases | + +Für die Produktion fixieren Sie auf `sha-` oder ein Semver-Tag — +`latest` verschiebt sich mit der Zeit. + +## Mit dem mitgelieferten Beispiel ausführen + +```bash +docker run --rm -p 3000:3000 \ + -e OS_AUTH_SECRET="$(openssl rand -hex 32)" \ + ghcr.io/objectstack-ai/objectos:latest +``` + +Öffnen Sie anschließend http://localhost:3000. Das Image enthält eine +leere Beispiel-App, sodass Sie überprüfen können, ob die Laufzeitumgebung +startet und Console/Account rendern, bevor Sie es auf Ihr eigenes +Artefakt richten. + +`OS_AUTH_SECRET` ist zum Starten erforderlich. Eine Rotation macht +bestehende Sitzungen ungültig. + +## Mit Ihrem eigenen Artefakt ausführen + +Ihre App-Definition ist eine einzige Datei: `dist/objectstack.json`. Sie +wird erzeugt durch: + +| Quelle | Vorgehen | +|---|---| +| Ihr eigenes Projekt | `pnpm exec objectstack compile` nach dem Bearbeiten von `objectstack.config.ts` | +| Eine Vorlage | Aus dem [Templates-Repo](https://github.com/objectstack-ai/templates) klonen, dann `pnpm install && pnpm exec objectstack compile` ausführen | +| App-marketplace | Als Teil der veröffentlichten App bereitgestellt | + +Binden Sie die Datei unter `/artifacts/objectstack.json` ein und richten +Sie die Laufzeitumgebung darauf aus: + +```bash +docker run --rm -p 3000:3000 \ + -e OS_AUTH_SECRET="$(openssl rand -hex 32)" \ + -e OS_ARTIFACT_FILE=/artifacts/objectstack.json \ + -v "$PWD/dist:/artifacts:ro" \ + -v objectos-data:/var/lib/objectos \ + ghcr.io/objectstack-ai/objectos:latest +``` + +Das Volume `objectos-data` enthält die SQLite-Datenbank (wenn keine +externe DB konfiguriert ist) sowie alle lokal gespeicherten +hochgeladenen Dateien. + +## Postgres statt SQLite verwenden + +```bash +docker run --rm -p 3000:3000 \ + -e OS_AUTH_SECRET="$(openssl rand -hex 32)" \ + -e OS_ARTIFACT_FILE=/artifacts/objectstack.json \ + -e OS_DATABASE_DRIVER=postgres \ + -e OS_DATABASE_URL='postgres://user:pass@db.internal:5432/myapp' \ + -v "$PWD/dist:/artifacts:ro" \ + ghcr.io/objectstack-ai/objectos:latest +``` + +Siehe [Runtime Configuration](/docs/configure/runtime) für die +vollständige Matrix der Treiber und Verbindungsoptionen. + +## Docker Compose + +Eine Referenz-`docker-compose.yml` liegt im Repo unter `docker/`: + +```bash +git clone https://github.com/objectstack-ai/objectos.git +cd objectos +mkdir -p docker/artifacts +cp /path/to/your/objectstack.json docker/artifacts/ +export OS_AUTH_SECRET="$(openssl rand -hex 32)" +docker compose -f docker/docker-compose.yml up +``` + +Der Standardport ist `3000`; überschreiben Sie ihn mit `OBJECTOS_PORT=3200 docker compose ...`. + +## Ihr eigenes Image bauen + +Wenn Sie ein Artefakt, benutzerdefinierte Plugins oder Ihr eigenes +SSL-/CA-Bundle einbetten müssen: + +```bash +git clone https://github.com/objectstack-ai/objectos.git +cd objectos +docker build -f docker/Dockerfile -t myorg/objectos:custom . +``` + +Das mitgelieferte Dockerfile ist ein mehrstufiger Build, der ein +schlankes Laufzeit-Image auf Node 20 Alpine erzeugt. + +## Was Sie getrennt halten müssen + +| Asset | Wo es liegen sollte | +|---|---| +| Artefakt (`objectstack.json`) | Image (unveränderlich) oder eingebundenes Volume | +| Business-Datenbank | Extern verwaltetes Postgres / MySQL / Mongo | +| Identität & Sitzungen | Dieselbe Datenbank | +| Hochgeladene Dateien | Extern verwaltetes S3 / R2 / Disk-Volume | +| Secrets (`OS_AUTH_SECRET`, DB-URL, API-Keys) | Ihr Secret-Manager, als Umgebungsvariablen eingespeist | +| Logs | stdout — von Ihrem Log-Treiber erfasst | + +## Überprüfen + +Nach dem Start: + +```bash +curl -fsS http://localhost:3000/health +# {"status":"ok",...} +``` + +Melden Sie sich dann unter http://localhost:3000/_account/register an und +bestätigen Sie, dass die API antwortet: + +```bash +curl http://localhost:3000/api/v1/data/ +``` + +## Weiter + +- [Kubernetes](/docs/deploy/kubernetes) — Orchestrierung auf Produktionsniveau +- [Air-gapped](/docs/deploy/air-gapped) — Betrieb ohne Internet-Ausgang +- [Production Readiness](/docs/operate/production) — Pre-Flight-Checkliste +- [Observability](/docs/operate/observability) — Logs, Metriken, Audit diff --git a/content/docs/deploy/docker.es.mdx b/content/docs/deploy/docker.es.mdx new file mode 100644 index 0000000..3443533 --- /dev/null +++ b/content/docs/deploy/docker.es.mdx @@ -0,0 +1,153 @@ +--- +title: Docker +description: Ejecuta ObjectOS en un contenedor — para evaluación, staging o producción. +--- + +# Docker + +Docker es el camino que la mayoría de los equipos toman hacia producción. +Se ajusta a la forma en que el runtime está diseñado para operarse: un +contenedor sin estado por instancia, una base de datos externa, un almacén +de objetos externo para los archivos y secretos inyectados en tiempo de +ejecución. + +## Descarga la imagen precompilada + +Publicamos la imagen del runtime en GitHub Container Registry en cada +push a `main` y en las releases etiquetadas: + +```bash +docker pull ghcr.io/objectstack-ai/objectos:latest +``` + +Tags disponibles: + +| Tag | Canal | +|---|---| +| `latest` | Última compilación de `main` (recomendado para una primera evaluación) | +| `main` | Igual que `latest`, pero explícito | +| `sha-` | Fijado a un commit específico (recomendado para producción) | +| `vX.Y.Z`, `X.Y`, `X` | Releases etiquetadas | + +Para producción, fija a `sha-` o a un tag semver — `latest` irá +cambiando con el tiempo. + +## Ejecuta con el ejemplo incluido + +```bash +docker run --rm -p 3000:3000 \ + -e OS_AUTH_SECRET="$(openssl rand -hex 32)" \ + ghcr.io/objectstack-ai/objectos:latest +``` + +Luego abre http://localhost:3000. La imagen incluye una app de ejemplo +vacía para que puedas verificar que el runtime arranca y que Console/Account +se renderizan antes de apuntarla a tu propio artefacto. + +`OS_AUTH_SECRET` es obligatorio para arrancar. Rotarlo invalida las sesiones +existentes. + +## Ejecuta con tu propio artefacto + +La definición de tu app es un único archivo: `dist/objectstack.json`. Se +produce mediante: + +| Origen | Cómo | +|---|---| +| Tu propio proyecto | `pnpm exec objectstack compile` después de editar `objectstack.config.ts` | +| Una plantilla | Clónala desde el [repo de plantillas](https://github.com/objectstack-ai/templates), ejecuta `pnpm install && pnpm exec objectstack compile` | +| App del marketplace | Se proporciona como parte de la app publicada | + +Monta el archivo en `/artifacts/objectstack.json` y apunta el runtime +a él: + +```bash +docker run --rm -p 3000:3000 \ + -e OS_AUTH_SECRET="$(openssl rand -hex 32)" \ + -e OS_ARTIFACT_FILE=/artifacts/objectstack.json \ + -v "$PWD/dist:/artifacts:ro" \ + -v objectos-data:/var/lib/objectos \ + ghcr.io/objectstack-ai/objectos:latest +``` + +El volumen `objectos-data` contiene la base de datos SQLite (cuando no hay +una BD externa configurada) y cualquier archivo subido almacenado +localmente. + +## Usa Postgres en lugar de SQLite + +```bash +docker run --rm -p 3000:3000 \ + -e OS_AUTH_SECRET="$(openssl rand -hex 32)" \ + -e OS_ARTIFACT_FILE=/artifacts/objectstack.json \ + -e OS_DATABASE_DRIVER=postgres \ + -e OS_DATABASE_URL='postgres://user:pass@db.internal:5432/myapp' \ + -v "$PWD/dist:/artifacts:ro" \ + ghcr.io/objectstack-ai/objectos:latest +``` + +Consulta [Runtime Configuration](/docs/configure/runtime) para ver la +matriz completa de drivers y opciones de conexión. + +## Docker Compose + +En el repo hay un `docker-compose.yml` de referencia dentro de `docker/`: + +```bash +git clone https://github.com/objectstack-ai/objectos.git +cd objectos +mkdir -p docker/artifacts +cp /path/to/your/objectstack.json docker/artifacts/ +export OS_AUTH_SECRET="$(openssl rand -hex 32)" +docker compose -f docker/docker-compose.yml up +``` + +El puerto por defecto es `3000`; sobrescríbelo con `OBJECTOS_PORT=3200 docker compose ...`. + +## Construye tu propia imagen + +Si necesitas incrustar un artefacto, plugins personalizados o tu propio +bundle SSL/CA: + +```bash +git clone https://github.com/objectstack-ai/objectos.git +cd objectos +docker build -f docker/Dockerfile -t myorg/objectos:custom . +``` + +El Dockerfile incluido es una compilación multi-etapa que produce una +imagen de runtime ligera sobre Node 20 Alpine. + +## Lo que debes mantener separado + +| Recurso | Dónde debería residir | +|---|---| +| Artefacto (`objectstack.json`) | Imagen (inmutable) o volumen montado | +| Base de datos de negocio | Postgres / MySQL / Mongo gestionado externamente | +| Identidad y sesiones | La misma base de datos | +| Archivos subidos | S3 / R2 / volumen de disco gestionado externamente | +| Secretos (`OS_AUTH_SECRET`, URL de BD, claves de API) | Tu gestor de secretos, inyectados como variables de entorno | +| Logs | stdout — recopilados por tu driver de logs | + +## Verifica + +Tras el arranque: + +```bash +curl -fsS http://localhost:3000/health +# {"status":"ok",...} +``` + +Luego inicia sesión en http://localhost:3000/_account/register y confirma +que la API responde: + +```bash +curl http://localhost:3000/api/v1/data/ +``` + +## Siguiente + +- [Kubernetes](/docs/deploy/kubernetes) — orquestación de nivel producción +- [Air-gapped](/docs/deploy/air-gapped) — ejecución sin salida a internet +- [Production Readiness](/docs/operate/production) — checklist previo al despliegue +- [Observability](/docs/operate/observability) — logs, métricas, auditoría diff --git a/content/docs/deploy/docker.fr.mdx b/content/docs/deploy/docker.fr.mdx new file mode 100644 index 0000000..aecd7f7 --- /dev/null +++ b/content/docs/deploy/docker.fr.mdx @@ -0,0 +1,155 @@ +--- +title: Docker +description: Exécutez ObjectOS dans un conteneur — pour l'évaluation, la préproduction ou la production. +--- + +# Docker + +Docker est la voie que la plupart des équipes empruntent vers la +production. Elle correspond à la manière dont le runtime est censé être +exploité : un conteneur sans état par instance, une base de données +externe, un magasin d'objets externe pour les fichiers, des secrets +injectés à l'exécution. + +## Récupérer l'image pré-construite + +Nous publions l'image du runtime sur le GitHub Container Registry à +chaque push sur `main` et à chaque release taguée : + +```bash +docker pull ghcr.io/objectstack-ai/objectos:latest +``` + +Tags disponibles : + +| Tag | Canal | +|---|---| +| `latest` | Dernière build de `main` (recommandé pour une première évaluation) | +| `main` | Identique à `latest`, mais explicite | +| `sha-` | Épinglé sur un commit précis (recommandé pour la production) | +| `vX.Y.Z`, `X.Y`, `X` | Releases taguées | + +Pour la production, épinglez sur `sha-` ou un tag semver — `latest` +évoluera. + +## Exécuter avec l'exemple intégré + +```bash +docker run --rm -p 3000:3000 \ + -e OS_AUTH_SECRET="$(openssl rand -hex 32)" \ + ghcr.io/objectstack-ai/objectos:latest +``` + +Ouvrez ensuite http://localhost:3000. L'image est livrée avec un exemple +d'application vide afin que vous puissiez vérifier que le runtime démarre +et que Console/Account s'affichent avant de le pointer vers votre propre +artefact. + +`OS_AUTH_SECRET` est requis pour démarrer. Le faire tourner invalide les +sessions existantes. + +## Exécuter avec votre propre artefact + +La définition de votre application tient dans un seul fichier : +`dist/objectstack.json`. Il est produit par : + +| Source | Comment | +|---|---| +| Votre propre projet | `pnpm exec objectstack compile` après avoir modifié `objectstack.config.ts` | +| Un template | Clonez depuis le [dépôt de templates](https://github.com/objectstack-ai/templates), exécutez `pnpm install && pnpm exec objectstack compile` | +| Marketplace d'applications | Fourni dans le cadre de l'application publiée | + +Montez le fichier sur `/artifacts/objectstack.json` et pointez le runtime +dessus : + +```bash +docker run --rm -p 3000:3000 \ + -e OS_AUTH_SECRET="$(openssl rand -hex 32)" \ + -e OS_ARTIFACT_FILE=/artifacts/objectstack.json \ + -v "$PWD/dist:/artifacts:ro" \ + -v objectos-data:/var/lib/objectos \ + ghcr.io/objectstack-ai/objectos:latest +``` + +Le volume `objectos-data` contient la base de données SQLite (lorsqu'aucune +base de données externe n'est configurée) ainsi que tous les fichiers +téléversés stockés localement. + +## Utiliser Postgres au lieu de SQLite + +```bash +docker run --rm -p 3000:3000 \ + -e OS_AUTH_SECRET="$(openssl rand -hex 32)" \ + -e OS_ARTIFACT_FILE=/artifacts/objectstack.json \ + -e OS_DATABASE_DRIVER=postgres \ + -e OS_DATABASE_URL='postgres://user:pass@db.internal:5432/myapp' \ + -v "$PWD/dist:/artifacts:ro" \ + ghcr.io/objectstack-ai/objectos:latest +``` + +Consultez la [Configuration du runtime](/docs/configure/runtime) pour la +matrice complète des pilotes et des options de connexion. + +## Docker Compose + +Un fichier `docker-compose.yml` de référence se trouve dans le dépôt, sous +`docker/` : + +```bash +git clone https://github.com/objectstack-ai/objectos.git +cd objectos +mkdir -p docker/artifacts +cp /path/to/your/objectstack.json docker/artifacts/ +export OS_AUTH_SECRET="$(openssl rand -hex 32)" +docker compose -f docker/docker-compose.yml up +``` + +Le port par défaut est `3000` ; remplacez-le avec `OBJECTOS_PORT=3200 docker compose ...`. + +## Construire votre propre image + +Si vous devez intégrer un artefact, des plugins personnalisés ou votre +propre bundle SSL/CA : + +```bash +git clone https://github.com/objectstack-ai/objectos.git +cd objectos +docker build -f docker/Dockerfile -t myorg/objectos:custom . +``` + +Le Dockerfile fourni est une build multi-étapes qui produit une image +runtime légère basée sur Node 20 Alpine. + +## Ce que vous devez garder séparé + +| Ressource | Où elle doit se trouver | +|---|---| +| Artefact (`objectstack.json`) | Image (immuable) ou volume monté | +| Base de données métier | Postgres / MySQL / Mongo géré en externe | +| Identité et sessions | Même base de données | +| Fichiers téléversés | S3 / R2 / volume disque géré en externe | +| Secrets (`OS_AUTH_SECRET`, URL de la base, clés d'API) | Votre gestionnaire de secrets, injectés en tant que variables d'environnement | +| Logs | stdout — collectés par votre pilote de logs | + +## Vérifier + +Après le démarrage : + +```bash +curl -fsS http://localhost:3000/health +# {"status":"ok",...} +``` + +Connectez-vous ensuite sur http://localhost:3000/_account/register et +confirmez que l'API répond : + +```bash +curl http://localhost:3000/api/v1/data/ +``` + +## Étapes suivantes + +- [Kubernetes](/docs/deploy/kubernetes) — orchestration de niveau production +- [Air-gapped](/docs/deploy/air-gapped) — exécution sans accès Internet sortant +- [Préparation à la production](/docs/operate/production) — checklist de pré-vol +- [Observabilité](/docs/operate/observability) — logs, métriques, audit diff --git a/content/docs/deploy/docker.ja.mdx b/content/docs/deploy/docker.ja.mdx new file mode 100644 index 0000000..e9fea99 --- /dev/null +++ b/content/docs/deploy/docker.ja.mdx @@ -0,0 +1,136 @@ +--- +title: Docker +description: ObjectOS をコンテナで実行する — 評価、ステージング、本番のいずれにも対応。 +--- + +# Docker + +Docker は、多くのチームが本番環境へ到達するために選ぶ経路です。これは、ランタイムが本来意図されている運用方法と一致します。すなわち、インスタンスごとに 1 つのステートレスなコンテナ、外部データベース、ファイル用の外部オブジェクトストア、そして実行時に注入されるシークレットです。 + +## ビルド済みイメージを取得する + +`main` へのプッシュごとに、およびタグ付きリリースごとに、ランタイムイメージを GitHub Container Registry へ公開しています。 + +```bash +docker pull ghcr.io/objectstack-ai/objectos:latest +``` + +利用可能なタグ: + +| タグ | チャネル | +|---|---| +| `latest` | `main` の最新ビルド(初回評価に推奨) | +| `main` | `latest` と同じだが明示的 | +| `sha-` | 特定のコミットに固定(本番に推奨) | +| `vX.Y.Z`, `X.Y`, `X` | タグ付きリリース | + +本番環境では、`sha-` または semver タグに固定してください。`latest` は変動します。 + +## 同梱サンプルで実行する + +```bash +docker run --rm -p 3000:3000 \ + -e OS_AUTH_SECRET="$(openssl rand -hex 32)" \ + ghcr.io/objectstack-ai/objectos:latest +``` + +次に http://localhost:3000 を開きます。このイメージには空のサンプルアプリが同梱されているため、独自のアーティファクトを指定する前に、ランタイムが起動し Console/Account が描画されることを確認できます。 + +`OS_AUTH_SECRET` は起動に必須です。これをローテーションすると既存のセッションは無効になります。 + +## 独自のアーティファクトで実行する + +アプリ定義は単一のファイルです: `dist/objectstack.json`。これは次の方法で生成されます。 + +| ソース | 方法 | +|---|---| +| 独自のプロジェクト | `objectstack.config.ts` を編集した後に `pnpm exec objectstack compile` | +| テンプレート | [テンプレートリポジトリ](https://github.com/objectstack-ai/templates) からクローンし、`pnpm install && pnpm exec objectstack compile` を実行 | +| アプリ marketplace | 公開アプリの一部として提供 | + +このファイルを `/artifacts/objectstack.json` にマウントし、ランタイムがそれを指すように設定します。 + +```bash +docker run --rm -p 3000:3000 \ + -e OS_AUTH_SECRET="$(openssl rand -hex 32)" \ + -e OS_ARTIFACT_FILE=/artifacts/objectstack.json \ + -v "$PWD/dist:/artifacts:ro" \ + -v objectos-data:/var/lib/objectos \ + ghcr.io/objectstack-ai/objectos:latest +``` + +`objectos-data` ボリュームには、SQLite データベース(外部 DB が構成されていない場合)とローカルに保存されたアップロードファイルが保持されます。 + +## SQLite の代わりに Postgres を使用する + +```bash +docker run --rm -p 3000:3000 \ + -e OS_AUTH_SECRET="$(openssl rand -hex 32)" \ + -e OS_ARTIFACT_FILE=/artifacts/objectstack.json \ + -e OS_DATABASE_DRIVER=postgres \ + -e OS_DATABASE_URL='postgres://user:pass@db.internal:5432/myapp' \ + -v "$PWD/dist:/artifacts:ro" \ + ghcr.io/objectstack-ai/objectos:latest +``` + +ドライバーと接続オプションの完全な一覧については、[ランタイム構成](/docs/configure/runtime)を参照してください。 + +## Docker Compose + +リファレンスとなる `docker-compose.yml` はリポジトリの `docker/` 配下にあります。 + +```bash +git clone https://github.com/objectstack-ai/objectos.git +cd objectos +mkdir -p docker/artifacts +cp /path/to/your/objectstack.json docker/artifacts/ +export OS_AUTH_SECRET="$(openssl rand -hex 32)" +docker compose -f docker/docker-compose.yml up +``` + +デフォルトポートは `3000` です。`OBJECTOS_PORT=3200 docker compose ...` で上書きします。 + +## 独自のイメージをビルドする + +アーティファクト、カスタムプラグイン、または独自の SSL/CA バンドルを埋め込む必要がある場合: + +```bash +git clone https://github.com/objectstack-ai/objectos.git +cd objectos +docker build -f docker/Dockerfile -t myorg/objectos:custom . +``` + +同梱の Dockerfile はマルチステージビルドで、Node 20 Alpine 上にスリムなランタイムイメージを生成します。 + +## 分離して管理すべきもの + +| 資産 | 配置すべき場所 | +|---|---| +| アーティファクト(`objectstack.json`) | イメージ(イミュータブル)またはマウントされたボリューム | +| 業務データベース | 外部管理の Postgres / MySQL / Mongo | +| アイデンティティとセッション | 同じデータベース | +| アップロードファイル | 外部管理の S3 / R2 / ディスクボリューム | +| シークレット(`OS_AUTH_SECRET`、DB URL、API キー) | シークレットマネージャー(環境変数として注入) | +| ログ | stdout — ログドライバーによって収集 | + +## 検証 + +起動後: + +```bash +curl -fsS http://localhost:3000/health +# {"status":"ok",...} +``` + +次に http://localhost:3000/_account/register でサインインし、API が応答することを確認します。 + +```bash +curl http://localhost:3000/api/v1/data/ +``` + +## 次のステップ + +- [Kubernetes](/docs/deploy/kubernetes) — 本番グレードのオーケストレーション +- [エアギャップ](/docs/deploy/air-gapped) — インターネット送信なしでの実行 +- [本番準備](/docs/operate/production) — プリフライトチェックリスト +- [オブザーバビリティ](/docs/operate/observability) — ログ、メトリクス、監査 diff --git a/content/docs/deploy/docker.mdx b/content/docs/deploy/docker.mdx index cfe2a25..84ebaaa 100644 --- a/content/docs/deploy/docker.mdx +++ b/content/docs/deploy/docker.mdx @@ -78,8 +78,8 @@ DB is configured) and any locally-stored uploaded files. docker run --rm -p 3000:3000 \ -e OS_AUTH_SECRET="$(openssl rand -hex 32)" \ -e OS_ARTIFACT_FILE=/artifacts/objectstack.json \ - -e OS_DATA_DRIVER=postgres \ - -e OS_DATA_URL='postgres://user:pass@db.internal:5432/myapp' \ + -e OS_DATABASE_DRIVER=postgres \ + -e OS_DATABASE_URL='postgres://user:pass@db.internal:5432/myapp' \ -v "$PWD/dist:/artifacts:ro" \ ghcr.io/objectstack-ai/objectos:latest ``` @@ -114,7 +114,7 @@ docker build -f docker/Dockerfile -t myorg/objectos:custom . ``` The shipped Dockerfile is a multi-stage build that produces a slim -runtime image (~150 MB) on Node 22 Alpine. +runtime image on Node 20 Alpine. ## What you need to keep separate diff --git a/content/docs/deploy/docker.zh-Hans.mdx b/content/docs/deploy/docker.zh-Hans.mdx new file mode 100644 index 0000000..185a9dc --- /dev/null +++ b/content/docs/deploy/docker.zh-Hans.mdx @@ -0,0 +1,142 @@ +--- +title: Docker +description: 在容器中运行 ObjectOS —— 适用于评估、预发布或生产环境。 +--- + +# Docker + +Docker 是大多数团队迈向生产环境的路径。它契合运行时本应采用的运维方式: +每个实例对应一个无状态容器、一个外部数据库、一个用于存放文件的外部对象存储, +以及在运行时注入的密钥。 + +## 拉取预构建镜像 + +我们会在每次推送到 `main` 以及发布带标签的版本时,将运行时镜像发布到 +GitHub Container Registry: + +```bash +docker pull ghcr.io/objectstack-ai/objectos:latest +``` + +可用标签: + +| 标签 | 通道 | +|---|---| +| `latest` | `main` 的最新构建(推荐用于首次评估) | +| `main` | 与 `latest` 相同,但更明确 | +| `sha-` | 固定到特定提交(推荐用于生产环境) | +| `vX.Y.Z`、`X.Y`、`X` | 带标签的发布版本 | + +对于生产环境,请固定到 `sha-` 或语义化版本标签 —— `latest` 会随时间漂移。 + +## 使用内置示例运行 + +```bash +docker run --rm -p 3000:3000 \ + -e OS_AUTH_SECRET="$(openssl rand -hex 32)" \ + ghcr.io/objectstack-ai/objectos:latest +``` + +然后打开 http://localhost:3000。该镜像附带一个空的示例应用, +便于你在将其指向自己的产物之前,验证运行时能够启动并正确渲染 Console/Account。 + +启动时必须提供 `OS_AUTH_SECRET`。轮换它会使现有会话失效。 + +## 使用你自己的产物运行 + +你的应用定义是单个文件:`dist/objectstack.json`。它由以下方式生成: + +| 来源 | 方式 | +|---|---| +| 你自己的项目 | 编辑 `objectstack.config.ts` 后运行 `pnpm exec objectstack compile` | +| 模板 | 从 [templates 仓库](https://github.com/objectstack-ai/templates) 克隆,运行 `pnpm install && pnpm exec objectstack compile` | +| 应用 marketplace | 作为已发布应用的一部分提供 | + +将该文件挂载到 `/artifacts/objectstack.json` 并让运行时指向它: + +```bash +docker run --rm -p 3000:3000 \ + -e OS_AUTH_SECRET="$(openssl rand -hex 32)" \ + -e OS_ARTIFACT_FILE=/artifacts/objectstack.json \ + -v "$PWD/dist:/artifacts:ro" \ + -v objectos-data:/var/lib/objectos \ + ghcr.io/objectstack-ai/objectos:latest +``` + +`objectos-data` 卷用于保存 SQLite 数据库(当未配置外部数据库时)以及任何 +本地存储的上传文件。 + +## 使用 Postgres 代替 SQLite + +```bash +docker run --rm -p 3000:3000 \ + -e OS_AUTH_SECRET="$(openssl rand -hex 32)" \ + -e OS_ARTIFACT_FILE=/artifacts/objectstack.json \ + -e OS_DATABASE_DRIVER=postgres \ + -e OS_DATABASE_URL='postgres://user:pass@db.internal:5432/myapp' \ + -v "$PWD/dist:/artifacts:ro" \ + ghcr.io/objectstack-ai/objectos:latest +``` + +驱动和连接选项的完整矩阵请参阅[运行时配置](/docs/configure/runtime)。 + +## Docker Compose + +仓库的 `docker/` 目录下提供了一份参考 `docker-compose.yml`: + +```bash +git clone https://github.com/objectstack-ai/objectos.git +cd objectos +mkdir -p docker/artifacts +cp /path/to/your/objectstack.json docker/artifacts/ +export OS_AUTH_SECRET="$(openssl rand -hex 32)" +docker compose -f docker/docker-compose.yml up +``` + +默认端口为 `3000`;可通过 `OBJECTOS_PORT=3200 docker compose ...` 覆盖。 + +## 构建你自己的镜像 + +如果你需要嵌入产物、自定义插件,或你自己的 SSL/CA 证书包: + +```bash +git clone https://github.com/objectstack-ai/objectos.git +cd objectos +docker build -f docker/Dockerfile -t myorg/objectos:custom . +``` + +随附的 Dockerfile 是一个多阶段构建,可在 Node 20 Alpine 上生成一个精简的 +运行时镜像。 + +## 需要分开管理的内容 + +| 资产 | 应存放位置 | +|---|---| +| 产物(`objectstack.json`) | 镜像(不可变)或挂载的卷 | +| 业务数据库 | 外部托管的 Postgres / MySQL / Mongo | +| 身份与会话 | 同一数据库 | +| 上传的文件 | 外部托管的 S3 / R2 / 磁盘卷 | +| 密钥(`OS_AUTH_SECRET`、DB URL、API 密钥) | 你的密钥管理器,以环境变量形式注入 | +| 日志 | stdout —— 由你的日志驱动收集 | + +## 验证 + +启动之后: + +```bash +curl -fsS http://localhost:3000/health +# {"status":"ok",...} +``` + +然后在 http://localhost:3000/_account/register 登录,并确认 API 有响应: + +```bash +curl http://localhost:3000/api/v1/data/ +``` + +## 下一步 + +- [Kubernetes](/docs/deploy/kubernetes) —— 生产级编排 +- [Air-gapped](/docs/deploy/air-gapped) —— 在无互联网出站访问的环境中运行 +- [Production Readiness](/docs/operate/production) —— 上线前检查清单 +- [Observability](/docs/operate/observability) —— 日志、指标、审计 diff --git a/content/docs/deploy/index.de.mdx b/content/docs/deploy/index.de.mdx new file mode 100644 index 0000000..1c7ce38 --- /dev/null +++ b/content/docs/deploy/index.de.mdx @@ -0,0 +1,24 @@ +--- +title: Bereitstellung +description: Wählen Sie, wie Sie ObjectOS betreiben — Docker zur Evaluierung, Kubernetes für hochverfügbare Produktionsumgebungen oder ein Air-Gapped-Bundle für Netzwerke ohne ausgehenden Datenverkehr. +--- + +ObjectOS wird als ein einziges Laufzeit-Artefakt ausgeliefert, das in jeder Umgebung auf die gleiche Weise läuft. Wählen Sie die Bereitstellungsform, die zu Ihrer Infrastruktur passt. + +## Docker + +Ein einzelner Container ist der schnellste Weg, um ObjectOS zu evaluieren oder es auf einem einzelnen Host auszuführen. Binden Sie ein Volume für das Datenverzeichnis ein, verweisen Sie es auf Ihre Datenbank und starten Sie den Container. + +[Docker-Anleitung →](/docs/deploy/docker) + +## Kubernetes + +Führen Sie ObjectOS in der Produktion als Deployment hinter einem Service aus, mit persistentem Speicher für das Datenverzeichnis und Ihren Secrets, die über standardmäßige Kubernetes-Mechanismen bereitgestellt werden. + +[Kubernetes-Anleitung →](/docs/deploy/kubernetes) + +## Air-Gapped + +Bringen Sie ein Release-Bundle in ein Netzwerk ohne Internetzugang ein. ObjectOS liest sein Anwendungs-Artefakt aus einer lokalen Datei und greift niemals auf einen gehosteten Dienst zu. + +[Air-Gapped-Anleitung →](/docs/deploy/air-gapped) diff --git a/content/docs/deploy/index.es.mdx b/content/docs/deploy/index.es.mdx new file mode 100644 index 0000000..945dbfd --- /dev/null +++ b/content/docs/deploy/index.es.mdx @@ -0,0 +1,24 @@ +--- +title: Despliegue +description: Elige cómo ejecutar ObjectOS — Docker para evaluación, Kubernetes para alta disponibilidad en producción, o un paquete air-gapped para redes sin salida a internet. +--- + +ObjectOS se distribuye como un único artefacto de runtime que funciona de la misma forma en cada entorno. Elige el modelo de despliegue que se ajuste a tu infraestructura. + +## Docker + +Un único contenedor es la forma más rápida de evaluar ObjectOS o de ejecutarlo en un solo host. Monta un volumen para el directorio de datos, apúntalo a tu base de datos e inicia el contenedor. + +[Guía de Docker →](/docs/deploy/docker) + +## Kubernetes + +Para producción, ejecuta ObjectOS como un Deployment detrás de un Service, con almacenamiento persistente para el directorio de datos y tus secretos proporcionados mediante los mecanismos estándar de Kubernetes. + +[Guía de Kubernetes →](/docs/deploy/kubernetes) + +## Air-Gapped + +Lleva un paquete de release a una red sin salida a internet. ObjectOS lee su artefacto de aplicación desde un archivo local y nunca accede a un servicio alojado. + +[Guía air-gapped →](/docs/deploy/air-gapped) diff --git a/content/docs/deploy/index.fr.mdx b/content/docs/deploy/index.fr.mdx new file mode 100644 index 0000000..6d2170d --- /dev/null +++ b/content/docs/deploy/index.fr.mdx @@ -0,0 +1,24 @@ +--- +title: Déploiement +description: Choisissez comment exécuter ObjectOS — Docker pour l'évaluation, Kubernetes pour la haute disponibilité en production, ou un bundle isolé pour les réseaux sans accès sortant. +--- + +ObjectOS est livré sous forme d'un artefact d'exécution unique qui fonctionne de la même manière dans chaque environnement. Choisissez le format de déploiement adapté à votre infrastructure. + +## Docker + +Un conteneur unique est le moyen le plus rapide d'évaluer ObjectOS ou de l'exécuter sur un seul hôte. Montez un volume pour le répertoire de données, pointez-le vers votre base de données et démarrez le conteneur. + +[Guide Docker →](/docs/deploy/docker) + +## Kubernetes + +Pour la production, exécutez ObjectOS en tant que Deployment derrière un Service, avec un stockage persistant pour le répertoire de données et vos secrets fournis via les mécanismes standard de Kubernetes. + +[Guide Kubernetes →](/docs/deploy/kubernetes) + +## Air-Gapped + +Acheminez un bundle de version vers un réseau sans accès Internet sortant. ObjectOS lit son artefact applicatif depuis un fichier local et ne contacte jamais de service hébergé. + +[Guide air-gapped →](/docs/deploy/air-gapped) diff --git a/content/docs/deploy/index.ja.mdx b/content/docs/deploy/index.ja.mdx new file mode 100644 index 0000000..38c6de2 --- /dev/null +++ b/content/docs/deploy/index.ja.mdx @@ -0,0 +1,24 @@ +--- +title: デプロイ +description: ObjectOS の実行方法を選択します — 評価用の Docker、本番 HA 用の Kubernetes、または外部通信のないネットワーク向けのエアギャップ用バンドル。 +--- + +ObjectOS は、すべての環境で同じように動作する単一のランタイム成果物として提供されます。お使いのインフラに合ったデプロイ形態を選択してください。 + +## Docker + +単一のコンテナは、ObjectOS を評価したり単一ホストで実行したりする最も手早い方法です。データディレクトリ用のボリュームをマウントし、データベースを指定して、コンテナを起動します。 + +[Docker ガイド →](/docs/deploy/docker) + +## Kubernetes + +本番環境では、ObjectOS を Service の背後に配置した Deployment として実行し、データディレクトリ用の永続ストレージを用意し、シークレットは標準的な Kubernetes の仕組みを通じて供給します。 + +[Kubernetes ガイド →](/docs/deploy/kubernetes) + +## Air-Gapped + +リリースバンドルを、インターネットへの外部通信がないネットワークへ持ち込みます。ObjectOS はアプリケーション成果物をローカルファイルから読み込み、ホスティングされたサービスにアクセスすることは一切ありません。 + +[エアギャップガイド →](/docs/deploy/air-gapped) diff --git a/content/docs/deploy/index.cn.mdx b/content/docs/deploy/index.zh-Hans.mdx similarity index 100% rename from content/docs/deploy/index.cn.mdx rename to content/docs/deploy/index.zh-Hans.mdx diff --git a/content/docs/deploy/kubernetes.de.mdx b/content/docs/deploy/kubernetes.de.mdx new file mode 100644 index 0000000..caf00d8 --- /dev/null +++ b/content/docs/deploy/kubernetes.de.mdx @@ -0,0 +1,109 @@ +--- +title: Kubernetes +description: ObjectOS in einer Kubernetes-Umgebung bereitstellen. +--- + +# Kubernetes + +Verwenden Sie Kubernetes für Produktivbereitstellungen, die verwaltete +Secrets, Ingress, Probes, fortlaufende Upgrades und kundenverwaltete +Datenbanken benötigen. + +ObjectOS liefert noch kein gepacktes Helm-Chart aus, daher beschreibt die +folgende Anleitung die Manifeste, die Sie rund um das veröffentlichte +Container-Image zusammenstellen. + +## Aufbau der Bereitstellung + +Eine produktive ObjectOS-Bereitstellung umfasst in der Regel: + +| Komponente | Empfehlung | +|---|---| +| Deployment | Ein ObjectOS-Container-Image | +| Service | ClusterIP-Service für HTTP-Verkehr | +| Ingress | TLS-Terminierung und Routing über den Kunden-Hostnamen | +| Secret | `OS_AUTH_SECRET`, Control-Plane-Token, Datenbank-Zugangsdaten | +| ConfigMap | Nicht-geheime Laufzeitkonfiguration | +| Persistenter Speicher | Nur bei Verwendung lokaler Datei-Artefakte oder SQLite-Evaluierungsdaten | +| Externe Datenbank | Empfohlen für produktive Geschäftsdaten | + +## Erforderliche Konfiguration + +Konfigurieren Sie mindestens: + +```yaml +env: + - name: PORT + value: "3000" + - name: OS_AUTH_SECRET + valueFrom: + secretKeyRef: + name: objectos-secrets + key: auth-secret +``` + +Für den Cloud-verbundenen Modus: + +```yaml +env: + - name: OS_CLOUD_URL + value: "https://cloud.example.com" + - name: OS_CLOUD_API_KEY + valueFrom: + secretKeyRef: + name: objectos-secrets + key: cloud-api-key +``` + +Für den dateibasierten Modus binden Sie das Artefakt ein und setzen: + +```yaml +env: + - name: OS_ARTIFACT_FILE + value: "/artifacts/objectstack.json" +``` + +## Probes + +ObjectOS stellt einen integrierten `GET /health`-Endpunkt bereit, der +antwortet, bevor der Projekt-Kernel vollständig aufgelöst ist. Das macht +ihn zum richtigen Ziel sowohl für Liveness- als auch für Readiness-Probes: + +```yaml +readinessProbe: + httpGet: + path: /health + port: 3000 + initialDelaySeconds: 5 + periodSeconds: 10 +livenessProbe: + httpGet: + path: /health + port: 3000 + initialDelaySeconds: 15 + periodSeconds: 20 +``` + +Für strengere Readiness-Prüfungen richten Sie eine zusätzliche Probe auf +eine anwendungsspezifische, generierte API-Route — dies bestätigt, dass +das Artefakt geladen wurde und der Kernel Anfragen bedient. + +## Ingress und CORS + +Terminieren Sie TLS am Edge oder am Ingress. Konfigurieren Sie CORS +explizit für die vom Kunden verwendeten Front-End-Ursprünge. Kombinieren +Sie keine Wildcard-Ursprünge mit Anfragen, die Anmeldedaten enthalten. + +Wenn ObjectOS hinter einem Proxy läuft, stellen Sie sicher, dass der Proxy +clientseitig übermittelte `X-Forwarded-For`-Werte entfernt, bevor er seine +eigenen setzt. Rate Limiting und Audit-Trails sind auf eine +vertrauenswürdige Aufrufer-Identität angewiesen. + +## Fortlaufende Upgrades + +ObjectOS-Image-Versionen und Anwendungs-Artefakt-Versionen sind getrennt. +Rollen Sie sie unabhängig voneinander aus: + +- ObjectOS-Image: Upgrade durch Ändern des Container-Tags. +- Anwendungs-Artefakt: Veröffentlichen oder binden Sie ein neues, unveränderliches Artefakt ein. +- Rollback: Stellen Sie den vorherigen Image-Tag oder Artefakt-Zeiger wieder her. diff --git a/content/docs/deploy/kubernetes.es.mdx b/content/docs/deploy/kubernetes.es.mdx new file mode 100644 index 0000000..74bb4ad --- /dev/null +++ b/content/docs/deploy/kubernetes.es.mdx @@ -0,0 +1,109 @@ +--- +title: Kubernetes +description: Despliega ObjectOS en un entorno de Kubernetes. +--- + +# Kubernetes + +Usa Kubernetes para despliegues de producción que necesiten secretos +gestionados, ingress, sondas, actualizaciones progresivas y bases de datos +gestionadas por el cliente. + +ObjectOS todavía no incluye un chart de Helm empaquetado, por lo que la +orientación a continuación describe los manifiestos que debes ensamblar en +torno a la imagen de contenedor publicada. + +## Estructura del despliegue + +Un despliegue de ObjectOS en producción normalmente incluye: + +| Componente | Recomendación | +|---|---| +| Deployment | Una imagen de contenedor de ObjectOS | +| Service | Servicio ClusterIP para el tráfico HTTP | +| Ingress | Terminación TLS y enrutamiento por nombre de host del cliente | +| Secret | `OS_AUTH_SECRET`, token del plano de control, credenciales de la base de datos | +| ConfigMap | Configuración de tiempo de ejecución no secreta | +| Almacenamiento persistente | Solo al usar artefactos de archivos locales o datos de evaluación SQLite | +| Base de datos externa | Recomendada para los datos de negocio en producción | + +## Configuración requerida + +Como mínimo, configura: + +```yaml +env: + - name: PORT + value: "3000" + - name: OS_AUTH_SECRET + valueFrom: + secretKeyRef: + name: objectos-secrets + key: auth-secret +``` + +Para el modo conectado a la nube: + +```yaml +env: + - name: OS_CLOUD_URL + value: "https://cloud.example.com" + - name: OS_CLOUD_API_KEY + valueFrom: + secretKeyRef: + name: objectos-secrets + key: cloud-api-key +``` + +Para el modo respaldado por archivos, monta el artefacto y configura: + +```yaml +env: + - name: OS_ARTIFACT_FILE + value: "/artifacts/objectstack.json" +``` + +## Sondas + +ObjectOS expone un endpoint integrado `GET /health` que responde antes de +que el kernel del proyecto esté completamente resuelto, lo que lo convierte +en el destino adecuado tanto para las sondas de liveness como de readiness: + +```yaml +readinessProbe: + httpGet: + path: /health + port: 3000 + initialDelaySeconds: 5 + periodSeconds: 10 +livenessProbe: + httpGet: + path: /health + port: 3000 + initialDelaySeconds: 15 + periodSeconds: 20 +``` + +Para comprobaciones de readiness más estrictas, dirige una sonda adicional a +una ruta de API generada específica de la aplicación: esto confirma que el +artefacto se cargó y que el kernel está atendiendo solicitudes. + +## Ingress y CORS + +Termina TLS en el edge o en el ingress. Configura CORS explícitamente para +los orígenes de front-end utilizados por el cliente. No combines orígenes +comodín con solicitudes con credenciales. + +Cuando ObjectOS se ejecuta detrás de un proxy, asegúrate de que el proxy +elimine los valores `X-Forwarded-For` proporcionados por el cliente antes de +establecer los suyos propios. La limitación de tasa y los registros de +auditoría dependen de una identidad de llamante fiable. + +## Actualizaciones progresivas + +Las versiones de la imagen de ObjectOS y las versiones del artefacto de la +aplicación son independientes. Actualízalas por separado: + +- Imagen de ObjectOS: actualiza cambiando la etiqueta del contenedor. +- Artefacto de la aplicación: publica o monta un nuevo artefacto inmutable. +- Reversión: restaura la etiqueta de imagen anterior o el puntero del artefacto. diff --git a/content/docs/deploy/kubernetes.fr.mdx b/content/docs/deploy/kubernetes.fr.mdx new file mode 100644 index 0000000..53cc8dd --- /dev/null +++ b/content/docs/deploy/kubernetes.fr.mdx @@ -0,0 +1,111 @@ +--- +title: Kubernetes +description: Déployez ObjectOS dans un environnement Kubernetes. +--- + +# Kubernetes + +Utilisez Kubernetes pour les déploiements en production qui nécessitent +la gestion des secrets, l'ingress, les sondes (probes), les mises à +niveau progressives et des bases de données gérées par le client. + +ObjectOS ne fournit pas encore de chart Helm packagé ; les conseils +ci-dessous décrivent donc les manifests à assembler autour de l'image de +conteneur publiée. + +## Forme du déploiement + +Un déploiement ObjectOS en production comprend normalement : + +| Composant | Recommandation | +|---|---| +| Deployment | Une image de conteneur ObjectOS | +| Service | Service ClusterIP pour le trafic HTTP | +| Ingress | Terminaison TLS et routage par nom d'hôte du client | +| Secret | `OS_AUTH_SECRET`, jeton du plan de contrôle, identifiants de base de données | +| ConfigMap | Configuration d'exécution non secrète | +| Stockage persistant | Uniquement avec des artefacts de fichiers locaux ou des données d'évaluation SQLite | +| Base de données externe | Recommandée pour les données métier en production | + +## Configuration requise + +Configurez au minimum : + +```yaml +env: + - name: PORT + value: "3000" + - name: OS_AUTH_SECRET + valueFrom: + secretKeyRef: + name: objectos-secrets + key: auth-secret +``` + +Pour le mode connecté au cloud : + +```yaml +env: + - name: OS_CLOUD_URL + value: "https://cloud.example.com" + - name: OS_CLOUD_API_KEY + valueFrom: + secretKeyRef: + name: objectos-secrets + key: cloud-api-key +``` + +Pour le mode basé sur un fichier, montez l'artefact et définissez : + +```yaml +env: + - name: OS_ARTIFACT_FILE + value: "/artifacts/objectstack.json" +``` + +## Sondes (probes) + +ObjectOS expose un point de terminaison `GET /health` intégré qui répond +avant que le noyau du projet ne soit entièrement résolu, ce qui en fait +la cible idéale pour les sondes de liveness et de readiness : + +```yaml +readinessProbe: + httpGet: + path: /health + port: 3000 + initialDelaySeconds: 5 + periodSeconds: 10 +livenessProbe: + httpGet: + path: /health + port: 3000 + initialDelaySeconds: 15 + periodSeconds: 20 +``` + +Pour des vérifications de readiness plus strictes, dirigez une sonde +supplémentaire vers une route d'API générée spécifique à l'application — +cela confirme que l'artefact est chargé et que le noyau répond aux +requêtes. + +## Ingress et CORS + +Terminez le TLS en périphérie ou au niveau de l'ingress. Configurez CORS +explicitement pour les origines front-end utilisées par le client. Ne +combinez pas les origines génériques (wildcard) avec des requêtes +authentifiées (credentialed). + +Lorsque ObjectOS s'exécute derrière un proxy, assurez-vous que le proxy +supprime les valeurs `X-Forwarded-For` fournies par le client avant de +définir les siennes. La limitation de débit (rate limiting) et les +pistes d'audit dépendent d'une identité d'appelant fiable. + +## Mises à niveau progressives + +Les versions de l'image ObjectOS et les versions de l'artefact +applicatif sont distinctes. Déployez-les indépendamment : + +- Image ObjectOS : mettez à niveau en changeant le tag du conteneur. +- Artefact applicatif : publiez ou montez un nouvel artefact immuable. +- Rollback : restaurez le tag d'image précédent ou le pointeur d'artefact. diff --git a/content/docs/deploy/kubernetes.ja.mdx b/content/docs/deploy/kubernetes.ja.mdx new file mode 100644 index 0000000..0aebd0a --- /dev/null +++ b/content/docs/deploy/kubernetes.ja.mdx @@ -0,0 +1,106 @@ +--- +title: Kubernetes +description: Kubernetes 環境に ObjectOS をデプロイします。 +--- + +# Kubernetes + +マネージドシークレット、Ingress、プローブ、ローリングアップグレード、 +顧客管理データベースを必要とする本番デプロイには Kubernetes を使用します。 + +ObjectOS はまだパッケージ化された Helm チャートを提供していないため、 +以下のガイダンスでは公開コンテナイメージの周囲に構成するマニフェストについて説明します。 + +## デプロイメント構成 + +本番の ObjectOS デプロイメントには通常、次のものが含まれます。 + +| コンポーネント | 推奨事項 | +|---|---| +| Deployment | ObjectOS コンテナイメージ 1 つ | +| Service | HTTP トラフィック用の ClusterIP サービス | +| Ingress | TLS 終端と顧客ホスト名のルーティング | +| Secret | `OS_AUTH_SECRET`、コントロールプレーントークン、データベース認証情報 | +| ConfigMap | シークレット以外のランタイム構成 | +| 永続ストレージ | ローカルファイルのアーティファクトまたは SQLite 評価データを使用する場合のみ | +| 外部データベース | 本番の業務データには推奨 | + +## 必須の構成 + +最低限、次の構成を行います。 + +```yaml +env: + - name: PORT + value: "3000" + - name: OS_AUTH_SECRET + valueFrom: + secretKeyRef: + name: objectos-secrets + key: auth-secret +``` + +クラウド接続モードの場合: + +```yaml +env: + - name: OS_CLOUD_URL + value: "https://cloud.example.com" + - name: OS_CLOUD_API_KEY + valueFrom: + secretKeyRef: + name: objectos-secrets + key: cloud-api-key +``` + +ファイルバックモードの場合は、アーティファクトをマウントして次を設定します。 + +```yaml +env: + - name: OS_ARTIFACT_FILE + value: "/artifacts/objectstack.json" +``` + +## プローブ + +ObjectOS はプロジェクトカーネルが完全に解決される前に応答する組み込みの +`GET /health` エンドポイントを公開しており、これは liveness と readiness の +両方のプローブのターゲットとして適しています。 + +```yaml +readinessProbe: + httpGet: + path: /health + port: 3000 + initialDelaySeconds: 5 + periodSeconds: 10 +livenessProbe: + httpGet: + path: /health + port: 3000 + initialDelaySeconds: 15 + periodSeconds: 20 +``` + +より厳密な readiness チェックを行うには、追加のプローブをアプリケーション固有の +生成された API ルートに向けてください。これにより、アーティファクトが読み込まれ、 +カーネルがリクエストを処理していることを確認できます。 + +## Ingress と CORS + +エッジまたは Ingress で TLS を終端します。顧客が使用するフロントエンドの +オリジンに対して CORS を明示的に構成します。ワイルドカードのオリジンと +認証情報付きのリクエストを組み合わせないでください。 + +ObjectOS をプロキシの背後で実行する場合は、プロキシが独自の値を設定する前に +クライアントから提供された `X-Forwarded-For` 値を取り除くようにしてください。 +レート制限と監査証跡は、信頼できる呼び出し元の識別情報に依存します。 + +## ローリングアップグレード + +ObjectOS のイメージバージョンとアプリケーションアーティファクトのバージョンは +別個のものです。それぞれ独立してロールアウトします。 + +- ObjectOS イメージ: コンテナタグを変更してアップグレードします。 +- アプリケーションアーティファクト: 新しいイミュータブルなアーティファクトを公開またはマウントします。 +- ロールバック: 以前のイメージタグまたはアーティファクトのポインタを復元します。 diff --git a/content/docs/deploy/kubernetes.mdx b/content/docs/deploy/kubernetes.mdx index f8b0c9b..8bacab4 100644 --- a/content/docs/deploy/kubernetes.mdx +++ b/content/docs/deploy/kubernetes.mdx @@ -8,6 +8,9 @@ description: Deploy ObjectOS in a Kubernetes environment. Use Kubernetes for production deployments that need managed secrets, ingress, probes, rolling upgrades, and customer-managed databases. +ObjectOS does not yet ship a packaged Helm chart, so the guidance below +describes the manifests to assemble around the published container image. + ## Deployment shape A production ObjectOS deployment normally includes: diff --git a/content/docs/deploy/kubernetes.cn.mdx b/content/docs/deploy/kubernetes.zh-Hans.mdx similarity index 93% rename from content/docs/deploy/kubernetes.cn.mdx rename to content/docs/deploy/kubernetes.zh-Hans.mdx index e00bdd5..d73c553 100644 --- a/content/docs/deploy/kubernetes.cn.mdx +++ b/content/docs/deploy/kubernetes.zh-Hans.mdx @@ -7,6 +7,8 @@ description: 在 Kubernetes 环境部署 ObjectOS。 当你的生产部署需要受管的密钥、Ingress、探针、滚动升级和客户自管数据库时,使用 Kubernetes。 +ObjectOS 目前尚未提供打包好的 Helm chart,因此下面的指南将说明如何围绕已发布的容器镜像组装相应的清单(manifests)。 + ## 部署形态 一个生产形态的 ObjectOS 部署通常包含: diff --git a/content/docs/deploy/meta.de.json b/content/docs/deploy/meta.de.json new file mode 100644 index 0000000..3c22b99 --- /dev/null +++ b/content/docs/deploy/meta.de.json @@ -0,0 +1,10 @@ +{ + "title": "Bereitstellen", + "defaultOpen": false, + "pages": [ + "index", + "docker", + "kubernetes", + "air-gapped" + ] +} diff --git a/content/docs/deploy/meta.es.json b/content/docs/deploy/meta.es.json new file mode 100644 index 0000000..11c3d4e --- /dev/null +++ b/content/docs/deploy/meta.es.json @@ -0,0 +1,10 @@ +{ + "title": "Desplegar", + "defaultOpen": false, + "pages": [ + "index", + "docker", + "kubernetes", + "air-gapped" + ] +} diff --git a/content/docs/deploy/meta.fr.json b/content/docs/deploy/meta.fr.json new file mode 100644 index 0000000..90329bf --- /dev/null +++ b/content/docs/deploy/meta.fr.json @@ -0,0 +1,10 @@ +{ + "title": "Déploiement", + "defaultOpen": false, + "pages": [ + "index", + "docker", + "kubernetes", + "air-gapped" + ] +} diff --git a/content/docs/deploy/meta.ja.json b/content/docs/deploy/meta.ja.json new file mode 100644 index 0000000..e7f5006 --- /dev/null +++ b/content/docs/deploy/meta.ja.json @@ -0,0 +1,10 @@ +{ + "title": "デプロイ", + "defaultOpen": false, + "pages": [ + "index", + "docker", + "kubernetes", + "air-gapped" + ] +} diff --git a/content/docs/deploy/meta.cn.json b/content/docs/deploy/meta.zh-Hans.json similarity index 100% rename from content/docs/deploy/meta.cn.json rename to content/docs/deploy/meta.zh-Hans.json diff --git a/content/docs/index.de.mdx b/content/docs/index.de.mdx new file mode 100644 index 0000000..f5261b8 --- /dev/null +++ b/content/docs/index.de.mdx @@ -0,0 +1,99 @@ +--- +title: ObjectOS +description: Die Laufzeitumgebung für interne Tools, die in Ihrem Netzwerk bleibt. Ein Befehl zum Starten, Ihre Datenbank, Ihre Authentifizierung, Ihre Daten — niemals unsere. +--- + +# ObjectOS + +**ObjectOS ist eine selbst gehostete Laufzeitumgebung zum Erstellen +interner Tools, Admin-Panels und Back-Office-Anwendungen, ohne die +Kontrolle über Ihre Daten aufzugeben.** Beschreiben Sie dem +in der Console integrierten AI Builder, was Sie benötigen — oder forken Sie +eine Vorlage — und erhalten Sie REST-APIs, eine generierte Admin-UI, +Authentifizierung, RBAC, Audit-Logs, Dateispeicher, Hintergrundjobs, +Webhooks und KI-Integration. Alles läuft in Ihrem Netzwerk, auf Ihrer +Datenbank. + +Es ist das, was herauskäme, wenn Retool, Supabase und Salesforce ein Kind +bekämen, das innerhalb Ihrer Firewall läuft — mit einer KI, die die Apps für +Sie erstellt. + +## In 60 Sekunden einsatzbereit + +```bash +npm i -g @objectstack/cli +os start +``` + +Öffnen Sie **http://localhost:3000** und Sie haben ein funktionierendes +ObjectOS mit Console und Account, einem Audit-Log und einer +SQLite-Datenbank — ohne Konfiguration, ohne Scaffolding. + +Dann entweder: + +- **Sprechen Sie mit dem AI Builder** — *"Ich muss Support-Tickets mit + Priorität und zugewiesener Person verfolgen"* — und beobachten Sie, wie die + Metadaten generiert werden. Siehe + [Build → AI Builder](/docs/build/ai-builder). +- **Installieren Sie eine Vorlage** aus dem in der Console integrierten + marketplace (Todo, Contracts, Helpdesk, …) und erhalten Sie mit einem Klick + eine echte App. +- **Forken Sie eine [Vorlage](/docs/build/templates)**, wenn Sie + TypeScript-Quellcode unter Ihrer Kontrolle haben möchten. + +## Warum ObjectOS statt … + +| Sie verwenden | Schmerzpunkt | Was ObjectOS Ihnen bietet | +|---|---|---| +| **Retool / Appsmith** | Der UI-Builder ist großartig, aber Ihre Daten liegen in deren Cloud und die Preise skalieren mit der Nutzerzahl | Ihre Daten verlassen niemals Ihr Netzwerk; Apache-2.0, keine Lizenzgebühr pro Sitzplatz | +| **Supabase / Firebase** | Backend-as-a-Service ist schnell, aber an einen Anbieter gebunden; mandantenfähiges SaaS von Grund auf | Gleiche DX (automatische APIs, Authentifizierung, Speicher), aber Sie besitzen die Laufzeitumgebung und die Datenbank | +| **Salesforce / NetSuite** | Leistungsstarke Plattform, mühsame Anpassung, schwindelerregende Kosten pro Sitzplatz | Gleiches metadatengesteuertes Modell (Objekte, Felder, Rollen, Freigaberegeln), selbst gehostet, keine Gebühr pro Sitzplatz | +| **Selbstentwicklung (Next + Prisma + NextAuth)** | Sie bauen jedes Mal RBAC, Audit, Datei-Uploads, Einstellungen, Webhooks und Jobs neu auf | Liefern Sie die eigentliche Geschäftslogik aus; die Plattform-Infrastruktur ist bereits vorhanden | + +## Was Sie sofort erhalten + +| Bereich | Was es ist | +|---|---| +| **Automatische REST-API** | Jedes Objekt, das Sie deklarieren, erhält `/api/v1/data/` mit Filtern/Sortieren/Paginierung | +| **Console** (`/_console/`) | Generierte Admin-UI: Datensätze durchsuchen und bearbeiten, Benutzer/Rollen/Berechtigungssätze verwalten, Audit-Log, Sitzungen, API-Schlüssel und Einstellungen anzeigen | +| **Account** (`/_account/`) | Anmeldung, Registrierung, Passwort-Zurücksetzung, OAuth, OIDC/SSO, Passkeys, 2FA | +| **20+ Plugins** | RBAC + Sicherheit auf Zeilenebene, Audit, Dateispeicher, Queues, Jobs, E-Mail, KI, Webhooks — deklarativ, bei Bedarf | + +## Worüber Sie die Kontrolle behalten + +| Asset | Wo es liegt | +|---|---| +| Geschäftsdaten | **Ihre** Datenbank (Postgres, SQLite, MySQL, MongoDB) | +| Benutzeridentitäten & Sitzungen | **Ihre** Datenbank | +| Audit-Log | **Ihre** Datenbank | +| Dateien | **Ihr** Speicher (lokale Festplatte, S3 oder S3-kompatibel wie R2/MinIO) | +| Secrets | **Ihr** Secret Manager | +| Die Laufzeitumgebung selbst | **Ihre** Server, Container oder Ihr Laptop | + +ObjectOS funkt niemals nach Hause. Keine Telemetrie. Kein Lizenzserver. +Air-Gapped-Netzwerke sind ein erstklassiges Deployment-Ziel — siehe +[Air-gapped](/docs/deploy/air-gapped). + +## Wohin als Nächstes + +| Wenn Sie … möchten | Lesen Sie | +|---|---| +| Sehen, wie es tatsächlich funktioniert | [Quickstart](/docs/quickstart) | +| Verstehen, was drinsteckt | [Architecture](/docs/architecture) | +| Es in Docker ausführen | [Docker](/docs/deploy/docker) | +| Auf Kubernetes deployen | [Kubernetes](/docs/deploy/kubernetes) | +| Es mit Postgres / Ihrer DB verbinden | [Runtime Configuration](/docs/configure/runtime) | +| SSO einrichten | [Authentication](/docs/configure/authentication) | +| Festlegen, wer was sieht | [Permissions](/docs/configure/permissions) | +| Es von einem anderen Dienst aus aufrufen | [API Access](/docs/configure/api-access) | +| Ereignisse an andere Systeme senden | [Webhooks](/docs/configure/webhooks) | +| In Produktion gehen | [Production Readiness](/docs/operate/production) | + +## Lizenz & Preise + +Die ObjectOS-Laufzeitumgebung ist **Apache-2.0** — die freizügigste +weit verbreitete OSS-Lizenz. Verwenden Sie sie in kommerziellen Produkten, +betten Sie sie ein, verteilen Sie sie weiter, behalten Sie Ihre Änderungen +privat. Keine Gebühr pro Sitzplatz, kein Lizenzserver, kein +"ab 50.000 $/Jahr". Optionaler kommerzieller Support und Managed Hosting +sind separat verfügbar — siehe [License](/docs/resources/license). diff --git a/content/docs/index.es.mdx b/content/docs/index.es.mdx new file mode 100644 index 0000000..b3e6c0f --- /dev/null +++ b/content/docs/index.es.mdx @@ -0,0 +1,99 @@ +--- +title: ObjectOS +description: El runtime para herramientas internas que permanece en tu red. Un solo comando para empezar; tu base de datos, tu autenticación, tus datos — nunca los nuestros. +--- + +# ObjectOS + +**ObjectOS es un runtime autoalojado para crear herramientas internas, +paneles de administración y aplicaciones de back-office sin renunciar a +tus datos.** Describe lo que necesitas al AI Builder integrado en la +Console — o haz un fork de una plantilla — y obtén APIs REST, una UI de +administración generada, autenticación, RBAC, registros de auditoría, +almacenamiento de archivos, trabajos en segundo plano, webhooks e +integración con IA. Todo ejecutándose en tu red, sobre tu base de datos. + +Es lo que obtendrías si Retool, Supabase y Salesforce tuvieran un hijo +que se ejecutara dentro de tu firewall — con una IA que crea las +aplicaciones por ti. + +## Ponlo en marcha en 60 segundos + +```bash +npm i -g @objectstack/cli +os start +``` + +Abre **http://localhost:3000** y tendrás un ObjectOS funcional con +Console y Account, un registro de auditoría y una base de datos SQLite — +sin configuración, sin scaffolding. + +Luego, puedes: + +- **Hablar con el AI Builder** — *"Necesito hacer seguimiento de tickets + de soporte con prioridad y responsable asignado"* — y ver cómo se + generan los metadatos. Consulta + [Build → AI Builder](/docs/build/ai-builder). +- **Instalar una plantilla** desde el marketplace integrado en la Console + (Todo, Contracts, Helpdesk, …) y tener una aplicación real con un solo + clic. +- **Hacer un fork de una [plantilla](/docs/build/templates)** si quieres + el código fuente en TypeScript bajo tu control. + +## Por qué ObjectOS en lugar de … + +| Lo que usas | Punto de dolor | Lo que te ofrece ObjectOS | +|---|---|---| +| **Retool / Appsmith** | El constructor de UI es excelente, pero tus datos viven en su nube y sus precios escalan con los usuarios | Tus datos nunca salen de tu red; Apache-2.0, sin coste por asiento | +| **Supabase / Firebase** | El backend-as-a-service es rápido pero genera dependencia del proveedor; SaaS multitenant por diseño | La misma DX (APIs automáticas, autenticación, almacenamiento), pero tú eres dueño del runtime y la base de datos | +| **Salesforce / NetSuite** | Plataforma potente, personalización dolorosa, coste por asiento exorbitante | El mismo modelo orientado a metadatos (objetos, campos, roles, reglas de compartición), autoalojado, sin coste por asiento | +| **Construirlo tú mismo (Next + Prisma + NextAuth)** | Reconstruyes RBAC, auditoría, subida de archivos, ajustes, webhooks y trabajos cada vez | Despliega la lógica de negocio real; la infraestructura de la plataforma ya está lista | + +## Lo que obtienes de fábrica + +| Superficie | Qué es | +|---|---| +| **API REST automática** | Cada objeto que declaras obtiene `/api/v1/data/` con filtrado/ordenación/paginación | +| **Console** (`/_console/`) | UI de administración generada: explora y edita registros, gestiona usuarios/roles/conjuntos de permisos, consulta el registro de auditoría, sesiones, claves de API y ajustes | +| **Account** (`/_account/`) | Inicio de sesión, registro, restablecimiento de contraseña, OAuth, OIDC/SSO, passkeys, 2FA | +| **Más de 20 plugins** | RBAC + seguridad a nivel de fila, auditoría, almacenamiento de archivos, colas, trabajos, correo, IA, webhooks — declarativos y bajo demanda | + +## Sobre lo que mantienes el control + +| Activo | Dónde reside | +|---|---| +| Datos de negocio | **Tu** base de datos (Postgres, SQLite, MySQL, MongoDB) | +| Identidades de usuario y sesiones | **Tu** base de datos | +| Registro de auditoría | **Tu** base de datos | +| Archivos | **Tu** almacenamiento (disco local, S3 o compatible con S3 como R2/MinIO) | +| Secretos | **Tu** gestor de secretos | +| El runtime en sí | **Tus** servidores, contenedores o portátil | + +ObjectOS nunca se comunica con el exterior. Sin telemetría. Sin servidor +de licencias. Las redes aisladas (air-gapped) son un objetivo de +despliegue de primera clase — consulta +[Air-gapped](/docs/deploy/air-gapped). + +## A dónde ir a continuación + +| Si quieres … | Lee | +|---|---| +| Verlo funcionar de verdad | [Quickstart](/docs/quickstart) | +| Entender qué hay dentro | [Architecture](/docs/architecture) | +| Ejecutarlo en Docker | [Docker](/docs/deploy/docker) | +| Desplegarlo en Kubernetes | [Kubernetes](/docs/deploy/kubernetes) | +| Conectarlo a Postgres / tu BD | [Runtime Configuration](/docs/configure/runtime) | +| Configurar SSO | [Authentication](/docs/configure/authentication) | +| Restringir quién ve qué | [Permissions](/docs/configure/permissions) | +| Llamarlo desde otro servicio | [API Access](/docs/configure/api-access) | +| Enviar eventos a otros sistemas | [Webhooks](/docs/configure/webhooks) | +| Pasar a producción | [Production Readiness](/docs/operate/production) | + +## Licencia y precios + +El runtime de ObjectOS es **Apache-2.0** — la licencia OSS de uso +extendido más permisiva. Úsalo en productos comerciales, incrústalo, +redistribúyelo, mantén tus modificaciones privadas. Sin tarifa por +asiento, sin servidor de licencias, sin "desde 50.000 $/año". Hay +soporte comercial y alojamiento gestionado opcionales disponibles por +separado — consulta [License](/docs/resources/license). diff --git a/content/docs/index.fr.mdx b/content/docs/index.fr.mdx new file mode 100644 index 0000000..fc39b98 --- /dev/null +++ b/content/docs/index.fr.mdx @@ -0,0 +1,97 @@ +--- +title: ObjectOS +description: Le runtime des outils internes qui reste dans votre réseau. Une seule commande pour démarrer, votre base de données, votre authentification, vos données — jamais les nôtres. +--- + +# ObjectOS + +**ObjectOS est un runtime auto-hébergé pour créer des outils internes, des +panneaux d'administration et des applications de back-office sans renoncer +à vos données.** Décrivez ce dont vous avez besoin à l'AI Builder intégré à +la Console — ou forkez un template — et obtenez des API REST, une interface +d'administration générée, l'authentification, le RBAC, des journaux d'audit, +le stockage de fichiers, des tâches en arrière-plan, des webhooks et +l'intégration de l'IA. Le tout s'exécutant dans votre réseau, sur votre base +de données. + +C'est ce que vous obtiendriez si Retool, Supabase et Salesforce avaient un +enfant qui s'exécutait à l'intérieur de votre pare-feu — avec une IA qui +construit les applications pour vous. + +## Opérationnel en 60 secondes + +```bash +npm i -g @objectstack/cli +os start +``` + +Ouvrez **http://localhost:3000** et vous disposez d'un ObjectOS fonctionnel +avec la Console et l'Account, un journal d'audit et une base de données +SQLite — zéro configuration, zéro échafaudage. + +Ensuite, au choix : + +- **Parlez à l'AI Builder** — *« J'ai besoin de suivre des tickets de support + avec une priorité et un destinataire assigné »* — et observez la génération + des métadonnées. Voir [Build → AI Builder](/docs/build/ai-builder). +- **Installez un template** depuis le marketplace intégré à la Console (Todo, + Contracts, Helpdesk, …) et obtenez une vraie application en un clic. +- **Forkez un [template](/docs/build/templates)** si vous voulez du code source + TypeScript sous votre contrôle. + +## Pourquoi ObjectOS plutôt que … + +| Vous utilisez | Point de friction | Ce qu'ObjectOS vous apporte | +|---|---|---| +| **Retool / Appsmith** | Le générateur d'interface est excellent, mais vos données résident dans leur cloud et leur tarification augmente avec le nombre d'utilisateurs | Vos données ne quittent jamais votre réseau ; Apache-2.0, sans taxe par siège | +| **Supabase / Firebase** | Le backend-as-a-service est rapide mais soumis au verrouillage fournisseur ; SaaS multi-tenant par conception | Même expérience développeur (API automatiques, authentification, stockage), mais vous possédez le runtime et la base de données | +| **Salesforce / NetSuite** | Plateforme puissante, personnalisation pénible, coût par siège exorbitant | Même modèle piloté par métadonnées (objets, champs, rôles, règles de partage), auto-hébergé, sans taxe par siège | +| **Tout reconstruire soi-même (Next + Prisma + NextAuth)** | Vous reconstruisez le RBAC, l'audit, le téléversement de fichiers, les paramètres, les webhooks et les tâches à chaque fois | Livrez la véritable logique métier ; la plomberie de la plateforme est déjà là | + +## Ce que vous obtenez d'emblée + +| Surface | De quoi il s'agit | +|---|---| +| **API REST automatique** | Chaque objet que vous déclarez obtient `/api/v1/data/` avec filtrage/tri/pagination | +| **Console** (`/_console/`) | Interface d'administration générée : parcourir et modifier les enregistrements, gérer les utilisateurs/rôles/ensembles de permissions, consulter le journal d'audit, les sessions, les clés API, les paramètres | +| **Account** (`/_account/`) | Connexion, inscription, réinitialisation du mot de passe, OAuth, OIDC/SSO, passkeys, 2FA | +| **Plus de 20 plugins** | RBAC + sécurité au niveau des lignes, audit, stockage de fichiers, files d'attente, tâches, e-mail, IA, webhooks — déclaratifs, à la demande | + +## Ce dont vous gardez le contrôle + +| Ressource | Où elle réside | +|---|---| +| Données métier | **Votre** base de données (Postgres, SQLite, MySQL, MongoDB) | +| Identités et sessions des utilisateurs | **Votre** base de données | +| Journal d'audit | **Votre** base de données | +| Fichiers | **Votre** stockage (disque local, S3 ou compatible S3 comme R2/MinIO) | +| Secrets | **Votre** gestionnaire de secrets | +| Le runtime lui-même | **Vos** serveurs, conteneurs ou ordinateur portable | + +ObjectOS ne communique jamais avec l'extérieur. Aucune télémétrie. Aucun +serveur de licence. Les réseaux isolés (air-gapped) sont une cible de +déploiement de premier ordre — voir [Air-gapped](/docs/deploy/air-gapped). + +## Où aller ensuite + +| Si vous voulez … | Lire | +|---|---| +| Le voir fonctionner concrètement | [Quickstart](/docs/quickstart) | +| Comprendre ce qu'il y a dans la boîte | [Architecture](/docs/architecture) | +| L'exécuter dans Docker | [Docker](/docs/deploy/docker) | +| Le déployer sur Kubernetes | [Kubernetes](/docs/deploy/kubernetes) | +| Le connecter à Postgres / votre base de données | [Runtime Configuration](/docs/configure/runtime) | +| Configurer le SSO | [Authentication](/docs/configure/authentication) | +| Verrouiller qui voit quoi | [Permissions](/docs/configure/permissions) | +| L'appeler depuis un autre service | [API Access](/docs/configure/api-access) | +| Envoyer des événements vers d'autres systèmes | [Webhooks](/docs/configure/webhooks) | +| Passer en production | [Production Readiness](/docs/operate/production) | + +## Licence et tarification + +Le runtime ObjectOS est sous **Apache-2.0** — la licence open source la plus +permissive et la plus largement utilisée. Utilisez-le dans des produits +commerciaux, intégrez-le, redistribuez-le, gardez vos modifications privées. +Aucun frais par siège, aucun serveur de licence, aucun « à partir de +50 000 $/an ». Un support commercial et un hébergement managé optionnels sont +disponibles séparément — voir [License](/docs/resources/license). diff --git a/content/docs/index.ja.mdx b/content/docs/index.ja.mdx new file mode 100644 index 0000000..e4f492f --- /dev/null +++ b/content/docs/index.ja.mdx @@ -0,0 +1,75 @@ +--- +title: ObjectOS +description: ネットワーク内にとどまる社内ツール向けランタイム。1つのコマンドで起動でき、データベースも認証もデータもすべてあなたのもの——決して私たちのものにはなりません。 +--- + +# ObjectOS + +**ObjectOS は、データを手放すことなく社内ツール、管理パネル、バックオフィスアプリを構築するためのセルフホスト型ランタイムです。** 必要なものを Console 内の AI Builder に説明する——あるいはテンプレートをフォークする——だけで、REST API、生成された管理 UI、認証、RBAC、監査ログ、ファイルストレージ、バックグラウンドジョブ、Webhook、AI 連携が手に入ります。すべてはあなたのネットワーク内で、あなたのデータベース上で動作します。 + +これは、Retool と Supabase と Salesforce の子どもがあなたのファイアウォールの内側で動くようなもの——しかもアプリをあなたの代わりに構築する AI 付きです。 + +## 60 秒で起動 + +```bash +npm i -g @objectstack/cli +os start +``` + +**http://localhost:3000** を開けば、Console と Account、監査ログ、SQLite データベースを備えた稼働中の ObjectOS が手に入ります——設定不要、スキャフォールディング不要です。 + +そのうえで、次のいずれかを行えます。 + +- **AI Builder に話しかける**——*「優先度と担当者付きでサポートチケットを管理したい」*——と、メタデータが生成される様子を見られます。[Build → AI Builder](/docs/build/ai-builder) を参照してください。 +- Console 内の marketplace から **テンプレートをインストール**する(Todo、Contracts、Helpdesk、…)と、ワンクリックで実際のアプリが動きます。 +- 自分の管理下に TypeScript ソースを置きたい場合は、**[テンプレート](/docs/build/templates)をフォーク**します。 + +## なぜ … ではなく ObjectOS なのか + +| 利用中のもの | 課題 | ObjectOS が提供するもの | +|---|---|---| +| **Retool / Appsmith** | UI ビルダーは優れているが、データは彼らのクラウドに置かれ、料金はユーザー数に応じて増加する | データがネットワークから出ることはなく、Apache-2.0、シート課金もなし | +| **Supabase / Firebase** | Backend-as-a-Service は高速だがベンダーロックインされる。設計上マルチテナント SaaS である | 同等の DX(自動 API、認証、ストレージ)でありながら、ランタイムとデータベースはあなたが所有する | +| **Salesforce / NetSuite** | 強力なプラットフォームだが、カスタマイズが苦痛で、シート単価が目を見張るほど高い | 同じメタデータ駆動モデル(オブジェクト、フィールド、ロール、共有ルール)をセルフホストで、シート課金なし | +| **自前構築(Next + Prisma + NextAuth)** | RBAC、監査、ファイルアップロード、設定、Webhook、ジョブを毎回作り直す | 実際のビジネスロジックを出荷できる。プラットフォームの配管はすでに整っている | + +## すぐに使える機能 + +| 機能領域 | 概要 | +|---|---| +| **自動 REST API** | 宣言したすべてのオブジェクトに、フィルター/ソート/ページネーション付きの `/api/v1/data/` が用意される | +| **Console** (`/_console/`) | 生成された管理 UI:レコードの閲覧と編集、ユーザー/ロール/権限セットの管理、監査ログ・セッション・API キー・設定の表示 | +| **Account** (`/_account/`) | ログイン、登録、パスワードリセット、OAuth、OIDC/SSO、パスキー、2FA | +| **20 以上のプラグイン** | RBAC + 行レベルセキュリティ、監査、ファイルストレージ、キュー、ジョブ、メール、AI、Webhook——宣言的に、必要に応じて | + +## あなたが制御し続けるもの + +| 資産 | 保管場所 | +|---|---| +| 業務データ | **あなたの**データベース(Postgres、SQLite、MySQL、MongoDB) | +| ユーザー ID とセッション | **あなたの**データベース | +| 監査ログ | **あなたの**データベース | +| ファイル | **あなたの**ストレージ(ローカルディスク、S3、または R2/MinIO のような S3 互換ストレージ) | +| シークレット | **あなたの**シークレットマネージャー | +| ランタイムそのもの | **あなたの**サーバー、コンテナ、またはノート PC | + +ObjectOS が外部に通信することはありません。テレメトリーなし。ライセンスサーバーなし。エアギャップネットワークは第一級のデプロイ対象です——[エアギャップ](/docs/deploy/air-gapped)を参照してください。 + +## 次に読むべきもの + +| やりたいこと | 読むべきもの | +|---|---| +| 実際の動作を見る | [クイックスタート](/docs/quickstart) | +| 中身を理解する | [アーキテクチャ](/docs/architecture) | +| Docker で実行する | [Docker](/docs/deploy/docker) | +| Kubernetes にデプロイする | [Kubernetes](/docs/deploy/kubernetes) | +| Postgres / 自分の DB に接続する | [ランタイム構成](/docs/configure/runtime) | +| SSO を設定する | [認証](/docs/configure/authentication) | +| 誰が何を見られるかを制限する | [権限](/docs/configure/permissions) | +| 別のサービスから呼び出す | [API アクセス](/docs/configure/api-access) | +| 他システムへイベントを送信する | [Webhook](/docs/configure/webhooks) | +| 本番環境へ移行する | [本番運用への準備](/docs/operate/production) | + +## ライセンスと料金 + +ObjectOS ランタイムは **Apache-2.0**——広く使われている OSS ライセンスの中で最も寛容なものです。商用製品で利用する、組み込む、再配布する、変更内容を非公開にしておく——いずれも可能です。シート単価なし、ライセンスサーバーなし、「年間 5 万ドルから」もありません。オプションの商用サポートとマネージドホスティングは別途提供しています——[ライセンス](/docs/resources/license)を参照してください。 diff --git a/content/docs/index.mdx b/content/docs/index.mdx index 5b9e0fb..86e9ee6 100644 --- a/content/docs/index.mdx +++ b/content/docs/index.mdx @@ -52,16 +52,16 @@ Then either: | **Auto REST API** | Every object you declare gets `/api/v1/data/` with filter/sort/paginate | | **Console** (`/_console/`) | Generated admin UI: browse and edit records, manage users/roles/permission sets, view audit log, sessions, API keys, settings | | **Account** (`/_account/`) | Login, register, password reset, OAuth, OIDC/SSO, passkeys, 2FA | -| **23 plugins** | RBAC + row-level security, audit, file storage, queues, jobs, email, AI, webhooks — declarative, on demand | +| **20+ plugins** | RBAC + row-level security, audit, file storage, queues, jobs, email, AI, webhooks — declarative, on demand | ## What you keep control of | Asset | Where it lives | |---|---| -| Business data | **Your** database (Postgres, SQLite, MySQL, Turso, MongoDB) | +| Business data | **Your** database (Postgres, SQLite, MySQL, MongoDB) | | User identities & sessions | **Your** database | | Audit log | **Your** database | -| Files | **Your** storage (local disk, S3, R2) | +| Files | **Your** storage (local disk, S3, or S3-compatible like R2/MinIO) | | Secrets | **Your** secret manager | | The runtime itself | **Your** servers, containers, or laptop | diff --git a/content/docs/index.cn.mdx b/content/docs/index.zh-Hans.mdx similarity index 100% rename from content/docs/index.cn.mdx rename to content/docs/index.zh-Hans.mdx diff --git a/content/docs/operate/backup.de.mdx b/content/docs/operate/backup.de.mdx new file mode 100644 index 0000000..874b4b8 --- /dev/null +++ b/content/docs/operate/backup.de.mdx @@ -0,0 +1,167 @@ +--- +title: Backup und Disaster Recovery +description: Was gesichert werden muss, wie wiederhergestellt wird und wie man für den Ausfall plant. +--- + +# Backup und Disaster Recovery + +ObjectOS selbst ist zustandslos — die Laufzeitumgebung kann aus dem +Container-Image neu aufgebaut werden. **Bei Backups geht es um die Daten, +von denen ObjectOS abhängt, nicht um ObjectOS selbst.** Planen Sie die +Wiederherstellung rund um diese Datensätze. + +## Was gesichert werden muss + +| Asset | Verantwortlich | Backup-Strategie | +|---|---|---| +| Geschäftsdatenbank | Kunde | Datenbank-native Sicherung (PITR für Managed Services); Wiederherstellung vierteljährlich testen | +| Kompiliertes Artefakt (`objectstack.json`) | Anwendungs-/Release-Team | Jedes veröffentlichte Artefakt in unveränderlichem Speicher ablegen; niemals überschreiben | +| Secrets-Baseline | Secret-Manager des Kunden | Anbieter-native Sicherung; Rotationsintervall gemäß Richtlinie | +| Objekt-/Dateispeicher (wenn die `storage`-Capability aktiviert ist) | Kunde | Bucket-Versionierung + bei Bedarf regionsübergreifende Replikation | +| Vom Kunden verwalteter Identitätsanbieter | IdP-Anbieter | Anbieter-native | + +ObjectOS benötigt **kein** separates Backup seines Container-Dateisystems. +Cache-Verzeichnisse (`OS_CACHE_DIR`) sind neu aufbaubar. + +## Datenbank-Backups + +Passen Sie die Strategie an den Treiber an: + +| Treiber | Empfohlener Ansatz | +|---|---| +| PostgreSQL | Kontinuierliches WAL-Archiving + Base-Backup; Point-in-Time-Wiederherstellung | +| MySQL | Binärlog-Archiving + vollständiger Dump; Point-in-Time-Wiederherstellung | +| MongoDB | Replica-Set-Snapshots; Oplog für PITR | +| SQLite (Single-Node / Desktop) | WAL-Modus + Hot-Snapshots über `VACUUM INTO` oder die Online Backup API; optional Litestream für kontinuierliche Replikation — siehe [SQLite-Deployments](#sqlite-deployments) unten | + +Validieren Sie unabhängig vom Treiber, dass: + +- Backups innerhalb des RPO des Kunden abgeschlossen werden; +- eine frische Datenbank ObjectOS aus demselben Artefakt starten und + Traffic bedienen kann; +- Wiederherstellungstests mindestens einmal pro Quartal durchgängig + durchgeführt werden. + +## SQLite-Deployments + +SQLite ist der Standardtreiber und eine legitime Produktionswahl für +**Single-Node**-ObjectOS — Desktop-Apps, interne Tools für ein kleines +Team, Edge-/On-Prem-Appliances, Evaluierungsumgebungen. Der Kompromiss +ist struktureller Natur: SQLite ist ein Single-Writer und eignet sich +daher nicht für Multi-Node-ObjectOS, hohen gleichzeitigen Schreibdurchsatz +oder Deployments mit gemeinsam genutzter Datenbank. Verwenden Sie dafür +PostgreSQL. + +Wenn Sie SQLite in der Produktion betreiben, gehören die Konfiguration, +die es sicher macht, und das Backup-Rezept zusammen: + +**Laufzeitkonfiguration** + +- WAL aktivieren: `PRAGMA journal_mode=WAL` (Leser blockieren den + Schreiber nicht; absturzsicher). +- `PRAGMA synchronous=NORMAL` ist der übliche Desktop-/Single-Node-Standard + — sicher mit WAL, deutlich schneller als `FULL`. +- Halten Sie die Datenbankdatei auf **lokalem Datenträger**. Legen Sie sie + **nicht** auf NFS, SMB oder in einen von Dropbox / OneDrive / iCloud + synchronisierten Ordner, während die Laufzeitumgebung läuft — die + Sperrmechanismen von SQLite sind dort unzuverlässig, und dies ist die + häufigste Ursache für die Beschädigung von SQLite-Deployments. + +**Hot-Snapshot (ohne Ausfallzeit)** + +Die Laufzeitumgebung bedient weiterhin Traffic, während Sie mit der +Online Backup API von SQLite oder `VACUUM INTO` einen Snapshot erstellen: + +```sql +VACUUM INTO '/var/backups/objectos/db-2026-05-27T13-00Z.sqlite'; +``` + +Planen Sie ihn (cron, systemd-Timer oder der In-Process-Scheduler) in +einem Intervall, das Ihrem RPO entspricht. Versehen Sie jeden Snapshot mit +der Artefaktversion, die ihn erzeugt hat, damit Sie Datenbank + Artefakt +gemeinsam zurückrollen können (siehe [Artefakt-Versionierung](#artifact-versioning) +unten). + +**Externe Kopie** + +Ein lokaler Snapshot übersteht keinen Datenträgerverlust. Übertragen Sie +jeden Snapshot in dauerhaften Speicher: + +- Server / VM: in S3 oder einen beliebigen S3-kompatiblen Bucket übertragen + (Sie haben wahrscheinlich bereits einen für die `storage`-Capability + konfiguriert). +- Desktop-App: den Snapshot in einen vom Benutzer kontrollierten + Sync-Ordner schreiben (OneDrive / iCloud / Google Drive) — hier + akzeptabel, weil die Snapshot-Datei **geschlossen und unveränderlich** + ist, anders als die Live-Datenbank. + +**Kontinuierliche Replikation (niedrigeres RPO)** + +Für ein RPO im Sekundenbereich, ohne SQLite aufzugeben, betreiben Sie +[Litestream](https://litestream.io) neben dem ObjectOS-Prozess. Es streamt +das WAL in S3-kompatiblen Speicher und unterstützt +Point-in-Time-Wiederherstellung. Dies ist der empfohlene Weg, wenn ein +Single-Node-SQLite-Deployment einen nahezu verlustfreien Betrieb benötigt. + +**Wiederherstellung** + +Stoppen Sie die Laufzeitumgebung, ersetzen Sie die Datenbankdatei durch +den gewählten Snapshot (oder führen Sie `litestream restore` aus) und +starten Sie die Laufzeitumgebung gegen dieselbe Artefaktversion, die den +Snapshot erzeugt hat. + +## Artefakt-Versionierung + +Behandeln Sie veröffentlichte Artefakte als unveränderlich. Versehen Sie +jedes Artefakt mit der Release-ID, die zum Kompilieren verwendet wurde +(z. B. `objectstack-2026-05-24.json`). Eine Wiederherstellung in einen +bekannten guten Geschäftszustand bedeutet in der Regel: + +1. Stellen Sie die Datenbank auf den gewählten Zeitpunkt wieder her. +2. Verweisen Sie ObjectOS erneut auf die Artefaktversion, die zu diesem + Zeitpunkt aktiv war. +3. Starten Sie die Laufzeitumgebung neu. + +Wenn Sie Artefakte direkt überschreiben, verlieren Sie die Möglichkeit, +sauber zurückzurollen — selbst wenn das Datenbank-Backup einwandfrei ist. + +## RPO-/RTO-Planung + +Ein praktikables Ausgangsziel für Kunden-Deployments: + +| Klasse | RPO | RTO | Hinweise | +|---|---|---|---| +| Evaluierung / Demo | nach bestem Bemühen | nach bestem Bemühen | SQLite-Snapshot ist ausreichend | +| Desktop-App / Single-Node für kleines Team | ≤ 1 Stunde (Snapshots) oder ≤ Sekunden (Litestream) | Minuten | SQLite + WAL + geplantes `VACUUM INTO` + externe Kopie | +| Single-Tenant-Produktion | ≤ 15 Min | ≤ 1 Stunde | Managed PostgreSQL mit PITR + Warm-Image | +| Multi-Tenant / reguliert | ≤ 5 Min | ≤ 30 Min | HA-Datenbank + Multi-AZ-ObjectOS + getestetes Runbook | + +Engere Ziele erfordern Plattformänderungen außerhalb des +ObjectOS-Containers selbst (HA-Datenbank, Multi-AZ-Ingress, +Warm-Replicas). + +## Ausfallszenarien, die das Üben wert sind + +- **Datenbank über einen langen Zeitraum nicht verfügbar.** Stellen Sie + sicher, dass die Laufzeitumgebung einen klaren 503 ausgibt und dass + Probes Pods korrekt als ungesund markieren. +- **Artefakt-Regression.** Rollen Sie den Artefakt-Zeiger zurück; die + Daten sind nicht betroffen. +- **Secret-Rotation.** Die Rotation von `AUTH_SECRET` macht jede Session + ungültig. Führen Sie sie während eines Wartungsfensters durch oder + staffeln Sie sie über die Replicas. +- **Regionsausfall.** Wenn der Kunde ein regionsübergreifendes Failover + benötigt, müssen die Geschäftsdatenbank, der Secret-Manager und der + Ingress alle regionsübergreifend ausgelegt sein. ObjectOS selbst kann + überall dort laufen, wo das Image verfügbar ist. + +## Was im Runbook festgehalten werden sollte + +- Backup-Zeitplan, Aufbewahrung und On-Call-Kontakt für jeden Datensatz. +- Schritt-für-Schritt-Wiederherstellungsprozedur (zuerst Datenbank, dann + Artefakt, dann ObjectOS starten). +- Verifizierungsabfragen, um zu bestätigen, dass die wiederhergestellte + Datenbank konsistent ist. +- Rollback-Plan für ObjectOS-Image und Artefaktversion (siehe + [Upgrade und Rollback](/docs/operate/upgrade)). +- Kommunikationsvorlage für kundensichtbare Vorfälle. diff --git a/content/docs/operate/backup.es.mdx b/content/docs/operate/backup.es.mdx new file mode 100644 index 0000000..511b9e5 --- /dev/null +++ b/content/docs/operate/backup.es.mdx @@ -0,0 +1,167 @@ +--- +title: Copias de seguridad y recuperación ante desastres +description: Qué respaldar, cómo restaurar y cómo planificar ante fallos. +--- + +# Copias de seguridad y recuperación ante desastres + +ObjectOS en sí mismo es stateless: el runtime puede reconstruirse a partir +de la imagen del contenedor. **Las copias de seguridad tratan sobre los +datos de los que ObjectOS depende, no sobre ObjectOS en sí.** Planifica la +recuperación en torno a esos conjuntos de datos. + +## Qué respaldar + +| Activo | Propiedad de | Estrategia de copia de seguridad | +|---|---|---| +| Base de datos de negocio | Cliente | Copia de seguridad nativa de la base de datos (PITR para servicios gestionados); prueba la restauración trimestralmente | +| Artefacto compilado (`objectstack.json`) | Equipo de aplicación/release | Almacena cada artefacto publicado en almacenamiento inmutable; nunca lo sobrescribas | +| Línea base de secretos | Gestor de secretos del cliente | Copia de seguridad nativa del proveedor; cadencia de rotación según la política | +| Almacenamiento de objetos/archivos (cuando la capacidad `storage` está habilitada) | Cliente | Versionado de buckets + replicación entre regiones si es necesario | +| Proveedor de identidad gestionado por el cliente | Proveedor del IdP | Nativo del proveedor | + +ObjectOS **no** requiere una copia de seguridad separada del sistema de +archivos de su contenedor. Los directorios de caché (`OS_CACHE_DIR`) se +pueden reconstruir. + +## Copias de seguridad de la base de datos + +Adapta la estrategia al driver: + +| Driver | Enfoque recomendado | +|---|---| +| PostgreSQL | Archivado continuo de WAL + base backup; restauración point-in-time | +| MySQL | Archivado de binary-log + volcado completo; restauración point-in-time | +| MongoDB | Snapshots del replica-set; oplog para PITR | +| SQLite (nodo único / escritorio) | Modo WAL + snapshots en caliente mediante `VACUUM INTO` o la Online Backup API; opcionalmente Litestream para replicación continua — consulta [Despliegues de SQLite](#sqlite-deployments) más abajo | + +Sea cual sea el driver, valida que: + +- las copias de seguridad se completen dentro del RPO del cliente; +- una base de datos nueva pueda arrancar ObjectOS desde el mismo artefacto + y atender tráfico; +- las pruebas de restauración se ejerciten de extremo a extremo al menos + una vez por trimestre. + +## Despliegues de SQLite + +SQLite es el driver por defecto y es una elección de producción legítima +para ObjectOS de **nodo único**: aplicaciones de escritorio, herramientas +internas para un equipo pequeño, dispositivos edge / on-prem, entornos de +evaluación. La contrapartida es estructural: SQLite es de un único escritor, +por lo que no encaja con ObjectOS multinodo, alto rendimiento de escritura +concurrente ni despliegues de base de datos compartida. Para esos casos, +usa PostgreSQL. + +Cuando ejecutes SQLite en producción, la configuración que lo hace seguro y +la receta de copia de seguridad van de la mano: + +**Configuración del runtime** + +- Habilita WAL: `PRAGMA journal_mode=WAL` (los lectores no bloquean al + escritor; resistente a fallos). +- `PRAGMA synchronous=NORMAL` es el valor por defecto habitual en + escritorio/nodo único: seguro con WAL, mucho más rápido que `FULL`. +- Mantén el archivo de la base de datos en **disco local**. **No** lo + pongas en NFS, SMB ni dentro de una carpeta sincronizada por Dropbox / + OneDrive / iCloud mientras el runtime está en ejecución: el bloqueo de + SQLite es poco fiable en esos casos y esta es la forma más común en que + los despliegues de SQLite se corrompen. + +**Snapshot en caliente (sin tiempo de inactividad)** + +El runtime sigue atendiendo tráfico mientras tomas un snapshot usando la +Online Backup API de SQLite o `VACUUM INTO`: + +```sql +VACUUM INTO '/var/backups/objectos/db-2026-05-27T13-00Z.sqlite'; +``` + +Prográmalo (cron, systemd timer o el planificador in-process) a una +cadencia acorde con tu RPO. Etiqueta cada snapshot con la versión del +artefacto que lo produjo para poder revertir la base de datos + el +artefacto juntos (consulta [Versionado de artefactos](#artifact-versioning) +más abajo). + +**Copia externa** + +Un snapshot local no sobrevive a la pérdida del disco. Envía cada snapshot +a almacenamiento duradero: + +- Servidor / VM: envíalo a S3 o a cualquier bucket compatible con S3 + (probablemente ya tengas uno configurado para la capacidad `storage`). +- Aplicación de escritorio: escribe el snapshot en una carpeta de + sincronización controlada por el usuario (OneDrive / iCloud / Google + Drive) — aceptable aquí porque el archivo de snapshot está **cerrado e + inmutable**, a diferencia de la base de datos en vivo. + +**Replicación continua (RPO más bajo)** + +Para un RPO inferior al minuto sin renunciar a SQLite, ejecuta +[Litestream](https://litestream.io) junto al proceso de ObjectOS. Transmite +el WAL a almacenamiento compatible con S3 y admite restauración +point-in-time. Esta es la vía recomendada cuando un despliegue de SQLite de +nodo único necesita una pérdida de datos casi nula. + +**Restauración** + +Detén el runtime, reemplaza el archivo de la base de datos por el snapshot +elegido (o ejecuta `litestream restore`), e inicia el runtime contra la +misma versión de artefacto que produjo el snapshot. + +## Versionado de artefactos + +Trata los artefactos publicados como inmutables. Etiqueta cada artefacto +con el id de release usado para compilarlo (p. ej. +`objectstack-2026-05-24.json`). Recuperar un estado de negocio conocido y +correcto suele implicar: + +1. Restaurar la base de datos al punto en el tiempo elegido. +2. Reapuntar ObjectOS al artefacto que estaba en vivo en ese momento. +3. Reiniciar el runtime. + +Si sobrescribes los artefactos en su sitio, pierdes la capacidad de revertir +limpiamente incluso cuando la copia de seguridad de la base de datos es +perfecta. + +## Planificación de RPO/RTO + +Un objetivo de partida viable para los despliegues de clientes: + +| Clase | RPO | RTO | Notas | +|---|---|---|---| +| Evaluación / demo | mejor esfuerzo | mejor esfuerzo | Un snapshot de SQLite es suficiente | +| Aplicación de escritorio / nodo único de equipo pequeño | ≤ 1 hora (snapshots) o ≤ segundos (Litestream) | minutos | SQLite + WAL + `VACUUM INTO` programado + copia externa | +| Producción de un solo inquilino | ≤ 15 min | ≤ 1 hora | PostgreSQL gestionado con PITR + imagen en caliente | +| Multiinquilino / regulado | ≤ 5 min | ≤ 30 min | Base de datos HA + ObjectOS multi-AZ + runbook probado | + +Objetivos más estrictos requieren cambios de plataforma que están fuera del +propio contenedor de ObjectOS (base de datos HA, ingress multi-AZ, réplicas +en caliente). + +## Modos de fallo que vale la pena ensayar + +- **Base de datos no disponible durante una ventana prolongada.** Confirma + que el runtime expone un 503 claro y que las probes marcan correctamente + los pods como no saludables. +- **Regresión del artefacto.** Revierte el puntero del artefacto; los datos + no se ven afectados. +- **Rotación de secretos.** Rotar `AUTH_SECRET` invalida todas las + sesiones. Hazlo durante una ventana de mantenimiento o escalónalo entre + réplicas. +- **Caída de región.** Si el cliente requiere failover de región, la base + de datos de negocio, el gestor de secretos y el ingress deben ser todos + multirregión. ObjectOS en sí puede ejecutarse en cualquier lugar donde la + imagen esté disponible. + +## Qué documentar en el runbook + +- Calendario de copias de seguridad, retención y contacto de guardia para + cada conjunto de datos. +- Procedimiento de restauración paso a paso (primero la base de datos, + luego el artefacto, luego iniciar ObjectOS). +- Consultas de verificación para confirmar que la base de datos restaurada + es consistente. +- Plan de reversión tanto para la imagen de ObjectOS como para la versión + del artefacto (consulta [Actualización y reversión](/docs/operate/upgrade)). +- Plantilla de comunicación para incidentes visibles al cliente. diff --git a/content/docs/operate/backup.fr.mdx b/content/docs/operate/backup.fr.mdx new file mode 100644 index 0000000..d912318 --- /dev/null +++ b/content/docs/operate/backup.fr.mdx @@ -0,0 +1,170 @@ +--- +title: Sauvegarde et reprise après sinistre +description: Quoi sauvegarder, comment restaurer et comment planifier les pannes. +--- + +# Sauvegarde et reprise après sinistre + +ObjectOS est lui-même sans état — le runtime peut être reconstruit à +partir de l'image de conteneur. **Les sauvegardes concernent les données +dont dépend ObjectOS, et non ObjectOS lui-même.** Planifiez la reprise +autour de ces jeux de données. + +## Quoi sauvegarder + +| Actif | Détenu par | Stratégie de sauvegarde | +|---|---|---| +| Base de données métier | Client | Sauvegarde native de la base de données (PITR pour les services managés) ; tester la restauration chaque trimestre | +| Artefact compilé (`objectstack.json`) | Équipe applicative / de release | Stocker chaque artefact publié dans un stockage immuable ; ne jamais écraser | +| Référentiel des secrets | Gestionnaire de secrets du client | Sauvegarde native du fournisseur ; rotation selon la politique en vigueur | +| Stockage d'objets / de fichiers (lorsque la capacité `storage` est activée) | Client | Versionnage des buckets + réplication inter-régions si nécessaire | +| Fournisseur d'identité géré par le client | Fournisseur IdP | Native au fournisseur | + +ObjectOS **ne nécessite pas** de sauvegarde distincte de son système de +fichiers de conteneur. Les répertoires de cache (`OS_CACHE_DIR`) sont +reconstructibles. + +## Sauvegardes de base de données + +Adaptez la stratégie au driver : + +| Driver | Approche recommandée | +|---|---| +| PostgreSQL | Archivage continu du WAL + sauvegarde de base ; restauration à un instant précis | +| MySQL | Archivage du journal binaire + dump complet ; restauration à un instant précis | +| MongoDB | Snapshots du replica set ; oplog pour le PITR | +| SQLite (mononœud / poste de travail) | Mode WAL + snapshots à chaud via `VACUUM INTO` ou l'Online Backup API ; éventuellement Litestream pour une réplication continue — voir [Déploiements SQLite](#sqlite-deployments) ci-dessous | + +Quel que soit le driver, vérifiez que : + +- les sauvegardes s'achèvent dans le RPO du client ; +- une base de données neuve peut démarrer ObjectOS à partir du même + artefact et traiter le trafic ; +- les tests de restauration sont exécutés de bout en bout au moins une + fois par trimestre. + +## Déploiements SQLite + +SQLite est le driver par défaut et constitue un choix de production +légitime pour un ObjectOS **mononœud** — applications de bureau, outils +internes pour une petite équipe, appliances edge / on-prem, +environnements d'évaluation. Le compromis est structurel : SQLite +n'autorise qu'un seul rédacteur, il ne convient donc pas à un ObjectOS +multinœud, à un débit d'écriture concurrent élevé ou aux déploiements à +base de données partagée. Pour ces cas, utilisez PostgreSQL. + +Lorsque vous exécutez SQLite en production, la configuration qui le rend +sûr et la recette de sauvegarde vont de pair : + +**Configuration du runtime** + +- Activez le WAL : `PRAGMA journal_mode=WAL` (les lecteurs ne bloquent + pas le rédacteur ; résistant aux pannes). +- `PRAGMA synchronous=NORMAL` est la valeur par défaut habituelle pour + les postes de travail / mononœuds — sûre avec le WAL, bien plus rapide + que `FULL`. +- Conservez le fichier de base de données sur un **disque local**. Ne le + placez **pas** sur NFS, SMB, ni dans un dossier synchronisé par + Dropbox / OneDrive / iCloud pendant que le runtime est en cours + d'exécution — le verrouillage de SQLite n'est pas fiable dans ces cas, + et c'est la cause la plus fréquente de corruption des déploiements + SQLite. + +**Snapshot à chaud (sans interruption)** + +Le runtime continue de traiter le trafic pendant que vous prenez un +snapshot à l'aide de l'Online Backup API de SQLite ou de `VACUUM INTO` : + +```sql +VACUUM INTO '/var/backups/objectos/db-2026-05-27T13-00Z.sqlite'; +``` + +Planifiez-le (cron, timer systemd ou le planificateur in-process) à une +cadence correspondant à votre RPO. Étiquetez chaque snapshot avec la +version d'artefact qui l'a produit, afin de pouvoir restaurer ensemble +la base de données et l'artefact (voir [Versionnage des +artefacts](#artifact-versioning) ci-dessous). + +**Copie hors site** + +Un snapshot local ne survit pas à la perte du disque. Poussez chaque +snapshot vers un stockage durable : + +- Serveur / VM : poussez vers S3 ou tout bucket compatible S3 (vous en + avez probablement déjà un configuré pour la capacité `storage`). +- Application de bureau : écrivez le snapshot dans un dossier de + synchronisation contrôlé par l'utilisateur (OneDrive / iCloud / Google + Drive) — acceptable ici car le fichier de snapshot est **fermé et + immuable**, contrairement à la base de données active. + +**Réplication continue (RPO réduit)** + +Pour un RPO inférieur à la minute sans renoncer à SQLite, exécutez +[Litestream](https://litestream.io) aux côtés du processus ObjectOS. Il +diffuse le WAL vers un stockage compatible S3 et prend en charge la +restauration à un instant précis. C'est la voie recommandée lorsqu'un +déploiement SQLite mononœud exige une perte de données quasi nulle. + +**Restauration** + +Arrêtez le runtime, remplacez le fichier de base de données par le +snapshot choisi (ou exécutez `litestream restore`), démarrez le runtime +avec la même version d'artefact que celle ayant produit le snapshot. + +## Versionnage des artefacts + +Considérez les artefacts publiés comme immuables. Étiquetez chaque +artefact avec l'identifiant de release utilisé pour le compiler (par +exemple `objectstack-2026-05-24.json`). La reprise vers un état métier +sain implique généralement de : + +1. Restaurer la base de données à l'instant choisi. +2. Re-pointer ObjectOS vers la version d'artefact qui était active à ce + moment-là. +3. Redémarrer le runtime. + +Si vous écrasez les artefacts sur place, vous perdez la possibilité de +revenir en arrière proprement, même lorsque la sauvegarde de la base de +données est parfaite. + +## Planification RPO/RTO + +Un objectif de départ réaliste pour les déploiements clients : + +| Classe | RPO | RTO | Notes | +|---|---|---|---| +| Évaluation / démo | au mieux | au mieux | Un snapshot SQLite suffit | +| Application de bureau / mononœud petite équipe | ≤ 1 heure (snapshots) ou ≤ quelques secondes (Litestream) | minutes | SQLite + WAL + `VACUUM INTO` planifié + copie hors site | +| Production mono-locataire | ≤ 15 min | ≤ 1 heure | PostgreSQL managé avec PITR + image préchauffée | +| Multi-locataire / réglementé | ≤ 5 min | ≤ 30 min | Base de données HA + ObjectOS multi-AZ + runbook testé | + +Des objectifs plus stricts nécessitent des changements de plateforme +extérieurs au conteneur ObjectOS lui-même (base de données HA, ingress +multi-AZ, réplicas préchauffés). + +## Modes de défaillance à répéter + +- **Base de données indisponible sur une longue période.** Confirmez que + le runtime renvoie un 503 clair et que les sondes marquent + correctement les pods comme défaillants. +- **Régression d'artefact.** Revenez au pointeur d'artefact précédent ; + les données ne sont pas affectées. +- **Rotation de secret.** La rotation de `AUTH_SECRET` invalide toutes + les sessions. Effectuez-la pendant une fenêtre de maintenance ou + échelonnez-la entre les réplicas. +- **Panne de région.** Si le client exige un basculement de région, la + base de données métier, le gestionnaire de secrets et l'ingress + doivent tous être inter-régions. ObjectOS lui-même peut s'exécuter + partout où l'image est disponible. + +## Que consigner dans le runbook + +- Calendrier de sauvegarde, rétention et contact d'astreinte pour chaque + jeu de données. +- Procédure de restauration étape par étape (base de données d'abord, + puis artefact, puis démarrage d'ObjectOS). +- Requêtes de vérification pour confirmer que la base de données + restaurée est cohérente. +- Plan de rollback à la fois pour l'image ObjectOS et la version + d'artefact (voir [Mise à niveau et rollback](/docs/operate/upgrade)). +- Modèle de communication pour les incidents visibles par les clients. diff --git a/content/docs/operate/backup.ja.mdx b/content/docs/operate/backup.ja.mdx new file mode 100644 index 0000000..7d2e5d3 --- /dev/null +++ b/content/docs/operate/backup.ja.mdx @@ -0,0 +1,156 @@ +--- +title: バックアップと災害復旧 +description: 何をバックアップし、どう復元し、障害にどう備えるか。 +--- + +# バックアップと災害復旧 + +ObjectOS 自体はステートレスであり、ランタイムはコンテナイメージから +再構築できます。**バックアップの対象は ObjectOS が依存するデータであり、 +ObjectOS 自体ではありません。** 復旧計画はそれらのデータセットを中心に +立てましょう。 + +## 何をバックアップするか + +| アセット | 所有者 | バックアップ戦略 | +|---|---|---| +| 業務データベース | 顧客 | データベースネイティブのバックアップ(マネージドサービスでは PITR)。四半期ごとに復元をテストする | +| コンパイル成果物(`objectstack.json`) | アプリケーション/リリースチーム | 公開した成果物はすべてイミュータブルストレージに保存し、決して上書きしない | +| シークレットのベースライン | 顧客のシークレットマネージャー | ベンダーネイティブのバックアップ。ポリシーに従ってローテーション頻度を設定する | +| オブジェクト/ファイルストレージ(`storage` 機能が有効な場合) | 顧客 | バケットのバージョニング + 必要に応じてクロスリージョンレプリケーション | +| 顧客管理の ID プロバイダー | IdP ベンダー | ベンダーネイティブ | + +ObjectOS はコンテナファイルシステムの個別バックアップを**必要としません**。 +キャッシュディレクトリ(`OS_CACHE_DIR`)は再構築可能です。 + +## データベースのバックアップ + +戦略はドライバーに合わせます。 + +| ドライバー | 推奨アプローチ | +|---|---| +| PostgreSQL | 継続的な WAL アーカイブ + ベースバックアップ。ポイントインタイムリストア | +| MySQL | バイナリログのアーカイブ + フルダンプ。ポイントインタイムリストア | +| MongoDB | レプリカセットのスナップショット。PITR 用に oplog | +| SQLite(単一ノード / デスクトップ) | WAL モード + `VACUUM INTO` または Online Backup API によるホットスナップショット。必要に応じて継続的レプリケーションには Litestream を使用 — 後述の [SQLite デプロイ](#sqlite-deployments) を参照 | + +どのドライバーであっても、次の点を検証してください。 + +- バックアップが顧客の RPO 内に完了すること。 +- 新しいデータベースが同じ成果物から ObjectOS を起動し、 + トラフィックを処理できること。 +- 復元テストが少なくとも四半期に一度はエンドツーエンドで実施されること。 + +## SQLite デプロイ + +SQLite はデフォルトのドライバーであり、**単一ノード**の ObjectOS にとって +正当な本番選択肢です — デスクトップアプリ、小規模チーム向けの社内ツール、 +エッジ / オンプレミスのアプライアンス、評価環境などです。トレードオフは +構造的なもので、SQLite は単一ライターであるため、マルチノードの ObjectOS、 +高い同時書き込みスループット、共有データベースのデプロイには適しません。 +そうしたケースでは PostgreSQL を使用してください。 + +本番で SQLite を実行する場合、安全性を確保する構成とバックアップの +レシピは一体です。 + +**ランタイム構成** + +- WAL を有効にする: `PRAGMA journal_mode=WAL`(リーダーがライターを + ブロックせず、クラッシュセーフ)。 +- `PRAGMA synchronous=NORMAL` は通常のデスクトップ/単一ノードの + デフォルトです — WAL と組み合わせれば安全で、`FULL` よりはるかに高速です。 +- データベースファイルは**ローカルディスク**に置いてください。ランタイムの + 実行中に、NFS、SMB、または Dropbox / OneDrive / iCloud で同期される + フォルダの内部には置か**ないでください** — SQLite のロックはそれらでは + 信頼できず、これが SQLite デプロイで最もよく見られる破損の原因です。 + +**ホットスナップショット(ダウンタイムなし)** + +ランタイムはトラフィックを処理し続けながら、SQLite の Online Backup API +または `VACUUM INTO` を使ってスナップショットを取得します。 + +```sql +VACUUM INTO '/var/backups/objectos/db-2026-05-27T13-00Z.sqlite'; +``` + +RPO に合わせた頻度でスケジュールします(cron、systemd タイマー、または +プロセス内スケジューラ)。各スナップショットには、それを生成した成果物 +バージョンのタグを付け、データベースと成果物をまとめてロールバックできる +ようにします(後述の [成果物のバージョニング](#artifact-versioning) を参照)。 + +**オフサイトコピー** + +ローカルスナップショットはディスク喪失に耐えられません。各スナップショットを +耐久性のあるストレージにプッシュしてください。 + +- サーバー / VM: S3 または任意の S3 互換バケットにプッシュ(おそらく + `storage` 機能用にすでに 1 つ構成済みでしょう)。 +- デスクトップアプリ: スナップショットをユーザーが管理する同期フォルダ + (OneDrive / iCloud / Google Drive)に書き込みます — スナップショット + ファイルは**クローズされたイミュータブル**なもので、稼働中のデータベースとは + 異なるため、ここでは許容されます。 + +**継続的レプリケーション(より低い RPO)** + +SQLite を手放さずにサブ分の RPO を実現するには、ObjectOS プロセスと並行して +[Litestream](https://litestream.io) を実行します。WAL を S3 互換ストレージに +ストリーミングし、ポイントインタイムリストアをサポートします。単一ノードの +SQLite デプロイでほぼゼロのデータ損失が必要な場合の推奨パスです。 + +**復元** + +ランタイムを停止し、データベースファイルを選択したスナップショットで +置き換え(または `litestream restore` を実行)、そのスナップショットを +生成したのと同じ成果物バージョンに対してランタイムを起動します。 + +## 成果物のバージョニング + +公開した成果物はイミュータブルとして扱います。各成果物には、それを +コンパイルするために使用したリリース ID のタグを付けます +(例: `objectstack-2026-05-24.json`)。既知の正常な業務状態への復旧は、 +通常次のことを意味します。 + +1. データベースを選択した時点まで復元する。 +2. その時点で稼働していた成果物バージョンに ObjectOS を再び向ける。 +3. ランタイムを再起動する。 + +成果物をその場で上書きすると、データベースのバックアップが完璧であっても、 +きれいにロールバックする能力を失います。 + +## RPO/RTO の計画 + +顧客デプロイで実現可能な出発点としての目標値: + +| クラス | RPO | RTO | 備考 | +|---|---|---|---| +| 評価 / デモ | ベストエフォート | ベストエフォート | SQLite スナップショットで十分 | +| デスクトップアプリ / 小規模チームの単一ノード | ≤ 1 時間(スナップショット)または ≤ 数秒(Litestream) | 数分 | SQLite + WAL + スケジュールされた `VACUUM INTO` + オフサイトコピー | +| シングルテナント本番 | ≤ 15 分 | ≤ 1 時間 | PITR を備えたマネージド PostgreSQL + ウォームイメージ | +| マルチテナント / 規制対象 | ≤ 5 分 | ≤ 30 分 | HA データベース + マルチ AZ の ObjectOS + テスト済みランブック | + +より厳しい目標値には、ObjectOS コンテナ自体の外側にあるプラットフォーム +変更(HA データベース、マルチ AZ イングレス、ウォームレプリカ)が必要です。 + +## リハーサルする価値のある障害モード + +- **データベースが長時間利用不能。** ランタイムが明確な 503 を返し、 + プローブが Pod を正しく不健全とマークすることを確認します。 +- **成果物のリグレッション。** 成果物ポインタをロールバックします。 + データは影響を受けません。 +- **シークレットのローテーション。** `AUTH_SECRET` をローテーションすると、 + すべてのセッションが無効になります。メンテナンスウィンドウ中に実行するか、 + レプリカ間でずらして行います。 +- **リージョン障害。** 顧客がリージョンフェイルオーバーを必要とする場合、 + 業務データベース、シークレットマネージャー、イングレスのすべてが + クロスリージョンである必要があります。ObjectOS 自体はイメージが利用可能な + 場所であればどこでも実行できます。 + +## ランブックに記載すべき内容 + +- 各データセットのバックアップスケジュール、保持期間、オンコール連絡先。 +- ステップバイステップの復元手順(最初にデータベース、次に成果物、 + 最後に ObjectOS の起動)。 +- 復元したデータベースの整合性を確認する検証クエリ。 +- ObjectOS イメージと成果物バージョンの両方のロールバック計画 + ([アップグレードとロールバック](/docs/operate/upgrade) を参照)。 +- 顧客に見える障害のためのコミュニケーションテンプレート。 diff --git a/content/docs/operate/backup.mdx b/content/docs/operate/backup.mdx index 55476f1..d9bff5b 100644 --- a/content/docs/operate/backup.mdx +++ b/content/docs/operate/backup.mdx @@ -29,7 +29,7 @@ Match the strategy to the driver: | Driver | Recommended approach | |---|---| | PostgreSQL | Continuous WAL archiving + base backup; point-in-time restore | -| Turso / libSQL | Use the platform's backup feature; export to SQLite locally for cold copy | +| MySQL | Binary-log archiving + full dump; point-in-time restore | | MongoDB | Replica-set snapshots; oplog for PITR | | SQLite (single-node / desktop) | WAL mode + hot snapshots via `VACUUM INTO` or the Online Backup API; optionally Litestream for continuous replication — see [SQLite deployments](#sqlite-deployments) below | @@ -137,7 +137,7 @@ replicas). surfaces a clear 503 and that probes correctly mark pods unhealthy. - **Artifact regression.** Roll back the artifact pointer; data is unaffected. -- **Secret rotation.** Rotating `OS_AUTH_SECRET` invalidates every +- **Secret rotation.** Rotating `AUTH_SECRET` invalidates every session. Run during a maintenance window or stagger across replicas. - **Region outage.** If the customer requires region failover, the business database, secret manager, and ingress all need to be diff --git a/content/docs/operate/backup.cn.mdx b/content/docs/operate/backup.zh-Hans.mdx similarity index 95% rename from content/docs/operate/backup.cn.mdx rename to content/docs/operate/backup.zh-Hans.mdx index 89ad4c6..6e60632 100644 --- a/content/docs/operate/backup.cn.mdx +++ b/content/docs/operate/backup.zh-Hans.mdx @@ -29,9 +29,9 @@ ObjectOS **不**需要对其容器文件系统做单独备份。缓存目录 | 驱动 | 推荐方式 | |---|---| | PostgreSQL | 持续 WAL 归档 + 基础备份;支持时间点恢复 | -| Turso / libSQL | 使用平台的备份功能;本地导出为 SQLite 作冷备 | +| MySQL | 二进制日志归档 + 完整转储;支持时间点恢复 | | MongoDB | 副本集快照;通过 oplog 实现 PITR | -| SQLite(单节点 / 桌面) | 启用 WAL 模式 + 用 `VACUUM INTO` 或 Online Backup API 做热快照;如需更低 RPO 可叠加 Litestream 持续复制 —— 见下方 [SQLite 部署](#sqlite-部署) | +| SQLite(单节点 / 桌面) | 启用 WAL 模式 + 用 `VACUUM INTO` 或 Online Backup API 做热快照;如需更低 RPO 可叠加 Litestream 持续复制 —— 见下方 [SQLite 部署](#sqlite-deployments) | 无论使用哪种驱动,都需验证: @@ -69,7 +69,7 @@ VACUUM INTO '/var/backups/objectos/db-2026-05-27T13-00Z.sqlite'; 按照你的 RPO 节奏用 cron、systemd timer 或运行时内置 scheduler 触发。 给每份快照打上当时所用的产物版本标签,以便将数据库和产物作为一组 -回滚(见下方 [产物版本化](#产物版本化))。 +回滚(见下方 [产物版本化](#artifact-versioning))。 **异地副本** @@ -123,8 +123,8 @@ restore`),用产生该快照时所对应的产物版本重新启动运行时 - **数据库长时间不可用。** 确认运行时返回明确的 503,并且探针正确 地把 Pod 标记为不健康。 - **产物回归。** 回滚产物指针;数据不受影响。 -- **Secret 轮换。** 轮换 `OS_AUTH_SECRET` 会使所有会话失效。请在 - 维护窗口执行,或在副本之间分批进行。 +- **Secret 轮换。** 轮换 `AUTH_SECRET` 会使所有会话失效。请在维护 + 窗口执行,或在副本之间分批进行。 - **区域故障。** 如果客户要求区域级故障切换,业务数据库、密钥 管理器和入口都需要跨区域。ObjectOS 本身可以运行在任何能拉到 镜像的地方。 diff --git a/content/docs/operate/meta.de.json b/content/docs/operate/meta.de.json new file mode 100644 index 0000000..b34df3d --- /dev/null +++ b/content/docs/operate/meta.de.json @@ -0,0 +1,11 @@ +{ + "title": "Betrieb", + "defaultOpen": false, + "pages": [ + "production", + "observability", + "backup", + "upgrade", + "troubleshooting" + ] +} diff --git a/content/docs/operate/meta.es.json b/content/docs/operate/meta.es.json new file mode 100644 index 0000000..d06fd7f --- /dev/null +++ b/content/docs/operate/meta.es.json @@ -0,0 +1,11 @@ +{ + "title": "Operar", + "defaultOpen": false, + "pages": [ + "production", + "observability", + "backup", + "upgrade", + "troubleshooting" + ] +} diff --git a/content/docs/operate/meta.fr.json b/content/docs/operate/meta.fr.json new file mode 100644 index 0000000..9fb6b1b --- /dev/null +++ b/content/docs/operate/meta.fr.json @@ -0,0 +1,11 @@ +{ + "title": "Exploitation", + "defaultOpen": false, + "pages": [ + "production", + "observability", + "backup", + "upgrade", + "troubleshooting" + ] +} diff --git a/content/docs/operate/meta.ja.json b/content/docs/operate/meta.ja.json new file mode 100644 index 0000000..aac8652 --- /dev/null +++ b/content/docs/operate/meta.ja.json @@ -0,0 +1,11 @@ +{ + "title": "運用", + "defaultOpen": false, + "pages": [ + "production", + "observability", + "backup", + "upgrade", + "troubleshooting" + ] +} diff --git a/content/docs/operate/meta.cn.json b/content/docs/operate/meta.zh-Hans.json similarity index 100% rename from content/docs/operate/meta.cn.json rename to content/docs/operate/meta.zh-Hans.json diff --git a/content/docs/operate/observability.de.mdx b/content/docs/operate/observability.de.mdx new file mode 100644 index 0000000..b40ba16 --- /dev/null +++ b/content/docs/operate/observability.de.mdx @@ -0,0 +1,117 @@ +--- +title: Observability +description: Logs, Request-IDs, Metriken, Fehler, Sitzungen und Audit-Logs. +--- + +# Observability + +Der Betrieb von ObjectOS benötigt sowohl Infrastruktursignale als auch +Anwendungssignale. Das Framework stellt Request-ID-, Metrik-, Error-Reporter- +und Audit-Primitive bereit; das Deployment entscheidet, wohin diese exportiert +werden. + +## Request-Identität + +Jedes Produktions-Deployment sollte eine Request-ID weiterleiten oder erzeugen: + +```text +X-Request-Id +``` + +Verwenden Sie sie, um Folgendes zu korrelieren: + +- Ingress-Logs; +- ObjectOS-Logs; +- langsame Datenbankabfragen; +- Fehlerberichte; +- Support-Tickets von Kunden. + +## Metriken und Fehler + +Die Runtime stellt austauschbare Schnittstellen für Metriken und Error-Reporter +bereit. Verbinden Sie diese mit dem vom Kunden gewählten System, etwa Prometheus, +OpenTelemetry, Datadog, Sentry oder einem anderen genehmigten Backend. + +Erfassen Sie mindestens: + +| Signal | Warum | +|---|---| +| Anzahl der Requests nach Route/Status | Fehlerspitzen erkennen | +| Request-Dauer | Latenzregressionen erkennen | +| 5xx-Fehler | Bei Runtime-Fehlern alarmieren | +| Authentifizierungsfehler | Konfigurations- oder Angriffsmuster erkennen | +| Artifact-/Kernel-Cache-Misses | Cold-Start-Verhalten verstehen | + +### Minimales Prometheus-Beispiel + +ObjectOS stellt einen Prometheus-kompatiblen Metrik-Endpunkt bereit, wenn der +Metrik-Dienst aktiviert ist: + +```yaml +# prometheus.yml +scrape_configs: + - job_name: objectos + metrics_path: /metrics + static_configs: + - targets: ['objectos:3000'] +``` + +Nützliche Start-Alerts: + +```yaml +groups: + - name: objectos + rules: + - alert: ObjectOS5xxSpike + expr: | + sum(rate(http_requests_total{status=~"5.."}[5m])) + / sum(rate(http_requests_total[5m])) > 0.02 + for: 5m + annotations: + summary: "ObjectOS 5xx rate above 2% for 5 minutes" + + - alert: ObjectOSAuthFailureSpike + expr: rate(auth_failures_total[5m]) > 5 + for: 10m + annotations: + summary: "Sustained auth failure rate — check for misconfiguration or attack" + + - alert: ObjectOSKernelColdStartHigh + expr: rate(kernel_cache_misses_total[15m]) > 1 + for: 15m + annotations: + summary: "Frequent project kernel cold starts — consider raising OS_KERNEL_CACHE_SIZE" +``` + +Für OpenTelemetry setzen Sie `OTEL_EXPORTER_OTLP_ENDPOINT`, und ObjectOS gibt +Traces und Metriken im OTLP-Format aus. Die Struktur der Spans entspricht dem +[Request-Ablauf](/docs/architecture#how-a-request-is-served). + +## Audit-Logs + +Wenn die Audit-Funktion aktiviert ist, schreibt ObjectOS Audit-Datensätze nach +`sys_audit_log`. + +Verwenden Sie Audit-Logs für: + +- berechtigungsrelevante Änderungen; +- Einstellungsänderungen; +- Untersuchungen von Benutzern/Sitzungen; +- Integrationsaktivität; +- Analyse verweigerter Zugriffe. + +Machen Sie in regulierten Umgebungen die Audit-Tabelle auf Datenbank- oder +Speicherebene append-only und definieren Sie eine Aufbewahrungsrichtlinie. + +## Console-Diagnose + +Die Console stellt operative Oberflächen bereit, etwa: + +- Sessions; +- Audit Logs; +- Notifications; +- Webhook Deliveries, wenn Webhooks aktiviert sind; +- Übersichts-Dashboards für System und Security. + +Diese sind für Operatoren und Support-Ingenieure gedacht, nicht nur für +Entwickler. diff --git a/content/docs/operate/observability.es.mdx b/content/docs/operate/observability.es.mdx new file mode 100644 index 0000000..84d5054 --- /dev/null +++ b/content/docs/operate/observability.es.mdx @@ -0,0 +1,117 @@ +--- +title: Observabilidad +description: Logs, identificadores de solicitud, métricas, errores, sesiones y registros de auditoría. +--- + +# Observabilidad + +Las operaciones de ObjectOS necesitan tanto señales de infraestructura como +señales de aplicación. El framework proporciona primitivas de request-id, +métricas, reportador de errores y auditoría; el despliegue decide dónde +exportarlas. + +## Identidad de la solicitud + +Cada despliegue de producción debería propagar o generar un identificador de solicitud: + +```text +X-Request-Id +``` + +Úsalo para correlacionar: + +- logs de ingress; +- logs de ObjectOS; +- consultas lentas de la base de datos; +- reportes de errores; +- tickets de soporte al cliente. + +## Métricas y errores + +El runtime expone interfaces conectables de métricas y reportador de errores. +Conéctalas al sistema elegido por el cliente, como Prometheus, OpenTelemetry, +Datadog, Sentry u otro backend aprobado. + +Registra al menos: + +| Señal | Por qué | +|---|---| +| Conteo de solicitudes por ruta/estado | Detectar picos de errores | +| Duración de la solicitud | Detectar regresiones de latencia | +| Errores 5xx | Alertar sobre fallos del runtime | +| Fallos de autenticación | Detectar patrones de configuración o de ataque | +| Fallos de caché de artefactos/kernel | Entender el comportamiento de arranque en frío | + +### Ejemplo mínimo con Prometheus + +ObjectOS expone un endpoint de métricas compatible con Prometheus cuando el +servicio de métricas está habilitado: + +```yaml +# prometheus.yml +scrape_configs: + - job_name: objectos + metrics_path: /metrics + static_configs: + - targets: ['objectos:3000'] +``` + +Alertas iniciales útiles: + +```yaml +groups: + - name: objectos + rules: + - alert: ObjectOS5xxSpike + expr: | + sum(rate(http_requests_total{status=~"5.."}[5m])) + / sum(rate(http_requests_total[5m])) > 0.02 + for: 5m + annotations: + summary: "ObjectOS 5xx rate above 2% for 5 minutes" + + - alert: ObjectOSAuthFailureSpike + expr: rate(auth_failures_total[5m]) > 5 + for: 10m + annotations: + summary: "Sustained auth failure rate — check for misconfiguration or attack" + + - alert: ObjectOSKernelColdStartHigh + expr: rate(kernel_cache_misses_total[15m]) > 1 + for: 15m + annotations: + summary: "Frequent project kernel cold starts — consider raising OS_KERNEL_CACHE_SIZE" +``` + +Para OpenTelemetry, establece `OTEL_EXPORTER_OTLP_ENDPOINT` y ObjectOS +emitirá trazas y métricas en formato OTLP. La forma de los spans coincide con el +[flujo de la solicitud](/docs/architecture#how-a-request-is-served). + +## Registros de auditoría + +Cuando la capacidad de auditoría está habilitada, ObjectOS escribe registros de +auditoría en `sys_audit_log`. + +Usa los registros de auditoría para: + +- cambios sensibles a permisos; +- cambios de configuración; +- investigación de usuarios/sesiones; +- actividad de integraciones; +- análisis de accesos denegados. + +Para entornos regulados, haz que la tabla de auditoría sea de solo anexado en la +capa de base de datos o almacenamiento y define una política de retención. + +## Diagnósticos de Console + +Console expone superficies operativas como: + +- Sesiones; +- Registros de auditoría; +- Notificaciones; +- Entregas de webhooks cuando los webhooks están habilitados; +- Paneles de resumen de sistema y seguridad. + +Están pensados para operadores e ingenieros de soporte, no solo para +desarrolladores. diff --git a/content/docs/operate/observability.fr.mdx b/content/docs/operate/observability.fr.mdx new file mode 100644 index 0000000..7678a69 --- /dev/null +++ b/content/docs/operate/observability.fr.mdx @@ -0,0 +1,119 @@ +--- +title: Observabilité +description: Journaux, identifiants de requête, métriques, erreurs, sessions et journaux d'audit. +--- + +# Observabilité + +Les opérations ObjectOS nécessitent à la fois des signaux d'infrastructure +et des signaux applicatifs. Le framework fournit les primitives d'identifiant +de requête, de métriques, de rapport d'erreurs et d'audit ; le déploiement +décide où les exporter. + +## Identité de la requête + +Chaque déploiement de production doit propager ou générer un identifiant de +requête : + +```text +X-Request-Id +``` + +Utilisez-le pour corréler : + +- les journaux d'entrée (ingress) ; +- les journaux ObjectOS ; +- les requêtes lentes de la base de données ; +- les rapports d'erreurs ; +- les tickets de support client. + +## Métriques et erreurs + +Le runtime expose des interfaces enfichables de métriques et de rapport +d'erreurs. Connectez-les au système choisi par le client, tel que Prometheus, +OpenTelemetry, Datadog, Sentry ou un autre backend approuvé. + +Suivez au minimum : + +| Signal | Pourquoi | +|---|---| +| Nombre de requêtes par route/statut | Détecter les pics d'erreurs | +| Durée des requêtes | Détecter les régressions de latence | +| Erreurs 5xx | Alerter sur les défaillances du runtime | +| Échecs d'authentification | Détecter les problèmes de configuration ou les schémas d'attaque | +| Échecs de cache d'artefact/kernel | Comprendre le comportement de démarrage à froid | + +### Exemple minimal Prometheus + +ObjectOS expose un point de terminaison de métriques compatible Prometheus +lorsque le service de métriques est activé : + +```yaml +# prometheus.yml +scrape_configs: + - job_name: objectos + metrics_path: /metrics + static_configs: + - targets: ['objectos:3000'] +``` + +Alertes de démarrage utiles : + +```yaml +groups: + - name: objectos + rules: + - alert: ObjectOS5xxSpike + expr: | + sum(rate(http_requests_total{status=~"5.."}[5m])) + / sum(rate(http_requests_total[5m])) > 0.02 + for: 5m + annotations: + summary: "ObjectOS 5xx rate above 2% for 5 minutes" + + - alert: ObjectOSAuthFailureSpike + expr: rate(auth_failures_total[5m]) > 5 + for: 10m + annotations: + summary: "Sustained auth failure rate — check for misconfiguration or attack" + + - alert: ObjectOSKernelColdStartHigh + expr: rate(kernel_cache_misses_total[15m]) > 1 + for: 15m + annotations: + summary: "Frequent project kernel cold starts — consider raising OS_KERNEL_CACHE_SIZE" +``` + +Pour OpenTelemetry, définissez `OTEL_EXPORTER_OTLP_ENDPOINT` et ObjectOS +émettra les traces et les métriques au format OTLP. La forme des spans +correspond au [flux de requête](/docs/architecture#how-a-request-is-served). + +## Journaux d'audit + +Lorsque la capacité d'audit est activée, ObjectOS écrit des enregistrements +d'audit dans `sys_audit_log`. + +Utilisez les journaux d'audit pour : + +- les modifications sensibles aux permissions ; +- les changements de paramètres ; +- les investigations sur les utilisateurs/sessions ; +- l'activité d'intégration ; +- l'analyse des accès refusés. + +Pour les environnements réglementés, rendez la table d'audit en mode +append-only au niveau de la base de données ou de la couche de stockage et +définissez une politique de rétention. + +## Diagnostics de la Console + +La Console expose des surfaces opérationnelles telles que : + +- Sessions ; +- Journaux d'audit ; +- Notifications ; +- Livraisons de webhooks lorsque les webhooks sont activés ; +- Tableaux de bord de vue d'ensemble Système et Sécurité. + +Ces surfaces sont destinées aux opérateurs et aux ingénieurs de support, et +pas uniquement aux développeurs. diff --git a/content/docs/operate/observability.ja.mdx b/content/docs/operate/observability.ja.mdx new file mode 100644 index 0000000..28edaff --- /dev/null +++ b/content/docs/operate/observability.ja.mdx @@ -0,0 +1,116 @@ +--- +title: オブザーバビリティ +description: ログ、リクエスト ID、メトリクス、エラー、セッション、監査ログ。 +--- + +# オブザーバビリティ + +ObjectOS の運用には、インフラストラクチャのシグナルとアプリケーションの +シグナルの両方が必要です。フレームワークは request-id、メトリクス、エラー +レポーター、監査のプリミティブを提供し、それらをどこにエクスポートするかは +デプロイメントが決定します。 + +## リクエストアイデンティティ + +すべての本番デプロイメントでは、リクエスト ID を伝播するか生成する必要が +あります: + +```text +X-Request-Id +``` + +これを使って以下を相関付けします: + +- イングレスのログ; +- ObjectOS のログ; +- データベースのスロークエリ; +- エラーレポート; +- カスタマーサポートのチケット。 + +## メトリクスとエラー + +ランタイムは、プラグイン可能なメトリクスとエラーレポーターのインターフェイスを +公開します。Prometheus、OpenTelemetry、Datadog、Sentry、その他の承認された +バックエンドなど、顧客が選択したシステムに接続してください。 + +少なくとも以下を追跡します: + +| シグナル | 理由 | +|---|---| +| ルート/ステータス別のリクエスト数 | エラーの急増を検出する | +| リクエスト時間 | レイテンシのリグレッションを検出する | +| 5xx エラー | ランタイム障害をアラートする | +| 認証失敗 | 設定ミスや攻撃パターンを検出する | +| アーティファクト/カーネルのキャッシュミス | コールドスタートの挙動を把握する | + +### 最小限の Prometheus の例 + +メトリクスサービスが有効な場合、ObjectOS は Prometheus 互換のメトリクス +エンドポイントを公開します: + +```yaml +# prometheus.yml +scrape_configs: + - job_name: objectos + metrics_path: /metrics + static_configs: + - targets: ['objectos:3000'] +``` + +便利なスターターアラート: + +```yaml +groups: + - name: objectos + rules: + - alert: ObjectOS5xxSpike + expr: | + sum(rate(http_requests_total{status=~"5.."}[5m])) + / sum(rate(http_requests_total[5m])) > 0.02 + for: 5m + annotations: + summary: "ObjectOS 5xx rate above 2% for 5 minutes" + + - alert: ObjectOSAuthFailureSpike + expr: rate(auth_failures_total[5m]) > 5 + for: 10m + annotations: + summary: "Sustained auth failure rate — check for misconfiguration or attack" + + - alert: ObjectOSKernelColdStartHigh + expr: rate(kernel_cache_misses_total[15m]) > 1 + for: 15m + annotations: + summary: "Frequent project kernel cold starts — consider raising OS_KERNEL_CACHE_SIZE" +``` + +OpenTelemetry の場合は `OTEL_EXPORTER_OTLP_ENDPOINT` を設定すると、ObjectOS は +OTLP 形式でトレースとメトリクスを送信します。スパンの形状は +[リクエストフロー](/docs/architecture#how-a-request-is-served) に対応します。 + +## 監査ログ + +監査機能が有効な場合、ObjectOS は監査レコードを `sys_audit_log` に書き込みます。 + +監査ログは以下の用途に使用します: + +- 権限に影響する変更; +- 設定の変更; +- ユーザー/セッションの調査; +- 統合のアクティビティ; +- アクセス拒否の分析。 + +規制環境では、監査テーブルをデータベースまたはストレージのレイヤーで +追記専用(append-only)にし、保持ポリシーを定義してください。 + +## Console の診断 + +Console は以下のような運用面のサーフェスを公開します: + +- セッション; +- 監査ログ; +- 通知; +- Webhook が有効な場合の Webhook 配信; +- システムおよびセキュリティの概要ダッシュボード。 + +これらは開発者だけでなく、オペレーターやサポートエンジニアを対象としています。 diff --git a/content/docs/operate/observability.cn.mdx b/content/docs/operate/observability.zh-Hans.mdx similarity index 100% rename from content/docs/operate/observability.cn.mdx rename to content/docs/operate/observability.zh-Hans.mdx diff --git a/content/docs/operate/production.de.mdx b/content/docs/operate/production.de.mdx new file mode 100644 index 0000000..1dc2204 --- /dev/null +++ b/content/docs/operate/production.de.mdx @@ -0,0 +1,82 @@ +--- +title: Produktionsreife +description: Checkliste für den sicheren Betrieb von ObjectOS in der Produktion. +--- + +# Produktionsreife + +Verwenden Sie diese Checkliste, bevor Sie ObjectOS dem Produktionsverkehr aussetzen. + +## HTTP-Härtung + +Die ObjectStack-Laufzeitumgebung stellt konservative Sicherheits-Header für +Dispatcher-Routen bereit. Produktionsbereitstellungen sollten Folgendes überprüfen: + +- `Content-Security-Policy`; +- `X-Content-Type-Options`; +- `X-Frame-Options`; +- `Referrer-Policy`; +- `Permissions-Policy`; +- `Cross-Origin-Resource-Policy`; +- HSTS, nachdem TLS bestätigt wurde. + +Wenn ein Reverse-Proxy die Header verwaltet, überprüfen Sie die endgültige Antwort mit: + +```bash +curl -I https://app.example.com +``` + +## Geheimnisse + +Speichern Sie diese in einem Secret Manager: + +| Geheimnis | Zweck | +|---|---| +| `OS_AUTH_SECRET` | Basis-Geheimnis zur Signierung von Sitzungen | +| `OS_CLOUD_API_KEY` | Zugriff auf die Artifact-API der Control-Plane | +| Datenbank-Anmeldedaten | Zugriff auf die Geschäftsdatenbank | +| OIDC-Client-Secret | Enterprise-SSO | +| Provider-API-Schlüssel | E-Mail, Speicher, KI, Integrationen | + +Betten Sie Geheimnisse niemals in Artefakte oder Images ein. + +## Rate Limiting + +Das Framework stellt einen Token-Bucket-Rate-Limiter bereit. Richten Sie das Rate +Limiting auf der Adapter-, Ingress- oder Gateway-Ebene ein, wo die Aufrufer-IP und +die authentifizierte Identität vertrauenswürdig sind. + +Empfohlene Buckets: + +| Verkehr | Beispiel-Limit | +|---|---:| +| Auth-Endpunkte | 10/Min/IP | +| Schreibanfragen | 60/Min/IP | +| Leseanfragen | 600/Min/IP | + +Verwenden Sie ein gemeinsames Backend wie Redis für Bereitstellungen mit mehreren Pods. + +## CORS + +Konfigurieren Sie explizite Ursprünge: + +```text +https://app.example.com +https://admin.example.com +``` + +Verwenden Sie keine Wildcard-Ursprünge bei Anfragen mit Anmeldedaten. + +## Go-Live-Checkliste + +- [ ] TLS wird am Edge oder Ingress terminiert. +- [ ] Sicherheits-Header sind vorhanden. +- [ ] HSTS ist nach der TLS-Validierung aktiviert. +- [ ] CORS-Ursprünge sind explizit. +- [ ] Rate-Limits schützen Auth- und Schreib-Endpunkte. +- [ ] `OS_AUTH_SECRET` ist stark und wird als Geheimnis gespeichert. +- [ ] OIDC-Callback-URLs stimmen mit der öffentlichen Domain überein. +- [ ] Backup und Wiederherstellung der Geschäftsdatenbank sind getestet. +- [ ] Audit-Logs werden gemäß der Kundenrichtlinie aufbewahrt. +- [ ] Negative Zugriffstests über Organisationsgrenzen hinweg bestehen. +- [ ] Der Rollback-Plan deckt sowohl das ObjectOS-Image als auch die Artefaktversion ab. diff --git a/content/docs/operate/production.es.mdx b/content/docs/operate/production.es.mdx new file mode 100644 index 0000000..1eda5c2 --- /dev/null +++ b/content/docs/operate/production.es.mdx @@ -0,0 +1,82 @@ +--- +title: Preparación para producción +description: Lista de verificación para ejecutar ObjectOS de forma segura en producción. +--- + +# Preparación para producción + +Usa esta lista de verificación antes de exponer ObjectOS al tráfico de producción. + +## Endurecimiento de HTTP + +El runtime de ObjectStack proporciona cabeceras de seguridad conservadoras para las +rutas del dispatcher. Los despliegues de producción deben verificar: + +- `Content-Security-Policy`; +- `X-Content-Type-Options`; +- `X-Frame-Options`; +- `Referrer-Policy`; +- `Permissions-Policy`; +- `Cross-Origin-Resource-Policy`; +- HSTS una vez confirmado el TLS. + +Si un proxy inverso gestiona las cabeceras, verifica la respuesta final con: + +```bash +curl -I https://app.example.com +``` + +## Secretos + +Almacena estos valores en un gestor de secretos: + +| Secreto | Propósito | +|---|---| +| `OS_AUTH_SECRET` | Secreto base para la firma de sesiones | +| `OS_CLOUD_API_KEY` | Acceso a la Artifact API del plano de control | +| Credenciales de base de datos | Acceso a la base de datos de negocio | +| Secreto de cliente OIDC | SSO empresarial | +| Claves de API de proveedores | Correo electrónico, almacenamiento, IA, integraciones | + +Nunca incrustes secretos en artefactos ni en imágenes. + +## Limitación de tasa + +El framework expone un limitador de tasa de tipo token-bucket. Configura la limitación +de tasa en la capa de adaptador, ingress o gateway, donde la IP del llamante y la +identidad autenticada sean fiables. + +Buckets recomendados: + +| Tráfico | Límite de ejemplo | +|---|---:| +| Endpoints de autenticación | 10/min/IP | +| Solicitudes de escritura | 60/min/IP | +| Solicitudes de lectura | 600/min/IP | + +Usa un backend compartido como Redis para despliegues con múltiples pods. + +## CORS + +Configura orígenes explícitos: + +```text +https://app.example.com +https://admin.example.com +``` + +No uses orígenes comodín con solicitudes que incluyan credenciales. + +## Lista de verificación para la puesta en marcha + +- [ ] El TLS se termina en el edge o en el ingress. +- [ ] Las cabeceras de seguridad están presentes. +- [ ] HSTS está habilitado tras la validación del TLS. +- [ ] Los orígenes de CORS son explícitos. +- [ ] Los límites de tasa protegen los endpoints de autenticación y escritura. +- [ ] `OS_AUTH_SECRET` es robusto y se almacena como secreto. +- [ ] Las URL de callback de OIDC coinciden con el dominio público. +- [ ] La copia de seguridad y la restauración de la base de datos de negocio están probadas. +- [ ] Los registros de auditoría se conservan según la política del cliente. +- [ ] Las pruebas negativas de acceso entre organizaciones pasan. +- [ ] El plan de reversión cubre tanto la imagen de ObjectOS como la versión del artefacto. diff --git a/content/docs/operate/production.fr.mdx b/content/docs/operate/production.fr.mdx new file mode 100644 index 0000000..a0cbf0a --- /dev/null +++ b/content/docs/operate/production.fr.mdx @@ -0,0 +1,83 @@ +--- +title: Préparation à la production +description: Liste de contrôle pour exécuter ObjectOS en toute sécurité en production. +--- + +# Préparation à la production + +Utilisez cette liste de contrôle avant d'exposer ObjectOS au trafic de production. + +## Renforcement HTTP + +Le runtime ObjectStack fournit des en-têtes de sécurité prudents pour les +routes du dispatcher. Les déploiements en production doivent vérifier : + +- `Content-Security-Policy` ; +- `X-Content-Type-Options` ; +- `X-Frame-Options` ; +- `Referrer-Policy` ; +- `Permissions-Policy` ; +- `Cross-Origin-Resource-Policy` ; +- HSTS une fois le TLS confirmé. + +Si un reverse proxy gère les en-têtes, vérifiez la réponse finale avec : + +```bash +curl -I https://app.example.com +``` + +## Secrets + +Stockez ces éléments dans un gestionnaire de secrets : + +| Secret | Objet | +|---|---| +| `OS_AUTH_SECRET` | Secret de base pour la signature des sessions | +| `OS_CLOUD_API_KEY` | Accès à l'Artifact API du plan de contrôle | +| Identifiants de base de données | Accès à la base de données métier | +| Secret client OIDC | SSO d'entreprise | +| Clés API de fournisseurs | E-mail, stockage, IA, intégrations | + +N'intégrez jamais de secrets dans les artefacts ou les images. + +## Limitation de débit + +Le framework expose un limiteur de débit de type token-bucket. Mettez en place +la limitation de débit au niveau de l'adaptateur, de l'ingress ou de la +passerelle, là où l'IP de l'appelant et l'identité authentifiée sont fiables. + +Buckets recommandés : + +| Trafic | Limite exemple | +|---|---:| +| Points de terminaison d'authentification | 10/min/IP | +| Requêtes d'écriture | 60/min/IP | +| Requêtes de lecture | 600/min/IP | + +Utilisez un backend partagé tel que Redis pour les déploiements multi-pods. + +## CORS + +Configurez des origines explicites : + +```text +https://app.example.com +https://admin.example.com +``` + +N'utilisez pas d'origines avec caractère générique pour les requêtes +authentifiées. + +## Liste de contrôle de mise en production + +- [ ] Le TLS est terminé au niveau de l'edge ou de l'ingress. +- [ ] Les en-têtes de sécurité sont présents. +- [ ] HSTS est activé après validation du TLS. +- [ ] Les origines CORS sont explicites. +- [ ] Les limites de débit protègent les points de terminaison d'authentification et d'écriture. +- [ ] `OS_AUTH_SECRET` est robuste et stocké comme un secret. +- [ ] Les URL de callback OIDC correspondent au domaine public. +- [ ] La sauvegarde et la restauration de la base de données métier sont testées. +- [ ] Les journaux d'audit sont conservés conformément à la politique du client. +- [ ] Les tests d'accès négatifs inter-organisations réussissent. +- [ ] Le plan de rollback couvre à la fois l'image ObjectOS et la version de l'artefact. diff --git a/content/docs/operate/production.ja.mdx b/content/docs/operate/production.ja.mdx new file mode 100644 index 0000000..347d7b7 --- /dev/null +++ b/content/docs/operate/production.ja.mdx @@ -0,0 +1,79 @@ +--- +title: 本番運用の準備 +description: ObjectOS を本番環境で安全に運用するためのチェックリスト。 +--- + +# 本番運用の準備 + +ObjectOS を本番トラフィックに公開する前に、このチェックリストを使用してください。 + +## HTTP のハードニング + +ObjectStack ランタイムは、ディスパッチャールートに対して保守的なセキュリティヘッダーを提供します。本番デプロイでは、以下を確認してください。 + +- `Content-Security-Policy` +- `X-Content-Type-Options` +- `X-Frame-Options` +- `Referrer-Policy` +- `Permissions-Policy` +- `Cross-Origin-Resource-Policy` +- TLS が確認できたら HSTS + +リバースプロキシがヘッダーを管理している場合は、次のコマンドで最終的なレスポンスを確認してください。 + +```bash +curl -I https://app.example.com +``` + +## シークレット + +以下はシークレットマネージャーに保管してください。 + +| シークレット | 用途 | +|---|---| +| `OS_AUTH_SECRET` | セッション署名のベースシークレット | +| `OS_CLOUD_API_KEY` | コントロールプレーンの Artifact API アクセス | +| データベース認証情報 | 業務データベースへのアクセス | +| OIDC クライアントシークレット | エンタープライズ SSO | +| プロバイダーの API キー | メール、ストレージ、AI、連携 | + +シークレットをアーティファクトやイメージに埋め込まないでください。 + +## レート制限 + +フレームワークはトークンバケット方式のレートリミッターを提供します。呼び出し元の IP と認証済みアイデンティティが信頼できる、アダプター、イングレス、またはゲートウェイの層でレート制限を組み込んでください。 + +推奨バケット: + +| トラフィック | 制限の例 | +|---|---:| +| 認証エンドポイント | 10/分/IP | +| 書き込みリクエスト | 60/分/IP | +| 読み取りリクエスト | 600/分/IP | + +複数ポッドのデプロイでは、Redis などの共有バックエンドを使用してください。 + +## CORS + +許可するオリジンを明示的に設定してください。 + +```text +https://app.example.com +https://admin.example.com +``` + +認証情報付きリクエストでワイルドカードのオリジンを使用しないでください。 + +## 本番公開チェックリスト + +- [ ] TLS がエッジまたはイングレスで終端されている。 +- [ ] セキュリティヘッダーが存在する。 +- [ ] TLS の検証後に HSTS が有効になっている。 +- [ ] CORS のオリジンが明示的に指定されている。 +- [ ] レート制限が認証エンドポイントと書き込みエンドポイントを保護している。 +- [ ] `OS_AUTH_SECRET` が強力で、シークレットとして保管されている。 +- [ ] OIDC のコールバック URL が公開ドメインと一致している。 +- [ ] 業務データベースのバックアップとリストアがテスト済みである。 +- [ ] 監査ログが顧客のポリシーに従って保持されている。 +- [ ] 組織をまたいだネガティブアクセステストに合格している。 +- [ ] ロールバック計画が ObjectOS イメージとアーティファクトバージョンの両方をカバーしている。 diff --git a/content/docs/operate/production.cn.mdx b/content/docs/operate/production.zh-Hans.mdx similarity index 100% rename from content/docs/operate/production.cn.mdx rename to content/docs/operate/production.zh-Hans.mdx diff --git a/content/docs/operate/troubleshooting.de.mdx b/content/docs/operate/troubleshooting.de.mdx new file mode 100644 index 0000000..22630f5 --- /dev/null +++ b/content/docs/operate/troubleshooting.de.mdx @@ -0,0 +1,94 @@ +--- +title: Fehlerbehebung +description: Diagnostizieren Sie Probleme bei Start, Artefakten, Authentifizierung, Berechtigungen und Deployment. +--- + +# Fehlerbehebung + +Beginnen Sie mit dem Symptom und prüfen Sie dann zuerst die kleinste Abgrenzung. + +## ObjectOS startet nicht + +Prüfen Sie: + +1. Container-Logs. +2. Node-Version und Paketinstallation. +3. `PORT`-Konflikt. +4. Fehlendes Artefakt. +5. Fehlendes `OS_AUTH_SECRET`, wenn Auth-Endpunkte erwartet werden. + +Für Docker: + +```bash +docker compose -f docker/docker-compose.yml logs objectos +``` + +## Artefakt kann nicht geladen werden + +Prüfen Sie: + +- `OS_ARTIFACT_FILE` zeigt auf die eingehängte Datei; +- die Datei existiert innerhalb des Containers; +- die Datei ist gültiges JSON; +- das Artefakt ist ein kompiliertes ObjectStack-Artefakt, keine Quell-Metadaten; +- die Dateiberechtigungen erlauben Lesezugriff. + +Innerhalb eines Containers: + +```bash +ls -l /artifacts/objectstack.json +``` + +## Anmeldung schlägt fehl + +Prüfen Sie: + +- `OS_AUTH_SECRET` ist konfiguriert; +- öffentliche URL und Callback-URL stimmen überein; +- die OIDC-Discovery-URL ist von ObjectOS aus erreichbar; +- die vertrauenswürdigen Origins enthalten die öffentliche Domain; +- Cookies sind auf den korrekten Projekt-Hostnamen begrenzt; +- der Projekt-Kernel hat die Authentifizierung aktiviert. + +## Benutzer kann keine Datensätze sehen + +Prüfen Sie: + +1. Korrekter Projekt-Hostname. +2. Der Benutzer gehört zur erwarteten Organisation. +3. Objekt-Berechtigung `read`. +4. Sicherheit auf Zeilenebene. +5. Freigaberegeln oder Datensatzfreigaben. +6. Feldsicherheit, wenn nur einige Felder fehlen. + +## Einstellungen sind nicht bearbeitbar + +Eine Einstellung kann durch eine Umgebungsüberschreibung gesperrt sein. Effektive Einstellungen +werden in dieser Reihenfolge aufgelöst: + +```text +Environment -> Tenant -> User -> Default +``` + +Wenn die Umgebung einen Wert bereitstellt, sollten Laufzeitänderungen abgelehnt werden, +anstatt ihn stillschweigend zu überschreiben. + +## Webhooks oder Jobs werden nicht ausgeführt + +Prüfen Sie: + +- die `requires`-Liste des Artefakts enthält die benötigte Capability; +- das ObjectOS-Image enthält das optionale Service-Paket; +- die Konfiguration des Queue-/Job-Service ist verfügbar; +- ausgehender Netzwerkzugriff auf das Ziel ist erlaubt; +- Zustelllogs oder Job-Läufe sind in der Console-Diagnose sichtbar. + +## Datenbankfehler + +Prüfen Sie: + +- Datenbank-URL und Treibertyp; +- Netzwerkzugriff von ObjectOS auf die Datenbank; +- Anmeldedaten und TLS-Optionen; +- Logs zur Schema-Synchronisierung/-Migration; +- Speicherpersistenz bei Verwendung von lokalem SQLite. diff --git a/content/docs/operate/troubleshooting.es.mdx b/content/docs/operate/troubleshooting.es.mdx new file mode 100644 index 0000000..258c8f4 --- /dev/null +++ b/content/docs/operate/troubleshooting.es.mdx @@ -0,0 +1,94 @@ +--- +title: Resolución de problemas +description: Diagnostica problemas de arranque, artefactos, autenticación, permisos e implementación. +--- + +# Resolución de problemas + +Comienza por el síntoma y luego revisa primero el límite más pequeño. + +## ObjectOS no arranca + +Revisa: + +1. Los registros del contenedor. +2. La versión de Node y la instalación de paquetes. +3. Conflictos en `PORT`. +4. Artefacto faltante. +5. Falta de `OS_AUTH_SECRET` cuando se esperan endpoints de autenticación. + +Para Docker: + +```bash +docker compose -f docker/docker-compose.yml logs objectos +``` + +## No se puede cargar el artefacto + +Revisa: + +- que `OS_ARTIFACT_FILE` apunte al archivo montado; +- que el archivo exista dentro del contenedor; +- que el archivo sea un JSON válido; +- que el artefacto sea un artefacto compilado de ObjectStack, no metadatos de origen; +- que los permisos del archivo permitan el acceso de lectura. + +Dentro de un contenedor: + +```bash +ls -l /artifacts/objectstack.json +``` + +## El inicio de sesión falla + +Revisa: + +- que `OS_AUTH_SECRET` esté configurado; +- que la URL pública y la URL de callback coincidan; +- que la URL de descubrimiento de OIDC sea accesible desde ObjectOS; +- que los orígenes de confianza incluyan el dominio público; +- que las cookies estén delimitadas al nombre de host correcto del proyecto; +- que el kernel del proyecto tenga la autenticación habilitada. + +## El usuario no puede ver registros + +Revisa: + +1. El nombre de host correcto del proyecto. +2. Que el usuario pertenezca a la organización esperada. +3. El permiso `read` del objeto. +4. La seguridad a nivel de fila. +5. Las reglas de compartición o los registros compartidos. +6. La seguridad de campo si solo faltan algunos campos. + +## Los ajustes no se pueden editar + +Un ajuste puede estar bloqueado por una anulación de entorno. Los ajustes efectivos +se resuelven en este orden: + +```text +Environment -> Tenant -> User -> Default +``` + +Si el entorno proporciona un valor, las ediciones en tiempo de ejecución deberían rechazarse +en lugar de sobrescribirlo de forma silenciosa. + +## Los webhooks o trabajos no se ejecutan + +Revisa: + +- que la lista `requires` del artefacto incluya la capacidad necesaria; +- que la imagen de ObjectOS incluya el paquete de servicio opcional; +- que la configuración del servicio de cola/trabajos esté disponible; +- que se permita el acceso de red saliente hacia el destino; +- que los registros de entrega o las ejecuciones de trabajos sean visibles en los diagnósticos de Console. + +## Errores de base de datos + +Revisa: + +- la URL de la base de datos y el tipo de controlador; +- el acceso de red desde ObjectOS hacia la base de datos; +- las credenciales y las opciones de TLS; +- los registros de sincronización/migración de esquema; +- la persistencia del almacenamiento si usas SQLite local. diff --git a/content/docs/operate/troubleshooting.fr.mdx b/content/docs/operate/troubleshooting.fr.mdx new file mode 100644 index 0000000..8b20e9b --- /dev/null +++ b/content/docs/operate/troubleshooting.fr.mdx @@ -0,0 +1,94 @@ +--- +title: Dépannage +description: Diagnostiquer les problèmes de démarrage, d'artefact, d'authentification, de permission et de déploiement. +--- + +# Dépannage + +Commencez par le symptôme, puis vérifiez d'abord la plus petite limite. + +## ObjectOS ne démarre pas + +Vérifiez : + +1. Les journaux du conteneur. +2. La version de Node et l'installation des paquets. +3. Un conflit de `PORT`. +4. Un artefact manquant. +5. L'absence de `OS_AUTH_SECRET` lorsque des points de terminaison d'authentification sont attendus. + +Pour Docker : + +```bash +docker compose -f docker/docker-compose.yml logs objectos +``` + +## L'artefact ne peut pas être chargé + +Vérifiez : + +- que `OS_ARTIFACT_FILE` pointe vers le fichier monté ; +- que le fichier existe à l'intérieur du conteneur ; +- que le fichier est un JSON valide ; +- que l'artefact est un artefact ObjectStack compilé, et non des métadonnées source ; +- que les permissions du fichier autorisent l'accès en lecture. + +À l'intérieur d'un conteneur : + +```bash +ls -l /artifacts/objectstack.json +``` + +## La connexion échoue + +Vérifiez : + +- que `OS_AUTH_SECRET` est configuré ; +- que l'URL publique et l'URL de rappel correspondent ; +- que l'URL de découverte OIDC est joignable depuis ObjectOS ; +- que les origines de confiance incluent le domaine public ; +- que les cookies sont limités au nom d'hôte de projet correct ; +- que le kernel du projet a l'authentification activée. + +## Un utilisateur ne voit pas les enregistrements + +Vérifiez : + +1. Le nom d'hôte de projet correct. +2. Que l'utilisateur appartient à l'organisation attendue. +3. La permission `read` sur l'objet. +4. La sécurité au niveau des lignes. +5. Les règles de partage ou les partages d'enregistrements. +6. La sécurité des champs si seuls certains champs sont manquants. + +## Les paramètres ne sont pas modifiables + +Un paramètre peut être verrouillé par une surcharge d'environnement. Les paramètres +effectifs sont résolus dans cet ordre : + +```text +Environment -> Tenant -> User -> Default +``` + +Si l'environnement fournit une valeur, les modifications à l'exécution doivent être rejetées +au lieu de l'écraser silencieusement. + +## Les webhooks ou les tâches ne s'exécutent pas + +Vérifiez : + +- que la liste `requires` de l'artefact inclut la capacité nécessaire ; +- que l'image ObjectOS inclut le paquet de service optionnel ; +- que la configuration du service de file d'attente/de tâches est disponible ; +- que l'accès réseau sortant vers la cible est autorisé ; +- que les journaux de livraison ou les exécutions de tâches sont visibles dans les diagnostics de la Console. + +## Erreurs de base de données + +Vérifiez : + +- l'URL de la base de données et le type de pilote ; +- l'accès réseau depuis ObjectOS vers la base de données ; +- les identifiants et les options TLS ; +- les journaux de synchronisation/migration du schéma ; +- la persistance du stockage si vous utilisez SQLite en local. diff --git a/content/docs/operate/troubleshooting.ja.mdx b/content/docs/operate/troubleshooting.ja.mdx new file mode 100644 index 0000000..184c27d --- /dev/null +++ b/content/docs/operate/troubleshooting.ja.mdx @@ -0,0 +1,92 @@ +--- +title: トラブルシューティング +description: 起動、アーティファクト、認証、権限、デプロイに関する問題を診断します。 +--- + +# トラブルシューティング + +まず症状から始め、最も小さな境界から確認しましょう。 + +## ObjectOS が起動しない + +確認事項: + +1. コンテナのログ。 +2. Node のバージョンとパッケージのインストール。 +3. `PORT` の競合。 +4. アーティファクトの欠落。 +5. 認証エンドポイントが必要な場合の `OS_AUTH_SECRET` の欠落。 + +Docker の場合: + +```bash +docker compose -f docker/docker-compose.yml logs objectos +``` + +## アーティファクトを読み込めない + +確認事項: + +- `OS_ARTIFACT_FILE` がマウントされたファイルを指していること。 +- そのファイルがコンテナ内に存在すること。 +- そのファイルが有効な JSON であること。 +- アーティファクトがソースのメタデータではなく、コンパイル済みの ObjectStack アーティファクトであること。 +- ファイルの権限が読み取りアクセスを許可していること。 + +コンテナ内で: + +```bash +ls -l /artifacts/objectstack.json +``` + +## ログインに失敗する + +確認事項: + +- `OS_AUTH_SECRET` が設定されていること。 +- 公開 URL とコールバック URL が一致していること。 +- OIDC ディスカバリ URL に ObjectOS から到達できること。 +- 信頼されたオリジンに公開ドメインが含まれていること。 +- Cookie が正しいプロジェクトのホスト名にスコープされていること。 +- プロジェクトカーネルで認証が有効になっていること。 + +## ユーザーがレコードを表示できない + +確認事項: + +1. 正しいプロジェクトのホスト名。 +2. ユーザーが想定される組織に属していること。 +3. オブジェクトの `read` 権限。 +4. 行レベルセキュリティ。 +5. 共有ルールまたはレコード共有。 +6. 一部のフィールドのみが表示されない場合はフィールドセキュリティ。 + +## 設定を編集できない + +設定が環境のオーバーライドによってロックされている場合があります。有効な設定は次の順序で解決されます: + +```text +Environment -> Tenant -> User -> Default +``` + +環境が値を提供している場合、ランタイムでの編集は、暗黙的に上書きするのではなく拒否されるべきです。 + +## Webhook やジョブが実行されない + +確認事項: + +- アーティファクトの `requires` リストに必要な機能が含まれていること。 +- ObjectOS イメージにオプションのサービスパッケージが含まれていること。 +- キュー/ジョブサービスの構成が利用可能であること。 +- ターゲットへのアウトバウンドネットワークアクセスが許可されていること。 +- 配信ログまたはジョブ実行が Console の診断機能で確認できること。 + +## データベースエラー + +確認事項: + +- データベース URL とドライバの種類。 +- ObjectOS からデータベースへのネットワークアクセス。 +- 認証情報と TLS オプション。 +- スキーマの同期/マイグレーションのログ。 +- ローカル SQLite を使用している場合のストレージの永続化。 diff --git a/content/docs/operate/troubleshooting.cn.mdx b/content/docs/operate/troubleshooting.zh-Hans.mdx similarity index 100% rename from content/docs/operate/troubleshooting.cn.mdx rename to content/docs/operate/troubleshooting.zh-Hans.mdx diff --git a/content/docs/operate/upgrade.cn.mdx b/content/docs/operate/upgrade.cn.mdx deleted file mode 100644 index d8ecd09..0000000 --- a/content/docs/operate/upgrade.cn.mdx +++ /dev/null @@ -1,66 +0,0 @@ ---- -title: 升级与回滚 -description: 安全升级 ObjectOS 与应用产物。 ---- - -# 升级与回滚 - -ObjectOS 有两条版本流: - -| 版本 | 拥有者 | 回滚 | -|---|---|---| -| ObjectOS 镜像/运行时 | 平台/运行时团队 | 上一个容器 tag | -| 应用产物 | 应用/控制面发布团队 | 上一个产物或项目版本指针 | - -不要就地修改产物。请发布一个新产物,再把运行时切换过去。 - -## 升级 ObjectOS - -Docker Compose: - -```bash -docker compose -f docker/docker-compose.yml pull -docker compose -f docker/docker-compose.yml up -d -``` - -Kubernetes 下,更新镜像 tag,让 Deployment 滚动更新。 - -## 升级产物 - -文件挂载模式: - -```bash -cp objectstack-2026-05-24.json docker/artifacts/objectstack.json -docker compose -f docker/docker-compose.yml restart objectos -``` - -云连接模式: - -1. 将新产物发布到控制面。 -2. 把当前的项目/环境指针指向新版本。 -3. 等待 ObjectOS 在缓存过期后重新拉取,或重启以强制重新加载。 - -## 回滚 - -回滚 ObjectOS: - -```bash -docker compose -f docker/docker-compose.yml up -d objectos -``` - -使用上一个镜像 tag 即可。 - -回滚产物: - -- 恢复之前挂载的文件;或 -- 将控制面指针移回上一个产物版本。 - -## 兼容性检查 - -升级前: - -- 确认产物所针对的 ObjectStack 版本与目标兼容; -- 确认所需能力在 ObjectOS 镜像中可用; -- 确认数据库迁移或 schema 同步行为已被理解; -- 跑一遍认证与权限的冒烟测试; -- 确认回滚不需要破坏性的数据变更。 diff --git a/content/docs/operate/upgrade.de.mdx b/content/docs/operate/upgrade.de.mdx new file mode 100644 index 0000000..2ca494e --- /dev/null +++ b/content/docs/operate/upgrade.de.mdx @@ -0,0 +1,66 @@ +--- +title: Upgrade und Rollback +description: ObjectOS und Anwendungsartefakte sicher aktualisieren. +--- + +# Upgrade und Rollback + +ObjectOS hat zwei Versionsstränge: + +| Version | Verantwortlich | Rollback | +|---|---|---| +| ObjectOS-Image/Runtime | Plattform-/Runtime-Team | Vorheriger Container-Tag | +| Anwendungsartefakt | Anwendungs-/Control-Plane-Release | Vorheriges Artefakt oder Projektversions-Zeiger | + +Ändern Sie Artefakte nicht direkt. Veröffentlichen Sie ein neues Artefakt und +schalten Sie die Runtime darauf um. + +## ObjectOS aktualisieren + +Für Docker Compose: + +```bash +docker compose -f docker/docker-compose.yml pull +docker compose -f docker/docker-compose.yml up -d +``` + +Aktualisieren Sie für Kubernetes den Image-Tag und lassen Sie das Deployment rollen. + +## Artefakt aktualisieren + +Dateibasierter Modus: + +```bash +cp objectstack-2026-05-24.json docker/artifacts/objectstack.json +docker compose -f docker/docker-compose.yml restart objectos +``` + +Cloud-verbundener Modus: + +1. Veröffentlichen Sie das neue Artefakt in der Control Plane. +2. Verschieben Sie den aktuellen Projekt-/Umgebungszeiger auf die neue Version. +3. Lassen Sie ObjectOS nach Ablauf des Caches neu abrufen oder starten Sie neu, um ein Neuladen zu erzwingen. + +## Rollback + +ObjectOS zurückrollen: Pinnen Sie den vorherigen Image-Tag in Ihrer Compose-Datei +(oder im Deployment-Manifest) und wenden Sie ihn erneut an. + +```bash +docker compose -f docker/docker-compose.yml up -d objectos +``` + +Artefakt zurückrollen: + +- Stellen Sie die vorherige gemountete Datei wieder her; oder +- Verschieben Sie den Control-Plane-Zeiger zurück auf die vorherige Artefaktversion. + +## Kompatibilitätsprüfungen + +Vor dem Upgrade: + +- bestätigen Sie, dass das Artefakt gegen eine kompatible ObjectStack-Version erstellt wurde; +- bestätigen Sie, dass die erforderlichen Funktionen im ObjectOS-Image verfügbar sind; +- bestätigen Sie, dass das Verhalten von Datenbankmigrationen oder Schema-Sync verstanden wurde; +- führen Sie Smoke-Tests für Authentifizierung und Berechtigungen durch; +- stellen Sie sicher, dass das Rollback keine destruktiven Datenänderungen erfordert. diff --git a/content/docs/operate/upgrade.es.mdx b/content/docs/operate/upgrade.es.mdx new file mode 100644 index 0000000..6a7c049 --- /dev/null +++ b/content/docs/operate/upgrade.es.mdx @@ -0,0 +1,66 @@ +--- +title: Actualización y reversión +description: Actualiza ObjectOS y los artefactos de la aplicación de forma segura. +--- + +# Actualización y reversión + +ObjectOS tiene dos flujos de versiones: + +| Versión | Responsable | Reversión | +|---|---|---| +| Imagen/runtime de ObjectOS | Equipo de plataforma/runtime | Etiqueta del contenedor anterior | +| Artefacto de la aplicación | Publicación de la aplicación/plano de control | Artefacto anterior o puntero de versión del proyecto | + +No modifiques los artefactos en su lugar. Publica un nuevo artefacto y cambia el +runtime para que lo use. + +## Actualizar ObjectOS + +Para Docker Compose: + +```bash +docker compose -f docker/docker-compose.yml pull +docker compose -f docker/docker-compose.yml up -d +``` + +Para Kubernetes, actualiza la etiqueta de la imagen y deja que el despliegue se renueve. + +## Actualizar el artefacto + +Modo basado en archivos: + +```bash +cp objectstack-2026-05-24.json docker/artifacts/objectstack.json +docker compose -f docker/docker-compose.yml restart objectos +``` + +Modo conectado a la nube: + +1. Publica el nuevo artefacto en el plano de control. +2. Mueve el puntero del proyecto/entorno actual a la nueva versión. +3. Deja que ObjectOS vuelva a obtenerlo tras la expiración de la caché o reinícialo para forzar la recarga. + +## Reversión + +Revertir ObjectOS: fija la etiqueta de la imagen anterior en tu archivo Compose (o +manifiesto de despliegue) y vuelve a aplicarlo. + +```bash +docker compose -f docker/docker-compose.yml up -d objectos +``` + +Revertir el artefacto: + +- restaura el archivo montado anterior; o +- mueve el puntero del plano de control de vuelta a la versión anterior del artefacto. + +## Comprobaciones de compatibilidad + +Antes de actualizar: + +- confirma que el artefacto se compiló contra una versión compatible de ObjectStack; +- confirma que las capacidades requeridas están disponibles en la imagen de ObjectOS; +- confirma que se comprende el comportamiento de las migraciones de base de datos o la sincronización del esquema; +- ejecuta pruebas de humo de autenticación y permisos; +- verifica que la reversión no requiere cambios destructivos en los datos. diff --git a/content/docs/operate/upgrade.fr.mdx b/content/docs/operate/upgrade.fr.mdx new file mode 100644 index 0000000..968c1e7 --- /dev/null +++ b/content/docs/operate/upgrade.fr.mdx @@ -0,0 +1,66 @@ +--- +title: Mise à niveau et restauration +description: Mettez à niveau ObjectOS et les artefacts d'application en toute sécurité. +--- + +# Mise à niveau et restauration + +ObjectOS possède deux flux de versions : + +| Version | Responsable | Restauration | +|---|---|---| +| Image/runtime ObjectOS | Équipe plateforme/runtime | Tag de conteneur précédent | +| Artefact d'application | Publication application/plan de contrôle | Artefact précédent ou pointeur de version du projet | + +Ne modifiez pas les artefacts en place. Publiez un nouvel artefact et faites pointer le +runtime vers celui-ci. + +## Mettre à niveau ObjectOS + +Pour Docker Compose : + +```bash +docker compose -f docker/docker-compose.yml pull +docker compose -f docker/docker-compose.yml up -d +``` + +Pour Kubernetes, mettez à jour le tag de l'image et laissez le déploiement se dérouler. + +## Mettre à niveau l'artefact + +Mode basé sur fichier : + +```bash +cp objectstack-2026-05-24.json docker/artifacts/objectstack.json +docker compose -f docker/docker-compose.yml restart objectos +``` + +Mode connecté au cloud : + +1. Publiez le nouvel artefact sur le plan de contrôle. +2. Déplacez le pointeur de projet/environnement actuel vers la nouvelle version. +3. Laissez ObjectOS récupérer à nouveau les données après l'expiration du cache ou redémarrez pour forcer le rechargement. + +## Restauration + +Restaurer ObjectOS : épinglez le tag d'image précédent dans votre fichier Compose (ou +votre manifeste de déploiement), puis réappliquez-le. + +```bash +docker compose -f docker/docker-compose.yml up -d objectos +``` + +Restaurer l'artefact : + +- restaurez le fichier monté précédent ; ou +- ramenez le pointeur du plan de contrôle vers la version d'artefact précédente. + +## Vérifications de compatibilité + +Avant la mise à niveau : + +- confirmez que l'artefact a été construit pour une version compatible d'ObjectStack ; +- confirmez que les capacités requises sont disponibles dans l'image ObjectOS ; +- confirmez que les migrations de base de données ou le comportement de synchronisation du schéma sont bien compris ; +- exécutez des tests de fumée d'authentification et de permissions ; +- vérifiez que la restauration ne nécessite pas de modifications destructrices des données. diff --git a/content/docs/operate/upgrade.ja.mdx b/content/docs/operate/upgrade.ja.mdx new file mode 100644 index 0000000..e311ed9 --- /dev/null +++ b/content/docs/operate/upgrade.ja.mdx @@ -0,0 +1,66 @@ +--- +title: アップグレードとロールバック +description: ObjectOS とアプリケーションアーティファクトを安全にアップグレードします。 +--- + +# アップグレードとロールバック + +ObjectOS には 2 つのバージョンストリームがあります。 + +| バージョン | 所有者 | ロールバック | +|---|---|---| +| ObjectOS イメージ/ランタイム | プラットフォーム/ランタイムチーム | 以前のコンテナタグ | +| アプリケーションアーティファクト | アプリケーション/コントロールプレーンのリリース | 以前のアーティファクトまたはプロジェクトバージョンポインター | + +アーティファクトをその場で変更しないでください。新しいアーティファクトを公開し、 +ランタイムをそれに切り替えてください。 + +## ObjectOS のアップグレード + +Docker Compose の場合: + +```bash +docker compose -f docker/docker-compose.yml pull +docker compose -f docker/docker-compose.yml up -d +``` + +Kubernetes の場合は、イメージタグを更新し、デプロイメントをロールさせます。 + +## アーティファクトのアップグレード + +ファイルベースモード: + +```bash +cp objectstack-2026-05-24.json docker/artifacts/objectstack.json +docker compose -f docker/docker-compose.yml restart objectos +``` + +クラウド接続モード: + +1. 新しいアーティファクトをコントロールプレーンに公開します。 +2. 現在のプロジェクト/環境ポインターを新しいバージョンに移動します。 +3. キャッシュの有効期限切れ後に ObjectOS を再取得させるか、再起動して強制的に再読み込みします。 + +## ロールバック + +ObjectOS のロールバック: Compose ファイル(またはデプロイメントマニフェスト)で +以前のイメージタグを固定し、それを再適用します。 + +```bash +docker compose -f docker/docker-compose.yml up -d objectos +``` + +アーティファクトのロールバック: + +- 以前のマウントされたファイルを復元する。または +- コントロールプレーンのポインターを以前のアーティファクトバージョンに戻す。 + +## 互換性チェック + +アップグレードの前に: + +- アーティファクトが互換性のある ObjectStack バージョンに対してビルドされていることを確認する。 +- 必要な機能が ObjectOS イメージで利用可能であることを確認する。 +- データベースマイグレーションまたはスキーマ同期の動作を理解していることを確認する。 +- 認証および権限のスモークテストを実行する。 +- ロールバックが破壊的なデータ変更を必要としないことを確認する。 diff --git a/content/docs/operate/upgrade.mdx b/content/docs/operate/upgrade.mdx index b1c2528..cd50d01 100644 --- a/content/docs/operate/upgrade.mdx +++ b/content/docs/operate/upgrade.mdx @@ -43,14 +43,13 @@ Cloud-connected mode: ## Rollback -Rollback ObjectOS: +Rollback ObjectOS: pin the previous image tag in your Compose file (or +deployment manifest), then re-apply it. ```bash docker compose -f docker/docker-compose.yml up -d objectos ``` -with the previous image tag. - Rollback artifact: - restore the previous mounted file; or diff --git a/content/docs/operate/upgrade.zh-Hans.mdx b/content/docs/operate/upgrade.zh-Hans.mdx new file mode 100644 index 0000000..6372665 --- /dev/null +++ b/content/docs/operate/upgrade.zh-Hans.mdx @@ -0,0 +1,64 @@ +--- +title: 升级与回滚 +description: 安全地升级 ObjectOS 与应用制品。 +--- + +# 升级与回滚 + +ObjectOS 有两条版本流: + +| 版本 | 所有者 | 回滚 | +|---|---|---| +| ObjectOS 镜像/运行时 | 平台/运行时团队 | 上一个容器标签 | +| 应用制品 | 应用/控制平面发布 | 上一个制品或项目版本指针 | + +不要就地修改制品。请发布一个新制品,并将运行时切换到它。 + +## 升级 ObjectOS + +对于 Docker Compose: + +```bash +docker compose -f docker/docker-compose.yml pull +docker compose -f docker/docker-compose.yml up -d +``` + +对于 Kubernetes,更新镜像标签并让部署自动滚动更新。 + +## 升级制品 + +文件支撑模式: + +```bash +cp objectstack-2026-05-24.json docker/artifacts/objectstack.json +docker compose -f docker/docker-compose.yml restart objectos +``` + +云连接模式: + +1. 将新制品发布到控制平面。 +2. 将当前项目/环境指针指向新版本。 +3. 让 ObjectOS 在缓存过期后重新拉取,或重启以强制重新加载。 + +## 回滚 + +回滚 ObjectOS:在你的 Compose 文件(或部署清单)中固定上一个镜像标签,然后重新应用它。 + +```bash +docker compose -f docker/docker-compose.yml up -d objectos +``` + +回滚制品: + +- 恢复之前挂载的文件;或 +- 将控制平面指针移回上一个制品版本。 + +## 兼容性检查 + +升级前: + +- 确认制品是针对兼容的 ObjectStack 版本构建的; +- 确认所需能力在 ObjectOS 镜像中可用; +- 确认理解数据库迁移或模式同步行为; +- 运行身份验证与权限冒烟测试; +- 验证回滚不需要进行破坏性的数据变更。 diff --git a/content/docs/quickstart.de.mdx b/content/docs/quickstart.de.mdx new file mode 100644 index 0000000..042dea8 --- /dev/null +++ b/content/docs/quickstart.de.mdx @@ -0,0 +1,233 @@ +--- +title: Schnellstart +description: Von null zu einem laufenden ObjectOS — eine CLI installieren, einen Befehl ausführen, schon haben Sie eine App. +--- + +# Schnellstart + +Es gibt zwei Möglichkeiten zu starten, je nachdem, was Sie vorhaben. + +| Sie sind … | Hier starten | +|---|---| +| Sie testen ObjectOS zum ersten Mal oder betreiben es in der Produktion | [Pfad A — `os start`](#path-a--os-start-operator-first-time-evaluator) | +| Sie entwickeln oder passen eine App im Code an | [Pfad B — `os init`](#path-b--os-init-developer) | + +Beide erzeugen einen laufenden Server mit Console + Account. Der +Unterschied besteht darin, ob Sie Quelldateien als Gerüst erstellen. + +## Voraussetzungen + +- **Node.js 20 oder neuer** — `node --version` +- Ein Terminal + +Das war's. Kein Docker. Keine Datenbank. Keine Kontoregistrierung. + +--- + +## Pfad A — `os start` (Operator / erstmaliger Tester) + +Installieren Sie die CLI global und führen Sie sie dann aus: + +```bash +npm i -g @objectstack/cli +os start +``` + +Sie sehen: + +```text +◆ ObjectStack +──────────────────────────────────────── +🏠 Home: ~/.objectstack +📦 Artifact: none (empty kernel — install apps via Console marketplace) +🗄️ Database: file:~/.objectstack/data/objectstack.db + + ✓ Server is ready + + ➜ API: http://localhost:3000/ + ➜ Console: http://localhost:3000/_console/ + ➜ Account: http://localhost:3000/_account/ + ➜ Console: http://localhost:3000/_console/ + + Plugins: 23 loaded +``` + +Das war's. Sie betreiben jetzt ObjectOS. + +### Was läuft + +| URL | Was es ist | +|---|---| +| http://localhost:3000/_account/register | Erstellen Sie Ihr erstes Konto | +| http://localhost:3000/_console/ | Die Admin-Oberfläche — und der **App-marketplace** | +| http://localhost:3000/_console/ | Benutzer, Rollen, Audit-Log, Einstellungen | +| http://localhost:3000/health | Liveness-Probe | + +Die Laufzeitumgebung startet in einem **leeren Kernel** — keine Objekte, keine Apps — +und stellt den marketplace bereit, sodass Sie fertige Apps in +Sekunden installieren können. + +### Per Chat erstellen — der AI Builder + +Sobald Sie angemeldet sind, öffnen Sie den KI-Assistenten in der Console (Funkel-Symbol +oben rechts) und beschreiben Sie, was Sie benötigen: + +> *„Ich muss Kundensupport-Tickets verfolgen. Jedes hat einen Betreff, +> eine Beschreibung, eine Priorität (niedrig/mittel/hoch/dringend), einen Status und +> einen Bearbeiter. Füge eine Kanban-Ansicht hinzu, gruppiert nach Status."* + +Die KI schlägt einen Plan vor, Sie genehmigen ihn, und die Metadaten sind aktiv — +REST-Endpunkte, Console-Ansichten, Audit-Log-Einträge, Berechtigungsschranken. +Keine Datei bearbeitet, kein Neustart. Siehe [Build → AI Builder](/docs/build/ai-builder) +für das vollständige Vokabular. + +> **Handcodierung in Ihrer IDE?** Führen Sie `npx skills add objectstack-ai/framework` aus, +> um Claude Code / Cursor / Copilot / Codex beizubringen, wie man +> ObjectOS-Metadaten gegen die echten Zod-Schemas verfasst. Siehe +> [Build → IDE Skills](/docs/build/ai-skills). + +### Eine App aus dem marketplace installieren + +Öffnen Sie **http://localhost:3000/_console/**, melden Sie sich an und wählen Sie eine App aus: + +| App | Was sie Ihnen bietet | +|---|---| +| Todo | Universeller Aufgaben- und Projekt-Tracker | +| Contracts | Vertragslebenszyklus mit KI-Extraktion | +| Procurement | Lieferanten, Bestellungen, 3-Wege-Abgleich | +| Compliance | SOC 2 / ISO 27001 Kontrollen + Nachweise | +| Helpdesk | KI-zentrierter Kundensupport | +| Content | Redaktionskalender + Kanal-ROI | +| HR | Verzeichnis, Organigramm, Abwesenheiten | + +Installieren → neu laden → schon ist sie da, mit ihren Objekten, Ansichten, Berechtigungen +und Beispieldaten. Kein Neustart erforderlich. + +### Häufige Flags + +```bash +os start --port 3200 # different port +os start --database postgres://... # external database +os start --auth-secret "$(openssl rand -hex 32)" # enable auth in /api/v1/auth/* +os start --home /var/lib/objectos # persistent home (production) +``` + +Siehe [Runtime Configuration](/docs/configure/runtime) für jede Option +und [Docker](/docs/deploy/docker) für den produktionsnahen Weg. + +--- + +## Pfad B — `os init` (Entwickler) + +Verwenden Sie dies, wenn Sie TypeScript schreiben, um Ihr eigenes Datenmodell, +Ihre Ansichten und Flows zu definieren. + +```bash +npx @objectstack/cli init my-app -t app --install +cd my-app +pnpm dev +``` + +Sie sehen: + +```text +✓ Project initialized! + +◆ Compile + ✓ Build complete (462ms) + Data: 1 Objects 3 Fields + +◆ Development Mode + ✓ Server is ready + + ➜ API: http://localhost:3002/ + ➜ Console: http://localhost:3002/_console/ + ➜ Account: http://localhost:3002/_account/ + ➜ Console: http://localhost:3002/_console/ +``` + +Beachten Sie, dass der Dev-Server Port **3002** verwendet, um eine Kollision mit einem +laufenden `os start` auf Port 3000 zu vermeiden. + +### Fügen Sie Ihr eigenes Objekt hinzu + +Bearbeiten Sie `src/objects/task.ts`: + +```ts +// src/objects/task.ts +import { ObjectSchema, Field } from '@objectstack/spec/data'; + +export const Task = ObjectSchema.create({ + name: 'task', + label: 'Task', + fields: { + subject: Field.text({ label: 'Subject', required: true, maxLength: 200 }), + done: Field.boolean({ label: 'Done', defaultValue: false }), + due: Field.date({ label: 'Due' }), + assignee: Field.lookup({ label: 'Assignee', reference: 'sys_user' }), + }, +}); +``` + +Speichern. Der Dev-Server kompiliert neu, und Sie haben sofort: + +- **`/api/v1/data/task`** — vollständiges CRUD mit Filtern/Sortieren/Paginieren +- **Eine „Task"-Ansicht in der Console** — Liste, Formular, Detailansicht, alles generiert +- **Berechtigungszeilen in der Console** — gewähren Sie Lese-/Schreibzugriff pro Rolle +- **Audit-Log-Einträge** — jedes Anlegen/Aktualisieren/Löschen wird erfasst + +Keine Migrationen. Keine Codegenerierung. Kein Neustart. + +### Projektaufbau + +```text +my-app/ +├── objectstack.config.ts # Stack definition (manifest + objects) +├── src/ +│ └── objects/ # Your data model — add files here +├── dist/ +│ └── objectstack.json # Compiled artifact (regenerated on save) +├── package.json +└── tsconfig.json +``` + +`dist/objectstack.json` ist das, was Sie in die Produktion ausliefern — binden Sie es in einen +laufenden ObjectOS-Container ein, und das wird zu Ihrer App. + +### Oder starten Sie von einer Vorlage + +Produktionsnahe Starter befinden sich unter +[github.com/objectstack-ai/templates](https://github.com/objectstack-ai/templates): + +```bash +git clone https://github.com/objectstack-ai/templates.git +cd templates/packages/todo +pnpm install +pnpm dev # http://localhost:4002 +``` + +Jede Vorlage umfasst weniger als 2500 LOC, ist in einer Sitzung lesbar und läuft eigenständig. + +--- + +## Was standardmäßig geladen wird + +Beide Pfade geben Ihnen diese 23 Plugins automatisch: + +> Auth, Security (RBAC + RLS + FLS), Audit, REST API, Console UI, +> Account UI, Console UI, AI Service, Queue, Jobs, Cache, Settings, +> Email, Storage, Marketplace, Metadata, ObjectQL, plus dem SQL-Treiber. + +Sie importieren oder verdrahten keines davon — sie werden aktiviert, wenn etwas +deklariert, dass es sie benötigt. + +## Nächste Schritte + +| Was nun | Lesen | +|---|---| +| In Docker ausführen (produktionsnah) | [Docker](/docs/deploy/docker) | +| Postgres statt SQLite verwenden | [Runtime Configuration](/docs/configure/runtime) | +| Google / Okta / Entra Login hinzufügen | [Authentication](/docs/configure/authentication) | +| Festlegen, wer was tun darf | [Permissions](/docs/configure/permissions) | +| Ereignisse an Slack / Zapier / Ihren Dienst senden | [Webhooks](/docs/configure/webhooks) | +| In die Produktion deployen | [Production Readiness](/docs/operate/production) | diff --git a/content/docs/quickstart.es.mdx b/content/docs/quickstart.es.mdx new file mode 100644 index 0000000..0e47892 --- /dev/null +++ b/content/docs/quickstart.es.mdx @@ -0,0 +1,233 @@ +--- +title: Inicio rápido +description: "De cero a un ObjectOS en marcha: instala una CLI, ejecuta un comando y tienes una aplicación." +--- + +# Inicio rápido + +Hay dos formas de empezar, según lo que vayas a hacer. + +| Tú eres … | Empieza aquí | +|---|---| +| Probando ObjectOS por primera vez, o ejecutándolo en producción | [Ruta A — `os start`](#path-a--os-start-operator-first-time-evaluator) | +| Creando o personalizando una aplicación con código | [Ruta B — `os init`](#path-b--os-init-developer) | + +Ambas generan un servidor en marcha con Console + Account. La +diferencia está en si generas archivos de código fuente. + +## Requisitos previos + +- **Node.js 20 o más reciente** — `node --version` +- Una terminal + +Eso es todo. Sin Docker. Sin base de datos. Sin registro de cuenta. + +--- + +## Ruta A — `os start` (operador / evaluador por primera vez) + +Instala la CLI de forma global y luego ejecútala: + +```bash +npm i -g @objectstack/cli +os start +``` + +Verás: + +```text +◆ ObjectStack +──────────────────────────────────────── +🏠 Home: ~/.objectstack +📦 Artifact: none (empty kernel — install apps via Console marketplace) +🗄️ Database: file:~/.objectstack/data/objectstack.db + + ✓ Server is ready + + ➜ API: http://localhost:3000/ + ➜ Console: http://localhost:3000/_console/ + ➜ Account: http://localhost:3000/_account/ + ➜ Console: http://localhost:3000/_console/ + + Plugins: 23 loaded +``` + +Eso es todo. Ya tienes ObjectOS en marcha. + +### Qué está en ejecución + +| URL | Qué es | +|---|---| +| http://localhost:3000/_account/register | Crea tu primera cuenta | +| http://localhost:3000/_console/ | La interfaz de administración — y el **marketplace de aplicaciones** | +| http://localhost:3000/_console/ | Usuarios, roles, registro de auditoría, ajustes | +| http://localhost:3000/health | Sonda de actividad | + +El runtime arranca en un **kernel vacío** — sin objetos, sin aplicaciones — +y expone el marketplace para que puedas instalar aplicaciones listas para usar en +segundos. + +### Crea conversando — el AI Builder + +Una vez que hayas iniciado sesión, abre el asistente de IA en Console (el icono de +destello en la esquina superior derecha) y describe lo que necesitas: + +> *"Necesito hacer seguimiento de tickets de soporte al cliente. Cada uno tiene un asunto, +> una descripción, una prioridad (baja/media/alta/urgente), un estado y un +> responsable. Añade una vista kanban agrupada por estado."* + +La IA propone un plan, tú lo apruebas y los metadatos quedan activos — +endpoints REST, vistas de Console, entradas de registro de auditoría, controles de permisos. +Sin editar archivos, sin reiniciar. Consulta [Build → AI Builder](/docs/build/ai-builder) +para conocer todo el vocabulario. + +> **¿Programando a mano en tu IDE?** Ejecuta `npx skills add objectstack-ai/framework` +> para enseñar a Claude Code / Cursor / Copilot / Codex a crear +> metadatos de ObjectOS con los esquemas reales de Zod. Consulta +> [Build → IDE Skills](/docs/build/ai-skills). + +### Instala una aplicación desde el marketplace + +Abre **http://localhost:3000/_console/**, inicia sesión y elige una aplicación: + +| Aplicación | Qué te ofrece | +|---|---| +| Todo | Gestor universal de tareas y proyectos | +| Contracts | Ciclo de vida de contratos con extracción por IA | +| Procurement | Proveedores, órdenes de compra, conciliación a 3 vías | +| Compliance | Controles de SOC 2 / ISO 27001 + evidencias | +| Helpdesk | Soporte al cliente con IA primero | +| Content | Calendario editorial + ROI por canal | +| HR | Directorio, organigrama, ausencias | + +Instala → recarga → ahí está, con sus objetos, vistas, permisos +y datos iniciales. Sin necesidad de reiniciar. + +### Opciones habituales + +```bash +os start --port 3200 # different port +os start --database postgres://... # external database +os start --auth-secret "$(openssl rand -hex 32)" # enable auth in /api/v1/auth/* +os start --home /var/lib/objectos # persistent home (production) +``` + +Consulta [Runtime Configuration](/docs/configure/runtime) para todas las opciones, +y [Docker](/docs/deploy/docker) para la ruta orientada a producción. + +--- + +## Ruta B — `os init` (desarrollador) + +Usa esto cuando escribas TypeScript para definir tu propio modelo de datos, +vistas y flujos. + +```bash +npx @objectstack/cli init my-app -t app --install +cd my-app +pnpm dev +``` + +Verás: + +```text +✓ Project initialized! + +◆ Compile + ✓ Build complete (462ms) + Data: 1 Objects 3 Fields + +◆ Development Mode + ✓ Server is ready + + ➜ API: http://localhost:3002/ + ➜ Console: http://localhost:3002/_console/ + ➜ Account: http://localhost:3002/_account/ + ➜ Console: http://localhost:3002/_console/ +``` + +Ten en cuenta que el servidor de desarrollo usa el puerto **3002** para evitar +colisionar con un `os start` en marcha en el 3000. + +### Añade tu propio objeto + +Edita `src/objects/task.ts`: + +```ts +// src/objects/task.ts +import { ObjectSchema, Field } from '@objectstack/spec/data'; + +export const Task = ObjectSchema.create({ + name: 'task', + label: 'Task', + fields: { + subject: Field.text({ label: 'Subject', required: true, maxLength: 200 }), + done: Field.boolean({ label: 'Done', defaultValue: false }), + due: Field.date({ label: 'Due' }), + assignee: Field.lookup({ label: 'Assignee', reference: 'sys_user' }), + }, +}); +``` + +Guarda. El servidor de desarrollo recompila e inmediatamente tienes: + +- **`/api/v1/data/task`** — CRUD completo con filtrado/ordenación/paginación +- **Una vista "Task" en Console** — lista, formulario, detalle, todo generado +- **Filas de permisos en Console** — concede lectura/escritura por rol +- **Entradas de registro de auditoría** — cada creación/actualización/eliminación queda registrada + +Sin migraciones. Sin generación de código. Sin reinicios. + +### Estructura del proyecto + +```text +my-app/ +├── objectstack.config.ts # Stack definition (manifest + objects) +├── src/ +│ └── objects/ # Your data model — add files here +├── dist/ +│ └── objectstack.json # Compiled artifact (regenerated on save) +├── package.json +└── tsconfig.json +``` + +`dist/objectstack.json` es lo que envías a producción — móntalo en un +contenedor de ObjectOS en marcha y eso se convierte en tu aplicación. + +### O empieza desde una plantilla + +Las plantillas iniciales orientadas a producción están en +[github.com/objectstack-ai/templates](https://github.com/objectstack-ai/templates): + +```bash +git clone https://github.com/objectstack-ai/templates.git +cd templates/packages/todo +pnpm install +pnpm dev # http://localhost:4002 +``` + +Cada plantilla tiene menos de 2500 líneas de código, se lee de una sentada y se ejecuta de forma independiente. + +--- + +## Qué viene cargado de fábrica + +Cualquiera de las dos rutas te ofrece estos 23 plugins automáticamente: + +> Auth, Security (RBAC + RLS + FLS), Audit, REST API, Console UI, +> Account UI, Console UI, AI Service, Queue, Jobs, Cache, Settings, +> Email, Storage, Marketplace, Metadata, ObjectQL, además del controlador SQL. + +No importas ni conectas ninguno de ellos — se activan cuando algo +declara que los necesita. + +## Próximos pasos + +| Qué hacer ahora | Lee | +|---|---| +| Ejecutarlo en Docker (orientado a producción) | [Docker](/docs/deploy/docker) | +| Usar Postgres en lugar de SQLite | [Runtime Configuration](/docs/configure/runtime) | +| Añadir inicio de sesión con Google / Okta / Entra | [Authentication](/docs/configure/authentication) | +| Restringir quién puede hacer qué | [Permissions](/docs/configure/permissions) | +| Enviar eventos a Slack / Zapier / tu servicio | [Webhooks](/docs/configure/webhooks) | +| Desplegar en producción | [Production Readiness](/docs/operate/production) | diff --git a/content/docs/quickstart.fr.mdx b/content/docs/quickstart.fr.mdx new file mode 100644 index 0000000..3c211d2 --- /dev/null +++ b/content/docs/quickstart.fr.mdx @@ -0,0 +1,234 @@ +--- +title: Démarrage rapide +description: De zéro à un ObjectOS opérationnel — installez une CLI, exécutez une commande, vous avez une application. +--- + +# Démarrage rapide + +Il existe deux façons de commencer, selon ce que vous faites. + +| Vous êtes … | Commencez ici | +|---|---| +| Vous essayez ObjectOS pour la première fois, ou vous l'exécutez en production | [Parcours A — `os start`](#path-a--os-start-operator-first-time-evaluator) | +| Vous créez ou personnalisez une application dans le code | [Parcours B — `os init`](#path-b--os-init-developer) | + +Les deux produisent un serveur opérationnel avec Console + Account. La +différence réside dans le fait que vous générez ou non des fichiers source. + +## Prérequis + +- **Node.js 20 ou plus récent** — `node --version` +- Un terminal + +C'est tout. Pas de Docker. Pas de base de données. Pas d'inscription de compte. + +--- + +## Parcours A — `os start` (opérateur / premier évaluateur) + +Installez la CLI globalement, puis exécutez-la : + +```bash +npm i -g @objectstack/cli +os start +``` + +Vous verrez : + +```text +◆ ObjectStack +──────────────────────────────────────── +🏠 Home: ~/.objectstack +📦 Artifact: none (empty kernel — install apps via Console marketplace) +🗄️ Database: file:~/.objectstack/data/objectstack.db + + ✓ Server is ready + + ➜ API: http://localhost:3000/ + ➜ Console: http://localhost:3000/_console/ + ➜ Account: http://localhost:3000/_account/ + ➜ Console: http://localhost:3000/_console/ + + Plugins: 23 loaded +``` + +C'est tout. ObjectOS est en cours d'exécution. + +### Ce qui est en cours d'exécution + +| URL | Ce que c'est | +|---|---| +| http://localhost:3000/_account/register | Créez votre premier compte | +| http://localhost:3000/_console/ | L'interface d'administration — et le **marketplace d'applications** | +| http://localhost:3000/_console/ | Utilisateurs, rôles, journal d'audit, paramètres | +| http://localhost:3000/health | Sonde de disponibilité | + +Le runtime démarre sur un **kernel vide** — aucun objet, aucune application — +et expose le marketplace pour que vous puissiez installer des applications +prêtes à l'emploi en quelques secondes. + +### Construire par conversation — l'AI Builder + +Une fois connecté, ouvrez l'assistant IA dans Console (icône étincelle en +haut à droite) et décrivez ce dont vous avez besoin : + +> *« J'ai besoin de suivre les tickets de support client. Chacun a un sujet, +> une description, une priorité (basse/moyenne/haute/urgente), un statut et +> un assigné. Ajoutez une vue kanban regroupée par statut. »* + +L'IA propose un plan, vous l'approuvez, et les métadonnées sont actives — +points de terminaison REST, vues Console, entrées du journal d'audit, contrôles +de permissions. Aucun fichier modifié, aucun redémarrage. Consultez +[Build → AI Builder](/docs/build/ai-builder) pour le vocabulaire complet. + +> **Vous codez à la main dans votre IDE ?** Exécutez `npx skills add objectstack-ai/framework` +> pour apprendre à Claude Code / Cursor / Copilot / Codex comment rédiger +> des métadonnées ObjectOS conformes aux véritables schémas Zod. Consultez +> [Build → IDE Skills](/docs/build/ai-skills). + +### Installer une application depuis le marketplace + +Ouvrez **http://localhost:3000/_console/**, connectez-vous et choisissez une application : + +| Application | Ce qu'elle vous apporte | +|---|---| +| Todo | Suivi universel des tâches et des projets | +| Contracts | Cycle de vie des contrats avec extraction par IA | +| Procurement | Fournisseurs, bons de commande, rapprochement à 3 voies | +| Compliance | Contrôles SOC 2 / ISO 27001 + preuves | +| Helpdesk | Support client centré sur l'IA | +| Content | Calendrier éditorial + ROI par canal | +| HR | Annuaire, organigramme, congés | + +Installer → recharger → c'est là, avec ses objets, ses vues, ses permissions +et ses données initiales. Aucun redémarrage requis. + +### Options courantes + +```bash +os start --port 3200 # different port +os start --database postgres://... # external database +os start --auth-secret "$(openssl rand -hex 32)" # enable auth in /api/v1/auth/* +os start --home /var/lib/objectos # persistent home (production) +``` + +Consultez [Runtime Configuration](/docs/configure/runtime) pour toutes les options, +et [Docker](/docs/deploy/docker) pour le parcours orienté production. + +--- + +## Parcours B — `os init` (développeur) + +Utilisez ceci lorsque vous écrivez du TypeScript pour définir votre propre +modèle de données, vos vues et vos flux. + +```bash +npx @objectstack/cli init my-app -t app --install +cd my-app +pnpm dev +``` + +Vous verrez : + +```text +✓ Project initialized! + +◆ Compile + ✓ Build complete (462ms) + Data: 1 Objects 3 Fields + +◆ Development Mode + ✓ Server is ready + + ➜ API: http://localhost:3002/ + ➜ Console: http://localhost:3002/_console/ + ➜ Account: http://localhost:3002/_account/ + ➜ Console: http://localhost:3002/_console/ +``` + +Notez que le serveur de développement utilise le port **3002** pour éviter +tout conflit avec un `os start` en cours d'exécution sur le port 3000. + +### Ajouter votre propre objet + +Modifiez `src/objects/task.ts` : + +```ts +// src/objects/task.ts +import { ObjectSchema, Field } from '@objectstack/spec/data'; + +export const Task = ObjectSchema.create({ + name: 'task', + label: 'Task', + fields: { + subject: Field.text({ label: 'Subject', required: true, maxLength: 200 }), + done: Field.boolean({ label: 'Done', defaultValue: false }), + due: Field.date({ label: 'Due' }), + assignee: Field.lookup({ label: 'Assignee', reference: 'sys_user' }), + }, +}); +``` + +Enregistrez. Le serveur de développement recompile et vous disposez immédiatement de : + +- **`/api/v1/data/task`** — CRUD complet avec filtrage/tri/pagination +- **Une vue « Task » dans Console** — liste, formulaire, détail, tout généré +- **Des lignes de permissions dans Console** — accordez lecture/écriture par rôle +- **Des entrées de journal d'audit** — chaque création/mise à jour/suppression enregistrée + +Aucune migration. Aucune génération de code. Aucun redémarrage. + +### Structure du projet + +```text +my-app/ +├── objectstack.config.ts # Stack definition (manifest + objects) +├── src/ +│ └── objects/ # Your data model — add files here +├── dist/ +│ └── objectstack.json # Compiled artifact (regenerated on save) +├── package.json +└── tsconfig.json +``` + +`dist/objectstack.json` est ce que vous livrez en production — montez-le sur +un conteneur ObjectOS en cours d'exécution et cela devient votre application. + +### Ou partez d'un modèle + +Des modèles de démarrage orientés production sont disponibles sur +[github.com/objectstack-ai/templates](https://github.com/objectstack-ai/templates) : + +```bash +git clone https://github.com/objectstack-ai/templates.git +cd templates/packages/todo +pnpm install +pnpm dev # http://localhost:4002 +``` + +Chaque modèle fait moins de 2500 lignes de code, se lit en une seule séance +et s'exécute de manière autonome. + +--- + +## Ce qui est chargé par défaut + +Les deux parcours vous fournissent automatiquement ces 23 plugins : + +> Auth, Security (RBAC + RLS + FLS), Audit, REST API, Console UI, +> Account UI, Console UI, AI Service, Queue, Jobs, Cache, Settings, +> Email, Storage, Marketplace, Metadata, ObjectQL, ainsi que le pilote SQL. + +Vous n'en importez ni n'en câblez aucun — ils s'activent lorsqu'un élément +déclare en avoir besoin. + +## Étapes suivantes + +| Et maintenant | À lire | +|---|---| +| L'exécuter dans Docker (orienté production) | [Docker](/docs/deploy/docker) | +| Utiliser Postgres au lieu de SQLite | [Runtime Configuration](/docs/configure/runtime) | +| Ajouter la connexion Google / Okta / Entra | [Authentication](/docs/configure/authentication) | +| Verrouiller qui peut faire quoi | [Permissions](/docs/configure/permissions) | +| Envoyer des événements vers Slack / Zapier / votre service | [Webhooks](/docs/configure/webhooks) | +| Déployer en production | [Production Readiness](/docs/operate/production) | diff --git a/content/docs/quickstart.ja.mdx b/content/docs/quickstart.ja.mdx new file mode 100644 index 0000000..97449e9 --- /dev/null +++ b/content/docs/quickstart.ja.mdx @@ -0,0 +1,212 @@ +--- +title: クイックスタート +description: ゼロから動作する ObjectOS まで — CLI を 1 つインストールし、コマンドを 1 つ実行すれば、アプリの完成です。 +--- + +# クイックスタート + +何をしたいかに応じて、2 つの始め方があります。 + +| あなたは … | ここから始める | +|---|---| +| ObjectOS を初めて試す、または本番環境で実行する | [パス A — `os start`](#path-a--os-start-operator-first-time-evaluator) | +| コードでアプリを構築・カスタマイズする | [パス B — `os init`](#path-b--os-init-developer) | + +どちらも Console + Account を備えた動作するサーバーを生成します。違いは、ソースファイルをスキャフォールドするかどうかです。 + +## 前提条件 + +- **Node.js 20 以降** — `node --version` +- ターミナル + +これだけです。Docker も不要。データベースも不要。アカウント登録も不要です。 + +--- + +## パス A — `os start`(オペレーター / 初回評価者) + +CLI をグローバルにインストールして実行します。 + +```bash +npm i -g @objectstack/cli +os start +``` + +次のように表示されます。 + +```text +◆ ObjectStack +──────────────────────────────────────── +🏠 Home: ~/.objectstack +📦 Artifact: none (empty kernel — install apps via Console marketplace) +🗄️ Database: file:~/.objectstack/data/objectstack.db + + ✓ Server is ready + + ➜ API: http://localhost:3000/ + ➜ Console: http://localhost:3000/_console/ + ➜ Account: http://localhost:3000/_account/ + ➜ Console: http://localhost:3000/_console/ + + Plugins: 23 loaded +``` + +これだけです。ObjectOS が動作しています。 + +### 動作しているもの + +| URL | 内容 | +|---|---| +| http://localhost:3000/_account/register | 最初のアカウントを作成 | +| http://localhost:3000/_console/ | 管理 UI — そして **アプリ marketplace** | +| http://localhost:3000/_console/ | ユーザー、ロール、監査ログ、設定 | +| http://localhost:3000/health | 死活監視プローブ | + +ランタイムは **空のカーネル** で起動します — オブジェクトもアプリもありません — そして marketplace を公開するので、既製のアプリを数秒でインストールできます。 + +### チャットで構築する — AI Builder + +サインインしたら、Console の AI アシスタント(右上のキラキラアイコン)を開き、必要なものを記述します。 + +> *「カスタマーサポートのチケットを追跡したい。各チケットには件名、説明、優先度(低 / 中 / 高 / 緊急)、ステータス、担当者がある。ステータスでグループ化したかんばんビューを追加して。」* + +AI がプランを提案し、あなたが承認すると、メタデータが即座に有効になります — REST エンドポイント、Console ビュー、監査ログのエントリ、権限ゲート。ファイルの編集も再起動も不要です。完全な語彙については [Build → AI Builder](/docs/build/ai-builder) を参照してください。 + +> **IDE で手書きコーディングしますか?** `npx skills add objectstack-ai/framework` を実行すると、Claude Code / Cursor / Copilot / Codex に、本物の Zod スキーマに対して ObjectOS メタデータを記述する方法を教えられます。[Build → IDE Skills](/docs/build/ai-skills) を参照してください。 + +### marketplace からアプリをインストールする + +**http://localhost:3000/_console/** を開き、サインインしてアプリを選びます。 + +| アプリ | 提供される機能 | +|---|---| +| Todo | 汎用的なタスク & プロジェクトトラッカー | +| Contracts | AI 抽出付きの契約ライフサイクル | +| Procurement | ベンダー、発注書、3-way マッチ | +| Compliance | SOC 2 / ISO 27001 のコントロール + エビデンス | +| Helpdesk | AI ファーストなカスタマーサポート | +| Content | 編集カレンダー + チャネル ROI | +| HR | ディレクトリ、組織図、休暇管理 | + +インストール → 再読み込み → オブジェクト、ビュー、権限、シードデータとともにそこに表示されます。再起動は不要です。 + +### よく使うフラグ + +```bash +os start --port 3200 # different port +os start --database postgres://... # external database +os start --auth-secret "$(openssl rand -hex 32)" # enable auth in /api/v1/auth/* +os start --home /var/lib/objectos # persistent home (production) +``` + +すべてのオプションについては [Runtime Configuration](/docs/configure/runtime) を、本番環境向けのパスについては [Docker](/docs/deploy/docker) を参照してください。 + +--- + +## パス B — `os init`(開発者) + +TypeScript を書いて独自のデータモデル、ビュー、フローを定義する場合は、こちらを使います。 + +```bash +npx @objectstack/cli init my-app -t app --install +cd my-app +pnpm dev +``` + +次のように表示されます。 + +```text +✓ Project initialized! + +◆ Compile + ✓ Build complete (462ms) + Data: 1 Objects 3 Fields + +◆ Development Mode + ✓ Server is ready + + ➜ API: http://localhost:3002/ + ➜ Console: http://localhost:3002/_console/ + ➜ Account: http://localhost:3002/_account/ + ➜ Console: http://localhost:3002/_console/ +``` + +dev サーバーは、3000 で実行中の `os start` と衝突しないように、ポート **3002** を使用する点に注意してください。 + +### 独自のオブジェクトを追加する + +`src/objects/task.ts` を編集します。 + +```ts +// src/objects/task.ts +import { ObjectSchema, Field } from '@objectstack/spec/data'; + +export const Task = ObjectSchema.create({ + name: 'task', + label: 'Task', + fields: { + subject: Field.text({ label: 'Subject', required: true, maxLength: 200 }), + done: Field.boolean({ label: 'Done', defaultValue: false }), + due: Field.date({ label: 'Due' }), + assignee: Field.lookup({ label: 'Assignee', reference: 'sys_user' }), + }, +}); +``` + +保存します。dev サーバーが再コンパイルし、すぐに次のものが手に入ります。 + +- **`/api/v1/data/task`** — フィルター / ソート / ページネーション付きの完全な CRUD +- **Console の「Task」ビュー** — リスト、フォーム、詳細、すべて自動生成 +- **Console の権限行** — ロールごとに読み取り / 書き込みを付与 +- **監査ログのエントリ** — すべての作成 / 更新 / 削除を記録 + +マイグレーション不要。コード生成不要。再起動不要です。 + +### プロジェクト構成 + +```text +my-app/ +├── objectstack.config.ts # Stack definition (manifest + objects) +├── src/ +│ └── objects/ # Your data model — add files here +├── dist/ +│ └── objectstack.json # Compiled artifact (regenerated on save) +├── package.json +└── tsconfig.json +``` + +`dist/objectstack.json` が本番環境に出荷するものです — 動作中の ObjectOS コンテナにマウントすれば、それがあなたのアプリになります。 + +### またはテンプレートから始める + +本番環境向けのスターターは [github.com/objectstack-ai/templates](https://github.com/objectstack-ai/templates) にあります。 + +```bash +git clone https://github.com/objectstack-ai/templates.git +cd templates/packages/todo +pnpm install +pnpm dev # http://localhost:4002 +``` + +各テンプレートは 2500 行未満で、一度に読み切れる量で、単独で動作します。 + +--- + +## 標準で読み込まれるもの + +どちらのパスでも、これら 23 のプラグインが自動的に手に入ります。 + +> Auth、Security(RBAC + RLS + FLS)、Audit、REST API、Console UI、Account UI、Console UI、AI Service、Queue、Jobs、Cache、Settings、Email、Storage、Marketplace、Metadata、ObjectQL、そして SQL ドライバー。 + +これらをインポートしたり配線したりする必要はありません — 何かがそれらを必要とすると宣言したときに有効になります。 + +## 次のステップ + +| 次にやること | 読む | +|---|---| +| Docker で実行する(本番環境向け) | [Docker](/docs/deploy/docker) | +| SQLite の代わりに Postgres を使う | [Runtime Configuration](/docs/configure/runtime) | +| Google / Okta / Entra ログインを追加する | [Authentication](/docs/configure/authentication) | +| 誰が何をできるかを制限する | [Permissions](/docs/configure/permissions) | +| Slack / Zapier / 自社サービスにイベントを送信する | [Webhooks](/docs/configure/webhooks) | +| 本番環境にデプロイする | [Production Readiness](/docs/operate/production) | diff --git a/content/docs/quickstart.cn.mdx b/content/docs/quickstart.zh-Hans.mdx similarity index 100% rename from content/docs/quickstart.cn.mdx rename to content/docs/quickstart.zh-Hans.mdx diff --git a/content/docs/reference/cel.de.mdx b/content/docs/reference/cel.de.mdx new file mode 100644 index 0000000..829cb96 --- /dev/null +++ b/content/docs/reference/cel.de.mdx @@ -0,0 +1,167 @@ +--- +title: CEL-Ausdrücke +description: Die Ausdruckssprache, die für Formeln, Prädikate, Zeitpläne und vorlagenbasierte Zeichenketten verwendet wird — bereitgestellt über fünf getaggte Templates. +--- + +# CEL-Ausdrücke + +ObjectOS verwendet [CEL](https://github.com/google/cel-spec) (Common +Expression Language) überall dort, wo Sie einen kleinen, sicheren, +sandboxed Ausdruck benötigen: Formelfelder, Validierungsregeln, +Sichtbarkeitsprädikate, Freigabebedingungen, Flow-Guards, Zeitpläne und +vorlagenbasierte Zeichenketten. + +Das Erstellen erfolgt über **fünf getaggte Templates**, die aus +`@objectstack/spec` importiert werden. Sie alle erzeugen ein kleines +JSON-Objekt, das die Laufzeit parst: + +```ts +{ dialect: 'cel' | 'template' | 'cron', source: string } +``` + +Schema-Quelle: +[`packages/spec/src/shared/expression.zod.ts`](https://github.com/objectstack-ai/framework/blob/main/packages/spec/src/shared/expression.zod.ts). + +## Die fünf getaggten Templates + +| Template | Dialekt | Verwendung für | Beispiel | +|:--|:--|:--|:--| +| `` F`...` `` | `cel` | **Formelfelder** — abgeleitete Werte, die zusammen mit dem Datensatz gespeichert werden | `` F`record.amount * 0.1` `` | +| `` P`...` `` | `cel` | **Prädikate** — Booleans für Validierung / Freigabe / Sichtbarkeit / Bedingungen | `` P`record.status == "open"` `` | +| `` cel`...` `` | `cel` | **Allgemeines CEL** — wenn weder F noch P passt (z. B. ein Parameterwert) | `` cel`now() + duration("P30D")` `` | +| `` tmpl`...` `` | `template` | **Zeichenketten-Templates** mit `{{var}}`-Interpolation | `` tmpl`Order from {{record.customer.name}}` `` | +| `` cron`...` `` | `cron` | **Zeitpläne** — standardmäßige Cron-Syntax mit 5 Feldern | `` cron`0 9 * * 1-5` `` | + +Zur Auswertungszeit gibt es keinen funktionalen Unterschied zwischen `F`, +`P` und `cel` — sie alle führen CEL aus. Die Aufteilung existiert, damit +Schemas (und KI-Agenten) wissen, welche Rolle der Ausdruck spielt, und +damit der Editor eine Typprüfung durchführen kann (Formeln müssen einen +Wert zurückgeben, Prädikate müssen einen Boolean zurückgeben). + +### Import + +```ts +import { F, P, cel, tmpl, cron } from '@objectstack/spec' +``` + +## Wo jedes verwendet wird + +| Feld einer Spec | Tag | Beispielort | +|:--|:--|:--| +| `Field.expression` (Formeltyp) | `F` | `*.object.ts` Formelfelder | +| `Field.conditionalRequired` | `P` | Objektfelder | +| `Validation.predicate` | `P` | Objektvalidierungen | +| `SharingRule.condition` | `P` | Freigaberegeln | +| `View.conditionalFormatting[].condition` | `P` | Ansichten | +| `Flow.step.when` / `Flow.transition.when` | `P` | Flows | +| `Action.guard` | `P` | Aktionen | +| Benachrichtigungsbetreffe / Nachrichtentexte | `tmpl` | Benachrichtigungen | +| `Schedule.cron` | `cron` | geplante Flows / Berichte | +| Beliebiger Wertparameter | `cel` | Flow-Schritt-Eingaben | + +## Variablen-Geltungsbereich + +CEL-Ausdrücke werden in einem Kontext mit diesen Top-Level-Variablen +ausgewertet: + +| Variable | Verfügbar wenn | Inhalt | +|:--|:--|:--| +| `record` | fast immer | Der aktuell ausgewertete Datensatz | +| `previous` | bei Update-Hooks / Änderungserkennung | Der Zustand des Datensatzes vor der Änderung (oder `null`) | +| `input` | Aktionen, Flow-Schritte | Die vom Benutzer bereitgestellte Eingabe-Payload | +| `os.user` | immer | `{ id, roles: string[], permissions: string[] }` | +| `os.org` | immer | Organisations- / Mandantenkontext | +| `os.env` | immer | Für Ausdrücke verfügbar gemachte Umgebungsvariablen | + +> Die veralteten Variablen `OLD` / `NEW` wurden in M9.5 entfernt. +> Verwenden Sie `previous` und `record`. + +## Standardbibliothek + +Registriert in +[`packages/formula/src/stdlib.ts`](https://github.com/objectstack-ai/framework/blob/main/packages/formula/src/stdlib.ts). +Die am häufigsten verwendeten Built-ins: + +### Zeit + +| Funktion | Gibt zurück | Hinweise | +|:--|:--|:--| +| `now()` | `Timestamp` | An den Auswertungskontext gebunden — innerhalb einer Abfrage stabil | +| `today()` | `Timestamp` | Beginn des UTC-Tages | +| `daysFromNow(int)` | `Timestamp` | Zukünftiges Datum | +| `daysAgo(int)` | `Timestamp` | Vergangenes Datum | + +CEL enthält außerdem die nativen `timestamp(...)`, `duration(...)`, +`date.getDayOfWeek()` usw. — siehe die +[CEL-Spezifikation](https://github.com/google/cel-spec/blob/master/doc/langdef.md#standard-definitions). + +### Hilfsfunktionen + +| Funktion | Zweck | +|:--|:--| +| `isBlank(x)` | `true` wenn `null`, `undefined`, `""` oder leere Liste | +| `coalesce(a, b)` | Erster Nicht-Null-Wert | +| `trim(s)` | Whitespace entfernen | +| `joinNonEmpty(list, sep)` | Nicht-leere Einträge verketten | + +Native CEL-String-Helfer (`.contains(...)`, `.startsWith(...)`, +`.matches(...)`, `.size()`) sind immer verfügbar. + +## Beispiele + +**Formelfeld** — Positionssumme: + +```ts +{ name: 'subtotal', type: 'formula', expression: F`record.quantity * record.unit_price` } +``` + +**Validierung** — Abschlussdatum muss nach heute liegen: + +```ts +{ message: 'Close date must be in the future', predicate: P`record.close_date > today()` } +``` + +**Sichtbarkeit** — Feld nur für Manager anzeigen: + +```ts +{ visibleIf: P`'manager' in os.user.roles` } +``` + +**Flow-Guard** — Schritt überspringen, wenn der Betrag klein ist: + +```ts +{ when: P`record.amount >= 1000` } +``` + +**Zeitplan** — wochentags 9 Uhr: + +```ts +{ schedule: cron`0 9 * * 1-5` } +``` + +**Template** — Benachrichtigungsbetreff: + +```ts +{ subject: tmpl`[{{record.priority}}] {{record.subject}}` } +``` + +## Fehler + +Ausdrücke werden zur Ladezeit kompiliert. Fehler erscheinen als +`VALIDATION_ERROR` mit der Quellposition: + +```json +{ "code": "VALIDATION_ERROR", "message": "CEL: unknown field 'amout' on Record", "details": { "field": "subtotal", "expression": "record.amout * 0.1" } } +``` + +Eine fehlgeschlagene Auswertung zur Laufzeit wird für Formelfelder als +`null` und für Prädikate als `false` behandelt, zusätzlich zu einem +Eintrag im Audit-Log. + +## Siehe auch + +- [Feldtypen](./field-types) — Formel- und bedingt erforderliche Felder +- [Build → Datenmodell](/docs/build/data-model) — Validierungen und Prädikate +- [Build → Flows](/docs/build/flows) — Guards und Zeitpläne +- [`@objectstack/spec/shared/expression.zod.ts`](https://github.com/objectstack-ai/framework/blob/main/packages/spec/src/shared/expression.zod.ts) — Schema +- [`@objectstack/formula/stdlib.ts`](https://github.com/objectstack-ai/framework/blob/main/packages/formula/src/stdlib.ts) — Built-ins diff --git a/content/docs/reference/cel.es.mdx b/content/docs/reference/cel.es.mdx new file mode 100644 index 0000000..3c0c7fc --- /dev/null +++ b/content/docs/reference/cel.es.mdx @@ -0,0 +1,166 @@ +--- +title: Expresiones CEL +description: El lenguaje de expresiones usado para fórmulas, predicados, programaciones y cadenas con plantilla — expuesto mediante cinco plantillas etiquetadas. +--- + +# Expresiones CEL + +ObjectOS usa [CEL](https://github.com/google/cel-spec) (Common +Expression Language) para cada lugar donde necesitas una expresión +pequeña, segura y aislada: campos de fórmula, reglas de validación, +predicados de visibilidad, condiciones de compartición, guardas de flujo, +programaciones y cadenas con plantilla. + +La autoría se realiza a través de **cinco plantillas etiquetadas** +importadas desde `@objectstack/spec`. Todas producen un pequeño objeto JSON +que el runtime analiza: + +```ts +{ dialect: 'cel' | 'template' | 'cron', source: string } +``` + +Fuente del esquema: +[`packages/spec/src/shared/expression.zod.ts`](https://github.com/objectstack-ai/framework/blob/main/packages/spec/src/shared/expression.zod.ts). + +## Las cinco plantillas etiquetadas + +| Plantilla | Dialecto | Úsala para | Ejemplo | +|:--|:--|:--|:--| +| `` F`...` `` | `cel` | **Campos de fórmula** — valores derivados almacenados junto al registro | `` F`record.amount * 0.1` `` | +| `` P`...` `` | `cel` | **Predicados** — booleanos para validación / compartición / visibilidad / condiciones | `` P`record.status == "open"` `` | +| `` cel`...` `` | `cel` | **CEL general** — cuando ni F ni P encajan (p. ej. el valor de un parámetro) | `` cel`now() + duration("P30D")` `` | +| `` tmpl`...` `` | `template` | **Plantillas de cadenas** con interpolación `{{var}}` | `` tmpl`Order from {{record.customer.name}}` `` | +| `` cron`...` `` | `cron` | **Programaciones** — sintaxis cron estándar de 5 campos | `` cron`0 9 * * 1-5` `` | + +No hay diferencia funcional entre `F`, `P` y `cel` en el momento de la +evaluación — todas ejecutan CEL. La división existe para que los esquemas +(y los agentes de IA) sepan qué rol desempeña la expresión y para que el +editor pueda comprobar tipos (las fórmulas deben devolver un valor, los +predicados deben devolver un bool). + +### Importación + +```ts +import { F, P, cel, tmpl, cron } from '@objectstack/spec' +``` + +## Dónde se usa cada una + +| Campo en una spec | Etiqueta | Ubicación de ejemplo | +|:--|:--|:--| +| `Field.expression` (tipo fórmula) | `F` | campos de fórmula en `*.object.ts` | +| `Field.conditionalRequired` | `P` | campos de objeto | +| `Validation.predicate` | `P` | validaciones de objeto | +| `SharingRule.condition` | `P` | reglas de compartición | +| `View.conditionalFormatting[].condition` | `P` | vistas | +| `Flow.step.when` / `Flow.transition.when` | `P` | flujos | +| `Action.guard` | `P` | acciones | +| Asuntos de notificaciones / cuerpos de mensaje | `tmpl` | notificaciones | +| `Schedule.cron` | `cron` | flujos / informes programados | +| Cualquier parámetro de valor | `cel` | entradas de pasos de flujo | + +## Ámbito de variables + +Las expresiones CEL se evalúan en un contexto con estas variables de nivel superior: + +| Variable | Disponible cuando | Contenido | +|:--|:--|:--| +| `record` | casi siempre | El registro actual que se está evaluando | +| `previous` | en hooks de actualización / detección de cambios | El estado del registro previo al cambio (o `null`) | +| `input` | acciones, pasos de flujo | La carga útil de entrada proporcionada por el usuario | +| `os.user` | siempre | `{ id, roles: string[], permissions: string[] }` | +| `os.org` | siempre | Contexto de organización / tenant | +| `os.env` | siempre | Variables de entorno expuestas a las expresiones | + +> Las variables heredadas `OLD` / `NEW` se eliminaron en M9.5. Usa `previous` +> y `record`. + +## Biblioteca estándar + +Registrada en +[`packages/formula/src/stdlib.ts`](https://github.com/objectstack-ai/framework/blob/main/packages/formula/src/stdlib.ts). +Las funciones integradas más usadas: + +### Tiempo + +| Función | Devuelve | Notas | +|:--|:--|:--| +| `now()` | `Timestamp` | Fijada al contexto de evaluación — estable dentro de una consulta | +| `today()` | `Timestamp` | Inicio del día UTC | +| `daysFromNow(int)` | `Timestamp` | Fecha futura | +| `daysAgo(int)` | `Timestamp` | Fecha pasada | + +CEL también incluye los nativos `timestamp(...)`, `duration(...)`, +`date.getDayOfWeek()`, etc. — consulta la +[especificación de CEL](https://github.com/google/cel-spec/blob/master/doc/langdef.md#standard-definitions). + +### Utilidad + +| Función | Propósito | +|:--|:--| +| `isBlank(x)` | `true` si es `null`, `undefined`, `""` o una lista vacía | +| `coalesce(a, b)` | Primer valor no nulo | +| `trim(s)` | Elimina espacios en blanco | +| `joinNonEmpty(list, sep)` | Concatena las entradas no vacías | + +Los ayudantes de cadenas nativos de CEL (`.contains(...)`, `.startsWith(...)`, +`.matches(...)`, `.size()`) siempre están disponibles. + +## Ejemplos + +**Campo de fórmula** — total de línea de artículo: + +```ts +{ name: 'subtotal', type: 'formula', expression: F`record.quantity * record.unit_price` } +``` + +**Validación** — la fecha de cierre debe ser posterior a hoy: + +```ts +{ message: 'Close date must be in the future', predicate: P`record.close_date > today()` } +``` + +**Visibilidad** — mostrar el campo solo a los gerentes: + +```ts +{ visibleIf: P`'manager' in os.user.roles` } +``` + +**Guarda de flujo** — omitir el paso cuando el importe es pequeño: + +```ts +{ when: P`record.amount >= 1000` } +``` + +**Programación** — días laborables a las 9 a. m.: + +```ts +{ schedule: cron`0 9 * * 1-5` } +``` + +**Plantilla** — asunto de notificación: + +```ts +{ subject: tmpl`[{{record.priority}}] {{record.subject}}` } +``` + +## Errores + +Las expresiones se compilan en el momento de la carga. Los fallos aparecen como +`VALIDATION_ERROR` con la ubicación en la fuente: + +```json +{ "code": "VALIDATION_ERROR", "message": "CEL: unknown field 'amout' on Record", "details": { "field": "subtotal", "expression": "record.amout * 0.1" } } +``` + +Una evaluación fallida en tiempo de ejecución se trata como `null` para los +campos de fórmula y como `false` para los predicados, además de generar una +entrada en el registro de auditoría. + +## Véase también + +- [Tipos de campo](./field-types) — campos de fórmula y de obligatoriedad condicional +- [Build → Modelo de datos](/docs/build/data-model) — validaciones y predicados +- [Build → Flujos](/docs/build/flows) — guardas y programaciones +- [`@objectstack/spec/shared/expression.zod.ts`](https://github.com/objectstack-ai/framework/blob/main/packages/spec/src/shared/expression.zod.ts) — esquema +- [`@objectstack/formula/stdlib.ts`](https://github.com/objectstack-ai/framework/blob/main/packages/formula/src/stdlib.ts) — funciones integradas diff --git a/content/docs/reference/cel.fr.mdx b/content/docs/reference/cel.fr.mdx new file mode 100644 index 0000000..9ec1d08 --- /dev/null +++ b/content/docs/reference/cel.fr.mdx @@ -0,0 +1,169 @@ +--- +title: Expressions CEL +description: Le langage d'expression utilisé pour les formules, les prédicats, les planifications et les chaînes à modèle — exposé via cinq tagged templates. +--- + +# Expressions CEL + +ObjectOS utilise [CEL](https://github.com/google/cel-spec) (Common +Expression Language) partout où vous avez besoin d'une expression +petite, sûre et isolée : champs de formule, règles de validation, +prédicats de visibilité, conditions de partage, gardes de flux, +planifications et chaînes à modèle. + +La rédaction se fait via **cinq tagged templates** importés depuis +`@objectstack/spec`. Ils produisent tous un petit objet JSON que le +runtime analyse : + +```ts +{ dialect: 'cel' | 'template' | 'cron', source: string } +``` + +Source du schéma : +[`packages/spec/src/shared/expression.zod.ts`](https://github.com/objectstack-ai/framework/blob/main/packages/spec/src/shared/expression.zod.ts). + +## Les cinq tagged templates + +| Template | Dialecte | À utiliser pour | Exemple | +|:--|:--|:--|:--| +| `` F`...` `` | `cel` | **Champs de formule** — valeurs dérivées stockées avec l'enregistrement | `` F`record.amount * 0.1` `` | +| `` P`...` `` | `cel` | **Prédicats** — booléens pour la validation / le partage / la visibilité / les conditions | `` P`record.status == "open"` `` | +| `` cel`...` `` | `cel` | **CEL générique** — quand ni F ni P ne convient (par ex. une valeur de paramètre) | `` cel`now() + duration("P30D")` `` | +| `` tmpl`...` `` | `template` | **Chaînes à modèle** avec interpolation `{{var}}` | `` tmpl`Order from {{record.customer.name}}` `` | +| `` cron`...` `` | `cron` | **Planifications** — syntaxe cron standard à 5 champs | `` cron`0 9 * * 1-5` `` | + +Il n'y a aucune différence fonctionnelle entre `F`, `P` et `cel` au +moment de l'évaluation — ils exécutent tous CEL. La distinction existe +pour que les schémas (et les agents IA) sachent quel rôle joue +l'expression et pour que l'éditeur puisse vérifier les types (les +formules doivent renvoyer une valeur, les prédicats doivent renvoyer un +booléen). + +### Import + +```ts +import { F, P, cel, tmpl, cron } from '@objectstack/spec' +``` + +## Où chacun est utilisé + +| Champ sur une spec | Tag | Emplacement d'exemple | +|:--|:--|:--| +| `Field.expression` (type formule) | `F` | champs de formule `*.object.ts` | +| `Field.conditionalRequired` | `P` | champs d'objet | +| `Validation.predicate` | `P` | validations d'objet | +| `SharingRule.condition` | `P` | règles de partage | +| `View.conditionalFormatting[].condition` | `P` | vues | +| `Flow.step.when` / `Flow.transition.when` | `P` | flux | +| `Action.guard` | `P` | actions | +| Sujets de notification / corps de message | `tmpl` | notifications | +| `Schedule.cron` | `cron` | flux / rapports planifiés | +| Toute valeur de paramètre | `cel` | entrées d'étape de flux | + +## Portée des variables + +Les expressions CEL s'évaluent dans un contexte comportant ces +variables de premier niveau : + +| Variable | Disponible quand | Contenu | +|:--|:--|:--| +| `record` | presque toujours | L'enregistrement en cours d'évaluation | +| `previous` | sur les hooks de mise à jour / la détection de changement | L'état de l'enregistrement avant le changement (ou `null`) | +| `input` | actions, étapes de flux | La charge utile d'entrée fournie par l'utilisateur | +| `os.user` | toujours | `{ id, roles: string[], permissions: string[] }` | +| `os.org` | toujours | Contexte d'organisation / de locataire | +| `os.env` | toujours | Variables d'environnement exposées aux expressions | + +> Les anciennes variables `OLD` / `NEW` ont été supprimées en M9.5. +> Utilisez `previous` et `record`. + +## Bibliothèque standard + +Enregistrée dans +[`packages/formula/src/stdlib.ts`](https://github.com/objectstack-ai/framework/blob/main/packages/formula/src/stdlib.ts). +Les fonctions intégrées les plus utilisées : + +### Temps + +| Fonction | Renvoie | Notes | +|:--|:--|:--| +| `now()` | `Timestamp` | Figé au contexte d'évaluation — stable au sein d'une même requête | +| `today()` | `Timestamp` | Début du jour UTC | +| `daysFromNow(int)` | `Timestamp` | Date future | +| `daysAgo(int)` | `Timestamp` | Date passée | + +CEL inclut aussi les fonctions natives `timestamp(...)`, +`duration(...)`, `date.getDayOfWeek()`, etc. — voir la +[spécification CEL](https://github.com/google/cel-spec/blob/master/doc/langdef.md#standard-definitions). + +### Utilitaires + +| Fonction | Objet | +|:--|:--| +| `isBlank(x)` | `true` si `null`, `undefined`, `""` ou liste vide | +| `coalesce(a, b)` | Première valeur non nulle | +| `trim(s)` | Supprime les espaces | +| `joinNonEmpty(list, sep)` | Concatène les entrées non vides | + +Les fonctions natives CEL pour les chaînes (`.contains(...)`, +`.startsWith(...)`, `.matches(...)`, `.size()`) sont toujours +disponibles. + +## Exemples + +**Champ de formule** — total d'une ligne d'article : + +```ts +{ name: 'subtotal', type: 'formula', expression: F`record.quantity * record.unit_price` } +``` + +**Validation** — la date de clôture doit être postérieure à aujourd'hui : + +```ts +{ message: 'Close date must be in the future', predicate: P`record.close_date > today()` } +``` + +**Visibilité** — afficher le champ uniquement aux managers : + +```ts +{ visibleIf: P`'manager' in os.user.roles` } +``` + +**Garde de flux** — ignorer l'étape lorsque le montant est faible : + +```ts +{ when: P`record.amount >= 1000` } +``` + +**Planification** — 9h en semaine : + +```ts +{ schedule: cron`0 9 * * 1-5` } +``` + +**Modèle** — sujet de notification : + +```ts +{ subject: tmpl`[{{record.priority}}] {{record.subject}}` } +``` + +## Erreurs + +Les expressions sont compilées au moment du chargement. Les échecs +apparaissent comme `VALIDATION_ERROR` avec l'emplacement source : + +```json +{ "code": "VALIDATION_ERROR", "message": "CEL: unknown field 'amout' on Record", "details": { "field": "subtotal", "expression": "record.amout * 0.1" } } +``` + +Un échec d'évaluation au runtime est traité comme `null` pour les +champs de formule et `false` pour les prédicats, avec en plus une +entrée dans le journal d'audit. + +## Voir aussi + +- [Types de champs](./field-types) — champs de formule et à exigence conditionnelle +- [Build → Modèle de données](/docs/build/data-model) — validations et prédicats +- [Build → Flux](/docs/build/flows) — gardes et planifications +- [`@objectstack/spec/shared/expression.zod.ts`](https://github.com/objectstack-ai/framework/blob/main/packages/spec/src/shared/expression.zod.ts) — schéma +- [`@objectstack/formula/stdlib.ts`](https://github.com/objectstack-ai/framework/blob/main/packages/formula/src/stdlib.ts) — fonctions intégrées diff --git a/content/docs/reference/cel.ja.mdx b/content/docs/reference/cel.ja.mdx new file mode 100644 index 0000000..15b8645 --- /dev/null +++ b/content/docs/reference/cel.ja.mdx @@ -0,0 +1,157 @@ +--- +title: CEL 式 +description: 数式、述語、スケジュール、テンプレート文字列に使用される式言語 — 5 つのタグ付きテンプレートを通じて提供されます。 +--- + +# CEL 式 + +ObjectOS は、小さく安全でサンドボックス化された式が必要なあらゆる場所で [CEL](https://github.com/google/cel-spec)(Common +Expression Language)を使用します。対象は、数式フィールド、検証ルール、表示述語、共有条件、フロー +ガード、スケジュール、テンプレート文字列です。 + +オーサリングは `@objectstack/spec` からインポートする **5 つのタグ付きテンプレート** を通じて行います。これらはいずれも、ランタイムが解析する小さな JSON オブジェクトを生成します。 + +```ts +{ dialect: 'cel' | 'template' | 'cron', source: string } +``` + +スキーマソース: +[`packages/spec/src/shared/expression.zod.ts`](https://github.com/objectstack-ai/framework/blob/main/packages/spec/src/shared/expression.zod.ts)。 + +## 5 つのタグ付きテンプレート + +| テンプレート | Dialect | 用途 | 例 | +|:--|:--|:--|:--| +| `` F`...` `` | `cel` | **数式フィールド** — レコードと共に保存される派生値 | `` F`record.amount * 0.1` `` | +| `` P`...` `` | `cel` | **述語** — 検証 / 共有 / 表示 / 条件のためのブール値 | `` P`record.status == "open"` `` | +| `` cel`...` `` | `cel` | **汎用 CEL** — F でも P でも合わない場合(例: パラメータ値) | `` cel`now() + duration("P30D")` `` | +| `` tmpl`...` `` | `template` | `{{var}}` 補間を伴う **文字列テンプレート** | `` tmpl`Order from {{record.customer.name}}` `` | +| `` cron`...` `` | `cron` | **スケジュール** — 標準の 5 フィールド cron 構文 | `` cron`0 9 * * 1-5` `` | + +`F`、`P`、`cel` は評価時には機能的な違いはありません — いずれも CEL を実行します。この区別は、スキーマ(および AI エージェント)が式の役割を把握し、エディタが型チェックを行えるようにするために存在します(数式は値を返さなければならず、述語はブール値を返さなければなりません)。 + +### インポート + +```ts +import { F, P, cel, tmpl, cron } from '@objectstack/spec' +``` + +## それぞれの使用場所 + +| spec 上のフィールド | タグ | 使用場所の例 | +|:--|:--|:--| +| `Field.expression`(formula 型) | `F` | `*.object.ts` の数式フィールド | +| `Field.conditionalRequired` | `P` | オブジェクトフィールド | +| `Validation.predicate` | `P` | オブジェクト検証 | +| `SharingRule.condition` | `P` | 共有ルール | +| `View.conditionalFormatting[].condition` | `P` | ビュー | +| `Flow.step.when` / `Flow.transition.when` | `P` | フロー | +| `Action.guard` | `P` | アクション | +| 通知の件名 / メッセージ本文 | `tmpl` | 通知 | +| `Schedule.cron` | `cron` | スケジュール実行されるフロー / レポート | +| 任意の値パラメータ | `cel` | フローステップの入力 | + +## 変数スコープ + +CEL 式は、次のトップレベル変数を持つコンテキスト内で評価されます。 + +| 変数 | 利用可能なタイミング | 内容 | +|:--|:--|:--| +| `record` | ほぼ常時 | 評価中の現在のレコード | +| `previous` | 更新フック / 変更検出時 | レコードの変更前の状態(または `null`) | +| `input` | アクション、フローステップ | ユーザーが指定した入力ペイロード | +| `os.user` | 常時 | `{ id, roles: string[], permissions: string[] }` | +| `os.org` | 常時 | 組織 / テナントのコンテキスト | +| `os.env` | 常時 | 式に公開される環境変数 | + +> レガシーの `OLD` / `NEW` 変数は M9.5 で削除されました。`previous` +> と `record` を使用してください。 + +## 標準ライブラリ + +[`packages/formula/src/stdlib.ts`](https://github.com/objectstack-ai/framework/blob/main/packages/formula/src/stdlib.ts) +に登録されています。 +最もよく使われる組み込み関数: + +### 時刻 + +| 関数 | 戻り値 | 備考 | +|:--|:--|:--| +| `now()` | `Timestamp` | 評価コンテキストに固定される — 1 つのクエリ内では安定 | +| `today()` | `Timestamp` | UTC の日の開始時刻 | +| `daysFromNow(int)` | `Timestamp` | 未来の日付 | +| `daysAgo(int)` | `Timestamp` | 過去の日付 | + +CEL にはネイティブの `timestamp(...)`、`duration(...)`、 +`date.getDayOfWeek()` なども含まれます — +[CEL spec](https://github.com/google/cel-spec/blob/master/doc/langdef.md#standard-definitions) を参照してください。 + +### ユーティリティ + +| 関数 | 目的 | +|:--|:--| +| `isBlank(x)` | `null`、`undefined`、`""`、または空リストの場合に `true` | +| `coalesce(a, b)` | 最初の非 null 値 | +| `trim(s)` | 空白を除去 | +| `joinNonEmpty(list, sep)` | 空でないエントリを連結 | + +ネイティブの CEL 文字列ヘルパー(`.contains(...)`、`.startsWith(...)`、 +`.matches(...)`、`.size()`)は常に利用可能です。 + +## 例 + +**数式フィールド** — 明細項目の合計: + +```ts +{ name: 'subtotal', type: 'formula', expression: F`record.quantity * record.unit_price` } +``` + +**検証** — 完了日は今日より後でなければならない: + +```ts +{ message: 'Close date must be in the future', predicate: P`record.close_date > today()` } +``` + +**表示** — マネージャーにのみフィールドを表示する: + +```ts +{ visibleIf: P`'manager' in os.user.roles` } +``` + +**フローガード** — 金額が小さい場合はステップをスキップする: + +```ts +{ when: P`record.amount >= 1000` } +``` + +**スケジュール** — 平日の午前 9 時: + +```ts +{ schedule: cron`0 9 * * 1-5` } +``` + +**テンプレート** — 通知の件名: + +```ts +{ subject: tmpl`[{{record.priority}}] {{record.subject}}` } +``` + +## エラー + +式はロード時にコンパイルされます。失敗はソースの場所とともに +`VALIDATION_ERROR` として表示されます。 + +```json +{ "code": "VALIDATION_ERROR", "message": "CEL: unknown field 'amout' on Record", "details": { "field": "subtotal", "expression": "record.amout * 0.1" } } +``` + +ランタイムでの評価失敗は、数式フィールドでは `null`、述語では `false` +として扱われ、あわせて監査ログにエントリが記録されます。 + +## 関連項目 + +- [Field types](./field-types) — 数式フィールドと条件付き必須フィールド +- [Build → Data model](/docs/build/data-model) — 検証と述語 +- [Build → Flows](/docs/build/flows) — ガードとスケジュール +- [`@objectstack/spec/shared/expression.zod.ts`](https://github.com/objectstack-ai/framework/blob/main/packages/spec/src/shared/expression.zod.ts) — スキーマ +- [`@objectstack/formula/stdlib.ts`](https://github.com/objectstack-ai/framework/blob/main/packages/formula/src/stdlib.ts) — 組み込み関数 diff --git a/content/docs/reference/cel.cn.mdx b/content/docs/reference/cel.zh-Hans.mdx similarity index 100% rename from content/docs/reference/cel.cn.mdx rename to content/docs/reference/cel.zh-Hans.mdx diff --git a/content/docs/reference/cli.de.mdx b/content/docs/reference/cli.de.mdx new file mode 100644 index 0000000..6a7497c --- /dev/null +++ b/content/docs/reference/cli.de.mdx @@ -0,0 +1,209 @@ +--- +title: CLI-Referenz +description: Jeder `os`-Befehl, was er tut und die nützlichsten Flags. +--- + +# CLI-Referenz + +Das Paket `@objectstack/cli` installiert eine einzelne Binärdatei, `os` (auch +verfügbar als `objectstack`). Alle Beispiele unten verwenden das kürzere `os`. + +```bash +npm i -g @objectstack/cli +os --help +``` + +## Server-Befehle + +### `os start` — Boot ohne Konfiguration + +Erkennt automatisch 4 eskalierende Modi: + +1. **Leerer Boot** — kein Artefakt, keine Konfiguration im cwd → bootet einen + minimalen Kernel mit Console + marketplace. +2. **Projekt-Boot** — `objectstack.config.ts` im cwd → kompiliert automatisch + zu `./dist/objectstack.json` und bootet daraus. +3. **Artefakt-Boot** — `dist/objectstack.json` erreichbar → bootet direkt + daraus. +4. **Explizite Überschreibungen** — `--artifact`, `--database`, `--port` gewinnen. + +```bash +os start # default port 3000 +os start --port 8080 +os start --artifact ./build/myapp.json +os start --artifact https://cdn.example.com/app.json +os start --database file:./data/prod.db +os start --database postgres://user:pass@host:5432/mydb +os start --database libsql://my-db.turso.io --database-auth-token $TURSO +os start --auth-secret "$(openssl rand -hex 32)" +os start --home /var/lib/objectos # persistent home dir +os start --no-ui # API only (no Console/Account) +``` + +Standardwert des HOME-Verzeichnisses: +- mit einer Projektkonfiguration im cwd → `/.objectstack` (projektlokal) +- ohne → `~/.objectstack` (global, über Aufrufe hinweg gemeinsam genutzt) + +### `os serve` — Produktionsserver + +Liest `objectstack.config.ts`, falls vorhanden, andernfalls greift es auf +`dist/objectstack.json` zurück (oder `OS_ARTIFACT_PATH`, einschließlich `http(s)://`-URLs). +Verwenden Sie dies in Produktionscontainern, wenn Sie striktes Verhalten wünschen. + +```bash +os serve # port 3000 +os serve --port 4000 --no-ui +``` + +### `os dev` — Entwicklung mit Hot-Reload + +Überwacht `objectstack.config.ts` und `src/`. Rekompiliert + lädt beim +Speichern neu. Wird in gerüsteten Projekten als npm-`dev`-Skript verwendet. + +```bash +os dev # port 3002 by default +os dev -p 4002 +``` + +### `os studio` — Console mit Dev-Server + +Wie `os dev`, aber mit explizit aktivierter Console. + +## Projekt-Befehle + +### `os init` — ein neues Projekt aufsetzen + +```bash +os init my-app # interactive +os init my-app -t app --install # auto-install with default pnpm +os init my-app -t app --install -p npm +os init my-app -t plugin # plugin scaffold +os init my-app -t empty # bare minimum +``` + +Vorlagen: +| Vorlage | Was sie Ihnen bietet | +|---|---| +| `app` | Vollständige App — Objekte, Views, Aktionen, bereit zum Erweitern | +| `plugin` | Plugin-Gerüst zum Verteilen wiederverwendbarer Funktionen | +| `empty` | Nur Manifest + tsconfig | + +### `os create` — ein Paket, Plugin oder Beispiel aus einer Vorlage erstellen + +```bash +os create plugin my-plugin +os create example my-example +``` + +## Build- / Validierungs-Befehle + +| Befehl | Zweck | +|---|---| +| `os compile` (`os build`) | `objectstack.config.ts` → `dist/objectstack.json` kompilieren | +| `os validate` | Konfiguration gegen das Protokollschema validieren | +| `os lint` | Stil- und Konventionsprüfungen (empfohlen in CI) | +| `os diff ` | Zwei Konfigurationen vergleichen, Breaking Changes erkennen | +| `os info` | Metadaten-Zusammenfassung einer Konfiguration oder eines Artefakts ausgeben | +| `os explain ` | Menschenlesbare Erklärung eines Objektschemas | +| `os doctor` | Health-Check: erkennt zirkuläre Abhängigkeiten, defekte Referenzen, Umgebungsprobleme | +| `os generate` (`os g`) | TypeScript-Typen / Metadatendateien generieren | + +`os doctor` ist das **Erste, das man ausführen sollte, wenn etwas nicht stimmt** — es +fängt Fehlkonfigurationen ab, die die Laufzeit nur als Laufzeitwarnung melden würde. + +## Daten-Befehle + +Arbeiten Sie mit Datensätzen vom Terminal aus — nützlich für Seeding, Migrationen +und CI-Smoke-Tests. + +```bash +os data create --data '{"subject": "Hello"}' +os data get +os data query --filter 'status:active' --limit 10 +os data update --data '{"done": true}' +os data delete +``` + +## Metadaten-Befehle + +Metadaten-Datensätze (Objekte, Views, Berechtigungssätze, …) zur Laufzeit +lesen/schreiben. + +```bash +os meta list +os meta get +os meta register +os meta delete +``` + +## i18n-Befehle + +```bash +os i18n extract # extract translation keys from source +os i18n check # find missing keys across configured locales +``` + +## Cloud-Befehle + +Für Benutzer von ObjectStack Cloud (der optionalen gehosteten Control-Plane). + +```bash +os login # interactive +os logout +os whoami +os register # create an account +os cloud login | logout | whoami +``` + +## Publish- / Package-Befehle + +```bash +os package publish # publish artifact as a versioned package +os publish # publish to ObjectStack Cloud +os rollback # activate a previous artifact revision +``` + +## Umgebungs-Befehle + +Für Deployments mit mehreren Umgebungen pro Projekt (dev, staging, +prod), die von einer Control-Plane unterstützt werden. + +```bash +os environments list +os environments show +os environments create +os environments switch +os environments bind # bind local artifact to an environment +``` + +## Test-Befehl + +```bash +os test # run Quality Protocol scenarios against a running server +``` + +## Gängige Flag-Konventionen + +| Flag | Bedeutung | +|---|---| +| `-p, --port` | HTTP-Port | +| `-a, --artifact` | Pfad oder URL zum kompilierten Artefakt | +| `-d, --database` | Datenbank-URL | +| `--home` | Verzeichnis für persistenten Zustand | +| `-v, --verbose` | Ausführliche Ausgabe | +| `--no-ui` | Console-/Account-Portale deaktivieren | + +Führen Sie einen beliebigen Befehl mit `--help` aus, um die vollständige Flag-Liste zu erhalten: + +```bash +os start --help +os data query --help +``` + +## Wo die CLI hineinpasst + +- **Operator / erster Start** → `os start` +- **Entwickler, der eine App baut** → `os init` → `os dev` → `os compile` +- **CI / Release-Pipeline** → `os lint && os validate && os compile && os test` +- **Produktions-Laufzeit** → `os serve` (typischerweise im `CMD` des Docker-Images) +- **Diagnose** → `os doctor`, `os info`, `os explain` diff --git a/content/docs/reference/cli.es.mdx b/content/docs/reference/cli.es.mdx new file mode 100644 index 0000000..5601ef9 --- /dev/null +++ b/content/docs/reference/cli.es.mdx @@ -0,0 +1,210 @@ +--- +title: Referencia de la CLI +description: Cada comando `os`, qué hace y los flags más útiles. +--- + +# Referencia de la CLI + +El paquete `@objectstack/cli` instala un único binario, `os` (también +disponible como `objectstack`). Todos los ejemplos a continuación usan el `os` más corto. + +```bash +npm i -g @objectstack/cli +os --help +``` + +## Comandos del servidor + +### `os start` — arranque sin configuración + +Detecta automáticamente 4 modos escalonados: + +1. **Arranque vacío** — sin artefacto ni configuración en el cwd → arranca un + kernel básico con Console + marketplace. +2. **Arranque de proyecto** — `objectstack.config.ts` en el cwd → compila + automáticamente a `./dist/objectstack.json` y arranca desde ahí. +3. **Arranque de artefacto** — `dist/objectstack.json` accesible → arranca desde + él directamente. +4. **Sobrescrituras explícitas** — `--artifact`, `--database`, `--port` tienen prioridad. + +```bash +os start # default port 3000 +os start --port 8080 +os start --artifact ./build/myapp.json +os start --artifact https://cdn.example.com/app.json +os start --database file:./data/prod.db +os start --database postgres://user:pass@host:5432/mydb +os start --database libsql://my-db.turso.io --database-auth-token $TURSO +os start --auth-secret "$(openssl rand -hex 32)" +os start --home /var/lib/objectos # persistent home dir +os start --no-ui # API only (no Console/Account) +``` + +Directorio HOME por defecto: +- con una configuración de proyecto en el cwd → `/.objectstack` (local al proyecto) +- sin ella → `~/.objectstack` (global, compartido entre invocaciones) + +### `os serve` — servidor de producción + +Lee `objectstack.config.ts` si está presente; de lo contrario recurre a +`dist/objectstack.json` (o `OS_ARTIFACT_PATH`, incluyendo URLs `http(s)://`). +Usa esto en contenedores de producción cuando quieras un comportamiento estricto. + +```bash +os serve # port 3000 +os serve --port 4000 --no-ui +``` + +### `os dev` — desarrollo con recarga en caliente + +Observa `objectstack.config.ts` y `src/`. Recompila + recarga al +guardar. Se usa como el script npm `dev` en los proyectos generados. + +```bash +os dev # port 3002 by default +os dev -p 4002 +``` + +### `os studio` — Console con servidor de desarrollo + +Igual que `os dev` pero con Console habilitada explícitamente. + +## Comandos de proyecto + +### `os init` — genera un nuevo proyecto + +```bash +os init my-app # interactive +os init my-app -t app --install # auto-install with default pnpm +os init my-app -t app --install -p npm +os init my-app -t plugin # plugin scaffold +os init my-app -t empty # bare minimum +``` + +Plantillas: +| Plantilla | Qué te ofrece | +|---|---| +| `app` | App completa — objetos, vistas, acciones, lista para ampliar | +| `plugin` | Andamiaje de plugin para distribuir capacidades reutilizables | +| `empty` | Solo manifiesto + tsconfig | + +### `os create` — crea un paquete, plugin o ejemplo desde una plantilla + +```bash +os create plugin my-plugin +os create example my-example +``` + +## Comandos de compilación / validación + +| Comando | Propósito | +|---|---| +| `os compile` (`os build`) | Compila `objectstack.config.ts` → `dist/objectstack.json` | +| `os validate` | Valida la configuración contra el esquema del protocolo | +| `os lint` | Comprobaciones de estilo y convenciones (recomendado en CI) | +| `os diff ` | Compara dos configuraciones, detecta cambios incompatibles | +| `os info` | Imprime un resumen de metadatos de una configuración o artefacto | +| `os explain ` | Explicación legible del esquema de un objeto | +| `os doctor` | Chequeo de salud: detecta dependencias circulares, referencias rotas, problemas de entorno | +| `os generate` (`os g`) | Genera tipos de TypeScript / archivos de metadatos | + +`os doctor` es **lo primero que debes ejecutar cuando algo parece ir mal** — detecta +configuraciones erróneas que el runtime solo mostraría como una advertencia en tiempo +de ejecución. + +## Comandos de datos + +Operan sobre registros desde la terminal — útiles para sembrar datos, migraciones +y pruebas de humo en CI. + +```bash +os data create --data '{"subject": "Hello"}' +os data get +os data query --filter 'status:active' --limit 10 +os data update --data '{"done": true}' +os data delete +``` + +## Comandos de metadatos + +Lee/escribe registros de metadatos (objetos, vistas, conjuntos de permisos, …) en +tiempo de ejecución. + +```bash +os meta list +os meta get +os meta register +os meta delete +``` + +## Comandos de i18n + +```bash +os i18n extract # extract translation keys from source +os i18n check # find missing keys across configured locales +``` + +## Comandos de la nube + +Para usuarios de ObjectStack Cloud (el plano de control alojado opcional). + +```bash +os login # interactive +os logout +os whoami +os register # create an account +os cloud login | logout | whoami +``` + +## Comandos de publicación / empaquetado + +```bash +os package publish # publish artifact as a versioned package +os publish # publish to ObjectStack Cloud +os rollback # activate a previous artifact revision +``` + +## Comandos de entorno + +Para despliegues que usan múltiples entornos por proyecto (dev, staging, +prod) respaldados por un plano de control. + +```bash +os environments list +os environments show +os environments create +os environments switch +os environments bind # bind local artifact to an environment +``` + +## Comando de prueba + +```bash +os test # run Quality Protocol scenarios against a running server +``` + +## Convenciones comunes de flags + +| Flag | Significado | +|---|---| +| `-p, --port` | Puerto HTTP | +| `-a, --artifact` | Ruta o URL al artefacto compilado | +| `-d, --database` | URL de la base de datos | +| `--home` | Directorio de estado persistente | +| `-v, --verbose` | Salida detallada | +| `--no-ui` | Deshabilita los portales Console / Account | + +Ejecuta cualquier comando con `--help` para ver la lista completa de flags: + +```bash +os start --help +os data query --help +``` + +## Dónde encaja la CLI + +- **Operador / primer arranque** → `os start` +- **Desarrollador que construye una app** → `os init` → `os dev` → `os compile` +- **Pipeline de CI / release** → `os lint && os validate && os compile && os test` +- **Runtime de producción** → `os serve` (normalmente dentro del `CMD` de la imagen Docker) +- **Diagnóstico** → `os doctor`, `os info`, `os explain` diff --git a/content/docs/reference/cli.fr.mdx b/content/docs/reference/cli.fr.mdx new file mode 100644 index 0000000..4708092 --- /dev/null +++ b/content/docs/reference/cli.fr.mdx @@ -0,0 +1,210 @@ +--- +title: Référence de la CLI +description: Chaque commande `os`, ce qu'elle fait, et les options les plus utiles. +--- + +# Référence de la CLI + +Le paquet `@objectstack/cli` installe un binaire unique, `os` (également +disponible sous le nom `objectstack`). Tous les exemples ci-dessous utilisent la forme plus courte `os`. + +```bash +npm i -g @objectstack/cli +os --help +``` + +## Commandes du serveur + +### `os start` — démarrage sans configuration + +Détecte automatiquement 4 modes croissants : + +1. **Démarrage vide** — aucun artefact, aucune configuration dans le répertoire courant → démarre un + kernel minimal avec Console + marketplace. +2. **Démarrage de projet** — `objectstack.config.ts` dans le répertoire courant → compile automatiquement + vers `./dist/objectstack.json` et démarre à partir de celui-ci. +3. **Démarrage d'artefact** — `dist/objectstack.json` accessible → démarre directement + à partir de celui-ci. +4. **Surcharges explicites** — `--artifact`, `--database`, `--port` l'emportent. + +```bash +os start # default port 3000 +os start --port 8080 +os start --artifact ./build/myapp.json +os start --artifact https://cdn.example.com/app.json +os start --database file:./data/prod.db +os start --database postgres://user:pass@host:5432/mydb +os start --database libsql://my-db.turso.io --database-auth-token $TURSO +os start --auth-secret "$(openssl rand -hex 32)" +os start --home /var/lib/objectos # persistent home dir +os start --no-ui # API only (no Console/Account) +``` + +Répertoire HOME par défaut : +- avec une configuration de projet dans le répertoire courant → `/.objectstack` (local au projet) +- sans → `~/.objectstack` (global, partagé entre les invocations) + +### `os serve` — serveur de production + +Lit `objectstack.config.ts` s'il est présent, sinon se rabat sur +`dist/objectstack.json` (ou `OS_ARTIFACT_PATH`, y compris les URL `http(s)://`). +Utilisez cette commande dans les conteneurs de production lorsque vous voulez un comportement strict. + +```bash +os serve # port 3000 +os serve --port 4000 --no-ui +``` + +### `os dev` — développement avec rechargement à chaud + +Surveille `objectstack.config.ts` et `src/`. Recompile + recharge à chaque +enregistrement. Utilisé comme script npm `dev` dans les projets générés. + +```bash +os dev # port 3002 by default +os dev -p 4002 +``` + +### `os studio` — Console avec serveur de développement + +Identique à `os dev` mais avec la Console explicitement activée. + +## Commandes de projet + +### `os init` — générer un nouveau projet + +```bash +os init my-app # interactive +os init my-app -t app --install # auto-install with default pnpm +os init my-app -t app --install -p npm +os init my-app -t plugin # plugin scaffold +os init my-app -t empty # bare minimum +``` + +Modèles : +| Modèle | Ce qu'il vous fournit | +|---|---| +| `app` | Application complète — objets, vues, actions, prête à étendre | +| `plugin` | Squelette de plugin pour distribuer des capacités réutilisables | +| `empty` | Manifeste + tsconfig uniquement | + +### `os create` — créer un package, un plugin ou un exemple à partir d'un modèle + +```bash +os create plugin my-plugin +os create example my-example +``` + +## Commandes de build / validation + +| Commande | Objectif | +|---|---| +| `os compile` (`os build`) | Compile `objectstack.config.ts` → `dist/objectstack.json` | +| `os validate` | Valide la configuration par rapport au schéma du protocole | +| `os lint` | Vérifications de style et de conventions (recommandé en CI) | +| `os diff ` | Compare deux configurations, détecte les changements incompatibles | +| `os info` | Affiche un résumé des métadonnées d'une configuration ou d'un artefact | +| `os explain ` | Explication lisible du schéma d'un objet | +| `os doctor` | Bilan de santé : détecte les dépendances circulaires, les références cassées, les problèmes d'environnement | +| `os generate` (`os g`) | Génère les types TypeScript / fichiers de métadonnées | + +`os doctor` est la **première chose à exécuter lorsque quelque chose semble anormal** — elle +détecte les mauvaises configurations que le runtime ne ferait remonter que sous forme d'avertissement +à l'exécution. + +## Commandes de données + +Opèrent sur les enregistrements depuis le terminal — utiles pour l'initialisation, les migrations +et les tests de fumée en CI. + +```bash +os data create --data '{"subject": "Hello"}' +os data get +os data query --filter 'status:active' --limit 10 +os data update --data '{"done": true}' +os data delete +``` + +## Commandes de métadonnées + +Lecture/écriture des enregistrements de métadonnées (objets, vues, ensembles de permissions, …) à +l'exécution. + +```bash +os meta list +os meta get +os meta register +os meta delete +``` + +## Commandes i18n + +```bash +os i18n extract # extract translation keys from source +os i18n check # find missing keys across configured locales +``` + +## Commandes Cloud + +Pour les utilisateurs d'ObjectStack Cloud (le plan de contrôle hébergé optionnel). + +```bash +os login # interactive +os logout +os whoami +os register # create an account +os cloud login | logout | whoami +``` + +## Commandes de publication / packaging + +```bash +os package publish # publish artifact as a versioned package +os publish # publish to ObjectStack Cloud +os rollback # activate a previous artifact revision +``` + +## Commandes d'environnement + +Pour les déploiements utilisant plusieurs environnements par projet (dev, staging, +prod) adossés à un plan de contrôle. + +```bash +os environments list +os environments show +os environments create +os environments switch +os environments bind # bind local artifact to an environment +``` + +## Commande de test + +```bash +os test # run Quality Protocol scenarios against a running server +``` + +## Conventions courantes des options + +| Option | Signification | +|---|---| +| `-p, --port` | Port HTTP | +| `-a, --artifact` | Chemin ou URL vers l'artefact compilé | +| `-d, --database` | URL de la base de données | +| `--home` | Répertoire d'état persistant | +| `-v, --verbose` | Sortie détaillée | +| `--no-ui` | Désactive les portails Console / Account | + +Exécutez n'importe quelle commande avec `--help` pour la liste complète des options : + +```bash +os start --help +os data query --help +``` + +## Où la CLI s'inscrit + +- **Opérateur / premier lancement** → `os start` +- **Développeur construisant une application** → `os init` → `os dev` → `os compile` +- **Pipeline CI / de release** → `os lint && os validate && os compile && os test` +- **Runtime de production** → `os serve` (généralement à l'intérieur du `CMD` de l'image Docker) +- **Diagnostics** → `os doctor`, `os info`, `os explain` diff --git a/content/docs/reference/cli.ja.mdx b/content/docs/reference/cli.ja.mdx new file mode 100644 index 0000000..f059b20 --- /dev/null +++ b/content/docs/reference/cli.ja.mdx @@ -0,0 +1,210 @@ +--- +title: CLI リファレンス +description: すべての `os` コマンド、その機能、そして最も役立つフラグ。 +--- + +# CLI リファレンス + +`@objectstack/cli` パッケージは単一のバイナリ `os`(`objectstack` としても +利用可能)をインストールします。以下の例ではすべて短い `os` を使用します。 + +```bash +npm i -g @objectstack/cli +os --help +``` + +## サーバーコマンド + +### `os start` — ゼロコンフィグ起動 + +段階的にエスカレートする 4 つのモードを自動検出します。 + +1. **空起動** — アーティファクトなし、cwd に設定なし → Console と marketplace + を備えた最小限のカーネルを起動します。 +2. **プロジェクト起動** — cwd に `objectstack.config.ts` がある場合 → + 自動的に `./dist/objectstack.json` にコンパイルし、そこから起動します。 +3. **アーティファクト起動** — `dist/objectstack.json` に到達可能な場合 → + そこから直接起動します。 +4. **明示的なオーバーライド** — `--artifact`、`--database`、`--port` が優先されます。 + +```bash +os start # default port 3000 +os start --port 8080 +os start --artifact ./build/myapp.json +os start --artifact https://cdn.example.com/app.json +os start --database file:./data/prod.db +os start --database postgres://user:pass@host:5432/mydb +os start --database libsql://my-db.turso.io --database-auth-token $TURSO +os start --auth-secret "$(openssl rand -hex 32)" +os start --home /var/lib/objectos # persistent home dir +os start --no-ui # API only (no Console/Account) +``` + +HOME ディレクトリのデフォルト: +- cwd にプロジェクト設定がある場合 → `/.objectstack`(プロジェクトローカル) +- ない場合 → `~/.objectstack`(グローバル、呼び出し間で共有) + +### `os serve` — 本番サーバー + +`objectstack.config.ts` が存在すればそれを読み込み、なければ +`dist/objectstack.json`(または `OS_ARTIFACT_PATH`、`http(s)://` URL を含む)に +フォールバックします。厳格な動作が必要な本番コンテナで使用してください。 + +```bash +os serve # port 3000 +os serve --port 4000 --no-ui +``` + +### `os dev` — ホットリロード付き開発 + +`objectstack.config.ts` と `src/` を監視します。保存時に再コンパイルして +リロードします。スキャフォールドされたプロジェクトで npm の `dev` スクリプトとして +使用されます。 + +```bash +os dev # port 3002 by default +os dev -p 4002 +``` + +### `os studio` — 開発サーバー付き Console + +`os dev` と同じですが、Console が明示的に有効化されています。 + +## プロジェクトコマンド + +### `os init` — 新しいプロジェクトのスキャフォールド + +```bash +os init my-app # interactive +os init my-app -t app --install # auto-install with default pnpm +os init my-app -t app --install -p npm +os init my-app -t plugin # plugin scaffold +os init my-app -t empty # bare minimum +``` + +テンプレート: +| テンプレート | 提供される内容 | +|---|---| +| `app` | 完全なアプリ — オブジェクト、ビュー、アクション、拡張可能な状態 | +| `plugin` | 再利用可能な機能を配布するためのプラグインスキャフォールド | +| `empty` | マニフェストと tsconfig のみ | + +### `os create` — テンプレートからパッケージ、プラグイン、または例を作成 + +```bash +os create plugin my-plugin +os create example my-example +``` + +## ビルド / 検証コマンド + +| コマンド | 目的 | +|---|---| +| `os compile` (`os build`) | `objectstack.config.ts` を `dist/objectstack.json` にコンパイル | +| `os validate` | プロトコルスキーマに対して設定を検証 | +| `os lint` | スタイルと規約のチェック(CI で推奨) | +| `os diff ` | 2 つの設定を比較し、破壊的変更を検出 | +| `os info` | 設定またはアーティファクトのメタデータ概要を出力 | +| `os explain ` | オブジェクトスキーマの人間が読める説明 | +| `os doctor` | ヘルスチェック: 循環依存、壊れた参照、環境の問題を検出 | +| `os generate` (`os g`) | TypeScript 型 / メタデータファイルを生成 | + +`os doctor` は **何かおかしいと感じたときに最初に実行すべきもの** です。 +ランタイムが警告としてのみ表面化させるような設定ミスを捕捉します。 + +## データコマンド + +ターミナルからレコードを操作します — シーディング、マイグレーション、 +CI のスモークテストに役立ちます。 + +```bash +os data create --data '{"subject": "Hello"}' +os data get +os data query --filter 'status:active' --limit 10 +os data update --data '{"done": true}' +os data delete +``` + +## メタデータコマンド + +ランタイムでメタデータレコード(オブジェクト、ビュー、パーミッションセットなど)を +読み書きします。 + +```bash +os meta list +os meta get +os meta register +os meta delete +``` + +## i18n コマンド + +```bash +os i18n extract # extract translation keys from source +os i18n check # find missing keys across configured locales +``` + +## クラウドコマンド + +ObjectStack Cloud(オプションのホスト型コントロールプレーン)のユーザー向けです。 + +```bash +os login # interactive +os logout +os whoami +os register # create an account +os cloud login | logout | whoami +``` + +## パブリッシュ / パッケージコマンド + +```bash +os package publish # publish artifact as a versioned package +os publish # publish to ObjectStack Cloud +os rollback # activate a previous artifact revision +``` + +## 環境コマンド + +コントロールプレーンに支えられた、プロジェクトごとに複数の環境(dev、staging、 +prod)を使用するデプロイメント向けです。 + +```bash +os environments list +os environments show +os environments create +os environments switch +os environments bind # bind local artifact to an environment +``` + +## テストコマンド + +```bash +os test # run Quality Protocol scenarios against a running server +``` + +## 共通のフラグ規約 + +| フラグ | 意味 | +|---|---| +| `-p, --port` | HTTP ポート | +| `-a, --artifact` | コンパイル済みアーティファクトへのパスまたは URL | +| `-d, --database` | データベース URL | +| `--home` | 永続的な状態ディレクトリ | +| `-v, --verbose` | 詳細な出力 | +| `--no-ui` | Console / Account ポータルを無効化 | + +完全なフラグ一覧を表示するには、任意のコマンドを `--help` 付きで実行します。 + +```bash +os start --help +os data query --help +``` + +## CLI の位置づけ + +- **オペレーター / 初回実行** → `os start` +- **アプリを構築する開発者** → `os init` → `os dev` → `os compile` +- **CI / リリースパイプライン** → `os lint && os validate && os compile && os test` +- **本番ランタイム** → `os serve`(通常は Docker イメージの `CMD` 内) +- **診断** → `os doctor`、`os info`、`os explain` diff --git a/content/docs/reference/cli.cn.mdx b/content/docs/reference/cli.zh-Hans.mdx similarity index 100% rename from content/docs/reference/cli.cn.mdx rename to content/docs/reference/cli.zh-Hans.mdx diff --git a/content/docs/reference/environment-variables.de.mdx b/content/docs/reference/environment-variables.de.mdx new file mode 100644 index 0000000..bb422b9 --- /dev/null +++ b/content/docs/reference/environment-variables.de.mdx @@ -0,0 +1,87 @@ +--- +title: Umgebungsvariablen +description: Referenz der ObjectOS-Laufzeitumgebungsvariablen. +--- + +# Umgebungsvariablen + +Verwenden Sie Umgebungsvariablen für Konfiguration und Geheimnisse auf Deployment-Ebene. +Verwenden Sie Systemeinstellungen für anwendungsbezogene Konfiguration, die von Mandanten/Benutzern bearbeitet werden kann. + +> **Benennung.** Ab dem nächsten Release verwenden alle ObjectStack-eigenen Variablen das +> Präfix `OS_`. Unpräfixierte Pre-1.0-Namen (`PORT`, `AUTH_SECRET`, `OS_MULTI_TENANT`, +> …) funktionieren weiterhin, geben aber eine einmalige Verwarnung zur Veralterung aus. Bevorzugen Sie die kanonischen +> `OS_*`-Namen in neuen Deployments; siehe [Veraltete Aliasse](#legacy-aliases). + +## Kern + +| Variable | Erforderlich | Beschreibung | +|---|---:|---| +| `OS_PORT` | Nein | HTTP-Port, auf dem die Laufzeit lauscht. Standardwert ist `3000`. Veralteter Alias: `PORT`. | +| `OS_AUTH_SECRET` | Ja für Auth | Basisgeheimnis, aus dem projektspezifische Auth-Geheimnisse abgeleitet werden. Veralteter Alias: `AUTH_SECRET`. | + +## Artefakt- und Projektauflösung + +| Variable | Erforderlich | Beschreibung | +|---|---:|---| +| `OS_ARTIFACT_FILE` | Dateimodus | Pfad zu einer lokal kompilierten `objectstack.json`. Wird vom ObjectOS-App-Wrapper gelesen und als `fileConfig.artifactPath` weitergeleitet. | +| `OS_ARTIFACT_PATH` | Alternative | Framework-Name für denselben Pfad oder eine `http(s)://`-URL. Wird direkt von `@objectstack/runtime` berücksichtigt (CLI `dev`/`start`, Standalone-Modus). | +| `OS_PROJECT_ID` | Optional | Veralteter Alias für `OS_ENVIRONMENT_ID`, der vom ObjectOS-Wrapper aus Gründen der Abwärtskompatibilität akzeptiert wird. Bevorzugen Sie `OS_ENVIRONMENT_ID` in neuen Deployments. | +| `OS_ENVIRONMENT_ID` | Optional | Umgebungs-ID für den Standalone-/dateibasierten Modus (Standard `proj_local`). Wird auch zur Ableitung des projektspezifischen Auth-Geheimnisses verwendet. Der ObjectOS-Wrapper akzeptiert außerdem den veralteten Alias `OS_PROJECT_ID`. | +| `OS_ORGANIZATION_ID` | Optional | Standard-Organisations-ID für den dateibasierten Modus (Standard `org_local`). | +| `OS_WATCH_ARTIFACT` | Nein | Auf `1` setzen, um das lokale Artefakt bei Änderungen neu zu laden. Nur in der Entwicklung verwenden. | +| `OS_CLOUD_URL` | Cloud-Modus | Basis-URL der Steuerungsebene für die Hostnamenauflösung und den Artefaktabruf. Auf `off` oder `local` setzen, um cloud-verbundenes Verhalten abzuwählen. | +| `OS_CLOUD_API_KEY` | Optional | Bearer-Token für den Zugriff auf die private Artefakt-API der Steuerungsebene. | +| `OS_MULTI_ORG_ENABLED` | Nein | Auf `true` setzen, um Multi-Mandanten-Routing / Organisationswechsel zu aktivieren (Standard `false`). Veralteter Alias: `OS_MULTI_TENANT`. | +| `OS_RUNTIME_PORT` | Nur Dev | Localhost-Port, der zum Aufbau von Plattform-SSO-Callback-URLs bei der Entwicklung auf `http://localhost:` verwendet wird. | + +## Cache + +| Variable | Standard | Beschreibung | +|---|---:|---| +| `OS_KERNEL_CACHE_SIZE` | `32` | Maximale Anzahl zwischengespeicherter Projektkernel. | +| `OS_KERNEL_TTL_MS` | `900000` | Leerlauf-TTL für Projektkernel. | +| `OS_ENV_CACHE_TTL_MS` | `300000` | TTL des Umgebungs-/Hostnamen-Caches. | +| `OS_ARTIFACT_CACHE_TTL_MS` | `300000` | TTL des Artefakt-Antwort-Caches. | + +## Auth und vertrauenswürdige Ursprünge + +| Variable | Beschreibung | +|---|---| +| `AUTH_SECRET` | Veralteter Alias für `OS_AUTH_SECRET`. Wird in diesem Release noch berücksichtigt; bevorzugen Sie `OS_AUTH_SECRET`. | +| `OS_TRUSTED_ORIGINS` | Kommagetrennte zusätzliche vertrauenswürdige Ursprünge. | +| `OS_ROOT_DOMAIN` | Root-Domain, die zum Vertrauen von Projekt-Subdomains in Plattform-SSO-Deployments verwendet wird. | +| `OS_PLATFORM_SSO` | Auf `false` setzen, um die Plattform-SSO-Verdrahtung zu deaktivieren. | +| `OS_RUNTIME_PORT` | Hilfe für die lokale Entwicklung von localhost-Projekt-Hostnamen. | + +## Datenbank + +Im cloud-verbundenen Modus gibt die Steuerungsebene die projektspezifische +Laufzeit-Datenbankkonfiguration mit der Artefaktantwort zurück. Im +dateibasierten Modus liest ObjectOS Datenquellendeklarationen aus dem +Artefakt. Als letzten Ausweg berücksichtigt das Framework außerdem: + +| Variable | Beschreibung | +|---|---| +| `OS_DATABASE_URL` | Verbindungs-URL (`file:./db.sqlite`, `libsql://…`, `postgres://…`, `mongodb://…`, `memory://`). Wird vom Standalone-Modus und der CLI `dev` verwendet. | +| `OS_DATABASE_DRIVER` | Überschreibt den aus der URL automatisch erkannten Treiber. | +| `OS_DATABASE_AUTH_TOKEN` | Auth-Token für verwaltete Treiber wie Turso/libSQL. | +| `OS_BUSINESS_DB_URL` | ObjectOS-Wrapper-Konvention für die projektspezifische Geschäftsdatenbank-URL. Lösen Sie sie in Ihrem Deployment zu `OS_DATABASE_URL` oder einer Laufzeit-Datenquellen-Überschreibung auf. | +| `OS_CACHE_DIR` | Lokales Verzeichnis für Artefakt- und Laufzeit-Cache (Standard `/var/cache/objectos`). | +| `OS_SKIP_SCHEMA_SYNC` | Auf `1` setzen, um die ObjectQL-DDL-Synchronisierung beim Start zu überspringen. Verwenden, wenn das Schema außerhalb verwaltet wird. | + +Bevorzugen Sie für ObjectOS-Kundendeployments eine explizite Laufzeitkonfiguration der +Steuerungsebene oder eine Artefakt-Datenquellenkonfiguration, anstatt sich auf +container-lokale Standardwerte zu verlassen. + +## Veraltete Aliasse + +Diese Pre-1.0-Namen funktionieren in diesem Release noch, geben aber eine einmalige +Verwarnung zur Veralterung aus. Sie werden in einer zukünftigen Hauptversion entfernt. Bevorzugen Sie den kanonischen Namen. + +| Kanonisch | Veraltet | +|---|---| +| `OS_PORT` | `PORT` | +| `OS_AUTH_SECRET` | `AUTH_SECRET` | +| `OS_MULTI_ORG_ENABLED` | `OS_MULTI_TENANT` | +| `OS_ENVIRONMENT_ID` | `OS_PROJECT_ID` | diff --git a/content/docs/reference/environment-variables.es.mdx b/content/docs/reference/environment-variables.es.mdx new file mode 100644 index 0000000..997e672 --- /dev/null +++ b/content/docs/reference/environment-variables.es.mdx @@ -0,0 +1,87 @@ +--- +title: Variables de entorno +description: Referencia de variables de entorno del entorno de ejecución de ObjectOS. +--- + +# Variables de entorno + +Use variables de entorno para la configuración a nivel de despliegue y los secretos. +Use la configuración del sistema para la configuración de la aplicación editable por inquilino/usuario. + +> **Nomenclatura.** A partir de la próxima versión, todas las variables propiedad de ObjectStack usan el +> prefijo `OS_`. Los nombres sin prefijo anteriores a 1.0 (`PORT`, `AUTH_SECRET`, `OS_MULTI_TENANT`, +> …) siguen funcionando, pero emiten una advertencia de obsolescencia de una sola vez. Prefiera los nombres canónicos +> `OS_*` en los nuevos despliegues; consulte [Alias heredados](#legacy-aliases). + +## Núcleo + +| Variable | Obligatoria | Descripción | +|---|---:|---| +| `OS_PORT` | No | Puerto HTTP en el que escucha el entorno de ejecución. Por defecto es `3000`. Alias heredado: `PORT`. | +| `OS_AUTH_SECRET` | Sí para auth | Secreto base utilizado para derivar los secretos de autenticación por proyecto. Alias heredado: `AUTH_SECRET`. | + +## Resolución de artefactos y proyectos + +| Variable | Obligatoria | Descripción | +|---|---:|---| +| `OS_ARTIFACT_FILE` | Modo archivo | Ruta a un archivo `objectstack.json` compilado localmente. Leído por el envoltorio de la aplicación ObjectOS y reenviado como `fileConfig.artifactPath`. | +| `OS_ARTIFACT_PATH` | Alternativa | Nombre a nivel de framework para la misma ruta o URL `http(s)://`. Reconocido directamente por `@objectstack/runtime` (CLI `dev`/`start`, modo independiente). | +| `OS_PROJECT_ID` | Opcional | Alias heredado de `OS_ENVIRONMENT_ID`, aceptado por el envoltorio de ObjectOS por compatibilidad con versiones anteriores. Prefiera `OS_ENVIRONMENT_ID` en los nuevos despliegues. | +| `OS_ENVIRONMENT_ID` | Opcional | Id de entorno para el modo independiente/respaldado por archivo (por defecto `proj_local`). También se usa para derivar el secreto de autenticación por proyecto. El envoltorio de ObjectOS también acepta el alias heredado `OS_PROJECT_ID`. | +| `OS_ORGANIZATION_ID` | Opcional | Id de organización por defecto para el modo respaldado por archivo (por defecto `org_local`). | +| `OS_WATCH_ARTIFACT` | No | Establézcalo en `1` para recargar el artefacto local cuando cambie. Úselo solo en desarrollo. | +| `OS_CLOUD_URL` | Modo nube | URL base del plano de control para la resolución de nombres de host y la obtención de artefactos. Establézcalo en `off` o `local` para excluirse del comportamiento conectado a la nube. | +| `OS_CLOUD_API_KEY` | Opcional | Token portador para el acceso privado a la API de artefactos del plano de control. | +| `OS_MULTI_ORG_ENABLED` | No | Establézcalo en `true` para habilitar el enrutamiento multiinquilino / cambio de organización (por defecto `false`). Alias heredado: `OS_MULTI_TENANT`. | +| `OS_RUNTIME_PORT` | Solo desarrollo | Puerto de localhost utilizado para construir las URL de callback de SSO de plataforma al desarrollar en `http://localhost:`. | + +## Caché + +| Variable | Por defecto | Descripción | +|---|---:|---| +| `OS_KERNEL_CACHE_SIZE` | `32` | Máximo de kernels de proyecto en caché. | +| `OS_KERNEL_TTL_MS` | `900000` | TTL de inactividad para los kernels de proyecto. | +| `OS_ENV_CACHE_TTL_MS` | `300000` | TTL de la caché de entorno/nombre de host. | +| `OS_ARTIFACT_CACHE_TTL_MS` | `300000` | TTL de la caché de respuestas de artefactos. | + +## Autenticación y orígenes de confianza + +| Variable | Descripción | +|---|---| +| `AUTH_SECRET` | Alias heredado de `OS_AUTH_SECRET`. Aún reconocido en esta versión; prefiera `OS_AUTH_SECRET`. | +| `OS_TRUSTED_ORIGINS` | Orígenes de confianza adicionales separados por comas. | +| `OS_ROOT_DOMAIN` | Dominio raíz utilizado para confiar en los subdominios de proyecto en despliegues de SSO de plataforma. | +| `OS_PLATFORM_SSO` | Establézcalo en `false` para desactivar el cableado del SSO de plataforma. | +| `OS_RUNTIME_PORT` | Ayudante de desarrollo local para los nombres de host de proyecto en localhost. | + +## Base de datos + +En el modo conectado a la nube, el plano de control devuelve la configuración de la base de datos +del entorno de ejecución por proyecto junto con la respuesta del artefacto. En +el modo respaldado por archivo, ObjectOS lee las declaraciones de origen de datos del +artefacto. Como último recurso, el framework también reconoce: + +| Variable | Descripción | +|---|---| +| `OS_DATABASE_URL` | URL de conexión (`file:./db.sqlite`, `libsql://…`, `postgres://…`, `mongodb://…`, `memory://`). Utilizada por el modo independiente y la CLI `dev`. | +| `OS_DATABASE_DRIVER` | Anula el controlador detectado automáticamente a partir de la URL. | +| `OS_DATABASE_AUTH_TOKEN` | Token de autenticación para controladores gestionados como Turso/libSQL. | +| `OS_BUSINESS_DB_URL` | Convención del envoltorio de ObjectOS para la URL de la base de datos de negocio por proyecto. Resuélvala a `OS_DATABASE_URL` o a una anulación de origen de datos del entorno de ejecución en su despliegue. | +| `OS_CACHE_DIR` | Directorio local de caché de artefactos y del entorno de ejecución (por defecto `/var/cache/objectos`). | +| `OS_SKIP_SCHEMA_SYNC` | Establézcalo en `1` para omitir la sincronización de DDL de ObjectQL en el arranque. Úselo cuando el esquema se gestiona de forma externa. | + +Para los despliegues de clientes de ObjectOS, prefiera la configuración explícita del entorno de ejecución +del plano de control o la configuración de origen de datos del artefacto en lugar de depender de los valores +por defecto locales del contenedor. + +## Alias heredados + +Estos nombres anteriores a 1.0 siguen funcionando en esta versión, pero emiten una advertencia de obsolescencia +de una sola vez. Se eliminarán en una versión mayor futura. Prefiera el nombre canónico. + +| Canónico | Heredado | +|---|---| +| `OS_PORT` | `PORT` | +| `OS_AUTH_SECRET` | `AUTH_SECRET` | +| `OS_MULTI_ORG_ENABLED` | `OS_MULTI_TENANT` | +| `OS_ENVIRONMENT_ID` | `OS_PROJECT_ID` | diff --git a/content/docs/reference/environment-variables.fr.mdx b/content/docs/reference/environment-variables.fr.mdx new file mode 100644 index 0000000..f70fa49 --- /dev/null +++ b/content/docs/reference/environment-variables.fr.mdx @@ -0,0 +1,87 @@ +--- +title: Variables d'environnement +description: Référence des variables d'environnement d'exécution d'ObjectOS. +--- + +# Variables d'environnement + +Utilisez les variables d'environnement pour la configuration au niveau du déploiement et les secrets. +Utilisez les paramètres système pour la configuration applicative modifiable par le locataire ou l'utilisateur. + +> **Nommage.** À partir de la prochaine version, toutes les variables appartenant à ObjectStack utilisent le +> préfixe `OS_`. Les noms sans préfixe antérieurs à la version 1.0 (`PORT`, `AUTH_SECRET`, `OS_MULTI_TENANT`, +> …) fonctionnent toujours mais émettent un avertissement de dépréciation unique. Préférez les noms canoniques +> `OS_*` dans les nouveaux déploiements ; voir [Alias hérités](#legacy-aliases). + +## Cœur + +| Variable | Requis | Description | +|---|---:|---| +| `OS_PORT` | Non | Port HTTP sur lequel le runtime écoute. Par défaut `3000`. Alias hérité : `PORT`. | +| `OS_AUTH_SECRET` | Oui pour l'authentification | Secret de base utilisé pour dériver les secrets d'authentification par projet. Alias hérité : `AUTH_SECRET`. | + +## Résolution des artefacts et des projets + +| Variable | Requis | Description | +|---|---:|---| +| `OS_ARTIFACT_FILE` | Mode fichier | Chemin vers un `objectstack.json` compilé localement. Lu par le wrapper de l'application ObjectOS et transmis en tant que `fileConfig.artifactPath`. | +| `OS_ARTIFACT_PATH` | Alternative | Nom au niveau du framework pour le même chemin ou une URL `http(s)://`. Pris en charge directement par `@objectstack/runtime` (CLI `dev`/`start`, mode autonome). | +| `OS_PROJECT_ID` | Optionnel | Alias hérité pour `OS_ENVIRONMENT_ID`, accepté par le wrapper ObjectOS pour des raisons de rétrocompatibilité. Préférez `OS_ENVIRONMENT_ID` dans les nouveaux déploiements. | +| `OS_ENVIRONMENT_ID` | Optionnel | Identifiant d'environnement pour le mode autonome/adossé à un fichier (par défaut `proj_local`). Également utilisé pour dériver le secret d'authentification par projet. Le wrapper ObjectOS accepte aussi l'alias hérité `OS_PROJECT_ID`. | +| `OS_ORGANIZATION_ID` | Optionnel | Identifiant d'organisation par défaut pour le mode adossé à un fichier (par défaut `org_local`). | +| `OS_WATCH_ARTIFACT` | Non | Définissez-le à `1` pour recharger l'artefact local lorsqu'il change. À utiliser uniquement en développement. | +| `OS_CLOUD_URL` | Mode cloud | URL de base du plan de contrôle pour la résolution des noms d'hôte et la récupération des artefacts. Définissez-le à `off` ou `local` pour désactiver le comportement connecté au cloud. | +| `OS_CLOUD_API_KEY` | Optionnel | Jeton Bearer pour l'accès privé à l'API Artifact du plan de contrôle. | +| `OS_MULTI_ORG_ENABLED` | Non | Définissez-le à `true` pour activer le routage multi-locataire / le changement d'organisation (par défaut `false`). Alias hérité : `OS_MULTI_TENANT`. | +| `OS_RUNTIME_PORT` | Dev uniquement | Port localhost utilisé pour construire les URL de rappel SSO de la plateforme lors du développement sur `http://localhost:`. | + +## Cache + +| Variable | Par défaut | Description | +|---|---:|---| +| `OS_KERNEL_CACHE_SIZE` | `32` | Nombre maximal de kernels de projet en cache. | +| `OS_KERNEL_TTL_MS` | `900000` | TTL d'inactivité pour les kernels de projet. | +| `OS_ENV_CACHE_TTL_MS` | `300000` | TTL du cache d'environnement/de noms d'hôte. | +| `OS_ARTIFACT_CACHE_TTL_MS` | `300000` | TTL du cache des réponses d'artefacts. | + +## Authentification et origines de confiance + +| Variable | Description | +|---|---| +| `AUTH_SECRET` | Alias hérité pour `OS_AUTH_SECRET`. Toujours pris en charge dans cette version ; préférez `OS_AUTH_SECRET`. | +| `OS_TRUSTED_ORIGINS` | Origines de confiance supplémentaires, séparées par des virgules. | +| `OS_ROOT_DOMAIN` | Domaine racine utilisé pour faire confiance aux sous-domaines de projet dans les déploiements SSO de la plateforme. | +| `OS_PLATFORM_SSO` | Définissez-le à `false` pour désactiver le câblage SSO de la plateforme. | +| `OS_RUNTIME_PORT` | Aide au développement local pour les noms d'hôte de projet en localhost. | + +## Base de données + +En mode connecté au cloud, le plan de contrôle renvoie la configuration de la +base de données d'exécution par projet avec la réponse d'artefact. En +mode adossé à un fichier, ObjectOS lit les déclarations de source de données depuis +l'artefact. En dernier recours, le framework prend également en charge : + +| Variable | Description | +|---|---| +| `OS_DATABASE_URL` | URL de connexion (`file:./db.sqlite`, `libsql://…`, `postgres://…`, `mongodb://…`, `memory://`). Utilisée par le mode autonome et la CLI `dev`. | +| `OS_DATABASE_DRIVER` | Remplace le pilote auto-détecté à partir de l'URL. | +| `OS_DATABASE_AUTH_TOKEN` | Jeton d'authentification pour les pilotes managés tels que Turso/libSQL. | +| `OS_BUSINESS_DB_URL` | Convention du wrapper ObjectOS pour l'URL de la base de données métier par projet. Résolvez-la vers `OS_DATABASE_URL` ou un remplacement de source de données d'exécution dans votre déploiement. | +| `OS_CACHE_DIR` | Répertoire de cache local des artefacts et de l'exécution (par défaut `/var/cache/objectos`). | +| `OS_SKIP_SCHEMA_SYNC` | Définissez-le à `1` pour ignorer la synchronisation DDL ObjectQL au démarrage. À utiliser lorsque le schéma est géré hors bande. | + +Pour les déploiements clients ObjectOS, préférez une configuration d'exécution +explicite du plan de contrôle ou une configuration de source de données d'artefact +plutôt que de vous appuyer sur les valeurs par défaut locales au conteneur. + +## Alias hérités + +Ces noms antérieurs à la version 1.0 fonctionnent toujours dans cette version mais émettent un avertissement +de dépréciation unique. Ils seront supprimés dans une future version majeure. Préférez le nom canonique. + +| Canonique | Hérité | +|---|---| +| `OS_PORT` | `PORT` | +| `OS_AUTH_SECRET` | `AUTH_SECRET` | +| `OS_MULTI_ORG_ENABLED` | `OS_MULTI_TENANT` | +| `OS_ENVIRONMENT_ID` | `OS_PROJECT_ID` | diff --git a/content/docs/reference/environment-variables.ja.mdx b/content/docs/reference/environment-variables.ja.mdx new file mode 100644 index 0000000..24ebd43 --- /dev/null +++ b/content/docs/reference/environment-variables.ja.mdx @@ -0,0 +1,87 @@ +--- +title: 環境変数 +description: ObjectOS ランタイムの環境変数リファレンス。 +--- + +# 環境変数 + +デプロイメントレベルの設定とシークレットには環境変数を使用します。 +テナント/ユーザーが編集可能なアプリケーション設定にはシステム設定を使用します。 + +> **命名規則。** 次のリリースから、ObjectStack が所有するすべての変数は +> `OS_` プレフィックスを使用します。1.0 以前のプレフィックスなしの名前(`PORT`、`AUTH_SECRET`、`OS_MULTI_TENANT`、 +> …)も引き続き動作しますが、一度限りの非推奨警告を出力します。新しいデプロイメントでは正規の +> `OS_*` 名を優先してください。[レガシーエイリアス](#legacy-aliases)を参照してください。 + +## コア + +| 変数 | 必須 | 説明 | +|---|---:|---| +| `OS_PORT` | いいえ | ランタイムがリッスンする HTTP ポート。デフォルトは `3000`。レガシーエイリアス: `PORT`。 | +| `OS_AUTH_SECRET` | 認証には必須 | プロジェクトごとの認証シークレットを導出するために使用する基本シークレット。レガシーエイリアス: `AUTH_SECRET`。 | + +## アーティファクトとプロジェクトの解決 + +| 変数 | 必須 | 説明 | +|---|---:|---| +| `OS_ARTIFACT_FILE` | ファイルモード | ローカルでコンパイルされた `objectstack.json` へのパス。ObjectOS アプリラッパーによって読み取られ、`fileConfig.artifactPath` として転送されます。 | +| `OS_ARTIFACT_PATH` | 代替 | 同じパスまたは `http(s)://` URL に対するフレームワークレベルの名前。`@objectstack/runtime` によって直接処理されます(CLI `dev`/`start`、スタンドアロンモード)。 | +| `OS_PROJECT_ID` | 任意 | `OS_ENVIRONMENT_ID` のレガシーエイリアスで、後方互換性のために ObjectOS ラッパーが受け付けます。新しいデプロイメントでは `OS_ENVIRONMENT_ID` を優先してください。 | +| `OS_ENVIRONMENT_ID` | 任意 | スタンドアロン/ファイルバックモード用の環境 id(デフォルト `proj_local`)。プロジェクトごとの認証シークレットの導出にも使用されます。ObjectOS ラッパーはレガシーエイリアス `OS_PROJECT_ID` も受け付けます。 | +| `OS_ORGANIZATION_ID` | 任意 | ファイルバックモードのデフォルト組織 id(デフォルト `org_local`)。 | +| `OS_WATCH_ARTIFACT` | いいえ | `1` に設定すると、ローカルアーティファクトが変更されたときに再読み込みします。開発時のみ使用してください。 | +| `OS_CLOUD_URL` | クラウドモード | ホスト名解決とアーティファクト取得のためのコントロールプレーンのベース URL。クラウド接続動作をオプトアウトするには `off` または `local` に設定します。 | +| `OS_CLOUD_API_KEY` | 任意 | プライベートコントロールプレーンの Artifact API アクセス用のベアラートークン。 | +| `OS_MULTI_ORG_ENABLED` | いいえ | マルチテナントルーティング/組織切り替えを有効にするには `true` に設定します(デフォルト `false`)。レガシーエイリアス: `OS_MULTI_TENANT`。 | +| `OS_RUNTIME_PORT` | 開発のみ | `http://localhost:` で開発する際にプラットフォーム SSO のコールバック URL を構築するために使用するローカルホストポート。 | + +## キャッシュ + +| 変数 | デフォルト | 説明 | +|---|---:|---| +| `OS_KERNEL_CACHE_SIZE` | `32` | キャッシュするプロジェクトカーネルの最大数。 | +| `OS_KERNEL_TTL_MS` | `900000` | プロジェクトカーネルのアイドル TTL。 | +| `OS_ENV_CACHE_TTL_MS` | `300000` | 環境/ホスト名のキャッシュ TTL。 | +| `OS_ARTIFACT_CACHE_TTL_MS` | `300000` | アーティファクトレスポンスのキャッシュ TTL。 | + +## 認証と信頼できるオリジン + +| 変数 | 説明 | +|---|---| +| `AUTH_SECRET` | `OS_AUTH_SECRET` のレガシーエイリアス。このリリースでは引き続き処理されますが、`OS_AUTH_SECRET` を優先してください。 | +| `OS_TRUSTED_ORIGINS` | カンマ区切りの追加の信頼できるオリジン。 | +| `OS_ROOT_DOMAIN` | プラットフォーム SSO デプロイメントでプロジェクトのサブドメインを信頼するために使用するルートドメイン。 | +| `OS_PLATFORM_SSO` | プラットフォーム SSO の接続を無効にするには `false` に設定します。 | +| `OS_RUNTIME_PORT` | localhost プロジェクトのホスト名向けのローカル開発ヘルパー。 | + +## データベース + +クラウド接続モードでは、コントロールプレーンがアーティファクトレスポンスとともに +プロジェクトごとのランタイムデータベース設定を返します。ファイルバックモードでは、 +ObjectOS はアーティファクトからデータソース宣言を読み取ります。最終手段として、 +フレームワークは次のものも処理します。 + +| 変数 | 説明 | +|---|---| +| `OS_DATABASE_URL` | 接続 URL(`file:./db.sqlite`、`libsql://…`、`postgres://…`、`mongodb://…`、`memory://`)。スタンドアロンモードと CLI `dev` で使用されます。 | +| `OS_DATABASE_DRIVER` | URL から自動検出されるドライバーを上書きします。 | +| `OS_DATABASE_AUTH_TOKEN` | Turso/libSQL などのマネージドドライバー用の認証トークン。 | +| `OS_BUSINESS_DB_URL` | プロジェクトごとのビジネスデータベース URL に対する ObjectOS ラッパーの規約。デプロイメントでは `OS_DATABASE_URL` またはランタイムデータソースの上書きに解決してください。 | +| `OS_CACHE_DIR` | ローカルアーティファクトおよびランタイムキャッシュのディレクトリ(デフォルト `/var/cache/objectos`)。 | +| `OS_SKIP_SCHEMA_SYNC` | 起動時の ObjectQL DDL 同期をスキップするには `1` に設定します。スキーマを別途管理する場合に使用します。 | + +ObjectOS の顧客デプロイメントでは、コンテナローカルのデフォルトに依存するよりも、 +明示的なコントロールプレーンのランタイム設定またはアーティファクトのデータソース設定を +優先してください。 + +## レガシーエイリアス + +これらの 1.0 以前の名前はこのリリースでは引き続き動作しますが、一度限りの非推奨 +警告を出力します。これらは将来のメジャーバージョンで削除されます。正規の名前を優先してください。 + +| 正規 | レガシー | +|---|---| +| `OS_PORT` | `PORT` | +| `OS_AUTH_SECRET` | `AUTH_SECRET` | +| `OS_MULTI_ORG_ENABLED` | `OS_MULTI_TENANT` | +| `OS_ENVIRONMENT_ID` | `OS_PROJECT_ID` | diff --git a/content/docs/reference/environment-variables.cn.mdx b/content/docs/reference/environment-variables.zh-Hans.mdx similarity index 100% rename from content/docs/reference/environment-variables.cn.mdx rename to content/docs/reference/environment-variables.zh-Hans.mdx diff --git a/content/docs/reference/field-types.de.mdx b/content/docs/reference/field-types.de.mdx new file mode 100644 index 0000000..d9f493c --- /dev/null +++ b/content/docs/reference/field-types.de.mdx @@ -0,0 +1,208 @@ +--- +title: Feldtypen +description: Jeder Feldtyp, den du auf einem Objekt deklarieren kannst — was er speichert, welche Optionen er akzeptiert, wie er in REST, Console und im AI Builder erscheint. +--- + +# Feldtypen + +53 integrierte Feldtypen, gruppiert nach Familie. Das vollständige Zod-Schema befindet sich in +[`packages/spec/src/data/field.zod.ts`](https://github.com/objectstack-ai/framework/blob/main/packages/spec/src/data/field.zod.ts) — diese Seite ist eine praktische Zusammenfassung. + +## Kerneigenschaften (jedes Feld) + +| Eigenschaft | Typ | Standard | Zweck | +|:--|:--|:--|:--| +| `name` | string (snake_case) | — | Maschinen-Bezeichner — REST-Pfadsegment, SQL-Spalte | +| `label` | string | — | Anzeigebezeichnung in der Console | +| `type` | FieldType | — | Siehe Typtabellen unten | +| `required` | boolean | `false` | NOT NULL-Beschränkung | +| `unique` | boolean | `false` | Eindeutiger Index | +| `searchable` | boolean | `false` | Indexiert für `/api/v1/search` | +| `multiple` | boolean | `false` | Speichert ein Array von Werten | +| `defaultValue` | unknown | — | Anfangswert (Literal oder CEL) | +| `columnName` | string | = `name` | Überschreibt physische DB-Spalte | +| `hidden` | boolean | `false` | In Standard-Console-Ansichten ausblenden | +| `readonly` | boolean | `false` | In Formularen deaktivieren | +| `system` | boolean | `false` | Automatisch eingefügt (id, created_at, …) | +| `index` | boolean | `false` | Erstellt einen DB-Index | +| `externalId` | boolean | `false` | Für Upsert über externen Schlüssel geeignet | +| `inlineHelpText` | string | — | Tooltip / Hilfetext | +| `conditionalRequired` | `P`-Prädikat | — | Erforderlich, wenn CEL wahr ist | +| `auditTrail` | boolean | `false` | Jede Änderung im Audit-Log verfolgen | +| `encryptionConfig` | object | — | Verschlüsselung auf Feldebene (siehe [Security](./security)) | +| `maskingRule` | string | — | PII-Maskierungsmuster | + +## Text-Familie + +| Typ | Verwendung für | Wichtige Optionen | +|:--|:--|:--| +| `text` | kurze Zeichenketten | `maxLength`, `minLength` | +| `textarea` | mehrzeilig | `maxLength` | +| `email` | E-Mail | formatvalidiert; kleingeschrieben | +| `url` | URL | formatvalidiert | +| `phone` | Telefon | E.164 | +| `password` | Geheimnisse | gehasht; nie von GET zurückgegeben | +| `markdown` | Markdown-Inhalt | in Console-Vorschau gerendert | +| `html` | bereinigtes HTML | DOMPurify beim Schreiben | +| `richtext` | WYSIWYG | Console-Editor + serialisiertes JSON | + +## Zahlen + +| Typ | Verwendung für | Wichtige Optionen | +|:--|:--|:--| +| `number` | Gleitkommazahlen | `min`, `max`, `precision`, `scale` | +| `currency` | Geld | `currencyConfig: { precision, currencyMode: 'fixed' \| 'dynamic', defaultCurrency }` | +| `percent` | 0–100 % | `min`, `max`, `scale` | + +> `integer` und `decimal` sind keine eigenen Typen — verwende `number` mit +> `scale: 0` für Ganzzahlen, `precision`+`scale` für feste Dezimalstellen. + +## Datum / Uhrzeit + +| Typ | Speichert | Hinweise | +|:--|:--|:--| +| `date` | Kalenderdatum | keine Zeitzone | +| `datetime` | Zeitpunkt | UTC | +| `time` | Uhrzeit | kein Datum | + +## Logik + +| Typ | Hinweise | +|:--|:--| +| `boolean` | Kontrollkästchen | +| `toggle` | Wie boolean, Schalter-UI | + +## Auswahl + +| Typ | Hinweise | +|:--|:--| +| `select` | Einzelauswahl — Optionen inline deklariert oder aus einer Auswahlliste referenziert | +| `multiselect` | Mehrfachauswahl, als Array gespeichert | +| `radio` | UI-Alias für `select` mit Radio-Button-Darstellung | +| `checkboxes` | UI-Alias für `multiselect` mit Kontrollkästchen-Darstellung | + +Optionsform: + +```ts +options: [ + { value: 'low', label: 'Low' }, + { value: 'high', label: 'High', color: '#e02' }, + { value: 'urgent', label: 'Urgent', color: '#c00' } +] +``` + +## Beziehungen + +| Typ | Kardinalität | Semantik | +|:--|:--|:--| +| `lookup` | viele-zu-eins | Lose Referenz; das Löschen des übergeordneten Datensatzes löscht das untergeordnete standardmäßig nicht | +| `master_detail` | viele-zu-eins, kaskadierend | Untergeordneter Datensatz kann ohne übergeordneten nicht existieren; Berechtigungen werden vom übergeordneten geerbt | +| `tree` | Selbstreferenz | Hierarchisch (parent_id auf demselben Objekt) | + +Häufige Optionen: + +```ts +{ + type: 'lookup', + reference: 'account', // target object name + referenceFilters: ['status:active'], // narrow the lookup picker + deleteBehavior: 'set_null' // 'set_null' | 'cascade' | 'restrict' +} +``` + +## Berechnet + +| Typ | Funktion | Wichtige Option | +|:--|:--|:--| +| `formula` | Abgeleiteter Wert, beim Lesen oder Neuberechnen ausgewertet | `expression: F\`record.qty * record.unit_price\`` — siehe [CEL](./cel) | +| `summary` | Aggregation über eine untergeordnete Beziehung | `summaryOperations: { object, field, function }` (`count` \| `sum` \| `avg` \| `min` \| `max`) | +| `autonumber` | Automatisch hochzählende Anzeigenummer | `format` (z. B. `TKT-{0000}`), `startAt` | + +Formel-Beispiel: + +```ts +{ + name: 'profit_margin', + type: 'formula', + expression: F`(record.revenue - record.cost) / record.revenue * 100` +} +``` + +## Medien + +| Typ | Verwendung für | Wichtige Option | +|:--|:--|:--| +| `image` | Bildanhänge | `fileAttachmentConfig` (siehe unten) | +| `file` | beliebige Datei | dasselbe | +| `avatar` | Profilbilder | quadratischer Zuschnitt, sinnvolle Standardwerte | +| `video` | Video-Uploads | Dauer + Thumbnail-Erfassung | +| `audio` | Audio | Wellenform-Vorschau | + +```ts +fileAttachmentConfig: { + maxSize: 10_000_000, // bytes + allowedTypes: ['image/png','image/jpeg'], + virusScan: true, + storageProvider: 's3', // see Configure → Storage + imageValidation: { minWidth: 200, maxWidth: 4096, generateThumbnails: ['sm','md','lg'] } +} +``` + +## Strukturiert + +| Typ | Speichert | Hinweise | +|:--|:--|:--| +| `json` | beliebiges JSON | Auf Postgres als JSONB gespeichert | +| `composite` | Unterdatensatz mit benannten Feldern | Inline-Struktur, keine separate Tabelle | +| `repeater` | Array von zusammengesetzten Werten | Eins-zu-viele ohne untergeordnetes Objekt | + +## Erweiterte UI + +| Typ | Hinweise | +|:--|:--| +| `location` | Breiten-/Längengrad + Genauigkeit | +| `address` | Straße / Stadt / Region / Postleitzahl / Land | +| `code` | Quellcode-Feld — `language`, `theme`, `lineNumbers` | +| `color` | `colorFormat: 'hex' \| 'rgb' \| 'rgba' \| 'hsl'`, `presetColors[]` | +| `rating` | 1–N Sterne — `max`, `icon` | +| `slider` | begrenzte Zahl mit Schieberegler-UI | +| `signature` | gezeichnete Unterschrift, als Bild gespeichert | +| `qrcode` | rendert den Wert als QR-Code — `qrErrorCorrection: 'L' \| 'M' \| 'Q' \| 'H'` | +| `barcode` | EAN/UPC/Code128 — `barcodeFormat` | +| `progress` | abgeleiteter Prozentwert als Balken dargestellt | +| `tags` | frei wählbares Tag-Array mit Autovervollständigung | +| `vector` | Embedding-Spalte — `vectorConfig: { dimensions, distanceMetric: 'cosine' \| 'euclidean', indexed, indexType: 'hnsw' \| 'ivfflat' }` | + +## Systemfelder (automatisch auf jedem Objekt eingefügt) + +| Feld | Typ | Hinweise | +|:--|:--|:--| +| `id` | text (ULID) | Primärschlüssel | +| `created_at` | datetime | UTC-Einfügezeit | +| `updated_at` | datetime | UTC-Zeit der letzten Schreiboperation | +| `created_by` | lookup → `user` | wer eingefügt hat | +| `updated_by` | lookup → `user` | wer zuletzt geschrieben hat | +| `version` | integer | Token für optimistische Nebenläufigkeit | + +Diese deklarierst du nicht — deaktiviere sie pro Objekt mit +`ObjectSpec.systemFields: false` (selten eine gute Idee). + +## Wie Felder durch den Stack fließen + +``` +*.object.ts (field spec) + │ + ├─► Postgres / MySQL / SQLite column + index + constraint + ├─► REST: validated on POST/PATCH, exposed on GET + ├─► Console: form widget + list column + ├─► AI Builder: tool argument schema (so the AI knows what to ask) + └─► Audit: change-tracked if `auditTrail: true` +``` + +## Siehe auch + +- [Build → Datenmodell](/docs/build/data-model) — Felder zu Objekten zusammensetzen +- [CEL](./cel) — `expression`, `conditionalRequired`, Validierungen +- [ObjectQL](./objectql) — diese Felder abfragen +- [REST API](./rest-api) — Endpunkte, die sie erzeugen / konsumieren +- [`@objectstack/spec/data/field.zod.ts`](https://github.com/objectstack-ai/framework/blob/main/packages/spec/src/data/field.zod.ts) — maßgebliches Schema diff --git a/content/docs/reference/field-types.es.mdx b/content/docs/reference/field-types.es.mdx new file mode 100644 index 0000000..6a5cfd1 --- /dev/null +++ b/content/docs/reference/field-types.es.mdx @@ -0,0 +1,208 @@ +--- +title: Tipos de campo +description: Cada tipo de campo que puedes declarar en un objeto — qué almacena, qué opciones acepta y cómo se manifiesta en REST, Console y el AI Builder. +--- + +# Tipos de campo + +53 tipos de campo integrados, agrupados por familia. El esquema Zod completo está en +[`packages/spec/src/data/field.zod.ts`](https://github.com/objectstack-ai/framework/blob/main/packages/spec/src/data/field.zod.ts) — esta página es un resumen práctico. + +## Propiedades fundamentales (cada campo) + +| Propiedad | Tipo | Predeterminado | Propósito | +|:--|:--|:--|:--| +| `name` | string (snake_case) | — | Identificador de máquina — segmento de ruta REST, columna SQL | +| `label` | string | — | Etiqueta de visualización en Console | +| `type` | FieldType | — | Consulta las tablas de tipos a continuación | +| `required` | boolean | `false` | Restricción NOT NULL | +| `unique` | boolean | `false` | Índice único | +| `searchable` | boolean | `false` | Indexado para `/api/v1/search` | +| `multiple` | boolean | `false` | Almacena un arreglo de valores | +| `defaultValue` | unknown | — | Valor inicial (literal o CEL) | +| `columnName` | string | = `name` | Sobrescribe la columna física de la BD | +| `hidden` | boolean | `false` | Oculta de las vistas predeterminadas de Console | +| `readonly` | boolean | `false` | Deshabilita en formularios | +| `system` | boolean | `false` | Inyectado automáticamente (id, created_at, …) | +| `index` | boolean | `false` | Crea un índice en la BD | +| `externalId` | boolean | `false` | Apto para upsert mediante clave externa | +| `inlineHelpText` | string | — | Texto de información sobre herramientas / ayuda | +| `conditionalRequired` | predicado `P` | — | Obligatorio cuando el CEL es verdadero | +| `auditTrail` | boolean | `false` | Registra cada cambio en el log de auditoría | +| `encryptionConfig` | object | — | Cifrado a nivel de campo (consulta [Security](./security)) | +| `maskingRule` | string | — | Patrón de enmascaramiento de PII | + +## Familia de texto + +| Tipo | Para qué usarlo | Opciones clave | +|:--|:--|:--| +| `text` | cadenas cortas | `maxLength`, `minLength` | +| `textarea` | varias líneas | `maxLength` | +| `email` | correo electrónico | validado por formato; en minúsculas | +| `url` | URL | validado por formato | +| `phone` | teléfono | E.164 | +| `password` | secretos | con hash; nunca devuelto por GET | +| `markdown` | cuerpo markdown | renderizado en la vista previa de Console | +| `html` | HTML saneado | DOMPurify al escribir | +| `richtext` | WYSIWYG | editor de Console + JSON serializado | + +## Números + +| Tipo | Para qué usarlo | Opciones clave | +|:--|:--|:--| +| `number` | flotantes | `min`, `max`, `precision`, `scale` | +| `currency` | dinero | `currencyConfig: { precision, currencyMode: 'fixed' \| 'dynamic', defaultCurrency }` | +| `percent` | 0–100 % | `min`, `max`, `scale` | + +> `integer` y `decimal` no son tipos separados — usa `number` con +> `scale: 0` para enteros, `precision`+`scale` para decimales fijos. + +## Fecha / hora + +| Tipo | Almacena | Notas | +|:--|:--|:--| +| `date` | fecha de calendario | sin zona horaria | +| `datetime` | instante | UTC | +| `time` | hora del reloj | sin fecha | + +## Lógica + +| Tipo | Notas | +|:--|:--| +| `boolean` | Casilla de verificación | +| `toggle` | Igual que boolean, con interfaz de interruptor | + +## Selección + +| Tipo | Notas | +|:--|:--| +| `select` | Opción única — opciones declaradas en línea o referenciadas desde una lista de selección | +| `multiselect` | Varias opciones, almacenadas como un arreglo | +| `radio` | Alias de interfaz para `select` con renderizado de botones de opción | +| `checkboxes` | Alias de interfaz para `multiselect` con renderizado de casillas de verificación | + +Estructura de las opciones: + +```ts +options: [ + { value: 'low', label: 'Low' }, + { value: 'high', label: 'High', color: '#e02' }, + { value: 'urgent', label: 'Urgent', color: '#c00' } +] +``` + +## Relaciones + +| Tipo | Cardinalidad | Semántica | +|:--|:--|:--| +| `lookup` | muchos a uno | Referencia laxa; eliminar el padre no elimina el hijo de forma predeterminada | +| `master_detail` | muchos a uno, en cascada | El hijo no puede existir sin el padre; los permisos se heredan del padre | +| `tree` | autorreferencia | Jerárquico (parent_id en el mismo objeto) | + +Opciones comunes: + +```ts +{ + type: 'lookup', + reference: 'account', // target object name + referenceFilters: ['status:active'], // narrow the lookup picker + deleteBehavior: 'set_null' // 'set_null' | 'cascade' | 'restrict' +} +``` + +## Calculados + +| Tipo | Qué hace | Opción clave | +|:--|:--|:--| +| `formula` | Valor derivado, evaluado al leer o al recalcular | `expression: F\`record.qty * record.unit_price\`` — consulta [CEL](./cel) | +| `summary` | Acumulación sobre una relación hija | `summaryOperations: { object, field, function }` (`count` \| `sum` \| `avg` \| `min` \| `max`) | +| `autonumber` | Número de visualización autoincremental | `format` (p. ej. `TKT-{0000}`), `startAt` | + +Ejemplo de fórmula: + +```ts +{ + name: 'profit_margin', + type: 'formula', + expression: F`(record.revenue - record.cost) / record.revenue * 100` +} +``` + +## Multimedia + +| Tipo | Para qué usarlo | Opción clave | +|:--|:--|:--| +| `image` | adjuntos de imagen | `fileAttachmentConfig` (ver abajo) | +| `file` | cualquier archivo | igual | +| `avatar` | fotos de perfil | recorte cuadrado, valores predeterminados sensatos | +| `video` | subidas de video | captura de duración + miniatura | +| `audio` | audio | vista previa de forma de onda | + +```ts +fileAttachmentConfig: { + maxSize: 10_000_000, // bytes + allowedTypes: ['image/png','image/jpeg'], + virusScan: true, + storageProvider: 's3', // see Configure → Storage + imageValidation: { minWidth: 200, maxWidth: 4096, generateThumbnails: ['sm','md','lg'] } +} +``` + +## Estructurados + +| Tipo | Almacena | Notas | +|:--|:--|:--| +| `json` | JSON arbitrario | Almacenado como JSONB en Postgres | +| `composite` | subregistro con campos nombrados | Estructura en línea, no una tabla separada | +| `repeater` | arreglo de valores compuestos | Uno a muchos sin un objeto hijo | + +## Interfaz mejorada + +| Tipo | Notas | +|:--|:--| +| `location` | latitud/longitud + precisión | +| `address` | calle / ciudad / región / código postal / país | +| `code` | campo de código fuente — `language`, `theme`, `lineNumbers` | +| `color` | `colorFormat: 'hex' \| 'rgb' \| 'rgba' \| 'hsl'`, `presetColors[]` | +| `rating` | 1–N estrellas — `max`, `icon` | +| `slider` | número acotado con interfaz de control deslizante | +| `signature` | firma dibujada, almacenada como imagen | +| `qrcode` | renderiza el valor como un código QR — `qrErrorCorrection: 'L' \| 'M' \| 'Q' \| 'H'` | +| `barcode` | EAN/UPC/Code128 — `barcodeFormat` | +| `progress` | porcentaje derivado renderizado como una barra | +| `tags` | arreglo de etiquetas de formato libre con autocompletado | +| `vector` | columna de embedding — `vectorConfig: { dimensions, distanceMetric: 'cosine' \| 'euclidean', indexed, indexType: 'hnsw' \| 'ivfflat' }` | + +## Campos del sistema (inyectados automáticamente en cada objeto) + +| Campo | Tipo | Notas | +|:--|:--|:--| +| `id` | text (ULID) | clave primaria | +| `created_at` | datetime | hora de inserción UTC | +| `updated_at` | datetime | hora de última escritura UTC | +| `created_by` | lookup → `user` | quién insertó | +| `updated_by` | lookup → `user` | quién escribió por última vez | +| `version` | integer | token de concurrencia optimista | + +No declaras estos campos — desactívalos por objeto con +`ObjectSpec.systemFields: false` (rara vez es buena idea). + +## Cómo fluyen los campos a través de la pila + +``` +*.object.ts (field spec) + │ + ├─► Postgres / MySQL / SQLite column + index + constraint + ├─► REST: validated on POST/PATCH, exposed on GET + ├─► Console: form widget + list column + ├─► AI Builder: tool argument schema (so the AI knows what to ask) + └─► Audit: change-tracked if `auditTrail: true` +``` + +## Consulta también + +- [Build → Modelo de datos](/docs/build/data-model) — composición de campos en objetos +- [CEL](./cel) — `expression`, `conditionalRequired`, validaciones +- [ObjectQL](./objectql) — consulta de estos campos +- [REST API](./rest-api) — endpoints que los producen / consumen +- [`@objectstack/spec/data/field.zod.ts`](https://github.com/objectstack-ai/framework/blob/main/packages/spec/src/data/field.zod.ts) — esquema autoritativo diff --git a/content/docs/reference/field-types.fr.mdx b/content/docs/reference/field-types.fr.mdx new file mode 100644 index 0000000..cc9bdf2 --- /dev/null +++ b/content/docs/reference/field-types.fr.mdx @@ -0,0 +1,208 @@ +--- +title: Types de champ +description: Chaque type de champ que vous pouvez déclarer sur un objet — ce qu'il stocke, les options qu'il accepte, comment il apparaît dans REST, la Console et l'AI Builder. +--- + +# Types de champ + +53 types de champ intégrés, regroupés par famille. Le schéma Zod complet se trouve dans +[`packages/spec/src/data/field.zod.ts`](https://github.com/objectstack-ai/framework/blob/main/packages/spec/src/data/field.zod.ts) — cette page en est un résumé pratique. + +## Propriétés fondamentales (chaque champ) + +| Propriété | Type | Valeur par défaut | Objectif | +|:--|:--|:--|:--| +| `name` | string (snake_case) | — | Identifiant machine — segment de chemin REST, colonne SQL | +| `label` | string | — | Libellé d'affichage dans la Console | +| `type` | FieldType | — | Voir les tableaux de types ci-dessous | +| `required` | boolean | `false` | Contrainte NOT NULL | +| `unique` | boolean | `false` | Index unique | +| `searchable` | boolean | `false` | Indexé pour `/api/v1/search` | +| `multiple` | boolean | `false` | Stocke un tableau de valeurs | +| `defaultValue` | unknown | — | Valeur initiale (littéral ou CEL) | +| `columnName` | string | = `name` | Remplace la colonne physique en base de données | +| `hidden` | boolean | `false` | Masquer dans les vues Console par défaut | +| `readonly` | boolean | `false` | Désactiver dans les formulaires | +| `system` | boolean | `false` | Injecté automatiquement (id, created_at, …) | +| `index` | boolean | `false` | Créer un index en base de données | +| `externalId` | boolean | `false` | Éligible à l'upsert via clé externe | +| `inlineHelpText` | string | — | Infobulle / texte d'aide | +| `conditionalRequired` | prédicat `P` | — | Requis lorsque le CEL est vrai | +| `auditTrail` | boolean | `false` | Suivre chaque modification dans le journal d'audit | +| `encryptionConfig` | object | — | Chiffrement au niveau du champ (voir [Sécurité](./security)) | +| `maskingRule` | string | — | Modèle de masquage des données personnelles | + +## Famille texte + +| Type | À utiliser pour | Options clés | +|:--|:--|:--| +| `text` | chaînes courtes | `maxLength`, `minLength` | +| `textarea` | multi-ligne | `maxLength` | +| `email` | e-mail | format validé ; mis en minuscules | +| `url` | URL | format validé | +| `phone` | téléphone | E.164 | +| `password` | secrets | haché ; jamais renvoyé par GET | +| `markdown` | corps en markdown | rendu dans l'aperçu de la Console | +| `html` | HTML assaini | DOMPurify à l'écriture | +| `richtext` | WYSIWYG | éditeur Console + JSON sérialisé | + +## Nombres + +| Type | À utiliser pour | Options clés | +|:--|:--|:--| +| `number` | nombres à virgule flottante | `min`, `max`, `precision`, `scale` | +| `currency` | montants | `currencyConfig: { precision, currencyMode: 'fixed' \| 'dynamic', defaultCurrency }` | +| `percent` | 0–100 % | `min`, `max`, `scale` | + +> `integer` et `decimal` ne sont pas des types distincts — utilisez `number` avec +> `scale: 0` pour un entier, `precision`+`scale` pour un décimal fixe. + +## Date / heure + +| Type | Stocke | Remarques | +|:--|:--|:--| +| `date` | date calendaire | sans fuseau horaire | +| `datetime` | instant | UTC | +| `time` | heure d'horloge | sans date | + +## Logique + +| Type | Remarques | +|:--|:--| +| `boolean` | Case à cocher | +| `toggle` | Identique à boolean, interface à interrupteur | + +## Sélection + +| Type | Remarques | +|:--|:--| +| `select` | Choix unique — options déclarées en ligne ou référencées depuis une picklist | +| `multiselect` | Plusieurs choix, stockés sous forme de tableau | +| `radio` | Alias d'interface pour `select` avec rendu en boutons radio | +| `checkboxes` | Alias d'interface pour `multiselect` avec rendu en cases à cocher | + +Forme des options : + +```ts +options: [ + { value: 'low', label: 'Low' }, + { value: 'high', label: 'High', color: '#e02' }, + { value: 'urgent', label: 'Urgent', color: '#c00' } +] +``` + +## Relations + +| Type | Cardinalité | Sémantique | +|:--|:--|:--| +| `lookup` | plusieurs-à-un | Référence souple ; supprimer le parent ne supprime pas l'enfant par défaut | +| `master_detail` | plusieurs-à-un, en cascade | L'enfant ne peut exister sans parent ; les permissions héritent du parent | +| `tree` | auto-référence | Hiérarchique (parent_id sur le même objet) | + +Options courantes : + +```ts +{ + type: 'lookup', + reference: 'account', // target object name + referenceFilters: ['status:active'], // narrow the lookup picker + deleteBehavior: 'set_null' // 'set_null' | 'cascade' | 'restrict' +} +``` + +## Calculé + +| Type | Ce qu'il fait | Option clé | +|:--|:--|:--| +| `formula` | Valeur dérivée, évaluée à la lecture ou au recalcul | `expression: F\`record.qty * record.unit_price\`` — voir [CEL](./cel) | +| `summary` | Agrégation sur une relation enfant | `summaryOperations: { object, field, function }` (`count` \| `sum` \| `avg` \| `min` \| `max`) | +| `autonumber` | Numéro d'affichage auto-incrémenté | `format` (par ex. `TKT-{0000}`), `startAt` | + +Exemple de formule : + +```ts +{ + name: 'profit_margin', + type: 'formula', + expression: F`(record.revenue - record.cost) / record.revenue * 100` +} +``` + +## Média + +| Type | À utiliser pour | Option clé | +|:--|:--|:--| +| `image` | pièces jointes image | `fileAttachmentConfig` (voir ci-dessous) | +| `file` | tout fichier | identique | +| `avatar` | photos de profil | recadrage carré, valeurs par défaut sensées | +| `video` | téléversements vidéo | durée + capture de miniature | +| `audio` | audio | aperçu en forme d'onde | + +```ts +fileAttachmentConfig: { + maxSize: 10_000_000, // bytes + allowedTypes: ['image/png','image/jpeg'], + virusScan: true, + storageProvider: 's3', // see Configure → Storage + imageValidation: { minWidth: 200, maxWidth: 4096, generateThumbnails: ['sm','md','lg'] } +} +``` + +## Structuré + +| Type | Stocke | Remarques | +|:--|:--|:--| +| `json` | JSON arbitraire | Stocké en JSONB sur Postgres | +| `composite` | sous-enregistrement avec champs nommés | Structure en ligne, pas une table séparée | +| `repeater` | tableau de valeurs composites | Un-à-plusieurs sans objet enfant | + +## Interface enrichie + +| Type | Remarques | +|:--|:--| +| `location` | lat/long + précision | +| `address` | rue / ville / région / code postal / pays | +| `code` | champ de code source — `language`, `theme`, `lineNumbers` | +| `color` | `colorFormat: 'hex' \| 'rgb' \| 'rgba' \| 'hsl'`, `presetColors[]` | +| `rating` | 1–N étoiles — `max`, `icon` | +| `slider` | nombre borné avec interface à curseur | +| `signature` | signature dessinée, stockée sous forme d'image | +| `qrcode` | affiche la valeur sous forme de QR — `qrErrorCorrection: 'L' \| 'M' \| 'Q' \| 'H'` | +| `barcode` | EAN/UPC/Code128 — `barcodeFormat` | +| `progress` | pourcentage dérivé affiché sous forme de barre | +| `tags` | tableau de tags libres avec autocomplétion | +| `vector` | colonne d'embedding — `vectorConfig: { dimensions, distanceMetric: 'cosine' \| 'euclidean', indexed, indexType: 'hnsw' \| 'ivfflat' }` | + +## Champs système (injectés automatiquement sur chaque objet) + +| Champ | Type | Remarques | +|:--|:--|:--| +| `id` | text (ULID) | clé primaire | +| `created_at` | datetime | heure d'insertion UTC | +| `updated_at` | datetime | heure de dernière écriture UTC | +| `created_by` | lookup → `user` | qui a inséré | +| `updated_by` | lookup → `user` | qui a écrit en dernier | +| `version` | integer | jeton de concurrence optimiste | + +Vous ne déclarez pas ces champs — désactivez-les par objet avec +`ObjectSpec.systemFields: false` (rarement une bonne idée). + +## Comment les champs circulent à travers la pile + +``` +*.object.ts (field spec) + │ + ├─► Postgres / MySQL / SQLite column + index + constraint + ├─► REST: validated on POST/PATCH, exposed on GET + ├─► Console: form widget + list column + ├─► AI Builder: tool argument schema (so the AI knows what to ask) + └─► Audit: change-tracked if `auditTrail: true` +``` + +## Voir aussi + +- [Build → Modèle de données](/docs/build/data-model) — composer des champs en objets +- [CEL](./cel) — `expression`, `conditionalRequired`, validations +- [ObjectQL](./objectql) — interroger ces champs +- [API REST](./rest-api) — points d'accès qui les produisent / consomment +- [`@objectstack/spec/data/field.zod.ts`](https://github.com/objectstack-ai/framework/blob/main/packages/spec/src/data/field.zod.ts) — schéma de référence diff --git a/content/docs/reference/field-types.ja.mdx b/content/docs/reference/field-types.ja.mdx new file mode 100644 index 0000000..009eede --- /dev/null +++ b/content/docs/reference/field-types.ja.mdx @@ -0,0 +1,208 @@ +--- +title: フィールドタイプ +description: オブジェクトに宣言できるすべてのフィールドタイプ — 何を格納し、どのオプションを受け付け、REST、Console、AI Builder にどう現れるか。 +--- + +# フィールドタイプ + +53 個の組み込みフィールドタイプを、ファミリーごとに分類しています。完全な Zod スキーマは +[`packages/spec/src/data/field.zod.ts`](https://github.com/objectstack-ai/framework/blob/main/packages/spec/src/data/field.zod.ts) にあります — このページは実用的なサマリーです。 + +## コアプロパティ(すべてのフィールド) + +| プロパティ | 型 | デフォルト | 目的 | +|:--|:--|:--|:--| +| `name` | string (snake_case) | — | マシン識別子 — REST パスセグメント、SQL カラム | +| `label` | string | — | Console での表示ラベル | +| `type` | FieldType | — | 下記の型テーブルを参照 | +| `required` | boolean | `false` | NOT NULL 制約 | +| `unique` | boolean | `false` | ユニークインデックス | +| `searchable` | boolean | `false` | `/api/v1/search` 用にインデックス化 | +| `multiple` | boolean | `false` | 値の配列を格納 | +| `defaultValue` | unknown | — | 初期値(リテラルまたは CEL) | +| `columnName` | string | = `name` | 物理 DB カラムを上書き | +| `hidden` | boolean | `false` | デフォルトの Console ビューから非表示 | +| `readonly` | boolean | `false` | フォームで無効化 | +| `system` | boolean | `false` | 自動注入(id, created_at, …) | +| `index` | boolean | `false` | DB インデックスを作成 | +| `externalId` | boolean | `false` | 外部キーによる upsert の対象 | +| `inlineHelpText` | string | — | ツールチップ / ヘルパーテキスト | +| `conditionalRequired` | `P` 述語 | — | CEL が真のとき必須 | +| `auditTrail` | boolean | `false` | すべての変更を監査ログで追跡 | +| `encryptionConfig` | object | — | フィールドレベルの暗号化([Security](./security) を参照) | +| `maskingRule` | string | — | PII マスキングパターン | + +## テキストファミリー + +| 型 | 用途 | 主なオプション | +|:--|:--|:--| +| `text` | 短い文字列 | `maxLength`, `minLength` | +| `textarea` | 複数行 | `maxLength` | +| `email` | メールアドレス | フォーマット検証あり。小文字化される | +| `url` | URL | フォーマット検証あり | +| `phone` | 電話番号 | E.164 | +| `password` | シークレット | ハッシュ化され、GET では返されない | +| `markdown` | markdown 本文 | Console プレビューでレンダリング | +| `html` | サニタイズ済み HTML | 書き込み時に DOMPurify を適用 | +| `richtext` | WYSIWYG | Console エディタ + シリアライズされた JSON | + +## 数値 + +| 型 | 用途 | 主なオプション | +|:--|:--|:--| +| `number` | 浮動小数点 | `min`, `max`, `precision`, `scale` | +| `currency` | 金額 | `currencyConfig: { precision, currencyMode: 'fixed' \| 'dynamic', defaultCurrency }` | +| `percent` | 0〜100 % | `min`, `max`, `scale` | + +> `integer` と `decimal` は別の型ではありません。整数には `scale: 0` を指定した `number`、 +> 固定小数には `precision`+`scale` を指定した `number` を使用してください。 + +## 日付 / 時刻 + +| 型 | 格納するもの | 備考 | +|:--|:--|:--| +| `date` | カレンダー日付 | タイムゾーンなし | +| `datetime` | 瞬間 | UTC | +| `time` | 壁時計の時刻 | 日付なし | + +## ロジック + +| 型 | 備考 | +|:--|:--| +| `boolean` | チェックボックス | +| `toggle` | boolean と同じ。スイッチ UI | + +## 選択 + +| 型 | 備考 | +|:--|:--| +| `select` | 単一選択 — オプションをインラインで宣言するか、picklist から参照 | +| `multiselect` | 複数選択。配列として格納 | +| `radio` | ラジオ表示の `select` の UI エイリアス | +| `checkboxes` | チェックボックス表示の `multiselect` の UI エイリアス | + +オプションの形: + +```ts +options: [ + { value: 'low', label: 'Low' }, + { value: 'high', label: 'High', color: '#e02' }, + { value: 'urgent', label: 'Urgent', color: '#c00' } +] +``` + +## リレーション + +| 型 | 多重度 | セマンティクス | +|:--|:--|:--| +| `lookup` | 多対一 | 緩い参照。親を削除してもデフォルトでは子は削除されない | +| `master_detail` | 多対一、カスケード | 親なしには子が存在できない。権限は親から継承される | +| `tree` | 自己参照 | 階層構造(同じオブジェクト上の parent_id) | + +共通オプション: + +```ts +{ + type: 'lookup', + reference: 'account', // target object name + referenceFilters: ['status:active'], // narrow the lookup picker + deleteBehavior: 'set_null' // 'set_null' | 'cascade' | 'restrict' +} +``` + +## 算出 + +| 型 | 機能 | 主なオプション | +|:--|:--|:--| +| `formula` | 導出値。読み取り時または再計算時に評価される | `expression: F\`record.qty * record.unit_price\`` — [CEL](./cel) を参照 | +| `summary` | 子リレーションのロールアップ | `summaryOperations: { object, field, function }`(`count` \| `sum` \| `avg` \| `min` \| `max`) | +| `autonumber` | 自動採番される表示番号 | `format`(例: `TKT-{0000}`)、`startAt` | + +Formula の例: + +```ts +{ + name: 'profit_margin', + type: 'formula', + expression: F`(record.revenue - record.cost) / record.revenue * 100` +} +``` + +## メディア + +| 型 | 用途 | 主なオプション | +|:--|:--|:--| +| `image` | 画像添付 | `fileAttachmentConfig`(下記参照) | +| `file` | 任意のファイル | 同上 | +| `avatar` | プロフィール画像 | 正方形クロップ、適切なデフォルト | +| `video` | 動画アップロード | 再生時間 + サムネイルキャプチャ | +| `audio` | 音声 | 波形プレビュー | + +```ts +fileAttachmentConfig: { + maxSize: 10_000_000, // bytes + allowedTypes: ['image/png','image/jpeg'], + virusScan: true, + storageProvider: 's3', // see Configure → Storage + imageValidation: { minWidth: 200, maxWidth: 4096, generateThumbnails: ['sm','md','lg'] } +} +``` + +## 構造化 + +| 型 | 格納するもの | 備考 | +|:--|:--|:--| +| `json` | 任意の JSON | Postgres では JSONB として格納 | +| `composite` | 名前付きフィールドを持つサブレコード | インライン構造体。別テーブルではない | +| `repeater` | composite 値の配列 | 子オブジェクトなしの一対多 | + +## 拡張 UI + +| 型 | 備考 | +|:--|:--| +| `location` | 緯度/経度 + 精度 | +| `address` | 番地 / 市区町村 / 地域 / 郵便番号 / 国 | +| `code` | ソースコードフィールド — `language`, `theme`, `lineNumbers` | +| `color` | `colorFormat: 'hex' \| 'rgb' \| 'rgba' \| 'hsl'`, `presetColors[]` | +| `rating` | 1〜N 個の星 — `max`, `icon` | +| `slider` | スライダー UI を持つ範囲付き数値 | +| `signature` | 手書き署名。画像として格納 | +| `qrcode` | 値を QR としてレンダリング — `qrErrorCorrection: 'L' \| 'M' \| 'Q' \| 'H'` | +| `barcode` | EAN/UPC/Code128 — `barcodeFormat` | +| `progress` | 導出されたパーセントをバーとして表示 | +| `tags` | オートコンプリート付きの自由形式タグ配列 | +| `vector` | 埋め込みカラム — `vectorConfig: { dimensions, distanceMetric: 'cosine' \| 'euclidean', indexed, indexType: 'hnsw' \| 'ivfflat' }` | + +## システムフィールド(すべてのオブジェクトに自動注入) + +| フィールド | 型 | 備考 | +|:--|:--|:--| +| `id` | text (ULID) | 主キー | +| `created_at` | datetime | UTC の挿入時刻 | +| `updated_at` | datetime | UTC の最終書き込み時刻 | +| `created_by` | lookup → `user` | 挿入したユーザー | +| `updated_by` | lookup → `user` | 最後に書き込んだユーザー | +| `version` | integer | 楽観的並行性トークン | + +これらは宣言しません — オブジェクトごとに +`ObjectSpec.systemFields: false` でオプトアウトできます(推奨されることはほとんどありません)。 + +## フィールドがスタックを流れる仕組み + +``` +*.object.ts (field spec) + │ + ├─► Postgres / MySQL / SQLite column + index + constraint + ├─► REST: validated on POST/PATCH, exposed on GET + ├─► Console: form widget + list column + ├─► AI Builder: tool argument schema (so the AI knows what to ask) + └─► Audit: change-tracked if `auditTrail: true` +``` + +## 関連項目 + +- [Build → Data model](/docs/build/data-model) — フィールドをオブジェクトに組み立てる +- [CEL](./cel) — `expression`、`conditionalRequired`、検証 +- [ObjectQL](./objectql) — これらのフィールドへのクエリ +- [REST API](./rest-api) — それらを生成 / 消費するエンドポイント +- [`@objectstack/spec/data/field.zod.ts`](https://github.com/objectstack-ai/framework/blob/main/packages/spec/src/data/field.zod.ts) — 正式なスキーマ diff --git a/content/docs/reference/field-types.cn.mdx b/content/docs/reference/field-types.zh-Hans.mdx similarity index 100% rename from content/docs/reference/field-types.cn.mdx rename to content/docs/reference/field-types.zh-Hans.mdx diff --git a/content/docs/reference/meta.de.json b/content/docs/reference/meta.de.json new file mode 100644 index 0000000..1b2e953 --- /dev/null +++ b/content/docs/reference/meta.de.json @@ -0,0 +1,15 @@ +{ + "title": "Referenz", + "defaultOpen": false, + "pages": [ + "rest-api", + "objectql", + "cel", + "field-types", + "skills-cli", + "cli", + "environment-variables", + "runtime-capabilities", + "security" + ] +} diff --git a/content/docs/reference/meta.es.json b/content/docs/reference/meta.es.json new file mode 100644 index 0000000..c176174 --- /dev/null +++ b/content/docs/reference/meta.es.json @@ -0,0 +1,15 @@ +{ + "title": "Referencia", + "defaultOpen": false, + "pages": [ + "rest-api", + "objectql", + "cel", + "field-types", + "skills-cli", + "cli", + "environment-variables", + "runtime-capabilities", + "security" + ] +} diff --git a/content/docs/reference/meta.fr.json b/content/docs/reference/meta.fr.json new file mode 100644 index 0000000..fbecb8c --- /dev/null +++ b/content/docs/reference/meta.fr.json @@ -0,0 +1,15 @@ +{ + "title": "Référence", + "defaultOpen": false, + "pages": [ + "rest-api", + "objectql", + "cel", + "field-types", + "skills-cli", + "cli", + "environment-variables", + "runtime-capabilities", + "security" + ] +} diff --git a/content/docs/reference/meta.ja.json b/content/docs/reference/meta.ja.json new file mode 100644 index 0000000..f4112a4 --- /dev/null +++ b/content/docs/reference/meta.ja.json @@ -0,0 +1,15 @@ +{ + "title": "リファレンス", + "defaultOpen": false, + "pages": [ + "rest-api", + "objectql", + "cel", + "field-types", + "skills-cli", + "cli", + "environment-variables", + "runtime-capabilities", + "security" + ] +} diff --git a/content/docs/reference/meta.cn.json b/content/docs/reference/meta.zh-Hans.json similarity index 100% rename from content/docs/reference/meta.cn.json rename to content/docs/reference/meta.zh-Hans.json diff --git a/content/docs/reference/objectql.de.mdx b/content/docs/reference/objectql.de.mdx new file mode 100644 index 0000000..9df223c --- /dev/null +++ b/content/docs/reference/objectql.de.mdx @@ -0,0 +1,216 @@ +--- +title: ObjectQL +description: Das strukturierte Abfrageformat, das von /api/v1/data/*, Views, Reports und KI-Tools verwendet wird. +--- + +# ObjectQL + +ObjectQL ist das JSON-Abfrageformat, das die Daten-Engine verarbeitet. Es ist das, +was `/api/v1/data/:object` akzeptiert, wozu Views kompiliert werden, wozu Reports +serialisiert werden und was das KI-Tool `query_data` erzeugt. + +Zwei Formen: + +- **Einfache Liste** — `where`, `orderBy`, `limit`, `expand` usw. als + Query-String-Parameter an `GET /api/v1/data/:object` übergeben. +- **Erweiterte Abfrage** — den vollständigen Abfragekörper an + `/api/v1/data/:object/query` per POST senden (erforderlich für `groupBy` und + `aggregations`). + +## Abfrageform + +```ts +{ + object: string, // required — target object name + fields?: string[], // projection (default: all visible fields) + where?: FilterCondition, // see Filters + orderBy?: SortNode[], // [{ field, order: 'asc' | 'desc' }] + limit?: number, // page size + offset?: number, // offset pagination + cursor?: string, // cursor pagination (preferred) + expand?: string[], // batch-resolve relation fields + joins?: JoinNode[], // explicit joins (inner | left | right | full) + groupBy?: (string | GroupByNode)[], + aggregations?: AggregationNode[], // sum/avg/count/min/max/... + having?: FilterCondition, // filter after aggregation + distinct?: boolean +} +``` + +Schema-Quelle: [`packages/spec/src/data/query.zod.ts`](https://github.com/objectstack-ai/framework/blob/main/packages/spec/src/data/query.zod.ts). + +## Filter + +`where` ist ein Baum von Bedingungen. Feldoperatoren werden mit +`$` präfixiert; logische Verknüpfungen (`$and`, `$or`, `$not`) stehen auf der obersten Ebene. + +### Vergleich + +| Operator | Beispiel | Hinweise | +|:--|:--|:--| +| `$eq` | `{ status: { $eq: "open" } }` | Gleichheit | +| `$ne` | `{ priority: { $ne: "low" } }` | Ungleichheit | +| `$gt`, `$gte`, `$lt`, `$lte` | `{ amount: { $gte: 1000 } }` | Vergleiche | + +Alle Vergleichsoperatoren akzeptieren auch eine **Feldreferenz** für +feldübergreifende Vergleiche: `{ end_at: { $gt: { $field: "start_at" } } }`. + +### Menge & Bereich + +| Operator | Beispiel | +|:--|:--| +| `$in` | `{ status: { $in: ["new","open"] } }` | +| `$nin` | `{ owner_id: { $nin: ["u_1","u_2"] } }` | +| `$between` | `{ created_at: { $between: ["2026-01-01","2026-02-01"] } }` | + +### Zeichenkette + +| Operator | Beispiel | Hinweise | +|:--|:--|:--| +| `$contains` | `{ subject: { $contains: "refund" } }` | Groß-/Kleinschreibung wird ignoriert | +| `$notContains` | `{ notes: { $notContains: "test" } }` | | +| `$startsWith` | `{ email: { $startsWith: "@" } }` | | +| `$endsWith` | `{ email: { $endsWith: "@acme.com" } }` | | + +### Null & Existenz + +| Operator | Beispiel | +|:--|:--| +| `$null` | `{ closed_at: { $null: true } }` | +| `$exists` | `{ external_id: { $exists: false } }` | + +### Logische Verknüpfungen + +```jsonc +{ + "$and": [ + { "status": { "$eq": "open" } }, + { + "$or": [ + { "priority": { "$in": ["high", "urgent"] } }, + { "due_at": { "$lt": { "$cel": "now()" } } } + ] + } + ] +} +``` + +CEL-Ausdrücke können mit `{ "$cel": "..." }` eingebettet werden — nützlich für +„zeitrelative" Filter, die der Server zur Abfragezeit auswertet. + +## Sortierung + +```jsonc +"orderBy": [ + { "field": "priority", "order": "desc" }, + { "field": "created_at", "order": "asc" } +] +``` + +Query-String-Kurzform: `?orderBy=-priority,created_at`. + +## Paginierung + +**Cursor (empfohlen).** Die Antwort enthält `nextCursor`; gib ihn +bei der nächsten Anfrage als `cursor` zurück. + +```http +GET /api/v1/data/ticket?limit=50&orderBy=-created_at +→ { items: [...], nextCursor: "eyJ..." } + +GET /api/v1/data/ticket?limit=50&cursor=eyJ... +``` + +**Offset.** Einfacher, verschlechtert sich aber bei großen Tabellen. + +```http +GET /api/v1/data/ticket?limit=50&offset=200 +``` + +Die Laufzeitumgebung begrenzt `limit` pro Objekt über `ObjectSpec.maxPageSize` +(Standard 200). + +## Relationen — `expand` + +`expand` löst Fremdschlüssel im Stapel auf, sodass keine N+1-Abfragen entstehen. + +```jsonc +{ + "object": "support_ticket", + "expand": ["assignee", "customer.account"], + "limit": 20 +} +``` + +Liefert jedes Ticket mit `assignee` und `customer.account` als +verschachtelte Objekte zurück, statt nur als IDs. + +## Joins + +Für Ad-hoc-Joins außerhalb des Metadaten-Graphen: + +```jsonc +"joins": [ + { "type": "left", "object": "user", "as": "u", "on": "assignee_id = u.id" } +] +``` + +`type`: `inner` | `left` | `right` | `full`. Verbundene Tabellen sind +in `where`, `orderBy` und `aggregations` über den `as`-Alias +zugänglich. + +## Aggregation + +Nur `POST /api/v1/data/:object/query`. + +```jsonc +{ + "object": "order", + "where": { "status": { "$ne": "cancelled" } }, + "groupBy": [ + "customer_id", + { "field": "created_at", "dateGranularity": "month" } + ], + "aggregations": [ + { "function": "sum", "field": "amount", "alias": "total_sales" }, + { "function": "count", "alias": "order_count" } + ], + "having": { "total_sales": { "$gt": 10000 } }, + "orderBy": [{ "field": "total_sales", "order": "desc" }], + "limit": 25 +} +``` + +**Funktionen:** `count`, `sum`, `avg`, `min`, `max`, `count_distinct`, +`array_agg`, `string_agg`. + +**Datumsgranularität** (für zeitlich gebucketete Gruppierung): +`day` | `week` | `month` | `quarter` | `year`. + +## Distinct + +```jsonc +{ "object": "ticket", "fields": ["status"], "distinct": true } +``` + +## Suche + +Die Volltextsuche über `searchable: true`-Felder wird unter +`GET /api/v1/search?q=...&object=ticket` bereitgestellt. Objektspezifische Scoring-Regeln +werden in der Objekt-Spezifikation konfiguriert. + +## Wo ObjectQL zum Einsatz kommt + +- `GET /api/v1/data/:object` — Query-String-Form +- `POST /api/v1/data/:object/query` — vollständiger Körper, unterstützt Aggregationen +- View-Definitionen (`filter`, `sort`) — werden zu ObjectQL kompiliert +- Reports — werden zu ObjectQL serialisiert +- Das KI-Tool `query_data` — erzeugt einen ObjectQL-Körper für die + Freigabe-Warteschlange + +## Siehe auch + +- [REST API](./rest-api) — Endpunkte, die ObjectQL verarbeiten +- [Field types](./field-types) — was abfragbar ist +- [CEL](./cel) — Ausdruckssprache, die in `$cel`-Filtern verwendet wird +- [`@objectstack/spec/data/query.zod.ts`](https://github.com/objectstack-ai/framework/blob/main/packages/spec/src/data/query.zod.ts) — maßgebliches Schema diff --git a/content/docs/reference/objectql.es.mdx b/content/docs/reference/objectql.es.mdx new file mode 100644 index 0000000..6e4fa9f --- /dev/null +++ b/content/docs/reference/objectql.es.mdx @@ -0,0 +1,215 @@ +--- +title: ObjectQL +description: El formato de consulta estructurado que usan /api/v1/data/*, las vistas, los informes y las herramientas de IA. +--- + +# ObjectQL + +ObjectQL es el formato de consulta JSON que consume el motor de datos. Es lo que +acepta `/api/v1/data/:object`, lo que compilan las vistas, lo que serializan los informes +y lo que produce la herramienta de IA `query_data`. + +Dos formas: + +- **Lista simple** — pasa `where`, `orderBy`, `limit`, `expand`, etc. como + parámetros de cadena de consulta a `GET /api/v1/data/:object`. +- **Consulta avanzada** — envía mediante POST el cuerpo completo de la consulta a + `/api/v1/data/:object/query` (obligatorio para `groupBy` y + `aggregations`). + +## Forma de la consulta + +```ts +{ + object: string, // required — target object name + fields?: string[], // projection (default: all visible fields) + where?: FilterCondition, // see Filters + orderBy?: SortNode[], // [{ field, order: 'asc' | 'desc' }] + limit?: number, // page size + offset?: number, // offset pagination + cursor?: string, // cursor pagination (preferred) + expand?: string[], // batch-resolve relation fields + joins?: JoinNode[], // explicit joins (inner | left | right | full) + groupBy?: (string | GroupByNode)[], + aggregations?: AggregationNode[], // sum/avg/count/min/max/... + having?: FilterCondition, // filter after aggregation + distinct?: boolean +} +``` + +Origen del esquema: [`packages/spec/src/data/query.zod.ts`](https://github.com/objectstack-ai/framework/blob/main/packages/spec/src/data/query.zod.ts). + +## Filtros + +`where` es un árbol de condiciones. Los operadores de campo llevan el prefijo +`$`; los combinadores lógicos (`$and`, `$or`, `$not`) se ubican en el nivel superior. + +### Comparación + +| Operador | Ejemplo | Notas | +|:--|:--|:--| +| `$eq` | `{ status: { $eq: "open" } }` | Igualdad | +| `$ne` | `{ priority: { $ne: "low" } }` | Desigualdad | +| `$gt`, `$gte`, `$lt`, `$lte` | `{ amount: { $gte: 1000 } }` | Comparaciones | + +Todos los operadores de comparación también aceptan una **referencia de campo** para +la comparación entre campos: `{ end_at: { $gt: { $field: "start_at" } } }`. + +### Conjunto y rango + +| Operador | Ejemplo | +|:--|:--| +| `$in` | `{ status: { $in: ["new","open"] } }` | +| `$nin` | `{ owner_id: { $nin: ["u_1","u_2"] } }` | +| `$between` | `{ created_at: { $between: ["2026-01-01","2026-02-01"] } }` | + +### Cadena + +| Operador | Ejemplo | Notas | +|:--|:--|:--| +| `$contains` | `{ subject: { $contains: "refund" } }` | No distingue mayúsculas/minúsculas | +| `$notContains` | `{ notes: { $notContains: "test" } }` | | +| `$startsWith` | `{ email: { $startsWith: "@" } }` | | +| `$endsWith` | `{ email: { $endsWith: "@acme.com" } }` | | + +### Nulo y existencia + +| Operador | Ejemplo | +|:--|:--| +| `$null` | `{ closed_at: { $null: true } }` | +| `$exists` | `{ external_id: { $exists: false } }` | + +### Combinadores lógicos + +```jsonc +{ + "$and": [ + { "status": { "$eq": "open" } }, + { + "$or": [ + { "priority": { "$in": ["high", "urgent"] } }, + { "due_at": { "$lt": { "$cel": "now()" } } } + ] + } + ] +} +``` + +Las expresiones CEL se pueden incrustar con `{ "$cel": "..." }` — útil para +filtros "relativos a ahora" que el servidor evalúa en el momento de la consulta. + +## Ordenación + +```jsonc +"orderBy": [ + { "field": "priority", "order": "desc" }, + { "field": "created_at", "order": "asc" } +] +``` + +Forma abreviada en cadena de consulta: `?orderBy=-priority,created_at`. + +## Paginación + +**Cursor (recomendado).** La respuesta incluye `nextCursor`; pásalo +de vuelta como `cursor` en la siguiente solicitud. + +```http +GET /api/v1/data/ticket?limit=50&orderBy=-created_at +→ { items: [...], nextCursor: "eyJ..." } + +GET /api/v1/data/ticket?limit=50&cursor=eyJ... +``` + +**Offset.** Más sencillo pero se degrada en tablas grandes. + +```http +GET /api/v1/data/ticket?limit=50&offset=200 +``` + +El runtime limita el `limit` por objeto mediante `ObjectSpec.maxPageSize` +(valor predeterminado 200). + +## Relaciones — `expand` + +`expand` resuelve por lotes las claves foráneas para que no incurras en N+1. + +```jsonc +{ + "object": "support_ticket", + "expand": ["assignee", "customer.account"], + "limit": 20 +} +``` + +Devuelve cada ticket con `assignee` y `customer.account` materializados +como objetos anidados en lugar de solo los ID. + +## Joins + +Para joins ad-hoc fuera del grafo de metadatos: + +```jsonc +"joins": [ + { "type": "left", "object": "user", "as": "u", "on": "assignee_id = u.id" } +] +``` + +`type`: `inner` | `left` | `right` | `full`. Las tablas unidas son +accesibles en `where`, `orderBy` y `aggregations` mediante el alias `as`. + +## Agregación + +Solo `POST /api/v1/data/:object/query`. + +```jsonc +{ + "object": "order", + "where": { "status": { "$ne": "cancelled" } }, + "groupBy": [ + "customer_id", + { "field": "created_at", "dateGranularity": "month" } + ], + "aggregations": [ + { "function": "sum", "field": "amount", "alias": "total_sales" }, + { "function": "count", "alias": "order_count" } + ], + "having": { "total_sales": { "$gt": 10000 } }, + "orderBy": [{ "field": "total_sales", "order": "desc" }], + "limit": 25 +} +``` + +**Funciones:** `count`, `sum`, `avg`, `min`, `max`, `count_distinct`, +`array_agg`, `string_agg`. + +**Granularidad de fecha** (para agrupaciones por intervalos de tiempo): +`day` | `week` | `month` | `quarter` | `year`. + +## Distinct + +```jsonc +{ "object": "ticket", "fields": ["status"], "distinct": true } +``` + +## Búsqueda + +La búsqueda de texto completo en los campos con `searchable: true` se expone en +`GET /api/v1/search?q=...&object=ticket`. Las reglas de puntuación por objeto se +configuran en la especificación del objeto. + +## Dónde aparece ObjectQL + +- `GET /api/v1/data/:object` — forma en cadena de consulta +- `POST /api/v1/data/:object/query` — cuerpo completo, admite agregaciones +- Definiciones de vistas (`filter`, `sort`) — compilan a ObjectQL +- Informes — serializan a ObjectQL +- La herramienta de IA `query_data` — produce un cuerpo ObjectQL para la + cola de aprobación + +## Véase también + +- [REST API](./rest-api) — endpoints que consumen ObjectQL +- [Field types](./field-types) — qué es consultable +- [CEL](./cel) — lenguaje de expresiones usado dentro de los filtros `$cel` +- [`@objectstack/spec/data/query.zod.ts`](https://github.com/objectstack-ai/framework/blob/main/packages/spec/src/data/query.zod.ts) — esquema autoritativo diff --git a/content/docs/reference/objectql.fr.mdx b/content/docs/reference/objectql.fr.mdx new file mode 100644 index 0000000..3600ecb --- /dev/null +++ b/content/docs/reference/objectql.fr.mdx @@ -0,0 +1,215 @@ +--- +title: ObjectQL +description: Le format de requête structuré utilisé par /api/v1/data/*, les vues, les rapports et les outils d'IA. +--- + +# ObjectQL + +ObjectQL est le format de requête JSON consommé par le moteur de données. C'est ce que +`/api/v1/data/:object` accepte, ce vers quoi les vues sont compilées, ce que les rapports +sérialisent, et ce que l'outil d'IA `query_data` produit. + +Deux formes : + +- **Liste simple** — passez `where`, `orderBy`, `limit`, `expand` etc. comme + paramètres de chaîne de requête à `GET /api/v1/data/:object`. +- **Requête avancée** — envoyez le corps de requête complet en POST vers + `/api/v1/data/:object/query` (requis pour `groupBy` et + `aggregations`). + +## Forme de la requête + +```ts +{ + object: string, // required — target object name + fields?: string[], // projection (default: all visible fields) + where?: FilterCondition, // see Filters + orderBy?: SortNode[], // [{ field, order: 'asc' | 'desc' }] + limit?: number, // page size + offset?: number, // offset pagination + cursor?: string, // cursor pagination (preferred) + expand?: string[], // batch-resolve relation fields + joins?: JoinNode[], // explicit joins (inner | left | right | full) + groupBy?: (string | GroupByNode)[], + aggregations?: AggregationNode[], // sum/avg/count/min/max/... + having?: FilterCondition, // filter after aggregation + distinct?: boolean +} +``` + +Source du schéma : [`packages/spec/src/data/query.zod.ts`](https://github.com/objectstack-ai/framework/blob/main/packages/spec/src/data/query.zod.ts). + +## Filtres + +`where` est un arbre de conditions. Les opérateurs de champ sont préfixés par +`$` ; les combinateurs logiques (`$and`, `$or`, `$not`) se situent au niveau supérieur. + +### Comparaison + +| Opérateur | Exemple | Notes | +|:--|:--|:--| +| `$eq` | `{ status: { $eq: "open" } }` | Égalité | +| `$ne` | `{ priority: { $ne: "low" } }` | Inégalité | +| `$gt`, `$gte`, `$lt`, `$lte` | `{ amount: { $gte: 1000 } }` | Comparaisons | + +Tous les opérateurs de comparaison acceptent aussi une **référence de champ** pour +la comparaison inter-champs : `{ end_at: { $gt: { $field: "start_at" } } }`. + +### Ensemble et intervalle + +| Opérateur | Exemple | +|:--|:--| +| `$in` | `{ status: { $in: ["new","open"] } }` | +| `$nin` | `{ owner_id: { $nin: ["u_1","u_2"] } }` | +| `$between` | `{ created_at: { $between: ["2026-01-01","2026-02-01"] } }` | + +### Chaîne de caractères + +| Opérateur | Exemple | Notes | +|:--|:--|:--| +| `$contains` | `{ subject: { $contains: "refund" } }` | Insensible à la casse | +| `$notContains` | `{ notes: { $notContains: "test" } }` | | +| `$startsWith` | `{ email: { $startsWith: "@" } }` | | +| `$endsWith` | `{ email: { $endsWith: "@acme.com" } }` | | + +### Null et existence + +| Opérateur | Exemple | +|:--|:--| +| `$null` | `{ closed_at: { $null: true } }` | +| `$exists` | `{ external_id: { $exists: false } }` | + +### Combinateurs logiques + +```jsonc +{ + "$and": [ + { "status": { "$eq": "open" } }, + { + "$or": [ + { "priority": { "$in": ["high", "urgent"] } }, + { "due_at": { "$lt": { "$cel": "now()" } } } + ] + } + ] +} +``` + +Les expressions CEL peuvent être intégrées avec `{ "$cel": "..." }` — utile pour +les filtres « relatifs à maintenant » que le serveur évalue au moment de la requête. + +## Tri + +```jsonc +"orderBy": [ + { "field": "priority", "order": "desc" }, + { "field": "created_at", "order": "asc" } +] +``` + +Forme abrégée en chaîne de requête : `?orderBy=-priority,created_at`. + +## Pagination + +**Curseur (recommandé).** La réponse inclut `nextCursor` ; renvoyez-le +en tant que `cursor` sur la requête suivante. + +```http +GET /api/v1/data/ticket?limit=50&orderBy=-created_at +→ { items: [...], nextCursor: "eyJ..." } + +GET /api/v1/data/ticket?limit=50&cursor=eyJ... +``` + +**Décalage.** Plus simple, mais se dégrade sur les grandes tables. + +```http +GET /api/v1/data/ticket?limit=50&offset=200 +``` + +Le runtime plafonne `limit` par objet via `ObjectSpec.maxPageSize` +(par défaut 200). + +## Relations — `expand` + +`expand` résout les clés étrangères par lots pour éviter le N+1. + +```jsonc +{ + "object": "support_ticket", + "expand": ["assignee", "customer.account"], + "limit": 20 +} +``` + +Renvoie chaque ticket avec `assignee` et `customer.account` matérialisés +sous forme d'objets imbriqués au lieu de simples identifiants. + +## Jointures + +Pour les jointures ad hoc en dehors du graphe de métadonnées : + +```jsonc +"joins": [ + { "type": "left", "object": "user", "as": "u", "on": "assignee_id = u.id" } +] +``` + +`type` : `inner` | `left` | `right` | `full`. Les tables jointes sont +accessibles dans `where`, `orderBy` et `aggregations` via l'alias `as`. + +## Agrégation + +`POST /api/v1/data/:object/query` uniquement. + +```jsonc +{ + "object": "order", + "where": { "status": { "$ne": "cancelled" } }, + "groupBy": [ + "customer_id", + { "field": "created_at", "dateGranularity": "month" } + ], + "aggregations": [ + { "function": "sum", "field": "amount", "alias": "total_sales" }, + { "function": "count", "alias": "order_count" } + ], + "having": { "total_sales": { "$gt": 10000 } }, + "orderBy": [{ "field": "total_sales", "order": "desc" }], + "limit": 25 +} +``` + +**Fonctions :** `count`, `sum`, `avg`, `min`, `max`, `count_distinct`, +`array_agg`, `string_agg`. + +**Granularité temporelle** (pour le regroupement par tranches de temps) : +`day` | `week` | `month` | `quarter` | `year`. + +## Distinct + +```jsonc +{ "object": "ticket", "fields": ["status"], "distinct": true } +``` + +## Recherche + +La recherche en texte intégral sur les champs `searchable: true` est exposée à +`GET /api/v1/search?q=...&object=ticket`. Les règles de scoring par objet +sont configurées sur le spec de l'objet. + +## Où ObjectQL apparaît + +- `GET /api/v1/data/:object` — forme en chaîne de requête +- `POST /api/v1/data/:object/query` — corps complet, prend en charge les agrégations +- Définitions de vues (`filter`, `sort`) — compilées en ObjectQL +- Rapports — sérialisés en ObjectQL +- L'outil d'IA `query_data` — produit un corps ObjectQL pour la + file d'attente d'approbation + +## Voir aussi + +- [REST API](./rest-api) — points de terminaison qui consomment ObjectQL +- [Field types](./field-types) — ce qui est interrogeable +- [CEL](./cel) — langage d'expression utilisé dans les filtres `$cel` +- [`@objectstack/spec/data/query.zod.ts`](https://github.com/objectstack-ai/framework/blob/main/packages/spec/src/data/query.zod.ts) — schéma faisant autorité diff --git a/content/docs/reference/objectql.ja.mdx b/content/docs/reference/objectql.ja.mdx new file mode 100644 index 0000000..71a4725 --- /dev/null +++ b/content/docs/reference/objectql.ja.mdx @@ -0,0 +1,215 @@ +--- +title: ObjectQL +description: /api/v1/data/* 、ビュー、レポート、AI ツールで使用される構造化クエリ形式。 +--- + +# ObjectQL + +ObjectQL は、データエンジンが消費する JSON クエリ形式です。 +`/api/v1/data/:object` が受け付けるもの、ビューがコンパイルされる先、レポートが +シリアライズされる形式、そして AI の `query_data` ツールが生成するものです。 + +2 つの形式があります: + +- **シンプルリスト** — `where`、`orderBy`、`limit`、`expand` などを + `GET /api/v1/data/:object` のクエリ文字列パラメータとして渡します。 +- **アドバンスドクエリ** — 完全なクエリボディを + `/api/v1/data/:object/query` に POST します(`groupBy` と + `aggregations` には必須)。 + +## クエリの形式 + +```ts +{ + object: string, // required — target object name + fields?: string[], // projection (default: all visible fields) + where?: FilterCondition, // see Filters + orderBy?: SortNode[], // [{ field, order: 'asc' | 'desc' }] + limit?: number, // page size + offset?: number, // offset pagination + cursor?: string, // cursor pagination (preferred) + expand?: string[], // batch-resolve relation fields + joins?: JoinNode[], // explicit joins (inner | left | right | full) + groupBy?: (string | GroupByNode)[], + aggregations?: AggregationNode[], // sum/avg/count/min/max/... + having?: FilterCondition, // filter after aggregation + distinct?: boolean +} +``` + +スキーマのソース: [`packages/spec/src/data/query.zod.ts`](https://github.com/objectstack-ai/framework/blob/main/packages/spec/src/data/query.zod.ts)。 + +## フィルター + +`where` は条件のツリーです。フィールド演算子には +`$` のプレフィックスが付きます。論理結合子(`$and`、`$or`、`$not`)はトップレベルに配置されます。 + +### 比較 + +| 演算子 | 例 | 備考 | +|:--|:--|:--| +| `$eq` | `{ status: { $eq: "open" } }` | 等価 | +| `$ne` | `{ priority: { $ne: "low" } }` | 不等価 | +| `$gt`, `$gte`, `$lt`, `$lte` | `{ amount: { $gte: 1000 } }` | 比較 | + +すべての比較演算子は、フィールド間比較のための**フィールド参照**も受け付けます: +`{ end_at: { $gt: { $field: "start_at" } } }`。 + +### 集合と範囲 + +| 演算子 | 例 | +|:--|:--| +| `$in` | `{ status: { $in: ["new","open"] } }` | +| `$nin` | `{ owner_id: { $nin: ["u_1","u_2"] } }` | +| `$between` | `{ created_at: { $between: ["2026-01-01","2026-02-01"] } }` | + +### 文字列 + +| 演算子 | 例 | 備考 | +|:--|:--|:--| +| `$contains` | `{ subject: { $contains: "refund" } }` | 大文字小文字を区別しない | +| `$notContains` | `{ notes: { $notContains: "test" } }` | | +| `$startsWith` | `{ email: { $startsWith: "@" } }` | | +| `$endsWith` | `{ email: { $endsWith: "@acme.com" } }` | | + +### Null と存在 + +| 演算子 | 例 | +|:--|:--| +| `$null` | `{ closed_at: { $null: true } }` | +| `$exists` | `{ external_id: { $exists: false } }` | + +### 論理結合子 + +```jsonc +{ + "$and": [ + { "status": { "$eq": "open" } }, + { + "$or": [ + { "priority": { "$in": ["high", "urgent"] } }, + { "due_at": { "$lt": { "$cel": "now()" } } } + ] + } + ] +} +``` + +CEL 式は `{ "$cel": "..." }` で埋め込むことができます。サーバーがクエリ実行時に +評価する「現在時刻基準」のフィルターに便利です。 + +## ソート + +```jsonc +"orderBy": [ + { "field": "priority", "order": "desc" }, + { "field": "created_at", "order": "asc" } +] +``` + +クエリ文字列の短縮形: `?orderBy=-priority,created_at`。 + +## ページネーション + +**カーソル(推奨)。** レスポンスには `nextCursor` が含まれます。 +それを次のリクエストの `cursor` として渡し戻します。 + +```http +GET /api/v1/data/ticket?limit=50&orderBy=-created_at +→ { items: [...], nextCursor: "eyJ..." } + +GET /api/v1/data/ticket?limit=50&cursor=eyJ... +``` + +**オフセット。** よりシンプルですが、大きなテーブルでは性能が低下します。 + +```http +GET /api/v1/data/ticket?limit=50&offset=200 +``` + +ランタイムはオブジェクトごとに `ObjectSpec.maxPageSize` を通じて `limit` の上限を +設定します(デフォルト 200)。 + +## リレーション — `expand` + +`expand` は外部キーをバッチで解決するため、N+1 を回避できます。 + +```jsonc +{ + "object": "support_ticket", + "expand": ["assignee", "customer.account"], + "limit": 20 +} +``` + +各 ticket を、ID だけではなくネストされたオブジェクトとして実体化された +`assignee` と `customer.account` とともに返します。 + +## ジョイン + +メタデータグラフ外でのアドホックなジョインの場合: + +```jsonc +"joins": [ + { "type": "left", "object": "user", "as": "u", "on": "assignee_id = u.id" } +] +``` + +`type`: `inner` | `left` | `right` | `full`。ジョインされたテーブルは、 +`as` エイリアスを通じて `where`、`orderBy`、`aggregations` でアクセスできます。 + +## 集計 + +`POST /api/v1/data/:object/query` のみ。 + +```jsonc +{ + "object": "order", + "where": { "status": { "$ne": "cancelled" } }, + "groupBy": [ + "customer_id", + { "field": "created_at", "dateGranularity": "month" } + ], + "aggregations": [ + { "function": "sum", "field": "amount", "alias": "total_sales" }, + { "function": "count", "alias": "order_count" } + ], + "having": { "total_sales": { "$gt": 10000 } }, + "orderBy": [{ "field": "total_sales", "order": "desc" }], + "limit": 25 +} +``` + +**関数:** `count`、`sum`、`avg`、`min`、`max`、`count_distinct`、 +`array_agg`、`string_agg`。 + +**日付の粒度**(時間バケット化された group-by 用): +`day` | `week` | `month` | `quarter` | `year`。 + +## Distinct + +```jsonc +{ "object": "ticket", "fields": ["status"], "distinct": true } +``` + +## 検索 + +`searchable: true` のフィールドにわたる全文検索は +`GET /api/v1/search?q=...&object=ticket` で公開されています。オブジェクトごとの +スコアリングルールはオブジェクト仕様で設定されます。 + +## ObjectQL が登場する場所 + +- `GET /api/v1/data/:object` — クエリ文字列形式 +- `POST /api/v1/data/:object/query` — 完全なボディ、集計をサポート +- ビュー定義(`filter`、`sort`)— ObjectQL にコンパイルされる +- レポート — ObjectQL にシリアライズされる +- AI の `query_data` ツール — 承認キュー用の ObjectQL ボディを + 生成する + +## 関連項目 + +- [REST API](./rest-api) — ObjectQL を消費するエンドポイント +- [Field types](./field-types) — クエリ可能なもの +- [CEL](./cel) — `$cel` フィルター内で使用される式言語 +- [`@objectstack/spec/data/query.zod.ts`](https://github.com/objectstack-ai/framework/blob/main/packages/spec/src/data/query.zod.ts) — 正式なスキーマ diff --git a/content/docs/reference/objectql.cn.mdx b/content/docs/reference/objectql.zh-Hans.mdx similarity index 100% rename from content/docs/reference/objectql.cn.mdx rename to content/docs/reference/objectql.zh-Hans.mdx diff --git a/content/docs/reference/rest-api.de.mdx b/content/docs/reference/rest-api.de.mdx new file mode 100644 index 0000000..e07e6e9 --- /dev/null +++ b/content/docs/reference/rest-api.de.mdx @@ -0,0 +1,193 @@ +--- +title: REST API +description: Die HTTP-Schnittstelle, die ObjectOS bereitstellt — aus deinen Metadaten generiert, durch Berechtigungen eingegrenzt, per OpenAPI beschrieben. +--- + +# REST API + +Jedes Objekt, das du deklarierst, erhält automatisch einen vollständigen +Satz von REST-Endpunkten. Jede Action wird zu einem `POST`. Jeder Flow +wird zu einem `POST` auf `/flows/...`. Es gibt keine separate API-Schicht, +die du schreiben oder bereitstellen musst. + +Basis-URL: `https:///api/v1`. +Die OpenAPI-Spezifikation ist live unter [`/api/v1/openapi.json`](#discovery) verfügbar. + +## Authentication + +ObjectOS verwendet [Better Auth](https://www.better-auth.com/). Alle Routen +unter `/api/v1` erfordern eine authentifizierte Sitzung, sofern sie nicht +ausdrücklich als **public** markiert sind (siehe [Public forms](#public-forms)). +Die Authentifizierungsmethoden werden in `apps//auth.config.ts` +konfiguriert — typischerweise ein Session-Cookie oder ein Bearer-Token von +`/api/v1/auth/sign-in`. + +Berechtigungen werden **pro Route, pro Datensatz** geprüft. Routen, die unten +mit einem Berechtigungsschlüssel (z. B. `ai:chat`) annotiert sind, rufen +`requirePermission(...)` auf; der Zugriff auf Datensatzebene wird durch RBAC + +Row-Level Security + Field-Level Security innerhalb der Daten-Engine +durchgesetzt. + +## Discovery + +| Pfad | Methode | Zweck | +|:--|:--|:--| +| `/api/v1` | GET | Service Discovery — listet alle registrierten Routen, die Version und den Scoping-Modus auf | +| `/api/v1/openapi.json` | GET | OpenAPI-3.0-Spezifikation für jeden Endpunkt im laufenden Runtime | +| `/api/v1/search` | GET | Volltextsuche über durchsuchbare Felder aller Objekte | + +## Data — `/api/v1/data/*` + +CRUD + erweiterte Abfragen für jedes Objekt, das du deklarierst. `:object` ist +der `name` des Objekts (snake_case). + +| Pfad | Methode | Zweck | +|:--|:--|:--| +| `/data/:object` | GET | Auflisten / Abfragen — übergib `where`, `orderBy`, `limit`, `offset`, `cursor`, `expand`, `select` als Query-Parameter | +| `/data/:object/query` | POST | Erweiterte Abfrage — vollständiger ObjectQL-Body mit `groupBy` + `aggregations` (siehe [ObjectQL](./objectql)) | +| `/data/:object/:id` | GET | Einen Datensatz abrufen. Unterstützt `?select=` und `?expand=` | +| `/data/:object` | POST | Erstellen. Gibt `201` mit dem neuen Datensatz zurück | +| `/data/:object/:id` | PATCH | Aktualisieren. Übergib den Header `If-Match: ` (oder `expectedVersion` im Body) für optimistische Nebenläufigkeit — `409 CONCURRENT_UPDATE` bei einem Konflikt | +| `/data/:object/:id` | DELETE | Löschen. Gleiche `If-Match`-Regel | +| `/data/:object/import` | POST | Massenimport (CSV oder JSON). Body: `{ format, csv? \| rows?, mapping?, dryRun? }`. Maximal 5.000 Zeilen pro Anfrage | +| `/data/:object/export` | POST | Datensätze als `csv` / `xlsx` / `pdf` / `json` exportieren | +| `/data/:object/:id/shares` | GET / POST | Freigabe pro Datensatz — Freigaben auflisten, Zugriff gewähren | +| `/data/:object/:id/shares/:shareId` | DELETE | Eine Freigabe widerrufen | +| `/data/lead/:id/convert` | POST | Lead-Konvertierung im Salesforce-Stil (CRM-Vorlage). Body: `{ accountId?, contactId?, createOpportunity? }` | + +### Kurzes Beispiel + +```http +GET /api/v1/data/support_ticket?where={"status":{"$eq":"open"}}&orderBy=-created_at&limit=20 +Authorization: Bearer +``` + +```json +{ + "items": [ { "id": "...", "subject": "...", "status": "open" } ], + "total": 137, + "nextCursor": "eyJpZCI6IjAxSDA..." +} +``` + +## AI — `/api/v1/ai/*` + +Die Endpunkte, auf denen der [AI Builder](/docs/build/ai-builder) und deine +[Agenten](/docs/build/agents) aufsetzen. + +| Pfad | Methode | Berechtigung | Zweck | +|:--|:--|:--|:--| +| `/ai/models` | GET | `ai:chat` | Verfügbare Modelle der konfigurierten Anbieter auflisten | +| `/ai/chat` | POST | `ai:chat` | Einmalige Chat-Completion (synchron) | +| `/ai/chat/stream` | POST | `ai:chat` | Streaming-Chat (SSE) | +| `/ai/complete` | POST | `ai:chat` | Roher Completion-Endpunkt | +| `/ai/conversations` | GET / POST | `ai:chat` | Persistente Konversationen auflisten / erstellen | +| `/ai/conversations/:id` | GET / DELETE | `ai:chat` | Eine Konversation lesen / löschen | +| `/ai/conversations/:id/messages` | POST | `ai:chat` | Eine Benutzernachricht anhängen und den Agenten ausführen | +| `/ai/pending-actions` | GET | `ai:read` | Die HITL-Freigabewarteschlange — von der KI vorgeschlagene Mutationen | +| `/ai/pending-actions/:id` | GET | `ai:read` | Eine eingereihte Mutation inspizieren | +| `/ai/pending-actions/:id/approve` | POST | `ai:approve` | Die Mutation anwenden | +| `/ai/pending-actions/:id/reject` | POST | `ai:approve` | Sie verwerfen | + +Die Trennung zwischen `ai:read` und `ai:approve` ist das +Sicherheitsprimitiv, das den AI Builder für Endbenutzer sicher macht. + +## Actions — `/api/v1/actions/*` + +Jede `*.action.ts`, die du deklarierst, wird zu einem Endpunkt. + +| Pfad | Methode | Zweck | +|:--|:--|:--| +| `/actions/:action` | POST | Die Action aufrufen. Der Body ist das Input-Schema der Action. Berechtigungen und Eingabevalidierung stammen aus der Action-Deklaration | + +Jede Action wird der KI außerdem als `action_`-Tool bereitgestellt — siehe +[Actions](/docs/build/actions). + +## Flows — `/api/v1/flows/*` + +| Pfad | Methode | Zweck | +|:--|:--|:--| +| `/flows/:flow/start` | POST | Einen Flow starten. Der Body ist die Flow-Eingabe | +| `/flows/:flow/runs/:runId` | GET | Status + Schritt-Ausgabe eines laufenden / abgeschlossenen Flows | +| `/flows/:flow/runs/:runId/cancel` | POST | Einen laufenden Durchlauf abbrechen | + +## Metadata — `/api/v1/meta/*` + +Schreibgeschützte Introspektion der Metadaten des laufenden Runtime. Nützlich +für Tooling und die Console. + +| Pfad | Methode | Zweck | +|:--|:--|:--| +| `/meta` | GET | Alle Metadatentypen (`object`, `view`, `action`, `flow`, `agent`, …) | +| `/meta/:type` | GET | Elemente eines Typs auflisten. Filtern mit `?package=` | +| `/meta/:type/:name` | GET | Ein Element abrufen. `?layers=true` liefert die 3-Zustands-Diff-Ansicht (base / package / overlay) | +| `/meta/:type/:name/references` | GET | Jedes Metadatenelement finden, das auf dieses verweist | +| `/meta/:type/:name/history` | GET | Audit-Verlauf für dieses Element | +| `/meta/:type/:section/:name` | GET / POST | Ein in Abschnitte gegliedertes Metadatenelement lesen / upserten | +| `/meta/:type/:section/:name` | DELETE | Ein in Abschnitte gegliedertes Element löschen | + +## Sharing & Freigaben + +| Pfad | Methode | Zweck | +|:--|:--|:--| +| `/sharing/rules` | GET / POST / DELETE | Freigaberegeln verwalten | +| `/sharing/rules/:idOrName/evaluate` | POST | Eine Regel testweise gegen einen Kontext ausführen | +| `/approvals/processes` | GET / POST | Definitionen von Genehmigungsprozessen | +| `/approvals/requests` | GET / POST | Genehmigungsanfragen einreichen / auflisten | +| `/approvals/requests/:id/approve` | POST | Entscheidung: genehmigen | +| `/approvals/requests/:id/reject` | POST | Entscheidung: ablehnen | + +## Reports & Suche + +| Pfad | Methode | Zweck | +|:--|:--|:--| +| `/reports` | GET / POST / PATCH | Report-CRUD | +| `/reports/:id/run` | POST | Einen Report ausführen — gibt aggregierte Zeilen zurück | +| `/reports/:id/schedule` | POST | Wiederkehrende Auslieferung planen | + +## Public forms + +Die einzigen Routen, die **unauthentifiziert** sind, per Opt-in über +`FormView.sharing.allowAnonymous`. + +| Pfad | Methode | Auth | +|:--|:--|:--| +| `/forms/:slug` | GET | public — gibt das Formularschema zurück | +| `/forms/:slug/submit` | POST | public — übermittelt eine Antwort | + +## Utilities + +| Pfad | Methode | Berechtigung | Zweck | +|:--|:--|:--|:--| +| `/email/send` | POST | `email:send` | Eine E-Mail über den konfigurierten Anbieter senden | + +## Fehler-Envelope + +Jede Antwort, die nicht 2xx ist, folgt derselben Struktur: + +```json +{ + "error": { + "code": "PERMISSION_DENIED", + "message": "Missing ai:approve on conversation 01H…", + "details": { "permission": "ai:approve", "subject": "01H…" } + } +} +``` + +Häufige Codes: `UNAUTHENTICATED`, `PERMISSION_DENIED`, +`VALIDATION_ERROR`, `NOT_FOUND`, `CONCURRENT_UPDATE`, +`RATE_LIMITED`, `INTERNAL`. + +## Versionierung + +`/api/v1` ist die **stabile** API. Breaking Changes gehen nach `/api/v2`, und +beide werden für ein Minor-Release parallel bereitgestellt. Die aktuelle +Version und der Deprecation-Horizont stehen in `GET /api/v1`. + +## Siehe auch + +- [ObjectQL](./objectql) — die von `/data/*` verwendete Abfragesprache +- [Field types](./field-types) — welche Formen Daten annehmen können +- [Build → Actions](/docs/build/actions) — eigene Endpunkte deklarieren +- [Security](./security) — was jede Route prüft, bevor sie ausgeführt wird diff --git a/content/docs/reference/rest-api.es.mdx b/content/docs/reference/rest-api.es.mdx new file mode 100644 index 0000000..92326ab --- /dev/null +++ b/content/docs/reference/rest-api.es.mdx @@ -0,0 +1,190 @@ +--- +title: REST API +description: La superficie HTTP que expone ObjectOS — generada a partir de tus metadatos, delimitada por permisos y descrita con OpenAPI. +--- + +# REST API + +Cada objeto que declaras obtiene automáticamente un conjunto completo de endpoints REST. +Cada acción se convierte en un `POST`. Cada flujo se convierte en un `POST` a +`/flows/...`. No hay que escribir ni desplegar una capa de API aparte. + +URL base: `https:///api/v1`. +La especificación OpenAPI está disponible en vivo en [`/api/v1/openapi.json`](#discovery). + +## Autenticación + +ObjectOS utiliza [Better Auth](https://www.better-auth.com/). Todas las rutas +bajo `/api/v1` requieren una sesión autenticada, salvo que estén marcadas +explícitamente como **públicas** (consulta [Formularios públicos](#public-forms)). Los métodos de autenticación +se configuran en `apps//auth.config.ts` — normalmente una cookie de sesión o +un token bearer obtenido de `/api/v1/auth/sign-in`. + +Los permisos se comprueban **por ruta y por registro**. Las rutas anotadas +a continuación con una clave de permiso (p. ej. `ai:chat`) invocan +`requirePermission(...)`; el acceso a nivel de registro lo aplica RBAC + +seguridad a nivel de fila + seguridad a nivel de campo dentro del motor de datos. + +## Discovery + +| Ruta | Método | Propósito | +|:--|:--|:--| +| `/api/v1` | GET | Descubrimiento de servicios — lista todas las rutas registradas, la versión y el modo de delimitación | +| `/api/v1/openapi.json` | GET | Especificación OpenAPI 3.0 de cada endpoint del runtime en ejecución | +| `/api/v1/search` | GET | Búsqueda de texto completo en los campos indexables de todos los objetos | + +## Datos — `/api/v1/data/*` + +CRUD + consultas avanzadas para cada objeto que declaras. `:object` es el +`name` del objeto (snake_case). + +| Ruta | Método | Propósito | +|:--|:--|:--| +| `/data/:object` | GET | Listar / consultar — pasa `where`, `orderBy`, `limit`, `offset`, `cursor`, `expand`, `select` como parámetros de consulta | +| `/data/:object/query` | POST | Consulta avanzada — cuerpo ObjectQL completo con `groupBy` + `aggregations` (consulta [ObjectQL](./objectql)) | +| `/data/:object/:id` | GET | Obtener un registro. Admite `?select=` y `?expand=` | +| `/data/:object` | POST | Crear. Devuelve `201` con el nuevo registro | +| `/data/:object/:id` | PATCH | Actualizar. Pasa la cabecera `If-Match: ` (o `expectedVersion` en el cuerpo) para concurrencia optimista — `409 CONCURRENT_UPDATE` en caso de conflicto | +| `/data/:object/:id` | DELETE | Eliminar. Misma regla de `If-Match` | +| `/data/:object/import` | POST | Importación masiva (CSV o JSON). Cuerpo: `{ format, csv? \| rows?, mapping?, dryRun? }`. Máximo 5.000 filas por solicitud | +| `/data/:object/export` | POST | Exportar registros como `csv` / `xlsx` / `pdf` / `json` | +| `/data/:object/:id/shares` | GET / POST | Compartición por registro — listar concesiones, conceder acceso | +| `/data/:object/:id/shares/:shareId` | DELETE | Revocar una compartición | +| `/data/lead/:id/convert` | POST | Conversión de lead al estilo Salesforce (plantilla CRM). Cuerpo: `{ accountId?, contactId?, createOpportunity? }` | + +### Ejemplo rápido + +```http +GET /api/v1/data/support_ticket?where={"status":{"$eq":"open"}}&orderBy=-created_at&limit=20 +Authorization: Bearer +``` + +```json +{ + "items": [ { "id": "...", "subject": "...", "status": "open" } ], + "total": 137, + "nextCursor": "eyJpZCI6IjAxSDA..." +} +``` + +## AI — `/api/v1/ai/*` + +Los endpoints sobre los que se apoyan el [AI Builder](/docs/build/ai-builder) y tus +[agentes](/docs/build/agents). + +| Ruta | Método | Permiso | Propósito | +|:--|:--|:--|:--| +| `/ai/models` | GET | `ai:chat` | Listar los modelos disponibles de los proveedores configurados | +| `/ai/chat` | POST | `ai:chat` | Completado de chat de un solo paso (síncrono) | +| `/ai/chat/stream` | POST | `ai:chat` | Chat en streaming (SSE) | +| `/ai/complete` | POST | `ai:chat` | Endpoint de completado en bruto | +| `/ai/conversations` | GET / POST | `ai:chat` | Listar / crear conversaciones persistentes | +| `/ai/conversations/:id` | GET / DELETE | `ai:chat` | Leer / eliminar una conversación | +| `/ai/conversations/:id/messages` | POST | `ai:chat` | Añadir un mensaje del usuario y ejecutar el agente | +| `/ai/pending-actions` | GET | `ai:read` | La cola de aprobación HITL — mutaciones que la IA ha propuesto | +| `/ai/pending-actions/:id` | GET | `ai:read` | Inspeccionar una mutación en cola | +| `/ai/pending-actions/:id/approve` | POST | `ai:approve` | Aplicar la mutación | +| `/ai/pending-actions/:id/reject` | POST | `ai:approve` | Descartarla | + +La separación entre `ai:read` y `ai:approve` es la primitiva de seguridad +que hace que el AI Builder sea seguro para los usuarios finales. + +## Acciones — `/api/v1/actions/*` + +Cada `*.action.ts` que declaras se convierte en un endpoint. + +| Ruta | Método | Propósito | +|:--|:--|:--| +| `/actions/:action` | POST | Invocar la acción. El cuerpo es el esquema de entrada de la acción. Los permisos y la validación de entrada provienen de la declaración de la acción | + +Cada acción también se expone a la IA como una herramienta `action_` — consulta +[Acciones](/docs/build/actions). + +## Flujos — `/api/v1/flows/*` + +| Ruta | Método | Propósito | +|:--|:--|:--| +| `/flows/:flow/start` | POST | Iniciar un flujo. El cuerpo es la entrada del flujo | +| `/flows/:flow/runs/:runId` | GET | Estado + salida de los pasos de un flujo en ejecución / completado | +| `/flows/:flow/runs/:runId/cancel` | POST | Cancelar una ejecución en curso | + +## Metadatos — `/api/v1/meta/*` + +Introspección de solo lectura de los metadatos del runtime en ejecución. Útil +para herramientas y para la Console. + +| Ruta | Método | Propósito | +|:--|:--|:--| +| `/meta` | GET | Todos los tipos de metadatos (`object`, `view`, `action`, `flow`, `agent`, …) | +| `/meta/:type` | GET | Listar los elementos de un tipo. Filtra con `?package=` | +| `/meta/:type/:name` | GET | Obtener un elemento. `?layers=true` devuelve la vista de diferencias de 3 estados (base / package / overlay) | +| `/meta/:type/:name/references` | GET | Encontrar todos los elementos de metadatos que hacen referencia a este | +| `/meta/:type/:name/history` | GET | Registro de auditoría de ese elemento | +| `/meta/:type/:section/:name` | GET / POST | Leer / insertar o actualizar un elemento de metadatos seccionado | +| `/meta/:type/:section/:name` | DELETE | Eliminar un elemento seccionado | + +## Compartición y aprobaciones + +| Ruta | Método | Propósito | +|:--|:--|:--| +| `/sharing/rules` | GET / POST / DELETE | Gestionar reglas de compartición | +| `/sharing/rules/:idOrName/evaluate` | POST | Ejecutar en seco una regla contra un contexto | +| `/approvals/processes` | GET / POST | Definiciones de procesos de aprobación | +| `/approvals/requests` | GET / POST | Enviar / listar solicitudes de aprobación | +| `/approvals/requests/:id/approve` | POST | Decisión: aprobar | +| `/approvals/requests/:id/reject` | POST | Decisión: rechazar | + +## Informes y búsqueda + +| Ruta | Método | Propósito | +|:--|:--|:--| +| `/reports` | GET / POST / PATCH | CRUD de informes | +| `/reports/:id/run` | POST | Ejecutar un informe — devuelve filas agregadas | +| `/reports/:id/schedule` | POST | Programar entrega recurrente | + +## Formularios públicos + +Las únicas rutas que son **no autenticadas**, habilitadas de forma opcional mediante +`FormView.sharing.allowAnonymous`. + +| Ruta | Método | Autenticación | +|:--|:--|:--| +| `/forms/:slug` | GET | pública — devuelve el esquema del formulario | +| `/forms/:slug/submit` | POST | pública — envía una respuesta | + +## Utilidades + +| Ruta | Método | Permiso | Propósito | +|:--|:--|:--|:--| +| `/email/send` | POST | `email:send` | Enviar un correo electrónico a través del proveedor configurado | + +## Envoltorio de errores + +Toda respuesta distinta de 2xx sigue la misma forma: + +```json +{ + "error": { + "code": "PERMISSION_DENIED", + "message": "Missing ai:approve on conversation 01H…", + "details": { "permission": "ai:approve", "subject": "01H…" } + } +} +``` + +Códigos comunes: `UNAUTHENTICATED`, `PERMISSION_DENIED`, +`VALIDATION_ERROR`, `NOT_FOUND`, `CONCURRENT_UPDATE`, +`RATE_LIMITED`, `INTERNAL`. + +## Versionado + +`/api/v1` es la API **estable**. Los cambios incompatibles van a `/api/v2` y +ambas se sirven en paralelo durante una versión menor. La versión actual y +el horizonte de obsolescencia están en `GET /api/v1`. + +## Véase también + +- [ObjectQL](./objectql) — el lenguaje de consulta utilizado por `/data/*` +- [Tipos de campo](./field-types) — qué formas pueden adoptar los datos +- [Build → Acciones](/docs/build/actions) — declarar endpoints personalizados +- [Seguridad](./security) — qué comprueba cada ruta antes de ejecutarse diff --git a/content/docs/reference/rest-api.fr.mdx b/content/docs/reference/rest-api.fr.mdx new file mode 100644 index 0000000..badb4b1 --- /dev/null +++ b/content/docs/reference/rest-api.fr.mdx @@ -0,0 +1,190 @@ +--- +title: API REST +description: La surface HTTP exposée par ObjectOS — générée à partir de vos métadonnées, cadrée par les permissions, décrite via OpenAPI. +--- + +# API REST + +Chaque objet que vous déclarez obtient automatiquement un ensemble complet de points de terminaison REST. +Chaque action devient un `POST`. Chaque flow devient un `POST` vers +`/flows/...`. Il n'y a aucune couche API distincte à écrire ou à déployer. + +URL de base : `https:///api/v1`. +La spécification OpenAPI est disponible en direct sur [`/api/v1/openapi.json`](#discovery). + +## Authentification + +ObjectOS utilise [Better Auth](https://www.better-auth.com/). Toutes les routes +sous `/api/v1` requièrent une session authentifiée, sauf si elles sont explicitement +marquées comme **publiques** (voir [Formulaires publics](#public-forms)). Les méthodes d'authentification sont +configurées dans `apps//auth.config.ts` — typiquement un cookie de session ou +un jeton bearer issu de `/api/v1/auth/sign-in`. + +Les permissions sont vérifiées **par route, par enregistrement**. Les routes annotées +ci-dessous avec une clé de permission (par ex. `ai:chat`) appellent +`requirePermission(...)` ; l'accès au niveau de l'enregistrement est appliqué par RBAC + +sécurité au niveau des lignes + sécurité au niveau des champs au sein du moteur de données. + +## Discovery + +| Chemin | Méthode | Objectif | +|:--|:--|:--| +| `/api/v1` | GET | Découverte de service — liste toutes les routes enregistrées, la version, le mode de cadrage | +| `/api/v1/openapi.json` | GET | Spécification OpenAPI 3.0 pour chaque point de terminaison du runtime en cours d'exécution | +| `/api/v1/search` | GET | Recherche plein texte sur les champs recherchables de tous les objets | + +## Données — `/api/v1/data/*` + +CRUD + requêtes avancées pour chaque objet que vous déclarez. `:object` est le +`name` de l'objet (snake_case). + +| Chemin | Méthode | Objectif | +|:--|:--|:--| +| `/data/:object` | GET | Lister / interroger — passez `where`, `orderBy`, `limit`, `offset`, `cursor`, `expand`, `select` comme paramètres de requête | +| `/data/:object/query` | POST | Requête avancée — corps ObjectQL complet avec `groupBy` + `aggregations` (voir [ObjectQL](./objectql)) | +| `/data/:object/:id` | GET | Récupérer un enregistrement. Prend en charge `?select=` et `?expand=` | +| `/data/:object` | POST | Créer. Renvoie `201` avec le nouvel enregistrement | +| `/data/:object/:id` | PATCH | Mettre à jour. Passez l'en-tête `If-Match: ` (ou `expectedVersion` dans le corps) pour la concurrence optimiste — `409 CONCURRENT_UPDATE` en cas de conflit | +| `/data/:object/:id` | DELETE | Supprimer. Même règle `If-Match` | +| `/data/:object/import` | POST | Import en masse (CSV ou JSON). Corps : `{ format, csv? \| rows?, mapping?, dryRun? }`. Maximum 5 000 lignes/requête | +| `/data/:object/export` | POST | Exporter les enregistrements en `csv` / `xlsx` / `pdf` / `json` | +| `/data/:object/:id/shares` | GET / POST | Partage par enregistrement — lister les octrois, accorder l'accès | +| `/data/:object/:id/shares/:shareId` | DELETE | Révoquer un partage | +| `/data/lead/:id/convert` | POST | Conversion de lead à la Salesforce (modèle CRM). Corps : `{ accountId?, contactId?, createOpportunity? }` | + +### Exemple rapide + +```http +GET /api/v1/data/support_ticket?where={"status":{"$eq":"open"}}&orderBy=-created_at&limit=20 +Authorization: Bearer +``` + +```json +{ + "items": [ { "id": "...", "subject": "...", "status": "open" } ], + "total": 137, + "nextCursor": "eyJpZCI6IjAxSDA..." +} +``` + +## IA — `/api/v1/ai/*` + +Les points de terminaison sur lesquels reposent l'[AI Builder](/docs/build/ai-builder) et vos +[agents](/docs/build/agents). + +| Chemin | Méthode | Permission | Objectif | +|:--|:--|:--|:--| +| `/ai/models` | GET | `ai:chat` | Lister les modèles disponibles des fournisseurs configurés | +| `/ai/chat` | POST | `ai:chat` | Complétion de chat en un seul coup (synchrone) | +| `/ai/chat/stream` | POST | `ai:chat` | Chat en streaming (SSE) | +| `/ai/complete` | POST | `ai:chat` | Point de terminaison de complétion brute | +| `/ai/conversations` | GET / POST | `ai:chat` | Lister / créer des conversations persistantes | +| `/ai/conversations/:id` | GET / DELETE | `ai:chat` | Lire / supprimer une conversation | +| `/ai/conversations/:id/messages` | POST | `ai:chat` | Ajouter un message utilisateur et exécuter l'agent | +| `/ai/pending-actions` | GET | `ai:read` | La file d'approbation HITL — mutations proposées par l'IA | +| `/ai/pending-actions/:id` | GET | `ai:read` | Inspecter une mutation en file d'attente | +| `/ai/pending-actions/:id/approve` | POST | `ai:approve` | Appliquer la mutation | +| `/ai/pending-actions/:id/reject` | POST | `ai:approve` | La rejeter | + +La séparation entre `ai:read` et `ai:approve` est la primitive de sécurité +qui rend l'AI Builder sûr pour les utilisateurs finaux. + +## Actions — `/api/v1/actions/*` + +Chaque `*.action.ts` que vous déclarez devient un point de terminaison. + +| Chemin | Méthode | Objectif | +|:--|:--|:--| +| `/actions/:action` | POST | Invoquer l'action. Le corps correspond au schéma d'entrée de l'action. Les permissions et la validation des entrées proviennent de la déclaration de l'action | + +Chaque action est également exposée à l'IA sous forme d'outil `action_` — voir +[Actions](/docs/build/actions). + +## Flows — `/api/v1/flows/*` + +| Chemin | Méthode | Objectif | +|:--|:--|:--| +| `/flows/:flow/start` | POST | Démarrer un flow. Le corps correspond à l'entrée du flow | +| `/flows/:flow/runs/:runId` | GET | Statut + sortie des étapes d'un flow en cours / terminé | +| `/flows/:flow/runs/:runId/cancel` | POST | Annuler une exécution en cours | + +## Métadonnées — `/api/v1/meta/*` + +Introspection en lecture seule des métadonnées du runtime en cours d'exécution. Utile +pour l'outillage et la Console. + +| Chemin | Méthode | Objectif | +|:--|:--|:--| +| `/meta` | GET | Tous les types de métadonnées (`object`, `view`, `action`, `flow`, `agent`, …) | +| `/meta/:type` | GET | Lister les éléments d'un type. Filtrer avec `?package=` | +| `/meta/:type/:name` | GET | Récupérer un élément. `?layers=true` renvoie la vue de diff à 3 états (base / package / overlay) | +| `/meta/:type/:name/references` | GET | Trouver chaque élément de métadonnées qui référence celui-ci | +| `/meta/:type/:name/history` | GET | Piste d'audit pour cet élément | +| `/meta/:type/:section/:name` | GET / POST | Lire / insérer-ou-mettre-à-jour un élément de métadonnées sectionné | +| `/meta/:type/:section/:name` | DELETE | Supprimer un élément sectionné | + +## Partage et approbations + +| Chemin | Méthode | Objectif | +|:--|:--|:--| +| `/sharing/rules` | GET / POST / DELETE | Gérer les règles de partage | +| `/sharing/rules/:idOrName/evaluate` | POST | Exécuter une règle à blanc sur un contexte | +| `/approvals/processes` | GET / POST | Définitions de processus d'approbation | +| `/approvals/requests` | GET / POST | Soumettre / lister les demandes d'approbation | +| `/approvals/requests/:id/approve` | POST | Décision : approuver | +| `/approvals/requests/:id/reject` | POST | Décision : rejeter | + +## Rapports et recherche + +| Chemin | Méthode | Objectif | +|:--|:--|:--| +| `/reports` | GET / POST / PATCH | CRUD des rapports | +| `/reports/:id/run` | POST | Exécuter un rapport — renvoie des lignes agrégées | +| `/reports/:id/schedule` | POST | Planifier une diffusion récurrente | + +## Formulaires publics + +Les seules routes qui sont **non authentifiées**, activées de manière optionnelle via +`FormView.sharing.allowAnonymous`. + +| Chemin | Méthode | Authentification | +|:--|:--|:--| +| `/forms/:slug` | GET | publique — renvoie le schéma du formulaire | +| `/forms/:slug/submit` | POST | publique — soumet une réponse | + +## Utilitaires + +| Chemin | Méthode | Permission | Objectif | +|:--|:--|:--|:--| +| `/email/send` | POST | `email:send` | Envoyer un e-mail via le fournisseur configuré | + +## Enveloppe d'erreur + +Chaque réponse non-2xx suit la même forme : + +```json +{ + "error": { + "code": "PERMISSION_DENIED", + "message": "Missing ai:approve on conversation 01H…", + "details": { "permission": "ai:approve", "subject": "01H…" } + } +} +``` + +Codes courants : `UNAUTHENTICATED`, `PERMISSION_DENIED`, +`VALIDATION_ERROR`, `NOT_FOUND`, `CONCURRENT_UPDATE`, +`RATE_LIMITED`, `INTERNAL`. + +## Versionnage + +`/api/v1` est l'API **stable**. Les changements incompatibles vont vers `/api/v2` et +les deux sont servies en parallèle pendant une version mineure. La version actuelle et +l'horizon de dépréciation se trouvent dans `GET /api/v1`. + +## Voir aussi + +- [ObjectQL](./objectql) — le langage de requête utilisé par `/data/*` +- [Types de champs](./field-types) — les formes que peuvent prendre les données +- [Build → Actions](/docs/build/actions) — déclarer des points de terminaison personnalisés +- [Sécurité](./security) — ce que chaque route vérifie avant de s'exécuter diff --git a/content/docs/reference/rest-api.ja.mdx b/content/docs/reference/rest-api.ja.mdx new file mode 100644 index 0000000..899a4ca --- /dev/null +++ b/content/docs/reference/rest-api.ja.mdx @@ -0,0 +1,189 @@ +--- +title: REST API +description: ObjectOS が公開する HTTP インターフェース — メタデータから生成され、権限でスコープされ、OpenAPI で記述されます。 +--- + +# REST API + +宣言したすべてのオブジェクトに、完全な REST エンドポイントセットが自動的に付与されます。 +すべてのアクションは `POST` になります。すべてのフローは +`/flows/...` への `POST` になります。記述やデプロイが必要な独立した API レイヤーは存在しません。 + +ベース URL: `https:///api/v1`。 +OpenAPI 仕様は [`/api/v1/openapi.json`](#discovery) で公開されています。 + +## Authentication + +ObjectOS は [Better Auth](https://www.better-auth.com/) を使用します。 +`/api/v1` 配下のすべてのルートは、明示的に **public** とマークされていない限り、 +認証済みセッションを必要とします([Public forms](#public-forms) を参照)。認証方式は +`apps//auth.config.ts` で設定します。通常はセッション Cookie か、 +`/api/v1/auth/sign-in` から取得したベアラートークンです。 + +権限は **ルートごと、レコードごと** にチェックされます。以下で権限キー +(例: `ai:chat`)が付記されているルートは +`requirePermission(...)` を呼び出します。レコードレベルのアクセスは、データエンジン内部の +RBAC + 行レベルセキュリティ + フィールドレベルセキュリティによって強制されます。 + +## Discovery + +| Path | Method | 目的 | +|:--|:--|:--| +| `/api/v1` | GET | サービスディスカバリ — 登録されたすべてのルート、バージョン、スコープモードを一覧表示 | +| `/api/v1/openapi.json` | GET | 実行中のランタイムにあるすべてのエンドポイントの OpenAPI 3.0 仕様 | +| `/api/v1/search` | GET | すべてのオブジェクトの検索可能フィールドにまたがる全文検索 | + +## Data — `/api/v1/data/*` + +宣言したすべてのオブジェクトに対する CRUD + 高度なクエリ。`:object` は +オブジェクトの `name`(snake_case)です。 + +| Path | Method | 目的 | +|:--|:--|:--| +| `/data/:object` | GET | リスト / クエリ — クエリパラメータとして `where`、`orderBy`、`limit`、`offset`、`cursor`、`expand`、`select` を渡します | +| `/data/:object/query` | POST | 高度なクエリ — `groupBy` + `aggregations` を含む完全な ObjectQL ボディ([ObjectQL](./objectql) を参照) | +| `/data/:object/:id` | GET | 1 件のレコードを取得。`?select=` と `?expand=` をサポート | +| `/data/:object` | POST | 作成。新しいレコードとともに `201` を返します | +| `/data/:object/:id` | PATCH | 更新。楽観的並行性制御のために `If-Match: ` ヘッダー(またはボディ内の `expectedVersion`)を渡します — 競合時は `409 CONCURRENT_UPDATE` | +| `/data/:object/:id` | DELETE | 削除。同じ `If-Match` ルールが適用されます | +| `/data/:object/import` | POST | 一括インポート(CSV または JSON)。ボディ: `{ format, csv? \| rows?, mapping?, dryRun? }`。リクエストあたり最大 5,000 行 | +| `/data/:object/export` | POST | レコードを `csv` / `xlsx` / `pdf` / `json` としてエクスポート | +| `/data/:object/:id/shares` | GET / POST | レコードごとの共有 — 付与の一覧表示、アクセスの付与 | +| `/data/:object/:id/shares/:shareId` | DELETE | 共有を取り消し | +| `/data/lead/:id/convert` | POST | Salesforce 風のリード変換(CRM テンプレート)。ボディ: `{ accountId?, contactId?, createOpportunity? }` | + +### Quick example + +```http +GET /api/v1/data/support_ticket?where={"status":{"$eq":"open"}}&orderBy=-created_at&limit=20 +Authorization: Bearer +``` + +```json +{ + "items": [ { "id": "...", "subject": "...", "status": "open" } ], + "total": 137, + "nextCursor": "eyJpZCI6IjAxSDA..." +} +``` + +## AI — `/api/v1/ai/*` + +[AI Builder](/docs/build/ai-builder) と +[エージェント](/docs/build/agents) が動作するためのエンドポイントです。 + +| Path | Method | Permission | 目的 | +|:--|:--|:--|:--| +| `/ai/models` | GET | `ai:chat` | 設定されたプロバイダーから利用可能なモデルを一覧表示 | +| `/ai/chat` | POST | `ai:chat` | 単発のチャット補完(同期) | +| `/ai/chat/stream` | POST | `ai:chat` | ストリーミングチャット(SSE) | +| `/ai/complete` | POST | `ai:chat` | 生の補完エンドポイント | +| `/ai/conversations` | GET / POST | `ai:chat` | 永続的な会話の一覧表示 / 作成 | +| `/ai/conversations/:id` | GET / DELETE | `ai:chat` | 会話の読み取り / 削除 | +| `/ai/conversations/:id/messages` | POST | `ai:chat` | ユーザーメッセージを追加してエージェントを実行 | +| `/ai/pending-actions` | GET | `ai:read` | HITL 承認キュー — AI が提案したミューテーション | +| `/ai/pending-actions/:id` | GET | `ai:read` | キューに入ったミューテーションを確認 | +| `/ai/pending-actions/:id/approve` | POST | `ai:approve` | ミューテーションを適用 | +| `/ai/pending-actions/:id/reject` | POST | `ai:approve` | 破棄 | + +`ai:read` と `ai:approve` の分離は、AI Builder をエンドユーザーにとって安全なものにする +セキュリティプリミティブです。 + +## Actions — `/api/v1/actions/*` + +宣言したすべての `*.action.ts` がエンドポイントになります。 + +| Path | Method | 目的 | +|:--|:--|:--| +| `/actions/:action` | POST | アクションを呼び出します。ボディはアクションの入力スキーマです。権限と入力検証はアクション宣言から得られます | + +各アクションは `action_` ツールとして AI にも公開されます — +[Actions](/docs/build/actions) を参照してください。 + +## Flows — `/api/v1/flows/*` + +| Path | Method | 目的 | +|:--|:--|:--| +| `/flows/:flow/start` | POST | フローを開始します。ボディはフローの入力です | +| `/flows/:flow/runs/:runId` | GET | 実行中 / 完了したフローのステータス + ステップ出力 | +| `/flows/:flow/runs/:runId/cancel` | POST | 進行中の実行をキャンセル | + +## Metadata — `/api/v1/meta/*` + +実行中のランタイムのメタデータへの読み取り専用のイントロスペクション。 +ツールや Console に役立ちます。 + +| Path | Method | 目的 | +|:--|:--|:--| +| `/meta` | GET | すべてのメタデータタイプ(`object`、`view`、`action`、`flow`、`agent`、…) | +| `/meta/:type` | GET | あるタイプの項目を一覧表示。`?package=` でフィルタ | +| `/meta/:type/:name` | GET | 1 件の項目を取得。`?layers=true` で 3 状態の差分ビュー(base / package / overlay)を返します | +| `/meta/:type/:name/references` | GET | この項目を参照しているすべてのメタデータ項目を検索 | +| `/meta/:type/:name/history` | GET | その項目の監査証跡 | +| `/meta/:type/:section/:name` | GET / POST | セクション化されたメタデータ項目の読み取り / アップサート | +| `/meta/:type/:section/:name` | DELETE | セクション化された項目を削除 | + +## Sharing & approvals + +| Path | Method | 目的 | +|:--|:--|:--| +| `/sharing/rules` | GET / POST / DELETE | 共有ルールを管理 | +| `/sharing/rules/:idOrName/evaluate` | POST | コンテキストに対してルールをドライラン | +| `/approvals/processes` | GET / POST | 承認プロセスの定義 | +| `/approvals/requests` | GET / POST | 承認リクエストの送信 / 一覧表示 | +| `/approvals/requests/:id/approve` | POST | 決定: 承認 | +| `/approvals/requests/:id/reject` | POST | 決定: 却下 | + +## Reports & search + +| Path | Method | 目的 | +|:--|:--|:--| +| `/reports` | GET / POST / PATCH | レポートの CRUD | +| `/reports/:id/run` | POST | レポートを実行 — 集計された行を返します | +| `/reports/:id/schedule` | POST | 定期配信をスケジュール | + +## Public forms + +`FormView.sharing.allowAnonymous` でオプトインする、唯一の **認証なし** のルートです。 + +| Path | Method | Auth | +|:--|:--|:--| +| `/forms/:slug` | GET | public — フォームスキーマを返します | +| `/forms/:slug/submit` | POST | public — 応答を送信します | + +## Utilities + +| Path | Method | Permission | 目的 | +|:--|:--|:--|:--| +| `/email/send` | POST | `email:send` | 設定されたプロバイダー経由でメールを送信 | + +## Error envelope + +すべての非 2xx 応答は同じ形式に従います: + +```json +{ + "error": { + "code": "PERMISSION_DENIED", + "message": "Missing ai:approve on conversation 01H…", + "details": { "permission": "ai:approve", "subject": "01H…" } + } +} +``` + +一般的なコード: `UNAUTHENTICATED`、`PERMISSION_DENIED`、 +`VALIDATION_ERROR`、`NOT_FOUND`、`CONCURRENT_UPDATE`、 +`RATE_LIMITED`、`INTERNAL`。 + +## Versioning + +`/api/v1` は **安定版** API です。破壊的変更は `/api/v2` に入り、 +両方が 1 つのマイナーリリースの間並行して提供されます。現在のバージョンと +非推奨化の予定は `GET /api/v1` にあります。 + +## See also + +- [ObjectQL](./objectql) — `/data/*` で使用されるクエリ言語 +- [Field types](./field-types) — データが取り得る形状 +- [Build → Actions](/docs/build/actions) — カスタムエンドポイントを宣言 +- [Security](./security) — すべてのルートが実行前にチェックする内容 diff --git a/content/docs/reference/rest-api.cn.mdx b/content/docs/reference/rest-api.zh-Hans.mdx similarity index 100% rename from content/docs/reference/rest-api.cn.mdx rename to content/docs/reference/rest-api.zh-Hans.mdx diff --git a/content/docs/reference/runtime-capabilities.de.mdx b/content/docs/reference/runtime-capabilities.de.mdx new file mode 100644 index 0000000..2f6113e --- /dev/null +++ b/content/docs/reference/runtime-capabilities.de.mdx @@ -0,0 +1,80 @@ +--- +title: Laufzeit-Funktionen +description: Funktionen, die ObjectOS aus ObjectStack-Framework-Paketen laden kann. +--- + +# Laufzeit-Funktionen + +ObjectOS lädt für jedes Projekt eine Basis-Laufzeitumgebung und installiert +anschließend die optionalen Funktionen, die vom Anwendungsartefakt deklariert +werden. + +## Basis-Laufzeitumgebung + +Der Basis-Projektkernel umfasst: + +- ObjectKernel-Lebenszyklus und Service-Registry; +- ObjectQL-Datenengine; +- konfigurierter Datentreiber; +- Metadatendienst; +- Registrierung des Anwendungsartefakts; +- Authentifizierung, wenn `OS_AUTH_SECRET` konfiguriert ist; +- Security-Plugin für RBAC, zeilenbasierte Sicherheit und Feldsicherheit; +- i18n-Dienst. + +## Optionale Funktionen + +Artefakte können Funktionen in ihrer `requires`-Liste deklarieren. ObjectOS +lädt passende Framework-Pakete, sofern sie im Image vorhanden sind. + +| Funktion | Paket | Zweck | +|---|---|---| +| `automation` | `@objectstack/service-automation` | Flow-/DAG-Ausführung und Automatisierungsknoten | +| `ai` | `@objectstack/service-ai` | LLM-Adapter, Konversationen, Tools, SSE-Routen | +| `analytics` | `@objectstack/service-analytics` | Cubes, Analyseabfragen, Reporting-Daten | +| `audit` | `@objectstack/plugin-audit` | Audit-Log-Objekt und Audit-Trail | +| `cache` | `@objectstack/service-cache` | Cache-Abstraktion und Adapter | +| `storage` | `@objectstack/service-storage` | Datei-/Objektspeicherdienst | +| `queue` | `@objectstack/service-queue` | Queue-Abstraktion und Worker | +| `job` | `@objectstack/service-job` | Geplante/Hintergrund-Jobs | +| `realtime` | `@objectstack/service-realtime` | WebSocket- und Pub/Sub-Echtzeit | +| `feed` | `@objectstack/service-feed` | Kommentare, Reaktionen, Abonnements, Aktivitäts-Feed | +| `settings` | `@objectstack/service-settings` | Settings-Manifeste und K/V-Resolver | + +Wird eine Funktion angefordert, das Image enthält das Paket jedoch nicht, +**protokolliert ObjectOS eine Warnung und läuft mit deaktivierter Funktion +weiter.** Das ist beabsichtigt – es hält die Laufzeitumgebung auch dann +startfähig, wenn während der Entwicklung ein optionales Paket fehlt – aber in +der **Produktion ist es ein echtes Risiko**: + +- Eine Anwendung, die Audit erfordert und in ein Image ohne + `@objectstack/plugin-audit` geladen wird, startet sauber **und schreibt + kein Audit-Log**. Compliance-Nachweise fehlen, ohne dass ein Fehler + auftritt. +- Eine Job-gesteuerte Anwendung, die in ein Image ohne + `@objectstack/service-job` geladen wird, startet sauber **und führt + geplante Arbeiten stillschweigend nie aus**. + +**Produktions-Checkliste:** + +1. Behandeln Sie Funktionswarnungen als Bereitstellungsfehler. Durchsuchen + Sie die Startprotokolle nach `capability not loaded` (oder Ihrem + Äquivalent) und lassen Sie die Readiness-Probe / das Rollout fehlschlagen, + falls solche Warnungen auftreten. +2. Fixieren Sie das Laufzeit-Image auf eines, das jedes Paket enthält, das + Ihre Artefakte in `requires` deklarieren. +3. Dokumentieren Sie beim Veröffentlichen eines Artefakts dessen + `requires`-Liste mit, damit Betreiber das passende Image überprüfen können. + +## API-Oberfläche + +ObjectOS stellt üblicherweise bereit: + +- generierte REST-APIs; +- Auth-Endpunkte unter `/api/v1/auth/*`; +- Metadaten- und i18n-Endpunkte; +- Dienst-Endpunkte für aktivierte Funktionen. + +GraphQL und OData sind Funktionen auf Framework-Ebene und sollten nur dann als +unterstützt dokumentiert werden, wenn sie vom bereitgestellten +Laufzeitpaket enthalten und aktiviert sind. diff --git a/content/docs/reference/runtime-capabilities.es.mdx b/content/docs/reference/runtime-capabilities.es.mdx new file mode 100644 index 0000000..0ab91e6 --- /dev/null +++ b/content/docs/reference/runtime-capabilities.es.mdx @@ -0,0 +1,77 @@ +--- +title: Capacidades de runtime +description: Capacidades que ObjectOS puede cargar desde los paquetes del framework ObjectStack. +--- + +# Capacidades de runtime + +ObjectOS carga un runtime base para cada proyecto y luego instala las +capacidades opcionales declaradas por el artefacto de la aplicación. + +## Runtime base + +El núcleo base del proyecto incluye: + +- el ciclo de vida de ObjectKernel y el registro de servicios; +- el motor de datos ObjectQL; +- el controlador de datos configurado; +- el servicio de metadatos; +- el registro del artefacto de la aplicación; +- autenticación cuando `OS_AUTH_SECRET` está configurado; +- el plugin de seguridad para RBAC, seguridad a nivel de fila y seguridad de campos; +- el servicio de i18n. + +## Capacidades opcionales + +Los artefactos pueden declarar capacidades en su lista `requires`. ObjectOS +carga los paquetes del framework correspondientes cuando están presentes en la imagen. + +| Capacidad | Paquete | Propósito | +|---|---|---| +| `automation` | `@objectstack/service-automation` | Ejecución de flujos/DAG y nodos de automatización | +| `ai` | `@objectstack/service-ai` | Adaptadores de LLM, conversaciones, herramientas, rutas SSE | +| `analytics` | `@objectstack/service-analytics` | Cubos, consultas de analítica, datos de informes | +| `audit` | `@objectstack/plugin-audit` | Objeto de registro de auditoría y pista de auditoría | +| `cache` | `@objectstack/service-cache` | Abstracción de caché y adaptadores | +| `storage` | `@objectstack/service-storage` | Servicio de almacenamiento de archivos/objetos | +| `queue` | `@objectstack/service-queue` | Abstracción de colas y workers | +| `job` | `@objectstack/service-job` | Trabajos programados/en segundo plano | +| `realtime` | `@objectstack/service-realtime` | WebSocket y realtime mediante pub/sub | +| `feed` | `@objectstack/service-feed` | Comentarios, reacciones, suscripciones, feed de actividad | +| `settings` | `@objectstack/service-settings` | Manifiestos de configuración y resolución de K/V | + +Si se solicita una capacidad pero la imagen no incluye el paquete, +**ObjectOS registra una advertencia y continúa ejecutándose con esa capacidad +deshabilitada.** Esto es intencional: mantiene el runtime arrancable incluso +cuando falta un paquete opcional durante el desarrollo, pero en +**producción es un riesgo real**: + +- Una aplicación que requiere auditoría cargada en una imagen sin + `@objectstack/plugin-audit` arrancará correctamente **y no escribirá ningún + registro de auditoría**. Faltará la evidencia de cumplimiento sin ningún error. +- Una aplicación basada en trabajos cargada en una imagen sin + `@objectstack/service-job` arrancará correctamente **y nunca ejecutará en + silencio el trabajo programado**. + +**Lista de comprobación para producción:** + +1. Trata las advertencias de capacidades como fallos de despliegue. Busca con + grep en los logs de arranque `capability not loaded` (o su equivalente) y + haz que la sonda de readiness / el despliegue fallen si aparece alguna. +2. Fija la imagen del runtime a una que incluya todos los paquetes que tus + artefactos declaran en `requires`. +3. Al publicar un artefacto, documenta su lista `requires` junto a él para + que los operadores puedan verificar la imagen correspondiente. + +## Superficie de API + +ObjectOS expone habitualmente: + +- APIs REST generadas; +- endpoints de autenticación bajo `/api/v1/auth/*`; +- endpoints de metadatos e i18n; +- endpoints de servicio para las capacidades habilitadas. + +GraphQL y OData son capacidades a nivel de framework y solo deben +documentarse como compatibles cuando están incluidas y habilitadas por el +paquete de runtime desplegado. diff --git a/content/docs/reference/runtime-capabilities.fr.mdx b/content/docs/reference/runtime-capabilities.fr.mdx new file mode 100644 index 0000000..8c351f1 --- /dev/null +++ b/content/docs/reference/runtime-capabilities.fr.mdx @@ -0,0 +1,77 @@ +--- +title: Capacités d'exécution +description: Capacités qu'ObjectOS peut charger depuis les paquets du framework ObjectStack. +--- + +# Capacités d'exécution + +ObjectOS charge un runtime de base pour chaque projet, puis installe les +capacités optionnelles déclarées par l'artefact de l'application. + +## Runtime de base + +Le noyau de projet de base comprend : + +- le cycle de vie d'ObjectKernel et le registre de services ; +- le moteur de données ObjectQL ; +- le pilote de données configuré ; +- le service de métadonnées ; +- l'enregistrement de l'artefact de l'application ; +- l'authentification lorsque `OS_AUTH_SECRET` est configuré ; +- le plugin de sécurité pour le RBAC, la sécurité au niveau des lignes et la sécurité des champs ; +- le service i18n. + +## Capacités optionnelles + +Les artefacts peuvent déclarer des capacités dans leur liste `requires`. ObjectOS +charge les paquets de framework correspondants lorsqu'ils sont présents dans l'image. + +| Capacité | Paquet | Objectif | +|---|---|---| +| `automation` | `@objectstack/service-automation` | Exécution de flux/DAG et nœuds d'automatisation | +| `ai` | `@objectstack/service-ai` | Adaptateurs LLM, conversations, outils, routes SSE | +| `analytics` | `@objectstack/service-analytics` | Cubes, requêtes analytiques, données de reporting | +| `audit` | `@objectstack/plugin-audit` | Objet de journal d'audit et piste d'audit | +| `cache` | `@objectstack/service-cache` | Abstraction de cache et adaptateurs | +| `storage` | `@objectstack/service-storage` | Service de stockage de fichiers/objets | +| `queue` | `@objectstack/service-queue` | Abstraction de file d'attente et workers | +| `job` | `@objectstack/service-job` | Tâches planifiées/en arrière-plan | +| `realtime` | `@objectstack/service-realtime` | Temps réel WebSocket et pub/sub | +| `feed` | `@objectstack/service-feed` | Commentaires, réactions, abonnements, flux d'activité | +| `settings` | `@objectstack/service-settings` | Manifestes de paramètres et résolveur clé/valeur | + +Si une capacité est demandée mais que l'image n'inclut pas le paquet, +**ObjectOS enregistre un avertissement et continue de fonctionner avec cette +capacité désactivée.** C'est intentionnel — cela permet de maintenir le runtime +démarrable même lorsqu'un paquet optionnel est absent pendant le développement — mais en +**production, c'est un risque réel** : + +- Une application nécessitant l'audit chargée dans une image sans + `@objectstack/plugin-audit` démarrera correctement **et n'écrira aucun + journal d'audit**. Les preuves de conformité seront manquantes sans aucune erreur. +- Une application pilotée par des tâches chargée dans une image sans + `@objectstack/service-job` démarrera correctement **et n'exécutera silencieusement jamais + les travaux planifiés**. + +**Liste de contrôle pour la production :** + +1. Traitez les avertissements de capacité comme des échecs de déploiement. Recherchez dans les journaux de démarrage + `capability not loaded` (ou son équivalent) et faites échouer la + sonde de disponibilité / le déploiement si l'un d'eux apparaît. +2. Épinglez l'image du runtime à une image qui inclut chaque paquet que vos + artefacts déclarent dans `requires`. +3. Lors de la publication d'un artefact, documentez sa liste `requires` à côté de + lui afin que les opérateurs puissent vérifier l'image correspondante. + +## Surface d'API + +ObjectOS expose couramment : + +- des API REST générées ; +- des points de terminaison d'authentification sous `/api/v1/auth/*` ; +- des points de terminaison de métadonnées et d'i18n ; +- des points de terminaison de service pour les capacités activées. + +GraphQL et OData sont des capacités au niveau du framework et ne doivent être +documentés comme pris en charge que lorsqu'ils sont inclus et activés par le paquet +de runtime déployé. diff --git a/content/docs/reference/runtime-capabilities.ja.mdx b/content/docs/reference/runtime-capabilities.ja.mdx new file mode 100644 index 0000000..ff4b2e9 --- /dev/null +++ b/content/docs/reference/runtime-capabilities.ja.mdx @@ -0,0 +1,61 @@ +--- +title: ランタイム機能 +description: ObjectOS が ObjectStack フレームワークパッケージから読み込める機能。 +--- + +# ランタイム機能 + +ObjectOS はすべてのプロジェクトに対してベースランタイムを読み込み、その後アプリケーションアーティファクトによって宣言されたオプション機能をインストールします。 + +## ベースランタイム + +ベースプロジェクトカーネルには以下が含まれます。 + +- ObjectKernel のライフサイクルとサービスレジストリ +- ObjectQL データエンジン +- 構成されたデータドライバ +- メタデータサービス +- アプリケーションアーティファクトの登録 +- `OS_AUTH_SECRET` が構成されている場合の認証 +- RBAC、行レベルセキュリティ、フィールドセキュリティのためのセキュリティプラグイン +- i18n サービス + +## オプション機能 + +アーティファクトは `requires` リストに機能を宣言できます。ObjectOS はイメージ内に存在する場合、一致するフレームワークパッケージを読み込みます。 + +| 機能 | パッケージ | 目的 | +|---|---|---| +| `automation` | `@objectstack/service-automation` | Flow/DAG の実行と自動化ノード | +| `ai` | `@objectstack/service-ai` | LLM アダプタ、会話、ツール、SSE ルート | +| `analytics` | `@objectstack/service-analytics` | Cube、分析クエリ、レポートデータ | +| `audit` | `@objectstack/plugin-audit` | 監査ログオブジェクトと監査証跡 | +| `cache` | `@objectstack/service-cache` | キャッシュ抽象化とアダプタ | +| `storage` | `@objectstack/service-storage` | ファイル/オブジェクトストレージサービス | +| `queue` | `@objectstack/service-queue` | キュー抽象化とワーカー | +| `job` | `@objectstack/service-job` | スケジュールされた/バックグラウンドのジョブ | +| `realtime` | `@objectstack/service-realtime` | WebSocket と pub/sub のリアルタイム | +| `feed` | `@objectstack/service-feed` | コメント、リアクション、サブスクリプション、アクティビティフィード | +| `settings` | `@objectstack/service-settings` | 設定マニフェストと K/V リゾルバ | + +機能がリクエストされたものの、イメージにそのパッケージが含まれていない場合、**ObjectOS は警告をログに記録し、その機能を無効にしたまま実行を継続します。** これは意図的なものであり、開発中にオプションパッケージが欠落していてもランタイムを起動可能に保つためですが、**本番環境では実際のリスクとなります**。 + +- 監査が必須のアプリを `@objectstack/plugin-audit` を含まないイメージに読み込むと、正常に起動し、**監査ログを一切書き込みません**。コンプライアンスの証跡が、何のエラーもなく欠落することになります。 +- ジョブ駆動のアプリを `@objectstack/service-job` を含まないイメージに読み込むと、正常に起動し、**スケジュールされた作業を黙って一切実行しません**。 + +**本番環境のチェックリスト:** + +1. 機能の警告をデプロイの失敗として扱ってください。起動ログから `capability not loaded`(またはそれに相当するもの)を grep し、いずれかが出現した場合はレディネスプローブ / ロールアウトを失敗させてください。 +2. アーティファクトが `requires` で宣言するすべてのパッケージを含むランタイムイメージにピン留めしてください。 +3. アーティファクトを公開する際には、その `requires` リストを併せてドキュメント化し、運用者が一致するイメージを検証できるようにしてください。 + +## API サーフェス + +ObjectOS は一般的に以下を公開します。 + +- 生成された REST API +- `/api/v1/auth/*` 配下の認証エンドポイント +- メタデータと i18n のエンドポイント +- 有効化された機能のサービスエンドポイント + +GraphQL と OData はフレームワークレベルの機能であり、デプロイされたランタイムパッケージに含まれ、有効化されている場合にのみサポート対象としてドキュメント化されるべきです。 diff --git a/content/docs/reference/runtime-capabilities.cn.mdx b/content/docs/reference/runtime-capabilities.zh-Hans.mdx similarity index 100% rename from content/docs/reference/runtime-capabilities.cn.mdx rename to content/docs/reference/runtime-capabilities.zh-Hans.mdx diff --git a/content/docs/reference/security.es.mdx b/content/docs/reference/security.es.mdx new file mode 100644 index 0000000..ea33c1c --- /dev/null +++ b/content/docs/reference/security.es.mdx @@ -0,0 +1,277 @@ +--- +title: Seguridad y Cumplimiento +description: Qué se protege, cómo y quién es responsable — para revisión de seguridad. +--- + +# Seguridad y Cumplimiento + +Esta página está dirigida a revisores de seguridad, administradores de TI y +cualquier persona que tenga que responder "¿es seguro adoptar esto?" + +## El modelo de amenazas en una frase + +ObjectOS se ejecuta como un único proceso de Node.js dentro de **tu** red, +se comunica con **tu** base de datos y nunca se conecta a casa. El radio de +impacto de un compromiso es la información de la base de datos a la que se +conecta — nada más. + +## Residencia de los datos + +| Clase de datos | Reside en | ¿Sale de tu red? | +|---|---|---| +| Registros de negocio | Tu base de datos | **No** | +| Cuentas de usuario, sesiones, tokens OAuth | Tu base de datos | **No** | +| Registro de auditoría | Tu base de datos | **No** | +| Configuración, claves de API | Tu base de datos / tu gestor de secretos | **No** | +| Archivos subidos | Tu disco o bucket compatible con S3 | **No** | +| Telemetría / datos de uso | — | **No se recopila nada** | + +ObjectOS realiza **cero llamadas salientes** a menos que las configures +explícitamente (descubrimiento OIDC, proveedor de correo, proveedor de IA, +destinos de webhook, almacenamiento externo). No se conecta a casa, no +consulta un servidor de licencias, no hace ping en busca de actualizaciones. + +## Cifrado + +| Capa | Mecanismo | Responsabilidad | +|---|---|---| +| En tránsito (navegador ↔ ObjectOS) | TLS, terminado en tu edge / ingress | Tú | +| En tránsito (ObjectOS ↔ base de datos) | TLS a nivel de driver (Postgres `sslmode=require`, MongoDB `tls=true`, …) | Tú — define la cadena de conexión | +| En reposo (datos de negocio) | Nativo de la base de datos (p. ej. Postgres TDE, cifrado de RDS) | Tú | +| En reposo (archivos subidos) | Nativo del almacenamiento (S3 SSE, R2 por defecto, FDE a nivel de disco) | Tú | +| Secretos en la BD (configuración, secreto de cliente OIDC) | Cifrados por el servicio de configuración | ObjectOS | +| Cookies de sesión / tokens | Firmados con HMAC mediante `OS_AUTH_SECRET` | ObjectOS | +| Valores de claves de API | **Hasheados** en la BD — una fila de BD filtrada no puede reconstruir la clave | ObjectOS | + +## Autenticación + +Integrada (mediante `@objectstack/plugin-auth`, impulsada por Better Auth): + +- correo/contraseña con verificación + restablecimiento +- gestión de sesiones con revocación +- OAuth social (Google, GitHub, Microsoft, Apple, …) +- OIDC/SSO empresarial (Okta, Entra ID, Keycloak, Ping) +- doble factor (TOTP) +- passkeys / WebAuthn +- enlaces mágicos +- flujo de dispositivo CLI/navegador +- claves de API (hasheadas, con caducidad, revocables, vinculadas a un usuario) + +Consulta [Authentication](/docs/configure/authentication). + +## Autorización + +Aplicación por capas (mediante `@objectstack/plugin-security`): + +1. **Permisos de objeto** — CRUD por objeto y por conjunto de permisos +2. **Seguridad a nivel de fila** — expresiones de política declarativas inyectadas en + las consultas; no es opcional +3. **Seguridad a nivel de campo** — campos eliminados de las respuestas / + rechazados en escritura +4. **Alcance por organización** — aislamiento multiinquilino; omitirlo requiere + `viewAllRecords` explícito + +Las operaciones en contexto de sistema omiten las comprobaciones para que los trabajos +internos / migraciones puedan ejecutarse — estas rutas son auditables. + +Consulta [Permissions](/docs/configure/permissions). + +## Auditoría y evidencias + +Cuando la capacidad de auditoría está cargada (`@objectstack/plugin-audit`): + +- Cada operación CRUD sobre cada objeto → una fila de auditoría. +- Valores anteriores/posteriores de los cambios de campo. +- Eventos de autenticación, concesión de permisos, revocación de sesiones. +- Las filas de auditoría son **inmutables**: no pueden modificarse, solo archivarse. +- La retención es configurable; combínala con la política de archivado de tu BD. + +Esta es la base de evidencias para SOC 2 CC6/CC7, ISO 27001 A.12.4, HIPAA +§164.312(b) y el Artículo 30 del RGPD. + +## Marcos de cumplimiento + +ObjectOS proporciona las **primitivas técnicas** que pide cada marco común. +La certificación es una propiedad del despliegue, no del software — pero los +controles se mapean con claridad: + +| Marco | Qué te aporta ObjectOS | +|---|---| +| **SOC 2** | Control de acceso (CC6), gestión de cambios (registro de auditoría), cifrado (despliegue), monitorización (observabilidad), copias de seguridad (operate/backup) | +| **ISO 27001** | A.5 políticas (RBAC), A.8 gestión de activos (catálogo de objetos), A.9 control de acceso, A.12 operaciones, A.18 cumplimiento | +| **HIPAA** | Controles de acceso (§164.312(a)), controles de auditoría (§164.312(b)), integridad (auditoría inmutable), seguridad en la transmisión (TLS) | +| **RGPD** | Artículo 30 registros de actividades de tratamiento (auditoría), Artículo 32 seguridad del tratamiento, Artículo 17 derecho de supresión (se admite borrado lógico + físico), residencia de datos (tú eliges la región) | +| **CCPA / China DSL / Russia 152-FZ** | El autoalojamiento en la región adecuada satisface la residencia; los controles de acceso + auditoría cubren la mayoría de las obligaciones de reporte | + +ObjectOS en sí **no está certificado** porque la certificación corresponde a un +despliegue en ejecución, no a un binario. Tu despliegue sí puede certificarse — +muchos ya lo están. + +## Manejo de secretos + +| Secreto | Dónde colocarlo | +|---|---| +| `OS_AUTH_SECRET` | Tu gestor de secretos (Vault, AWS Secrets Manager, k8s Secret); inyéctalo como variable de entorno | +| URL de base de datos con credenciales | Igual | +| Secreto de cliente OIDC | Igual | +| Secretos de proveedores OAuth | Igual | +| Claves de proveedores de API (correo, almacenamiento, IA) | Igual | +| Configuración almacenada en la BD | Cifrada en reposo por el servicio de configuración | + +**Nunca** incorpores secretos en el artefacto (`objectstack.json`), la +imagen de Docker, el archivo compose ni en Git. La interfaz de configuración en Console +muestra los valores gestionados por entorno como bloqueados, de modo que los operadores no puedan +sobrescribirlos accidentalmente. + +## Modelo de red + +Entrada requerida: +- HTTPS desde tu ingress / balanceador de carga hacia ObjectOS en `:3000` (por defecto). + +Salida requerida (solo si configuras estas funciones): +- Tu base de datos (Postgres / Mongo / Turso / …). +- Almacenamiento compatible con S3 (si la capacidad `storage` está habilitada con el adaptador de S3). +- URL de descubrimiento OIDC (si SSO está habilitado). +- API del proveedor de correo (Resend / Postmark). +- API del proveedor de IA (OpenAI / Anthropic / Google / …). +- Destinos de webhook. + +Esa es toda la superficie de salida. Consulta [Air-gapped](/docs/deploy/air-gapped) +para despliegues que reducen aún más. + +## IA: herramientas, aprobaciones, aislamiento + +El AI Builder es la superficie más sensible a la seguridad que vas a exponer, +por lo que cuenta con su propia capa de aplicación además de todo lo anterior. + +### Cómo puede la IA modificar el estado + +El modelo **no puede escribir directamente** en tu base de datos. La única manera +de que cambie el estado es emitiendo una llamada estructurada a una herramienta que el servicio +de IA recibe, valida y encola. La cadena: + +```text +user prompt + → model emits tool call (e.g. add_field { object: 'ticket', name: 'severity', type: 'select' }) + → AI service validates payload against the tool's Zod schema + → if the tool is "mutating": queue as pending action (no state change yet) + → human reviewer approves → mutation applied → audit row written + → if the tool is "read-only": run immediately, response returned to model +``` + +Hay 11 herramientas de metadatos de primera parte +([consulta Build → AI Builder](/docs/build/ai-builder)) más una herramienta +`action_` por cada acción declarada. Cada herramienta — de primera parte o +personalizada — tiene el mismo ciclo de vida. + +### Claves de permiso + +| Clave | Concede | +|:--|:--| +| `ai:chat` | Mantener una conversación; consumir modelos; permitir que el agente llame a herramientas de solo lectura | +| `ai:complete` | Endpoint de completado en bruto (sin bucle de agente) | +| `ai:conversations` | Listar / inspeccionar / eliminar conversaciones (propias o todas, según el alcance de RBAC) | +| `ai:agents` | Gestionar metadatos de agentes (junto con `ai:chat` para invocarlos) | +| `ai:tools` | Listar el catálogo de herramientas | +| `ai:execute` | Invocar una herramienta directamente vía REST (avanzado — normalmente solo los agentes ambientales lo necesitan) | +| `ai:read` | Leer la cola de acciones pendientes y la lista de modelos | +| `ai:approve` | Aprobar / rechazar mutaciones encoladas | +| `ai:admin` | Administración completa del servicio de IA | + +La división crítica es **`ai:chat` ≠ `ai:approve`**. Otorga a la mayoría de los usuarios +`ai:chat` para que el asistente funcione; reserva `ai:approve` para los +administradores / propietarios de la aplicación que deban revisar cambios estructurales. Los usuarios +finales pueden, por tanto, "construir al vuelo" de forma segura — lo peor que pueden hacer es +encolar un cambio incorrecto que otra persona debe aceptar. + +### Aislamiento de inquilinos + +- Los agentes, conversaciones, bases de conocimiento y acciones pendientes están + acotados a un único **Environment** (inquilino). El inquilino A no puede ver las + conversaciones del inquilino B, las herramientas que la IA propuso ni los corpus de conocimiento — + incluso si se instaló la misma definición de agente desde el mismo + paquete del marketplace. +- Las herramientas de metadatos (`create_object`, `add_field`, …) operan sobre + el **paquete activo** en el inquilino del llamante. No pueden salir + de él. +- Las entradas de las herramientas se validan con CEL y el motor rechaza referencias a + paquetes de sistema reservados (`sys.*`) o a nombres de objeto de otros inquilinos. + +### Eventos de auditoría + +Cuando la capacidad de auditoría está cargada: + +- `ai.chat.message` — cada mensaje de usuario / asistente, con modelo + recuento de tokens +- `ai.tool.call` — nombre de herramienta, entrada validada, salida completa (o error) +- `ai.pending_action.queued` — mutación propuesta, diff completo +- `ai.pending_action.approved` / `.rejected` — quién decidió, cuándo, por qué +- `ai.metadata.applied` — escritura real en el almacén de metadatos, con diff + +Estas filas son inmutables y pueden exportarse para revisión de seguridad o +imputación de costes. Los recuentos de tokens por (proveedor, modelo, usuario) alimentan la +atribución de costes. + +### Postura frente a la inyección de prompts + +La inyección indirecta de prompts (p. ej. contenido malicioso en un documento que +el agente recupera) es un riesgo real; ObjectOS reduce el radio de impacto por +construcción: + +- La IA **no puede eludir la validación de herramientas** — incluso si se la convence de + emitir una carga maliciosa, el esquema de Zod rechaza las entradas malformadas + antes de que lleguen al motor. +- Las herramientas mutadoras siempre se encolan. Un prompt inyectado no puede escribir + silenciosamente en la base de datos. +- Las llamadas a herramientas heredan los **permisos del usuario final**, no los permisos + de la cuenta de servicio del modelo. Un usuario nunca puede usar la IA para hacer + algo que no pudiera hacer por sí mismo a través de Console o REST. +- Las skills cargadas en los agentes están versionadas y son explícitas — consulta + [Build → IDE Skills](/docs/build/ai-skills) y + [Build → AI Builder](/docs/build/ai-builder). + +### Flujo de datos hacia proveedores de IA externos + +Cuando configuras un proveedor (OpenAI, Anthropic, …), solo lo +siguiente sale de tu red: + +- El historial de conversación que el modelo necesita (sujeto a la configuración + `redact` de tu servicio de IA — consulta [Configure → AI](/docs/configure/ai)) +- Definiciones de herramientas (nombres, esquemas JSON — sin datos de registros) +- Salidas de herramientas que el modelo necesita para continuar (p. ej. el resultado de una consulta + que el usuario solicitó explícitamente) + +Para despliegues air-gapped, apunta el servicio de IA a un endpoint local de Ollama / +vLLM / TGI y el mismo flujo permanece dentro de tu perímetro. + +## Divulgación de vulnerabilidades + +Reporta los problemas de seguridad de forma privada a +**security@objectstack.ai**. Respondemos en un plazo de 1 día hábil. No +abras issues públicas en GitHub para problemas de seguridad. + +## Cadena de suministro + +- Imágenes precompiladas publicadas desde [github.com/objectstack-ai/objectos](https://github.com/objectstack-ai/objectos) + con procedencia de compilación reproducible. +- Todos los paquetes `@objectstack/*` tienen el código fuente publicado en GitHub — + Apache-2.0, sin ofuscación. +- Usa etiquetas de imagen ancladas a SHA (`sha-`) en producción para evitar + desviaciones; consulta [Docker](/docs/deploy/docker). + +## Lista de verificación de endurecimiento sugerida + +- [ ] TLS terminado en el edge con un certificado real. +- [ ] `OS_AUTH_SECRET` tiene 32+ bytes aleatorios, en un gestor de secretos. +- [ ] La conexión a la base de datos usa TLS. +- [ ] HSTS habilitado tras validar TLS. +- [ ] Orígenes CORS explícitos (nunca `*` con credenciales). +- [ ] Límites de tasa en los endpoints de autenticación (`10/min/IP` recomendado). +- [ ] La retención de auditoría coincide con la política. +- [ ] OIDC para cuentas humanas; claves de API para cuentas de máquina. +- [ ] Simulacro de copia de seguridad + restauración ejecutado y cronometrado. +- [ ] Pruebas negativas: acceso entre organizaciones denegado, la seguridad de campo se mantiene, la sesión expirada se rechaza. +- [ ] Imagen anclada a una etiqueta `sha-` o semver. +- [ ] `os doctor` limpio en CI antes de cada release. + +Consulta [Production Readiness](/docs/operate/production) para la lista de +verificación completa de puesta en marcha. diff --git a/content/docs/reference/security.fr.mdx b/content/docs/reference/security.fr.mdx new file mode 100644 index 0000000..9371af2 --- /dev/null +++ b/content/docs/reference/security.fr.mdx @@ -0,0 +1,276 @@ +--- +title: Sécurité et conformité +description: Ce qui est protégé, comment, qui est responsable — pour la revue de sécurité. +--- + +# Sécurité et conformité + +Cette page s'adresse aux examinateurs de sécurité, aux administrateurs IT et à toute personne qui doit +répondre à la question « est-il sûr de l'adopter ? » + +## Le modèle de menace en une phrase + +ObjectOS s'exécute comme un unique processus Node.js à l'intérieur de **votre** réseau, +communique avec **votre** base de données et ne rappelle jamais sa base. Le rayon d'impact d'une +compromission se limite aux données de la base de données à laquelle il se connecte — rien de +plus. + +## Résidence des données + +| Classe de données | Réside dans | Quitte votre réseau ? | +|---|---|---| +| Enregistrements métier | Votre base de données | **Non** | +| Comptes utilisateurs, sessions, jetons OAuth | Votre base de données | **Non** | +| Journal d'audit | Votre base de données | **Non** | +| Paramètres, clés API | Votre base de données / votre gestionnaire de secrets | **Non** | +| Fichiers téléversés | Votre disque ou bucket compatible S3 | **Non** | +| Télémétrie / données d'usage | — | **Aucune collecte** | + +ObjectOS effectue **zéro appel sortant** sauf si vous les configurez explicitement +(découverte OIDC, fournisseur d'e-mail, fournisseur d'IA, cibles de webhook, +stockage externe). Il ne rappelle pas sa base, ne contacte pas un serveur de +licence, ne sonde pas pour des mises à jour. + +## Chiffrement + +| Couche | Mécanisme | Responsabilité | +|---|---|---| +| En transit (navigateur ↔ ObjectOS) | TLS, terminé au niveau de votre edge / ingress | Vous | +| En transit (ObjectOS ↔ base de données) | TLS au niveau du pilote (Postgres `sslmode=require`, MongoDB `tls=true`, …) | Vous — définissez la chaîne de connexion | +| Au repos (données métier) | Natif à la base de données (par ex. Postgres TDE, chiffrement RDS) | Vous | +| Au repos (fichiers téléversés) | Natif au stockage (S3 SSE, R2 par défaut, FDE au niveau du disque) | Vous | +| Secrets en base (paramètres, secret client OIDC) | Chiffrés par le service de paramètres | ObjectOS | +| Cookies / jetons de session | Signés par HMAC avec `OS_AUTH_SECRET` | ObjectOS | +| Valeurs des clés API | **Hachées** en base — une ligne de base fuitée ne permet pas de reconstruire la clé | ObjectOS | + +## Authentification + +Intégrée (via `@objectstack/plugin-auth`, propulsée par Better Auth) : + +- e-mail/mot de passe avec vérification + réinitialisation +- gestion des sessions avec révocation +- OAuth social (Google, GitHub, Microsoft, Apple, …) +- OIDC/SSO d'entreprise (Okta, Entra ID, Keycloak, Ping) +- double authentification (TOTP) +- passkeys / WebAuthn +- liens magiques +- flux d'appareil CLI/navigateur +- clés API (hachées, expirables, révocables, liées à un utilisateur) + +Voir [Authentication](/docs/configure/authentication). + +## Autorisation + +Application en couches (via `@objectstack/plugin-security`) : + +1. **Permissions sur les objets** — CRUD par objet par jeu de permissions +2. **Sécurité au niveau des lignes** — expressions de politique déclaratives injectées dans + les requêtes ; non optionnelle +3. **Sécurité au niveau des champs** — champs retirés des réponses / + rejetés en écriture +4. **Cloisonnement par organisation** — isolation multi-locataire ; le contournement requiert + un `viewAllRecords` explicite + +Les opérations en contexte système contournent les vérifications afin que les tâches internes / migrations +puissent s'exécuter — ces chemins sont auditables. + +Voir [Permissions](/docs/configure/permissions). + +## Audit et preuves + +Lorsque la capacité d'audit est chargée (`@objectstack/plugin-audit`) : + +- Chaque opération CRUD sur chaque objet → ligne d'audit. +- Valeurs avant/après pour les modifications de champs. +- Événements d'authentification, d'attribution de permissions, de révocation de session. +- Les lignes d'audit sont **immuables** : elles ne peuvent être modifiées, seulement archivées. +- La rétention est configurable ; à coupler avec la politique d'archivage de votre base de données. + +C'est la base de preuves pour SOC 2 CC6/CC7, ISO 27001 A.12.4, HIPAA +§164.312(b) et l'article 30 du RGPD. + +## Cadres de conformité + +ObjectOS fournit les **primitives techniques** que chaque cadre courant +demande. La certification est une propriété du déploiement, pas du +logiciel — mais les contrôles s'y rattachent proprement : + +| Cadre | Ce qu'ObjectOS vous apporte | +|---|---| +| **SOC 2** | Contrôle d'accès (CC6), gestion des changements (journal d'audit), chiffrement (déploiement), surveillance (observabilité), sauvegarde (operate/backup) | +| **ISO 27001** | A.5 politiques (RBAC), A.8 gestion des actifs (catalogue d'objets), A.9 contrôle d'accès, A.12 exploitation, A.18 conformité | +| **HIPAA** | Contrôles d'accès (§164.312(a)), contrôles d'audit (§164.312(b)), intégrité (audit immuable), sécurité de la transmission (TLS) | +| **RGPD** | Article 30 registres de traitement (audit), Article 32 sécurité du traitement, Article 17 droit à l'effacement (suppression douce + définitive prises en charge), résidence des données (vous choisissez la région) | +| **CCPA / China DSL / Russia 152-FZ** | L'auto-hébergement dans la bonne région satisfait la résidence ; les contrôles d'accès + l'audit couvrent la plupart des obligations de déclaration | + +ObjectOS lui-même n'est **pas certifié** car la certification porte sur un +déploiement en exécution, et non sur un binaire. Votre déploiement peut être certifié — +beaucoup le sont déjà. + +## Gestion des secrets + +| Secret | Où le placer | +|---|---| +| `OS_AUTH_SECRET` | Votre gestionnaire de secrets (Vault, AWS Secrets Manager, k8s Secret) ; injecté comme variable d'environnement | +| URL de base de données avec identifiants | Idem | +| Secret client OIDC | Idem | +| Secrets de fournisseur OAuth | Idem | +| Clés de fournisseur API (e-mail, stockage, IA) | Idem | +| Paramètres stockés en base | Chiffrés au repos par le service de paramètres | + +**N'intégrez jamais** de secrets dans l'artefact (`objectstack.json`), l' +image Docker, le fichier compose ou Git. L'interface de paramètres dans Console +affiche les valeurs gérées par variables d'environnement comme verrouillées, de sorte que les opérateurs ne puissent pas accidentellement +les remplacer. + +## Modèle réseau + +Entrant requis : +- HTTPS depuis votre ingress / répartiteur de charge vers ObjectOS sur `:3000` (par défaut). + +Sortant requis (uniquement si vous configurez ces fonctionnalités) : +- Votre base de données (Postgres / Mongo / Turso / …). +- Stockage compatible S3 (si la capacité `storage` est activée avec l'adaptateur S3). +- URL de découverte OIDC (si le SSO est activé). +- API de fournisseur d'e-mail (Resend / Postmark). +- API de fournisseur d'IA (OpenAI / Anthropic / Google / …). +- Cibles de webhook. + +Voilà toute la surface de sortie. Voir [Air-gapped](/docs/deploy/air-gapped) +pour des déploiements qui en retranchent encore davantage. + +## IA : outils, approbations, isolation + +L'AI Builder est la surface la plus sensible en matière de sécurité que vous exposerez, +il dispose donc de sa propre couche d'application en plus de tout ce qui précède. + +### Comment l'IA peut modifier l'état + +Le modèle **ne peut pas écrire directement** dans votre base de données. La seule façon dont +l'état change est en émettant un appel d'outil structuré que le service d'IA +reçoit, valide et met en file d'attente. La chaîne : + +```text +user prompt + → model emits tool call (e.g. add_field { object: 'ticket', name: 'severity', type: 'select' }) + → AI service validates payload against the tool's Zod schema + → if the tool is "mutating": queue as pending action (no state change yet) + → human reviewer approves → mutation applied → audit row written + → if the tool is "read-only": run immediately, response returned to model +``` + +Il existe 11 outils de métadonnées de première partie +([voir Build → AI Builder](/docs/build/ai-builder)) plus un +outil `action_` par action déclarée. Chaque outil — de première partie ou +personnalisé — suit le même cycle de vie. + +### Clés de permission + +| Clé | Octroie | +|:--|:--| +| `ai:chat` | Tenir une conversation ; consommer des modèles ; laisser l'agent appeler des outils en lecture seule | +| `ai:complete` | Point de terminaison de complétion brute (sans boucle d'agent) | +| `ai:conversations` | Lister / inspecter / supprimer des conversations (les siennes ou toutes, selon la portée RBAC) | +| `ai:agents` | Gérer les métadonnées d'agent (avec `ai:chat` pour les invoquer) | +| `ai:tools` | Lister le catalogue d'outils | +| `ai:execute` | Invoquer un outil directement via REST (avancé — normalement, seuls les agents ambiants en ont besoin) | +| `ai:read` | Lire la file des actions en attente et la liste des modèles | +| `ai:approve` | Approuver / rejeter les mutations en file d'attente | +| `ai:admin` | Administration complète du service d'IA | + +La distinction critique est **`ai:chat` ≠ `ai:approve`**. Accordez `ai:chat` à la +plupart des utilisateurs pour que l'assistant fonctionne ; réservez `ai:approve` aux +administrateurs / propriétaires d'applications qui doivent examiner les changements structurels. Les utilisateurs +finaux peuvent ainsi « construire à l'instinct » en toute sécurité — au pire, ils peuvent +mettre en file d'attente un mauvais changement que quelqu'un d'autre doit accepter. + +### Isolation des locataires + +- Les agents, conversations, bases de connaissances et actions en attente sont + cloisonnés à un seul **Environment** (locataire). Le locataire A ne peut pas voir les + conversations, les outils proposés par l'IA ou les corpus de connaissances du locataire B — + même si la même définition d'agent a été installée depuis le même + package du marketplace. +- Les outils de métadonnées (`create_object`, `add_field`, …) opèrent sur le + **package actif** dans le locataire de l'appelant. Ils ne peuvent pas en sortir. +- Les entrées d'outils sont validées par CEL et le moteur refuse les références aux + packages système réservés (`sys.*`) ou aux noms d'objets d'autres locataires. + +### Événements d'audit + +Lorsque la capacité d'audit est chargée : + +- `ai.chat.message` — chaque message utilisateur / assistant, avec le modèle + le décompte de jetons +- `ai.tool.call` — nom de l'outil, entrée validée, sortie complète (ou erreur) +- `ai.pending_action.queued` — mutation proposée, diff complet +- `ai.pending_action.approved` / `.rejected` — qui a décidé, quand, pourquoi +- `ai.metadata.applied` — écriture effective dans le magasin de métadonnées, avec diff + +Ces lignes sont immuables et peuvent être exportées pour une revue de sécurité ou +une refacturation. Les décomptes de jetons par (fournisseur, modèle, utilisateur) alimentent l'attribution +des coûts. + +### Posture face à l'injection de prompt + +L'injection de prompt indirecte (par ex. un contenu malveillant dans un document que +l'agent récupère) est un risque réel ; ObjectOS réduit le rayon d'impact par +conception : + +- L'IA **ne peut pas contourner la validation des outils** — même si on la convainc d' + émettre une charge utile malveillante, le schéma Zod rejette les entrées mal formées + avant qu'elles n'atteignent le moteur. +- Les outils mutants sont toujours mis en file d'attente. Un prompt injecté ne peut pas écrire + silencieusement dans la base de données. +- Les appels d'outils héritent des **permissions de l'utilisateur final**, et non des + permissions de compte de service du modèle. Un utilisateur ne peut jamais utiliser l'IA pour faire + quelque chose qu'il ne pourrait pas faire lui-même via Console ou REST. +- Les AI Skills chargées dans les agents sont versionnées et explicites — voir + [Build → IDE Skills](/docs/build/ai-skills) et + [Build → AI Builder](/docs/build/ai-builder). + +### Flux de données vers un fournisseur d'IA externe + +Lorsque vous configurez un fournisseur (OpenAI, Anthropic, …), seuls les +éléments suivants quittent votre réseau : + +- L'historique de conversation dont le modèle a besoin (sous réserve de la configuration `redact` + de votre service d'IA — voir [Configure → AI](/docs/configure/ai)) +- Les définitions d'outils (noms, schémas JSON — aucune donnée d'enregistrement) +- Les sorties d'outils dont le modèle a besoin pour continuer (par ex. un résultat de requête + que l'utilisateur a explicitement demandé) + +Pour les déploiements isolés (air-gapped), pointez le service d'IA vers un point de terminaison local Ollama / +vLLM / TGI et le même flux reste à l'intérieur de votre périmètre. + +## Divulgation des vulnérabilités + +Signalez les problèmes de sécurité de manière privée à +**security@objectstack.ai**. Nous répondons sous 1 jour ouvré. Ne +créez pas d'issues GitHub publiques pour les problèmes de sécurité. + +## Chaîne d'approvisionnement + +- Images préconstruites publiées depuis [github.com/objectstack-ai/objectos](https://github.com/objectstack-ai/objectos) + avec une provenance de build reproductible. +- Tous les packages `@objectstack/*` ont leur source publiée sur GitHub — + Apache-2.0, sans obfuscation. +- Utilisez des tags d'image épinglés par SHA (`sha-`) en production pour éviter la + dérive ; voir [Docker](/docs/deploy/docker). + +## Liste de durcissement suggérée + +- [ ] TLS terminé en périphérie avec un certificat réel. +- [ ] `OS_AUTH_SECRET` fait 32 octets aléatoires ou plus, dans un gestionnaire de secrets. +- [ ] La connexion à la base de données utilise TLS. +- [ ] HSTS activé après validation du TLS. +- [ ] Origines CORS explicites (jamais `*` avec des identifiants). +- [ ] Limitation de débit sur les points de terminaison d'authentification (`10/min/IP` recommandé). +- [ ] La rétention d'audit correspond à la politique. +- [ ] OIDC pour les comptes humains ; clés API pour les comptes machines. +- [ ] Exercice de sauvegarde + restauration exécuté et chronométré. +- [ ] Tests négatifs : accès inter-organisations refusé, sécurité des champs tenue, session expirée rejetée. +- [ ] Image épinglée à un tag `sha-` ou semver. +- [ ] `os doctor` propre en CI avant chaque release. + +Voir [Production Readiness](/docs/operate/production) pour la liste complète +de mise en production. diff --git a/content/docs/reference/security.ja.mdx b/content/docs/reference/security.ja.mdx new file mode 100644 index 0000000..dc900d9 --- /dev/null +++ b/content/docs/reference/security.ja.mdx @@ -0,0 +1,219 @@ +--- +title: セキュリティとコンプライアンス +description: 何が、どのように保護され、誰が責任を負うのか — セキュリティレビュー向け。 +--- + +# セキュリティとコンプライアンス + +このページは、セキュリティレビュー担当者、IT 管理者、そして「これを導入しても安全か?」に答えなければならないすべての人のためのものです。 + +## ひとことで言う脅威モデル + +ObjectOS は **あなた自身の** ネットワーク内で単一の Node.js プロセスとして動作し、**あなた自身の** データベースと通信し、決して外部へ通信を行いません。侵害が及ぶ影響範囲は、接続先のデータベース上のデータに限られ、それ以上ではありません。 + +## データレジデンシー + +| データ分類 | 保存場所 | ネットワーク外へ出るか? | +|---|---|---| +| 業務レコード | あなたのデータベース | **いいえ** | +| ユーザーアカウント、セッション、OAuth トークン | あなたのデータベース | **いいえ** | +| 監査ログ | あなたのデータベース | **いいえ** | +| 設定、API キー | あなたのデータベース / あなたのシークレットマネージャー | **いいえ** | +| アップロードされたファイル | あなたのディスク、または S3 互換バケット | **いいえ** | +| テレメトリ / 使用状況データ | — | **収集しない** | + +ObjectOS は、明示的に構成しない限り **外部への通信を一切行いません**(OIDC ディスカバリ、メールプロバイダー、AI プロバイダー、Webhook ターゲット、外部ストレージ)。外部へのフォンホームも、ライセンスサーバーの確認も、アップデートの確認も行いません。 + +## 暗号化 + +| レイヤー | メカニズム | 責任者 | +|---|---|---| +| 転送中(ブラウザ ↔ ObjectOS) | TLS、あなたのエッジ / イングレスで終端 | あなた | +| 転送中(ObjectOS ↔ データベース) | ドライバーレベルの TLS(Postgres `sslmode=require`、MongoDB `tls=true`、…) | あなた — 接続文字列を設定 | +| 保存時(業務データ) | データベースネイティブ(例: Postgres TDE、RDS 暗号化) | あなた | +| 保存時(アップロードされたファイル) | ストレージネイティブ(S3 SSE、R2 デフォルト、ディスクレベルの FDE) | あなた | +| DB 内のシークレット(設定、OIDC クライアントシークレット) | 設定サービスによって暗号化 | ObjectOS | +| セッションクッキー / トークン | `OS_AUTH_SECRET` による HMAC 署名 | ObjectOS | +| API キーの値 | DB 内で **ハッシュ化** — DB の行が漏洩してもキーは復元できない | ObjectOS | + +## 認証 + +組み込み機能(`@objectstack/plugin-auth` 経由、Better Auth による): + +- 検証 + リセット付きのメール / パスワード認証 +- 失効機能を備えたセッション管理 +- ソーシャル OAuth(Google、GitHub、Microsoft、Apple、…) +- エンタープライズ OIDC/SSO(Okta、Entra ID、Keycloak、Ping) +- 二要素認証(TOTP) +- パスキー / WebAuthn +- マジックリンク +- CLI / ブラウザのデバイスフロー +- API キー(ハッシュ化、有効期限設定可、失効可、ユーザーに紐付け) + +[認証](/docs/configure/authentication) を参照してください。 + +## 認可 + +階層的な強制(`@objectstack/plugin-security` 経由): + +1. **オブジェクト権限** — パーミッションセットごと、オブジェクトごとの CRUD +2. **行レベルセキュリティ** — クエリに注入される宣言的なポリシー式。省略不可 +3. **フィールドレベルセキュリティ** — レスポンスから除去 / 書き込み時に拒否されるフィールド +4. **組織スコープ** — マルチテナント分離。バイパスには明示的な `viewAllRecords` が必要 + +システムコンテキストの操作はチェックをバイパスするため、内部ジョブ / マイグレーションを実行できます。これらの経路は監査可能です。 + +[権限](/docs/configure/permissions) を参照してください。 + +## 監査とエビデンス + +監査機能がロードされている場合(`@objectstack/plugin-audit`): + +- すべてのオブジェクトにわたるすべての CRUD 操作 → 監査行。 +- フィールド変更の前後の値。 +- 認証、権限付与、セッション失効イベント。 +- 監査行は **イミュータブル** です。変更はできず、アーカイブのみ可能です。 +- 保持期間は構成可能です。DB のアーカイブポリシーと組み合わせてください。 + +これは SOC 2 CC6/CC7、ISO 27001 A.12.4、HIPAA §164.312(b)、GDPR 第 30 条のエビデンス基盤となります。 + +## コンプライアンスフレームワーク + +ObjectOS は、一般的なフレームワークが求める **技術的なプリミティブ** を提供します。認証はデプロイメントの属性であってソフトウェアの属性ではありませんが、コントロールはきれいにマッピングできます。 + +| フレームワーク | ObjectOS が提供するもの | +|---|---| +| **SOC 2** | アクセス制御(CC6)、変更管理(監査ログ)、暗号化(デプロイメント)、モニタリング(可観測性)、バックアップ(operate/backup) | +| **ISO 27001** | A.5 ポリシー(RBAC)、A.8 資産管理(オブジェクトカタログ)、A.9 アクセス制御、A.12 運用、A.18 コンプライアンス | +| **HIPAA** | アクセス制御(§164.312(a))、監査制御(§164.312(b))、完全性(イミュータブルな監査)、伝送セキュリティ(TLS) | +| **GDPR** | 第 30 条 処理活動の記録(監査)、第 32 条 処理のセキュリティ、第 17 条 消去権(ソフト削除 + ハード削除に対応)、データレジデンシー(リージョンを自分で選択) | +| **CCPA / 中国 DSL / ロシア 152-FZ** | 適切なリージョンでのセルフホスティングがレジデンシーを満たす。アクセス制御 + 監査がほとんどの報告義務をカバー | + +ObjectOS そのものは **認証を取得していません**。認証は実行中のデプロイメントに対するものであって、バイナリに対するものではないためです。あなたのデプロイメントは認証を取得でき、すでに多くが取得しています。 + +## シークレットの取り扱い + +| シークレット | 配置場所 | +|---|---| +| `OS_AUTH_SECRET` | あなたのシークレットマネージャー(Vault、AWS Secrets Manager、k8s Secret)。環境変数として注入 | +| 認証情報を含むデータベース URL | 同上 | +| OIDC クライアントシークレット | 同上 | +| OAuth プロバイダーシークレット | 同上 | +| API プロバイダーキー(メール、ストレージ、AI) | 同上 | +| DB に保存される設定 | 設定サービスによって保存時に暗号化 | + +シークレットをアーティファクト(`objectstack.json`)、Docker イメージ、compose ファイル、Git に **決して** 焼き込まないでください。Console の設定 UI は環境変数で管理される値をロックして表示するため、オペレーターが誤って上書きすることはありません。 + +## ネットワークモデル + +必須のインバウンド: +- あなたのイングレス / ロードバランサーから ObjectOS への HTTPS、ポート `:3000`(デフォルト)。 + +必須のアウトバウンド(これらの機能を構成する場合のみ): +- あなたのデータベース(Postgres / Mongo / Turso / …)。 +- S3 互換ストレージ(S3 アダプターで `storage` 機能を有効にした場合)。 +- OIDC ディスカバリ URL(SSO を有効にした場合)。 +- メールプロバイダー API(Resend / Postmark)。 +- AI プロバイダー API(OpenAI / Anthropic / Google / …)。 +- Webhook ターゲット。 + +これがエグレスサーフェスのすべてです。さらに削減するデプロイメントについては [エアギャップ](/docs/deploy/air-gapped) を参照してください。 + +## AI: ツール、承認、分離 + +AI Builder は、あなたが公開する最もセキュリティに敏感なサーフェスであるため、上記すべてに加えて独自の強制レイヤーを備えています。 + +### AI が状態を変更する仕組み + +モデルはあなたのデータベースに **直接書き込むことはできません**。状態が変化する唯一の方法は、AI サービスが受信、検証、キューイングする構造化されたツールコールを発行することです。その連鎖は次のとおりです。 + +```text +user prompt + → model emits tool call (e.g. add_field { object: 'ticket', name: 'severity', type: 'select' }) + → AI service validates payload against the tool's Zod schema + → if the tool is "mutating": queue as pending action (no state change yet) + → human reviewer approves → mutation applied → audit row written + → if the tool is "read-only": run immediately, response returned to model +``` + +11 個のファーストパーティのメタデータツール([Build → AI Builder を参照](/docs/build/ai-builder))に加え、宣言された各アクションごとに 1 つの `action_` ツールがあります。すべてのツール — ファーストパーティであれカスタムであれ — は同じライフサイクルを持ちます。 + +### パーミッションキー + +| キー | 付与する権限 | +|:--|:--| +| `ai:chat` | 会話を保持する。モデルを消費する。エージェントに読み取り専用ツールを呼び出させる | +| `ai:complete` | 生の補完エンドポイント(エージェントループなし) | +| `ai:conversations` | 会話の一覧 / 検査 / 削除(RBAC スコープに応じて自分のものまたはすべて) | +| `ai:agents` | エージェントメタデータの管理(呼び出すには `ai:chat` と併用) | +| `ai:tools` | ツールカタログの一覧表示 | +| `ai:execute` | REST 経由でツールを直接呼び出す(上級者向け — 通常はアンビエントエージェントのみが必要) | +| `ai:read` | 保留中アクションのキューとモデル一覧の読み取り | +| `ai:approve` | キューイングされたミューテーションの承認 / 却下 | +| `ai:admin` | AI サービスの完全な管理 | + +重要な区別は **`ai:chat` ≠ `ai:approve`** です。アシスタントが機能するように、ほとんどのユーザーには `ai:chat` を付与してください。`ai:approve` は、構造的な変更をレビューすべき管理者 / アプリ所有者のために確保してください。これにより、エンドユーザーは安全に「バイブビルド」できます。最悪の場合でも、他の誰かが受け入れなければならない不適切な変更をキューに入れるだけです。 + +### テナント分離 + +- エージェント、会話、ナレッジベース、保留中アクションは、1 つの **Environment**(テナント)にスコープされます。同じ marketplace パッケージから同じエージェント定義がインストールされていたとしても、テナント A はテナント B の会話、AI が提案したツール、ナレッジコーパスを見ることはできません。 +- メタデータツール(`create_object`、`add_field`、…)は、呼び出し元のテナント内の **アクティブパッケージ** に対して動作します。その外には到達できません。 +- ツール入力は CEL で検証され、エンジンは予約済みのシステムパッケージ(`sys.*`)や他テナントのオブジェクト名への参照を拒否します。 + +### 監査イベント + +監査機能がロードされている場合: + +- `ai.chat.message` — すべてのユーザー / アシスタントメッセージ、モデル + トークン数付き +- `ai.tool.call` — ツール名、検証済み入力、完全な出力(またはエラー) +- `ai.pending_action.queued` — 提案されたミューテーション、完全な差分 +- `ai.pending_action.approved` / `.rejected` — 誰が、いつ、なぜ決定したか +- `ai.metadata.applied` — メタデータストアへの実際の書き込み、差分付き + +これらの行はイミュータブルであり、セキュリティレビューやチャージバックのためにエクスポートできます。(プロバイダー、モデル、ユーザー)ごとのトークン数はコスト配賦に利用されます。 + +### プロンプトインジェクションへの姿勢 + +間接プロンプトインジェクション(例: エージェントが取得するドキュメント内の悪意あるコンテンツ)は現実的なリスクです。ObjectOS は構造上、影響範囲を低減します。 + +- AI は **ツール検証をバイパスできません**。悪意あるペイロードを発行するよう仕向けられたとしても、Zod スキーマが不正な入力をエンジンに到達する前に拒否します。 +- ミューテーションを行うツールは常にキューイングされます。注入されたプロンプトが密かにデータベースへ書き込むことはできません。 +- ツールコールは、モデルのサービスアカウントの権限ではなく、**エンドユーザーの権限** を継承します。ユーザーは、Console や REST で自分ができないことを AI を使って行うことは決してできません。 +- エージェントにロードされる Skills はバージョン管理され、明示的です。[Build → IDE Skills](/docs/build/ai-skills) および [Build → AI Builder](/docs/build/ai-builder) を参照してください。 + +### 外部 AI プロバイダーのデータフロー + +プロバイダー(OpenAI、Anthropic、…)を構成した場合、ネットワークから出るのは次のものだけです。 + +- モデルが必要とする会話履歴(AI サービスの `redact` 設定に従う — [Configure → AI](/docs/configure/ai) を参照) +- ツール定義(名前、JSON スキーマ — レコードデータは含まない) +- モデルが続行するために必要なツール出力(例: ユーザーが明示的に要求したクエリ結果) + +エアギャップデプロイメントの場合、AI サービスをローカルの Ollama / vLLM / TGI エンドポイントに向ければ、同じフローがあなたの境界内に留まります。 + +## 脆弱性の開示 + +セキュリティ問題は **security@objectstack.ai** へ非公開で報告してください。営業日 1 日以内に対応します。セキュリティ上の問題について、公開された GitHub issue を作成しないでください。 + +## サプライチェーン + +- 事前ビルドされたイメージは [github.com/objectstack-ai/objectos](https://github.com/objectstack-ai/objectos) から、再現可能なビルドプロビナンス付きで公開されています。 +- すべての `@objectstack/*` パッケージは GitHub 上でソースが公開されています — Apache-2.0、難読化なし。 +- 本番環境では SHA 固定のイメージタグ(`sha-`)を使用してドリフトを回避してください。[Docker](/docs/deploy/docker) を参照してください。 + +## 推奨ハードニングチェックリスト + +- [ ] エッジで TLS を本物の証明書で終端している。 +- [ ] `OS_AUTH_SECRET` は 32 バイト以上のランダム値で、シークレットマネージャーに保管されている。 +- [ ] データベース接続が TLS を使用している。 +- [ ] TLS 検証後に HSTS を有効化している。 +- [ ] CORS オリジンが明示的である(認証情報付きで `*` を使用していない)。 +- [ ] 認証エンドポイントにレート制限がかかっている(`10/min/IP` を推奨)。 +- [ ] 監査の保持期間がポリシーに合致している。 +- [ ] 人間のアカウントには OIDC、マシンアカウントには API キーを使用している。 +- [ ] バックアップ + リストアの訓練を実施し、所要時間を計測している。 +- [ ] ネガティブテスト: クロス組織アクセスが拒否される、フィールドセキュリティが維持される、期限切れセッションが拒否される。 +- [ ] イメージが `sha-` または semver タグに固定されている。 +- [ ] 各リリース前に CI で `os doctor` がクリーンである。 + +本番稼働の完全なチェックリストについては [本番準備](/docs/operate/production) を参照してください。 diff --git a/content/docs/reference/security.cn.mdx b/content/docs/reference/security.zh-Hans.mdx similarity index 100% rename from content/docs/reference/security.cn.mdx rename to content/docs/reference/security.zh-Hans.mdx diff --git a/content/docs/reference/skills-cli.de.mdx b/content/docs/reference/skills-cli.de.mdx new file mode 100644 index 0000000..08a0b64 --- /dev/null +++ b/content/docs/reference/skills-cli.de.mdx @@ -0,0 +1,102 @@ +--- +title: skills CLI +description: Der npx-Befehl, der ObjectOS-Skill-Bundles in deinen Coding-Agenten installiert. +--- + +# `skills` CLI + +Das [`skills`](https://www.npmjs.com/package/skills) CLI (von +[vercel-labs/skills](https://github.com/vercel-labs/skills)) ist die +Standardmethode, um domänenspezifische Anweisungen an KI-Coding-Agenten +zu verteilen. ObjectOS veröffentlicht darüber 9 offizielle Skills. + +Diese Seite ist eine Referenzkarte. Eine konzeptionelle Übersicht +findest du unter [Build → IDE Skills](/docs/build/ai-skills). + +## Installation + +```bash +npx skills add objectstack-ai/framework +``` + +Beim ersten Ausführen wird das +[`skills`](https://www.npmjs.com/package/skills)-Paket über `npx` von npm +heruntergeladen, anschließend wird das Skill-Bundle von +[github.com/objectstack-ai/framework](https://github.com/objectstack-ai/framework) +(`skills//`-Ordner) abgerufen und in die Agenten-Konfiguration +deines Projekts geschrieben. + +Führe den Befehl jederzeit erneut aus, um die neuesten Versionen zu holen. + +## Was geschrieben wird + +Automatisch erkannt anhand dessen, was sich in deinem Projekt befindet: + +| Agent | Geschriebener Pfad | +|:--|:--| +| Claude Code | `.claude/skills//SKILL.md` | +| Cursor | `.cursor/rules/.mdc` | +| GitHub Copilot | `.github/copilot-instructions.md` (konsolidiert) | +| Codex / Codex CLI | `AGENTS.md` (konsolidiert) | +| Gemini CLI | `.gemini/skills//` | +| Windsurf, Cline, Continue, Roo, Goose, Kiro, opencode, … | ihr natives Skill-/Rules-Format | + +Führe `npx skills detect` aus, um zu sehen, was das CLI schreiben wird. + +## Was ObjectOS veröffentlicht + +| Skill | Laden für | +|:--|:--| +| `objectstack-platform` | `defineStack`, Driver, Adapter, Plugins, Services, `os` CLI, Deployment | +| `objectstack-data` | `*.object.ts`, `*.seed.ts`, Felder, Beziehungen, Validierungen, Indizes, RLS, Lifecycle-Hooks | +| `objectstack-query` | [ObjectQL](./objectql) — Filter, Sortierung, Pagination, Aggregation, Joins, Volltext | +| `objectstack-ui` | [Views](/docs/build/views), Apps, Pages, Dashboards, Reports, Charts, Actions | +| `objectstack-automation` | Flows, Workflows, Trigger, Genehmigungen, Zeitpläne, Webhooks | +| `objectstack-ai` | Agents, Tools, Skills, Conversations, Model Registry, MCP | +| `objectstack-api` | REST/GraphQL-Endpunkte, Authentifizierung, Realtime, Fehler-Envelopes | +| `objectstack-i18n` | Übersetzungs-Bundles, Locale-Fallback | +| `objectstack-formula` | [CEL](./cel)-Ausdrücke — Formelfelder, Prädikate, Bedingungen, Zeitpläne | + +Das Frontmatter der jeweiligen `SKILL.md` deklariert, wann der Agent sie +laden soll und wann an einen verwandten Skill abgegeben werden soll. + +## Häufige Befehle + +```bash +npx skills add / # add a skill bundle from a GitHub repo +npx skills add /@ # pin to a tag / branch / SHA +npx skills list # list installed skills +npx skills remove # remove a skill +npx skills detect # show which agents the CLI will write to +npx skills --help # full options +``` + +Pinne eine Version für reproduzierbare CI: + +```bash +npx skills add objectstack-ai/framework@v5.0.0 +``` + +## Wo die Ausgabe committet werden sollte + +**Committe sie.** Skills sind Markdown, das dein gesamtes Team — +einschließlich CI-Agenten — teilen sollte. Das CLI schreibt in +standardmäßige Agenten-Pfade (`.claude/`, `.cursor/`, `AGENTS.md`, …), +die du ohnehin normalerweise einchecken würdest. + +## Aktualisieren + +```bash +npx skills add objectstack-ai/framework # pulls latest matching the spec version range +``` + +Führe den Befehl nach dem Upgrade von `@objectstack/spec` erneut aus, +damit der Agent mit den neuesten Zod-Schemas, CEL-Helfern und dem +Metadaten-Vokabular synchron bleibt. + +## Siehe auch + +- [Build → IDE Skills](/docs/build/ai-skills) — konzeptionelle Übersicht, AI Builder vs. Skills +- [Build → AI Builder](/docs/build/ai-builder) — das Gegenstück in der Console +- [vercel-labs/skills](https://github.com/vercel-labs/skills) — Upstream-CLI +- [objectstack-ai/framework/skills](https://github.com/objectstack-ai/framework/tree/main/skills) — Source of Truth für jeden Skill diff --git a/content/docs/reference/skills-cli.es.mdx b/content/docs/reference/skills-cli.es.mdx new file mode 100644 index 0000000..6e30db9 --- /dev/null +++ b/content/docs/reference/skills-cli.es.mdx @@ -0,0 +1,102 @@ +--- +title: CLI de skills +description: El comando npx que instala paquetes de skills de ObjectOS en tu agente de programación. +--- + +# CLI de `skills` + +La CLI de [`skills`](https://www.npmjs.com/package/skills) (de +[vercel-labs/skills](https://github.com/vercel-labs/skills)) es la +forma estándar de distribuir instrucciones acotadas a un dominio para +agentes de programación con IA. ObjectOS publica 9 skills oficiales a +través de ella. + +Esta página es una tarjeta de referencia. Para la visión conceptual, +consulta [Build → IDE Skills](/docs/build/ai-skills). + +## Instalación + +```bash +npx skills add objectstack-ai/framework +``` + +La primera ejecución descarga el paquete [`skills`](https://www.npmjs.com/package/skills) +desde npm mediante `npx`, luego obtiene el paquete de skills desde +[github.com/objectstack-ai/framework](https://github.com/objectstack-ai/framework) +(carpetas `skills//`) y los escribe en la configuración del +agente de tu proyecto. + +Vuelve a ejecutarlo en cualquier momento para obtener las últimas versiones. + +## Qué se escribe + +Se detecta automáticamente según lo que haya en tu proyecto: + +| Agente | Ruta escrita | +|:--|:--| +| Claude Code | `.claude/skills//SKILL.md` | +| Cursor | `.cursor/rules/.mdc` | +| GitHub Copilot | `.github/copilot-instructions.md` (consolidado) | +| Codex / Codex CLI | `AGENTS.md` (consolidado) | +| Gemini CLI | `.gemini/skills//` | +| Windsurf, Cline, Continue, Roo, Goose, Kiro, opencode, … | su formato nativo de skill / reglas | + +Ejecuta `npx skills detect` para ver qué planea escribir la CLI. + +## Qué publica ObjectOS + +| Skill | Cárgalo para | +|:--|:--| +| `objectstack-platform` | `defineStack`, drivers, adaptadores, plugins, servicios, CLI de `os`, despliegue | +| `objectstack-data` | `*.object.ts`, `*.seed.ts`, campos, relaciones, validaciones, índices, RLS, hooks de ciclo de vida | +| `objectstack-query` | [ObjectQL](./objectql) — filtros, ordenación, paginación, agregación, joins, texto completo | +| `objectstack-ui` | [Views](/docs/build/views), Apps, Pages, Dashboards, Reports, Charts, Actions | +| `objectstack-automation` | Flows, Workflows, Triggers, Approvals, programaciones, webhooks | +| `objectstack-ai` | Agents, Tools, Skills, Conversations, Model Registry, MCP | +| `objectstack-api` | endpoints REST/GraphQL, autenticación, tiempo real, envoltorios de errores | +| `objectstack-i18n` | Paquetes de traducción, alternativa de configuración regional | +| `objectstack-formula` | expresiones [CEL](./cel) — campos de fórmula, predicados, condiciones, programaciones | + +El frontmatter de `SKILL.md` de cada skill declara cuándo debe el +agente cargarlo y cuándo delegar en uno hermano. + +## Comandos comunes + +```bash +npx skills add / # add a skill bundle from a GitHub repo +npx skills add /@ # pin to a tag / branch / SHA +npx skills list # list installed skills +npx skills remove # remove a skill +npx skills detect # show which agents the CLI will write to +npx skills --help # full options +``` + +Fija una versión para una CI reproducible: + +```bash +npx skills add objectstack-ai/framework@v5.0.0 +``` + +## Dónde confirmar la salida + +**Confírmala.** Las skills son markdown que todo tu equipo —incluidos +los agentes de CI— debería compartir. La CLI escribe en rutas estándar +de agentes (`.claude/`, `.cursor/`, `AGENTS.md`, …) que normalmente +incluirías en el control de versiones de todos modos. + +## Actualización + +```bash +npx skills add objectstack-ai/framework # pulls latest matching the spec version range +``` + +Vuelve a ejecutarlo después de actualizar `@objectstack/spec` para que +el agente se mantenga sincronizado con los últimos esquemas de Zod, +helpers de CEL y vocabulario de metadatos. + +## Véase también + +- [Build → IDE Skills](/docs/build/ai-skills) — visión conceptual, AI Builder frente a skills +- [Build → AI Builder](/docs/build/ai-builder) — la contraparte dentro de Console +- [vercel-labs/skills](https://github.com/vercel-labs/skills) — CLI original +- [objectstack-ai/framework/skills](https://github.com/objectstack-ai/framework/tree/main/skills) — fuente de verdad para cada skill diff --git a/content/docs/reference/skills-cli.fr.mdx b/content/docs/reference/skills-cli.fr.mdx new file mode 100644 index 0000000..855c6cd --- /dev/null +++ b/content/docs/reference/skills-cli.fr.mdx @@ -0,0 +1,103 @@ +--- +title: CLI skills +description: La commande npx qui installe les bundles de skills ObjectOS dans votre agent de codage. +--- + +# CLI `skills` + +La CLI [`skills`](https://www.npmjs.com/package/skills) (par +[vercel-labs/skills](https://github.com/vercel-labs/skills)) est la +manière standard de distribuer des instructions à portée métier aux +agents de codage IA. ObjectOS publie 9 skills officiels par son +intermédiaire. + +Cette page est une fiche de référence. Pour une vue d'ensemble +conceptuelle, voir [Build → IDE Skills](/docs/build/ai-skills). + +## Installation + +```bash +npx skills add objectstack-ai/framework +``` + +Lors de la première exécution, le paquet +[`skills`](https://www.npmjs.com/package/skills) est téléchargé depuis +npm via `npx`, puis le bundle de skills est récupéré depuis +[github.com/objectstack-ai/framework](https://github.com/objectstack-ai/framework) +(dossiers `skills//`) et écrit dans la configuration de l'agent de +votre projet. + +Réexécutez à tout moment pour récupérer les dernières versions. + +## Ce qui est écrit + +Détecté automatiquement en fonction du contenu de votre projet : + +| Agent | Chemin écrit | +|:--|:--| +| Claude Code | `.claude/skills//SKILL.md` | +| Cursor | `.cursor/rules/.mdc` | +| GitHub Copilot | `.github/copilot-instructions.md` (consolidé) | +| Codex / Codex CLI | `AGENTS.md` (consolidé) | +| Gemini CLI | `.gemini/skills//` | +| Windsurf, Cline, Continue, Roo, Goose, Kiro, opencode, … | leur format natif de skill / rules | + +Exécutez `npx skills detect` pour voir ce que la CLI prévoit d'écrire. + +## Ce qu'ObjectOS publie + +| Skill | À charger pour | +|:--|:--| +| `objectstack-platform` | `defineStack`, drivers, adaptateurs, plugins, services, CLI `os`, déploiement | +| `objectstack-data` | `*.object.ts`, `*.seed.ts`, champs, relations, validations, index, RLS, hooks de cycle de vie | +| `objectstack-query` | [ObjectQL](./objectql) — filtres, tri, pagination, agrégation, jointures, recherche plein texte | +| `objectstack-ui` | [Views](/docs/build/views), Apps, Pages, Dashboards, Reports, Charts, Actions | +| `objectstack-automation` | Flows, Workflows, Triggers, Approvals, planifications, webhooks | +| `objectstack-ai` | Agents, Tools, Skills, Conversations, Model Registry, MCP | +| `objectstack-api` | endpoints REST/GraphQL, authentification, temps réel, enveloppes d'erreur | +| `objectstack-i18n` | bundles de traduction, repli de locale | +| `objectstack-formula` | expressions [CEL](./cel) — champs formule, prédicats, conditions, planifications | + +La frontmatter du `SKILL.md` de chaque skill déclare quand l'agent doit +le charger et quand déférer à un skill voisin. + +## Commandes courantes + +```bash +npx skills add / # add a skill bundle from a GitHub repo +npx skills add /@ # pin to a tag / branch / SHA +npx skills list # list installed skills +npx skills remove # remove a skill +npx skills detect # show which agents the CLI will write to +npx skills --help # full options +``` + +Épinglez une version pour une CI reproductible : + +```bash +npx skills add objectstack-ai/framework@v5.0.0 +``` + +## Où committer la sortie + +**Committez-la.** Les skills sont du markdown que toute votre équipe — y +compris les agents de CI — devrait partager. La CLI écrit dans les +chemins d'agents standard (`.claude/`, `.cursor/`, `AGENTS.md`, …) que +vous versionneriez normalement de toute façon. + +## Mise à jour + +```bash +npx skills add objectstack-ai/framework # pulls latest matching the spec version range +``` + +Réexécutez après avoir mis à niveau `@objectstack/spec` afin que l'agent +reste synchronisé avec les derniers schémas Zod, helpers CEL et +vocabulaire de métadonnées. + +## Voir aussi + +- [Build → IDE Skills](/docs/build/ai-skills) — vue d'ensemble conceptuelle, AI Builder vs skills +- [Build → AI Builder](/docs/build/ai-builder) — l'équivalent dans la Console +- [vercel-labs/skills](https://github.com/vercel-labs/skills) — CLI en amont +- [objectstack-ai/framework/skills](https://github.com/objectstack-ai/framework/tree/main/skills) — source de vérité pour chaque skill diff --git a/content/docs/reference/skills-cli.ja.mdx b/content/docs/reference/skills-cli.ja.mdx new file mode 100644 index 0000000..762507e --- /dev/null +++ b/content/docs/reference/skills-cli.ja.mdx @@ -0,0 +1,99 @@ +--- +title: skills CLI +description: ObjectOS のスキルバンドルをコーディングエージェントにインストールする npx コマンド。 +--- + +# `skills` CLI + +[`skills`](https://www.npmjs.com/package/skills) CLI +([vercel-labs/skills](https://github.com/vercel-labs/skills) 製)は、 +ドメインに特化した指示を AI コーディングエージェントに配布するための +標準的な手段です。ObjectOS はこれを通じて 9 つの公式スキルを公開しています。 + +このページはリファレンスカードです。概念的な概要については +[Build → IDE Skills](/docs/build/ai-skills) を参照してください。 + +## インストール + +```bash +npx skills add objectstack-ai/framework +``` + +初回実行時には、`npx` 経由で npm から +[`skills`](https://www.npmjs.com/package/skills) パッケージをダウンロードし、 +続いて [github.com/objectstack-ai/framework](https://github.com/objectstack-ai/framework) +(`skills//` フォルダ)からスキルバンドルを取得して、プロジェクトの +エージェント設定に書き込みます。 + +最新バージョンを取得するには、いつでも再実行できます。 + +## 書き込まれる内容 + +プロジェクトの内容に基づいて自動的に検出されます。 + +| エージェント | 書き込まれるパス | +|:--|:--| +| Claude Code | `.claude/skills//SKILL.md` | +| Cursor | `.cursor/rules/.mdc` | +| GitHub Copilot | `.github/copilot-instructions.md`(統合) | +| Codex / Codex CLI | `AGENTS.md`(統合) | +| Gemini CLI | `.gemini/skills//` | +| Windsurf, Cline, Continue, Roo, Goose, Kiro, opencode, … | それぞれのネイティブなスキル/ルール形式 | + +CLI が書き込もうとする内容を確認するには `npx skills detect` を実行します。 + +## ObjectOS が公開している内容 + +| スキル | 読み込む対象 | +|:--|:--| +| `objectstack-platform` | `defineStack`、ドライバ、アダプタ、プラグイン、サービス、`os` CLI、デプロイ | +| `objectstack-data` | `*.object.ts`、`*.seed.ts`、フィールド、リレーションシップ、バリデーション、インデックス、RLS、ライフサイクルフック | +| `objectstack-query` | [ObjectQL](./objectql) — フィルタ、ソート、ページネーション、集計、結合、全文検索 | +| `objectstack-ui` | [Views](/docs/build/views)、Apps、Pages、Dashboards、Reports、Charts、Actions | +| `objectstack-automation` | Flows、Workflows、Triggers、Approvals、スケジュール、Webhook | +| `objectstack-ai` | Agents、Tools、Skills、Conversations、Model Registry、MCP | +| `objectstack-api` | REST/GraphQL エンドポイント、認証、リアルタイム、エラーエンベロープ | +| `objectstack-i18n` | 翻訳バンドル、ロケールフォールバック | +| `objectstack-formula` | [CEL](./cel) 式 — 数式フィールド、述語、条件、スケジュール | + +各スキルの `SKILL.md` のフロントマターには、エージェントがそのスキルを +いつ読み込むべきか、いつ兄弟スキルに委ねるべきかが宣言されています。 + +## よく使うコマンド + +```bash +npx skills add / # add a skill bundle from a GitHub repo +npx skills add /@ # pin to a tag / branch / SHA +npx skills list # list installed skills +npx skills remove # remove a skill +npx skills detect # show which agents the CLI will write to +npx skills --help # full options +``` + +再現可能な CI のためにバージョンを固定する場合: + +```bash +npx skills add objectstack-ai/framework@v5.0.0 +``` + +## 出力をどこにコミットするか + +**コミットしてください。** スキルは、CI エージェントを含むチーム全体で +共有すべき Markdown です。CLI は、通常チェックインするであろう標準的な +エージェントパス(`.claude/`、`.cursor/`、`AGENTS.md`、…)に書き込みます。 + +## 更新 + +```bash +npx skills add objectstack-ai/framework # pulls latest matching the spec version range +``` + +`@objectstack/spec` をアップグレードした後に再実行すると、エージェントが +最新の Zod スキーマ、CEL ヘルパー、メタデータ語彙と同期した状態を保てます。 + +## 関連項目 + +- [Build → IDE Skills](/docs/build/ai-skills) — 概念的な概要、AI Builder とスキルの比較 +- [Build → AI Builder](/docs/build/ai-builder) — Console 内の対応機能 +- [vercel-labs/skills](https://github.com/vercel-labs/skills) — 上流の CLI +- [objectstack-ai/framework/skills](https://github.com/objectstack-ai/framework/tree/main/skills) — すべてのスキルのソースオブトゥルース diff --git a/content/docs/reference/skills-cli.cn.mdx b/content/docs/reference/skills-cli.zh-Hans.mdx similarity index 100% rename from content/docs/reference/skills-cli.cn.mdx rename to content/docs/reference/skills-cli.zh-Hans.mdx diff --git a/content/docs/resources/changelog.de.mdx b/content/docs/resources/changelog.de.mdx new file mode 100644 index 0000000..c73daf3 --- /dev/null +++ b/content/docs/resources/changelog.de.mdx @@ -0,0 +1,99 @@ +--- +title: Changelog & Versionierung +description: Wie ObjectOS versioniert wird, was sich zwischen Releases ändert und was unterstützt wird. +--- + +# Changelog & Versionierung + +## Versionierungsrichtlinie + +ObjectOS folgt **[Semantic Versioning](https://semver.org/)**: `MAJOR.MINOR.PATCH`. + +| Versionssprung | Was es bedeutet | Was zu tun ist | +|---|---|---| +| **Patch** (`4.0.1 → 4.0.2`) | Fehlerbehebungen, keine Verhaltensänderung | Aktualisieren, keine App-Änderungen nötig | +| **Minor** (`4.0 → 4.1`) | Neue Funktionen, abwärtskompatibel | Aktualisieren, optional neue Funktionen übernehmen | +| **Major** (`4 → 5`) | Breaking Changes, in den Release Notes dokumentiert | Lesen Sie den Migrationsleitfaden vor dem Upgrade | + +Alle `@objectstack/*`-Pakete werden gemeinsam mit einer synchronisierten +Versionsnummer veröffentlicht — sie werden als Matrix getestet, nicht einzeln. + +## Kompatibilitätsmatrix + +| Komponente | Kompatibilitätsregel | +|---|---| +| ObjectOS-Image ↔ kompiliertes Artefakt | Gleiche Minor-Version. Ein 4.0.x-Image führt ein 4.0.x-Artefakt aus; ein 4.1-Artefakt kann Funktionen nutzen, die in einem 4.0-Image nicht verfügbar sind. | +| ObjectOS ↔ CLI | Gleiche Minor-Version empfohlen. Die per `npm i -g` installierte CLI erzeugt Scaffolds, die auf ihre eigene Version gepinnt sind. | +| ObjectOS ↔ Datenbanktreiber | Treiber durch den Image-Build gepinnt; prüfen Sie Postgres ≥ 13 / MongoDB ≥ 5 / Turso (jede aktuelle Version). | +| Node.js | **20 LTS oder neuer**. 22 LTS empfohlen für neue Deployments. | + +## Support-Zeiträume + +| Branch | Status | Bis | +|---|---|---| +| **4.x** (aktuell) | Aktive Entwicklung; neue Funktionen und Fixes | Mindestens 12 Monate nach dem Erscheinen von 5.0 | +| **3.x** | Nur Sicherheitsfixes | EOL mit dem Release von 5.0 | +| **≤ 2.x** | Nicht unterstützt | Bereits EOL | + +Kritische Sicherheitsfixes werden auf den aktuellen und den vorherigen +Major-Branch zurückportiert. Alles andere landet auf `main`. + +## Release Notes + +Veröffentlichte ObjectOS-Versionen und ihre CHANGELOG-Einträge werden hier publiziert: + +- **npm**: [`@objectstack/runtime`](https://www.npmjs.com/package/@objectstack/runtime) +- **GitHub**: [github.com/objectstack-ai/objectos/releases](https://github.com/objectstack-ai/objectos/releases) +- **Quell-CHANGELOG**: [`CHANGELOG.md`](https://github.com/objectstack-ai/framework/blob/main/CHANGELOG.md) +- **Ausführliche Release Notes**: [`RELEASE_NOTES.md`](https://github.com/objectstack-ai/framework/blob/main/RELEASE_NOTES.md) + +Abonnieren Sie Releases auf GitHub, um benachrichtigt zu werden. + +## Aktuelle Highlights + +### 4.0.x — aktueller Release-Zug + +- **42 Pakete** auf npm unter `@objectstack/*` veröffentlicht. +- Console erhielt vollständige Konfigurationsseiten für Einstellungen (AI, Storage, + Knowledge). +- Embedder-Dienst: 10 Anbieter (`openai`, `azure`, 阿里通义, + 智谱, 硅基流动, 火山, MiniMax, Ollama, benutzerdefiniert). +- Live-Einstellungen → Runtime-Bridge — wechseln Sie den Anbieter in Console, mit + In-Process-Austausch ohne Neustart. + +### 5.0 (kommend) — Umbenennung `project` → `environment` + +Das Runtime-Konzept, das früher *Project* hieß, wird durchgängig in *Environment* +umbenannt. Betroffen sind: + +- CLI-Flags: `--environment` / `-e` +- HTTP-Pfade: `/api/v1/environments/:environmentId/...` +- Header: `X-Environment-Id` +- Umgebungsvariablen: `OS_ENVIRONMENT_ID` (`OS_PROJECT_ID` bleibt als Alias in 4.x erhalten, entfernt in 5.0) +- DB-Spalten: `environment_id` +- JSON-Schemas: `EnvironmentArtifact` + +Keine Aliase oder Deprecation-Shims. Planen Sie das Upgrade sorgfältig — siehe den +5.0-Migrationsleitfaden zum Release. + +## Upgrade + +Siehe [Upgrade und Rollback](/docs/operate/upgrade) für die konkreten +Schritte. Vorab-Prüfung: + +1. Lesen Sie den CHANGELOG-Eintrag für jede Minor-Version zwischen Ihrer + aktuellen und der Zielversion. +2. Führen Sie `os diff ` aus, um Breaking + Schema-Änderungen aufzudecken. +3. Führen Sie `os doctor` gegen die Zielversion aus. +4. Bringen Sie eine Canary-Instanz hoch, bevor Sie die gesamte Flotte ausrollen. +5. Halten Sie einen Rollback-Plan sowohl für das Image-Tag als auch für die + Artefakt-Version bereit (sie werden unabhängig voneinander ausgerollt). + +## Regressionen melden + +Wenn ein Patch oder eine Minor-Version etwas zuvor Funktionierendes bricht, melden Sie +einen Bug unter +[github.com/objectstack-ai/objectos/issues](https://github.com/objectstack-ai/objectos/issues) +mit der Version, von der / auf die Sie aktualisiert haben. Wir behandeln Regressionen als +die höchstpriorisierte Fehlerklasse. diff --git a/content/docs/resources/changelog.es.mdx b/content/docs/resources/changelog.es.mdx new file mode 100644 index 0000000..432c576 --- /dev/null +++ b/content/docs/resources/changelog.es.mdx @@ -0,0 +1,99 @@ +--- +title: Registro de cambios y versionado +description: Cómo se versiona ObjectOS, qué cambia entre versiones y qué tiene soporte. +--- + +# Registro de cambios y versionado + +## Política de versionado + +ObjectOS sigue el **[Versionado semántico](https://semver.org/)**: `MAJOR.MINOR.PATCH`. + +| Incremento de versión | Qué significa | Qué hacer | +|---|---|---| +| **Parche** (`4.0.1 → 4.0.2`) | Corrección de errores, sin cambios de comportamiento | Actualiza, no se requieren cambios en la aplicación | +| **Menor** (`4.0 → 4.1`) | Nuevas funciones, compatible con versiones anteriores | Actualiza y, opcionalmente, adopta las nuevas funciones | +| **Mayor** (`4 → 5`) | Cambios incompatibles documentados en las notas de versión | Lee la guía de migración antes de actualizar | + +Todos los paquetes `@objectstack/*` se publican juntos con un número de +versión sincronizado: se prueban como una matriz, no de forma independiente. + +## Matriz de compatibilidad + +| Componente | Regla de compatibilidad | +|---|---| +| Imagen de ObjectOS ↔ artefacto compilado | Misma versión menor. Una imagen 4.0.x ejecuta un artefacto 4.0.x; un artefacto 4.1 puede usar funciones no disponibles en una imagen 4.0. | +| ObjectOS ↔ CLI | Se recomienda la misma versión menor. La CLI en `npm i -g` genera andamiajes fijados a su propia versión. | +| ObjectOS ↔ controlador de base de datos | El controlador queda fijado por la compilación de la imagen; verifica Postgres ≥ 13 / MongoDB ≥ 5 / Turso (cualquiera actual). | +| Node.js | **20 LTS o posterior**. Se recomienda 22 LTS para nuevos despliegues. | + +## Ventanas de soporte + +| Rama | Estado | Hasta | +|---|---|---| +| **4.x** (actual) | Desarrollo activo; nuevas funciones y correcciones | Al menos 12 meses después del lanzamiento de 5.0 | +| **3.x** | Solo correcciones de seguridad | EOL en el lanzamiento de 5.0 | +| **≤ 2.x** | Sin soporte | Ya en EOL | + +Las correcciones de seguridad críticas se retroportan a la versión mayor +actual y a la anterior. Todo lo demás se incorpora en `main`. + +## Notas de versión + +Las versiones publicadas de ObjectOS y sus entradas de CHANGELOG se publican en: + +- **npm**: [`@objectstack/runtime`](https://www.npmjs.com/package/@objectstack/runtime) +- **GitHub**: [github.com/objectstack-ai/objectos/releases](https://github.com/objectstack-ai/objectos/releases) +- **CHANGELOG de origen**: [`CHANGELOG.md`](https://github.com/objectstack-ai/framework/blob/main/CHANGELOG.md) +- **Notas de versión extensas**: [`RELEASE_NOTES.md`](https://github.com/objectstack-ai/framework/blob/main/RELEASE_NOTES.md) + +Suscríbete a las versiones en GitHub para recibir notificaciones. + +## Aspectos destacados recientes + +### 4.0.x — tren de versiones actual + +- **42 paquetes** publicados en npm bajo `@objectstack/*`. +- Console incorporó páginas completas de configuración (AI, Storage, + Knowledge). +- Servicio de incrustación: 10 proveedores (`openai`, `azure`, 阿里通义, + 智谱, 硅基流动, 火山, MiniMax, Ollama, personalizado). +- Puente de configuración en vivo → runtime: cambia el proveedor en Console, + con intercambio en proceso sin reinicio. + +### 5.0 (próximamente) — cambio de nombre de `project` a `environment` + +El concepto de runtime antes llamado *Project* pasa a llamarse *Environment* +en todo el sistema. Afecta a: + +- Indicadores de CLI: `--environment` / `-e` +- Rutas HTTP: `/api/v1/environments/:environmentId/...` +- Cabeceras: `X-Environment-Id` +- Variables de entorno: `OS_ENVIRONMENT_ID` (`OS_PROJECT_ID` se mantiene como alias en 4.x, eliminado en 5.0) +- Columnas de BD: `environment_id` +- Esquemas JSON: `EnvironmentArtifact` + +Sin alias ni adaptadores de compatibilidad. Planifica la actualización con +cuidado: consulta la guía de migración a 5.0 en el lanzamiento. + +## Actualización + +Consulta [Actualización y reversión](/docs/operate/upgrade) para los pasos +mecánicos. Comprobaciones previas: + +1. Lee la entrada del CHANGELOG de cada versión menor entre tu versión + actual y la de destino. +2. Ejecuta `os diff ` para detectar cambios + de esquema incompatibles. +3. Ejecuta `os doctor` contra la versión de destino. +4. Pon en marcha una instancia canary antes de desplegar en toda la flota. +5. Ten un plan de reversión tanto para la etiqueta de la imagen como para + la versión del artefacto (se revierten de forma independiente). + +## Informar regresiones + +Si un parche o una versión menor rompe algo que antes funcionaba, abre un +informe de error en +[github.com/objectstack-ai/objectos/issues](https://github.com/objectstack-ai/objectos/issues) +indicando la versión desde la que actualizaste y a la que actualizaste. +Tratamos las regresiones como la clase de error de máxima prioridad. diff --git a/content/docs/resources/changelog.fr.mdx b/content/docs/resources/changelog.fr.mdx new file mode 100644 index 0000000..85c6594 --- /dev/null +++ b/content/docs/resources/changelog.fr.mdx @@ -0,0 +1,101 @@ +--- +title: Journal des modifications et versionnage +description: Comment ObjectOS est versionné, ce qui change entre les versions et ce qui est pris en charge. +--- + +# Journal des modifications et versionnage + +## Politique de versionnage + +ObjectOS suit le **[versionnage sémantique](https://semver.org/)** : `MAJOR.MINOR.PATCH`. + +| Incrément de version | Signification | Que faire | +|---|---|---| +| **Patch** (`4.0.1 → 4.0.2`) | Corrections de bogues, aucun changement de comportement | Mettre à jour, aucune modification de l'application nécessaire | +| **Mineur** (`4.0 → 4.1`) | Nouvelles fonctionnalités, rétrocompatibles | Mettre à jour, adopter éventuellement les nouvelles fonctionnalités | +| **Majeur** (`4 → 5`) | Changements incompatibles documentés dans les notes de version | Lire le guide de migration avant de mettre à niveau | + +Tous les paquets `@objectstack/*` sont publiés ensemble avec un numéro de +version synchronisé — ils sont testés en tant que matrice, et non +indépendamment. + +## Matrice de compatibilité + +| Composant | Règle de compatibilité | +|---|---| +| Image ObjectOS ↔ artefact compilé | Même version mineure. Une image 4.0.x exécute un artefact 4.0.x ; un artefact 4.1 peut utiliser des fonctionnalités indisponibles dans une image 4.0. | +| ObjectOS ↔ CLI | Même version mineure recommandée. Le CLI dans `npm i -g` écrit des squelettes épinglés à sa propre version. | +| ObjectOS ↔ pilote de base de données | Pilote épinglé par la construction de l'image ; vérifier Postgres ≥ 13 / MongoDB ≥ 5 / Turso (toute version actuelle). | +| Node.js | **20 LTS ou plus récent**. 22 LTS recommandé pour les nouveaux déploiements. | + +## Fenêtres de support + +| Branche | Statut | Jusqu'à | +|---|---|---| +| **4.x** (actuelle) | Développement actif ; nouvelles fonctionnalités et corrections | Au moins 12 mois après la sortie de la 5.0 | +| **3.x** | Corrections de sécurité uniquement | Fin de vie à la sortie de la 5.0 | +| **≤ 2.x** | Non prise en charge | Déjà en fin de vie | + +Les correctifs de sécurité critiques sont rétroportés vers la version +majeure actuelle et la précédente. Tout le reste atterrit sur `main`. + +## Notes de version + +Les versions publiées d'ObjectOS et leurs entrées de CHANGELOG sont publiées à : + +- **npm** : [`@objectstack/runtime`](https://www.npmjs.com/package/@objectstack/runtime) +- **GitHub** : [github.com/objectstack-ai/objectos/releases](https://github.com/objectstack-ai/objectos/releases) +- **CHANGELOG source** : [`CHANGELOG.md`](https://github.com/objectstack-ai/framework/blob/main/CHANGELOG.md) +- **Notes de version détaillées** : [`RELEASE_NOTES.md`](https://github.com/objectstack-ai/framework/blob/main/RELEASE_NOTES.md) + +Abonnez-vous aux versions sur GitHub pour être notifié. + +## Points marquants récents + +### 4.0.x — train de versions actuel + +- **42 paquets** publiés sur npm sous `@objectstack/*`. +- La Console a obtenu des pages de paramètres de Configuration complètes + (AI, Storage, Knowledge). +- Service d'embedder : 10 fournisseurs (`openai`, `azure`, 阿里通义, + 智谱, 硅基流动, 火山, MiniMax, Ollama, personnalisé). +- Pont paramètres en direct → runtime — changez de fournisseur dans la + Console, échange en cours de processus sans redémarrage. + +### 5.0 (à venir) — renommage de `project` → `environment` + +Le concept de runtime autrefois appelé *Project* est renommé en +*Environment* partout. Cela affecte : + +- Drapeaux CLI : `--environment` / `-e` +- Chemins HTTP : `/api/v1/environments/:environmentId/...` +- En-têtes : `X-Environment-Id` +- Variables d'environnement : `OS_ENVIRONMENT_ID` (`OS_PROJECT_ID` conservé comme alias en 4.x, supprimé en 5.0) +- Colonnes de base de données : `environment_id` +- Schémas JSON : `EnvironmentArtifact` + +Aucun alias ni adaptateur de dépréciation. Prévoyez une mise à niveau +soigneuse — voir le guide de migration 5.0 à sa sortie. + +## Mise à niveau + +Voir [Mise à niveau et restauration](/docs/operate/upgrade) pour les +étapes mécaniques. Avant le décollage : + +1. Lire l'entrée du CHANGELOG pour chaque version mineure entre votre + version actuelle et la version cible. +2. Exécuter `os diff ` pour faire apparaître + les changements de schéma incompatibles. +3. Exécuter `os doctor` sur la version cible. +4. Démarrer une instance canari avant de déployer sur l'ensemble du parc. +5. Avoir un plan de restauration à la fois pour le tag d'image et la + version d'artefact (ils sont restaurés indépendamment). + +## Signaler des régressions + +Si un correctif ou une version mineure casse quelque chose qui +fonctionnait auparavant, signalez un bogue sur +[github.com/objectstack-ai/objectos/issues](https://github.com/objectstack-ai/objectos/issues) +en indiquant la version depuis / vers laquelle vous avez effectué la mise +à niveau. Nous traitons les régressions comme la catégorie de bogues la +plus prioritaire. diff --git a/content/docs/resources/changelog.ja.mdx b/content/docs/resources/changelog.ja.mdx new file mode 100644 index 0000000..31e9fef --- /dev/null +++ b/content/docs/resources/changelog.ja.mdx @@ -0,0 +1,84 @@ +--- +title: 変更履歴とバージョニング +description: ObjectOS のバージョン管理方法、リリース間の変更点、サポート対象について。 +--- + +# 変更履歴とバージョニング + +## バージョニングポリシー + +ObjectOS は **[セマンティックバージョニング](https://semver.org/)** に従います: `MAJOR.MINOR.PATCH`。 + +| バージョンの更新 | 意味 | 対応 | +|---|---|---| +| **パッチ** (`4.0.1 → 4.0.2`) | バグ修正、動作の変更なし | そのまま更新でき、アプリの変更は不要 | +| **マイナー** (`4.0 → 4.1`) | 新機能、後方互換あり | そのまま更新でき、必要に応じて新機能を採用 | +| **メジャー** (`4 → 5`) | リリースノートに記載された破壊的変更 | アップグレード前に移行ガイドを必読 | + +すべての `@objectstack/*` パッケージは、同期されたバージョン番号で一緒にリリースされます。これらは個別ではなく、マトリックスとしてテストされます。 + +## 互換性マトリックス + +| コンポーネント | 互換性ルール | +|---|---| +| ObjectOS イメージ ↔ コンパイル済みアーティファクト | 同一のマイナーバージョン。4.0.x のイメージは 4.0.x のアーティファクトを実行します。4.1 のアーティファクトは 4.0 のイメージで利用できない機能を使用している場合があります。 | +| ObjectOS ↔ CLI | 同一のマイナーバージョンを推奨。`npm i -g` の CLI は、自身のバージョンに固定されたスキャフォールドを書き出します。 | +| ObjectOS ↔ データベースドライバー | ドライバーはイメージビルドで固定されます。Postgres ≥ 13 / MongoDB ≥ 5 / Turso(現行いずれか)を確認してください。 | +| Node.js | **20 LTS 以降**。新規デプロイには 22 LTS を推奨。 | + +## サポート期間 + +| ブランチ | ステータス | 期限 | +|---|---|---| +| **4.x**(現行) | 活発に開発中。新機能と修正 | 5.0 リリース後、少なくとも 12 か月 | +| **3.x** | セキュリティ修正のみ | 5.0 リリースで EOL | +| **≤ 2.x** | サポート対象外 | すでに EOL | + +重大なセキュリティ修正は、現行および 1 つ前のメジャーバージョンにバックポートされます。それ以外はすべて `main` に取り込まれます。 + +## リリースノート + +リリース済みの ObjectOS バージョンとその CHANGELOG エントリは、次の場所で公開されています: + +- **npm**: [`@objectstack/runtime`](https://www.npmjs.com/package/@objectstack/runtime) +- **GitHub**: [github.com/objectstack-ai/objectos/releases](https://github.com/objectstack-ai/objectos/releases) +- **ソース CHANGELOG**: [`CHANGELOG.md`](https://github.com/objectstack-ai/framework/blob/main/CHANGELOG.md) +- **詳細リリースノート**: [`RELEASE_NOTES.md`](https://github.com/objectstack-ai/framework/blob/main/RELEASE_NOTES.md) + +GitHub でリリースを購読すると、通知を受け取れます。 + +## 最近のハイライト + +### 4.0.x — 現行リリーストレイン + +- **42 個のパッケージ** を `@objectstack/*` 配下で npm に公開。 +- Console に完全な Configuration 設定ページ(AI、Storage、Knowledge)を追加。 +- Embedder サービス: 10 のプロバイダー(`openai`、`azure`、阿里通義、智谱、硅基流动、火山、MiniMax、Ollama、custom)。 +- ライブ設定 → ランタイムのブリッジ — Console でプロバイダーを変更すると、再起動なしでプロセス内で切り替わります。 + +### 5.0(予定) — `project` → `environment` への名称変更 + +これまで *Project* と呼ばれていたランタイムの概念が、全体を通して *Environment* に名称変更されます。影響範囲: + +- CLI フラグ: `--environment` / `-e` +- HTTP パス: `/api/v1/environments/:environmentId/...` +- ヘッダー: `X-Environment-Id` +- 環境変数: `OS_ENVIRONMENT_ID`(`OS_PROJECT_ID` は 4.x ではエイリアスとして維持され、5.0 で削除) +- DB カラム: `environment_id` +- JSON スキーマ: `EnvironmentArtifact` + +エイリアスや非推奨用のシムはありません。慎重にアップグレードを計画してください。リリース時の 5.0 移行ガイドを参照してください。 + +## アップグレード + +具体的な手順については [アップグレードとロールバック](/docs/operate/upgrade) を参照してください。事前チェック: + +1. 現行バージョンとターゲットバージョンの間にあるすべてのマイナーについて、CHANGELOG エントリを読みます。 +2. `os diff ` を実行して、破壊的なスキーマ変更を洗い出します。 +3. ターゲットバージョンに対して `os doctor` を実行します。 +4. フリート全体に展開する前に、カナリアインスタンスを 1 台立ち上げます。 +5. イメージタグとアーティファクトバージョンの両方についてロールバック計画を用意します(これらは独立してロールします)。 + +## リグレッションの報告 + +パッチまたはマイナーによって、以前は動作していたものが壊れた場合は、[github.com/objectstack-ai/objectos/issues](https://github.com/objectstack-ai/objectos/issues) で、アップグレード元/先のバージョンを添えてバグを報告してください。リグレッションは最優先で対応すべきバグとして扱います。 diff --git a/content/docs/resources/changelog.cn.mdx b/content/docs/resources/changelog.zh-Hans.mdx similarity index 100% rename from content/docs/resources/changelog.cn.mdx rename to content/docs/resources/changelog.zh-Hans.mdx diff --git a/content/docs/resources/faq.de.mdx b/content/docs/resources/faq.de.mdx new file mode 100644 index 0000000..af5d5f2 --- /dev/null +++ b/content/docs/resources/faq.de.mdx @@ -0,0 +1,207 @@ +--- +title: FAQ +description: Antworten auf die Fragen, die uns am häufigsten gestellt werden. +--- + +# FAQ + +## Erste Schritte + +**F: Was ist der absolut schnellste Weg, ObjectOS auszuprobieren?** +A: `npm i -g @objectstack/cli && os start` — und dann +http://localhost:3000 öffnen. Siehe [Quickstart](/docs/quickstart). + +**F: Brauche ich Docker?** +A: Nein. Node 20+ und die CLI reichen aus. Docker ist die empfohlene +Form für das Produktiv-Deployment. + +**F: Brauche ich eine Datenbank?** +A: Nein, nicht für den Anfang — ObjectOS verwendet standardmäßig lokales +SQLite. Wechseln Sie zu Postgres / MySQL / Turso / Mongo, wenn Sie in +die Produktion gehen. + +**F: Brauche ich ein Konto / einen Cloud-Dienst?** +A: Nein. ObjectOS ist vollständig eigenständig. ObjectStack Cloud ist +optional für Deployments über mehrere Umgebungen / mehrere Apps mit +einer Control Plane. + +## Architektur + +**F: Kann ich Postgres / MySQL / MongoDB verwenden?** +A: Ja — Postgres, MySQL, SQLite, Turso/libSQL und MongoDB sind +unterstützte Treiber. Siehe [Runtime Configuration](/docs/configure/runtime). + +**F: Kann ich Console / Account deaktivieren und nur die REST-API nutzen?** +A: Ja. Führen Sie `os start --no-ui` aus oder setzen Sie die +entsprechenden Flags. Die REST-API ist dieselbe, egal ob die UIs +eingebunden sind oder nicht. + +**F: Kann ich mein eigenes Frontend anstelle von Console verwenden?** +A: Ja. Console verwendet dieselben `/api/v1/*`-Endpunkte, die Sie aus +Ihrem eigenen Code aufrufen würden. Verwenden Sie das +`@objectstack/client` SDK oder einen beliebigen HTTP-Client. + +**F: Unterstützt ObjectOS GraphQL?** +A: REST ist die primäre Schnittstelle. GraphQL ist auf der Roadmap — bis +dahin deckt die Abfragesprache ObjectQL (über REST `?filter=`/`?sort=`) +dasselbe Terrain ab. + +**F: Wie wird Mandantenfähigkeit (Multi-Tenancy) gehandhabt?** +A: Ein ObjectOS-Prozess kann viele Environments (Mandanten) bedienen. +Die Auflösung Hostname → Environment wird in einem LRU zwischengespeichert; +jedes Environment hat seine eigene Datenbank, Identität und sein eigenes +Audit-Log. Cookies sind pro Hostname gescoped, sodass Sessions nicht +zwischen Mandanten durchsickern können. + +**F: Kann ObjectOS in einer Serverless-/Lambda-Umgebung laufen?** +A: Die Laufzeit ist ein langlebiger Node-Prozess — ausgelegt für +Container oder VMs, nicht für zustandslose Funktionen. Sowohl der +Kernel-Cache als auch das Better-Auth-Session-Modell hängen von warmem +prozessinternem Zustand ab. + +**F: Skaliert es horizontal?** +A: Ja. Führen Sie mehrere Instanzen hinter einem Load Balancer aus. +Sessions liegen in der Datenbank (nicht im Speicher), sodass jede +Instanz jede Anfrage bedienen kann. Verwenden Sie Redis für gemeinsames +Rate-Limiting und Queueing, wenn Sie diese Funktionen aktivieren. + +## Daten & Migrationen + +**F: Wie werden Schema-Migrationen gehandhabt?** +A: Der Treiber synchronisiert das Datenbankschema beim Hochfahren mit +Ihren deklarierten Objekten. Für Postgres sind das `CREATE TABLE` / +`ALTER TABLE`-Anweisungen. Für kontrollierte Migrationen in regulierten +Umgebungen setzen Sie `OS_SKIP_SCHEMA_SYNC=1` und verwalten das DDL +selbst. + +**F: Was passiert mit Daten, wenn ich ein Feld umbenenne?** +A: Eine Umbenennung ist auf der Datenebene eine destruktive Änderung +(sie sieht aus wie „alte Spalte löschen, neue Spalte hinzufügen"). +Verwenden Sie `os diff`, um dies zu erkennen, und fügen Sie einen +Migrationsschritt hinzu (Spalte in der DB umbenennen, bevor das neue +Artefakt deployt wird). + +**F: Kann ich Daten aus CSV / Excel / Salesforce importieren?** +A: CSV: ja, per `os data create` in einer Schleife oder über den +Bulk-Upload in der Console. Salesforce: Der beste Weg heute ist der +Export nach CSV und der anschließende Import. Native Konnektoren sind +auf der Roadmap. + +**F: Gehen beim Upgrade von ObjectOS meine Daten verloren?** +A: Nein. Patch- und Minor-Upgrades sind nicht-destruktiv. Major-Upgrades +(z. B. 4 → 5) dokumentieren erforderliche Migrationen ausdrücklich. +Erstellen Sie zuerst ein Backup — [Backup & DR](/docs/operate/backup). + +## Berechtigungen & Mandantenfähigkeit + +**F: Wie realisiere ich Sicherheit auf Zeilenebene (Row-Level Security)?** +A: Deklarieren Sie eine Sharing-Regel (deklarativ, wie bei Salesforce) +oder ein CEL-Prädikat in der `recordAccess`-Konfiguration eines Objekts. +Das Security-Plugin fügt bei jeder Abfrage den entsprechenden Filter +ein. Siehe [Permissions](/docs/configure/permissions). + +**F: Kann ich bestimmte Felder für bestimmte Benutzer unsichtbar machen?** +A: Ja — Sicherheit auf Feldebene in Permission Sets. Verbergen oder +schreibgeschützt, pro Feld pro Permission Set. Wird einheitlich über +REST, ObjectQL und Console durchgesetzt. Siehe +[Permission Sets](/docs/configure/permissions/permission-sets). + +**F: Wie integriere ich Okta / Entra / Keycloak?** +A: OIDC. Konfigurieren Sie die Discovery-URL + Client-ID/-Secret unter +**Console → Authentication** (oder per Env). Die Callback-URL des +Providers ist `/api/v1/auth/oauth2/callback/`. Siehe +[Authentication](/docs/configure/authentication). + +## Integrationen + +**F: Kann ich Webhooks senden?** +A: Ja — aktivieren Sie `webhooks` in `requires`. ObjectOS verwendet +eine persistente Outbox mit HMAC-SHA256-Signierung. Siehe +[Webhooks](/docs/configure/webhooks). + +**F: Kann ich mit Zapier / Make / n8n integrieren?** +A: Ja — Webhooks für ausgehende und die REST-API + API-Keys für +eingehende Kommunikation. Native Konnektoren für gängige iPaaS-Tools +sind auf der Roadmap. + +**F: Können KI-Agenten mein ObjectOS aufrufen?** +A: Ja, über MCP (`@objectstack/plugin-mcp-server`) — stellt Objekte +und Aktionen als MCP-Tools bereit, die Claude Desktop, IDEs oder andere +MCP-Clients verwenden können. Siehe [AI Service](/docs/configure/ai). + +## Anpassung + +**F: Kann ich eigene Plugins schreiben?** +A: Ja — Plugins folgen einem einfachen DI- + Lifecycle-Muster +(`init → start → destroy`). Beispiele finden Sie in den +`@objectstack/plugin-*`-Paketen auf GitHub. + +**F: Kann ich das Erscheinungsbild von Console anpassen?** +A: Branding (Logo, Akzentfarbe, Standard-Theme) befindet sich unter +**Console → System Settings**. Tiefgreifende UI-Anpassung bedeutet, das +`@objectstack/client-react` zu forken oder Ihr eigenes Frontend gegen +die REST-API zu bauen. + +**F: Kann ich andere Sprachen als Englisch hinzufügen?** +A: Ja — i18n ist erstklassig integriert. Verwenden Sie +`os i18n extract` / `os i18n check` und liefern Sie ein +Übersetzungs-Bundle aus. + +## Betrieb + +**F: Was ist das empfohlene Produktiv-Deployment?** +A: Docker (oder Kubernetes für mehrere Pods) + verwaltetes Postgres + S3 +oder R2 für Dateien + Ihr Secret-Manager für `OS_AUTH_SECRET`. Siehe +[Production Readiness](/docs/operate/production). + +**F: Hat ObjectOS eine Statusseite?** +A: Für Ihr selbst gehostetes Deployment ist der Status Ihre Angelegenheit +— verbinden Sie `/health` mit Ihrem Monitor. Für gehostete Dienste siehe +[status.objectstack.ai](https://status.objectstack.ai). + +**F: Welche Metriken sollte ich überwachen?** +A: 5xx-Rate, p95-Latenz, Auth-Fehlerrate, Kernel-Cache-Miss-Rate, +Queue-Tiefe. Ein minimales Prometheus-Beispiel finden Sie in +[Observability](/docs/operate/observability). + +**F: Wie erstelle ich ein Backup?** +A: Sichern Sie die **Datenbank** und den **Storage-Bucket** — diese +enthalten alle Kundendaten. ObjectOS selbst ist zustandslos. Siehe +[Backup](/docs/operate/backup). + +## Preise & Rechtliches + +**F: Ist ObjectOS wirklich kostenlos?** +A: Ja. Apache-2.0. Keine Sitze, keine Nutzungsstufe, kein Lizenzserver. + +**F: Kann ich ObjectOS in einem kommerziellen Produkt verwenden, das ich verkaufe?** +A: Ja. Apache-2.0 erlaubt die kommerzielle Nutzung. Siehe +[License](/docs/resources/license). + +**F: Erfassen Sie Telemetrie?** +A: Nein. Null ausgehende Aufrufe, sofern Sie sie nicht konfigurieren +(OIDC, E-Mail, AI, Webhooks). Siehe +[Security & Compliance](/docs/reference/security#data-residency). + +**F: Ist ObjectOS SOC 2 / ISO 27001 / HIPAA / GDPR-konform?** +A: ObjectOS stellt die **Primitive** bereit, die jedes Framework +benötigt (RBAC, Audit, verschlüsselungsbereit, Residenz). Eine +Zertifizierung ist eine Eigenschaft Ihres **Deployments**, nicht der +Binärdatei. Viele ObjectOS-Deployments sind zertifiziert. Siehe +[Security & Compliance](/docs/reference/security#compliance-frameworks). + +## Wenn Sie nicht weiterkommen + +**F: Etwas ist kaputt — wo fange ich an?** +A: `os doctor`. Das erkennt 80 % der Fehlkonfigurationen von selbst. +Danach [Troubleshooting](/docs/operate/troubleshooting). + +**F: Wo melde ich einen Fehler?** +A: [GitHub Issues](https://github.com/objectstack-ai/objectos/issues). +Fügen Sie die Ausgabe von `os doctor` bei. Sicherheitsprobleme: +**security@objectstack.ai**. + +**F: Wo bekomme ich Hilfe von echten Menschen?** +A: [GitHub Discussions](https://github.com/objectstack-ai/objectos/discussions), +der Community-Discord oder **sales@objectstack.ai** für kommerziellen +Support. diff --git a/content/docs/resources/faq.es.mdx b/content/docs/resources/faq.es.mdx new file mode 100644 index 0000000..bc51ea2 --- /dev/null +++ b/content/docs/resources/faq.es.mdx @@ -0,0 +1,201 @@ +--- +title: Preguntas frecuentes +description: Respuestas a las preguntas que más nos hacen. +--- + +# Preguntas frecuentes + +## Primeros pasos + +**P: ¿Cuál es la forma más rápida de probar ObjectOS?** +R: `npm i -g @objectstack/cli && os start` — luego abre +http://localhost:3000. Consulta [Quickstart](/docs/quickstart). + +**P: ¿Necesito Docker?** +R: No. Node 20+ y la CLI son suficientes. Docker es la forma de +despliegue de producción recomendada. + +**P: ¿Necesito una base de datos?** +R: No, no para empezar — ObjectOS usa SQLite local de forma predeterminada. +Cámbiala por Postgres / MySQL / Turso / Mongo cuando pases a producción. + +**P: ¿Necesito una cuenta / servicio en la nube?** +R: No. ObjectOS es totalmente autónomo. ObjectStack Cloud es opcional +para despliegues multientorno / multiaplicación con un plano de control. + +## Arquitectura + +**P: ¿Puedo usar Postgres / MySQL / MongoDB?** +R: Sí — Postgres, MySQL, SQLite, Turso/libSQL y MongoDB son +controladores compatibles. Consulta [Runtime Configuration](/docs/configure/runtime). + +**P: ¿Puedo desactivar Console / Account y usar solo la API REST?** +R: Sí. Ejecuta `os start --no-ui` o establece los indicadores +correspondientes. La API REST es la misma tanto si las interfaces de +usuario están montadas como si no. + +**P: ¿Puedo usar mi propio front-end en lugar de Console?** +R: Sí. Console usa los mismos endpoints `/api/v1/*` que llamarías desde +tu propio código. Usa el SDK `@objectstack/client` o cualquier cliente HTTP. + +**P: ¿ObjectOS admite GraphQL?** +R: REST es la superficie principal. GraphQL está en la hoja de ruta — +hasta entonces, el lenguaje de consulta ObjectQL (sobre REST +`?filter=`/`?sort=`) cubre el mismo terreno. + +**P: ¿Cómo se gestiona la multitenencia?** +R: Un proceso de ObjectOS puede servir a muchos Environments (tenants). +La resolución de hostname → Environment se almacena en caché en una LRU; +cada Environment tiene su propia base de datos, identidad y registro de +auditoría. Las cookies tienen un alcance por hostname para que las +sesiones no puedan filtrarse entre tenants. + +**P: ¿Puede ObjectOS ejecutarse en un entorno serverless / Lambda?** +R: El runtime es un proceso Node de larga duración — diseñado para +contenedores o VMs, no para funciones sin estado. Tanto la caché del +kernel como el modelo de sesión de Better Auth dependen de un estado +en proceso "caliente". + +**P: ¿Escala horizontalmente?** +R: Sí. Ejecuta varias instancias detrás de un balanceador de carga. Las +sesiones viven en la base de datos (no en memoria), por lo que cualquier +instancia puede atender cualquier solicitud. Usa Redis para la limitación +de tasa y la cola compartidas si habilitas esas capacidades. + +## Datos y migraciones + +**P: ¿Cómo se gestionan las migraciones de esquema?** +R: El controlador sincroniza el esquema de la base de datos con los +objetos que declaras durante el arranque. Para Postgres, eso son +sentencias `CREATE TABLE` / `ALTER TABLE`. Para migraciones controladas +en entornos regulados, establece `OS_SKIP_SCHEMA_SYNC=1` y gestiona el +DDL tú mismo. + +**P: ¿Qué ocurre con los datos cuando renombro un campo?** +R: Un cambio de nombre es un cambio destructivo en la capa de datos +(parece "eliminar la columna antigua, añadir la columna nueva"). Usa +`os diff` para detectarlo y añade un paso de migración (renombra la +columna en la BD antes de desplegar el nuevo artefacto). + +**P: ¿Puedo importar datos desde CSV / Excel / Salesforce?** +R: CSV: sí, mediante `os data create` en bucle o la carga masiva de +Console. Salesforce: el mejor camino hoy es exportar a CSV e importar. +Los conectores nativos están en la hoja de ruta. + +**P: ¿Actualizar ObjectOS hará que pierda mis datos?** +R: No. Las actualizaciones de parche y menores no son destructivas. Las +actualizaciones mayores (p. ej. 4 → 5) documentan explícitamente las +migraciones necesarias. Haz una copia de seguridad primero — +[Backup & DR](/docs/operate/backup). + +## Permisos y multitenencia + +**P: ¿Cómo implemento la seguridad a nivel de fila?** +R: Declara una regla de uso compartido (declarativa, como Salesforce) o +un predicado CEL en la configuración `recordAccess` de un objeto. El +plugin de seguridad inyecta el filtro correspondiente en cada consulta. +Consulta [Permissions](/docs/configure/permissions). + +**P: ¿Puedo hacer que algunos campos sean invisibles para ciertos usuarios?** +R: Sí — seguridad a nivel de campo en los conjuntos de permisos. Oculto +o de solo lectura, por campo y por conjunto de permisos. Se aplica de +manera uniforme en REST, ObjectQL y Console. Consulta +[Permission Sets](/docs/configure/permissions/permission-sets). + +**P: ¿Cómo integro Okta / Entra / Keycloak?** +R: OIDC. Configura la URL de descubrimiento + el id/secreto de cliente +en **Console → Authentication** (o mediante env). La URL de callback del +proveedor es `/api/v1/auth/oauth2/callback/`. Consulta +[Authentication](/docs/configure/authentication). + +## Integraciones + +**P: ¿Puedo enviar webhooks?** +R: Sí — habilita `webhooks` en `requires`. ObjectOS usa una bandeja de +salida persistente con firma HMAC-SHA256. Consulta [Webhooks](/docs/configure/webhooks). + +**P: ¿Puedo integrarme con Zapier / Make / n8n?** +R: Sí — webhooks para la salida y la API REST + claves de API para la +entrada. Los conectores nativos para herramientas iPaaS populares están +en la hoja de ruta. + +**P: ¿Pueden los agentes de IA llamar a mi ObjectOS?** +R: Sí, mediante MCP (`@objectstack/plugin-mcp-server`) — expone objetos +y acciones como herramientas MCP que Claude Desktop, los IDE u otros +clientes MCP pueden usar. Consulta [AI Service](/docs/configure/ai). + +## Personalización + +**P: ¿Puedo escribir plugins personalizados?** +R: Sí — los plugins siguen un patrón sencillo de DI + ciclo de vida +(`init → start → destroy`). Consulta los paquetes `@objectstack/plugin-*` +en GitHub para ver ejemplos. + +**P: ¿Puedo personalizar el aspecto de Console?** +R: La personalización de marca (logo, color de acento, tema +predeterminado) está en **Console → System Settings**. La personalización +profunda de la interfaz implica hacer un fork de +`@objectstack/client-react` o construir tu propio front-end contra la +API REST. + +**P: ¿Puedo añadir idiomas distintos del inglés?** +R: Sí — i18n es de primera clase. Usa `os i18n extract` / `os i18n check` +y entrega un paquete de traducción. + +## Operaciones + +**P: ¿Cuál es el despliegue de producción recomendado?** +R: Docker (o Kubernetes para multipod) + Postgres gestionado + S3 o R2 +para archivos + tu gestor de secretos para `OS_AUTH_SECRET`. Consulta +[Production Readiness](/docs/operate/production). + +**P: ¿ObjectOS tiene una página de estado?** +R: Para tu despliegue autoalojado, el estado es asunto tuyo — conecta +`/health` a tu monitor. Para servicios alojados, consulta +[status.objectstack.ai](https://status.objectstack.ai). + +**P: ¿Qué métricas debo monitorizar?** +R: tasa de 5xx, latencia p95, tasa de fallos de autenticación, tasa de +fallos de caché del kernel, profundidad de la cola. Ejemplo mínimo de +Prometheus en [Observability](/docs/operate/observability). + +**P: ¿Cómo hago una copia de seguridad?** +R: Haz una copia de seguridad de la **base de datos** y del **bucket de +almacenamiento** — esos contienen todos los datos de clientes. ObjectOS +en sí no tiene estado. Consulta [Backup](/docs/operate/backup). + +## Precios y aspectos legales + +**P: ¿ObjectOS es realmente gratis?** +R: Sí. Apache-2.0. Sin asientos, sin nivel de uso, sin servidor de +licencias. + +**P: ¿Puedo usar ObjectOS en un producto comercial que vendo?** +R: Sí. Apache-2.0 permite el uso comercial. Consulta [License](/docs/resources/license). + +**P: ¿Recopilan telemetría?** +R: No. Cero llamadas salientes a menos que las configures (OIDC, email, +IA, webhooks). Consulta [Security & Compliance](/docs/reference/security#data-residency). + +**P: ¿ObjectOS cumple con SOC 2 / ISO 27001 / HIPAA / GDPR?** +R: ObjectOS proporciona las **primitivas** que requiere todo framework +(RBAC, auditoría, listo para cifrado, residencia). La certificación es +una propiedad de tu **despliegue**, no del binario. Muchos despliegues +de ObjectOS están certificados. Consulta +[Security & Compliance](/docs/reference/security#compliance-frameworks). + +## Resolver bloqueos + +**P: Algo está roto — ¿por dónde empiezo?** +R: `os doctor`. Detecta por sí solo el 80% de las configuraciones +incorrectas. Después de eso, [Troubleshooting](/docs/operate/troubleshooting). + +**P: ¿Dónde reporto un error?** +R: [GitHub Issues](https://github.com/objectstack-ai/objectos/issues). +Incluye la salida de `os doctor`. Problemas de seguridad: +**security@objectstack.ai**. + +**P: ¿Dónde obtengo ayuda de personas reales?** +R: [GitHub Discussions](https://github.com/objectstack-ai/objectos/discussions), +el Discord de la comunidad o **sales@objectstack.ai** para soporte +comercial. diff --git a/content/docs/resources/faq.fr.mdx b/content/docs/resources/faq.fr.mdx new file mode 100644 index 0000000..475c76e --- /dev/null +++ b/content/docs/resources/faq.fr.mdx @@ -0,0 +1,205 @@ +--- +title: FAQ +description: Réponses aux questions qu'on nous pose le plus souvent. +--- + +# FAQ + +## Premiers pas + +**Q : Quel est le moyen le plus rapide d'essayer ObjectOS ?** +R : `npm i -g @objectstack/cli && os start` — puis ouvrez +http://localhost:3000. Voir [Démarrage rapide](/docs/quickstart). + +**Q : Ai-je besoin de Docker ?** +R : Non. Node 20+ et le CLI suffisent. Docker est la forme de +déploiement recommandée pour la production. + +**Q : Ai-je besoin d'une base de données ?** +R : Non, pas pour démarrer — ObjectOS utilise SQLite en local par défaut. +Remplacez-le par Postgres / MySQL / Turso / Mongo lorsque vous passez en +production. + +**Q : Ai-je besoin d'un compte / d'un service cloud ?** +R : Non. ObjectOS est entièrement autonome. ObjectStack Cloud est +optionnel pour les déploiements multi-environnements / multi-applications +avec un plan de contrôle. + +## Architecture + +**Q : Puis-je utiliser Postgres / MySQL / MongoDB ?** +R : Oui — Postgres, MySQL, SQLite, Turso/libSQL et MongoDB sont des +pilotes pris en charge. Voir [Configuration du runtime](/docs/configure/runtime). + +**Q : Puis-je désactiver Console / Account et n'utiliser que l'API REST ?** +R : Oui. Exécutez `os start --no-ui` ou définissez les indicateurs +correspondants. L'API REST est la même que les interfaces soient montées +ou non. + +**Q : Puis-je utiliser mon propre front-end à la place de Console ?** +R : Oui. Console utilise les mêmes points de terminaison `/api/v1/*` que +vous appelleriez depuis votre propre code. Utilisez le SDK +`@objectstack/client` ou n'importe quel client HTTP. + +**Q : ObjectOS prend-il en charge GraphQL ?** +R : REST est la surface principale. GraphQL est dans la feuille de route — +en attendant, le langage de requête ObjectQL (par-dessus REST +`?filter=`/`?sort=`) couvre le même périmètre. + +**Q : Comment la multilocation est-elle gérée ?** +R : Un seul processus ObjectOS peut servir de nombreux Environments +(locataires). La résolution nom d'hôte → Environment est mise en cache +dans un LRU ; chaque Environment a sa propre base de données, son identité +et son journal d'audit. Les cookies sont délimités par nom d'hôte afin que +les sessions ne puissent pas fuiter entre locataires. + +**Q : ObjectOS peut-il s'exécuter dans un environnement serverless / Lambda ?** +R : Le runtime est un processus Node de longue durée — conçu pour des +conteneurs ou des VM, pas pour des fonctions sans état. Le cache du noyau +et le modèle de session Better Auth dépendent tous deux d'un état chaud +en cours de processus. + +**Q : Est-ce que ça monte en charge horizontalement ?** +R : Oui. Exécutez plusieurs instances derrière un répartiteur de charge. +Les sessions résident dans la base de données (et non en mémoire), de +sorte que n'importe quelle instance peut servir n'importe quelle requête. +Utilisez Redis pour la limitation de débit partagée et la file d'attente +si vous activez ces capacités. + +## Données & migrations + +**Q : Comment les migrations de schéma sont-elles gérées ?** +R : Le pilote synchronise le schéma de la base de données avec vos objets +déclarés au démarrage. Pour Postgres, ce sont des instructions +`CREATE TABLE` / `ALTER TABLE`. Pour des migrations contrôlées dans des +environnements réglementés, définissez `OS_SKIP_SCHEMA_SYNC=1` et gérez le +DDL vous-même. + +**Q : Qu'advient-il des données lorsque je renomme un champ ?** +R : Un renommage est une modification destructrice au niveau de la couche +de données (cela ressemble à « supprimer l'ancienne colonne, ajouter une +nouvelle colonne »). Utilisez `os diff` pour le détecter et ajoutez une +étape de migration (renommez la colonne dans la base de données avant de +déployer le nouvel artefact). + +**Q : Puis-je importer des données depuis CSV / Excel / Salesforce ?** +R : CSV : oui, via `os data create` dans une boucle ou via le téléversement +en masse de Console. Salesforce : la meilleure voie aujourd'hui consiste à +exporter vers CSV puis à importer. Des connecteurs natifs sont dans la +feuille de route. + +**Q : La mise à niveau d'ObjectOS fera-t-elle perdre mes données ?** +R : Non. Les mises à niveau de correctif et mineures ne sont pas +destructrices. Les mises à niveau majeures (par ex. 4 → 5) documentent +explicitement les migrations requises. Faites d'abord une sauvegarde — +[Sauvegarde & DR](/docs/operate/backup). + +## Permissions & multilocation + +**Q : Comment mettre en place une sécurité au niveau des lignes ?** +R : Déclarez une règle de partage (déclarative, comme Salesforce) ou un +prédicat CEL sur la configuration `recordAccess` d'un objet. Le plugin de +sécurité injecte le filtre correspondant à chaque requête. Voir +[Permissions](/docs/configure/permissions). + +**Q : Puis-je rendre certains champs invisibles pour certains utilisateurs ?** +R : Oui — sécurité au niveau des champs dans les ensembles de permissions. +Masqué ou en lecture seule, par champ et par ensemble de permissions. +Appliqué uniformément sur REST, ObjectQL et Console. Voir +[Ensembles de permissions](/docs/configure/permissions/permission-sets). + +**Q : Comment intégrer Okta / Entra / Keycloak ?** +R : OIDC. Configurez l'URL de découverte + le client id/secret dans +**Console → Authentication** (ou via les variables d'environnement). L'URL +de rappel du fournisseur est +`/api/v1/auth/oauth2/callback/`. Voir [Authentification](/docs/configure/authentication). + +## Intégrations + +**Q : Puis-je envoyer des webhooks ?** +R : Oui — activez `webhooks` dans `requires`. ObjectOS utilise une boîte +d'envoi persistante avec signature HMAC-SHA256. Voir [Webhooks](/docs/configure/webhooks). + +**Q : Puis-je intégrer Zapier / Make / n8n ?** +R : Oui — des webhooks pour le sortant et l'API REST + des clés d'API pour +l'entrant. Des connecteurs natifs pour les outils iPaaS populaires sont +dans la feuille de route. + +**Q : Les agents IA peuvent-ils appeler mon ObjectOS ?** +R : Oui, via MCP (`@objectstack/plugin-mcp-server`) — il expose les objets +et les actions comme des outils MCP que Claude Desktop, les IDE ou d'autres +clients MCP peuvent utiliser. Voir [Service IA](/docs/configure/ai). + +## Personnalisation + +**Q : Puis-je écrire des plugins personnalisés ?** +R : Oui — les plugins suivent un modèle simple d'injection de dépendances +et de cycle de vie (`init → start → destroy`). Voir les paquets +`@objectstack/plugin-*` sur GitHub pour des exemples. + +**Q : Puis-je personnaliser l'apparence de Console ?** +R : L'image de marque (logo, couleur d'accentuation, thème par défaut) se +trouve dans **Console → System Settings**. Une personnalisation poussée de +l'UI implique de forker `@objectstack/client-react` ou de créer votre +propre front-end basé sur l'API REST. + +**Q : Puis-je ajouter d'autres langues que l'anglais ?** +R : Oui — l'i18n est de première classe. Utilisez `os i18n extract` / +`os i18n check` et livrez un bundle de traduction. + +## Exploitation + +**Q : Quel est le déploiement de production recommandé ?** +R : Docker (ou Kubernetes pour le multi-pod) + Postgres managé + S3 ou R2 +pour les fichiers + votre gestionnaire de secrets pour `OS_AUTH_SECRET`. +Voir [Préparation à la production](/docs/operate/production). + +**Q : ObjectOS dispose-t-il d'une page de statut ?** +R : Pour votre déploiement auto-hébergé, le statut est de votre ressort — +branchez `/health` à votre moniteur. Pour les services hébergés, voir +[status.objectstack.ai](https://status.objectstack.ai). + +**Q : Quelles métriques dois-je surveiller ?** +R : Taux de 5xx, latence p95, taux d'échec d'authentification, taux d'échec +de cache du noyau, profondeur de la file d'attente. Exemple Prometheus +minimal dans [Observabilité](/docs/operate/observability). + +**Q : Comment effectuer une sauvegarde ?** +R : Sauvegardez la **base de données** et le **bucket de stockage** — ce +sont eux qui contiennent toutes les données client. ObjectOS lui-même est +sans état. Voir [Sauvegarde](/docs/operate/backup). + +## Tarification & aspects juridiques + +**Q : ObjectOS est-il vraiment gratuit ?** +R : Oui. Apache-2.0. Pas de sièges, pas de palier d'utilisation, pas de +serveur de licences. + +**Q : Puis-je utiliser ObjectOS dans un produit commercial que je vends ?** +R : Oui. Apache-2.0 autorise un usage commercial. Voir [Licence](/docs/resources/license). + +**Q : Collectez-vous de la télémétrie ?** +R : Non. Zéro appel sortant sauf si vous les configurez (OIDC, e-mail, IA, +webhooks). Voir [Sécurité & conformité](/docs/reference/security#data-residency). + +**Q : ObjectOS est-il conforme à SOC 2 / ISO 27001 / HIPAA / RGPD ?** +R : ObjectOS fournit les **primitives** que tout framework requiert (RBAC, +audit, prêt pour le chiffrement, résidence). La certification est une +propriété de votre **déploiement**, pas du binaire. De nombreux +déploiements ObjectOS sont certifiés. Voir [Sécurité & conformité](/docs/reference/security#compliance-frameworks). + +## Se débloquer + +**Q : Quelque chose ne fonctionne pas — par où commencer ?** +R : `os doctor`. Il détecte à lui seul 80 % des erreurs de configuration. +Ensuite, [Dépannage](/docs/operate/troubleshooting). + +**Q : Où signaler un bug ?** +R : [GitHub Issues](https://github.com/objectstack-ai/objectos/issues). +Incluez la sortie de `os doctor`. Problèmes de sécurité : +**security@objectstack.ai**. + +**Q : Où obtenir de l'aide auprès d'humains ?** +R : [GitHub Discussions](https://github.com/objectstack-ai/objectos/discussions), +le Discord communautaire, ou **sales@objectstack.ai** pour le support +commercial. diff --git a/content/docs/resources/faq.ja.mdx b/content/docs/resources/faq.ja.mdx new file mode 100644 index 0000000..56b2e9c --- /dev/null +++ b/content/docs/resources/faq.ja.mdx @@ -0,0 +1,201 @@ +--- +title: FAQ +description: よく寄せられる質問への回答。 +--- + +# FAQ + +## はじめに + +**Q: ObjectOS を最速で試す方法は?** +A: `npm i -g @objectstack/cli && os start` を実行し、 +http://localhost:3000 を開いてください。[クイックスタート](/docs/quickstart)を参照してください。 + +**Q: Docker は必要ですか?** +A: いいえ。Node 20+ と CLI があれば十分です。Docker は本番環境への +推奨デプロイ構成です。 + +**Q: データベースは必要ですか?** +A: いいえ、開始時には不要です。ObjectOS はデフォルトでローカルの SQLite を +使用します。本番環境に移行する際は Postgres / MySQL / Turso / Mongo に +切り替えてください。 + +**Q: アカウントやクラウドサービスは必要ですか?** +A: いいえ。ObjectOS は完全に自己完結しています。ObjectStack Cloud は、 +コントロールプレーンを備えたマルチ環境・マルチアプリのデプロイにおいて +任意で利用できます。 + +## アーキテクチャ + +**Q: Postgres / MySQL / MongoDB を使えますか?** +A: はい。Postgres、MySQL、SQLite、Turso/libSQL、MongoDB が +サポートされるドライバです。[ランタイム設定](/docs/configure/runtime)を参照してください。 + +**Q: Console / Account を無効化して REST API のみを使えますか?** +A: はい。`os start --no-ui` を実行するか、対応するフラグを設定してください。 +REST API は UI がマウントされているかどうかに関わらず同一です。 + +**Q: Console の代わりに独自のフロントエンドを使えますか?** +A: はい。Console は、独自のコードから呼び出すのと同じ `/api/v1/*` +エンドポイントを使用します。`@objectstack/client` SDK または任意の HTTP +クライアントを使用してください。 + +**Q: ObjectOS は GraphQL をサポートしていますか?** +A: REST が主要なインターフェースです。GraphQL はロードマップにあります。 +それまでは、ObjectQL クエリ言語(REST の `?filter=`/`?sort=` 上)が +同等の範囲をカバーします。 + +**Q: マルチテナンシーはどのように扱われますか?** +A: 1 つの ObjectOS プロセスが多数の Environment(テナント)を提供できます。 +ホスト名 → Environment の解決は LRU にキャッシュされ、各 Environment は +独自のデータベース、アイデンティティ、監査ログを持ちます。Cookie は +ホスト名ごとにスコープされるため、セッションがテナント間で漏れることは +ありません。 + +**Q: ObjectOS はサーバーレス / Lambda 環境で実行できますか?** +A: ランタイムは長時間稼働する Node プロセスであり、ステートレスな関数では +なくコンテナや VM 向けに設計されています。カーネルキャッシュと Better Auth +のセッションモデルはいずれも、プロセス内のウォームな状態に依存します。 + +**Q: 水平方向にスケールしますか?** +A: はい。複数のインスタンスをロードバランサーの背後で実行してください。 +セッションはデータベース(インメモリではない)に保存されるため、どの +インスタンスでも任意のリクエストを処理できます。共有のレート制限やキューを +有効にする場合は Redis を使用してください。 + +## データとマイグレーション + +**Q: スキーマのマイグレーションはどのように扱われますか?** +A: ドライバは起動時に、宣言したオブジェクトに合わせてデータベース +スキーマを同期します。Postgres の場合、`CREATE TABLE` / `ALTER TABLE` +ステートメントになります。規制された環境で制御されたマイグレーションを +行う場合は、`OS_SKIP_SCHEMA_SYNC=1` を設定し、DDL を自分で管理してください。 + +**Q: フィールド名を変更するとデータはどうなりますか?** +A: 名前の変更はデータ層では破壊的な変更です(「古い列を削除し、新しい列を +追加する」ように見えます)。`os diff` でこれを検出し、マイグレーションの +ステップを追加してください(新しいアーティファクトをデプロイする前に DB で +列名を変更します)。 + +**Q: CSV / Excel / Salesforce からデータをインポートできますか?** +A: CSV: はい、ループ内での `os data create` または Console の一括アップロードで +可能です。Salesforce: 現時点で最善の方法は CSV にエクスポートしてから +インポートすることです。ネイティブコネクタはロードマップにあります。 + +**Q: ObjectOS をアップグレードするとデータが失われますか?** +A: いいえ。パッチおよびマイナーアップグレードは非破壊的です。メジャー +アップグレード(例: 4 → 5)では必要なマイグレーションが明示的に文書化されます。 +まずバックアップを取得してください。[バックアップと DR](/docs/operate/backup)。 + +## 権限とマルチテナンシー + +**Q: 行レベルのセキュリティはどう実装しますか?** +A: 共有ルール(Salesforce のような宣言的なもの)、またはオブジェクトの +`recordAccess` 設定における CEL の述語を宣言してください。セキュリティ +プラグインがすべてのクエリに対応するフィルタを注入します。 +[権限](/docs/configure/permissions)を参照してください。 + +**Q: 特定のユーザーには一部のフィールドを非表示にできますか?** +A: はい。権限セットでのフィールドレベルセキュリティです。権限セットごと、 +フィールドごとに非表示または読み取り専用にできます。REST、ObjectQL、 +Console 全体で一様に適用されます。 +[権限セット](/docs/configure/permissions/permission-sets)を参照してください。 + +**Q: Okta / Entra / Keycloak とどう統合しますか?** +A: OIDC です。**Console → Authentication**(または env 経由)で +ディスカバリ URL とクライアント id / secret を設定してください。プロバイダの +コールバック URL は `/api/v1/auth/oauth2/callback/` です。 +[認証](/docs/configure/authentication)を参照してください。 + +## 連携 + +**Q: Webhook を送信できますか?** +A: はい。`requires` で `webhooks` を有効にしてください。ObjectOS は +HMAC-SHA256 署名付きの永続的な outbox を使用します。 +[Webhooks](/docs/configure/webhooks)を参照してください。 + +**Q: Zapier / Make / n8n と統合できますか?** +A: はい。アウトバウンドには Webhook、インバウンドには REST API + API キーを +使用します。人気の iPaaS ツール向けのネイティブコネクタはロードマップに +あります。 + +**Q: AI エージェントは私の ObjectOS を呼び出せますか?** +A: はい、MCP(`@objectstack/plugin-mcp-server`)経由で可能です。オブジェクトや +アクションを MCP ツールとして公開し、Claude Desktop、IDE、その他の MCP +クライアントが利用できます。[AI Service](/docs/configure/ai)を参照してください。 + +## カスタマイズ + +**Q: カスタムプラグインを書けますか?** +A: はい。プラグインはシンプルな DI + ライフサイクルパターン +(`init → start → destroy`)に従います。例については GitHub 上の +`@objectstack/plugin-*` パッケージを参照してください。 + +**Q: Console の見た目をカスタマイズできますか?** +A: ブランディング(ロゴ、アクセントカラー、デフォルトテーマ)は +**Console → System Settings** にあります。より高度な UI カスタマイズには、 +`@objectstack/client-react` をフォークするか、REST API に対して独自の +フロントエンドを構築する必要があります。 + +**Q: 英語以外の言語を追加できますか?** +A: はい。i18n はファーストクラスでサポートされています。`os i18n extract` / +`os i18n check` を使用し、翻訳バンドルを同梱してください。 + +## 運用 + +**Q: 推奨される本番デプロイ構成は?** +A: Docker(マルチポッドの場合は Kubernetes)+ マネージド Postgres + +ファイル用の S3 または R2 + `OS_AUTH_SECRET` 用のシークレットマネージャです。 +[本番環境への準備](/docs/operate/production)を参照してください。 + +**Q: ObjectOS にステータスページはありますか?** +A: セルフホスト型のデプロイでは、ステータスはあなたの責任です。`/health` を +監視ツールに接続してください。ホスト型サービスについては +[status.objectstack.ai](https://status.objectstack.ai) を参照してください。 + +**Q: どのメトリクスを監視すべきですか?** +A: 5xx 率、p95 レイテンシ、認証失敗率、カーネルキャッシュのミス率、 +キューの深さです。最小限の Prometheus の例は +[Observability](/docs/operate/observability)にあります。 + +**Q: バックアップはどう取得しますか?** +A: **データベース**と**ストレージバケット**をバックアップしてください。 +それらにすべての顧客データが保持されています。ObjectOS 自体はステートレスです。 +[バックアップ](/docs/operate/backup)を参照してください。 + +## 料金と法務 + +**Q: ObjectOS は本当に無料ですか?** +A: はい。Apache-2.0 です。シート課金も使用量ティアもライセンスサーバーも +ありません。 + +**Q: 販売する商用製品に ObjectOS を使えますか?** +A: はい。Apache-2.0 は商用利用を許可しています。 +[ライセンス](/docs/resources/license)を参照してください。 + +**Q: テレメトリを収集しますか?** +A: いいえ。あなたが設定しない限り、アウトバウンド通信は一切ありません +(OIDC、メール、AI、Webhook)。 +[セキュリティとコンプライアンス](/docs/reference/security#data-residency)を参照してください。 + +**Q: ObjectOS は SOC 2 / ISO 27001 / HIPAA / GDPR に準拠していますか?** +A: ObjectOS は、あらゆるフレームワークが必要とする**プリミティブ**(RBAC、 +監査、暗号化対応、データレジデンシー)を提供します。認証はバイナリではなく +あなたの**デプロイ**の属性です。多くの ObjectOS デプロイが認証を取得しています。 +[セキュリティとコンプライアンス](/docs/reference/security#compliance-frameworks)を参照してください。 + +## 行き詰まったときは + +**Q: 何かが壊れている、まず何をすべき?** +A: `os doctor` です。これだけで設定ミスの 80% を捕捉します。その後は +[トラブルシューティング](/docs/operate/troubleshooting)へ。 + +**Q: バグはどこに報告しますか?** +A: [GitHub Issues](https://github.com/objectstack-ai/objectos/issues) です。 +`os doctor` の出力を含めてください。セキュリティの問題は +**security@objectstack.ai** へ。 + +**Q: 人によるサポートはどこで受けられますか?** +A: [GitHub Discussions](https://github.com/objectstack-ai/objectos/discussions)、 +コミュニティの Discord、または商用サポートについては **sales@objectstack.ai** +へ。 diff --git a/content/docs/resources/faq.cn.mdx b/content/docs/resources/faq.zh-Hans.mdx similarity index 100% rename from content/docs/resources/faq.cn.mdx rename to content/docs/resources/faq.zh-Hans.mdx diff --git a/content/docs/resources/glossary.de.mdx b/content/docs/resources/glossary.de.mdx new file mode 100644 index 0000000..d75edfe --- /dev/null +++ b/content/docs/resources/glossary.de.mdx @@ -0,0 +1,230 @@ +--- +title: Glossar +description: Das in ObjectOS und ObjectStack verwendete Vokabular — jeweils eine Definition. +--- + +# Glossar + +Eine einzige kanonische Definition für jeden in dieser Dokumentation verwendeten Begriff. + +### Artifact + +Eine kompilierte `objectstack.json`-Datei. Eine in sich geschlossene, unveränderliche +Beschreibung einer App — Manifest, Objekte, Views, Apps, Flows, +Berechtigungen, Übersetzungen. Erzeugt durch `os compile`. Das, was +ObjectOS tatsächlich ausführt. + +### Action + +Ein in den Metadaten deklarierter, benannter Vorgang, der über REST +(`/api/v1/data//actions/`), Console-Schaltflächen oder Flow-Schritte +aufgerufen werden kann. Erbt die Berechtigungen des Aufrufers. + +### Adapter + +Ein Framework-Paket, das ObjectStack mit einer Host-Laufzeitumgebung integriert — +Express, Fastify, Hono, Next.js, Nuxt, SvelteKit, NestJS. Die meisten +ObjectOS-Deployments benötigen keinen; ObjectOS bringt seinen eigenen HTTP- +Server mit. + +### App + +Ein Bündel aus Objekten + Views + Berechtigungen, das als eine einzige +navigierbare Anwendung in der Console dargestellt wird. Mehrere Apps können in einer +Laufzeitumgebung koexistieren (z. B. CRM + Helpdesk + Setup). + +### Better Auth + +Die Auth-Bibliothek, die `@objectstack/plugin-auth` antreibt. Du konfigurierst +Better Auth nicht direkt; das Plugin kapselt es. + +### Capability + +Ein optionales Laufzeit-Feature, das ein Artifact in seiner `requires`-Liste +deklariert. Wird einem Paket zugeordnet — z. B. `audit` → `@objectstack/plugin-audit`. +Bei Bedarf von ObjectOS geladen. Siehe +[Runtime Capabilities](/docs/reference/runtime-capabilities). + +### CEL + +[Common Expression Language](https://github.com/google/cel-spec) — +Googles sichere, isolierte Ausdruckssyntax. Wird in Formeln, +Validierungsregeln, Berechtigungsprädikaten, Sharing-Regeln und Flow- +Bedingungen verwendet. + +### Console + +Die System-UI unter `/_console/` — verwaltet Benutzer, Rollen, Permission Sets, +Audit-Log, Sessions, API-Schlüssel, Systemeinstellungen. Unterscheidet sich von der Console +(Business-UI). + +### Control Plane + +Ein optionaler Dienst, der versionierte Artifacts an ObjectOS-Instanzen +veröffentlicht. Wird als ObjectStack Cloud gehostet oder selbst betrieben. Die meisten +Deployments benötigen keine — der dateibasierte Modus funktioniert für die +produktive Bereitstellung einer einzelnen App. + +### Driver + +Eine Implementierung eines Daten-Backends: `driver-sql` (Postgres, MySQL, SQLite, +Turso/libSQL), `driver-mongodb`, `driver-memory`. Wird beim Start anhand +der Datenbank-URL ausgewählt. + +### Embedder + +Der Dienst, der Text für RAG / semantische Suche in Vektoren umwandelt. +Über verschiedene Anbieter hinweg austauschbar (OpenAI, Azure, 硅基流动, Ollama, …). +Siehe [AI Service](/docs/configure/ai). + +### Environment + +Eine mandantenspezifische Laufzeitinstanz, die von ihrer eigenen Datenbank und Identität +gestützt wird. In v4.x manchmal *Project* genannt (Alias beibehalten). v5.0 standardisiert auf +*Environment* in CLI, HTTP, Umgebungsvariablen und Schemas. + +### Field + +Eine typisierte Eigenschaft eines Objects. ~25 eingebaute Typen: `text`, `select`, +`lookup`, `markdown`, `attachment`, `formula`, `rollup` usw. Siehe +[Data Model](/docs/build/data-model). + +### Flow + +Deklarative Geschäftslogik — automatisch gestartet (Datensatz-Trigger), geplant +(Cron) oder manuell (Schaltfläche / API). Wird als DAG mit +Bedingungs-/Schleifen-/Wiederholungs-/Parallel-Primitiven ausgeführt. Siehe +[Flows & Automation](/docs/build/flows). + +### Formula field + +Ein berechnetes Feld, dessen Wert ein CEL-Ausdruck ist, der beim Lesen +ausgewertet wird. Nicht gespeichert. + +### Hook + +Eine Funktion, die in den Objektlebenszyklus eingefügt wird (`beforeInsert`, +`afterUpdate`, …). In TypeScript geschrieben. Anders als ein Flow: +Hooks sind erstklassiger Code; Flows sind Metadaten. + +### Kernel + +Der Mikrokernel innerhalb von ObjectOS, der Plugins lädt, den DI- +Container hält, Events verteilt und die Metadaten eines einzelnen Environments +bereitstellt. Ein Prozess kann viele zwischengespeicherte Kernels (einen pro +Environment) in einem LRU halten. + +### Manifest + +Die Metadaten auf oberster Ebene am Kopf eines Artifacts: `id`, `namespace`, +`version`, `type` (`app` / `plugin` / `service`), `name`, +`description`, `requires`-Liste. + +### Marketplace + +Der in der Console integrierte Katalog installierbarer Apps. Gestützt durch eine konfigurierbare +Paket-Registry. Siehe [Marketplace](/docs/build/marketplace). + +### MCP (Model Context Protocol) + +Ein offenes Protokoll, mit dem KI-Agenten Werkzeuge entdecken und aufrufen können. +ObjectOS kann seine Objekte + Actions über +`@objectstack/plugin-mcp-server` als MCP bereitstellen. + +### Object + +Eine typisierte Geschäftsentität — `task`, `account`, `invoice`. Wird als +TypeScript-Schema deklariert; erzeugt automatisch REST-APIs, Console-Views, Audit-Einträge, +RBAC-Prüfpunkte. Siehe [Data Model](/docs/build/data-model). + +### ObjectOS + +Die Laufzeitumgebung — ein einzelner Node.js-Prozess, der deine Apps bereitstellt. Open +Source, Apache-2.0. **Diese Dokumentationsseite ist für ObjectOS.** + +### ObjectQL + +Das Datenschicht-Protokoll und die Query-Engine. Kompiliert deklarative Abfragen +in native SQL-/Mongo-Abfragen. Wird von REST-Endpunkten, Console, +Flows verwendet — alles dieselbe Engine. + +### ObjectStack + +Das übergeordnete Projekt: das Framework (`@objectstack/*` npm-Pakete), +die Laufzeitumgebung (ObjectOS), der optionale Cloud-Dienst und der +marketplace. Manchmal auch „die Plattform“ genannt. + +### ObjectUI + +Das View-Schicht-Protokoll — Apps, Views, Seiten, Dashboards, Actions, +Diagramme, Navigation. Die Console rendert ObjectUI-Deklarationen. + +### Permission Set + +Ein Bündel aus Berechtigungen — Objektberechtigungen, Feldberechtigungen, Systemberechtigungen. +Wird Benutzern direkt oder über Rollen zugewiesen. Die primäre +Autorisierungseinheit. Siehe [Permissions](/docs/configure/permissions). + +### Plugin + +Ein Framework-Paket, das die Laufzeitumgebung um eine Capability erweitert — +`plugin-auth`, `plugin-security`, `plugin-audit`, `plugin-webhooks`, +`plugin-mcp-server` usw. Wird über DI + Lifecycle-Hooks aktiviert +(`init → start → destroy`). + +### Project + +Alter Name für **Environment**. Wird in v4.x noch in CLI/Umgebung verwendet (als Alias). +In v5.0 entfernt. + +### Record Share + +Eine direkte Zugriffsgewährung auf einen bestimmten Datensatz für einen bestimmten Benutzer / +eine bestimmte Rolle / Gruppe. Gespeichert als `sys_record_share`-Zeilen. Unterscheidet sich von +Sharing-Regeln (deklarative Kriterien). + +### Sharing Rule + +Eine deklarative Regel, die den Datensatzzugriff anhand von Kriterien gewährt +(„regionale Manager können Datensätze in ihrer Region sehen“). Wird zur +Abfragezeit ausgewertet und in Zeilenebene-Filter kompiliert. + +### Console + +Die Business-UI unter `/_console/` — Datensätze durchsuchen, erstellen, bearbeiten, +Views konfigurieren, Apps aus dem marketplace installieren. Unterscheidet sich von der Console (System-UI). + +### Surface + +Einer der vier HTTP-Einstiegspunkte, die ein laufendes ObjectOS bereitstellt: +`/` (REST API), `/_console/`, `/_account/`, `/_console/`. + +### System Context + +Der interne Ausführungsmodus, der von Plugins, Hooks und Seed-Skripten +verwendet wird, die Sicherheitsprüfungen umgehen müssen. Auditierbar; nicht für +Benutzercode zugänglich. + +### Tenant + +Eine logische Isolationsgrenze in Multi-Tenant-Deployments. Ein Tenant +entspricht typischerweise einem Environment. Cookies und Sessions sind pro +Hostname gescoped; Daten sind pro Environment gescoped. + +### Trigger + +Die Bedingung, die einen Flow auslöst — Datensatzereignis (`after_insert`), +Zeitplan (Cron) oder manueller Aufruf. + +### View + +Eine deklarative UI-Konfiguration — Liste, Formular, Kanban, Kalender, Gantt — +die an ein Object angehängt ist. Die Console rendert sie; du schreibst die +Komponente nicht. + +### Zod schema + +Das Laufzeit- und Compile-Zeit-Typsystem, das von `@objectstack/spec` verwendet wird. +Jedes Objekt, Feld, jede View, App und jeder Flow wird durch ein Zod- +Schema geparst und validiert. JSON Schema, TypeScript-Typen und REST-Request-Validatoren +werden alle aus denselben Zod-Definitionen abgeleitet. diff --git a/content/docs/resources/glossary.es.mdx b/content/docs/resources/glossary.es.mdx new file mode 100644 index 0000000..4ad9630 --- /dev/null +++ b/content/docs/resources/glossary.es.mdx @@ -0,0 +1,233 @@ +--- +title: Glosario +description: El vocabulario utilizado en ObjectOS y ObjectStack — una definición para cada término. +--- + +# Glosario + +Una única definición canónica para cada término utilizado en esta documentación. + +### Artifact + +Un archivo `objectstack.json` compilado. Una descripción autónoma e +inmutable de una aplicación — manifiesto, objetos, vistas, apps, flujos, +permisos, traducciones. Producido por `os compile`. Lo que ObjectOS +realmente ejecuta. + +### Action + +Una operación con nombre declarada en los metadatos, invocable mediante REST +(`/api/v1/data//actions/`), botones de Console o pasos de +flujo. Hereda los permisos de quien la invoca. + +### Adapter + +Un paquete del framework que integra ObjectStack con un runtime anfitrión — +Express, Fastify, Hono, Next.js, Nuxt, SvelteKit, NestJS. La mayoría de los +despliegues de ObjectOS no necesitan uno; ObjectOS incluye su propio +servidor HTTP. + +### App + +Un conjunto de objetos + vistas + permisos presentado como una única +aplicación navegable en Console. Múltiples apps pueden coexistir en un mismo +runtime (p. ej. CRM + Helpdesk + Setup). + +### Better Auth + +La biblioteca de autenticación que impulsa `@objectstack/plugin-auth`. No +configuras Better Auth directamente; el plugin lo encapsula. + +### Capability + +Una funcionalidad opcional del runtime declarada por un artifact en su lista +`requires`. Se corresponde con un paquete — p. ej. `audit` → +`@objectstack/plugin-audit`. ObjectOS la carga bajo demanda. Consulta +[Runtime Capabilities](/docs/reference/runtime-capabilities). + +### CEL + +[Common Expression Language](https://github.com/google/cel-spec) — +la sintaxis de expresiones segura y aislada de Google. Se usa en fórmulas, +reglas de validación, predicados de permisos, reglas de compartición y +condiciones de flujo. + +### Console + +La interfaz del sistema en `/_console/` — gestiona usuarios, roles, conjuntos +de permisos, registro de auditoría, sesiones, claves de API y ajustes del +sistema. Distinta de Console (interfaz de negocio). + +### Control Plane + +Un servicio opcional que publica artifacts versionados en instancias de +ObjectOS. Alojado como ObjectStack Cloud o autohospedado. La mayoría de los +despliegues no necesitan uno — el modo basado en archivos funciona para +producción de una sola app. + +### Driver + +Una implementación de backend de datos: `driver-sql` (Postgres, MySQL, +SQLite, Turso/libSQL), `driver-mongodb`, `driver-memory`. Se elige al +arrancar mediante la URL de la base de datos. + +### Embedder + +El servicio que convierte texto en vectores para RAG / búsqueda semántica. +Conectable entre proveedores (OpenAI, Azure, 硅基流动, Ollama, …). +Consulta [AI Service](/docs/configure/ai). + +### Environment + +Una instancia de runtime por tenant respaldada por su propia base de datos e +identidad. En la v4.x a veces se le llamaba *Project* (se mantiene el alias). +La v5.0 estandariza *Environment* en CLI, HTTP, variables de entorno y +esquemas. + +### Field + +Una propiedad tipada en un Object. ~25 tipos integrados: `text`, `select`, +`lookup`, `markdown`, `attachment`, `formula`, `rollup`, etc. Consulta +[Data Model](/docs/build/data-model). + +### Flow + +Lógica de negocio declarativa — autolanzada (disparador de registro), +programada (cron) o manual (botón / API). Se ejecuta como un DAG con +primitivas de condición/bucle/reintento/paralelismo. Consulta +[Flows & Automation](/docs/build/flows). + +### Formula field + +Un campo calculado cuyo valor es una expresión CEL evaluada en el momento de +la lectura. No se almacena. + +### Hook + +Una función inyectada en el ciclo de vida del objeto (`beforeInsert`, +`afterUpdate`, …). Escrita en TypeScript. Diferente de un flujo: los hooks +son código de primera clase; los flujos son metadatos. + +### Kernel + +El microkernel dentro de ObjectOS que carga plugins, mantiene el contenedor +de DI, despacha eventos y sirve los metadatos de un único Environment. Un +proceso puede mantener muchos kernels en caché (uno por Environment) en una +LRU. + +### Manifest + +Los metadatos de nivel superior al inicio de un artifact: `id`, `namespace`, +`version`, `type` (`app` / `plugin` / `service`), `name`, +`description`, lista `requires`. + +### Marketplace + +El catálogo dentro de Console de apps instalables. Respaldado por un registro +de paquetes configurable. Consulta [Marketplace](/docs/build/marketplace). + +### MCP (Model Context Protocol) + +Un protocolo abierto para que los agentes de IA descubran e invoquen +herramientas. ObjectOS puede exponer sus objetos + acciones como MCP mediante +`@objectstack/plugin-mcp-server`. + +### Object + +Una entidad de negocio tipada — `task`, `account`, `invoice`. Declarada como +un esquema de TypeScript; genera APIs REST, vistas de Console, entradas de +auditoría y puntos de control de RBAC automáticamente. Consulta [Data Model](/docs/build/data-model). + +### ObjectOS + +El runtime — un único proceso de Node.js que sirve tus apps. De código +abierto, Apache-2.0. **Este sitio de documentación es para ObjectOS.** + +### ObjectQL + +El protocolo de la capa de datos y el motor de consultas. Compila consultas +declarativas a consultas nativas de SQL / Mongo. Usado por los endpoints +REST, Console y flujos — todos el mismo motor. + +### ObjectStack + +El proyecto paraguas: el framework (paquetes npm `@objectstack/*`), el +runtime (ObjectOS), el servicio en la nube opcional y el marketplace. A veces +llamado "la plataforma". + +### ObjectUI + +El protocolo de la capa de vistas — apps, vistas, páginas, paneles, acciones, +gráficos, navegación. Console renderiza las declaraciones de ObjectUI. + +### Permission Set + +Un conjunto de concesiones — permisos de objeto, permisos de campo, permisos +del sistema. Se asocia a los usuarios directamente o mediante roles. La +unidad principal de autorización. Consulta [Permissions](/docs/configure/permissions). + +### Plugin + +Un paquete del framework que extiende el runtime con una capability — +`plugin-auth`, `plugin-security`, `plugin-audit`, `plugin-webhooks`, +`plugin-mcp-server`, etc. Activado mediante DI + hooks de ciclo de vida +(`init → start → destroy`). + +### Project + +Antiguo nombre de **Environment**. Todavía se usa en la CLI/entorno de la +v4.x (con alias). Eliminado en la v5.0. + +### Record Share + +Una concesión directa de acceso a un registro específico para un usuario / +rol / grupo específico. Almacenada como filas `sys_record_share`. Diferente +de las reglas de compartición (criterios declarativos). + +### Sharing Rule + +Una regla declarativa que concede acceso a registros según criterios ("los +gerentes regionales pueden ver los registros de su región"). Evaluada en el +momento de la consulta, compilada en filtros a nivel de fila. + +### Console + +La interfaz de negocio en `/_console/` — explora, crea y edita registros, +configura vistas e instala apps desde el marketplace. Distinta de Console +(interfaz del sistema). + +### Surface + +Uno de los cuatro puntos de entrada HTTP que expone un ObjectOS en ejecución: +`/` (REST API), `/_console/`, `/_account/`, `/_console/`. + +### System Context + +El modo de ejecución interno usado por plugins, hooks y scripts de inicialización +que necesitan omitir las comprobaciones de seguridad. Auditable; no expuesto +al código de usuario. + +### Tenant + +Un límite de aislamiento lógico en despliegues multi-tenant. Un tenant +normalmente se corresponde con un Environment. Las cookies y sesiones tienen +alcance por nombre de host; los datos tienen alcance por Environment. + +### Trigger + +La condición que dispara un flujo — evento de registro (`after_insert`), +programación (cron) o invocación manual. + +### View + +Una configuración de UI declarativa — lista, formulario, kanban, calendario, +gantt — asociada a un Object. Console la renderiza; tú no escribes el +componente. + +### Zod schema + +El sistema de tipos en runtime + tiempo de compilación usado por +`@objectstack/spec`. Cada objeto, campo, vista, app y flujo es analizado y +validado por un esquema de Zod. JSON Schema, los tipos de TypeScript y los +validadores de peticiones REST se derivan todos de las mismas definiciones de +Zod. diff --git a/content/docs/resources/glossary.fr.mdx b/content/docs/resources/glossary.fr.mdx new file mode 100644 index 0000000..9668765 --- /dev/null +++ b/content/docs/resources/glossary.fr.mdx @@ -0,0 +1,231 @@ +--- +title: Glossaire +description: Le vocabulaire utilisé dans ObjectOS et ObjectStack — une définition pour chaque terme. +--- + +# Glossaire + +Une définition canonique unique pour chaque terme utilisé dans cette documentation. + +### Artifact + +Un fichier `objectstack.json` compilé. Description autonome et immuable +d'une application — manifeste, objets, vues, applications, flux, +permissions, traductions. Produit par `os compile`. C'est ce +qu'ObjectOS exécute réellement. + +### Action + +Une opération nommée déclarée dans les métadonnées, invocable via REST +(`/api/v1/data//actions/`), des boutons de Console ou des étapes +de flux. Hérite des permissions de l'appelant. + +### Adapter + +Un package du framework qui intègre ObjectStack à un runtime hôte — +Express, Fastify, Hono, Next.js, Nuxt, SvelteKit, NestJS. La plupart +des déploiements ObjectOS n'en ont pas besoin ; ObjectOS embarque son propre +serveur HTTP. + +### App + +Un ensemble d'objets + vues + permissions présenté comme une application +unique navigable dans Console. Plusieurs applications peuvent coexister dans un +même runtime (par exemple CRM + Helpdesk + Setup). + +### Better Auth + +La bibliothèque d'authentification qui alimente `@objectstack/plugin-auth`. Vous ne +configurez pas Better Auth directement ; le plugin l'encapsule. + +### Capability + +Une fonctionnalité runtime optionnelle déclarée par un artifact dans sa liste +`requires`. Correspond à un package — par exemple `audit` → `@objectstack/plugin-audit`. +Chargée à la demande par ObjectOS. Voir +[Runtime Capabilities](/docs/reference/runtime-capabilities). + +### CEL + +[Common Expression Language](https://github.com/google/cel-spec) — +la syntaxe d'expression sûre et sandboxée de Google. Utilisée dans les formules, +les règles de validation, les prédicats de permission, les règles de partage et les +conditions de flux. + +### Console + +L'interface système accessible à `/_console/` — gère les utilisateurs, les rôles, les ensembles de permissions, +le journal d'audit, les sessions, les clés API et les paramètres système. Distincte de Console +(interface métier). + +### Control Plane + +Un service optionnel qui publie des artifacts versionnés vers des instances +ObjectOS. Hébergé en tant qu'ObjectStack Cloud ou auto-hébergé. La plupart des +déploiements n'en ont pas besoin — le mode basé sur fichiers fonctionne pour une +production mono-application. + +### Driver + +Une implémentation de backend de données : `driver-sql` (Postgres, MySQL, SQLite, +Turso/libSQL), `driver-mongodb`, `driver-memory`. Choisi au démarrage via +l'URL de la base de données. + +### Embedder + +Le service qui convertit le texte en vecteurs pour le RAG / la recherche sémantique. +Interchangeable entre fournisseurs (OpenAI, Azure, 硅基流动, Ollama, …). +Voir [AI Service](/docs/configure/ai). + +### Environment + +Une instance runtime par tenant, adossée à sa propre base de données et identité. +Sur la v4.x, parfois appelée *Project* (alias conservé). La v5.0 standardise sur +*Environment* dans la CLI, le HTTP, les variables d'environnement et les schémas. + +### Field + +Une propriété typée sur un Object. ~25 types intégrés : `text`, `select`, +`lookup`, `markdown`, `attachment`, `formula`, `rollup`, etc. Voir +[Data Model](/docs/build/data-model). + +### Flow + +Logique métier déclarative — déclenchée automatiquement (déclencheur d'enregistrement), planifiée +(cron) ou manuelle (bouton / API). S'exécute sous forme de DAG avec des +primitives condition/boucle/réessai/parallèle. Voir +[Flows & Automation](/docs/build/flows). + +### Formula field + +Un champ calculé dont la valeur est une expression CEL évaluée au moment de +la lecture. Non stockée. + +### Hook + +Une fonction injectée dans le cycle de vie de l'objet (`beforeInsert`, +`afterUpdate`, …). Écrite en TypeScript. Différent d'un flux : +les hooks sont du code de première classe ; les flux sont des métadonnées. + +### Kernel + +Le micronoyau au cœur d'ObjectOS qui charge les plugins, contient le conteneur +DI, distribue les événements et sert les métadonnées d'un unique Environment. +Un processus peut contenir de nombreux kernels en cache (un par +Environment) dans un LRU. + +### Manifest + +Les métadonnées de plus haut niveau en tête d'un artifact : `id`, `namespace`, +`version`, `type` (`app` / `plugin` / `service`), `name`, +`description`, liste `requires`. + +### Marketplace + +Le catalogue dans Console des applications installables. Adossé à un registre de +packages configurable. Voir [Marketplace](/docs/build/marketplace). + +### MCP (Model Context Protocol) + +Un protocole ouvert permettant aux agents IA de découvrir et d'appeler des outils. +ObjectOS peut exposer ses objets + actions en tant que MCP via +`@objectstack/plugin-mcp-server`. + +### Object + +Une entité métier typée — `task`, `account`, `invoice`. Déclarée sous forme de +schéma TypeScript ; génère automatiquement les API REST, les vues de Console, les entrées +d'audit et les points de contrôle RBAC. Voir [Data Model](/docs/build/data-model). + +### ObjectOS + +Le runtime — un processus Node.js unique qui sert vos applications. Open +source, Apache-2.0. **Ce site de documentation est dédié à ObjectOS.** + +### ObjectQL + +Le protocole de la couche de données et le moteur de requêtes. Compile les requêtes +déclaratives en requêtes SQL / Mongo natives. Utilisé par les endpoints REST, Console, +les flux — tous le même moteur. + +### ObjectStack + +Le projet parapluie : le framework (packages npm `@objectstack/*`), +le runtime (ObjectOS), le service cloud optionnel et le +marketplace. Parfois appelé « la plateforme ». + +### ObjectUI + +Le protocole de la couche de présentation — applications, vues, pages, tableaux de bord, actions, +graphiques, navigation. Console rend les déclarations ObjectUI. + +### Permission Set + +Un ensemble d'attributions — permissions d'objet, permissions de champ, permissions +système. Rattaché directement aux utilisateurs ou via des rôles. L'unité d'autorisation +principale. Voir [Permissions](/docs/configure/permissions). + +### Plugin + +Un package du framework qui étend le runtime avec une capability — +`plugin-auth`, `plugin-security`, `plugin-audit`, `plugin-webhooks`, +`plugin-mcp-server`, etc. Activé via DI + hooks de cycle de vie +(`init → start → destroy`). + +### Project + +Ancien nom d'**Environment**. Toujours utilisé dans la CLI/env de la v4.x (alias). +Supprimé en v5.0. + +### Record Share + +Une attribution directe d'accès à un enregistrement spécifique pour un utilisateur / +rôle / groupe spécifique. Stockée sous forme de lignes `sys_record_share`. Différente des +règles de partage (critères déclaratifs). + +### Sharing Rule + +Une règle déclarative qui accorde l'accès aux enregistrements selon des critères +(« les responsables régionaux peuvent voir les enregistrements de leur région »). Évaluée au +moment de la requête, compilée en filtres au niveau des lignes. + +### Console + +L'interface métier accessible à `/_console/` — parcourir, créer, modifier des enregistrements, +configurer des vues, installer des applications depuis le marketplace. Distincte de Console +(interface système). + +### Surface + +L'un des quatre points d'entrée HTTP qu'expose un ObjectOS en cours d'exécution : +`/` (API REST), `/_console/`, `/_account/`, `/_console/`. + +### System Context + +Le mode d'exécution interne utilisé par les plugins, les hooks et les scripts de seed +qui doivent contourner les contrôles de sécurité. Auditable ; non exposé au code +utilisateur. + +### Tenant + +Une frontière d'isolation logique dans les déploiements multi-tenant. Un tenant +correspond généralement à un Environment. Les cookies et les sessions sont délimités par +nom d'hôte ; les données sont délimitées par Environment. + +### Trigger + +La condition qui déclenche un flux — événement d'enregistrement (`after_insert`), +planification (cron) ou invocation manuelle. + +### View + +Une configuration d'interface déclarative — liste, formulaire, kanban, calendrier, gantt — +rattachée à un Object. Console la rend ; vous n'écrivez pas le +composant. + +### Zod schema + +Le système de types runtime + compile-time utilisé par `@objectstack/spec`. +Chaque objet, champ, vue, application et flux est analysé et validé par un schéma +Zod. Les schémas JSON, les types TypeScript et les validateurs de requêtes REST sont +tous dérivés des mêmes définitions Zod. diff --git a/content/docs/resources/glossary.ja.mdx b/content/docs/resources/glossary.ja.mdx new file mode 100644 index 0000000..09fe4ac --- /dev/null +++ b/content/docs/resources/glossary.ja.mdx @@ -0,0 +1,156 @@ +--- +title: 用語集 +description: ObjectOS と ObjectStack 全体で使われる用語 — 各用語につき定義は1つ。 +--- + +# 用語集 + +このドキュメントで使われる各用語について、唯一の正式な定義を示します。 + +### Artifact + +コンパイル済みの `objectstack.json` ファイル。アプリの自己完結型かつ不変な記述で、マニフェスト、オブジェクト、ビュー、アプリ、フロー、権限、翻訳を含みます。`os compile` によって生成されます。ObjectOS が実際に実行する対象です。 + +### Action + +メタデータで宣言される名前付き操作で、REST(`/api/v1/data//actions/`)、Console のボタン、またはフローのステップから呼び出せます。呼び出し元の権限を継承します。 + +### Adapter + +ObjectStack をホストランタイムと統合するフレームワークパッケージ — Express、Fastify、Hono、Next.js、Nuxt、SvelteKit、NestJS。ほとんどの ObjectOS デプロイメントでは不要です。ObjectOS は独自の HTTP サーバーを内蔵しています。 + +### App + +オブジェクト + ビュー + 権限をまとめたもので、Console 上で単一のナビゲート可能なアプリケーションとして提供されます。複数のアプリを1つのランタイムに共存させることができます(例: CRM + Helpdesk + Setup)。 + +### Better Auth + +`@objectstack/plugin-auth` を支える認証ライブラリ。Better Auth を直接設定することはありません。プラグインがそれをラップします。 + +### Capability + +Artifact が `requires` リスト内で宣言する、オプションのランタイム機能。パッケージにマッピングされます — 例: `audit` → `@objectstack/plugin-audit`。ObjectOS によってオンデマンドで読み込まれます。[Runtime Capabilities](/docs/reference/runtime-capabilities) を参照してください。 + +### CEL + +[Common Expression Language](https://github.com/google/cel-spec) — Google による安全でサンドボックス化された式構文。数式、検証ルール、権限述語、共有ルール、フロー条件で使われます。 + +### Console + +`/_console/` にあるシステム UI — ユーザー、ロール、権限セット、監査ログ、セッション、API キー、システム設定を管理します。Console(ビジネス UI)とは区別されます。 + +### Control Plane + +バージョン管理された Artifact を ObjectOS インスタンスに公開するオプションのサービス。ObjectStack Cloud としてホストするか、セルフホストします。ほとんどのデプロイメントでは不要です — ファイルベースモードは単一アプリの本番環境で機能します。 + +### Driver + +データバックエンドの実装: `driver-sql`(Postgres、MySQL、SQLite、Turso/libSQL)、`driver-mongodb`、`driver-memory`。データベース URL を介して起動時に選択されます。 + +### Embedder + +RAG / セマンティック検索のためにテキストをベクトルに変換するサービス。プロバイダー間で差し替え可能です(OpenAI、Azure、硅基流动、Ollama、…)。[AI Service](/docs/configure/ai) を参照してください。 + +### Environment + +独自のデータベースとアイデンティティに裏付けられた、テナントごとのランタイムインスタンス。v4.x では *Project* と呼ばれることがあります(エイリアスは維持)。v5.0 では CLI、HTTP、環境変数、スキーマ全体で *Environment* に標準化されています。 + +### Field + +Object 上の型付きプロパティ。約25種類の組み込み型: `text`、`select`、`lookup`、`markdown`、`attachment`、`formula`、`rollup` など。[Data Model](/docs/build/data-model) を参照してください。 + +### Flow + +宣言的なビジネスロジック — 自動起動(レコードトリガー)、スケジュール(cron)、または手動(ボタン / API)。condition/loop/retry/parallel プリミティブを備えた DAG として実行されます。[Flows & Automation](/docs/build/flows) を参照してください。 + +### Formula field + +値が CEL 式で、読み取り時に評価される計算フィールド。保存されません。 + +### Hook + +オブジェクトのライフサイクル(`beforeInsert`、`afterUpdate`、…)に注入される関数。TypeScript で記述されます。フローとは異なります: フックはファーストクラスのコードで、フローはメタデータです。 + +### Kernel + +ObjectOS 内部のマイクロカーネルで、プラグインを読み込み、DI コンテナを保持し、イベントをディスパッチし、単一の Environment のメタデータを提供します。1つのプロセスは多数のキャッシュされたカーネル(Environment ごとに1つ)を LRU で保持できます。 + +### Manifest + +Artifact の先頭にあるトップレベルのメタデータ: `id`、`namespace`、`version`、`type`(`app` / `plugin` / `service`)、`name`、`description`、`requires` リスト。 + +### Marketplace + +インストール可能なアプリの Console 内カタログ。設定可能なパッケージレジストリに裏付けられています。[Marketplace](/docs/build/marketplace) を参照してください。 + +### MCP (Model Context Protocol) + +AI エージェントがツールを検出して呼び出すためのオープンプロトコル。ObjectOS は `@objectstack/plugin-mcp-server` を介して、オブジェクト + アクションを MCP として公開できます。 + +### Object + +型付きのビジネスエンティティ — `task`、`account`、`invoice`。TypeScript スキーマとして宣言され、REST API、Console ビュー、監査エントリ、RBAC チェックポイントを自動的に生成します。[Data Model](/docs/build/data-model) を参照してください。 + +### ObjectOS + +ランタイム — アプリを提供する単一の Node.js プロセス。オープンソース、Apache-2.0。**このドキュメントサイトは ObjectOS 向けです。** + +### ObjectQL + +データレイヤープロトコルおよびクエリエンジン。宣言的クエリをネイティブの SQL / Mongo クエリにコンパイルします。REST エンドポイント、Console、フローで使われます — すべて同じエンジンです。 + +### ObjectStack + +全体を包括するプロジェクト: フレームワーク(`@objectstack/*` npm パッケージ)、ランタイム(ObjectOS)、オプションのクラウドサービス、そして marketplace。「プラットフォーム」と呼ばれることもあります。 + +### ObjectUI + +ビューレイヤープロトコル — アプリ、ビュー、ページ、ダッシュボード、アクション、チャート、ナビゲーション。Console は ObjectUI 宣言をレンダリングします。 + +### Permission Set + +付与のまとまり — オブジェクト権限、フィールド権限、システム権限。ユーザーに直接、またはロールを介してアタッチされます。主要な認可単位です。[Permissions](/docs/configure/permissions) を参照してください。 + +### Plugin + +ランタイムをある機能で拡張するフレームワークパッケージ — `plugin-auth`、`plugin-security`、`plugin-audit`、`plugin-webhooks`、`plugin-mcp-server` など。DI + ライフサイクルフック(`init → start → destroy`)を介して有効化されます。 + +### Project + +**Environment** の旧名称。v4.x の CLI/環境変数では今も使われています(エイリアス)。v5.0 で削除されました。 + +### Record Share + +特定のユーザー / ロール / グループに対して、特定のレコードへのアクセスを直接付与するもの。`sys_record_share` の行として保存されます。共有ルール(宣言的な条件)とは異なります。 + +### Sharing Rule + +条件に基づいてレコードアクセスを付与する宣言的なルール(「地域マネージャーは自分の地域のレコードを参照できる」)。クエリ時に評価され、行レベルのフィルターにコンパイルされます。 + +### Console + +`/_console/` にあるビジネス UI — レコードの参照、作成、編集、ビューの設定、marketplace からのアプリのインストール。Console(システム UI)とは区別されます。 + +### Surface + +実行中の ObjectOS が公開する4つの HTTP エントリポイントの1つ: `/`(REST API)、`/_console/`、`/_account/`、`/_console/`。 + +### System Context + +セキュリティチェックをバイパスする必要があるプラグイン、フック、シードスクリプトが使う内部実行モード。監査可能で、ユーザーコードには公開されません。 + +### Tenant + +マルチテナントデプロイメントにおける論理的な分離境界。1つのテナントは通常1つの Environment にマッピングされます。Cookie とセッションはホスト名ごとにスコープされ、データは Environment ごとにスコープされます。 + +### Trigger + +フローを起動する条件 — レコードイベント(`after_insert`)、スケジュール(cron)、または手動呼び出し。 + +### View + +Object にアタッチされる宣言的な UI 設定 — リスト、フォーム、カンバン、カレンダー、ガント。Console がレンダリングし、コンポーネントを記述する必要はありません。 + +### Zod schema + +`@objectstack/spec` が使うランタイム + コンパイル時の型システム。すべてのオブジェクト、フィールド、ビュー、アプリ、フローは Zod スキーマによってパースおよび検証されます。JSON Schema、TypeScript 型、REST リクエストバリデーターはすべて同じ Zod 定義から派生します。 diff --git a/content/docs/resources/glossary.cn.mdx b/content/docs/resources/glossary.zh-Hans.mdx similarity index 100% rename from content/docs/resources/glossary.cn.mdx rename to content/docs/resources/glossary.zh-Hans.mdx diff --git a/content/docs/resources/license.de.mdx b/content/docs/resources/license.de.mdx new file mode 100644 index 0000000..3f17100 --- /dev/null +++ b/content/docs/resources/license.de.mdx @@ -0,0 +1,101 @@ +--- +title: Lizenz +description: ObjectOS-Lizenzierung — Apache-2.0, kommerzielle Optionen und FAQ. +--- + +# Lizenz + +## ObjectOS-Runtime — Apache-2.0 + +Die ObjectOS-Runtime und alle Open-Source-Pakete `@objectstack/*` sind +unter der [Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0) lizenziert. + +In einfachen Worten: + +| Sie dürfen | Sie müssen | +|---|---| +| Es in kommerziellen Produkten verwenden | Die Dateien LICENSE und NOTICE bei der Weiterverteilung beilegen | +| Es ändern, ohne die Änderungen zu teilen | Geänderte Dateien als geändert kennzeichnen | +| Es in proprietäre Software einbetten | ObjectStack-Marken nicht ohne Erlaubnis verwenden | +| Es zu jedem Zweck und überall ausführen | — | +| Es als Teil eines größeren Werks unterlizenzieren | — | + +Es gibt **kein Copyleft**. Änderungen, die Sie für den internen Gebrauch +vornehmen oder die Sie in einem Closed-Source-Produkt ausliefern, müssen +**nicht** zurückgegeben werden. Die Apache-2.0-Lizenz enthält außerdem +eine **ausdrückliche Patentlizenz** von den Mitwirkenden — wichtig für +die rechtliche Prüfung in Unternehmen. + +Volltext: [LICENSE](https://github.com/objectstack-ai/framework/blob/main/LICENSE) + +## Was unter Apache-2.0 enthalten ist + +| | Lizenz | +|---|---| +| ObjectOS-Runtime-Image | Apache-2.0 | +| Alle npm-Pakete `@objectstack/*` (Runtime, Plugins, Services, Treiber, Adapter, CLI, Client-SDKs) | Apache-2.0 | +| Templates-Repository (`objectstack-ai/templates`) | Apache-2.0 | +| Console- und Account-UIs | Apache-2.0 | +| Dokumentation | CC-BY-4.0 | + +## Wann eine kommerzielle Vereinbarung sinnvoll sein kann + +Apache-2.0 deckt die meisten Anwendungsfälle ab. Eine kommerzielle +Vereinbarung kann dennoch sinnvoll sein, wenn: + +| Szenario | Was wir anbieten | +|---|---| +| Sie **Support mit SLAs** benötigen | Kommerzieller Support | +| Sie möchten, dass wir es **für Sie hosten** | Managed Cloud (ObjectStack Cloud) | +| Sie **OEM-Rechte** wünschen (ObjectStack-Marken verwenden, es als Ihr eigenes Produkt kennzeichnen) | OEM-Vereinbarung | +| Sie eine **Gewährleistung / Freistellung** wünschen | Kommerzielle Vereinbarung (Apache-2.0 schließt Gewährleistung aus) | +| Sie **regulatorische Nachweise** benötigen (SOC-2-Bericht, ISO-Zertifikat des Runtime-Images) | Enterprise-Tier | + +Kontaktieren Sie **sales@objectstack.ai**, um darüber zu sprechen. + +## Preise für die Open-Source-Runtime + +**Kostenlos.** Für immer. Keine Plätze, keine Nutzungsstufe, kein Lizenzserver, kein Schlüssel. + +Führen Sie es aus auf: +- Ihrem Laptop +- Ihren Servern +- Den Servern Ihrer Kunden +- Einem Raspberry Pi +- Einem Kubernetes-Cluster mit 1000 Pods + +Die Lizenz ist in jedem Fall dieselbe. + +## Komponenten von Drittanbietern + +ObjectOS hängt von mehreren vorgelagerten Open-Source-Projekten ab (Node.js, +Hono, Zod, Better Auth, AI SDK, …). Jedes wird mit seiner eigenen Lizenz +ausgeliefert — allesamt entweder Apache-2.0, MIT oder permissive Lizenzen +im BSD-Stil, die mit kommerzieller Nutzung kompatibel sind. Die vollständige +Inventarliste finden Sie in der SBOM, die mit jedem Release veröffentlicht wird. + +## FAQ + +**F: Kann ich ObjectOS in einer Closed-Source-SaaS verwenden, die ich an meine Kunden verkaufe?** +A: Ja. Apache-2.0 hat kein Copyleft. Sie müssen Ihren Code nicht teilen. + +**F: Kann ich ObjectOS ändern und meine Änderungen nicht teilen?** +A: Ja. Apache-2.0 verlangt nicht, dass Sie Änderungen teilen. + +**F: Kann ich Console als Teil meines Produkts umbenennen (Rebranding)?** +A: Die UI selbst, ja. Die Verwendung des Namens oder Logos „ObjectStack", +um Ihr Produkt zu bewerben, erfordert eine OEM-Vereinbarung — kontaktieren Sie den Vertrieb. + +**F: Schulde ich Ihnen etwas, wenn mein Produkt Geld einbringt?** +A: Nein. Es gibt keine Lizenzgebühren oder Umsatzbeteiligung. + +**F: Sendet ObjectOS Nutzungsdaten nach Hause („phone home")?** +A: Nein. Es gibt keine Telemetrie, keine Lizenzprüfung, keinen Update-Ping. +Siehe [Security & Compliance](/docs/reference/security#data-residency). + +**F: Was, wenn ich eine vertragliche Gewährleistung möchte?** +A: Apache-2.0 schließt Gewährleistung aus. Erwerben Sie eine kommerzielle +Vereinbarung, und wir stellen eine bereit. + +**F: Wird die Open-Source-Version immer kostenlos sein?** +A: Ja. Apache-2.0-Lizenzen sind unwiderruflich. diff --git a/content/docs/resources/license.es.mdx b/content/docs/resources/license.es.mdx new file mode 100644 index 0000000..6a33910 --- /dev/null +++ b/content/docs/resources/license.es.mdx @@ -0,0 +1,101 @@ +--- +title: Licencia +description: Licencias de ObjectOS — Apache-2.0, opciones comerciales y preguntas frecuentes. +--- + +# Licencia + +## Runtime de ObjectOS — Apache-2.0 + +El runtime de ObjectOS y todos los paquetes de código abierto `@objectstack/*` están +licenciados bajo la [Licencia Apache, Versión 2.0](https://www.apache.org/licenses/LICENSE-2.0). + +En lenguaje sencillo: + +| Puedes | Debes | +|---|---| +| Usarlo en productos comerciales | Incluir los archivos LICENSE y NOTICE cuando lo redistribuyas | +| Modificarlo sin compartir los cambios | Marcar los archivos modificados como modificados | +| Integrarlo en software propietario | No usar las marcas registradas de ObjectStack sin permiso | +| Ejecutarlo para cualquier propósito, en cualquier lugar | — | +| Sublicenciarlo como parte de una obra mayor | — | + +No hay **copyleft**. Las modificaciones que hagas para uso interno, o +que distribuyas en un producto de código cerrado, **no** tienen que ser +aportadas de vuelta. La licencia Apache-2.0 también incluye una **concesión +expresa de patentes** por parte de los contribuyentes — algo importante para la +revisión legal empresarial. + +Texto completo: [LICENSE](https://github.com/objectstack-ai/framework/blob/main/LICENSE) + +## Qué está incluido bajo Apache-2.0 + +| | Licencia | +|---|---| +| Imagen del runtime de ObjectOS | Apache-2.0 | +| Todos los paquetes npm `@objectstack/*` (runtime, plugins, servicios, drivers, adaptadores, CLI, SDKs de cliente) | Apache-2.0 | +| Repositorio de plantillas (`objectstack-ai/templates`) | Apache-2.0 | +| Interfaces de Console y Account | Apache-2.0 | +| Documentación | CC-BY-4.0 | + +## Cuándo podrías querer un acuerdo comercial + +Apache-2.0 cubre la mayoría de los casos de uso. Aun así podrías querer un acuerdo +comercial cuando: + +| Escenario | Lo que ofrecemos | +|---|---| +| Necesitas **soporte con SLAs** | Soporte comercial | +| Quieres que lo **alojemos por ti** | Nube gestionada (ObjectStack Cloud) | +| Quieres **derechos OEM** (usar las marcas de ObjectStack, presentarlo como propio) | Acuerdo OEM | +| Quieres una **garantía / indemnización** | Acuerdo comercial (Apache-2.0 renuncia a la garantía) | +| Necesitas **certificaciones regulatorias** (informe SOC 2, certificado ISO de la imagen del runtime) | Nivel Enterprise | + +Contacta con **sales@objectstack.ai** para hablarlo. + +## Precio del runtime de código abierto + +**Gratis.** Para siempre. Sin asientos, sin niveles de uso, sin servidor de licencias, sin clave. + +Ejecútalo en: +- Tu portátil +- Tus servidores +- Los servidores de tus clientes +- Una Raspberry Pi +- Un clúster de Kubernetes de 1000 pods + +La licencia es la misma en todos los casos. + +## Componentes de terceros + +ObjectOS depende de varios proyectos de código abierto upstream (Node.js, +Hono, Zod, Better Auth, AI SDK, …). Cada uno se distribuye con su propia licencia — +todas las cuales son Apache-2.0, MIT o licencias permisivas de estilo BSD +compatibles con el uso comercial. Consulta el SBOM publicado con +cada versión para ver el inventario completo. + +## Preguntas frecuentes + +**P: ¿Puedo usar ObjectOS en un SaaS de código cerrado que vendo a mis clientes?** +R: Sí. Apache-2.0 no tiene copyleft. No necesitas compartir tu código. + +**P: ¿Puedo modificar ObjectOS y no compartir mis cambios?** +R: Sí. Apache-2.0 no te obliga a compartir las modificaciones. + +**P: ¿Puedo cambiar la marca de Console como parte de mi producto?** +R: La interfaz en sí, sí. Usar el nombre o el logo de "ObjectStack" para promocionar +tu producto requiere un acuerdo OEM — contacta con ventas. + +**P: ¿Te debo algo si mi producto genera dinero?** +R: No. No hay regalías ni reparto de ingresos. + +**P: ¿ObjectOS envía datos de uso a casa (phone home)?** +R: No. No hay telemetría, ni comprobación de licencia, ni ping de actualización. +Consulta [Security & Compliance](/docs/reference/security#data-residency). + +**P: ¿Y si quiero una garantía contractual?** +R: Apache-2.0 renuncia a la garantía. Compra un acuerdo comercial y te +proporcionamos una. + +**P: ¿La versión de código abierto será siempre gratuita?** +R: Sí. Las concesiones de Apache-2.0 son irrevocables. diff --git a/content/docs/resources/license.fr.mdx b/content/docs/resources/license.fr.mdx new file mode 100644 index 0000000..81b4074 --- /dev/null +++ b/content/docs/resources/license.fr.mdx @@ -0,0 +1,101 @@ +--- +title: Licence +description: Licence ObjectOS — Apache-2.0, options commerciales et FAQ. +--- + +# Licence + +## Runtime ObjectOS — Apache-2.0 + +Le runtime ObjectOS et tous les paquets open source `@objectstack/*` sont +distribués sous la [licence Apache, version 2.0](https://www.apache.org/licenses/LICENSE-2.0). + +En termes simples : + +| Vous pouvez | Vous devez | +|---|---| +| L'utiliser dans des produits commerciaux | Inclure les fichiers LICENSE et NOTICE lorsque vous le redistribuez | +| Le modifier sans partager vos modifications | Indiquer les fichiers modifiés comme tels | +| L'intégrer dans un logiciel propriétaire | Ne pas utiliser les marques ObjectStack sans autorisation | +| L'exécuter à n'importe quelle fin, n'importe où | — | +| Le sous-licencier dans le cadre d'une œuvre plus large | — | + +Il n'y a **aucun copyleft**. Les modifications que vous apportez pour un +usage interne, ou que vous livrez dans un produit à code source fermé, +n'ont **pas** à être reversées. La licence Apache-2.0 inclut également une +**concession expresse de brevet** de la part des contributeurs — un point +important pour les revues juridiques en entreprise. + +Texte intégral : [LICENSE](https://github.com/objectstack-ai/framework/blob/main/LICENSE) + +## Ce qui est couvert par Apache-2.0 + +| | Licence | +|---|---| +| Image du runtime ObjectOS | Apache-2.0 | +| Tous les paquets npm `@objectstack/*` (runtime, plugins, services, drivers, adaptateurs, CLI, SDK clients) | Apache-2.0 | +| Dépôt de templates (`objectstack-ai/templates`) | Apache-2.0 | +| Interfaces Console et Account | Apache-2.0 | +| Documentation | CC-BY-4.0 | + +## Quand un accord commercial peut être souhaitable + +Apache-2.0 couvre la plupart des cas d'usage. Vous pouvez néanmoins +souhaiter un accord commercial lorsque : + +| Scénario | Ce que nous proposons | +|---|---| +| Vous avez besoin d'un **support avec SLA** | Support commercial | +| Vous voulez que nous l'**hébergions pour vous** | Cloud managé (ObjectStack Cloud) | +| Vous voulez des **droits OEM** (utiliser les marques ObjectStack, le commercialiser sous votre propre nom) | Accord OEM | +| Vous voulez une **garantie / indemnisation** | Accord commercial (Apache-2.0 exclut toute garantie) | +| Vous avez besoin d'**attestations réglementaires** (rapport SOC 2, certificat ISO de l'image du runtime) | Offre Enterprise | + +Contactez **sales@objectstack.ai** pour en discuter. + +## Tarification du runtime open source + +**Gratuit.** Pour toujours. Pas de sièges, pas de palier d'utilisation, +pas de serveur de licences, pas de clé. + +Exécutez-le sur : +- Votre ordinateur portable +- Vos serveurs +- Les serveurs de vos clients +- Un Raspberry Pi +- Un cluster Kubernetes de 1000 pods + +La licence est la même dans tous les cas. + +## Composants tiers + +ObjectOS dépend de plusieurs projets open source en amont (Node.js, +Hono, Zod, Better Auth, AI SDK, …). Chacun est fourni avec sa propre +licence — toutes étant des licences permissives de type Apache-2.0, MIT +ou BSD, compatibles avec un usage commercial. Consultez le SBOM publié +avec chaque version pour l'inventaire complet. + +## FAQ + +**Q : Puis-je utiliser ObjectOS dans un SaaS à code source fermé que je vends à mes clients ?** +R : Oui. Apache-2.0 n'a aucun copyleft. Vous n'avez pas besoin de partager votre code. + +**Q : Puis-je modifier ObjectOS sans partager mes modifications ?** +R : Oui. Apache-2.0 ne vous oblige pas à partager vos modifications. + +**Q : Puis-je rebrander Console dans le cadre de mon produit ?** +R : L'interface elle-même, oui. Utiliser le nom ou le logo « ObjectStack » +pour promouvoir votre produit nécessite un accord OEM — contactez le service commercial. + +**Q : Vous dois-je quelque chose si mon produit génère des revenus ?** +R : Non. Il n'y a aucune redevance ni partage de revenus. + +**Q : ObjectOS envoie-t-il des données d'utilisation à distance ?** +R : Non. Il n'y a aucune télémétrie, aucune vérification de licence, aucun ping de mise à jour. +Voir [Sécurité et conformité](/docs/reference/security#data-residency). + +**Q : Et si je veux une garantie contractuelle ?** +R : Apache-2.0 exclut toute garantie. Souscrivez un accord commercial et nous vous en fournissons une. + +**Q : La version open source restera-t-elle toujours gratuite ?** +R : Oui. Les concessions Apache-2.0 sont irrévocables. diff --git a/content/docs/resources/license.ja.mdx b/content/docs/resources/license.ja.mdx new file mode 100644 index 0000000..860ec61 --- /dev/null +++ b/content/docs/resources/license.ja.mdx @@ -0,0 +1,99 @@ +--- +title: ライセンス +description: ObjectOS のライセンス — Apache-2.0、商用オプション、FAQ。 +--- + +# ライセンス + +## ObjectOS ランタイム — Apache-2.0 + +ObjectOS ランタイムおよびすべての `@objectstack/*` オープンソースパッケージは、 +[Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0) の下でライセンスされています。 + +平易に言うと: + +| できること | しなければならないこと | +|---|---| +| 商用製品で利用する | 再配布する際に LICENSE ファイルと NOTICE ファイルを含める | +| 変更内容を共有せずに改変する | 改変したファイルに変更済みである旨を明記する | +| プロプライエタリなソフトウェアに組み込む | 許可なく ObjectStack の商標を使用しない | +| 目的を問わず、どこででも実行する | — | +| より大きな成果物の一部としてサブライセンスする | — | + +**コピーレフトはありません**。社内利用のために加えた変更や、クローズドソース製品に +組み込んで出荷する変更を、貢献として還元する必要は **ありません**。Apache-2.0 +ライセンスには、コントリビューターからの **明示的な特許許諾** も含まれており、 +これはエンタープライズの法務レビューにおいて重要です。 + +全文: [LICENSE](https://github.com/objectstack-ai/framework/blob/main/LICENSE) + +## Apache-2.0 に含まれるもの + +| | ライセンス | +|---|---| +| ObjectOS ランタイムイメージ | Apache-2.0 | +| すべての `@objectstack/*` npm パッケージ(ランタイム、プラグイン、サービス、ドライバー、アダプター、CLI、クライアント SDK) | Apache-2.0 | +| テンプレートリポジトリ(`objectstack-ai/templates`) | Apache-2.0 | +| Console と Account の UI | Apache-2.0 | +| ドキュメント | CC-BY-4.0 | + +## 商用契約を検討したくなる場合 + +Apache-2.0 はほとんどのユースケースをカバーします。それでも、以下の場合には +商用契約をご検討いただくとよいでしょう: + +| シナリオ | 当社が提供するもの | +|---|---| +| **SLA 付きのサポート** が必要 | 商用サポート | +| **当社によるホスティング** を希望する | マネージドクラウド(ObjectStack Cloud) | +| **OEM 権利**(ObjectStack の商標を使用し、自社製品としてブランディングする)を希望する | OEM 契約 | +| **保証 / 補償** を希望する | 商用契約(Apache-2.0 は保証を否認しています) | +| **規制上の証明**(SOC 2 レポート、ランタイムイメージの ISO 認証)が必要 | エンタープライズプラン | + +ご相談は **sales@objectstack.ai** までご連絡ください。 + +## オープンソースランタイムの価格 + +**無料。** 永久に。シート課金なし、使用量ティアなし、ライセンスサーバーなし、キーなし。 + +実行できる環境: +- お使いのノートパソコン +- 自社のサーバー +- 顧客のサーバー +- Raspberry Pi +- 1000 ポッドの Kubernetes クラスター + +どの場合でもライセンスは同じです。 + +## サードパーティコンポーネント + +ObjectOS は、いくつかのアップストリームのオープンソースプロジェクト(Node.js、 +Hono、Zod、Better Auth、AI SDK、…)に依存しています。それぞれが独自のライセンスを +伴って提供されており、いずれも Apache-2.0、MIT、または BSD 系の寛容な +ライセンスで、商用利用と互換性があります。完全な一覧については、各リリースとともに +公開される SBOM をご覧ください。 + +## FAQ + +**Q: 顧客に販売するクローズドソースの SaaS で ObjectOS を使えますか?** +A: はい。Apache-2.0 にはコピーレフトがありません。コードを共有する必要はありません。 + +**Q: ObjectOS を改変して、その変更を共有しないことはできますか?** +A: はい。Apache-2.0 は改変内容の共有を求めていません。 + +**Q: 自社製品の一部として Console をリブランドできますか?** +A: UI 自体はできます。自社製品の宣伝のために「ObjectStack」の名称やロゴを +使用する場合は OEM 契約が必要です — sales までご連絡ください。 + +**Q: 製品で利益が出た場合、何か支払う義務はありますか?** +A: いいえ。ロイヤルティや収益分配はありません。 + +**Q: ObjectOS は使用状況データを外部に送信(phone home)しますか?** +A: いいえ。テレメトリも、ライセンスチェックも、アップデートの ping もありません。 +[セキュリティとコンプライアンス](/docs/reference/security#data-residency) をご覧ください。 + +**Q: 契約上の保証が欲しい場合はどうすればよいですか?** +A: Apache-2.0 は保証を否認しています。商用契約をご購入いただければ、当社が保証を提供します。 + +**Q: オープンソース版は常に無料ですか?** +A: はい。Apache-2.0 の許諾は撤回不能です。 diff --git a/content/docs/resources/license.cn.mdx b/content/docs/resources/license.zh-Hans.mdx similarity index 100% rename from content/docs/resources/license.cn.mdx rename to content/docs/resources/license.zh-Hans.mdx diff --git a/content/docs/resources/meta.de.json b/content/docs/resources/meta.de.json new file mode 100644 index 0000000..c65e7e6 --- /dev/null +++ b/content/docs/resources/meta.de.json @@ -0,0 +1,11 @@ +{ + "title": "Ressourcen", + "defaultOpen": false, + "pages": [ + "glossary", + "faq", + "changelog", + "license", + "support" + ] +} diff --git a/content/docs/resources/meta.es.json b/content/docs/resources/meta.es.json new file mode 100644 index 0000000..a5df889 --- /dev/null +++ b/content/docs/resources/meta.es.json @@ -0,0 +1,11 @@ +{ + "title": "Recursos", + "defaultOpen": false, + "pages": [ + "glossary", + "faq", + "changelog", + "license", + "support" + ] +} diff --git a/content/docs/resources/meta.fr.json b/content/docs/resources/meta.fr.json new file mode 100644 index 0000000..e59cba3 --- /dev/null +++ b/content/docs/resources/meta.fr.json @@ -0,0 +1,11 @@ +{ + "title": "Ressources", + "defaultOpen": false, + "pages": [ + "glossary", + "faq", + "changelog", + "license", + "support" + ] +} diff --git a/content/docs/resources/meta.ja.json b/content/docs/resources/meta.ja.json new file mode 100644 index 0000000..53df758 --- /dev/null +++ b/content/docs/resources/meta.ja.json @@ -0,0 +1,11 @@ +{ + "title": "リソース", + "defaultOpen": false, + "pages": [ + "glossary", + "faq", + "changelog", + "license", + "support" + ] +} diff --git a/content/docs/resources/meta.cn.json b/content/docs/resources/meta.zh-Hans.json similarity index 100% rename from content/docs/resources/meta.cn.json rename to content/docs/resources/meta.zh-Hans.json diff --git a/content/docs/resources/support.de.mdx b/content/docs/resources/support.de.mdx new file mode 100644 index 0000000..ded5afb --- /dev/null +++ b/content/docs/resources/support.de.mdx @@ -0,0 +1,78 @@ +--- +title: Support +description: Wo Sie Hilfe erhalten, wie Sie Fehler melden, welche Reaktionszeiten zu erwarten sind. +--- + +# Support + +## Wohin für welches Anliegen + +| Wenn Sie … | Gehen Sie zu | +|---|---| +| Eine „Wie mache ich …"-Frage haben | [GitHub Discussions](https://github.com/objectstack-ai/objectos/discussions) — Community + Maintainer | +| Einen Fehler gefunden haben | [GitHub Issues](https://github.com/objectstack-ai/objectos/issues) — bitte Version, Reproduktion sowie erwartetes vs. tatsächliches Verhalten angeben | +| Eine Sicherheitslücke gefunden haben | **security@objectstack.ai** — **kein** öffentliches Issue eröffnen | +| Kommerziellen Support / ein SLA benötigen | **sales@objectstack.ai** | +| Mit Nutzern + Maintainern chatten möchten | [Discord](https://discord.gg/objectstack) (von der Community betrieben) | +| Releases verfolgen möchten | [github.com/objectstack-ai/objectos](https://github.com/objectstack-ai/objectos) beobachten → Releases | +| Ein kostenpflichtiges Feature umgesetzt haben möchten | Eine Discussion eröffnen → mit `funding` taggen | + +## Einen guten Fehlerbericht erstellen + +Die 30-Sekunden-Variante: + +```text +ObjectOS version: 4.0.4 (or sha-abc123) +Node version: 22.4.0 +Install method: docker / npm -g / source +Database: postgres 16 / sqlite / turso / mongo +Repro steps: 1. ... 2. ... 3. ... +Expected: ... +Actual: ... +Logs: (sanitized, last 30 lines) +``` + +Bei Konfigurationsproblemen fügen Sie die Ausgabe von `os doctor` bei — es +diagnostiziert 80 % der Fehlkonfigurationen ganz von allein. + +## Reaktionszeiten + +| Kanal | Reaktionszeit nach bestem Bemühen | +|---|---| +| Security-E-Mail | 1 Werktag | +| GitHub Issues — Fehler, mit Reproduktion | 3 Werktage für die Triage, Fix mit dem nächsten Release-Zug | +| GitHub Issues — Feature-Anfrage | 7 Werktage für die Triage | +| GitHub Discussions | Community-getrieben; Maintainer melden sich regelmäßig zu Wort | +| Kommerzieller Support | Gemäß Ihrem Supportvertrag | + +Dies erfolgt nach bestem Bemühen und stellt keine SLAs dar. Verträge für +kommerziellen Support enthalten formale SLAs. + +## Kommerzieller Support & Dienstleistungen + +Verfügbar vom ObjectStack-Team: + +- **Kommerzieller Support** mit Reaktionszeit-SLAs. +- **Managed Hosting** — wir betreiben es für Sie. +- **Architektur-Review** — Plausibilitätsprüfung vor dem Deployment. +- **Individuelle Plugins / Funktionen**, gebaut nach Ihren Vorgaben. +- **OEM-Weiterverbreitung** — betten Sie ObjectOS in Ihr Produkt ein. + +Kontakt: **sales@objectstack.ai**. + +## Zurückgeben + +ObjectOS steht unter Apache-2.0 und nimmt Beiträge an: + +- [CONTRIBUTING.md](https://github.com/objectstack-ai/framework/blob/main/CONTRIBUTING.md) +- [Code of Conduct](https://github.com/objectstack-ai/framework/blob/main/CODE_OF_CONDUCT.md) +- Eröffnen Sie früh einen Draft-PR — wir prüfen lieber einen Entwurf, als dass + doppelte Arbeit entsteht. + +## Status & Vorfälle + +Gehostete Dienste (ObjectStack Cloud, Package-Registry): +[status.objectstack.ai](https://status.objectstack.ai). + +Für Ihr selbst gehostetes ObjectOS-Deployment liegt der Status in Ihrer +Verantwortung — binden Sie ihn an Ihr übliches Monitoring an (siehe [Observability](/docs/operate/observability)). diff --git a/content/docs/resources/support.es.mdx b/content/docs/resources/support.es.mdx new file mode 100644 index 0000000..07e623c --- /dev/null +++ b/content/docs/resources/support.es.mdx @@ -0,0 +1,78 @@ +--- +title: Soporte +description: Dónde obtener ayuda, cómo reportar errores y qué esperar en cuanto a respuestas. +--- + +# Soporte + +## A dónde acudir según el caso + +| Si tú … | Acude a | +|---|---| +| Tienes una pregunta del tipo "¿cómo hago…?" | [GitHub Discussions](https://github.com/objectstack-ai/objectos/discussions) — comunidad + mantenedores | +| Encontraste un error | [GitHub Issues](https://github.com/objectstack-ai/objectos/issues) — por favor incluye la versión, los pasos para reproducirlo y lo esperado frente a lo real | +| Encontraste una vulnerabilidad de seguridad | **security@objectstack.ai** — **no** abras un issue público | +| Necesitas soporte comercial / SLA | **sales@objectstack.ai** | +| Quieres charlar con usuarios y mantenedores | [Discord](https://discord.gg/objectstack) (gestionado por la comunidad) | +| Quieres seguir los lanzamientos | Observa [github.com/objectstack-ai/objectos](https://github.com/objectstack-ai/objectos) → Releases | +| Quieres que se implemente una función de pago | Abre una Discussion → etiquétala con `funding` | + +## Cómo redactar un buen reporte de error + +La versión de 30 segundos: + +```text +ObjectOS version: 4.0.4 (or sha-abc123) +Node version: 22.4.0 +Install method: docker / npm -g / source +Database: postgres 16 / sqlite / turso / mongo +Repro steps: 1. ... 2. ... 3. ... +Expected: ... +Actual: ... +Logs: (sanitized, last 30 lines) +``` + +Para problemas de configuración, adjunta la salida de `os doctor` — esto +diagnostica por sí solo el 80 % de las configuraciones incorrectas. + +## Qué esperar en cuanto a respuestas + +| Canal | Tiempo de respuesta estimado (best-effort) | +|---|---| +| Correo de seguridad | 1 día hábil | +| GitHub Issues — error, con pasos para reproducir | 3 días hábiles para la clasificación, corrección en el siguiente tren de lanzamientos | +| GitHub Issues — solicitud de función | 7 días hábiles para la clasificación | +| GitHub Discussions | Impulsado por la comunidad; los mantenedores participan con regularidad | +| Soporte comercial | Según tu contrato de soporte | + +Son tiempos de mejor esfuerzo (best-effort), no SLAs. Los contratos de soporte +comercial incluyen SLAs formales. + +## Soporte y servicios comerciales + +Disponibles a través del equipo de ObjectStack: + +- **Soporte comercial** con SLAs de tiempo de respuesta. +- **Hospedaje gestionado** — lo ejecutamos por ti. +- **Revisión de arquitectura** — verificación de viabilidad previa al despliegue. +- **Plugins / capacidades personalizadas** construidos según tus especificaciones. +- **Redistribución OEM** — integra ObjectOS en tu producto. + +Contacta a **sales@objectstack.ai**. + +## Contribuir de vuelta + +ObjectOS usa la licencia Apache-2.0 y acepta contribuciones: + +- [CONTRIBUTING.md](https://github.com/objectstack-ai/framework/blob/main/CONTRIBUTING.md) +- [Code of Conduct](https://github.com/objectstack-ai/framework/blob/main/CODE_OF_CONDUCT.md) +- Abre un borrador de PR pronto — preferimos revisar un esbozo a que haya + esfuerzo duplicado. + +## Estado e incidentes + +Servicios alojados (ObjectStack Cloud, registro de paquetes): +[status.objectstack.ai](https://status.objectstack.ai). + +Para tu despliegue autoalojado de ObjectOS, el estado es tu responsabilidad — +conéctalo a tu monitoreo habitual (consulta [Observability](/docs/operate/observability)). diff --git a/content/docs/resources/support.fr.mdx b/content/docs/resources/support.fr.mdx new file mode 100644 index 0000000..da92db6 --- /dev/null +++ b/content/docs/resources/support.fr.mdx @@ -0,0 +1,78 @@ +--- +title: Support +description: Où obtenir de l'aide, comment signaler des bugs, attentes en matière de délais de réponse. +--- + +# Support + +## Où aller pour quoi + +| Si vous … | Rendez-vous sur | +|---|---| +| Avez une question « comment faire » | [GitHub Discussions](https://github.com/objectstack-ai/objectos/discussions) — communauté + mainteneurs | +| Avez trouvé un bug | [GitHub Issues](https://github.com/objectstack-ai/objectos/issues) — merci d'indiquer la version, la reproduction, le comportement attendu vs réel | +| Avez trouvé une faille de sécurité | **security@objectstack.ai** — n'ouvrez **pas** une issue publique | +| Avez besoin d'un support commercial / SLA | **sales@objectstack.ai** | +| Souhaitez échanger avec les utilisateurs + mainteneurs | [Discord](https://discord.gg/objectstack) (géré par la communauté) | +| Souhaitez suivre les versions | Surveillez [github.com/objectstack-ai/objectos](https://github.com/objectstack-ai/objectos) → Releases | +| Souhaitez le développement d'une fonctionnalité payante | Ouvrez une Discussion → taguez avec `funding` | + +## Rédiger un bon rapport de bug + +La version en 30 secondes : + +```text +ObjectOS version: 4.0.4 (or sha-abc123) +Node version: 22.4.0 +Install method: docker / npm -g / source +Database: postgres 16 / sqlite / turso / mongo +Repro steps: 1. ... 2. ... 3. ... +Expected: ... +Actual: ... +Logs: (sanitized, last 30 lines) +``` + +Pour les problèmes de configuration, joignez la sortie de `os doctor` — elle +diagnostique à elle seule 80 % des erreurs de configuration. + +## Attentes en matière de réponse + +| Canal | Délai de réponse au mieux | +|---|---| +| E-mail de sécurité | 1 jour ouvré | +| GitHub Issues — bug, avec reproduction | 3 jours ouvrés pour le tri, correction lors de la prochaine vague de versions | +| GitHub Issues — demande de fonctionnalité | 7 jours ouvrés pour le tri | +| GitHub Discussions | Piloté par la communauté ; les mainteneurs interviennent régulièrement | +| Support commercial | Selon votre contrat de support | + +Il s'agit d'engagements au mieux, et non de SLA. Les contrats de support +commercial comportent des SLA formels. + +## Support commercial & services + +Disponibles auprès de l'équipe ObjectStack : + +- **Support commercial** avec des SLA sur les délais de réponse. +- **Hébergement managé** — nous l'exploitons pour vous. +- **Revue d'architecture** — vérification de bon sens avant déploiement. +- **Plugins / capacités sur mesure** développés selon vos spécifications. +- **Redistribution OEM** — intégrez ObjectOS dans votre produit. + +Contactez **sales@objectstack.ai**. + +## Contribuer en retour + +ObjectOS est sous licence Apache-2.0 et accepte les contributions : + +- [CONTRIBUTING.md](https://github.com/objectstack-ai/framework/blob/main/CONTRIBUTING.md) +- [Code of Conduct](https://github.com/objectstack-ai/framework/blob/main/CODE_OF_CONDUCT.md) +- Ouvrez une PR en brouillon tôt — nous préférons relire une ébauche plutôt + que de voir des efforts dupliqués. + +## Statut & incidents + +Services hébergés (ObjectStack Cloud, registre de paquets) : +[status.objectstack.ai](https://status.objectstack.ai). + +Pour votre déploiement ObjectOS auto-hébergé, le statut est de votre ressort — +reliez-le à votre supervision habituelle (voir [Observability](/docs/operate/observability)). diff --git a/content/docs/resources/support.ja.mdx b/content/docs/resources/support.ja.mdx new file mode 100644 index 0000000..40f3aee --- /dev/null +++ b/content/docs/resources/support.ja.mdx @@ -0,0 +1,78 @@ +--- +title: サポート +description: ヘルプの入手先、バグの報告方法、応答時間の目安。 +--- + +# サポート + +## 目的別の問い合わせ先 + +| 状況 | 問い合わせ先 | +|---|---| +| 「どうやって~する」という質問がある | [GitHub Discussions](https://github.com/objectstack-ai/objectos/discussions) — コミュニティ + メンテナー | +| バグを見つけた | [GitHub Issues](https://github.com/objectstack-ai/objectos/issues) — バージョン、再現手順、期待される動作と実際の動作を記載してください | +| セキュリティ脆弱性を見つけた | **security@objectstack.ai** — 公開 issue は**作成しない**でください | +| 商用サポート / SLA が必要 | **sales@objectstack.ai** | +| ユーザーやメンテナーと交流したい | [Discord](https://discord.gg/objectstack)(コミュニティ運営) | +| リリースを追いたい | [github.com/objectstack-ai/objectos](https://github.com/objectstack-ai/objectos) → Releases をウォッチ | +| 有償で機能を実装してほしい | Discussion を作成 → `funding` でタグ付け | + +## 良いバグレポートの書き方 + +30 秒で済むテンプレート: + +```text +ObjectOS version: 4.0.4 (or sha-abc123) +Node version: 22.4.0 +Install method: docker / npm -g / source +Database: postgres 16 / sqlite / turso / mongo +Repro steps: 1. ... 2. ... 3. ... +Expected: ... +Actual: ... +Logs: (sanitized, last 30 lines) +``` + +設定に関する問題の場合は、`os doctor` の出力を添付してください。 +これだけで設定ミスの 80% を診断できます。 + +## 応答時間の目安 + +| チャネル | ベストエフォートの応答時間 | +|---|---| +| セキュリティメール | 1 営業日 | +| GitHub Issues — バグ(再現手順あり) | トリアージまで 3 営業日、次回リリース時に修正 | +| GitHub Issues — 機能リクエスト | トリアージまで 7 営業日 | +| GitHub Discussions | コミュニティ主導。メンテナーも定期的に参加します | +| 商用サポート | サポート契約に準じます | + +これらはベストエフォートであり、SLA ではありません。商用サポート契約には +正式な SLA が付帯します。 + +## 商用サポート & サービス + +ObjectStack チームが提供します: + +- 応答時間 SLA 付きの**商用サポート**。 +- **マネージドホスティング** — 当社が運用を代行します。 +- **アーキテクチャレビュー** — デプロイ前の健全性チェック。 +- ご要望の仕様に合わせて構築する**カスタムプラグイン / 機能**。 +- **OEM 再配布** — ObjectOS を自社製品に組み込めます。 + +お問い合わせは **sales@objectstack.ai** まで。 + +## コントリビューション + +ObjectOS は Apache-2.0 ライセンスであり、コントリビューションを受け付けています: + +- [CONTRIBUTING.md](https://github.com/objectstack-ai/framework/blob/main/CONTRIBUTING.md) +- [Code of Conduct](https://github.com/objectstack-ai/framework/blob/main/CODE_OF_CONDUCT.md) +- 早めにドラフト PR を作成してください。重複した作業をするよりも、 + 下書きをレビューするほうが望ましいです。 + +## ステータス & インシデント + +ホスティングサービス(ObjectStack Cloud、パッケージレジストリ): +[status.objectstack.ai](https://status.objectstack.ai)。 + +セルフホストの ObjectOS デプロイのステータスはご自身で管理してください。 +通常の監視に組み込んでください([Observability](/docs/operate/observability) を参照)。 diff --git a/content/docs/resources/support.cn.mdx b/content/docs/resources/support.zh-Hans.mdx similarity index 100% rename from content/docs/resources/support.cn.mdx rename to content/docs/resources/support.zh-Hans.mdx diff --git a/content/docs/why.de.mdx b/content/docs/why.de.mdx new file mode 100644 index 0000000..33332d8 --- /dev/null +++ b/content/docs/why.de.mdx @@ -0,0 +1,148 @@ +--- +title: Warum ObjectOS +description: Der ehrliche Pitch — wann du es einsetzen solltest, wann nicht und was es anders macht. +--- + +# Warum ObjectOS + +Diese Seite gibt es, damit du nicht in jedem anderen Dokument zwischen +den Zeilen lesen musst, um herauszufinden, ob ObjectOS das Richtige für +dich ist. + +## Die Form der Wette + +ObjectOS geht eine klare Wette ein: **KI schreibt die Metadaten deiner +Anwendung, dir gehört die Runtime, die sie ausführt.** + +Du schreibst Objekte, Felder, Ansichten, Flows und Berechtigungen nicht +Datei für Datei von Hand. Deine Nutzer beschreiben in natürlicher +Sprache im Console-internen [AI Builder](/docs/build/ai-builder), was +sie brauchen; er ruft eine kleine Menge geprüfter Tools auf, stellt jede +Änderung zur menschlichen Freigabe in eine Warteschlange, und das +Ergebnis ist live — REST-Endpunkte, Console-Bildschirme, RBAC, +Audit-Log, alles aus denselben Metadaten generiert. + +Die Runtime liegt in **deiner** VPC, auf **deiner** Datenbank, unter +**deinem** Apache-2.0-Fork. Das Modell kommuniziert mit einer +gesandboxten Metadaten-API, nicht mit deinem Data Warehouse. + +Das ist der ganze Pitch. Der Rest dieser Seite handelt davon, zu wem das +passt und zu wem nicht. + +## Setze ObjectOS ein, wenn du … + +- ein internes Tool, ein Admin-Panel oder eine Back-Office-App brauchst, + **und** +- möchtest, dass die Menschen, die es nutzen (oder die KI-Agenten, die + für sie handeln), es *erweitern* können, ohne ein Ticket einzureichen, + **und** +- die Daten nicht in der Cloud eines anderen ablegen kannst (oder + willst), **und** +- nicht zum zehnten Mal Auth + RBAC + Audit + Datei-Uploads + Jobs + + Webhooks neu bauen willst. + +Typische Szenarien, in denen es passt: + +| Szenario | Warum es funktioniert | +|---|---| +| Ablösung einer Retool-/Appsmith-App, weil im Security Review Datenhoheit zum Thema wurde | ObjectOS läuft in deiner VPC; Daten verlassen sie nie | +| Aufbau eines Compliance-/Risiko-/Vendor-Management-Tools für ein reguliertes Unternehmen | Audit-Log, RBAC, Feldsicherheit und Zeilenisolation sind erstklassig — und jede KI-getriebene Änderung ist selbst ein Audit-Eintrag | +| Bereitstellung einer internen Verwaltung für ein SaaS-Produkt | Ein einziger Node-Prozess, reiht sich neben deinen bestehenden Diensten ein | +| Air-Gapped- oder On-Prem-Deployment für einen Enterprise-Kunden | Erstklassiges Deployment-Ziel, kein Internet-Egress erforderlich (BYO lokales Modell) | +| Mandantenfähiges internes Portal (eine Runtime, viele kleine Apps) | Kernel pro Projekt + LRU-Cache genau dafür entworfen | +| Du möchtest, dass deine Nutzer ihre eigenen Erweiterungen sicher „vibe-coden" | Der AI Builder + die HITL-Freigabe-Warteschlange + das Audit-Log sind der ganze Sinn | + +## Setze ObjectOS nicht ein, wenn du … + +- ein Consumer-Produkt mit hohem Traffic baust → nutze ein + klassisches Web-Framework, du hast mehr Kontrolle. +- eine pixelgenaue, maßgeschneiderte UI für Endnutzer brauchst → die + Console von ObjectOS ist für den Admin-/internen Gebrauch; kombiniere + sie über REST mit deinem eigenen Front-End. +- einen No-Code-Drag-and-Drop-Builder für Nicht-Entwickler und eine + gehostete Cloud willst → nutze Retool, Bubble oder Airtable. ObjectOS + ist code-first, KI-getrieben und self-hosted. +- Echtzeit-Kollaboration beim Editieren (im Figma-Stil) brauchst → das + löst das Realtime-Plugin nicht. + +## Im Vergleich zu dem, was du wahrscheinlich nutzt + +### vs. Retool / Appsmith / Internal + +| | Retool | ObjectOS | +|---|---|---| +| Datenstandort | Ihre Cloud (oder self-hosted in höheren Tarifen) | Dein Netzwerk, immer | +| UI-Builder | Drag-and-drop, sehr ausgefeilt | Metadatengetrieben, generiert; weniger individuell | +| Preismodell | Pro Nutzer, skaliert schmerzhaft | Self-hosted, Apache-2.0 | +| Workflow / Trigger | Ihre Workflow-Engine | Deklarative Flows + Plugins | +| Backend-Logik | Auf ihren Query-Editor beschränkt | Vollständiges TypeScript, gesamtes Node-Ökosystem | +| Am besten für | Schnelle Dashboards auf bestehenden APIs | Apps, denen ihre Daten *gehören* | + +### vs. Supabase / Firebase + +| | Supabase | ObjectOS | +|---|---|---| +| Einrichtungszeit | ~30 Sekunden | ~30 Sekunden | +| Datenbank | Postgres, ihres (Self-Hosting möglich) | Beliebige Postgres / MySQL / SQLite / Turso / Mongo, **deine** | +| Auth | Eingebaut | Eingebaut | +| Generierte APIs | PostgREST | ObjectQL-generiertes REST | +| Admin-UI | Console (einfach) | Console + Account | +| RBAC | Zeilenebene via Postgres RLS | RBAC + Zeilenebene + Feldebene, deklarativ | +| Audit-Log | Selbstgebaut | Erstklassig | +| Vendor-Lock-in | Ihre Auth + ihr Storage + ihr Realtime | Keiner — jede Schicht ist ein Plugin | +| Am besten für | Neue Apps, die ein BaaS wollen | Apps, die die Runtime besitzen müssen | + +### vs. Salesforce / NetSuite / ServiceNow + +| | Salesforce | ObjectOS | +|---|---|---| +| Datenmodell | Objekte + Felder + Beziehungen | Dasselbe | +| Berechtigungen | Profile + Permission Sets + Sharing Rules + FLS | **Dasselbe Vokabular**, deklaratives TypeScript | +| Kosten pro Nutzer | 150–300 $/Nutzer/Monat | 0 $ | +| Anpassung | Apex + Lightning + Flows | TypeScript + Flows | +| Wo es läuft | Ihre Cloud, Punkt | Deine Infrastruktur | +| Zeit bis „es gehört uns" | Monate an Beratungsarbeit | Ein Nachmittag | +| Am besten für | Vertriebsgetriebene Unternehmen, die für das Ökosystem zahlen | Teams, die das Modell ohne die Steuer wollen | + +### vs. selbst bauen (Next.js + Prisma + NextAuth) + +| | DIY | ObjectOS | +|---|---|---| +| Erster REST-Endpunkt | Ein paar Stunden | 60 Sekunden | +| Auth (E-Mail + OAuth + OIDC + Passkey + 2FA) | Wochen | Inbegriffen | +| Admin-UI für jedes Objekt | Pro Objekt bauen | Generiert | +| Audit-Log | Selbstgebaut | Plugin, deklarativ | +| Datei-Upload zu S3 mit Berechtigungen | Selbstgebaut | Plugin | +| Hintergrundjobs + Retries + Dead Letter | Selbstgebaut | Plugin | +| Mandantenfähigkeit | Selbstgebaut (und du machst es zweimal falsch) | Eingebaut | +| Am besten für | Öffentliche App mit maßgeschneiderter UX | Internes Tooling, bei dem Tempo zählt | + +## Die ehrlichen Kompromisse + +- **Weniger UI-Freiheit als Retool.** Die Console wird aus deinen + Metadaten generiert. Du kannst sie mit einem eigenen Front-End + kombinieren (die REST-API ist dieselbe, die die Console nutzt), aber + wenn du eine handgefertigte, pixelgenaue UI brauchst, baue sie selbst + und nutze ObjectOS als Backend. +- **TypeScript-first.** Nicht-Entwickler erstellen Objekte nicht direkt. + Salesforce-Admins sind es gewohnt, sich durch einen UI-Builder zu + klicken; hier ist es `git`. +- **Neuer als Salesforce.** Salesforce hat 25 Jahre dokumentierter + Sonderfälle. Wir haben ein paar hundert. Das Protokoll ist stabil; das + Ökosystem wächst. +- **Apache-2.0.** Nutze es in kommerziellen Produkten, bette es ein, + modifiziere es privat. Keine Copyleft-Überraschungen. Optionaler + kommerzieller Support separat erhältlich. + +## Realitätscheck + +Das kleinste lauffähige ObjectOS-Deployment ist ein einzelnes +`pnpm dev` oder ein einzelner Docker-Container mit SQLite. Das größte +heute im Produktivbetrieb bedient Zehntausende interne Nutzer über +mehrere Regionen hinweg mit Postgres + S3 + Redis. Beide sind dieselbe +Software. + +Beginne mit `npx @objectstack/cli init my-app` und entscheide in 5 +Minuten. Wenn es nichts für dich ist, hast du 5 Minuten verbrannt. + +[**Probiere den Quickstart →**](/docs/quickstart) diff --git a/content/docs/why.es.mdx b/content/docs/why.es.mdx new file mode 100644 index 0000000..78f76a0 --- /dev/null +++ b/content/docs/why.es.mdx @@ -0,0 +1,140 @@ +--- +title: Por qué ObjectOS +description: La propuesta honesta — cuándo deberías usarlo, cuándo no, y qué lo hace diferente. +--- + +# Por qué ObjectOS + +Esta página existe para que no tengas que leer entre líneas de cada +otro documento para averiguar si ObjectOS es adecuado para ti. + +## La forma de la apuesta + +ObjectOS hace una apuesta con una opinión clara: **la IA escribe los +metadatos de tu aplicación, tú eres dueño del runtime que los ejecuta.** + +No escribes a mano objetos, campos, vistas, flujos y permisos +archivo por archivo. Tus usuarios describen lo que necesitan en lenguaje +natural al [AI Builder](/docs/build/ai-builder) integrado en la Console; +este invoca un pequeño conjunto de herramientas auditadas, pone en cola +cada cambio para su aprobación humana, y el resultado está en vivo — +endpoints REST, pantallas de Console, RBAC, registro de auditoría, +todo generado a partir de los mismos metadatos. + +El runtime reside en **tu** VPC, en **tu** base de datos, bajo +**tu** fork con licencia Apache-2.0. El modelo se comunica con una API +de metadatos en sandbox, no con tu data warehouse. + +Esa es toda la propuesta. El resto de esta página trata sobre a quién +le encaja y a quién no. + +## Usa ObjectOS si … + +- necesitas una herramienta interna, panel de administración o aplicación de back-office, **y** +- quieres que las personas que la usan (o los agentes de IA que actúan en su nombre) puedan + *extenderla* sin abrir un ticket, **y** +- no puedes (o no quieres) poner los datos en la nube de otra persona, **y** +- no quieres reconstruir auth + RBAC + auditoría + cargas de archivos + trabajos + + webhooks por décima vez. + +Escenarios comunes donde encaja: + +| Escenario | Por qué funciona | +|---|---| +| Reemplazar una app de Retool / Appsmith porque la soberanía de datos surgió en una revisión de seguridad | ObjectOS se ejecuta en tu VPC; los datos nunca salen | +| Construir una herramienta de cumplimiento / riesgo / gestión de proveedores para un negocio regulado | El registro de auditoría, RBAC, seguridad a nivel de campo y aislamiento a nivel de fila son de primera clase — y cada cambio impulsado por IA es en sí mismo una entrada de auditoría | +| Levantar un administrador interno para un producto SaaS | Un único proceso de Node, encaja junto a tus servicios existentes | +| Despliegue air-gapped u on-premise para un cliente empresarial | Destino de despliegue de primera clase, sin necesidad de salida a internet (BYO modelo local) | +| Portal interno multi-inquilino (un runtime, muchas apps pequeñas) | Kernel por proyecto + caché LRU diseñados para esto | +| Quieres que tus usuarios "vibe-codeen" sus propias extensiones de forma segura | El AI Builder + la cola de aprobación HITL + el registro de auditoría son justamente el punto | + +## No uses ObjectOS si … + +- estás construyendo un producto de consumo de alto tráfico → usa un framework + web tradicional, tendrás más control. +- necesitas una interfaz a medida y perfecta al píxel para usuarios finales → la Console de ObjectOS es + para uso administrativo/interno; combínala con tu propio front-end vía REST. +- quieres un constructor no-code de arrastrar y soltar para no ingenieros y una nube + alojada → usa Retool, Bubble o Airtable. ObjectOS es code-first, impulsado por IA y autoalojado. +- necesitas edición colaborativa en tiempo real (estilo Figma) → no es lo que resuelve el + plugin de realtime. + +## Comparado con lo que probablemente estás usando + +### vs. Retool / Appsmith / Internal + +| | Retool | ObjectOS | +|---|---|---| +| Ubicación de los datos | Su nube (o autoalojado en un nivel superior) | Tu red, siempre | +| Constructor de UI | Arrastrar y soltar, muy pulido | Impulsado por metadatos, generado; menos personalizado | +| Precios | Por usuario, escala de forma dolorosa | Autoalojado, Apache-2.0 | +| Flujo de trabajo / disparadores | Su motor de flujos de trabajo | Flujos declarativos + plugins | +| Lógica de backend | Limitada a su editor de consultas | TypeScript completo, ecosistema completo de Node | +| Mejor para | Dashboards rápidos sobre APIs existentes | Apps que *son dueñas* de sus datos | + +### vs. Supabase / Firebase + +| | Supabase | ObjectOS | +|---|---|---| +| Tiempo de configuración | ~30 segundos | ~30 segundos | +| Base de datos | Postgres, suya (autoalojado posible) | Cualquier Postgres / MySQL / SQLite / Turso / Mongo, **tuya** | +| Auth | Incorporado | Incorporado | +| APIs generadas | PostgREST | REST generado por ObjectQL | +| UI de administración | Console (básica) | Console + Account | +| RBAC | A nivel de fila vía Postgres RLS | RBAC + a nivel de fila + a nivel de campo, declarativo | +| Registro de auditoría | Hazlo tú mismo | De primera clase | +| Dependencia del proveedor | Su auth + su almacenamiento + su realtime | Ninguna — cada capa es un plugin | +| Mejor para | Apps nuevas que quieren un BaaS | Apps que necesitan ser dueñas del runtime | + +### vs. Salesforce / NetSuite / ServiceNow + +| | Salesforce | ObjectOS | +|---|---|---| +| Modelo de datos | Objetos + campos + relaciones | Igual | +| Permisos | Perfil + conjuntos de permisos + reglas de compartición + FLS | **El mismo vocabulario**, TypeScript declarativo | +| Costo por usuario | $150-300/usuario/mes | $0 | +| Personalización | Apex + Lightning + flujos | TypeScript + flujos | +| Dónde se ejecuta | Su nube, punto | Tu infraestructura | +| Tiempo hasta "es nuestro" | Meses de trabajo de consultoría | Una tarde | +| Mejor para | Empresas lideradas por ventas que pagarán por el ecosistema | Equipos que quieren el modelo sin el impuesto | + +### vs. construir lo tuyo propio (Next.js + Prisma + NextAuth) + +| | DIY | ObjectOS | +|---|---|---| +| Primer endpoint REST | Unas horas | 60 segundos | +| Auth (email + OAuth + OIDC + passkey + 2FA) | Semanas | Incluido | +| UI de administración para cada objeto | Construir por objeto | Generada | +| Registro de auditoría | Hazlo tú mismo | Plugin, declarativo | +| Carga de archivos a S3 con permisos | Hazlo tú mismo | Plugin | +| Trabajos en segundo plano + reintentos + dead letter | Hazlo tú mismo | Plugin | +| Multi-inquilino | Hazlo tú mismo (y lo harás mal dos veces) | Incorporado | +| Mejor para | App pública con UX a medida | Tooling interno donde gana la velocidad | + +## Las concesiones honestas + +- **Menos libertad de UI que Retool.** La Console se genera a partir de tus + metadatos. Puedes combinarla con un front-end personalizado (la API REST es + la misma que usa la Console), pero si necesitas una interfaz hecha a mano y + perfecta al píxel, constrúyela tú mismo y usa ObjectOS como backend. +- **TypeScript primero.** Los no ingenieros no escribirán objetos directamente. + Los administradores de Salesforce están acostumbrados a hacer clic en un constructor de UI; aquí, + es `git`. +- **Más nuevo que Salesforce.** Salesforce tiene 25 años de casos límite + documentados. Nosotros tenemos unos cientos. El protocolo es estable; el + ecosistema está creciendo. +- **Apache-2.0.** Úsalo en productos comerciales, incorpóralo, modifícalo + de forma privada. Sin sorpresas de copyleft. Soporte comercial opcional + disponible por separado. + +## Verificación de la realidad + +El despliegue de ObjectOS viable más pequeño es un único `pnpm dev` o un +único contenedor Docker con SQLite. El más grande en producción hoy en día +sirve a decenas de miles de usuarios internos en múltiples regiones con +Postgres + S3 + Redis. Ambos son el mismo software. + +Comienza con `npx @objectstack/cli init my-app` y decide en 5 minutos. +Si no es para ti, habrás gastado 5 minutos. + +[**Prueba el Quickstart →**](/docs/quickstart) diff --git a/content/docs/why.fr.mdx b/content/docs/why.fr.mdx new file mode 100644 index 0000000..7950269 --- /dev/null +++ b/content/docs/why.fr.mdx @@ -0,0 +1,148 @@ +--- +title: Pourquoi ObjectOS +description: L'argumentaire honnête — quand l'utiliser, quand ne pas l'utiliser, et ce qui le rend différent. +--- + +# Pourquoi ObjectOS + +Cette page existe pour que vous n'ayez pas à lire entre les lignes de +chaque autre page de documentation pour déterminer si ObjectOS vous +convient. + +## La nature du pari + +ObjectOS fait un pari assumé : **l'IA écrit les métadonnées de votre +application, vous possédez le runtime qui les exécute.** + +Vous n'écrivez pas à la main les objets, les champs, les vues, les flux +et les permissions fichier par fichier. Vos utilisateurs décrivent ce +dont ils ont besoin en langage naturel à l'[AI Builder](/docs/build/ai-builder) +intégré à la Console ; celui-ci appelle un petit ensemble d'outils +audités, met chaque changement en file d'attente pour approbation +humaine, et le résultat est en production — points de terminaison REST, +écrans de la Console, RBAC, journal d'audit, le tout généré à partir des +mêmes métadonnées. + +Le runtime se trouve dans **votre** VPC, sur **votre** base de données, +sous **votre** fork Apache-2.0. Le modèle dialogue avec une API de +métadonnées en bac à sable, pas avec votre entrepôt de données. + +C'est tout l'argumentaire. Le reste de cette page indique à qui cela +convient et à qui cela ne convient pas. + +## Utilisez ObjectOS si vous … + +- avez besoin d'un outil interne, d'un panneau d'administration ou d'une + application back-office, **et** +- voulez que les personnes qui l'utilisent (ou les agents IA agissant + pour elles) puissent l'*étendre* sans ouvrir de ticket, **et** +- ne pouvez (ou ne voulez) pas placer les données dans le cloud de + quelqu'un d'autre, **et** +- ne voulez pas reconstruire l'authentification + RBAC + audit + envois + de fichiers + jobs + webhooks pour la dixième fois. + +Scénarios courants où cela convient : + +| Scénario | Pourquoi cela fonctionne | +|---|---| +| Remplacer une application Retool / Appsmith parce que la souveraineté des données a été soulevée lors d'une revue de sécurité | ObjectOS s'exécute dans votre VPC ; les données ne sortent jamais | +| Construire un outil de conformité / risque / gestion des fournisseurs pour une entreprise réglementée | Le journal d'audit, le RBAC, la sécurité des champs et l'isolation au niveau des lignes sont natifs — et chaque changement piloté par l'IA est lui-même une entrée d'audit | +| Mettre en place une administration interne pour un produit SaaS | Un seul processus Node, qui s'insère à côté de vos services existants | +| Déploiement air-gapped ou on-prem pour un client grand compte | Cible de déploiement de premier ordre, aucune sortie internet requise (modèle local en BYO) | +| Portail interne multi-locataire (un runtime, plusieurs petites applications) | Kernel par projet + cache LRU conçus pour cela | +| Vous voulez que vos utilisateurs « vibe-codent » leurs propres extensions en toute sécurité | L'AI Builder + la file d'approbation HITL + le journal d'audit en sont tout l'intérêt | + +## N'utilisez pas ObjectOS si vous … + +- construisez un produit grand public à fort trafic → utilisez un + framework web traditionnel, vous aurez plus de contrôle. +- avez besoin d'une interface sur mesure au pixel près pour les + utilisateurs finaux → la Console d'ObjectOS est destinée à un usage + administratif/interne ; associez-la à votre propre front-end via REST. +- voulez un constructeur no-code en glisser-déposer pour les + non-ingénieurs et un cloud hébergé → utilisez Retool, Bubble ou + Airtable. ObjectOS est code-first, piloté par l'IA, auto-hébergé. +- avez besoin d'une édition collaborative en temps réel (à la Figma) → + ce n'est pas ce que résout le plugin temps réel. + +## Comparé à ce que vous utilisez probablement + +### vs. Retool / Appsmith / Internal + +| | Retool | ObjectOS | +|---|---|---| +| Emplacement des données | Leur cloud (ou auto-hébergé sur une offre supérieure) | Votre réseau, toujours | +| Constructeur d'UI | Glisser-déposer, très soigné | Piloté par métadonnées, généré ; moins personnalisable | +| Tarification | Par utilisateur, montée en charge douloureuse | Auto-hébergé, Apache-2.0 | +| Workflow / déclencheurs | Leur moteur de workflow | Flux déclaratifs + plugins | +| Logique back-end | Limitée à leur éditeur de requêtes | TypeScript complet, tout l'écosystème Node | +| Idéal pour | Tableaux de bord rapides au-dessus d'API existantes | Applications qui *possèdent* leurs données | + +### vs. Supabase / Firebase + +| | Supabase | ObjectOS | +|---|---|---| +| Temps de configuration | ~30 secondes | ~30 secondes | +| Base de données | Postgres, la leur (auto-hébergement possible) | N'importe quel Postgres / MySQL / SQLite / Turso / Mongo, **la vôtre** | +| Authentification | Intégrée | Intégrée | +| API générées | PostgREST | REST généré par ObjectQL | +| Interface d'administration | Console (basique) | Console + Account | +| RBAC | Au niveau des lignes via le RLS de Postgres | RBAC + niveau des lignes + niveau des champs, déclaratif | +| Journal d'audit | À faire soi-même | Natif | +| Verrouillage fournisseur | Leur authentification + leur stockage + leur temps réel | Aucun — chaque couche est un plugin | +| Idéal pour | Nouvelles applications voulant un BaaS | Applications qui doivent posséder le runtime | + +### vs. Salesforce / NetSuite / ServiceNow + +| | Salesforce | ObjectOS | +|---|---|---| +| Modèle de données | Objets + champs + relations | Identique | +| Permissions | Profil + jeux de permissions + règles de partage + FLS | **Même vocabulaire**, TypeScript déclaratif | +| Coût par utilisateur | 150-300 $/utilisateur/mois | 0 $ | +| Personnalisation | Apex + Lightning + flux | TypeScript + flux | +| Où il s'exécute | Leur cloud, un point c'est tout | Votre infrastructure | +| Temps avant « on le possède » | Des mois de travail de consultants | Un après-midi | +| Idéal pour | Entreprises orientées ventes prêtes à payer pour l'écosystème | Équipes qui veulent le modèle sans la taxe | + +### vs. tout faire soi-même (Next.js + Prisma + NextAuth) + +| | DIY | ObjectOS | +|---|---|---| +| Premier point de terminaison REST | Quelques heures | 60 secondes | +| Authentification (e-mail + OAuth + OIDC + passkey + 2FA) | Des semaines | Incluse | +| Interface d'administration pour chaque objet | À construire par objet | Générée | +| Journal d'audit | À faire soi-même | Plugin, déclaratif | +| Envoi de fichiers vers S3 avec permissions | À faire soi-même | Plugin | +| Jobs en arrière-plan + relances + dead letter | À faire soi-même | Plugin | +| Multi-location | À faire soi-même (et vous vous tromperez deux fois) | Intégrée | +| Idéal pour | Application destinée au public avec une UX sur mesure | Outillage interne où la vitesse prime | + +## Les compromis honnêtes + +- **Moins de liberté d'UI que Retool.** La Console est générée à partir + de vos métadonnées. Vous pouvez l'associer à un front-end personnalisé + (l'API REST est la même que celle utilisée par la Console), mais si + vous avez besoin d'une interface au pixel près faite à la main, + construisez-la vous-même et utilisez ObjectOS comme back-end. +- **TypeScript d'abord.** Les non-ingénieurs n'écriront pas directement + les objets. Les administrateurs Salesforce ont l'habitude de cliquer + dans un constructeur d'UI ; ici, c'est `git`. +- **Plus récent que Salesforce.** Salesforce documente 25 ans de cas + limites. Nous en avons quelques centaines. Le protocole est stable ; + l'écosystème grandit. +- **Apache-2.0.** Utilisez-le dans des produits commerciaux, intégrez-le, + modifiez-le en privé. Aucune mauvaise surprise de copyleft. Un support + commercial optionnel est disponible séparément. + +## Mise au point + +Le plus petit déploiement viable d'ObjectOS est un simple `pnpm dev` ou +un seul conteneur Docker avec SQLite. Le plus grand en production +aujourd'hui sert des dizaines de milliers d'utilisateurs internes à +travers plusieurs régions avec Postgres + S3 + Redis. Les deux sont le +même logiciel. + +Commencez avec `npx @objectstack/cli init my-app` et décidez en 5 +minutes. Si ce n'est pas pour vous, vous aurez perdu 5 minutes. + +[**Essayer le Quickstart →**](/docs/quickstart) diff --git a/content/docs/why.ja.mdx b/content/docs/why.ja.mdx new file mode 100644 index 0000000..0e22bbe --- /dev/null +++ b/content/docs/why.ja.mdx @@ -0,0 +1,137 @@ +--- +title: なぜ ObjectOS なのか +description: 率直な提案 — いつ使うべきか、いつ使うべきでないか、そして何が違うのか。 +--- + +# なぜ ObjectOS なのか + +このページは、ObjectOS が自分に合っているかどうかを判断するために、 +他のすべてのドキュメントの行間を読まなくて済むように存在しています。 + +## この賭けのかたち + +ObjectOS はひとつの明確な賭けに出ています。**AI があなたのアプリケーションの +メタデータを記述し、あなたはそれを実行するランタイムを所有する。** + +オブジェクト、フィールド、ビュー、フロー、権限をファイルごとに手で書く必要は +ありません。ユーザーは必要なものを Console 内の [AI Builder](/docs/build/ai-builder) に +平易な言葉で説明します。AI Builder は監査済みの小さなツール群を呼び出し、 +すべての変更を人による承認のためにキューに入れ、その結果がそのまま稼働します。 +REST エンドポイント、Console 画面、RBAC、監査ログ — すべてが同じメタデータから +生成されます。 + +ランタイムは **あなたの** VPC 内、**あなたの** データベース上、**あなたの** +Apache-2.0 フォークのもとに置かれます。モデルが対話するのはサンドボックス化された +メタデータ API であり、あなたのデータウェアハウスではありません。 + +これが提案のすべてです。このページの残りは、これが誰に合い、誰に合わないかの話です。 + +## ObjectOS を使うべきなのは、あなたが … + +- 社内ツール、管理パネル、またはバックオフィスアプリを必要としていて、**かつ** +- それを使う人々(またはその人々の代わりに動く AI エージェント)が、チケットを + 起票することなく *拡張* できるようにしたい、**かつ** +- データを他社のクラウドに置けない(または置きたくない)、**かつ** +- 認証 + RBAC + 監査 + ファイルアップロード + ジョブ + Webhook を 10 回目も + 作り直したくない、という場合です。 + +合致する一般的なシナリオ: + +| シナリオ | なぜ機能するのか | +|---|---| +| セキュリティレビューでデータ主権が問題になったため Retool / Appsmith アプリを置き換える | ObjectOS はあなたの VPC 内で動作し、データが外に出ることはない | +| 規制対象ビジネス向けのコンプライアンス / リスク / ベンダー管理ツールを構築する | 監査ログ、RBAC、フィールドセキュリティ、行レベルの分離が標準機能 — しかも AI 主導の変更そのものが監査エントリになる | +| SaaS 製品の社内管理画面を立ち上げる | 単一の Node プロセスで、既存サービスの隣にそのまま組み込める | +| エンタープライズ顧客向けのエアギャップまたはオンプレミス展開 | 第一級の展開ターゲットで、インターネット送信は不要(ローカルモデルを持ち込み) | +| マルチテナント社内ポータル(ひとつのランタイム、多数の小規模アプリ) | プロジェクトごとのカーネル + LRU キャッシュがこのために設計されている | +| ユーザーに自分自身の拡張を安全に「バイブコーディング」させたい | AI Builder + HITL 承認キュー + 監査ログこそが核心 | + +## ObjectOS を使うべきでないのは、あなたが … + +- 高トラフィックのコンシューマー向け製品を構築している場合 → 従来の Web + フレームワークを使ってください。より多くの制御が得られます。 +- エンドユーザー向けにピクセル単位で作り込んだ専用 UI が必要な場合 → ObjectOS の + Console は管理 / 社内用途向けです。REST 経由で独自のフロントエンドと組み合わせてください。 +- 非エンジニア向けのノーコードのドラッグ&ドロップビルダーとホスティングされた + クラウドが欲しい場合 → Retool、Bubble、または Airtable を使ってください。ObjectOS は + コードファーストで AI 主導、セルフホストです。 +- リアルタイムの共同編集(Figma スタイル)が必要な場合 → これは realtime プラグインが + 解決する問題ではありません。 + +## あなたがおそらく使っているものとの比較 + +### vs. Retool / Appsmith / 社内ツール + +| | Retool | ObjectOS | +|---|---|---| +| データの所在 | 同社のクラウド(または上位プランでセルフホスト) | 常にあなたのネットワーク | +| UI ビルダー | ドラッグ&ドロップ、非常に洗練されている | メタデータ駆動で生成、カスタマイズ性は低め | +| 価格 | ユーザー単位で、スケールするほど苦しい | セルフホスト、Apache-2.0 | +| ワークフロー / トリガー | 同社のワークフローエンジン | 宣言的なフロー + プラグイン | +| バックエンドロジック | 同社のクエリエディタに限定 | フル TypeScript、フル Node エコシステム | +| 最適な用途 | 既存 API の上に素早くダッシュボードを作る | データを *所有* するアプリ | + +### vs. Supabase / Firebase + +| | Supabase | ObjectOS | +|---|---|---| +| セットアップ時間 | 約 30 秒 | 約 30 秒 | +| データベース | Postgres、同社のもの(セルフホストも可能) | 任意の Postgres / MySQL / SQLite / Turso / Mongo、**あなたのもの** | +| 認証 | 組み込み | 組み込み | +| 生成される API | PostgREST | ObjectQL が生成する REST | +| 管理 UI | Console(基本的) | Console + Account | +| RBAC | Postgres RLS による行レベル | RBAC + 行レベル + フィールドレベル、宣言的 | +| 監査ログ | 自前で実装 | 第一級機能 | +| ベンダーロックイン | 同社の認証 + 同社のストレージ + 同社のリアルタイム | なし — すべての層がプラグイン | +| 最適な用途 | BaaS を求める新規アプリ | ランタイムを所有する必要があるアプリ | + +### vs. Salesforce / NetSuite / ServiceNow + +| | Salesforce | ObjectOS | +|---|---|---| +| データモデル | オブジェクト + フィールド + リレーション | 同じ | +| 権限 | プロファイル + 権限セット + 共有ルール + FLS | **同じ語彙**、宣言的な TypeScript | +| ユーザー単位コスト | 1 ユーザーあたり月 $150〜300 | $0 | +| カスタマイズ | Apex + Lightning + フロー | TypeScript + フロー | +| 実行場所 | 同社のクラウドのみ | あなたのインフラ | +| 「所有できる」までの時間 | コンサルタントによる数か月の作業 | 一日の午後 | +| 最適な用途 | エコシステムに費用を払うセールス主導の企業 | 税金なしでモデルだけが欲しいチーム | + +### vs. 自前で構築する(Next.js + Prisma + NextAuth) + +| | 自前 (DIY) | ObjectOS | +|---|---|---| +| 最初の REST エンドポイント | 数時間 | 60 秒 | +| 認証(email + OAuth + OIDC + パスキー + 2FA) | 数週間 | 同梱 | +| 全オブジェクトの管理 UI | オブジェクトごとに構築 | 生成される | +| 監査ログ | 自前で実装 | プラグイン、宣言的 | +| 権限付きの S3 へのファイルアップロード | 自前で実装 | プラグイン | +| バックグラウンドジョブ + リトライ + デッドレター | 自前で実装 | プラグイン | +| マルチテナント | 自前で実装(そして 2 回は間違える) | 組み込み | +| 最適な用途 | 専用 UX を持つ一般公開アプリ | スピードが勝負の社内ツール | + +## 率直なトレードオフ + +- **Retool より UI の自由度は低い。** Console はあなたのメタデータから生成されます。 + カスタムフロントエンドと組み合わせることはできますが(REST API は Console が使うものと + 同じです)、手作りでピクセル単位に作り込んだ UI が必要なら、自分で構築し、ObjectOS は + バックエンドとして使ってください。 +- **TypeScript ファースト。** 非エンジニアがオブジェクトを直接記述することはありません。 + Salesforce の管理者は UI ビルダーをクリックして進めることに慣れていますが、ここでは + `git` です。 +- **Salesforce より新しい。** Salesforce には 25 年分のエッジケースが文書化されています。 + 私たちには数百件です。プロトコルは安定しており、エコシステムは成長中です。 +- **Apache-2.0。** 商用製品での利用、組み込み、非公開での改変が可能です。コピーレフトの + 不意打ちはありません。任意の商用サポートは別途利用できます。 + +## 現実的なチェック + +実用可能な最小の ObjectOS 構成は、単一の `pnpm dev`、または SQLite を伴う単一の +Docker コンテナです。現在の本番環境で最大のものは、Postgres + S3 + Redis を用いて、 +複数のリージョンにわたり数万人の社内ユーザーにサービスを提供しています。どちらも +同じソフトウェアです。 + +`npx @objectstack/cli init my-app` から始めて、5 分で判断してください。 +合わなければ、5 分を費やしただけです。 + +[**クイックスタートを試す →**](/docs/quickstart) diff --git a/content/docs/why.cn.mdx b/content/docs/why.zh-Hans.mdx similarity index 100% rename from content/docs/why.cn.mdx rename to content/docs/why.zh-Hans.mdx