Mandats : origin→FK identité + nomination auto + boutons + tests intégration

- origin TEXT → origin_id UUID FK duniter_identities (migration e3f4a5b6c7d8)
- GET /auth/identities?q= : recherche d'identités par nom/adresse
- MandateCreate.nomination_mode : auto (auto-assign auteur), collective, postpone
- Wizard new.vue : champ origine = picker identité, checkbox "Démarrer maintenant"
- [id].vue : modal "Assigner" = search-picker (résout UUID vs adresse SS58), affiche
  origin_display_name + mandatee_display_name, inputs natifs (<input>/<textarea>)
- Erreurs API visibles dans l'UI (plus de catch silencieux)
- test_mandate_flows.py : 17 tests intégration SQLite réels (origin, nomination,
  assign, lifecycle, revocation, interactions croisées) — 241 tests total OK

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Yvv
2026-04-25 20:48:27 +02:00
parent 3423ac2e7e
commit f56d84e76b
9 changed files with 883 additions and 427 deletions
+23 -1
View File
@@ -5,7 +5,8 @@ from __future__ import annotations
import secrets
from datetime import datetime, timedelta, timezone
from fastapi import APIRouter, Depends, HTTPException, Response, status
from fastapi import APIRouter, Depends, HTTPException, Query, Response, status
from sqlalchemy import or_, select
from sqlalchemy.ext.asyncio import AsyncSession
from app.config import settings
@@ -232,3 +233,24 @@ async def logout(
for session in sessions:
await db.delete(session)
await db.commit()
@router.get("/identities", response_model=list[IdentityOut])
async def search_identities(
q: str = Query(..., min_length=1, description="Recherche par adresse ou nom"),
limit: int = Query(default=10, ge=1, le=50),
db: AsyncSession = Depends(get_db),
) -> list[IdentityOut]:
"""Search Duniter identities by address prefix or display_name."""
result = await db.execute(
select(DuniterIdentity)
.where(
or_(
DuniterIdentity.address.ilike(f"{q}%"),
DuniterIdentity.display_name.ilike(f"%{q}%"),
)
)
.order_by(DuniterIdentity.display_name)
.limit(limit)
)
return [IdentityOut.model_validate(i) for i in result.scalars().all()]