fix(awooop): authenticate approval decisions
All checks were successful
Code Review / ai-code-review (push) Successful in 11s
CD Pipeline / tests (push) Successful in 1m3s
CD Pipeline / build-and-deploy (push) Successful in 3m28s
CD Pipeline / post-deploy-checks (push) Successful in 1m25s

This commit is contained in:
OG T
2026-05-06 13:05:51 +08:00
parent e6eae5cdc4
commit c696b99ccf
9 changed files with 294 additions and 6 deletions

View File

@@ -15,9 +15,13 @@ from decimal import Decimal
from typing import Any, Literal
from uuid import UUID
from fastapi import APIRouter, Query
from fastapi import APIRouter, Depends, Query
from pydantic import BaseModel, Field
from src.core.awooop_operator_auth import (
AwoooPOperatorPrincipal,
verify_awooop_operator,
)
from src.services.platform_operator_service import (
decide_approval as decide_approval_svc,
list_approvals as list_approvals_svc,
@@ -65,7 +69,10 @@ class ListApprovalsResponse(BaseModel):
class DecideApprovalRequest(BaseModel):
project_id: str = Field(..., description="租戶 ID")
decision: Literal["approve", "reject"] = Field(..., description="核准或拒絕")
approver_id: str = Field(..., description="審核人 IDplatform_subject_id 或 operator email")
approver_id: str | None = Field(
default=None,
description="Deprecated. Ignored; approver comes from trusted operator headers.",
)
reason: str | None = Field(None, description="決策原因(可選)")
@@ -127,11 +134,12 @@ async def list_approvals(
async def decide_approval(
run_id: str,
body: DecideApprovalRequest,
operator: AwoooPOperatorPrincipal = Depends(verify_awooop_operator),
) -> dict[str, Any]:
return await decide_approval_svc(
run_id=run_id,
project_id=body.project_id,
decision=body.decision,
approver_id=body.approver_id,
approver_id=operator.operator_id,
reason=body.reason,
)