mcpField
O
objectstack-api

objectstack-api

github.com/objectstack-ai開発76229 回インストール今日更新
リポジトリ

objectstack-api について

objectstack-api は、ObjectStack の HTTP API 設計・記述を支援するスキルです。自動生成されるデータルート、宣言的エンドポイント、アクセス方針、エンドポイントの制約を扱います。

主な機能

  1. 01オブジェクト向け REST ルートの自動生成
  2. 02apis によるエンドポイント宣言
  3. 03API メソッドとアクセス方針の指針
  4. 04エンドポイントのマッピングと命名規則
  5. 05公開フォームエンドポイントの仕様

活用シーン

  1. 01ObjectStack オブジェクトの CRUD・クエリルート設計
  2. 02データまたはフローパイプラインに委譲するエンドポイントの宣言
  3. 03匿名フォーム送信とエンドポイントアクセスの確認
  4. 04宣言的 API 定義を含むスタックのアップグレード

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/objectstack-ai/objectstack --skill objectstack-api

インストール後、Claude Code で/objectstack-apiを入力して読み込まれたか確認します。

同梱ファイルreferences/_index.mdevals/endpoints-auth-routes.json

詳細

API 設計 — ObjectStack API プロトコル

スキルの範囲

必要なこと代わりに使用
オブジェクト、フィールド、権限、またはデータソースをモデル化するobjectstack-data
リクエストをフィルター、ソート、ページネーション、または集計するobjectstack-query
カーネルサービスを登録する、またはプラグインから読み取るobjectstack-platform
ルートガードまたは認証述語で CEL を使用するobjectstack-formula

自動生成 API とカスタム API

自動生成 API

apiEnabled: true(デフォルト)を持つすべての ObjectStack オブジェクトには、 完全な REST API が自動的に生成されます。

GET    /api/v1/data/{object}          # List records (with filter, sort, pagination)
GET    /api/v1/data/{object}/:id      # Get single record
POST   /api/v1/data/{object}          # Create record
PATCH  /api/v1/data/{object}/:id      # Update record
DELETE /api/v1/data/{object}/:id      # Delete record (hard delete)
POST   /api/v1/data/{object}/query    # Complex queries + aggregation (QueryAST in body)
POST   /api/v1/data/{object}/batch    # Per-object batch operations
POST   /api/v1/batch                  # Cross-object atomic batch

データの CRUD は /data プレフィックスの下にあります。/bulk ルートも GET .../aggregate ルートもありません。バッチ書き込みは batch エンドポイント経由で行い、 集計はリクエスト本文の groupBy/aggregations を指定して POST /api/v1/data/{object}/query 経由で行います。

重要なルール: オブジェクトで apiMethods を定義すると、その操作(および そこから派生する操作)のみが公開されます。[] はすべて拒否することを意味します。定義可能な 値は6つのプリミティブです。**API メソッド(操作)**を参照してください。

メタデータ API(/meta)

メタデータの読み取り用エンドポイントは、上記のデータ CRUD ルートとは別に、 /api/v1/meta の下にあります。

GET /api/v1/meta/:type            # List metadata items of a type (object, view, flow, doc, …)
GET /api/v1/meta/:type/:name      # Read a single metadata item

読み取り側のクエリパラメーター(?preview=draft、?package=、?include=content)は クライアントの契約であり、これらを宣言するスタックはありません。

公開(匿名)フォームエンドポイント

FormView は、sharing に次の3つすべてが宣言されている場合に限り、匿名フォームエンドポイントで 提供されます。enabled: true(スキーマのデフォルトは false)、allowAnonymous: true、および publicLink スラッグです。いずれか1つでも 欠けていると、両方のエンドポイントは 404 FORM_NOT_FOUND を返します。その後、フォームは次の場所に マウントされます。

GET  /api/v1/forms/:slug         # returns form spec + restricted objectSchema
POST /api/v1/forms/:slug/submit  # whitelist-filtered INSERT, no auth header

