Major changes across backend, frontend, infrastructure: - Provider system with model selection (Google, DeepL, OpenAI, Ollama, Google Cloud) - Admin panel: user management, pricing, settings - Glossary system with CSV import/export - Subscription and tier quota management - Security hardening (rate limiting, API key auth, path traversal fixes) - Docker compose for dev, prod, and IONOS deployment - Alembic migrations for new tables - Frontend: dashboard, pricing page, landing page, i18n (en/fr) - Test suite and verification scripts Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
6.3 KiB
6.3 KiB
Story 2.14: Stockage Temporaire & Métadonnées
Status: done
Story
As a system, I want to store uploaded files temporarily with metadata logging, so that files can be processed and tracked efficiently while maintaining security and performance.
Acceptance Criteria
- Unique Storage: Every uploaded file is saved to a temporary location (configured via
config.UPLOAD_DIR) with a unique ID as the filename (FR51). - Metadata Logging: For every upload, the system logs the following metadata:
original_filenamefile_sizefile_hash(SHA256)timestampuser_id(if available)
- No Content Logging: Ensure that NO actual file content or sensitive internal document data is logged (NFR11, NFR16).
- Redis Tracking: The file path and basic metadata are stored in Redis with a TTL of 60 minutes (Story 2.14).
- Job Association: The metadata is correctly associated with the
job_idgenerated during the translation request. - Performance: Metadata extraction (hashing) must not significantly delay the initial response (NFR1-NFR5).
Tasks / Subtasks
- Task 1: Implement Metadata Extraction Utility
- 1.1 Add
calculate_sha256method toutils/file_handler.py. - 1.2 Update
FileHandler.get_file_infoor create a new method to include the hash and structured metadata.
- 1.1 Add
- Task 2: Integrate Redis for Temporary Tracking
- 2.1 Verify
TierQuotaService's Redis client usage for reuse. - 2.2 Implement a
StorageTrackerservice (or extendProgressTracker) to store file paths in Redis with TTL. - 2.3 Key pattern:
translation:file:{job_id}with 60 min TTL.
- 2.1 Verify
- Task 3: Update Translation Endpoint
- 3.1 In
routes/translate_routes.py, trigger metadata logging after successful file save. - 3.2 Ensure
user_idandtimestampare captured. - 3.3 Ensure the
input_pathis correctly pushed to Redis tracking.
- 3.1 In
- Task 4: Audit Trail & Logging
- 4.1 Use
structlog(or standard logging ifstructlognot yet integrated) to log the metadata in a structured JSON format. - 4.2 Validate that NO content is logged.
- 4.1 Use
- Task 5: Verification & Tests
- 5.1 Add unit tests for SHA256 calculation.
- 5.2 Add integration tests verifying Redis entry creation and TTL.
- 5.3 Verify log output format.
Dev Notes
Previous Story Intelligence (2.13)
2-13implemented robust file validation.- The
translate_document_v1endpoint already generates ajob_idand saves the file usingfile_handler_util.generate_unique_filename. 2.13also introducedCORRUPTED_FILEandINVALID_FORMATerror codes.
Architecture Compliance
- Storage: Use
config.UPLOAD_DIRandconfig.OUTPUT_DIR. - TTL:
config.FILE_TTL_MINUTES(60 min). - Security: SHA256 for integrity and collision avoidance in logs.
- Zero Retention: TTL in Redis is the first step toward the automated cleanup job (
2-15).
Project Structure Notes
utils/file_handler.py: Central place for file operations.routes/translate_routes.py: Orchestrates the upload flow.middleware/tier_quota.py: Good example of Redis client usage (_get_async_redis).
References
- [Source: _bmad-output/planning-artifacts/epics.md#Story 2.14]
- [Source: _bmad-output/planning-artifacts/prd.md#NFR11, NFR16]
- [Source: config.py#CLEANUP_ENABLED, FILE_TTL_MINUTES]
Dev Agent Record
Agent Model Used
Gemini CLI (Expert Agent)
Debug Log References
- SHA256 unit tests passed.
- StorageTracker unit tests (including Redis mocking and logging verification) passed.
- Translation endpoint integration tests passed.
Completion Notes List
- ✅ Implemented
calculate_sha256inFileHandler. - ✅ Updated
get_file_infoto include SHA256 hash. - ✅ Created
StorageTrackerservice usingredis.asyncio. - ✅ Integrated
StorageTrackerintotranslate_document_v1endpoint. - ✅ Added
structlog-compatible logging for file uploads (metadata only). - ✅ Added comprehensive unit and integration tests.
File List
utils/file_handler.pyservices/storage_tracker.pyroutes/translate_routes.pytests/test_file_handler.pytests/test_storage_tracker.pytests/test_translation_metadata_integration.py
Senior Developer Review (AI)
Reviewer: Claude (Opencode) Date: 2026-02-21 Outcome: ✅ APPROVED (with fixes applied)
Issues Found & Fixed
| # | Severity | Issue | Fix Applied |
|---|---|---|---|
| 1 | HIGH | calculate_sha256 sans gestion d'erreur |
Added try/except, returns None on failure |
| 2 | HIGH | Pas de cleanup si hash échoue | Added cleanup_file() call on hash failure in translate_routes.py |
| 3 | MEDIUM | Fichier orphelin si hash échoue | Fixed with cleanup on error |
| 4 | MEDIUM | file_hash pouvait être None sans validation |
Added validation + raise CORRUPTED_FILE error |
| 5 | MEDIUM | Échec Redis silencieux | Added _log_error("redis_not_available", ...) and _log_info("file_tracked_in_redis", ...) |
| 6 | MEDIUM | TTL hardcodée | Changed to _get_default_ttl() using config.FILE_TTL_MINUTES |
| 7 | LOW | print() au lieu de logger |
Changed to logging.getLogger(__name__) |
| 8 | LOW | Test mockait le hash | Added real SHA256 calculation test + hash failure test |
Files Modified in Review
utils/file_handler.py- Error handling incalculate_sha256, logging incleanup_fileservices/storage_tracker.py- Config-based TTL, improved loggingroutes/translate_routes.py- Hash validation + cleanup on failuretests/test_file_handler.py- Added edge case teststests/test_translation_metadata_integration.py- Added hash failure test
AC Validation
| AC | Status | Evidence |
|---|---|---|
| AC1: Unique Storage | ✅ | file_handler_util.generate_unique_filename() used |
| AC2: Metadata Logging | ✅ | _log_info("file_uploaded", ...) with all fields |
| AC3: No Content Logging | ✅ | Only metadata logged, no file content |
| AC4: Redis Tracking | ✅ | storage_tracker.track_file() with TTL |
| AC5: Job Association | ✅ | job_id passed to track_file() |
| AC6: Performance | ⚠️ | Hash is synchronous (noted for future async improvement) |
Change Log
- 2026-02-21: Code review completed, 8 issues found and fixed. Status → done.