Skip to content

feat(admin): Post editorial 후보 테이블 및 generate 파이프라인 트리거 #7

@cocoyoon

Description

@cocoyoon

목표

에디토리얼(post magazine) 생성 조건을 만족하는 포스트를 Admin에서 테이블로 조회하고, 행별 **「에디토리얼 생성」**으로 generate → gRPC 파이프라인을 실행한다. UI에서는 **post_magazines.status**로 진행 상태를 보여 준다 (post_magazine_id 존재만으로는 generating / failed / published 구분 불가).

배경

  • DB 테이블명은 **post_magazines**이며 파이프라인 상태는 status 컬럼. 별도 post_editorial 테이블 없음.
  • generate_post_magazine는 gRPC 결과와 무관하게 먼저 posts.post_magazine_id를 설정하므로, Admin 표시는 post_magazines.status(조인) 기준이 맞음.

비즈니스 규칙

  • 스팟 4개 이상, 각 스팟 솔루션 1개 이상 — 목록 필터와 generate 검증에서 동일하게 적용.
  • 목록: 스팟/솔루션 자격을 만족하는 포스트 전체, posts LEFT JOIN post_magazinespost_magazine_id, post_magazine_status 반환.
  • 생성 버튼: 현재 API가 post_magazine_id 있으면 거부하므로 기본은 없을 때만 활성. failed 재시도는 정책/스키마 필요 → 이번 범위 밖.

구현 체크리스트

api-server (Rust)

  • post_magazines/service.rsgenerate_post_magazine: 스팟 < 4 또는 스팟 중 솔루션 0개 시 400, 테스트 추가.
  • GET /api/v1/admin/posts/editorial-candidatesadmin/posts.rs에 추가, 라우트 editorial-candidates/{id}/status보다 먼저 등록.
  • 응답: PostListItem + post_magazine_id, post_magazine_status전용 DTO 권장. 쿼리는 SeaORM 또는 raw SQL 서브쿼리 + 기존 list 빌더.

Next.js (web)

  • GET /api/v1/admin/posts/editorial-candidatescheckIsAdmin, Rust로 Bearer 전달.
  • POST /api/v1/admin/post-editorial/generate{ post_id } → Rust POST .../post-magazines/generate.
  • GET /api/v1/post-magazines/[id] — 클라이언트 폴링용 (현재 상대 경로 프록시 없음).

Admin UI

  • /admin/post-editorial — 테이블: 썸네일, 제목/아티스트, spot_count, 생성일, 에디토리얼 상태, post_magazine_id, 생성 버튼.
  • 생성 후 목록 refetch 또는 매거진 GET 폴링.
  • AdminSidebar 네비 항목.

선택

  • docs/agent/api-v1-routes.md 동기화.

범위 밖 / 후속

  • gRPC 실패 후에도 post_magazine_id 유지 → 재시도posts/post_magazines 정리 규칙 + API 변경 필요.
  • Rust post-magazines/generate 인증 약함 → Next admin 게이트 우선, 네트워크 격리 또는 Rust 측 하드닝 권장.

참고 코드

  • packages/api-server/src/domains/post_magazines/service.rs
  • packages/api-server/src/domains/admin/posts.rs
  • packages/ai-server/docs/post-editorial.md

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions