From 631e4cd8ef5e6f1977f444091de18196a673425a Mon Sep 17 00:00:00 2001 From: hyungi Date: Thu, 25 Jun 2026 08:20:32 +0000 Subject: [PATCH] =?UTF-8?q?feat(publish):=20P1-1=20digest=20=EB=B0=9C?= =?UTF-8?q?=ED=96=89=20read=20API=20scaffold(503)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 기존 /published 라우터에 GET /published/digest 추가 — _verify_token(Bearer) + FeedResponse 엔벨로프 재사용(신규 라우터 X). DIGEST_PUBLISH_ENABLED 플래그 (기본 false=inert): off=503 "not enabled", on+projection 미구현=503. 실데이터·시크릿 0. 검증: 무토큰 401·잘못된 토큰 403·유효+off 503·기존 /feed 200 무회귀. docsrv-viewer-publish 트랙 (plan viewer-daily-report P1-1). Co-Authored-By: Claude Opus 4.8 (1M context) --- app/api/published.py | 22 ++++++++++++++++++++++ app/core/config.py | 3 +++ docker-compose.yml | 1 + 3 files changed, 26 insertions(+) diff --git a/app/api/published.py b/app/api/published.py index 2789b34..33984be 100644 --- a/app/api/published.py +++ b/app/api/published.py @@ -111,3 +111,25 @@ async def published_feed( next_since=next_since, has_more=has_more, ) + + +# ── P1-1: 뉴스/다이제스트 발행 read API (scaffold, docsrv-viewer-publish) ────────── +# 첫 실사용 = 추상화 적합성 시험(plan r2). 다이제스트는 문서용 불변식 일부 제외(content-type +# 파라미터화): rev=단순 version 커서(증분 pull) · pub_id=date-as-id(admin-gated feed 라 opacity +# 불필요) · tombstone 없음(다이제스트 미삭제). 엔벨로프는 /feed 와 동일(FeedResponse) → 뷰어 +# pull-sync 클라이언트 재사용. scaffold-first: DIGEST_PUBLISH_ENABLED off(기본)=503(명시적 미가동, +# no-silent). 점등돼도 projection 미구현이면 503 — 실데이터·시크릿 0. +DIGEST_FEED_SCHEMA_VERSION = 1 + + +@router.get("/digest", response_model=FeedResponse) +async def published_digest( + since: int = Query(0, ge=0), + limit: int = Query(DEFAULT_LIMIT, ge=1, le=MAX_LIMIT), + _auth: None = Depends(_verify_token), +): + """뉴스/다이제스트 발행 feed (version 커서 since). scaffold — 점등/projection 전 503.""" + if not settings.digest_publish_enabled: + raise HTTPException(status_code=503, detail="digest publish not enabled (scaffold)") + # TODO(P1 후속): global_digests/digest_topics -> render-ready projection (version 커서). + raise HTTPException(status_code=503, detail="digest publish projection not implemented (scaffold)") diff --git a/app/core/config.py b/app/core/config.py index 42909c4..bdb1aad 100644 --- a/app/core/config.py +++ b/app/core/config.py @@ -187,6 +187,7 @@ class Settings(BaseModel): study_card_extract_enabled: bool = True # 발행 레이어(docsrv-viewer-publish): publish_outbox 워커 게이트. 저자/4-A enqueue 결선(P0-1b) 후 true. study_publish_enabled: bool = False + digest_publish_enabled: bool = False # docsrv-viewer-publish P1-1 (뉴스/다이제스트 발행 feed gate) # 뷰어 write-back ingest(study-to-viewer P2) 게이트. /ingest/study/attempts 활성. 기본 false=inert(503). study_ingest_enabled: bool = False @@ -204,6 +205,7 @@ def load_settings() -> Settings: study_explanation_enabled = os.getenv("STUDY_EXPLANATION_ENABLED", "true").lower() in ("1", "true", "yes") study_card_extract_enabled = os.getenv("STUDY_CARD_EXTRACT_ENABLED", "true").lower() in ("1", "true", "yes") study_publish_enabled = os.getenv("STUDY_PUBLISH_ENABLED", "false").lower() in ("1", "true", "yes") + digest_publish_enabled = os.getenv("DIGEST_PUBLISH_ENABLED", "false").lower() in ("1", "true", "yes") study_ingest_enabled = os.getenv("STUDY_INGEST_ENABLED", "false").lower() in ("1", "true", "yes") internal_worker_token = os.getenv("INTERNAL_WORKER_TOKEN", "") viewer_sync_token = os.getenv("VIEWER_SYNC_TOKEN", "") @@ -340,6 +342,7 @@ def load_settings() -> Settings: study_explanation_enabled=study_explanation_enabled, study_card_extract_enabled=study_card_extract_enabled, study_publish_enabled=study_publish_enabled, + digest_publish_enabled=digest_publish_enabled, study_ingest_enabled=study_ingest_enabled, internal_worker_token=internal_worker_token, viewer_sync_token=viewer_sync_token, diff --git a/docker-compose.yml b/docker-compose.yml index 46a7303..111d186 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -212,6 +212,7 @@ services: - INTERNAL_WORKER_TOKEN=${INTERNAL_WORKER_TOKEN} # docsrv-viewer-publish: 발행 워커/저작 enqueue 게이트(기본 false=inert) + 뷰어↔DS feed Bearer. - STUDY_PUBLISH_ENABLED=${STUDY_PUBLISH_ENABLED:-false} + - DIGEST_PUBLISH_ENABLED=${DIGEST_PUBLISH_ENABLED:-false} - VIEWER_SYNC_TOKEN=${VIEWER_SYNC_TOKEN:-} # study-to-viewer P2: 뷰어 write-back ingest 게이트(기본 false=inert, 검증 후 점등). - STUDY_INGEST_ENABLED=${STUDY_INGEST_ENABLED:-false}