これらのエンドポイントは enforceAuth を迂回します(Web-to-Lead/Web-to-Case フロー)。送信はフォーム独自の 宣言によって許可されます。送信先オブジェクトに対する publicFormGrant(新しい行の作成と読み戻しのみで、 それ以外は許可されません)は、権限セットが解決される前に判定されます。送信コンテキストの guest_portal という名前には何の権限もなく、セットも不要です。この名前のセットがある場合も、 その結果マスカーにのみ適用されます。フレームワークはフォームの sections[].fields[] リストにない フィールドを除去します。送信先オブジェクトの beforeInsert フックでは、安全なデフォルト値 (status='new'、lead_source='web' など)を設定し、権限の強いキー (owner、internal_notes など)を delete してください。組織列によってオブジェクトが壁で隔てられている 制限付きの構成(group/isolated)では、そのオブジェクト上のフォームも提供されません。両方のエンドポイントが 404 を返し、保存/公開時には public-form-intake-unavailable の警告が表示されます。組織に 属さない行を扱うオブジェクトで再び利用できるようにするには、そのオブジェクトで tenancy: { enabled: false } を宣言してください。完全な仕様については、 node_modules/@objectstack/spec/src/ui/view.zod.ts(FormViewSchema)および node_modules/@objectstack/spec/src/ui/sharing.zod.ts(enabled/allowAnonymous/publicLink を含む SharingConfigSchema)を参照してください。


宣言型エンドポイント(apis:)— ハンドラーコード不要

defineStack({ apis }) は HTTP エンドポイントをメタデータとして宣言します。宣言された エンドポイントはプロトコル17から利用可能です。ランタイムは METHOD + path を照合し、エンドポイントのポリシーキーを実行してから、組み込みルートと 同じパイプラインに処理を委譲します。object_operation は /api/v1/data/{object} の背後にある データパイプラインへ、flow は POST /api/v1/automation/{name}/trigger の背後にある自動化パイプラインへ 委譲されます。エンドポイントとは、既存のパイプラインに対する安定した URL とポリシーレイヤーであり、 別の実行方式ではありません。

apis: とコードハンドラーの選択
用途場合
defineStack({ apis })エンドポイントが、プラットフォームがすでに実行するものの投影である場合:レコードをクエリして返す、またはフローをトリガーする場合です。コードもデプロイアーティファクトも不要で、公開時のゲートで検証されます。こちらを優先してください。
コードを実行するフローエンドポイントで実際のハンドラー CODE が必要な場合:type: 'flow' エンドポイントを、スタック関数を指定する script ノード(defineStack({ functions }))を持つフロー、または宣言済みコネクターを呼び出す connector_action ノードを持つフロー(アウトバウンド)に向けます。URL は宣言的なままで、コードはオートメーション機能がすでに実行されている場所で実行されます。

制御下にある送信元からの受信 Webhook は、type: 'api' フローです (objectstack-automation → 受信 Webhook(api)トリガー)。ObjectStack 独自の x-objectstack-signature を検証し、キューに登録して、202 を返します。 アプリが http.server にマウントされることはありません。このサービスはプラットフォームプラグイン独自のドア構築プリミティブであり、コードでマウントしたルートには、呼び出し元の ID、認証ゲート、レート制限、名前空間の割り当て、OpenAPI エントリーが付与されません。現在、アプリの機能として提供されていないケースが3つあります。存在しない機能を作り上げず、その旨を伝えてください。生のボディに対する独自の署名で検証されるサードパーティーのコールバック(フックが確認するのは x-objectstack-signature のみ)、ストリーミングレスポンス(宣言されたエンドポイントは1つの JSON エンベロープを返します)、そしてプラットフォームが対応していないプロトコルです。

import type { ApiEndpoint } from '@objectstack/spec/api';

// The stack declares `manifest: { namespace: 'acme', … }` — required, see below.
export const leadFeed: ApiEndpoint = {
  name: 'acme_lead_feed',
  path: '/api/v1/apps/acme/leads',      // /api/v1/apps/<namespace>/<subpath>
  method: 'GET',
  summary: 'Lead feed',
  type: 'object_operation',
  objectParams: { object: 'acme_lead', operation: 'find' },
  // `authRequired` omitted → defaults to `true`. Omission is SAFE.
  cacheTtlSeconds: 30,                   // GET-only; rides success answers only
};
パスの例外(ADR-0121 D1/D2)

