mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-08-29 03:56:43 +08:00
164 lines
4.6 KiB
Python
164 lines
4.6 KiB
Python
"""宿主 Module 的渐进式集成质量清单。"""
|
||
|
||
from __future__ import annotations
|
||
|
||
from dataclasses import dataclass
|
||
from enum import StrEnum
|
||
|
||
|
||
class ModuleQualityLevel(StrEnum):
|
||
"""描述模块当前接受的质量门禁等级。"""
|
||
|
||
LEGACY = "legacy"
|
||
ASSESSED = "assessed"
|
||
|
||
|
||
@dataclass(frozen=True, slots=True)
|
||
class ModuleQualityProfile:
|
||
"""记录一个模块已验证规则、维护者和精确豁免原因。"""
|
||
|
||
module: str
|
||
level: ModuleQualityLevel
|
||
owner: str
|
||
verified_rules: frozenset[str] = frozenset()
|
||
exemption_reason: str | None = None
|
||
|
||
|
||
QUALITY_RULES = frozenset(
|
||
{
|
||
"fake-client-or-fixture",
|
||
"zero-real-network-tests",
|
||
"sync-async-boundary",
|
||
"no-blocking-io-in-event-loop",
|
||
"auth-rate-timeout-offline-semantics",
|
||
"bounded-concurrency-or-polling",
|
||
"reload-stop-idempotent",
|
||
"module-contract-v2",
|
||
"sensitive-log-redaction",
|
||
"owner-declared",
|
||
}
|
||
)
|
||
|
||
COMMON_ASSESSED_RULES = frozenset(
|
||
{
|
||
"zero-real-network-tests",
|
||
"no-blocking-io-in-event-loop",
|
||
"module-contract-v2",
|
||
"owner-declared",
|
||
}
|
||
)
|
||
|
||
# 这些模块均已纳入全局真实网络守卫、async 阻塞扫描和 V2 方法契约门禁。
|
||
# 模块专属的鉴权、限流、并发和生命周期规则仍按 profile 中的精确豁免逐项补强,
|
||
# 但不再使用无法区分“未审查”和“已审查有缺口”的 legacy 状态。
|
||
BASELINE_ASSESSED_MODULES = frozenset(
|
||
{
|
||
"acoustid",
|
||
"anilist",
|
||
"discord",
|
||
"douban",
|
||
"emby",
|
||
"fanart",
|
||
"feishu",
|
||
"filemanager",
|
||
"filter",
|
||
"imdb",
|
||
"indexer",
|
||
"jellyfin",
|
||
"listenbrainz",
|
||
"lrclib",
|
||
"musicbrainz",
|
||
"navidrome",
|
||
"plex",
|
||
"postgresql",
|
||
"qbittorrent",
|
||
"qqbot",
|
||
"redis",
|
||
"rtorrent",
|
||
"slack",
|
||
"subtitle",
|
||
"synologychat",
|
||
"telegram",
|
||
"theaudiodb",
|
||
"themoviedb",
|
||
"thetvdb",
|
||
"transmission",
|
||
"trimemedia",
|
||
"ugreen",
|
||
"vocechat",
|
||
"webpush",
|
||
"wechat",
|
||
"wechatclawbot",
|
||
"zspace",
|
||
}
|
||
)
|
||
|
||
MODULE_QUALITY_PROFILES = {
|
||
module: ModuleQualityProfile(
|
||
module=module,
|
||
level=ModuleQualityLevel.ASSESSED,
|
||
owner="MoviePilot core",
|
||
verified_rules=COMMON_ASSESSED_RULES,
|
||
exemption_reason=(
|
||
"已完成宿主通用网络、异步阻塞、V2 方法契约与维护责任门禁;"
|
||
"模块专属鉴权、限流、并发、敏感日志及 reload/stop 语义只在有对应能力时适用,"
|
||
"继续由各模块专项测试证明"
|
||
),
|
||
)
|
||
for module in BASELINE_ASSESSED_MODULES
|
||
}
|
||
|
||
MODULE_QUALITY_PROFILES.update({
|
||
"bangumi": ModuleQualityProfile(
|
||
module="bangumi",
|
||
level=ModuleQualityLevel.ASSESSED,
|
||
owner="MoviePilot core",
|
||
verified_rules=frozenset(
|
||
{
|
||
"fake-client-or-fixture",
|
||
"zero-real-network-tests",
|
||
"sync-async-boundary",
|
||
"reload-stop-idempotent",
|
||
"module-contract-v2",
|
||
"sensitive-log-redaction",
|
||
"owner-declared",
|
||
}
|
||
),
|
||
exemption_reason=(
|
||
"外部 Bangumi API 的限流与并发策略仍沿用通用 HTTP adapter;"
|
||
"本轮仅对配置快照改动面启用 assessed 门禁"
|
||
),
|
||
),
|
||
"dingtalk": ModuleQualityProfile(
|
||
module="dingtalk",
|
||
level=ModuleQualityLevel.ASSESSED,
|
||
owner="MoviePilot core",
|
||
verified_rules=frozenset(
|
||
{
|
||
"fake-client-or-fixture",
|
||
"zero-real-network-tests",
|
||
"reload-stop-idempotent",
|
||
"module-contract-v2",
|
||
"sensitive-log-redaction",
|
||
"owner-declared",
|
||
}
|
||
),
|
||
exemption_reason=(
|
||
"钉钉自定义机器人仅提供同步出站 Webhook,不包含长连接、轮询或入站回调"
|
||
),
|
||
),
|
||
})
|
||
|
||
|
||
def get_module_quality_profile(module: str) -> ModuleQualityProfile:
|
||
"""返回显式 profile;未迁移模块以带原因的 legacy 视图呈现。"""
|
||
return MODULE_QUALITY_PROFILES.get(
|
||
module,
|
||
ModuleQualityProfile(
|
||
module=module,
|
||
level=ModuleQualityLevel.LEGACY,
|
||
owner="MoviePilot core",
|
||
exemption_reason="存量模块尚未在二阶段任务中修改,按渐进策略暂不提升门禁",
|
||
),
|
||
)
|