Add Fleet control plane and split manage.sh deploy menu.

Strategy nodes gain fleet token APIs; control/ app for local ops; manage.sh offers strategy vs control one-click deploy.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-07-30 10:46:40 +08:00
parent 200702d066
commit da5eb4c18c
44 changed files with 4623 additions and 15 deletions
+22
View File
@@ -11,9 +11,14 @@ from pydantic import BaseModel, Field
from ..config import Settings, get_settings
from ..credentials import get_credentials, update_credentials, upsert_env_file
from .auth import LoginRequest, LoginResponse, issue_token, require_user
from .fleet import consume_login_ticket
router = APIRouter(prefix="/api/auth", tags=["auth"])
class FleetExchangeRequest(BaseModel):
ticket: str = Field(min_length=8, max_length=256)
_login_hits: dict[str, list[float]] = defaultdict(list)
@@ -45,6 +50,23 @@ def _rate_limit_login(ip: str, settings: Settings) -> None:
)
@router.post("/fleet-exchange", response_model=LoginResponse)
async def fleet_exchange(
body: FleetExchangeRequest,
settings: Annotated[Settings, Depends(get_settings)],
) -> LoginResponse:
"""中控签发的一次性 ticket 兑换为普通登录会话(免密)。"""
username = consume_login_ticket(body.ticket)
token, ttl = issue_token(username, settings)
return LoginResponse(
token=token,
username=username,
expires_in=ttl,
env_name=settings.env_name,
mode=settings.mode,
)
@router.post("/login", response_model=LoginResponse)
async def login(
body: LoginRequest,