objectstack-platform について
objectstack-platform は、ObjectStack のプロジェクト設定、ランタイム構成、プラグイン開発を扱うスキルです。`defineStack()`、検証、メタデータ成果物、ドライバー、カーネルと HTTP の境界を説明します。
主な機能
- 01defineStack() によるスタック設定
- 02メタデータと相互参照の検証
- 03プロジェクトのひな形の構成
- 04ストレージドライバーの選択と接続
- 05プラグインとカーネル連携の開発
- 06Hono による ObjectStack HTTP ルートの統合
活用シーン
- 01ObjectStack プロジェクトの初期設定
- 02ランタイム起動前のスタックメタデータ確認
- 03開発・本番環境に応じたドライバー選択
- 04ObjectStack ルートの Hono アプリへの組み込み
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ objectstack-ai/ objectstack --skill objectstack-platformインストール後、Claude Code で/objectstack-platformを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
evals/config-plugins-ops.jsonreferences/_index.mdbootstrap.mdplugin-hooks.mdplugin-development.mdoperations.mdrules/plugin-lifecycle.mdservice-registry.md詳細
プラットフォーム — ObjectStack のブートストラップとプラグインシステム
1 つの defineStack()/カーネルのインターフェースで扱う 2 つの関心事です。プロジェクトのセットアップ
(objectstack.config.ts、ドライバー、ブートシーケンス)と、プラグイン開発(プラグイン、サービス、カーネルのフック/イベントハンドラー、
ObjectKernel と LiteKernel)。
defineStack() — コア設定
objectstack.config.ts は、すべてのプロジェクトの単一エントリーポイントです。
defineStack() を呼び出して、すべてのメタデータを宣言します。
→ references/bootstrap.md § 最小限の例にそのまま移動しました。
設定リファレンスの全項目
defineStack() は、トップレベルのキーとして
manifest、packages、objects、objectExtensions、picklists、
picklistExtensions、views、apps、pages、dashboards、reports、
datasets、actions、flows、jobs、
emailTemplates、docs、books、positions、permissions、
capabilities、sharingRules、apis、webhooks、api、server、
agents、tools、skills、hooks、functions、mappings、
analyticsCubes、connectors、data(シード)、datasources、
datasourceMapping、translations、i18n、plugins、devPlugins、
devHint、devLogins、requires、tiers、onEnable、appName、email、sms を持つ ObjectStackDefinitionInput を受け取ります。
意図的に、トップレベルの workflows コレクションも approvals コレクションもありません。
承認は Approval ノードを含むフローとして作成し(ADR-0019)、レコードのステートマシンは各オブジェクトの state_machine 検証ルールです(ADR-0020)。roles: や policies: のような実体のないキーは、黙って無視されるわけではありません。トップレベルで拒否され、スタックの読み込みに失敗します。
defineStack validation failed (1 issue):
✗ (root): Unrecognized key(s) on this stack definition: `policies`. …
未宣言のキーの扱いはインターフェースによって異なるため、次の 2 つの対応方針を区別してください。
- 拒否 —
defineStack()のトップレベル、各objects[]エントリー (ObjectSchema)、および各フィールド(FieldSchema)。パース時に例外が発生し、対象のインターフェースと問題のキーが示されます。TypeScript はそれより前の段階で、TS2353: Object literal may only specify known propertiesとしてリテラルを拒否します。 - 警告後に破棄 — まだ形状が確定していない作成インターフェース(
connectorsなど)。defineStack()はパースの前に警告を出力し、その値はパース後に残りません。defineStack: connectors.stripe.bogusKey: 'bogusKey' is not a declared connector key, so its value is dropped at load.これらは今後エラーになるものとして扱ってください。残る形状を確定する移行は予定されているため、現時点では警告のみのキーも、今後は拒否される見込みです。
任意キーやコレクション項目の型を含む、正確な Zod 形状については、
node_modules/@objectstack/spec/src/stack.zod.ts
(ObjectStackDefinitionSchema)を参照してください。各コレクションの項目形状は、それぞれのドメインフォルダー(data/object.zod.ts、ui/view.zod.ts など)にあります。
→ references/bootstrap.md § マップ形式(キー → 名前)・§ バレルインポートパターンにそのまま移動しました。
厳密な検証
defineStack() はデフォルトで検証します(strict: true)。
- Zod スキーマ — フィールド名、型、列挙型
- 相互参照 — ビュー/アクション/フローが、定義済みのオブジェクトを参照していること
- シードデータ — データセットのオブジェクトが定義内に存在すること
無効にする場合(上級者向け。たとえば、別のプラグインがオブジェクトを提供する場合):
export default defineStack(config, { strict: false });
コンパイル済みアーティファクトとランタイムメタデータの境界
ObjectStack のランタイムメタデータは、ローカル開発時にはソースファイルから、またはコンパイル済みアーティファクトから取得する必要があります。環境ランタイムがビジネスデータベースを通じてメタデータを読み書きするように設定しないでください。
# the CLI ships an `os` binary; `objectstack` is an alias for it
objectstack compile
# -> dist/objectstack.json
OS_ARTIFACT_PATH=./dist/objectstack.json objectstack dev
ランタイムの基本ルール:
| コンテキスト | メタデータソース | データベースの役割 |
|---|---|---|
| ローカル開発 | TS ファイルまたは dist/objectstack.json | ビジネスデータのみ |
| 本番ランタイム | アーティファクト API のレスポンス | ビジネスデータのみ |
| コントロールプレーン | メタデータストレージ内の公開済み JSON | 環境リビジョン、履歴、オーバーレイ |
objectstack.config.ts を生成するときは、オブジェクト名を短く snake_case にしてください。tableName は設定せず、環境ランタイムマニフェストに sys_metadata オブジェクトを追加しないでください。
マニフェストのリファレンス
エコシステム内で自身を識別するため、すべてのスタックに manifest が必要です。
manifest: {
id: 'com.example.crm', // Reverse domain unique ID
version: '1.0.0', // Semver
type: 'app', // app | plugin | driver | module | ...
name: 'Acme CRM', // Human-readable display name
description: 'CRM system', // Optional description
engines: { protocol: '^17' }, // Metadata-protocol major this app targets
}
manifest.engines.protocol: アプリの作成時に準拠するメタデータプロトコルのメジャーバージョンです。create-objectstack は、生成するすべてのプロジェクトにこれを設定します(3 つのサンプルアプリすべてにも設定されています)。ランタイムは何かを読み込む前にこれを確認するため、範囲外のランタイムは、後からクラッシュするのではなく、境界で正確な移行コマンドを示してアプリを拒否します。新しいプロトコルメジャーバージョンに意図的に移行するときに変更してください。不一致を黙らせるために変更してはいけません。
オブジェクトの命名: オブジェクトの name は正規識別子であり、物理テーブル名と一致します。ドメインのプレフィックスは名前に直接含めてください(例:name: 'crm_account')。オブジェクトレベルの namespace フィールド は廃止されており(ADR-0129 D3)、読み込み時に拒否されます。
manifest.namespace(ADR-0048): 任意ですが、一度設定すると適用されます。パッケージで manifest.namespace: 'crm' を宣言すると、すべての object.name が crm_ で始まる必要があります。そうでない場合、defineStack がエラーになります(@objectstack/spec の validateNamespacePrefix)。従来の <ns>__<short> という二重アンダースコア形式は拒否され、sys_ で始まる名前はプラットフォーム予約済みのため対象外です。名前空間はパッケージ所有権のキーでもあるため、同じ crm を宣言するパッケージを 2 つインストールすると、NamespaceConflictError が発生します(OS_METADATA_COLLISION=warn にすると警告に格下げされます)。名前空間が設定されている場合、os lint は名前がプレフィックスなしの UI/自動化項目(app、page、dashboard、flow、action、report、dataset)に対して、致命的ではない naming/namespace-prefix 警告も出力します。
アプリとプラットフォームの境界
ObjectStack アプリは、ビジネス機能を簡潔に実装したものです。プラットフォームの仕様に従ってメタデータを作成し、これらのスキルを参考にしながら、os コマンドで確認してください(作業内容の検証)。プラットフォームが担うものを作り直してはいけません。
- ビジネス機能はアプリに、機能はプラットフォームに属します。 デフォルト値がない、診断が間違っている、仕様で拒否される形式である場合、修正すべきなのは上流です。そちらで問題を報告し、ここで補おうとしないでください。
- メタデータだけを持ち、この会社についての知識がないものでも、これを書けるでしょうか? いいえ — この会社独自の判断(割引上限、案件の割り当て先、受注/失注の記録方法など)を表すものなら ⇒ アプリです。はい — メタデータに整合性があるかどうかだけを確認するもの(参照整合性、翻訳の網羅性、ビューの登録項目、共有ルールの適用範囲、CRUD の往復処理、宣言されたロールごとの RLS プローブなど)なら ⇒ プラットフォームです。
- プラットフォームの不具合がある場合は、プラットフォームの修正を待ちます。 防御的なコーディング、形式の許容、プラットフォームのルールを再実装する手書きの述語は避け、「できる半分だけを取り込む」ことも絶対にしないでください。これは契約優先の選択肢を消費し、判断を中途半端に実行したままにします。ブロック事項をプラットフォームのイシューに記録し、機械判読できるようにしてください。再開する前に、固定したバージョンに修正が含まれていること(上流へのマージ ≠ 固定したバージョンへの反映)を確認し、不具合固有の再現手順を再実行してください。
- プラットフォームの不適切なデフォルト値は修正すべきものであり、呼び出し箇所ごとに回避するものではありません。
テンプレート
blank は create-objectstack が提供する唯一のテンプレートで、デフォルトです。
create-objectstackに同梱されているため、ネットワークから取得する必要はありません- サンプルオブジェクトを1つ含みます。
requires: ['automation', 'triggers']に加えて、plugins:に汎用コネクター実行器を3つ含みます。また、8つのジェネレーターバレル(objects、views、actions、flows、dashboards、apps、skills、picklists)があり、それぞれのsrc/*/index.tsはexportsOfを通じて、名前と同じスタックキーに渡されます。スキャフォールドされたAGENTS.mdに追加方法が記載されています。メモリドライバーと Hono サーバーはファイルに含まれていません。CLI が起動時に両方を自動登録します - このスキルで説明するメタデータを追加するための、まっさらな状態です
→ references/bootstrap.md § Scaffolding Command にそのまま移動しました。
プロジェクト構造の規約
すべての ObjectStack プロジェクトは、次のディレクトリ構造に従います。
my-app/
├── objectstack.config.ts # ← THE entry point — defineStack()
├── package.json
├── tsconfig.json
└── src/
├── objects/ # Business object definitions
│ ├── task.object.ts # → exports a single object
│ └── index.ts # → barrel: export * from './task.object'
├── views/ # Optional: UI view definitions
│ ├── task.view.ts
│ └── index.ts
├── apps/ # Optional: app definitions (nav, pages)
│ ├── main.app.ts
│ └── index.ts
├── flows/ # Optional: automation flows
│ ├── task.flow.ts
│ └── index.ts
├── actions/ # Optional: action definitions
│ ├── task.action.ts
│ └── index.ts
├── dashboards/ # Optional: dashboards
├── reports/ # Optional: reports
├── datasets/ # Optional: analytics datasets
├── i18n/ # Optional: translation bundles
└── handlers/ # Optional: runtime hook handlers
命名規則
| 概念 | 規約 | 例 |
|---|---|---|
| ファイル名 | {name}.{type}.ts | task.object.ts、main.app.ts |
| マシン名 | snake_case | project_task、first_name |
| 設定キー | camelCase | maxLength、defaultValue |
| バレルエクスポート | Object.values(imported) | objects: Object.values(objects) |
ドライバー選択ガイド
ドライバーはストレージ層です。環境に応じて選択してください。
| ドライバー | パッケージ | 最適な用途 | 備考 |
|---|---|---|---|
| Memory | @objectstack/driver-memory | 開発、テスト、プロトタイピング | InMemoryDriver — 再起動するとデータは失われます |
| SQL | @objectstack/driver-sql | 本番環境(PostgreSQL、MySQL、SQLite) | SqlDriver — 内部では Knex.js を使用(pg/mysql/better-sqlite3 クライアント) |
| MongoDB | @objectstack/driver-mongodb | 本番環境(ドキュメントストア) | MongoDBDriver |
| SQLite WASM | @objectstack/driver-sqlite-wasm | ブラウザー/WebContainer | SqliteWasmDriver — インプロセスで動作し、サーバーは不要です |
| Turso | @objectstack/driver-turso | エッジ、サーバーレス、マルチテナント | クラウド/EE のみ — ObjectStack のクラウド/エンタープライズ配布版に同梱されており、オープンフレームワークには含まれていません。オープンコアの CLI は libsql:// URL を認識しますが、明確なエラー(UnsupportedDriverError)で失敗します |
ドライバーの接続 — 通常は不要です
os dev/os serve/os start では、CLI がデータベース URL からドライバーを自動的に解決し、DriverPlugin を登録します(開発環境では memory、本番環境では SQL)。設定の plugins: 配列にドライバーを追加しないでください。サンプルアプリではどれも追加しておらず、plugins: キーは CLI が推測できないプラグイン(コネクター実行器や独自プラグイン)用です。コードではなく、DB URL を設定してドライバーを選択してください。
DriverPlugin を自分で構築するのは、Runtime/ObjectKernel を組み込む場合や、カーネルを直接起動するテストなど、実行環境を自分で管理する場合に限ります。
import { DriverPlugin } from '@objectstack/runtime';
import { SqlDriver } from '@objectstack/driver-sql';
new DriverPlugin(new SqlDriver({ client: 'pg', connection: process.env.DATABASE_URL }));
HTTP レイヤー(Hono)
パッケージは2つあります。
| パッケージ | エクスポート | 使用する場面 |
|---|---|---|
@objectstack/hono | createHonoApp({ kernel, prefix }) | サーバーを自分で管理する場合。ObjectStack のルートを独自の Hono アプリ/デプロイ先に組み込みます。 |
@objectstack/plugin-hono-server | HonoServerPlugin | ObjectStack がサーバーを管理する場合。Hono アプリをホストして待ち受けソケットを開くカーネルプラグインです(os dev/os serve が登録するのはこちらです)。 |
@objectstack/adapter-* パッケージはありません(adapter-express/-fastify/-nextjs/-nuxt/-nestjs/-sveltekit もありません)。別のフレームワークと統合するには、Hono アプリ(Web 標準の fetch ハンドラー)をマウントするか、ディスパッチャーを直接呼び出してください。
使用パターン(Hono)
import { createHonoApp } from '@objectstack/hono';
// prefix defaults to '/api'.
export default createHonoApp({ kernel });
⚠️ prefix を指定しても認証の場所は変わりません。 /auth/* マウントは prefix ではなく、認証サービスの basePath(AuthPlugin のデフォルトは /api/v1/auth)に従います。createHonoApp({ kernel }) は better-auth の /api/v1/auth/* に到達します。basePath が含まれていない prefix を指定すると、起動時に両方の値を示して拒否されます。
アーキテクチャ
createHonoApp は HttpDispatcher を作成し、認証とディスカバリーの明示的なルートをマウントして、それ以外のすべてを HttpDispatcher に委譲します。そのため、HttpDispatcher に追加された新しいルートは自動的に機能します。
ランタイムの起動シーケンス
ObjectStack の起動方法を理解しておくと、デバッグやカスタマイズに役立ちます。
objectstack.config.ts
└── defineStack({ manifest, objects, views, ... })
│
▼
CLI: `os serve` / `os dev`
1. Load .env files (NODE_ENV-based)
2. Dynamic import of config file
3. Create Runtime + ObjectKernel
4. Auto-detect and register plugins (in this order):
├── ObjectQLPlugin (if objects defined)
├── DriverPlugin (memory in dev, SQL in prod)
├── AppPlugin (loads the defineStack bundle)
├── I18nServicePlugin (if translations/i18n defined)
├── HonoServerPlugin (registered BEFORE AuthPlugin — the server must
│ exist for plugins that mount routes during init/start)
├── AuthPlugin
├── Split platform-app plugins (ADR-0048, optional/best-effort, after AuthPlugin):
│ @objectstack/setup → createSetupAppPlugin (first-run wizard)
│ @objectstack/account → createAccountAppPlugin
│ (@objectstack/studio is intentionally NOT default-loaded — the
│ Console, mounted at /_console/ by `--ui`, ships its own Studio
│ surface at /_console/studio/…)
├── RESTPlugin (auto-generated API)
├── DispatcherPlugin
└── AIServicePlugin (cloud / EE only — reverse-mounted by a cloud host; absent in the open framework per cloud ADR-0025)
5. Runtime.start() → init + start all plugins
6. Server listens on the resolved port (see "Ports & networking" in Part 3)
ポートの解決(os dev と os start はどちらも os serve を実行):
--port フラグ › $OS_PORT › $PORT › 3000。競合時の動作はモードによって異なり、開発モードでは次の空きポートに移り、本番モードでは明確なエラーで失敗します。ポートとネットワークを参照してください。
requires: — 起動するサービスプラグイン
ステップ 4 のリストは固定のコアです。それ以外のサービスプラグインはすべてオプトインであり、スタックのルートにある requires: [...] で有効にします。CLI は各トークンを packages/cli/src/commands/serve.ts の CAPABILITY_PROVIDERS レジストリを通じて展開します。このレジストリには、次の 19 個のオプトイン項目があります。
| トークン | プロバイダーパッケージ |
|---|---|
automation | @objectstack/service-automation — フロー、および宣言的な connectors: エントリー |
analytics cache storage queue job messaging realtime settings sms | @objectstack/service- + トークン |
marketplace | @objectstack/service-package |
audit email sharing approvals webhooks | @objectstack/plugin- + トークン |
pinyin-search | @objectstack/plugin-pinyin-search |
mcp | @objectstack/mcp |
triggers | @objectstack/trigger-record-change、および trigger-schedule と trigger-api |
このマップにない PLATFORM_CAPABILITY_TOKENS のトークンは、このマップでは解決されません。
- ティアによる制御 —
ai、ai-studio、i18n、ui、authにはプロバイダーエントリーがありません。serve.tsのrun()にある専用ブロックが、代わりにそれぞれのティアを有効にします(ai/ai-studioはインテント駆動型の AI ブロックを通じて、残りの 3 つはそれぞれのティアブロックを通じて有効になります)。 - エンタープライズ/クラウド —
hierarchy-securityにはオープン版のプロバイダーがなく、@objectstack/security-enterpriseに含まれており、plugins[]を通じて読み込まれます。ai-seatとgovernanceはクラウドの objectos-runtime でのみ解決されます。
正式なリストは PLATFORM_CAPABILITY_TOKENS(@objectstack/spec、kernel/platform-capabilities.ts)です。不明なトークンは起動時ではなく、作成時に defineStack によって拒否されます。
記述内容に影響する 5 つのルール:
- 優先順位:
requires›tiers›--preset› 組み込みのデフォルト。plugins:に明示的なインスタンスがある場合は、常に能力の解決より優先されます。 - 宣言は要求です。 あなたが宣言した能力のプロバイダーパッケージが存在しない場合、起動時に致命的なエラーになります。プラットフォームが自動で注入した能力はベストエフォートとして扱われ(警告を出して続行します)。
authはemailを含意します。 認証コールバック(パスワードのリセット、メールアドレスの確認、マジックリンク、招待)にはメールサービスが必要なため、CLI はauthが要求されるとemailを追加します。plugins:にコネクターを列挙する場合は、automationを含めてください。 コネクターのエグゼキューターはプロバイダーファクトリーをautomationに登録します。これがないと登録先がなく、起動に失敗します。triggersとjobを組み合わせてください。triggersだけで有効になるのはレコード変更トリガーです。スケジュールトリガーと相対時刻トリガーはジョブサービスで実行されるため、jobがないと自動起動されるスケジュール済みフローは動作しません。
onEnable — アプリがランタイムコードをバインドする場所
objectstack.config.ts では、デフォルトのスタックと並べて onEnable をエクスポートできます。
AppPlugin は起動時にこれを呼び出し、アプリのライブなランタイムハンドルを渡します。宣言型のメタデータが命令型のコードに接続される唯一の接点です(アクションハンドラーの登録、ジョブへのデータハンドルの受け渡し、フィクスチャデータソースのプロビジョニングなど)。3つのサンプルアプリすべてで使用しています。
export const onEnable = async (ctx: { ql: { registerAction: (...a: unknown[]) => void } }) => {
registerTaskActionHandlers(ctx.ql);
};
→ references/bootstrap.md の § プラグインの読み込み順が重要 · § プログラムによるブートストラップ(CLI なし)へ、そのまま移動しました。
→ references/bootstrap.md の § 複数アプリの合成へ、そのまま移動しました。
シードデータ
スタックの data: コレクションは defineSeed() を使って定義します。これは objectstack-data が管理しています。externalId による照合、env: のスコープ設定、導出されるキーについては、そちらを参照してください。特に、object はオブジェクト定義から導出されるため、手書きしないでください。また、data: [{ object: … }] のようなリテラルを直接書かないでください。
mode によって、シードの実行時に既存の行をどう扱うかが決まります。
| モード | 動作 |
|---|---|
upsert(デフォルト) | externalId の一致に基づいて挿入または更新します |
insert | 常に挿入します(重複時は失敗します) |
update | 見つかったレコードのみ更新し、新規レコードは無視します |
ignore | 存在しない場合は挿入し、存在する場合はスキップします |
replace | ⚠️ データ損失 — すべてのレコードを削除して再挿入します |
CLI コマンド
日常的に使うコマンドはパート 3 — 運用にあります。 ブートストラップループのチートシート:
npx create-objectstack my-app
cd my-app && npm install
os dev --ui # dev server + Console at /_console/ (auto-hops port if taken)
os validate # metadata cross-reference checks
os compile # produce dist/ artifact
os migrate plan # preview metadata↔DB schema drift (additive sync never alters existing columns)
os migrate apply # reconcile DB to metadata (loosening only; --allow-destructive for drops/tightenings)
PORT=8080 os start # production — pin the port explicitly (see Ports & networking)
→ references/bootstrap.md の § 完全な動作例へ、そのまま移動しました。
→ パート 2 — プラグイン開発とカーネル拡張は、そのまま references/plugin-development.md(クイックリファレンス — 詳細なルール · ObjectKernel と LiteKernel の比較 · プラグインインターフェース — クイック概要 · PluginContext API · プラグインの完全な例 · プラグインの使用 · プラグインのテスト · 既知のプラグイン名とサービス · MetadataPlugin のランタイム境界 · ヘルスモニタリング · 機能フラグ)へ移動しました。詳細なルールは rules/plugin-lifecycle.md · rules/service-registry.md · references/plugin-hooks.md にあります。
→ パート 3 — 運用:CLI、テスト、デプロイは、そのまま references/operations.md(日常ループのコマンド · ビルドとランタイム · 作業の確認 · ポートとネットワーク · データとマイグレーション · 環境とデプロイ · プラグインのリリース · テストのパターン · デプロイ先 · ヘルスと可観測性 · よくある運用上の落とし穴)へ移動しました。
リファレンス
Zod スキーマの全一覧(一行の説明付き)は references/_index.md を参照してください。node_modules/@objectstack/spec/src/ 内の各ファイルへの参照が記載されています。フィールドの正確な形状を確認するには、必ずソースを Read してください。プロパティ名の記憶に頼らないでください。