コンテンツにスキップ

アクセス経路とクライアントのモデリング

English · 日本語(このファイル)

📚 ガイドシリーズ 第4章 / 全5章 | ← 前章: 進化・移行 | 次章 →: 伝達

プロダクトのアーキテクチャを描くとき、サービスの内部構造(service → domain → usecase)と同じくらい重要なのが アクセス経路 — 「誰が、どの面(クライアント)を介して、何(サービス)に到達するか」です。エンドユーザーは普通サービスを直接叩きません。モバイルアプリや Web フロントを経由します。この user → client → service の系統を、karasu は専用の語彙でモデル化します。

このガイドは、web / mobile / BFF / AI エージェントを含むプロダクトの「面」を karasu で描くアーキテクト向けです。正確な構文は docs/spec/syntax.ja.md を参照してください。.krs スニペットは検証済みです。


0. system の二系統 — アクセス経路とサービス階層

Section titled “0. system の二系統 — アクセス経路とサービス階層”

karasu の system には 2 つの系統が同居します(docs/concepts.ja.md の三面構造)。

system
├─ user → client → service (アクセス経路:誰が、どの面を介して、何に到達するか)
└─ service → domain → usecase → resource (サービス階層:各サービスの内部構造)

境界設計ガイドオンボーディングガイド が主に下段(サービス階層)を扱ったのに対し、このガイドは上段(アクセス経路)に焦点を当てます。


1. user — 人間と AI エージェント

Section titled “1. user — 人間と AI エージェント”

user はシステムを駆動するアクターです。タグで人間([human])と AI エージェント([ai])を区別し、role で業務上の役割を一行で記述します。

system Shop {
user Customer [human] {
label "購入者"
role "商品を購入する一般ユーザー"
}
user Ops [ai] {
label "運用エージェント"
role "在庫を監視して自動発注する AI"
}
}

AI エージェントを [ai]user として一級に描けるのが karasu の特徴です。「人間の購入者」と「自動化エージェント」が同じシステムをどう駆動するかを並置できます。

roleauthz primitive ではありません — RBAC の permission や requires role 述語ではなく、「このユーザーが何をするか」の要約です。認可制約は descriptionアクセス: 規約と policy リンクで表します(docs/spec/syntax.ja.md の認可ノート節)。


2. client — 自社が出荷するソフトウェア

Section titled “2. client — 自社が出荷するソフトウェア”

clientエンドユーザーの委譲で動く、自社が配布するクライアントソフトウェア です。userservice の間に位置します。form-factor タグで種類を示します。

タグForm factor
[mobile]iOS / Android ネイティブアプリ
[web]自社オリジンで動く SPA
[desktop]デスクトップアプリ(Electron / ネイティブ)
[cli]エンドユーザーに配布する CLI / SDK
[device]IoT / 専用端末 / KIOSK
[extension]他アプリがホストする拡張(ブラウザ / IDE 拡張)
[embed]サードパーティ Web に埋め込む widget / SDK
client MobileApp [mobile] {
label "モバイルアプリ"
description "iOS / Android 向け公式アプリ"
}
client WebApp [web] {
label "Web アプリ"
}

clientuser の境界: clientプロジェクト自身が配布するソフトウェア に限ります。サードパーティのブラウザ・IDE・外部 AI エージェントがシステムを利用する場合は、client ではなく user[human] / [ai])でモデル化します。「自分たちが出荷したか」が判断基準です(ADR-20260428-06)。


user -> client -> service をエッジで繋ぎ、到達経路を描きます。

system Shop {
user Customer [human] { label "購入者" }
client MobileApp [mobile] { label "モバイルアプリ" }
client WebApp [web] { label "Web アプリ" }
service Backend {
label "バックエンド"
domain Order { label "受注" }
}
Customer -> MobileApp "アプリを使う"
Customer -> WebApp "ブラウザで使う"
MobileApp -> Backend "API 呼び出し"
WebApp -> Backend "API 呼び出し"
}

system view — 04-access-path

これで「購入者はモバイルと Web の 2 つの面からバックエンドに到達する」が俯瞰で読めます。クライアントとサービスの間の通常の API 呼び出しは普通の -> で書きます。


