From 324a0e324d936dda9bde0730a57fe0b77412aca9 Mon Sep 17 00:00:00 2001 From: "control-plane-agent[bot]" <318806258+control-plane-agent[bot]@users.noreply.github.com> Date: Tue, 29 Sep 2026 21:58:29 -0700 Subject: [PATCH 1/2] DOCS: the program renders as a site with navigation and search The page was one hand-written HTML file beside the README, two homes for the same words. The site is now generated from the documents at build time, the way build-doctrine's and manifest-identity's are: the README as the front page, then the phase plan, monitoring, recovery, pipelines, and the decisions, with the diagrams and the banner beside them, rendered in strict mode so a broken link fails the build. A test holds that every root document is a page and every anchor resolves. The hand-written page is gone, and the figures check reads the README alone. Co-authored-by: Claude --- .github/workflows/ci.yml | 13 +- .github/workflows/docs.yml | 55 ++ .gitignore | 8 + README.md | 6 +- index.html | 185 ------- mkdocs.yml | 44 ++ requirements-docs.in | 2 + requirements-docs.txt | 497 ++++++++++++++++++ .../__pycache__/build_docs.cpython-314.pyc | Bin 0 -> 6212 bytes scripts/build_docs.py | 91 ++++ scripts/check_figures.py | 2 +- .../test_docs_build.cpython-314.pyc | Bin 0 -> 4661 bytes tests/test_docs_build.py | 48 ++ 13 files changed, 762 insertions(+), 189 deletions(-) create mode 100644 .github/workflows/docs.yml create mode 100644 .gitignore delete mode 100644 index.html create mode 100644 mkdocs.yml create mode 100644 requirements-docs.in create mode 100644 requirements-docs.txt create mode 100644 scripts/__pycache__/build_docs.cpython-314.pyc create mode 100644 scripts/build_docs.py create mode 100644 tests/__pycache__/test_docs_build.cpython-314.pyc create mode 100644 tests/test_docs_build.py diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4f91e77..5d3349c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -48,6 +48,17 @@ jobs: run: | ! grep -rnIE "\b(TODO|FIXME|HACK|XXX)\b" --exclude-dir=.git --exclude-dir=.github --exclude=.pre-commit-config.yaml . + docs: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + - name: every document is a page and every anchor resolves + run: python3 -m unittest discover -s tests + - name: the pages generate + run: python3 scripts/build_docs.py + links: runs-on: ubuntu-latest steps: @@ -63,7 +74,7 @@ jobs: # Offline on purpose: the pipeline checks the cross-references # inside this repository and fetches nothing. - name: check internal links - run: git ls-files -z "*.md" "*.html" | xargs -0 "$RUNNER_TEMP/lychee-x86_64-unknown-linux-gnu/lychee" --offline --no-progress --include-fragments + run: git ls-files -z "*.md" | xargs -0 "$RUNNER_TEMP/lychee-x86_64-unknown-linux-gnu/lychee" --offline --no-progress --include-fragments doctrine: runs-on: ubuntu-latest diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 0000000..e220dc0 --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,55 @@ +# The documentation site, published to GitHub Pages from the same +# documents the gates check. The pages are generated at build time by +# scripts/build_docs.py from the root documents, then rendered by the +# generator installed from the hash-pinned docs tree, in strict mode, +# so a broken link or anchor fails here before it can reach a reader. +# Runs when a document it renders changes on main. +name: docs + +permissions: + contents: read + +on: + push: + branches: [main] + paths: + - "*.md" + - "diagrams/**" + - "images/**" + - "mkdocs.yml" + - "scripts/build_docs.py" + - "requirements-docs.txt" + - ".github/workflows/docs.yml" + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + - name: install the docs tree, hashes enforced + run: | + python3 -m venv "$RUNNER_TEMP/venv" + "$RUNNER_TEMP/venv/bin/pip" install --no-cache-dir --require-hashes -r requirements-docs.txt + - name: generate the pages from the documents + run: python3 scripts/build_docs.py + - name: render the site, strictly + run: '"$RUNNER_TEMP/venv/bin/mkdocs" build --strict' + - uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0 + with: + path: site + + deploy: + needs: build + runs-on: ubuntu-latest + permissions: + pages: write + id-token: write + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + steps: + - id: deployment + uses: actions/deploy-pages@368f82528645a54fb793d4d04e342629a3f51346 # v5.0.1 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7a7dd7b --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +# The documentation site, generated at build time and never committed +docs/site/ +site/ + +.DS_Store +Thumbs.db +.vscode/ +.idea/ diff --git a/README.md b/README.md index ab3e422..39b4cf5 100644 --- a/README.md +++ b/README.md @@ -59,8 +59,10 @@ It will have: secure-expense-mvp is a small application built before the program as a learning exercise, kept as a reference. -The rendered site is this repository, served at -https://tltaylor1.github.io. +This repository is the program's home. Its documents render as a site +with side navigation and search at +, generated from these files +at build time; the account's own page is at . ## The parts diff --git a/index.html b/index.html deleted file mode 100644 index 8211904..0000000 --- a/index.html +++ /dev/null @@ -1,185 +0,0 @@ - - - - - -control-plane - - - - -
-

control-plane

- control-plane: the shared platform grid behind the applications -

control-plane is a security engineering program that one person - is building in public with an AI coding agent. The agent writes the - code and the documents; the person reviews and approves every - change; every decision and every mistake is recorded. It has three - parts.

-

build-doctrine is the rulebook for all the code. It is the - standards for letting an AI agent write code that a person is - responsible for, and it provides the tools that check any repository - against them.

-

It carries:

-
    -
  • Rules where each one names the problem behind it and the check - that catches it.
  • -
  • A scorer that grades any repository from 0 to 5 on each - rule.
  • -
  • A vetting tool that examines a dependency before it is - adopted.
  • -
  • A project template with the checks already switched on.
  • -
  • Coverage of seven frameworks: OWASP Top 10, OWASP API Security - Top 10, OWASP Top 10 for LLM Applications, STRIDE, NIST SSDF, OWASP - ASVS, and SLSA. Eighty items mapped to the rules, gaps listed.
  • -
-

manifest-identity is the application built under those rules. It - keeps two records about every identity in a cloud estate, what - access it holds and what access a named person authorized, and it - shows every difference between them.

-

It has:

-
    -
  • Seven providers read from their own export files: AWS, GitHub, - Kubernetes, Google Cloud, Azure and Entra, Okta, Active Directory. - Any other provider through a table.
  • -
  • Review campaigns that put each difference in front of the - person responsible for it, one decision at a time.
  • -
  • Twenty findings, each explaining itself: unused identities, - keys past their age, administrators by capability, trusts open to - the world.
  • -
  • A read-only API and a change feed, so other systems follow the - decisions.
  • -
  • more than 400 tests, 84 recorded decisions, 34 controls proven by - mutation, five outside ratings, a release verifiable with one - command.
  • -
-

The cloud deployment is the part still to build, phases 3 to 7. - It is the application run in AWS the way the rulebook says.

-

It will have:

-
    -
  • An AWS organization defined as code.
  • -
  • One account that persists; the workloads inside it torn down - and rebuilt daily, so recovery is routine.
  • -
  • Deploys without stored credentials; the image promoted by - digest.
  • -
  • The pipeline tested by planting a flaw; the cloud's own - monitoring switched on.
  • -
  • The ability to change a cloud account comes last, earned by - everything before it. Each phase's plan is published before the - work.
  • -
-

secure-expense-mvp is a small application built before the - program as a learning exercise, kept as a reference.

- -

The parts

-
-

The program is four repositories. Each is public, and each is - scored against the rulebook in its own pipeline.

-

They are:

-
    -
  • manifest-identity: - the application.
  • -
  • build-doctrine: - the rulebook, the scorer, the vetting tool, and the - template.
  • -
  • aws-platform: the cloud deployment, arriving with Phase 3 as - reusable Terraform modules for an organization, its baseline, - account vending, and keyless deploys.
  • -
  • secure-expense-mvp: - the learning exercise from before the program, kept as a - reference.
  • -
-
- -

The program documents

-
-

Some things no single repository can answer for. They are kept - here, and each carries the date it was last checked, so it goes - stale on a schedule rather than quietly.

-

They are:

-
    -
  • The plan for the current phase, - published before the work starts, so a change of plan is a - recorded decision.
  • -
  • Monitoring: what is watched at - each layer, what signal it gives, and who hears it.
  • -
  • Recovery: what is rebuilt from code - and what real state is backed up, with the date each drill last - ran.
  • -
  • Pipelines: how every repository - blocks a bad change, and how the blocking tools are verified - before they run.
  • -
-
- -

The method

-
-

Every change takes the same path, whichever repository it is - in. The agent proposes, the checks run, and a person approves.

-

The rules of the path:

