"""Feishu approval-flow mapping gate for data-access requests. DAX-003 only resolves the externally-authored Feishu approval template mapped to the canonical ``data_access_group_grant`` flow key. It does not fetch or author Feishu template widgets, create approval instances, or create durable data-access request state. """ from __future__ import annotations from dataclasses import dataclass from typing import Any from sqlalchemy.ext.asyncio import AsyncSession from app.core.exceptions import AppException from app.domains.data_access.constants import ( APPROVAL_FLOW_DATA_ACCESS_GROUP_GRANT, APPROVAL_FLOW_DATA_ACCESS_PERSONAL_GRANT, APPROVAL_FLOW_DATA_ACCESS_SERVICE_ACCOUNT_GRANT, ) from app.integrations.service import get_approval_flow @dataclass(frozen=True, slots=True) class DataAccessApprovalFlow: """Resolved Feishu flow mapping used by future data-access submissions.""" flow_key: str external_code: str payload_schema: dict[str, Any] | None async def resolve_data_access_group_grant_flow( *, session: AsyncSession, ) -> DataAccessApprovalFlow: """Return the active Feishu mapping for DAX group grants. Missing or inactive mappings fail closed through ``get_approval_flow``. Direct Feishu-originated instances are also rejected here: DAX requests must originate in Helix after semantic resource/principal validation, otherwise the Feishu template becomes a second policy authority. """ row = await get_approval_flow( APPROVAL_FLOW_DATA_ACCESS_GROUP_GRANT, session=session, ) if row.accept_external_origin: raise AppException( code="DATA_ACCESS_APPROVAL_FLOW_EXTERNAL_ORIGIN_FORBIDDEN", message=( "data_access_group_grant must be Helix-originated. Disable " "accept_external_origin on the approval-flow mapping before " "submitting data-access requests." ), status_code=503, ) return DataAccessApprovalFlow( flow_key=row.flow_key, external_code=row.external_code, payload_schema=( dict(row.payload_schema) if isinstance(row.payload_schema, dict) else None ), ) async def resolve_data_access_service_account_grant_flow( *, session: AsyncSession, ) -> DataAccessApprovalFlow: """Resolve the separately governed Service Account grant template.""" flow = await get_approval_flow( APPROVAL_FLOW_DATA_ACCESS_SERVICE_ACCOUNT_GRANT, session=session, ) if flow.accept_external_origin: raise AppException( code="DATA_ACCESS_APPROVAL_FLOW_EXTERNAL_ORIGIN_FORBIDDEN", message="Data-access approval flow may not accept external origin.", status_code=503, ) return DataAccessApprovalFlow( flow_key=flow.flow_key, external_code=flow.external_code, payload_schema=dict(flow.payload_schema or {}), ) async def resolve_data_access_personal_grant_flow( *, session: AsyncSession, ) -> DataAccessApprovalFlow: """Resolve the separately governed direct-employee grant template.""" flow = await get_approval_flow( APPROVAL_FLOW_DATA_ACCESS_PERSONAL_GRANT, session=session, ) if flow.accept_external_origin: raise AppException( code="DATA_ACCESS_APPROVAL_FLOW_EXTERNAL_ORIGIN_FORBIDDEN", message="Data-access approval flow may not accept external origin.", status_code=503, ) return DataAccessApprovalFlow( flow_key=flow.flow_key, external_code=flow.external_code, payload_schema=dict(flow.payload_schema or {}), )