authplane-sdk 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 (139) hide show
  1. authplane_sdk-0.1.0/.github/CODEOWNERS +1 -0
  2. authplane_sdk-0.1.0/.github/ISSUE_TEMPLATE/bug-report.md +68 -0
  3. authplane_sdk-0.1.0/.github/ISSUE_TEMPLATE/feature-request.md +38 -0
  4. authplane_sdk-0.1.0/.github/ISSUE_TEMPLATE/mcp-compatibility.md +76 -0
  5. authplane_sdk-0.1.0/.github/dependabot.yml +70 -0
  6. authplane_sdk-0.1.0/.github/pull_request_template.md +35 -0
  7. authplane_sdk-0.1.0/.github/workflows/backport-fixes.yml +125 -0
  8. authplane_sdk-0.1.0/.github/workflows/ci.yml +101 -0
  9. authplane_sdk-0.1.0/.github/workflows/cut-release.yml +213 -0
  10. authplane_sdk-0.1.0/.github/workflows/dependency-review.yml +26 -0
  11. authplane_sdk-0.1.0/.github/workflows/publish-pypi.yml +126 -0
  12. authplane_sdk-0.1.0/.github/workflows/release.yml +289 -0
  13. authplane_sdk-0.1.0/.github/workflows/scorecard.yml +58 -0
  14. authplane_sdk-0.1.0/.github/workflows/security.yml +79 -0
  15. authplane_sdk-0.1.0/.github/workflows/stale.yml +43 -0
  16. authplane_sdk-0.1.0/.gitignore +68 -0
  17. authplane_sdk-0.1.0/.pinact.yaml +16 -0
  18. authplane_sdk-0.1.0/.python-version +1 -0
  19. authplane_sdk-0.1.0/CHANGELOG.md +11 -0
  20. authplane_sdk-0.1.0/CONTRIBUTING.md +197 -0
  21. authplane_sdk-0.1.0/LICENSE +191 -0
  22. authplane_sdk-0.1.0/PKG-INFO +78 -0
  23. authplane_sdk-0.1.0/README.md +109 -0
  24. authplane_sdk-0.1.0/RELEASE_POLICY.md +39 -0
  25. authplane_sdk-0.1.0/RELEASE_SETUP.md +62 -0
  26. authplane_sdk-0.1.0/SECURITY.md +57 -0
  27. authplane_sdk-0.1.0/authplane/README.md +46 -0
  28. authplane_sdk-0.1.0/authplane/__init__.py +116 -0
  29. authplane_sdk-0.1.0/authplane/auth_provider.py +28 -0
  30. authplane_sdk-0.1.0/authplane/cache.py +78 -0
  31. authplane_sdk-0.1.0/authplane/circuit_breaker.py +90 -0
  32. authplane_sdk-0.1.0/authplane/client.py +483 -0
  33. authplane_sdk-0.1.0/authplane/credentials.py +34 -0
  34. authplane_sdk-0.1.0/authplane/docs/user-guide.md +629 -0
  35. authplane_sdk-0.1.0/authplane/dpop.py +363 -0
  36. authplane_sdk-0.1.0/authplane/dpop_verification.py +191 -0
  37. authplane_sdk-0.1.0/authplane/errors.py +363 -0
  38. authplane_sdk-0.1.0/authplane/internal/__init__.py +26 -0
  39. authplane_sdk-0.1.0/authplane/internal/cache_headers.py +55 -0
  40. authplane_sdk-0.1.0/authplane/internal/document_cache.py +205 -0
  41. authplane_sdk-0.1.0/authplane/internal/document_fetcher.py +115 -0
  42. authplane_sdk-0.1.0/authplane/internal/fetch_result.py +19 -0
  43. authplane_sdk-0.1.0/authplane/internal/jwt.py +17 -0
  44. authplane_sdk-0.1.0/authplane/internal/metadata.py +110 -0
  45. authplane_sdk-0.1.0/authplane/internal/urls.py +95 -0
  46. authplane_sdk-0.1.0/authplane/net/__init__.py +16 -0
  47. authplane_sdk-0.1.0/authplane/net/fetch_settings.py +56 -0
  48. authplane_sdk-0.1.0/authplane/net/http.py +113 -0
  49. authplane_sdk-0.1.0/authplane/net/ip_validation.py +149 -0
  50. authplane_sdk-0.1.0/authplane/net/ssrf.py +367 -0
  51. authplane_sdk-0.1.0/authplane/oauth/__init__.py +29 -0
  52. authplane_sdk-0.1.0/authplane/oauth/client_credentials.py +72 -0
  53. authplane_sdk-0.1.0/authplane/oauth/introspection.py +84 -0
  54. authplane_sdk-0.1.0/authplane/oauth/parsing.py +82 -0
  55. authplane_sdk-0.1.0/authplane/oauth/prm.py +41 -0
  56. authplane_sdk-0.1.0/authplane/oauth/revocation.py +61 -0
  57. authplane_sdk-0.1.0/authplane/oauth/token_exchange.py +92 -0
  58. authplane_sdk-0.1.0/authplane/oauth/types.py +88 -0
  59. authplane_sdk-0.1.0/authplane/py.typed +0 -0
  60. authplane_sdk-0.1.0/authplane/verifier/__init__.py +6 -0
  61. authplane_sdk-0.1.0/authplane/verifier/claims.py +84 -0
  62. authplane_sdk-0.1.0/authplane/verifier/verifier.py +413 -0
  63. authplane_sdk-0.1.0/authplane-fastmcp/.gitignore +79 -0
  64. authplane_sdk-0.1.0/authplane-fastmcp/README.md +51 -0
  65. authplane_sdk-0.1.0/authplane-fastmcp/authplane_fastmcp/__init__.py +23 -0
  66. authplane_sdk-0.1.0/authplane-fastmcp/authplane_fastmcp/auth.py +283 -0
  67. authplane_sdk-0.1.0/authplane-fastmcp/authplane_fastmcp/py.typed +0 -0
  68. authplane_sdk-0.1.0/authplane-fastmcp/authplane_fastmcp/url_elicitation.py +42 -0
  69. authplane_sdk-0.1.0/authplane-fastmcp/authplane_fastmcp/verifier.py +95 -0
  70. authplane_sdk-0.1.0/authplane-fastmcp/demo/README.md +55 -0
  71. authplane_sdk-0.1.0/authplane-fastmcp/demo/mcpserver.py +70 -0
  72. authplane_sdk-0.1.0/authplane-fastmcp/demo/run.sh +35 -0
  73. authplane_sdk-0.1.0/authplane-fastmcp/docs/user-guide.md +490 -0
  74. authplane_sdk-0.1.0/authplane-fastmcp/pyproject.toml +89 -0
  75. authplane_sdk-0.1.0/authplane-fastmcp/pyrightconfig.json +16 -0
  76. authplane_sdk-0.1.0/authplane-fastmcp/tests/conftest.py +141 -0
  77. authplane_sdk-0.1.0/authplane-fastmcp/tests/test_auth_factory.py +312 -0
  78. authplane_sdk-0.1.0/authplane-fastmcp/tests/test_integration.py +34 -0
  79. authplane_sdk-0.1.0/authplane-fastmcp/tests/test_url_elicitation.py +141 -0
  80. authplane_sdk-0.1.0/authplane-fastmcp/tests/test_verifier.py +105 -0
  81. authplane_sdk-0.1.0/authplane-mcp/.gitignore +7 -0
  82. authplane_sdk-0.1.0/authplane-mcp/.python-version +1 -0
  83. authplane_sdk-0.1.0/authplane-mcp/README.md +46 -0
  84. authplane_sdk-0.1.0/authplane-mcp/authplane_mcp/__init__.py +25 -0
  85. authplane_sdk-0.1.0/authplane-mcp/authplane_mcp/auth.py +327 -0
  86. authplane_sdk-0.1.0/authplane-mcp/authplane_mcp/py.typed +0 -0
  87. authplane_sdk-0.1.0/authplane-mcp/authplane_mcp/url_elicitation.py +42 -0
  88. authplane_sdk-0.1.0/authplane-mcp/authplane_mcp/verifier.py +71 -0
  89. authplane_sdk-0.1.0/authplane-mcp/demo/README.md +65 -0
  90. authplane_sdk-0.1.0/authplane-mcp/demo/mcpserver.py +117 -0
  91. authplane_sdk-0.1.0/authplane-mcp/demo/run.sh +28 -0
  92. authplane_sdk-0.1.0/authplane-mcp/docs/user-guide.md +517 -0
  93. authplane_sdk-0.1.0/authplane-mcp/pyproject.toml +91 -0
  94. authplane_sdk-0.1.0/authplane-mcp/pyrightconfig.json +16 -0
  95. authplane_sdk-0.1.0/authplane-mcp/tests/test_auth.py +332 -0
  96. authplane_sdk-0.1.0/authplane-mcp/tests/test_url_elicitation.py +139 -0
  97. authplane_sdk-0.1.0/authplane-mcp/tests/test_verifier.py +78 -0
  98. authplane_sdk-0.1.0/conformance-tests/README.md +85 -0
  99. authplane_sdk-0.1.0/conformance-tests/conftest.py +310 -0
  100. authplane_sdk-0.1.0/conformance-tests/test_catalog_alignment.py +46 -0
  101. authplane_sdk-0.1.0/conformance-tests/test_jwt_and_dpop_conformance.py +1372 -0
  102. authplane_sdk-0.1.0/conformance-tests/test_oauth_protocol_conformance.py +621 -0
  103. authplane_sdk-0.1.0/conformance-tests/test_rfc8414_conformance.py +276 -0
  104. authplane_sdk-0.1.0/llm-full.txt +387 -0
  105. authplane_sdk-0.1.0/llm.txt +86 -0
  106. authplane_sdk-0.1.0/pyproject.toml +107 -0
  107. authplane_sdk-0.1.0/pyrightconfig.json +16 -0
  108. authplane_sdk-0.1.0/scripts/backport-fixes.sh +175 -0
  109. authplane_sdk-0.1.0/scripts/manual-e2e-setup.sh +47 -0
  110. authplane_sdk-0.1.0/scripts/manual-e2e-smoke.sh +180 -0
  111. authplane_sdk-0.1.0/tests/conftest.py +279 -0
  112. authplane_sdk-0.1.0/tests/internal/test_cache_headers.py +144 -0
  113. authplane_sdk-0.1.0/tests/internal/test_document_cache.py +446 -0
  114. authplane_sdk-0.1.0/tests/internal/test_jwks.py +486 -0
  115. authplane_sdk-0.1.0/tests/internal/test_jwks_fetcher.py +222 -0
  116. authplane_sdk-0.1.0/tests/internal/test_jwks_key_lookup.py +127 -0
  117. authplane_sdk-0.1.0/tests/internal/test_metadata.py +284 -0
  118. authplane_sdk-0.1.0/tests/internal/test_urls.py +56 -0
  119. authplane_sdk-0.1.0/tests/net/test_fetch_settings.py +75 -0
  120. authplane_sdk-0.1.0/tests/net/test_http.py +21 -0
  121. authplane_sdk-0.1.0/tests/net/test_ssrf.py +463 -0
  122. authplane_sdk-0.1.0/tests/net/test_ssrf_edge_cases.py +546 -0
  123. authplane_sdk-0.1.0/tests/oauth/test_client_credentials.py +73 -0
  124. authplane_sdk-0.1.0/tests/oauth/test_introspection.py +233 -0
  125. authplane_sdk-0.1.0/tests/oauth/test_prm.py +76 -0
  126. authplane_sdk-0.1.0/tests/oauth/test_revoke.py +45 -0
  127. authplane_sdk-0.1.0/tests/oauth/test_token_exchange.py +513 -0
  128. authplane_sdk-0.1.0/tests/test_cache.py +81 -0
  129. authplane_sdk-0.1.0/tests/test_circuit_breaker.py +75 -0
  130. authplane_sdk-0.1.0/tests/test_client.py +118 -0
  131. authplane_sdk-0.1.0/tests/test_dev_mode.py +349 -0
  132. authplane_sdk-0.1.0/tests/test_dpop_and_security.py +575 -0
  133. authplane_sdk-0.1.0/tests/test_errors.py +109 -0
  134. authplane_sdk-0.1.0/tests/test_protocol_and_http_edges.py +215 -0
  135. authplane_sdk-0.1.0/tests/verifier/test_claims.py +250 -0
  136. authplane_sdk-0.1.0/tests/verifier/test_revocation.py +372 -0
  137. authplane_sdk-0.1.0/tests/verifier/test_verifier.py +909 -0
  138. authplane_sdk-0.1.0/tests/verifier/test_verifier_coverage.py +187 -0
  139. authplane_sdk-0.1.0/tests/verifier/test_verifier_edge_cases.py +195 -0