宣言するパスは /api/v1/apps/<manifest.namespace>/<subpath> でなければなりません。名前を指定できるのはサブパスのみで、その内部には以下の通常の命名規則が適用されます。manifest.namespace は明示的に宣言する必要があり、manifest.id から導出されることはありません。この範囲外のパスは公開時に拒否されます。

5つの公開ゲートと、それぞれの対処方法

このランタイムが処理できない宣言は、ゲートごとに公開時に拒否されます。ゲートの文言を暗記する必要はありません。拒否メッセージを読んでください。そこに修正方法が記載されています。5つのゲートは、名前空間(上記の例外)、サポート対象のターゲット(script / proxy は 17.x では実行されません。object_operation には objectParams.object と .operation の両方が必要です。flow には target が必要です)、マッピング(以下)、ポリシー(以下)、一意性(スタックごとに METHOD + パスの組み合わせは1つのみ)です。

authRequired と D6 の組み合わせ

authRequired のデフォルトは true なので、省略しても安全です。明示的に false に設定すると、認証なしで実行できるエントリーポイントが開きます。その場合は ADR-0121 D6 により、有効化された予算を組み合わせる必要があります。

authRequired: false,
rateLimit: { enabled: true, windowMs: 60_000, maxRequests: 100 },

ゲートの判定条件は rateLimit.enabled === true であり、キーの存在ではありません。RateLimitConfigSchema.enabled 自体のデフォルトは false なので、windowMs / maxRequests のみを記述しても、何も計測されない予算を宣言することになります。エンドポイントの予算は、サーバーレベルの server.security.rateLimit とは独立して計測されます。

マッピングキー:投影のみ

inputMapping / outputMapping は、ドットパスでフィールドを移動および名前変更するだけで、それ以上のことはできません。inputMapping はリクエストボディをマッピングし、ポリシーチェーンの適用後、委譲の前に実行されます(したがって、マッピングによって呼び出し元が authRequired やレート制限を回避することはできません)。outputMapping は、成功したレスポンスボディにのみ適用されます。作成する前に知っておくべき重要な点は3つあります。

  • transform は拒否されます。変換関数レジストリーはありません。 値は生成される場所(フローまたは数式フィールド)で計算してください。
  • リクエストボディを読み取らない find / get / delete の object_operation では、inputMapping は拒否されます。
  • 複数のエントリーで同じターゲットパスに書き込むことはできません。また、一方が他方の配下にあるパス(x と x.y)も指定できません。
バージョン 17 未満のスタックからのアップグレード

古いメジャーバージョン向けに記述された apis: ブロックは、1 バイトも変更されずに意味が変わります。実行されないドキュメントが、実行エントリーポイントになります。アップグレード前に、プロトコルアップグレードガイドの declarative-apis-endpoints-live の項目を確認してください。これは名前の変更ではなく、セキュリティレビューです。重要な手順は 2 つです。すべての path を例外枠に移すことと、各エントリーを検索して authRequired: false がないか確認することです。


エンドポイントの命名規則

パターン用途例
/api/v1/data/{object}自動生成されるコレクション/api/v1/data/accounts
/api/v1/data/{object}/:id自動生成されるレコード/api/v1/data/accounts/abc123
/api/v1/{object}/:id/{action}レコードに対するカスタムアクション/api/v1/cases/:id/close
/api/v1/{domain}/{action}ドメインレベルのアクション/api/v1/ai/chat
/api/v1/apps/{namespace}/{subpath}宣言型 apis: エンドポイント — 例外枠であり、自由に選べるものではありません/api/v1/apps/acme/leads

ルール:

  • コレクションのパスには、必ず複数形の名詞を使ってください(account ではなく accounts)。
  • 複数語のパスには snake_case を使ってください(projectTasks ではなく project_tasks)。
  • 動詞は CRUD ではなく、アクションにのみ使ってください(/close、/approve)。
  • バージョン管理のため、必ず /api/v1/ をプレフィックスとして付けてください。

API メソッド(オペレーション)

作成者が指定できる ApiMethod 列挙型は、6 つの基本操作です。より広い実効語彙(14 個の値)は、ゲートとレスポンスが使用するもので、追加の 8 つの動詞が apiMethods で宣言されることはありません。

作成者が指定できる基本操作:

