diff --git a/nonos-data/trust/capsules/wallpaper.manifest.bin b/nonos-data/trust/capsules/wallpaper.manifest.bin
new file mode 100644
index 000000000..31cb54973
Binary files /dev/null and b/nonos-data/trust/capsules/wallpaper.manifest.bin differ
diff --git a/nonos-data/trust/capsules/wallpaper.nonos_id_cert.bin b/nonos-data/trust/capsules/wallpaper.nonos_id_cert.bin
new file mode 100644
index 000000000..995ac2f82
Binary files /dev/null and b/nonos-data/trust/capsules/wallpaper.nonos_id_cert.bin differ
diff --git a/nonos-data/trust/keys/wallpaper_publisher_ed25519.pub b/nonos-data/trust/keys/wallpaper_publisher_ed25519.pub
new file mode 100644
index 000000000..b17fa17e3
Binary files /dev/null and b/nonos-data/trust/keys/wallpaper_publisher_ed25519.pub differ
diff --git a/nonos-data/trust/keys/wallpaper_publisher_mldsa65.pub b/nonos-data/trust/keys/wallpaper_publisher_mldsa65.pub
new file mode 100644
index 000000000..8163e8368
Binary files /dev/null and b/nonos-data/trust/keys/wallpaper_publisher_mldsa65.pub differ
diff --git a/src/userspace/capsule_wallpaper/embed.rs b/src/userspace/capsule_wallpaper/embed.rs
index 672a01c4a..d1cf9f510 100644
--- a/src/userspace/capsule_wallpaper/embed.rs
+++ b/src/userspace/capsule_wallpaper/embed.rs
@@ -14,16 +14,26 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-// Compile-time embed of the userland wallpaper binary. The
-// userland crate must be built first (`make nonos-mk-wallpaper`)
-// or the kernel build with `nonos-capsule-wallpaper` will fail
-// at this `include_bytes!` with a clear file-not-found.
#[cfg(feature = "nonos-capsule-wallpaper")]
pub(crate) const WALLPAPER_ELF: &[u8] = include_bytes!(
"../../../userland/capsule_wallpaper/target/x86_64-nonos-user/release/wallpaper"
);
+#[cfg(feature = "nonos-capsule-wallpaper")]
+pub(crate) const WALLPAPER_NONOS_ID_CERT_BYTES: &[u8] =
+ include_bytes!("../../../nonos-data/trust/capsules/wallpaper.nonos_id_cert.bin");
+
+#[cfg(feature = "nonos-capsule-wallpaper")]
+pub(crate) const WALLPAPER_MANIFEST_BYTES: &[u8] =
+ include_bytes!("../../../nonos-data/trust/capsules/wallpaper.manifest.bin");
+
#[cfg(not(feature = "nonos-capsule-wallpaper"))]
pub(crate) const WALLPAPER_ELF: &[u8] = &[];
+#[cfg(not(feature = "nonos-capsule-wallpaper"))]
+pub(crate) const WALLPAPER_NONOS_ID_CERT_BYTES: &[u8] = &[];
+
+#[cfg(not(feature = "nonos-capsule-wallpaper"))]
+pub(crate) const WALLPAPER_MANIFEST_BYTES: &[u8] = &[];
+
pub(crate) const WALLPAPER_PATH: &str = "/capsules/wallpaper";
diff --git a/src/userspace/capsule_wallpaper/mod.rs b/src/userspace/capsule_wallpaper/mod.rs
index 0cbb58f32..3e9e583de 100644
--- a/src/userspace/capsule_wallpaper/mod.rs
+++ b/src/userspace/capsule_wallpaper/mod.rs
@@ -28,7 +28,9 @@ mod embed;
mod launch;
mod seed;
mod spawn;
+mod state;
pub use launch::launch;
pub use seed::seed;
pub use spawn::spawn_wallpaper_capsule;
+pub use state::shared_state;
diff --git a/src/userspace/capsule_wallpaper/spawn.rs b/src/userspace/capsule_wallpaper/spawn.rs
index 5f4072b91..a1c38a2ab 100644
--- a/src/userspace/capsule_wallpaper/spawn.rs
+++ b/src/userspace/capsule_wallpaper/spawn.rs
@@ -14,55 +14,44 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-use crate::kernel_core::process_spawn::capsule_spawn::SpawnError;
-
-#[cfg(not(feature = "nonos-production"))]
-use super::embed::WALLPAPER_ELF;
-#[cfg(not(feature = "nonos-production"))]
+use super::embed::{WALLPAPER_ELF, WALLPAPER_MANIFEST_BYTES, WALLPAPER_NONOS_ID_CERT_BYTES};
+use super::state;
use crate::capabilities::Capability;
-#[cfg(not(feature = "nonos-production"))]
-use crate::kernel_core::process_spawn::capsule_spawn::{self, CapsuleSpec};
+use crate::kernel_core::process_spawn::capsule_spawn::{self, CapsuleSpecVerified};
+use crate::security::nonos_id_cert::IdCertVerifyError;
+use crate::security::nonos_trust_anchor::{
+ decode as decode_trust_anchor, BAKED_TRUST_ANCHOR_POLICY,
+};
-#[cfg(not(feature = "nonos-production"))]
-const SERVICE_NAME: &str = "display";
-#[cfg(not(feature = "nonos-production"))]
-const SERVICE_PORT: u32 = 4300;
-#[cfg(not(feature = "nonos-production"))]
-const REPLY_INBOX: &str = "endpoint.display.reply";
-#[cfg(not(feature = "nonos-production"))]
-const REPLY_PORT: u32 = 4301;
+pub use crate::kernel_core::process_spawn::capsule_spawn::SpawnError;
-#[cfg(feature = "nonos-production")]
-pub fn spawn_wallpaper_capsule() -> Result<(), SpawnError> {
- Err(SpawnError::FeatureDisabled)
-}
+const SERVICE_NAME: &str = "wallpaper";
+const SERVICE_PORT: u32 = 4340;
+const REPLY_INBOX: &str = "endpoint.wallpaper.reply";
+const REPLY_PORT: u32 = 4341;
+const TARGET_TRIPLE: &str = "x86_64-nonos-user";
-#[cfg(not(feature = "nonos-production"))]
pub fn spawn_wallpaper_capsule() -> Result<(), SpawnError> {
- if WALLPAPER_ELF.is_empty() {
- return Err(SpawnError::FeatureDisabled);
- }
- let mut caps_bits = 0u64;
- for cap in [
- Capability::CoreExec,
- Capability::Memory,
- Capability::Debug,
- Capability::GraphicsDisplayQuery,
- Capability::GraphicsSurfaceCreate,
- Capability::GraphicsSurfaceMap,
- Capability::GraphicsPresent,
- ] {
- caps_bits |= cap.bit();
- }
- let spec = CapsuleSpec {
+ let trust_anchor = decode_trust_anchor(BAKED_TRUST_ANCHOR_POLICY)
+ .map_err(|_| SpawnError::NonosIdCertRejected(IdCertVerifyError::TrustAnchorPolicy))?;
+ let spec = CapsuleSpecVerified {
name: SERVICE_NAME,
service_port: SERVICE_PORT,
reply_inbox: REPLY_INBOX,
reply_port: REPLY_PORT,
elf: WALLPAPER_ELF,
- caps_bits,
+ nonos_id_cert_bytes: WALLPAPER_NONOS_ID_CERT_BYTES,
+ manifest_bytes: WALLPAPER_MANIFEST_BYTES,
+ target_triple: TARGET_TRIPLE,
+ requested_caps: Capability::CoreExec.bit()
+ | Capability::IPC.bit()
+ | Capability::Memory.bit()
+ | Capability::Debug.bit()
+ | Capability::GraphicsDisplayQuery.bit()
+ | Capability::GraphicsSurfaceCreate.bit(),
debug_tag: b"[WALLPAPER-DEBUG] load_elf_executable error:",
};
- let _ = capsule_spawn::spawn(&spec)?;
+ let pid = capsule_spawn::spawn_verified(&spec, &trust_anchor, None)?;
+ state::set_alive(pid);
Ok(())
}
diff --git a/src/userspace/capsule_wallpaper/state.rs b/src/userspace/capsule_wallpaper/state.rs
new file mode 100644
index 000000000..f18bb639b
--- /dev/null
+++ b/src/userspace/capsule_wallpaper/state.rs
@@ -0,0 +1,27 @@
+// NONOS Operating System
+// Copyright (C) 2026 NONOS Contributors
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+use crate::services::lifecycle::CapsuleState;
+
+static STATE: CapsuleState = CapsuleState::new();
+
+pub(super) fn set_alive(pid: u32) {
+ STATE.set_alive(pid);
+}
+
+pub fn shared_state() -> &'static CapsuleState {
+ &STATE
+}
diff --git a/src/userspace/init/entry.rs b/src/userspace/init/entry.rs
index 813ce7f37..b94b5a1e9 100644
--- a/src/userspace/init/entry.rs
+++ b/src/userspace/init/entry.rs
@@ -407,10 +407,10 @@ fn spawn_process_manager_capsule() {
fn spawn_wallpaper_capsule() {
use crate::userspace::capsule_wallpaper;
super::capsule_boot::boot(
- "DISPLAY",
- "display",
+ "WALLPAPER",
+ "wallpaper",
capsule_wallpaper::spawn_wallpaper_capsule,
- || Some("display"),
+ capsule_wallpaper::shared_state,
);
}