[{"data":1,"prerenderedAt":684},["ShallowReactive",2],{"navigation":3,"doc-/backend/layering":217,"docs-all-paths":629},[4,19,39,63,87,111,127,195,211],{"title":5,"path":6,"stem":7,"children":8},"Welcome","/welcome","01.welcome",[9,11,15],{"title":5,"path":6,"stem":10},"01.welcome/index",{"title":12,"path":13,"stem":14},"Astar とは（5分）","/welcome/product-in-5-min","01.welcome/01.product-in-5-min",{"title":16,"path":17,"stem":18},"事業文脈","/welcome/business-context","01.welcome/02.business-context",{"title":20,"path":21,"stem":22,"children":23},"Getting Started","/getting-started","02.getting-started",[24,27,31,35],{"title":25,"path":21,"stem":26},"はじめかた","02.getting-started/index",{"title":28,"path":29,"stem":30},"リポジトリ取得と環境構築","/getting-started/repo-setup","02.getting-started/01.repo-setup",{"title":32,"path":33,"stem":34},"日々の開発ループ","/getting-started/dev-loop","02.getting-started/02.dev-loop",{"title":36,"path":37,"stem":38},"検証の 4 層","/getting-started/verification-tiers","02.getting-started/03.verification-tiers",{"title":40,"path":41,"stem":42,"children":43},"Architecture","/architecture","03.architecture",[44,47,51,55,59],{"title":45,"path":41,"stem":46},"アーキテクチャ","03.architecture/index",{"title":48,"path":49,"stem":50},"マルチテナンシーと RLS","/architecture/multi-tenancy-rls","03.architecture/01.multi-tenancy-rls",{"title":52,"path":53,"stem":54},"認可モデル","/architecture/authorization","03.architecture/02.authorization",{"title":56,"path":57,"stem":58},"AI サブシステム","/architecture/ai-subsystem","03.architecture/03.ai-subsystem",{"title":60,"path":61,"stem":62},"データモデル","/architecture/data-model","03.architecture/04.data-model",{"title":64,"path":65,"stem":66,"children":67},"Backend","/backend","04.backend",[68,71,75,79,83],{"title":69,"path":65,"stem":70},"バックエンド","04.backend/index",{"title":72,"path":73,"stem":74},"層構造","/backend/layering","04.backend/01.layering",{"title":76,"path":77,"stem":78},"規約","/backend/conventions","04.backend/02.conventions",{"title":80,"path":81,"stem":82},"テスト","/backend/testing","04.backend/03.testing",{"title":84,"path":85,"stem":86},"マイグレーション","/backend/migrations","04.backend/04.migrations",{"title":88,"path":89,"stem":90,"children":91},"Frontend","/frontend","05.frontend",[92,95,99,103,107],{"title":93,"path":89,"stem":94},"フロントエンド","05.frontend/index",{"title":96,"path":97,"stem":98},"モジュール内部構造","/frontend/module-anatomy","05.frontend/01.module-anatomy",{"title":100,"path":101,"stem":102},"API アクセスの一本道","/frontend/api-access-chain","05.frontend/02.api-access-chain",{"title":104,"path":105,"stem":106},"i18n","/frontend/i18n","05.frontend/03.i18n",{"title":108,"path":109,"stem":110},"デザインシステム","/frontend/design-system","05.frontend/04.design-system",{"title":112,"path":113,"stem":114,"children":115},"Go Agent And Cli","/go-agent-and-cli","06.go-agent-and-cli",[116,119,123],{"title":117,"path":113,"stem":118},"Go agent と CLI","06.go-agent-and-cli/index",{"title":120,"path":121,"stem":122},"Go agent","/go-agent-and-cli/go-agent","06.go-agent-and-cli/01.go-agent",{"title":124,"path":125,"stem":126},"CLI","/go-agent-and-cli/cli","06.go-agent-and-cli/02.cli",{"title":128,"path":129,"stem":130,"children":131},"Modules","/modules","07.modules",[132,135,139,143,147,151,155,159,163,167,171,175,179,183,187,191],{"title":133,"path":129,"stem":134},"モジュール","07.modules/index",{"title":136,"path":137,"stem":138},"テーブル","/modules/table","07.modules/01.table",{"title":140,"path":141,"stem":142},"ドキュメントツリー","/modules/document","07.modules/02.document",{"title":144,"path":145,"stem":146},"AIチャット","/modules/ai","07.modules/03.ai",{"title":148,"path":149,"stem":150},"認証・権限","/modules/auth","07.modules/04.auth",{"title":152,"path":153,"stem":154},"AI取込","/modules/organize","07.modules/05.organize",{"title":156,"path":157,"stem":158},"ストレージ","/modules/storage","07.modules/06.storage",{"title":160,"path":161,"stem":162},"NAS同期","/modules/sync","07.modules/07.sync",{"title":164,"path":165,"stem":166},"ワークスペース","/modules/workspace","07.modules/08.workspace",{"title":168,"path":169,"stem":170},"テナントとメンバーシップ","/modules/tenant-membership","07.modules/09.tenant-membership",{"title":172,"path":173,"stem":174},"検索","/modules/search","07.modules/10.search",{"title":176,"path":177,"stem":178},"表示ビュー","/modules/display","07.modules/11.display",{"title":180,"path":181,"stem":182},"テンプレート","/modules/template","07.modules/12.template",{"title":184,"path":185,"stem":186},"メール","/modules/mail","07.modules/13.mail",{"title":188,"path":189,"stem":190},"電話","/modules/phone","07.modules/14.phone",{"title":192,"path":193,"stem":194},"リアルタイム","/modules/realtime","07.modules/15.realtime",{"title":196,"path":197,"stem":198,"children":199},"Infra And Deploy","/infra-and-deploy","08.infra-and-deploy",[200,203,207],{"title":201,"path":197,"stem":202},"インフラとデプロイ","08.infra-and-deploy/index",{"title":204,"path":205,"stem":206},"環境の種類","/infra-and-deploy/environments","08.infra-and-deploy/01.environments",{"title":208,"path":209,"stem":210},"セルフホスト構成","/infra-and-deploy/self-host","08.infra-and-deploy/02.self-host",{"title":212,"path":213,"stem":214,"children":215},"docs-map","/docs-map","09.docs-map/index",[216],{"title":212,"path":213,"stem":214},{"id":218,"title":72,"body":219,"description":623,"extension":624,"meta":625,"navigation":626,"path":73,"seo":627,"stem":74,"__hash__":628},"docs/04.backend/01.layering.md",{"type":220,"value":221,"toc":612},"minimark",[222,225,238,246,256,307,335,342,348,354,382,388,451,454,461,497,501,507,609],[223,224,72],"h1",{"id":72},[226,227,228,229,233,234,237],"p",{},"Astar のバックエンドは Spring Modulith で、",[230,231,232],"code",{},"core/"," 配下に 47 個のドメインモジュール、",[230,235,236],{},"shared/"," 配下に 11 個の横断モジュールがあります。すべてのモジュールが同じ 3 層規約に従います。",[239,240,242,245],"h2",{"id":241},"coremodule-の-3-層",[230,243,244],{},"core/{module}/"," の 3 層",[247,248,253],"pre",{"className":249,"code":251,"language":252},[250],"language-text","core/{module}/\n├── api/{controller,dto,mapper}                        # HTTP 層\n├── domain/{model,repository,service,port,event,config,exception}\n└── infrastructure/\n    ├── persistence/{table,repository,resolver}          # Exposed DB 層\n    ├── adapter/        # Port の実装\n    ├── config/         # @Configuration / @ConfigurationProperties\n    ├── listener/        # @TransactionalEventListener / @Async — domain/ には置かない\n    └── scheduler/        # @Scheduled — domain/ には置かない\n","text",[230,254,251],{"__ignoreMap":255},"",[257,258,259,275,293],"ul",{},[260,261,262,266,267,270,271,274],"li",{},[263,264,265],"strong",{},"api/",": HTTP の窓口。Controller は Service に委譲するだけで、ビジネスロジックを持たない。DTO は ",[230,268,269],{},"kotlinx.serialization"," で（詳細は ",[272,273,76],"a",{"href":77}," 参照）。",[260,276,277,280,281,284,285,288,289,292],{},[263,278,279],{},"domain/",": ビジネスロジックの本体。",[230,282,283],{},"model/"," は不変 data class、",[230,286,287],{},"repository/"," はドメイン型だけを話す interface（実装は infrastructure 側）、",[230,290,291],{},"service/"," がユースケースとトランザクション境界を持つ。",[260,294,295,298,299,302,303,306],{},[263,296,297],{},"infrastructure/",": 技術的関心事の実装。DB アクセス (Exposed)、外部サービス連携 (Port の実装)、非同期処理 (",[230,300,301],{},"@Async"," リスナー、",[230,304,305],{},"@Scheduled"," ジョブ) はすべてここに閉じ込める。",[226,308,309,310,313,314,316,317,319,320,323,324,327,328,330,331,334],{},"依存の向きは ",[263,311,312],{},"api → domain → infrastructure"," の一方向です。",[230,315,279],{}," は ",[230,318,297],{}," の実装クラスを知らず、",[230,321,322],{},"domain/repository"," の interface 越しにしか DB を触りません。この向きが逆転する典型例（",[230,325,326],{},"Controller"," が Repository を直接呼ぶ、",[230,329,326],{}," に ",[230,332,333],{},"@Transactional"," を書く）は現状 ArchUnit ルールが存在せず CI で検知されないので、レビューで見る必要があります。",[239,336,338,339],{"id":337},"参照実装-coretag","参照実装: ",[230,340,341],{},"core/tag/",[226,343,344,345,347],{},"一番小さく、規約に最も忠実な完全実装が ",[230,346,341],{}," です。迷ったらまずここを読んでください。",[247,349,352],{"className":350,"code":351,"language":252},[250],"core/tag/\n├── api/\n│   ├── controller/TagController.kt\n│   └── dto/\n│       ├── TagCreateRequest.kt\n│       ├── TagDto.kt\n│       ├── TaggableDto.kt\n│       └── TagUpdateRequest.kt\n├── domain/\n│   ├── exception/TagNotFoundException.kt\n│   ├── model/\n│   │   ├── Tag.kt\n│   │   ├── Taggable.kt\n│   │   └── TaggableType.kt\n│   ├── repository/\n│   │   ├── TaggableRepository.kt        # interface — ドメイン型のみ\n│   │   └── TagRepository.kt\n│   └── service/\n│       ├── TaggingService.kt\n│       └── TagService.kt\n└── infrastructure/\n    ├── adapter/TagTenantResolutionAdapter.kt\n    └── persistence/\n        ├── repository/\n        │   ├── TagExposedRepositoryImpl.kt      # TagRepository の実装\n        │   └── TaggableExposedRepositoryImpl.kt\n        ├── resolver/TagIdResolver.kt\n        └── table/\n            ├── TagsTable.kt                       # Exposed table object = カラム定義の SSoT\n            └── TaggablesTable.kt\n",[230,353,351],{"__ignoreMap":255},[226,355,356,359,360,363,364,367,368,359,371,374,375,378,379,381],{},[230,357,358],{},"TagRepository","（",[230,361,362],{},"domain/repository/","）は interface で ",[230,365,366],{},"Tag"," などのドメイン型しか登場しません。実装クラス ",[230,369,370],{},"TagExposedRepositoryImpl",[230,372,373],{},"infrastructure/persistence/repository/","）が ",[230,376,377],{},"TagsTable","（Exposed table object）を使って実際の SQL を発行します。この分離のおかげで、",[230,380,279],{}," 側のコードは「DB が Exposed である」ことすら知らずに書けます。",[239,383,385,387],{"id":384},"shared-の位置づけ",[230,386,236],{}," の位置づけ",[226,389,390,392,393,395,396,395,399,395,401,395,404,395,407,395,409,395,412,395,415,395,418,395,421,424,425,428,429,432,433,432,436,439,440,443,444,450],{},[230,391,236],{}," は特定モジュールに属さない横断的な関心事です。",[230,394,265],{}," ",[230,397,398],{},"application/",[230,400,279],{},[230,402,403],{},"exception/",[230,405,406],{},"extension/",[230,408,297],{},[230,410,411],{},"testing/",[230,413,414],{},"toolcontext/",[230,416,417],{},"util/",[230,419,420],{},"validation/",[230,422,423],{},"workflow/"," の 11 サブディレクトリがあり、たとえば ",[230,426,427],{},"EntityId\u003CT>","（型安全な ID ラッパー）、RLS 機構一式（",[230,430,431],{},"RLSInterceptor","・",[230,434,435],{},"RlsDispatchers",[230,437,438],{},"RlsTransactions","）、",[230,441,442],{},"WebMvcConfig","（kotlinx.serialization 用の HTTP メッセージコンバータ設定）などがここに置かれています。",[263,445,446,447,449],{},"モジュール固有のロジックを ",[230,448,236],{}," に置かない"," — 2 つ以上のモジュールが本当に必要とするものだけがここに来ます。",[239,452,453],{"id":453},"モジュールをまたぐ依存",[226,455,456,457,460],{},"モジュール間の呼び出しは基本的に避け、必要な場合は ",[230,458,459],{},"ModuleBoundaryTest.INTENTIONAL_CROSS_DOMAIN_TARGETS"," に明示的に登録されたパスのみ許可されます。新しいモジュール間依存を追加する前に、既存の登録例を確認してください。",[226,462,463,466,467,470,471,470,474,470,477,470,480,470,483,470,486,470,489,492,493,496],{},[230,464,465],{},"core/organize/"," のように、単一モジュール内をさらに機能パッケージ（",[230,468,469],{},"extraction","/",[230,472,473],{},"citation",[230,475,476],{},"review",[230,478,479],{},"publicaccess",[230,481,482],{},"interview",[230,484,485],{},"convert",[230,487,488],{},"workflow",[230,490,491],{},"pack","）に分割し、パッケージ間の許可された依存だけを ArchUnit（",[230,494,495],{},"OrganizeFeatureBoundaryTest","）で固定しているケースもあります。モジュールが育つと、この「モジュール内サブ境界」パターンが選択肢になります。",[239,498,500],{"id":499},"最初に踏みやすい-choke-point","最初に踏みやすい choke point",[226,502,503,506],{},[230,504,505],{},"backend/CLAUDE.md"," の Choke Points 表（全量）から、新人がまず遭遇しやすいものを抜粋します。「似た機能を作る前に、まずこれで足りないか確認する」ためのリストです。",[508,509,510,526],"table",{},[511,512,513],"thead",{},[514,515,516,520,523],"tr",{},[517,518,519],"th",{},"やりたいこと",[517,521,522],{},"使うべき choke point",[517,524,525],{},"自分で書いてはいけないもの",[527,528,529,547,563,585],"tbody",{},[514,530,531,535,544],{},[532,533,534],"td",{},"ドキュメント/フォルダの作成・更新・削除",[532,536,537,359,540,543],{},[230,538,539],{},"StorageAwareDocumentService",[230,541,542],{},"core/editor/domain/service/","）",[532,545,546],{},"NAS と DB の整合を取る CUD ロジックの自前実装",[514,548,549,552,560],{},[532,550,551],{},"レコード作成",[532,553,554,359,557,543],{},[230,555,556],{},"RecordService.persistNewRecords",[230,558,559],{},"core/table/",[532,561,562],{},"テーブルへの直接 INSERT・バリデーションのバイパス",[514,564,565,568,582],{},[532,566,567],{},"認可判定",[532,569,570,573,574,577,578,581],{},[230,571,572],{},"AuthorizationService"," + ",[230,575,576],{},"CustomMethodSecurityExpressionRoot"," の primitive (",[230,579,580],{},"canAccessResource"," 等)",[532,583,584],{},"Service 層での手書き権限チェック",[514,586,587,590,603],{},[532,588,589],{},"外部 URL へのアクセス (AI fetch / mail / bot 等)",[532,591,592,595,596,595,599,602],{},[230,593,594],{},"EgressGuard"," / ",[230,597,598],{},"SsrfGuard",[230,600,601],{},"WebhookUrlValidator","（用途別に使い分け）",[532,604,605,608],{},[230,606,607],{},"HttpClient"," での直接リクエスト",[226,610,611],{},"これらはすべて ArchUnit テストや専用ガードで守られています。似た機能を追加する前に「既存の choke point で表現できないか」を先に確認するのが最短ルートです。",{"title":255,"searchDepth":613,"depth":613,"links":614},2,[615,617,619,621,622],{"id":241,"depth":613,"text":616},"core/{module}/ の 3 層",{"id":337,"depth":613,"text":618},"参照実装: core/tag/",{"id":384,"depth":613,"text":620},"shared/ の位置づけ",{"id":453,"depth":613,"text":453},{"id":499,"depth":613,"text":500},"core/{module}/ の api → domain → infrastructure 3 層規約を、最小の完全な参照実装 core/tag/ で確認する。","md",{},{"title":72},{"title":72,"description":623},"j_g0eGTVg0dams6p-Jvp9hQTbKpy4I4r20AqzK7WrQo",[630,632,633,635,636,637,638,639,640,641,642,643,645,646,647,648,649,651,652,653,654,655,657,659,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,679,680,681,682],{"path":13,"title":631},"Astar とは何か（5分で）",{"path":17,"title":16},{"path":6,"title":634},"ようこそ",{"path":29,"title":28},{"path":33,"title":32},{"path":37,"title":36},{"path":21,"title":25},{"path":49,"title":48},{"path":53,"title":52},{"path":57,"title":56},{"path":61,"title":60},{"path":41,"title":644},"システムアーキテクチャ",{"path":73,"title":72},{"path":77,"title":76},{"path":81,"title":80},{"path":85,"title":84},{"path":65,"title":650},"バックエンドガイド",{"path":97,"title":96},{"path":101,"title":100},{"path":105,"title":104},{"path":109,"title":108},{"path":89,"title":656},"フロントエンドガイド",{"path":121,"title":658},"Go agent — NAS 同期エージェント",{"path":125,"title":660},"astar CLI",{"path":113,"title":117},{"path":137,"title":136},{"path":141,"title":140},{"path":145,"title":144},{"path":149,"title":148},{"path":153,"title":152},{"path":157,"title":156},{"path":161,"title":160},{"path":165,"title":164},{"path":169,"title":168},{"path":173,"title":172},{"path":177,"title":176},{"path":181,"title":180},{"path":185,"title":184},{"path":189,"title":188},{"path":193,"title":192},{"path":129,"title":678},"モジュール索引",{"path":205,"title":204},{"path":209,"title":208},{"path":197,"title":201},{"path":213,"title":683},"docs/ 地図",1785452454980]