baobab-auth-security 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 (178) hide show
  1. baobab_auth_security-0.1.0/.cursor/rules/000-core.mdc +23 -0
  2. baobab_auth_security-0.1.0/.editorconfig +18 -0
  3. baobab_auth_security-0.1.0/.env.example +9 -0
  4. baobab_auth_security-0.1.0/.gitattributes +18 -0
  5. baobab_auth_security-0.1.0/.github/ISSUE_TEMPLATE/01-user-story.yml +32 -0
  6. baobab_auth_security-0.1.0/.github/ISSUE_TEMPLATE/02-feature.yml +32 -0
  7. baobab_auth_security-0.1.0/.github/ISSUE_TEMPLATE/03-task.yml +34 -0
  8. baobab_auth_security-0.1.0/.github/ISSUE_TEMPLATE/config.yml +1 -0
  9. baobab_auth_security-0.1.0/.github/dependabot.yml +20 -0
  10. baobab_auth_security-0.1.0/.github/pull_request_template.md +21 -0
  11. baobab_auth_security-0.1.0/.github/workflows/ci.yml +145 -0
  12. baobab_auth_security-0.1.0/.github/workflows/release.yml +114 -0
  13. baobab_auth_security-0.1.0/.gitignore +52 -0
  14. baobab_auth_security-0.1.0/.pre-commit-config.yaml +46 -0
  15. baobab_auth_security-0.1.0/AGENTS.md +109 -0
  16. baobab_auth_security-0.1.0/CHANGELOG.md +33 -0
  17. baobab_auth_security-0.1.0/CLAUDE.md +15 -0
  18. baobab_auth_security-0.1.0/CONTRIBUTING.md +36 -0
  19. baobab_auth_security-0.1.0/LICENSE +21 -0
  20. baobab_auth_security-0.1.0/Makefile +43 -0
  21. baobab_auth_security-0.1.0/PKG-INFO +257 -0
  22. baobab_auth_security-0.1.0/README.md +196 -0
  23. baobab_auth_security-0.1.0/SECURITY.md +27 -0
  24. baobab_auth_security-0.1.0/docs/_static/.gitkeep +0 -0
  25. baobab_auth_security-0.1.0/docs/api/index.rst +10 -0
  26. baobab_auth_security-0.1.0/docs/conf.py +30 -0
  27. baobab_auth_security-0.1.0/docs/guides/how-to/ajouter-une-classe.rst +25 -0
  28. baobab_auth_security-0.1.0/docs/guides/how-to/architecture-ecosysteme.rst +52 -0
  29. baobab_auth_security-0.1.0/docs/guides/how-to/hash-mot-de-passe.rst +46 -0
  30. baobab_auth_security-0.1.0/docs/guides/how-to/jwks.rst +42 -0
  31. baobab_auth_security-0.1.0/docs/guides/how-to/jwt.rst +60 -0
  32. baobab_auth_security-0.1.0/docs/guides/how-to/refresh-tokens.rst +42 -0
  33. baobab_auth_security-0.1.0/docs/guides/how-to/revocation.rst +51 -0
  34. baobab_auth_security-0.1.0/docs/guides/how-to/rotation-cles.rst +47 -0
  35. baobab_auth_security-0.1.0/docs/guides/index.rst +26 -0
  36. baobab_auth_security-0.1.0/docs/guides/tutorials/premiers-pas.rst +26 -0
  37. baobab_auth_security-0.1.0/docs/index.rst +23 -0
  38. baobab_auth_security-0.1.0/docs/specifications/cahier-des-charges/README.md +13 -0
  39. baobab_auth_security-0.1.0/docs/specifications/cahier-des-charges/cahier_des_charges.md +2166 -0
  40. baobab_auth_security-0.1.0/docs/specifications/glossary.rst +16 -0
  41. baobab_auth_security-0.1.0/docs/specifications/index.rst +36 -0
  42. baobab_auth_security-0.1.0/docs/specifications/us/US-001-socle/FEAT-001.1-structure-package.rst +29 -0
  43. baobab_auth_security-0.1.0/docs/specifications/us/US-001-socle/index.rst +32 -0
  44. baobab_auth_security-0.1.0/docs/specifications/us/US-002-mots-de-passe/FEAT-002.1-modeles-password.rst +25 -0
  45. baobab_auth_security-0.1.0/docs/specifications/us/US-002-mots-de-passe/FEAT-002.2-argon2-password-hasher.rst +27 -0
  46. baobab_auth_security-0.1.0/docs/specifications/us/US-002-mots-de-passe/index.rst +32 -0
  47. baobab_auth_security-0.1.0/docs/specifications/us/US-003-refresh-tokens/FEAT-003.1-refresh-token-generator.rst +23 -0
  48. baobab_auth_security-0.1.0/docs/specifications/us/US-003-refresh-tokens/FEAT-003.2-refresh-token-hasher.rst +23 -0
  49. baobab_auth_security-0.1.0/docs/specifications/us/US-003-refresh-tokens/index.rst +32 -0
  50. baobab_auth_security-0.1.0/docs/specifications/us/US-004-cles/FEAT-004.1-modeles-cles.rst +23 -0
  51. baobab_auth_security-0.1.0/docs/specifications/us/US-004-cles/FEAT-004.2-key-providers.rst +25 -0
  52. baobab_auth_security-0.1.0/docs/specifications/us/US-004-cles/index.rst +32 -0
  53. baobab_auth_security-0.1.0/docs/specifications/us/US-005-jwks/FEAT-005.1-jwks-provider.rst +25 -0
  54. baobab_auth_security-0.1.0/docs/specifications/us/US-005-jwks/index.rst +30 -0
  55. baobab_auth_security-0.1.0/docs/specifications/us/US-006-jwt/FEAT-006.1-modeles-jwt.rst +23 -0
  56. baobab_auth_security-0.1.0/docs/specifications/us/US-006-jwt/FEAT-006.2-jwt-encoder-decoder.rst +24 -0
  57. baobab_auth_security-0.1.0/docs/specifications/us/US-006-jwt/FEAT-006.3-jwt-validator.rst +24 -0
  58. baobab_auth_security-0.1.0/docs/specifications/us/US-006-jwt/index.rst +33 -0
  59. baobab_auth_security-0.1.0/docs/specifications/us/US-007-rotation-cles/FEAT-007.1-key-rotation-service.rst +24 -0
  60. baobab_auth_security-0.1.0/docs/specifications/us/US-007-rotation-cles/index.rst +31 -0
  61. baobab_auth_security-0.1.0/docs/specifications/us/US-008-revocation/FEAT-008.1-token-revocation-checker.rst +24 -0
  62. baobab_auth_security-0.1.0/docs/specifications/us/US-008-revocation/index.rst +30 -0
  63. baobab_auth_security-0.1.0/docs/specifications/us/US-009-integration-core/FEAT-009.1-core-adapters.rst +24 -0
  64. baobab_auth_security-0.1.0/docs/specifications/us/US-009-integration-core/index.rst +31 -0
  65. baobab_auth_security-0.1.0/docs/specifications/us/US-010-documentation/FEAT-010.1-docs-et-exemples.rst +26 -0
  66. baobab_auth_security-0.1.0/docs/specifications/us/US-010-documentation/index.rst +31 -0
  67. baobab_auth_security-0.1.0/docs/specifications/us/index.rst +16 -0
  68. baobab_auth_security-0.1.0/docs/workflow/README.md +66 -0
  69. baobab_auth_security-0.1.0/docs/workflow/SETUP.md +109 -0
  70. baobab_auth_security-0.1.0/docs/workflow/gates.md +38 -0
  71. baobab_auth_security-0.1.0/docs/workflow/handoff.md +53 -0
  72. baobab_auth_security-0.1.0/docs/workflow/prompts/init.md +42 -0
  73. baobab_auth_security-0.1.0/docs/workflow/prompts/orchestration.md +25 -0
  74. baobab_auth_security-0.1.0/docs/workflow/roles/00-orchestrateur.md +24 -0
  75. baobab_auth_security-0.1.0/docs/workflow/roles/01-product-owner.md +22 -0
  76. baobab_auth_security-0.1.0/docs/workflow/roles/02-architecte.md +22 -0
  77. baobab_auth_security-0.1.0/docs/workflow/roles/03-developpeur.md +23 -0
  78. baobab_auth_security-0.1.0/docs/workflow/roles/04-relecteur.md +24 -0
  79. baobab_auth_security-0.1.0/docs/workflow/roles/05-securite.md +26 -0
  80. baobab_auth_security-0.1.0/docs/workflow/roles/06-release-manager.md +27 -0
  81. baobab_auth_security-0.1.0/docs/workflow/roles/07-support.md +22 -0
  82. baobab_auth_security-0.1.0/examples/generate_jwks.py +26 -0
  83. baobab_auth_security-0.1.0/examples/generate_token.py +40 -0
  84. baobab_auth_security-0.1.0/examples/rotate_key.py +48 -0
  85. baobab_auth_security-0.1.0/examples/validate_token.py +42 -0
  86. baobab_auth_security-0.1.0/examples/verify_password.py +22 -0
  87. baobab_auth_security-0.1.0/pyproject.toml +127 -0
  88. baobab_auth_security-0.1.0/scripts/bootstrap_github_issues.py +214 -0
  89. baobab_auth_security-0.1.0/scripts/setup_github.sh +58 -0
  90. baobab_auth_security-0.1.0/src/baobab_auth_security/__init__.py +10 -0
  91. baobab_auth_security-0.1.0/src/baobab_auth_security/config/__init__.py +7 -0
  92. baobab_auth_security-0.1.0/src/baobab_auth_security/config/jwt_security_settings.py +44 -0
  93. baobab_auth_security-0.1.0/src/baobab_auth_security/config/key_settings.py +32 -0
  94. baobab_auth_security-0.1.0/src/baobab_auth_security/config/refresh_token_settings.py +34 -0
  95. baobab_auth_security-0.1.0/src/baobab_auth_security/exceptions/__init__.py +5 -0
  96. baobab_auth_security-0.1.0/src/baobab_auth_security/exceptions/baobab_auth_security_error.py +10 -0
  97. baobab_auth_security-0.1.0/src/baobab_auth_security/integration/__init__.py +17 -0
  98. baobab_auth_security-0.1.0/src/baobab_auth_security/integration/claims_mapper.py +48 -0
  99. baobab_auth_security-0.1.0/src/baobab_auth_security/integration/core_integration_gaps.py +25 -0
  100. baobab_auth_security-0.1.0/src/baobab_auth_security/integration/core_password_hasher_adapter.py +50 -0
  101. baobab_auth_security-0.1.0/src/baobab_auth_security/integration/core_token_provider_adapter.py +25 -0
  102. baobab_auth_security-0.1.0/src/baobab_auth_security/keys/__init__.py +51 -0
  103. baobab_auth_security-0.1.0/src/baobab_auth_security/keys/exceptions.py +80 -0
  104. baobab_auth_security-0.1.0/src/baobab_auth_security/keys/in_memory_key_provider.py +131 -0
  105. baobab_auth_security-0.1.0/src/baobab_auth_security/keys/jwk.py +67 -0
  106. baobab_auth_security-0.1.0/src/baobab_auth_security/keys/jwks.py +24 -0
  107. baobab_auth_security-0.1.0/src/baobab_auth_security/keys/jwks_provider.py +87 -0
  108. baobab_auth_security-0.1.0/src/baobab_auth_security/keys/key_algorithm.py +14 -0
  109. baobab_auth_security-0.1.0/src/baobab_auth_security/keys/key_generator.py +65 -0
  110. baobab_auth_security-0.1.0/src/baobab_auth_security/keys/key_pair.py +43 -0
  111. baobab_auth_security-0.1.0/src/baobab_auth_security/keys/key_provider.py +35 -0
  112. baobab_auth_security-0.1.0/src/baobab_auth_security/keys/key_rotation_service.py +130 -0
  113. baobab_auth_security-0.1.0/src/baobab_auth_security/keys/key_status.py +15 -0
  114. baobab_auth_security-0.1.0/src/baobab_auth_security/keys/pem_loader.py +45 -0
  115. baobab_auth_security-0.1.0/src/baobab_auth_security/password/__init__.py +27 -0
  116. baobab_auth_security-0.1.0/src/baobab_auth_security/password/argon2_password_hasher.py +117 -0
  117. baobab_auth_security-0.1.0/src/baobab_auth_security/password/exceptions.py +38 -0
  118. baobab_auth_security-0.1.0/src/baobab_auth_security/password/password_hash_policy.py +45 -0
  119. baobab_auth_security-0.1.0/src/baobab_auth_security/password/password_hash_result.py +32 -0
  120. baobab_auth_security-0.1.0/src/baobab_auth_security/password/password_hasher.py +43 -0
  121. baobab_auth_security-0.1.0/src/baobab_auth_security/password/password_verification_result.py +22 -0
  122. baobab_auth_security-0.1.0/src/baobab_auth_security/refresh_tokens/__init__.py +21 -0
  123. baobab_auth_security-0.1.0/src/baobab_auth_security/refresh_tokens/exceptions.py +31 -0
  124. baobab_auth_security-0.1.0/src/baobab_auth_security/refresh_tokens/refresh_token_generator.py +43 -0
  125. baobab_auth_security-0.1.0/src/baobab_auth_security/refresh_tokens/refresh_token_hasher.py +81 -0
  126. baobab_auth_security-0.1.0/src/baobab_auth_security/refresh_tokens/refresh_token_result.py +40 -0
  127. baobab_auth_security-0.1.0/src/baobab_auth_security/revocation/__init__.py +8 -0
  128. baobab_auth_security-0.1.0/src/baobab_auth_security/revocation/in_memory_revocation_checker.py +75 -0
  129. baobab_auth_security-0.1.0/src/baobab_auth_security/revocation/token_revocation_checker.py +39 -0
  130. baobab_auth_security-0.1.0/src/baobab_auth_security/tokens/__init__.py +51 -0
  131. baobab_auth_security-0.1.0/src/baobab_auth_security/tokens/exceptions.py +101 -0
  132. baobab_auth_security-0.1.0/src/baobab_auth_security/tokens/jwt_decoder.py +162 -0
  133. baobab_auth_security-0.1.0/src/baobab_auth_security/tokens/jwt_encoder.py +71 -0
  134. baobab_auth_security-0.1.0/src/baobab_auth_security/tokens/jwt_token_provider.py +68 -0
  135. baobab_auth_security-0.1.0/src/baobab_auth_security/tokens/jwt_validation_result.py +30 -0
  136. baobab_auth_security-0.1.0/src/baobab_auth_security/tokens/jwt_validator.py +150 -0
  137. baobab_auth_security-0.1.0/src/baobab_auth_security/tokens/token_claims.py +78 -0
  138. baobab_auth_security-0.1.0/src/baobab_auth_security/tokens/token_pair.py +32 -0
  139. baobab_auth_security-0.1.0/src/baobab_auth_security/tokens/token_type.py +14 -0
  140. baobab_auth_security-0.1.0/src/baobab_auth_security/version.py +8 -0
  141. baobab_auth_security-0.1.0/tests/baobab_auth_security/config/test_jwt_security_settings.py +37 -0
  142. baobab_auth_security-0.1.0/tests/baobab_auth_security/config/test_key_settings.py +20 -0
  143. baobab_auth_security-0.1.0/tests/baobab_auth_security/config/test_refresh_token_settings.py +28 -0
  144. baobab_auth_security-0.1.0/tests/baobab_auth_security/exceptions/test_baobab_auth_security_error.py +18 -0
  145. baobab_auth_security-0.1.0/tests/baobab_auth_security/integration/test_claims_mapper.py +50 -0
  146. baobab_auth_security-0.1.0/tests/baobab_auth_security/integration/test_core_adapters.py +54 -0
  147. baobab_auth_security-0.1.0/tests/baobab_auth_security/integration/test_key_rotation_integration.py +68 -0
  148. baobab_auth_security-0.1.0/tests/baobab_auth_security/integration/test_revocation_integration.py +92 -0
  149. baobab_auth_security-0.1.0/tests/baobab_auth_security/keys/test_in_memory_key_provider.py +57 -0
  150. baobab_auth_security-0.1.0/tests/baobab_auth_security/keys/test_jwk.py +50 -0
  151. baobab_auth_security-0.1.0/tests/baobab_auth_security/keys/test_jwks.py +33 -0
  152. baobab_auth_security-0.1.0/tests/baobab_auth_security/keys/test_jwks_provider.py +51 -0
  153. baobab_auth_security-0.1.0/tests/baobab_auth_security/keys/test_key_enums.py +18 -0
  154. baobab_auth_security-0.1.0/tests/baobab_auth_security/keys/test_key_generator.py +27 -0
  155. baobab_auth_security-0.1.0/tests/baobab_auth_security/keys/test_key_pair.py +41 -0
  156. baobab_auth_security-0.1.0/tests/baobab_auth_security/keys/test_key_rotation_service.py +70 -0
  157. baobab_auth_security-0.1.0/tests/baobab_auth_security/keys/test_pem_loader.py +31 -0
  158. baobab_auth_security-0.1.0/tests/baobab_auth_security/password/test_argon2_password_hasher.py +57 -0
  159. baobab_auth_security-0.1.0/tests/baobab_auth_security/password/test_exceptions.py +39 -0
  160. baobab_auth_security-0.1.0/tests/baobab_auth_security/password/test_password_hash_policy.py +41 -0
  161. baobab_auth_security-0.1.0/tests/baobab_auth_security/password/test_password_hash_result.py +45 -0
  162. baobab_auth_security-0.1.0/tests/baobab_auth_security/password/test_password_hasher.py +47 -0
  163. baobab_auth_security-0.1.0/tests/baobab_auth_security/password/test_password_verification_result.py +47 -0
  164. baobab_auth_security-0.1.0/tests/baobab_auth_security/refresh_tokens/test_refresh_token_generator.py +38 -0
  165. baobab_auth_security-0.1.0/tests/baobab_auth_security/refresh_tokens/test_refresh_token_hasher.py +62 -0
  166. baobab_auth_security-0.1.0/tests/baobab_auth_security/refresh_tokens/test_refresh_token_result.py +49 -0
  167. baobab_auth_security-0.1.0/tests/baobab_auth_security/revocation/test_in_memory_revocation_checker.py +43 -0
  168. baobab_auth_security-0.1.0/tests/baobab_auth_security/revocation/test_token_revocation_checker.py +18 -0
  169. baobab_auth_security-0.1.0/tests/baobab_auth_security/test_init.py +14 -0
  170. baobab_auth_security-0.1.0/tests/baobab_auth_security/test_version.py +29 -0
  171. baobab_auth_security-0.1.0/tests/baobab_auth_security/tokens/test_jwt_decoder.py +142 -0
  172. baobab_auth_security-0.1.0/tests/baobab_auth_security/tokens/test_jwt_encoder.py +87 -0
  173. baobab_auth_security-0.1.0/tests/baobab_auth_security/tokens/test_jwt_validation_result.py +39 -0
  174. baobab_auth_security-0.1.0/tests/baobab_auth_security/tokens/test_jwt_validator.py +236 -0
  175. baobab_auth_security-0.1.0/tests/baobab_auth_security/tokens/test_token_claims.py +103 -0
  176. baobab_auth_security-0.1.0/tests/baobab_auth_security/tokens/test_token_pair.py +29 -0
  177. baobab_auth_security-0.1.0/tests/baobab_auth_security/tokens/test_token_type.py +17 -0
  178. baobab_auth_security-0.1.0/tests/examples/test_examples_runnable.py +34 -0
