node-app-build 6.4.3

Mini app developer CLI: scaffold, validate, package node-app-* Debian packages
//! GPG sidecar signing for `node-app package`.
//!
//! Apt.economy1.cloud's release flow validates app provenance from a
//! detached GPG signature over the app's `manifest.json`, written next
//! to the `.deb` itself (rather than baked into `dpkg-sig`). This lets
//! the publish pipeline verify the manifest without unpacking the deb,
//! and lets the manifest signature outlive the deb when assets are
//! re-packed for different architectures.
//!
//! Phase 4c of econ-v1/node#868 — restores sidecar signing that the
//! legacy 838-line `node-app package` had but that PR #874's bun-only
//! refactor dropped.

use anyhow::{bail, Context, Result};
use std::path::{Path, PathBuf};
use std::process::Command;

/// Run `gpg --detach-sign` over `manifest`, writing
/// `<out_dir>/node-app-<name>_<version>.manifest.json.sig`.
pub fn sign_sidecar(
    manifest: &Path,
    out_dir: &Path,
    name: &str,
    version: &str,
    gpg_key: &str,
) -> Result<PathBuf> {
    let sig_name = format!("node-app-{}_{}.manifest.json.sig", name, version);
    let sig_path = out_dir.join(&sig_name);

    // Remove any stale signature so gpg doesn't refuse with "file exists".
    let _ = std::fs::remove_file(&sig_path);

    println!("→ gpg --detach-sign (key {})", gpg_key);
    let status = Command::new("gpg")
        .args([
            "--batch",
            "--yes",
            "--quiet",
            "--default-key",
            gpg_key,
            "--detach-sign",
            "--output",
        ])
        .arg(&sig_path)
        .arg(manifest)
        .status()
        .with_context(|| {
            "failed to run `gpg` — is GPG installed? \
             (On macOS: `brew install gnupg`.)"
        })?;

    if !status.success() {
        bail!("`gpg --detach-sign` failed (exit: {})", status);
    }
    if !sig_path.exists() {
        bail!(
            "gpg reported success but the sidecar signature was not written: {}",
            sig_path.display()
        );
    }
    Ok(sig_path)
}