Files
docs/standards/lib/01_build_recipe/index.html
Vishesh 'ironeagle' Bangotra 5971f26c08 feat(standards): MR-based tag strategy + repository inventory (registry://repos)
Versioning standard now documents the MR flow: bump pyproject.toml/VERSION and promote CHANGELOG in the MR (referencing the version/tag, not a commit id), merge/squash, then tag the resulting commit. Adds the agent-assisted tagging procedure (wait for the go-ahead, find the version-bump commit, tag only it, ask the user to push) to both the reference page and the releasing wiki runbook. Adds the repo inventory (src/repos.json -> mcp/repos.json), the registry://repos resource + list_repos tool, the 15_repository_inventory lib page, and two MCP prompts: compliance (remediate repos) and release (agent tagging).
2026-10-15 14:39:21 +05:30

1188 lines
47 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!doctype html>
<html lang="en" class="no-js">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="description" content="The rules and library registry of the standardized application blueprint.">
<link rel="prev" href="..">
<link rel="next" href="../02_layering_rules/">
<link rel="icon" href="../assets/images/favicon.png">
<meta name="generator" content="mkdocs-1.6.1, mkdocs-material-9.6.23">
<title>Build Recipe - Aetos Standards — Reference</title>
<link rel="stylesheet" href="../assets/stylesheets/main.84d31ad4.min.css">
<link rel="stylesheet" href="../assets/stylesheets/palette.06af60db.min.css">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Inter:300,300i,400,400i,700,700i%7CJetBrains+Mono:400,400i,700,700i&display=fallback">
<style>:root{--md-text-font:"Inter";--md-code-font:"JetBrains Mono"}</style>
<script>__md_scope=new URL("..",location),__md_hash=e=>[...e].reduce(((e,_)=>(e<<5)-e+_.charCodeAt(0)),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
</head>
<body dir="ltr" data-md-color-scheme="slate" data-md-color-primary="deep-purple" data-md-color-accent="cyan">
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
<label class="md-overlay" for="__drawer"></label>
<div data-md-component="skip">
<a href="#build-recipe" class="md-skip">
Skip to content
</a>
</div>
<div data-md-component="announce">
</div>
<header class="md-header md-header--shadow" data-md-component="header">
<nav class="md-header__inner md-grid" aria-label="Header">
<a href=".." title="Aetos Standards — Reference" class="md-header__button md-logo" aria-label="Aetos Standards — Reference" data-md-component="logo">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54"/></svg>
</a>
<label class="md-header__button md-icon" for="__drawer">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3zm0 5h18v2H3zm0 5h18v2H3z"/></svg>
</label>
<div class="md-header__title" data-md-component="header-title">
<div class="md-header__ellipsis">
<div class="md-header__topic">
<span class="md-ellipsis">
Aetos Standards — Reference
</span>
</div>
<div class="md-header__topic" data-md-component="header-topic">
<span class="md-ellipsis">
Build Recipe
</span>
</div>
</div>
</div>
<form class="md-header__option" data-md-component="palette">
<input class="md-option" data-md-color-media="" data-md-color-scheme="slate" data-md-color-primary="deep-purple" data-md-color-accent="cyan" aria-hidden="true" type="radio" name="__palette" id="__palette_0">
</form>
<script>var palette=__md_get("__palette");if(palette&&palette.color){if("(prefers-color-scheme)"===palette.color.media){var media=matchMedia("(prefers-color-scheme: light)"),input=document.querySelector(media.matches?"[data-md-color-media='(prefers-color-scheme: light)']":"[data-md-color-media='(prefers-color-scheme: dark)']");palette.color.media=input.getAttribute("data-md-color-media"),palette.color.scheme=input.getAttribute("data-md-color-scheme"),palette.color.primary=input.getAttribute("data-md-color-primary"),palette.color.accent=input.getAttribute("data-md-color-accent")}for(var[key,value]of Object.entries(palette.color))document.body.setAttribute("data-md-color-"+key,value)}</script>
<label class="md-header__button md-icon" for="__search">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
</label>
<div class="md-search" data-md-component="search" role="dialog">
<label class="md-search__overlay" for="__search"></label>
<div class="md-search__inner" role="search">
<form class="md-search__form" name="search">
<input type="text" class="md-search__input" name="query" aria-label="Search" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" required>
<label class="md-search__icon md-icon" for="__search">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"/></svg>
</label>
<nav class="md-search__options" aria-label="Search">
<a href="javascript:void(0)" class="md-search__icon md-icon" title="Share" aria-label="Share" data-clipboard data-clipboard-text="" data-md-component="search-share" tabindex="-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M18 16.08c-.76 0-1.44.3-1.96.77L8.91 12.7c.05-.23.09-.46.09-.7s-.04-.47-.09-.7l7.05-4.11c.54.5 1.25.81 2.04.81a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3c0 .24.04.47.09.7L8.04 9.81C7.5 9.31 6.79 9 6 9a3 3 0 0 0-3 3 3 3 0 0 0 3 3c.79 0 1.5-.31 2.04-.81l7.12 4.15c-.05.21-.08.43-.08.66 0 1.61 1.31 2.91 2.92 2.91s2.92-1.3 2.92-2.91A2.92 2.92 0 0 0 18 16.08"/></svg>
</a>
<button type="reset" class="md-search__icon md-icon" title="Clear" aria-label="Clear" tabindex="-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg>
</button>
</nav>
<div class="md-search__suggest" data-md-component="search-suggest"></div>
</form>
<div class="md-search__output">
<div class="md-search__scrollwrap" tabindex="0" data-md-scrollfix>
<div class="md-search-result" data-md-component="search-result">
<div class="md-search-result__meta">
Initializing search
</div>
<ol class="md-search-result__list" role="presentation"></ol>
</div>
</div>
</div>
</div>
</div>
</nav>
</header>
<div class="md-container" data-md-component="container">
<main class="md-main" data-md-component="main">
<div class="md-main__inner md-grid">
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" >
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--primary" aria-label="Navigation" data-md-level="0">
<label class="md-nav__title" for="__drawer">
<a href=".." title="Aetos Standards — Reference" class="md-nav__button md-logo" aria-label="Aetos Standards — Reference" data-md-component="logo">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54"/></svg>
</a>
Aetos Standards — Reference
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href=".." class="md-nav__link">
<span class="md-ellipsis">
Home
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--active">
<input class="md-nav__toggle md-toggle" type="checkbox" id="__toc">
<label class="md-nav__link md-nav__link--active" for="__toc">
<span class="md-ellipsis">
Build Recipe
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<a href="./" class="md-nav__link md-nav__link--active">
<span class="md-ellipsis">
Build Recipe
</span>
</a>
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
<label class="md-nav__title" for="__toc">
<span class="md-nav__icon md-icon"></span>
Table of contents
</label>
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
<li class="md-nav__item">
<a href="#summary" class="md-nav__link">
<span class="md-ellipsis">
Summary
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#bootstrap" class="md-nav__link">
<span class="md-ellipsis">
🚀 Bootstrap
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#agent-prompt-copyable" class="md-nav__link">
<span class="md-ellipsis">
📋 Agent prompt (copyable)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#where-the-steps-land" class="md-nav__link">
<span class="md-ellipsis">
🧭 Where the steps land
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#the-codegen-fast-path-in-detail" class="md-nav__link">
<span class="md-ellipsis">
🔧 The codegen fast path, in detail
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#definition-of-done" class="md-nav__link">
<span class="md-ellipsis">
⚠️ Definition of done
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#related" class="md-nav__link">
<span class="md-ellipsis">
Related
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../02_layering_rules/" class="md-nav__link">
<span class="md-ellipsis">
Layering Rules
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../03_composition_root/" class="md-nav__link">
<span class="md-ellipsis">
Composition Root
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../04_spec_first_routing/" class="md-nav__link">
<span class="md-ellipsis">
Spec-First Routing
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../05_crud_template/" class="md-nav__link">
<span class="md-ellipsis">
CRUD Template
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../06_pipeline_scaffold/" class="md-nav__link">
<span class="md-ellipsis">
Pipeline Scaffold
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../07_worker_and_progress/" class="md-nav__link">
<span class="md-ellipsis">
Worker & Progress
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../08_human_in_loop/" class="md-nav__link">
<span class="md-ellipsis">
Human-in-the-Loop
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../09_infra_adaptors/" class="md-nav__link">
<span class="md-ellipsis">
Infra Adapters
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../10_drone_pipelines/" class="md-nav__link">
<span class="md-ellipsis">
Drone Pipelines
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../11_versioning_and_changelog/" class="md-nav__link">
<span class="md-ellipsis">
Versioning & Changelog
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../15_repository_inventory/" class="md-nav__link">
<span class="md-ellipsis">
Repository Inventory
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../12_genericity_matrix/" class="md-nav__link">
<span class="md-ellipsis">
Genericity Matrix
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../14_auth_integration/" class="md-nav__link">
<span class="md-ellipsis">
Auth Integration
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../13_library_registry/" class="md-nav__link">
<span class="md-ellipsis">
Library Registry
</span>
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc" >
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
<label class="md-nav__title" for="__toc">
<span class="md-nav__icon md-icon"></span>
Table of contents
</label>
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
<li class="md-nav__item">
<a href="#summary" class="md-nav__link">
<span class="md-ellipsis">
Summary
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#bootstrap" class="md-nav__link">
<span class="md-ellipsis">
🚀 Bootstrap
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#agent-prompt-copyable" class="md-nav__link">
<span class="md-ellipsis">
📋 Agent prompt (copyable)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#where-the-steps-land" class="md-nav__link">
<span class="md-ellipsis">
🧭 Where the steps land
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#the-codegen-fast-path-in-detail" class="md-nav__link">
<span class="md-ellipsis">
🔧 The codegen fast path, in detail
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#definition-of-done" class="md-nav__link">
<span class="md-ellipsis">
⚠️ Definition of done
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#related" class="md-nav__link">
<span class="md-ellipsis">
Related
</span>
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-content" data-md-component="content">
<article class="md-content__inner md-typeset">
<h1 id="build-recipe">Build Recipe</h1>
<h2 id="summary">Summary</h2>
<p>The ordered, deterministic checklist for generating a new application of the
standard shape. Every step is fixed; only the resource model (step 2), the
codegen pass (step 3), and the pipeline family (step 8) need app-specific work.</p>
<p>This page is served by the <code>standards</code> MCP as <code>docs://modules/build_recipe</code>. The
<code>start_app</code> prompt on that server collects the two axes and hands off here; pull
exact files with <code>get_app_component</code>.</p>
<hr />
<h2 id="bootstrap">🚀 Bootstrap</h2>
<p>From the standards docs checkout:</p>
<div class="language-bash highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal"><a href="#__codelineno-0-1">1</a></span>
<span class="normal"><a href="#__codelineno-0-2">2</a></span></pre></div></td><td class="code"><div><pre><span></span><code><span id="__span-0-1"><a id="__codelineno-0-1" name="__codelineno-0-1"></a>cp<span class="w"> </span>-r<span class="w"> </span>&lt;docs&gt;/standards/src/templates/app<span class="w"> </span>apps/&lt;your-app&gt;
</span><span id="__span-0-2"><a id="__codelineno-0-2" name="__codelineno-0-2"></a><span class="nb">cd</span><span class="w"> </span>apps/&lt;your-app&gt;
</span></code></pre></div></td></tr></table></div>
<p>Install the internal libraries — editable local checkouts (preferred in
development) or the private index (CI / fresh machines). Credentials are
environment-only; never commit them.</p>
<div class="language-bash highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal"><a href="#__codelineno-1-1">1</a></span>
<span class="normal"><a href="#__codelineno-1-2">2</a></span>
<span class="normal"><a href="#__codelineno-1-3">3</a></span>
<span class="normal"><a href="#__codelineno-1-4">4</a></span>
<span class="normal"><a href="#__codelineno-1-5">5</a></span>
<span class="normal"><a href="#__codelineno-1-6">6</a></span></pre></div></td><td class="code"><div><pre><span></span><code><span id="__span-1-1"><a id="__codelineno-1-1" name="__codelineno-1-1"></a><span class="c1"># local checkouts</span>
</span><span id="__span-1-2"><a id="__codelineno-1-2" name="__codelineno-1-2"></a>pip<span class="w"> </span>install<span class="w"> </span>-e<span class="w"> </span>../aetos/openapi-first<span class="w"> </span>-e<span class="w"> </span>../aetos/mongo-ops<span class="w"> </span>-e<span class="w"> </span>../aetos/hexa<span class="w"> </span><span class="se">\</span>
</span><span id="__span-1-3"><a id="__codelineno-1-3" name="__codelineno-1-3"></a><span class="w"> </span>-e<span class="w"> </span>../aetos/dagpipe<span class="w"> </span>-e<span class="w"> </span>../aetos/doc-forge
</span><span id="__span-1-4"><a id="__codelineno-1-4" name="__codelineno-1-4"></a><span class="c1"># private index</span>
</span><span id="__span-1-5"><a id="__codelineno-1-5" name="__codelineno-1-5"></a>pip<span class="w"> </span>install<span class="w"> </span>--extra-index-url<span class="w"> </span><span class="se">\</span>
</span><span id="__span-1-6"><a id="__codelineno-1-6" name="__codelineno-1-6"></a><span class="w"> </span><span class="s2">&quot;https://</span><span class="nv">$PIP_REGISTRY_USERNAME</span><span class="s2">:</span><span class="nv">$PIP_REGISTRY_PASSWORD</span><span class="s2">@pip.aetoskia.com/simple&quot;</span><span class="w"> </span>.
</span></code></pre></div></td></tr></table></div>
<hr />
<h2 id="agent-prompt-copyable">📋 Agent prompt (copyable)</h2>
<div class="language-markdown highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal"><a href="#__codelineno-2-1"> 1</a></span>
<span class="normal"><a href="#__codelineno-2-2"> 2</a></span>
<span class="normal"><a href="#__codelineno-2-3"> 3</a></span>
<span class="normal"><a href="#__codelineno-2-4"> 4</a></span>
<span class="normal"><a href="#__codelineno-2-5"> 5</a></span>
<span class="normal"><a href="#__codelineno-2-6"> 6</a></span>
<span class="normal"><a href="#__codelineno-2-7"> 7</a></span>
<span class="normal"><a href="#__codelineno-2-8"> 8</a></span>
<span class="normal"><a href="#__codelineno-2-9"> 9</a></span>
<span class="normal"><a href="#__codelineno-2-10">10</a></span>
<span class="normal"><a href="#__codelineno-2-11">11</a></span>
<span class="normal"><a href="#__codelineno-2-12">12</a></span>
<span class="normal"><a href="#__codelineno-2-13">13</a></span>
<span class="normal"><a href="#__codelineno-2-14">14</a></span>
<span class="normal"><a href="#__codelineno-2-15">15</a></span>
<span class="normal"><a href="#__codelineno-2-16">16</a></span>
<span class="normal"><a href="#__codelineno-2-17">17</a></span>
<span class="normal"><a href="#__codelineno-2-18">18</a></span>
<span class="normal"><a href="#__codelineno-2-19">19</a></span>
<span class="normal"><a href="#__codelineno-2-20">20</a></span>
<span class="normal"><a href="#__codelineno-2-21">21</a></span>
<span class="normal"><a href="#__codelineno-2-22">22</a></span>
<span class="normal"><a href="#__codelineno-2-23">23</a></span>
<span class="normal"><a href="#__codelineno-2-24">24</a></span>
<span class="normal"><a href="#__codelineno-2-25">25</a></span>
<span class="normal"><a href="#__codelineno-2-26">26</a></span>
<span class="normal"><a href="#__codelineno-2-27">27</a></span>
<span class="normal"><a href="#__codelineno-2-28">28</a></span>
<span class="normal"><a href="#__codelineno-2-29">29</a></span>
<span class="normal"><a href="#__codelineno-2-30">30</a></span>
<span class="normal"><a href="#__codelineno-2-31">31</a></span>
<span class="normal"><a href="#__codelineno-2-32">32</a></span>
<span class="normal"><a href="#__codelineno-2-33">33</a></span>
<span class="normal"><a href="#__codelineno-2-34">34</a></span>
<span class="normal"><a href="#__codelineno-2-35">35</a></span>
<span class="normal"><a href="#__codelineno-2-36">36</a></span>
<span class="normal"><a href="#__codelineno-2-37">37</a></span>
<span class="normal"><a href="#__codelineno-2-38">38</a></span>
<span class="normal"><a href="#__codelineno-2-39">39</a></span>
<span class="normal"><a href="#__codelineno-2-40">40</a></span>
<span class="normal"><a href="#__codelineno-2-41">41</a></span>
<span class="normal"><a href="#__codelineno-2-42">42</a></span>
<span class="normal"><a href="#__codelineno-2-43">43</a></span>
<span class="normal"><a href="#__codelineno-2-44">44</a></span>
<span class="normal"><a href="#__codelineno-2-45">45</a></span>
<span class="normal"><a href="#__codelineno-2-46">46</a></span>
<span class="normal"><a href="#__codelineno-2-47">47</a></span>
<span class="normal"><a href="#__codelineno-2-48">48</a></span>
<span class="normal"><a href="#__codelineno-2-49">49</a></span>
<span class="normal"><a href="#__codelineno-2-50">50</a></span>
<span class="normal"><a href="#__codelineno-2-51">51</a></span>
<span class="normal"><a href="#__codelineno-2-52">52</a></span>
<span class="normal"><a href="#__codelineno-2-53">53</a></span>
<span class="normal"><a href="#__codelineno-2-54">54</a></span>
<span class="normal"><a href="#__codelineno-2-55">55</a></span>
<span class="normal"><a href="#__codelineno-2-56">56</a></span>
<span class="normal"><a href="#__codelineno-2-57">57</a></span>
<span class="normal"><a href="#__codelineno-2-58">58</a></span>
<span class="normal"><a href="#__codelineno-2-59">59</a></span>
<span class="normal"><a href="#__codelineno-2-60">60</a></span>
<span class="normal"><a href="#__codelineno-2-61">61</a></span>
<span class="normal"><a href="#__codelineno-2-62">62</a></span>
<span class="normal"><a href="#__codelineno-2-63">63</a></span>
<span class="normal"><a href="#__codelineno-2-64">64</a></span>
<span class="normal"><a href="#__codelineno-2-65">65</a></span>
<span class="normal"><a href="#__codelineno-2-66">66</a></span>
<span class="normal"><a href="#__codelineno-2-67">67</a></span>
<span class="normal"><a href="#__codelineno-2-68">68</a></span>
<span class="normal"><a href="#__codelineno-2-69">69</a></span>
<span class="normal"><a href="#__codelineno-2-70">70</a></span>
<span class="normal"><a href="#__codelineno-2-71">71</a></span>
<span class="normal"><a href="#__codelineno-2-72">72</a></span>
<span class="normal"><a href="#__codelineno-2-73">73</a></span>
<span class="normal"><a href="#__codelineno-2-74">74</a></span>
<span class="normal"><a href="#__codelineno-2-75">75</a></span>
<span class="normal"><a href="#__codelineno-2-76">76</a></span>
<span class="normal"><a href="#__codelineno-2-77">77</a></span>
<span class="normal"><a href="#__codelineno-2-78">78</a></span>
<span class="normal"><a href="#__codelineno-2-79">79</a></span>
<span class="normal"><a href="#__codelineno-2-80">80</a></span>
<span class="normal"><a href="#__codelineno-2-81">81</a></span>
<span class="normal"><a href="#__codelineno-2-82">82</a></span>
<span class="normal"><a href="#__codelineno-2-83">83</a></span>
<span class="normal"><a href="#__codelineno-2-84">84</a></span>
<span class="normal"><a href="#__codelineno-2-85">85</a></span>
<span class="normal"><a href="#__codelineno-2-86">86</a></span>
<span class="normal"><a href="#__codelineno-2-87">87</a></span>
<span class="normal"><a href="#__codelineno-2-88">88</a></span>
<span class="normal"><a href="#__codelineno-2-89">89</a></span>
<span class="normal"><a href="#__codelineno-2-90">90</a></span>
<span class="normal"><a href="#__codelineno-2-91">91</a></span></pre></div></td><td class="code"><div><pre><span></span><code><span id="__span-2-1"><a id="__codelineno-2-1" name="__codelineno-2-1"></a><span class="gh"># Build a new application from the Aetos Standards blueprint</span>
</span><span id="__span-2-2"><a id="__codelineno-2-2" name="__codelineno-2-2"></a>
</span><span id="__span-2-3"><a id="__codelineno-2-3" name="__codelineno-2-3"></a>You are coding a complete new backend application conforming to the Aetos
</span><span id="__span-2-4"><a id="__codelineno-2-4" name="__codelineno-2-4"></a>standard app blueprint. Execute every step in order. Only steps 2–4 use the
</span><span id="__span-2-5"><a id="__codelineno-2-5" name="__codelineno-2-5"></a>app-specific details provided by the user; everything else is deterministic.
</span><span id="__span-2-6"><a id="__codelineno-2-6" name="__codelineno-2-6"></a>
</span><span id="__span-2-7"><a id="__codelineno-2-7" name="__codelineno-2-7"></a><span class="gu">## Before writing any code</span>
</span><span id="__span-2-8"><a id="__codelineno-2-8" name="__codelineno-2-8"></a>
</span><span id="__span-2-9"><a id="__codelineno-2-9" name="__codelineno-2-9"></a>Connect to the <span class="sb">`standards`</span> MCP server and read:
</span><span id="__span-2-10"><a id="__codelineno-2-10" name="__codelineno-2-10"></a><span class="k">-</span><span class="w"> </span><span class="sb">`docs://nav`</span> (the module list)
</span><span id="__span-2-11"><a id="__codelineno-2-11" name="__codelineno-2-11"></a><span class="k">-</span><span class="w"> </span><span class="sb">`docs://modules/genericity_matrix`</span> (Tier A library / Tier B template / Tier C authored)
</span><span id="__span-2-12"><a id="__codelineno-2-12" name="__codelineno-2-12"></a><span class="k">-</span><span class="w"> </span><span class="sb">`docs://modules/layering_rules`</span> (the dependency rules)
</span><span id="__span-2-13"><a id="__codelineno-2-13" name="__codelineno-2-13"></a>
</span><span id="__span-2-14"><a id="__codelineno-2-14" name="__codelineno-2-14"></a>Then:
</span><span id="__span-2-15"><a id="__codelineno-2-15" name="__codelineno-2-15"></a><span class="k">-</span><span class="w"> </span>call <span class="sb">`find_library`</span> with <span class="sb">`db`</span>, <span class="sb">`di`</span>, <span class="sb">`routing`</span>, <span class="sb">`ingestion`</span>, <span class="sb">`pipeline`</span>, <span class="sb">`docs`</span>
</span><span id="__span-2-16"><a id="__codelineno-2-16" name="__codelineno-2-16"></a> and note the Tier A libraries that already exist — never reimplement one;
</span><span id="__span-2-17"><a id="__codelineno-2-17" name="__codelineno-2-17"></a><span class="k">-</span><span class="w"> </span>call <span class="sb">`list_app_components()`</span> and pull each file you need with
</span><span id="__span-2-18"><a id="__codelineno-2-18" name="__codelineno-2-18"></a> <span class="sb">`get_app_component(kind, resource=..., family=...)`</span> instead of writing it from
</span><span id="__span-2-19"><a id="__codelineno-2-19" name="__codelineno-2-19"></a> scratch.
</span><span id="__span-2-20"><a id="__codelineno-2-20" name="__codelineno-2-20"></a>
</span><span id="__span-2-21"><a id="__codelineno-2-21" name="__codelineno-2-21"></a><span class="gu">## Steps</span>
</span><span id="__span-2-22"><a id="__codelineno-2-22" name="__codelineno-2-22"></a>
</span><span id="__span-2-23"><a id="__codelineno-2-23" name="__codelineno-2-23"></a><span class="k">1.</span> <span class="gs">**Scaffold**</span> — copy <span class="sb">`standards/src/templates/app/`</span> into <span class="sb">`apps/&lt;your-app&gt;/`</span>
</span><span id="__span-2-24"><a id="__codelineno-2-24" name="__codelineno-2-24"></a> (or pull the same tree via <span class="sb">`get_app_template`</span>). Keep the tree: <span class="sb">`domain/`</span>,
</span><span id="__span-2-25"><a id="__codelineno-2-25" name="__codelineno-2-25"></a> <span class="sb">`infra/`</span>, <span class="sb">`interfaces/`</span>, <span class="sb">`pipelines/`</span>, <span class="sb">`tests/`</span>, <span class="sb">`scripts/`</span>, plus
</span><span id="__span-2-26"><a id="__codelineno-2-26" name="__codelineno-2-26"></a> <span class="sb">`pyproject.toml`</span>, <span class="sb">`openapi.yaml`</span>, <span class="sb">`config.py`</span>, <span class="sb">`init.py`</span>, <span class="sb">`main.py`</span>,
</span><span id="__span-2-27"><a id="__codelineno-2-27" name="__codelineno-2-27"></a> <span class="sb">`worker.py`</span>, <span class="sb">`Dockerfile`</span>, <span class="sb">`docker-compose.yaml`</span>, <span class="sb">`.env.example`</span>.
</span><span id="__span-2-28"><a id="__codelineno-2-28" name="__codelineno-2-28"></a>
</span><span id="__span-2-29"><a id="__codelineno-2-29" name="__codelineno-2-29"></a><span class="k">2.</span> <span class="gs">**Author the spec (app-specific)**</span> — write <span class="sb">`openapi.yaml`</span>: resources,
</span><span id="__span-2-30"><a id="__codelineno-2-30" name="__codelineno-2-30"></a> schemas, <span class="sb">`operationId`</span>s, security, and extension metadata. This is the
</span><span id="__span-2-31"><a id="__codelineno-2-31" name="__codelineno-2-31"></a> contract and drives all routing. Every operation MUST have an <span class="sb">`operationId`</span>.
</span><span id="__span-2-32"><a id="__codelineno-2-32" name="__codelineno-2-32"></a>
</span><span id="__span-2-33"><a id="__codelineno-2-33" name="__codelineno-2-33"></a><span class="k">3.</span> <span class="gs">**Generate the scaffold (codegen)**</span> — from the spec, generate the wire
</span><span id="__span-2-34"><a id="__codelineno-2-34" name="__codelineno-2-34"></a> models and the exact handler signatures:
</span><span id="__span-2-35"><a id="__codelineno-2-35" name="__codelineno-2-35"></a><span class="sb"> ```bash</span>
</span><span id="__span-2-36"><a id="__codelineno-2-36" name="__codelineno-2-36"></a><span class="w"> </span>openapi-first<span class="w"> </span>models<span class="w"> </span>openapi.yaml<span class="w"> </span>-o<span class="w"> </span>_gen/models.py
</span><span id="__span-2-37"><a id="__codelineno-2-37" name="__codelineno-2-37"></a><span class="w"> </span>openapi-first<span class="w"> </span>routes<span class="w"> </span>openapi.yaml<span class="w"> </span>-o<span class="w"> </span>_gen/routes<span class="w"> </span><span class="se">\</span>
</span><span id="__span-2-38"><a id="__codelineno-2-38" name="__codelineno-2-38"></a><span class="w"> </span>--use-models<span class="w"> </span>--models-module<span class="w"> </span>_gen.models<span class="w"> </span>--inject-request<span class="w"> </span>--package<span class="w"> </span>--template-style
</span><span id="__span-2-39"><a id="__codelineno-2-39" name="__codelineno-2-39"></a><span class="sb"> ```</span>
</span><span id="__span-2-40"><a id="__codelineno-2-40" name="__codelineno-2-40"></a> <span class="sb">`_gen/models.py`</span> is the <span class="gs">**wire contract**</span> (Pydantic, one class per
</span><span id="__span-2-41"><a id="__codelineno-2-41" name="__codelineno-2-41"></a> <span class="sb">`components.schemas`</span> entry). <span class="sb">`_gen/routes/&lt;resource&gt;/routes.py`</span> lists every
</span><span id="__span-2-42"><a id="__codelineno-2-42" name="__codelineno-2-42"></a> <span class="sb">`operationId`</span> with its exact parameter signature. <span class="sb">`--template-style`</span> makes
</span><span id="__span-2-43"><a id="__codelineno-2-43" name="__codelineno-2-43"></a> those stubs <span class="sb">`async def`</span> with a <span class="sb">`body`</span> parameter, matching the handlers you
</span><span id="__span-2-44"><a id="__codelineno-2-44" name="__codelineno-2-44"></a> keep in <span class="sb">`interfaces/`</span> (without it they are sync <span class="sb">`def`</span> stubs taking
</span><span id="__span-2-45"><a id="__codelineno-2-45" name="__codelineno-2-45"></a> <span class="sb">`payload`</span>; both bind the same way). Treat <span class="sb">`_gen/`</span> as generated
</span><span id="__span-2-46"><a id="__codelineno-2-46" name="__codelineno-2-46"></a> (never hand-edit it) — the canonical handlers live in <span class="sb">`interfaces/`</span>.
</span><span id="__span-2-47"><a id="__codelineno-2-47" name="__codelineno-2-47"></a>
</span><span id="__span-2-48"><a id="__codelineno-2-48" name="__codelineno-2-48"></a><span class="k">4.</span> <span class="gs">**Write each CRUD slice (app-specific)**</span> — per resource create the four-file
</span><span id="__span-2-49"><a id="__codelineno-2-49" name="__codelineno-2-49"></a> slice: <span class="sb">`models.py`</span> (domain model, <span class="gs">**no `id`**</span>), <span class="sb">`ports/db.py`</span>
</span><span id="__span-2-50"><a id="__codelineno-2-50" name="__codelineno-2-50"></a> (<span class="sb">`class XDocument(BaseDocument, X)`</span> — id comes from <span class="sb">`BaseDocument`</span>),
</span><span id="__span-2-51"><a id="__codelineno-2-51" name="__codelineno-2-51"></a> <span class="sb">`ports/service.py`</span>, and optional <span class="sb">`converters.py`</span>. Follow the CRUD template.
</span><span id="__span-2-52"><a id="__codelineno-2-52" name="__codelineno-2-52"></a>
</span><span id="__span-2-53"><a id="__codelineno-2-53" name="__codelineno-2-53"></a><span class="k">5.</span> <span class="gs">**Wire the composition root**</span> — in <span class="sb">`init.py`</span>, build leaf repositories, then
</span><span id="__span-2-54"><a id="__codelineno-2-54" name="__codelineno-2-54"></a> dependent repositories, then services; add infra adapters (db, cache, stores,
</span><span id="__span-2-55"><a id="__codelineno-2-55" name="__codelineno-2-55"></a> progress bus, fetchers). Expose <span class="sb">`get_svc`</span> overloads.
</span><span id="__span-2-56"><a id="__codelineno-2-56" name="__codelineno-2-56"></a>
</span><span id="__span-2-57"><a id="__codelineno-2-57" name="__codelineno-2-57"></a><span class="k">6.</span> <span class="gs">**Add routes**</span> — create <span class="sb">`interfaces/&lt;resource&gt;/routes.py`</span> thin handlers whose
</span><span id="__span-2-58"><a id="__codelineno-2-58" name="__codelineno-2-58"></a> names match the <span class="sb">`operationId`</span>s (use the signatures from step 3 as your
</span><span id="__span-2-59"><a id="__codelineno-2-59" name="__codelineno-2-59"></a> checklist) and re-export them in <span class="sb">`interfaces/openapi.py`</span>. Add the cache
</span><span id="__span-2-60"><a id="__codelineno-2-60" name="__codelineno-2-60"></a> decorator to read endpoints.
</span><span id="__span-2-61"><a id="__codelineno-2-61" name="__codelineno-2-61"></a>
</span><span id="__span-2-62"><a id="__codelineno-2-62" name="__codelineno-2-62"></a><span class="k">7.</span> <span class="gs">**Bootstrap app and worker**</span> — confirm <span class="sb">`main.py`</span> runs the OpenAPI-first app
</span><span id="__span-2-63"><a id="__codelineno-2-63" name="__codelineno-2-63"></a> with its lifespan. If the app has long-running jobs, adapt <span class="sb">`worker.py`</span> to poll
</span><span id="__span-2-64"><a id="__codelineno-2-64" name="__codelineno-2-64"></a> the job collection, run the pipeline, and publish progress.
</span><span id="__span-2-65"><a id="__codelineno-2-65" name="__codelineno-2-65"></a>
</span><span id="__span-2-66"><a id="__codelineno-2-66" name="__codelineno-2-66"></a><span class="k">8.</span> <span class="gs">**Add pipeline families (only if data-driven)**</span> — copy <span class="sb">`pipelines/example/`</span>
</span><span id="__span-2-67"><a id="__codelineno-2-67" name="__codelineno-2-67"></a> to <span class="sb">`pipelines/&lt;family&gt;/`</span> with <span class="sb">`abc.py`</span>, <span class="sb">`impl.py`</span>, <span class="sb">`pipeline.yaml`</span>,
</span><span id="__span-2-68"><a id="__codelineno-2-68" name="__codelineno-2-68"></a> <span class="sb">`resources/`</span>, and reuse <span class="sb">`pipelines/shared/`</span> (loader + registry). Register the
</span><span id="__span-2-69"><a id="__codelineno-2-69" name="__codelineno-2-69"></a> root. Add fixtures and a parity test.
</span><span id="__span-2-70"><a id="__codelineno-2-70" name="__codelineno-2-70"></a>
</span><span id="__span-2-71"><a id="__codelineno-2-71" name="__codelineno-2-71"></a><span class="k">9.</span> <span class="gs">**Add infrastructure only where needed**</span> — Tier A capability: use the
</span><span id="__span-2-72"><a id="__codelineno-2-72" name="__codelineno-2-72"></a> library. Tier B capability: copy the template. Never hand-write a Tier A
</span><span id="__span-2-73"><a id="__codelineno-2-73" name="__codelineno-2-73"></a> library.
</span><span id="__span-2-74"><a id="__codelineno-2-74" name="__codelineno-2-74"></a>
</span><span id="__span-2-75"><a id="__codelineno-2-75" name="__codelineno-2-75"></a><span class="k">10.</span> <span class="gs">**Tests**</span> — integration tests with fakes at the HTTP edge; unit tests for
</span><span id="__span-2-76"><a id="__codelineno-2-76" name="__codelineno-2-76"></a> domain and pipeline logic; a config-consistency test for rule-driven
</span><span id="__span-2-77"><a id="__codelineno-2-77" name="__codelineno-2-77"></a> pipelines. Include <span class="sb">`tests/integration/test_openapi_app_builds.py`</span> (imports
</span><span id="__span-2-78"><a id="__codelineno-2-78" name="__codelineno-2-78"></a> the app, asserts <span class="sb">`import main`</span> binds every operation).
</span><span id="__span-2-79"><a id="__codelineno-2-79" name="__codelineno-2-79"></a>
</span><span id="__span-2-80"><a id="__codelineno-2-80" name="__codelineno-2-80"></a><span class="k">11.</span> <span class="gs">**Scripts and seeds**</span> — operator scripts under <span class="sb">`scripts/`</span> using
</span><span id="__span-2-81"><a id="__codelineno-2-81" name="__codelineno-2-81"></a> <span class="sb">`init()`</span> / <span class="sb">`get_svc()`</span> / <span class="sb">`shutdown()`</span>; run as <span class="sb">`python -m scripts.&lt;name&gt;`</span>.
</span><span id="__span-2-82"><a id="__codelineno-2-82" name="__codelineno-2-82"></a>
</span><span id="__span-2-83"><a id="__codelineno-2-83" name="__codelineno-2-83"></a><span class="k">12.</span> <span class="gs">**Docs**</span> — author GSDFC docstrings, generate <span class="sb">`.pyi`</span> stubs, mark the package
</span><span id="__span-2-84"><a id="__codelineno-2-84" name="__codelineno-2-84"></a> <span class="sb">`py.typed`</span>, and build the docs.
</span><span id="__span-2-85"><a id="__codelineno-2-85" name="__codelineno-2-85"></a>
</span><span id="__span-2-86"><a id="__codelineno-2-86" name="__codelineno-2-86"></a><span class="gs">**Definition of done:**</span>
</span><span id="__span-2-87"><a id="__codelineno-2-87" name="__codelineno-2-87"></a><span class="k">-</span><span class="w"> </span><span class="sb">`python -c &quot;import main&quot;`</span> succeeds.
</span><span id="__span-2-88"><a id="__codelineno-2-88" name="__codelineno-2-88"></a><span class="k">-</span><span class="w"> </span><span class="sb">`pytest`</span> passes.
</span><span id="__span-2-89"><a id="__codelineno-2-89" name="__codelineno-2-89"></a><span class="k">-</span><span class="w"> </span>The app serves every operation in the spec; the worker drains its queue.
</span><span id="__span-2-90"><a id="__codelineno-2-90" name="__codelineno-2-90"></a><span class="k">-</span><span class="w"> </span>No domain module imports a web framework.
</span><span id="__span-2-91"><a id="__codelineno-2-91" name="__codelineno-2-91"></a><span class="k">-</span><span class="w"> </span>No Tier A library was reimplemented.
</span></code></pre></div></td></tr></table></div>
<hr />
<h2 id="where-the-steps-land">🧭 Where the steps land</h2>
<p>The steps map onto the layers as follows:</p>
<table>
<thead>
<tr>
<th>Step</th>
<th>Package / file</th>
<th>Depends on</th>
</tr>
</thead>
<tbody>
<tr>
<td>1 · Scaffold</td>
<td>whole <code>templates/app/</code></td>
<td>—</td>
</tr>
<tr>
<td>2 · Spec</td>
<td><code>openapi.yaml</code></td>
<td>—</td>
</tr>
<tr>
<td>3 · Codegen</td>
<td><code>_gen/</code> (generated)</td>
<td>spec, openapi-first</td>
</tr>
<tr>
<td>4 · CRUD slices</td>
<td><code>domain/&lt;resource&gt;/</code></td>
<td>spec, CRUD template</td>
</tr>
<tr>
<td>5 · Wiring</td>
<td><code>init.py</code></td>
<td>every slice</td>
</tr>
<tr>
<td>6 · Routes</td>
<td><code>interfaces/&lt;resource&gt;/</code></td>
<td>services, openapi route registry</td>
</tr>
<tr>
<td>7 · Bootstrap</td>
<td><code>main.py</code>, <code>worker.py</code></td>
<td>composition root</td>
</tr>
<tr>
<td>8 · Pipelines</td>
<td><code>pipelines/&lt;family&gt;/</code>, <code>shared/</code></td>
<td>library pipeline engine</td>
</tr>
<tr>
<td>9 · Infra</td>
<td><code>infra/</code></td>
<td>domain ports</td>
</tr>
<tr>
<td>10 · Tests</td>
<td><code>tests/</code></td>
<td>app + fixtures</td>
</tr>
<tr>
<td>11 · Scripts</td>
<td><code>scripts/</code></td>
<td>composition root</td>
</tr>
<tr>
<td>12 · Docs</td>
<td>docstrings + docs build</td>
<td>code, Doc Forge</td>
</tr>
</tbody>
</table>
<hr />
<h2 id="the-codegen-fast-path-in-detail">🔧 The codegen fast path, in detail</h2>
<p><code>openapi-first</code> is spec → code only (it never generates a spec). Use it to erase
the two mechanical parts of the build:</p>
<table>
<thead>
<tr>
<th>Generated artifact</th>
<th>Replaces</th>
<th>Notes</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>_gen/models.py</code></td>
<td>hand-writing Pydantic wire models</td>
<td>one class per <code>components.schemas</code> entry</td>
</tr>
<tr>
<td><code>_gen/routes/&lt;resource&gt;/routes.py</code></td>
<td>hand-typing handler signatures</td>
<td>names == <code>operationId</code>s; <code>request: Request</code> injected</td>
</tr>
</tbody>
</table>
<p>Rules of the road:</p>
<ul>
<li><strong>Wire models are not domain models.</strong> <code>_gen/models.py</code> is the HTTP contract;
<code>domain/&lt;resource&gt;/models.py</code> is your business shape. If the spec's schema has
a required <code>id: str</code>, keep it off the domain model and let the document get its
id from <code>BaseDocument</code>.</li>
<li><strong>Use <code>--template-style</code>.</strong> Stubs are then <code>async def ...(request, body: ...)</code>
matching <code>interfaces/</code>; without it they are sync <code>def ...(payload: ...)</code>.
Either binds (the router introspects the signature), but <code>--template-style</code>
keeps the scaffold consistent with the code you keep.</li>
<li><strong>Resource names are sanitized.</strong> <code>/fetch-requests</code> → <code>fetch_requests.py</code>.</li>
<li><strong>Multipart bodies expand</strong> to <code>UploadFile = File(...)</code> / <code>Form(...)</code> params.</li>
<li><strong><code>_gen/</code> is disposable.</strong> Regenerate on every spec change; <code>git diff</code> shows
exactly what moved.</li>
</ul>
<hr />
<h2 id="definition-of-done">⚠️ Definition of done</h2>
<ul>
<li><code>python -c "import main"</code> succeeds.</li>
<li><code>pytest</code> passes.</li>
<li>The app serves the spec's operations; the worker drains its queue.</li>
<li>No domain module imports a web framework.</li>
<li>No Tier A library was reimplemented.</li>
</ul>
<hr />
<h2 id="related">Related</h2>
<ul>
<li><a href="../02_layering_rules/">02 – Layering Rules</a> · <a href="../05_crud_template/">05 – CRUD Template</a> · <a href="../06_pipeline_scaffold/">06 – Pipeline Scaffold</a> · <a href="../12_genericity_matrix/">12 – Genericity Matrix</a></li>
</ul>
</article>
</div>
<script>var tabs=__md_get("__tabs");if(Array.isArray(tabs))e:for(var set of document.querySelectorAll(".tabbed-set")){var labels=set.querySelector(".tabbed-labels");for(var tab of tabs)for(var label of labels.getElementsByTagName("label"))if(label.innerText.trim()===tab){var input=document.getElementById(label.htmlFor);input.checked=!0;continue e}}</script>
<script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script>
</div>
<button type="button" class="md-top md-icon" data-md-component="top" hidden>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8z"/></svg>
Back to top
</button>
</main>
<footer class="md-footer">
<div class="md-footer-meta md-typeset">
<div class="md-footer-meta__inner md-grid">
<div class="md-copyright">
Made with
<a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
Material for MkDocs
</a>
</div>
</div>
</div>
</footer>
</div>
<div class="md-dialog" data-md-component="dialog">
<div class="md-dialog__inner md-typeset"></div>
</div>
<script id="__config" type="application/json">{"base": "..", "features": ["navigation.sections", "navigation.expand", "navigation.top", "navigation.instant", "navigation.tracking", "navigation.indexes", "content.code.copy", "content.code.annotate", "content.tabs.link", "content.action.edit", "search.highlight", "search.share", "search.suggest"], "search": "../assets/javascripts/workers/search.973d3a69.min.js", "tags": null, "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}, "version": null}</script>
<script src="../assets/javascripts/bundle.f55a23d4.min.js"></script>
</body>
</html>