Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
remote_update.hpp
Go to the documentation of this file.
1#pragma once
2
3// Decide whether a remotely-fetched UX update may be applied. This is the pure,
4// fail-closed heart of the opt-in remote-update path (Apple-style signed
5// auto-update): the network layer downloads a pack, and this function decides
6// accept/reject from the bytes + policy alone — no I/O here. Every check is
7// fail-closed and the signature is the trust anchor (a hostile or MITM'd host still
8// cannot forge a signed pack).
9//
10// The remote lane carries UX ONLY (ui-script) — native/DSP delivery is a separate,
11// stricter path and must never ride this channel.
12
16
17#include <cstdint>
18#include <filesystem>
19#include <string>
20#include <vector>
21
22namespace pulp::format::reload {
23
33
39
46 const std::filesystem::path& pack_root, const SwapPackManifest& m,
47 const std::vector<std::uint8_t>& trusted_public_key,
48 std::uint64_t installed_pack_version, const view::CapabilitySet& host_granted,
49 bool srl_fresh, const SignedRevocationList* srl) {
50 // 1. Authenticity first — nothing else means anything without it.
51 if (auto v = verify_swap_pack(pack_root, m, trusted_public_key); !v.ok())
52 return {RemoteUpdateVerdict::RejectSignature, v.detail};
53
54 // 2. This channel carries UX only.
55 if (m.pack_type != SwapPackKind::UiScript)
57 "remote update channel accepts ui-script packs only"};
58
59 // 3. Revocation must be FRESH for a remote fetch (fail closed), then honored.
60 if (!srl_fresh || srl == nullptr)
62 "no fresh revocation list for this remote fetch"};
63 const std::string signer_fpr = srl_hex_encode(m.signer_public_key);
64 if (is_revoked(*srl, signer_fpr, /*artifact_hash=*/""))
65 return {RemoteUpdateVerdict::RejectRevoked, "signer key is revoked"};
66 for (const auto& f : m.files)
67 if (is_revoked(*srl, /*signer=*/"", f.sha256_hex))
68 return {RemoteUpdateVerdict::RejectRevoked, "artifact is revoked"};
69
70 // 4. No downgrades (a since-fixed-vulnerable version must not replace a newer one).
71 if (m.pack_version <= installed_pack_version)
73 "pack version " + std::to_string(m.pack_version) +
74 " does not exceed installed " + std::to_string(installed_pack_version)};
75
76 // 5. A pushed UX may not request more than the installed plugin was granted.
77 view::CapabilitySet requested;
78 if (!view::CapabilitySet::parse(m.declared_capabilities, requested))
80 "declared capabilities include an unknown token"};
85 if (requested.has(c) && !host_granted.has(c))
87 "pushed UX requests capability '" + std::string(view::capability_name(c)) +
88 "' the host did not grant"};
89 }
90
91 return {RemoteUpdateVerdict::Accept, ""};
92}
93
94} // namespace pulp::format::reload
A granted-capability set.
Definition reload_capabilities.hpp:74
static bool parse(const std::vector< std::string > &names, CapabilitySet &out)
Parse a declared-capability name list (from the signed manifest).
Definition reload_capabilities.hpp:117
bool has(ReloadCapability c) const
Definition reload_capabilities.hpp:86
Definition build_fingerprint.hpp:23
RemoteUpdateResult evaluate_remote_ux_update(const std::filesystem::path &pack_root, const SwapPackManifest &m, const std::vector< std::uint8_t > &trusted_public_key, std::uint64_t installed_pack_version, const view::CapabilitySet &host_granted, bool srl_fresh, const SignedRevocationList *srl)
Definition remote_update.hpp:45
bool is_revoked(const SignedRevocationList &srl, std::string_view signer_key_fpr, std::string_view artifact_hash)
True iff signer_key_fpr is a revoked signer OR artifact_hash is a revoked artifact in srl.
Definition revocation.hpp:286
SwapPackVerifyResult verify_swap_pack(const std::filesystem::path &root, const SwapPackManifest &manifest, const std::vector< std::uint8_t > &trusted_public_key)
Full fail-closed verify: signature FIRST (binds the file hashes without reading the files),...
Definition swap_pack.hpp:300
std::string srl_hex_encode(const std::vector< std::uint8_t > &bytes)
Encode bytes to lowercase hex.
Definition revocation.hpp:106
@ UiScript
Definition swap_pack.hpp:37
RemoteUpdateVerdict
Definition remote_update.hpp:24
@ RejectRevoked
signer key or artifact is on the revocation list
Definition remote_update.hpp:29
@ RejectSignature
bad signature or integrity (untrusted/tampered)
Definition remote_update.hpp:26
@ RejectKind
not a UX (ui-script) pack — wrong lane
Definition remote_update.hpp:27
@ RejectDowngrade
pack_version <= the installed version
Definition remote_update.hpp:30
@ RejectCapabilityEscalation
requests a capability the host did not grant
Definition remote_update.hpp:31
@ RejectStaleRevocation
no fresh revocation info for a remote fetch
Definition remote_update.hpp:28
@ Accept
Definition remote_update.hpp:25
std::string_view capability_name(ReloadCapability c)
Stable wire name for a capability (used in the SIGNED pack manifest + config).
Definition reload_capabilities.hpp:45
@ RuntimeImport
evaluate a runtime-imported JS bundle (dynamic code load)
Definition reload_capabilities.hpp:38
@ Clipboard
read/write the system clipboard
Definition reload_capabilities.hpp:34
@ Ai
AI-CLI bridge.
Definition reload_capabilities.hpp:37
@ Storage
persistent key/value + preset temp files
Definition reload_capabilities.hpp:36
@ Exec
shell exec/execAsync — ALSO compiled out unless the PULP_DEV_BRIDGE_EXEC CMake option is ON (release/...
Definition reload_capabilities.hpp:32
@ Filesystem
read arbitrary file paths (asset file loads, native dialogs)
Definition reload_capabilities.hpp:35
@ Network
outbound network (reserved; used by remote-UX-push, not the bridge today)
Definition reload_capabilities.hpp:39
Signed Revocation List (SRL) + namespaced monotonic epoch floor.
Definition remote_update.hpp:34
bool ok() const
Definition remote_update.hpp:37
RemoteUpdateVerdict verdict
Definition remote_update.hpp:35
std::string detail
Definition remote_update.hpp:36
A signed revocation list.
Definition revocation.hpp:54
Definition swap_pack.hpp:66
Sealed swap-pack manifest + per-file integrity.