]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
docs(auth): Modernize
authorPieter Lexis <pieter.lexis@powerdns.com>
Tue, 27 Jan 2026 15:27:39 +0000 (16:27 +0100)
committerPieter Lexis <pieter.lexis@powerdns.com>
Mon, 23 Mar 2026 09:32:46 +0000 (10:32 +0100)
22 files changed:
docs/_static/extra.css [new file with mode: 0644]
docs/_static/favicon.ico [new file with mode: 0644]
docs/_static/pdns.css [deleted file]
docs/_static/powerdns-logo-500px.png [new file with mode: 0644]
docs/_static/powerdns-logo-trans.png [new file with mode: 0644]
docs/_static/powerdns_logo_white_orange_rgb.png [new file with mode: 0644]
docs/appendices/backend-writers-guide.rst
docs/changelog/4.1.rst
docs/conf.py
docs/http-api/autoprimaries.rst
docs/http-api/cache.rst
docs/http-api/cryptokey.rst
docs/http-api/index.rst
docs/http-api/metadata.rst
docs/http-api/search.rst
docs/http-api/server.rst
docs/http-api/statistics.rst
docs/http-api/swagger/authoritative-api-swagger.yaml
docs/http-api/tsigkey.rst
docs/http-api/zone.rst
docs/requirements.in
docs/requirements.txt

