baobab-auth-api 0.9.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.
- baobab_auth_api-0.9.0/.cursor/rules/000-core.mdc +23 -0
- baobab_auth_api-0.9.0/.editorconfig +18 -0
- baobab_auth_api-0.9.0/.env.example +20 -0
- baobab_auth_api-0.9.0/.gitattributes +18 -0
- baobab_auth_api-0.9.0/.github/ISSUE_TEMPLATE/01-user-story.yml +32 -0
- baobab_auth_api-0.9.0/.github/ISSUE_TEMPLATE/02-feature.yml +32 -0
- baobab_auth_api-0.9.0/.github/ISSUE_TEMPLATE/03-task.yml +34 -0
- baobab_auth_api-0.9.0/.github/ISSUE_TEMPLATE/config.yml +1 -0
- baobab_auth_api-0.9.0/.github/dependabot.yml +20 -0
- baobab_auth_api-0.9.0/.github/pull_request_template.md +21 -0
- baobab_auth_api-0.9.0/.github/workflows/ci.yml +145 -0
- baobab_auth_api-0.9.0/.github/workflows/release.yml +114 -0
- baobab_auth_api-0.9.0/.gitignore +52 -0
- baobab_auth_api-0.9.0/.pre-commit-config.yaml +46 -0
- baobab_auth_api-0.9.0/AGENTS.md +112 -0
- baobab_auth_api-0.9.0/CHANGELOG.md +86 -0
- baobab_auth_api-0.9.0/CLAUDE.md +15 -0
- baobab_auth_api-0.9.0/CONTRIBUTING.md +36 -0
- baobab_auth_api-0.9.0/LICENSE +21 -0
- baobab_auth_api-0.9.0/Makefile +43 -0
- baobab_auth_api-0.9.0/PKG-INFO +276 -0
- baobab_auth_api-0.9.0/README.md +211 -0
- baobab_auth_api-0.9.0/SECURITY.md +27 -0
- baobab_auth_api-0.9.0/conftest.py +8 -0
- baobab_auth_api-0.9.0/docs/_static/.gitkeep +0 -0
- baobab_auth_api-0.9.0/docs/api/index.rst +10 -0
- baobab_auth_api-0.9.0/docs/conf.py +38 -0
- baobab_auth_api-0.9.0/docs/configuration.md +50 -0
- baobab_auth_api-0.9.0/docs/core_contract.md +40 -0
- baobab_auth_api-0.9.0/docs/endpoints.md +285 -0
- baobab_auth_api-0.9.0/docs/errors.md +79 -0
- baobab_auth_api-0.9.0/docs/guides/how-to/ajouter-une-classe.rst +25 -0
- baobab_auth_api-0.9.0/docs/guides/index.rst +19 -0
- baobab_auth_api-0.9.0/docs/guides/tutorials/premiers-pas.rst +26 -0
- baobab_auth_api-0.9.0/docs/index.rst +23 -0
- baobab_auth_api-0.9.0/docs/jwks.md +91 -0
- baobab_auth_api-0.9.0/docs/security.md +85 -0
- baobab_auth_api-0.9.0/docs/specifications/cahier-des-charges/README.md +13 -0
- baobab_auth_api-0.9.0/docs/specifications/cahier-des-charges/cahier_des_charges.md +1875 -0
- baobab_auth_api-0.9.0/docs/specifications/glossary.rst +16 -0
- baobab_auth_api-0.9.0/docs/specifications/index.rst +36 -0
- baobab_auth_api-0.9.0/docs/specifications/us/US-001-socle/FEAT-001.1-structure-package.rst +33 -0
- baobab_auth_api-0.9.0/docs/specifications/us/US-001-socle/index.rst +17 -0
- baobab_auth_api-0.9.0/docs/specifications/us/US-002-configuration/FEAT-002.1-auth-api-settings.rst +33 -0
- baobab_auth_api-0.9.0/docs/specifications/us/US-002-configuration/FEAT-002.2-create-app.rst +36 -0
- baobab_auth_api-0.9.0/docs/specifications/us/US-002-configuration/index.rst +19 -0
- baobab_auth_api-0.9.0/docs/specifications/us/US-003-schemas/FEAT-003.1-schemas-auth.rst +29 -0
- baobab_auth_api-0.9.0/docs/specifications/us/US-003-schemas/FEAT-003.2-schemas-read.rst +29 -0
- baobab_auth_api-0.9.0/docs/specifications/us/US-003-schemas/FEAT-003.3-schema-erreur.rst +26 -0
- baobab_auth_api-0.9.0/docs/specifications/us/US-003-schemas/index.rst +19 -0
- baobab_auth_api-0.9.0/docs/specifications/us/US-004-services/FEAT-004.1-auth-service.rst +36 -0
- baobab_auth_api-0.9.0/docs/specifications/us/US-004-services/FEAT-004.2-user-session-service.rst +33 -0
- baobab_auth_api-0.9.0/docs/specifications/us/US-004-services/FEAT-004.3-role-permission-service.rst +33 -0
- baobab_auth_api-0.9.0/docs/specifications/us/US-004-services/FEAT-004.4-audit-service.rst +29 -0
- baobab_auth_api-0.9.0/docs/specifications/us/US-004-services/index.rst +20 -0
- baobab_auth_api-0.9.0/docs/specifications/us/US-005-endpoints-auth/FEAT-005.1-register-login.rst +28 -0
- baobab_auth_api-0.9.0/docs/specifications/us/US-005-endpoints-auth/FEAT-005.2-refresh-logout.rst +27 -0
- baobab_auth_api-0.9.0/docs/specifications/us/US-005-endpoints-auth/FEAT-005.3-me.rst +29 -0
- baobab_auth_api-0.9.0/docs/specifications/us/US-005-endpoints-auth/index.rst +19 -0
- baobab_auth_api-0.9.0/docs/specifications/us/US-006-jwks/FEAT-006.1-jwks-endpoint.rst +30 -0
- baobab_auth_api-0.9.0/docs/specifications/us/US-006-jwks/index.rst +17 -0
- baobab_auth_api-0.9.0/docs/specifications/us/US-007-roles-permissions/FEAT-007.1-endpoints-catalogue.rst +28 -0
- baobab_auth_api-0.9.0/docs/specifications/us/US-007-roles-permissions/FEAT-007.2-permissions-effectives-jwt.rst +27 -0
- baobab_auth_api-0.9.0/docs/specifications/us/US-007-roles-permissions/index.rst +18 -0
- baobab_auth_api-0.9.0/docs/specifications/us/US-008-healthcheck/FEAT-008.1-health-ready.rst +30 -0
- baobab_auth_api-0.9.0/docs/specifications/us/US-008-healthcheck/index.rst +17 -0
- baobab_auth_api-0.9.0/docs/specifications/us/US-009-securite/FEAT-009.1-durcissement.rst +34 -0
- baobab_auth_api-0.9.0/docs/specifications/us/US-009-securite/index.rst +18 -0
- baobab_auth_api-0.9.0/docs/specifications/us/US-010-documentation/FEAT-010.1-documentation-complete.rst +36 -0
- baobab_auth_api-0.9.0/docs/specifications/us/US-010-documentation/index.rst +17 -0
- baobab_auth_api-0.9.0/docs/specifications/us/US-011-integration-core-0.9/index.rst +41 -0
- baobab_auth_api-0.9.0/docs/specifications/us/index.rst +17 -0
- baobab_auth_api-0.9.0/docs/testing.md +86 -0
- baobab_auth_api-0.9.0/docs/workflow/README.md +66 -0
- baobab_auth_api-0.9.0/docs/workflow/SETUP.md +109 -0
- baobab_auth_api-0.9.0/docs/workflow/gates.md +38 -0
- baobab_auth_api-0.9.0/docs/workflow/handoff.md +53 -0
- baobab_auth_api-0.9.0/docs/workflow/prompts/init.md +42 -0
- baobab_auth_api-0.9.0/docs/workflow/prompts/orchestration.md +25 -0
- baobab_auth_api-0.9.0/docs/workflow/roles/00-orchestrateur.md +24 -0
- baobab_auth_api-0.9.0/docs/workflow/roles/01-product-owner.md +22 -0
- baobab_auth_api-0.9.0/docs/workflow/roles/02-architecte.md +22 -0
- baobab_auth_api-0.9.0/docs/workflow/roles/03-developpeur.md +23 -0
- baobab_auth_api-0.9.0/docs/workflow/roles/04-relecteur.md +24 -0
- baobab_auth_api-0.9.0/docs/workflow/roles/05-securite.md +26 -0
- baobab_auth_api-0.9.0/docs/workflow/roles/06-release-manager.md +27 -0
- baobab_auth_api-0.9.0/docs/workflow/roles/07-support.md +22 -0
- baobab_auth_api-0.9.0/pyproject.toml +140 -0
- baobab_auth_api-0.9.0/scripts/setup_github.sh +58 -0
- baobab_auth_api-0.9.0/src/baobab_auth_api/__init__.py +13 -0
- baobab_auth_api-0.9.0/src/baobab_auth_api/app.py +79 -0
- baobab_auth_api-0.9.0/src/baobab_auth_api/config.py +113 -0
- baobab_auth_api-0.9.0/src/baobab_auth_api/error_handlers.py +123 -0
- baobab_auth_api-0.9.0/src/baobab_auth_api/exceptions/__init__.py +26 -0
- baobab_auth_api-0.9.0/src/baobab_auth_api/exceptions/auth.py +71 -0
- baobab_auth_api-0.9.0/src/baobab_auth_api/exceptions/registration.py +29 -0
- baobab_auth_api-0.9.0/src/baobab_auth_api/integration/__init__.py +13 -0
- baobab_auth_api-0.9.0/src/baobab_auth_api/integration/core_endpoint_spec.py +20 -0
- baobab_auth_api-0.9.0/src/baobab_auth_api/integration/core_exception_http_mapper.py +57 -0
- baobab_auth_api-0.9.0/src/baobab_auth_api/integration/core_integration_gaps.py +26 -0
- baobab_auth_api-0.9.0/src/baobab_auth_api/integration/core_route_catalog.py +83 -0
- baobab_auth_api-0.9.0/src/baobab_auth_api/lifespan.py +35 -0
- baobab_auth_api-0.9.0/src/baobab_auth_api/log_filters.py +53 -0
- baobab_auth_api-0.9.0/src/baobab_auth_api/main.py +12 -0
- baobab_auth_api-0.9.0/src/baobab_auth_api/models/__init__.py +22 -0
- baobab_auth_api-0.9.0/src/baobab_auth_api/models/audit_event.py +38 -0
- baobab_auth_api-0.9.0/src/baobab_auth_api/models/audit_event_type.py +38 -0
- baobab_auth_api-0.9.0/src/baobab_auth_api/models/permission.py +27 -0
- baobab_auth_api-0.9.0/src/baobab_auth_api/models/role.py +30 -0
- baobab_auth_api-0.9.0/src/baobab_auth_api/models/session.py +35 -0
- baobab_auth_api-0.9.0/src/baobab_auth_api/models/token_pair.py +27 -0
- baobab_auth_api-0.9.0/src/baobab_auth_api/models/user.py +38 -0
- baobab_auth_api-0.9.0/src/baobab_auth_api/openapi.py +37 -0
- baobab_auth_api-0.9.0/src/baobab_auth_api/ports/__init__.py +18 -0
- baobab_auth_api-0.9.0/src/baobab_auth_api/ports/audit_repository.py +25 -0
- baobab_auth_api-0.9.0/src/baobab_auth_api/ports/jwt_service.py +62 -0
- baobab_auth_api-0.9.0/src/baobab_auth_api/ports/password_service.py +34 -0
- baobab_auth_api-0.9.0/src/baobab_auth_api/ports/session_repository.py +72 -0
- baobab_auth_api-0.9.0/src/baobab_auth_api/ports/user_repository.py +64 -0
- baobab_auth_api-0.9.0/src/baobab_auth_api/py.typed +0 -0
- baobab_auth_api-0.9.0/src/baobab_auth_api/routers/__init__.py +5 -0
- baobab_auth_api-0.9.0/src/baobab_auth_api/routers/auth.py +218 -0
- baobab_auth_api-0.9.0/src/baobab_auth_api/routers/health.py +61 -0
- baobab_auth_api-0.9.0/src/baobab_auth_api/routers/jwks.py +47 -0
- baobab_auth_api-0.9.0/src/baobab_auth_api/routers/permissions.py +50 -0
- baobab_auth_api-0.9.0/src/baobab_auth_api/routers/roles.py +51 -0
- baobab_auth_api-0.9.0/src/baobab_auth_api/schemas/__init__.py +35 -0
- baobab_auth_api-0.9.0/src/baobab_auth_api/schemas/auth.py +64 -0
- baobab_auth_api-0.9.0/src/baobab_auth_api/schemas/errors.py +39 -0
- baobab_auth_api-0.9.0/src/baobab_auth_api/schemas/jwks.py +23 -0
- baobab_auth_api-0.9.0/src/baobab_auth_api/schemas/permission_list_response.py +21 -0
- baobab_auth_api-0.9.0/src/baobab_auth_api/schemas/permissions.py +28 -0
- baobab_auth_api-0.9.0/src/baobab_auth_api/schemas/role_list_response.py +21 -0
- baobab_auth_api-0.9.0/src/baobab_auth_api/schemas/roles.py +31 -0
- baobab_auth_api-0.9.0/src/baobab_auth_api/schemas/tokens.py +56 -0
- baobab_auth_api-0.9.0/src/baobab_auth_api/schemas/users.py +33 -0
- baobab_auth_api-0.9.0/src/baobab_auth_api/services/__init__.py +20 -0
- baobab_auth_api-0.9.0/src/baobab_auth_api/services/audit_service.py +53 -0
- baobab_auth_api-0.9.0/src/baobab_auth_api/services/auth_service.py +198 -0
- baobab_auth_api-0.9.0/src/baobab_auth_api/services/permission_service.py +108 -0
- baobab_auth_api-0.9.0/src/baobab_auth_api/services/role_service.py +83 -0
- baobab_auth_api-0.9.0/src/baobab_auth_api/services/session_service.py +114 -0
- baobab_auth_api-0.9.0/src/baobab_auth_api/services/user_service.py +117 -0
- baobab_auth_api-0.9.0/tests/baobab_auth_api/api/test_jwks.py +123 -0
- baobab_auth_api-0.9.0/tests/baobab_auth_api/api/test_me.py +168 -0
- baobab_auth_api-0.9.0/tests/baobab_auth_api/api/test_refresh_logout.py +213 -0
- baobab_auth_api-0.9.0/tests/baobab_auth_api/api/test_register_login.py +275 -0
- baobab_auth_api-0.9.0/tests/baobab_auth_api/api/test_roles_permissions.py +154 -0
- baobab_auth_api-0.9.0/tests/baobab_auth_api/contracts/__init__.py +0 -0
- baobab_auth_api-0.9.0/tests/baobab_auth_api/contracts/core/__init__.py +0 -0
- baobab_auth_api-0.9.0/tests/baobab_auth_api/contracts/core/test_core_exception_handler.py +43 -0
- baobab_auth_api-0.9.0/tests/baobab_auth_api/contracts/core/test_core_exception_http_mapper.py +48 -0
- baobab_auth_api-0.9.0/tests/baobab_auth_api/contracts/core/test_core_route_catalog_contract.py +34 -0
- baobab_auth_api-0.9.0/tests/baobab_auth_api/exceptions/test_auth.py +84 -0
- baobab_auth_api-0.9.0/tests/baobab_auth_api/exceptions/test_registration.py +59 -0
- baobab_auth_api-0.9.0/tests/baobab_auth_api/integration/test_core_integration_gaps.py +12 -0
- baobab_auth_api-0.9.0/tests/baobab_auth_api/models/test_audit_event.py +49 -0
- baobab_auth_api-0.9.0/tests/baobab_auth_api/models/test_audit_event_type.py +35 -0
- baobab_auth_api-0.9.0/tests/baobab_auth_api/models/test_permission.py +36 -0
- baobab_auth_api-0.9.0/tests/baobab_auth_api/models/test_role.py +58 -0
- baobab_auth_api-0.9.0/tests/baobab_auth_api/models/test_session.py +54 -0
- baobab_auth_api-0.9.0/tests/baobab_auth_api/models/test_token_pair.py +40 -0
- baobab_auth_api-0.9.0/tests/baobab_auth_api/models/test_user.py +68 -0
- baobab_auth_api-0.9.0/tests/baobab_auth_api/routers/test_auth.py +47 -0
- baobab_auth_api-0.9.0/tests/baobab_auth_api/routers/test_health.py +102 -0
- baobab_auth_api-0.9.0/tests/baobab_auth_api/routers/test_jwks.py +27 -0
- baobab_auth_api-0.9.0/tests/baobab_auth_api/routers/test_permissions.py +29 -0
- baobab_auth_api-0.9.0/tests/baobab_auth_api/routers/test_roles.py +29 -0
- baobab_auth_api-0.9.0/tests/baobab_auth_api/schemas/test_auth.py +109 -0
- baobab_auth_api-0.9.0/tests/baobab_auth_api/schemas/test_errors.py +72 -0
- baobab_auth_api-0.9.0/tests/baobab_auth_api/schemas/test_jwks.py +47 -0
- baobab_auth_api-0.9.0/tests/baobab_auth_api/schemas/test_permission_list_response.py +32 -0
- baobab_auth_api-0.9.0/tests/baobab_auth_api/schemas/test_permissions.py +56 -0
- baobab_auth_api-0.9.0/tests/baobab_auth_api/schemas/test_role_list_response.py +36 -0
- baobab_auth_api-0.9.0/tests/baobab_auth_api/schemas/test_roles.py +64 -0
- baobab_auth_api-0.9.0/tests/baobab_auth_api/schemas/test_tokens.py +80 -0
- baobab_auth_api-0.9.0/tests/baobab_auth_api/schemas/test_users.py +68 -0
- baobab_auth_api-0.9.0/tests/baobab_auth_api/services/test_audit_service.py +84 -0
- baobab_auth_api-0.9.0/tests/baobab_auth_api/services/test_auth_service.py +368 -0
- baobab_auth_api-0.9.0/tests/baobab_auth_api/services/test_permission_service.py +100 -0
- baobab_auth_api-0.9.0/tests/baobab_auth_api/services/test_role_service.py +88 -0
- baobab_auth_api-0.9.0/tests/baobab_auth_api/services/test_session_service.py +132 -0
- baobab_auth_api-0.9.0/tests/baobab_auth_api/services/test_user_service.py +173 -0
- baobab_auth_api-0.9.0/tests/baobab_auth_api/test_app.py +315 -0
- baobab_auth_api-0.9.0/tests/baobab_auth_api/test_config.py +211 -0
- baobab_auth_api-0.9.0/tests/baobab_auth_api/test_init.py +15 -0
- baobab_auth_api-0.9.0/tests/baobab_auth_api/test_log_filters.py +113 -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,20 @@
|
|
|
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é et validé via pydantic-settings (AuthApiSettings dans config.py).
|
|
4
|
+
|
|
5
|
+
BAOBAB_AUTH_DATABASE_URL=postgresql+asyncpg://auth:auth@localhost:5432/auth
|
|
6
|
+
BAOBAB_AUTH_ISSUER=baobab-auth
|
|
7
|
+
BAOBAB_AUTH_AUDIENCE=baobab-api
|
|
8
|
+
BAOBAB_AUTH_ACCESS_TOKEN_TTL_SECONDS=900
|
|
9
|
+
BAOBAB_AUTH_REFRESH_TOKEN_TTL_SECONDS=2592000
|
|
10
|
+
BAOBAB_AUTH_JWT_ALGORITHM=RS256
|
|
11
|
+
BAOBAB_AUTH_PASSWORD_MIN_LENGTH=12
|
|
12
|
+
BAOBAB_AUTH_LOG_LEVEL=INFO
|
|
13
|
+
BAOBAB_AUTH_ENVIRONMENT=dev
|
|
14
|
+
BAOBAB_AUTH_DEBUG=false
|
|
15
|
+
|
|
16
|
+
# CORS (liste JSON) — laisser vide en production sans validation explicite
|
|
17
|
+
# BAOBAB_AUTH_CORS_ORIGINS=["http://localhost:3000"]
|
|
18
|
+
|
|
19
|
+
# Trusted Hosts — laisser vide pour désactiver
|
|
20
|
+
# BAOBAB_AUTH_TRUSTED_HOSTS=["localhost","127.0.0.1"]
|
|
@@ -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]
|