dmslanes/lanes

Lanes - team task boards with roles, history and an MCP endpoint for Claude and ChatGPT

A remix template · 0 remixes · Remix dmslanes/lanes

app/application/ports.py

"""What the use cases need from the outside world. Infrastructure implements it."""
from __future__ import annotations

from typing import Protocol

from app.domain.model import Activity, Board, BoardList, Card, Membership, Workspace


class Repository(Protocol):
    # workspaces and people
    def add_workspace(self, ws: Workspace) -> None: ...
    def get_workspace(self, workspace_id: str) -> Workspace | None: ...
    def get_membership(self, workspace_id: str, email: str) -> Membership | None: ...
    def memberships_of_workspace(self, workspace_id: str) -> list[Membership]: ...
    def memberships_of_person(self, email: str) -> list[Membership]: ...
    def save_membership(self, m: Membership) -> None: ...
    def delete_membership(self, workspace_id: str, email: str) -> None: ...

    # boards and lists
    def add_board(self, board: Board) -> None: ...
    def get_board(self, board_id: str) -> Board | None: ...
    def boards_of_workspaces(self, workspace_ids: list[str]) -> list[Board]: ...
    def add_list(self, lst: BoardList) -> None: ...
    def get_list(self, list_id: str) -> BoardList | None: ...
    def lists_of_board(self, board_id: str) -> list[BoardList]: ...

    # cards
    def claim_card_number(self) -> int:
        """Next card number, unique across the app (a plain INSERT claim)."""
        ...

    def add_card(self, card: Card) -> None: ...
    def save_card(self, card: Card, expected_version: int) -> None:
        """Write `card` only if the stored version is still `expected_version`, else Conflict."""
        ...

    def delete_card(self, card_id: str) -> None: ...
    def get_card(self, card_id: str) -> Card | None: ...
    def get_card_by_number(self, number: int) -> Card | None: ...
    def cards_of_board(self, board_id: str) -> list[Card]: ...
    def cards_of_workspaces(self, workspace_ids: list[str]) -> list[Card]: ...

    # history
    def add_activity(self, a: Activity) -> None: ...
    def activity_of_card(self, card_id: str) -> list[Activity]: ...
    def activity_of_board(self, board_id: str, limit: int) -> list[Activity]: ...


class Assistant(Protocol):
    """The AI the use cases lean on (Dodil Models when deployed, a fake in the tests)."""

    def complete(self, system: str, prompt: str) -> str: ...
    def embed(self, texts: list[str]) -> list[list[float]]: ...