Files
ODIAN_Launcher/crates/odian-packs/src/lib.rs
T
Kelorastus b7f3061be3 ODIAN Launcher: hub, installer, local stack and remembered sign-in (M2)
- Tauri 2 + Svelte 5 hub in ODIAN dark: patch notes and roadmap, install and
  update progress, local stack status, settings with DHP and MCP addresses.
- crates/odian-packs: Rust installer for pack format v1 (signed manifests,
  resumable verified downloads from a DHP or an ODIAN drive), byte-compatible
  with ODIAN_MCP_Server's Python odian_packs.
- Local stack on 127.0.0.1: Postgres -> Engine API -> tile server -> Odian.exe,
  one Job Object, clean shutdown; database snapshot restore on a fresh PC only.
- Keycloak sign-in through the DHP's MCP, remembered until Sign out with a
  launcher session that renews the Engine token silently.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-15 15:23:17 +02:00

74 lines
2.9 KiB
Rust

//! ODIAN packs, format v1: verify a signed version manifest and install that version from a
//! site's update service or from an ODIAN drive, checking every byte.
//!
//! A byte-for-byte compatible port of the Python installer (`odian_packs.fetch` in
//! ODIAN_MCP_Server; the format is its `src/odian_packs/README.md`). An install made by
//! either one is resumed and re-verified by the other: same layout, same progress files.
//!
//! ```text
//! dest/versions/<v>/manifest.json written LAST: its presence means "installed"
//! dest/versions/<v>/<app paths>
//! dest/data/db/<snapshot>/...
//! dest/data/src/<paths> + <path>.chunks.json while partial, <path>.ok when done
//! dest/data/tiles/<style>/<dataset>/<z>/<x>/<y><ext> + .blocks-done.json
//! ```
pub mod canonical;
pub mod error;
pub mod hashing;
pub mod manifest;
pub mod signing;
pub mod tiles;
mod copy;
mod install;
mod progress;
mod source;
mod tileblocks;
pub use canonical::canonical_bytes;
pub use error::{Error, IntegrityKind, Result};
pub use install::{
install, AppSummary, DbSummary, InstallOptions, SrcFileSummary, Summary, TileSetSummary,
};
pub use manifest::{safe_relpath, validate, Manifest, VerifiedManifest};
pub use progress::{Progress, Stage};
pub use source::Source;
use tokio_util::sync::CancellationToken;
/// The ODIAN release public key that ships with the launcher (`ed25519:<base64>`).
pub fn bundled_public_key() -> &'static str {
include_str!("../keys/odian-release.pub").trim()
}
/// The source's CURRENT version manifest: fetched, validated and signature-checked.
/// The raw bytes are kept ([`VerifiedManifest::raw`]) because the install writes them verbatim.
pub async fn current_manifest(source: &Source, public_key: &str) -> Result<VerifiedManifest> {
let backend = source::Backend::new(source)?;
let raw = backend.current_manifest(&CancellationToken::new()).await?;
VerifiedManifest::from_bytes(raw, public_key)
}
/// A specific version's manifest, verified, and checked to really be that version.
pub async fn version_manifest(source: &Source, version: &str, public_key: &str) -> Result<VerifiedManifest> {
let backend = source::Backend::new(source)?;
let raw = backend.version_manifest(version, &CancellationToken::new()).await?;
let verified = VerifiedManifest::from_bytes(raw, public_key)?;
if verified.version() != version {
return Err(Error::integrity(
IntegrityKind::Version,
format!("manifest for {version}"),
format!("asked for {version}, the signed manifest says {}", verified.version()),
));
}
Ok(verified)
}
/// A version's patch notes (Markdown). **Untrusted text**: not covered by the signature.
pub async fn fetch_notes(source: &Source, version: &str) -> Result<String> {
let backend = source::Backend::new(source)?;
let raw = backend.notes(version, &CancellationToken::new()).await?;
Ok(String::from_utf8_lossy(&raw).into_owned())
}