@@ -0,0 +1 @@
1
+ * @AuthPlane/authplane-eng
@@ -0,0 +1,68 @@
1
+ ---
2
+ name: Bug Report
3
+ about: Report a bug in the Authplane Python SDK or an adapter
4
+ title: "[Bug] "
5
+ labels: bug
6
+ assignees: ""
7
+ ---
8
+
9
+ ## Description
10
+
11
+ A clear description of the bug.
12
+
13
+ ## Affected Package
14
+
15
+ - [ ] `authplane-sdk`
16
+ - [ ] `authplane-mcp`
17
+ - [ ] `authplane-fastmcp`
18
+
19
+ ## Steps to Reproduce
20
+
21
+ 1. Install package(s) ...
22
+ 2. Configure / call ...
23
+ 3. Observe ...
24
+
25
+ Minimal reproducible code snippet:
26
+
27
+ ```python
28
+ # paste here
29
+ ```
30
+
31
+ ## Expected Behavior
32
+
33
+ What you expected to happen.
34
+
35
+ ## Actual Behavior
36
+
37
+ What actually happened. Include exception traceback, HTTP status codes, and relevant log output.
38
+
39
+ ## Environment
40
+
41
+ - **Package version:** (e.g., `authplane-sdk==1.2.3`)
42
+ - **Python version:** (`python --version`)
43
+ - **OS:** (e.g., Ubuntu 22.04, macOS 14)
44
+ - **Framework (if adapter):** (e.g., FastAPI 0.115, FastMCP 2.x, MCP SDK 1.27)
45
+ - **Authplane `authserver` version / issuer:** (if relevant)
46
+
47
+ ## Configuration
48
+
49
+ Relevant SDK configuration (redact secrets):
50
+
51
+ ```python
52
+ # paste here
53
+ ```
54
+
55
+ ## Logs
56
+
57
+ <details>
58
+ <summary>Relevant logs</summary>
59
+
60
+ ```
61
+ (paste relevant logs here — redact any sensitive data, especially tokens)
62
+ ```
63
+
64
+ </details>
65
+
66
+ ## Additional Context
67
+
68
+ Any other relevant information.
@@ -0,0 +1,38 @@
1
+ ---
2
+ name: Feature Request
3
+ about: Suggest a new feature for the Authplane Python SDK or an adapter
4
+ title: "[Feature] "
5
+ labels: enhancement
6
+ assignees: ""
7
+ ---
8
+
9
+ ## Affected Package
10
+
11
+ - [ ] `authplane-sdk`
12
+ - [ ] `authplane-mcp`
13
+ - [ ] `authplane-fastmcp`
14
+ - [ ] New package
15
+
16
+ ## Problem
17
+
18
+ Describe the problem this feature would solve. What are you trying to do that you can't do today?
19
+
20
+ ## Proposed Solution
21
+
22
+ Describe your proposed solution. How should this work? Include a rough API sketch if possible:
23
+
24
+ ```python
25
+ # example usage
26
+ ```
27
+
28
+ ## Alternatives Considered
29
+
30
+ What alternatives have you considered? Why is this approach better?
31
+
32
+ ## Use Case
33
+
34
+ Describe the use case. Who benefits from this feature? Is this blocking integration with a specific framework or service?
35
+
36
+ ## Additional Context
37
+
38
+ Any other relevant information, links to RFCs or specs, or examples from other projects.
@@ -0,0 +1,76 @@
1
+ ---
2
+ name: MCP Compatibility Report
3
+ about: Report compatibility of an MCP client or server with the Authplane Python adapters
4
+ title: "[Compat] <Client or Server> <Version>"
5
+ labels: compatibility, mcp
6
+ assignees: ""
7
+ ---
8
+
9
+ ## Adapter
10
+
11
+ - [ ] `authplane-mcp` (official MCP Python SDK adapter)
12
+ - [ ] `authplane-fastmcp` (FastMCP adapter)
13
+
14
+ ## MCP Library Version
15
+
16
+ - **Library:** (e.g., `mcp`, `fastmcp`)
17
+ - **Version:**
18
+ - **Transport:** (e.g., streamable-http, stdio)
19
+
20
+ ## MCP Client (if reporting a client-side issue)
21
+
22
+ - **Client:** (e.g., Claude Code, MCP Inspector, Cursor)
23
+ - **Version:**
24
+ - **Platform:** (macOS / Linux / Windows)
25
+
26
+ ## Authplane SDK Version
27
+
28
+ - `authplane-sdk`:
29
+ - `authplane-mcp` / `authplane-fastmcp`:
30
+ - `authserver` (issuer):
31
+
32
+ ## Description
33
+
34
+ Brief summary of the compatibility observation.
35
+
36
+ ## Compatibility Scenarios
37
+
38
+ Check each that was tested. Mark pass / fail / skip.
39
+
40
+ - [ ] **JWT validation** — protected tool accepts valid bearer token
41
+ - [ ] **Scope enforcement** — tool-specific scope required and checked
42
+ - [ ] **DPoP-bound tokens** — proof-of-possession verified end-to-end (if applicable)
43
+ - [ ] **Token refresh** — client refreshes without losing session
44
+ - [ ] **Metadata discovery** — adapter surfaces `WWW-Authenticate` / protected-resource metadata correctly
45
+ - [ ] **Error handling** — expired, revoked, malformed tokens produce the expected error shape
46
+
47
+ ## Reproduction Steps
48
+
49
+ 1. Install adapter ...
50
+ 2. Configure MCP server with Authplane middleware ...
51
+ 3. Connect client ...
52
+ 4. Observe results
53
+
54
+ ## Logs
55
+
56
+ <details>
57
+ <summary>Server logs (adapter)</summary>
58
+
59
+ ```
60
+ (paste relevant logs here)
61
+ ```
62
+
63
+ </details>
64
+
65
+ <details>
66
+ <summary>Client logs</summary>
67
+
68
+ ```
69
+ (paste relevant logs here)
70
+ ```
71
+
72
+ </details>
73
+
74
+ ## Additional Context
75
+
76
+ Screenshots, network traces, spec references, or upstream issues.
@@ -0,0 +1,70 @@
1
+ version: 2
2
+
3
+ updates:
4
+ # Python SDK (root)
5
+ - package-ecosystem: pip
6
+ directory: /
7
+ schedule:
8
+ interval: weekly
9
+ day: monday
10
+ labels:
11
+ - dependencies
12
+ - python
13
+ commit-message:
14
+ prefix: "deps"
15
+ open-pull-requests-limit: 10
16
+ groups:
17
+ pip-all:
18
+ patterns:
19
+ - "*"
20
+
21
+ # Python MCP adapter
22
+ - package-ecosystem: pip
23
+ directory: /authplane-mcp
24
+ schedule:
25
+ interval: weekly
26
+ day: monday
27
+ labels:
28
+ - dependencies
29
+ - python
30
+ commit-message:
31
+ prefix: "deps"
32
+ open-pull-requests-limit: 10
33
+ groups:
34
+ pip-all:
35
+ patterns:
36
+ - "*"
37
+
38
+ # Python FastMCP adapter
39
+ - package-ecosystem: pip
40
+ directory: /authplane-fastmcp
41
+ schedule:
42
+ interval: weekly
43
+ day: monday
44
+ labels:
45
+ - dependencies
46
+ - python
47
+ commit-message:
48
+ prefix: "deps"
49
+ open-pull-requests-limit: 10
50
+ groups:
51
+ pip-all:
52
+ patterns:
53
+ - "*"
54
+
55
+ # GitHub Actions
56
+ - package-ecosystem: github-actions
57
+ directory: /
58
+ schedule:
59
+ interval: weekly
60
+ day: monday
61
+ labels:
62
+ - dependencies
63
+ - ci
64
+ commit-message:
65
+ prefix: "ci"
66
+ open-pull-requests-limit: 5
67
+ groups:
68
+ actions-all:
69
+ patterns:
70
+ - "*"
@@ -0,0 +1,35 @@
1
+ ## Summary
2
+
3
+ Brief description of what this PR does and why.
4
+
5
+ ## Linked Issue
6
+
7
+ <!-- e.g., Fixes #123 -->
8
+
9
+ ## Changes
10
+
11
+ -
12
+
13
+ ## Affected Packages
14
+
15
+ - [ ] `authplane-sdk` (root)
16
+ - [ ] `authplane-mcp`
17
+ - [ ] `authplane-fastmcp`
18
+ - [ ] None (infra / docs / CI only)
19
+
20
+ ## Test Plan
21
+
22
+ How was this tested? Include relevant test names or manual verification steps.
23
+
24
+ ## Checklist
25
+
26
+ - [ ] `ruff check .` passes
27
+ - [ ] `ruff format --check .` passes
28
+ - [ ] `pyright` passes (SDK root)
29
+ - [ ] `pytest` passes for affected packages
30
+ - [ ] Coverage unchanged or improved (≥ 80%)
31
+ - [ ] Tests added for new functionality
32
+ - [ ] Documentation updated (if applicable)
33
+ - [ ] `CHANGELOG.md` entry added under `[Unreleased]` (if user-facing)
34
+ - [ ] New workflow actions are SHA-pinned (`pinact run` after changes)
35
+ - [ ] No token values, secrets, or key material in logs or test fixtures
@@ -0,0 +1,125 @@
1
+ name: Backport fixes to default branch
2
+
3
+ # Thin wrapper around scripts/backport-fixes.sh for maintainers who
4
+ # prefer dispatching from the Actions UI. Behavior:
5
+ #
6
+ # - Happy path (no conflicts): runs the script, pushes the backport
7
+ # branch, opens a PR against the target.
8
+ # - Any conflict: cherry-pick fails, the workflow fails loudly. Re-run
9
+ # the script locally to finish:
10
+ # scripts/backport-fixes.sh --from <fromBranch> --to <toBranch>
11
+ # and resolve conflicts via git's native cherry-pick state machine.
12
+ #
13
+ # fromBranch can be a branch (release/v*, hotfix/v*) or a tag (vX.Y.Z).
14
+ # After the release workflow runs, the release branch is deleted — use the
15
+ # tag as the fromBranch instead.
16
+
17
+ on:
18
+ workflow_dispatch:
19
+ inputs:
20
+ fromBranch:
21
+ description: 'Source ref on origin (branch or tag, e.g. release/v0.6.0, hotfix/v0.5.1, or v0.6.0). Do not include origin/.'
22
+ required: true
23
+ type: string
24
+ toBranch:
25
+ description: 'Target branch on origin. Leave empty to use the repository default branch.'
26
+ required: false
27
+ type: string
28
+ default: ''
29
+
30
+ concurrency:
31
+ group: backport-${{ inputs.fromBranch }}-to-${{ inputs.toBranch }}
32
+ cancel-in-progress: false
33
+
34
+ jobs:
35
+ backport:
36
+ runs-on: ubuntu-latest
37
+ permissions:
38
+ contents: write
39
+ pull-requests: write
40
+ steps:
41
+ - name: Resolve target branch
42
+ id: target
43
+ run: |
44
+ to="${{ inputs.toBranch }}"
45
+ if [[ -z "$to" ]]; then
46
+ to="${{ github.event.repository.default_branch }}"
47
+ fi
48
+ echo "to=$to" >> "$GITHUB_OUTPUT"
49
+
50
+ - name: Check out repo with full history
51
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
52
+ with:
53
+ fetch-depth: 0
54
+
55
+ - name: Configure git author
56
+ run: |
57
+ git config user.name "github-actions[bot]"
58
+ git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
59
+
60
+ - name: Run backport script
61
+ id: run
62
+ run: |
63
+ ./scripts/backport-fixes.sh \
64
+ --from "${{ inputs.fromBranch }}" \
65
+ --to "${{ steps.target.outputs.to }}"
66
+ echo "branch=$(git rev-parse --abbrev-ref HEAD)" >> "$GITHUB_OUTPUT"
67
+
68
+ - name: Push backport branch
69
+ if: startsWith(steps.run.outputs.branch, 'backport/')
70
+ run: |
71
+ git push origin "${{ steps.run.outputs.branch }}"
72
+
73
+ - name: Open pull request
74
+ if: startsWith(steps.run.outputs.branch, 'backport/')
75
+ env:
76
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
77
+ run: |
78
+ from="${{ inputs.fromBranch }}"
79
+ to="${{ steps.target.outputs.to }}"
80
+ branch="${{ steps.run.outputs.branch }}"
81
+ title="chore: backport from $from to $to"
82
+ body=$(cat <<EOF
83
+ Automated backport from \`$from\` to \`$to\`.
84
+
85
+ All candidate commits applied cleanly. If the set looks wrong,
86
+ curate this branch locally:
87
+
88
+ \`\`\`
89
+ git fetch origin
90
+ git checkout $branch
91
+ git rebase -i origin/$to # drop commits you don't want
92
+ git push --force-with-lease
93
+ \`\`\`
94
+
95
+ **Merge with "Rebase and merge"** (not squash) — preserves
96
+ per-commit \`-x\` attribution on \`$to\`.
97
+ EOF
98
+ )
99
+ gh pr create \
100
+ --base "$to" \
101
+ --head "$branch" \
102
+ --title "$title" \
103
+ --body "$body"
104
+
105
+ - name: Nothing to backport notice
106
+ if: steps.run.outputs.branch != '' && !startsWith(steps.run.outputs.branch, 'backport/')
107
+ run: |
108
+ echo "::notice::Nothing to backport — all commits on origin/${{ inputs.fromBranch }} are already present on origin/${{ steps.target.outputs.to }}."
109
+
110
+ - name: Conflict guidance (on failure)
111
+ if: failure()
112
+ run: |
113
+ {
114
+ echo "### Backport failed"
115
+ echo ""
116
+ echo "At least one cherry-pick conflicted. Finish manually:"
117
+ echo ""
118
+ echo '```'
119
+ echo "scripts/backport-fixes.sh \\"
120
+ echo " --from ${{ inputs.fromBranch }} \\"
121
+ echo " --to ${{ steps.target.outputs.to }}"
122
+ echo '```'
123
+ echo ""
124
+ echo "Then resolve conflicts and \`git cherry-pick --continue\` (or \`--skip\` / \`--abort\`)."
125
+ } >> "$GITHUB_STEP_SUMMARY"
@@ -0,0 +1,101 @@
1
+ name: CI
2
+
3
+ on:
4
+ pull_request:
5
+ push:
6
+ branches:
7
+ - main
8
+
9
+ jobs:
10
+ quality:
11
+ runs-on: ubuntu-latest
12
+ strategy:
13
+ fail-fast: false
14
+ matrix:
15
+ python-version: ["3.11", "3.12", "3.13"]
16
+ package:
17
+ - root
18
+ - authplane-mcp
19
+ - authplane-fastmcp
20
+ steps:
21
+ - name: Checkout
22
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
23
+
24
+ # AuthPlane/conformance is the public sibling repo carrying the shared
25
+ # oauth-sdk-conformance-catalog.yaml. Without it, conformance-tests
26
+ # cannot run.
27
+ - name: Check out shared conformance catalog
28
+ if: matrix.package == 'root'
29
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
30
+ with:
31
+ repository: AuthPlane/conformance
32
+ path: conformance
33
+ fetch-depth: 1
34
+
35
+ - name: Setup Python
36
+ uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
37
+ with:
38
+ python-version: ${{ matrix.python-version }}
39
+
40
+ - name: Install tooling
41
+ run: |
42
+ python -m pip install --upgrade pip
43
+ pip install build twine
44
+
45
+ - name: Install package dependencies
46
+ run: |
47
+ if [ "${{ matrix.package }}" = "root" ]; then
48
+ pip install -e ".[dev]"
49
+ else
50
+ # Adapters depend on authplane; install local SDK package first.
51
+ pip install -e .
52
+ pip install -e "${{ matrix.package }}[dev]"
53
+ fi
54
+
55
+ - name: Ruff check
56
+ run: |
57
+ if [ "${{ matrix.package }}" = "root" ]; then
58
+ ruff check .
59
+ else
60
+ ruff check "${{ matrix.package }}"
61
+ fi
62
+
63
+ - name: Ruff format check
64
+ run: |
65
+ if [ "${{ matrix.package }}" = "root" ]; then
66
+ ruff format --check .
67
+ else
68
+ ruff format --check "${{ matrix.package }}"
69
+ fi
70
+
71
+ - name: Pyright (SDK only)
72
+ if: matrix.package == 'root'
73
+ run: pyright
74
+
75
+ - name: Test and coverage
76
+ env:
77
+ CONFORMANCE_CATALOG_PATH: ${{ github.workspace }}/conformance/oauth-sdk-conformance-catalog.yaml
78
+ run: |
79
+ if [ "${{ matrix.package }}" = "root" ]; then
80
+ coverage run -m pytest tests conformance-tests && coverage report
81
+ else
82
+ cd "${{ matrix.package }}"
83
+ coverage run -m pytest tests && coverage report
84
+ fi
85
+
86
+ - name: Build package artifacts
87
+ run: |
88
+ if [ "${{ matrix.package }}" = "root" ]; then
89
+ python -m build
90
+ else
91
+ cd "${{ matrix.package }}"
92
+ python -m build
93
+ fi
94
+
95
+ - name: Validate package metadata
96
+ run: |
97
+ if [ "${{ matrix.package }}" = "root" ]; then
98
+ twine check dist/*
99
+ else
100
+ twine check "${{ matrix.package }}/dist/*"
101
+ fi