<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
  <channel>
    <title><![CDATA[Thomas Gazagnaire]]></title>
    <description><![CDATA[Building Functional Systems from Cloud to Orbit.]]></description>
    <link>https://gazagnaire.org</link>
    <lastBuildDate>Wed, 25 Feb 2026 00:00:00 GMT</lastBuildDate>
    <atom:link href="https://gazagnaire.org/feed.xml" rel="self" type="application/rss+xml"/>
    <item>
      <title><![CDATA[Is Running Untrusted Code on a Satellite a Good Idea?]]></title>
      <description><![CDATA[<p>The same conversation keeps happening. I explain what
<a href="https://parsimoni.co/">Parsimoni</a> does (run third-party software
on someone else's satellite) and the response is always some
variant of: &quot;I would never trust code I have not reviewed to run
on my satellite.&quot;
They are right to worry -- I would say the same thing in their
position. And the security research community has been saying it loudly
for several years now.</p>
<p>To understand where the gaps are, it helps to separate the two
halves of the stack. Bus software (attitude control, power, thermal)
runs on qualified RTOSes and is the satellite manufacturer's domain.
Payload software (imaging, communications, data processing)
increasingly runs on COTS (commercial off-the-shelf)
processors with memory management units (MMUs) perfectly capable of enforcing memory
isolation. For LEO missions on COTS hardware, the hardware is
there. The software running on it does not use it.</p>
<p>I think three things are missing for anyone wanting to run hosted
payloads or patch software in orbit safely:</p>
<ol>
<li>
<p><strong>Hardware-enforced memory isolation</strong> between payloads and
flight software, either through a hypervisor (like Xen or KVM) or
a separation kernel (seL4 has a formal proof of functional
correctness on specific hardware configurations). Both use the
MMU to ensure a compromised payload cannot reach the bus.</p>
</li>
<li>
<p><strong>A standard OTA deployment format</strong> so &quot;install this application&quot;
means the same thing across different satellites: cryptographically
signed, designed for 10-minute LEO pass windows and partial
transfers.</p>
</li>
<li>
<p><strong>A metered runtime</strong> that enforces resource quotas (CPU, memory,
storage, bus bandwidth) so one payload cannot starve the others.
Resource requirements should be declarative, embedded in the
deployment image, and verified before installation.</p>
</li>
</ol>
<p>The tools to address much of this exist in the terrestrial world:
memory-safe languages (<a href="https://msrc.microsoft.com/blog/2019/07/we-need-a-safer-systems-programming-approach/">roughly 70% of CVEs</a>
in large C/C++ codebases are memory-safety issues, a figure consistent
across Microsoft, Google, and Android since 2019), verified cryptography,
minimal single-purpose OS images. These are not theoretical: Google
<a href="https://security.googleblog.com/2024/09/eliminating-memory-safety-vulnerabilities-Android.html">cut Android memory-safety vulnerabilities by 76%</a>
in six years by writing new code in memory-safe languages, and AWS
runs millions of serverless workloads on
<a href="https://www.usenix.org/conference/nsdi20/presentation/agache">Firecracker</a>,
a 50,000-line Rust VMM that boots in under 125 ms. None of these
have made it into flight software yet, even as the number of
spacecraft in orbit (and the attack surface) has grown sharply.
<a href="https://doi.org/10.1109/SP46215.2023.10351029">Space Odyssey</a> examined
three satellites and found vulnerabilities in all of them, and those are
only the ones someone bothered to look for.</p>
<div class="my-6 flex flex-col items-center not-prose">
  <img src="https://gazagnaire.org/blog/images/satellite-cves.svg" alt="Mass launched to orbit versus publicly disclosed satellite software vulnerabilities, 2000-2025" class="max-w-2xl w-full">
  <p class="text-sm text-gray-500 mt-2 max-w-2xl text-center">Mass launched to orbit (blue) versus publicly disclosed satellite software vulnerabilities (red bars, from CVE/NVD and conference disclosures; <a href="https://gazagnaire.org/blog/images/satellite-cves.py" class="underline">data and sources</a>). The gap between the curves is the problem: launch volume has exploded, security scrutiny has barely started.</p>
</div>
<p>The evidence is mounting. None of the Space Odyssey satellites
had ASLR, stack canaries, or DEP; one had no authentication
on its telecommand interface. The Viasat/KA-SAT attack in February
2022 disrupted Ukrainian communications and 5,800 German wind
turbines, making the threat operational (Boschetti, Gordon and Falco,
<a href="https://doi.org/10.2514/6.2022-4380">ASCEND 2022</a>). At Black Hat
2025, a
<a href="https://visionspace.com/nasa-cfs-version-aquila-software-vulnerability-assessment/">vulnerability assessment</a>
of NASA's core Flight System (cFS) found remote code execution,
path traversal, and denial-of-service, all from textbook C memory
bugs. NASA's own
<a href="https://github.com/nasa/CryptoLib/security">CryptoLib</a>, the
reference implementation of CCSDS encryption, has had recurring
buffer overflows in its parsing code
(<a href="https://github.com/nasa/CryptoLib/security/advisories/GHSA-q2pc-c3jx-3852">CVE-2025-29909</a>,
CVSS 9.8). A memory-safe language eliminates these classes of bug
by construction.</p>
<p>The pattern across all of these is consistent: space software
engineering has a safety-versus-security bias (Pavur and Martinovic,
<a href="https://doi.org/10.1093/cybsec/tyac008">J. Cybersecur. 2022</a>;
Falco, <a href="https://doi.org/10.2514/1.I010693">JAIS 2019</a>). Systems are
designed for availability and determinism (watchdogs, radiation
tolerance, FDIR). Integrity and confidentiality are secondary. This
is not irrational: a satellite that loses attitude control is a more
immediate problem than one that leaks telemetry. But it leaves
software stacks undefended against adversarial threats. Jero et al.
(<a href="https://doi.org/10.14722/spacesec.2024.23015">NDSS SpaceSec 2024</a>)
proposed a defence-in-depth taxonomy -- secure boot, memory
protection, authenticated updates, compartmentalisation -- that
overlaps substantially with the three gaps above.</p>
<p>So why does the current stack not provide the three things above?
Most small-sat payload software runs on
<a href="https://www.windriver.com/products/vxworks">VxWorks</a>,
<a href="https://www.rtems.org/">RTEMS</a>, embedded Linux
(<a href="https://www.yoctoproject.org/">Yocto</a>,
<a href="https://buildroot.org/">Buildroot</a>), or bare metal. The RTOS path
typically runs everything in a single address space: the hardware has
an MMU, but most CubeSat missions do not enable memory protection
because it requires rethinking memory management, interrupt handling,
and DMA buffer allocation. This is exactly the architecture Space
Odyssey found vulnerable. Embedded Linux gives you process isolation,
but hardening it for multi-tenancy and certifying it for flight
remains a substantial undertaking. ESA's
<a href="https://www.esa.int/Enabling_Support/Operations/OPS-SAT">OPS-SAT</a>
demonstrated deploying new applications before its re-entry in 2024,
but it remains the exception.</p>
<p>The isolation and metering techniques are not new. Cloud
infrastructure solved analogous problems years ago, and avionics
systems (ARINC 653, DO-178C) have their own qualified solutions. The
gap is in LEO payload software, where neither stack fits: the cloud
stack assumes abundant resources, the avionics stack assumes a single
operator and a multi-year qualification budget. I am not going to
minimise how much work qualification (under ECSS-Q-ST-80C or
equivalent) requires. Calabrese,
Kavallieratos and Falco
(<a href="https://doi.org/10.2514/6.2024-0270">SCITECH 2024</a>) emulated a
cyberattack from a hosted payload on OPS-SAT that compromised the
bus, demonstrating why isolation matters. But a real multi-tenant
satellite also needs FDIR (Fault Detection, Isolation, and Recovery)
integration, thermal management, power budgeting, and link budget
allocation. I am focusing on the software infrastructure, but I do
not want to pretend the problem ends there.</p>
<p>The regulatory pressure is new. The EU Cyber Resilience Act is
pushing toward stronger isolation and update mechanisms.
<a href="https://www.enisa.europa.eu/publications/space-threat-landscape">ENISA</a>
is calling out the space sector. The White House
<a href="https://tarides.com/blog/2024-03-07-a-time-for-change-our-response-to-the-white-house-cybersecurity-press-release/">called for memory-safe languages</a>
in critical infrastructure in 2024, a recommendation that applies
to flight software as much as to anything on the ground. OCaml, the
language Parsimoni and Tarides use, is memory-safe in its default
fragment. And the hardware is finally there:
radiation-tolerant processors with enough compute for on-board
processing are commercially available at CubeSat price points. The
missing piece is the software infrastructure.</p>
<p>These are the problems I co-founded
<a href="https://parsimoni.co/">Parsimoni</a> to work on. Our payload software
platform, SpaceOS, builds on the OCaml ecosystem that
<a href="https://tarides.com/blog/2023-12-14-ocaml-memory-safety-and-beyond/">Tarides maintains</a>.
Our first payload
reached orbit on SpaceX Transporter-13 in March 2025. If you are
building payload software and running into these constraints, or if
you are an operator considering hosted payloads, we would like to
hear from you: <a href="https://parsimoni.co/index.html#contact">get in touch</a>.</p>
]]></description>
      <link>https://gazagnaire.org/blog/2026-02-25-satellite-software.html</link>
      <guid isPermaLink="false">https://gazagnaire.org/blog/2026-02-25-satellite-software.html</guid>
      <dc:creator><![CDATA[Thomas Gazagnaire]]></dc:creator>
      <pubDate>Wed, 25 Feb 2026 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title><![CDATA[From ASPLOS to Orbit: Unikernels Twelve Years Later]]></title>
      <description><![CDATA[<p>Our 2013 ASPLOS paper,
&quot;<a href="https://doi.org/10.1145/2451116.2451167">Unikernels: Library Operating Systems for the Cloud</a>&quot;,
received a <a href="https://anil.recoil.org/notes/unikernels-test-of-time">test-of-time
award</a> in
March 2025. The title says &quot;for the Cloud.&quot; We wrote it while I was
in <a href="https://www.cl.cam.ac.uk/~jac22/">Jon Crowcroft</a>'s group at the University of Cambridge. The core
idea: instead of running an application on a general-purpose OS,
compile the application and only the OS libraries it needs into a
single sealed image that runs directly on a hypervisor. No kernel, no
shell, no unused drivers. Our DNS server image was 200 KB. The BIND
appliance it replaced was over 400 MB.</p>
<p>Five properties fell out of that architecture. None of them are
unique to unikernels (a careful Yocto configuration can achieve most
of them), but unikernels make them the default. I think they hold up
better now than they did in the cloud:</p>
<ol>
<li><strong>Sealed images.</strong> The binary is fixed at compile time. No runtime
package installation, no configuration files, no shell to log into.</li>
<li><strong>Dead code elimination.</strong> If the application does not use the
filesystem, the filesystem is not in the binary.</li>
<li><strong>Single address space.</strong> One application, one address space (no
internal process isolation, the hypervisor provides isolation
between unikernels).</li>
<li><strong>Configuration is compilation.</strong> Network addresses, TLS
certificates, and firewall rules are baked in at build time. No
configuration parser at runtime means no configuration parser to
exploit.</li>
<li><strong>Small trusted computing base.</strong> The TCB is the hypervisor plus
the application. No general-purpose kernel, no init system, no
sshd.</li>
</ol>
<div  class="my-8 not-prose">
<div >
<div >
  <div >Application</div>
  <div >System libraries</div>
  <div >Unused packages</div>
  <div >Shell, sshd, cron</div>
  <div >OS kernel</div>
  <div >Hypervisor</div>
</div>
<p >Traditional VM</p>
</div>
<div >
<div >
  <div >Application + OS libs</div>
  <div >OCaml runtime</div>
  <div >Hypervisor</div>
</div>
<p >MirageOS unikernel</p>
</div>
</div>
<p>Anil, Balraj and I co-founded Unikernel Systems to bring this to
production.
<a href="https://www.mosaicventures.com/blog/the-story-of-our-investment-in-docker-via-unikernel-systems-and-why-enterprises-are-running-their-business-on-their-commercial-platform">Docker acquired us three months later</a>.
At Docker, we built
<a href="https://www.docker.com/blog/how-docker-desktop-networking-works-under-the-hood/">Docker Desktop</a>
from scratch, adding <a href="https://mirageos.org/">MirageOS</a> unikernel
components to the networking stack
via <a href="https://github.com/moby/vpnkit">vpnkit</a> (we wrote an <a href="https://doi.org/10.1145/3747525">ICFP
paper</a> about how that works).
Millions of developers use it daily. Meanwhile, containers won the
cloud and <a href="https://unikraft.com/">Unikraft</a> took the unikernel
deployment model in a POSIX-compatible direction for serverless. The
unikernel-as-product did not take over (yet!), but the libraries shipped
further than we ever expected.</p>
<p>In 2021, when <a href="https://tarides.com/">Tarides</a> joined Cyber@Station F,
I pitched unikernels to over thirty internal teams at Thales: cyber,
compliance, transport, defence, ... Most were politely interested. The one that
clicked was Régis de Ferluc at
<a href="https://www.thalesaleniaspace.com/">Thales Alenia Space</a>. His
reaction was not &quot;that is interesting&quot; but &quot;that is how we already
build embedded systems, but done in a principled way (and where you
can safely introduce dynamic behaviour).&quot;</p>
<div class="image-grid grid grid-cols-1 sm:grid-cols-2 gap-4 my-8 not-prose">
  <figure class="m-0 cursor-pointer">
    <a href="https://gazagnaire.org/blog/images/asplos25-award.jpg"><img class="w-full max-h-64 object-cover object-bottom rounded-lg" src="https://gazagnaire.org/blog/images/asplos25-award.jpg" alt="Richard Mortier accepting the ASPLOS test-of-time award in Rotterdam"></a>
    <figcaption class="text-xs text-gray-500 mt-2 leading-tight">Richard Mortier accepting the ASPLOS test-of-time award in Rotterdam (2025).</figcaption>
  </figure>
  <figure class="m-0 cursor-pointer">
    <a href="https://gazagnaire.org/blog/images/tas.jpg"><img class="w-full max-h-64 object-cover rounded-lg" src="https://gazagnaire.org/blog/images/tas.jpg" alt="Early whiteboard session with Régis de Ferluc at TAS Cannes"></a>
    <figcaption class="text-xs text-gray-500 mt-2 leading-tight">Early whiteboard session with Régis de Ferluc at TAS Cannes, evaluating MirageOS components for space (2022).</figcaption>
  </figure>
</div>
<p>He was right. Satellite flight software ships
as fixed binaries, qualified on the ground, no shell access in orbit,
no runtime configuration changes. The five properties above are not
innovations in space, they are requirements. What satellite software
does not have is the type safety, the tooling, and the library
ecosystem that <a href="https://ocaml.org/">OCaml</a> and MirageOS provide.</p>
<p>Régis pushed us to look deeper, introduced us to EU programmes
(ORCHIDE via Horizon Europe, CEOS), and
<a href="https://parsimoni.co/blog/2023-07-31-ocaml-in-space-welcome-spaceos.html">SpaceOS</a>
was born. <a href="https://www.linkedin.com/in/miklostomka/">Miklos</a> and I co-founded
<a href="https://parsimoni.co/">Parsimoni</a> to build it.</p>
<p>The ASPLOS paper asked whether sealed, single-purpose images could
improve cloud infrastructure. Twelve years later, I think the more
interesting question is whether those same properties matter more in
constrained environments (satellites, hardware security modules,
embedded controllers) where every kilobyte counts, you cannot ssh in
after deployment, and &quot;no unused code&quot; is not an optimisation but a
qualification requirement.</p>
]]></description>
      <link>https://gazagnaire.org/blog/2026-02-23-asplos-unikernels.html</link>
      <guid isPermaLink="false">https://gazagnaire.org/blog/2026-02-23-asplos-unikernels.html</guid>
      <dc:creator><![CDATA[Thomas Gazagnaire]]></dc:creator>
      <pubDate>Mon, 23 Feb 2026 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title><![CDATA[F Prime Looks a Lot Like MirageOS (but in C++)]]></title>
      <description><![CDATA[<p>Last week I attended the
<a href="https://gazagnaire.org/blog/2026-02-17-los-angeles.html">F Prime workshop at JPL</a>, over 100
people, from CubeSat student teams to flagship mission engineers. I
learned a lot about F Prime, and I kept noticing how familiar the
concepts felt. This post is some of my thoughts on why.</p>
<p><a href="https://nasa.github.io/fprime/">F Prime</a> (<a href="https://github.com/nasa/fprime">GitHub</a>) is NASA's open-source
framework for building <em>reusable</em> flight software. Before it, most
missions started from scratch or copy-pasted code from previous
ones. It already flies on
<a href="https://mars.nasa.gov/technology/helicopter/">Ingenuity</a> (Mars
Helicopter),
<a href="https://www.jpl.nasa.gov/missions/cadre">CADRE</a> (autonomous lunar
rovers), and <a href="https://europa.nasa.gov/">Europa Clipper</a>. It is trying to
bring standard software engineering practices (modularity, unit
testing, reusability, continuous integration) to a domain that has
historically resisted them.</p>
<p>The framework has its own modelling language called
<a href="https://nasa.github.io/fpp/fpp-users-guide.html">FPP</a> (F Prime
Prime). You describe your system in FPP (components, ports, state
machines, topologies) and the toolchain generates thousands of lines
of C++ for you (plus a fair amount of CMake glue to wire the build
together). That is the point: you write the architecture, not the
boilerplate. If you have ever worked with MirageOS, all of this should sound
oddly familiar.</p>
<p>For those who do not know,
<a href="https://mirageos.org/">MirageOS</a> (<a href="https://github.com/mirage/mirage">GitHub</a>) is a library operating system where
the entire application, from the network stack to the storage layer,
is built from OCaml modules wired together by functors. The runtime
is minimal (Solo5 provides about ten hypercalls), no general-purpose
OS, no libc, just typed interfaces all the way down. Our
<a href="https://doi.org/10.1145/2451116.2451167">ASPLOS 2013 paper</a>
received the
<a href="https://anil.recoil.org/notes/unikernels-test-of-time">Influential Paper Award</a>
in 2025. I think F Prime and MirageOS share a surprising number of
ideas. Here is how I see the two relate.</p>
<p><strong>Components are module types.</strong> In F Prime, you define a component
by declaring its ports, typed interfaces that connect it to the
rest of the system. The FPP paper puts it nicely: a port &quot;has a type
and a kind; the type is like a function signature.&quot; Components have
no compile- or link-time dependencies on each other: each component
depends only on the types of the ports that it uses.</p>
<p>FPP distinguishes three kinds of components: passive (called
synchronously by the caller), queued (has an internal message queue
but no thread of its own), and active (has its own thread that
drains its queue). This is a concurrency model baked into the
component types:</p>
<div >
<div >
<pre><code class="language-fpp">passive component Thermometer {
  sync input port cmdIn: Fw.Cmd
  output port tlmOut: Fw.Tlm
  telemetry Temperature: F32
}
</code></pre>
<p >FPP: a passive component declares typed ports.</p>
</div>
<div >
<pre><code class="language-ocaml">module type THERMOMETER = sig
  type t
  val cmd_in : t -&gt; Cmd.t -&gt; unit
  val tlm_out : t -&gt; Tlm.t
  val temperature : t -&gt; float
end
</code></pre>
<p >OCaml: a module type declares the same interface.</p>
</div>
</div>
<p>Both say the same thing: anything that calls itself a thermometer
must accept commands, emit telemetry, and report a temperature. The
ports are the function signatures. The component type is the module
type.</p>
<p>The mapping is suggestive, not exact. FPP ports have directionality
(input vs output) and invocation kinds (sync, async, guarded) that a
flat OCaml signature does not enforce. In MirageOS we used phantom
types on device connectors to recover some of this structure (see
<a href="https://arxiv.org/abs/1905.02529">Radanne, Gazagnaire et al., 2019</a>)
but the parallel is clear enough to be useful.</p>
<p>The concurrency story is interesting too. F Prime's
active/passive/queued distinction maps loosely to what OCaml has been
working through for years. A passive component is a plain function
call. An active component has its own thread that drains a message
queue. Compare:</p>
<div >
<div >
<pre><code class="language-fpp">active component Logger {
  async input port logIn: Fw.Log
}
</code></pre>
<p >FPP: an active component has its own thread.</p>
</div>
<div >
<pre><code class="language-ocaml">module type LOGGER = sig
  type t
  val log_in : t -&gt; Log.t -&gt; unit Lwt.t
end
</code></pre>
<p >OCaml: <code>Lwt.t</code> marks the call as asynchronous.</p>
</div>
</div>
<p>In FPP, a component is either passive, queued, or active. In OCaml,
you can mix synchronous and asynchronous functions in the same module
signature: some values return <code>unit</code>, others return <code>unit Lwt.t</code>. The
concurrency model is per-function, not per-component. Queued
components sit in between, an event loop without a dedicated thread.
OCaml has been moving from monadic concurrency (<code>Lwt.t</code>) to
<a href="https://ocaml.org/manual/effects.html">effect handlers</a> in OCaml 5,
which delegate scheduling to a library
like <a href="https://github.com/ocaml-multicore/eio">Eio</a> without colouring
every type signature. F Prime bakes the concurrency model into the
component kind; OCaml delegates it to the application scheduler.</p>
<p><strong>State machines are GADTs.</strong> This one is not specific to MirageOS,
it is about OCaml's type system more broadly. FPP has built-in
state machine support (states, signals, guards, and transitions).
Here is a door controller (from the
<a href="https://nasa.github.io/fpp/fpp-users-guide.html">FPP User's Guide</a>):</p>
<div >
<div >
<pre><code class="language-fpp">state machine Door {
  signal open
  signal close
  guard isLocked

  initial enter Closed

  state Closed {
    on open if isLocked enter Closed
    on open enter Open
  }

  state Open {
    on close enter Closed
  }
}
</code></pre>
<p >FPP: a door with two states and a guard.</p>
</div>
<div >
<img src="https://gazagnaire.org/blog/images/door-sm.svg" alt="Door state machine" >
<p >The generated state machine diagram.</p>
</div>
</div>
<p>In OCaml, you can encode the same transitions as a GADT. The type
parameters track which state you are in and which state a signal
takes you to:</p>
<div >
<div >
<pre><code class="language-ocaml">type closed
type opened

type _ state =
  | Closed : closed state
  | Open : opened state

type (_, _) signal =
  | Open  : (closed, opened) signal
  | Close : (opened, closed) signal

type guard = Locked | Unlocked

let step : type a b. a state -&gt; (a, b) signal -&gt; guard
    -&gt; (b state, a state) result =
  fun state signal guard -&gt;
    match state, signal, guard with
    | Closed, Open, Locked   -&gt; Error state
    | Closed, Open, Unlocked -&gt; Ok Open
    | Open, Close, _         -&gt; Ok Closed
</code></pre>
<p >OCaml: the GADT encodes valid transitions in the types. The guard returns a result: you either advance or stay put.</p>
</div>
</div>
<p>The type <code>(closed, opened) signal</code> means: this signal is only valid
from the <code>closed</code> state, and it produces the <code>opened</code> state. Try to
close an already-closed door and the compiler rejects it. The guard
is a runtime check (just like in FPP), but the result type makes the
self-loop explicit: <code>Error state</code> means the guard blocked and you
stayed where you were. FPP's state machine compiler does the same
checks at the FPP level; the GADT pushes them into OCaml's own type
system.</p>
<p><strong>The wiring is where they diverge.</strong> How you describe the way all
these components connect into a running system is where the two
frameworks take different paths.</p>
<p>In F Prime, you define a <em>topology</em>: a
wiring diagram that connects component instances through their ports,
the way an engineer connects chips on a board. Sub-topologies let you
group and reuse partial wirings (think of them as sub-circuits). The
FPP compiler checks that port types match, then the autocoder
generates C++ and a fair amount of CMake glue. For the final assembly,
users customise init sequences, thread priorities, and buffer sizes
through C++ templates and build rules. There are many knobs to turn.</p>
<div >
<div >
<pre><code class="language-fpp">topology Mission {
  instance sensor: Sensors.Thermometer
  instance dispatcher: Svc.CmdDispatcher

  connections command {
    dispatcher.compCmdSend -&gt; sensor.cmdIn
  }
}
</code></pre>
<p >FPP: a topology wires component instances through their ports.</p>
</div>
<div >
<pre><code class="language-ocaml">module Mission
    (Sensor : THERMOMETER)
    (Dispatcher : CMD_DISPATCHER) = struct
  let dispatch sensor cmd =
    Sensor.cmd_in sensor cmd
  let init sensor =
    Dispatcher.register (dispatch sensor)
end
</code></pre>
<p >OCaml: a functor wires modules through their signatures.</p>
</div>
</div>
<p>In MirageOS, a <em>functor</em> is a function from modules to modules: you
pass a module satisfying some signature, and you get a new module
back. The functor is the sub-topology. People write functor
applications by hand all the time in OCaml, and it works fine. But
in MirageOS we wanted to automate redeployment across different
hypervisors and driver sets (Xen, KVM, Solo5, each with their own
network and storage stacks), so we built
<a href="https://arxiv.org/abs/1905.02529">Functoria</a>, an eDSL that
describes the assemblage and generates the build rules and functor
applications for each target. That is structurally closer to what
F Prime's autocoder does: both take a high-level wiring description
and produce glue code for a specific target.</p>
<p>Both check that the wiring is type-correct, but in different places:
FPP in its own compiler, OCaml in the host language's type system.
FPP gives you a graph-oriented model that maps naturally to how
electronic engineers think. Functoria gives you composability
(functors are first-class language constructs), but the resulting
code can get... involved. (Who said Irmin in the back? :p)</p>
<p>The unit of compute seems settled: small typed components, explicit
async I/O, function types as interfaces. The global wiring is not. I
have seen it spawn build system rules (Makefile spaghetti),
domain-specific languages (FPP, Functoria), and language-specific support (functors).
<a href="https://doi.org/10.1145/361598.361623">Parnas (1972)</a> told us to
hide information behind interfaces. Nobody told us how to wire a
thousand of them together ;-)</p>
]]></description>
      <link>https://gazagnaire.org/blog/2026-02-19-nasa-fprime.html</link>
      <guid isPermaLink="false">https://gazagnaire.org/blog/2026-02-19-nasa-fprime.html</guid>
      <dc:creator><![CDATA[Thomas Gazagnaire]]></dc:creator>
      <pubDate>Thu, 19 Feb 2026 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title><![CDATA[New Year, New Blog]]></title>
      <description><![CDATA[<p>Hello world, finally this is live :-)</p>
<p>The last couple of weeks have been pretty intense as I've been moving
to LA with my family. I am spending six months here, working on
<a href="https://parsimoni.co/">Parsimoni</a> and getting closer to the US space
industry.</p>
<p>Last week I visited NASA's <a href="https://www.jpl.nasa.gov/">Jet Propulsion Laboratory (JPL)</a> and saw
Voyager 2's control room -- still running after 48 years.
<a href="https://mars.nasa.gov/resources/26340/optimism-in-jpls-mars-yard/">Optimism</a>,
Perseverance's ground twin, was rolling over Pasadena sand in a test
enclosure next door. I also attended the
<a href="https://nasa.github.io/fprime/">F Prime</a> workshop and completed two
workshops on flight software engineering. F Prime is NASA's open-source
flight software framework. Over 100 people attended -- university and
student teams, internal JPL product teams, and large projects like
<a href="https://www.nasa.gov/game-changing-development-projects/high-performance-spaceflight-computing-hpsc/">HPSC</a>.
Only a small bunch of us were not from the US.</p>
<div class="image-grid grid grid-cols-1 sm:grid-cols-3 gap-4 my-8 not-prose">
  <figure class="m-0 cursor-pointer">
    <a href="https://gazagnaire.org/blog/images/IMG_0410.jpeg"><img class="w-full aspect-[4/3] object-cover rounded-lg" src="https://gazagnaire.org/blog/images/IMG_0410.jpeg" alt="Charles Elachi Mission Control Center at JPL"></a>
    <figcaption class="text-xs text-gray-500 mt-2 leading-tight">Charles Elachi Mission Control Center at JPL. The right screen reads VGR2 +48 YY.</figcaption>
  </figure>
  <figure class="m-0 cursor-pointer">
    <a href="https://gazagnaire.org/blog/images/IMG_0395.jpeg"><img class="w-full aspect-[4/3] object-cover rounded-lg" src="https://gazagnaire.org/blog/images/IMG_0395.jpeg" alt="Optimism rover at JPL"></a>
    <figcaption class="text-xs text-gray-500 mt-2 leading-tight">Optimism, Perseverance's ground twin, in the JPL test enclosure.</figcaption>
  </figure>
  <figure class="m-0 cursor-pointer">
    <a href="https://gazagnaire.org/blog/images/IMG_0344.jpeg"><img class="w-full aspect-[4/3] object-cover rounded-lg" src="https://gazagnaire.org/blog/images/IMG_0344.jpeg" alt="F Prime workshop at JPL"></a>
    <figcaption class="text-xs text-gray-500 mt-2 leading-tight">The F Prime workshop at JPL.</figcaption>
  </figure>
</div>
<p>The recurring theme in every conversation: flying a helicopter on Mars
is now routine, but deploying shared payload software to a satellite is still
real science fiction (no pressure!).</p>
<p>On the <a href="https://tarides.com/">Tarides</a> side, the team continues to
maintain and develop the OCaml platform -- opam, Dune, Merlin, odoc
-- while I am on a different timezone. Lots of things are
happening (see the <a href="https://tarides.com/blog/">Tarides blog</a>) and many
more are planned for 2026. In a world where people write apps by
chatting with AI bots, core language tools are even more important to make
sure we keep trust in our software systems (more on this later in this
blog, hopefully).</p>
<p>I intend to write here more regularly this year -- about SpaceOS,
the OCaml platform, and what happens when you try to put unikernels
in orbit. Stay tuned.</p>
]]></description>
      <link>https://gazagnaire.org/blog/2026-02-17-los-angeles.html</link>
      <guid isPermaLink="false">https://gazagnaire.org/blog/2026-02-17-los-angeles.html</guid>
      <dc:creator><![CDATA[Thomas Gazagnaire]]></dc:creator>
      <pubDate>Tue, 17 Feb 2026 00:00:00 GMT</pubDate>
    </item>
  </channel>
</rss>