feat: complete Epic 0 — foundation migration & infrastructure setup

Stories 0.2-0.5: rename folders→declarations (backend+frontend), configure
Redis for cache/queue/sessions, add foundation database migrations
(permissions, archived_at), replace DeclarationStatus enum with architecture
lifecycle values, create DeclarationObserver for status transition validation
and auto-archive, fix controller status transitions to respect observer rules.

93 tests pass (240 assertions).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-12 18:25:32 +00:00
parent d380df4074
commit fd43a6f429
105 changed files with 3899 additions and 1558 deletions

View File

@@ -14,17 +14,17 @@ Route::middleware(['auth', 'verified'])->group(function () {
Route::middleware('workspace')->group(function () {
Route::resource('clients', \App\Http\Controllers\ClientController::class);
Route::resource('folders', \App\Http\Controllers\FolderController::class);
Route::post('folders/{folder}/messages', [\App\Http\Controllers\FolderMessageController::class, 'store'])
->name('folders.messages.store');
Route::post('folders/{folder}/media', [\App\Http\Controllers\FolderMediaController::class, 'store'])
->name('folders.media.store');
Route::get('folders/{folder}/media/{mediaId}', [\App\Http\Controllers\FolderMediaController::class, 'download'])
->name('folders.media.download')
Route::resource('declarations', \App\Http\Controllers\DeclarationController::class);
Route::post('declarations/{declaration}/messages', [\App\Http\Controllers\DeclarationMessageController::class, 'store'])
->name('declarations.messages.store');
Route::post('declarations/{declaration}/media', [\App\Http\Controllers\DeclarationMediaController::class, 'store'])
->name('declarations.media.store');
Route::get('declarations/{declaration}/media/{mediaId}', [\App\Http\Controllers\DeclarationMediaController::class, 'download'])
->name('declarations.media.download')
->whereNumber('mediaId');
Route::post('folders/{folder}/mentions', [\App\Http\Controllers\FolderMentionController::class, 'store'])
Route::post('declarations/{declaration}/mentions', [\App\Http\Controllers\DeclarationMentionController::class, 'store'])
->middleware('throttle:10,1')
->name('folders.mentions.store');
->name('declarations.mentions.store');
});
Route::post('notifications/{id}/read', [\App\Http\Controllers\NotificationController::class, 'markAsRead'])->name('notifications.read');
@@ -36,7 +36,7 @@ Route::middleware(['auth', 'verified'])->group(function () {
});
});
Route::prefix('c')->name('client.')->middleware('folder.invitation')->group(function () {
Route::prefix('c')->name('client.')->middleware('client-portal')->group(function () {
Route::get('upload/{token}', [\App\Http\Controllers\Client\UploadController::class, 'show'])
->name('upload');
Route::post('upload/{token}', [\App\Http\Controllers\Client\UploadController::class, 'store'])