Oregami
Repositories/oxedyne/daimond

oxedyne/daimond/hand/src/lib.rs

5.1 KiB, 1 run

created by r2519314175:919, which is this file's identity for as long as the history lasts, whatever it is later renamed to

download · who wrote it · its history

1//! Daimond's machine hand: the program outside the page that runs commands.
2//!
3//! A web page cannot create a process. There is no flag and no future API, so
4//! the capability has to live in a program outside the page, and the whole of
5//! this crate's design is an answer to *where that program sits and who may
6//! talk to it*.
7//!
8//! The answer is a **native messaging host**. Chrome launches this binary and
9//! connects it to one extension only; the extension is connectable from
10//! `daimond.oxedyne.com` only. There is therefore no port to find and no
11//! secret to steal -- the browser is the doorman. A loopback daemon would be
12//! reachable by any page the user visits, and its entire defence would be one
13//! pasted secret.
14//!
15//! Four things are kept apart on purpose:
16//!
17//! * [`wire`] -- what the two ends say to each other, and how it is framed.
18//! Designed for remote from the first line: loopback is the degenerate case
19//! of remote, and a localhost-only protocol is a rewrite waiting to happen.
20//! * [`exec`] -- running a command. **`argv` only, never a shell string**, so
21//! there is no injection surface to defend rather than a defence to get right.
22//! * [`fence`] -- what a command may touch. Platform-specific, and therefore
23//! behind an enum from the start with the platforms that are not built yet
24//! declared rather than forgotten.
25//! * [`verify`] -- running a NAMED verifier out of the tracked tree, clean and
26//! under each break it declares, and refusing to report a passing count
27//! without the count of breaks that reddened nothing.
28//! * [`journal`] -- what was run, what it returned, and what it was stopped
29//! from doing. Load-bearing: the product's claim is that it can be checked
30//! rather than trusted, and that claim has to cover the hand too.
31
32use oxedyne_fe2o3_core::prelude::*;
33
34pub mod codec;
35pub mod exec;
36pub mod fence;
37pub mod journal;
38#[cfg(unix)]
39pub mod pty;
40pub mod seccomp;
41pub mod verify;
42pub mod wire;
43
44/// The wire protocol version this build speaks.
45///
46/// Sent in the opening [`wire::Req::Hello`] and answered in
47/// [`wire::Resp::Hello`], so a hand and a page that have drifted say so on the
48/// first exchange rather than at the first command that needs the difference.
49///
50/// **2 since 2026-08-25**, when the two answers a walk and a read come back with
51/// both changed shape: a read now opens with three numbers rather than one --
52/// the whole file's lines, its bytes, and how many lines this answer holds --
53/// and a search sends the LINES its pattern matched rather than whole file
54/// texts. Either read by the older parser is wrong in silence rather than
55/// loudly, which is exactly what this number exists to stop.
56pub const PROTO: u32 = 2;
57
58/// The name this build reports to the page, for the device roster.
59pub const HOST_NAME: &str = "daimond-hand";
60
61/// The file, beside the journal, naming the one folder the hand may work in.
62///
63/// A file rather than an environment variable because the browser hands a
64/// native messaging host *its own* environment, so nothing the user exports
65/// reaches this program. Here rather than in `main.rs` because [`journal`]
66/// counts it as its own furniture: a directory holding the record and this file
67/// and nothing else is one the hand made, and may be tightened to 0700.
68pub const ROOT_FILE: &str = "root.txt";
69
70/// The file, beside the journal, naming the widest a TERMINAL may ever reach.
71///
72/// A terminal is the user at a keyboard and a command is a daimon, and the two
73/// deserve different sizes: the owner asked for exactly that on 2026-08-26, having
74/// picked `~/usr` for the one root he had "for no reason other than I saw no need to
75/// go higher".
76///
77/// It is a CEILING and not the working value. The page may name a terminal's folder
78/// within it and may never widen past it, which is the whole reason this lives on the
79/// machine and is written by the installer: a page that could name its own root could
80/// name a wider one, and every other rule here rests on its not being able to.
81///
82/// Absent, and a terminal gets [`ROOT_FILE`] exactly as before.
83pub const TERMINAL_ROOT_FILE: &str = "terminal-root.txt";
84
85/// The version string this build reports, taken from the manifest at compile time.
86pub fn version() -> &'static str {
87 env!("CARGO_PKG_VERSION")
88}
89
90/// The operating system this build runs on, as the wire spells it.
91///
92/// A single vocabulary, so the page can say "this hand cannot fence on Windows
93/// yet" without parsing a target triple.
94pub fn os() -> &'static str {
95 if cfg!(target_os = "linux") {
96 "linux"
97 } else if cfg!(target_os = "macos") {
98 "macos"
99 } else if cfg!(target_os = "windows") {
100 "windows"
101 } else {
102 "unknown"
103 }
104}
105
106/// A guard against a build that reports an operating system it has no fence for.
107///
108/// # Returns
109/// The OS name, or an error naming the platform that needs a [`fence`] arm.
110pub fn checked_os() -> Outcome<&'static str> {
111 match os() {
112 "unknown" => Err(err!(
113 "The hand does not know what platform it was built for, so it \
114 cannot say what fence applies to it.";
115 Unimplemented, Configuration)),
116 name => Ok(name),
117 }
118}