nativeapps

package module
v0.23.9 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 17, 2026 License: MIT Imports: 41 Imported by: 1

README

Floe Native Apps

A private graphical runtime for applications on your Linux host.

Prepare Xpra, a headless X server, and their native dependencies through one Go API. Keep applications on the host, with their own files, identity, and permissions.

Source checks CodeQL Go Reference

Get started · Integration · Platforms · Contributing · Security

What it does

Floe Native Apps supplies the optional native graphics layer behind a host application launcher. A server can start without a desktop environment or a monitor. The SDK acquires a pinned component set into a private directory, verifies it, and proves that it can render a window, receive input, and retain the same application across WebSocket viewer disconnects before making it available to the product.

  • Private installation: no root password, system package installation, global loader configuration, or changes to the host's software sources.
  • Verified acquisition: exact archive sizes and SHA-256 digests, bounded extraction, contained links, and atomic activation after a graphical check.
  • Recoverable preparation: observable progress, owner-scoped cancellation, idempotent requests, explicit interruption after restart, and offline delivery.
  • Native execution: the user's applications run directly on Linux. No production container or virtual machine sits between the application and host.

This is an embeddable preparation SDK. The consuming product supplies the app catalog, authorization, session lifecycle, viewer, and user interface. Redeven is one consumer.

flowchart LR
    Catalog["Pinned publisher archives"] --> Verify["Download & verify"]
    Offline["Offline ZIP"] --> Verify
    Verify --> Stage["Private staging directory"]
    Stage --> Check["Launch · pixels · input"]
    Check --> Ready["Atomic activation"]

Get started

Use Go 1.27.2, aligned with Redeven. Install the released module:

go get github.com/floegence/floe-native-apps@v0.5.0

Select a supported package and create one long-lived manager for an absolute, private state directory. Construction does not download or execute components. Start preparation only after the host product admits the user's action.

pkg, err := nativeapps.NativePackage()
if err != nil {
    return err // Unsupported hosts must not offer Linux preparation.
}
manager, err := nativeapps.New(stateRoot, pkg, nil)
if err != nil {
    return err
}
defer manager.Close()

// Derive owner from the authenticated session. Retain requestID across retries.
status, err := manager.Start(owner, requestID, "download", 0)
if err != nil {
    return err
}
_ = status // Observe progress with Watch and Snapshot until ready or failure.

Import the package as nativeapps "github.com/floegence/floe-native-apps". The compiling lifecycle example demonstrates subscription, terminal states, context cancellation, and tool resolution. In a service, keep the manager alive across HTTP requests; closing it cancels active preparation.

To try the standalone qualification tool on a Linux host:

go run ./cmd/floe-native-apps -state "$HOME/.local/share/floe-native-apps"

The command reports JSON progress, performs the real graphical check, and prints the installed directory when ready. It prepares components; it does not expose a remote desktop or launch a user's application.

Integration contract

Owner Responsibilities
This SDK Fixed catalog, downloads, verification, extraction, private support environment, durable preparation, graphical self-check
Host product User admission, authentication, state-directory ownership, application metadata, private display/session, application launch, viewer and window lifetime
Operating system Process identity, filesystem permissions, network policy, executable mounts, and security policy

Observe current state. Watch provides coalesced invalidations, not an event log. Subscribe, read Snapshot(owner), and read it again after each notification. Unsubscribing or losing an observer does not cancel preparation. state reports one preparation operation; installed.ready independently reports the current usable installation. Directory continues resolving it during an update and after failure, cancellation or interruption. Retry requires an explicit user action. No partial installation is activated.

Update components independently. SDK upgrades continue accepting published r1 and r2 installations for the matching architecture and private Xpra 6 contract. update_available compares the active installation with the reviewed recommendation; it does not disable the installed feature. The v1 operation record is migrated atomically to v2 with an explicit installed identity. Unknown records are rejected without rewriting them, and damaged installations retain a distinct diagnostic. Package digests and existing package trees are unchanged. The r1 recipe retains its known short-frame decoder defect; compatibility does not claim that old bytes contain the r2 fix. Offer the r2 update to improve connection stability. Do not prepare components merely because a status was read.

Keep running applications on their original components. Persist the selected installed.digest with a new backend and use DirectoryFor when recovering it. InstallationForProcess can identify a legacy private loader from a verified Linux process generation; the host must still verify application ownership and backend identity. Updates retain previous package directories and change the selection only after the target passes graphical qualification. There is no automatic installed-package garbage collection.

Transfer only missing archives. After explicit user action, Plan(ctx) verifies the host cache and reports the target digest and missing original archive identities/bytes. Complete caches use Start(..., "cache", 0) with no network or upload. Otherwise the host downloads missing files, or Desktop uses WriteTransferBundle with its own trusted matching catalog. Plans cannot select URLs, paths or unrecognized artifacts. An old Desktop must report a target mismatch rather than silently substituting its package. The receiver verifies the union of cached and uploaded files; stale plans fail without changing the installed selection. Complete offline ZIPs remain supported.

Preserve request identity. Retry an uncertain Start response with the same owner, request ID, source, and upload size. A competing operation returns ErrBusy. Only the authenticated operation owner may upload or cancel. The consumer must authorize reads and writes before calling the SDK; an owner string is an identity binding, not an authentication mechanism.

Keep support libraries out of host applications. Use the complete toolset from ResolveTools and Tools.Environment for support processes. Before a GIO launch, restore the saved FLOE_NATIVE_APPLICATION_ENV map onto the application's launch context and remove that variable and FLOE_NATIVE_ROOT. Retain the session's private display and D-Bus addresses. Never export the private loader path to user applications or substitute the support Python for their interpreter.

Keep the trust boundary closed. Use the checked-in catalog selected through NativePackage or ForPlatform. Do not accept executable paths, artifact URLs, hashes as acquisition specifications, or custom catalogs from renderer/client input. Transfer plan identities may only select a subset of the matching compiled catalog. Pass nil as the validator to retain the built-in graphical check. A custom validator is a trusted host integration hook, not a client option.

Disable unused audio completely. Append XpraNoAudioArgs() when starting a silent Xpra 6.x graphics session. It disables the audio subsystem, PulseAudio, speaker, and microphone support. --speaker=off and --microphone=off only start muted; they still initialize audio codecs and can make every window inventory query wait five seconds when an audio backend is unavailable. The graphical self-check uses the same options and requires two inventory queries to complete within three seconds each, in addition to proving decoded pixels and input. Consumers retain their own authentication, private display, process lifetime, transport, and actual-window readiness checks.

Combined Wayland and Xwayland applications

Use DesktopForPlatform with the same component Manager to prepare the combined recipe. Manager.PlanDesktop resolves an authorized desktop entry and binds its bytes, executable and package revision. PrepareDesktopSession creates a new, private immutable resource snapshot and returns the persistent helper command and authenticated endpoint. Launch it independently of viewer and Runtime cancellation, retaining its process generation and component identity.

DialDesktop supplies bounded window, PNG frame, cursor, clipboard and lifecycle events. Decode and paint before frame_ack; bind input to that connection, window and geometry generation. Client input controllers own composition and pointer gestures. The helper owns native delivery and ordering. An unavailable context is an explicit failure; no text is replayed or sent through another route. Waiting for a window and unavailable capture never imply application exit. Closing the attachment retains the application; terminate_application requires explicit force-quit authorization.

The private software compositor supports Wayland and Xwayland windows, menus, popups and remote file dialogs. Native DEB/RPM and AppImage applications retain their installed runtime. Strict/classic Snap and Flatpak retain their actual sandbox and require their installed package services. Snap scope requests reach only the real user systemd through an instance-bound adapter; Flatpak document authorization uses the official host document portal. Missing services fail clearly without installing packages, changing security policy or exposing the host desktop bus. Applications redirected to external existing processes are not adopted, and preparation never creates a replacement user profile.

Native qualification includes Snap Firefox, Flatpak GTK/Qt, GNOME Text Editor, AppImage, RPM and pure Wayland GTK/Qt/Chromium application receipts. GNOME Xorg/Wayland, KDE Wayland and Xfce X11 fixtures establish desktop compatibility, not physical GPU certification or support for every application. Exact-tag release qualification must pass on native amd64 and arm64. See CONTRIBUTING.md for the contracts and evidence boundaries. Existing Xpra instances retain their original component and resource snapshot; there is no automatic backend retry or conversion of a running application.