メソッド現在の HTTP インターフェイス目的
getGET /data/{object}/:id単一のレコードを取得する
listGET /data/{object}フィルター、並べ替え、ページネーションを指定してレコードを一覧表示する
createPOST /data/{object}新しいレコードを作成する
updatePATCH /data/{object}/:id既存のレコードを更新する
deleteDELETE /data/{object}/:idレコードを削除する
bulkPOST /data/{object}/batch作成、更新、削除を一括処理する(bulk ∧ 子オペレーション)

派生オペレーション(自動的に許可され、作成者が指定することはありません):

オペレーション派生元現在の HTTP インターフェイス
upsertcreate ∧ update生成されません
aggregatelistgroupBy/aggregations を指定した POST /data/{object}/query
searchlist ∧ searchableグローバルな GET /api/v1/search。オブジェクト単位ではありません
importcreate ∨ update(writeMode による厳密な判定)POST /data/{object}/import
exportlistGET /data/{object}/export

history(get ∧ trackHistory から派生)はゲートのみを制御します。restore/purge は派生されません。ごみ箱のインターフェイスは廃止されています。派生動詞を apiMethods で宣言すると、解析時に削除され、FROM → TO の警告が表示されます。


ディスカバリーとヘルスチェック

GET /api/v1/health、GET /ready(実行中は 200/起動中は 503)、GET /api/v1/discovery(サービスごとのステータス)は、すべてのデプロイ環境に存在します。3 つともレスポンス用のインターフェイスであり、定義する必要はありません。


ディスパッチャーのエラーコード

HttpDispatcher は中央のリクエストルーターで、次のように応答します。

HTTP ステータスエラーコード発生条件
404ROUTE_NOT_FOUNDパスに一致するルートがありません
405METHOD_NOT_ALLOWEDルートは存在しますが、メソッドがサポートされていません
501NOT_IMPLEMENTEDルートは宣言されていますが、ハンドラーはスタブです
503SERVICE_UNAVAILABLEサービスは登録されていますが、準備ができていません

リアルタイムサブスクリプション

リアルタイムの契約はポインタースタイルです。正確な形状は仕様ソースを参照してください。

  • node_modules/@objectstack/spec/src/api/realtime.zod.ts — TransportProtocol (websocket | sse | polling)、SubscriptionSchema(id、events[]、 transport、任意の channel)、RealtimeEventSchema、および RealtimeConfigSchema。
  • node_modules/@objectstack/spec/src/api/websocket.zod.ts — WebSocket メッセージプロトコル:subscribe/unsubscribe メッセージ、イベント配信、プレゼンス、 カーソルおよび共同編集メッセージ、ack/error/ping/pong フレーム。

認証と認可

RBAC(definePermissionSet)とRLSはobjectstack-data側の機能であり、このセクションでは エンドポイント独自の認証キーを扱います。

認証設定

エンドポイントにネストされた auth ブロックや、name/request/ response フィールドはありません。認証は RestApiEndpointSchema 上の フラットな public + permissions のペアであり、宣言型の ApiEndpointSchema エンドポイント(およびディスパッチャー)では authRequired: boolean(デフォルトは true)を使用します。これを false に 設定する場合は、rateLimit を必ず設定してください(ADR-0121 D6 — 上記の 宣言型エンドポイント → authRequired とD6の組み合わせを参照)。レート制限ポリシー自体は RateLimitConfigSchema によって定義されます。

import { RateLimitConfigSchema, type RateLimitConfig } from '@objectstack/spec/shared';

const limit: RateLimitConfig = RateLimitConfigSchema.parse({
  enabled: true,
  windowMs: 60_000,     // time window in milliseconds
  maxRequests: 100,     // max requests per window
});
認証プロバイダー

プロバイダーとログインの契約は node_modules/@objectstack/spec/src/api/auth.zod.ts にあります。AuthProvider は 'local' | 'google' | 'github' | 'microsoft' | 'ldap' | 'saml' であり、 LoginRequestSchema には type(ログイン方法)に加えて、任意の email、 username、password、provider、redirectTo が含まれます。認証フローを 実装する前に、そのファイルでセッションとトークンのレスポンス形式を確認してください。


データソース