diff --git a/docs/_static/extra.css b/docs/_static/extra.css
new file mode 100644 (file)
index 0000000..c18a332
--- /dev/null
@@ -0,0 +1,21 @@
+:root {
+    --md-primary-fg-color:        #e66e00;
+    --md-primary-fg-color--light: #e66e00;
+    --md-primary-fg-color--dark:  #e66e00;
+}
+
+.md-header {
+    background-color: #666666;
+}
+
+.md-tabs {
+    background-color: #e66e00;
+}
+
+.md-nav .md-nav__item--section {
+    font-size: 125%;
+}
+
+td > code {
+    white-space: nowrap;
+}
diff --git a/docs/_static/favicon.ico b/docs/_static/favicon.ico
new file mode 100644 (file)
index 0000000..70dd4c2
Binary files /dev/null and b/docs/_static/favicon.ico differ
diff --git a/docs/_static/pdns.css b/docs/_static/pdns.css
deleted file mode 100644 (file)
index 0a6f10c..0000000
+++ /dev/null
@@ -1,1052 +0,0 @@
-body {
-  background-color: #edf0f2;
-  margin: 0;
-  padding: 0;
-  font-family: "Open Sans", Helvetica, Arial, sans-serif;
-  font-size: 16px;
-  color: #333;
-  line-height: 1.5;
-}
-
-#left-column {
-  float: left;
-  position: fixed;
-  height: 100%;
-  border-right: 1px solid #e0e0e0;
-  width: 300px;
-  overflow: auto;
-  background: #fafafa;
-}
-
-#right-column {
-  padding: 20px 0;
-  margin-left: 300px;
-  background-color: #fff;
-  max-width: 900px;
-}
-
-a.headerlink {
-  visibility: hidden;
-  color: #ddd;
-  padding: 0 4px;
-  text-decoration: none;
-}
-
-h1:hover > a.headerlink,
-h2:hover > a.headerlink,
-h3:hover > a.headerlink,
-h4:hover > a.headerlink,
-h5:hover > a.headerlink,
-h6:hover > a.headerlink,
-dt:hover > a.headerlink {
-  visibility: visible;
-}
-
-h1 > a, h2 > a, h3 > a, h4 > a, h5 > a, h6 > a {
-  color: #5C7C98;
-}
-
-h1, h2, h3, h4, h5, h6 {
-  color: black;
-  font-weight: normal;
-  padding: 0;
-  font-family: "Source Serif Pro", "serif";
-}
-
-h1, h2, h3 {
-  margin-top: 30px;
-  margin-bottom: 20px;
-}
-
-h1 {
-  font-size: 38px;
-  padding: 10px 10px 10px 45px;
-  margin: 20px 0 35px -45px;
-  background-color: aliceblue;
-  width: calc(100% + 90px);
-  border-bottom: 1px solid #D8E4EF;
-}
-
-h1 > pre,
-h1 > code,
-h1 > tt {
-  font-size: 38px;
-}
-
-h2 {
-  font-size: 34px;
-  padding: .2em 0;
-  border-bottom: 1px solid #ddd;
-}
-
-h2 > pre,
-h2 > code,
-h2 > tt {
-  font-size: 34px;
-}
-
-h3 {
-  margin-top: 35px;
-  font-size: 28px;
-}
-
-h3 > pre,
-h3 > code,
-h3 > tt {
-  font-size: 28px;
-}
-
-h4 {
-  margin-top: 30px;
-  font-size: 24px;
-}
-
-h4 > pre,
-h4 > code,
-h4 > tt {
-  font-size: 24px;
-}
-
-h5 {
-  margin-top: 25px;
-  font-size: 20px;
-}
-
-h5 > pre,
-h5 > code,
-h5 > tt {
-  font-size: 20px;
-}
-
-div.clearer {
-  clear: both;
-}
-
-.container-wrapper {
-  padding: 0;
-  position: relative;
-}
-
-div.related {
-  display: none;
-}
-
-p {
-  padding: 0;
-  font-family: inherit;
-  font-size: inherit;
-  color: #333;
-}
-
-code, pre, tt {
-  font-size: 15px;
-  font-family: Consolas, monospace;
-}
-
-code, tt {
-  color: #8D1A38;
-}
-
-tt {
-  padding: 0 2px;
-}
-
-code, pre {
-  line-height: 23px;
-  margin: 20px 0;
-  word-wrap: normal;
-  background-color: #fff;
-}
-
-pre {
-  color: #333;
-  background-color: #fff;
-  overflow: auto;
-  border-width: 0 0 0 2px;
-  border-color: #eee;
-  border-style: solid;
-  padding: 14px 0 14px 20px;
-  padding-right: 0;
-  margin: 20px 0;
-}
-
-div.highlight {
-  background-color: white;
-}
-
-a.internal em {
-  font-style: normal;
-}
-
-dl dd {
-  margin: 3px 0 10px 30px;
-}
-
-dl.method {
-  border-bottom: 1px solid #ccc;
-}
-
-.breadcrumb {
-  font-size: 15px;
-  margin-bottom: 12px;
-  background: #fff;
-}
-
-blockquote {
-  border-width: .1em 0 .1em 0;
-  border-color: #e5eef2;
-  border-style: solid;
-  background-color: #f3f8f9;
-  color: #000;
-  margin: 20px 0;
-  padding: 15px 20px;
-  font-size: 16px;
-}
-
-/* Sphinx sidebar
--------------------------------------------------- */
-
-div.sphinxsidebar {
-  word-wrap: break-word;
-}
-
-div.sphinxsidebar .panel-default > .panel-heading {
-    background-image: none;
-}
-
-.sidebar-wrapper {
-  padding: 0 22px;
-}
-
-div.sphinxsidebar h3,
-div.sphinxsidebar h4 {
-  color: #444;
-  font-size: 20px;
-  font-weight: normal;
-  margin: 0;
-  padding: 0;
-}
-
-div.sphinxsidebar h4 {
-  font-size: 16px;
-}
-
-div.sphinxsidebar p {
-  color: #555;
-  margin: 10px 0;
-}
-
-.sidebar-toc {
-  font-size: 15px;
-}
-
-div.sphinxsidebar .sidebar-toc ul {
-  margin: 0 0 4px 0;
-  list-style-type: none;
-  color: #000;
-}
-
-div.sphinxsidebar .sidebar-toc a {
-  font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
-  color: #444;
-  text-decoration: none;
-}
-
-.sidebar-toc > ul {
-    padding: 0 !important;
-    list-style-type: none;
-    margin: 0;
-}
-
-.sidebar-toc ul li a {
-  display: block;
-}
-
-.sidebar-toc ul li a:hover {
-  background-color: #428bca;
-  color: #fff;
-}
-
-.sidebar-toc ul li.current > a,
-.sidebar-toc ul li.current > a:hover {
-  background-color: #e6e6e6;
-  color: #444;
-}
-
-.sidebar-toc ul li.toctree-l1 a {
-  padding: 5px 25px;
-}
-
-.sidebar-toc ul li.toctree-l2 a {
-  padding: 5px 50px;
-}
-
-.sidebar-toc ul li.toctree-l3 a {
-  padding: 5px 75px;
-}
-
-div.sphinxsidebar ul.want-points {
-  padding-left: 20px;
-  margin: 0;
-}
-
-div.sphinxsidebar .sidebar-toc ul ul {
-  margin: 0;
-  padding: 0;
-}
-
-.sidebar-localtoc ul {
-    padding-left: 24px;
-}
-
-div.sphinxsidebar input {
-  border: 1px solid #ccc;
-  font-family: Helvetica, arial, freesans, clean, sans-serif;
-  font-size: 1em;
-}
-
-.margin-top-1em {
-  margin-top: 1em;
-}
-
-.sidebar-block {
-  padding: 0;
-  margin: 14px 0 30px 0;
-}
-
-.sidebar-block h2 {
-  border-bottom: none;
-  margin: 0 0 17px 0;
-  font-size: 14px;
-  font-family: "Open Sans", Helvetica, Arial, sans-serif;
-  padding: 0 0 6px 0;
-  font-weight: bold;
-  text-transform: uppercase;
-  color: #606060;
-}
-
-.sidebar-block .bd {
-  font-size: 16px;
-}
-
-.sphinxsidebar > .sidebar-block:not(:last-child):after {
-    content: '';
-    display:block;
-    border-top: 1px solid #ccc;
-    margin: 24px 22px 0 22px;
-}
-
-.text-logo {
-  font-size: 18px;
-  text-align: center;
-  display: block;
-  padding: 8px;
-  color: #fff;
-  font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
-  margin: 0 0 20px 0;
-  font-weight: bold;
-  background-color: #337ab7;
-  border-bottom: 1px solid #fff;
-}
-
-.text-logo:hover {
-  color: #fff;
-}
-
-/* Left-nav search box
--------------------------------------------------- */
-
-#main-search form .input-group {
-  width: 100%;
-  margin: 0 0 12px 0;
-  padding: 0;
-  border: none;
-}
-
-#main-search form .input-group input {
-  padding: 4px;
-  width: 100%;
-  border-radius: 5px;
-  margin: 0;
-  font-size: 15px;
-}
-
-.search-page-form {
-  width: 350px;
-}
-
-/* Two-pane table list
--------------------------------------------------- */
-
-.table-bordered>thead>tr>th,
-.table-bordered>tbody>tr>th,
-.table-bordered>tfoot>tr>th,
-.table-bordered>thead>tr>td,
-.table-bordered>tbody>tr>td,
-.table-bordered>tfoot>tr>td,
-table.two-column.table-bordered caption+thead tr:first-child th:first-child,
-table.two-column.table-bordered caption+tbody tr:first-child td:first-child,
-table.two-column.table-bordered colgroup+thead tr:first-child th:first-child,
-table.two-column.table-bordered colgroup+tbody tr:first-child td:first-child,
-table.two-column tbody td
-  border: 0 0 1px 0 solid #eee;
-  border-left: none;
-  padding: 8px 4px;
-  font-size: 16px;
-}
-
-table.two-column {
-  width: 100%;
-  border: 0px none !important;
-  box-shadow: none;
-}
-
-/* Disqus comments styles
--------------------------------------------------- */
-
-.comment-container {
-  margin: 24px auto;
-}
-
-/* Next and previous links
--------------------------------------------------- */
-
-.footer-relations {
-  display: relative;
-  border-top: 1px solid #ccc;
-  padding: 12px 45px;
-  margin-top: 30px;
-  font-size: 24px;
-}
-
-.rel-spacer {
-  height: 40px;
-}
-
-/* Footer styling
--------------------------------------------------- */
-
-div.footer {
-  padding: 25px;
-  font-size: 14px;
-  color: #888;
-  text-align: right;
-  max-width: 1200px;
-  width: 100%;
-}
-
-div.footer a {
-  color: #888;
-}
-
-/* -- relbar ---------------------------------------------------------------- */
-
-div.related {
-  width: 100%;
-  font-size: 90%;
-}
-
-div.related h3 {
-  display: none;
-}
-
-div.related ul {
-  margin: 0;
-  padding: 0 0 0 10px;
-  list-style: none;
-}
-
-div.related li {
-  display: inline;
-}
-
-div.related li.right {
-  float: right;
-  margin-right: 5px;
-}
-
-/* -- search page ----------------------------------------------------------- */
-
-ul.search {
-  margin: 10px 0 0 20px;
-  padding: 0;
-}
-
-ul.search li {
-  padding: 5px 0 5px 20px;
-  background: url(file.png) no-repeat 0 7px;
-}
-
-ul.search li a {
-  font-weight: bold;
-}
-
-ul.search li div.context {
-  color: #888;
-  margin: 2px 0 0 30px;
-  text-align: left;
-}
-
-ul.keywordmatches li.goodmatch a {
-  font-weight: bold;
-}
-
-/* -- general index --------------------------------------------------------- */
-
-table {
-  margin-bottom: 20px;
-}
-
-table.indextable {
-  width: 100%;
-}
-
-table.indextable td {
-  text-align: left;
-  vertical-align: top;
-}
-
-table.indextable dl, table.indextable dd {
-  margin-top: 0;
-  margin-bottom: 0;
-}
-
-table.indextable tr.pcap {
-  height: 10px;
-}
-
-table.indextable tr.cap {
-  margin-top: 10px;
-  background-color: #f2f2f2;
-}
-
-img.toggler {
-  margin-right: 3px;
-  margin-top: 3px;
-  cursor: pointer;
-}
-
-div.modindex-jumpbox {
-  border-top: 1px solid #ddd;
-  border-bottom: 1px solid #ddd;
-  margin: 1em 0 1em 0;
-  padding: 0.4em;
-}
-
-div.genindex-jumpbox {
-  border-top: 1px solid #ddd;
-  border-bottom: 1px solid #ddd;
-  margin: 1em 0 1em 0;
-  padding: 0.4em;
-}
-
-/* -- general body styles --------------------------------------------------- */
-
-.body {
-  padding: 0 45px;
-}
-
-div.body p.caption {
-  text-align: inherit;
-}
-
-table.field-list {
-  border: 1px solid #ddd;
-  border-collapse: collapse;
-  border-spacing: 0;
-  width: 100%;
-}
-
-table.field-list td,
-table.field-list th {
-  border: 1px solid #ddd;
-  padding: 8px;
-  vertical-align: top;
-  line-height: 1.4;
-}
-
-.field-list ul {
-  padding-left: 1em;
-}
-
-.first {
-  margin-top: 0 !important;
-}
-
-p.rubric {
-  margin-top: 30px;
-  font-weight: bold;
-}
-
-img.align-left, .figure.align-left, object.align-left {
-  clear: left;
-  float: left;
-  margin-right: 1em;
-}
-
-img.align-right, .figure.align-right, object.align-right {
-  clear: right;
-  float: right;
-  margin-left: 1em;
-}
-
-img.align-center, .figure.align-center, object.align-center {
-  display: block;
-  margin-left: auto;
-  margin-right: auto;
-}
-
-.align-left {
-  text-align: left;
-}
-
-.align-center {
-  text-align: center;
-}
-
-.align-right {
-  text-align: right;
-}
-
-/* -- topics ---------------------------------------------------------------- */
-
-div.topic {
-  border: 1px solid #e8e8e8;
-  padding: 7px 7px 0 7px;
-  margin: 10px 0 10px 0;
-  background-color: #f8f8f8;
-}
-
-p.topic-title {
-  font-size: 1.1em;
-  font-weight: bold;
-  margin-top: 10px;
-}
-
-/* -- contents-------------------------------------------------------------- */
-
-div.topic.contents {
-    display: inline-block;
-    border-radius: 3px;
-    padding: 24px 36px 18px 36px;
-}
-
-div.topic.contents > ul {
-    padding-left: 20px;
-}
-
-/* -- admonitions ----------------------------------------------------------- */
-
-.admonition {
-  margin: 20px 0;
-  padding: 20px;
-  background-color: #fff;
-  border: 1px solid #eee;
-  border-left-width: 6px;
-  border-radius: 3px;
-}
-
-.admonition dt {
-  font-weight: bold;
-}
-
-.admonition dl {
-  margin-bottom: 0;
-}
-
-.admonition-title {
-  margin: 0px 0 5px;
-  padding: 0;
-  font-weight: bold;
-  font-size: 18px;
-  line-height: 1.1;
-  font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
-}
-
-.admonition.danger,
-.admonition.error {
-  border-left-color: #d9534f;
-}
-
-.admonition.danger .admonition-title,
-.admonition.error .admonition-title {
-  color: #d9534f;
-}
-
-.admonition.important,
-.admonition.warning,
-.admonition.attention,
-.admonition.caution {
-  border-left-color: #f0ad4e;
-}
-
-.admonition.important .admonition-title,
-.admonition.warning .admonition-title,
-.admonition.attention .admonition-title,
-.admonition.caution .admonition-title {
-  color: #9B581F;
-}
-
-.admonition.note,
-.admonition.hint {
-  border-left-color: #31708f;
-}
-
-.admonition.note .admonition-title,
-.admonition.hint .admonition-title {
-  color: #31708f;
-}
-
-.admonition.tip {
-  border-left-color: #3c763d;
-}
-
-.admonition.tip .admonition-title {
-  color: #3c763d;
-}
-
-div.body p.centered {
-  text-align: center;
-  margin-top: 25px;
-}
-
-div.seealso {
-  background-color: #ffc;
-  border: 1px solid #ff6;
-}
-
-div.admonition tt.xref, div.admonition a tt {
-  border-bottom: 1px solid #fafafa;
-}
-
-div.admonition p.last {
-  margin-bottom: 0;
-}
-
-/* -- other body styles ----------------------------------------------------- */
-
-ol.arabic {
-  list-style: decimal;
-}
-
-ol.loweralpha {
-  list-style: lower-alpha;
-}
-
-ol.upperalpha {
-  list-style: upper-alpha;
-}
-
-ol.lowerroman {
-  list-style: lower-roman;
-}
-
-ol.upperroman {
-  list-style: upper-roman;
-}
-
-.highlighted {
-  background-color: #fbe54e;
-}
-
-dl.glossary dt {
-  font-weight: bold;
-  font-size: 1.1em;
-}
-
-.field-list ul {
-  margin: 0;
-  padding-left: 1em;
-}
-
-.refcount {
-  color: #060;
-}
-
-.optional {
-  font-size: 1.3em;
-}
-
-.versionmodified {
-  font-style: italic;
-}
-
-.system-message {
-  background-color: #fda;
-  padding: 5px;
-  border: 3px solid red;
-}
-
-.footnote:target  {
-  background-color: #ffa;
-}
-
-.line-block {
-  display: block;
-  margin-top: 1em;
-  margin-bottom: 1em;
-}
-
-.line-block .line-block {
-  margin-top: 0;
-  margin-bottom: 0;
-  margin-left: 1.5em;
-}
-
-.guilabel, .menuselection {
-  font-family: sans-serif;
-}
-
-.accelerator {
-  text-decoration: underline;
-}
-
-.classifier {
-  font-style: oblique;
-}
-
-abbr, acronym {
-  border-bottom: dotted 1px;
-  cursor: help;
-}
-
-dt:target, .highlight {
-  background: #FAF3E8;
-}
-
-/* -- code displays --------------------------------------------------------- */
-
-td.linenos pre {
-  padding: 5px 0px;
-  border: 0;
-  background-color: transparent;
-  color: #aaa;
-}
-
-table.highlighttable {
-  margin-left: 0.5em;
-}
-
-table.highlighttable td {
-  padding: 0 0.5em 0 0.5em;
-}
-
-code.descname {
-  padding: 0px;
-}
-
-code.descclassname {
-  padding: 0px;
-}
-
-tt.descname {
-  background-color: transparent;
-  font-weight: bold;
-  padding-right: 0.08em;
-}
-
-tt.descclassname {
-  background-color: transparent;
-}
-
-tt.descname, tt.descclassname {
-  font-size: 0.95em;
-}
-
-tt.xref, a tt {
-  background-color: transparent;
-  font-weight: bold;
-}
-
-h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
-  background-color: transparent;
-}
-
-.viewcode-link {
-  float: right;
-}
-
-.viewcode-back {
-  float: right;
-  font-family: sans-serif;
-}
-
-div.viewcode-block:target {
-  margin: -1px -10px;
-  padding: 0 10px;
-}
-
-/* -- math display ---------------------------------------------------------- */
-
-img.math {
-  vertical-align: middle;
-}
-
-div.body div.math p {
-  text-align: center;
-}
-
-span.eqno {
-  float: right;
-}
-
-/* -- Theme specific classes - */
-
-.overflow-height-500px {
-  overflow: auto;
-  height: 500px;
-}
-
-.overflow-height-250px {
-  overflow: auto;
-  height: 250px;
-}
-
-/* Toggle mobile view
--------------------------------------------------- */
-
-#mobile-toggle {
-  height: 40px;
-  width: 100%;
-  display: none;
-  padding: 12px;
-  border-bottom: 1px solid #ccc;
-  position: fixed;
-  top: 0;
-  left: 0;
-  background-color: #fff;
-  z-index: 1;
-}
-
-/* Small screen styles
--------------------------------------------------- */
-
-@media screen and (max-width: 768px) {
-
-  body {
-    padding: 0px;
-    margin: 0px;
-    background-color: #fff;
-  }
-
-  h1 {
-    margin-left: 0;
-    width: 100%;
-    padding: 10px;
-    font-size: 40px;
-  }
-
-  #left-column {
-    position: relative;
-    top: 0;
-    left: 0;
-    display: none;
-    width: 100%;
-    float: none;
-    margin: 40px 0 0 0;
-  }
-
-  .footer-relations {
-    padding: 12px 0;
-  }
-
-  #right-column {
-    margin-left: 0;
-    margin-top: 0;
-    padding: 50px 20px 8px 20px;
-    width: 100%;
-    float: none;
-  }
-
-  .document {
-    position: relative;
-    padding: 0;
-    width: 100%
-  }
-
-  .body {
-    padding: 0px;
-  }
-
-  #mobile-toggle {
-    display: block;
-  }
-
-  p {
-    padding: 0;
-  }
-}
-
-/* Account for when the left column is closed then page is expanded.
--------------------------------------------------- */
-
-@media screen and (min-width: 769px) {
-  #left-column {
-    display: block !important;
-  }
-}
-
-/* Syntax highlighting
--------------------------------------------------- */
-
-.hll { background-color: #ffffcc }
-.c { color: #999988; font-style: italic } /* Comment */
-.err { color: #a61717; background-color: #e3d2d2 } /* Error */
-.k { color: #000000; font-weight: bold } /* Keyword */
-.o { color: #000000; font-weight: bold } /* Operator */
-.cm { color: #999988; font-style: italic } /* Comment.Multiline */
-.cp { color: #999999; font-weight: bold; font-style: italic } /* Comment.Preproc */
-.c1 { color: #999988; font-style: italic } /* Comment.Single */
-.cs { color: #999999; font-weight: bold; font-style: italic } /* Comment.Special */
-.gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
-.ge { color: #000000; font-style: italic } /* Generic.Emph */
-.gr { color: #aa0000 } /* Generic.Error */
-.gh { color: #999999 } /* Generic.Heading */
-.gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
-.go { color: #888888 } /* Generic.Output */
-.gp { color: #555555 } /* Generic.Prompt */
-.gs { font-weight: bold } /* Generic.Strong */
-.gu { color: #aaaaaa } /* Generic.Subheading */
-.gt { color: #aa0000 } /* Generic.Traceback */
-.kc { color: #000000; font-weight: bold } /* Keyword.Constant */
-.kd { color: #000000; font-weight: bold } /* Keyword.Declaration */
-.kn { color: #000000; font-weight: bold } /* Keyword.Namespace */
-.kp { color: #000000; font-weight: bold } /* Keyword.Pseudo */
-.kr { color: #000000; font-weight: bold } /* Keyword.Reserved */
-.kt { color: #445588; font-weight: bold } /* Keyword.Type */
-.m { color: #009999 } /* Literal.Number */
-.s { color: #d01040 } /* Literal.String */
-.na { color: #008080 } /* Name.Attribute */
-.nb { color: #0086B3 } /* Name.Builtin */
-.nc { color: #445588; font-weight: bold } /* Name.Class */
-.no { color: #008080 } /* Name.Constant */
-.nd { color: #3c5d5d; font-weight: bold } /* Name.Decorator */
-.ni { color: #800080 } /* Name.Entity */
-.ne { color: #990000; font-weight: bold } /* Name.Exception */
-.nf { color: #990000; font-weight: bold } /* Name.Function */
-.nl { color: #990000; font-weight: bold } /* Name.Label */
-.nn { color: #555555 } /* Name.Namespace */
-.nt { color: #000080 } /* Name.Tag */
-.nv { color: #008080 } /* Name.Variable */
-.ow { color: #000000; font-weight: bold } /* Operator.Word */
-.w { color: #bbbbbb } /* Text.Whitespace */
-.mf { color: #009999 } /* Literal.Number.Float */
-.mh { color: #009999 } /* Literal.Number.Hex */
-.mi { color: #009999 } /* Literal.Number.Integer */
-.mo { color: #009999 } /* Literal.Number.Oct */
-.sb { color: #d01040 } /* Literal.String.Backtick */
-.sc { color: #d01040 } /* Literal.String.Char */
-.sd { color: #d01040 } /* Literal.String.Doc */
-.s2 { color: #d01040 } /* Literal.String.Double */
-.se { color: #d01040 } /* Literal.String.Escape */
-.sh { color: #d01040 } /* Literal.String.Heredoc */
-.si { color: #d01040 } /* Literal.String.Interpol */
-.sx { color: #d01040 } /* Literal.String.Other */
-.sr { color: #009926 } /* Literal.String.Regex */
-.s1 { color: #d01040 } /* Literal.String.Single */
-.ss { color: #990073 } /* Literal.String.Symbol */
-.bp { color: #999999 } /* Name.Builtin.Pseudo */
-.vc { color: #008080 } /* Name.Variable.Class */
-.vg { color: #008080 } /* Name.Variable.Global */
-.vi { color: #008080 } /* Name.Variable.Instance */
-.il { color: #009999 } /* Literal.Number.Integer.Long */
diff --git a/docs/_static/powerdns-logo-500px.png b/docs/_static/powerdns-logo-500px.png
new file mode 100644 (file)
index 0000000..f362b86
Binary files /dev/null and b/docs/_static/powerdns-logo-500px.png differ
diff --git a/docs/_static/powerdns-logo-trans.png b/docs/_static/powerdns-logo-trans.png
new file mode 100644 (file)
index 0000000..d49bdf0
Binary files /dev/null and b/docs/_static/powerdns-logo-trans.png differ
diff --git a/docs/_static/powerdns_logo_white_orange_rgb.png b/docs/_static/powerdns_logo_white_orange_rgb.png
new file mode 100644 (file)
index 0000000..838a414
Binary files /dev/null and b/docs/_static/powerdns_logo_white_orange_rgb.png differ
index 799638ae4d603304286bc7070e6becfedf2c9845..a6adc35b257550849c35ad38d9aebc81019f6a8c 100644 (file)
@@ -623,7 +623,7 @@ this zone.
   otherwise. This is a first line of checks to guard against reloading a
   domain unnecessarily.
 
-.. cpp:function:: void DomainInfo::getUnfreshSecondaryInfos(vector\<DomainInfo\>* domains)
+.. cpp:function:: void DomainInfo::getUnfreshSecondaryInfos(vector<DomainInfo>* domains)
 
   When called, the backend should examine its list of secondary domains and
   add any unfresh ones to the domains vector.
index 94c39bab72bc39c4e6bd728b2a7b17b8c61b90aa..a156d54d438d4cee992f8282d08a69511312bf9b 100644 (file)
@@ -935,7 +935,7 @@ Changelogs for 4.1.x
     :pullreq: 4106
     :tickets: 706
 
-    Implement :json:object:`CryptoKey` in the API (Wolfgang Studier, @MrM0nkey, Tudor Soroceanu, Benjamin Zengin).
+    Implement :json:schema:`Cryptokey` in the API (Wolfgang Studier, @MrM0nkey, Tudor Soroceanu, Benjamin Zengin).
 
   .. change::
     :tags: Internals, Bug Fixes
index 44f8f9214ad3efdbfe309cd8f41e4252393c2cf4..c325f38e1b444f05f70ab527bfc441d5c610f265 100644 (file)
@@ -21,7 +21,6 @@
 import glob
 import sys
 from pathlib import Path
-import guzzle_sphinx_theme
 
 # -- General configuration ------------------------------------------------
 
@@ -35,8 +34,15 @@ sys.path.append(str(Path(".").resolve()))
 # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
 # ones.
 # extensions = []
-# extensions = ['redjack.sphinx.lua', 'sphinxcontrib.httpdomain', 'sphinxjsondomain']
-extensions = ["sphinxcontrib.openapi", "sphinxcontrib.fulltoc", "changelog", "depfile"]
+extensions = [
+    "changelog",
+    "depfile",
+    "sphinx_immaterial",
+    "sphinx_immaterial.apidoc.json.domain",
+    "sphinxcontrib.fulltoc",
+    "sphinxcontrib.httpdomain",
+    "sphinxcontrib.openapi",
+]
 
 # Add any paths that contain templates here, relative to this directory.
 templates_path = ["_templates"]
@@ -69,7 +75,7 @@ author = "PowerDNS.COM BV"
 #
 # This is also used if you do content translation via gettext catalogs.
 # Usually you set "language" from the command line for these cases.
-language = None
+language = "en"
 
 # List of patterns, relative to source directory, that match files and
 # directories to ignore when looking for source files.
@@ -91,6 +97,9 @@ pygments_style = "sphinx"
 # If true, `todo` and `todoList` produce output, else they produce nothing.
 todo_include_todos = False
 
+object_description_options = [
+    ("cpp:class", dict(generate_synopses="first_sentence")),
+]
 
 # -- Changelog Options ----------------------------------------------------
 
@@ -115,36 +124,42 @@ changelog_inner_tag_sort = [
 
 changelog_hide_tags_in_entry = True
 
+# -- Options for the Sphinx-Immaterial JSON Domain ------------------------
+json_schemas = ["http-api/swagger/authoritative-api-swagger.yaml"]
+
 # -- Options for HTML output ----------------------------------------------
 
 # The theme to use for HTML and HTML Help pages.  See the documentation for
 # a list of builtin themes.
 #
-html_theme_path = guzzle_sphinx_theme.html_theme_path()
-html_theme = "guzzle_sphinx_theme"
-
-extensions.append("guzzle_sphinx_theme")
+html_theme = "sphinx_immaterial"
 
 html_theme_options = {
-    # Set the name of the project to appear in the sidebar
-    "project_nav_name": "PowerDNS Authoritative Server",
+    "site_url": "https://doc.powerdns.com/authoritative",
+    "features": [
+        "navigation.tabs",
+        "navigation.tabs.sticky",
+        "navigation.top",
+        "navigation.tracking",
+        "navigation.sections",
+        "navigation.footer",
+        "toc.integrate",
+        "toc.follow",
+        "search.highlight",
+        "search.share",
+        "search.suggest",
+    ],
 }
-html_favicon = "common/favicon.ico"
 
-html_sidebars = {"**": ["logo-text.html", "searchbox.html", "relations.html", "localtoc.html", "sourcelink.html"]}
-
-# Theme options are theme-specific and customize the look and feel of a theme
-# further.  For a list of options available for each theme, see the
-# documentation.
-#
-# html_theme_options = {}
+html_css_files = ["extra.css"]
 
 # Add any paths that contain custom static files (such as style sheets) here,
 # relative to this directory. They are copied after the builtin static files,
 # so a file named "default.css" will overwrite the builtin "default.css".
 html_static_path = ["_static"]
-html_style = "pdns.css"
 
+html_favicon = "_static/favicon.ico"
+html_logo = "_static/powerdns_logo_white_orange_rgb.png"
 
 # -- Options for HTMLHelp output ------------------------------------------
 
@@ -220,7 +235,16 @@ for f in glob.glob("manpages/*.1.rst"):
     srcname = ".".join(f.split(".")[:-1])
     destname = srcname.split("/")[-1][:-2]
     man_pages.append((srcname, destname, descriptions.get(destname, ""), [author], 1))
-man_pages.append(("manpages/ixfrdist.yml.5", "ixfrdist.yml", "The ixfrdist configuration file", [author], 5))
+
+man_pages.append(
+    (
+        "manpages/ixfrdist.yml.5",
+        "ixfrdist.yml",
+        "The ixfrdist configuration file",
+        [author],
+        5,
+    )
+)
 # -- Options for Texinfo output -------------------------------------------
 
 # Grouping the document tree into Texinfo files. List of tuples
index ab269d4d7c06832265913aa2ef796c0360430479..725a9634c28638e3c50c4d44bc624cbfad9c210f 100644 (file)
@@ -14,8 +14,7 @@ Objects
 
 An autoprimary object represents a single autoprimary server.
 
-.. openapi:: swagger/authoritative-api-swagger.yaml
-  :definitions: Autoprimary
+.. json:schema:: Autoprimary
 
 Examples
 --------
index 9437efb043490a1db0d69cee7813adbcedec144b..e1526c5d706d2e9ab572c7403c11d8239126bf28 100644 (file)
@@ -8,5 +8,4 @@ Endpoints
 
 Objects
 -------
-.. openapi:: swagger/authoritative-api-swagger.yaml
-  :definitions: CacheFlushResult
+.. json:schema:: CacheFlushResult
index 2d73ab7a36e0a8f9d4e4b530c57cfdc5fc509abb..3555a36a5d64d05a8cff7df8c9b51219fbdfbfda 100644 (file)
@@ -9,5 +9,4 @@ Endpoints
 
 Objects
 -------
-.. openapi:: swagger/authoritative-api-swagger.yaml
-  :definitions: Cryptokey
+.. json:schema:: Cryptokey
index 5a914d3f9c06e65ddbac05d30579825923d67489..c2bbb4d13cf8a36e626589174449fe8a6a72c9bf 100644 (file)
@@ -338,8 +338,7 @@ Response code ``4xx`` or ``5xx``, depending on the situation.
 
 Error responses have a JSON body of this format:
 
-.. openapi:: swagger/authoritative-api-swagger.yaml
-  :definitions: Error
+.. json:schema:: Error
 
 Data format
 ~~~~~~~~~~~
index 8c3d96ca7318736b0688092ef566798e3dd2a0e0..ce5c507576a575c6fd9c10941cdc4c17c70ff978 100644 (file)
@@ -8,5 +8,4 @@ Endpoints
 
 Objects
 -------
-.. openapi:: swagger/authoritative-api-swagger.yaml
-  :definitions: Metadata
+.. json:schema:: Metadata
index 2ebd06682d7cee6739b8c796ca96f61cb39b9fd5..e2bd3f718025b07f7215621c563c9f67822c845d 100644 (file)
@@ -1,7 +1,7 @@
 Searching
 =========
 
-The API allows searching for data in :json:object:`Zone`\ s, :json:object:`Comment`\ s and :json:object:`RRSet`\ s.
+The API allows searching for data in :json:schema:`Zones <Zone>`, :json:schema:`Comments <Comment>` and :json:schema:`RRSets <RRSet>`.
 
 .. note::
 
@@ -16,5 +16,4 @@ Endpoints
 
 Objects
 -------
-.. openapi:: swagger/authoritative-api-swagger.yaml
-  :definitions: SearchResult
+.. json:schema:: SearchResult
index 00b1de982e890682f6d21f7302f10adbfac6642c..b8061948f5aa48f3477c331cd7cc31a6e11c0288 100644 (file)
@@ -13,8 +13,7 @@ Endpoints
 
 Objects
 -------
-.. openapi:: swagger/authoritative-api-swagger.yaml
-  :definitions: Server
+.. json:schema:: Server
 
 Examples
 --------
index 23975cd514d9eb01d79f48eaed021209c07c14c2..165861c5cb8340e938213982976c901e2777f97d 100644 (file)
@@ -12,16 +12,10 @@ Objects
 
 The Statistics endpoint returns an array of objects that can be StatisticItem, MapStatisticItem or RingStatisticItem :
 
-.. openapi:: swagger/authoritative-api-swagger.yaml
-  :definitions: StatisticItem
-
-.. openapi:: swagger/authoritative-api-swagger.yaml
-  :definitions: MapStatisticItem
-
-.. openapi:: swagger/authoritative-api-swagger.yaml
-  :definitions: RingStatisticItem
+.. json:schema:: StatisticItem
+.. json:schema:: MapStatisticItem
+.. json:schema:: RingStatisticItem
 
 Both MapStatisticItem and RingStatisticItem objects contains an array of SimpleStatisticItem
 
-.. openapi:: swagger/authoritative-api-swagger.yaml
-  :definitions: SimpleStatisticItem
\ No newline at end of file
+.. json:schema:: SimpleStatisticItem
index bd1cd35d1af958d54ef2cb9b5e39fa77cc3154d6..c5d32eb73ea96da4610180a4edd58ffd352e7af2 100644 (file)
@@ -1,4 +1,5 @@
-swagger: '2.0'
+openapi: 3.1.0
+$id: "PDNS Auth webserver"
 info:
   version: "0.0.17"
   title: PowerDNS Authoritative HTTP API
@@ -23,102 +24,98 @@ security:
 #       We need to look at the code and figure out the default HTTP response
 #       codes and adjust docs accordingly.
 paths:
-  '/error':
+  "/error":
     get:
       summary: Will always generate an error
       operationId: error
       responses: &commonErrors
-        '400':
+        "400":
           description: The supplied request was not valid
           schema:
-            $ref: '#/definitions/Error'
-        '404':
+            $ref: Error
+        "404":
           description: Requested item was not found
           schema:
-            $ref: '#/definitions/Error'
-        '422':
+            $ref: Error
+        "422":
           description: The input to the operation was not valid
           schema:
-            $ref: '#/definitions/Error'
-        '500':
+            $ref: Error
+        "500":
           description: Internal server error
           schema:
-            $ref: '#/definitions/Error'
+            $ref: Error
 
-  '/servers':
+  "/servers":
     get:
       summary: List all servers
       operationId: listServers
       tags:
         - servers
       responses:
-        '200':
+        "200":
           description: An array of servers
           schema:
             type: array
             items:
-              $ref: '#/definitions/Server'
+              $ref: Server
         <<: *commonErrors
 
-  '/servers/{server_id}':
+  "/servers/{server_id}":
     get:
       summary: List a server
       operationId: listServer
       tags:
         - servers
       parameters:
-        - name: server_id
+        - &server_id
+          name: server_id
           in: path
           required: true
           description: The id of the server to retrieve
-          type: string
+          schema:
+            type: string
       responses:
-        '200':
+        "200":
           description: An server
           schema:
-            $ref: '#/definitions/Server'
+            $ref: Server
         <<: *commonErrors
 
-  '/servers/{server_id}/cache/flush':
+  "/servers/{server_id}/cache/flush":
     put:
       summary: Flush a cache-entry by name
       operationId: cacheFlushByName
       tags:
         - servers
       parameters:
-        - name: server_id
-          in: path
-          required: true
-          description: The id of the server to retrieve
-          type: string
+        - <<: *server_id
         - name: domain
           in: query
           required: true
           description: The domain name to flush from the cache
-          type: string
+          schema:
+            type: string
       responses:
-        '200':
+        "200":
           description: Flush successful
           schema:
-            $ref: '#/definitions/CacheFlushResult'
+            $ref: CacheFlushResult
         <<: *commonErrors
 
-  '/servers/{server_id}/zones':
+  "/servers/{server_id}/zones":
     get:
       summary: List all Zones in a server
       operationId: listZones
       tags:
         - zones
       parameters:
-        - name: server_id
-          in: path
-          required: true
-          description: The id of the server to retrieve
-          type: string
+        - <<: *server_id
         - name: zone
           in: query
           required: false
-          type: string
+          schema:
+            type: string
           description: |
             When set to the name of a zone, only this zone is returned.
             If no zone with that name exists, the response is an empty array.
@@ -126,16 +123,17 @@ paths:
         - name: dnssec
           in: query
           required: false
-          type: boolean
+          schema:
+            type: boolean
           default: true
-          description: '“true” (default) or “false”, whether to include the “dnssec” and “edited_serial” fields in the Zone objects. Setting this to ”false” will make the query a lot faster.'
+          description: "“true” (default) or “false”, whether to include the “dnssec” and “edited_serial” fields in the Zone objects. Setting this to ”false” will make the query a lot faster."
       responses:
-        '200':
+        "200":
           description: An array of Zones
           schema:
             type: array
             items:
-              $ref: '#/definitions/Zone'
+              $ref: Zone
         <<: *commonErrors
     post:
       summary: Creates a new domain, returns the Zone on creation.
@@ -143,68 +141,67 @@ paths:
       tags:
         - zones
       parameters:
-        - name: server_id
-          in: path
-          required: true
-          description: The id of the server to retrieve
-          type: string
+        - <<: *server_id
         - name: rrsets
           in: query
-          description: '“true” (default) or “false”, whether to include the “rrsets” in the response Zone object.'
-          type: boolean
+          description: "“true” (default) or “false”, whether to include the “rrsets” in the response Zone object."
+          schema:
+            type: boolean
           default: true
         - name: zone_struct
           description: The zone struct to patch with
           required: true
           in: body
           schema:
-            $ref: '#/definitions/Zone'
+            $ref: Zone
       responses:
-        '201':
+        "201":
           description: A zone
           schema:
-              $ref: '#/definitions/Zone'
+            $ref: Zone
         <<: *commonErrors
 
-  '/servers/{server_id}/zones/{zone_id}':
+  "/servers/{server_id}/zones/{zone_id}":
     get:
       summary: zone managed by a server
       operationId: listZone
       tags:
         - zones
       parameters:
-        - name: server_id
-          in: path
-          required: true
-          description: The id of the server to retrieve
-          type: string
-        - name: zone_id
-          type: string
+        - <<: *server_id
+        - &zone_id
+          name: zone_id
           in: path
           required: true
           description: The id of the zone to retrieve
+          schema:
+            type: string
         - name: rrsets
           in: query
-          description: '“true” (default) or “false”, whether to include the “rrsets” in the response Zone object.'
-          type: boolean
+          description: "“true” (default) or “false”, whether to include the “rrsets” in the response Zone object."
+          schema:
+            type: boolean
           default: true
         - name: rrset_name
           in: query
           description: Limit output to RRsets for this name.
-          type: string
+          schema:
+            type: string
         - name: rrset_type
           in: query
           description: Limit output to the RRset of this type. Can only be used together with rrset_name.
-          type: string
+          schema:
+            type: string
         - name: include_disabled
           in: query
-          description: '“true” (default) or “false”, whether to include disabled RRsets in the response.'
-          type: boolean
+          description: "“true” (default) or “false”, whether to include disabled RRsets in the response."
+          schema:
+            type: boolean
       responses:
-        '200':
+        "200":
           description: A Zone
           schema:
-            $ref: '#/definitions/Zone'
+            $ref: Zone
         <<: *commonErrors
     delete:
       summary: Deletes this zone, all attached metadata and rrsets.
@@ -212,588 +209,432 @@ paths:
       tags:
         - zones
       parameters:
-        - name: server_id
-          in: path
-          required: true
-          description: The id of the server to retrieve
-          type: string
-        - name: zone_id
-          type: string
-          in: path
-          required: true
-          description: The id of the zone to retrieve
+        - <<: *server_id
+        - <<: *zone_id
       responses:
-        '204':
-          description: 'Returns 204 No Content on success.'
+        "204":
+          description: "Returns 204 No Content on success."
         <<: *commonErrors
     patch:
-      summary: 'Creates/modifies/deletes RRsets present in the payload and their comments. Returns 204 No Content on success.'
+      summary: "Creates/modifies/deletes RRsets present in the payload and their comments. Returns 204 No Content on success."
       operationId: patchZone
       tags:
         - zones
       parameters:
-        - name: server_id
-          in: path
-          required: true
-          description: The id of the server to retrieve
-          type: string
-        - name: zone_id
-          type: string
-          in: path
-          required: true
+        - <<: *server_id
+        - <<: *zone_id
         - name: zone_struct
           description: The zone struct to patch with
           required: true
           in: body
           schema:
-            $ref: '#/definitions/Zone'
+            $ref: Zone
       responses:
-        '204':
-          description: 'Returns 204 No Content on success.'
+        "204":
+          description: "Returns 204 No Content on success."
         <<: *commonErrors
 
     put:
       summary: Modifies basic zone data.
-      description: 'The only fields in the zone structure which can be modified are: kind, masters, catalog, account, soa_edit, soa_edit_api, api_rectify, dnssec, and nsec3param. All other fields are ignored.'
+      description: "The only fields in the zone structure which can be modified are: kind, masters, catalog, account, soa_edit, soa_edit_api, api_rectify, dnssec, and nsec3param. All other fields are ignored."
       operationId: putZone
       tags:
         - zones
       parameters:
-        - name: server_id
-          in: path
-          required: true
-          description: The id of the server to retrieve
-          type: string
-        - name: zone_id
-          type: string
-          in: path
-          required: true
+        - <<: *server_id
+        - <<: *zone_id
         - name: zone_struct
           description: The zone struct to patch with
           required: true
           in: body
           schema:
-            $ref: '#/definitions/Zone'
+            $ref: Zone
       responses:
-        '204':
-          description: 'Returns 204 No Content on success.'
+        "204":
+          description: "Returns 204 No Content on success."
         <<: *commonErrors
 
-  '/servers/{server_id}/zones/{zone_id}/notify':
+  "/servers/{server_id}/zones/{zone_id}/notify":
     put:
       summary: Send a DNS NOTIFY to all secondaries.
-      description: 'Fails when zone kind is not Master or Slave, or primary and secondary are disabled in the configuration. Only works for Slave if renotify is on. Clients MUST NOT send a body.'
+      description: "Fails when zone kind is not Master or Slave, or primary and secondary are disabled in the configuration. Only works for Slave if renotify is on. Clients MUST NOT send a body."
       operationId: notifyZone
       tags:
         - zones
       parameters:
-        - name: server_id
-          in: path
-          required: true
-          description: The id of the server to retrieve
-          type: string
-        - name: zone_id
-          type: string
-          in: path
-          required: true
-          description: The id of the zone to retrieve
+        - <<: *server_id
+        - <<: *zone_id
       responses:
-        '200':
+        "200":
           description: OK
         <<: *commonErrors
 
-  '/servers/{server_id}/zones/{zone_id}/axfr-retrieve':
+  "/servers/{server_id}/zones/{zone_id}/axfr-retrieve":
     put:
       summary: Retrieve secondary zone from its primary.
-      description: 'Fails when zone kind is not Slave, or secondary is disabled in the configuration. Clients MUST NOT send a body.'
+      description: "Fails when zone kind is not Slave, or secondary is disabled in the configuration. Clients MUST NOT send a body."
       operationId: axfrRetrieveZone
       tags:
         - zones
       parameters:
-        - name: server_id
-          in: path
-          required: true
-          description: The id of the server to retrieve
-          type: string
-        - name: zone_id
-          type: string
-          in: path
-          required: true
-          description: The id of the zone to retrieve
+        - <<: *server_id
+        - <<: *zone_id
       responses:
-        '200':
+        "200":
           description: OK
         <<: *commonErrors
 
-  '/servers/{server_id}/zones/{zone_id}/export':
+  "/servers/{server_id}/zones/{zone_id}/export":
     get:
-      summary: 'Returns the zone in AXFR format.'
+      summary: "Returns the zone in AXFR format."
       operationId: axfrExportZone
       tags:
         - zones
       parameters:
-        - name: server_id
-          in: path
-          required: true
-          description: The id of the server to retrieve
-          type: string
-        - name: zone_id
-          type: string
-          in: path
-          required: true
-          description: The id of the zone to retrieve
+        - <<: *server_id
+        - <<: *zone_id
       responses:
-        '200':
+        "200":
           description: OK
           schema:
             type: string
         <<: *commonErrors
 
-  '/servers/{server_id}/zones/{zone_id}/rectify':
+  "/servers/{server_id}/zones/{zone_id}/rectify":
     put:
-      summary: 'Rectify the zone data.'
-      description: 'This does not take into account the API-RECTIFY metadata. Fails on secondary zones.'
+      summary: "Rectify the zone data."
+      description: "This does not take into account the API-RECTIFY metadata. Fails on secondary zones."
       operationId: rectifyZone
       tags:
         - zones
       parameters:
-        - name: server_id
-          in: path
-          required: true
-          description: The id of the server to retrieve
-          type: string
-        - name: zone_id
-          type: string
-          in: path
-          required: true
-          description: The id of the zone to retrieve
+        - <<: *server_id
+        - <<: *zone_id
       responses:
-        '200':
+        "200":
           description: OK
           schema:
             type: string
         <<: *commonErrors
 
-  '/servers/{server_id}/config':
+  "/servers/{server_id}/config":
     get:
-      summary: 'Returns all ConfigSettings for a single server'
+      summary: "Returns all ConfigSettings for a single server"
       operationId: getConfig
       tags:
         - config
       parameters:
-        - name: server_id
-          in: path
-          required: true
-          description: The id of the server to retrieve
-          type: string
+        - <<: *server_id
       responses:
-        '200':
+        "200":
           description: List of config values
           schema:
             type: array
             items:
-              $ref: '#/definitions/ConfigSetting'
+              $ref: ConfigSetting
         <<: *commonErrors
 
-  '/servers/{server_id}/config/{config_setting_name}':
+  "/servers/{server_id}/config/{config_setting_name}":
     get:
-      summary: 'Returns a specific ConfigSetting for a single server'
-      description: 'NOT IMPLEMENTED'
+      summary: "Returns a specific ConfigSetting for a single server"
+      description: "NOT IMPLEMENTED"
       operationId: getConfigSetting
       tags:
         - config
       parameters:
-        - name: server_id
-          in: path
-          required: true
-          description: The id of the server to retrieve
-          type: string
+        - <<: *server_id
         - name: config_setting_name
           in: path
           required: true
           description: The name of the setting to retrieve
           type: string
       responses:
-        '200':
+        "200":
           description: List of config values
           schema:
-            $ref: '#/definitions/ConfigSetting'
+            $ref: ConfigSetting
         <<: *commonErrors
 
-  '/servers/{server_id}/statistics':
+  "/servers/{server_id}/statistics":
     get:
-      summary: 'Query statistics.'
-      description: 'Query PowerDNS internal statistics.'
+      summary: "Query statistics."
+      description: "Query PowerDNS internal statistics."
       operationId: getStats
       tags:
         - stats
       parameters:
-        - name: server_id
-          in: path
-          required: true
-          description: The id of the server to retrieve
-          type: string
+        - <<: *server_id
         - name: statistic
           in: query
           required: false
-          type: string
+          schema:
+            type: string
           description: |
             When set to the name of a specific statistic, only this value is returned.
             If no statistic with that name exists, the response has a 422 status and an error message.
         - name: includerings
           in: query
           required: false
-          type: boolean
+          schema:
+            type: boolean
           default: true
-          description: '“true” (default) or “false”, whether to include the Ring items, which can contain thousands of log messages or queried domains. Setting this to ”false” may make the response a lot smaller.'
+          description: "“true” (default) or “false”, whether to include the Ring items, which can contain thousands of log messages or queried domains. Setting this to ”false” may make the response a lot smaller."
       responses:
-        '200':
+        "200":
           description: List of Statistic Items
           schema:
             type: array
             items:
-              - $ref: '#/definitions/StatisticItem'
-              - $ref: '#/definitions/MapStatisticItem'
-              - $ref: '#/definitions/RingStatisticItem'
-        '422':
-          description: 'Returned when a non-existing statistic name has been requested. Contains an error message'
+              oneOf:
+                - $ref: StatisticItem
+                - $ref: MapStatisticItem
+                - $ref: RingStatisticItem
+        "422":
+          description: "Returned when a non-existing statistic name has been requested. Contains an error message"
         <<: *commonErrors
 
-  '/servers/{server_id}/search-data':
+  "/servers/{server_id}/search-data":
     get:
-      summary: 'Search the data inside PowerDNS'
-      description: 'Search the data inside PowerDNS for search_term and return at most max_results. This includes zones, records and comments. The * character can be used in search_term as a wildcard character and the ? character can be used as a wildcard for a single character.'
+      summary: "Search the data inside PowerDNS"
+      description: "Search the data inside PowerDNS for search_term and return at most max_results. This includes zones, records and comments. The * character can be used in search_term as a wildcard character and the ? character can be used as a wildcard for a single character."
       operationId: searchData
       tags:
         - search
       parameters:
-        - name: server_id
-          in: path
-          required: true
-          description: The id of the server to retrieve
-          type: string
+        - <<: *server_id
         - name: q
           in: query
           required: true
-          description: 'The string to search for'
-          type: string
+          description: "The string to search for"
+          schema:
+            type: string
         - name: max
           in: query
           required: true
-          description: 'Maximum number of entries to return'
-          type: integer
+          description: "Maximum number of entries to return"
+          schema:
+            type: integer
         - name: object_type
           in: query
           required: false
-          description: 'Type of data to search for, one of “all”, “zone”, “record”, “comment”'
-          type: string
+          description: "Type of data to search for, one of “all”, “zone”, “record”, “comment”"
+          schema:
+            type: string
       responses:
-        '200':
+        "200":
           description: Returns a JSON array with results
           schema:
-            $ref: '#/definitions/SearchResults'
+            $ref: SearchResults
         <<: *commonErrors
 
-  '/servers/{server_id}/zones/{zone_id}/metadata':
+  "/servers/{server_id}/zones/{zone_id}/metadata":
     get:
-      summary: 'Get all the Metadata associated with the zone.'
+      summary: "Get all the Metadata associated with the zone."
       operationId: listMetadata
       tags:
         - zonemetadata
       parameters:
-        - name: server_id
-          in: path
-          required: true
-          description: The id of the server to retrieve
-          type: string
-        - name: zone_id
-          type: string
-          in: path
-          required: true
-          description: The id of the zone to retrieve
+        - <<: *server_id
+        - <<: *zone_id
       responses:
-        '200':
+        "200":
           description: List of Metadata objects
           schema:
             type: array
             items:
-              $ref: '#/definitions/Metadata'
+              $ref: Metadata
         <<: *commonErrors
     post:
-      summary: 'Creates a set of metadata entries'
-      description: 'Creates a set of metadata entries of given kind for the zone. Existing metadata entries for the zone with the same kind are not overwritten.'
+      summary: "Creates a set of metadata entries"
+      description: "Creates a set of metadata entries of given kind for the zone. Existing metadata entries for the zone with the same kind are not overwritten."
       operationId: createMetadata
       tags:
         - zonemetadata
       parameters:
-        - name: server_id
-          in: path
-          required: true
-          description: The id of the server to retrieve
-          type: string
-        - name: zone_id
-          type: string
-          in: path
-          required: true
+        - <<: *server_id
+        - <<: *zone_id
         - name: metadata
           description: Metadata object with list of values to create
           required: true
           in: body
           schema:
-            $ref: '#/definitions/Metadata'
+            $ref: Metadata
       responses:
-        '204':
+        "204":
           description: OK
         <<: *commonErrors
 
-  '/servers/{server_id}/zones/{zone_id}/metadata/{metadata_kind}':
+  "/servers/{server_id}/zones/{zone_id}/metadata/{metadata_kind}":
     get:
-      summary: 'Get the content of a single kind of domain metadata as a Metadata object.'
+      summary: "Get the content of a single kind of domain metadata as a Metadata object."
       operationId: getMetadata
       tags:
         - zonemetadata
       parameters:
-        - name: server_id
-          in: path
-          required: true
-          description: The id of the server to retrieve
-          type: string
-        - name: zone_id
-          type: string
-          in: path
-          required: true
-          description: The id of the zone to retrieve
-        - name: metadata_kind
-          type: string
+        - <<: *server_id
+        - <<: *zone_id
+        - &metadata_kind
+          name: metadata_kind
+          schema:
+            type: string
           in: path
           required: true
           description: The kind of metadata
       responses:
-        '200':
+        "200":
           description: Metadata object with list of values
           schema:
-            $ref: '#/definitions/Metadata'
+            $ref: Metadata
         <<: *commonErrors
     put:
-      summary: 'Replace the content of a single kind of domain metadata.'
-      description: 'Creates a set of metadata entries of given kind for the zone. Existing metadata entries for the zone with the same kind are removed.'
+      summary: "Replace the content of a single kind of domain metadata."
+      description: "Creates a set of metadata entries of given kind for the zone. Existing metadata entries for the zone with the same kind are removed."
       operationId: modifyMetadata
       tags:
         - zonemetadata
       parameters:
-        - name: server_id
-          in: path
-          required: true
-          description: The id of the server to retrieve
-          type: string
-        - name: zone_id
-          type: string
-          in: path
-          required: true
-        - name: metadata_kind
-          description: The kind of metadata
-          required: true
-          type: string
-          in: path
+        - <<: *server_id
+        - <<: *zone_id
+        - <<: *metadata_kind
         - name: metadata
           description: metadata to add/create
           required: true
           in: body
           schema:
-            $ref: '#/definitions/Metadata'
+            $ref: Metadata
       responses:
-        '200':
+        "200":
           description: Metadata object with list of values
           schema:
-            $ref: '#/definitions/Metadata'
+            $ref: Metadata
         <<: *commonErrors
     delete:
-      summary: 'Delete all items of a single kind of domain metadata.'
+      summary: "Delete all items of a single kind of domain metadata."
       operationId: deleteMetadata
       tags:
         - zonemetadata
       parameters:
-        - name: server_id
-          in: path
-          required: true
-          description: The id of the server to retrieve
-          type: string
-        - name: zone_id
-          type: string
-          in: path
-          required: true
-          description: The id of the zone to retrieve
-        - name: metadata_kind
-          type: string
-          in: path
-          required: true
-          description: The kind of metadata
+        - <<: *server_id
+        - <<: *zone_id
+        - <<: *metadata_kind
       responses:
-        '204':
+        "204":
           description: OK
         <<: *commonErrors
 
-  '/servers/{server_id}/zones/{zone_id}/cryptokeys':
+  "/servers/{server_id}/zones/{zone_id}/cryptokeys":
     get:
-      summary: 'Get all CryptoKeys for a zone, except the privatekey'
+      summary: "Get all CryptoKeys for a zone, except the privatekey"
       operationId: listCryptokeys
       tags:
         - zonecryptokey
       parameters:
-        - name: server_id
-          in: path
-          required: true
-          description: The id of the server to retrieve
-          type: string
-        - name: zone_id
-          type: string
-          in: path
-          required: true
-          description: The id of the zone to retrieve
+        - <<: *server_id
+        - <<: *zone_id
       responses:
-        '200':
+        "200":
           description: List of Cryptokey objects
           schema:
             type: array
             items:
-              $ref: '#/definitions/Cryptokey'
+              $ref: Cryptokey
         <<: *commonErrors
     post:
-      summary: 'Creates a Cryptokey'
-      description: 'This method adds a new key to a zone. The key can either be generated or imported by supplying the content parameter. if content, bits and algo are null, a key will be generated based on the default-ksk-algorithm and default-ksk-size settings for a KSK and the default-zsk-algorithm and default-zsk-size options for a ZSK.'
+      summary: "Creates a Cryptokey"
+      description: "This method adds a new key to a zone. The key can either be generated or imported by supplying the content parameter. if content, bits and algo are null, a key will be generated based on the default-ksk-algorithm and default-ksk-size settings for a KSK and the default-zsk-algorithm and default-zsk-size options for a ZSK."
       operationId: createCryptokey
       tags:
         - zonecryptokey
       parameters:
-        - name: server_id
-          in: path
-          required: true
-          description: The id of the server to retrieve
-          type: string
-        - name: zone_id
-          type: string
-          in: path
-          required: true
+        - <<: *server_id
+        - <<: *zone_id
         - name: cryptokey
           description: Add a Cryptokey
           required: true
           in: body
           schema:
-            $ref: '#/definitions/Cryptokey'
+            $ref: Cryptokey
       responses:
-        '201':
+        "201":
           description: Created
           schema:
-            $ref: '#/definitions/Cryptokey'
+            $ref: Cryptokey
         <<: *commonErrors
 
-  '/servers/{server_id}/zones/{zone_id}/cryptokeys/{cryptokey_id}':
+  "/servers/{server_id}/zones/{zone_id}/cryptokeys/{cryptokey_id}":
     get:
-      summary: 'Returns all data about the CryptoKey, including the privatekey.'
+      summary: "Returns all data about the CryptoKey, including the privatekey."
       operationId: getCryptokey
       tags:
         - zonecryptokey
       parameters:
-        - name: server_id
+        - <<: *server_id
+        - <<: *zone_id
+        - &cryptokey_id
+          name: cryptokey_id
           in: path
           required: true
-          description: The id of the server to retrieve
-          type: string
-        - name: zone_id
-          type: string
-          in: path
-          required: true
-          description: The id of the zone to retrieve
-        - name: cryptokey_id
-          type: string
-          in: path
-          required: true
-          description: 'The id value of the CryptoKey'
+          description: "The id value of the CryptoKey"
+          schema:
+            type: string
       responses:
-        '200':
+        "200":
           description: Cryptokey
           schema:
-            $ref: '#/definitions/Cryptokey'
+            $ref: Cryptokey
         <<: *commonErrors
     put:
-      summary: 'This method (de)activates a key from zone_name specified by cryptokey_id'
+      summary: "This method (de)activates a key from zone_name specified by cryptokey_id"
       operationId: modifyCryptokey
       tags:
         - zonecryptokey
       parameters:
-        - name: server_id
-          in: path
-          required: true
-          description: The id of the server to retrieve
-          type: string
-        - name: zone_id
-          type: string
-          in: path
-          required: true
-        - name: cryptokey_id
-          description: Cryptokey to manipulate
-          required: true
-          in: path
-          type: string
+        - <<: *server_id
+        - <<: *zone_id
+        - <<: *cryptokey_id
         - name: cryptokey
           description: the Cryptokey
           required: true
           in: body
           schema:
-            $ref: '#/definitions/Cryptokey'
+            $ref: Cryptokey
       responses:
-        '204':
+        "204":
           description: OK
         <<: *commonErrors
     delete:
-      summary: 'This method deletes a key specified by cryptokey_id.'
+      summary: "This method deletes a key specified by cryptokey_id."
       operationId: deleteCryptokey
       tags:
         - zonecryptokey
       parameters:
-        - name: server_id
-          in: path
-          required: true
-          description: The id of the server to retrieve
-          type: string
-        - name: zone_id
-          type: string
-          in: path
-          required: true
-          description: The id of the zone to retrieve
-        - name: cryptokey_id
-          type: string
-          in: path
-          required: true
-          description: 'The id value of the Cryptokey'
+        - <<: *server_id
+        - <<: *zone_id
+        - <<: *cryptokey_id
       responses:
-        '204':
+        "204":
           description: OK
         <<: *commonErrors
 
-  '/servers/{server_id}/tsigkeys':
+  "/servers/{server_id}/tsigkeys":
     parameters:
-      - name: server_id
-        in: path
-        required: true
-        description: 'The id of the server'
-        type: string
+      - <<: *server_id
     get:
-      summary: 'Get all TSIGKeys on the server, except the actual key'
+      summary: "Get all TSIGKeys on the server, except the actual key"
       operationId: listTSIGKeys
       tags:
         - tsigkey
       responses:
-        '200':
+        "200":
           description: List of TSIGKey objects
           schema:
             type: array
             items:
-              $ref: '#/definitions/TSIGKey'
+              $ref: TSIGKey
         <<: *commonErrors
     post:
-      summary: 'Add a TSIG key'
-      description: 'This methods add a new TSIGKey. The actual key can be generated by the server or be provided by the client'
+      summary: "Add a TSIG key"
+      description: "This methods add a new TSIGKey. The actual key can be generated by the server or be provided by the client"
       operationId: createTSIGKey
       tags:
         - tsigkey
@@ -803,40 +644,37 @@ paths:
           required: true
           in: body
           schema:
-            $ref: '#/definitions/TSIGKey'
+            $ref: TSIGKey
       responses:
-        '201':
+        "201":
           description: Created
           schema:
-            $ref: '#/definitions/TSIGKey'
-        '409':
+            $ref: TSIGKey
+        "409":
           description: An item with this name already exists
           schema:
-            $ref: '#/definitions/Error'
+            $ref: Error
         <<: *commonErrors
 
-  '/servers/{server_id}/tsigkeys/{tsigkey_id}':
+  "/servers/{server_id}/tsigkeys/{tsigkey_id}":
     parameters:
-      - name: server_id
-        in: path
-        required: true
-        description: 'The id of the server to retrieve the key from'
-        type: string
+      - <<: *server_id
       - name: tsigkey_id
         in: path
         required: true
         description: 'The id of the TSIGkey. Should match the "id" field in the TSIGKey object'
-        type: string
+        schema:
+          type: string
     get:
-      summary: 'Get a specific TSIGKeys on the server, including the actual key'
+      summary: "Get a specific TSIGKeys on the server, including the actual key"
       operationId: getTSIGKey
       tags:
         - tsigkey
       responses:
-        '200':
+        "200":
           description: OK.
           schema:
-            $ref: '#/definitions/TSIGKey'
+            $ref: TSIGKey
         <<: *commonErrors
     put:
       description: |
@@ -853,50 +691,46 @@ paths:
         - name: tsigkey
           description: A (possibly stripped down) TSIGKey object with the new values
           schema:
-            $ref: '#/definitions/TSIGKey'
+            $ref: TSIGKey
           in: body
           required: true
       responses:
-        '200':
+        "200":
           description: OK. TSIGKey is changed.
           schema:
-            $ref: '#/definitions/TSIGKey'
-        '409':
+            $ref: TSIGKey
+        "409":
           description: An item with this name already exists
           schema:
-            $ref: '#/definitions/Error'
+            $ref: Error
         <<: *commonErrors
     delete:
-      summary: 'Delete the TSIGKey with tsigkey_id'
+      summary: "Delete the TSIGKey with tsigkey_id"
       operationId: deleteTSIGKey
       tags:
         - tsigkey
       responses:
-        '204':
-          description: 'OK, key was deleted'
+        "204":
+          description: "OK, key was deleted"
         <<: *commonErrors
 
-  '/servers/{server_id}/autoprimaries':
+  "/servers/{server_id}/autoprimaries":
     parameters:
-      - name: server_id
-        in: path
-        required: true
-        description: 'The id of the server to manage the list of autoprimaries on'
-        type: string
+      - <<: *server_id
     get:
-      summary: 'Get a list of autoprimaries'
+      summary: "Get a list of autoprimaries"
       operationId: getAutoprimaries
       tags:
         - autoprimary
       responses:
-        '200':
+        "200":
           description: OK.
           schema:
-            $ref: '#/definitions/Autoprimary'
+            $ref: Autoprimary
         <<: *commonErrors
     post:
-      summary: 'Add an autoprimary'
-      description: 'This methods add a new autoprimary server.'
+      summary: "Add an autoprimary"
+      description: "This methods add a new autoprimary server."
       operationId: createAutoprimary
       tags:
         - autoprimary
@@ -906,80 +740,71 @@ paths:
           required: true
           in: body
           schema:
-            $ref: '#/definitions/Autoprimary'
+            $ref: Autoprimary
       responses:
-        '201':
+        "201":
           description: Created
         <<: *commonErrors
 
-  '/servers/{server_id}/autoprimaries/{ip}/{nameserver}':
+  "/servers/{server_id}/autoprimaries/{ip}/{nameserver}":
     parameters:
-      - name: server_id
-        in: path
-        required: true
-        description: 'The id of the server to delete the autoprimary from'
-        type: string
+      - <<: *server_id
       - name: ip
         in: path
         required: true
-        description: 'IP address of autoprimary'
-        type: string
+        description: "IP address of autoprimary"
+        schema:
+          type: string
       - name: nameserver
         in: path
         required: true
-        description: 'DNS name of the autoprimary'
-        type: string
+        description: "DNS name of the autoprimary"
+        schema:
+          type: string
     delete:
-      summary: 'Delete the autoprimary entry'
+      summary: "Delete the autoprimary entry"
       operationId: deleteAutoprimary
       tags:
         - autoprimary
       responses:
-        '204':
-          description: 'OK, key was deleted'
+        "204":
+          description: "OK, key was deleted"
         <<: *commonErrors
 
-  '/servers/{server_id}/views':
+  "/servers/{server_id}/views":
+    parameters:
+      - <<: *server_id
     get:
       summary: List all views in a server
       operationId: listViews
       tags:
         - views
-      parameters:
-        - name: server_id
-          in: path
-          required: true
-          description: The id of the server to retrieve
-          type: string
       responses:
-        '200':
+        "200":
           description: An array of view names
           schema:
-            $ref: '#/definitions/Views'
+            $ref: Views
         <<: *commonErrors
 
-  '/servers/{server_id}/views/{view}':
+  "/servers/{server_id}/views/{view}":
+    parameters:
+      - <<: *server_id
+      - name: view
+        schema:
+          type: string
+        in: path
+        required: true
+        description: The name of the view to retrieve
     get:
       summary: List the contents of a given view
       operationId: listView
       tags:
         - views
-      parameters:
-        - name: server_id
-          in: path
-          required: true
-          description: The id of the server to retrieve
-          type: string
-        - name: view
-          type: string
-          in: path
-          required: true
-          description: The name of the view to retrieve
       responses:
-        '200':
+        "200":
           description: An array of zone names
           schema:
-            $ref: '#/definitions/View'
+            $ref: View
         <<: *commonErrors
     post:
       summary: Adds a zone to a given view, creating it if needed
@@ -987,13 +812,10 @@ paths:
       tags:
         - views
       parameters:
-        - name: server_id
-          in: path
-          required: true
-          description: The id of the server to retrieve
-          type: string
+        - <<: *server_id
         - name: view
-          type: string
+          schema:
+            type: string
           in: path
           required: true
           description: The name of the view to update
@@ -1004,24 +826,21 @@ paths:
           schema:
             type: string
       responses:
-        '204':
-          description: 'Returns 204 No Content on success.'
+        "204":
+          description: "Returns 204 No Content on success."
         <<: *commonErrors
 
-  '/servers/{server_id}/views/{view}/{id}':
+  "/servers/{server_id}/views/{view}/{id}":
     delete:
       summary: Removes the given zone from the given view
       operationId: deleteFromView
       tags:
         - views
       parameters:
-        - name: server_id
-          in: path
-          required: true
-          description: The id of the server to retrieve
-          type: string
+        - <<: *server_id
         - name: view
-          type: string
+          schema:
+            type: string
           in: path
           required: true
           description: The name of the view to update
@@ -1029,58 +848,53 @@ paths:
           description: The zone to remove from the view
           required: true
           in: path
-          type: string
+          schema:
+            type: string
       responses:
-        '204':
-          description: 'Returns 204 No Content on success.'
+        "204":
+          description: "Returns 204 No Content on success."
         <<: *commonErrors
 
-  '/servers/{server_id}/networks':
+  "/servers/{server_id}/networks":
     get:
       summary: List all registered networks and views in a server
       operationId: listNetworks
       tags:
         - networks
       parameters:
-        - name: server_id
-          in: path
-          required: true
-          description: The id of the server to retrieve
-          type: string
+        - <<: *server_id
       responses:
-        '200':
+        "200":
           description: An array of networks
           schema:
-            $ref: '#/definitions/Networks'
+            $ref: Networks
         <<: *commonErrors
 
-  '/servers/{server_id}/networks/{ip}/{prefixlen}':
+  "/servers/{server_id}/networks/{ip}/{prefixlen}":
     get:
       summary: Return the view associated to the given network
       operationId: getNetwork
       tags:
         - networks
       parameters:
-        - name: server_id
-          in: path
-          required: true
-          description: The id of the server to retrieve
-          type: string
+        - <<: *server_id
         - name: ip
-          type: string
+          schema:
+            type: string
           in: path
           required: true
           description: The base address of the network
         - name: prefixlen
-          type: string
+          schema:
+            type: string
           in: path
           required: true
           description: The length of the network prefix
       responses:
-        '200':
+        "200":
           description: A network
           schema:
-            $ref: '#/definitions/Network'
+            $ref: Network
         <<: *commonErrors
     put:
       summary: Sets the view associated to the given network
@@ -1088,18 +902,16 @@ paths:
       tags:
         - networks
       parameters:
-        - name: server_id
-          in: path
-          required: true
-          description: The id of the server to retrieve
-          type: string
+        - <<: *server_id
         - name: ip
-          type: string
+          schema:
+            type: string
           in: path
           required: true
           description: The base address of the network
         - name: prefixlen
-          type: string
+          schema:
+            type: string
           in: path
           required: true
           description: The length of the network prefix
@@ -1110,142 +922,150 @@ paths:
           schema:
             type: string
       responses:
-        '204':
-          description: 'Returns 204 No Content on success.'
+        "204":
+          description: "Returns 204 No Content on success."
         <<: *commonErrors
 
 definitions:
   Server:
+    $id: Server
+    type: object
     title: Server
     properties:
       type:
         type: string
-        description: 'Set to “Server”'
+        description: "Set to “Server”"
       id:
         type: string
-        description: 'The id of the server, “localhost”'
+        description: "The id of the server, “localhost”"
       daemon_type:
         type: string
-        description: '“recursor” for the PowerDNS Recursor and “authoritative” for the Authoritative Server'
+        description: "“recursor” for the PowerDNS Recursor and “authoritative” for the Authoritative Server"
       version:
         type: string
-        description: 'The version of the server software'
+        description: "The version of the server software"
       url:
         type: string
-        description: 'The API endpoint for this server'
+        description: "The API endpoint for this server"
       config_url:
         type: string
-        description: 'The API endpoint for this server’s configuration'
+        description: "The API endpoint for this server’s configuration"
       zones_url:
         type: string
-        description: 'The API endpoint for this server’s zones'
+        description: "The API endpoint for this server’s zones"
 
   Servers:
+    $id: Servers
     type: array
     items:
-      $ref: '#/definitions/Server'
+      $ref: Server
 
   Zone:
+    $id: Zone
     title: Zone
     description: This represents an authoritative DNS Zone.
+    type: object
     properties:
       id:
         type: string
-        description: 'Opaque zone id (string), assigned by the server, should not be interpreted by the application. Guaranteed to be safe for embedding in URLs.'
+        description: "Opaque zone id (string), assigned by the server, should not be interpreted by the application. Guaranteed to be safe for embedding in URLs."
       name:
         type: string
-        description: 'Name of the zone (e.g. “example.com.”) MUST have a trailing dot'
+        description: "Name of the zone (e.g. “example.com.”) MUST have a trailing dot"
       type:
         type: string
-        description: 'Set to “Zone”'
+        description: "Set to “Zone”"
       url:
         type: string
-        description: 'API endpoint for this zone'
+        description: "API endpoint for this zone"
       kind:
         type: string
         enum:
-          - 'Native'
-          - 'Master'
-          - 'Slave'
-          - 'Producer'
-          - 'Consumer'
-        description: 'Zone kind, one of “Native”, “Master”, “Slave”, “Producer”, “Consumer”'
+          - "Native"
+          - "Master"
+          - "Slave"
+          - "Producer"
+          - "Consumer"
+        description: "Zone kind, one of “Native”, “Master”, “Slave”, “Producer”, “Consumer”"
       rrsets:
         type: array
         items:
-          $ref: '#/definitions/RRSet'
-        description: 'RRSets in this zone (for zones/{zone_id} endpoint only; omitted during GET on the .../zones list endpoint)'
+          $ref: RRSet
+        description: "RRSets in this zone (for zones/{zone_id} endpoint only; omitted during GET on the .../zones list endpoint)"
       serial:
         type: integer
-        description: 'The SOA serial number'
+        description: "The SOA serial number"
       notified_serial:
         type: integer
-        description: 'The SOA serial notifications have been sent out for'
+        description: "The SOA serial notifications have been sent out for"
       edited_serial:
         type: integer
-        description: 'The SOA serial as seen in query responses. Calculated using the SOA-EDIT metadata, default-soa-edit and default-soa-edit-signed settings'
+        description: "The SOA serial as seen in query responses. Calculated using the SOA-EDIT metadata, default-soa-edit and default-soa-edit-signed settings"
       masters:
         type: array
         items:
           type: string
-        description: ' List of IP addresses configured as a primary for this zone (“Slave” type zones only)'
+        description: "List of IP addresses configured as a primary for this zone (“Slave” type zones only)"
       dnssec:
         type: boolean
-        description: 'Whether or not this zone is DNSSEC signed (inferred from presigned being true XOR presence of at least one cryptokey with active being true)'
+        description: "Whether or not this zone is DNSSEC signed (inferred from presigned being true XOR presence of at least one cryptokey with active being true)"
       nsec3param:
         type: string
-        description: 'The NSEC3PARAM record'
+        description: "The NSEC3PARAM record"
       nsec3narrow:
         type: boolean
-        description: 'Whether or not the zone uses NSEC3 narrow'
+        description: "Whether or not the zone uses NSEC3 narrow"
       presigned:
         type: boolean
-        description: 'Whether or not the zone is pre-signed'
+        description: "Whether or not the zone is pre-signed"
       soa_edit:
         type: string
-        description: 'The SOA-EDIT metadata item'
+        description: "The SOA-EDIT metadata item"
       soa_edit_api:
         type: string
-        description: 'The SOA-EDIT-API metadata item'
+        description: "The SOA-EDIT-API metadata item"
       api_rectify:
         type: boolean
-        description: 'Whether or not the zone will be rectified on data changes via the API'
+        description: "Whether or not the zone will be rectified on data changes via the API"
       zone:
         type: string
-        description: 'MAY contain a BIND-style zone file when creating a zone'
+        description: "MAY contain a BIND-style zone file when creating a zone"
       catalog:
         type: string
-        description: 'The catalog this zone is a member of'
+        description: "The catalog this zone is a member of"
       account:
         type: string
-        description: 'MAY be set. Its value is defined by local policy'
+        description: "MAY be set. Its value is defined by local policy"
       nameservers:
         type: array
         items:
           type: string
-        description: 'MAY be sent in client bodies during creation, and MUST NOT be sent by the server. Simple list of strings of nameserver names, including the trailing dot. Not required for secondary zones.'
+        description: "MAY be sent in client bodies during creation, and MUST NOT be sent by the server. Simple list of strings of nameserver names, including the trailing dot. Not required for secondary zones."
       master_tsig_key_ids:
         type: array
         items:
           type: string
-        description: 'The id of the TSIG keys used for primary operation in this zone'
+        description: "The id of the TSIG keys used for primary operation in this zone"
         externalDocs:
-          url: 'https://doc.powerdns.com/authoritative/tsig.html#provisioning-outbound-axfr-access'
+          url: "https://doc.powerdns.com/authoritative/tsig.html#provisioning-outbound-axfr-access"
       slave_tsig_key_ids:
         type: array
         items:
           type: string
-        description: 'The id of the TSIG keys used for secondary operation in this zone'
+        description: "The id of the TSIG keys used for secondary operation in this zone"
         externalDocs:
-          url: 'https://doc.powerdns.com/authoritative/tsig.html#provisioning-signed-notification-and-axfr-requests'
+          url: "https://doc.powerdns.com/authoritative/tsig.html#provisioning-signed-notification-and-axfr-requests"
 
   Zones:
+    $id: Zones
     type: array
     items:
-      $ref: '#/definitions/Zone'
+      $ref: Zone
 
   RRSet:
+    $id: RRSet
     title: RRSet
+    type: object
     description: This represents a Resource Record Set (all records with the same name and type).
     required:
       - name
@@ -1256,165 +1076,184 @@ definitions:
     properties:
       name:
         type: string
-        description: 'Name for record set (e.g. “www.powerdns.com.”)'
+        description: "Name for record set (e.g. “www.powerdns.com.”)"
       type:
         type: string
-        description: 'Type of this record (e.g. “A”, “PTR”, “MX”)'
+        description: "Type of this record (e.g. “A”, “PTR”, “MX”)"
       ttl:
         type: integer
-        description: 'DNS TTL of the records, in seconds. MUST NOT be included when changetype is set to “DELETE”.'
+        description: "DNS TTL of the records, in seconds. MUST NOT be included when changetype is set to “DELETE”."
       changetype:
         type: string
-        description: 'MUST be added when updating the RRSet. Must be one of DELETE, EXTEND, PRUNE or REPLACE. EXTEND and PRUNE are available since versions 4.9.12 and 5.0.2. With DELETE, all existing RRs matching name and type will be deleted, including all comments. With EXTEND, only a single record shall be present, and it will be added to the RRSet if not already present. With PRUNE, only a single record shall be present, and it will be deleted from the RRSet if present. With REPLACE, when records is present, all existing RRs matching name and type will be deleted, and then new records given in records will be created. If no records are left, any existing comments will be deleted as well. When comments is present, all existing comments for the RRs matching name and type will be deleted, and then new comments given in comments will be created.'
+        description: "MUST be added when updating the RRSet. Must be one of DELETE, EXTEND, PRUNE or REPLACE. EXTEND and PRUNE are available since versions 4.9.12 and 5.0.2. With DELETE, all existing RRs matching name and type will be deleted, including all comments. With EXTEND, only a single record shall be present, and it will be added to the RRSet if not already present. With PRUNE, only a single record shall be present, and it will be deleted from the RRSet if present. With REPLACE, when records is present, all existing RRs matching name and type will be deleted, and then new records given in records will be created. If no records are left, any existing comments will be deleted as well. When comments is present, all existing comments for the RRs matching name and type will be deleted, and then new comments given in comments will be created."
       records:
         type: array
-        description: 'All records in this RRSet. When updating Records, this is the list of new records (replacing the old ones). Must be empty when changetype is set to DELETE, and must contain only one element when changetype is set to EXTEND or PRUNE. An empty list results in deletion of all records (and comments).'
+        description: "All records in this RRSet. When updating Records, this is the list of new records (replacing the old ones). Must be empty when changetype is set to DELETE, and must contain only one element when changetype is set to EXTEND or PRUNE. An empty list results in deletion of all records (and comments)."
         items:
-          $ref: '#/definitions/Record'
+          $ref: Record
       comments:
         type: array
-        description: 'List of Comment. Must be empty when changetype is set to DELETE, EXTEND or PRUNE. An empty list results in deletion of all comments. modified_at is optional and defaults to the current server time.'
+        description: "List of Comment. Must be empty when changetype is set to DELETE, EXTEND or PRUNE. An empty list results in deletion of all comments. modified_at is optional and defaults to the current server time."
         items:
-          $ref: '#/definitions/Comment'
+          $ref: Comment
 
   Record:
+    $id: Record
     title: Record
+    type: object
     description: The RREntry object represents a single record.
     required:
       - content
     properties:
       content:
         type: string
-        description: 'The content of this record'
+        description: "The content of this record"
       disabled:
         type: boolean
-        description: 'Whether or not this record is disabled. When unset, the record is not disabled'
+        description: "Whether or not this record is disabled. When unset, the record is not disabled"
       modified_at:
         type: integer
-        description: 'Timestamp of the last change to the record'
+        description: "Timestamp of the last change to the record"
 
   Comment:
+    $id: Comment
     title: Comment
+    type: object
     description: A comment about an RRSet.
     properties:
       content:
         type: string
-        description: 'The actual comment'
+        description: "The actual comment"
       account:
         type: string
-        description: 'Name of an account that added the comment'
+        description: "Name of an account that added the comment"
       modified_at:
         type: integer
-        description: 'Timestamp of the last change to the comment'
+        description: "Timestamp of the last change to the comment"
 
   TSIGKey:
+    $id: TSIGKey
     title: TSIGKey
+    type: object
     description: A TSIG key that can be used to authenticate NOTIFY, AXFR, and DNSUPDATE queries.
     properties:
       name:
         type: string
-        description: 'The name of the key'
+        description: "The name of the key"
       id:
         type: string
-        description: 'The ID for this key, used in the TSIGkey URL endpoint.'
+        description: "The ID for this key, used in the TSIGkey URL endpoint."
         readOnly: true
       algorithm:
         type: string
-        description: 'The algorithm of the TSIG key'
+        description: "The algorithm of the TSIG key"
       key:
         type: string
-        description: 'The Base64 encoded secret key, empty when listing keys. MAY be empty when POSTing to have the server generate the key material'
+        description: "The Base64 encoded secret key, empty when listing keys. MAY be empty when POSTing to have the server generate the key material"
       type:
         type: string
         description: 'Set to "TSIGKey"'
         readOnly: true
 
   Autoprimary:
-     title: Autoprimary server
-     description: An autoprimary server that can provision new domains.
-     properties:
-       ip:
-         type: string
-         description: "IP address of the autoprimary server"
-       nameserver:
-         type: string
-         description: "DNS name of the autoprimary server"
-       account:
-         type: string
-         description: "Account name for the autoprimary server"
+    $id: Autoprimary
+    title: Autoprimary server
+    type: object
+    description: An autoprimary server that can provision new domains.
+    properties:
+      ip:
+        type: string
+        description: "IP address of the autoprimary server"
+      nameserver:
+        type: string
+        description: "DNS name of the autoprimary server"
+      account:
+        type: string
+        description: "Account name for the autoprimary server"
 
   ConfigSetting:
+    $id: ConfigSetting
     title: ConfigSetting
+    type: object
     properties:
       name:
         type: string
         description: 'set to "ConfigSetting"'
       type:
         type: string
-        description: 'The name of this setting (e.g. ‘webserver-port’)'
+        description: "The name of this setting (e.g. ‘webserver-port’)"
       value:
         type: string
-        description: 'The value of setting name'
+        description: "The value of setting name"
 
   SimpleStatisticItem:
+    $id: SimpleStatisticItem
     title: SimpleStatisticItem
     type: object
     properties:
       name:
-          type: string
-          description: 'Item name'
+        type: string
+        description: "Item name"
       value:
-          type: string
-          description: 'Item value'
+        type: string
+        description: "Item value"
 
   StatisticItem:
+    $id: StatisticItem
     title: StatisticItem
+    type: object
     properties:
       name:
         type: string
-        description: 'Item name'
+        description: "Item name"
       type:
         type: string
         description: 'set to "StatisticItem"'
       value:
         type: string
-        description: 'Item value'
+        description: "Item value"
 
   MapStatisticItem:
+    $id: MapStatisticItem
     title: MapStatisticItem
+    type: object
     properties:
       name:
         type: string
-        description: 'Item name'
+        description: "Item name"
       type:
         type: string
         description: 'Set to "MapStatisticItem"'
       value:
         type: array
-        description: 'Named values'
+        description: "Named values"
         items:
-          $ref: '#/definitions/SimpleStatisticItem'
+          $ref: SimpleStatisticItem
 
   RingStatisticItem:
+    $id: RingStatisticItem
     title: RingStatisticItem
+    type: object
     properties:
       name:
         type: string
-        description: 'Item name'
+        description: "Item name"
       type:
         type: string
         description: 'Set to "RingStatisticItem"'
       size:
         type: integer
-        description: 'Ring size'
+        description: "Ring size"
       value:
         type: array
-        description: 'Named values'
+        description: "Named values"
         items:
-          $ref: '#/definitions/SimpleStatisticItem'
+          $ref: SimpleStatisticItem
 
   SearchResultZone:
+    $id: SearchResultZone
     title: SearchResultZone
+    type: object
     properties:
       name:
         type: string
@@ -1425,7 +1264,9 @@ definitions:
         type: string
 
   SearchResultRecord:
+    $id: SearchResultRecord
     title: SearchResultRecord
+    type: object
     properties:
       content:
         type: string
@@ -1446,7 +1287,9 @@ definitions:
         type: integer
 
   SearchResultComment:
+    $id: SearchResultComment
     title: SearchResultComment
+    type: object
     properties:
       content:
         type: string
@@ -1460,154 +1303,170 @@ definitions:
       zone:
         type: string
 
-# FIXME: This is problematic at the moment, because swagger doesn't support this type of mixed response
-#  SearchResult:
-#    anyOf:
-#      - $ref: '#/definitions/SearchResultZone'
-#      - $ref: '#/definitions/SearchResultRecord'
-#      - $ref: '#/definitions/SearchResultComment'
-
-# Since we can't do 'anyOf' at the moment, we create a 'superset object'
   SearchResult:
-    title: SearchResult
-    properties:
-      content:
-        type: string
-      disabled:
-        type: boolean
-      name:
-        type: string
-      object_type:
-        type: string
-        description: 'set to one of "record, zone, comment"'
-      zone_id:
-        type: string
-      zone:
-        type: string
-      type:
-        type: string
-      ttl:
-        type: integer
+    $id: SearchResult
+    anyOf:
+      - $ref: SearchResultZone
+      - $ref: SearchResultRecord
+      - $ref: SearchResultComment
+
+  # Since we can't do 'anyOf' at the moment, we create a 'superset object'
+  # SearchResult:
+  #   title: SearchResult
+  #   properties:
+  #     content:
+  #       type: string
+  #     disabled:
+  #       type: boolean
+  #     name:
+  #       type: string
+  #     object_type:
+  #       type: string
+  #       description: 'set to one of "record, zone, comment"'
+  #     zone_id:
+  #       type: string
+  #     zone:
+  #       type: string
+  #     type:
+  #       type: string
+  #     ttl:
+  #       type: integer
 
   SearchResults:
+    $id: SearchResults
     type: array
     items:
-      $ref: '#/definitions/SearchResult'
+      $ref: SearchResult
 
   Metadata:
+    $id: Metadata
     title: Metadata
+    type: object
     description: Represents zone metadata
     properties:
       kind:
         type: string
-        description: 'Name of the metadata'
+        description: "Name of the metadata"
       metadata:
         type: array
         items:
           type: string
-        description: 'Array with all values for this metadata kind.'
+        description: "Array with all values for this metadata kind."
 
   Cryptokey:
+    $id: Cryptokey
     title: Cryptokey
-    description: 'Describes a DNSSEC cryptographic key'
+    type: object
+    description: "Describes a DNSSEC cryptographic key"
     properties:
       type:
         type: string
         description: 'set to "Cryptokey"'
       id:
         type: integer
-        description: 'The internal identifier, read only'
+        description: "The internal identifier, read only"
       keytype:
         type: string
         enum: [ksk, zsk, csk]
       active:
         type: boolean
-        description: 'Whether or not the key is in active use'
+        description: "Whether or not the key is in active use"
       published:
         type: boolean
-        description: 'Whether or not the DNSKEY record is published in the zone'
+        description: "Whether or not the DNSKEY record is published in the zone"
       dnskey:
         type: string
-        description: 'The DNSKEY record for this key'
+        description: "The DNSKEY record for this key"
       ds:
         type: array
         items:
           type: string
-        description: 'An array of DS records for this key'
+        description: "An array of DS records for this key"
       cds:
         type: array
         items:
           type: string
-        description: 'An array of DS records for this key, filtered by CDS publication settings'
+        description: "An array of DS records for this key, filtered by CDS publication settings"
       privatekey:
         type: string
-        description: 'The private key in ISC format'
+        description: "The private key in ISC format"
       algorithm:
         type: string
-        description: 'The name of the algorithm of the key, should be a mnemonic'
+        description: "The name of the algorithm of the key, should be a mnemonic"
       bits:
         type: integer
-        description: 'The size of the key'
+        description: "The size of the key"
 
   Error:
+    $id: Error
     title: Error
-    description: 'Returned when the server encounters an error, either in client input or internally'
+    type: object
+    description: "Returned when the server encounters an error, either in client input or internally"
     properties:
       error:
         type: string
-        description: 'A human readable error message'
+        description: "A human readable error message"
       errors:
         type: array
         items:
           type: string
-        description: 'Optional array of multiple errors encountered during processing'
+        description: "Optional array of multiple errors encountered during processing"
     required:
       - error
 
   CacheFlushResult:
+    $id: CacheFlushResult
     title: CacheFlushResult
-    description: 'The result of a cache-flush'
+    type: object
+    description: "The result of a cache-flush"
     properties:
       count:
         type: number
-        description: 'Amount of entries flushed'
+        description: "Amount of entries flushed"
       result:
         type: string
         description: 'A message about the result like "Flushed cache"'
 
   View:
+    $id: View
     title: View
+    type: object
     properties:
       zones:
         type: array
         items:
           type: string
-        description: 'An array of zone names'
+        description: "An array of zone names"
 
   Views:
+    $id: Views
     title: Views
+    type: object
     properties:
       views:
         type: array
         items:
           type: string
-        description: 'An array of view names'
+        description: "An array of view names"
 
   Network:
+    $id: Network
     title: Network
+    type: object
     properties:
       network:
         type: string
-        description: 'Network specification in human-readable form base address/prefix length'
+        description: "Network specification in human-readable form base address/prefix length"
       view:
         type: string
-        description: 'The name of the view'
+        description: "The name of the view"
 
   Networks:
+    $id: Networks
     title: Networks
+    type: object
     properties:
       networks:
         type: array
         items:
-          $ref: '#/definitions/Network'
-          
+          $ref: Network
index 0c1bab429843c20a8a83fd856340e5dc35fe16e4..a6f1f006aff7948750da7c4a83c063c170534452 100644 (file)
@@ -13,8 +13,7 @@ TSIGKey Endpoints
 Objects
 -------
 
-.. openapi:: swagger/authoritative-api-swagger.yaml
-  :definitions: TSIGKey
+.. json:schema:: TSIGKey
 
 Examples
 --------
index e3f4d30cf26ab2fcc8214e1d151b442936297425..93f48a618a1f9f2e408a8435bbb478e5fe30f901 100644 (file)
@@ -14,12 +14,15 @@ Objects
 
 A Zone object represents an authoritative DNS Zone.
 
+.. json:schema:: Zone
+
 A Resource Record Set (below as "RRset") are all records for a given name and type.
 
+.. json:schema:: RRSet
+
 Comments are per-RRset.
 
-.. openapi:: swagger/authoritative-api-swagger.yaml
-  :definitions: Zone RRSet Record Comment
+.. json:schema:: Comment
 
 .. note::
 
@@ -38,7 +41,7 @@ Changes made through the Zones API will always yield valid zone data, as the API
 
 DNSSEC-enabled zones should be :ref:`rectified <rules-for-filling-out-dnssec-fields>` after changing the zone data.
 This can be done by the API automatically after a change when the :ref:`metadata-api-rectify` metadata is set.
-When creating or updating a zone, the "api_rectify" field of the :json:object:`Zone` can be set to `true` to enable this behaviour.
+When creating or updating a zone, the "api_rectify" field of the :json:schema:`Zone` can be set to `true` to enable this behaviour.
 
 Backends might implement additional features (by coincidence or not).
 These things are not supported through the API.
index 1377866a69d3ed55c3a7b26abd0c2d8ae0898bd4..bf9421c004beb42b15ba681fef81dd40f33dee46 100644 (file)
@@ -1,20 +1,15 @@
 # To generate requirements.txt, install pip-tools and run:
 #  pip-compile --generate-hashes -U requirements.in
 
-wheel==0.46.2
+# Sphinx >9 breaks the immaterial theme
+# See https://github.com/jbms/sphinx-immaterial/pull/477
+Sphinx>=8.2,<9
+
+sphinx-immaterial [json]>=0.13,<0.14
 setuptools-git==1.2
-Sphinx>=1.5.0,!=1.8.0,<2.0
-alabaster==0.7.13 # higher versions require Sphinx>3.4
-https://github.com/PowerDNS/sphinxcontrib-openapi/archive/refs/heads/use-jsondomain-pdns-py3.10-noscm.zip
-https://github.com/PowerDNS/sphinx-jsondomain/archive/refs/heads/no-type-links.zip
-changelog>=0.5.6,<0.6
+sphinxcontrib-openapi==0.8.4
+changelog>=0.6,<0.7
 sphinxcontrib-fulltoc
-guzzle_sphinx_theme
-docutils!=0.15,<0.18
-jinja2<3.1.0
 pyyaml==6.0.1
-setuptools-scm==8.0.3 # setup-requires for sphinxcontrib-openapi
 pbr # setup-requires for sphinxcontrib-fulltoc
-standard.pipes
-standard.imghdr
 setuptools<82
index 219aa19e27884b16cc6968bc26a1e04fcb92903f..2216b3d93a0f70ea69da98f2edefad6462ee0835 100644 (file)
@@ -1,15 +1,21 @@
 #
-# This file is autogenerated by pip-compile with Python 3.11
+# This file is autogenerated by pip-compile with Python 3.13
 # by the following command:
 #
 #    pip-compile --allow-unsafe --generate-hashes requirements.in
 #
-alabaster==0.7.13 \
-    --hash=sha256:1ee19aca801bbabb5ba3f5f258e4422dfa86f82f3e9cefb0859b283cdd7f62a3 \
-    --hash=sha256:a27a4a084d5e690e16e01e03ad2b2e552c61a65469419b907243193de1a84ae2
-    # via
-    #   -r requirements.in
-    #   sphinx
+alabaster==1.0.0 \
+    --hash=sha256:c00dca57bca26fa62a6d7d0a9fcce65f3e026e9bfe33e9c538fd3fbb2144fd9e \
+    --hash=sha256:fc6786402dc3fcb2de3cabd5fe455a2db534b371124f1f21de8731783dec828b
+    # via sphinx
+annotated-types==0.7.0 \
+    --hash=sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53 \
+    --hash=sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89
+    # via pydantic
+appdirs==1.4.4 \
+    --hash=sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41 \
+    --hash=sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128
+    # via sphinx-immaterial
 attrs==25.4.0 \
     --hash=sha256:16d5969b87f0859ef33a48b35d55ac1be6e42ae49d5e853b597db70c35c57e11 \
     --hash=sha256:adcf7e2a1fb3b36ac48d97835bb6d8ade15b8dcce26aba8bf1d14847b57a3373
@@ -24,9 +30,9 @@ certifi==2026.1.4 \
     --hash=sha256:9943707519e4add1115f44c2bc244f782c0249876bf51b6599fee1ffbedd685c \
     --hash=sha256:ac726dd470482006e014ad384921ed6438c457018f4b3d204aea4281258b2120
     # via requests
-changelog==0.5.8 \
-    --hash=sha256:43b21840874130666b7534b76b402bbb914f8c9c413d5ea9d45850ca4767dafb \
-    --hash=sha256:cd67a8a30e1a38731ebc25568788fe499748113d27324a7e67ad8ee443509415
+changelog==0.6.2 \
+    --hash=sha256:39f934b3d2c40edb2808d03baae69dad2f208b42b8f6fc6d06905bf05d8ffd40 \
+    --hash=sha256:d25be94ca0415bb48185664079eb7a2e072b8c561b48bb5e7d77136ce2da699e
     # via -r requirements.in
 charset-normalizer==3.4.4 \
     --hash=sha256:027f6de494925c0ab2a55eab46ae5129951638a49a34d87f4c3eda90f696b4ad \
@@ -143,19 +149,17 @@ charset-normalizer==3.4.4 \
     --hash=sha256:faa3a41b2b66b6e50f84ae4a68c64fcd0c44355741c6374813a800cd6695db9e \
     --hash=sha256:fd44c878ea55ba351104cb93cc85e74916eb8fa440ca7903e57575e97394f608
     # via requests
-docutils==0.17.1 \
-    --hash=sha256:686577d2e4c32380bb50cbb22f575ed742d58168cee37e99117a854bcd88f125 \
-    --hash=sha256:cf316c8370a737a022b72b56874f6602acf974a37a9fba42ec2876387549fc61
+deepmerge==2.0 \
+    --hash=sha256:5c3d86081fbebd04dd5de03626a0607b809a98fb6ccba5770b62466fe940ff20 \
+    --hash=sha256:6de9ce507115cff0bed95ff0ce9ecc31088ef50cbdf09bc90a09349a318b3d00
+    # via sphinxcontrib-openapi
+docutils==0.21.2 \
+    --hash=sha256:3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f \
+    --hash=sha256:dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2
     # via
-    #   -r requirements.in
+    #   changelog
     #   sphinx
-fake-factory==0.5.11 \
-    --hash=sha256:24950d2cf028080f70830b79e8ceba8711cd2b9dccd99e3b6992dcf7da6e46cd \
-    --hash=sha256:cc450de0e0e9f3f4f89fea715b772b38bb5ad9d458e594fd7fed0f8b934ba636
-    # via sphinx-jsondomain
-guzzle-sphinx-theme==0.7.11 \
-    --hash=sha256:9b8c1639c343c02c3f3db7df660ddf6f533b5454ee92a5f7b02edaa573fed3e6
-    # via -r requirements.in
+    #   sphinx-mdinclude
 idna==3.11 \
     --hash=sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea \
     --hash=sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902
@@ -164,12 +168,10 @@ imagesize==1.4.1 \
     --hash=sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b \
     --hash=sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a
     # via sphinx
-jinja2==3.0.3 \
-    --hash=sha256:077ce6014f7b40d03b47d1f1ca4b0fc8328a692bd284016f806ed0eaca390ad8 \
-    --hash=sha256:611bb273cd68f3b993fabdc4064fc858c5b47a973cb5aa7999ec1ba405c87cd7
-    # via
-    #   -r requirements.in
-    #   sphinx
+jinja2==3.1.6 \
+    --hash=sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d \
+    --hash=sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67
+    # via sphinx
 jsonschema==4.26.0 \
     --hash=sha256:0c26707e2efad8aa1bfc5b7ce170f3fccc2e4918ff85989ba9ffa9facb2be326 \
     --hash=sha256:d489f15263b8d200f8387e64b4c3a75f06629559fb73deb8fdfb525f2dab50ce
@@ -178,6 +180,10 @@ jsonschema-specifications==2025.9.1 \
     --hash=sha256:98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe \
     --hash=sha256:b540987f239e745613c7a9176f3edb72b832a4ac465cf02712288397832b5e8d
     # via jsonschema
+looseversion==1.3.0 \
+    --hash=sha256:781ef477b45946fc03dd4c84ea87734b21137ecda0e1e122bcb3c8d16d2a56e0 \
+    --hash=sha256:ebde65f3f6bb9531a81016c6fef3eb95a61181adc47b7f949e9c0ea47911669e
+    # via changelog
 markupsafe==3.0.3 \
     --hash=sha256:0303439a41979d9e74d18ff5e2dd8c43ed6c6001fd40e5bf2e43f7bd9bbc523f \
     --hash=sha256:068f375c472b3e7acbe2d5318dea141359e6900156b5b2ba06a30b169086b91a \
@@ -268,26 +274,164 @@ markupsafe==3.0.3 \
     --hash=sha256:f71a396b3bf33ecaa1626c255855702aca4d3d9fea5e051b41ac59a9c1c41edc \
     --hash=sha256:f9e130248f4462aaa8e2552d547f36ddadbeaa573879158d721bbd33dfe4743a \
     --hash=sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50
-    # via jinja2
+    # via
+    #   jinja2
+    #   sphinx-immaterial
+mistune==3.2.0 \
+    --hash=sha256:708487c8a8cdd99c9d90eb3ed4c3ed961246ff78ac82f03418f5183ab70e398a \
+    --hash=sha256:febdc629a3c78616b94393c6580551e0e34cc289987ec6c35ed3f4be42d0eee1
+    # via sphinx-mdinclude
 packaging==26.0 \
     --hash=sha256:00243ae351a257117b6a241061796684b084ed1c516a08c48a3f7e147a9d80b4 \
     --hash=sha256:b36f1fef9334a5588b4166f8bcd26a14e521f2b55e6b9de3aaa80d3ff7a37529
-    # via
-    #   setuptools-scm
-    #   sphinx
-    #   wheel
+    # via sphinx
 pbr==7.0.3 \
     --hash=sha256:b46004ec30a5324672683ec848aed9e8fc500b0d261d40a3229c2d2bbfcedc29 \
     --hash=sha256:ff223894eb1cd271a98076b13d3badff3bb36c424074d26334cd25aebeecea6b
     # via -r requirements.in
+picobox==4.0.0 \
+    --hash=sha256:114da1b5606b2f615e8b0eb68d04198ad9de75af5adbcf5b36fe4f664ab927b6 \
+    --hash=sha256:4c27eb689fe45dabd9e64c382e04418147d0b746d155b4e80057dbb7ff82027e
+    # via sphinxcontrib-openapi
+pydantic==2.12.5 \
+    --hash=sha256:4d351024c75c0f085a9febbb665ce8c0c6ec5d30e903bdb6394b7ede26aebb49 \
+    --hash=sha256:e561593fccf61e8a20fc46dfc2dfe075b8be7d0188df33f221ad1f0139180f9d
+    # via
+    #   pydantic-extra-types
+    #   sphinx-immaterial
+pydantic-core==2.41.5 \
+    --hash=sha256:0177272f88ab8312479336e1d777f6b124537d47f2123f89cb37e0accea97f90 \
+    --hash=sha256:01a3d0ab748ee531f4ea6c3e48ad9dac84ddba4b0d82291f87248f2f9de8d740 \
+    --hash=sha256:0384e2e1021894b1ff5a786dbf94771e2986ebe2869533874d7e43bc79c6f504 \
+    --hash=sha256:03b77d184b9eb40240ae9fd676ca364ce1085f203e1b1256f8ab9984dca80a84 \
+    --hash=sha256:03ca43e12fab6023fc79d28ca6b39b05f794ad08ec2feccc59a339b02f2b3d33 \
+    --hash=sha256:05a2c8852530ad2812cb7914dc61a1125dc4e06252ee98e5638a12da6cc6fb6c \
+    --hash=sha256:070259a8818988b9a84a449a2a7337c7f430a22acc0859c6b110aa7212a6d9c0 \
+    --hash=sha256:08daa51ea16ad373ffd5e7606252cc32f07bc72b28284b6bc9c6df804816476e \
+    --hash=sha256:0cbaad15cb0c90aa221d43c00e77bb33c93e8d36e0bf74760cd00e732d10a6a0 \
+    --hash=sha256:100baa204bb412b74fe285fb0f3a385256dad1d1879f0a5cb1499ed2e83d132a \
+    --hash=sha256:112e305c3314f40c93998e567879e887a3160bb8689ef3d2c04b6cc62c33ac34 \
+    --hash=sha256:16f80f7abe3351f8ea6858914ddc8c77e02578544a0ebc15b4c2e1a0e813b0b2 \
+    --hash=sha256:1746d4a3d9a794cacae06a5eaaccb4b8643a131d45fbc9af23e353dc0a5ba5c3 \
+    --hash=sha256:1962293292865bca8e54702b08a4f26da73adc83dd1fcf26fbc875b35d81c815 \
+    --hash=sha256:1d1d9764366c73f996edd17abb6d9d7649a7eb690006ab6adbda117717099b14 \
+    --hash=sha256:1f8d33a7f4d5a7889e60dc39856d76d09333d8a6ed0f5f1190635cbec70ec4ba \
+    --hash=sha256:22f0fb8c1c583a3b6f24df2470833b40207e907b90c928cc8d3594b76f874375 \
+    --hash=sha256:239edca560d05757817c13dc17c50766136d21f7cd0fac50295499ae24f90fdf \
+    --hash=sha256:242a206cd0318f95cd21bdacff3fcc3aab23e79bba5cac3db5a841c9ef9c6963 \
+    --hash=sha256:25e1c2af0fce638d5f1988b686f3b3ea8cd7de5f244ca147c777769e798a9cd1 \
+    --hash=sha256:266fb4cbf5e3cbd0b53669a6d1b039c45e3ce651fd5442eff4d07c2cc8d66808 \
+    --hash=sha256:2782c870e99878c634505236d81e5443092fba820f0373997ff75f90f68cd553 \
+    --hash=sha256:287dad91cfb551c363dc62899a80e9e14da1f0e2b6ebde82c806612ca2a13ef1 \
+    --hash=sha256:29452c56df2ed968d18d7e21f4ab0ac55e71dc59524872f6fc57dcf4a3249ed2 \
+    --hash=sha256:299e0a22e7ae2b85c1a57f104538b2656e8ab1873511fd718a1c1c6f149b77b5 \
+    --hash=sha256:2a5e06546e19f24c6a96a129142a75cee553cc018ffee48a460059b1185f4470 \
+    --hash=sha256:2b761d210c9ea91feda40d25b4efe82a1707da2ef62901466a42492c028553a2 \
+    --hash=sha256:2c010c6ded393148374c0f6f0bf89d206bf3217f201faa0635dcd56bd1520f6b \
+    --hash=sha256:2ff4321e56e879ee8d2a879501c8e469414d948f4aba74a2d4593184eb326660 \
+    --hash=sha256:3006c3dd9ba34b0c094c544c6006cc79e87d8612999f1a5d43b769b89181f23c \
+    --hash=sha256:33cb885e759a705b426baada1fe68cbb0a2e68e34c5d0d0289a364cf01709093 \
+    --hash=sha256:346285d28e4c8017da95144c7f3acd42740d637ff41946af5ce6e5e420502dd5 \
+    --hash=sha256:34a64bc3441dc1213096a20fe27e8e128bd3ff89921706e83c0b1ac971276594 \
+    --hash=sha256:35b44f37a3199f771c3eaa53051bc8a70cd7b54f333531c59e29fd4db5d15008 \
+    --hash=sha256:378bec5c66998815d224c9ca994f1e14c0c21cb95d2f52b6021cc0b2a58f2a5a \
+    --hash=sha256:3f37a19d7ebcdd20b96485056ba9e8b304e27d9904d233d7b1015db320e51f0a \
+    --hash=sha256:3f84d5c1b4ab906093bdc1ff10484838aca54ef08de4afa9de0f5f14d69639cd \
+    --hash=sha256:4009935984bd36bd2c774e13f9a09563ce8de4abaa7226f5108262fa3e637284 \
+    --hash=sha256:406bf18d345822d6c21366031003612b9c77b3e29ffdb0f612367352aab7d586 \
+    --hash=sha256:4819fa52133c9aa3c387b3328f25c1facc356491e6135b459f1de698ff64d869 \
+    --hash=sha256:482c982f814460eabe1d3bb0adfdc583387bd4691ef00b90575ca0d2b6fe2294 \
+    --hash=sha256:4bc36bbc0b7584de96561184ad7f012478987882ebf9f9c389b23f432ea3d90f \
+    --hash=sha256:506d766a8727beef16b7adaeb8ee6217c64fc813646b424d0804d67c16eddb66 \
+    --hash=sha256:56121965f7a4dc965bff783d70b907ddf3d57f6eba29b6d2e5dabfaf07799c51 \
+    --hash=sha256:58133647260ea01e4d0500089a8c4f07bd7aa6ce109682b1426394988d8aaacc \
+    --hash=sha256:5921a4d3ca3aee735d9fd163808f5e8dd6c6972101e4adbda9a4667908849b97 \
+    --hash=sha256:5a4e67afbc95fa5c34cf27d9089bca7fcab4e51e57278d710320a70b956d1b9a \
+    --hash=sha256:5cb1b2f9742240e4bb26b652a5aeb840aa4b417c7748b6f8387927bc6e45e40d \
+    --hash=sha256:62de39db01b8d593e45871af2af9e497295db8d73b085f6bfd0b18c83c70a8f9 \
+    --hash=sha256:634e8609e89ceecea15e2d61bc9ac3718caaaa71963717bf3c8f38bfde64242c \
+    --hash=sha256:63510af5e38f8955b8ee5687740d6ebf7c2a0886d15a6d65c32814613681bc07 \
+    --hash=sha256:650ae77860b45cfa6e2cdafc42618ceafab3a2d9a3811fcfbd3bbf8ac3c40d36 \
+    --hash=sha256:6561e94ba9dacc9c61bce40e2d6bdc3bfaa0259d3ff36ace3b1e6901936d2e3e \
+    --hash=sha256:65840751b72fbfd82c3c640cff9284545342a4f1eb1586ad0636955b261b0b05 \
+    --hash=sha256:6cb58b9c66f7e4179a2d5e0f849c48eff5c1fca560994d6eb6543abf955a149e \
+    --hash=sha256:6f52298fbd394f9ed112d56f3d11aabd0d5bd27beb3084cc3d8ad069483b8941 \
+    --hash=sha256:707625ef0983fcfb461acfaf14de2067c5942c6bb0f3b4c99158bed6fedd3cf3 \
+    --hash=sha256:72f6c8b11857a856bcfa48c86f5368439f74453563f951e473514579d44aa612 \
+    --hash=sha256:753e230374206729bf0a807954bcc6c150d3743928a73faffee51ac6557a03c3 \
+    --hash=sha256:76d0819de158cd855d1cbb8fcafdf6f5cf1eb8e470abe056d5d161106e38062b \
+    --hash=sha256:76ee27c6e9c7f16f47db7a94157112a2f3a00e958bc626e2f4ee8bec5c328fbe \
+    --hash=sha256:77b63866ca88d804225eaa4af3e664c5faf3568cea95360d21f4725ab6e07146 \
+    --hash=sha256:79ec52ec461e99e13791ec6508c722742ad745571f234ea6255bed38c6480f11 \
+    --hash=sha256:7b93a4d08587e2b7e7882de461e82b6ed76d9026ce91ca7915e740ecc7855f60 \
+    --hash=sha256:7da7087d756b19037bc2c06edc6c170eeef3c3bafcb8f532ff17d64dc427adfd \
+    --hash=sha256:7f3bf998340c6d4b0c9a2f02d6a400e51f123b59565d74dc60d252ce888c260b \
+    --hash=sha256:80aa89cad80b32a912a65332f64a4450ed00966111b6615ca6816153d3585a8c \
+    --hash=sha256:8566def80554c3faa0e65ac30ab0932b9e3a5cd7f8323764303d468e5c37595a \
+    --hash=sha256:873e0d5b4fb9b89ef7c2d2a963ea7d02879d9da0da8d9d4933dee8ee86a8b460 \
+    --hash=sha256:88942d3a3dff3afc8288c21e565e476fc278902ae4d6d134f1eeda118cc830b1 \
+    --hash=sha256:8bfeaf8735be79f225f3fefab7f941c712aaca36f1128c9d7e2352ee1aa87bdf \
+    --hash=sha256:8e7c86f27c585ef37c35e56a96363ab8de4e549a95512445b85c96d3e2f7c1bf \
+    --hash=sha256:915c3d10f81bec3a74fbd4faebe8391013ba61e5a1a8d48c4455b923bdda7858 \
+    --hash=sha256:93e8740d7503eb008aa2df04d3b9735f845d43ae845e6dcd2be0b55a2da43cd2 \
+    --hash=sha256:941103c9be18ac8daf7b7adca8228f8ed6bb7a1849020f643b3a14d15b1924d9 \
+    --hash=sha256:97aeba56665b4c3235a0e52b2c2f5ae9cd071b8a8310ad27bddb3f7fb30e9aa2 \
+    --hash=sha256:a39455728aabd58ceabb03c90e12f71fd30fa69615760a075b9fec596456ccc3 \
+    --hash=sha256:a3a52f6156e73e7ccb0f8cced536adccb7042be67cb45f9562e12b319c119da6 \
+    --hash=sha256:a668ce24de96165bb239160b3d854943128f4334822900534f2fe947930e5770 \
+    --hash=sha256:a75dafbf87d6276ddc5b2bf6fae5254e3d0876b626eb24969a574fff9149ee5d \
+    --hash=sha256:aabf5777b5c8ca26f7824cb4a120a740c9588ed58df9b2d196ce92fba42ff8dc \
+    --hash=sha256:aec5cf2fd867b4ff45b9959f8b20ea3993fc93e63c7363fe6851424c8a7e7c23 \
+    --hash=sha256:b2379fa7ed44ddecb5bfe4e48577d752db9fc10be00a6b7446e9663ba143de26 \
+    --hash=sha256:b4ececa40ac28afa90871c2cc2b9ffd2ff0bf749380fbdf57d165fd23da353aa \
+    --hash=sha256:b5819cd790dbf0c5eb9f82c73c16b39a65dd6dd4d1439dcdea7816ec9adddab8 \
+    --hash=sha256:b74557b16e390ec12dca509bce9264c3bbd128f8a2c376eaa68003d7f327276d \
+    --hash=sha256:b80aa5095cd3109962a298ce14110ae16b8c1aece8b72f9dafe81cf597ad80b3 \
+    --hash=sha256:b93590ae81f7010dbe380cdeab6f515902ebcbefe0b9327cc4804d74e93ae69d \
+    --hash=sha256:b96d5f26b05d03cc60f11a7761a5ded1741da411e7fe0909e27a5e6a0cb7b034 \
+    --hash=sha256:bd3d54f38609ff308209bd43acea66061494157703364ae40c951f83ba99a1a9 \
+    --hash=sha256:bfea2a5f0b4d8d43adf9d7b8bf019fb46fdd10a2e5cde477fbcb9d1fa08c68e1 \
+    --hash=sha256:c007fe8a43d43b3969e8469004e9845944f1a80e6acd47c150856bb87f230c56 \
+    --hash=sha256:c1df3d34aced70add6f867a8cf413e299177e0c22660cc767218373d0779487b \
+    --hash=sha256:c23e27686783f60290e36827f9c626e63154b82b116d7fe9adba1fda36da706c \
+    --hash=sha256:c8d8b4eb992936023be7dee581270af5c6e0697a8559895f527f5b7105ecd36a \
+    --hash=sha256:c9e19dd6e28fdcaa5a1de679aec4141f691023916427ef9bae8584f9c2fb3b0e \
+    --hash=sha256:d0d2568a8c11bf8225044aa94409e21da0cb09dcdafe9ecd10250b2baad531a9 \
+    --hash=sha256:d38548150c39b74aeeb0ce8ee1d8e82696f4a4e16ddc6de7b1d8823f7de4b9b5 \
+    --hash=sha256:d3a978c4f57a597908b7e697229d996d77a6d3c94901e9edee593adada95ce1a \
+    --hash=sha256:d5160812ea7a8a2ffbe233d8da666880cad0cbaf5d4de74ae15c313213d62556 \
+    --hash=sha256:dc799088c08fa04e43144b164feb0c13f9a0bc40503f8df3e9fde58a3c0c101e \
+    --hash=sha256:df3959765b553b9440adfd3c795617c352154e497a4eaf3752555cfb5da8fc49 \
+    --hash=sha256:dfa8a0c812ac681395907e71e1274819dec685fec28273a28905df579ef137e2 \
+    --hash=sha256:e25c479382d26a2a41b7ebea1043564a937db462816ea07afa8a44c0866d52f9 \
+    --hash=sha256:e4f4a984405e91527a0d62649ee21138f8e3d0ef103be488c1dc11a80d7f184b \
+    --hash=sha256:e536c98a7626a98feb2d3eaf75944ef6f3dbee447e1f841eae16f2f0a72d8ddc \
+    --hash=sha256:e56ba91f47764cc14f1daacd723e3e82d1a89d783f0f5afe9c364b8bb491ccdb \
+    --hash=sha256:e672ba74fbc2dc8eea59fb6d4aed6845e6905fc2a8afe93175d94a83ba2a01a0 \
+    --hash=sha256:e7b576130c69225432866fe2f4a469a85a54ade141d96fd396dffcf607b558f8 \
+    --hash=sha256:e8465ab91a4bd96d36dde3263f06caa6a8a6019e4113f24dc753d79a8b3a3f82 \
+    --hash=sha256:e96cea19e34778f8d59fe40775a7a574d95816eb150850a85a7a4c8f4b94ac69 \
+    --hash=sha256:ece5c59f0ce7d001e017643d8d24da587ea1f74f6993467d85ae8a5ef9d4f42b \
+    --hash=sha256:eceb81a8d74f9267ef4081e246ffd6d129da5d87e37a77c9bde550cb04870c1c \
+    --hash=sha256:ed2e99c456e3fadd05c991f8f437ef902e00eedf34320ba2b0842bd1c3ca3a75 \
+    --hash=sha256:f0cd744688278965817fd0839c4a4116add48d23890d468bc436f78beb28abf5 \
+    --hash=sha256:f14f8f046c14563f8eb3f45f499cc658ab8d10072961e07225e507adb700e93f \
+    --hash=sha256:f15489ba13d61f670dcc96772e733aad1a6f9c429cc27574c6cdaed82d0146ad \
+    --hash=sha256:f31d95a179f8d64d90f6831d71fa93290893a33148d890ba15de25642c5d075b \
+    --hash=sha256:f41a7489d32336dbf2199c8c0a215390a751c5b014c2c1c5366e817202e9cdf7 \
+    --hash=sha256:f41eb9797986d6ebac5e8edff36d5cef9de40def462311b3eb3eeded1431e425 \
+    --hash=sha256:f547144f2966e1e16ae626d8ce72b4cfa0caedc7fa28052001c94fb2fcaa1c52
+    # via pydantic
+pydantic-extra-types==2.11.0 \
+    --hash=sha256:4e9991959d045b75feb775683437a97991d02c138e00b59176571db9ce634f0e \
+    --hash=sha256:84b864d250a0fc62535b7ec591e36f2c5b4d1325fa0017eb8cda9aeb63b374a6
+    # via sphinx-immaterial
 pygments==2.19.2 \
     --hash=sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887 \
     --hash=sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b
-    # via sphinx
-python-dateutil==2.9.0.post0 \
-    --hash=sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3 \
-    --hash=sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427
-    # via fake-factory
+    # via
+    #   sphinx
+    #   sphinx-mdinclude
 pyyaml==6.0.1 \
     --hash=sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5 \
     --hash=sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc \
@@ -342,6 +486,7 @@ pyyaml==6.0.1 \
     --hash=sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f
     # via
     #   -r requirements.in
+    #   sphinx-immaterial
     #   sphinxcontrib-openapi
 referencing==0.37.0 \
     --hash=sha256:381329a9f99628c9069361716891d34ad94af76e461dcb0335825aecc7692231 \
@@ -352,6 +497,16 @@ referencing==0.37.0 \
 requests==2.32.5 \
     --hash=sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6 \
     --hash=sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf
+    # via
+    #   sphinx
+    #   sphinx-immaterial
+roman-numerals==4.1.0 \
+    --hash=sha256:1af8b147eb1405d5839e78aeb93131690495fe9da5c91856cb33ad55a7f1e5b2 \
+    --hash=sha256:647ba99caddc2cc1e55a51e4360689115551bf4476d90e8162cf8c345fe233c7
+    # via roman-numerals-py
+roman-numerals-py==4.1.0 \
+    --hash=sha256:553114c1167141c1283a51743759723ecd05604a1b6b507225e91dc1a6df0780 \
+    --hash=sha256:f5d7b2b4ca52dd855ef7ab8eb3590f428c0b1ea480736ce32b01fef2a5f8daf9
     # via sphinx
 rpds-py==0.30.0 \
     --hash=sha256:07ae8a593e1c3c6b82ca3292efbe73c30b61332fd612e05abee07c79359f292f \
@@ -476,73 +631,79 @@ setuptools-git==1.2 \
     --hash=sha256:e7764dccce7d97b4b5a330d7b966aac6f9ac026385743fd6cedad553f2494cfa \
     --hash=sha256:ff64136da01aabba76ae88b050e7197918d8b2139ccbf6144e14d472b9c40445
     # via -r requirements.in
-setuptools-scm==8.0.3 \
-    --hash=sha256:0169fd70197efda2f8c4d0b2a7a3d614431b488116f37b79d031e9e7ec884d8c \
-    --hash=sha256:813822234453438a13c78d05c8af29918fbc06f88efb33d38f065340bbb48c39
-    # via -r requirements.in
-six==1.17.0 \
-    --hash=sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274 \
-    --hash=sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81
-    # via
-    #   fake-factory
-    #   python-dateutil
-    #   sphinx
-    #   sphinxcontrib-httpdomain
 snowballstemmer==3.0.1 \
     --hash=sha256:6cd7b3897da8d6c9ffb968a6781fa6532dce9c3618a4b127d920dab764a19064 \
     --hash=sha256:6d5eeeec8e9f84d4d56b847692bacf79bc2c8e90c7f80ca4444ff8b6f2e52895
     # via sphinx
-sphinx==1.8.6 \
-    --hash=sha256:5973adbb19a5de30e15ab394ec8bc05700317fa83f122c349dd01804d983720f \
-    --hash=sha256:e096b1b369dbb0fcb95a31ba8c9e1ae98c588e601f08eada032248e1696de4b1
+sphinx==8.2.3 \
+    --hash=sha256:398ad29dee7f63a75888314e9424d40f52ce5a6a87ae88e7071e80af296ec348 \
+    --hash=sha256:4405915165f13521d875a8c29c8970800a0141c14cc5416a38feca4ea5d9b9c3
     # via
     #   -r requirements.in
-    #   guzzle-sphinx-theme
-    #   sphinx-jsondomain
+    #   changelog
+    #   sphinx-immaterial
+    #   sphinx-mdinclude
     #   sphinxcontrib-httpdomain
-sphinx-jsondomain @ https://github.com/PowerDNS/sphinx-jsondomain/archive/refs/heads/no-type-links.zip \
-    --hash=sha256:0df65f5b93902e9e4f03935f39d91ae2a6a782116078f8af99ec1e370f999257
-    # via
-    #   -r requirements.in
     #   sphinxcontrib-openapi
+sphinx-immaterial[json]==0.13.9 \
+    --hash=sha256:5ea92d2ddc6befcd0fedbd3e6766ea4746e94d9a8a5cc0ab092a946e1fde4254
+    # via -r requirements.in
+sphinx-mdinclude==0.6.2 \
+    --hash=sha256:447462e82cb8be61404a2204227f920769eb923d2f57608e3325f3bb88286b4c \
+    --hash=sha256:648e78edb067c0e4bffc22943278d49d54a0714494743592032fa3ad82a86984
+    # via sphinxcontrib-openapi
+sphinxcontrib-applehelp==2.0.0 \
+    --hash=sha256:2f29ef331735ce958efa4734873f084941970894c6090408b079c61b2e1c06d1 \
+    --hash=sha256:4cd3f0ec4ac5dd9c17ec65e9ab272c9b867ea77425228e68ecf08d6b28ddbdb5
+    # via sphinx
+sphinxcontrib-devhelp==2.0.0 \
+    --hash=sha256:411f5d96d445d1d73bb5d52133377b4248ec79db5c793ce7dbe59e074b4dd1ad \
+    --hash=sha256:aefb8b83854e4b0998877524d1029fd3e6879210422ee3780459e28a1f03a8a2
+    # via sphinx
 sphinxcontrib-fulltoc==1.2.0 \
     --hash=sha256:c845d62fc467f3135d4543e9f10e13ef91852683bd1c90fd19d07f9d36757cd9
     # via -r requirements.in
-sphinxcontrib-httpdomain==1.8.1 \
-    --hash=sha256:21eefe1270e4d9de8d717cc89ee92cc4871b8736774393bafc5e38a6bb77b1d5 \
-    --hash=sha256:6c2dfe6ca282d75f66df333869bb0ce7331c01b475db6809ff9d107b7cdfe04b
+sphinxcontrib-htmlhelp==2.1.0 \
+    --hash=sha256:166759820b47002d22914d64a075ce08f4c46818e17cfc9470a9786b759b19f8 \
+    --hash=sha256:c9e2916ace8aad64cc13a0d233ee22317f2b9025b9cf3295249fa985cc7082e9
+    # via sphinx
+sphinxcontrib-httpdomain==2.0.0 \
+    --hash=sha256:9e4e8733bf41ee4d9d5f9eb4dbf3cc2c22a665221ba42c5c3ae181b98af8855d \
+    --hash=sha256:e968775c9994f8139cb6ff91e1f6a8557396a2cc08073997eed10d9b39f96df3
     # via sphinxcontrib-openapi
-sphinxcontrib-openapi @ https://github.com/PowerDNS/sphinxcontrib-openapi/archive/refs/heads/use-jsondomain-pdns-py3.10-noscm.zip \
-    --hash=sha256:ad6659a5e86e4899386d249f1eae18a459175a92da0dd851ce20f8b8ff6569b0
+sphinxcontrib-jsmath==1.0.1 \
+    --hash=sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178 \
+    --hash=sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8
+    # via sphinx
+sphinxcontrib-openapi==0.8.4 \
+    --hash=sha256:50911c18d452d9390ee3a384ef8dc8bde6135f542ba55691f81e1fbc0b71014e \
+    --hash=sha256:df883808a5b5e4b4113ad697185c43a3f42df3dce70453af78ba7076907e9a20
     # via -r requirements.in
+sphinxcontrib-qthelp==2.0.0 \
+    --hash=sha256:4fe7d0ac8fc171045be623aba3e2a8f613f8682731f9153bb2e40ece16b9bbab \
+    --hash=sha256:b18a828cdba941ccd6ee8445dbe72ffa3ef8cbe7505d8cd1fa0d42d3f2d5f3eb
+    # via sphinx
 sphinxcontrib-serializinghtml==2.0.0 \
     --hash=sha256:6e2cb0eef194e10c27ec0023bfeb25badbbb5868244cf5bc5bdc04e4464bf331 \
     --hash=sha256:e9d912827f872c029017a53f0ef2180b327c3f7fd23c87229f7a8e8b70031d4d
-    # via sphinxcontrib-websupport
-sphinxcontrib-websupport==1.2.4 \
-    --hash=sha256:4edf0223a0685a7c485ae5a156b6f529ba1ee481a1417817935b20bde1956232 \
-    --hash=sha256:6fc9287dfc823fe9aa432463edd6cea47fa9ebbf488d7f289b322ffcfca075c7
     # via sphinx
-standard-imghdr==3.13.0 \
-    --hash=sha256:30a1bff5465605bb496f842a6ac3cc1f2131bf3025b0da28d4877d6d4b7cc8e9 \
-    --hash=sha256:8d9c68058d882f6fc3542a8d39ef9ff94d2187dc90bd0c851e0902776b7b7a42
-    # via -r requirements.in
-standard-pipes==3.13.0 \
-    --hash=sha256:5805d0738fa17192e58cc4dea26dcfe9b8c5cd9c77e78d5dbded8bc3bda428c9 \
-    --hash=sha256:cde270ae625064211dbcd1c8f35a540b70d8ccd7443b099a496f8e6a44fed2f3
-    # via -r requirements.in
 typing-extensions==4.15.0 \
     --hash=sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466 \
     --hash=sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548
-    # via referencing
+    # via
+    #   pydantic
+    #   pydantic-core
+    #   pydantic-extra-types
+    #   sphinx-immaterial
+    #   typing-inspection
+typing-inspection==0.4.2 \
+    --hash=sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7 \
+    --hash=sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464
+    # via pydantic
 urllib3==2.6.3 \
     --hash=sha256:1b62b6884944a57dbe321509ab94fd4d3b307075e0c2eae991ac71ee15ad38ed \
     --hash=sha256:bf272323e553dfb2e87d9bfd225ca7b0f467b919d7bbd355436d3fd37cb0acd4
     # via requests
-wheel==0.46.2 \
-    --hash=sha256:33ae60725d69eaa249bc1982e739943c23b34b58d51f1cb6253453773aca6e65 \
-    --hash=sha256:3d79e48fde9847618a5a181f3cc35764c349c752e2fe911e65fa17faab9809b0
-    # via -r requirements.in
 
 # The following packages are considered to be unsafe in a requirements file:
 setuptools==81.0.0 \
@@ -551,5 +712,3 @@ setuptools==81.0.0 \
     # via
     #   -r requirements.in
     #   pbr
-    #   setuptools-scm
-    #   sphinx