Offline delivery

Hosts that supply another reviewed archive catalog can use the public github.com/floegence/floe-native-apps/artifactcache package. This is the same acquisition implementation used by native component preparation and offline bundles. It downloads original publisher bytes without extracting or executing them, independently of the downloading machine's OS and architecture. A trusted catalog may include reviewed HTTPS mirrors; when archives are missing, the acquirer probes representative entries, uses the fastest validated source, and falls back through the catalog order without changing the pinned digest.

result, err := artifactcache.Acquire(ctx, privateCacheDirectory, artifactcache.Spec{
    URL: pinnedPublisherURL,
    SHA256: pinnedSHA256,
    SizeBytes: pinnedSize,
}, artifactcache.Options{
    OnProgress: func(p artifactcache.Progress) error {
        // Absolute byte counts; checking, downloading, or verifying.
        return report(p)
    },
})
// Use result.Path only after success. result.FromCache identifies a verified hit.

The host chooses the catalog, absolute private cache directory and user consent before calling Acquire; renderer-supplied URLs, digests and paths are not a trusted catalog. Cache filenames are exact SHA-256 digests. Every reuse checks length and digest without network access. Verify validates an existing regular file without modifying it; integrity errors match artifactcache.ErrIntegrity, while cancellation and filesystem errors retain their normal classifications. HTTP redirects cannot downgrade HTTPS. Invalid or incomplete downloads never replace a cache entry. Concurrent acquisitions serialize through an OS-backed cache lease, recheck verified files after waiting, and release ownership on cancellation or process exit. The returned path from Acquire must not race with maintenance. Consumers that read archives while maintenance is enabled use OpenSession, then its Acquire, Verify, and Path methods, retaining the session until the last read.

Session.Prune and standalone Maintain accept an opt-in artifactcache.Policy with MaxIdleAge and MaxBytes. Zero disables each limit. Maintenance first removes expired archives, then evicts the least recently used archives to meet the byte budget. Successful acquisition or Session.Touch refreshes file mtime; existing files use their original mtime without an index migration. Only recognized regular archive and abandoned download files are removed. Symlinks, unknown files, subdirectories and the stable lease file are preserved. Maintain can return ErrBusy immediately instead of waiting for active readers.

WriteBundleWithOptions and WriteTransferBundleWithOptions retain this lease through ZIP creation. BundleOptions supplies optional retention and structured progress: waiting, checking, downloading and packing. Cache/download totals remain absent until inspection completes; downloaded bytes count only network reads. Maintenance runs after packing or failure; its separate callback reports cleanup errors without replacing the acquisition result. Existing bundle methods delegate to the same path without enabling archive eviction. Products own consent, private placement, policy values and localized presentation. This API grants neither permission to install nor to execute an archive.

Acquire original publisher archives on Linux, macOS, or Windows for a Linux target. Acquisition does not execute those components on the downloading machine.

go run ./cmd/floe-native-apps \
  -arch arm64 \
  -state /absolute/private/cache \
  -bundle /absolute/native-arm64.zip

On the receiving host:

  1. Call Start(owner, requestID, "upload", actualZIPSize).
  2. Send ordered chunks of at most 256 KiB through WriteChunk using the returned operation ID. An identical replay is accepted; gaps and conflicting replays are rejected. Resume an interrupted connection from ReceivedBytes.
  3. Call CompleteUpload. The host verifies every original archive and performs the same installation and graphical qualification as a direct download.

A process restart reports an interrupted operation and discards incomplete staging; begin a new admitted operation. An already activated package remains available. Redistributing the ZIP carries the components' license obligations.

Platforms and requirements

Capability Platforms
Install and execute native graphics Linux amd64, Linux arm64; glibc and musl hosts
Acquire an offline ZIP Linux, macOS, Windows; portable CLI builds checked for amd64 and arm64
macOS application capture and control Owned by the consuming product's macOS integration

The pinned stack uses Alpine 3.23 packages, Xpra 6.2.2, and Xpra HTML5 v20. Each architecture includes its own musl loader and library closure. It does not replace the host's libc. Applications still use their own installed dependencies.

The host needs an executable writable state filesystem, a compatible Linux kernel, /bin/sh and basic shell utilities, ordinary process/Unix socket permissions, and access to the catalog's HTTPS publishers (or an offline ZIP). A physical monitor, desktop session, GPU, and system Xpra installation are not required. The Xpra recipe supports X11; the combined desktop recipe supports Wayland and Xwayland in one private application session. GPU/DRM capture and arbitrary third-party application compatibility are outside this SDK's guarantee. SELinux, AppArmor, and other host policies remain in force; a denied operation fails without changing policy or escalating privileges.

Qualification evidence

The component set shipped since v0.1.2 passed GIO application launch, a live private D-Bus connection, window discovery, decoded pixels, and input delivery:

Environment Architecture Evidence scope
Ubuntu 22.04; Debian 11 arm64; amd64 respectively Native hosts
Debian 13; Alpine 3.23 amd64 and arm64 Clean unprivileged userspace fixtures
Arch Linux; Rocky Linux 9; AlmaLinux 9; RHEL UBI 9 amd64 Clean unprivileged userspace fixtures

RHEL UBI qualifies the userspace image, not a subscribed RHEL host, its kernel, or every SELinux policy. The release qualification workflow repeats fresh installation on native GitHub Linux runners for both architectures and runs the clean distribution fixtures. Its logs record the actual images and results. Containers are test fixtures only.

Development and maintenance

./scripts/check.sh
# Network-backed security checks, also scheduled and required for releases:
go tool govulncheck ./...
go tool govulncheck golang.org/x/vuln/cmd/govulncheck github.com/rhysd/actionlint/cmd/actionlint

The source gate checks formatting, module tidiness and checksums, vet, race tests, workflow syntax, Python/shell syntax, and six portable build targets. Tests cover malicious archives, integrity, ownership, idempotency, cancellation, restart, persistence failure, and activation. The runtime uses the Go standard library; go.mod and go.sum additionally pin maintained development tools and their transitive dependencies. Native archive integrity is separately pinned in catalog.json.

CodeQL scans Go, Python, and GitHub Actions daily and on demand with extended security queries. Dependency vulnerability checks run daily and before release. Dependabot proposes weekly dependency and action updates; updates require review and passing checks. See CONTRIBUTING.md for release criteria, platform qualification, catalog changes, and commit attribution.

License and security

The Go SDK, installer, and repository code are MIT-licensed. Downloaded components retain their original licenses; each catalog entry records its publisher URL, SHA-256, license, and source location. This repository releases source and a catalog, not a combined third-party binary distribution. If you redistribute archives or an installed stack, satisfy the relevant licenses, including applicable source availability obligations. Retained original license files and catalog metadata are evidence, not a substitute for those obligations.

Report vulnerabilities through GitHub's private reporting form. See SECURITY.md for the security boundary and supported versions.

Application lifetime primitives

WriteApplicationLauncher supplies a Linux GIO launcher that restores the host application environment and observes the launched process tree, including adopted descendants. Invoke it using the native tools’ Python with the selected absolute desktop-entry path and a private receipt path. The atomic receipt reports running, exited, or failed; running does not imply a window or decoded pixels. XpraApplicationLifetimeArgs keeps the display alive until that monitored child exits, independently of viewer detachment or window count.

ObserveProcess and ProcessIdentity.Alive distinguish one Linux process generation from a reused PID across host restarts. This is observation, not authorization or permission to signal a persisted PID. A consumer recovering a backend must also verify its private endpoint identity. Consumers continue to own application inventory, authorization, instance persistence, sharing connections, resource limits and explicit termination policy. These primitives do not create a background service or recover applications whose display server was destroyed.

Client-owned input

Input protocol version 1 gives the client sole ownership of composition and candidate selection. The host has no composition engine or candidate window. It delivers keys through Xpra and confirmed Unicode through the application's toolkit context or the commit-only xcb-imdkit bridge, without clipboard injection.

Probe the interpreter owning Xpra with ProbeClientInput. Managed tools expose Tools.Python; SystemClientInputPython resolves a supported installed script's interpreter. Both use the same launcher and scheduler. The current contract requires the Xpra 6 server API, GIO and xcb-imdkit/xcb libraries; managed r3 supplies that closure. Existing r1/r2 installations remain identifiable for surviving apps but do not acquire this capability merely by upgrading the SDK. The same aggregate server adapter is qualified with managed Xpra 6.2.2 and system Xpra 6.5.3; it does not depend on their different internal input mixins.

PrepareClientInput installs adapters in a new private session directory. Run its Launcher with that interpreter, normal Xpra arguments and XpraArgs. Start the private application bus first and pass its address explicitly to the application environment. The bridge starts before applications. These input settings are confined to that session; host desktop IBus/Fcitx and global input sources are untouched. GTK3 and GTK4 adapters require glibc 2.31 or later (GTK4 4.0 or later); Qt5 requires 5.15 or later, and Qt6 requires 6.4 with glibc 2.36 or later. Other XIM-aware apps use the protocol bridge with a UTF-8 locale; non-Unicode XIM contexts are rejected before delivery. Incompatible/private toolkit loaders are not claimed as supported adapters. GTK4 modules use a private, ABI-specific GTK_PATH; GTK3 retains its module cache. No GTK4 library is injected into GTK3 or generic GIO processes.

PrepareInputClient prepares Xpra HTML5 v20/v21 with external input ownership. The bootstrap window.floeXpraInput.version is 2, independently of the unchanged version 1 text and pointer protocols. It identifies the prepared focus contract and GTK4-capable release. Consumers must reject older prepared sessions before creating input controllers; preserve their processes and ask users to save, quit and reopen. Reconnecting alone does not replace a running application's assets. The host obtains the client with window.floeXpraInput.getClient() and uses client.floeInput. bindTarget(wid) returns an immutable connection/window token; sendKey, commitText, release, clipboard and paste consume it. Wire these to the published floe-webapp remote-input controller and attach paste to its textarea. The host owns permissions, first-frame gating, labels, keyboard controls and errors. The adapter registers no DOM input. Xpra's old keyboard/tablet/virtual keyboard listeners and focus-stealing clipboard handlers are removed; graphics, windows, pointer and clipboard transport stay with Xpra.

OpenClientAssets(preparedDirectory) creates an immutable public-resource snapshot of that prepared client. It precompresses assets, supplies a digest of their exact names and bytes, and implements http.Handler for resource paths such as /js/Client.js. Mount it behind host authorization at a stable path containing assets.Digest(), stripping that prefix before serving. Use assets.RewriteHTML(document, "/client/"+assets.Digest()+"/") on each uncached, authenticated session document. Resources can then be reused across session URLs; the original graphics and protocol workers resolve their imports from the same resource version. Source directories and installed vendor files remain unchanged.

Only recognized public scripts, styles, images and fonts are included. HTML, configuration, credentials and session data are never served by this handler. The version includes the prepared input adapter and worker changes, not only the native package identity. Successful GET/HEAD responses use private immutable caching, representation-specific ETags and negotiated gzip; errors are uncached. Hosts own snapshot lifetime, permission checks and exact digest routing. A cached script grants no authority to view or control an application. Normal HTTPS/client trust and browser capability checks still govern video decoding; resource caching does not enable secure-context capabilities over an insecure connection.

Both authenticated hellos advertise floe-input: 1. Old clients cannot enter this input flow. Old sessions must be reopened explicitly without terminating unsaved applications. floe-input(sequence, window, text) accepts one nonempty, NUL-free commit up to 16,000 UTF-8 bytes. No commit is truncated or retried. XIM delivers bounded UTF-8 fragments to the same input context because legacy consumers have fixed lookup buffers. The scheduler holds later input until every fragment is acknowledged; cancellation discards unsent fragments and never replays a partially delivered operation. GTK/Qt receive one native text commit. Text, following keys, pointer/focus changes and clipboard claims share one scheduler. Toolkit acknowledgement occurs after committing in its native input filter; a D-Bus transport reply is not application delivery. XIM uses protocol synchronization. Invalid or timed-out contexts return an explicit error, revoke the attachment's pending input and release its held keys. Reattachment does not replay input.

Input bodies and document histories are not logged. Pending text exists only until delivery or revocation. onError(code) exposes stable error codes without user text. See CONTRIBUTING.md for native qualification and THIRD_PARTY_NOTICES.md for licenses and module provenance.

Current-user desktop capture

The separate host-desktop contract connects to the authenticated graphical session selected by the consuming product. It does not create an application private desktop or expand product permissions. Linux Wayland uses the desktop portal and PipeWire; Linux X11 requires a local authenticated display, a little-endian 24-bit TrueColor visual, MIT-SHM 1.2 and XFixes. XCB reads the selected RandR rectangle into an anonymous shared mapping without grabbing the X server. Cursor shapes are cached until XFixes reports a change, and pointer positions remain fresh. Unsupported layouts and protocol failures stop capture; there is no switch to another graphical session.

Each desktop frame declares cursor: separate or cursor: embedded. The player sets data-floe-desktop-cursor only after drawing a current frame; consumers show the local pointer only for separate control frames and hide it for embedded or view-only frames. Reset removes presentation and shape together. Cursor packets never grant painted input authority. Missing legacy presentation is treated as embedded, since those frames cannot promise cursor-free pixels.

The player confirms pixels only after a rendering opportunity and the following task. During continuous presentation, cumulative frame receipts carry the newest confirmed picture at most every 50 ms. First and idle updates return credit immediately; a settled followup still returns credit by its pending deadline. Unconfirmed replacement pixels never enter that receipt. Reset, recovery and close cancel both pending confirmation and pending credit from the old generation.

X11 control streams send XFixes shapes separately. Wayland selects portal cursor metadata only when advertised, consumes pixels and bounded SPA_META_Cursor through one public PipeWire stream, and uses the existing shape channel for control. View-only capture composites that same shape at its remote position. Position-only updates retain the current bitmap; hidden cursors remain hidden. An unavailable metadata capability retains embedded capture. macOS display capture also declares embedded presentation. These paths display one cursor; embedded capture does not promise immediate local movement. Metadata layout or capture failure stops the affected stream instead of silently losing its cursor. Damage rectangles only optimize pixel comparison. An out-of-surface rectangle discards that frame's damage hints and compares the complete bounded pixel plane; malformed metadata storage and invalid pixel layouts still stop capture.

GStreamer encodes H.264 and system-output Opus from the selected backend. Acquisition may sample twice per negotiated frame interval to observe compositor commits, but unchanged pixels are discarded before encoding. Only the latest unencoded image is retained; encoded dependencies use bounded frame credits. On macOS, ScreenCaptureKit pixel comparison runs separately from VideoToolbox completion delivery through a single pending-sample mailbox. Stop closes that mailbox, and old callbacks cannot restart a retired stream.

When the Wayland compositor retires the authorized PipeWire capture source, the helper revokes input and reports reconnect_required with DISPLAY_STREAM_LOST. The consumer may recreate the portal session using its existing authorization policy; codec and audio failures do not use that recovery path. Retired pipeline errors cannot revoke a replacement pipeline. On macOS, an attachment admitted while the console is locked remains paused until the host user unlocks locally. Capture then resumes with a fresh generation and requires a new painted frame before input.

These are scheduling and resource guarantees, not a universal frame-rate claim. Real-host performance, permissions, physical displays and audio still require qualification in the consuming product's authenticated transport.

Documentation

Overview

Package nativeapps prepares a private native graphical stack without changing system packages. Callers own user consent, authorization, and application launch.

Index

Examples

Constants

View Source
const (
	ServiceUnsupported   = hostdesktop.ServiceUnsupported
	ServiceNotInstalled  = hostdesktop.ServiceNotInstalled
	ServiceAuthorization = hostdesktop.ServiceAuthorization
	ServiceInstalling    = hostdesktop.ServiceInstalling
	ServiceActive        = hostdesktop.ServiceActive
	ServiceStopped       = hostdesktop.ServiceStopped
	ServiceFailed        = hostdesktop.ServiceFailed
	ServiceUninstalling  = hostdesktop.ServiceUninstalling
)
View Source
const ClientInputTextLimit = 16000

ClientInputTextLimit bounds one atomic text commit in UTF-8 bytes. Applications must report rejected commits; truncation and automatic retry are forbidden.

View Source
const ClientInputVersion = 1

ClientInputVersion is the confirmed-text protocol advertised on Xpra's authenticated connection. Consumers must reject sessions without this version.