-
    -
  • Design first. The plan is public before the first line of - code.
  • -
  • Every change is a pull request under the agent's own - identity. The checks must pass, a person must approve, and the - merge is the record.
  • -
  • Every figure in a document is checked against the running - system, or a test fails.
  • -
  • Every mistake becomes a rule, and the second time a fix is - done by hand it becomes automation.
  • -
  • What was left out on purpose is written down beside what was - built.
  • -
-
- -

The arc

- The eight phases as a timeline, with the current position marked -

The program runs in eight phases, counted from zero to match the - repositories. Phases 0 to 2 are complete. The Phase 3 plan is - written in PHASE-3.md, and no Phase 3 code - exists yet.

-

The phases:

-
    -
  1. Design, before any code
  2. -
  3. The application: the observed half in twelve review-gated - subphases, then the authorized half in fourteen more
  4. -
  5. Local Kubernetes: admission, network policy, identity
  6. -
  7. The cloud enclave as code: the plan is written, no code yet
  8. -
  9. Managed Kubernetes
  10. -
  11. The security-gated pipeline, proven by a planted flaw
  12. -
  13. Runtime detection and response
  14. -
  15. Human-triggered remediation, last, because write access is earned
  16. -
- -
phases 0 through 2 are tagged v0.2.0 with build provenance - verifiable against the public transparency log
-
- - diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 0000000..f73e10f --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,44 @@ +# The documentation site: generated pages under docs/site, produced by +# scripts/build_docs.py from the root documents at build time, so the +# site has no source of its own to drift. Strict mode turns a broken +# link or anchor into a failed build. +site_name: control-plane +site_description: A security engineering program built in public, its rulebook, its application, and its cloud deployment +site_url: https://tltaylor1.github.io/control-plane/ +repo_url: https://github.com/tltaylor1/control-plane +repo_name: tltaylor1/control-plane +docs_dir: docs/site +site_dir: site +strict: true + +theme: + name: material + features: + - navigation.sections + - navigation.top + - navigation.footer + - search.highlight + - content.code.copy + palette: + - media: "(prefers-color-scheme: light)" + scheme: default + toggle: + icon: material/weather-night + name: Switch to dark mode + - media: "(prefers-color-scheme: dark)" + scheme: slate + toggle: + icon: material/weather-sunny + name: Switch to light mode + +markdown_extensions: + - toc: + permalink: true + - tables + - attr_list + - pymdownx.superfences + +validation: + anchors: warn + absolute_links: warn + unrecognized_links: warn diff --git a/requirements-docs.in b/requirements-docs.in new file mode 100644 index 0000000..9a8a4ca --- /dev/null +++ b/requirements-docs.in @@ -0,0 +1,2 @@ +mkdocs +mkdocs-material diff --git a/requirements-docs.txt b/requirements-docs.txt new file mode 100644 index 0000000..2c18ade --- /dev/null +++ b/requirements-docs.txt @@ -0,0 +1,497 @@ +# +# This file is autogenerated by pip-compile with Python 3.14 +# by the following command: +# +# pip-compile --generate-hashes --output-file=requirements-docs.txt --strip-extras requirements-docs.in +# +babel==2.18.0 \ + --hash=sha256:b80b99a14bd085fcacfa15c9165f651fbb3406e66cc603abf11c5750937c992d \ + --hash=sha256:e2b422b277c2b9a9630c1d7903c2a00d0830c409c59ac8cae9081c92f1aeba35 + # via mkdocs-material +backrefs==8.0 \ + --hash=sha256:4a627b817fd2dce43b79ab48da63613340509381cd8ce0897078a0bce79a2ab8 \ + --hash=sha256:601ce68ca12385dbda06ce264406b4c4210cf5b79fd0fd627592365c92f29a88 \ + --hash=sha256:87f0fae8c5f207fe9f4b2887efc71d42f4900ac78faa1af08d675ef303692dc5 \ + --hash=sha256:9ec96efa080938be92323e8e730e57718c9c88eb15ad70bbef4e1766df591408 \ + --hash=sha256:b556cd7d36c3a3a2f256b89590b176b8eddfb73bcfaee3a3ddd84ea66d21ce50 \ + --hash=sha256:f0c35cf0102ba6b6070c12a492be3c1c1d3f5839529784b9a9565d6d04569a01 + # via mkdocs-material +certifi==2026.7.22 \ + --hash=sha256:62f22742b58a1a33014a2b6b706588a8d7e2a88ae7bd1a6ebe8c992928483775 \ + --hash=sha256:741e2c3b351ddf169a738da9f2c048608ff7f2c5cc02f1ebc6b118bb090d5d55 + # via requests +charset-normalizer==3.5.1 \ + --hash=sha256:00668ebb0609751758682eb0b5857e7c35b9f00e84dfdef062e103244ec94d45 \ + --hash=sha256:012a22b88a77ca2e59b98ac5889b0deb604147666032f45e6d6e217634d2550d \ + --hash=sha256:01e93745f7f219b703b60ba7afead36cfc4242782be5af484673fc500df12da5 \ + --hash=sha256:04368edf83514385ffc3e1cfd4546e595f4f1272dd23ba437a93a9cc3741d47b \ + --hash=sha256:0722590aabf9dc6a6c0343d523c05458fa2b5047dbe6302fd526bb570600753f \ + --hash=sha256:07ffd07412fc5d5e84cd8952acf9ff7e4ed7a708e69d1bada19d8ba91711353f \ + --hash=sha256:09a7bba9f739468c8e78c36a75c33768e53cb1959fc638f510454c14683f00d5 \ + --hash=sha256:0b2b1b3fa5670c127b246df1d0c059defd41f689a868a3b9d79df9b1cac42d22 \ + --hash=sha256:0c6dfb5ca6723eeed15aa8e564a014d69fcb8812f94eef11fe3631e0508199f5 \ + --hash=sha256:0d929fc574b4d6fd9e7c0f5c2ede8716a41911923aa7fa5fce38e0818aa4a1ac \ + --hash=sha256:13e3afe97712e8887cd516e960c63f0b93122971e5b5e4b2622fe7701771e838 \ + --hash=sha256:15f024313246a4ed976c60f440bb8d257815513a681d212ff74fd46f7d715a90 \ + --hash=sha256:195ce897c6153c0700078142cf8efe3e6454ca4cf4357499e4078dfd83396626 \ + --hash=sha256:19a3dd5aa73cef1c99687c4fc57db016a9c17104ae1185da88ba566a5d3bebe4 \ + --hash=sha256:1d1c7a53a6c2103925cdd6d7229f8c567379f211c869793df679f2e9f738c369 \ + --hash=sha256:1f5883d77fd409a261abb5dc8ccbe335720d798b1de4abb3b1d47ccbbc76b53b \ + --hash=sha256:21b82d8082f6f5e7f456ef0bd16323d08de1266efbfeb476e64b2a91d1471a4e \ + --hash=sha256:252d099029bcbea642f2a06c4ed5046bdf8b5a8150b64afa5e027e88b106e5ee \ + --hash=sha256:256dd4d85d9e4dc595e2bc983c980e73f62ddeb3165c58b4c3dfe78c5c8548c1 \ + --hash=sha256:26422d45fd13551cf564c58932f7d72b4f58b93b0fcf18c35ba6be12b46bb102 \ + --hash=sha256:2679de311c7946dde5d3b6f44941844133ff5c7cb86099c0061ab1e8901c20a8 \ + --hash=sha256:29880d17a8eb0b5cfdfd8944b468322928059aa35f1f5fa8ff22b149ec0b42f8 \ + --hash=sha256:2bced4061f000f7187254a02ad3433ae17eaf991747ceea2f478422590a5bba9 \ + --hash=sha256:2e9cf9253119d8e5d111f05d71626786fd3d6193817316eab1ca088cdb8593cf \ + --hash=sha256:2f06b7eae9dbe77fe1d644ca244dad508de8d302870a43f3c559b521270938a0 \ + --hash=sha256:2f293479cce755c75f1697e87c409b7ae4c555c7dfecb6e988ad13abba943031 \ + --hash=sha256:329fc3ccb63ad22d867d84c2adea759a64079a37ba4a343433b02c7a2816871e \ + --hash=sha256:343fb4f2821043bd87095f7b08a1a181febc8e36ac64212143bbfd0a0e1bc235 \ + --hash=sha256:3588e376b3ea2eea84976f67273d679f229e24c66dce7b82ae45aef04ff6e072 \ + --hash=sha256:35aea775dc2bd5f54cd84a1cd2696cc3207c479cb9cf0bd346f0d343e4300ddb \ + --hash=sha256:35fe081843b35aad20ffeccec3eeffbe637b15d14f3fb22cc1b59cd8ec17e93c \ + --hash=sha256:36047af20e17097c3bb9476c2b7655f2f7aa51322c0ba58c07695bedf755a950 \ + --hash=sha256:3617ac3cfd8b9888f145ad89dd6e692285834b0201c6074a5eeaad3fd4d668c2 \ + --hash=sha256:366ec70f5547c640d3ce1985722490f23faf4eb5216a7eeba78277490e78dacb \ + --hash=sha256:394fea06235c8543390050ed5f529187074b029fb027213f6c46ac11ab5d950e \ + --hash=sha256:3d27167433c0d5f18dc850f07d0b3816221984fecdc405d6c157a6f0b8f8e9e6 \ + --hash=sha256:3e5e1224c0a6a90e05843e07adfec669edebec17801c67072f51e59561d63c0b \ + --hash=sha256:41876ee62a3dddf48ff1121ad8f0798032aa03f2fd35f21f34a4cab14f18d8d2 \ + --hash=sha256:433c5a81eade63b47e522303bad236f59dba55ea6951746f5558355eeed8c75d \ + --hash=sha256:4582c27e8c889d64811987b5967fbd3ae0c823fe1fd933b543d55ac20bb475fa \ + --hash=sha256:485a0d363cafefcd2538a73c7c838daa2035f09b2c9f9b5e3133f80c6aeb84c2 \ + --hash=sha256:494b70049a4d69aec6e8137c13af4cf8db8c9f9820a1392ac293b0dd2987a818 \ + --hash=sha256:496846868fea80e479324862fa877f02411f2fd0f83b79ccee2607aa68b2a032 \ + --hash=sha256:4abdc5f9ad448c1ecbfae2974b820535d6bc6e7eef63babbab3d81cf46968c71 \ + --hash=sha256:4b599739b93b2cbeded49645ae3c8d1405c29ddfbceac1545c87a3f9580a9e96 \ + --hash=sha256:4bea7f8ebe90bbd7f0e4a2de42ca6924ba23e3e76418c408ff82f1d46fabd687 \ + --hash=sha256:4c4fb141a727957c93edfe5c32a26ceb6b5f6461d67146e2d39f51e16170bea8 \ + --hash=sha256:4c9548dc78002099910abaebc0a72ac58b7d30931869e0351c09b507dff4ece3 \ + --hash=sha256:4d26f14f041e83dd8edfd61f4cd4fa7285d31798b5bf1f28e70c367ba6c41d61 \ + --hash=sha256:4f298bdadb8f0b9e5672877f647d1be9373ef5320c9e2f049795e26cad28b6a9 \ + --hash=sha256:52ec005752a56ae79547a05c0139ca2501a0c866390b6115008456b9f0e7cde1 \ + --hash=sha256:55261ac0d2941c42f196dd576f543d87a8ee03cd6f5e30dfb4d807b2e3b9121a \ + --hash=sha256:56490c595a28b1bb27dfc583e816152a9767721ef58b2c03b13f954d2f707420 \ + --hash=sha256:58d3e12c88e0950bca850ae1f7c256055c097639c2edb9eb123af9807d8b15e4 \ + --hash=sha256:58d4aa13a59c969dbfdf9e6a9560e242cbfd9e8a8f50c2747714df1a423adf65 \ + --hash=sha256:59171c6e45bf07d0d5cab3b0bf81d945035530f6873398b3b531c31184d46663 \ + --hash=sha256:5b6d1386bf0096d26d3a863dc0a487a5b4eb9aa93cf5ba69683d29dde6b9d60f \ + --hash=sha256:5c0ea61a470e070686aa30892fed79e297d2c8d0ab46b8bcdf027d38c51da591 \ + --hash=sha256:5c84bec0ab5ae0c64bfe73a7d2adcb5ce73b467523fc27fd6a28ab2aa6cbe35a \ + --hash=sha256:5ca0555312ae2fe82715cada7fac375530c2f3349e1eaa1bcb33d0283ac79a18 \ + --hash=sha256:5d8531a6569d025f68e2321e7638fb7978f23db58e5f69f56913837aae03816e \ + --hash=sha256:5e2d0e146dcb57034f8b97dc58d2d512cb90aba253960ce449f695fec6a82c6f \ + --hash=sha256:5fc45d653ea8c9a20479167e11d4a0f8cb2fa3470737ab6f9c827532313187b7 \ + --hash=sha256:6117b84ea48435e5356dc737f5121485c30920ba43375fa7b434fd753df0eac3 \ + --hash=sha256:6199d5606e2bbf2b096cf64d03f8b6790c91081d5ac866b8e7bb6422738cc60c \ + --hash=sha256:62b55f6722735a6c472f88361cde6640608773d9443cebdbb51abf436a1fcdd3 \ + --hash=sha256:687c9ca3035544b113bea2055e180af96fb63c0c476e22a9180f51925186e7b7 \ + --hash=sha256:6b7430cf5728e68f6c462254009a6ef4086e1bea43cf2f57aa9c55fb4f50ff96 \ + --hash=sha256:6ba32c4d2abf1d2fe7cf27d280f4cca5664233b0f885549c7761719eb977f486 \ + --hash=sha256:6c9cdde8becb25a7fde49924511aa2644d6f8081cc8df8e9452724303348d8e3 \ + --hash=sha256:6df0ec430f9a831772c23ca5a224cba36517a58a84bb32c32bb59a9fa67c47f6 \ + --hash=sha256:6e2912d4babbc65196ac13c2f53468dc57fb8b9c25ef913e8c59ddf7c6dc0e1b \ + --hash=sha256:6e5e4d73d588ca5ed09df1b7dcd1b203d1df3c542e3f50d126c947d432b10731 \ + --hash=sha256:70055ff39b97c99e7ae40ea3e393fb62aa2e44dbd9b29f8d14f42fb0025c3959 \ + --hash=sha256:706bfd38730a5ac7a365793269a00f4e988178cec121391f4248d84ad8c972e9 \ + --hash=sha256:7235dc28fc6dd9d832ac7c7bce95367dedb85929f17368a0c2bee1e080b9acbf \ + --hash=sha256:774d157f112367ff4abd29019f38f023c24e00e56edc7829c20e358a5a913ad8 \ + --hash=sha256:77efcff2b23071c349402ac1066667a3d011f62398d81408c9b88ad991747c9e \ + --hash=sha256:789b8982559ae28dad2356519f841655756cdcd96616410590ae0b17454ee64f \ + --hash=sha256:7ac76cf9afd34929d76eb7fcb63be476a4853d8a96f0dcf2d0db68a0cbdf9885 \ + --hash=sha256:7c0c10730342b0c9b35dd1d619beb8214e520bd96a1f870f452680b238aab3e0 \ + --hash=sha256:823f82903d189af463d7df250ef1f7f696f3cee08cc8d91deb565e8d425f6506 \ + --hash=sha256:838648accb3a7fd9803fd45c87bce8509648eb0c11bc34e216141300977244f2 \ + --hash=sha256:854066be00447fa8de2ccbbe893e2ffc4b123ef16d897af794c1e18bd4a714b0 \ + --hash=sha256:85d5855daafc240cc045c026d7a15fd198a09b0fc8ff6f5ecbb5297b509cb11e \ + --hash=sha256:85de3134b5379856e323ba37c19c9256d39425f7b76a63af52b09fb4664c2e8f \ + --hash=sha256:87e4f41d375c0b9be2fb5251aee4b8a689169e134535aed81bf085c3b647451e \ + --hash=sha256:88ca277405c2d3b71c4e1c2ee0e7966e807bcba86a69d11e19ba199d18ae4491 \ + --hash=sha256:88e85ab89cb822c1e635f51d6d32e488f94e002e70e2f492bdb8b945543f345a \ + --hash=sha256:8ac8c94b6539074e0f40899301273ac8402b9b3e01c7b7ba269ff30340aaaf20 \ + --hash=sha256:8fe532b3c966d1fb794e0698e4589d0444017ae77fc0b31edea13c0e35bcc449 \ + --hash=sha256:9085f87b0e38a2b92b8923059b4e8789fe40d9279712d15dcc670048d77079af \ + --hash=sha256:90b7481fb62fbe172c558bc6fd1c4c98d82004a54a7551f20e11ac9bf0b8708c \ + --hash=sha256:92caef967d287a407085d61176fce4012b1dd62daed4eb6d5ceb26d3d2538712 \ + --hash=sha256:9362dd90aa7dab48c0054a21187791ccf05473f7dba5d92b8033ae62164675e7 \ + --hash=sha256:94d78ecec2605a8d0398b0f365d5f12a63248438516f5dac536a5eff7337df4a \ + --hash=sha256:94fbf1c0c6cc0d3d5e50f9a9313a8cdca90dd696d34b381cd1704f8c9e939f20 \ + --hash=sha256:950f23cb393f85543777b0433f082cddd25b51ab398eac7971146495679efe5f \ + --hash=sha256:96eefc178f8636b9c760c5829345307fd81cfae9ab1e80997dbddeb0f54ee9a3 \ + --hash=sha256:96fef3e886d6a9874b14f27fc193fbdc69d5d8035783d86aa4e1cea594e695f9 \ + --hash=sha256:977cdbd483a9cff38179bea4fd754289a6f2195c7abd414aba85410b3e66cc5e \ + --hash=sha256:978eab16f55b4ab2c2a745be9a0a840bf8f09a7f227d9c76eb30214d078865a5 \ + --hash=sha256:994e883d17c559cdfd38c84003c8b27d25424a1077272a17e7cd27bfe0bf57b2 \ + --hash=sha256:9ac4444d8d4fd4c4bd08bf451ed3167aa9e7ec6cdb41b648794f1d1103652e36 \ + --hash=sha256:9b5db6052055d34d41230fb78d7c439c23dc536a9896f6cb039e8dd92cfc1263 \ + --hash=sha256:9d9a0dc7cbe9bec24c3f767c9122c41fe5a1bc43f47cd099d00d393e09769de4 \ + --hash=sha256:9dbdd9205662134957cf0c324f639bdc5031c0ca056e2369e238db75187c0f11 \ + --hash=sha256:9eea3ab2597a5e65fe65296e2d6a84570845a6b55532d90333d740d48bbc850a \ + --hash=sha256:a2028475ba855475b8b4d3cfeb4994269c967aea8b9892dfba907f4263a863a3 \ + --hash=sha256:a3a370082ce34d0612f421e15fe011c53bb1feff21a26d06ad4fb244dab5a375 \ + --hash=sha256:a545775cfe815855ea32d7c27731d79da358ef2055b4a25830231b1622dd18aa \ + --hash=sha256:a5cbd90ecf0fc62e64726917ad083b73001f0563657a87ec3c0b504e277dc90d \ + --hash=sha256:a6d095662e73e74f0a49988e0593373e243e3a52e27bfeea0a859e88acf4a0f5 \ + --hash=sha256:a6dac12ff6b846103483683f60c5f8fee205121adc58ffd87e90a90a3af69e99 \ + --hash=sha256:a951ad59cad9145664a730d3036b40b844e74d2d3683da40111463cd3a83845d \ + --hash=sha256:aa1099b956fb795e686d073568f6dc002a0bb89765ea6d5b055dd7d9bf1b116c \ + --hash=sha256:aa2bb0b37202dca27175591f761108b5d34096ade1191ffe4808bdf6b1571488 \ + --hash=sha256:aae2ee51122d3ae968a3837d97dc24a0aeebb0dea23694422cd172bd30017cd6 \ + --hash=sha256:ab743e9bc90c1f73552ec33e10e3331315acd2c397b36065b591b0181de533cc \ + --hash=sha256:ac00177c4831ffa650f8609e4bdddd5fe09c03b1c0c47acece7e6ea20421598b \ + --hash=sha256:ac13b004224fb341e1e25a1ed5e19d32f57cdb2a403e01f003b46f051a550f6f \ + --hash=sha256:acaf604462bf330b0d07e7a07c1d6e4adac79e5fb13e9c5140590542cafacc00 \ + --hash=sha256:ae31a1a1db2ee6cc2942fccaf695c934bc7f3db9f2133a3fef1f367cf1a4ab10 \ + --hash=sha256:ae4a097991662cd4fff0ddc74e0fe7874f82e00042fa0ea00855645ed0c79598 \ + --hash=sha256:aea996a6aba25260827c9ea511d1addfde2da9eb686ac961838509086188b7e6 \ + --hash=sha256:b39b69b347e5e47a3b5b8cfc005c68c1ba347474e3960236c4944a8ecd174962 \ + --hash=sha256:b54e7e13267d49ffbfe68e25b3cbd774dab38fa37238f71265e91b36146eb21c \ + --hash=sha256:b9af956078716df40d985fb0dfeb2c2120c5ca92ba4ff4b388acfd01cdc14d08 \ + --hash=sha256:ba2f37ee79e6338845261a3c5b1784e5d1acdff2c0785b284f1b633033d136ab \ + --hash=sha256:ba501e667c17d8411f98e67a022d9604ef179aff0e459b7e292c796837c13573 \ + --hash=sha256:baf3775a2635e5a11fbd5e4e64ee69c7e86875d224a5c72aca4c141064589a90 \ + --hash=sha256:bb57753e36e4855b8ca375069482250a6246372331a3e4f3407eaebb007443f5 \ + --hash=sha256:bd6c173f04743d483881bffa1478d5a4624475b8cd1d2194956a75548e191c18 \ + --hash=sha256:be47f99644b208bff7766314013f9acf57b056b04191d570d68ad14022cf5b1d \ + --hash=sha256:c010f5581d9c612804cc59fcf7b524b707fbcb72828551237ab545bb5c7034af \ + --hash=sha256:c1dcc36dcb96abc02236e182d17e0f71430152a6c2c7447421da2d2dc144edea \ + --hash=sha256:c428c6c31eb5f4277d7f8eccaf767fbd548ddd5ce3c8b4f4cbbfab3d96b5904c \ + --hash=sha256:c658c50ac0c98cd755a2dd50b7977d3bca7df401dcc47fbdfa87db53ef7d4e8b \ + --hash=sha256:c71fb0d56c920c269cd3e2e3fe7c610e3f1fdb21a6ce60efa6430ff63676cea6 \ + --hash=sha256:c7b742bf31c88566b4bb6335a7f393bb322e580b6bb98df7bd0c25e6e3519ce8 \ + --hash=sha256:cc0329df4caaceb950d2f580b5ac716a377f7059624a0bafaeaf8a218c6ed774 \ + --hash=sha256:cc5d36d96478aa9c60654bd932525bf32964c62a7281eafdf16d85003a8d6004 \ + --hash=sha256:ce854f5f478050ade5a238731c4ca985a7d3b3cb53ff600a9b5c3b689b5f0a7a \ + --hash=sha256:ced3fdd71aaa83ce593746c2edb42b7a59cb4c19c8b5c407781c72e493aae55a \ + --hash=sha256:cee5dd7c6fb5dd52a0fe2a740f9bc6e3593f5f8b1788bde49de02086f30182b2 \ + --hash=sha256:cfa1c0cc3a8f9f53f1243a5a99ac36fd003880199383b37672e86ddda9cb07e2 \ + --hash=sha256:d1ee1e296209fdce05b81b663250eefa02213a2da7b41bf26f7829b8ba3545aa \ + --hash=sha256:d59b75732e9b6f27388e10c14b0259cc5f2e48c78627d185e6a177b58ad3cffe \ + --hash=sha256:d63600d620ad0064c3a748b950ac5ea38a80190e5498532efefa4b7b3f1da1f3 \ + --hash=sha256:dd732602a7009217f658d5863d12d79d373a4de0eebc111094bcdd3bb8e0a6cc \ + --hash=sha256:e06efa066f7dbadbc84ebc126a97c452a6451dfcf589d89d788484949e1cf795 \ + --hash=sha256:e199fb99720074809a7720f1c0b4d919eea8b87e88713e0f8f602f7bef543d9d \ + --hash=sha256:e4b018dc5a0eee4676e38fe84a47a427816c590b93b55d9025274ec4d6ffc2dc \ + --hash=sha256:e6621fb2a4988d6e53eedc455e5903e2679f3967b8acb3d639f1b63c14a2e893 \ + --hash=sha256:e71c909f353863b2b89c83de2ebed71ea6d0df8a6ef65a128193c5e650766bef \ + --hash=sha256:e90251c0c7bdd54a100a0dce3c07b7e637278c93af29dbf78ebb89a58c4bac7d \ + --hash=sha256:e9fbdce1e47394b09bc9f26ab117dfc8d6491977a11d86f592bb42c779db2fda \ + --hash=sha256:eb12fb2ba69ffa05f8695f61c69e591dc4b4a12ac3757ac8af8adb259bf56d17 \ + --hash=sha256:eda059b6bc8bc0812d626fd91a7ce01bf583df0a61296eff390fd94141a34e30 \ + --hash=sha256:f03ac127268b43ef4fe9e6ab6794a6794b49485a0cc0c1db79876d2f33f75bc7 \ + --hash=sha256:f298e218441525d3794428b4c8b8fb8662c6d3ea79925d4807ee6b9a96a3bca5 \ + --hash=sha256:f5542f9b941279d82d41eb0aa9f98eba36fe4df5c7086c651df7944935b37182 \ + --hash=sha256:f6f7deae3feb4edfa2efaf7c574fe88cbf055038a6abdb40188e4fff66d5699f \ + --hash=sha256:f9b1e28d0e8dbfa858abdba91d6b547beaf2df1a59bec6da6faae7b96a4991a9 \ + --hash=sha256:f9f8405c2c758532c74fed975dbee57be1f31a6e865c031870c79a6ed3212ada \ + --hash=sha256:fa48b1b63d639f9483e0633e092f5851e2348c352f1f9bb6c8182f87884ef876 \ + --hash=sha256:fb78f6e7fcd8ad785d28cd577168bc1aaee827b25bb8755638f694794ea98f0a \ + --hash=sha256:fbc597639158fd7c14d55e808718848319540f51b0e6746e3eefa59723a4a348 \ + --hash=sha256:fce8cbd4997efeb450bd298b54f755dcdff18d496f7a5ddbb4867c6d7c88fdc3 \ + --hash=sha256:fd0350afdc3aabd5576f60ea109228bd5538139713c7b094c5cd27c73a98bc6f \ + --hash=sha256:fd0a274c0e5f9a21565cd9d3dd749b61f96b7aa1e20a93aa1ba4029518f2e5c0 \ + --hash=sha256:fdb8a068947befafba9952162645dc2fecaeb400e64584829ed5e9b2fbe21a7f + # via requests +click==8.5.0 \ + --hash=sha256:255bc9599cf7748b4b1a446ccc735421bd08a2ae529a8b88597d3de5664ee360 \ + --hash=sha256:ba0d2089de75ea0310e2dde03160e6ca10009947fb95a182f9b54021bb272e34 + # via mkdocs +colorama==0.4.6 \ + --hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \ + --hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6 + # via mkdocs-material +ghp-import==2.1.0 \ + --hash=sha256:8337dd7b50877f163d4c0289bc1f1c7f127550241988d568c1db512c4324a619 \ + --hash=sha256:9c535c4c61193c2df8871222567d7fd7e5014d835f97dc7b7439069e2413d343 + # via mkdocs +idna==3.19 \ + --hash=sha256:5e0811a4383b21dc5838069f801c4fb62113b7447663d2530d2bd6e77b49bf15 \ + --hash=sha256:815e7be7a7806d54abb586dc943addc79e8b2ee16915059658cbeff4b1b43bf4 + # via requests +jinja2==3.1.6 \ + --hash=sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d \ + --hash=sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67 + # via + # mkdocs + # mkdocs-material +markdown==3.10.3 \ + --hash=sha256:3589362618f743188b4d955b874402bc814f4f83f544dc207719f4baa7d9c45f \ + --hash=sha256:fa6c92a00a4a3c98b22728c64a935ae1928250ae65058a6ded814d2cc29a4cea + # via + # mkdocs + # mkdocs-material + # pymdown-extensions +markupsafe==3.0.3 \ + --hash=sha256:0303439a41979d9e74d18ff5e2dd8c43ed6c6001fd40e5bf2e43f7bd9bbc523f \ + --hash=sha256:068f375c472b3e7acbe2d5318dea141359e6900156b5b2ba06a30b169086b91a \ + --hash=sha256:0bf2a864d67e76e5c9a34dc26ec616a66b9888e25e7b9460e1c76d3293bd9dbf \ + --hash=sha256:0db14f5dafddbb6d9208827849fad01f1a2609380add406671a26386cdf15a19 \ + --hash=sha256:0eb9ff8191e8498cca014656ae6b8d61f39da5f95b488805da4bb029cccbfbaf \ + --hash=sha256:0f4b68347f8c5eab4a13419215bdfd7f8c9b19f2b25520968adfad23eb0ce60c \ + --hash=sha256:1085e7fbddd3be5f89cc898938f42c0b3c711fdcb37d75221de2666af647c175 \ + --hash=sha256:116bb52f642a37c115f517494ea5feb03889e04df47eeff5b130b1808ce7c219 \ + --hash=sha256:12c63dfb4a98206f045aa9563db46507995f7ef6d83b2f68eda65c307c6829eb \ + --hash=sha256:133a43e73a802c5562be9bbcd03d090aa5a1fe899db609c29e8c8d815c5f6de6 \ + --hash=sha256:1353ef0c1b138e1907ae78e2f6c63ff67501122006b0f9abad68fda5f4ffc6ab \ + --hash=sha256:15d939a21d546304880945ca1ecb8a039db6b4dc49b2c5a400387cdae6a62e26 \ + --hash=sha256:177b5253b2834fe3678cb4a5f0059808258584c559193998be2601324fdeafb1 \ + --hash=sha256:1872df69a4de6aead3491198eaf13810b565bdbeec3ae2dc8780f14458ec73ce \ + --hash=sha256:1b4b79e8ebf6b55351f0d91fe80f893b4743f104bff22e90697db1590e47a218 \ + --hash=sha256:1b52b4fb9df4eb9ae465f8d0c228a00624de2334f216f178a995ccdcf82c4634 \ + --hash=sha256:1ba88449deb3de88bd40044603fafffb7bc2b055d626a330323a9ed736661695 \ + --hash=sha256:1cc7ea17a6824959616c525620e387f6dd30fec8cb44f649e31712db02123dad \ + --hash=sha256:218551f6df4868a8d527e3062d0fb968682fe92054e89978594c28e642c43a73 \ + --hash=sha256:26a5784ded40c9e318cfc2bdb30fe164bdb8665ded9cd64d500a34fb42067b1c \ + --hash=sha256:2713baf880df847f2bece4230d4d094280f4e67b1e813eec43b4c0e144a34ffe \ + --hash=sha256:2a15a08b17dd94c53a1da0438822d70ebcd13f8c3a95abe3a9ef9f11a94830aa \ + --hash=sha256:2f981d352f04553a7171b8e44369f2af4055f888dfb147d55e42d29e29e74559 \ + --hash=sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa \ + --hash=sha256:3524b778fe5cfb3452a09d31e7b5adefeea8c5be1d43c4f810ba09f2ceb29d37 \ + --hash=sha256:3537e01efc9d4dccdf77221fb1cb3b8e1a38d5428920e0657ce299b20324d758 \ + --hash=sha256:35add3b638a5d900e807944a078b51922212fb3dedb01633a8defc4b01a3c85f \ + --hash=sha256:38664109c14ffc9e7437e86b4dceb442b0096dfe3541d7864d9cbe1da4cf36c8 \ + --hash=sha256:3a7e8ae81ae39e62a41ec302f972ba6ae23a5c5396c8e60113e9066ef893da0d \ + --hash=sha256:3b562dd9e9ea93f13d53989d23a7e775fdfd1066c33494ff43f5418bc8c58a5c \ + --hash=sha256:457a69a9577064c05a97c41f4e65148652db078a3a509039e64d3467b9e7ef97 \ + --hash=sha256:4bd4cd07944443f5a265608cc6aab442e4f74dff8088b0dfc8238647b8f6ae9a \ + --hash=sha256:4e885a3d1efa2eadc93c894a21770e4bc67899e3543680313b09f139e149ab19 \ + --hash=sha256:4faffd047e07c38848ce017e8725090413cd80cbc23d86e55c587bf979e579c9 \ + --hash=sha256:509fa21c6deb7a7a273d629cf5ec029bc209d1a51178615ddf718f5918992ab9 \ + --hash=sha256:5678211cb9333a6468fb8d8be0305520aa073f50d17f089b5b4b477ea6e67fdc \ + --hash=sha256:591ae9f2a647529ca990bc681daebdd52c8791ff06c2bfa05b65163e28102ef2 \ + --hash=sha256:5a7d5dc5140555cf21a6fefbdbf8723f06fcd2f63ef108f2854de715e4422cb4 \ + --hash=sha256:69c0b73548bc525c8cb9a251cddf1931d1db4d2258e9599c28c07ef3580ef354 \ + --hash=sha256:6b5420a1d9450023228968e7e6a9ce57f65d148ab56d2313fcd589eee96a7a50 \ + --hash=sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698 \ + --hash=sha256:729586769a26dbceff69f7a7dbbf59ab6572b99d94576a5592625d5b411576b9 \ + --hash=sha256:77f0643abe7495da77fb436f50f8dab76dbc6e5fd25d39589a0f1fe6548bfa2b \ + --hash=sha256:795e7751525cae078558e679d646ae45574b47ed6e7771863fcc079a6171a0fc \ + --hash=sha256:7be7b61bb172e1ed687f1754f8e7484f1c8019780f6f6b0786e76bb01c2ae115 \ + --hash=sha256:7c3fb7d25180895632e5d3148dbdc29ea38ccb7fd210aa27acbd1201a1902c6e \ + --hash=sha256:7e68f88e5b8799aa49c85cd116c932a1ac15caaa3f5db09087854d218359e485 \ + --hash=sha256:83891d0e9fb81a825d9a6d61e3f07550ca70a076484292a70fde82c4b807286f \ + --hash=sha256:8485f406a96febb5140bfeca44a73e3ce5116b2501ac54fe953e488fb1d03b12 \ + --hash=sha256:8709b08f4a89aa7586de0aadc8da56180242ee0ada3999749b183aa23df95025 \ + --hash=sha256:8f71bc33915be5186016f675cd83a1e08523649b0e33efdb898db577ef5bb009 \ + --hash=sha256:915c04ba3851909ce68ccc2b8e2cd691618c4dc4c4232fb7982bca3f41fd8c3d \ + --hash=sha256:949b8d66bc381ee8b007cd945914c721d9aba8e27f71959d750a46f7c282b20b \ + --hash=sha256:94c6f0bb423f739146aec64595853541634bde58b2135f27f61c1ffd1cd4d16a \ + --hash=sha256:9a1abfdc021a164803f4d485104931fb8f8c1efd55bc6b748d2f5774e78b62c5 \ + --hash=sha256:9b79b7a16f7fedff2495d684f2b59b0457c3b493778c9eed31111be64d58279f \ + --hash=sha256:a320721ab5a1aba0a233739394eb907f8c8da5c98c9181d1161e77a0c8e36f2d \ + --hash=sha256:a4afe79fb3de0b7097d81da19090f4df4f8d3a2b3adaa8764138aac2e44f3af1 \ + --hash=sha256:ad2cf8aa28b8c020ab2fc8287b0f823d0a7d8630784c31e9ee5edea20f406287 \ + --hash=sha256:b8512a91625c9b3da6f127803b166b629725e68af71f8184ae7e7d54686a56d6 \ + --hash=sha256:bc51efed119bc9cfdf792cdeaa4d67e8f6fcccab66ed4bfdd6bde3e59bfcbb2f \ + --hash=sha256:bdc919ead48f234740ad807933cdf545180bfbe9342c2bb451556db2ed958581 \ + --hash=sha256:bdd37121970bfd8be76c5fb069c7751683bdf373db1ed6c010162b2a130248ed \ + --hash=sha256:be8813b57049a7dc738189df53d69395eba14fb99345e0a5994914a3864c8a4b \ + --hash=sha256:c0c0b3ade1c0b13b936d7970b1d37a57acde9199dc2aecc4c336773e1d86049c \ + --hash=sha256:c47a551199eb8eb2121d4f0f15ae0f923d31350ab9280078d1e5f12b249e0026 \ + --hash=sha256:c4ffb7ebf07cfe8931028e3e4c85f0357459a3f9f9490886198848f4fa002ec8 \ + --hash=sha256:ccfcd093f13f0f0b7fdd0f198b90053bf7b2f02a3927a30e63f3ccc9df56b676 \ + --hash=sha256:d2ee202e79d8ed691ceebae8e0486bd9a2cd4794cec4824e1c99b6f5009502f6 \ + --hash=sha256:d53197da72cc091b024dd97249dfc7794d6a56530370992a5e1a08983ad9230e \ + --hash=sha256:d6dd0be5b5b189d31db7cda48b91d7e0a9795f31430b7f271219ab30f1d3ac9d \ + --hash=sha256:d88b440e37a16e651bda4c7c2b930eb586fd15ca7406cb39e211fcff3bf3017d \ + --hash=sha256:de8a88e63464af587c950061a5e6a67d3632e36df62b986892331d4620a35c01 \ + --hash=sha256:df2449253ef108a379b8b5d6b43f4b1a8e81a061d6537becd5582fba5f9196d7 \ + --hash=sha256:e1c1493fb6e50ab01d20a22826e57520f1284df32f2d8601fdd90b6304601419 \ + --hash=sha256:e1cf1972137e83c5d4c136c43ced9ac51d0e124706ee1c8aa8532c1287fa8795 \ + --hash=sha256:e2103a929dfa2fcaf9bb4e7c091983a49c9ac3b19c9061b6d5427dd7d14d81a1 \ + --hash=sha256:e56b7d45a839a697b5eb268c82a71bd8c7f6c94d6fd50c3d577fa39a9f1409f5 \ + --hash=sha256:e8afc3f2ccfa24215f8cb28dcf43f0113ac3c37c2f0f0806d8c70e4228c5cf4d \ + --hash=sha256:e8fc20152abba6b83724d7ff268c249fa196d8259ff481f3b1476383f8f24e42 \ + --hash=sha256:eaa9599de571d72e2daf60164784109f19978b327a3910d3e9de8c97b5b70cfe \ + --hash=sha256:ec15a59cf5af7be74194f7ab02d0f59a62bdcf1a537677ce67a2537c9b87fcda \ + --hash=sha256:f190daf01f13c72eac4efd5c430a8de82489d9cff23c364c3ea822545032993e \ + --hash=sha256:f34c41761022dd093b4b6896d4810782ffbabe30f2d443ff5f083e0cbbb8c737 \ + --hash=sha256:f3e98bb3798ead92273dc0e5fd0f31ade220f59a266ffd8a4f6065e0a3ce0523 \ + --hash=sha256:f42d0984e947b8adf7dd6dde396e720934d12c506ce84eea8476409563607591 \ + --hash=sha256:f71a396b3bf33ecaa1626c255855702aca4d3d9fea5e051b41ac59a9c1c41edc \ + --hash=sha256:f9e130248f4462aaa8e2552d547f36ddadbeaa573879158d721bbd33dfe4743a \ + --hash=sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50 + # via + # jinja2 + # mkdocs +mergedeep==1.3.4 \ + --hash=sha256:0096d52e9dad9939c3d975a774666af186eda617e6ca84df4c94dec30004f2a8 \ + --hash=sha256:70775750742b25c0d8f36c55aed03d24c3384d17c951b3175d898bd778ef0307 + # via + # mkdocs + # mkdocs-get-deps +mkdocs==1.6.1 \ + --hash=sha256:7b432f01d928c084353ab39c57282f29f92136665bdd6abf7c1ec8d822ef86f2 \ + --hash=sha256:db91759624d1647f3f34aa0c3f327dd2601beae39a366d6e064c03468d35c20e + # via + # -r requirements-docs.in + # mkdocs-material +mkdocs-get-deps==0.2.2 \ + --hash=sha256:8ee8d5f316cdbbb2834bc1df6e69c08fe769a83e040060de26d3c19fad3599a1 \ + --hash=sha256:e7878cbeac04860b8b5e0ca31d3abad3df9411a75a32cde82f8e44b6c16ff650 + # via mkdocs +mkdocs-material==9.7.7 \ + --hash=sha256:8ea9bb1737a5b524a5f9dcf2e1b4ebda8274ae3008aa7845720a97083bef708f \ + --hash=sha256:c0649c065b1b0512d60aad8c10f947f8e455284475239b364b610f2deb4d0855 + # via -r requirements-docs.in +mkdocs-material-extensions==1.3.1 \ + --hash=sha256:10c9511cea88f568257f960358a467d12b970e1f7b2c0e5fb2bb48cab1928443 \ + --hash=sha256:adff8b62700b25cb77b53358dad940f3ef973dd6db797907c49e3c2ef3ab4e31 + # via mkdocs-material +packaging==26.3 \ + --hash=sha256:94edc256424af38762eb31306eed28beb9f0efc50a8837492c9d6fd6004aed79 \ + --hash=sha256:d7193f7c8e4e93f444fde0262bf90af30e16fa0ad0ad44cb553c87339b23cd1c + # via mkdocs +paginate==0.5.7 \ + --hash=sha256:22bd083ab41e1a8b4f3690544afb2c60c25e5c9a63a30fa2f483f6c60c8e5945 \ + --hash=sha256:b885e2af73abcf01d9559fd5216b57ef722f8c42affbb63942377668e35c7591 + # via mkdocs-material +pathspec==1.1.1 \ + --hash=sha256:17db5ecd524104a120e173814c90367a96a98d07c45b2e10c2f3919fff91bf5a \ + --hash=sha256:a00ce642f577bf7f473932318056212bc4f8bfdf53128c78bbd5af0b9b20b189 + # via mkdocs +platformdirs==4.11.8 \ + --hash=sha256:52f2f181bbfde907966932cc8312d967d02976422d66d537ea16092b8e291081 \ + --hash=sha256:f23abafea7dd4276d1f29104b83598d7dcc567cafd07c9c951e66665645437fc + # via mkdocs-get-deps +pygments==2.21.0 \ + --hash=sha256:2363c69b61c4a97c838da3b130dcd6468f4848992b21a82f2a63ec34377137d9 \ + --hash=sha256:610ca751c9bc2492b38eb9a38a7fbc93edbbb2d7182edaf34e66ae493dee5c8c + # via mkdocs-material +pymdown-extensions==11.0.2 \ + --hash=sha256:259910762019732caa1dfd76f3faa62c59f191d46573e80bcb1d13c0f675bbe5 \ + --hash=sha256:9506fcbe66fa355a775b768084334238dd6805020ac4b92bea0c0dda6f8f223d + # via mkdocs-material +python-dateutil==2.9.0.post0 \ + --hash=sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3 \ + --hash=sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427 + # via ghp-import +pyyaml==6.0.3 \ + --hash=sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c \ + --hash=sha256:0150219816b6a1fa26fb4699fb7daa9caf09eb1999f3b70fb6e786805e80375a \ + --hash=sha256:02893d100e99e03eda1c8fd5c441d8c60103fd175728e23e431db1b589cf5ab3 \ + --hash=sha256:02ea2dfa234451bbb8772601d7b8e426c2bfa197136796224e50e35a78777956 \ + --hash=sha256:0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6 \ + --hash=sha256:10892704fc220243f5305762e276552a0395f7beb4dbf9b14ec8fd43b57f126c \ + --hash=sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65 \ + --hash=sha256:1d37d57ad971609cf3c53ba6a7e365e40660e3be0e5175fa9f2365a379d6095a \ + --hash=sha256:1ebe39cb5fc479422b83de611d14e2c0d3bb2a18bbcb01f229ab3cfbd8fee7a0 \ + --hash=sha256:214ed4befebe12df36bcc8bc2b64b396ca31be9304b8f59e25c11cf94a4c033b \ + --hash=sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1 \ + --hash=sha256:22ba7cfcad58ef3ecddc7ed1db3409af68d023b7f940da23c6c2a1890976eda6 \ + --hash=sha256:27c0abcb4a5dac13684a37f76e701e054692a9b2d3064b70f5e4eb54810553d7 \ + --hash=sha256:28c8d926f98f432f88adc23edf2e6d4921ac26fb084b028c733d01868d19007e \ + --hash=sha256:2e71d11abed7344e42a8849600193d15b6def118602c4c176f748e4583246007 \ + --hash=sha256:34d5fcd24b8445fadc33f9cf348c1047101756fd760b4dacb5c3e99755703310 \ + --hash=sha256:37503bfbfc9d2c40b344d06b2199cf0e96e97957ab1c1b546fd4f87e53e5d3e4 \ + --hash=sha256:3c5677e12444c15717b902a5798264fa7909e41153cdf9ef7ad571b704a63dd9 \ + --hash=sha256:3ff07ec89bae51176c0549bc4c63aa6202991da2d9a6129d7aef7f1407d3f295 \ + --hash=sha256:41715c910c881bc081f1e8872880d3c650acf13dfa8214bad49ed4cede7c34ea \ + --hash=sha256:418cf3f2111bc80e0933b2cd8cd04f286338bb88bdc7bc8e6dd775ebde60b5e0 \ + --hash=sha256:44edc647873928551a01e7a563d7452ccdebee747728c1080d881d68af7b997e \ + --hash=sha256:4a2e8cebe2ff6ab7d1050ecd59c25d4c8bd7e6f400f5f82b96557ac0abafd0ac \ + --hash=sha256:4ad1906908f2f5ae4e5a8ddfce73c320c2a1429ec52eafd27138b7f1cbe341c9 \ + --hash=sha256:501a031947e3a9025ed4405a168e6ef5ae3126c59f90ce0cd6f2bfc477be31b7 \ + --hash=sha256:5190d403f121660ce8d1d2c1bb2ef1bd05b5f68533fc5c2ea899bd15f4399b35 \ + --hash=sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb \ + --hash=sha256:5cf4e27da7e3fbed4d6c3d8e797387aaad68102272f8f9752883bc32d61cb87b \ + --hash=sha256:5e0b74767e5f8c593e8c9b5912019159ed0533c70051e9cce3e8b6aa699fcd69 \ + --hash=sha256:5ed875a24292240029e4483f9d4a4b8a1ae08843b9c54f43fcc11e404532a8a5 \ + --hash=sha256:5fcd34e47f6e0b794d17de1b4ff496c00986e1c83f7ab2fb8fcfe9616ff7477b \ + --hash=sha256:5fdec68f91a0c6739b380c83b951e2c72ac0197ace422360e6d5a959d8d97b2c \ + --hash=sha256:6344df0d5755a2c9a276d4473ae6b90647e216ab4757f8426893b5dd2ac3f369 \ + --hash=sha256:64386e5e707d03a7e172c0701abfb7e10f0fb753ee1d773128192742712a98fd \ + --hash=sha256:652cb6edd41e718550aad172851962662ff2681490a8a711af6a4d288dd96824 \ + --hash=sha256:66291b10affd76d76f54fad28e22e51719ef9ba22b29e1d7d03d6777a9174198 \ + --hash=sha256:66e1674c3ef6f541c35191caae2d429b967b99e02040f5ba928632d9a7f0f065 \ + --hash=sha256:6adc77889b628398debc7b65c073bcb99c4a0237b248cacaf3fe8a557563ef6c \ + --hash=sha256:79005a0d97d5ddabfeeea4cf676af11e647e41d81c9a7722a193022accdb6b7c \ + --hash=sha256:7c6610def4f163542a622a73fb39f534f8c101d690126992300bf3207eab9764 \ + --hash=sha256:7f047e29dcae44602496db43be01ad42fc6f1cc0d8cd6c83d342306c32270196 \ + --hash=sha256:8098f252adfa6c80ab48096053f512f2321f0b998f98150cea9bd23d83e1467b \ + --hash=sha256:850774a7879607d3a6f50d36d04f00ee69e7fc816450e5f7e58d7f17f1ae5c00 \ + --hash=sha256:8d1fab6bb153a416f9aeb4b8763bc0f22a5586065f86f7664fc23339fc1c1fac \ + --hash=sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8 \ + --hash=sha256:8dc52c23056b9ddd46818a57b78404882310fb473d63f17b07d5c40421e47f8e \ + --hash=sha256:9149cad251584d5fb4981be1ecde53a1ca46c891a79788c0df828d2f166bda28 \ + --hash=sha256:93dda82c9c22deb0a405ea4dc5f2d0cda384168e466364dec6255b293923b2f3 \ + --hash=sha256:96b533f0e99f6579b3d4d4995707cf36df9100d67e0c8303a0c55b27b5f99bc5 \ + --hash=sha256:9c57bb8c96f6d1808c030b1687b9b5fb476abaa47f0db9c0101f5e9f394e97f4 \ + --hash=sha256:9c7708761fccb9397fe64bbc0395abcae8c4bf7b0eac081e12b809bf47700d0b \ + --hash=sha256:9f3bfb4965eb874431221a3ff3fdcddc7e74e3b07799e0e84ca4a0f867d449bf \ + --hash=sha256:a33284e20b78bd4a18c8c2282d549d10bc8408a2a7ff57653c0cf0b9be0afce5 \ + --hash=sha256:a80cb027f6b349846a3bf6d73b5e95e782175e52f22108cfa17876aaeff93702 \ + --hash=sha256:b30236e45cf30d2b8e7b3e85881719e98507abed1011bf463a8fa23e9c3e98a8 \ + --hash=sha256:b3bc83488de33889877a0f2543ade9f70c67d66d9ebb4ac959502e12de895788 \ + --hash=sha256:b865addae83924361678b652338317d1bd7e79b1f4596f96b96c77a5a34b34da \ + --hash=sha256:b8bb0864c5a28024fac8a632c443c87c5aa6f215c0b126c449ae1a150412f31d \ + --hash=sha256:ba1cc08a7ccde2d2ec775841541641e4548226580ab850948cbfda66a1befcdc \ + --hash=sha256:bdb2c67c6c1390b63c6ff89f210c8fd09d9a1217a465701eac7316313c915e4c \ + --hash=sha256:c1ff362665ae507275af2853520967820d9124984e0f7466736aea23d8611fba \ + --hash=sha256:c2514fceb77bc5e7a2f7adfaa1feb2fb311607c9cb518dbc378688ec73d8292f \ + --hash=sha256:c3355370a2c156cffb25e876646f149d5d68f5e0a3ce86a5084dd0b64a994917 \ + --hash=sha256:c458b6d084f9b935061bc36216e8a69a7e293a2f1e68bf956dcd9e6cbcd143f5 \ + --hash=sha256:d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26 \ + --hash=sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f \ + --hash=sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b \ + --hash=sha256:eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be \ + --hash=sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c \ + --hash=sha256:efd7b85f94a6f21e4932043973a7ba2613b059c4a000551892ac9f1d11f5baf3 \ + --hash=sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6 \ + --hash=sha256:fa160448684b4e94d80416c0fa4aac48967a969efe22931448d853ada8baf926 \ + --hash=sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0 + # via + # mkdocs + # mkdocs-get-deps + # pymdown-extensions + # pyyaml-env-tag +pyyaml-env-tag==1.1 \ + --hash=sha256:17109e1a528561e32f026364712fee1264bc2ea6715120891174ed1b980d2e04 \ + --hash=sha256:2eb38b75a2d21ee0475d6d97ec19c63287a7e140231e4214969d0eac923cd7ff + # via mkdocs +requests==2.34.2 \ + --hash=sha256:2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0 \ + --hash=sha256:f288924cae4e29463698d6d60bc6a4da69c89185ad1e0bcc4104f584e960b9ed + # via mkdocs-material +six==1.17.0 \ + --hash=sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274 \ + --hash=sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81 + # via python-dateutil +urllib3==2.7.0 \ + --hash=sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c \ + --hash=sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897 + # via requests +watchdog==6.0.0 \ + --hash=sha256:07df1fdd701c5d4c8e55ef6cf55b8f0120fe1aef7ef39a1c6fc6bc2e606d517a \ + --hash=sha256:20ffe5b202af80ab4266dcd3e91aae72bf2da48c0d33bdb15c66658e685e94e2 \ + --hash=sha256:212ac9b8bf1161dc91bd09c048048a95ca3a4c4f5e5d4a7d1b1a7d5752a7f96f \ + --hash=sha256:2cce7cfc2008eb51feb6aab51251fd79b85d9894e98ba847408f662b3395ca3c \ + --hash=sha256:490ab2ef84f11129844c23fb14ecf30ef3d8a6abafd3754a6f75ca1e6654136c \ + --hash=sha256:6eb11feb5a0d452ee41f824e271ca311a09e250441c262ca2fd7ebcf2461a06c \ + --hash=sha256:6f10cb2d5902447c7d0da897e2c6768bca89174d0c6e1e30abec5421af97a5b0 \ + --hash=sha256:7607498efa04a3542ae3e05e64da8202e58159aa1fa4acddf7678d34a35d4f13 \ + --hash=sha256:76aae96b00ae814b181bb25b1b98076d5fc84e8a53cd8885a318b42b6d3a5134 \ + --hash=sha256:7a0e56874cfbc4b9b05c60c8a1926fedf56324bb08cfbc188969777940aef3aa \ + --hash=sha256:82dc3e3143c7e38ec49d61af98d6558288c415eac98486a5c581726e0737c00e \ + --hash=sha256:9041567ee8953024c83343288ccc458fd0a2d811d6a0fd68c4c22609e3490379 \ + --hash=sha256:90c8e78f3b94014f7aaae121e6b909674df5b46ec24d6bebc45c44c56729af2a \ + --hash=sha256:9513f27a1a582d9808cf21a07dae516f0fab1cf2d7683a742c498b93eedabb11 \ + --hash=sha256:9ddf7c82fda3ae8e24decda1338ede66e1c99883db93711d8fb941eaa2d8c282 \ + --hash=sha256:a175f755fc2279e0b7312c0035d52e27211a5bc39719dd529625b1930917345b \ + --hash=sha256:a1914259fa9e1454315171103c6a30961236f508b9b623eae470268bbcc6a22f \ + --hash=sha256:afd0fe1b2270917c5e23c2a65ce50c2a4abb63daafb0d419fde368e272a76b7c \ + --hash=sha256:bc64ab3bdb6a04d69d4023b29422170b74681784ffb9463ed4870cf2f3e66112 \ + --hash=sha256:bdd4e6f14b8b18c334febb9c4425a878a2ac20efd1e0b231978e7b150f92a948 \ + --hash=sha256:c7ac31a19f4545dd92fc25d200694098f42c9a8e391bc00bdd362c5736dbf881 \ + --hash=sha256:c7c15dda13c4eb00d6fb6fc508b3c0ed88b9d5d374056b239c4ad1611125c860 \ + --hash=sha256:c897ac1b55c5a1461e16dae288d22bb2e412ba9807df8397a635d88f671d36c3 \ + --hash=sha256:cbafb470cf848d93b5d013e2ecb245d4aa1c8fd0504e863ccefa32445359d680 \ + --hash=sha256:d1cdb490583ebd691c012b3d6dae011000fe42edb7a82ece80965b42abd61f26 \ + --hash=sha256:e3df4cbb9a450c6d49318f6d14f4bbc80d763fa587ba46ec86f99f9e6876bb26 \ + --hash=sha256:e6439e374fc012255b4ec786ae3c4bc838cd7309a540e5fe0952d03687d8804e \ + --hash=sha256:e6f0e77c9417e7cd62af82529b10563db3423625c5fce018430b249bf977f9e8 \ + --hash=sha256:e7631a77ffb1f7d2eefa4445ebbee491c720a5661ddf6df3498ebecae5ed375c \ + --hash=sha256:ef810fbf7b781a5a593894e4f439773830bdecb885e6880d957d5b9382a960d2 + # via mkdocs diff --git a/scripts/__pycache__/build_docs.cpython-314.pyc b/scripts/__pycache__/build_docs.cpython-314.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8985460a72d83967d0ffc11aeedcef2eb59dffa8 GIT binary patch literal 6212 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 str: + """The anchor both GitHub and the site's toc extension derive from + a heading: lowercase, punctuation dropped, spaces to hyphens.""" + text = re.sub(r"[`*_]", "", text).lower() + text = re.sub(r"[^\w\s-]", "", text) + return re.sub(r"\s+", "-", text.strip()) + + +def rewrite_links(body: str, pages: dict[str, str]) -> str: + def fix(m: re.Match[str]) -> str: + target = m.group(1) + if target.startswith(("#", "http://", "https://", "mailto:")): + return m.group(0) + path, _, fragment = target.partition("#") + path = path.lstrip("./") + suffix = f"#{fragment}" if fragment else "" + if path in pages: + return f"]({pages[path]}{suffix})" + for src, dst in ASSET_DIRS.items(): + if path.startswith(src + "/"): + return f"]({dst}/{path[len(src) + 1:]})" + kind = "tree" if path.endswith("/") or "." not in path.rsplit("/", 1)[-1] else "blob" + return f"]({REPO_URL}/{kind}/main/{path}{suffix})" + return LINK.sub(fix, body) + + +def build(out: Path) -> list[str]: + if out.exists(): + shutil.rmtree(out) + out.mkdir(parents=True) + pages = dict(PAGES) + written = [] + for src, dst in PAGES: + (out / dst).write_text(rewrite_links((ROOT / src).read_text(), pages)) + written.append(dst) + for src, dst in ASSET_DIRS.items(): + if (ROOT / src).is_dir(): + shutil.copytree(ROOT / src, out / dst) + return written + + +def main() -> int: + parser = argparse.ArgumentParser(description=__doc__.splitlines()[0]) + parser.add_argument("--out", default="docs/site") + args = parser.parse_args() + written = build(ROOT / args.out) + print(f"{len(written)} pages written to {args.out}") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/scripts/check_figures.py b/scripts/check_figures.py index fbcc01e..7e49a35 100644 --- a/scripts/check_figures.py +++ b/scripts/check_figures.py @@ -22,7 +22,7 @@ ROOT = Path(__file__).resolve().parent.parent SOURCE = "https://raw.githubusercontent.com/manifest-identity/manifest-identity/main/README.md" STATED = re.compile(r"more than (\d+) tests, (\d+) recorded(\s+)decisions") -FILES = ["README.md", "index.html"] +FILES = ["README.md"] STEP = 100 diff --git a/tests/__pycache__/test_docs_build.cpython-314.pyc b/tests/__pycache__/test_docs_build.cpython-314.pyc new file mode 100644 index 0000000000000000000000000000000000000000..07cb6ebcffc9fac77e2e43bc558192d2298dba00 GIT binary patch literal 4661 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 J;vUBQzX7G2+xY+h literal 0 HcmV?d00001 diff --git a/tests/test_docs_build.py b/tests/test_docs_build.py new file mode 100644 index 0000000..bbfedb6 --- /dev/null +++ b/tests/test_docs_build.py @@ -0,0 +1,48 @@ +"""The documentation site is generated from the documents, never +written beside them. + +Every root document has a page in reading order, so a document added +without the site noticing is impossible, and every link between the +documents resolves to a page that holds the heading it names. +""" + +import re +import sys +import tempfile +import unittest +from pathlib import Path + +sys.path.insert(0, str(Path(__file__).resolve().parent.parent / "scripts")) +import build_docs # noqa: E402 + +ROOT = Path(__file__).resolve().parent.parent + + +class Site(unittest.TestCase): + def test_every_root_document_is_a_page(self) -> None: + docs = {p.name for p in ROOT.glob("*.md")} - build_docs.NOT_PAGES + self.assertEqual(docs, {src for src, _ in build_docs.PAGES}) + + def test_every_cross_page_anchor_resolves(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + out = Path(tmp) / "site" + written = build_docs.build(out) + headings = { + name: {build_docs.slug(m.group(2)) + for m in build_docs.HEADING.finditer((out / name).read_text())} + for name in written + } + for name in written: + for m in re.finditer(r"\]\(([\w.-]+\.md)?#([\w-]+)\)", (out / name).read_text()): + page = m.group(1) or name + self.assertIn(page, headings, (name, m.group(0))) + self.assertIn(m.group(2), headings[page], (name, m.group(0))) + self.assertTrue((out / "diagrams").is_dir()) + joined = "".join((out / n).read_text() for n in written) + self.assertNotIn("](diagrams/../", joined) + self.assertTrue((out / "images").is_dir()) + self.assertNotIn("](PHASE-3.md", joined) + + +if __name__ == "__main__": + unittest.main() From 4bb304cf1410e756f4dbb2b2b92e55c9c3516478 Mon Sep 17 00:00:00 2001 From: "control-plane-agent[bot]" <318806258+control-plane-agent[bot]@users.noreply.github.com> Date: Tue, 29 Sep 2026 22:03:57 -0700 Subject: [PATCH 2/2] CI: build-doctrine pin moved past the retired-name fix The list no longer retires the address this repository now links. Co-authored-by: Claude --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5d3349c..691143a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -85,7 +85,7 @@ jobs: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: repository: tltaylor1/build-doctrine - ref: 110a64984ad306f4c502b571a6d359afb5cd4c81 + ref: a235068d87c618bc7d8b70cf83a52c071056df80 path: doctrine persist-credentials: false - name: no retired project name in active text