Update shared Gaia workflows and Sargo development tooling

Fix camera switching and Contacts/SMS activity routing across shared hosts.
Integrate Marketplace installation and native standalone recovery tools,
Bluetooth runtime packages and trusted certificates.

Update English/French READMEs and the shared changelog with tested scope
and remaining radio/audio/Bluetooth limitations. Preview17 remains the
existing APK; no new native image is released.

Validation: shared JavaScript and native Python tests; Android packaging
and payload parity from an isolated publication checkout.
This commit is contained in:
OverSu 2026-10-08 14:27:17 +02:00
commit 0041cd9660
101 changed files with 3883 additions and 335 deletions

View file

@ -0,0 +1,82 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: MPL-2.0
"""Stage pinned package payloads missing from the original ARM64 reference."""
import hashlib
import io
import json
from pathlib import Path
import shutil
import subprocess
import tarfile
import tempfile
import urllib.request
PACKAGES = (
('libdw1t64_0.196-1_arm64.deb', 'e/elfutils', 'a82634454de2b28d73374f693e4ab6c1c2634fa53b0139312c5f439c294dad2b'),
('libelf1t64_0.196-1_arm64.deb', 'e/elfutils', 'ead8a1244824d982ce51fb82be4904312d5dc44ddc157e589def58c257738476'),
('bluez_5.87-4_arm64.deb', 'b/bluez', 'fe733034dbdfa6146fc94112ad8ca0fce71d8e01d22a59ddb49ef2df3777d6b5'),
('ca-certificates_20260816_all.deb', 'c/ca-certificates', '1cb8b73c74c47677b329fad4095fb9370227d4b8f1969372411478a4586c46cf'),
)
# Existing libelf 0.194-4 files in the inventoried runtime; reject other replacements.
REPLACES = {'usr/lib/aarch64-linux-gnu/libelf-0.194.so': 'ade23632ea253cb4ecfe95d5436bfeb3d40ae2003c5fe10bf1ac1c5b30bdf2e2', 'usr/share/doc/libelf1t64/changelog.Debian.gz': 'ffb0ea69fdbf6f32053059985048676931fd7d5c4458f8ca4bc54750cf4b1b31', 'usr/share/doc/libelf1t64/changelog.gz': '2e8e0af5c39ab744ac6934fe07419b5fd5504a50cd2f42110dd04315c548a708', 'usr/share/doc/libelf1t64/copyright': '2409860c86675ab33f8ad22480608faf849cbc2559d6478f708c23c508a1dbf2', 'usr/share/locale/de/LC_MESSAGES/elfutils.mo': 'f72328e130e63f231acb8e1a56ce5f4f3e91d0fc290db95d7ba4e4b2448d4d93', 'usr/share/locale/en@boldquot/LC_MESSAGES/elfutils.mo': '90158a24e3f85aaacc64085ef2644ba19075cb847c754341c9f245aaa69e94c6', 'usr/share/locale/en@quot/LC_MESSAGES/elfutils.mo': '33c6cda39c2145463dfdb2eb849922dbf6ccf51a9e4bfa8fd757744712d9abfa', 'usr/share/locale/es/LC_MESSAGES/elfutils.mo': '1ebff7e5583759b3f08eb5caaf18dd1a6ed6eb5ec71a02502ed8e21b134ad54f', 'usr/share/locale/ja/LC_MESSAGES/elfutils.mo': '764ed859f3aebd861da0b73c69da4d72d0f252952bb3be1c9c66360258a1661c', 'usr/share/locale/pl/LC_MESSAGES/elfutils.mo': '8abb000f43024994a9ec3032b52eb10858e004b81bc61c7ceea96f7467d13fdd', 'usr/share/locale/uk/LC_MESSAGES/elfutils.mo': 'ce0d747f478ee91a1cdef66bfd1e230a3ff1e787358f4c6e1ffb6513df713117'}
def stage(root, cache=None):
cache = cache or Path(__file__).resolve().parents[1]/'downloads/native-packages-20261008'
cache.mkdir(parents=True, exist_ok=True)
records = []
for name, directory, sha in PACKAGES:
url = 'https://deb.debian.org/debian/pool/main/'+directory+'/'+name
package = cache/name
if not package.exists():
with urllib.request.urlopen(url, timeout=60) as response:
data = response.read()
if hashlib.sha256(data).hexdigest() != sha:
raise ValueError('Package checksum mismatch: '+name)
package.write_bytes(data)
if hashlib.sha256(package.read_bytes()).hexdigest() != sha:
raise ValueError('Package checksum mismatch: '+name)
members = subprocess.check_output(['ar', 't', str(package)], text=True).splitlines()
member = next(m for m in members if m.startswith('data.tar'))
payload = subprocess.check_output(['ar', 'p', str(package), member])
with tempfile.TemporaryDirectory() as folder:
source = Path(folder)
with tarfile.open(fileobj=io.BytesIO(payload)) as archive:
archive.extractall(source, filter='data')
if name.startswith('ca-certificates'):
certificates = sorted((source/'usr/share/ca-certificates/mozilla').glob('*.crt'))
if len(certificates) < 50:
raise ValueError('Incomplete CA bundle')
target = root/'etc/ssl/certs/ca-certificates.crt'
target.parent.mkdir(parents=True, exist_ok=True)
target.write_bytes(b'\n'.join(p.read_bytes() for p in certificates)+b'\n')
target.chmod(0o644)
cert_link = root/'usr/lib/ssl/cert.pem'
cert_link.parent.mkdir(parents=True, exist_ok=True)
if not cert_link.exists() and not cert_link.is_symlink():
cert_link.symlink_to('../../../etc/ssl/certs/ca-certificates.crt')
selected = [source/'usr/share/doc/ca-certificates/copyright']
else:
selected = [p for p in (source/'usr').rglob('*') if p.is_file() or p.is_symlink()]
for path in selected:
target = root/path.relative_to(source)
target.parent.mkdir(parents=True, exist_ok=True)
if path.is_symlink():
if target.exists() or target.is_symlink():
if not target.is_symlink() or target.readlink() != path.readlink():
raise ValueError('Conflicting package link: '+str(target))
else:
target.symlink_to(path.readlink())
else:
if target.exists() and target.read_bytes() != path.read_bytes():
expected = REPLACES.get(str(path.relative_to(source)))
if not expected or hashlib.sha256(target.read_bytes()).hexdigest() != expected:
raise ValueError('Conflicting package file: '+str(target))
shutil.copyfile(path, target)
target.chmod(path.stat().st_mode & 0o777)
records.append({'file': name, 'url': url, 'sha256': sha})
record = root/'usr/share/vulpes/runtime-packages.json'
record.parent.mkdir(parents=True, exist_ok=True)
record.write_text(json.dumps(records, indent=2)+'\n')
return records