View Source
const HostDesktopDefaultFrameWindow = hostdesktop.HostDesktopDefaultFrameWindow
View Source
const HostDesktopMaxFrameWindow = hostdesktop.HostDesktopMaxFrameWindow
View Source
const HostDesktopProtocolVersion = hostdesktop.HostDesktopProtocolVersion

hostdesktop owns the physical-desktop wire and privileged service boundary. Root aliases preserve the published SDK API; the standalone service imports only hostdesktop and cannot recursively embed distribution artifacts.

View Source
const LoginScreenService = hostdesktop.LoginScreenService
View Source
const LoginServiceManagementVersion = hostdesktop.LoginServiceManagementVersion
View Source
const LoginServiceSocket = hostdesktop.LoginServiceSocket

Variables

View Source
var (
	ErrServiceUnsupported    = hostdesktop.ErrServiceUnsupported
	ErrServiceAuthorization  = hostdesktop.ErrServiceAuthorization
	ErrServiceNotInstalled   = hostdesktop.ErrServiceNotInstalled
	ErrServiceUpdateRequired = hostdesktop.ErrServiceUpdateRequired
)
View Source
var ErrBusy = errors.New("native preparation is already running")
View Source
var ErrDesktopProtocol = errors.New("invalid native desktop helper protocol")

ErrDesktopProtocol reports invalid helper framing or metadata, without including application content, input text, or authentication material.

View Source
var ErrForbidden = errors.New("native preparation belongs to another caller")
View Source
var ErrHostDesktopProtocol = hostdesktop.ErrHostDesktopProtocol
View Source
var ErrInvalid = errors.New("invalid native preparation request")
View Source
var ErrUnsupported = errors.New("native graphical components are unavailable for this platform")

Functions

func CursorClientSource added in v0.12.4

func CursorClientSource() []byte

CursorClientSource returns the shared standalone JavaScript cursor owner. Consumers build this released asset into their viewer instead of duplicating normalization. FloeRemoteCursor accepts an apply callback and PNG metadata. Its receive, hide, reset and dispose methods own decode/DPR resource lifetime.

func DesktopFramesClientSource added in v0.21.0

func DesktopFramesClientSource() []byte

DesktopFramesClientSource supplies the browser decoder for the released native frame contract. It owns ordered damage composition and bounded decode work; hosts own presentation, transport, target validity, and paint acknowledgements.

func DesktopSelfTest added in v0.14.0

func DesktopSelfTest(ctx context.Context, root, architecture string) error

DesktopSelfTest executes only an installation-owned GTK fixture. It requires decoded pixels, actual Unicode/Enter document bytes, reconnect and normal exit. It does not establish Snap/Flatpak or desktop-environment support by itself.

func DialDesktop added in v0.12.4

func DialDesktop(ctx context.Context, endpoint DesktopEndpoint) (*DesktopConnection, DesktopState, error)

DialDesktop authenticates to an already running Linux helper and returns its initial observed state. It neither prepares nor launches an application. The endpoint is a 0600 Unix socket in an owner-only 0700 directory; kernel peer credentials must match this user before any token is sent. Close detaches only this viewer. The caller owns authorization, lifetime context, and recovery UI.

func HostDesktopClientResource added in v0.22.0

func HostDesktopClientResource(name string) ([]byte, error)

HostDesktopClientResource returns a known immutable module. The host owns authenticated asset routing, session control, browser input, and product UI.

func HostDesktopSelfTest added in v0.22.0

func HostDesktopSelfTest(parent context.Context, root, architecture string) error

HostDesktopSelfTest proves the installed codec round trip using synthetic pixels and audio. Interactive current-desktop authorization and qualification remain separate and are never requested as a side effect of installation.

func PrepareInputClient added in v0.5.0

func PrepareInputClient(source, destination string) error

PrepareInputClient prepares an Xpra HTML5 v20/v21 distribution with exactly one external keyboard owner and one external pointer owner. It retains the graphics, clipboard and pointer transport. The destination must not exist. Neither a failed preparation nor an unsupported source is usable as a client. Consumers serve this directory through the same authenticated Xpra endpoint.

func PrepareLoginScreenMedia added in v0.22.28

func PrepareLoginScreenMedia(ctx context.Context, cache, output string, progress func(Status)) (string, error)

PrepareLoginScreenMedia acquires and checks the released media closure on the target as an ordinary SSH user. No service, driver or authority is changed.

func RunLoginScreenService added in v0.22.23

func RunLoginScreenService(ctx context.Context, config LoginServiceConfig) error

func SelfTest

func SelfTest(parent context.Context, root string) (result error)

SelfTest creates only its own virtual display and transient GTK fixture. A successful check proves actual window discovery, rendered pixels, and input; importing a module or starting a process alone is not readiness evidence.

func SystemClientInputPython added in v0.5.0

func SystemClientInputPython(ctx context.Context, xpra string, environment []string) (string, error)

SystemClientInputPython resolves the interpreter selected by an installed Xpra script, then probes that exact interpreter. It never substitutes the host's unrelated desktop Python or installs missing system dependencies.

func VerifyLoginServiceAdmission added in v0.23.0

func VerifyLoginServiceAdmission(ctx context.Context, path string, proof LoginServiceAdmissionProof) (string, error)

func WriteApplicationLauncher added in v0.3.0

func WriteApplicationLauncher(directory string) (string, error)

WriteApplicationLauncher installs the Linux GIO launcher in a consumer-owned private directory. Invoke it with the tools' Python, an absolute .desktop file and an absolute receipt path. The atomic receipt reports running, exited or failed. A running receipt confirms process launch, not window/pixel readiness. Spawn failures include phase and a stable error_code. Final receipts include the actual direct-launcher exit_code (negative for a signal), per-launcher statuses and termination_requested. These are process observations; the graphical backend determines whether launch or established execution ended. The supervisor retains a nonzero launcher result after reaping descendants. The launcher restores the host application environment and reaps descendants; closing a window or losing a viewer never terminates the application. A verified Snap plan additionally requires FLOE_NATIVE_HOST_BUS to identify the real user bus, separate from DBUS_SESSION_BUS_ADDRESS. Only the supervisor receives that handoff; it is removed from the final application's environment. The supervisor exposes only its admitted direct launcher's scope operation.

func WriteBundle

func WriteBundle(ctx context.Context, pkg Package, cacheRoot string, output io.Writer, progress func(int64)) error

WriteBundle acquires the exact catalog archives for an offline host. It neither extracts nor executes them; the destination host verifies every original byte. Callers must publish the output only after this function returns successfully.

func WriteBundleWithOptions added in v0.9.0

func WriteBundleWithOptions(ctx context.Context, pkg Package, cacheRoot string, output io.Writer, options BundleOptions) error

WriteBundleWithOptions keeps the cache lease through the final ZIP read and applies optional maintenance afterwards, including on cancellation or failure.

func WriteDesktopLauncher added in v0.14.0

func WriteDesktopLauncher(directory, component, architecture string) (string, error)

WriteDesktopLauncher installs one immutable first-party Linux helper source snapshot in a new private directory. Invoke the returned executable with an owner-only version-1 launch configuration. Component must be the caller-verified native package for architecture; its private Python/GIO runs the helper. The helper owns native preparation and the existing application supervisor; a viewer or Runtime must not tie its lifetime to their attachment context.

This installs source only. It does not authorize launch, resolve components, qualify a platform, or activate the combined display distribution. The trusted host must supply verified native resources matching its launch plan. Never rewrite a running instance's snapshot when updating installed support.

func WriteHostDesktopCommand added in v0.22.0

func WriteHostDesktopCommand(writer io.Writer, command HostDesktopCommand) error

func WriteHostDesktopMessage added in v0.22.0

func WriteHostDesktopMessage(writer io.Writer, message HostDesktopMessage) error

func WriteTransferBundle added in v0.4.0

func WriteTransferBundle(ctx context.Context, pkg Package, plan TransferPlan, cacheRoot string, output io.Writer, progress func(int64)) error

WriteTransferBundle accepts only a subset of the supplied trusted recipe. Consumer adapters must resolve pkg from their compiled catalog, not a client. An empty plan needs no bundle: use Manager.Start with source "cache" instead.

func WriteTransferBundleWithOptions added in v0.9.0

func WriteTransferBundleWithOptions(ctx context.Context, pkg Package, plan TransferPlan, cacheRoot string, output io.Writer, options BundleOptions) error