@@ -0,0 +1,23 @@
1
+ ---
2
+ description: Règles de développement du projet (source unique de vérité)
3
+ globs:
4
+ alwaysApply: true
5
+ ---
6
+
7
+ # Règles de développement
8
+
9
+ La **source unique de vérité** des règles de ce projet est le fichier [`AGENTS.md`](../../AGENTS.md)
10
+ à la racine du dépôt. **Lis-le et applique-le intégralement.** Ne duplique pas son contenu.
11
+
12
+ Rappels prioritaires (le détail complet est dans `AGENTS.md`) :
13
+
14
+ - **Python ≥ 3.11, orienté objet.** 1 classe = 1 fichier (module nommé d'après la classe).
15
+ - **PEP 8** + **PEP 20** ; en cas de conflit, **PEP 8 prime**.
16
+ - **Type hints obligatoires** ; `ruff` (lint+format) ; `mypy` strict.
17
+ - **Docstrings en reStructuredText**, avec `:spec: <ID>`.
18
+ - **Tests `pytest` en arborescence miroir** ; 1 classe testée = 1 classe de test ;
19
+ classe abstraite testée via une classe concrète de test ; **couverture ≥ 90 %**.
20
+ - Doc **Sphinx/RST** ; dossier `docs/guides/` obligatoire.
21
+ - Environnement virtuel **`.venv`** (`python -m venv .venv`), non versionné.
22
+ - Aucun secret en clair (`.env` gitignoré + `.env.example`).
23
+ - **Conventional Commits** + chaîne d'ID **US-001 / FEAT-001.1 / TASK-001.1.1**.
@@ -0,0 +1,18 @@
1
+ root = true
2
+
3
+ [*]
4
+ charset = utf-8
5
+ end_of_line = lf
6
+ insert_final_newline = true
7
+ trim_trailing_whitespace = true
8
+ indent_style = space
9
+
10
+ [*.py]
11
+ indent_size = 4
12
+ max_line_length = 100
13
+
14
+ [*.{rst,md,yml,yaml,toml,cfg}]
15
+ indent_size = 2
16
+
17
+ [Makefile]
18
+ indent_style = tab
@@ -0,0 +1,9 @@
1
+ # Copiez ce fichier en `.env` et renseignez vos valeurs.
2
+ # `.env` est gitignoré : n'y mettez jamais de secret dans le dépôt.
3
+ # Chargé/validé via pydantic-settings (voir src/<package>/settings.py si présent).
4
+
5
+ APP_ENV=development
6
+ LOG_LEVEL=INFO
7
+
8
+ # Exemple de secret (ne jamais committer la vraie valeur)
9
+ # API_KEY=changeme
@@ -0,0 +1,18 @@
1
+ # Normalise les fins de ligne : LF dans le dépôt, quel que soit l'OS du dev.
2
+ * text=auto eol=lf
3
+
4
+ # Scripts Windows : conserver CRLF (requis par cmd.exe).
5
+ *.bat text eol=crlf
6
+ *.cmd text eol=crlf
7
+
8
+ # Fichiers binaires : aucune normalisation.
9
+ *.png binary
10
+ *.jpg binary
11
+ *.jpeg binary
12
+ *.gif binary
13
+ *.ico binary
14
+ *.pdf binary
15
+ *.zip binary
16
+ *.gz binary
17
+ *.woff binary
18
+ *.woff2 binary
@@ -0,0 +1,32 @@
1
+ name: "📘 User Story"
2
+ description: "Décrire un besoin utilisateur (US)"
3
+ title: "[US-XXX] "
4
+ labels: ["type:us"]
5
+ body:
6
+ - type: input
7
+ id: id
8
+ attributes:
9
+ label: Identifiant
10
+ placeholder: "US-001"
11
+ validations:
12
+ required: true
13
+ - type: textarea
14
+ id: story
15
+ attributes:
16
+ label: Récit
17
+ description: "En tant que… je veux… afin de…"
18
+ placeholder: "En tant qu'utilisateur, je veux …, afin de …"
19
+ validations:
20
+ required: true
21
+ - type: textarea
22
+ id: acceptance
23
+ attributes:
24
+ label: Critères d'acceptation
25
+ placeholder: "- [ ] …"
26
+ validations:
27
+ required: true
28
+ - type: input
29
+ id: spec
30
+ attributes:
31
+ label: Spécification (RST)
32
+ placeholder: "docs/specifications/us/US-001-.../index.rst"
@@ -0,0 +1,32 @@
1
+ name: "🧩 Feature"
2
+ description: "Découper une US en fonctionnalité (FEAT)"
3
+ title: "[FEAT-XXX.Y] "
4
+ labels: ["type:feat"]
5
+ body:
6
+ - type: input
7
+ id: id
8
+ attributes:
9
+ label: Identifiant
10
+ placeholder: "FEAT-001.1"
11
+ validations:
12
+ required: true
13
+ - type: input
14
+ id: parent
15
+ attributes:
16
+ label: US parente
17
+ placeholder: "US-001 (#numéro de l'issue)"
18
+ validations:
19
+ required: true
20
+ - type: textarea
21
+ id: description
22
+ attributes:
23
+ label: Description
24
+ validations:
25
+ required: true
26
+ - type: textarea
27
+ id: acceptance
28
+ attributes:
29
+ label: Critères d'acceptation
30
+ placeholder: "- [ ] …"
31
+ validations:
32
+ required: true
@@ -0,0 +1,34 @@
1
+ name: "🔧 Task (backlog)"
2
+ description: "Tâche concrète rattachée à une Feature"
3
+ title: "[TASK-XXX.Y.Z] "
4
+ labels: ["type:task"]
5
+ body:
6
+ - type: input
7
+ id: id
8
+ attributes:
9
+ label: Identifiant
10
+ placeholder: "TASK-001.1.1"
11
+ validations:
12
+ required: true
13
+ - type: input
14
+ id: parent
15
+ attributes:
16
+ label: Feature parente
17
+ placeholder: "FEAT-001.1 (#numéro de l'issue)"
18
+ validations:
19
+ required: true
20
+ - type: textarea
21
+ id: description
22
+ attributes:
23
+ label: Description / étapes
24
+ validations:
25
+ required: true
26
+ - type: checkboxes
27
+ id: dod
28
+ attributes:
29
+ label: Definition of Done
30
+ options:
31
+ - label: "Code POO, 1 classe/fichier, type hints complets"
32
+ - label: "ruff + mypy strict passent"
33
+ - label: "Test miroir présent, couverture ≥ 90 %"
34
+ - label: "Docstrings RST / guide à jour si besoin"
@@ -0,0 +1 @@
1
+ blank_issues_enabled: false
@@ -0,0 +1,20 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: "pip"
4
+ directory: "/"
5
+ schedule:
6
+ interval: "weekly"
7
+ open-pull-requests-limit: 5
8
+ commit-message:
9
+ prefix: "chore"
10
+ include: "scope"
11
+ labels:
12
+ - "type:task"
13
+ - "dependencies"
14
+
15
+ - package-ecosystem: "github-actions"
16
+ directory: "/"
17
+ schedule:
18
+ interval: "weekly"
19
+ commit-message:
20
+ prefix: "ci"
@@ -0,0 +1,21 @@
1
+ ## Description
2
+
3
+ <!-- Que fait cette PR ? Rattachez l'ID spec. -->
4
+
5
+ Closes #
6
+
7
+ ## Type de changement
8
+
9
+ - [ ] `feat` — nouvelle fonctionnalité
10
+ - [ ] `fix` — correction de bug
11
+ - [ ] `docs` — documentation
12
+ - [ ] `refactor` / `test` / `chore`
13
+
14
+ ## Checklist (Definition of Done)
15
+
16
+ - [ ] 1 classe = 1 fichier ; type hints complets ; docstrings RST avec `:spec:`
17
+ - [ ] Test miroir présent (classe abstraite testée via classe concrète de test)
18
+ - [ ] `ruff` + `mypy` strict passent
19
+ - [ ] Couverture ≥ 90 %
20
+ - [ ] Doc / guide mis à jour si le comportement public change
21
+ - [ ] Commits en Conventional Commits avec ID
@@ -0,0 +1,145 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+
8
+ # Annule les runs obsolètes sur une même branche/PR.
9
+ concurrency:
10
+ group: ci-${{ github.ref }}
11
+ cancel-in-progress: true
12
+
13
+ permissions:
14
+ contents: read
15
+
16
+ jobs:
17
+ lint:
18
+ runs-on: ubuntu-latest
19
+ steps:
20
+ - uses: actions/checkout@v4
21
+ with:
22
+ fetch-depth: 0 # hatch-vcs a besoin de l'historique/tags
23
+ - uses: actions/setup-python@v5
24
+ with:
25
+ python-version: "3.12"
26
+ cache: pip
27
+ - run: pip install -e ".[dev]"
28
+ - name: Ruff (lint)
29
+ run: ruff check .
30
+ - name: Ruff (format)
31
+ run: ruff format --check .
32
+
33
+ type:
34
+ runs-on: ubuntu-latest
35
+ steps:
36
+ - uses: actions/checkout@v4
37
+ with:
38
+ fetch-depth: 0
39
+ - uses: actions/setup-python@v5
40
+ with:
41
+ python-version: "3.12"
42
+ cache: pip
43
+ - run: pip install -e ".[dev]"
44
+ - name: Mypy (strict)
45
+ run: mypy
46
+
47
+ security:
48
+ runs-on: ubuntu-latest
49
+ permissions:
50
+ contents: read
51
+ security-events: write # publier le SARIF dans l'onglet Security
52
+ steps:
53
+ - uses: actions/checkout@v4
54
+ with:
55
+ fetch-depth: 0
56
+ - uses: actions/setup-python@v5
57
+ with:
58
+ python-version: "3.12"
59
+ cache: pip
60
+ - run: pip install -e ".[dev]"
61
+ - name: Bandit (génère le SARIF)
62
+ run: bandit -c pyproject.toml -r src -f sarif -o bandit.sarif
63
+ continue-on-error: true
64
+ - name: Publier le SARIF dans l'onglet Security
65
+ if: always()
66
+ continue-on-error: true # tolère repo privé sans GitHub Advanced Security
67
+ uses: github/codeql-action/upload-sarif@v3
68
+ with:
69
+ sarif_file: bandit.sarif
70
+ - name: Bandit (gate)
71
+ run: bandit -c pyproject.toml -r src
72
+ - name: pip-audit (dépendances)
73
+ run: pip-audit
74
+
75
+ build:
76
+ runs-on: ubuntu-latest
77
+ steps:
78
+ - uses: actions/checkout@v4
79
+ with:
80
+ fetch-depth: 0
81
+ - uses: actions/setup-python@v5
82
+ with:
83
+ python-version: "3.12"
84
+ - name: Build sdist + wheel (validation packaging)
85
+ run: |
86
+ python -m pip install --upgrade build
87
+ python -m build
88
+ - uses: actions/upload-artifact@v4
89
+ with:
90
+ name: dist-ci
91
+ path: dist/
92
+ retention-days: 7
93
+
94
+ docs:
95
+ runs-on: ubuntu-latest
96
+ steps:
97
+ - uses: actions/checkout@v4
98
+ with:
99
+ fetch-depth: 0
100
+ - uses: actions/setup-python@v5
101
+ with:
102
+ python-version: "3.12"
103
+ cache: pip
104
+ - run: pip install -e ".[docs]"
105
+ - name: Build Sphinx (validation stricte)
106
+ run: sphinx-build -b html -W docs docs/_build/html
107
+ - name: Upload doc HTML (aperçu, sans hébergement)
108
+ uses: actions/upload-artifact@v4
109
+ with:
110
+ name: docs-html
111
+ path: docs/_build/html/
112
+ retention-days: 14
113
+
114
+ test:
115
+ runs-on: ubuntu-latest
116
+ strategy:
117
+ fail-fast: false
118
+ matrix:
119
+ python-version: ["3.12", "3.13"]
120
+ steps:
121
+ - uses: actions/checkout@v4
122
+ with:
123
+ fetch-depth: 0
124
+ - uses: actions/setup-python@v5
125
+ with:
126
+ python-version: ${{ matrix.python-version }}
127
+ cache: pip
128
+ - run: pip install -e ".[dev]"
129
+ - name: Tests + coverage (JUnit + HTML)
130
+ run: pytest --junitxml=junit-${{ matrix.python-version }}.xml --cov-report=html
131
+ - name: Upload rapports (couverture HTML + JUnit)
132
+ if: always()
133
+ uses: actions/upload-artifact@v4
134
+ with:
135
+ name: reports-py${{ matrix.python-version }}
136
+ path: |
137
+ junit-${{ matrix.python-version }}.xml
138
+ htmlcov/
139
+ retention-days: 14
140
+ - name: Upload coverage to Codecov
141
+ if: matrix.python-version == '3.12'
142
+ uses: codecov/codecov-action@v4
143
+ with:
144
+ files: coverage.xml
145
+ fail_ci_if_error: false
@@ -0,0 +1,114 @@
1
+ name: Release
2
+
3
+ # Déclenché par un tag de version créé par le Release Manager (ex. v1.2.0).
4
+ # Tag de pré-release (ex. v1.2.0rc1) → TestPyPI ; tag final → PyPI public.
5
+ on:
6
+ push:
7
+ tags: ["v*"]
8
+
9
+ permissions:
10
+ contents: read
11
+
12
+ jobs:
13
+ meta:
14
+ runs-on: ubuntu-latest
15
+ outputs:
16
+ prerelease: ${{ steps.detect.outputs.prerelease }}
17
+ steps:
18
+ - id: detect
19
+ run: |
20
+ if [[ "${GITHUB_REF_NAME}" =~ (rc|a|b|alpha|beta|dev)[0-9]*$ ]]; then
21
+ echo "prerelease=true" >> "$GITHUB_OUTPUT"
22
+ else
23
+ echo "prerelease=false" >> "$GITHUB_OUTPUT"
24
+ fi
25
+
26
+ build:
27
+ needs: meta
28
+ runs-on: ubuntu-latest
29
+ permissions:
30
+ id-token: write # attestation de provenance
31
+ attestations: write
32
+ contents: read
33
+ steps:
34
+ - uses: actions/checkout@v4
35
+ with:
36
+ fetch-depth: 0 # tag complet requis pour hatch-vcs
37
+ - uses: actions/setup-python@v5
38
+ with:
39
+ python-version: "3.12"
40
+ - name: Build sdist + wheel
41
+ run: |
42
+ python -m pip install --upgrade build
43
+ python -m build
44
+ - name: Attestation de provenance (supply chain)
45
+ uses: actions/attest-build-provenance@v1
46
+ with:
47
+ subject-path: "dist/*"
48
+ - uses: actions/upload-artifact@v4
49
+ with:
50
+ name: dist
51
+ path: dist/
52
+
53
+ publish-testpypi:
54
+ needs: [meta, build]
55
+ if: needs.meta.outputs.prerelease == 'true'
56
+ runs-on: ubuntu-latest
57
+ environment: testpypi
58
+ permissions:
59
+ id-token: write # Trusted Publishing (OIDC)
60
+ steps:
61
+ - uses: actions/download-artifact@v4
62
+ with:
63
+ name: dist
64
+ path: dist/
65
+ - name: Publish to TestPyPI
66
+ uses: pypa/gh-action-pypi-publish@release/v1
67
+ with:
68
+ repository-url: https://test.pypi.org/legacy/
69
+
70
+ publish-pypi:
71
+ needs: [meta, build]
72
+ if: needs.meta.outputs.prerelease == 'false'
73
+ runs-on: ubuntu-latest
74
+ environment: pypi
75
+ permissions:
76
+ id-token: write # Trusted Publishing (OIDC) — aucun token stocké
77
+ steps:
78
+ - uses: actions/download-artifact@v4
79
+ with:
80
+ name: dist
81
+ path: dist/
82
+ - name: Publish to PyPI
83
+ uses: pypa/gh-action-pypi-publish@release/v1
84
+
85
+ github-release:
86
+ needs: [meta, build]
87
+ runs-on: ubuntu-latest
88
+ permissions:
89
+ contents: write # créer la Release + attacher les assets
90
+ steps:
91
+ - uses: actions/checkout@v4
92
+ with:
93
+ fetch-depth: 0 # hatch-vcs (install du paquet pour le SBOM)
94
+ - uses: actions/setup-python@v5
95
+ with:
96
+ python-version: "3.12"
97
+ - uses: actions/download-artifact@v4
98
+ with:
99
+ name: dist
100
+ path: dist/
101
+ - name: Générer le SBOM (CycloneDX)
102
+ run: |
103
+ python -m pip install pip-audit .
104
+ pip-audit -f cyclonedx-json -o sbom.json
105
+ continue-on-error: true
106
+ - name: Create GitHub Release (dist + SBOM attachés)
107
+ uses: softprops/action-gh-release@v2
108
+ with:
109
+ files: |
110
+ dist/*
111
+ sbom.json
112
+ generate_release_notes: true
113
+ prerelease: ${{ needs.meta.outputs.prerelease == 'true' }}
114
+ body: "Voir le CHANGELOG.md pour le détail des changements."
@@ -0,0 +1,52 @@
1
+ # Environnement virtuel (jamais versionné)
2
+ .venv/
3
+ venv/
4
+ env/
5
+
6
+ # Secrets
7
+ .env
8
+ .env.*
9
+ !.env.example
10
+
11
+ # Python
12
+ __pycache__/
13
+ *.py[cod]
14
+ *$py.class
15
+ *.egg-info/
16
+ .eggs/
17
+ build/
18
+ dist/
19
+ *.egg
20
+
21
+ # Tests & couverture
22
+ .pytest_cache/
23
+ .coverage
24
+ .coverage.*
25
+ htmlcov/
26
+ coverage.xml
27
+ junit*.xml
28
+ .tox/
29
+ .nox/
30
+
31
+ # Rapports d'analyse (générés en CI)
32
+ bandit.sarif
33
+ sbom.json
34
+
35
+ # Typage / lint caches
36
+ .mypy_cache/
37
+ .ruff_cache/
38
+ .dmypy.json
39
+
40
+ # Documentation construite
41
+ docs/_build/
42
+ docs/api/_autosummary/
43
+
44
+ # IDE / OS
45
+ .idea/
46
+ .vscode/
47
+ .DS_Store
48
+ Thumbs.db
49
+
50
+ # Claude Code (local uniquement)
51
+ CLAUDE.local.md
52
+ .claude/settings.local.json
@@ -0,0 +1,46 @@
1
+ # Garde-fous mécaniques : appliqués quoi que l'IA décide.
2
+ # Installation : pre-commit install
3
+ default_language_version:
4
+ python: python3
5
+
6
+ repos:
7
+ - repo: https://github.com/pre-commit/pre-commit-hooks
8
+ rev: v4.6.0
9
+ hooks:
10
+ - id: trailing-whitespace
11
+ - id: end-of-file-fixer
12
+ - id: check-yaml
13
+ - id: check-toml
14
+ - id: check-added-large-files
15
+ - id: detect-private-key
16
+
17
+ - repo: https://github.com/astral-sh/ruff-pre-commit
18
+ rev: v0.6.9
19
+ hooks:
20
+ - id: ruff # lint
21
+ args: [--fix]
22
+ - id: ruff-format # format
23
+
24
+ - repo: https://github.com/pre-commit/mirrors-mypy
25
+ rev: v1.11.2
26
+ hooks:
27
+ - id: mypy
28
+ additional_dependencies: ["pydantic-settings"]
29
+ args: [--strict]
30
+
31
+ - repo: https://github.com/PyCQA/bandit
32
+ rev: 1.7.10
33
+ hooks:
34
+ - id: bandit
35
+ args: ["-c", "pyproject.toml"]
36
+ additional_dependencies: ["bandit[toml]"]
37
+
38
+ - repo: local
39
+ hooks:
40
+ - id: pytest-cov-90
41
+ name: pytest (couverture >= 90%)
42
+ entry: pytest
43
+ language: system
44
+ pass_filenames: false
45
+ always_run: true
46
+ stages: [pre-push]
@@ -0,0 +1,109 @@
1
+ # AGENTS.md — Règles de développement (source unique de vérité)
2
+
3
+ > Ce fichier est **la** source des règles pour **toutes** les IA de développement
4
+ > (Codex le lit nativement ; `CLAUDE.md` l'importe ; `.cursor/rules/000-core.mdc` le reflète).
5
+ > Toute modification de règle se fait **ici**, jamais en double.
6
+
7
+ ## Langage & conception
8
+
9
+ - Langage : **Python ≥ 3.11**, **orienté objet**. Respect de **SOLID**, composition > héritage.
10
+ - **1 classe = 1 fichier.** Le module porte le nom de la classe en `snake_case`
11
+ (`class FactureClient` → `facture_client.py`).
12
+ - *Dérogation* : une **hiérarchie d'exceptions** (classes courtes) peut être regroupée
13
+ dans un sous-package `exceptions/` organisé **par catégorie** (un fichier par famille).
14
+ - Pas de logique exécutable au niveau module ; tout passe par des classes/méthodes.
15
+
16
+ ## Librairie consommable (contrat d'API)
17
+
18
+ - Le livrable est une **librairie réutilisable**, susceptible d'être intégrée dans un
19
+ projet parent. Ce qui est exporté dans `__all__` est un **contrat**.
20
+ - Rupture du contrat (suppression/modification incompatible d'un symbole public) →
21
+ **bump SemVer majeur** + entrée `CHANGELOG` « BREAKING » + note de migration.
22
+ - Aucune hypothèse sur l'hôte : pas d'état global, config **injectée** (`pydantic-settings`).
23
+ Ce dépôt *expose*, il ne *dépend jamais* d'un projet parent.
24
+
25
+ ## PEP 8 & PEP 20
26
+
27
+ - Respect de **PEP 8** (style) et de **PEP 20** (Zen of Python : explicite, simple, lisible).
28
+ - **En cas de conflit entre PEP 8 et PEP 20, la PEP 8 prime.**
29
+
30
+ ## Typage & style
31
+
32
+ - **Type hints obligatoires** sur toutes les signatures (paramètres et retours).
33
+ - Lint + format : **`ruff`** (unique outil). Vérification de types : **`mypy`** (mode strict).
34
+ - **Docstrings en reStructuredText (RST)** sur tout élément public
35
+ (champs `:param:`, `:returns:`, `:raises:`, et `:spec: <ID>` pour la traçabilité).
36
+
37
+ ## Tests
38
+
39
+ - Framework : **`pytest`**, structure **AAA** (Arrange / Act / Assert), tests déterministes.
40
+ - **Arborescence miroir** : `src/<pkg>/a/b/c.py` ⇒ `tests/<pkg>/a/b/test_c.py`.
41
+ - **Une classe testée = une classe de test** (`class FactureClient` ⇒ `class TestFactureClient`).
42
+ - **Classe abstraite** : on la teste via une **classe concrète de test** définie dans le fichier de test.
43
+ - Nom de test porteur de l'ID spec : `def test_FEAT_001_1_cas_nominal(...)`.
44
+ - **Couverture ≥ 90 %**, imposée par `--cov-fail-under=90` (voir `pyproject.toml`).
45
+
46
+ ## Documentation
47
+
48
+ - **Sphinx** + **RST**. La doc API est générée par **`autodoc`** depuis les docstrings.
49
+ - Dossier **`docs/guides/` obligatoire**, organisé selon **Diátaxis** :
50
+ `tutorials/` (apprendre) et `how-to/` (résoudre un problème précis).
51
+ - **`README.md`** : suit la structure « 15 sections » (voir le fichier) et porte **tous les badges**
52
+ que le projet peut légitimement afficher (version, couverture, CI, licence, style, types, docs…).
53
+
54
+ ## Arborescence (layout `src/`)
55
+
56
+ ```
57
+ .
58
+ ├── src/<package>/ # code (1 classe par fichier)
59
+ ├── tests/<package>/ # tests en miroir de src/
60
+ ├── docs/
61
+ │ ├── specifications/ # cahier des charges : US / FEAT (RST, stable)
62
+ │ ├── api/ # doc API (autodoc)
63
+ │ └── guides/ # tutorials/ + how-to/ (OBLIGATOIRE)
64
+ ├── pyproject.toml # config unique (projet, ruff, mypy, pytest, coverage)
65
+ ├── .pre-commit-config.yaml
66
+ └── .github/ # CI + templates d'issues (US/FEAT/Task) + PR
67
+ ```
68
+
69
+ ## Environnement & dépendances
70
+
71
+ - **Toujours un environnement virtuel** : `python -m venv .venv` dans le dossier **`.venv`**.
72
+ - `.venv/` n'est **jamais** versionné (cf. `.gitignore`).
73
+ - Config projet et dépendances dans **`pyproject.toml`** (PEP 621). Install dev : `pip install -e ".[dev,docs]"`.
74
+
75
+ ## Sécurité
76
+
77
+ - **Aucun secret** dans le code ou Git. Variables via `.env` (gitignoré) + `.env.example` versionné.
78
+ - Chargement/validation de la config via **`pydantic-settings`**.
79
+
80
+ ## Git & traçabilité
81
+
82
+ - **Conventional Commits** portant l'ID spec : `feat(FEAT-001.1): export PDF de la facture`.
83
+ - **SemVer** pour les versions.
84
+ - Chaîne d'identifiants propagée partout :
85
+ **US-001** → **FEAT-001.1** → **TASK-001.1.1**
86
+ (titres d'issues, branches, commits `Closes #<n>`, noms de tests, docstrings `:spec:`).
87
+ - **Provenance** : chaque US/FEAT porte un champ `:origin:` (cahier des charges, ou projet
88
+ externe demandeur) dans sa spec RST et son issue, pour la traçabilité inter-projets.
89
+ - **Fermeture au merge** : une issue ne se ferme qu'**après** le merge de sa PR sur `main`,
90
+ jamais avant (sinon le tracker dit « terminé » alors que le code dort sur une branche).
91
+
92
+ ## Workflow
93
+
94
+ - Le processus de dev (rôles, machine à états, handoff, prompts) est décrit dans
95
+ **`docs/workflow/`**. L'IA endosse un rôle à la fois, de façon séquentielle, et reprend
96
+ via la **note de handoff** + le GitHub Project.
97
+ - **Format des fichiers** : les instructions opérationnelles (`AGENTS.md`, `CLAUDE.md`,
98
+ `docs/workflow/`) sont en **Markdown** ; la **documentation du projet**
99
+ (specifications, API, guides) est en **reStructuredText**.
100
+ - Le cahier des charges brut se dépose dans `docs/specifications/cahier-des-charges/` ;
101
+ le rôle PO en dérive `docs/specifications/us/` (RST).
102
+
103
+ ## Definition of Done (une tâche n'est close que si)
104
+
105
+ 1. Code POO, 1 classe/fichier, type hints complets.
106
+ 2. `ruff` (lint+format) et `mypy` strict passent.
107
+ 3. Tests présents en miroir, couverture ≥ 90 %.
108
+ 4. Docstrings RST + guide mis à jour si le comportement public change.
109
+ 5. Commit conforme (Conventional Commits + ID), PR fusionnée.