teuthis-cms 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.
- teuthis_cms-0.1.0/.env.example +71 -0
- teuthis_cms-0.1.0/.flake8 +3 -0
- teuthis_cms-0.1.0/.gitignore +450 -0
- teuthis_cms-0.1.0/Dockerfile +20 -0
- teuthis_cms-0.1.0/PKG-INFO +19 -0
- teuthis_cms-0.1.0/alembic/env.py +59 -0
- teuthis_cms-0.1.0/alembic/script.py.mako +24 -0
- teuthis_cms-0.1.0/alembic/versions/0001_initial_tenant_site.py +58 -0
- teuthis_cms-0.1.0/alembic/versions/0002_content_type_engine.py +76 -0
- teuthis_cms-0.1.0/alembic/versions/0003_page_builder.py +67 -0
- teuthis_cms-0.1.0/alembic/versions/0004_listing_engine.py +117 -0
- teuthis_cms-0.1.0/alembic/versions/0005_lifecycle_workflow.py +139 -0
- teuthis_cms-0.1.0/alembic/versions/0006_rgpd_audit_cookies.py +251 -0
- teuthis_cms-0.1.0/alembic/versions/0007_rbac_acl_extranet.py +291 -0
- teuthis_cms-0.1.0/alembic/versions/0008_plugin_sdk.py +111 -0
- teuthis_cms-0.1.0/alembic/versions/0009_ai_socle.py +469 -0
- teuthis_cms-0.1.0/alembic/versions/0010_forms_notifications_discussions.py +229 -0
- teuthis_cms-0.1.0/alembic/versions/0011_recherche_complete.py +229 -0
- teuthis_cms-0.1.0/alembic/versions/0012_comptes_usagers.py +431 -0
- teuthis_cms-0.1.0/alembic/versions/0013_conformite_generee.py +190 -0
- teuthis_cms-0.1.0/alembic/versions/0014_multisite_propagation.py +307 -0
- teuthis_cms-0.1.0/alembic/versions/0015_json_none_backfill.py +58 -0
- teuthis_cms-0.1.0/alembic.ini +38 -0
- teuthis_cms-0.1.0/app/__init__.py +0 -0
- teuthis_cms-0.1.0/app/ai/__init__.py +58 -0
- teuthis_cms-0.1.0/app/ai/administration.py +326 -0
- teuthis_cms-0.1.0/app/ai/breaker.py +84 -0
- teuthis_cms-0.1.0/app/ai/capabilities.py +101 -0
- teuthis_cms-0.1.0/app/ai/catalogue/models.yaml +178 -0
- teuthis_cms-0.1.0/app/ai/catalogue/providers.yaml +93 -0
- teuthis_cms-0.1.0/app/ai/embeddings.py +470 -0
- teuthis_cms-0.1.0/app/ai/journal.py +165 -0
- teuthis_cms-0.1.0/app/ai/manager.py +727 -0
- teuthis_cms-0.1.0/app/ai/policies.py +320 -0
- teuthis_cms-0.1.0/app/ai/ports.py +302 -0
- teuthis_cms-0.1.0/app/ai/providers/__init__.py +17 -0
- teuthis_cms-0.1.0/app/ai/providers/loopback.py +138 -0
- teuthis_cms-0.1.0/app/ai/registry.py +379 -0
- teuthis_cms-0.1.0/app/ai/runtime.py +49 -0
- teuthis_cms-0.1.0/app/ai/schemas.py +358 -0
- teuthis_cms-0.1.0/app/ai/sovereignty.py +144 -0
- teuthis_cms-0.1.0/app/ai/suggestions.py +265 -0
- teuthis_cms-0.1.0/app/ai/tasks.py +232 -0
- teuthis_cms-0.1.0/app/ai/vector.py +82 -0
- teuthis_cms-0.1.0/app/ai_editorial/__init__.py +74 -0
- teuthis_cms-0.1.0/app/ai_editorial/alt_text.py +220 -0
- teuthis_cms-0.1.0/app/ai_editorial/chunking.py +136 -0
- teuthis_cms-0.1.0/app/ai_editorial/extraction.py +232 -0
- teuthis_cms-0.1.0/app/ai_editorial/obsolescence.py +596 -0
- teuthis_cms-0.1.0/app/ai_editorial/rag.py +709 -0
- teuthis_cms-0.1.0/app/ai_editorial/references.py +155 -0
- teuthis_cms-0.1.0/app/ai_editorial/schemas.py +305 -0
- teuthis_cms-0.1.0/app/ai_editorial/seo.py +450 -0
- teuthis_cms-0.1.0/app/api/__init__.py +0 -0
- teuthis_cms-0.1.0/app/api/access.py +511 -0
- teuthis_cms-0.1.0/app/api/account.py +775 -0
- teuthis_cms-0.1.0/app/api/ai_admin.py +597 -0
- teuthis_cms-0.1.0/app/api/ai_editorial.py +789 -0
- teuthis_cms-0.1.0/app/api/auth.py +577 -0
- teuthis_cms-0.1.0/app/api/compliance.py +791 -0
- teuthis_cms-0.1.0/app/api/content_types.py +559 -0
- teuthis_cms-0.1.0/app/api/cookies.py +435 -0
- teuthis_cms-0.1.0/app/api/discussions.py +206 -0
- teuthis_cms-0.1.0/app/api/end_user_admin.py +145 -0
- teuthis_cms-0.1.0/app/api/exports.py +158 -0
- teuthis_cms-0.1.0/app/api/forms.py +248 -0
- teuthis_cms-0.1.0/app/api/lifecycle.py +492 -0
- teuthis_cms-0.1.0/app/api/listings.py +194 -0
- teuthis_cms-0.1.0/app/api/multisite.py +658 -0
- teuthis_cms-0.1.0/app/api/pages.py +600 -0
- teuthis_cms-0.1.0/app/api/personal_files.py +134 -0
- teuthis_cms-0.1.0/app/api/plugins.py +244 -0
- teuthis_cms-0.1.0/app/api/public_forms.py +515 -0
- teuthis_cms-0.1.0/app/api/rgpd.py +479 -0
- teuthis_cms-0.1.0/app/api/search.py +135 -0
- teuthis_cms-0.1.0/app/api/search_dictionaries.py +379 -0
- teuthis_cms-0.1.0/app/api/staff_users.py +424 -0
- teuthis_cms-0.1.0/app/bundled_plugins/__init__.py +55 -0
- teuthis_cms-0.1.0/app/bundled_plugins/cartography.py +264 -0
- teuthis_cms-0.1.0/app/bundled_plugins/comments.py +37 -0
- teuthis_cms-0.1.0/app/bundled_plugins/sve.py +445 -0
- teuthis_cms-0.1.0/app/cli/__init__.py +34 -0
- teuthis_cms-0.1.0/app/cli/docker.py +241 -0
- teuthis_cms-0.1.0/app/cli/main.py +299 -0
- teuthis_cms-0.1.0/app/cli/manage.py +129 -0
- teuthis_cms-0.1.0/app/cli/migrate.py +68 -0
- teuthis_cms-0.1.0/app/cli/templates.py +143 -0
- teuthis_cms-0.1.0/app/compliance/__init__.py +30 -0
- teuthis_cms-0.1.0/app/compliance/accessibility.py +479 -0
- teuthis_cms-0.1.0/app/compliance/attributions.py +152 -0
- teuthis_cms-0.1.0/app/compliance/disclaimer.py +111 -0
- teuthis_cms-0.1.0/app/compliance/policy.py +114 -0
- teuthis_cms-0.1.0/app/compliance/privacy_policy.py +253 -0
- teuthis_cms-0.1.0/app/compliance/referential.py +330 -0
- teuthis_cms-0.1.0/app/compliance/referentials/rgaa-4.1.2.yaml +657 -0
- teuthis_cms-0.1.0/app/compliance/runtime.py +43 -0
- teuthis_cms-0.1.0/app/compliance/schemas.py +218 -0
- teuthis_cms-0.1.0/app/content/__init__.py +0 -0
- teuthis_cms-0.1.0/app/content/conditions.py +257 -0
- teuthis_cms-0.1.0/app/content/fields.py +555 -0
- teuthis_cms-0.1.0/app/content/geo.py +247 -0
- teuthis_cms-0.1.0/app/content/query.py +226 -0
- teuthis_cms-0.1.0/app/content/schemas.py +155 -0
- teuthis_cms-0.1.0/app/core/__init__.py +0 -0
- teuthis_cms-0.1.0/app/core/config.py +130 -0
- teuthis_cms-0.1.0/app/core/database.py +20 -0
- teuthis_cms-0.1.0/app/discussions/__init__.py +6 -0
- teuthis_cms-0.1.0/app/discussions/service.py +137 -0
- teuthis_cms-0.1.0/app/discussions/threads.py +114 -0
- teuthis_cms-0.1.0/app/end_users/__init__.py +14 -0
- teuthis_cms-0.1.0/app/end_users/accounts.py +466 -0
- teuthis_cms-0.1.0/app/end_users/export.py +358 -0
- teuthis_cms-0.1.0/app/end_users/identity.py +144 -0
- teuthis_cms-0.1.0/app/end_users/lifecycle.py +586 -0
- teuthis_cms-0.1.0/app/end_users/oidc.py +550 -0
- teuthis_cms-0.1.0/app/end_users/policy.py +239 -0
- teuthis_cms-0.1.0/app/end_users/prefill.py +94 -0
- teuthis_cms-0.1.0/app/end_users/schemas.py +281 -0
- teuthis_cms-0.1.0/app/end_users/sessions.py +167 -0
- teuthis_cms-0.1.0/app/end_users/space.py +382 -0
- teuthis_cms-0.1.0/app/forms/__init__.py +22 -0
- teuthis_cms-0.1.0/app/forms/captcha.py +246 -0
- teuthis_cms-0.1.0/app/forms/config.py +255 -0
- teuthis_cms-0.1.0/app/forms/export.py +320 -0
- teuthis_cms-0.1.0/app/forms/prefill.py +127 -0
- teuthis_cms-0.1.0/app/forms/submissions.py +553 -0
- teuthis_cms-0.1.0/app/forms/validation.py +223 -0
- teuthis_cms-0.1.0/app/lifecycle/__init__.py +1 -0
- teuthis_cms-0.1.0/app/lifecycle/engine.py +345 -0
- teuthis_cms-0.1.0/app/lifecycle/notifications.py +114 -0
- teuthis_cms-0.1.0/app/lifecycle/registry.py +332 -0
- teuthis_cms-0.1.0/app/lifecycle/rules.py +471 -0
- teuthis_cms-0.1.0/app/lifecycle/schemas.py +104 -0
- teuthis_cms-0.1.0/app/lifecycle/settings.py +355 -0
- teuthis_cms-0.1.0/app/lifecycle/workflow.py +202 -0
- teuthis_cms-0.1.0/app/listing/__init__.py +0 -0
- teuthis_cms-0.1.0/app/listing/config.py +366 -0
- teuthis_cms-0.1.0/app/listing/filters.py +378 -0
- teuthis_cms-0.1.0/app/listing/indexing.py +419 -0
- teuthis_cms-0.1.0/app/listing/resolver.py +320 -0
- teuthis_cms-0.1.0/app/listing/rss.py +72 -0
- teuthis_cms-0.1.0/app/listing/schemas.py +32 -0
- teuthis_cms-0.1.0/app/main.py +187 -0
- teuthis_cms-0.1.0/app/models/__init__.py +86 -0
- teuthis_cms-0.1.0/app/models/access.py +84 -0
- teuthis_cms-0.1.0/app/models/accessibility.py +142 -0
- teuthis_cms-0.1.0/app/models/ai.py +524 -0
- teuthis_cms-0.1.0/app/models/content.py +193 -0
- teuthis_cms-0.1.0/app/models/discussion.py +86 -0
- teuthis_cms-0.1.0/app/models/end_user.py +357 -0
- teuthis_cms-0.1.0/app/models/end_user_space.py +138 -0
- teuthis_cms-0.1.0/app/models/forms.py +146 -0
- teuthis_cms-0.1.0/app/models/lifecycle.py +60 -0
- teuthis_cms-0.1.0/app/models/multisite.py +239 -0
- teuthis_cms-0.1.0/app/models/notification.py +134 -0
- teuthis_cms-0.1.0/app/models/page_builder.py +65 -0
- teuthis_cms-0.1.0/app/models/personal_file.py +119 -0
- teuthis_cms-0.1.0/app/models/plugin.py +99 -0
- teuthis_cms-0.1.0/app/models/rgpd.py +225 -0
- teuthis_cms-0.1.0/app/models/search.py +157 -0
- teuthis_cms-0.1.0/app/models/search_index.py +189 -0
- teuthis_cms-0.1.0/app/models/staff.py +178 -0
- teuthis_cms-0.1.0/app/models/tenant.py +120 -0
- teuthis_cms-0.1.0/app/multisite/__init__.py +14 -0
- teuthis_cms-0.1.0/app/multisite/factory.py +513 -0
- teuthis_cms-0.1.0/app/multisite/guards.py +129 -0
- teuthis_cms-0.1.0/app/multisite/hashing.py +126 -0
- teuthis_cms-0.1.0/app/multisite/projection.py +190 -0
- teuthis_cms-0.1.0/app/multisite/replication.py +626 -0
- teuthis_cms-0.1.0/app/multisite/schema_lock.py +142 -0
- teuthis_cms-0.1.0/app/multisite/schemas.py +145 -0
- teuthis_cms-0.1.0/app/multisite/sharing.py +305 -0
- teuthis_cms-0.1.0/app/multisite/taxonomy.py +234 -0
- teuthis_cms-0.1.0/app/notifications/__init__.py +14 -0
- teuthis_cms-0.1.0/app/notifications/bridge.py +111 -0
- teuthis_cms-0.1.0/app/notifications/engine.py +464 -0
- teuthis_cms-0.1.0/app/notifications/templates.py +230 -0
- teuthis_cms-0.1.0/app/page_builder/__init__.py +0 -0
- teuthis_cms-0.1.0/app/page_builder/blocks.py +367 -0
- teuthis_cms-0.1.0/app/page_builder/columns.py +36 -0
- teuthis_cms-0.1.0/app/page_builder/content_source.py +239 -0
- teuthis_cms-0.1.0/app/page_builder/layout.py +48 -0
- teuthis_cms-0.1.0/app/page_builder/render.py +115 -0
- teuthis_cms-0.1.0/app/page_builder/schemas.py +143 -0
- teuthis_cms-0.1.0/app/page_builder/validation.py +318 -0
- teuthis_cms-0.1.0/app/plugins/__init__.py +275 -0
- teuthis_cms-0.1.0/app/plugins/ai.py +225 -0
- teuthis_cms-0.1.0/app/plugins/catalogue.py +68 -0
- teuthis_cms-0.1.0/app/plugins/composition.py +351 -0
- teuthis_cms-0.1.0/app/plugins/installation.py +296 -0
- teuthis_cms-0.1.0/app/plugins/manifest.py +603 -0
- teuthis_cms-0.1.0/app/plugins/runtime.py +53 -0
- teuthis_cms-0.1.0/app/plugins/schemas.py +96 -0
- teuthis_cms-0.1.0/app/rbac/__init__.py +53 -0
- teuthis_cms-0.1.0/app/rbac/acl.py +551 -0
- teuthis_cms-0.1.0/app/rbac/identity.py +277 -0
- teuthis_cms-0.1.0/app/rbac/mfa.py +132 -0
- teuthis_cms-0.1.0/app/rbac/passwords.py +226 -0
- teuthis_cms-0.1.0/app/rbac/policy.py +98 -0
- teuthis_cms-0.1.0/app/rbac/providers.py +181 -0
- teuthis_cms-0.1.0/app/rbac/roles.py +388 -0
- teuthis_cms-0.1.0/app/rbac/schemas.py +370 -0
- teuthis_cms-0.1.0/app/rbac/sessions.py +188 -0
- teuthis_cms-0.1.0/app/rgpd/__init__.py +1 -0
- teuthis_cms-0.1.0/app/rgpd/actor.py +104 -0
- teuthis_cms-0.1.0/app/rgpd/cookies.py +495 -0
- teuthis_cms-0.1.0/app/rgpd/detection.py +286 -0
- teuthis_cms-0.1.0/app/rgpd/exclusion.py +101 -0
- teuthis_cms-0.1.0/app/rgpd/journal.py +383 -0
- teuthis_cms-0.1.0/app/rgpd/policy.py +109 -0
- teuthis_cms-0.1.0/app/rgpd/processing.py +196 -0
- teuthis_cms-0.1.0/app/rgpd/purge.py +184 -0
- teuthis_cms-0.1.0/app/rgpd/schemas.py +276 -0
- teuthis_cms-0.1.0/app/search/__init__.py +31 -0
- teuthis_cms-0.1.0/app/search/dictionaries.py +260 -0
- teuthis_cms-0.1.0/app/search/engine.py +869 -0
- teuthis_cms-0.1.0/app/search/normalize.py +100 -0
- teuthis_cms-0.1.0/app/search/query.py +351 -0
- teuthis_cms-0.1.0/app/search/reindex.py +129 -0
- teuthis_cms-0.1.0/app/search/schemas.py +82 -0
- teuthis_cms-0.1.0/app/storage/__init__.py +7 -0
- teuthis_cms-0.1.0/app/storage/personal_files.py +418 -0
- teuthis_cms-0.1.0/pyproject.toml +72 -0
- teuthis_cms-0.1.0/tests/conftest.py +145 -0
- teuthis_cms-0.1.0/tests/test_ai_admin_api.py +440 -0
- teuthis_cms-0.1.0/tests/test_ai_editorial.py +1798 -0
- teuthis_cms-0.1.0/tests/test_ai_editorial_api.py +693 -0
- teuthis_cms-0.1.0/tests/test_ai_socle.py +1437 -0
- teuthis_cms-0.1.0/tests/test_cartography.py +856 -0
- teuthis_cms-0.1.0/tests/test_cli.py +512 -0
- teuthis_cms-0.1.0/tests/test_compliance.py +1553 -0
- teuthis_cms-0.1.0/tests/test_content_engine.py +366 -0
- teuthis_cms-0.1.0/tests/test_end_users.py +1623 -0
- teuthis_cms-0.1.0/tests/test_forms_engine.py +1693 -0
- teuthis_cms-0.1.0/tests/test_health.py +12 -0
- teuthis_cms-0.1.0/tests/test_lifecycle.py +1378 -0
- teuthis_cms-0.1.0/tests/test_listing_engine.py +787 -0
- teuthis_cms-0.1.0/tests/test_multisite.py +1847 -0
- teuthis_cms-0.1.0/tests/test_page_builder.py +879 -0
- teuthis_cms-0.1.0/tests/test_plugin_sdk.py +1093 -0
- teuthis_cms-0.1.0/tests/test_rbac.py +1544 -0
- teuthis_cms-0.1.0/tests/test_rgpd.py +1436 -0
- teuthis_cms-0.1.0/tests/test_search_engine.py +1176 -0
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Copier en .env pour le développement local. Aucune valeur IA n'est
|
|
2
|
+
# nécessaire pour que l'API démarre (CDC §14.11).
|
|
3
|
+
#
|
|
4
|
+
# --- Authentification (Epic E6) : rien à renseigner, et ce n'est pas un oubli.
|
|
5
|
+
# Les sessions du back-office sont des jetons opaques aléatoires adossés à la
|
|
6
|
+
# table `staff_sessions` (ADR-0008), pas des JWT signés : il n'y a donc aucun
|
|
7
|
+
# secret de signature à configurer, et aucun secret de développement à risquer
|
|
8
|
+
# d'emporter en production. La politique de mot de passe (16 caractères, 4
|
|
9
|
+
# classes — CDC §8.3) et la durée de session sont paramétrables **par tenant**
|
|
10
|
+
# dans `tenants.settings["rbac"]`, pas par variable d'environnement : ce sont
|
|
11
|
+
# des règles d'un projet, pas de l'instance.
|
|
12
|
+
#
|
|
13
|
+
# Le premier administrateur se crée par `POST /api/v1/auth/bootstrap`, qui ne
|
|
14
|
+
# répond que tant que le tenant n'a aucun compte de back-office — plutôt qu'un
|
|
15
|
+
# couple admin/admin posé par une migration, c'est-à-dire un mot de passe par
|
|
16
|
+
# défaut oublié en production.
|
|
17
|
+
|
|
18
|
+
DATABASE_URL=postgresql+asyncpg://teuthis:teuthis@postgres:5432/teuthis
|
|
19
|
+
REDIS_URL=redis://redis:6379/0
|
|
20
|
+
|
|
21
|
+
STORAGE_ENDPOINT=http://minio:9000
|
|
22
|
+
STORAGE_BUCKET=teuthis-media
|
|
23
|
+
STORAGE_ACCESS_KEY=teuthis
|
|
24
|
+
STORAGE_SECRET_KEY=teuthis-dev-secret
|
|
25
|
+
|
|
26
|
+
# --- IA — désactivé par défaut, à renseigner uniquement avec le profil ai-local ---
|
|
27
|
+
AI_OLLAMA_ENDPOINT=
|
|
28
|
+
AI_VLLM_ENDPOINT=
|
|
29
|
+
AI_LLAMACPP_ENDPOINT=
|
|
30
|
+
AI_OPENAI_API_KEY=
|
|
31
|
+
AI_ANTHROPIC_API_KEY=
|
|
32
|
+
AI_MISTRAL_API_KEY=
|
|
33
|
+
AI_GEMINI_API_KEY=
|
|
34
|
+
AI_CUSTOM_ENDPOINT=
|
|
35
|
+
AI_CUSTOM_API_KEY=
|
|
36
|
+
AI_CUSTOM_PROTOCOL=openai_compatible
|
|
37
|
+
|
|
38
|
+
# « restricted » (défaut) : aucun modèle déclaré comme faisant sortir les
|
|
39
|
+
# données de l'infrastructure n'est appelé. « hybrid » : sortie possible si la
|
|
40
|
+
# politique de la tâche l'autorise, jamais pour des données personnelles.
|
|
41
|
+
# « open » : sortie possible, toujours journalisée. Une valeur inconnue vaut
|
|
42
|
+
# « restricted » — une faute de frappe ne doit pas ouvrir un canal de sortie.
|
|
43
|
+
AI_SOVEREIGNTY_MODE=restricted
|
|
44
|
+
# Catalogues YAML supplémentaires du Model Registry (Epic E8). Vide = seul le
|
|
45
|
+
# catalogue livré avec le CMS est chargé. Ajouter un modèle local ne demande
|
|
46
|
+
# donc ni déploiement de code, ni migration.
|
|
47
|
+
AI_MODEL_REGISTRY_DIR=
|
|
48
|
+
# Volontairement vide : le choix du modèle d'embedding par défaut reste ouvert
|
|
49
|
+
# (ADR-0004, faute de comparatif sur des contenus français). Le premier modèle
|
|
50
|
+
# réellement déployé verrouille la dimension pgvector ; en changer ensuite est
|
|
51
|
+
# une migration avec réindexation planifiée, refusée techniquement sans elle.
|
|
52
|
+
AI_DEFAULT_EMBEDDING_MODEL=
|
|
53
|
+
AI_MAX_MONTHLY_COST=
|
|
54
|
+
AI_REQUIRE_HUMAN_VALIDATION=true
|
|
55
|
+
AI_JOB_TIMEOUT_SECONDS=120
|
|
56
|
+
AI_CACHE_TTL_DAYS=30
|
|
57
|
+
|
|
58
|
+
# --- Accessibilité : référentiels d'audit (Epic E15, ADR-0018) ---
|
|
59
|
+
# Répertoire de référentiels YAML supplémentaires. Vide = seuls les
|
|
60
|
+
# référentiels livrés sont chargés (`app/compliance/referentials/`).
|
|
61
|
+
#
|
|
62
|
+
# C'est ce réglage qui rend tenable la contrainte du point ouvert #8 : le
|
|
63
|
+
# RGAA 5 est annoncé pour fin 2026, et sa prise en charge consistera à
|
|
64
|
+
# déposer un fichier ici — sans déploiement de code, sans migration, et sans
|
|
65
|
+
# que les audits déjà saisis sous la grille 4.1.2 cessent d'être lisibles.
|
|
66
|
+
#
|
|
67
|
+
# Aucun référentiel par défaut n'est nommé, volontairement : chaque audit
|
|
68
|
+
# déclare la grille sous laquelle il a été conduit. Un « référentiel par
|
|
69
|
+
# défaut » de l'installation serait redevenu, à l'usage, « le référentiel du
|
|
70
|
+
# CMS ».
|
|
71
|
+
ACCESSIBILITY_REFERENTIAL_DIR=
|
|
@@ -0,0 +1,450 @@
|
|
|
1
|
+
## Ignore Visual Studio temporary files, build results, and
|
|
2
|
+
## files generated by popular Visual Studio add-ons.
|
|
3
|
+
##
|
|
4
|
+
## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
|
|
5
|
+
|
|
6
|
+
# User-specific files
|
|
7
|
+
*.rsuser
|
|
8
|
+
*.suo
|
|
9
|
+
*.user
|
|
10
|
+
*.userosscache
|
|
11
|
+
*.sln.docstates
|
|
12
|
+
*.env
|
|
13
|
+
|
|
14
|
+
# User-specific files (MonoDevelop/Xamarin Studio)
|
|
15
|
+
*.userprefs
|
|
16
|
+
|
|
17
|
+
# Mono auto generated files
|
|
18
|
+
mono_crash.*
|
|
19
|
+
|
|
20
|
+
# Build results
|
|
21
|
+
[Dd]ebug/
|
|
22
|
+
[Dd]ebugPublic/
|
|
23
|
+
[Rr]elease/
|
|
24
|
+
[Rr]eleases/
|
|
25
|
+
|
|
26
|
+
[Dd]ebug/x64/
|
|
27
|
+
[Dd]ebugPublic/x64/
|
|
28
|
+
[Rr]elease/x64/
|
|
29
|
+
[Rr]eleases/x64/
|
|
30
|
+
bin/x64/
|
|
31
|
+
obj/x64/
|
|
32
|
+
|
|
33
|
+
[Dd]ebug/x86/
|
|
34
|
+
[Dd]ebugPublic/x86/
|
|
35
|
+
[Rr]elease/x86/
|
|
36
|
+
[Rr]eleases/x86/
|
|
37
|
+
bin/x86/
|
|
38
|
+
obj/x86/
|
|
39
|
+
|
|
40
|
+
[Ww][Ii][Nn]32/
|
|
41
|
+
[Aa][Rr][Mm]/
|
|
42
|
+
[Aa][Rr][Mm]64/
|
|
43
|
+
[Aa][Rr][Mm]64[Ee][Cc]/
|
|
44
|
+
bld/
|
|
45
|
+
[Oo]bj/
|
|
46
|
+
[Oo]ut/
|
|
47
|
+
[Ll]og/
|
|
48
|
+
[Ll]ogs/
|
|
49
|
+
|
|
50
|
+
# Build results on 'Bin' directories
|
|
51
|
+
**/[Bb]in/*
|
|
52
|
+
# Uncomment if you have tasks that rely on *.refresh files to move binaries
|
|
53
|
+
# (https://github.com/github/gitignore/pull/3736)
|
|
54
|
+
#!**/[Bb]in/*.refresh
|
|
55
|
+
|
|
56
|
+
# Visual Studio 2015/2017 cache/options directory
|
|
57
|
+
.vs/
|
|
58
|
+
# Uncomment if you have tasks that create the project's static files in wwwroot
|
|
59
|
+
#wwwroot/
|
|
60
|
+
|
|
61
|
+
# Visual Studio 2017 auto generated files
|
|
62
|
+
Generated\ Files/
|
|
63
|
+
|
|
64
|
+
# MSTest test Results
|
|
65
|
+
[Tt]est[Rr]esult*/
|
|
66
|
+
[Bb]uild[Ll]og.*
|
|
67
|
+
*.trx
|
|
68
|
+
|
|
69
|
+
# NUnit
|
|
70
|
+
*.VisualState.xml
|
|
71
|
+
TestResult.xml
|
|
72
|
+
nunit-*.xml
|
|
73
|
+
|
|
74
|
+
# Approval Tests result files
|
|
75
|
+
*.received.*
|
|
76
|
+
|
|
77
|
+
# Build Results of an ATL Project
|
|
78
|
+
[Dd]ebugPS/
|
|
79
|
+
[Rr]eleasePS/
|
|
80
|
+
dlldata.c
|
|
81
|
+
|
|
82
|
+
# Benchmark Results
|
|
83
|
+
BenchmarkDotNet.Artifacts/
|
|
84
|
+
|
|
85
|
+
# .NET Core
|
|
86
|
+
project.lock.json
|
|
87
|
+
project.fragment.lock.json
|
|
88
|
+
artifacts/
|
|
89
|
+
.artifacts/
|
|
90
|
+
|
|
91
|
+
# ASP.NET Scaffolding
|
|
92
|
+
ScaffoldingReadMe.txt
|
|
93
|
+
|
|
94
|
+
# StyleCop
|
|
95
|
+
StyleCopReport.xml
|
|
96
|
+
|
|
97
|
+
# Files built by Visual Studio
|
|
98
|
+
*_i.c
|
|
99
|
+
*_p.c
|
|
100
|
+
*_h.h
|
|
101
|
+
*.ilk
|
|
102
|
+
*.meta
|
|
103
|
+
*.obj
|
|
104
|
+
*.idb
|
|
105
|
+
*.iobj
|
|
106
|
+
*.pch
|
|
107
|
+
*.pdb
|
|
108
|
+
*.ipdb
|
|
109
|
+
*.pgc
|
|
110
|
+
*.pgd
|
|
111
|
+
*.rsp
|
|
112
|
+
# but not Directory.Build.rsp, as it configures directory-level build defaults
|
|
113
|
+
!Directory.Build.rsp
|
|
114
|
+
*.sbr
|
|
115
|
+
*.tlb
|
|
116
|
+
*.tli
|
|
117
|
+
*.tlh
|
|
118
|
+
*.tmp
|
|
119
|
+
*.tmp_proj
|
|
120
|
+
*_wpftmp.csproj
|
|
121
|
+
*.log
|
|
122
|
+
*.tlog
|
|
123
|
+
*.vspscc
|
|
124
|
+
*.vssscc
|
|
125
|
+
.builds
|
|
126
|
+
*.pidb
|
|
127
|
+
*.svclog
|
|
128
|
+
*.scc
|
|
129
|
+
|
|
130
|
+
# Chutzpah Test files
|
|
131
|
+
_Chutzpah*
|
|
132
|
+
|
|
133
|
+
# Visual C++ cache files
|
|
134
|
+
ipch/
|
|
135
|
+
*.aps
|
|
136
|
+
*.ncb
|
|
137
|
+
*.opendb
|
|
138
|
+
*.opensdf
|
|
139
|
+
*.sdf
|
|
140
|
+
*.cachefile
|
|
141
|
+
*.VC.db
|
|
142
|
+
*.VC.VC.opendb
|
|
143
|
+
|
|
144
|
+
# Visual Studio profiler
|
|
145
|
+
*.psess
|
|
146
|
+
*.vsp
|
|
147
|
+
*.vspx
|
|
148
|
+
*.sap
|
|
149
|
+
|
|
150
|
+
# Visual Studio Trace Files
|
|
151
|
+
*.e2e
|
|
152
|
+
|
|
153
|
+
# TFS 2012 Local Workspace
|
|
154
|
+
$tf/
|
|
155
|
+
|
|
156
|
+
# Guidance Automation Toolkit
|
|
157
|
+
*.gpState
|
|
158
|
+
|
|
159
|
+
# ReSharper is a .NET coding add-in
|
|
160
|
+
_ReSharper*/
|
|
161
|
+
*.[Rr]e[Ss]harper
|
|
162
|
+
*.DotSettings.user
|
|
163
|
+
|
|
164
|
+
# TeamCity is a build add-in
|
|
165
|
+
_TeamCity*
|
|
166
|
+
|
|
167
|
+
# DotCover is a Code Coverage Tool
|
|
168
|
+
*.dotCover
|
|
169
|
+
|
|
170
|
+
# AxoCover is a Code Coverage Tool
|
|
171
|
+
.axoCover/*
|
|
172
|
+
!.axoCover/settings.json
|
|
173
|
+
|
|
174
|
+
# Coverlet is a free, cross platform Code Coverage Tool
|
|
175
|
+
coverage*.json
|
|
176
|
+
coverage*.xml
|
|
177
|
+
coverage*.info
|
|
178
|
+
|
|
179
|
+
# Visual Studio code coverage results
|
|
180
|
+
*.coverage
|
|
181
|
+
*.coveragexml
|
|
182
|
+
|
|
183
|
+
# NCrunch
|
|
184
|
+
_NCrunch_*
|
|
185
|
+
.NCrunch_*
|
|
186
|
+
.*crunch*.local.xml
|
|
187
|
+
nCrunchTemp_*
|
|
188
|
+
|
|
189
|
+
# MightyMoose
|
|
190
|
+
*.mm.*
|
|
191
|
+
AutoTest.Net/
|
|
192
|
+
|
|
193
|
+
# Web workbench (sass)
|
|
194
|
+
.sass-cache/
|
|
195
|
+
|
|
196
|
+
# Installshield output folder
|
|
197
|
+
[Ee]xpress/
|
|
198
|
+
|
|
199
|
+
# DocProject is a documentation generator add-in
|
|
200
|
+
DocProject/buildhelp/
|
|
201
|
+
DocProject/Help/*.HxT
|
|
202
|
+
DocProject/Help/*.HxC
|
|
203
|
+
DocProject/Help/*.hhc
|
|
204
|
+
DocProject/Help/*.hhk
|
|
205
|
+
DocProject/Help/*.hhp
|
|
206
|
+
DocProject/Help/Html2
|
|
207
|
+
DocProject/Help/html
|
|
208
|
+
|
|
209
|
+
# Click-Once directory
|
|
210
|
+
publish/
|
|
211
|
+
|
|
212
|
+
# Publish Web Output
|
|
213
|
+
*.[Pp]ublish.xml
|
|
214
|
+
*.azurePubxml
|
|
215
|
+
# Note: Comment the next line if you want to checkin your web deploy settings,
|
|
216
|
+
# but database connection strings (with potential passwords) will be unencrypted
|
|
217
|
+
*.pubxml
|
|
218
|
+
*.publishproj
|
|
219
|
+
|
|
220
|
+
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
|
221
|
+
# checkin your Azure Web App publish settings, but sensitive information contained
|
|
222
|
+
# in these scripts will be unencrypted
|
|
223
|
+
PublishScripts/
|
|
224
|
+
|
|
225
|
+
# NuGet Packages
|
|
226
|
+
*.nupkg
|
|
227
|
+
# NuGet Symbol Packages
|
|
228
|
+
*.snupkg
|
|
229
|
+
# The packages folder can be ignored because of Package Restore
|
|
230
|
+
**/[Pp]ackages/*
|
|
231
|
+
# except build/, which is used as an MSBuild target.
|
|
232
|
+
!**/[Pp]ackages/build/
|
|
233
|
+
# Uncomment if necessary however generally it will be regenerated when needed
|
|
234
|
+
#!**/[Pp]ackages/repositories.config
|
|
235
|
+
# NuGet v3's project.json files produces more ignorable files
|
|
236
|
+
*.nuget.props
|
|
237
|
+
*.nuget.targets
|
|
238
|
+
|
|
239
|
+
# Microsoft Azure Build Output
|
|
240
|
+
csx/
|
|
241
|
+
*.build.csdef
|
|
242
|
+
|
|
243
|
+
# Microsoft Azure Emulator
|
|
244
|
+
ecf/
|
|
245
|
+
rcf/
|
|
246
|
+
|
|
247
|
+
# Windows Store app package directories and files
|
|
248
|
+
AppPackages/
|
|
249
|
+
BundleArtifacts/
|
|
250
|
+
Package.StoreAssociation.xml
|
|
251
|
+
_pkginfo.txt
|
|
252
|
+
*.appx
|
|
253
|
+
*.appxbundle
|
|
254
|
+
*.appxupload
|
|
255
|
+
|
|
256
|
+
# Visual Studio cache files
|
|
257
|
+
# files ending in .cache can be ignored
|
|
258
|
+
*.[Cc]ache
|
|
259
|
+
# but keep track of directories ending in .cache
|
|
260
|
+
!?*.[Cc]ache/
|
|
261
|
+
|
|
262
|
+
# Others
|
|
263
|
+
ClientBin/
|
|
264
|
+
~$*
|
|
265
|
+
*~
|
|
266
|
+
*.dbmdl
|
|
267
|
+
*.dbproj.schemaview
|
|
268
|
+
*.jfm
|
|
269
|
+
*.pfx
|
|
270
|
+
*.publishsettings
|
|
271
|
+
orleans.codegen.cs
|
|
272
|
+
|
|
273
|
+
# Including strong name files can present a security risk
|
|
274
|
+
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
|
|
275
|
+
#*.snk
|
|
276
|
+
|
|
277
|
+
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
|
278
|
+
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
|
279
|
+
#bower_components/
|
|
280
|
+
|
|
281
|
+
# RIA/Silverlight projects
|
|
282
|
+
Generated_Code/
|
|
283
|
+
|
|
284
|
+
# Backup & report files from converting an old project file
|
|
285
|
+
# to a newer Visual Studio version. Backup files are not needed,
|
|
286
|
+
# because we have git ;-)
|
|
287
|
+
_UpgradeReport_Files/
|
|
288
|
+
Backup*/
|
|
289
|
+
UpgradeLog*.XML
|
|
290
|
+
UpgradeLog*.htm
|
|
291
|
+
ServiceFabricBackup/
|
|
292
|
+
*.rptproj.bak
|
|
293
|
+
|
|
294
|
+
# SQL Server files
|
|
295
|
+
*.mdf
|
|
296
|
+
*.ldf
|
|
297
|
+
*.ndf
|
|
298
|
+
|
|
299
|
+
# Business Intelligence projects
|
|
300
|
+
*.rdl.data
|
|
301
|
+
*.bim.layout
|
|
302
|
+
*.bim_*.settings
|
|
303
|
+
*.rptproj.rsuser
|
|
304
|
+
*- [Bb]ackup.rdl
|
|
305
|
+
*- [Bb]ackup ([0-9]).rdl
|
|
306
|
+
*- [Bb]ackup ([0-9][0-9]).rdl
|
|
307
|
+
|
|
308
|
+
# Microsoft Fakes
|
|
309
|
+
FakesAssemblies/
|
|
310
|
+
|
|
311
|
+
# GhostDoc plugin setting file
|
|
312
|
+
*.GhostDoc.xml
|
|
313
|
+
|
|
314
|
+
# Node.js Tools for Visual Studio
|
|
315
|
+
.ntvs_analysis.dat
|
|
316
|
+
node_modules/
|
|
317
|
+
|
|
318
|
+
# Visual Studio 6 build log
|
|
319
|
+
*.plg
|
|
320
|
+
|
|
321
|
+
# Visual Studio 6 workspace options file
|
|
322
|
+
*.opt
|
|
323
|
+
|
|
324
|
+
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
|
325
|
+
*.vbw
|
|
326
|
+
|
|
327
|
+
# Visual Studio 6 workspace and project file (working project files containing files to include in project)
|
|
328
|
+
*.dsw
|
|
329
|
+
*.dsp
|
|
330
|
+
|
|
331
|
+
# Visual Studio 6 technical files
|
|
332
|
+
*.ncb
|
|
333
|
+
*.aps
|
|
334
|
+
|
|
335
|
+
# Visual Studio LightSwitch build output
|
|
336
|
+
**/*.HTMLClient/GeneratedArtifacts
|
|
337
|
+
**/*.DesktopClient/GeneratedArtifacts
|
|
338
|
+
**/*.DesktopClient/ModelManifest.xml
|
|
339
|
+
**/*.Server/GeneratedArtifacts
|
|
340
|
+
**/*.Server/ModelManifest.xml
|
|
341
|
+
_Pvt_Extensions
|
|
342
|
+
|
|
343
|
+
# Paket dependency manager
|
|
344
|
+
**/.paket/paket.exe
|
|
345
|
+
paket-files/
|
|
346
|
+
|
|
347
|
+
# FAKE - F# Make
|
|
348
|
+
**/.fake/
|
|
349
|
+
|
|
350
|
+
# CodeRush personal settings
|
|
351
|
+
**/.cr/personal
|
|
352
|
+
|
|
353
|
+
# Python Tools for Visual Studio (PTVS)
|
|
354
|
+
**/__pycache__/
|
|
355
|
+
*.pyc
|
|
356
|
+
|
|
357
|
+
# Cake - Uncomment if you are using it
|
|
358
|
+
#tools/**
|
|
359
|
+
#!tools/packages.config
|
|
360
|
+
|
|
361
|
+
# Tabs Studio
|
|
362
|
+
*.tss
|
|
363
|
+
|
|
364
|
+
# Telerik's JustMock configuration file
|
|
365
|
+
*.jmconfig
|
|
366
|
+
|
|
367
|
+
# BizTalk build output
|
|
368
|
+
*.btp.cs
|
|
369
|
+
*.btm.cs
|
|
370
|
+
*.odx.cs
|
|
371
|
+
*.xsd.cs
|
|
372
|
+
|
|
373
|
+
# OpenCover UI analysis results
|
|
374
|
+
OpenCover/
|
|
375
|
+
|
|
376
|
+
# Azure Stream Analytics local run output
|
|
377
|
+
ASALocalRun/
|
|
378
|
+
|
|
379
|
+
# MSBuild Binary and Structured Log
|
|
380
|
+
*.binlog
|
|
381
|
+
MSBuild_Logs/
|
|
382
|
+
|
|
383
|
+
# AWS SAM Build and Temporary Artifacts folder
|
|
384
|
+
.aws-sam
|
|
385
|
+
|
|
386
|
+
# NVidia Nsight GPU debugger configuration file
|
|
387
|
+
*.nvuser
|
|
388
|
+
|
|
389
|
+
# MFractors (Xamarin productivity tool) working folder
|
|
390
|
+
**/.mfractor/
|
|
391
|
+
|
|
392
|
+
# Local History for Visual Studio
|
|
393
|
+
**/.localhistory/
|
|
394
|
+
|
|
395
|
+
# Visual Studio History (VSHistory) files
|
|
396
|
+
.vshistory/
|
|
397
|
+
|
|
398
|
+
# BeatPulse healthcheck temp database
|
|
399
|
+
healthchecksdb
|
|
400
|
+
|
|
401
|
+
# Backup folder for Package Reference Convert tool in Visual Studio 2017
|
|
402
|
+
MigrationBackup/
|
|
403
|
+
|
|
404
|
+
# Ionide (cross platform F# VS Code tools) working folder
|
|
405
|
+
**/.ionide/
|
|
406
|
+
|
|
407
|
+
# Fody - auto-generated XML schema
|
|
408
|
+
FodyWeavers.xsd
|
|
409
|
+
|
|
410
|
+
# VS Code files for those working on multiple tools
|
|
411
|
+
.vscode/*
|
|
412
|
+
!.vscode/settings.json
|
|
413
|
+
!.vscode/tasks.json
|
|
414
|
+
!.vscode/launch.json
|
|
415
|
+
!.vscode/extensions.json
|
|
416
|
+
!.vscode/*.code-snippets
|
|
417
|
+
|
|
418
|
+
# Local History for Visual Studio Code
|
|
419
|
+
.history/
|
|
420
|
+
|
|
421
|
+
# Built Visual Studio Code Extensions
|
|
422
|
+
*.vsix
|
|
423
|
+
|
|
424
|
+
# Windows Installer files from build outputs
|
|
425
|
+
*.cab
|
|
426
|
+
*.msi
|
|
427
|
+
*.msix
|
|
428
|
+
*.msm
|
|
429
|
+
*.msp
|
|
430
|
+
|
|
431
|
+
|
|
432
|
+
# Claude Code local tooling (agents, settings) — not shared via git
|
|
433
|
+
.claude/
|
|
434
|
+
|
|
435
|
+
# calamars monorepo — Nuxt / Python build & env artifacts
|
|
436
|
+
apps/admin/.nuxt/
|
|
437
|
+
apps/admin/.output/
|
|
438
|
+
apps/api/.venv/
|
|
439
|
+
apps/api/__pycache__/
|
|
440
|
+
apps/api/.pytest_cache/
|
|
441
|
+
apps/api/*.egg-info/
|
|
442
|
+
.env
|
|
443
|
+
apps/api/.env
|
|
444
|
+
apps/admin/.env
|
|
445
|
+
|
|
446
|
+
# Dépôt local des fichiers liés à une personne physique (Epic E12,
|
|
447
|
+
# `settings.personal_file_root`). Des données personnelles réelles y
|
|
448
|
+
# atterrissent dès le premier export RGPD : elles ne doivent jamais
|
|
449
|
+
# entrer dans un dépôt Git, fût-il privé.
|
|
450
|
+
apps/api/var/
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# python:3.12-alpine, épinglé par digest pour la reproductibilité des builds
|
|
2
|
+
# (cf. docs/adr/0007-image-base-python-api-alpine.md). Pas de build-deps
|
|
3
|
+
# (gcc/libpq-dev) : asyncpg/uvloop/httptools publient des wheels musllinux
|
|
4
|
+
# prêts à l'emploi, aucune compilation native requise.
|
|
5
|
+
FROM python:3.12-alpine@sha256:d09d15e60962ca365d1cd544a48773bac9d33f2fb1b00f2aa0deec78ade7dc31
|
|
6
|
+
|
|
7
|
+
WORKDIR /app
|
|
8
|
+
|
|
9
|
+
# COPY . . précède le pip install : `-e .` construit un editable install qui
|
|
10
|
+
# a besoin du paquet `app/` présent sur disque au moment de l'install (sans
|
|
11
|
+
# quoi hatchling ne l'enregistre nulle part et `import app` échoue partout
|
|
12
|
+
# hors du répertoire de travail — y compris pour `pytest` exécuté seul dans
|
|
13
|
+
# l'image). Coût assumé : le layer pip install n'est plus mis en cache
|
|
14
|
+
# indépendamment du code source.
|
|
15
|
+
COPY . .
|
|
16
|
+
RUN pip install --no-cache-dir -e ".[dev]"
|
|
17
|
+
|
|
18
|
+
EXPOSE 8000
|
|
19
|
+
|
|
20
|
+
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: teuthis-cms
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Teuthis-CMS — API Core (Sprint 0 skeleton)
|
|
5
|
+
Requires-Python: >=3.12
|
|
6
|
+
Requires-Dist: alembic>=1.14
|
|
7
|
+
Requires-Dist: asyncpg>=0.30
|
|
8
|
+
Requires-Dist: fastapi>=0.115
|
|
9
|
+
Requires-Dist: pydantic-settings>=2.6
|
|
10
|
+
Requires-Dist: pydantic>=2.9
|
|
11
|
+
Requires-Dist: pyyaml>=6.0
|
|
12
|
+
Requires-Dist: redis>=5.2
|
|
13
|
+
Requires-Dist: sqlalchemy[asyncio]>=2.0
|
|
14
|
+
Requires-Dist: uvicorn[standard]>=0.32
|
|
15
|
+
Provides-Extra: dev
|
|
16
|
+
Requires-Dist: httpx>=0.27; extra == 'dev'
|
|
17
|
+
Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
|
|
18
|
+
Requires-Dist: pytest>=8.3; extra == 'dev'
|
|
19
|
+
Requires-Dist: ruff>=0.7; extra == 'dev'
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
from logging.config import fileConfig
|
|
3
|
+
|
|
4
|
+
from sqlalchemy.ext.asyncio import create_async_engine
|
|
5
|
+
|
|
6
|
+
from alembic import context
|
|
7
|
+
from app.core.config import settings
|
|
8
|
+
from app.core.database import Base
|
|
9
|
+
from app.models import Site, Tenant # noqa: F401 (enregistre les modèles sur Base.metadata)
|
|
10
|
+
|
|
11
|
+
config = context.config
|
|
12
|
+
if config.config_file_name is not None:
|
|
13
|
+
fileConfig(config.config_file_name)
|
|
14
|
+
|
|
15
|
+
# URL de la base : l'appelant peut l'imposer par `sqlalchemy.url`, sinon on
|
|
16
|
+
# retombe sur la configuration applicative.
|
|
17
|
+
#
|
|
18
|
+
# Le second cas est celui du dépôt — `alembic upgrade head`, la CI,
|
|
19
|
+
# `docker compose up` —, où `alembic.ini` laisse volontairement
|
|
20
|
+
# `sqlalchemy.url` vide pour qu'aucune URL ne soit écrite en dur à côté de
|
|
21
|
+
# celle du `.env`. Le premier est celui de la CLI de packaging (ADR-0023,
|
|
22
|
+
# `app/cli/migrate.py`) : `teuthiscms <projet>` migre la base du projet
|
|
23
|
+
# qu'elle vient de créer alors qu'elle s'exécute encore depuis le répertoire
|
|
24
|
+
# *parent*, où `Settings` n'a aucun `.env` à lire et retomberait sur l'hôte
|
|
25
|
+
# `postgres` de `docker-compose.yml`. Sans cette lecture, l'URL passée en
|
|
26
|
+
# paramètre serait silencieusement ignorée.
|
|
27
|
+
database_url = config.get_main_option("sqlalchemy.url") or settings.database_url
|
|
28
|
+
|
|
29
|
+
target_metadata = Base.metadata
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def run_migrations_offline() -> None:
|
|
33
|
+
context.configure(
|
|
34
|
+
url=database_url,
|
|
35
|
+
target_metadata=target_metadata,
|
|
36
|
+
literal_binds=True,
|
|
37
|
+
dialect_opts={"paramstyle": "named"},
|
|
38
|
+
)
|
|
39
|
+
with context.begin_transaction():
|
|
40
|
+
context.run_migrations()
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def do_run_migrations(connection) -> None:
|
|
44
|
+
context.configure(connection=connection, target_metadata=target_metadata)
|
|
45
|
+
with context.begin_transaction():
|
|
46
|
+
context.run_migrations()
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
async def run_migrations_online() -> None:
|
|
50
|
+
connectable = create_async_engine(database_url)
|
|
51
|
+
async with connectable.connect() as connection:
|
|
52
|
+
await connection.run_sync(do_run_migrations)
|
|
53
|
+
await connectable.dispose()
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
if context.is_offline_mode():
|
|
57
|
+
run_migrations_offline()
|
|
58
|
+
else:
|
|
59
|
+
asyncio.run(run_migrations_online())
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"""${message}
|
|
2
|
+
|
|
3
|
+
Revision ID: ${up_revision}
|
|
4
|
+
Revises: ${down_revision | comma,n}
|
|
5
|
+
Create Date: ${create_date}
|
|
6
|
+
"""
|
|
7
|
+
from typing import Sequence, Union
|
|
8
|
+
|
|
9
|
+
from alembic import op
|
|
10
|
+
import sqlalchemy as sa
|
|
11
|
+
${imports if imports else ""}
|
|
12
|
+
|
|
13
|
+
revision: str = ${repr(up_revision)}
|
|
14
|
+
down_revision: Union[str, None] = ${repr(down_revision)}
|
|
15
|
+
branch_labels: Union[str, Sequence[str], None] = ${repr(branch_labels)}
|
|
16
|
+
depends_on: Union[str, Sequence[str], None] = ${repr(depends_on)}
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def upgrade() -> None:
|
|
20
|
+
${upgrades if upgrades else "pass"}
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def downgrade() -> None:
|
|
24
|
+
${downgrades if downgrades else "pass"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"""Extensions PostgreSQL + socle tenant/site.
|
|
2
|
+
|
|
3
|
+
Pose dès le Sprint 0 (CDC §3.2, §14.11) :
|
|
4
|
+
- `pgvector`, nécessaire pour les embeddings de l'Epic AI Socle (E8), même si
|
|
5
|
+
aucune table `ai_embeddings` n'existe encore — éviter une extension ajoutée
|
|
6
|
+
au dernier moment sur une base en production.
|
|
7
|
+
- `unaccent`, condition 2 de la trajectoire recherche du CDC §10.2 (config
|
|
8
|
+
linguistique française explicite, pas seulement de l'anglais par défaut).
|
|
9
|
+
- Les tables `tenants` / `sites`, socle multi-tenant minimal, sans aucune
|
|
10
|
+
règle de mutualisation (Epic E10 / jalon M9).
|
|
11
|
+
|
|
12
|
+
Revision ID: 0001
|
|
13
|
+
Revises:
|
|
14
|
+
Create Date: 2026-08-19
|
|
15
|
+
"""
|
|
16
|
+
from collections.abc import Sequence
|
|
17
|
+
|
|
18
|
+
import sqlalchemy as sa
|
|
19
|
+
from sqlalchemy.dialects import postgresql
|
|
20
|
+
|
|
21
|
+
from alembic import op
|
|
22
|
+
|
|
23
|
+
revision: str = "0001"
|
|
24
|
+
down_revision: str | None = None
|
|
25
|
+
branch_labels: str | Sequence[str] | None = None
|
|
26
|
+
depends_on: str | Sequence[str] | None = None
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def upgrade() -> None:
|
|
30
|
+
op.execute("CREATE EXTENSION IF NOT EXISTS vector")
|
|
31
|
+
op.execute("CREATE EXTENSION IF NOT EXISTS unaccent")
|
|
32
|
+
|
|
33
|
+
op.create_table(
|
|
34
|
+
"tenants",
|
|
35
|
+
sa.Column("id", postgresql.UUID(as_uuid=True), primary_key=True),
|
|
36
|
+
sa.Column("name", sa.String(255), nullable=False),
|
|
37
|
+
sa.Column("created_at", sa.DateTime(timezone=True), server_default=sa.func.now()),
|
|
38
|
+
)
|
|
39
|
+
op.create_table(
|
|
40
|
+
"sites",
|
|
41
|
+
sa.Column("id", postgresql.UUID(as_uuid=True), primary_key=True),
|
|
42
|
+
sa.Column(
|
|
43
|
+
"tenant_id",
|
|
44
|
+
postgresql.UUID(as_uuid=True),
|
|
45
|
+
sa.ForeignKey("tenants.id", ondelete="CASCADE"),
|
|
46
|
+
nullable=False,
|
|
47
|
+
),
|
|
48
|
+
sa.Column("name", sa.String(255), nullable=False),
|
|
49
|
+
sa.Column("subdomain", sa.String(255), nullable=False, unique=True),
|
|
50
|
+
sa.Column("created_at", sa.DateTime(timezone=True), server_default=sa.func.now()),
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def downgrade() -> None:
|
|
55
|
+
op.drop_table("sites")
|
|
56
|
+
op.drop_table("tenants")
|
|
57
|
+
op.execute("DROP EXTENSION IF EXISTS unaccent")
|
|
58
|
+
op.execute("DROP EXTENSION IF EXISTS vector")
|