WriteTransferBundleWithOptions validates receiver identities before any cache access, then uses the same leased acquisition path as a complete bundle.

func XpraApplicationLifetimeArgs added in v0.3.0

func XpraApplicationLifetimeArgs() []string

XpraApplicationLifetimeArgs binds an Xpra server to a monitored application child, independently of its viewers and windows. Use a --start-child command that remains alive until the application and its descendants have exited. Consumers still own application authorization, persistence and session policy.

func XpraNoAudioArgs added in v0.2.1

func XpraNoAudioArgs() []string

XpraNoAudioArgs disables audio support for a silent Xpra 6.x graphics session. Muting the speaker and microphone with "off" still initializes audio codecs; a missing audio backend can then delay every server inventory request. Session ownership, transport, and all other feature choices remain with the host.

Types

type ApplicationLaunchPlan added in v0.11.0

type ApplicationLaunchPlan struct {
	// contains filtered or unexported fields
}

ApplicationLaunchPlan is an immutable, short-lived snapshot. It is not an authorization token, a persistent application record, or a backend fallback. Package updates require a fresh plan before executing the application.

func PlanApplication added in v0.11.0

func PlanApplication(ctx context.Context, options ApplicationPlanOptions) (ApplicationLaunchPlan, error)

PlanApplication observes the desktop entry and installed package metadata without starting an application. Unknown protocol metadata selects the combined Wayland/Xwayland backend; its absence is explicit, never an Xpra retry.

func (ApplicationLaunchPlan) Description added in v0.11.0

func (ApplicationLaunchPlan) Revalidate added in v0.11.0

Revalidate rereads the same desktop entry, executable and package revision. The supervisor must also revalidate at its execution boundary. Calling this method alone cannot authorize a later unchecked launch.

func (ApplicationLaunchPlan) Write added in v0.11.0

func (p ApplicationLaunchPlan) Write(directory string) (string, error)

Write places this plan in the new application's private directory. Invoke the installed application launcher as --plan PATH RECEIPT. It revalidates before GIO creates a child; graphical resources must already match Backend.Component. Do not overwrite a running instance's plan or change its backend identity.

type ApplicationPackage added in v0.11.0

type ApplicationPackage struct {
	Kind        string `json:"kind"`
	ID          string `json:"id"`
	Revision    string `json:"revision"`
	Version     string `json:"version,omitempty"`
	Confinement string `json:"confinement,omitempty"`
	Application string `json:"application,omitempty"`
	SecurityTag string `json:"security_tag,omitempty"`
	Ref         string `json:"ref,omitempty"`
	Deployment  string `json:"deployment,omitempty"`
	Format      int    `json:"format,omitempty"`
}

type ApplicationPlanDescription added in v0.11.0

type ApplicationPlanDescription struct {
	Version       int                `json:"version"`
	SHA256        string             `json:"sha256"`
	Backend       BackendCapability  `json:"backend"`
	Package       ApplicationPackage `json:"package"`
	Services      []string           `json:"services"`
	Desktop       string             `json:"desktop"`
	DesktopSHA256 string             `json:"desktop_sha256"`
}

ApplicationPlanDescription describes identity and required resources without granting readiness or input permission. Each call returns independent values.

type ApplicationPlanOptions added in v0.11.0

type ApplicationPlanOptions struct {
	Python      string
	Environment []string
	DesktopFile string
	// BrowserProfileDirectory opts supported native browsers into a persistent,
	// private profile. The host chooses its owner/application-scoped location.
	// Existing explicit profile arguments and sandboxed packages retain their
	// own launch contract; no personal profile is read, copied, or unlocked.
	BrowserProfileDirectory string
	Backends                []BackendCapability
}

ApplicationPlanOptions contains the already authorized host desktop entry. Python must provide GIO. Environment is the original host environment, or a Tools.Environment result whose saved overrides the planner restores.

type Artifact

type Artifact struct {
	Name    string   `json:"name"`
	URL     string   `json:"url"`
	Mirrors []string `json:"mirrors,omitempty"`
	SHA256  string   `json:"sha256"`
	Size    int64    `json:"size_bytes"`
	Format  string   `json:"format"`
	License string   `json:"license"`
	Source  string   `json:"source"`
}

type BackendCapability added in v0.11.0

type BackendCapability struct {
	ID        string   `json:"id"`
	Component string   `json:"component"`
	Protocols []string `json:"protocols"`
	Services  []string `json:"services,omitempty"`
}

BackendCapability describes one prepared backend. The trusted host obtains these values from its installed backend, never from a browser request. A capability describes available resources, not application readiness.

type BundleOptions added in v0.9.0

type BundleOptions struct {
	CachePolicy   artifactcache.Policy
	OnProgress    func(BundleProgress) error
	OnMaintenance func(artifactcache.Maintenance, error)
	// Client is a trusted network policy/test hook, never a renderer input.
	Client *http.Client
}

type BundleProgress added in v0.9.0

type BundleProgress struct {
	Phase           string `json:"phase"`
	ComponentBytes  int64  `json:"component_bytes"`
	CachedBytes     *int64 `json:"cached_bytes,omitempty"`
	DownloadBytes   *int64 `json:"download_bytes,omitempty"`
	DownloadedBytes int64  `json:"downloaded_bytes"`
}

BundleProgress distinguishes verified cache bytes from actual network bytes. Totals remain absent until every requested archive has been checked.

type ClientAssets added in v0.6.0

type ClientAssets struct {
	// contains filtered or unexported fields
}

ClientAssets is an immutable snapshot of public resources from a directory produced by PrepareInputClient. It excludes HTML, configuration and session files. Hosts own authorization, route placement and snapshot lifetime.

func OpenClientAssets added in v0.6.0

func OpenClientAssets(directory string) (*ClientAssets, error)

OpenClientAssets snapshots and precompresses a prepared Xpra HTML5 v20/v21 client. Worker URLs follow the script's resource directory, independently of the session document URL. The source and installed vendor files are unchanged. The digest covers the exact prepared resource names and bytes, including the input adapter and worker transformation, rather than only the native recipe.

func (*ClientAssets) Digest added in v0.6.0

func (a *ClientAssets) Digest() string

Digest is the content version to include in the host's resource route.

func (*ClientAssets) RewriteHTML added in v0.6.0

func (a *ClientAssets) RewriteHTML(document []byte, basePath string) ([]byte, error)

RewriteHTML relocates only references to resources in this snapshot. basePath must be an absolute same-origin directory path containing the content version. It leaves WebSocket addresses, session settings and inline startup code alone. The resulting session document must remain authenticated and uncached.

func (*ClientAssets) ServeHTTP added in v0.6.0

func (a *ClientAssets) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP serves a resource path (for example /js/Client.js). The host must first select this snapshot by its exact digest and strip the versioned prefix. Authorization belongs before this handler. Cached scripts never authorize a connection: hosts must continue authenticating session documents and traffic.

type ClientInput added in v0.5.0

type ClientInput struct {
	Launcher, GTKModules, QtPlugins string
	// GTKPath is a private module root. Only GTK4 scans its 4.0.0 ABI directory;
	// GTK3 uses GTKModules and must never load the GTK4 shared object.
	GTKPath string
}

ClientInput is prepared support for one private X11 application session. Launch Launcher with the probed Xpra Python interpreter, normal Xpra arguments and XpraArgs. Start a private session bus first and pass its address explicitly to the application's start environment. These paths contain first-party adapters, never a copied host toolkit or a second input method engine.

func PrepareClientInput added in v0.5.0

func PrepareClientInput(directory, architecture string) (ClientInput, error)

PrepareClientInput installs the complete input contract into a new absolute private directory. The architecture is the application host's Go architecture.

func (ClientInput) XpraArgs added in v0.5.0

func (input ClientInput) XpraArgs(baseEnvironment []string) []string

XpraArgs selects client-owned composition in the private application environment. No host desktop input configuration is inherited or modified.

type ClientInputCapability added in v0.5.0

type ClientInputCapability struct {
	Version     int    `json:"version"`
	XpraVersion string `json:"xpra_version"`
}

func ProbeClientInput added in v0.5.0

func ProbeClientInput(ctx context.Context, python string, environment []string) (ClientInputCapability, error)

ProbeClientInput checks the interpreter and original XIM library before any application is launched. It does not acquire components or require a display. A successful probe does not assert that a particular application has a focused editable input context; that boundary is checked for every submitted commit.

