Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 76 additions & 0 deletions .github/requirements/development-inputs.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# Exact reviewed producer tools; no release/client artifact adoption.
pip==26.2.1 --hash=sha256:71138adf1f4ca900cdb7d289c21b7494329f2332b6d85f0e1c42108c0384ed3e
packaging==26.3 --hash=sha256:d7193f7c8e4e93f444fde0262bf90af30e16fa0ad0ad44cb553c87339b23cd1c
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:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b \
--hash=sha256:eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be \
--hash=sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c \
--hash=sha256:efd7b85f94a6f21e4932043973a7ba2613b059c4a000551892ac9f1d11f5baf3 \
--hash=sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6 \
--hash=sha256:fa160448684b4e94d80416c0fa4aac48967a969efe22931448d853ada8baf926 \
--hash=sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0
83 changes: 83 additions & 0 deletions .github/workflows/development-source-inputs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
name: Development source input proposal
on:
pull_request:
push:
branches: [trunk]
permissions:
contents: read
concurrency:
group: development-inputs-${{ github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
jobs:
proposal:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7
with:
python-version: '3.12.3'
- name: Install reviewed producer tools
run: |
python -m pip install --require-hashes --only-binary=:all: -r .github/requirements/development-inputs.lock
- name: Run input tamper controls
run: |
python - <<'PYTHON'
from pathlib import Path
import yaml
for path in Path('.github/workflows').glob('*.yml'):
workflow = yaml.safe_load(path.read_text())
for job in workflow.get('jobs', {}).values():
for step in job.get('steps', []):
if 'run' in step:
assert isinstance(step['run'], str), (str(path), step.get('name'), type(step['run']).__name__)
PYTHON
python -m unittest discover -s tests -p test_development_source_inputs.py -v
python -m unittest discover -s tests -p test_governed_source_inputs.py -v
- name: Resolve all five profiles and original ordered source-install sequences
run: |
python scripts/development_source_inputs.py --source "$GITHUB_WORKSPACE" --revision "$(git rev-parse HEAD)" --destination "$RUNNER_TEMP/development-inputs"
python scripts/development_source_inputs.py --verify --source "$GITHUB_WORKSPACE" --revision "$(git rev-parse HEAD)" --destination "$RUNNER_TEMP/development-inputs"
python scripts/check_development_input_mutations.py --source "$GITHUB_WORKSPACE" --revision "$(git rev-parse HEAD)" --destination "$RUNNER_TEMP/development-inputs"
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
if: always()
with:
name: development-source-input-proposal
path: ${{ runner.temp }}/development-inputs
if-no-files-found: warn
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
if: always()
with:
name: development-synthetic-pip-control
path: ${{ runner.temp }}/development-pip-control
if-no-files-found: ignore
governed-document-runtime:
runs-on: ubuntu-24.04
defaults:
run:
working-directory: producer
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
path: producer
persist-credentials: false
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
# Read-only original governed subject; no source or release adoption.
ref: 5a79352066b8aa23f1bae45b5c38e6d83efd003f
path: subject
persist-credentials: false
- name: Pull exact original documentation image
run: |
docker pull python:3.12-bookworm@sha256:e91fec3d1ac69f04e4eddcd29c327e630ce34658cf31075bfa7e8b0e052bafea
- name: Observe original runtime and produce all immutable input sequences
run: |
python3 scripts/run_governed_source_inputs.py --implementation "$GITHUB_WORKSPACE/producer" --source "$GITHUB_WORKSPACE/subject" --revision 5a79352066b8aa23f1bae45b5c38e6d83efd003f --destination "$RUNNER_TEMP/governed-development-inputs"
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
if: always()
with:
name: governed-development-source-inputs
path: ${{ runner.temp }}/governed-development-inputs
if-no-files-found: warn
1 change: 1 addition & 0 deletions docs/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

* [Authenticate a client](auth.md)
* [Run the operator workflow from a terminal](cli/operator-workflow.md)
* [Produce immutable development source inputs](contributor/development-source-inputs.md)
* [Collect a support bundle](diagnostic-bundles.md)
* [Hand an ArcPy inventory to the codemod](honua-gp/scanner-handoff.md)
* [Import the geoprocessing package](migration/gp-import.md)
Expand Down
99 changes: 99 additions & 0 deletions docs/contributor/development-source-inputs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
---
type: guide
title: "Produce immutable development source inputs"
description: "Capture review-only source, dependency and backend inputs without admitting or publishing packages."
resource: "https://github.com/honua-io/honua-sdk-python/issues/311"
tags: [python, development, release]
---
# Review-only development source inputs

`python scripts/development_source_inputs.py --source /absolute/clean/checkout --revision FULL_40_CHARACTER_SHA --destination /absolute/new/proposal-directory`

Run with the exact Python, pip, packaging and platform declared in
`scripts/development-inputs/runtime.json`. The source must be a clean immutable
checkout of this repository. Outputs stay outside the checkout. The producer
captures every tracked source input and derives the core, grpc, geopandas,
raster, and combined SDK-with-all-extras plus Admin profiles from the actual
package metadata. All five profiles are mandatory.

The producer implementation and subject checkout have separate immutable
identities. A protected producer can inspect an older, still-governed clean
subject using `--source` and `--revision`; this does not adopt newer package
versions or turn source-built wheels into published artifacts.

The proposal also captures each original README and INSTALL source-install
block, including its exact document and fence bytes, ordered pip commands,
requested extras and editable flags. Each block uses an isolated environment;
each pip step records its actual resolver delta and installed closure before
and after execution. The backend closure is installed with hash enforcement
before source metadata or editable build hooks execute. Non-pip lint and test
commands remain unchanged for the executable-docs replay and are not executed
or counted as passed by this producer.

Default pip compilation remains enabled. Verification checks a finite mapping
from original wheel members to installed files, including pip metadata,
entrypoint scripts and compiled bytecode, and rejects extra installed or
editable-source files. Editable wheels and their exact copied source tree have
separate provenance from regular source-built wheels.

The default runtime policy describes the reviewed producer runtime. It does
not assert equivalence with a documentation container image. The later harness
must bind the actual governed image and invoked interpreter; a runtime mismatch
remains nonpassing until that exact input is produced and reviewed.

For the original governed documentation subject, first make the exact
`python:3.12-bookworm@sha256:e91fec3d1ac69f04e4eddcd29c327e630ce34658cf31075bfa7e8b0e052bafea`
image available to Docker, then use the governed launcher:

```bash
python3 scripts/run_governed_source_inputs.py --implementation /absolute/clean/producer-checkout --source /absolute/clean/governed-subject --revision 5a79352066b8aa23f1bae45b5c38e6d83efd003f --destination /absolute/new/governed-inputs
```

This subject remains SDK 0.1.16 and Admin 0.1.12. The producer implementation
has its own revision. The launcher uses the original image's Python 3.12.15
and pip 25.0.1, with their exact reviewed executable and tool hashes. Packaging
26.3 is a separately hash-verified, read-only implementation import; it is
never installed into the image and is excluded from every subject pip/backend
subprocess. Actual child observations and seven input-refusal controls check
that separation. Original pip compilation remains enabled.

The outer `execution.json` and original container observations bind the actual
image digest, container image ID, immutable subject and implementation, command,
read-only mounts, terminal state and cleanup. The inner `proposal/proposal.json`
binds all artifact and ordered input captures. A consumer must rejudge both
sets of original evidence; the policy's image string alone grants no identity
or admission. Failed actions retain their original output and daemon state.
A transport failure waits for live owned work to finish rather than cancelling
it. Unresolved work remains explicitly pending.

This captures inputs using declared fixed-interpreter commands, including
separate offline installation of the verified artifacts. It does not report
that the unchanged documentation commands, lint commands or full tests ran.
Those original commands and their actual runtime replay remain required by
honua-release issue 721.

Each profile retains the actual resolver command, interpreter environment,
original report and output, and anonymously downloaded wheels with canonical
PyPI origins, metadata, exact versions and SHA256 hashes. An independent registry
response must agree with every artifact. Dependency markers and extras are
rejudged recursively; missing dependencies fail. The exact Hatchling build
closure is resolved separately, installed with hash enforcement into a disposable
backend environment, and used without build isolation, dependency resolution or
network indexes to build both packages from tracked source bytes only.

`python scripts/development_source_inputs.py --verify --source /absolute/clean/checkout --revision FULL_40_CHARACTER_SHA --destination /absolute/existing/proposal-directory`

Verification rejoins source/runtime, original resolver reports, all profiles,
artifact bytes and recursive closure, and the separate source-built wheels.
Source or runtime refusal occurs before resolver execution. Drift detected after
resolution refuses before backend installation. Failure outputs are retained;
a missing final `proposal.json` is a failed proposal, never an admitted input.

This is an input proposal for honua-release issue 721 and Python issue 311.
Generation and verification do not admit a source install, relax default
PEP610/direct-origin refusal, establish published wheel identity, publish a
package, change a version or release pin, or qualify a release candidate. The
SDK and Admin publication sources may differ; these source-built wheels carry
their actual checkout identity and never inherit a published artifact's identity.
Every original document and command remains required for the later admitted
source and exact-candidate replay.
Loading
Loading