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

@@ -1,4 +1,5 @@
<script setup lang="ts">
import { Building2, Plus, Settings, Trash2, User } from 'lucide-vue-next';
import { computed } from 'vue';
import InputError from '@/components/InputError.vue';
import { Button } from '@/components/ui/button';
@@ -19,7 +20,6 @@ import {
SelectValue,
} from '@/components/ui/select';
import { Spinner } from '@/components/ui/spinner';
import { Building2, Plus, Settings, Trash2, User } from 'lucide-vue-next';
export type ClientContactData = {
id?: number;
@@ -180,9 +180,7 @@ const inputClass =
<InputError :message="form.errors.ice" />
</div>
<div class="space-y-2">
<Label for="fiscal_id"
>IF (Identifiant Fiscal)</Label
>
<Label for="fiscal_id">IF (Identifiant Fiscal)</Label>
<Input
id="fiscal_id"
v-model="form.fiscal_id"
@@ -241,7 +239,7 @@ const inputClass =
Responsables
</CardTitle>
<CardDescription>
Personnes à contacter pour les échanges et dossiers
Personnes à contacter pour les échanges et déclarations
</CardDescription>
</CardHeader>
<CardContent class="space-y-4">
@@ -288,16 +286,12 @@ const inputClass =
placeholder="Prénom Nom"
:class="inputClass"
:aria-invalid="
!!form.errors[
`contacts.${index}.full_name`
]
!!form.errors[`contacts.${index}.full_name`]
"
/>
<InputError
:message="
form.errors[
`contacts.${index}.full_name`
]
form.errors[`contacts.${index}.full_name`]
"
/>
</div>
@@ -314,9 +308,7 @@ const inputClass =
/>
</div>
<div class="space-y-2">
<Label :for="`contact_email_${index}`"
>Email</Label
>
<Label :for="`contact_email_${index}`">Email</Label>
<Input
:id="`contact_email_${index}`"
v-model="contact.email"