type DesktopClipboard added in v0.14.0

type DesktopClipboard struct {
	Connection uint64  `json:"connection"`
	Window     uint64  `json:"window"`
	Generation uint64  `json:"generation"`
	Text       *string `json:"text,omitempty"`
	Error      string  `json:"error,omitempty"`
}

DesktopClipboard is the private application's current UTF-8 selection. Text may be empty; Error instead reports an unavailable or unsupported offer. It is independent of confirmed-text input and never authorizes a target.

type DesktopConnection added in v0.12.4

type DesktopConnection struct {
	// contains filtered or unexported fields
}

DesktopConnection owns one authenticated helper attachment. It has no process owner, reconnect loop, frame queue, input scheduler, or implicit frame ack. One goroutine reads events while writers may send requests concurrently. Native validation and ordering remain authoritative in the helper.

func (*DesktopConnection) Close added in v0.12.4

func (c *DesktopConnection) Close() error

Close revokes this sharing attachment. It never terminates the helper, display or application. The helper releases input owned by the detached attachment.

func (*DesktopConnection) Connection added in v0.12.4

func (c *DesktopConnection) Connection() uint64

Connection returns the immutable attachment generation assigned by the helper. Reattachment creates another DesktopConnection and another generation.

func (*DesktopConnection) Read added in v0.12.4

Read returns one complete event without buffering subsequent frames or acknowledging pixels. Only one reader may call Read at a time. Cancellation closes the attachment rather than retaining a partially consumed packet.

func (*DesktopConnection) Send added in v0.12.4

func (c *DesktopConnection) Send(ctx context.Context, request DesktopRequest) (uint64, error)

Send writes one bounded request and returns its sequence. The reply is read by Read. Cancellation during I/O closes this attachment; no request is replayed. A caller should use a separate continuous reader so frame delivery cannot prevent it from consuming replies. Input ordering belongs to the helper.

func (*DesktopConnection) StreamVersion added in v0.21.0

func (c *DesktopConnection) StreamVersion() int

StreamVersion is the negotiated helper capability. Zero denotes a surviving legacy PNG session; hosts must not send configure_stream to that session.

type DesktopCursor added in v0.12.4

type DesktopCursor struct {
	Mode          string  `json:"mode"`
	Sequence      uint64  `json:"sequence"`
	Connection    uint64  `json:"connection"`
	Window        uint64  `json:"window"`
	Generation    uint64  `json:"generation"`
	Encoding      string  `json:"encoding,omitempty"`
	Width         int     `json:"width,omitempty"`
	Height        int     `json:"height,omitempty"`
	LogicalWidth  int     `json:"logical_width,omitempty"`
	LogicalHeight int     `json:"logical_height,omitempty"`
	XHot          float64 `json:"xhot,omitempty"`
	YHot          float64 `json:"yhot,omitempty"`
}

DesktopCursor carries the current native pointer shape. Image dimensions describe PNG pixels; LogicalWidth/Height and the hotspot are surface units. The shared cursor client caps CSS size without applying buffer scale twice. Hidden and default modes contain no pixel payload. Sequence is compositor-wide.

type DesktopEndpoint added in v0.12.4

type DesktopEndpoint struct {
	SocketPath string
	Instance   string
	Token      string
}

DesktopEndpoint identifies an existing private helper. A trusted application instance supplies these values; they are never taken from viewer input.

type DesktopEvent added in v0.12.4

type DesktopEvent struct {
	StreamVersion int               `json:"stream_version,omitempty"`
	Event         string            `json:"event,omitempty"`
	ID            uint64            `json:"id,omitempty"`
	Version       int               `json:"version,omitempty"`
	Connection    uint64            `json:"connection,omitempty"`
	State         *DesktopState     `json:"state,omitempty"`
	Frame         *DesktopFrame     `json:"frame,omitempty"`
	Cursor        *DesktopCursor    `json:"cursor,omitempty"`
	Clipboard     *DesktopClipboard `json:"clipboard,omitempty"`
	Bytes         int               `json:"bytes,omitempty"`
	Code          string            `json:"code,omitempty"`
	Error         string            `json:"error,omitempty"`
	Result        json.RawMessage   `json:"result,omitempty"`
	Pixels        []byte            `json:"-"`
}

DesktopEvent contains one complete helper event or request result. A frame event includes its bounded PNG payload. The caller owns those returned bytes. Result and Error preserve helper semantics: submitted is not a widget receipt.

type DesktopFrame added in v0.12.4

type DesktopFrame struct {
	X            int    `json:"x,omitempty"`
	Y            int    `json:"y,omitempty"`
	RegionWidth  int    `json:"region_width,omitempty"`
	RegionHeight int    `json:"region_height,omitempty"`
	Base         uint64 `json:"base,omitempty"`
	Encoding     string `json:"encoding"`
	Width        int    `json:"width"`
	Height       int    `json:"height"`
	Sequence     uint64 `json:"sequence"`
	Connection   uint64 `json:"connection"`
	Window       uint64 `json:"window"`
	Generation   uint64 `json:"generation"`
}

DesktopFrame binds pixels to the native connection, window and geometry generation. Receiving or parsing it does not grant input permission: the viewer must decode and paint it before sending frame_ack for Sequence.

type DesktopRequest added in v0.12.4

type DesktopRequest struct {
	Mode       string          `json:"mode,omitempty"`
	Method     string          `json:"method"`
	Connection uint64          `json:"connection,omitempty"`
	Window     uint64          `json:"window,omitempty"`
	Generation uint64          `json:"generation,omitempty"`
	Frame      uint64          `json:"frame,omitempty"`
	Operation  json.RawMessage `json:"operation,omitempty"`
}

DesktopRequest names a version-1 helper operation. Operation is the native input object for input requests; the helper validates it against the current acknowledged target. Other methods have no Operation. Target fields remain explicit so a stale callback cannot borrow the connection's current target. terminate_application is reserved for authorized explicit force-quit intent: the installed session signals its own supervisor. It takes no PID, signal or target and remains available after capture failure. Closing this connection never invokes it; the subsequent process receipt establishes the real exit. release_input cancels pending input and releases held keys/buttons only for the named, already-painted target. It preserves that frame's input authority.

type DesktopSessionOptions added in v0.14.0

type DesktopSessionOptions struct {
	Directory, Runtime, Instance string
	Plan                         ApplicationLaunchPlan
	Environment                  []string
	HostBus                      string
	InitialDocuments             []string
}

DesktopSessionOptions is an authorized new instance, never a renderer payload. Directory must not exist; Runtime is an existing owner-only socket directory. Environment is the original host environment, not a support-tool environment.

type DesktopState added in v0.12.4

type DesktopState struct {
	State      string          `json:"state"`
	Window     uint64          `json:"window"`
	Generation uint64          `json:"generation"`
	Windows    []DesktopWindow `json:"windows"`
}

DesktopState is native observation, not application lifetime. In particular, waiting or unavailable must never be interpreted as application exit.

type DesktopTools added in v0.14.0

type DesktopTools struct {
	Root, Python, Shell, Capture, Library, Xwayland, IBusDaemon, IBusPortal, QtPlugins, GTKModules string
}

DesktopTools is the single verified layout used by planning and launch. It does not discover a host compositor or substitute a system input service.

func ResolveDesktopTools added in v0.14.0

func ResolveDesktopTools(root, architecture string) (DesktopTools, error)

ResolveDesktopTools verifies installed derivations and the original executable closure without starting processes. Manager additionally checks recipe identity.

func (DesktopTools) Environment added in v0.14.0

func (t DesktopTools) Environment(base []string) []string

Environment isolates the planning interpreter while retaining the exact host resolution environment in the existing supervisor handoff.

type DesktopWindow added in v0.12.4

type DesktopWindow struct {
	Window      uint64 `json:"window"`
	Parent      uint64 `json:"parent"`
	Protocol    string `json:"protocol"`
	Width       int    `json:"width"`
	Height      int    `json:"height"`
	Title       string `json:"title"`
	Maximized   bool   `json:"maximized"`
	Fullscreen  bool   `json:"fullscreen"`
	Minimized   bool   `json:"minimized"`
	Interacting bool   `json:"interacting"`
}

type HostDesktopCapabilities added in v0.22.0

