{ "_doc": "Drift allowlist for scripts/check_config_field_drift.py. Every entry MUST have a non-empty 'reason'. Two valid exemption categories: (1) nested-object serialization — payload assigns a data class instance as a value, Gson recursively serializes its property names as JSON keys, so the field name only appears in the source class definition, not in ApkConfigJsonFactory.kt; (2) legitimately dead payload — written by payload but runtime path uses a different channel (e.g. networkSecurityConfig.xml) so ShellConfig intentionally does not declare it; (3) preview-only fields injected by ShellPreviewLauncher that exported APKs never populate. If a key here becomes stale (neither side references it) the script warns.", "allowlist": [ {"key": "schemaVersion", "reason": "Payload metadata written by toShellPayload header; ShellConfig does not version-track, runtime ignores it."}, {"key": "networkTrustConfig", "reason": "Dead payload subtree — ShellConfig never reads it. Real runtime paths: (1) source-project export writes res/xml/network_security_config.xml via NetworkSecurityConfigBuilder; (2) built APK embeds custom CA DERs at assets/dkc_custom_ca/ (written by ApkBuilder), consumed at runtime by CustomCaTrustStore, NOT via JSON."}, {"key": "trustSystemCa", "reason": "Dead payload subtree — see networkTrustConfig."}, {"key": "trustUserCa", "reason": "Dead payload subtree — see networkTrustConfig."}, {"key": "customCaCertificates", "reason": "Dead payload subtree — see networkTrustConfig; the cert bytes themselves ride assets/dkc_custom_ca/, not this JSON."}, {"key": "cleartextTrafficPermitted", "reason": "Dead payload subtree — see networkTrustConfig; built APK cleartext is governed by the shell manifest's usesCleartextTraffic, not this JSON."}, {"key": "displayName", "reason": "Nested object field of CustomCaCertificate, serialized via customCaCertificates.map{...} in networkTrustConfigPayload. Dead payload subtree (see networkTrustConfig)."}, {"key": "sha256", "reason": "Nested object field of CustomCaCertificate, serialized via customCaCertificates.map{...} in networkTrustConfigPayload. Dead payload subtree (see networkTrustConfig)."}, {"key": "siteDirName", "reason": "ShellConfig field present for runtime session isolation; export payload never emits it (preview-only)."}, {"key": "siteId", "reason": "ShellConfig field present for runtime session isolation; export payload never emits it (preview-only)."}, {"key": "previewMediaPath", "reason": "ShellConfig host-preview-only field: absolute host media path for IMAGE/VIDEO multi-web sites in host-run preview; export payload never emits it (like siteId/siteDirName)."}, {"key": "textColor", "reason": "Nested object field of LrcTheme; serialized via bgm.lrcTheme in BgmBlock → ShellConfig.bgmLrcTheme: LrcShellTheme."}, {"key": "highlightColor", "reason": "Nested object field of LrcTheme; see textColor."}, {"key": "fontSize", "reason": "Nested object field of LrcTheme; see textColor."}, {"key": "animationType", "reason": "Nested object field of LrcTheme; see textColor."}, {"key": "position", "reason": "Nested object field of LrcTheme; see textColor."}, {"key": "backgroundColor", "reason": "Nested object field of LrcTheme; see textColor. (Note: also collides with GalleryBlock.backgroundColor which IS in payload — collision is harmless.)"}, {"key": "coverAssetPath", "reason": "Nested object field of BgmItem; serialized via bgm.playlist: List → ShellConfig.bgmPlaylist: List."}, {"key": "lrcAssetPath", "reason": "Nested object field of BgmItem; see coverAssetPath."}, {"key": "assetPath", "reason": "Nested object field of GalleryItem; serialized via gallery.items: List → ShellConfig.galleryConfig.items: List."}, {"key": "duration", "reason": "Nested object field of GalleryItem; see assetPath."}, {"key": "thumbnailPath", "reason": "Nested object field of GalleryItem; see assetPath."}, {"key": "autoHide", "reason": "Nested object field of EmbeddedExtensionModuleUiConfig; serialized via embeddedExtensionModules[].uiConfig in EmbeddedExtensionModule.toPayload."}, {"key": "autoHideDelay", "reason": "Nested object field of EmbeddedExtensionModuleUiConfig; see autoHide."}, {"key": "initiallyHidden", "reason": "Nested object field of EmbeddedExtensionModuleUiConfig; see autoHide."}, {"key": "showOnlyOnMatch", "reason": "Nested object field of EmbeddedExtensionModuleUiConfig; see autoHide."}, {"key": "pattern", "reason": "Nested object field of EmbeddedUrlMatchRule; serialized via embeddedExtensionModules[].urlMatches in EmbeddedExtensionModule.toPayload."}, {"key": "isRegex", "reason": "Nested object field of EmbeddedUrlMatchRule; see pattern."}, {"key": "exclude", "reason": "Nested object field of EmbeddedUrlMatchRule; see pattern."}, {"key": "keepCpuAwake", "reason": "Nested object field of BackgroundRunConfig; payload returns the whole object via backgroundRunConfigPayload(): BackgroundRunConfig? → ShellConfig.backgroundRunConfig: BackgroundRunShellConfig?."}, {"key": "provider", "reason": "Nested object field of DnsApkConfig; payload assigns the whole object via \"dnsConfig\" to dns.config, Gson serializes DnsApkConfig.provider as JSON key → ShellConfig.dnsConfig: DnsShellConfig.provider."}, {"key": "customDohUrl", "reason": "Nested object field of DnsApkConfig; see provider."}, {"key": "dohMode", "reason": "Nested object field of DnsApkConfig; see provider."}, {"key": "bypassSystemDns", "reason": "Nested object field of DnsApkConfig; see provider."}, {"key": "echEnabled", "reason": "Nested object field of DnsApkConfig; see provider."}, {"key": "announcementAnimationEnabled", "reason": "Shell-internal default (true) for announcement dialog animation; no editor surface in WebApp/AnnouncementBlock, intentionally never flows from export."}, {"key": "announcementShowEmoji", "reason": "Shell-internal default (true) for announcement dialog emoji display; no editor surface in WebApp/AnnouncementBlock, intentionally never flows from export."}, {"key": "url", "reason": "Nested object field of MultiWebSiteShellConfig; serialized via multiWeb.sites: List → ShellConfig.multiWebConfig.sites. Collides with top-level targetUrl but lives at different JSON path."}, {"key": "faviconUrl", "reason": "Nested object field of MultiWebSiteShellConfig; see url."}, {"key": "iconEmoji", "reason": "Nested object field of MultiWebSiteShellConfig; see url."}, {"key": "themeColor", "reason": "Nested object field of MultiWebSiteShellConfig; see url."}, {"key": "cssSelector", "reason": "Nested object field of MultiWebSiteShellConfig; see url."}, {"key": "linkSelector", "reason": "Nested object field of MultiWebSiteShellConfig; see url."}, {"key": "localFilePath", "reason": "Nested object field of MultiWebSiteShellConfig; see url."}, {"key": "siteProjectId", "reason": "Nested object field of MultiWebSiteShellConfig; see url."}, {"key": "siteShellConfig", "reason": "Nested object field of MultiWebSiteShellConfig (recursive ShellConfig?); see url."}, {"key": "sortIndex", "reason": "Nested object field of MultiWebSiteShellConfig; see url."}, {"key": "sourceAppId", "reason": "Nested object field of MultiWebSiteShellConfig; see url."}, {"key": "sourceProjectId", "reason": "Nested object field of MultiWebSiteShellConfig; see url."} ] }