4. handles — クライアント/サービスが公開するドメイン

Section titled “4. handles — クライアント/サービスが公開するドメイン”

clientservicehandles呼び出し側に公開するドメイン id を宣言できます。これは検証付きクロスリファレンスで、公開するドメインが 1 ホップの expose ルールで到達可能でなければ unresolved-handles 警告が出ます。

system Shop {
service Backend {
domain Order {} // 自身が所有 — handles 不要
}
service Bff {
handles Order // 再公開: Order は Backend が所有し、下のエッジ経由で到達
}
client WebApp [web] {
handles Order // BFF 経由でエンドユーザーに Order を公開
}
WebApp -> Bff
Bff -> Backend
}

system view — 04-handles

expose ルール: ノード N がドメイン D を expose するのは、(1) N が domain D を子に持つ(自身が所有)、または (2) N が handles D を宣言し、かつ少なくとも 1 本の outgoing 通信エッジの宛先も D を expose しているとき。ルールは 1 ホップずつ展開されるので、client → BFF → backend の各リンクを明示的に宣言する必要があります(暗黙の auto-passthrough はありません)。

これにより「この Web アプリは結局どのドメインをエンドユーザーに見せているのか」が、経路の整合性込みで検証されます。


serviceclient配布する 関係(Next.js / Rails+React / Laravel+Vue のような BFF / SSR)は delivers で宣言します。サーバーサイドのバンドルとブラウザサイドのバンドルは OAuth2 client タイプが異なる別ノードとして扱い、delivers で結びます。

service NextBff {
label "Next.js BFF"
delivers WebApp // 単一
}
service Gateway {
delivers WebApp, AdminUI // カンマ区切り
}
client WebApp [web] {}
client AdminUI [desktop] {}

delivers の各エントリは、system view 上で service から参照先 client への 破線エッジ に合成されます。delivers は宣言的プロパティで、新しいエッジ種別ではありません。client と service 間の通常の API 呼び出しは引き続き -> で書きます。参照先が client に解決できないと delivers-target-not-client 警告が出ます。


6. クライアント側の resourcecapability

Section titled “6. クライアント側の resource と capability”

クライアントは固有の状態と権限を持ちます。これらを描くと、プロダクトの「面」のセキュリティ・データ局所性が見えます。

resource <storageKind> "<name>" — クライアント上のローカルストレージ。localStorage / sessionStorage / indexedDB / opfs / file / keychain の 6 種から選びます(認証クレデンシャルが黙って紛れ込まないよう種別を限定)。

capability <name> — クライアントが要求するデバイス / ブラウザ capability(camera / geolocation / notification など)。任意の kebab-case 識別子を受け付けます。

client MobileApp [mobile] {
label "モバイルアプリ"
handles Order
resource localStorage "preferences"
resource indexedDB "outbox" // オフライン送信キュー
capability notification
capability camera {
description "QR コード読み取り" // なぜこの capability か(脅威モデリング用メモ)
}
}

resource は client が読み書きするストレージ、capability は OS / browser が許可を与える機能、という別概念です。SVG カードはそれぞれ 📦 ×N / 🔐 ×N のカウントバッジで表示し、完全リストは詳細パネルに出ます。

cookie / session / 生クレデンシャルのストレージ、および脅威モデリングそのものは意図的に対象外です(karasu は基礎事実をモデル化するが、セキュリティ規律の shape は語彙に固定しない — ADR-20260430-01)。


7. まとめ — 面と内部を別系統で描く

Section titled “7. まとめ — 面と内部を別系統で描く”

アクセス経路(user → client → service)はプロダクトの 入口の地図 を、サービス階層(service → domain → usecase)は各サービスの 内部構造 を描きます。両者を同じ system の中に持ちつつ、ドリルダウンで見る系統を切り替えられるのが karasu の設計です。

完全な例は examples/ja/ec-platform/02.5-clients.krs(client + handles + delivers + resource)と、MCP / AI エージェントを含む examples/en/client-mcp/ を参照してください。


© 2026 Hiroki Kondo · Licensed under Apache-2.0