"""Validated release catalog and download content for the original website.""" import html import re from urllib.parse import urlsplit E = lambda value: html.escape(str(value), quote=True) FINGERPRINT = "2B1F01BC806C0B33CB6CEDDE52859CEBC91B8808" PROFILES = ( ("debian13-amd64-py313", "trixie", "Debian 13", "3.13"), ("ubuntu24.04-amd64-py312", "noble", "Ubuntu 24.04", "3.12"), ("mint22-amd64-py312", "mint22", "Linux Mint 22.x", "3.12"), ) VIDEO = "framebridge-preview-0.3.1-original-r4.mp4" POSTER = "framebridge-preview-0.3.1-original-r4.jpg" VIDEO_SHA256 = "b2a8b0b302063edbe05d84fb6dadb7f303a6f0f1b6d79dc151287df4671adc5b" POSTER_SHA256 = "2e867d4b6a22f81ecbefa293a88799b9e3c93f02aa7d1090c7f0a0dbfe44dc9f" def require(condition, message): if not condition: raise ValueError(message) def project_url(value, prefix=None): require(isinstance(value, str), "Artifact URL must be text") url = urlsplit(value) require(not url.query and not url.fragment and not url.username and not url.password, "Artifact URL must not contain credentials, a query or a fragment") require((not url.scheme and not url.netloc and url.path.startswith("/") and not value.startswith("//")) or (url.scheme == "https" and url.netloc == "framebridge.betancourt.one"), "Only canonical HTTPS or root-relative project URLs are allowed") require(".." not in url.path.split("/"), "Artifact URL path traversal") require(re.fullmatch(r"/[A-Za-z0-9/._+~:-]*",url.path), "Unsafe artifact URL characters") if prefix: require(url.path.startswith(prefix), "Unexpected artifact route") return value def asset(spec): require(isinstance(spec, dict), "Artifact metadata missing") require(re.fullmatch("[a-f0-9]{64}", spec.get("sha256", "")), "Exact artifact SHA-256 required") require(isinstance(spec.get("size_bytes"), int) and spec["size_bytes"] > 0, "Exact artifact size required") require(re.fullmatch("[A-Za-z0-9][A-Za-z0-9._+~-]*", spec.get("filename", "")), "Safe artifact filename required") project_url(spec.get("url", ""), "/downloads/") project_url(spec.get("signature_url", ""), "/downloads/") def validate(meta, ready): require(re.fullmatch(r"[0-9]+\.[0-9]+\.[0-9]+", meta.get("version", "")), "Release version must be numeric") require(meta.get("state") in ("preparing", "ready"), "Unknown release state") require(meta.get("site_url") == "https://framebridge.betancourt.one", "Canonical site origin required") require(meta.get("package_name") == "framebridge-original-expanded", "Unexpected binary package") require(meta.get("git_url") == "/git/gerardo/framebridge", "Use existing canonical Gitea repository") require(meta.get("git_clone_url") == "https://framebridge.betancourt.one/git/gerardo/framebridge.git", "Use existing canonical Gitea clone URL") expected = {x[0]: x[1:] for x in PROFILES} profiles = meta.get("profiles", []) require(isinstance(profiles, list) and len(profiles) == 3, "Exactly three profiles required") require(len({p.get("profile_id") for p in profiles}) == 3, "Duplicate profile") for profile in profiles: identity = profile.get("profile_id") require(identity in expected, "Unexpected profile") suite, label, python = expected[identity] require((profile.get("suite"), profile.get("label"), profile.get("python"), profile.get("architecture")) == (suite, label, python, "amd64"), "Profile identity does not match its tested distribution") if ready: asset(profile) if ready: require(meta.get("signing_fingerprint") == FINGERPRINT, "Unexpected official signing fingerprint") asset(meta.get("source")) deps = meta.get("dependency_sources", []) require(isinstance(deps, list) and len(deps) >= 2, "Dependency corresponding-source metadata required") for dependency in deps: asset(dependency) for key, prefix in (("signing_key_url", "/debian/"), ("checksums_url", "/downloads/"), ("checksums_signature_url", "/downloads/")): project_url(meta.get(key, ""), prefix) def code(text): return '
' + E(text) + '
' def apt_commands(meta, profile): require(meta.get("state") == "ready", "Do not offer installation commands for an unsigned preparation") validate(meta, True) key_url = meta["site_url"] + meta["signing_key_url"] if meta["signing_key_url"].startswith("/") else meta["signing_key_url"] return """sudo apt install ca-certificates curl gnupg ( set -eu key_file="$(mktemp)" trap 'rm -f "$key_file"' EXIT curl -fsSL '""" + key_url + """' -o "$key_file" key_info="$(gpg --batch --show-keys --with-colons "$key_file" 2>/dev/null)" actual="$(printf '%s\\n' "$key_info" | awk -F: '$1=="fpr" {print $10; exit}')" primary_count="$(printf '%s\\n' "$key_info" | awk -F: '$1=="pub" {n++} END {print n+0}')" test "$primary_count" -eq 1 test "$actual" = '""" + FINGERPRINT + """' sudo install -d -m 0755 /etc/apt/keyrings sudo install -m 0644 "$key_file" /etc/apt/keyrings/framebridge-archive-keyring.asc printf '%s\\n' \\ 'Types: deb' \\ 'URIs: https://framebridge.betancourt.one/debian/' \\ 'Suites: """ + profile["suite"] + """' \\ 'Components: main' \\ 'Architectures: amd64' \\ 'Signed-By: /etc/apt/keyrings/framebridge-archive-keyring.asc' \\ | sudo tee /etc/apt/sources.list.d/framebridge.sources >/dev/null sudo apt update sudo apt install framebridge-original-expanded )""" def download(meta): ready = meta["state"] == "ready" body = '
' body += '

