Files
MoviePilot/tests/fixtures/architecture/dependency-policy.json
T

420 lines
23 KiB
JSON

{
"schema_version": 3,
"scope": {
"dependency_kind": "static_runtime_imports",
"excluded_roots": [
"app/plugins"
],
"include_parent_package_initialization": true,
"root": "app"
},
"allowed_sccs": [
{
"classification": "temporary_debt",
"id": "chain-package-root",
"modules": [
"app.chain",
"app.chain._messaging",
"app.chain._recognition"
],
"reason": "ChainBase 仍由包根导出,包根又加载消息和识别实现;S2-L2 负责拆出 app.chain.base 并清零该环。",
"tracking": "ARCH-107"
},
{
"classification": "contained_vendor",
"id": "themoviedb-vendored-package",
"modules": [
"app.modules.themoviedb",
"app.modules.themoviedb.scraper",
"app.modules.themoviedb.tmdbapi",
"app.modules.themoviedb.tmdbv3api",
"app.modules.themoviedb.tmdbv3api.objs.account",
"app.modules.themoviedb.tmdbv3api.objs.auth",
"app.modules.themoviedb.tmdbv3api.objs.certification",
"app.modules.themoviedb.tmdbv3api.objs.change",
"app.modules.themoviedb.tmdbv3api.objs.collection",
"app.modules.themoviedb.tmdbv3api.objs.company",
"app.modules.themoviedb.tmdbv3api.objs.configuration",
"app.modules.themoviedb.tmdbv3api.objs.credit",
"app.modules.themoviedb.tmdbv3api.objs.discover",
"app.modules.themoviedb.tmdbv3api.objs.episode",
"app.modules.themoviedb.tmdbv3api.objs.find",
"app.modules.themoviedb.tmdbv3api.objs.genre",
"app.modules.themoviedb.tmdbv3api.objs.group",
"app.modules.themoviedb.tmdbv3api.objs.keyword",
"app.modules.themoviedb.tmdbv3api.objs.list",
"app.modules.themoviedb.tmdbv3api.objs.movie",
"app.modules.themoviedb.tmdbv3api.objs.network",
"app.modules.themoviedb.tmdbv3api.objs.person",
"app.modules.themoviedb.tmdbv3api.objs.provider",
"app.modules.themoviedb.tmdbv3api.objs.review",
"app.modules.themoviedb.tmdbv3api.objs.search",
"app.modules.themoviedb.tmdbv3api.objs.season",
"app.modules.themoviedb.tmdbv3api.objs.trending",
"app.modules.themoviedb.tmdbv3api.objs.tv",
"app.modules.themoviedb.tmdbv3api.tmdb"
],
"reason": "隔离的移植代码保持精确成员 containment;普通单向包外依赖允许,任何成员扩张或包外反向入环均失败。",
"tracking": "replace-or-upgrade-vendored-package"
}
],
"direct_adapter_imports": {
"classification": "temporary_debt",
"scope": {
"source_roots": [
"app.application",
"app.chain"
],
"target_root": "app.adapters",
"runtime_only": true,
"parent_package_expansion": false,
"imported_symbols": false
},
"entries": [
{
"source": "app.application.backup",
"target": "app.adapters.system.backup.files",
"tracking": "S2-L5"
},
{
"source": "app.application.directory",
"target": "app.adapters.system.host",
"tracking": "S2-L6"
},
{
"source": "app.application.image",
"target": "app.adapters.network.http",
"tracking": "S2-L6"
},
{
"source": "app.application.image",
"target": "app.adapters.network.ip",
"tracking": "S2-L6"
},
{
"source": "app.application.messaging.ingress",
"target": "app.adapters.network.http",
"tracking": "S2-L6"
},
{
"source": "app.application.rss",
"target": "app.adapters.network.browser",
"tracking": "S2-L6"
},
{
"source": "app.application.rss",
"target": "app.adapters.network.http",
"tracking": "S2-L6"
},
{
"source": "app.application.rss",
"target": "app.adapters.system",
"tracking": "S2-L6"
},
{
"source": "app.application.rules",
"target": "app.adapters.system",
"tracking": "S2-L6"
},
{
"source": "app.application.security.cookie",
"target": "app.adapters.external.ocr",
"tracking": "S2-L6"
},
{
"source": "app.application.security.cookie",
"target": "app.adapters.network.browser",
"tracking": "S2-L6"
},
{
"source": "app.application.security.cookie",
"target": "app.adapters.network.http",
"tracking": "S2-L6"
},
{
"source": "app.application.torrent",
"target": "app.adapters.network.http",
"tracking": "S2-L6"
},
{
"source": "app.application.transfer.workflow",
"target": "app.adapters.system.host",
"tracking": "S2-L6"
},
{
"source": "app.chain._recognition",
"target": "app.adapters.external.server",
"tracking": "S2-L7"
},
{
"source": "app.chain._transfer",
"target": "app.adapters.system.host",
"tracking": "S2-L7"
},
{
"source": "app.chain.download",
"target": "app.adapters.network.http",
"tracking": "S2-L7"
},
{
"source": "app.chain.download",
"target": "app.adapters.system.host",
"tracking": "S2-L7"
},
{
"source": "app.chain.message",
"target": "app.adapters.network.http",
"tracking": "S2-L7"
},
{
"source": "app.chain.scraping",
"target": "app.adapters.network.http",
"tracking": "S2-L7"
},
{
"source": "app.chain.site",
"target": "app.adapters.external.cookiecloud",
"tracking": "S2-L7"
},
{
"source": "app.chain.site",
"target": "app.adapters.network.browser",
"tracking": "S2-L7"
},
{
"source": "app.chain.site",
"target": "app.adapters.network.cloudflare",
"tracking": "S2-L7"
},
{
"source": "app.chain.site",
"target": "app.adapters.network.http",
"tracking": "S2-L7"
},
{
"source": "app.chain.subscribe",
"target": "app.adapters.external.server",
"tracking": "S2-L7"
},
{
"source": "app.chain.system",
"target": "app.adapters.network.http",
"tracking": "S2-L7"
},
{
"source": "app.chain.system",
"target": "app.adapters.system.host",
"tracking": "S2-L7"
}
],
"target_state": "empty"
},
"direct_egress": {
"scope": {
"root": "app",
"excluded_roots": ["app.plugins"],
"runtime_only": true,
"line_numbers": false
},
"registry": {
"raw_transports": [
"requests", "httpx", "httpx2", "aiohttp", "urllib.request", "urllib3",
"http.client", "websocket", "websockets", "curl_cffi", "cloudscraper",
"httplib2", "pycurl"
],
"network_sdks": [
"boto3", "botocore", "cloakbrowser", "ddgs", "discord", "docker",
"google.genai", "langchain_anthropic", "langchain_aws", "langchain_deepseek",
"langchain_google_genai", "langchain_openai", "lark_oapi", "openai", "oss2",
"plexapi", "pywebpush", "qbittorrentapi", "redis", "slack_bolt", "slack_sdk",
"smbclient", "smbprotocol", "telebot", "transmission_rpc"
],
"protocol_operations": [
"asyncio.open_connection", "socket.create_connection", "socket.getaddrinfo",
"socket.gethostbyname", "xmlrpc.client.ServerProxy"
],
"reexports": [
{
"source": "app.adapters.network.http.requests",
"target": "requests"
}
]
},
"groups": [
{
"classification": "temporary_debt",
"reason_code": "direct_http",
"tracking": "S2-L7",
"target_state": "empty",
"reason": "普通宿主 HTTP 与 SDK client factory 尚未收口;provider 的直接请求和注入 client 必须在同一迁移中处理。",
"facts": [
{"source": "app.agent.llm.provider", "target": "httpx", "kind": "raw_transport", "fingerprint": "a68ad216d86b4b33aa8c35572c26f7993245c0c12dd512e962bcacb46d7f15fc"},
{"source": "app.modules.filemanager.storages.alipan", "target": "requests", "kind": "raw_transport", "fingerprint": "82d84425f58ed9664a6e2a4ece53240198c95a0f9fee5d0afd0a11e3c459ecf6"},
{"source": "app.modules.filemanager.storages.u115", "target": "httpx", "kind": "raw_transport", "fingerprint": "f6678109963f9973d5d15e38e5f5e8dca01ec5e0117598ad1ac877b841ff7961"},
{"source": "app.modules.ugreen.api", "target": "requests", "kind": "raw_transport", "fingerprint": "a266dd2b74f216b289682e5d83c0b5a7d0d08b5447d79c165659b6d7302656d6"}
]
},
{
"classification": "temporary_debt",
"reason_code": "requestutils_session_bridge",
"tracking": "S2-L7",
"target_state": "empty",
"reason": "模块构造或接收 requests Session,并管理生命周期或桥接给 RequestUtils;迁移后不再直接拥有 transport。",
"facts": [
{"source": "app.modules.bangumi.bangumi", "target": "requests", "kind": "raw_transport", "fingerprint": "e5baf8a89b8661025169e9eec8d3c13d30660f63b35d94ec4896cd97e7fde3bf"},
{"source": "app.modules.douban.apiv2", "target": "requests", "kind": "raw_transport", "fingerprint": "6e871a27b88263676797edd65093d0b38db48f77fb5db2bb581b7b82e9b2977d"},
{"source": "app.modules.imdb.api", "target": "requests", "kind": "raw_transport", "fingerprint": "3d05532e62d2cddf3bb05495196176b76aa02216c2b0d868cf9281d2257d9627"},
{"source": "app.modules.indexer.parser", "target": "requests", "kind": "raw_transport", "fingerprint": "facdb091442bacba0fc0f631637643e95e18545bd7ab63f1d49d67a9a928d016"},
{"source": "app.modules.musicbrainz", "target": "requests", "kind": "raw_transport", "fingerprint": "c54a10dd672fb0ebb32a536ae42c221ad434313466cc108d43e433dd84cac9a5"},
{"source": "app.modules.plex.plex", "target": "requests", "kind": "raw_transport", "fingerprint": "93f20b9c01571553e9601f4b9f4ee9471073e65f938cb635320f72fa41ec3843"},
{"source": "app.modules.trimemedia.api", "target": "requests", "kind": "raw_transport", "fingerprint": "aecbe00404b2866c918c939bee5f1002045fc72aed4440c85e0811a4379913e4"}
]
},
{
"classification": "temporary_debt",
"reason_code": "direct_dns",
"tracking": "S2-L6",
"target_state": "empty",
"reason": "SSRF 校验仍在 Application 直接执行 DNS I/O;迁移到注入的解析 Port 后清零。",
"facts": [
{"source": "app.application.security.url", "target": "socket.getaddrinfo", "kind": "protocol_operation", "fingerprint": "89c563fdb640259584563fc718f7104a7b4dc6717e97b9c9e449f70f74a9532b"}
]
},
{
"classification": "approved_exception",
"reason_code": "canonical_transport",
"owner": "$source",
"reason": "精确 Adapter source 持有其 Redis、浏览器、HTTP 或 DNS transport;上层只能消费 Port 或统一 Facade。",
"facts": [
{"source": "app.adapters.cache.redis", "target": "redis", "kind": "network_sdk", "fingerprint": "49f0b28ef731b25aa772d6887febd762d03b981a1f52d6dfc8dff82f2f489f81"},
{"source": "app.adapters.network.browser", "target": "cloakbrowser", "kind": "network_sdk", "fingerprint": "15c1777b14eb9147d6cab9783f67577011714f9220600dda5db5269b59726173"},
{"source": "app.adapters.network.doh", "target": "socket.getaddrinfo", "kind": "protocol_operation", "fingerprint": "4ff03419dfacc6bf582b7d4421dd5a0666a63f8ca79be2b1e625f4c8f4c96b71"},
{"source": "app.adapters.network.doh", "target": "urllib.request", "kind": "raw_transport", "fingerprint": "6f5f5fd3da02a9e780ea5e7cc1e47bd962314a1a358f14b4ee698485f96ab52b"},
{"source": "app.adapters.network.http", "target": "httpx2", "kind": "raw_transport", "fingerprint": "a70799e9930ff79cd28ebed92836c8108cd2d18bc668e0081f68533d84f69d0d"},
{"source": "app.adapters.network.http", "target": "requests", "kind": "raw_transport", "fingerprint": "95fb4576cec363355f40aa1758d90fbb09242a2b1d029b7ab5ab65e2aaca12f8"},
{"source": "app.adapters.network.ip", "target": "socket.gethostbyname", "kind": "protocol_operation", "fingerprint": "a43e8969e2f26546fcf925b258728b309f1b9b966ff3c7b48a64273b8c82d048"}
]
},
{
"classification": "approved_exception",
"reason_code": "transport_configuration",
"owner": "$source",
"reason": "统一 HTTP Adapter 仅配置 urllib3 警告策略,不创建 urllib3 网络连接。",
"facts": [
{"source": "app.adapters.network.http", "target": "urllib3", "kind": "raw_transport", "fingerprint": "66cbd8ec4e7552bd458db0baada30f1953e6d0493793822d23a2199567bca98a"}
]
},
{
"classification": "approved_exception",
"reason_code": "sdk_transport",
"owner": "$source",
"reason": "命名 SDK 或显式注入的 SDK transport 由该精确 source 持有,不授权新增调用方。",
"facts": [
{"source": "app.agent.llm.capability", "target": "openai", "kind": "network_sdk", "fingerprint": "60160ab01b60be2c9794b9724a50b90f8875c6a10748ff9392a1e4bc7d48c334"},
{"source": "app.agent.llm.helper", "target": "google.genai", "kind": "network_sdk", "fingerprint": "d41688ecda4c5de296fabb0d0d25c79a7b0f29f67ccdd44569dc1110e1db9b86"},
{"source": "app.agent.llm.helper", "target": "httpx", "kind": "raw_transport", "fingerprint": "caeccd432f48d9a23948dd5b9220ddbebc57d2b2936bfa499fc7d4876e935ea8"},
{"source": "app.agent.llm.helper", "target": "langchain_anthropic", "kind": "network_sdk", "fingerprint": "c8d2c3166c4d42d61e7ef38a25080cac0f93422f47393df6dc19b329a7f72265"},
{"source": "app.agent.llm.helper", "target": "langchain_aws", "kind": "network_sdk", "fingerprint": "51dd02f5e2305cce4e1f6f29b4ed47edf54dde9f6557781178a6edf96bfeeb6b"},
{"source": "app.agent.llm.helper", "target": "langchain_deepseek", "kind": "network_sdk", "fingerprint": "bcf8b1ffae0995cfc33cfe26609cef8014cd2ce036b845c2a88c0cd878b1ebc4"},
{"source": "app.agent.llm.helper", "target": "langchain_google_genai", "kind": "network_sdk", "fingerprint": "79ae88c63908da9ea36dcfc23c4ad5345bc5d1977b80cc2e0b89292d063ed8ee"},
{"source": "app.agent.llm.helper", "target": "langchain_openai", "kind": "network_sdk", "fingerprint": "15775bf1694780d5cf516e6cc3d3b5174ebb25e3038433132d3071e6abceba52"},
{"source": "app.agent.llm.helper", "target": "openai", "kind": "network_sdk", "fingerprint": "dbebd5e9fa38b2a525a5a2e5a92d855ba9d05762410590bfb544e665fe38f620"},
{"source": "app.agent.llm.provider", "target": "boto3", "kind": "network_sdk", "fingerprint": "04ca4b5ecbda1531266d5f53817dde061dcfdd3293cabf9301fc8d8e4c281a88"},
{"source": "app.agent.llm.provider", "target": "botocore", "kind": "network_sdk", "fingerprint": "fbeaa702703665ca60233a153aade0da7e49dfb6fe31f72e5593c883fb7d3f11"},
{"source": "app.agent.llm.provider", "target": "google.genai", "kind": "network_sdk", "fingerprint": "b545cffb169b87f87606c17762b5d9da3f35372bd411c1f4ebba010b3d7c3ebb"},
{"source": "app.agent.llm.provider", "target": "openai", "kind": "network_sdk", "fingerprint": "ffac3b355eb640f6421299cf838cb4e24866a39afabd9dcfd8d0f340925dc1a8"},
{"source": "app.agent.tools.impl.search_web", "target": "ddgs", "kind": "network_sdk", "fingerprint": "377e73bb3be804b825d60ad6e792344ca633de107f8c4dbb45d50a34a4dfa04b"},
{"source": "app.api.endpoints.message", "target": "pywebpush", "kind": "network_sdk", "fingerprint": "7d83ca0dc89dfb6af1cdd7bc90d922105de94222e4e3a44bba4f53bbd97bc31b"},
{"source": "app.modules.discord.discord", "target": "discord", "kind": "network_sdk", "fingerprint": "e1486525fedbfe574aa47d60b483426c8c48e4e27fa35dbe34f6cd2f47d37c86"},
{"source": "app.modules.feishu.feishu", "target": "lark_oapi", "kind": "network_sdk", "fingerprint": "99d16968a59932b5980f6d42ea2bbc8fa35ccdb1a27933beec29b4bdc093d78b"},
{"source": "app.modules.filemanager.storages.smb", "target": "smbclient", "kind": "network_sdk", "fingerprint": "62e0585282ef206ac81b2bf9e93a58423fb058685edc0ef4ee592453bbf30376"},
{"source": "app.modules.filemanager.storages.u115", "target": "oss2", "kind": "network_sdk", "fingerprint": "f7b89c8ae6dad2603f0a9e0caaa159769aef5b3581d7e728f62445b979366eae"},
{"source": "app.modules.plex.plex", "target": "plexapi", "kind": "network_sdk", "fingerprint": "76c1334863dc6c6623ce6ad3415bec5ff92656f51c31e4d982285898f193e57e"},
{"source": "app.modules.qbittorrent.qbittorrent", "target": "qbittorrentapi", "kind": "network_sdk", "fingerprint": "b2f5a27f0c54cf95ed42fe99848fd6c9c0641caca8bc4ff8006a411cb427066d"},
{"source": "app.modules.slack.slack", "target": "slack_bolt", "kind": "network_sdk", "fingerprint": "be5dcb032ece8d8627abeb243f98143aaf60f26751ab6e5e098813d4048419e6"},
{"source": "app.modules.slack.slack", "target": "slack_sdk", "kind": "network_sdk", "fingerprint": "7559f31e4172ad3bbbaf161e1164ea48b997c56d05c77b49b82626298c39aa14"},
{"source": "app.modules.telegram.telegram", "target": "telebot", "kind": "network_sdk", "fingerprint": "78f5ab18bfd67ba4fa0f3c0fc4a1a561a7b1d9e81e335fb80de86edb480b84b8"},
{"source": "app.modules.transmission.transmission", "target": "transmission_rpc", "kind": "network_sdk", "fingerprint": "1652e661cb17dbadb039fdc4ab73d6d06e47eb118292ba3693313e45834959cf"},
{"source": "app.modules.webpush", "target": "pywebpush", "kind": "network_sdk", "fingerprint": "389c73b06150e3d5bcaf31f35a25178873d2ed38ef9a28354cb9bab691eeab76"}
]
},
{
"classification": "approved_exception",
"reason_code": "streaming_protocol",
"owner": "$source",
"reason": "产品长连接或 SCGI/XML-RPC transport 由该协议模块精确持有。",
"facts": [
{"source": "app.modules.qqbot.gateway", "target": "websocket", "kind": "raw_transport", "fingerprint": "6f6b7d61f3a95e620e67c450d544f0aa077f087a188d98f32e4501d94c6b37ae"},
{"source": "app.modules.rtorrent.rtorrent", "target": "socket.create_connection", "kind": "protocol_operation", "fingerprint": "878114d6b1bda091bd3b3d8aa819831d84381682feba78267592d2593295af90"},
{"source": "app.modules.rtorrent.rtorrent", "target": "xmlrpc.client.ServerProxy", "kind": "protocol_operation", "fingerprint": "2ac64b5670c930bc28bb2135cc4b73891c1cae01a74a9586f74e302878c45c85"},
{"source": "app.modules.wechat.wechatbot", "target": "websocket", "kind": "raw_transport", "fingerprint": "1bae78270eadce0571e2caaa111a5c0a9065ba2da97ebb26b8a5b76d3ed5eef6"}
]
},
{
"classification": "approved_exception",
"reason_code": "contained_vendor",
"owner": "$source",
"reason": "TMDB 移植客户端在 containment 内创建 Session,并把实际请求交给 RequestUtils。",
"facts": [
{"source": "app.modules.themoviedb.tmdbv3api.tmdb", "target": "requests", "kind": "raw_transport", "fingerprint": "d605eb176a203b3f4d205c5d183469b3002426682eb9cb4e7408bb6013652484"}
]
},
{
"classification": "approved_exception",
"reason_code": "local_control_plane",
"owner": "$source",
"reason": "CLI 只调用本机 MoviePilot 控制面,维持精确运维入口。",
"facts": [
{"source": "app.cli", "target": "urllib.request", "kind": "raw_transport", "fingerprint": "71b3e5be2a7d85fdc7a207d15c0e690d7ab96b335b882a3eaec03a1cb4ec1d1b"}
]
},
{
"classification": "approved_exception",
"reason_code": "diagnostic_probe",
"owner": "$source",
"reason": "doctor 按用户配置探测 PostgreSQL 与后端健康端点,可能指向远端,仅用于显式诊断。",
"facts": [
{"source": "app.doctor.checks", "target": "socket.create_connection", "kind": "protocol_operation", "fingerprint": "dfb34d4710353029dcc06e0e0ce3b299bae1a7e71a5743de1d253ac26380f9b6"},
{"source": "app.doctor.checks", "target": "urllib.request", "kind": "raw_transport", "fingerprint": "d8dd2279263ef58c3b4c59c70451533a4fc27d2ccd76960ca3aff29cd73f3354"}
]
},
{
"classification": "approved_exception",
"reason_code": "type_or_compat_only",
"owner": "$source",
"reason": "运行期 import 仅用于响应类型、协议解析或兼容补丁,uses 为空或不获取网络能力。",
"facts": [
{"source": "app.adapters.external.market", "target": "httpx2", "kind": "raw_transport", "fingerprint": "d4a648e8188818c0465013fc63cc3e49899da4df38541344303c251896564b1f"},
{"source": "app.adapters.external.market", "target": "requests", "kind": "raw_transport", "fingerprint": "ecc5368adfced20741e5ed8696008ea7555a4a81ceda6d7149e09f5f3d0ff7e3"},
{"source": "app.modules.douban.apiv2", "target": "httpx2", "kind": "raw_transport", "fingerprint": "edc337b12976d978cad3f83d0fa6faf71b2af2d814926dff890d5acc94f0a0a6"},
{"source": "app.modules.emby.emby", "target": "requests", "kind": "raw_transport", "fingerprint": "6c4c17fe170226ea1272f5859bc119c2775442cabe8ce2a9edcabaf9c37bec31"},
{"source": "app.modules.filemanager.storages.smb", "target": "smbprotocol", "kind": "network_sdk", "fingerprint": "f02686afd99c59820dffa7b4c2627a0be1ad62980c98a9cd33b7564697842b22"},
{"source": "app.modules.jellyfin.jellyfin", "target": "requests", "kind": "raw_transport", "fingerprint": "5c46d09ca9a4bcc0bae21ca5d554ef09baa3f901c562b27c5f5ee1439c7746b5"},
{"source": "app.modules.rtorrent.rtorrent", "target": "http.client", "kind": "raw_transport", "fingerprint": "6adc93b3bc479dfe81197554c7977930a60abc51714f14ef29298eb40730aaf7"},
{"source": "app.modules.telegram.compat", "target": "urllib3", "kind": "raw_transport", "fingerprint": "18862bbdb252b59573f57ea776b5d64bfb775e7739603fecd23cc8f2c38a7e0d"},
{"source": "app.modules.zspace.zspace", "target": "requests", "kind": "raw_transport", "fingerprint": "9df3fd27b9696d45a72e7c8f67b5a9ad79a7371d1fe690bbaa17485bd1960d51"},
{"source": "app.startup.lifecycle", "target": "urllib3", "kind": "raw_transport", "fingerprint": "cb6f0a314aeb1e2d3e76c240aa20460ac0c36d9f5c18c1a6ea3170f64dd3366b"}
]
},
{
"classification": "approved_exception",
"reason_code": "daemon_control_plane",
"owner": "$source",
"reason": "runtime state 连接配置指定的 Docker daemon 控制面,并由该进程能力 owner 收口。",
"facts": [
{"source": "app.runtime.state", "target": "docker", "kind": "network_sdk", "fingerprint": "20a91ec521f7dfe6a0153dfd8ea49c4bac7f0a16b55f1c0655dfb33f54a01215"}
]
},
{
"classification": "approved_exception",
"reason_code": "test_network_guard",
"owner": "$source",
"reason": "测试守卫包装 getaddrinfo 以拒绝真实外联,不执行新的 DNS 解析策略。",
"facts": [
{"source": "app.testing.network_guard", "target": "socket.getaddrinfo", "kind": "protocol_operation", "fingerprint": "2518de211c9ba32ccbc004cf58fe9c98837fe8ac95fe8ffb6ea82897b28d753f"}
]
}
]
}
}