[{"data":1,"prerenderedAt":927},["ShallowReactive",2],{"navigation":3,"doc-/architecture/multi-tenancy-rls":217,"docs-all-paths":872},[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":48,"body":219,"description":866,"extension":867,"meta":868,"navigation":869,"path":49,"seo":870,"stem":50,"__hash__":871},"docs/03.architecture/01.multi-tenancy-rls.md",{"type":220,"value":221,"toc":858},"minimark",[222,226,240,245,256,338,352,372,382,386,389,399,406,452,463,466,473,629,659,662,665,724,739,743,754,761,788,801,805,838,854],[223,224,48],"h1",{"id":225},"マルチテナンシーと-rls",[227,228,229,230,234,235,239],"p",{},"Astar のマルチテナント分離は ",[231,232,233],"strong",{},"PostgreSQL の Row Level Security (RLS)"," で実現しています。アプリケーションコードの ",[236,237,238],"code",{},"WHERE tenant_id = ..."," の書き忘れに依存せず、DB 側で強制するのが設計の核です。",[241,242,244],"h2",{"id":243},"_2層セキュリティモデル","2層セキュリティモデル",[227,246,247,248,251,252,255],{},"すべてのテーブルに RLS がかかっているわけではありません。",[231,249,250],{},"ビジネスデータ","と",[231,253,254],{},"認証メタデータ","で保護方式を分けています。",[257,258,259,275],"table",{},[260,261,262],"thead",{},[263,264,265,269,272],"tr",{},[266,267,268],"th",{},"分類",[266,270,271],{},"対象テーブル（例）",[266,273,274],{},"保護方式",[276,277,278,311],"tbody",{},[263,279,280,283,305],{},[281,282,250],"td",{},[281,284,285,288,289,288,292,288,295,288,298,288,301,304],{},[236,286,287],{},"workspaces"," / ",[236,290,291],{},"tables",[236,293,294],{},"records",[236,296,297],{},"document_nodes",[236,299,300],{},"tags",[236,302,303],{},"templates"," など",[281,306,307,310],{},[236,308,309],{},"FORCE ROW LEVEL SECURITY","（DB層で強制）",[263,312,313,315,335],{},[281,314,254],{},[281,316,317,288,320,288,323,288,326,288,329,288,332],{},[236,318,319],{},"users",[236,321,322],{},"tenants",[236,324,325],{},"tenant_users",[236,327,328],{},"roles",[236,330,331],{},"user_roles",[236,333,334],{},"role_permissions",[281,336,337],{},"RLS 無効。アプリ層（Repository）でフィルタリング",[227,339,340,341,344,345,347,348,351],{},"認証メタデータに RLS をかけない理由は",[231,342,343],{},"循環依存","です。JWT が届いた時点ではまだテナントコンテキストが確立していないのに、ユーザー認証にはまさにそのテナント情報（",[236,346,325],{}," 等）を読む必要があります。RLS は ",[236,349,350],{},"app.current_tenant_id"," の設定を前提とするため、「認証してからでないと RLS が効かないテーブルを、RLS が効く前提で読む」という矛盾が生まれます。これは業界標準の対処で、認証に必要な最小限のテーブルだけ RLS の外に置き、代わりにリポジトリ層でテナント/ユーザーフィルタを書きます。",[227,353,354,355,358,359,288,362,288,365,288,368,371],{},"除外テーブル一覧のSSoTはコード側 ",[236,356,357],{},"architecture/RlsCoverageExemptions.kt","（",[236,360,361],{},"AUTH_METADATA",[236,363,364],{},"INFRASTRUCTURE",[236,366,367],{},"GLOBAL_NO_TENANT",[236,369,370],{},"TENANT_SERVICE_LAYER_ENFORCED"," の4分類）です。新しいテーブルを RLS 対象外にできるかどうかは、必ずこのコードを確認してください——ドキュメント側の一覧は変わり得るスナップショットに過ぎません。",[373,374,376],"callout",{"type":375},"warning",[227,377,378,381],{},[236,379,380],{},"docs/infrastructure/multitenancy.md"," は現行方式と矛盾する古い3層プラン案です。参照しないでください。RLS が現行唯一の方式です。",[241,383,385],{"id":384},"guc-チェーン","GUC チェーン",[227,387,388],{},"RLS ポリシーは PostgreSQL のセッション変数（GUC）に依存します。このチェーンを誰が・いつ設定するかが RLS の心臓部です。",[390,391,396],"pre",{"className":392,"code":394,"language":395},[393],"language-text","TenantContextFilter（リクエスト受信時）\n    ↓\nTenantContextService（ThreadLocal に保持）\n    ↓\nRLSInterceptor（@Transactional への AOP アドバイス。トランザクションごとに1回だけ dedup）\n    ↓\nset_config（PostgreSQL セッションへ実際に反映）\n","text",[236,397,394],{"__ignoreMap":398},"",[227,400,401,402,405],{},"ポリシー本体は必ず ",[236,403,404],{},"public.current_tenant_id()"," ヘルパー関数経由で書きます。",[390,407,411],{"className":408,"code":409,"language":410,"meta":398,"style":398},"language-sql shiki shiki-themes github-light github-dark","-- OK\nCREATE POLICY tenant_isolation ON public.foo\n    USING (tenant_id = public.current_tenant_id());\n\n-- NG: current_setting() のインライン展開は禁止\nUSING (tenant_id = NULLIF(current_setting('app.current_tenant_id', true), '')::bigint)\n","sql",[236,412,413,421,427,433,440,446],{"__ignoreMap":398},[414,415,418],"span",{"class":416,"line":417},"line",1,[414,419,420],{},"-- OK\n",[414,422,424],{"class":416,"line":423},2,[414,425,426],{},"CREATE POLICY tenant_isolation ON public.foo\n",[414,428,430],{"class":416,"line":429},3,[414,431,432],{},"    USING (tenant_id = public.current_tenant_id());\n",[414,434,436],{"class":416,"line":435},4,[414,437,439],{"emptyLinePlaceholder":438},true,"\n",[414,441,443],{"class":416,"line":442},5,[414,444,445],{},"-- NG: current_setting() のインライン展開は禁止\n",[414,447,449],{"class":416,"line":448},6,[414,450,451],{},"USING (tenant_id = NULLIF(current_setting('app.current_tenant_id', true), '')::bigint)\n",[373,453,454],{"type":375},[227,455,456,459,460,462],{},[236,457,458],{},"current_setting()"," を直接インラインで書いたポリシーは、過去に何度も修正対象になっています。必ず ",[236,461,404],{}," を使ってください。",[241,464,465],{"id":465},"新しいテーブルを作るときの必須パターン",[227,467,468,469,472],{},"実際のマイグレーション（",[236,470,471],{},"V406__create_local_calendar_events.sql","）から、必須要素を抜粋します。",[390,474,476],{"className":408,"code":475,"language":410,"meta":398,"style":398},"CREATE TABLE public.local_calendar_events (\n    id                       BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,\n    public_id                UUID NOT NULL DEFAULT gen_random_uuid(),\n    tenant_id                BIGINT NOT NULL,\n    -- ドメインカラム ...\n    CONSTRAINT local_calendar_events_public_id_key UNIQUE (public_id),\n    CONSTRAINT local_calendar_events_tenant_id_id_unique UNIQUE (tenant_id, id),\n    CONSTRAINT local_calendar_events_tenant_id_fkey FOREIGN KEY (tenant_id)\n        REFERENCES public.tenants(id) ON DELETE CASCADE\n);\n\nALTER TABLE public.local_calendar_events ENABLE ROW LEVEL SECURITY;\nALTER TABLE public.local_calendar_events FORCE ROW LEVEL SECURITY;\n\nCREATE POLICY local_calendar_events_select ON public.local_calendar_events\n    FOR SELECT USING (tenant_id = public.current_tenant_id() AND user_id = public.current_user_id());\n\nCREATE POLICY local_calendar_events_insert ON public.local_calendar_events\n    FOR INSERT WITH CHECK (tenant_id = public.current_tenant_id() AND user_id = public.current_user_id());\n\nCREATE POLICY local_calendar_events_update ON public.local_calendar_events\n    FOR UPDATE\n    USING     (tenant_id = public.current_tenant_id() AND user_id = public.current_user_id())\n    WITH CHECK (tenant_id = public.current_tenant_id() AND user_id = public.current_user_id());\n\nCREATE POLICY local_calendar_events_delete ON public.local_calendar_events\n    FOR DELETE USING (tenant_id = public.current_tenant_id() AND user_id = public.current_user_id());\n",[236,477,478,483,488,493,498,503,508,514,520,526,532,537,543,549,554,560,566,571,577,583,588,594,600,606,612,617,623],{"__ignoreMap":398},[414,479,480],{"class":416,"line":417},[414,481,482],{},"CREATE TABLE public.local_calendar_events (\n",[414,484,485],{"class":416,"line":423},[414,486,487],{},"    id                       BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,\n",[414,489,490],{"class":416,"line":429},[414,491,492],{},"    public_id                UUID NOT NULL DEFAULT gen_random_uuid(),\n",[414,494,495],{"class":416,"line":435},[414,496,497],{},"    tenant_id                BIGINT NOT NULL,\n",[414,499,500],{"class":416,"line":442},[414,501,502],{},"    -- ドメインカラム ...\n",[414,504,505],{"class":416,"line":448},[414,506,507],{},"    CONSTRAINT local_calendar_events_public_id_key UNIQUE (public_id),\n",[414,509,511],{"class":416,"line":510},7,[414,512,513],{},"    CONSTRAINT local_calendar_events_tenant_id_id_unique UNIQUE (tenant_id, id),\n",[414,515,517],{"class":416,"line":516},8,[414,518,519],{},"    CONSTRAINT local_calendar_events_tenant_id_fkey FOREIGN KEY (tenant_id)\n",[414,521,523],{"class":416,"line":522},9,[414,524,525],{},"        REFERENCES public.tenants(id) ON DELETE CASCADE\n",[414,527,529],{"class":416,"line":528},10,[414,530,531],{},");\n",[414,533,535],{"class":416,"line":534},11,[414,536,439],{"emptyLinePlaceholder":438},[414,538,540],{"class":416,"line":539},12,[414,541,542],{},"ALTER TABLE public.local_calendar_events ENABLE ROW LEVEL SECURITY;\n",[414,544,546],{"class":416,"line":545},13,[414,547,548],{},"ALTER TABLE public.local_calendar_events FORCE ROW LEVEL SECURITY;\n",[414,550,552],{"class":416,"line":551},14,[414,553,439],{"emptyLinePlaceholder":438},[414,555,557],{"class":416,"line":556},15,[414,558,559],{},"CREATE POLICY local_calendar_events_select ON public.local_calendar_events\n",[414,561,563],{"class":416,"line":562},16,[414,564,565],{},"    FOR SELECT USING (tenant_id = public.current_tenant_id() AND user_id = public.current_user_id());\n",[414,567,569],{"class":416,"line":568},17,[414,570,439],{"emptyLinePlaceholder":438},[414,572,574],{"class":416,"line":573},18,[414,575,576],{},"CREATE POLICY local_calendar_events_insert ON public.local_calendar_events\n",[414,578,580],{"class":416,"line":579},19,[414,581,582],{},"    FOR INSERT WITH CHECK (tenant_id = public.current_tenant_id() AND user_id = public.current_user_id());\n",[414,584,586],{"class":416,"line":585},20,[414,587,439],{"emptyLinePlaceholder":438},[414,589,591],{"class":416,"line":590},21,[414,592,593],{},"CREATE POLICY local_calendar_events_update ON public.local_calendar_events\n",[414,595,597],{"class":416,"line":596},22,[414,598,599],{},"    FOR UPDATE\n",[414,601,603],{"class":416,"line":602},23,[414,604,605],{},"    USING     (tenant_id = public.current_tenant_id() AND user_id = public.current_user_id())\n",[414,607,609],{"class":416,"line":608},24,[414,610,611],{},"    WITH CHECK (tenant_id = public.current_tenant_id() AND user_id = public.current_user_id());\n",[414,613,615],{"class":416,"line":614},25,[414,616,439],{"emptyLinePlaceholder":438},[414,618,620],{"class":416,"line":619},26,[414,621,622],{},"CREATE POLICY local_calendar_events_delete ON public.local_calendar_events\n",[414,624,626],{"class":416,"line":625},27,[414,627,628],{},"    FOR DELETE USING (tenant_id = public.current_tenant_id() AND user_id = public.current_user_id());\n",[227,630,631,632,635,636,639,640,642,643,646,647,653,654,658],{},"このテーブルは所有者スコープ（",[236,633,634],{},"tenant_id"," に加えて ",[236,637,638],{},"user_id"," も絞る）の例です。テナント全体で共有するテーブルなら ",[236,641,638],{}," 条件は不要ですが、",[231,644,645],{},"4ポリシー全部","（SELECT/INSERT/UPDATE/DELETE）と、",[231,648,649,650],{},"UPDATE の ",[236,651,652],{},"WITH CHECK","（付け忘れると別テナントへの書き換えが通ってしまう）は必須です。マイグレーションの詳しい規約は ",[655,656,657],"a",{"href":85},"バックエンドガイド／マイグレーション"," を参照してください。",[241,660,661],{"id":661},"テナント指定の3層規約",[227,663,664],{},"エンドポイントがどこからテナントIDを取るかは、3パターンしかありません（4つ目を発明することは禁止されています）。",[257,666,667,680],{},[260,668,669],{},[263,670,671,674,677],{},[266,672,673],{},"種別",[266,675,676],{},"指定方法",[266,678,679],{},"理由",[276,681,682,699,713],{},[263,683,684,687,693],{},[281,685,686],{},"テナント内エンドポイント",[281,688,689,692],{},[236,690,691],{},"X-Tenant-Id"," ヘッダー",[281,694,695,698],{},[236,696,697],{},"TenantContextFilter"," が RLS コンテキストを設定",[263,700,701,704,710],{},[281,702,703],{},"プラットフォーム管理者のクロステナント操作",[281,705,706,709],{},[236,707,708],{},"/tenants/{tenantId}/"," パス変数",[281,711,712],{},"運用者は顧客テナントに所属しないためヘッダーを張れない",[263,714,715,718,721],{},[281,716,717],{},"（禁止）",[281,719,720],{},"クエリパラメータでのテナント指定",[281,722,723],{},"どちらの規約でもない逸脱",[227,725,726,727,730,731,734,735,738],{},"例外は SSE の ",[236,728,729],{},"EventSource","（ヘッダーを送れないブラウザ API の制約）で、",[236,732,733],{},"ticket"," + ",[236,736,737],{},"tenantId"," をクエリパラメータで渡しますが、コントローラは解決済みの principal からテナントを導出し、生のクエリパラメータをそのまま信用することはありません。",[241,740,742],{"id":741},"権限チェック時になぜ-403-と-404-を区別しないのか","権限チェック時になぜ 403 と 404 を区別しないのか",[227,744,745,746,749,750,753],{},"RLS の下では「他テナントのリソース」と「存在しないリソース」は構造的に見分けがつきません（クエリした瞬間に RLS が弾くため）。以前はこの2つを区別するために RLS をバイパスする ",[236,747,748],{},"SECURITY DEFINER"," 関数（",[236,751,752],{},"get_resource_tenant_id","）がありましたが、この関数は削除済みです。",[227,755,756,757,760],{},"現行設計はこの問題自体を解こうとしません。",[231,758,759],{},"意図的に区別しない","のが仕様です。",[762,763,764,771,781],"ul",{},[765,766,767,768],"li",{},"GET（読み取り）で権限が無い / リソースが存在しない → どちらも ",[231,769,770],{},"404",[765,772,773,774,358,777,780],{},"非GET（書き込み）で権限が無い → ",[231,775,776],{},"403",[236,778,779],{},"@PreAuthorize"," 自体の判定失敗のときのみ）",[765,782,783,784,787],{},"リソースの存在確認をする層（",[236,785,786],{},"ResourceTenantResolver","）は通常の RLS-aware クエリしか使わない — クロステナントリソースは常に「存在しない」扱い",[227,789,790,791,794,795,798,799,658],{},"これは情報漏洩の防止（「そのリソースは存在するが権限が無い」と教えてしまうと、リソースIDの存在自体が漏れる）を兼ねた設計判断です。詳しい実装（",[236,792,793],{},"getResourceTenantId"," と ",[236,796,797],{},"resolveResourceTenantForAuth"," の使い分けなど）は ",[655,800,52],{"href":53},[241,802,804],{"id":803},"コルーチン境界をまたぐ-rls-伝播","コルーチン境界をまたぐ RLS 伝播",[227,806,807,808,811,812,288,815,288,818,821,822,825,826,829,830,833,834,837],{},"Kotlin コルーチンは中断点の後で別スレッドに resume することがあり、ThreadLocal ベースの RLS コンテキストは素朴には生き延びません。この構造的ギャップは ",[236,809,810],{},"shared/infrastructure/security/rls/"," の3ファイル（",[236,813,814],{},"RlsDispatchers.kt",[236,816,817],{},"RlsContextElement.kt",[236,819,820],{},"RlsTransactions.kt","）で塞いでいます。読み取り専用のバッチ処理を並列化するときは ",[236,823,824],{},"coroutineScope { items.map { asyncIO { ... } }.awaitAll() }"," の形を使い、",[236,827,828],{},"withContext(Dispatchers.IO)"," を直接呼ばないでください（",[236,831,832],{},"withIO"," が唯一許可された呼び出し口で、それ以外はアーキテクチャテストで CI がブロックします）。詳細は ",[236,835,836],{},"backend/CLAUDE.md"," の RLS 節を参照してください。",[373,839,841],{"type":840},"info",[227,842,843,844,847,848,794,850,853],{},"本ページの設計思想の元ネタは ",[236,845,846],{},"docs/architecture/rls-security-architecture.md"," ですが、個別の migration 番号やクラス名は squash 前の記述が混在しており stale です。実装の現行 SSoT は常に ",[236,849,836],{},[236,851,852],{},"RlsCoverageExemptions.kt"," です。",[855,856,857],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":398,"searchDepth":423,"depth":423,"links":859},[860,861,862,863,864,865],{"id":243,"depth":423,"text":244},{"id":384,"depth":423,"text":385},{"id":465,"depth":423,"text":465},{"id":661,"depth":423,"text":661},{"id":741,"depth":423,"text":742},{"id":803,"depth":423,"text":804},"PostgreSQL Row Level Security によるテナント分離。GUC チェーン、current_tenant_id() ヘルパーの必須化、なぜこの方式を選んだか。","md",{},{"title":48},{"title":48,"description":866},"HgZjT9kQEYVUjqDWMaOl_JeLjSC64XInKmovJUdUVIg",[873,875,876,878,879,880,881,882,883,884,885,886,888,889,890,891,892,894,895,896,897,898,900,902,904,905,906,907,908,909,910,911,912,913,914,915,916,917,918,919,920,922,923,924,925],{"path":13,"title":874},"Astar とは何か（5分で）",{"path":17,"title":16},{"path":6,"title":877},"ようこそ",{"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":887},"システムアーキテクチャ",{"path":73,"title":72},{"path":77,"title":76},{"path":81,"title":80},{"path":85,"title":84},{"path":65,"title":893},"バックエンドガイド",{"path":97,"title":96},{"path":101,"title":100},{"path":105,"title":104},{"path":109,"title":108},{"path":89,"title":899},"フロントエンドガイド",{"path":121,"title":901},"Go agent — NAS 同期エージェント",{"path":125,"title":903},"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":921},"モジュール索引",{"path":205,"title":204},{"path":209,"title":208},{"path":197,"title":201},{"path":213,"title":926},"docs/ 地図",1785452454932]