FrameBridge helps one administrator manage their own home Linux network: inventory, services, storage, diagnostics, commands and persistent terminals. Desktop access is an auxiliary tool.

' body += '

Match the target computer

' + code("cat /etc/os-release\ndpkg --print-architecture\npython3 --version") body += '

The supported profiles below use amd64 and the distribution system Python. Select one matching suite for each computer.

' if not ready: body += '
Release preparation. Version ' + E(meta["version"]) + ' is being prepared. Download links and installation commands appear after the exact artifacts and signatures are verified.
' body += '
' for profile in meta["profiles"]: body += '

' + E(profile["label"]) + '

APT suite: ' + E(profile["suite"]) + '

' if ready: body += '

SHA-256: ' + E(profile["sha256"]) + '

' + E(profile["filename"]) + ' · ' + format(profile["size_bytes"], ",") + ' bytes

Install the signed APT channel' + code(apt_commands(meta, profile)) + '
' else: body += '

Version ' + E(meta["version"]) + ' · package and signature pending.

' body += '
' body += '
' if ready: body += '

Release verification and source

Expected signing-key fingerprint:

' + FINGERPRINT + '

SHA256SUMS · Checksum signature · Public key

Corresponding FrameBridge source · Source signature

SHA-256: ' + E(meta["source"]["sha256"]) + '

Third-party components retain their original licenses and notices. Unchanged dependency archives retain their historical filenames.

Normal updates

' + code("sudo apt update\napt-cache policy framebridge-original-expanded\nsudo apt install --only-upgrade framebridge-original-expanded\nfb status") body += '

APT verifies the repository signature and package hashes. Keep the selected distribution suite and its scoped Signed-By key.

' body += '

Connect and work

After installation, connect from the normal terminal on that computer:

' + code("fb connect\nfb status\nfb console") + '

One central installation can connect enrolled Linux nodes. Nodes use the central connection. Enter passwords and connection keys only in the normal local prompts.

Read the shared command guide · Browse the canonical source repository

' return body