type HostDesktopCapabilities = hostdesktop.HostDesktopCapabilities

type HostDesktopCommand added in v0.22.0

type HostDesktopCommand = hostdesktop.HostDesktopCommand

func ParseHostDesktopCommand added in v0.22.0

func ParseHostDesktopCommand(data []byte) (HostDesktopCommand, error)

type HostDesktopCursorPosition added in v0.22.28

type HostDesktopCursorPosition = hostdesktop.HostDesktopCursorPosition

type HostDesktopDisplay added in v0.22.0

type HostDesktopDisplay = hostdesktop.HostDesktopDisplay

type HostDesktopInput added in v0.22.0

type HostDesktopInput = hostdesktop.HostDesktopInput

type HostDesktopMessage added in v0.22.0

type HostDesktopMessage = hostdesktop.HostDesktopMessage

func ReadHostDesktopMessage added in v0.22.0

func ReadHostDesktopMessage(reader io.Reader) (HostDesktopMessage, error)

type HostDesktopPicture added in v0.22.0

type HostDesktopPicture = hostdesktop.HostDesktopPicture

type HostDesktopServiceKit added in v0.22.23

type HostDesktopServiceKit struct {
	ServiceSHA256 string            `json:"service_sha256"`
	WorkerSHA256  string            `json:"worker_sha256"`
	Files         map[string][]byte `json:"-"`
}

HostDesktopServiceKit is the reviewed release's SSH deployment closure. A host adapter selects architecture from the SSH host, never from renderer paths or URLs. Extracting this kit never requests authority or installs a service.

func LoginScreenServiceKit added in v0.22.23

func LoginScreenServiceKit(architecture string) (HostDesktopServiceKit, error)

func (HostDesktopServiceKit) Write added in v0.22.23

func (kit HostDesktopServiceKit) Write(ctx context.Context, directory string) error

type HostDesktopServiceStatus added in v0.22.17

type HostDesktopServiceStatus = hostdesktop.HostDesktopServiceStatus

type HostDesktopTools added in v0.22.0

type HostDesktopTools struct{ Root, Python, Helper string }

HostDesktopTools holds only the verified helper paths. The consumer passes a private persistent --state directory, --media-fd, and framed commands on stdin; stdout is control only. The media descriptor is a separate inherited pipe.

func ResolveHostDesktopTools added in v0.22.0

func ResolveHostDesktopTools(root, architecture string) (HostDesktopTools, error)

type Installation added in v0.4.0

type Installation struct {
	ID           string `json:"id"`
	Digest       string `json:"digest"`
	Architecture string `json:"architecture"`
	Contract     string `json:"contract"`
	Ready        bool   `json:"ready"`
}

Installation identifies an installed recipe independently of the SDK release. Ready is a lightweight check of its private marker and required tool layout.

type LaunchUnavailable added in v0.11.0

type LaunchUnavailable struct {
	Code  string `json:"code"`
	Stage string `json:"stage"`
}

LaunchUnavailable is safe for production diagnostics. It contains no child output, input text, environment values, or desktop file contents.

func (*LaunchUnavailable) Error added in v0.11.0

func (e *LaunchUnavailable) Error() string

type LoginScreenConnection added in v0.22.23

type LoginScreenConnection = hostdesktop.LoginScreenConnection

func OpenLoginScreenSession added in v0.22.23

func OpenLoginScreenSession(ctx context.Context, path string) (*LoginScreenConnection, error)

type LoginServiceAdmissionProof added in v0.23.2

type LoginServiceAdmissionProof = hostdesktop.LoginServiceAdmissionProof

type LoginServiceConfig added in v0.22.23

type LoginServiceConfig = hostdesktop.LoginServiceConfig

type LoginServiceDeploymentCommand added in v0.23.0

type LoginServiceDeploymentCommand = hostdesktop.LoginServiceDeploymentCommand

type LoginServiceDeploymentControl added in v0.23.0

type LoginServiceDeploymentControl = hostdesktop.LoginServiceDeploymentControl

type LoginServiceDeploymentEvent added in v0.22.23

type LoginServiceDeploymentEvent = hostdesktop.LoginServiceDeploymentEvent

type LoginServiceDeploymentRequest added in v0.22.23

type LoginServiceDeploymentRequest = hostdesktop.LoginServiceDeploymentRequest

type LoginServiceManager added in v0.22.17

type LoginServiceManager struct{}

LoginServiceManager observes installed state. It never simulates installation in memory and never elevates Runtime. Administrator-authorized SSH deployment uses ManageLoginScreenServiceControlled in a separate management process.

func NewLoginServiceManager added in v0.22.17

func NewLoginServiceManager() *LoginServiceManager

func (*LoginServiceManager) Install added in v0.22.17

func (*LoginServiceManager) OpenLoginSession deprecated added in v0.22.17

func (m *LoginServiceManager) OpenLoginSession(ctx context.Context) (string, ServiceStatus, error)

Deprecated: use OpenLoginScreenSession, which consumes its one-time ticket and owns the private attachment lifecycle rather than exposing an unbound token.

func (*LoginServiceManager) Status added in v0.22.17

func (*LoginServiceManager) Uninstall added in v0.22.17

func (m *LoginServiceManager) Uninstall(ctx context.Context) (ServiceStatus, error)

type Manager

type Manager struct {
	// contains filtered or unexported fields
}

func New

func New(root string, pkg Package, validate func(context.Context, string) error) (*Manager, error)

New requires a private state root. Creating a manager never downloads or starts native processes. The optional validator is useful for host-owned qualification; production callers use the built-in graphical self-check by passing nil.

Example

This example compiles in source checks but performs no network operations in tests. A service should retain its manager for the service's entire lifetime.

package main

import (
	"context"
	"fmt"
	"log"
	"os"
	"path/filepath"
	"time"

	nativeapps "github.com/floegence/floe-native-apps"
)

func main() {
	prepare := func(ctx context.Context, stateRoot, owner, requestID string) (nativeapps.Tools, error) {
		pkg, err := nativeapps.NativePackage()
		if err != nil {
			return nativeapps.Tools{}, err
		}
		manager, err := nativeapps.New(stateRoot, pkg, nil)
		if err != nil {
			return nativeapps.Tools{}, err
		}
		defer manager.Close()
		changes, stop := manager.Watch()
		defer stop()
		if _, err := manager.Start(owner, requestID, "download", 0); err != nil {
			return nativeapps.Tools{}, err
		}
		for {
			status := manager.Snapshot(owner)
			if status.State == "ready" {
				root, err := manager.Directory()
				if err != nil {
					return nativeapps.Tools{}, err
				}
				return nativeapps.ResolveTools(root)
			}
			if !status.Active() {
				return nativeapps.Tools{}, fmt.Errorf("preparation %s: %s", status.State, status.ErrorCode)
			}
			select {
			case <-ctx.Done():
				return nativeapps.Tools{}, ctx.Err()
			case <-changes:
			}
		}
	}
	cache, err := os.UserCacheDir()
	if err != nil {
		log.Fatal(err)
	}
	ctx, cancel := context.WithTimeout(context.Background(), 20*time.Minute)
	defer cancel()
	// A real product supplies an authenticated owner and a stable request ID.
	tools, err := prepare(ctx, filepath.Join(cache, "floe-native-apps"), "local-user", "prepare-1")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(tools.Xpra)
}

func (*Manager) Cancel

func (m *Manager) Cancel(owner, id string) (Status, error)

func (*Manager) Close

func (m *Manager) Close()

func (*Manager) CompleteUpload

func (m *Manager) CompleteUpload(owner, id string) (Status, error)

func (*Manager) DesktopBackend added in v0.14.0

func (m *Manager) DesktopBackend() (BackendCapability, error)

DesktopBackend returns the installed combined display capability. A surviving selection remains usable by surviving sessions; new launches require the current private capture ABI after preparation explicitly activates its update.

func (*Manager) Directory

func (m *Manager) Directory() (string, error)

func (*Manager) DirectoryFor added in v0.4.0

func (m *Manager) DirectoryFor(digest string) (string, error)

DirectoryFor resolves an exact supported installation for a surviving process. It never changes the current installation or prepares another version.

func (*Manager) HostDesktopTools added in v0.22.0

func (m *Manager) HostDesktopTools() (HostDesktopTools, error)

func (*Manager) InstallationForProcess added in v0.4.0

