Skip to content

routes

routes

Authenticated REST API for the native Succès module.

Classes

Functions:

planner_pastilles

planner_pastilles(start: str, end: str) -> dict[str, Any]

Les points du petit calendrier, exacts et en lecture seule.

Route synchrone (def) : elle ne fait que du SQLite — Starlette l'exécute dans un fil, la boucle d'événements reste libre.

Source code in src/diapason/succes/routes.py
@router.get("/planner/pastilles")
def planner_pastilles(start: str, end: str) -> dict[str, Any]:
    """Les points du petit calendrier, exacts et en lecture seule.

    Route synchrone (`def`) : elle ne fait que du SQLite — Starlette
    l'exécute dans un fil, la boucle d'événements reste libre.
    """
    store = get_store()
    if not isinstance(store, SuccesContinuityStore):
        raise HTTPException(
            status_code=503, detail="Le module Succès complet n'est pas initialisé."
        )
    return store.pastilles_planner(
        _resolved_date(start, allow_empty=False),
        _resolved_date(end, allow_empty=False),
    )

reorder_projects

reorder_projects(body: OrdreParIds) -> dict[str, Any]

Fixe l'ordre manuel des projets (leur rang dans ids).

Source code in src/diapason/succes/routes.py
@router.put("/projects/ordre")
def reorder_projects(body: OrdreParIds) -> dict[str, Any]:
    """Fixe l'ordre manuel des projets (leur rang dans `ids`)."""
    changed = _workspace_store().reorder_projects(body.ids)
    return {"reordered": len(changed)}

list_project_structures

list_project_structures() -> dict[str, Any]

Les cinq formes qu'un projet peut prendre, pour le sélecteur.

Source code in src/diapason/succes/routes.py
@router.get("/project-structures")
def list_project_structures() -> dict[str, Any]:
    """Les cinq formes qu'un projet peut prendre, pour le sélecteur."""
    from diapason.succes.structures import STRUCTURE_CATALOG

    return {"structures": list(STRUCTURE_CATALOG)}

list_note_categories

list_note_categories() -> dict[str, Any]

Les catégories vivantes, dans l'ordre choisi. Route synchrone : SQLite.

Source code in src/diapason/succes/routes.py
@router.get("/notes/categories")
def list_note_categories() -> dict[str, Any]:
    """Les catégories vivantes, dans l'ordre choisi. Route synchrone : SQLite."""
    return {"categories": _workspace_store().list_note_categories()}

reorder_notes

reorder_notes(body: OrdreParIds) -> dict[str, Any]

Fixe l'ordre manuel des notes citées (leur rang dans ids).

Source code in src/diapason/succes/routes.py
@router.put("/notes/ordre")
def reorder_notes(body: OrdreParIds) -> dict[str, Any]:
    """Fixe l'ordre manuel des notes citées (leur rang dans `ids`)."""
    changed = _workspace_store().reorder_notes(body.ids)
    return {"reordered": len(changed)}

create_sync_pairing

create_sync_pairing(body: PairingCreate) -> dict[str, Any]

Prepare a ten-minute invitation from the authenticated local app.

Source code in src/diapason/succes/routes.py
@router.post("/sync/pairings")
def create_sync_pairing(body: PairingCreate) -> dict[str, Any]:
    """Prepare a ten-minute invitation from the authenticated local app."""
    try:
        return _sync_store().create_pairing(body.deviceName)
    except SuccesError as exc:
        raise _domain_error(exc) from exc

redeem_sync_pairing

redeem_sync_pairing(body: PairingRedeem) -> dict[str, Any]

Redeem a pairing token (auth = valid invitation; no API key required).

Source code in src/diapason/succes/routes.py
@router.post("/sync/pair")
def redeem_sync_pairing(body: PairingRedeem) -> dict[str, Any]:
    """Redeem a pairing token (auth = valid invitation; no API key required)."""
    try:
        return _sync_store().redeem_pairing(body.pairingToken)
    except SuccesError as exc:
        raise HTTPException(status_code=401, detail=str(exc)) from exc

exchange_sync_operations

exchange_sync_operations(
    body: SyncExchangeBody,
) -> dict[str, Any]

Exchange operations authenticated by the peer sync token in the body.

Source code in src/diapason/succes/routes.py
@router.post("/sync/exchange")
def exchange_sync_operations(body: SyncExchangeBody) -> dict[str, Any]:
    """Exchange operations authenticated by the peer sync token in the body."""
    peer = _sync_store().peer_for_token(body.peerToken)
    if peer is None:
        raise HTTPException(
            status_code=401, detail="Cet appareil n'est pas autorisé à synchroniser."
        )
    try:
        return _sync_store().exchange(
            str(peer["id"]), after=body.cursor, operations=body.operations
        )
    except SuccesError as exc:
        raise _domain_error(exc) from exc

join_sync_remote

join_sync_remote(body: SyncJoinBody) -> dict[str, Any]

Redeem a remote invitation and store guest credentials locally.

Source code in src/diapason/succes/routes.py
@router.post("/sync/join")
def join_sync_remote(body: SyncJoinBody) -> dict[str, Any]:
    """Redeem a remote invitation and store guest credentials locally."""
    try:
        return _sync_store().join_remote(
            body.pairingToken,
            relay_url=body.relayUrl,
            device_name=body.deviceName,
        )
    except SuccesError as exc:
        raise HTTPException(status_code=400, detail=str(exc)) from exc

run_sync_exchange

run_sync_exchange() -> dict[str, Any]

Guest round-trip: push local ops, pull host ops through the relay.

Source code in src/diapason/succes/routes.py
@router.post("/sync/run")
def run_sync_exchange() -> dict[str, Any]:
    """Guest round-trip: push local ops, pull host ops through the relay."""
    try:
        return _sync_store().run_exchange()
    except SuccesError as exc:
        raise HTTPException(status_code=400, detail=str(exc)) from exc