[{"data":1,"prerenderedAt":931},["ShallowReactive",2],{"/ja-jp/blog/categories/engineering/page/6":3,"navigation-ja-jp":21,"banner-ja-jp":454,"footer-ja-jp":462,"engineering-category-page-total-items-ja-jp":716,"engineering-category-page-featured-ja-jp":717,"engineering-category-page-6-ja-jp":923},{"id":4,"title":5,"body":6,"category":6,"config":7,"content":11,"description":6,"extension":13,"meta":14,"navigation":15,"path":16,"seo":17,"slug":6,"stem":19,"testContent":6,"type":6,"__hash__":20},"blogCategories/ja-jp/blog/categories/engineering.yml","Engineering",null,{"template":8,"slug":9,"hide":10},"BlogCategory","engineering",false,{"name":12},"エンジニアリング","yml",{},true,"/ja-jp/blog/categories/engineering",{"title":12,"description":18},"Browse articles related to エンジニアリング on the GitLab Blog","ja-jp/blog/categories/engineering","SP1p0HNY-4BlLIVgrET9_T9CAStAMizH3Ee46PrhOa0",{"logo":22,"freeTrial":27,"sales":32,"login":37,"items":42,"search":373,"minimal":406,"duo":424,"switchNav":433,"pricingDeployment":444},{"config":23},{"href":24,"dataGaName":25,"dataGaLocation":26},"/ja-jp/","gitlab logo","header",{"text":28,"config":29},"無料トライアルを開始",{"href":30,"dataGaName":31,"dataGaLocation":26},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/ja-jp&glm_content=default-saas-trial/","free trial",{"text":33,"config":34},"デモをリクエスト",{"href":35,"dataGaName":36,"dataGaLocation":26},"/request-a-demo/","sales",{"text":38,"config":39},"サインイン",{"href":40,"dataGaName":41,"dataGaLocation":26},"https://gitlab.com/users/sign_in/","sign in",[43,129,217,222,297,351],{"text":44,"left":15,"config":45,"menu":47},"プラットフォーム",{"dataNavLevelOne":46},"platform",{"type":48,"link":49,"columns":53,"feature":118},"lists",{"text":50,"config":51},"プラットフォームを詳しく見る",{"href":52,"dataGaName":46,"dataGaLocation":26},"/ja-jp/platform/",[54,77,100],{"title":55,"items":56},"実行とワークフロー",[57,62,67,72],{"text":58,"config":59},"CI/CD",{"href":60,"dataGaLocation":26,"dataGaName":61},"/ja-jp/solutions/continuous-integration/","ci/cd",{"text":63,"config":64},"ソースコード管理",{"href":65,"dataGaLocation":26,"dataGaName":66},"/ja-jp/solutions/source-code-management/","source code management",{"text":68,"config":69},"アジャイルデリバリー",{"href":70,"dataGaLocation":26,"dataGaName":71},"/ja-jp/solutions/agile-delivery/","agile delivery",{"text":73,"config":74},"アーティファクト管理",{"href":75,"dataGaLocation":26,"dataGaName":76},"/ja-jp/artifact-central/","artifact management",{"title":78,"items":79},"セキュリティとガバナンス",[80,85,90,95],{"text":81,"config":82},"アプリケーションセキュリティテスト",{"href":83,"dataGaLocation":26,"dataGaName":84},"/ja-jp/solutions/application-security-testing/","application security testing",{"text":86,"config":87},"ガバナンスとコンプライアンス",{"href":88,"dataGaLocation":26,"dataGaName":89},"/ja-jp/solutions/software-compliance/","governance and compliance",{"text":91,"config":92},"シークレット管理",{"href":93,"dataGaLocation":26,"dataGaName":94},"/ja-jp/gitlab-secrets-manager/","secrets management",{"text":96,"config":97},"サプライチェーンセキュリティ",{"href":98,"dataGaLocation":26,"dataGaName":99},"/ja-jp/solutions/supply-chain/","supply chain security",{"title":101,"items":102},"コンテキストとAI",[103,108,113],{"text":104,"config":105},"エージェント型オーケストレーション",{"href":106,"dataGaLocation":26,"dataGaName":107},"/ja-jp/gitlab-duo-agent-platform/","agentic orchestration",{"text":109,"config":110},"コンテキストグラフ",{"href":111,"dataGaLocation":26,"dataGaName":112},"/ja-jp/gitlab-orbit/","context graph",{"text":114,"config":115},"可視性と測定",{"href":116,"dataGaLocation":26,"dataGaName":117},"/ja-jp/solutions/visibility-measurement/","visibility and measurement",{"config":119,"title":122,"text":123,"link":124},{"background":120,"textColor":121},"url('https://res.cloudinary.com/about-gitlab-com/image/upload/v1790185102/o7dn32anqcb6z8dgd3as.jpg')","#000","GitLabが選ばれる理由","ひとつのプラットフォームで、ソフトウェアライフサイクル全体を通じてスピードと制御を両立できます。",{"text":125,"config":126},"詳細はこちら",{"href":127,"dataGaName":128,"dataGaLocation":26},"/ja-jp/why-gitlab/","why gitlab",{"text":130,"left":15,"config":131,"menu":133},"ソリューション",{"dataNavLevelOne":132},"solutions",{"type":48,"link":134,"columns":138,"feature":208},{"text":135,"config":136},"すべてのソリューションを表示",{"href":137,"dataGaName":132,"dataGaLocation":26},"/ja-jp/solutions/",[139,157,175],{"title":140,"items":141},"成果",[142,147,152],{"text":143,"config":144},"DevOpsモダナイゼーション",{"href":145,"dataGaLocation":26,"dataGaName":146},"/ja-jp/assessments/devops-modernization-assessment/","devops modernization",{"text":148,"config":149},"セキュリティモダナイゼーション",{"href":150,"dataGaLocation":26,"dataGaName":151},"/ja-jp/assessments/security-modernization-assessment/","security modernization",{"text":153,"config":154},"AIモダナイゼーション",{"href":155,"dataGaLocation":26,"dataGaName":156},"/ja-jp/assessments/ai-modernization-assessment/","ai modernization",{"title":158,"items":159},"規模別",[160,165,170],{"text":161,"config":162},"エンタープライズ",{"href":163,"dataGaLocation":26,"dataGaName":164},"/ja-jp/enterprise/","enterprise",{"text":166,"config":167},"スモールビジネス",{"href":168,"dataGaLocation":26,"dataGaName":169},"/ja-jp/small-business/","small business",{"text":171,"config":172},"スタートアップ",{"href":173,"dataGaLocation":26,"dataGaName":174},"/ja-jp/solutions/startups/","startups",{"title":176,"items":177},"業界",[178,183,188,193,198,203],{"text":179,"config":180},"金融サービス",{"href":181,"dataGaLocation":26,"dataGaName":182},"/ja-jp/solutions/finance/","financial services",{"text":184,"config":185},"公共部門",{"href":186,"dataGaLocation":26,"dataGaName":187},"/ja-jp/solutions/public-sector/","public sector",{"text":189,"config":190},"通信",{"href":191,"dataGaLocation":26,"dataGaName":192},"/ja-jp/solutions/telecommunications/","telecommunications",{"text":194,"config":195},"自動車",{"href":196,"dataGaLocation":26,"dataGaName":197},"/ja-jp/solutions/automotive/","automotive",{"text":199,"config":200},"教育",{"href":201,"dataGaLocation":26,"dataGaName":202},"/ja-jp/solutions/education/","education",{"text":204,"config":205},"航空宇宙",{"href":206,"dataGaLocation":26,"dataGaName":207},"/ja-jp/solutions/aerospace/","aerospace",{"config":209,"title":210,"text":211,"link":212},{"background":120,"textColor":121},"GitLabのセキュリティ標準","セキュリティを犠牲にすることなく、ソフトウェアファクトリーを強化し、自律的なAIエージェントを実現する方法をご覧ください。",{"text":213,"config":214},"標準を見る",{"href":215,"dataGaName":216,"dataGaLocation":26},"/ja-jp/gitlab-security-standard/","gitlab security standard",{"text":218,"config":219},"価格",{"href":220,"dataGaName":221,"dataGaLocation":26,"dataNavLevelOne":221},"/ja-jp/pricing/","pricing",{"text":223,"config":224,"menu":226},"関連リソース",{"dataNavLevelOne":225},"resources",{"type":48,"link":227,"columns":231,"feature":288},{"text":228,"config":229},"すべてのリソースを表示",{"href":230,"dataGaName":225,"dataGaLocation":26},"/ja-jp/resources/",[232,260],{"title":233,"items":234},"検索する",[235,240,245,250,255],{"text":236,"config":237},"製品ドキュメント",{"href":238,"dataGaName":239,"dataGaLocation":26},"https://docs.gitlab.com/ja-jp/","docs",{"text":241,"config":242},"GitLab University",{"href":243,"dataGaName":244,"dataGaLocation":26},"https://university.gitlab.com/","university",{"text":246,"config":247},"技術デモ",{"href":248,"dataGaName":249,"dataGaLocation":26},"/ja-jp/gitlab-technical-demo-series/","demo series",{"text":251,"config":252},"インタラクティブデモ",{"href":253,"dataGaName":254,"dataGaLocation":26},"/ja-jp/demo-hub/","demo hub",{"text":256,"config":257},"GitLabサービス",{"href":258,"dataGaName":259,"dataGaLocation":26},"/ja-jp/services/","services",{"title":261,"items":262},"つなげる",[263,268,273,278,283],{"text":264,"config":265},"ブログ",{"href":266,"dataGaName":267,"dataGaLocation":26},"/ja-jp/blog/","blog",{"text":269,"config":270},"コミュニティ",{"href":271,"dataGaName":272,"dataGaLocation":26},"/community/","community",{"text":274,"config":275},"お客様事例",{"href":276,"dataGaName":277,"dataGaLocation":26},"/ja-jp/customers/","customers",{"text":279,"config":280},"パートナー",{"href":281,"dataGaName":282,"dataGaLocation":26},"/ja-jp/partners/","partners",{"text":284,"config":285},"イベント",{"href":286,"dataGaName":287,"dataGaLocation":26},"/events/","events",{"config":289,"title":290,"text":291,"link":292},{"background":120,"textColor":121},"GitLabの最新情報","最新の機能と改善点に関する情報をお届けします。",{"text":293,"config":294},"最新情報を読む",{"href":295,"dataGaName":296,"dataGaLocation":26},"/ja-jp/whats-new/","whats new",{"text":298,"config":299,"menu":301},"企業情報",{"dataNavLevelOne":300},"company",{"type":48,"columns":302},[303],{"items":304},[305,310,316,321,326,331,336,341,346],{"text":306,"config":307},"GitLabについて",{"href":308,"dataGaName":309,"dataGaLocation":26},"/ja-jp/company/","about",{"text":311,"config":312,"footerGa":315},"採用情報",{"href":313,"dataGaName":314,"dataGaLocation":26},"/jobs/","jobs",{"dataGaName":314},{"text":317,"config":318},"プレス",{"href":319,"dataGaName":320,"dataGaLocation":26},"/press/","press",{"text":322,"config":323},"ハンドブック",{"href":324,"dataGaName":325,"dataGaLocation":26},"https://handbook.gitlab.com/","handbook",{"text":327,"config":328},"経営陣",{"href":329,"dataGaName":330,"dataGaLocation":26},"/company/team/e-group/","leadership",{"text":332,"config":333},"投資家向け情報",{"href":334,"dataGaName":335,"dataGaLocation":26},"https://ir.gitlab.com/overview/default.aspx","investor relations",{"text":337,"config":338},"トラストセンター",{"href":339,"dataGaName":340,"dataGaLocation":26},"/ja-jp/security/","trust center",{"text":342,"config":343},"AI Transparency Center",{"href":344,"dataGaName":345,"dataGaLocation":26},"/ja-jp/ai-transparency-center/","ai transparency center",{"text":347,"config":348},"ニュースレター",{"href":349,"dataGaName":350,"dataGaLocation":26},"/company/contact/#contact-forms","newsletter",{"text":352,"config":353,"menu":354},"お問い合わせ",{"dataNavLevelOne":300},{"type":48,"columns":355},[356],{"items":357},[358,363,368],{"text":359,"config":360},"お問い合わせはこちら",{"href":361,"dataGaName":362,"dataGaLocation":26},"/ja-jp/sales/","talk to sales",{"text":364,"config":365},"サポートポータル",{"href":366,"dataGaName":367,"dataGaLocation":26},"https://support.gitlab.com/hc/en-us","support portal",{"text":369,"config":370},"カスタマーポータル",{"href":371,"dataGaName":372,"dataGaLocation":26},"https://customers.gitlab.com/customers/sign_in/","customer portal",{"close":374,"login":375,"suggestions":382},"閉じる",{"text":376,"link":377},"リポジトリとプロジェクトを検索するには、次にログインします",{"text":378,"config":379},"GitLab.com",{"href":40,"dataGaName":380,"dataGaLocation":381},"search login","search",{"text":383,"default":384},"提案",[385,388,392,394,398,402],{"text":386,"config":387},"GitLab Duo Agent Platform",{"href":106,"dataGaName":386,"dataGaLocation":381},{"text":389,"config":390},"コード提案（AI）",{"href":106,"dataGaName":391,"dataGaLocation":381},"Code Suggestions (AI)",{"text":58,"config":393},{"href":60,"dataGaName":58,"dataGaLocation":381},{"text":395,"config":396},"GitLab on AWS",{"href":397,"dataGaName":395,"dataGaLocation":381},"/ja-jp/partners/technology-partners/aws/",{"text":399,"config":400},"GitLab on Google Cloud",{"href":401,"dataGaName":399,"dataGaLocation":381},"/ja-jp/partners/technology-partners/google-cloud-platform/",{"text":403,"config":404},"GitLabを選ぶ理由",{"href":127,"dataGaName":405,"dataGaLocation":381},"Why GitLab?",{"freeTrial":407,"mobileIcon":411,"desktopIcon":416,"secondaryButton":419},{"text":28,"config":408},{"href":409,"dataGaName":31,"dataGaLocation":410},"https://gitlab.com/-/trials/new/","nav",{"altText":412,"config":413},"GitLabアイコン",{"src":414,"dataGaName":415,"dataGaLocation":410},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203874/jypbw1jx72aexsoohd7x.svg","gitlab icon",{"altText":412,"config":417},{"src":418,"dataGaName":415,"dataGaLocation":410},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203875/gs4c8p8opsgvflgkswz9.svg",{"text":420,"config":421},"はじめに",{"href":422,"dataGaName":423,"dataGaLocation":410},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/ja-jp/get-started/","get started",{"freeTrial":425,"mobileIcon":429,"desktopIcon":431},{"text":426,"config":427},"GitLab Duoの詳細はこちら",{"href":106,"dataGaName":428,"dataGaLocation":410},"gitlab duo",{"altText":412,"config":430},{"src":414,"dataGaName":415,"dataGaLocation":410},{"altText":412,"config":432},{"src":418,"dataGaName":415,"dataGaLocation":410},{"button":434,"mobileIcon":439,"desktopIcon":441},{"text":435,"config":436},"/switch",{"href":437,"dataGaName":438,"dataGaLocation":410},"#contact","switch",{"altText":412,"config":440},{"src":414,"dataGaName":415,"dataGaLocation":410},{"altText":412,"config":442},{"src":443,"dataGaName":415,"dataGaLocation":410},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1773335277/ohhpiuoxoldryzrnhfrh.png",{"freeTrial":445,"mobileIcon":450,"desktopIcon":452},{"text":446,"config":447},"料金ページに戻る",{"href":220,"dataGaName":448,"dataGaLocation":410,"icon":449},"back to pricing","GoBack",{"altText":412,"config":451},{"src":414,"dataGaName":415,"dataGaLocation":410},{"altText":412,"config":453},{"src":418,"dataGaName":415,"dataGaLocation":410},{"title":455,"titleMobile":456,"button":457,"config":460},"GitLab Orbitが登場: AIエージェントのためのコンテキストレイヤー","GitLab Orbitが登場",{"text":125,"config":458},{"href":111,"dataGaName":459,"dataGaLocation":26},"orbit",{"layout":461,"disabled":10},"release",{"data":463},{"text":464,"source":465,"edit":471,"contribute":476,"config":481,"items":486,"minimal":708},"GitはSoftware Freedom Conservancyの商標です。当社は「GitLab」をライセンスに基づいて使用しています",{"text":466,"config":467},"ページのソースを表示",{"href":468,"dataGaName":469,"dataGaLocation":470},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":472,"config":473},"このページを編集",{"href":474,"dataGaName":475,"dataGaLocation":470},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":477,"config":478},"ご協力をお願いします",{"href":479,"dataGaName":480,"dataGaLocation":470},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":482,"facebook":483,"youtube":484,"linkedin":485},"https://twitter.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[487,533,590,632,675],{"title":218,"links":488,"subMenu":503},[489,493,498],{"text":490,"config":491},"プランの表示",{"href":220,"dataGaName":492,"dataGaLocation":470},"view plans",{"text":494,"config":495},"Premiumを選ぶ理由",{"href":496,"dataGaName":497,"dataGaLocation":470},"/ja-jp/pricing/premium/","why premium",{"text":499,"config":500},"Ultimateを選ぶ理由",{"href":501,"dataGaName":502,"dataGaLocation":470},"/ja-jp/pricing/ultimate/","why ultimate",[504],{"title":352,"links":505},[506,509,511,513,518,523,528],{"text":507,"config":508},"営業担当へのお問い合わせ",{"href":361,"dataGaName":36,"dataGaLocation":470},{"text":364,"config":510},{"href":366,"dataGaName":367,"dataGaLocation":470},{"text":369,"config":512},{"href":371,"dataGaName":372,"dataGaLocation":470},{"text":514,"config":515},"ステータス",{"href":516,"dataGaName":517,"dataGaLocation":470},"https://status.gitlab.com/","status",{"text":519,"config":520},"利用規約",{"href":521,"dataGaName":522,"dataGaLocation":470},"/terms/","terms of use",{"text":524,"config":525},"プライバシーに関する声明",{"href":526,"dataGaName":527,"dataGaLocation":470},"/ja-jp/privacy/","privacy statement",{"text":529,"config":530},"Cookie設定",{"dataGaName":531,"dataGaLocation":470,"id":532,"isOneTrustButton":15},"cookie preferences","ot-sdk-btn",{"title":44,"links":534,"subMenu":547},[535,537,539,541,543,545],{"text":50,"config":536},{"href":52,"dataGaName":46,"dataGaLocation":470},{"text":104,"config":538},{"href":106,"dataGaName":107,"dataGaLocation":470},{"text":58,"config":540},{"href":60,"dataGaName":61,"dataGaLocation":470},{"text":109,"config":542},{"href":111,"dataGaName":112,"dataGaLocation":470},{"text":91,"config":544},{"href":93,"dataGaName":94,"dataGaLocation":470},{"text":122,"config":546},{"href":127,"dataGaName":128,"dataGaLocation":470},[548],{"title":549,"links":550},"トピック",[551,555,560,565,570,575,580,585],{"text":58,"config":552},{"href":553,"dataGaName":554,"dataGaLocation":470},"/ja-jp/topics/ci-cd/","cicd",{"text":556,"config":557},"GitOps",{"href":558,"dataGaName":559,"dataGaLocation":470},"/ja-jp/topics/gitops/","gitops",{"text":561,"config":562},"DevOps",{"href":563,"dataGaName":564,"dataGaLocation":470},"/ja-jp/topics/devops/","devops",{"text":566,"config":567},"バージョン管理",{"href":568,"dataGaName":569,"dataGaLocation":470},"/ja-jp/topics/version-control/","version control",{"text":571,"config":572},"DevSecOps",{"href":573,"dataGaName":574,"dataGaLocation":470},"/ja-jp/topics/devsecops/","devsecops",{"text":576,"config":577},"クラウドネイティブ",{"href":578,"dataGaName":579,"dataGaLocation":470},"/ja-jp/topics/cloud-native/","cloud native",{"text":581,"config":582},"コーディングのためのAI",{"href":583,"dataGaName":584,"dataGaLocation":470},"/ja-jp/topics/devops/ai-for-coding/","ai for coding",{"text":586,"config":587},"エージェント型AI",{"href":588,"dataGaName":589,"dataGaLocation":470},"/ja-jp/topics/agentic-ai/","agentic ai",{"title":130,"links":591},[592,594,596,598,600,603,605,607,609,611,613,615,617,620,624,628],{"text":143,"config":593},{"href":145,"dataGaName":146,"dataGaLocation":470},{"text":148,"config":595},{"href":150,"dataGaName":151,"dataGaLocation":470},{"text":153,"config":597},{"href":155,"dataGaName":156,"dataGaLocation":470},{"text":179,"config":599},{"href":181,"dataGaName":182,"dataGaLocation":470},{"text":601,"config":602},"公共機関",{"href":186,"dataGaName":187,"dataGaLocation":470},{"text":189,"config":604},{"href":191,"dataGaName":192,"dataGaLocation":470},{"text":194,"config":606},{"href":196,"dataGaName":197,"dataGaLocation":470},{"text":199,"config":608},{"href":201,"dataGaName":202,"dataGaLocation":470},{"text":204,"config":610},{"href":206,"dataGaName":207,"dataGaLocation":470},{"text":161,"config":612},{"href":163,"dataGaName":164,"dataGaLocation":470},{"text":166,"config":614},{"href":168,"dataGaName":169,"dataGaLocation":470},{"text":171,"config":616},{"href":173,"dataGaName":174,"dataGaLocation":470},{"text":556,"config":618},{"href":619,"dataGaName":559,"dataGaLocation":470},"/ja-jp/solutions/gitops/",{"text":621,"config":622},"ソフトウェアコンポジション解析",{"href":98,"dataGaName":623,"dataGaLocation":470},"software composition analysis",{"text":625,"config":626},"バリューストリーム管理",{"href":116,"dataGaName":627,"dataGaLocation":470},"value stream management",{"text":629,"config":630},"すべてのソリューション",{"href":137,"dataGaName":631,"dataGaLocation":470},"all solutions",{"title":633,"links":634},"リソース",[635,640,645,648,650,652,654,656,658,660,662,664,666,668,671],{"text":636,"config":637},"インストール",{"href":638,"dataGaName":639,"dataGaLocation":470},"/ja-jp/install/","install",{"text":641,"config":642},"クイックスタートガイド",{"href":643,"dataGaName":644,"dataGaLocation":470},"/ja-jp/get-started/","quick setup checklists",{"text":236,"config":646},{"href":647,"dataGaName":239,"dataGaLocation":470},"https://docs.gitlab.com/ja-jp",{"text":241,"config":649},{"href":243,"dataGaName":244,"dataGaLocation":470},{"text":246,"config":651},{"href":248,"dataGaName":249,"dataGaLocation":470},{"text":251,"config":653},{"href":253,"dataGaName":254,"dataGaLocation":470},{"text":256,"config":655},{"href":258,"dataGaName":259,"dataGaLocation":470},{"text":264,"config":657},{"href":266,"dataGaName":267,"dataGaLocation":470},{"text":269,"config":659},{"href":271,"dataGaName":272,"dataGaLocation":470},{"text":274,"config":661},{"href":276,"dataGaName":277,"dataGaLocation":470},{"text":279,"config":663},{"href":281,"dataGaName":282,"dataGaLocation":470},{"text":284,"config":665},{"href":286,"dataGaName":287,"dataGaLocation":470},{"text":347,"config":667},{"href":349,"dataGaName":350,"dataGaLocation":470},{"text":669,"config":670},"最新リリース",{"href":295,"dataGaName":296,"dataGaLocation":470},{"text":672,"config":673},"すべてのリソース",{"href":230,"dataGaName":674,"dataGaLocation":470},"all resources",{"title":676,"links":677},"会社情報",[678,680,682,684,686,688,690,692,694,698,703],{"text":306,"config":679},{"href":308,"dataGaName":300,"dataGaLocation":470},{"text":311,"config":681},{"href":313,"dataGaName":314,"dataGaLocation":470},{"text":317,"config":683},{"href":319,"dataGaName":320,"dataGaLocation":470},{"text":322,"config":685},{"href":324,"dataGaName":325,"dataGaLocation":470},{"text":327,"config":687},{"href":329,"dataGaName":330,"dataGaLocation":470},{"text":332,"config":689},{"href":334,"dataGaName":335,"dataGaLocation":470},{"text":337,"config":691},{"href":339,"dataGaName":340,"dataGaLocation":470},{"text":342,"config":693},{"href":344,"dataGaName":345,"dataGaLocation":470},{"text":695,"config":696},"Sustainability",{"href":697,"dataGaName":695,"dataGaLocation":470},"/sustainability/",{"text":699,"config":700},"ダイバーシティ、インクルージョン、ビロンギング（DIB）",{"href":701,"dataGaName":702,"dataGaLocation":470},"/ja-jp/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":704,"config":705},"現代奴隷制の透明性に関する声明",{"href":706,"dataGaName":707,"dataGaLocation":470},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"items":709},[710,712,714],{"text":519,"config":711},{"href":521,"dataGaName":522,"dataGaLocation":470},{"text":529,"config":713},{"dataGaName":531,"dataGaLocation":470,"id":532,"isOneTrustButton":15},{"text":524,"config":715},{"href":526,"dataGaName":527,"dataGaLocation":470},47,{"id":718,"title":719,"authors":720,"body":722,"category":9,"date":909,"description":910,"extension":911,"externalUrl":6,"faq":6,"featured":10,"heroImage":912,"meta":913,"navigation":15,"path":914,"seo":915,"slug":917,"stem":918,"tags":919,"template":920,"updatedDate":921,"__hash__":922},"blogPosts/ja-jp/blog/module-level-access-in-a-django-grc-app.md","Django製GRCツールにモジュール単位のアクセス制御を実装する",[721],"Donovan Felton",{"type":723,"value":724,"toc":899},"minimark",[725,729,732,736,744,749,752,755,758,761,764,767,770,773,776,779,790,796,811,816,827,830,833,836,839,842,867,870],[726,727,728],"p",{},"GitLabのエンジニアリングチームは、数多くの社内ツールを自前で開発しています。なかでも、認可の扱い方そのものを見直すきっかけになったのが、GRC（ガバナンス・リスク・コンプライアンス）の社内ツールでした。このツールは、セキュリティコンプライアンスチームと内部監査チームという、性質の大きく異なる2つのユーザー層を1つの基盤で支えています。",[726,730,731],{},"複数のオーディエンス、異なるデータ分類レベル、互いに混ざってはいけないデータ。こうした条件を抱えたDjango製の社内ツールを開発・運用しているなら、本記事が参考になるはずです。私たちが直面した課題と、その解決方法、そして同じパターンをご自身のアプリに適用する手順を順に紹介します。",[733,734,735],"h2",{"id":735},"課題",[726,737,738,739,743],{},"もともとのツールは、セキュリティコンプライアンスチーム専用に作られた単一のDjangoアプリで、すべてのビューに",[740,741,742],"code",{},"login_required","を付けていました。この設計は当初、正しいものでした。しかし、内部監査チームがこのツールに新しいユースケースを見いだしたことで前提が変わります。そのユースケースには、完全に独立したワークフロー、独自のデータ、独自のモデル、そしてセキュリティコンプライアンスチームには見せられない機密情報が含まれていたのです。",[726,745,746,748],{},[740,747,742],{},"が答えてくれるのは「ログインしているか」という1点だけ。マルチテナントの社内ツールで本当に問わなければならないのは「ここにアクセスしてよい人物か」という別の問いです。認証済みのセキュリティコンプライアンスチームのユーザーが内部監査チームのURLを開けば、ログインチェックを素通りして、本来見るべきではないデータに到達してしまいます。",[726,750,751],{},"後からもう1つのオーディエンスが増えたアプリであれば、思い当たる節があるかもしれません。ここで自問していただきたいのは、きわめてシンプルな問いです。アプリ内のすべてのビューは、ユーザーが「誰か」を確認しているでしょうか。それとも「ログインしているか」を確認しているだけでしょうか。後者であれば、私たちと同じ穴が空いている可能性が高いと言えます。",[726,753,754],{},"必要だったのは、きれいな分離でした。「このボタンには触れないでください」という運用上のお願いではなく、どのURLを直接入力されても崩れない、強制力のある境界です。",[733,756,757],{"id":757},"アーキテクチャの判断",[726,759,760],{},"内部監査チームのユースケースがロードマップに乗ったとき、典型的な分岐点が目の前に現れました。既存のアプリに機能を継ぎ足すか、構造から作り直すか。私たちは作り直す道を選びます。",[726,762,763],{},"できあがったのは、コアとなるDjangoプロジェクトの上に、独立した2つのモジュールアプリが乗る構成です。コアが持つのは、共通の認証、ユーザー管理、監査ログ、そして基本UIコンポーネント。その上にセキュリティコンプライアンス向けと内部監査向けのモジュールが1つずつ並び、各モジュールが自身のモデル、ビュー、API面を所有します。",[726,765,766],{},"そして、自分たちに課した制約こそが、この取り組みを記事にするに値する核心でした。コアはコンプライアンスのデータについても内部監査のデータについても一切知らない、という制約です。どちらのモジュールもコアに依存してよい。しかし、モジュール同士が依存し合うことは認めない。この一線があるからこそ、2つのアプリを場当たり的に継ぎはぎしただけの構造に陥らずに済みます。",[733,768,769],{"id":769},"アクセス制御",[726,771,772],{},"私たちは、機密性の高いコンプライアンスデータとリスクデータを保持するツールを開発する、コンプライアンスエンジニアリングの部門です。ここでアクセス制御が甘ければ、それは単なるバグでは済みません。信頼そのものを損なう重大な問題になります。",[726,774,775],{},"設計上の判断として選んだのは、Djangoに最初から備わっている認証システムでした。各モジュールは、ちょうど1つのグループに対応します。ユーザーは片方のグループだけに属することも、両方に属することも、どちらにも属さないことも可能で、どの組み合わせであってもシステムが適切な職務分離を各レイヤーで担保します。ナビゲーションUI、Djangoのビュー、REST APIが、それぞれ独立してグループメンバーシップを検証する仕組みです。",[733,777,778],{"id":778},"実装",[726,780,781,782,785,786,789],{},"コアには、両モジュールが継承する再利用可能なクラスが1つだけあります。",[740,783,784],{},"GroupRequiredMixin","です。このミックスインがグループメンバーシップを確認し、ユーザーが必要なグループに属していなければ",[740,787,788],{},"PermissionDenied","を送出します。",[726,791,792],{},[793,794,795],"strong",{},"モジュール単位のサブクラス",[726,797,798,799,802,803,806,807,810],{},"各モジュールが用意するのは、",[740,800,801],{},"required_group_name","を設定するだけの3行のサブクラスです。セキュリティコンプライアンス側には",[740,804,805],{},"GasGroupRequiredMixin","と",[740,808,809],{},"IsGasGroupMember","があり、内部監査側も同じパターンを繰り返します。モジュールに強制レイヤーを追加するコストは、これで全部。新しいファイルが1つ、新しい属性が1つだけ。実際のチェックロジックはコアに置かれ、以後そこに手を入れる必要はありません。",[726,812,813],{},[793,814,815],{},"UIレイヤー",[726,817,818,819,822,823,826],{},"最後に、テンプレートフィルター",[740,820,821],{},"user_in_group","を用意しました。ユーザーが実際に閲覧を許可されているものだけをナビゲーションに表示させるためです。ERMメンバーだけに見せたいナビゲーションブロックを、",[740,824,825],{},"user|user_in_group:'erm'","のようなチェックで囲みます。",[726,828,829],{},"ただし、これはUX上のガードであって、セキュリティ境界ではありません。ナビゲーションのリンクを隠したところで、URLを直接入力する行為は止められないからです。それを防ぐのがミックスインとDjango REST Frameworkのパーミッションクラスの役割であり、テンプレートフィルターは「そのユーザーに何が見えて何ができるのか」をUIの側で正直に保つためのものと言えます。",[733,831,832],{"id":832},"今後の展望とはじめの一歩",[726,834,835],{},"プラットフォームのレベルまで視点を引き上げると、この成果がモジュールにもチームにも依存しない再利用可能なパターンであることが見えてきます。仮に3つ目のモジュール、たとえばベンダーリスクのワークフローや監査管理モジュールなどが加わったとしても、同じアクセス制御の構造、同じ監査証跡、同じ共有認証をそのまま継承でき、強制ロジックを1行も新たに書く必要がありません。新しいモジュールのコストは、インフラの足場作りではなく、ほぼビジネス要件だけに収まります。",[726,837,838],{},"これが私たちの選んだ賭けでした。土台は一度だけ作り込み、以降のモジュールはすべてその上に乗せる。アクセス制御をゼロから作り直す作業は、もう繰り返しません。",[726,840,841],{},"同じ仕組みをご自身のアプリで試すなら、おすすめの順序は次のとおりです。",[843,844,845,855,858,864],"ol",{},[846,847,848,849,806,851,854],"li",{},"ビューに「ログイン確認」と「認可」のギャップがないかを点検します。",[740,850,742],{},[740,852,853],{},"LoginRequiredMixin","をgrepし、それぞれについて、匿名ユーザーだけでなく他の認証済みユーザーからも機密データを守れているかを確認してください。",[846,856,857],{},"コードを書く前にモジュール境界を引きます。本当に共有すべきもの（認証、基本UI、ロギング）と、特定のオーディエンスだけに属するものを切り分けてください。",[846,859,860,861,863],{},"ビューごとではなく、ミックスインを1つだけ書きます。コアアプリに置いた単一の",[740,862,784],{},"をモジュールごとにサブクラス化すれば、強制ロジックをレビューすべき箇所も、誤りが生じうる箇所も、それぞれ1か所に収まります。",[846,865,866],{},"ビュー、API、ナビゲーションの各レイヤーで独立して強制します。リンクを隠すことが唯一の防衛線になる状況を避けるためです。",[733,868,869],{"id":869},"参考リンク",[871,872,873,881,892],"ul",{},[846,874,875],{},[876,877,880],"a",{"href":878,"rel":879},"https://docs.djangoproject.com/en/stable/topics/auth/default/",[],"Django認証システム — Djangoの認証システムを使う",[846,882,883],{},[876,884,887,888,891],{"href":885,"rel":886},"https://docs.djangoproject.com/en/stable/topics/auth/default/#the-loginrequired-mixin",[],"Djangoクラスベースビュー — ",[740,889,890],{},"UserPassesTestMixin"," と権限ミックスインの使用",[846,893,894],{},[876,895,898],{"href":896,"rel":897},"https://www.django-rest-framework.org/api-guide/permissions/",[],"Django REST Framework — パーミッション",{"title":900,"searchDepth":901,"depth":901,"links":902},"",2,[903,904,905,906,907,908],{"id":735,"depth":901,"text":735},{"id":757,"depth":901,"text":757},{"id":769,"depth":901,"text":769},{"id":778,"depth":901,"text":778},{"id":832,"depth":901,"text":832},{"id":869,"depth":901,"text":869},"2026-10-05","GitLabのセキュリティコンプライアンスチームと内部監査チームという性質の異なる2つのチームを1つの基盤で支えるために、Django製の社内ツールをどう再構築したのか。その技術的な詳細を解説します。","md","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097663/Blog/Hero%20Images/Blog/Hero%20Images/Workflow%201800x945_2gQoQIbY9NvjLFpXtsxtXy_1750097663612.png",{},"/ja-jp/blog/module-level-access-in-a-django-grc-app",{"config":916,"title":719,"description":910},{"noIndex":10},"module-level-access-in-a-django-grc-app","ja-jp/blog/module-level-access-in-a-django-grc-app",[272],"BlogPost","2026-10-06","JZRsn25jqk3PV_Z7s6OFfC5RMhKrTUrjW5qFLbZ8OAY",[924],{"title":925,"heroImage":926,"category":9,"description":927,"authors":928,"slug":930,"externalUrl":6}," git Commit（コミット）の履歴が重要な理由とその整理方法","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749659457/Blog/Hero%20Images/keep-git-commit-history-clean.jpg","git コミット履歴は、煩雑になりがち。gitコミットのメッセージ履歴をクリーンに保ち、変更内容を把握する方法とその重要性をご紹介します。",[929],"Kushal Pandya","keeping-git-commit-history-clean",1791952304911]