From a8e19bdf153b439fe90df2a173100dbb129284ac Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Fri, 4 Sep 2026 21:09:29 +0000 Subject: [PATCH 1/5] =?UTF-8?q?=F0=9F=8E=A8=20Palette:=20=EA=B0=9C?= =?UTF-8?q?=EB=B0=9C=20=ED=99=98=EA=B2=BD=20Swagger=20UI=20=EC=9D=B8?= =?UTF-8?q?=EC=A6=9D=20=EC=A0=95=EB=B3=B4=20=EC=9C=A0=EC=A7=80=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .Jules/palette.md | 4 ++++ src/newsdom_api/main.py | 5 +++++ tests/test_health.py | 26 ++++++++++++++++++++++++++ 3 files changed, 35 insertions(+) diff --git a/.Jules/palette.md b/.Jules/palette.md index 6ac2f6ad..52f26867 100644 --- a/.Jules/palette.md +++ b/.Jules/palette.md @@ -29,3 +29,7 @@ ## 2026-07-07 - [Improve Swagger UX with Pydantic V2 Examples] **Learning:** Using json_schema_extra={'example': ...} instead of example=... in Pydantic V2 schemas ensures OpenAPI compatibility and prevents deprecation warnings, significantly improving Developer Experience (DX) for API consumers. **Action:** Apply json_schema_extra to Pydantic Field definitions to automatically generate rich, self-documenting OpenAPI schemas for headless APIs. + +## 2026-09-04 - [Developer Experience: Persist Authorization in Swagger] +**Learning:** For backend-only services without a frontend UI, Developer Experience (DX) is the primary user experience. Preserving authorization credentials across Swagger UI refreshes significantly improves DX and developer efficiency when interacting with the API in development environments. +**Action:** Always conditionally configure `swagger_ui_parameters` with `"persistAuthorization": True` when `runtime_profile` is "development" to enhance Developer Experience (DX) while maintaining security in production. diff --git a/src/newsdom_api/main.py b/src/newsdom_api/main.py index f61aafc2..81e2b0a7 100644 --- a/src/newsdom_api/main.py +++ b/src/newsdom_api/main.py @@ -321,6 +321,11 @@ def create_app( "displayRequestDuration": True, "syntaxHighlight.theme": "monokai", "tryItOutEnabled": True, + **( + {"persistAuthorization": True} + if application_settings.runtime_profile.value == "development" + else {} + ), }, ) application.state.runtime_settings = application_settings diff --git a/tests/test_health.py b/tests/test_health.py index 01a3b06f..8d31abca 100644 --- a/tests/test_health.py +++ b/tests/test_health.py @@ -57,3 +57,29 @@ def test_openapi_metadata_includes_contact_and_license(): "name": "MIT License", "identifier": "MIT", } + + +def test_openapi_swagger_ui_parameters_in_production(): + from newsdom_api.main import create_app + from newsdom_api.config import RuntimeSettings, RuntimeProfile + + app_prod = create_app( + RuntimeSettings(runtime_profile=RuntimeProfile.PRODUCTION, api_token="secret") + ) + params = app_prod.swagger_ui_parameters + assert params.get("persistAuthorization") is None + + +def test_openapi_swagger_ui_parameters_in_development(): + from newsdom_api.main import create_app + from newsdom_api.config import RuntimeSettings, RuntimeProfile, AuthenticationMode + + app_dev = create_app( + RuntimeSettings( + runtime_profile=RuntimeProfile.DEVELOPMENT, + authentication_mode=AuthenticationMode.DISABLED, + api_token=None, + ) + ) + params = app_dev.swagger_ui_parameters + assert params.get("persistAuthorization") is True From e6b68abaa9771bcc38bb3f3b1ddc1c3585810317 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 06:19:17 +0900 Subject: [PATCH 2/5] docs(ux): keep Swagger persistence decision local to feature --- .Jules/palette.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.Jules/palette.md b/.Jules/palette.md index 52f26867..6ac2f6ad 100644 --- a/.Jules/palette.md +++ b/.Jules/palette.md @@ -29,7 +29,3 @@ ## 2026-07-07 - [Improve Swagger UX with Pydantic V2 Examples] **Learning:** Using json_schema_extra={'example': ...} instead of example=... in Pydantic V2 schemas ensures OpenAPI compatibility and prevents deprecation warnings, significantly improving Developer Experience (DX) for API consumers. **Action:** Apply json_schema_extra to Pydantic Field definitions to automatically generate rich, self-documenting OpenAPI schemas for headless APIs. - -## 2026-09-04 - [Developer Experience: Persist Authorization in Swagger] -**Learning:** For backend-only services without a frontend UI, Developer Experience (DX) is the primary user experience. Preserving authorization credentials across Swagger UI refreshes significantly improves DX and developer efficiency when interacting with the API in development environments. -**Action:** Always conditionally configure `swagger_ui_parameters` with `"persistAuthorization": True` when `runtime_profile` is "development" to enhance Developer Experience (DX) while maintaining security in production. From 8412e3235dd90f117f5b5c5b74483d8857b99c1e Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 06:19:37 +0900 Subject: [PATCH 3/5] test(openapi): exercise persisted auth with development bearer enabled --- tests/test_health.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tests/test_health.py b/tests/test_health.py index 8d31abca..79657182 100644 --- a/tests/test_health.py +++ b/tests/test_health.py @@ -70,15 +70,14 @@ def test_openapi_swagger_ui_parameters_in_production(): assert params.get("persistAuthorization") is None -def test_openapi_swagger_ui_parameters_in_development(): +def test_openapi_swagger_ui_persists_authorization_only_in_authenticated_development(): + from newsdom_api.config import RuntimeProfile, RuntimeSettings from newsdom_api.main import create_app - from newsdom_api.config import RuntimeSettings, RuntimeProfile, AuthenticationMode app_dev = create_app( RuntimeSettings( runtime_profile=RuntimeProfile.DEVELOPMENT, - authentication_mode=AuthenticationMode.DISABLED, - api_token=None, + api_token="development-secret", ) ) params = app_dev.swagger_ui_parameters From bc362e7e04f40d1486d53edd3e1e2e34a8e74e3d Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 06:21:33 +0900 Subject: [PATCH 4/5] test(openapi): name persisted-auth contract precisely --- tests/test_health.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_health.py b/tests/test_health.py index 79657182..c05c3c00 100644 --- a/tests/test_health.py +++ b/tests/test_health.py @@ -70,7 +70,7 @@ def test_openapi_swagger_ui_parameters_in_production(): assert params.get("persistAuthorization") is None -def test_openapi_swagger_ui_persists_authorization_only_in_authenticated_development(): +def test_openapi_swagger_ui_persists_authorization_in_authenticated_development(): from newsdom_api.config import RuntimeProfile, RuntimeSettings from newsdom_api.main import create_app From 0a67037ce7e21e7dbd020b20eda2e74470b98540 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 06:22:17 +0900 Subject: [PATCH 5/5] docs(changelog): record development-only Swagger auth persistence --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2398ea5c..20b70d57 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 > acceptance are aligned for an actual 0.3.0 publication. ### Changed +- development 프로필의 Swagger UI에서 `persistAuthorization`을 활성화해 입력한 authorization 상태를 새로고침 이후에도 유지합니다. production 프로필은 Swagger UI 기본값(`false`)을 유지합니다. - `/parse`를 언어 선택형 파서로 일반화: MinerU `-l japan`/`-m ocr` 하드코딩을 제거하고 optional form 필드 `language`(MinerU 3.4.4 공식 기본 `ch`, 공개 언어군/alias 검증)와 `mode`(`auto`/`ocr`/`txt`, 기본 `auto`)로 파라미터화. `mode=auto`는 born-digital PDF가 강제 OCR을 건너뛰도록 함. 기존 입력 `language=japan&mode=ocr`는 공식 규약대로 `ch`/`ocr`로 정규화됨. - OpenAPI 제목/설명, README, `ArticleNode.headline` 문서를 일반 문서용 (section heading) 표현으로 재구성하여 특정 언어/신문 가정을 소비자에게 노출하지 않도록 함. 응답 스키마 필드는 하위 호환을 위해 변경하지 않음.