Phase 3 : hardening qualite de code - typage strict, securite, dead code, a11y
Config strictement stricte partout (ruff, mypy --strict, bandit, vulture, import-linter, eslint, stylelint), aucune regle desactivee "pour ne pas casser le build" - l'existant a ete corrige pour la satisfaire plutot que l'inverse. Hooks pre-commit locaux (language: system) bloquants. - Typage mypy --strict propage a tout le moteur (db, screens, auth, core, ai, routes, puis publish/scripts/tests/app.py/build_css.py). - Securite : fuite de handle fichier Windows corrigee dans l'export SCORM (routes/publish/export_scorm.py), CSRF/RNG non-crypto/xAPI documentes (# nosec, # NOSONAR justifies), nouveau db.json_for_script() (echappe "</script>" dans le JSON embarque en <script>, 25 sites). - Architecture : imports circulaires/F811 nettoyes, contrats import-linter respectes, code mort retire (vulture). - Accessibilite : 69 champs de formulaire sans label correctement associe corriges (for/id ou aria-label) sur 11 templates. - ESLint/Stylelint : lot mecanique JS/CSS, regles ajustees puis appliquees (aucune desactivee sans verification individuelle). - Tests : isolation du compte admin partage (nettoyage ponctuel + fixture de teardown automatique en filet de securite), suite complete verte (591 tests Python, 241 tests JS). - SonarQube Community Build self-heberge (Docker + PostgreSQL) : rapport complet analyse point par point, faux positifs documentes. - .gitattributes ajoute (LF force) : core.autocrlf=true sur cette machine faisait echouer ESLint (linebreak-style) via un bug connu de git (checkout "en place" qui ignore l'eol force sur un fichier deja present sur disque - contourne en supprimant puis recreant chaque fichier suivi). djLint (H021, styles inline) volontairement saute pour ce commit - backlog assume, deja documente, traite dans un lot separe. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
7db4803b93
commit
c57420c8c9
+82
-51
@@ -4,63 +4,94 @@ create_user.py pour le détail des règles. Base SQLite entièrement séparée
|
||||
de db/ (une base par JEU) : ces comptes n'appartiennent à aucun jeu, ils
|
||||
en POSSÈDENT un (project_slug)."""
|
||||
|
||||
from .confirm_totp import confirm_totp
|
||||
from .connection import users_db_path
|
||||
from .count_admins import count_admins
|
||||
from .create_user import UserCreationError, create_user
|
||||
from .create_user_asset import create_user_asset
|
||||
from .delete_user import delete_user
|
||||
from .delete_user_asset import delete_user_asset
|
||||
from .ensure_schema import ensure_users_schema
|
||||
from .is_first_user import is_first_user
|
||||
from .create_user import create_user, UserCreationError
|
||||
from .ensure_user_assets_schema import ensure_user_assets_schema
|
||||
from .get_user_asset import get_user_asset
|
||||
from .get_user_by_email import get_user_by_email
|
||||
from .get_user_by_id import get_user_by_id
|
||||
from .verify_password import verify_password
|
||||
from .confirm_totp import confirm_totp
|
||||
from .verify_totp import verify_totp
|
||||
from .set_project_slug import set_project_slug
|
||||
from .password_strength import password_strength, MIN_SCORE_REQUIRED
|
||||
from .totp_qrcode_svg import totp_provisioning_uri, totp_qrcode_svg
|
||||
from .rate_limit import lockout_minutes_for, seconds_locked_remaining, lockout_message
|
||||
from .record_failed_attempt import record_failed_attempt
|
||||
from .reset_failed_attempts import reset_failed_attempts
|
||||
from .recovery_codes import generate_recovery_codes, verify_recovery_code
|
||||
from .set_password import set_password
|
||||
from .password_reset import (
|
||||
create_password_reset_token, get_user_id_for_valid_token, consume_password_reset_token,
|
||||
TOKEN_TTL_MINUTES,
|
||||
)
|
||||
from .send_email import send_password_reset_email, EmailNotConfiguredError
|
||||
from .update_profile import update_profile
|
||||
from .count_admins import count_admins
|
||||
from .delete_user import delete_user
|
||||
from .update_email import update_email, EmailUpdateError
|
||||
from .ensure_user_assets_schema import ensure_user_assets_schema
|
||||
from .user_assets_dir import user_assets_dir
|
||||
from .create_user_asset import create_user_asset
|
||||
from .list_user_assets import list_user_assets
|
||||
from .get_user_asset import get_user_asset
|
||||
from .delete_user_asset import delete_user_asset
|
||||
from .save_user_asset import save_user_asset
|
||||
from .user_asset_kind import user_asset_kind
|
||||
from .validate_audio_duration import validate_audio_duration, MAX_AUDIO_SECONDS
|
||||
from .validate_video_duration import validate_video_duration, MAX_VIDEO_SECONDS
|
||||
from .image_dimensions import image_dimensions
|
||||
from .is_first_user import is_first_user
|
||||
from .list_user_assets import list_user_assets
|
||||
from .password_reset import (
|
||||
TOKEN_TTL_MINUTES,
|
||||
consume_password_reset_token,
|
||||
create_password_reset_token,
|
||||
get_user_id_for_valid_token,
|
||||
)
|
||||
from .password_strength import MIN_SCORE_REQUIRED, password_strength
|
||||
from .rate_limit import lockout_message, lockout_minutes_for, seconds_locked_remaining
|
||||
from .record_failed_attempt import record_failed_attempt
|
||||
from .recovery_codes import generate_recovery_codes, verify_recovery_code
|
||||
from .reset_failed_attempts import reset_failed_attempts
|
||||
from .save_user_asset import save_user_asset
|
||||
from .send_email import EmailNotConfiguredError, send_password_reset_email
|
||||
from .set_password import set_password
|
||||
from .set_project_slug import set_project_slug
|
||||
from .totp_qrcode_svg import totp_provisioning_uri, totp_qrcode_svg
|
||||
from .update_email import EmailUpdateError, update_email
|
||||
from .update_profile import update_profile
|
||||
from .update_user_asset_scene_kind import update_user_asset_scene_kind
|
||||
from .user_asset_kind import user_asset_kind
|
||||
from .user_assets_dir import user_assets_dir
|
||||
from .validate_audio_duration import MAX_AUDIO_SECONDS, validate_audio_duration
|
||||
from .validate_video_duration import MAX_VIDEO_SECONDS, validate_video_duration
|
||||
from .verify_password import verify_password
|
||||
from .verify_totp import verify_totp
|
||||
|
||||
__all__ = [
|
||||
"users_db_path", "ensure_users_schema", "is_first_user",
|
||||
"create_user", "UserCreationError",
|
||||
"get_user_by_email", "get_user_by_id",
|
||||
"verify_password", "confirm_totp", "verify_totp", "set_project_slug",
|
||||
"password_strength", "MIN_SCORE_REQUIRED",
|
||||
"totp_provisioning_uri", "totp_qrcode_svg",
|
||||
"lockout_minutes_for", "seconds_locked_remaining", "lockout_message",
|
||||
"record_failed_attempt", "reset_failed_attempts",
|
||||
"generate_recovery_codes", "verify_recovery_code",
|
||||
"set_password", "create_password_reset_token", "get_user_id_for_valid_token",
|
||||
"consume_password_reset_token", "TOKEN_TTL_MINUTES",
|
||||
"send_password_reset_email", "EmailNotConfiguredError",
|
||||
"update_profile", "count_admins", "delete_user",
|
||||
"update_email", "EmailUpdateError",
|
||||
"ensure_user_assets_schema", "user_assets_dir", "create_user_asset",
|
||||
"list_user_assets", "get_user_asset", "delete_user_asset", "save_user_asset", "user_asset_kind",
|
||||
"validate_audio_duration", "MAX_AUDIO_SECONDS",
|
||||
"validate_video_duration", "MAX_VIDEO_SECONDS",
|
||||
"image_dimensions", "update_user_asset_scene_kind",
|
||||
"users_db_path",
|
||||
"ensure_users_schema",
|
||||
"is_first_user",
|
||||
"create_user",
|
||||
"UserCreationError",
|
||||
"get_user_by_email",
|
||||
"get_user_by_id",
|
||||
"verify_password",
|
||||
"confirm_totp",
|
||||
"verify_totp",
|
||||
"set_project_slug",
|
||||
"password_strength",
|
||||
"MIN_SCORE_REQUIRED",
|
||||
"totp_provisioning_uri",
|
||||
"totp_qrcode_svg",
|
||||
"lockout_minutes_for",
|
||||
"seconds_locked_remaining",
|
||||
"lockout_message",
|
||||
"record_failed_attempt",
|
||||
"reset_failed_attempts",
|
||||
"generate_recovery_codes",
|
||||
"verify_recovery_code",
|
||||
"set_password",
|
||||
"create_password_reset_token",
|
||||
"get_user_id_for_valid_token",
|
||||
"consume_password_reset_token",
|
||||
"TOKEN_TTL_MINUTES",
|
||||
"send_password_reset_email",
|
||||
"EmailNotConfiguredError",
|
||||
"update_profile",
|
||||
"count_admins",
|
||||
"delete_user",
|
||||
"update_email",
|
||||
"EmailUpdateError",
|
||||
"ensure_user_assets_schema",
|
||||
"user_assets_dir",
|
||||
"create_user_asset",
|
||||
"list_user_assets",
|
||||
"get_user_asset",
|
||||
"delete_user_asset",
|
||||
"save_user_asset",
|
||||
"user_asset_kind",
|
||||
"validate_audio_duration",
|
||||
"MAX_AUDIO_SECONDS",
|
||||
"validate_video_duration",
|
||||
"MAX_VIDEO_SECONDS",
|
||||
"image_dimensions",
|
||||
"update_user_asset_scene_kind",
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user