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

@@ -15,16 +15,16 @@ class RefuseController extends Controller
*/
public function show(Request $request, string $token): Response
{
$invitation = $request->attributes->get('folder_invitation');
$folder = $invitation->folder;
$invitation = $request->attributes->get('declaration_invitation');
$declaration = $invitation->declaration;
$folder->load(['client']);
$declaration->load(['client']);
return Inertia::render('client/Refuse', [
'folder' => [
'id' => $folder->id,
'title' => $folder->title,
'client_name' => $folder->client->company_name,
'declaration' => [
'id' => $declaration->id,
'title' => $declaration->title,
'client_name' => $declaration->client->company_name,
],
'token' => $token,
'submitUrl' => route('client.refuse.store', ['token' => $token]),
@@ -36,14 +36,14 @@ class RefuseController extends Controller
*/
public function store(Request $request, string $token): RedirectResponse
{
$invitation = $request->attributes->get('folder_invitation');
$folder = $invitation->folder;
$invitation = $request->attributes->get('declaration_invitation');
$declaration = $invitation->declaration;
$request->validate([
'reason' => ['nullable', 'string', 'max:65535'],
]);
$folder->update([
$declaration->update([
'refused_at' => now(),
'refusal_reason' => $request->input('reason'),
]);