Multi-tenancy : espaces de travail + fix auth reload (rate limiter OPTIONS)

- Modèles Organization + OrgMember, migration Alembic (SQLite compatible)
- organization_id nullable sur Document, Decision, Mandate, VotingProtocol
- Service, schéma, router /organizations + dependency get_active_org_id
- Seed : Duniter G1 + Axiom Team ; tout le contenu seed attaché à Duniter G1
- Backend : list/create filtrés par header X-Organization
- Frontend : store organizations, WorkspaceSelector réel, useApi injecte l'org
- Fix critique : rate_limiter exclut les requêtes OPTIONS (CORS preflight)
  → résout le bug "Failed to fetch /auth/me" au reload (429 sur preflight)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Yvv
2026-04-23 15:17:14 +02:00
parent 224e5b0f5e
commit 79e468b40f
31 changed files with 1296 additions and 159 deletions

View File

@@ -1,24 +1,20 @@
<script setup lang="ts">
const auth = useAuthStore()
const orgsStore = useOrganizationsStore()
const route = useRoute()
const { initMood } = useMood()
const navigationItems = [
{
label: 'Boîte à outils',
icon: 'i-lucide-wrench',
to: '/tools',
label: 'Décisions',
icon: 'i-lucide-scale',
to: '/decisions',
},
{
label: 'Documents',
icon: 'i-lucide-book-open',
to: '/documents',
},
{
label: 'Decisions',
icon: 'i-lucide-scale',
to: '/decisions',
},
{
label: 'Mandats',
icon: 'i-lucide-user-check',
@@ -29,6 +25,11 @@ const navigationItems = [
icon: 'i-lucide-settings',
to: '/protocols',
},
{
label: 'Outils',
icon: 'i-lucide-wrench',
to: '/tools',
},
{
label: 'Sanctuaire',
icon: 'i-lucide-archive',
@@ -63,12 +64,18 @@ onMounted(async () => {
if (auth.token) {
try {
await auth.fetchMe()
} catch {
auth.logout()
} catch (err: any) {
// Déconnexion seulement sur session réellement invalide (401/403)
// Erreur réseau ou backend temporairement indisponible → conserver la session
if (err?.status === 401 || err?.status === 403) {
auth.logout()
}
}
}
ws.connect()
setupWsNotifications(ws)
// Load organizations in parallel — non-blocking, no auth required
orgsStore.fetchOrganizations()
})
onUnmounted(() => {