From 8d0a694816795c051a343eb7c1a2ff5d9c95033b Mon Sep 17 00:00:00 2001 From: jxxghp Date: Sat, 22 Aug 2026 20:35:27 +0800 Subject: [PATCH] refactor: migrate passkey runtime configuration --- app/application/configuration.py | 3 +++ app/application/security/passkey.py | 22 ++++++++++--------- app/startup/configuration.py | 3 +++ .../backend-architecture-next-stage.md | 2 ++ .../configuration-debt-baseline.json | 3 +-- .../architecture/dependency-baseline.json | 7 +++--- 6 files changed, 25 insertions(+), 15 deletions(-) diff --git a/app/application/configuration.py b/app/application/configuration.py index 7fc4cf4d9..b83c807a9 100644 --- a/app/application/configuration.py +++ b/app/application/configuration.py @@ -98,6 +98,9 @@ class ApiRuntimeConfig: cookie_path: Path = Path(".") root_path: Path = Path(".") version_flag: str = "v3" + app_domain: str | None = None + nginx_port: int = 3000 + passkey_require_uv: bool = True def rename_format(self, media_type: MediaType) -> str: """从请求快照返回指定媒体类型的稳定重命名格式。""" diff --git a/app/application/security/passkey.py b/app/application/security/passkey.py index e7214d191..b72c028e2 100644 --- a/app/application/security/passkey.py +++ b/app/application/security/passkey.py @@ -32,7 +32,7 @@ from webauthn.helpers.cose import COSEAlgorithmIdentifier from webauthn.helpers.exceptions import InvalidRegistrationResponse from app.runtime.cache import TTLCache -from app.runtime.config import settings +from app.application.configuration import get_api_runtime_config_snapshot from app.adapters.cache.redis import RedisHelper from app.runtime.log import logger @@ -127,8 +127,9 @@ class PassKeyHelper: """ 获取 Relying Party ID """ - if settings.APP_DOMAIN: - app_domain = settings.APP_DOMAIN.strip() + config = get_api_runtime_config_snapshot() + if config.app_domain: + app_domain = config.app_domain.strip() # 确保存在协议前缀,以便 urlparse 正确解析主机和端口 if not app_domain.startswith(('http://', 'https://')): app_domain = f'https://{app_domain}' @@ -137,7 +138,7 @@ class PassKeyHelper: if host: return host # 从 APP_DOMAIN 中提取域名 - host = settings.APP_DOMAIN.replace('https://', '').replace('http://', '') + host = config.app_domain.replace('https://', '').replace('http://', '') # 移除端口号 if ':' in host: host = host.split(':')[0] @@ -157,10 +158,11 @@ class PassKeyHelper: """ 获取源地址 """ - if settings.APP_DOMAIN: - return settings.APP_DOMAIN.rstrip('/') + config = get_api_runtime_config_snapshot() + if config.app_domain: + return config.app_domain.rstrip('/') # 如果未配置APP_DOMAIN,使用默认的localhost地址 - return f'http://localhost:{settings.NGINX_PORT}' + return f'http://localhost:{config.nginx_port}' @staticmethod def standardize_credential_id(credential_id: str) -> str: @@ -229,7 +231,7 @@ class PassKeyHelper: """ if user_verification: return UserVerificationRequirement(user_verification) - return UserVerificationRequirement.REQUIRED if settings.PASSKEY_REQUIRE_UV \ + return UserVerificationRequirement.REQUIRED if get_api_runtime_config_snapshot().passkey_require_uv \ else UserVerificationRequirement.PREFERRED @staticmethod @@ -337,7 +339,7 @@ class PassKeyHelper: expected_challenge=challenge_bytes, expected_rp_id=rp_id, expected_origin=origin, - require_user_verification=settings.PASSKEY_REQUIRE_UV + require_user_verification=get_api_runtime_config_snapshot().passkey_require_uv ) # 提取信息 @@ -441,7 +443,7 @@ class PassKeyHelper: expected_origin=origin, credential_public_key=public_key_bytes, credential_current_sign_count=credential_current_sign_count, - require_user_verification=settings.PASSKEY_REQUIRE_UV + require_user_verification=get_api_runtime_config_snapshot().passkey_require_uv ) return True, verification.new_sign_count diff --git a/app/startup/configuration.py b/app/startup/configuration.py index b53336ad2..a65c3b03c 100644 --- a/app/startup/configuration.py +++ b/app/startup/configuration.py @@ -46,6 +46,9 @@ def build_api_runtime_config(settings: Settings) -> ApiRuntimeConfig: cookie_path=settings.COOKIE_PATH, root_path=settings.ROOT_PATH, version_flag=settings.VERSION_FLAG, + app_domain=settings.APP_DOMAIN, + nginx_port=settings.NGINX_PORT, + passkey_require_uv=settings.PASSKEY_REQUIRE_UV, ) diff --git a/docs/refactor/backend-architecture-next-stage.md b/docs/refactor/backend-architecture-next-stage.md index 8813a84c8..9766bf784 100644 --- a/docs/refactor/backend-architecture-next-stage.md +++ b/docs/refactor/backend-architecture-next-stage.md @@ -981,6 +981,8 @@ Outbox adapter、DB 装饰器、Base 与 UoW,strict 清单扩大到 37 个源 `app/application/rss.py` 的代理和编码检测选项也已迁移到快照,配置债务降至 133 个文件;RSS、Rust 解析和音乐资源专项测试通过。 数据维护策略随后接入同一快照,`app/application/maintenance.py` 的直接配置读取移除,债务降至 132 个文件; 清理服务与 Chain 专项测试通过。 +Passkey 的 APP_DOMAIN、NGINX_PORT 和用户验证要求也已接入 API 配置快照,配置债务降至 131 个文件; +MFA/Passkey 专项测试与架构门禁通过,密钥类配置仍保留在安全端口范围内。 #### ARCH-272:异步阻塞检测 diff --git a/tests/fixtures/architecture/configuration-debt-baseline.json b/tests/fixtures/architecture/configuration-debt-baseline.json index 2b39cd63d..6b9217bf2 100644 --- a/tests/fixtures/architecture/configuration-debt-baseline.json +++ b/tests/fixtures/architecture/configuration-debt-baseline.json @@ -9,7 +9,7 @@ "root": "app" }, "settings_imports": { - "count": 132, + "count": 131, "files": [ "app/adapters/cache/backends.py", "app/adapters/cache/redis.py", @@ -48,7 +48,6 @@ "app/agent/tools/impl/update_agent_task.py", "app/agent/tools/impl/update_system_settings.py", "app/application/security/auth.py", - "app/application/security/passkey.py", "app/application/security/token.py", "app/application/security/url.py", "app/cli.py", diff --git a/tests/fixtures/architecture/dependency-baseline.json b/tests/fixtures/architecture/dependency-baseline.json index 9dbd176a1..72d2057e9 100644 --- a/tests/fixtures/architecture/dependency-baseline.json +++ b/tests/fixtures/architecture/dependency-baseline.json @@ -13,8 +13,8 @@ "runtime_to_db": [], "workflow_to_db": [] }, - "edge_count": 6398, - "edge_sha256": "ca0fced68968392288a03d38c2da937cf75e6a9fd2dc3be6dadcb72efdbc462b", + "edge_count": 6399, + "edge_sha256": "f3e4e76578ddfc1ac0717f9d0c2fc9a95c4c659e00c3cc25894304c69ae892fa", "edges": [ "app -> app.runtime", "app -> app.runtime.compat", @@ -2695,9 +2695,10 @@ "app.application.security.passkey -> app.adapters", "app.application.security.passkey -> app.adapters.cache", "app.application.security.passkey -> app.adapters.cache.redis", + "app.application.security.passkey -> app.application", + "app.application.security.passkey -> app.application.configuration", "app.application.security.passkey -> app.runtime", "app.application.security.passkey -> app.runtime.cache", - "app.application.security.passkey -> app.runtime.config", "app.application.security.passkey -> app.runtime.log", "app.application.security.token -> app.runtime", "app.application.security.token -> app.runtime.config",