defineDatasource、schemaMode、external 書き込みゲート、 credentialsRef についてはobjectstack-dataの rules/datasources.md を参照してください。ドライバーパッケージと Turso Cloud/EEに関する注意事項についてはobjectstack-platformの ドライバー選択 ガイドを参照してください。driver IDの語彙は data/driver/config-registry.zod.ts にあります。


エラーエンベロープとコード台帳(ADR-0112)

error.code は2層構造です。閉じた StandardErrorCode カタログに、 各所有パッケージが api/error-code-ledger.zod.ts で登録するコードが加わります。 ApiErrorSchema.code はその和集合を検証するため、未登録のコードは パースに失敗し、エンベロープ適合性テストに失敗し、CIにも失敗します。

この台帳の対象はフレームワークパッケージのみです。下流のリポジトリは独自の 台帳を保持し、2つのチェックを自ら組み合わせます。形状には envelopeViolations(body)、 語彙には makeApiErrorSchema(yourCodes) を使用します(どちらも api/contract.zod.ts にあります)。どのリポジトリも、いずれの台帳にもないコードを 出力してはなりません。


ベストプラクティス

  1. 可能な限り自動生成されたAPIを使用してください。 CRUD + トリガーでは表現できない ビジネスロジックに限り、カスタムエンドポイントを作成してください。
  2. 一貫したエラー形式を返してください。 ディスパッチャーのエンベロープは DispatcherErrorResponseSchema です。{ success: false, error: { code, message, httpStatus?, route?, service?, hint? } } の形式で、code は意味を表す 文字列であり、code/message は必須です。一般的なAPIエラーには ErrorResponseSchema(errors.zod.ts)を使用します。提供されているデータルートは 代わりにフラットな { error, code } 本文を返すことに注意してください(例: CONCURRENT_UPDATE → 409、VALIDATION_FAILED → 400)。すべてのエラーが success: false のエンベロープで届くとは限りません。
  3. 最小権限の認証を適用してください。 すべてのエンドポイントで、必要な権限を 明示的に宣言してください。
  4. 冪等な書き込みを意図的に設計してください。 upsertルートは生成されないため、 外部連携では一意な外部IDでクエリし、作成または更新に分岐します。これらの書き込みは POST /api/v1/data/{object}/batch でまとめてください。

よくある落とし穴

  1. 409 Conflict を処理しない。 生成される PATCH /api/v1/data/{object}/:id ルートでは、2 つの形式による楽観的同時実行制御が行われます。If-Match ヘッダー または JSON ボディの expectedVersion フィールドを使います。両方が送信された場合は ボディが優先され、トークンには通常、クライアントが読み取った updated_at の値を 使用します。どちらも送信しない場合、チェックはスキップされます。不一致の場合は 409 CONCURRENT_UPDATE が返されます。引用符で囲まれた空のエンティティタグ("")は 省略扱いではなく、400 VALIDATION_FAILED として拒否されます。
  2. DELETE で復元できると思い込む。 ObjectStack の DELETE は完全削除です。ごみ箱は ありません(使用されなくなった enable.trash フラグは 16.x で削除されました)。復元可能に するには、独自のソフトデリート処理ではなく、フィールドごとの trackHistory(監査証跡) または lifecycle のアーカイブポリシーを使用してください。

作業を検証する

*.endpoint.ts、カスタムルート、または認証プロバイダーを追加したら、完了を報告する前に 作成時のチェックを実行してください。

os validate     # Zod schema + CEL predicate validation + bindings (no artifact)
# or: os build  # the same gates, plus emits dist/

ルートガードと認証述語には CEL が使われます。このチェックではそれらを解析し、形式に誤りが ある場合は実行時にガードをすり抜けさせるのではなく、該当箇所を示すメッセージとともに ゼロ以外の終了コードを返します。スキャフォールドされたプロジェクトでは、チェックは npm run validate です。チェックの一覧については、objectstack-platform の 作業を検証する を参照してください。


参考資料

Zod スキーマの全一覧(各項目の説明付き)については、 references/_index.md を参照してください。各項目から node_modules/@objectstack/spec/src/ 内の該当箇所を参照できます。フィールドの正確な 形式を確認するには、必ずソースを Read してください。プロパティ名の記憶に頼らないでください。

コメント