func (m *Manager) InstallationForProcess(process ProcessIdentity) (*Installation, error)

InstallationForProcess identifies a legacy backend's private loader using kernel evidence. Nil means a system installation outside this manager's root. The caller still owns application authorization and backend identity checks.

func (*Manager) Package

func (m *Manager) Package() Package

func (*Manager) Plan added in v0.4.0

func (m *Manager) Plan(ctx context.Context) (TransferPlan, error)

Plan verifies archives only on explicit preparation/inspection, never on the normal application-open or status path. It performs no network requests.

func (*Manager) PlanDesktop added in v0.14.0

func (m *Manager) PlanDesktop(ctx context.Context, desktopFile string, environment []string) (ApplicationLaunchPlan, error)

PlanDesktop observes an authorized desktop entry against the verified installed component. Missing package/host services remain structured planning failures.

func (*Manager) PrepareDesktopSession added in v0.14.0

func (m *Manager) PrepareDesktopSession(ctx context.Context, options DesktopSessionOptions) (PreparedDesktopSession, error)

PrepareDesktopSession binds a plan to a known installed component, generates authentication and writes a new immutable source/configuration snapshot. It neither launches applications nor rewrites surviving session resources.

func (*Manager) Snapshot

func (m *Manager) Snapshot(owner string) Status

func (*Manager) Start

func (m *Manager) Start(owner, requestID, source string, uploadSize int64) (Status, error)

func (*Manager) Watch

func (m *Manager) Watch() (<-chan struct{}, func())

func (*Manager) WriteChunk

func (m *Manager) WriteChunk(owner, id string, offset int64, data []byte) (Status, error)

type Package

type Package struct {
	ID             string       `json:"id"`
	Architecture   string       `json:"architecture"`
	SizeBytes      int64        `json:"size_bytes"`
	InstalledBytes int64        `json:"installed_bytes"`
	Artifacts      []Artifact   `json:"artifacts"`
	Preparation    *Preparation `json:"preparation,omitempty"`
}

func DesktopForPlatform added in v0.14.0

func DesktopForPlatform(platform, architecture string) (Package, error)

DesktopForPlatform returns the combined display recipe. ForPlatform continues to return the published Xpra recipe for consumers of that existing contract. Installation alone never certifies an arbitrary application's compatibility.

func ForPlatform

func ForPlatform(platform, architecture string) (Package, error)

func HostDesktopForPlatform added in v0.22.0

func HostDesktopForPlatform(platform, architecture string) (Package, error)

HostDesktopForPlatform returns the current-user desktop media closure. It does not grant desktop access or select an application-private graphical session.

func NativePackage

func NativePackage() (Package, error)

func (Package) Digest

func (p Package) Digest() string

func (Package) Validate

func (p Package) Validate() error

type Preparation added in v0.14.0

type Preparation struct {
	Contract     string `json:"contract"`
	NativeSHA256 string `json:"native_sha256"`
}

Preparation identifies reviewed native derivations in addition to the original archives. Omission preserves the exact encoding of published Xpra recipes.

type PreparedDesktopSession added in v0.14.0

type PreparedDesktopSession struct {
	Executable, Configuration, Component string
	Endpoint                             DesktopEndpoint
}

PreparedDesktopSession contains immutable launch resources. Launch Executable with Configuration as its sole argument using a persistent process owner. Cancelling a viewer or Runtime attachment must never terminate this process.

type PreparedViewer added in v0.12.0

type PreparedViewer struct {
	// contains filtered or unexported fields
}

PreparedViewer is an immutable, matching document and resource snapshot made by this SDK from an original reviewed HTML5 distribution. It owns no backend, input module or application process. A host pins it for one sharing session.

func PrepareViewer added in v0.12.0

func PrepareViewer(source string) (*PreparedViewer, error)

PrepareViewer uses the same preparation as PrepareInputClient, independently of any application's old prepared directory. Failure never yields an older viewer. The source must be a trusted installed original v20/v21 distribution.

func (*PreparedViewer) Assets added in v0.12.0

func (v *PreparedViewer) Assets() *ClientAssets

Assets returns the immutable public resources. Hosts must authorize each request by owner, active sharing origin and exact content digest.

func (*PreparedViewer) Document added in v0.12.0

func (v *PreparedViewer) Document(basePath string) ([]byte, error)

Document returns this snapshot's entry point with versioned public references. The document, settings, credentials and transport must never be cached.

func (*PreparedViewer) DocumentWithOptions added in v0.22.8

func (v *PreparedViewer) DocumentWithOptions(basePath string, options ViewerDocumentOptions) ([]byte, error)

type ProcessIdentity added in v0.3.0

type ProcessIdentity struct {
	PID     int    `json:"pid"`
	Boot    string `json:"boot"`
	Started string `json:"started"`
}

ProcessIdentity is an observation of one Linux process generation. Persisting it allows a host to distinguish a surviving native backend from a reused PID after restart. It grants no authorization and must never be used alone to select an application or issue a signal.

func ObserveProcess added in v0.3.0

func ObserveProcess(pid int) (ProcessIdentity, error)

ObserveProcess reads the kernel's boot and start identity for a live process.

func (ProcessIdentity) Alive added in v0.3.0

func (p ProcessIdentity) Alive() bool

type ServiceStatus added in v0.22.17

type ServiceStatus = HostDesktopServiceStatus

func InstalledLoginServiceStatus added in v0.22.23

func InstalledLoginServiceStatus(ctx context.Context, path string) (ServiceStatus, error)

func ManageLoginScreenServiceControlled added in v0.23.0

func ManageLoginScreenServiceControlled(ctx context.Context, request LoginServiceDeploymentRequest, report func(LoginServiceDeploymentEvent), control LoginServiceDeploymentControl) (ServiceStatus, error)

type Status

type Status struct {
	State                 string        `json:"state"`
	OperationID           string        `json:"operation_id,omitempty"`
	ReceivedBytes         int64         `json:"received_bytes"`
	ExpectedBytes         int64         `json:"expected_bytes"`
	ErrorCode             string        `json:"error_code,omitempty"`
	CanCancel             bool          `json:"can_cancel"`
	Installed             *Installation `json:"installed,omitempty"`
	UpdateAvailable       bool          `json:"update_available"`
	InstallationErrorCode string        `json:"installation_error_code,omitempty"`
}

func (Status) Active

func (s Status) Active() bool

type Tools

type Tools struct{ Root, Xpra, Python, Xvfb, Xauth, DBus, HTML string }

func ResolveTools

func ResolveTools(root string) (Tools, error)

func (Tools) Environment

func (t Tools) Environment(base []string) []string

Environment scopes support-tool overrides. The GIO launcher must restore this small saved map on its AppLaunchContext before starting the user's program. Display and D-Bus addresses are deliberately not restored: those belong to the caller's private graphical session.

type TransferPlan added in v0.4.0

type TransferPlan struct {
	PackageDigest    string   `json:"package_digest"`
	Architecture     string   `json:"architecture"`
	MissingArtifacts []string `json:"missing_artifacts"`
	MissingBytes     int64    `json:"missing_bytes"`
}

TransferPlan contains only identities from the receiver's trusted catalog. It is a cache observation, not an authorization or a reservation of cache files.

type ViewerDocumentOptions added in v0.22.8

type ViewerDocumentOptions struct {
	TransportScriptURL string
}

ViewerDocumentOptions binds a prepared client to a host-owned transport. The same-origin script must synchronously publish floeHostTransport.WebSocket, a WebSocket-compatible constructor. Missing transport fails closed. Protocol processing stays in this realm; independent graphics decode workers remain enabled. The host owns authorization, carrier lifetime and script CSP permission.

Directories

Path Synopsis
Package artifactcache acquires pinned publisher archives into a private, content-addressed cache.
Package artifactcache acquires pinned publisher archives into a private, content-addressed cache.
cmd
floe-host-desktop-service command
floe-host-desktop-service is installed as a root-owned executable only after the host product has obtained administrator authorization.
floe-host-desktop-service is installed as a root-owned executable only after the host product has obtained administrator authorization.
floe-native-apps command
floe-native-apps is an explicit qualification and offline acquisition tool.
floe-native-apps is an explicit qualification and offline acquisition tool.
internal
qualification
desktop_launch command
desktop_launch is a private native fixture for the public installed launch API.
desktop_launch is a private native fixture for the public installed launch API.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL