codapact 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. codapact-0.1.0/.github/workflows/ci.yml +53 -0
  2. codapact-0.1.0/.github/workflows/mutation-alerts.yml +73 -0
  3. codapact-0.1.0/.github/workflows/mutation.yml +55 -0
  4. codapact-0.1.0/.github/workflows/release.yml +88 -0
  5. codapact-0.1.0/.release-please-manifest.json +1 -0
  6. codapact-0.1.0/CHANGELOG.md +14 -0
  7. codapact-0.1.0/LICENSE +21 -0
  8. codapact-0.1.0/PKG-INFO +62 -0
  9. codapact-0.1.0/README.md +47 -0
  10. codapact-0.1.0/branding/mark.svg +8 -0
  11. codapact-0.1.0/branding/wordmark.svg +11 -0
  12. codapact-0.1.0/docs/architecture.md +74 -0
  13. codapact-0.1.0/docs/branding.md +25 -0
  14. codapact-0.1.0/docs/configuration.md +167 -0
  15. codapact-0.1.0/docs/mutation.md +71 -0
  16. codapact-0.1.0/docs/releasing.md +41 -0
  17. codapact-0.1.0/docs/support.md +69 -0
  18. codapact-0.1.0/docs/verification.md +59 -0
  19. codapact-0.1.0/examples/cli.json +4 -0
  20. codapact-0.1.0/examples/pets.codapact.yaml +18 -0
  21. codapact-0.1.0/examples/pets.yaml +43 -0
  22. codapact-0.1.0/examples/runtime.json +5 -0
  23. codapact-0.1.0/pyproject.toml +141 -0
  24. codapact-0.1.0/pyproject.toml.orig +75 -0
  25. codapact-0.1.0/release-please-config.json +31 -0
  26. codapact-0.1.0/schemas/cli.v1.schema.json +23 -0
  27. codapact-0.1.0/scripts/mutation_alerts.py +384 -0
  28. codapact-0.1.0/scripts/mutation_report.py +110 -0
  29. codapact-0.1.0/scripts/verify_dist.py +35 -0
  30. codapact-0.1.0/src/codapact/__init__.py +3 -0
  31. codapact-0.1.0/src/codapact/__main__.py +83 -0
  32. codapact-0.1.0/src/codapact/cli.py +117 -0
  33. codapact-0.1.0/src/codapact/configuration.py +135 -0
  34. codapact-0.1.0/src/codapact/errors.py +30 -0
  35. codapact-0.1.0/src/codapact/generation.py +243 -0
  36. codapact-0.1.0/src/codapact/loading.py +121 -0
  37. codapact-0.1.0/src/codapact/model.py +83 -0
  38. codapact-0.1.0/src/codapact/net.py +100 -0
  39. codapact-0.1.0/src/codapact/openapi.py +294 -0
  40. codapact-0.1.0/src/codapact/profiles.py +171 -0
  41. codapact-0.1.0/src/codapact/project.py +173 -0
  42. codapact-0.1.0/src/codapact/py.typed +0 -0
  43. codapact-0.1.0/src/codapact/runtime.py +299 -0
  44. codapact-0.1.0/src/codapact/schemas/generation.v1.json +57 -0
  45. codapact-0.1.0/src/codapact/values.py +33 -0
  46. codapact-0.1.0/tests/conftest.py +170 -0
  47. codapact-0.1.0/tests/test_adversarial.py +140 -0
  48. codapact-0.1.0/tests/test_configuration.py +421 -0
  49. codapact-0.1.0/tests/test_distribution.py +104 -0
  50. codapact-0.1.0/tests/test_entrypoint.py +41 -0
  51. codapact-0.1.0/tests/test_generation.py +220 -0
  52. codapact-0.1.0/tests/test_loading.py +82 -0
  53. codapact-0.1.0/tests/test_mutation_alerts.py +277 -0
  54. codapact-0.1.0/tests/test_net.py +100 -0
  55. codapact-0.1.0/tests/test_openapi.py +84 -0
  56. codapact-0.1.0/tests/test_runtime.py +230 -0
  57. codapact-0.1.0/uv.lock +1239 -0
@@ -0,0 +1,53 @@
1
+ name: CI
2
+ on:
3
+ pull_request:
4
+ push:
5
+ branches: [main]
6
+ workflow_dispatch:
7
+ workflow_call:
8
+ permissions:
9
+ contents: read
10
+ jobs:
11
+ title:
12
+ name: Conventional PR title
13
+ if: github.event_name == 'pull_request'
14
+ runs-on: ubuntu-latest
15
+ steps:
16
+ - name: Check title
17
+ env:
18
+ TITLE: ${{ github.event.pull_request.title }}
19
+ run: |
20
+ pattern='^(feat|fix|perf|docs|build|ci|refactor|test|chore|style|revert)(\([^)]+\))?!?: .+'
21
+ [[ "$TITLE" =~ $pattern ]]
22
+ check:
23
+ name: Python ${{ matrix.python }} on ${{ matrix.os }}
24
+ runs-on: ${{ matrix.os }}
25
+ strategy:
26
+ matrix:
27
+ os: [ubuntu-latest, windows-latest]
28
+ python: ['3.13', '3.14']
29
+ steps:
30
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
31
+ with:
32
+ persist-credentials: false
33
+ - uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
34
+ with:
35
+ python-version: ${{ matrix.python }}
36
+ enable-cache: false
37
+ - run: uv sync --locked
38
+ - run: uv run poe check
39
+ - run: uv build
40
+ - run: uv run twine check --strict dist/*
41
+ passed:
42
+ name: CI passed
43
+ if: always()
44
+ needs: [check, title]
45
+ runs-on: ubuntu-latest
46
+ steps:
47
+ - name: Require all checks
48
+ env:
49
+ RESULT: ${{ needs.check.result }}
50
+ TITLE_RESULT: ${{ needs.title.result }}
51
+ run: |
52
+ test "$RESULT" = success
53
+ test "$TITLE_RESULT" = success || test "$TITLE_RESULT" = skipped
@@ -0,0 +1,73 @@
1
+ name: Mutation alerts
2
+ on:
3
+ workflow_run: # zizmor: ignore[dangerous-triggers] -- only same-repo main push/schedule/manual evidence; fixed-main checkout; artifacts parsed as data, never executed
4
+ workflows: [Mutation]
5
+ types: [completed]
6
+ branches: [main]
7
+ workflow_dispatch:
8
+ inputs:
9
+ selftest:
10
+ description: Verify issue creation, update, deduplication, and recovery using an isolated test incident
11
+ type: boolean
12
+ required: true
13
+ default: true
14
+ permissions:
15
+ contents: read
16
+ concurrency:
17
+ group: mutation-alerts
18
+ cancel-in-progress: false
19
+ jobs:
20
+ validate-ref:
21
+ runs-on: ubuntu-latest
22
+ steps:
23
+ - name: Reject non-default manual refs
24
+ run: test "$GITHUB_REF" = refs/heads/main
25
+ reconcile:
26
+ needs: validate-ref
27
+ # Only trusted main results; never a pull_request or fork write context.
28
+ if: >-
29
+ github.ref == 'refs/heads/main' &&
30
+ (github.event_name == 'workflow_dispatch' ||
31
+ (github.event.workflow_run.head_repository.full_name == github.repository &&
32
+ github.event.workflow_run.head_branch == 'main' &&
33
+ contains(fromJSON('["push","schedule","workflow_dispatch"]'), github.event.workflow_run.event)))
34
+ runs-on: ubuntu-latest
35
+ timeout-minutes: 10
36
+ permissions:
37
+ contents: read
38
+ actions: read
39
+ issues: write
40
+ steps:
41
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
42
+ with:
43
+ persist-credentials: false
44
+ ref: main
45
+ - uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
46
+ with:
47
+ python-version: '3.13'
48
+ enable-cache: false
49
+ - name: Download evidence from the trusted main run
50
+ if: github.event_name == 'workflow_run'
51
+ continue-on-error: true
52
+ uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
53
+ with:
54
+ name: mutation-report
55
+ path: mutation-report/
56
+ run-id: ${{ github.event.workflow_run.id }}
57
+ github-token: ${{ github.token }}
58
+ - name: Reconcile durable production alerts
59
+ if: github.event_name == 'workflow_run'
60
+ env:
61
+ GH_TOKEN: ${{ github.token }}
62
+ MUTATION_SHA: ${{ github.event.workflow_run.head_sha }}
63
+ MUTATION_RUN_URL: ${{ github.event.workflow_run.html_url }}
64
+ MUTATION_CONCLUSION: ${{ github.event.workflow_run.conclusion }}
65
+ MUTATION_RUN_ATTEMPT: ${{ github.event.workflow_run.run_attempt }}
66
+ run: uv run --no-project python scripts/mutation_alerts.py
67
+ - name: Verify hosted alert lifecycle
68
+ if: github.event_name == 'workflow_dispatch' && inputs.selftest
69
+ env:
70
+ GH_TOKEN: ${{ github.token }}
71
+ MUTATION_SHA: ${{ github.sha }}
72
+ MUTATION_RUN_URL: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}
73
+ run: uv run --no-project python scripts/mutation_alerts.py --selftest
@@ -0,0 +1,55 @@
1
+ name: Mutation
2
+ on:
3
+ push:
4
+ branches: [main]
5
+ schedule:
6
+ - cron: '23 6 * * 1'
7
+ workflow_dispatch:
8
+ permissions:
9
+ contents: read
10
+ concurrency:
11
+ group: mutation-main
12
+ cancel-in-progress: false
13
+ jobs:
14
+ validate-ref:
15
+ runs-on: ubuntu-latest
16
+ steps:
17
+ - name: Reject non-default manual refs
18
+ run: test "$GITHUB_REF" = refs/heads/main
19
+ scan:
20
+ needs: validate-ref
21
+ if: github.ref == 'refs/heads/main'
22
+ runs-on: ubuntu-latest
23
+ timeout-minutes: 25
24
+ steps:
25
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
26
+ with:
27
+ persist-credentials: false
28
+ - uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
29
+ with:
30
+ python-version: '3.13'
31
+ enable-cache: false
32
+ - run: uv sync --locked --group mutation
33
+ - name: Run bounded asynchronous mutation analysis
34
+ run: |
35
+ mkdir -p mutation-report
36
+ set +e
37
+ timeout --signal=TERM --kill-after=10s 18m uv run --group mutation mutmut run --max-children 2 > mutation-report/run.log 2>&1
38
+ code=$?
39
+ uv run --group mutation mutmut export-cicd-stats >> mutation-report/run.log 2>&1
40
+ uv run --group mutation mutmut results --all true > mutation-report/results.txt 2>&1
41
+ results_code=$?
42
+ tar -czf mutation-report/mutants.tar.gz -C mutants/src codapact
43
+ archive_code=$?
44
+ if test "$code" -eq 0 && { test "$results_code" -ne 0 || test "$archive_code" -ne 0; }; then
45
+ code=1
46
+ fi
47
+ uv run python scripts/mutation_report.py --exit-code "$code" --stats mutants/mutmut-cicd-stats.json --output mutation-report/report.json
48
+ - name: Preserve evidence on failure or incomplete run
49
+ if: always()
50
+ uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
51
+ with:
52
+ name: mutation-report
53
+ path: mutation-report/
54
+ if-no-files-found: warn
55
+ retention-days: 30
@@ -0,0 +1,88 @@
1
+ name: Release
2
+ on:
3
+ push:
4
+ branches: [main]
5
+ workflow_dispatch:
6
+ permissions:
7
+ contents: read
8
+ concurrency:
9
+ group: release
10
+ cancel-in-progress: false
11
+ jobs:
12
+ version:
13
+ # Repository and publisher setup must be completed before enabling releases.
14
+ if: vars.RELEASES_ENABLED == 'true'
15
+ runs-on: ubuntu-latest
16
+ permissions:
17
+ contents: write
18
+ actions: write
19
+ pull-requests: write
20
+ issues: write
21
+ outputs:
22
+ created: ${{ steps.release.outputs.release_created }}
23
+ tag: ${{ steps.release.outputs.tag_name }}
24
+ steps:
25
+ - id: release
26
+ uses: googleapis/release-please-action@45996ed1f6d02564a971a2fa1b5860e934307cf7 # v5.0.0
27
+ with:
28
+ token: ${{ secrets.RELEASE_PLEASE_TOKEN || secrets.GITHUB_TOKEN }}
29
+ config-file: release-please-config.json
30
+ manifest-file: .release-please-manifest.json
31
+ - name: Start CI for release pull request
32
+ if: steps.release.outputs.prs_created == 'true'
33
+ env:
34
+ GH_TOKEN: ${{ github.token }}
35
+ PR_JSON: ${{ steps.release.outputs.pr }}
36
+ run: |
37
+ branch=$(jq -r '.headBranchName' <<< "$PR_JSON")
38
+ gh workflow run ci.yml --repo "$GITHUB_REPOSITORY" --ref "$branch"
39
+ ci:
40
+ needs: version
41
+ if: needs.version.outputs.created == 'true'
42
+ uses: ./.github/workflows/ci.yml # zizmor: ignore[self-repository] -- portable local reuse, matching VerdiClip
43
+ permissions:
44
+ contents: read
45
+ build:
46
+ needs: [version, ci]
47
+ runs-on: ubuntu-latest
48
+ steps:
49
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
50
+ with:
51
+ persist-credentials: false
52
+ ref: ${{ needs.version.outputs.tag }}
53
+ - uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
54
+ with:
55
+ enable-cache: false
56
+ - run: uv sync --locked
57
+ - run: uv build
58
+ - run: uv run twine check --strict dist/*
59
+ - name: Verify distribution and tag versions
60
+ env:
61
+ RELEASE_TAG: ${{ needs.version.outputs.tag }}
62
+ run: uv run python scripts/verify_dist.py
63
+ - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
64
+ with:
65
+ name: dist
66
+ path: dist/
67
+ publish:
68
+ needs: [version, build]
69
+ runs-on: ubuntu-latest
70
+ environment: pypi
71
+ permissions:
72
+ id-token: write
73
+ attestations: write
74
+ contents: write
75
+ steps:
76
+ - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
77
+ with:
78
+ name: dist
79
+ path: dist/
80
+ - uses: actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8 # v4.2.2
81
+ with:
82
+ subject-path: dist/*
83
+ - uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2
84
+ - name: Attach distributions
85
+ env:
86
+ GH_TOKEN: ${{ github.token }}
87
+ TAG: ${{ needs.version.outputs.tag }}
88
+ run: gh release upload "$TAG" dist/* --repo "$GITHUB_REPOSITORY"
@@ -0,0 +1 @@
1
+ {".":"0.1.0"}
@@ -0,0 +1,14 @@
1
+ # Changelog
2
+
3
+ ## 0.1.0 (2026-10-29)
4
+
5
+ ### Features
6
+
7
+ * add generation manifests and XDG runtime profiles ([cd0e6a2](https://github.com/mikejhill/codapact/commit/cd0e6a20e813423d3b33ca5ba277a036c482dd8c))
8
+ * initialize codapact ([7daa7e2](https://github.com/mikejhill/codapact/commit/7daa7e2534bdd59bcd555dc90ec2e97a002f130c))
9
+
10
+ ### Bug Fixes
11
+
12
+ * document generated commands and release handoff ([9ea472c](https://github.com/mikejhill/codapact/commit/9ea472ca5e3cfe9fdf4bbc94bb22511d87eece22))
13
+ * harden contracts and add mutation alerts ([b4b1a06](https://github.com/mikejhill/codapact/commit/b4b1a06d2029a53fa68783f6ecd1c0dedb7854e2))
14
+ * reconcile asynchronous mutation alerts ([ba1737d](https://github.com/mikejhill/codapact/commit/ba1737d33f9e6157a7d9fe6f6c8b1d2878917dec))
codapact-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Mike Hill
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,62 @@
1
+ Metadata-Version: 2.4
2
+ Name: codapact
3
+ Version: 0.1.0
4
+ Summary: Contracts into callable tools: pluggable API client and CLI generation.
5
+ License-Expression: MIT
6
+ License-File: LICENSE
7
+ Requires-Dist: pyyaml>=6.0.3,<7
8
+ Requires-Dist: jsonschema>=4.25.1,<5
9
+ Requires-Python: >=3.13
10
+ Project-URL: Homepage, https://github.com/mikejhill/codapact
11
+ Project-URL: Documentation, https://github.com/mikejhill/codapact#readme
12
+ Project-URL: Changelog, https://github.com/mikejhill/codapact/blob/main/CHANGELOG.md
13
+ Project-URL: Issues, https://github.com/mikejhill/codapact/issues
14
+ Description-Content-Type: text/markdown
15
+
16
+ # CodaPact
17
+
18
+ ![CodaPact wordmark](branding/wordmark.svg)
19
+
20
+ **Contracts into callable tools.**
21
+
22
+ This first iteration generates an installable, typed Python client and a
23
+ scriptable CLI from a local or remote OpenAPI contract. The package, module, and
24
+ generator CLI are named `codapact`. Install a published release with
25
+ `uv tool install codapact`, or use the source workflow below.
26
+
27
+ ```powershell
28
+ uv sync
29
+ uv run codapact generate examples/pets.yaml --output .tmp/pets-client --package pets_client
30
+ uv build
31
+ uv pip install --no-deps .tmp/pets-client
32
+ uv run pets-client --config examples/runtime.json get-pet --arg-pet-id 7
33
+ ```
34
+
35
+ The example server address is intentionally inert. Override `base_url` with your
36
+ own trusted endpoint and set the environment variable referenced by the runtime
37
+ configuration. Tests use isolated loopback HTTP servers and synthetic credentials.
38
+
39
+ ```python
40
+ from pets_client import Client
41
+
42
+ client = Client(settings={"auth": {"token": {"env": "PETS_TOKEN"}}})
43
+ pet = client.get_pet(parameters={"pet_id": 7})
44
+ ```
45
+
46
+ Reusable generation values are supported with `uv run codapact generate
47
+ --manifest examples/pets.codapact.yaml`. The resulting `pets` command discovers
48
+ `config.json` and `auth.json` in `$XDG_CONFIG_HOME/pets` or `~/.config/pets`.
49
+ Override its directory with `pets --config-dir PATH ...`. See the configuration
50
+ guide for precedence, credential-file permissions, and every generation override.
51
+
52
+ - [Architecture and extension contracts](docs/architecture.md)
53
+ - [Supported features and safety boundaries](docs/support.md)
54
+ - [CLI definition and runtime configuration](docs/configuration.md)
55
+ - [Release process](docs/releasing.md)
56
+ - [Verification evidence and limits](docs/verification.md)
57
+ - [Asynchronous mutation testing and open alerts](docs/mutation.md)
58
+
59
+ Run `uv run poe check` for formatting, lint, type checking, and tests. Generated
60
+ packages depend on this runtime at the exact generator version. For unreleased
61
+ source changes, install the local runtime wheel and generated wheel together.
62
+ The end-to-end test proves that workflow in a fresh environment.
@@ -0,0 +1,47 @@
1
+ # CodaPact
2
+
3
+ ![CodaPact wordmark](branding/wordmark.svg)
4
+
5
+ **Contracts into callable tools.**
6
+
7
+ This first iteration generates an installable, typed Python client and a
8
+ scriptable CLI from a local or remote OpenAPI contract. The package, module, and
9
+ generator CLI are named `codapact`. Install a published release with
10
+ `uv tool install codapact`, or use the source workflow below.
11
+
12
+ ```powershell
13
+ uv sync
14
+ uv run codapact generate examples/pets.yaml --output .tmp/pets-client --package pets_client
15
+ uv build
16
+ uv pip install --no-deps .tmp/pets-client
17
+ uv run pets-client --config examples/runtime.json get-pet --arg-pet-id 7
18
+ ```
19
+
20
+ The example server address is intentionally inert. Override `base_url` with your
21
+ own trusted endpoint and set the environment variable referenced by the runtime
22
+ configuration. Tests use isolated loopback HTTP servers and synthetic credentials.
23
+
24
+ ```python
25
+ from pets_client import Client
26
+
27
+ client = Client(settings={"auth": {"token": {"env": "PETS_TOKEN"}}})
28
+ pet = client.get_pet(parameters={"pet_id": 7})
29
+ ```
30
+
31
+ Reusable generation values are supported with `uv run codapact generate
32
+ --manifest examples/pets.codapact.yaml`. The resulting `pets` command discovers
33
+ `config.json` and `auth.json` in `$XDG_CONFIG_HOME/pets` or `~/.config/pets`.
34
+ Override its directory with `pets --config-dir PATH ...`. See the configuration
35
+ guide for precedence, credential-file permissions, and every generation override.
36
+
37
+ - [Architecture and extension contracts](docs/architecture.md)
38
+ - [Supported features and safety boundaries](docs/support.md)
39
+ - [CLI definition and runtime configuration](docs/configuration.md)
40
+ - [Release process](docs/releasing.md)
41
+ - [Verification evidence and limits](docs/verification.md)
42
+ - [Asynchronous mutation testing and open alerts](docs/mutation.md)
43
+
44
+ Run `uv run poe check` for formatting, lint, type checking, and tests. Generated
45
+ packages depend on this runtime at the exact generator version. For unreleased
46
+ source changes, install the local runtime wheel and generated wheel together.
47
+ The end-to-end test proves that workflow in a fresh environment.
@@ -0,0 +1,8 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128" role="img" aria-labelledby="title desc">
2
+ <title id="title">CodaPact</title>
3
+ <desc id="desc">A coda-inspired open ring with a shared vertical axis and two balanced horizontal strokes.</desc>
4
+ <path d="M50 29a37 37 0 0 0 0 70M78 29a37 37 0 0 1 0 70" fill="none" stroke="#15a99b" stroke-width="12" stroke-linecap="round"/>
5
+ <path d="M64 12v104" fill="none" stroke="#18283e" stroke-width="10" stroke-linecap="round"/>
6
+ <path d="M13 64h38m26 0h38" fill="none" stroke="#18283e" stroke-width="10" stroke-linecap="round"/>
7
+ <circle cx="64" cy="64" r="7" fill="#d99732"/>
8
+ </svg>
@@ -0,0 +1,11 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="500" height="166" viewBox="0 0 500 166" role="img" aria-labelledby="title desc">
2
+ <title id="title">CodaPact — Contracts into callable tools</title>
3
+ <desc id="desc">A teal coda mark and navy wordmark, with an amber central accent.</desc>
4
+ <g transform="translate(10 19)">
5
+ <path d="M50 29a37 37 0 0 0 0 70M78 29a37 37 0 0 1 0 70" fill="none" stroke="#15a99b" stroke-width="12" stroke-linecap="round"/>
6
+ <path d="M64 12v104M13 64h38m26 0h38" fill="none" stroke="#18283e" stroke-width="10" stroke-linecap="round"/>
7
+ <circle cx="64" cy="64" r="7" fill="#d99732"/>
8
+ </g>
9
+ <text x="166" y="88" fill="#18283e" font-family="Segoe UI,Inter,Arial,sans-serif" font-size="67" font-weight="650" letter-spacing="-2">CodaPact</text>
10
+ <text x="170" y="125" fill="#52627a" font-family="Segoe UI,Inter,Arial,sans-serif" font-size="22">Contracts into callable tools.</text>
11
+ </svg>
@@ -0,0 +1,74 @@
1
+ # Architecture
2
+
3
+ Python 3.13 is the initial implementation and generated language. It fits the
4
+ existing uv-based release process and supports typed dictionaries without a
5
+ large code generation framework. Runtime schemas validate data independently
6
+ of static annotations. TypeScript remains a future target.
7
+
8
+ ```mermaid
9
+ flowchart LR
10
+ A[Bounded JSON/YAML loader] --> B[Contract translator plugin]
11
+ B --> C[Version 1 shared IR]
12
+ C --> D[Python generator plugin]
13
+ C --> E[CLI generator plugin]
14
+ D --> F[Ownership manifest]
15
+ E --> F
16
+ F --> G[Generated client and CLI]
17
+ G --> H[Authorization policy]
18
+ H --> I[Authentication provider]
19
+ I --> J[Transport]
20
+ ```
21
+
22
+ ## Layer contracts
23
+
24
+ | Layer | Initial implementation | Extension boundary |
25
+ | --- | --- | --- |
26
+ | Loading | Bounded JSON/YAML; local files and HTTP(S) | Explicit transport injection |
27
+ | Translation | OpenAPI 3.0 JSON HTTP subset | `Translator.translate(document) -> Contract` |
28
+ | Shared model | Frozen contract and operation records; schema dictionaries | IR major version, metadata, capability identifiers |
29
+ | Library generation | Typed dictionaries, typed methods, JSON IR resource | `Generator.generate(contract, package) -> files` |
30
+ | CLI generation | Version 1 definition, argparse commands | Independent generator and CLI runtime |
31
+ | Execution | Schema validation and JSON serialization | Generated client inherits `ClientBase` |
32
+ | Authentication | Environment-backed bearer, basic, header API key | `AuthProvider.headers(name, scheme)` |
33
+ | Policy | Operation allow/deny lists | `AuthorizationPolicy.authorize(operation)` |
34
+ | Transport | Pinned DNS, bounded HTTP, verified TLS | `Transport.send(...) -> Response` |
35
+ | Orchestration | Explicit registry, capability negotiation, ownership checks | Registry supplied to `generate` |
36
+
37
+ Plugin API version 1 and IR version 1 are separate contracts. Registration rejects
38
+ duplicate names and incompatible API versions. Targets declare required
39
+ capabilities; translators declare capabilities they can produce. Plugins are
40
+ trusted Python objects registered by the host application, never imported from
41
+ contract or configuration strings. A fixture translator and operation-index
42
+ generator exercise a complete alternate plugin path in tests.
43
+
44
+ The normalized IR records operations, parameter schemas, JSON request bodies,
45
+ successful and error response schemas, named component types, security OR/AND
46
+ requirements, and extensible metadata. OAuth2, GraphQL, Turbo-Stream, gRPC,
47
+ streaming transports, other languages, and other CLI styles are future plugins.
48
+ They are not implemented or advertised as supported.
49
+
50
+ ## Custom runtime hooks
51
+
52
+ Pass `auth=`, `policy=`, and `transport=` objects to a generated `Client`. Hooks
53
+ are explicit application code. An auth provider returns headers or raises
54
+ `AuthError` when credentials are unavailable. A policy raises `PolicyError`
55
+ before credentials are resolved and before network activity. Transport plugins
56
+ must preserve redirect, credential, timeout, and response-size guarantees.
57
+
58
+ The generated CLI uses the declarative built-in hooks. Applications needing
59
+ custom hooks can call `run_cli` with their own client factory. No configuration
60
+ option dynamically imports code or executes shell commands.
61
+
62
+ ## Regeneration
63
+
64
+ Generators return relative paths and Unicode file contents. The writer checks
65
+ all planned writes and removals before mutation, verifies SHA-256 ownership,
66
+ refuses modified/unowned files, rejects traversal and symlinks/junctions, and
67
+ preserves unrelated files. Obsolete owned files are removed. The manifest is
68
+ deterministic and written last; each file replacement is atomic.
69
+
70
+ A multi-file update is not an atomic filesystem transaction. If interrupted,
71
+ the next run fails closed on mismatched ownership. Preserve edited files and
72
+ generate into a new directory to recover. Concurrent generation into the same
73
+ directory is unsupported. Local plugins and users able to race filesystem
74
+ mutations are trusted; this is not an operating-system sandbox.
@@ -0,0 +1,25 @@
1
+ # CodaPact identity
2
+
3
+ **CodaPact** joins a musical coda, code, a contract, and the idea of impact.
4
+ The tagline is **Contracts into callable tools.**
5
+
6
+ The original mark takes the coda's circle and axes and opens the ring into two
7
+ balanced boundaries. It suggests a shared contract between interchangeable
8
+ implementations. The amber center marks the point where a definition becomes
9
+ an executable call. The identity uses a single symbol, without a collage of
10
+ music notes, terminal windows, and paperwork.
11
+
12
+ | Role | Color |
13
+ | --- | --- |
14
+ | Wordmark and axes | Navy `#18283e` |
15
+ | Open ring | Teal `#15a99b` |
16
+ | Execution point | Amber `#d99732` |
17
+ | Supporting text | Slate `#52627a` |
18
+
19
+ Use [the wordmark](../branding/wordmark.svg) on light backgrounds and
20
+ [the standalone mark](../branding/mark.svg) where space is limited. SVGs use
21
+ system fonts and contain no scripts, external resources, or embedded images.
22
+
23
+ Mike selected the name on 2026-10-29. Preliminary exact-name repository and
24
+ registry searches found no obvious collisions. This is not a reservation or
25
+ legal clearance; recheck before publication.