<?xml version="1.0" encoding="UTF-8"?>
  <?xml-stylesheet type="text/xsl" href="rfc2629.xslt" ?>
  <!-- generated by https://github.com/cabo/kramdown-rfc version 1.7.39 (Ruby 3.4.8) -->


<!DOCTYPE rfc  [
  <!ENTITY nbsp    "&#160;">
  <!ENTITY zwsp   "&#8203;">
  <!ENTITY nbhy   "&#8209;">
  <!ENTITY wj     "&#8288;">

]>


<rfc ipr="trust200902" docName="draft-projecttick-mmco-mmcs-00" category="info" tocInclude="true" sortRefs="true" symRefs="true">
  <front>
    <title abbrev="MMCO/MMCS">The MMCO Module Component Object and MMCS Composite Security Format</title>

    <author initials="" surname="" fullname="Mehmet Samet Duman">
      <organization>Project Tick</organization>
      <address>
        <email>yongdohyun@projecttick.org</email>
        <uri>https://projecttick.org/</uri>
      </address>
    </author>

    <date year="2026"/>

    <area>Applications</area>
    <workgroup>Independent Submission</workgroup>
    <keyword>plugin</keyword> <keyword>module</keyword> <keyword>shared library</keyword> <keyword>OpenPGP</keyword> <keyword>code signing</keyword> <keyword>SPDX</keyword>

    <abstract>


<?line 82?>

<t>This document specifies two cooperating formats used by the MeshMC
launcher to discover, validate, and load third-party native code
modules at run time:</t>

<t><list style="symbols">
  <t>MMCO (MMCO Module Component Object), a host-native dynamic library
container with a fixed C ABI describing the module's metadata,
dependencies, lifecycle entry points, and runtime context.</t>
  <t>MMCS (MMCO Module Composite Security), an OpenPGP-based detached
signature trailer appended to an MMCO file, together with the
license-driven verification policy that decides whether a given
module is permitted to load.</t>
</list></t>

<t>The two formats are layered: MMCS is defined strictly on top of MMCO
and never modifies the bytes that the host operating system parses as
a shared object. A conforming MMCO implementation <bcp14>MAY</bcp14> ignore MMCS and
still load OSI-approved open-source modules; a conforming MMCS
implementation <bcp14>MUST</bcp14> refuse to load a module whose trailer is present
but does not verify against a trusted key.</t>

<t>This document is intended as a stable reference for independent
implementers of MMCO toolchains, plugin authors, and packagers.</t>



    </abstract>



  </front>

  <middle>


<?line 106?>

<section anchor="introduction"><name>Introduction</name>

<t>The MeshMC launcher loads third-party functionality at run time from
self-contained native code modules called MMCO files. Each module is a
host-native shared library (ELF <xref target="ELF"/> on Linux, Mach-O <xref target="MACHO"/> on
macOS, PE <xref target="PE"/> on Windows) that exports a fixed set of C symbols
describing its identity, its required ABI version, its declared
dependencies on other modules, and three lifecycle entry points.</t>

<t>Native code loaded into the host process carries the same authority
as the host itself. Distributing such code therefore requires a
verifiable trust path between the module's bytes on disk and the
identity of its author. MMCS provides that trust path by appending a
detached OpenPGP signature <xref target="RFC4880"/> (or its successor <xref target="RFC9580"/>)
to the end of an MMCO file in a fixed-layout trailer, and by applying
a license-aware policy that distinguishes mandatory-signature modules
(typically proprietary) from optional-signature modules (under
OSI-approved open-source licenses <xref target="OSI"/>).</t>

<t>This document specifies both formats in a single normative
reference. <xref target="mmco"/> defines MMCO. <xref target="mmcs"/> defines MMCS as a layer on
top of MMCO. <xref target="interactions"/> describes their interaction during
discovery, verification, dependency resolution, and lifecycle. <xref target="iana"/>
registers the file extension, magic numbers, and hook identifier
ranges. <xref target="security"/> discusses the threat model and known weaknesses.</t>

<section anchor="requirements-language"><name>Requirements Language</name>

<t>The key words "<bcp14>MUST</bcp14>", "<bcp14>MUST NOT</bcp14>", "<bcp14>REQUIRED</bcp14>", "<bcp14>SHALL</bcp14>", "<bcp14>SHALL
NOT</bcp14>", "<bcp14>SHOULD</bcp14>", "<bcp14>SHOULD NOT</bcp14>", "<bcp14>RECOMMENDED</bcp14>", "<bcp14>NOT RECOMMENDED</bcp14>",
"<bcp14>MAY</bcp14>", and "<bcp14>OPTIONAL</bcp14>" in this document are to be interpreted as
described in BCP 14 <xref target="RFC2119"/> <xref target="RFC8174"/> when, and only when, they
appear in all capitals, as shown here.</t>

<?line -18?>

<t>The terms "<bcp14>MUST</bcp14>", "<bcp14>MUST NOT</bcp14>", "<bcp14>SHOULD</bcp14>", "<bcp14>SHOULD NOT</bcp14>", and "<bcp14>MAY</bcp14>" in
this document are to be interpreted as described in <xref target="RFC2119"/> and
<xref target="RFC8174"/> when, and only when, they appear in all capitals.</t>

</section>
<section anchor="terminology"><name>Terminology</name>

<dl>
  <dt>Host:</dt>
  <dd>
    <t>The process that loads MMCO modules. In the canonical
implementation, this is the MeshMC launcher binary.</t>
  </dd>
  <dt>Module:</dt>
  <dd>
    <t>A single MMCO file. Also called a "plugin" colloquially.</t>
  </dd>
  <dt>ABI:</dt>
  <dd>
    <t>Application Binary Interface; the set of C symbols, struct layouts,
calling conventions, and version constants that the host and a
module agree on at load time.</t>
  </dd>
  <dt>Trailer:</dt>
  <dd>
    <t>The MMCS-defined byte range appended to an MMCO file containing the
detached signature and the framing footer.</t>
  </dd>
  <dt>Payload:</dt>
  <dd>
    <t>The contiguous byte range from offset 0 up to (but not including)
the trailer. The payload is what the host operating system parses
as a shared object, and is also the exact byte range covered by
the MMCS signature.</t>
  </dd>
  <dt>OSS module:</dt>
  <dd>
    <t>A module whose <spanx style="verb">license</spanx> field carries an SPDX expression
<xref target="SPDX"/> that resolves to at least one OSI-approved
<xref target="OSI"/> identifier under the rules of <xref target="spdx-eval"/>.</t>
  </dd>
  <dt>Trusted key:</dt>
  <dd>
    <t>An OpenPGP public key present in the host-configured keyring at
signature verification time.</t>
  </dd>
</dl>

</section>
</section>
<section anchor="mmco"><name>MMCO Module Component Object</name>

<t>An MMCO module is a host-native shared library that conforms to all
of the following:</t>

<t><list style="numbers" type="1">
  <t>The host operating system's shared-object format (ELF, Mach-O, or
PE), unmodified at the byte ranges the host loader parses.</t>
  <t>The MMCO C ABI defined in <xref target="abi"/>.</t>
  <t>The exported-symbol contract defined in <xref target="symbols"/>.</t>
</list></t>

<t>A file is <bcp14>RECOMMENDED</bcp14> to use the <spanx style="verb">.mmco</spanx> extension. Hosts <bcp14>MUST NOT</bcp14>
require any particular extension and <bcp14>MUST</bcp14> identify modules by parsing
the exported <spanx style="verb">mmco_module_info</spanx> symbol (see <xref target="symbols"/>).</t>

<section anchor="file-container"><name>File Container</name>

<t>An MMCO file is the concatenation of two byte ranges:</t>

<figure><artwork><![CDATA[
   0                                          payload_size
   +------------------------------------------+
   |             MMCO payload                 |
   |  (ELF / Mach-O / PE shared object)       |
   +------------------------------------------+
   payload_size                              file_size
   +------------------------------------------+
   |   MMCS trailer (OPTIONAL — see {{mmcs}}) |
   +------------------------------------------+
]]></artwork></figure>

<t>When no MMCS trailer is present, <spanx style="verb">payload_size == file_size</spanx>. The
MMCS trailer is fully described in <xref target="mmcs"/>.</t>

<t>A conforming MMCO loader <bcp14>MUST</bcp14> be able to load a module whose file
ends exactly at <spanx style="verb">payload_size</spanx> (no trailer present). A conforming
MMCO loader <bcp14>MUST</bcp14> tolerate, without error, additional bytes appended
to the payload by an MMCS layer it understands, provided those bytes
do not change any byte the operating system loader parses. In
practice, the operating-system loader reads only sections referenced
by the program header table, none of which extend past <spanx style="verb">payload_size</spanx>
for shared objects produced by current ELF, Mach-O, or PE linkers;
the MMCS trailer therefore appears as opaque tail bytes to the OS
loader.</t>

</section>
<section anchor="abi"><name>ABI</name>

<t>The MMCO ABI is identified by a 32-bit magic number and a 32-bit
version number declared as preprocessor constants:</t>

<texttable>
      <ttcol align='left'>Constant</ttcol>
      <ttcol align='left'>Value</ttcol>
      <ttcol align='left'>Notes</ttcol>
      <c><spanx style="verb">MMCO_MAGIC</spanx></c>
      <c><spanx style="verb">0x4D4D434F</spanx></c>
      <c>ASCII "MMCO" (little-endian on disk).</c>
      <c><spanx style="verb">MMCO_ABI_VERSION</spanx></c>
      <c><spanx style="verb">2</spanx></c>
      <c>Incremented for incompatible changes.</c>
      <c><spanx style="verb">MMCO_EXTENSION</spanx></c>
      <c><spanx style="verb">".mmco"</spanx></c>
      <c><bcp14>RECOMMENDED</bcp14> file-name suffix.</c>
</texttable>

<t>Both constants are also embedded as fields of the <spanx style="verb">MMCOModuleInfo</spanx>
structure exported by every module (see <xref target="moduleinfo"/>). A host <bcp14>MUST</bcp14>
reject a module whose embedded <spanx style="verb">magic</spanx> field is not equal to
<spanx style="verb">MMCO_MAGIC</spanx>. A host <bcp14>MUST</bcp14> reject a module whose embedded
<spanx style="verb">abi_version</spanx> field is not equal to the host's compiled-in
<spanx style="verb">MMCO_ABI_VERSION</spanx>.</t>

<t>The ABI version is a single integer; semver-style ranges are not
honoured. ABI changes that add new fields at the end of a struct, or
new function pointers at the end of a context struct, are considered
incompatible and <bcp14>MUST</bcp14> bump <spanx style="verb">MMCO_ABI_VERSION</spanx>. This document
specifies <spanx style="verb">MMCO_ABI_VERSION == 2</spanx>.</t>

<section anchor="symbol-visibility"><name>Symbol Visibility</name>

<t>The host <bcp14>MUST</bcp14> resolve module symbols via the operating-system dynamic
loader's exported-symbol table. Modules <bcp14>MUST</bcp14> mark their exported
symbols with default visibility:</t>

<t><list style="symbols">
  <t>On ELF and Mach-O targets, modules <bcp14>MUST</bcp14> use
<spanx style="verb">__attribute__((visibility("default")))</spanx>.</t>
  <t>On PE targets, modules <bcp14>MUST</bcp14> use <spanx style="verb">__declspec(dllexport)</spanx>.</t>
</list></t>

<t>A reference implementation defines <spanx style="verb">MMCO_EXPORT</spanx> to expand to the
appropriate attribute for the build target.</t>

</section>
<section anchor="symbols"><name>Required Exported Symbols</name>

<t>Every MMCO module <bcp14>MUST</bcp14> export the following three symbols with C
linkage. Names are case-sensitive and reserved:</t>

<texttable>
      <ttcol align='left'>Symbol</ttcol>
      <ttcol align='left'>Type / Signature</ttcol>
      <c><spanx style="verb">mmco_module_info</spanx></c>
      <c><spanx style="verb">MMCOModuleInfo</spanx> (object, not function)</c>
      <c><spanx style="verb">mmco_init</spanx></c>
      <c><spanx style="verb">int  mmco_init(MMCOContext *ctx)</spanx></c>
      <c><spanx style="verb">mmco_unload</spanx></c>
      <c><spanx style="verb">void mmco_unload(void)</spanx></c>
</texttable>

<t>The host <bcp14>MUST</bcp14> resolve <spanx style="verb">mmco_module_info</spanx> before invoking any other
entry point. The host <bcp14>MUST</bcp14> validate the <spanx style="verb">magic</spanx> and <spanx style="verb">abi_version</spanx>
fields of <spanx style="verb">mmco_module_info</spanx> before resolving <spanx style="verb">mmco_init</spanx> or
<spanx style="verb">mmco_unload</spanx>. If either symbol is missing, the host <bcp14>MUST</bcp14> unload the
module without invoking any entry point.</t>

<t><spanx style="verb">mmco_init</spanx> is invoked exactly once per module, after all the
module's hard dependencies (see <xref target="dependencies"/>) have been
successfully initialized. It <bcp14>MUST</bcp14> return 0 on success. A non-zero
return value <bcp14>MUST</bcp14> be interpreted by the host as initialization
failure. On initialization failure, the host:</t>

<t><list style="symbols">
  <t><bcp14>MUST NOT</bcp14> subsequently dispatch any hook callback into that module.</t>
  <t><bcp14>MUST</bcp14> mark the module as not-initialized for the remainder of the
host's lifetime.</t>
  <t><bcp14>MAY</bcp14> (but is not required to) close the underlying shared library
immediately. The reference implementation closes it (subject to
the <spanx style="verb">RTLD_NODELETE</spanx> caveat described in <xref target="loading"/>).</t>
  <t><bcp14>SHOULD NOT</bcp14> call <spanx style="verb">mmco_unload</spanx> on a module whose <spanx style="verb">mmco_init</spanx>
returned non-zero, because <spanx style="verb">mmco_unload</spanx> is contracted as the
tear-down of a successfully-initialized module. A module that
fails initialization is responsible for releasing the resources
it has already acquired before returning non-zero.</t>
</list></t>

<t><spanx style="verb">mmco_unload</spanx> is invoked exactly once per successfully-initialized
module, in the reverse of the initialization order, during host
shutdown. It <bcp14>MUST NOT</bcp14> call back into the host's MMCO API: by the
time <spanx style="verb">mmco_unload</spanx> runs, the host has already begun tearing down
the resources backing the function pointers in <spanx style="verb">MMCOContext</spanx>.</t>

</section>
<section anchor="moduleinfo"><name>MMCOModuleInfo Structure</name>

<t>The <spanx style="verb">mmco_module_info</spanx> symbol is an object of type <spanx style="verb">MMCOModuleInfo</spanx>,
laid out as follows in C. All pointer fields point to objects of
static storage duration owned by the module; the module <bcp14>MUST</bcp14> keep
them valid until <spanx style="verb">mmco_unload</spanx> returns.</t>

<figure><sourcecode type="c"><![CDATA[
struct MMCOModuleInfo {
    uint32_t              magic;             /* = MMCO_MAGIC       */
    uint32_t              abi_version;       /* = MMCO_ABI_VERSION */
    const char           *name;              /* UTF-8, non-NULL    */
    const char           *version;           /* UTF-8, non-NULL    */
    const char           *author;            /* UTF-8 or NULL      */
    const char           *description;       /* UTF-8 or NULL      */
    const char           *license;           /* SPDX, or NULL      */
    uint32_t              flags;             /* reserved, MUST = 0 */
    const char           *code_link;         /* URI or NULL        */
    const char           *icon_set_resource; /* logical, or NULL   */
    const MMCODependency *dependencies;      /* or NULL if count=0 */
    uint32_t              dependency_count;
    const char           *signing_key_id;    /* OpenPGP id or NULL */
};
]]></sourcecode></figure>

<t>Field requirements:</t>

<dl>
  <dt><spanx style="verb">magic</spanx>:</dt>
  <dd>
    <t><bcp14>MUST</bcp14> equal <spanx style="verb">MMCO_MAGIC</spanx>. Used to detect accidentally-loaded
unrelated shared libraries.</t>
  </dd>
  <dt><spanx style="verb">abi_version</spanx>:</dt>
  <dd>
    <t><bcp14>MUST</bcp14> equal the host's <spanx style="verb">MMCO_ABI_VERSION</spanx>.</t>
  </dd>
  <dt><spanx style="verb">name</spanx>:</dt>
  <dd>
    <t>A non-empty, UTF-8 human-readable identifier. The combination of
<spanx style="verb">name</spanx> (case-insensitive) and the on-disk file name are both used
by the host for module identification; modules <bcp14>SHOULD</bcp14> ensure these
match so that the user-disable list (which is keyed on lowercased
<spanx style="verb">name</spanx>) and the dependency table (which is keyed on lowercased
<spanx style="verb">name</spanx>) refer to the same entity.</t>
  </dd>
  <dt><spanx style="verb">version</spanx>:</dt>
  <dd>
    <t>A UTF-8 string compared lexicographically segment-by-segment under
the algorithm of <xref target="version-compare"/>. The empty string and NULL
are equivalent and compare equal to themselves.</t>
  </dd>
  <dt><spanx style="verb">license</spanx>:</dt>
  <dd>
    <t>An SPDX license expression <xref target="SPDX"/> or NULL. NULL and the empty
string are treated identically by MMCS and <bcp14>MUST</bcp14> cause the module
to be classified as non-OSS (see <xref target="spdx-eval"/>).</t>
  </dd>
  <dt><spanx style="verb">flags</spanx>:</dt>
  <dd>
    <t>Reserved for future use. Modules <bcp14>MUST</bcp14> set this field to zero in
the absence of an allocated flag bit. Hosts <bcp14>MUST</bcp14> tolerate
unknown bits (i.e. <bcp14>MUST NOT</bcp14> refuse to load a module solely
because <spanx style="verb">flags</spanx> is non-zero) so that a future flag bit can be
introduced without invalidating older hosts. Future revisions of
this document <bcp14>MAY</bcp14> allocate specific bits and define their
semantics; once allocated, hosts implementing the new revision
<bcp14>MUST</bcp14> honour them.</t>
  </dd>
  <dt><spanx style="verb">code_link</spanx>:</dt>
  <dd>
    <t>An informational URI (typically https://) pointing to source code,
or NULL.</t>
  </dd>
  <dt><spanx style="verb">icon_set_resource</spanx>:</dt>
  <dd>
    <t>Logical name of a Qt-resource-bundled icon set inside the module,
or NULL. The host resolves icons via the path expression
<spanx style="verb">":/plugins/&lt;icon_set_resource&gt;/&lt;name&gt;"</spanx> at runtime.</t>
  </dd>
  <dt><spanx style="verb">dependencies</spanx>, <spanx style="verb">dependency_count</spanx>:</dt>
  <dd>
    <t>See <xref target="dependencies"/>.</t>
  </dd>
  <dt><spanx style="verb">signing_key_id</spanx>:</dt>
  <dd>
    <t>An informational identifier (typically an OpenPGP key fingerprint
or short id) of the key with which the module was signed, or NULL.
This field is purely a hint; the authoritative signing key is
whichever key the MMCS verifier extracts from the trailer
(see <xref target="mmcs"/>).</t>
  </dd>
</dl>

</section>
<section anchor="dependencies"><name>Dependencies</name>

<t>A module <bcp14>MAY</bcp14> declare dependencies on other MMCO modules via the
<spanx style="verb">dependencies</spanx> array. Each entry is laid out as follows:</t>

<figure><sourcecode type="c"><![CDATA[
struct MMCODependency {
    const char *name;         /* UTF-8, matched case-insensitively */
    const char *min_version;  /* SemVer-ish or NULL/""             */
    uint32_t    optional;     /* non-zero == optional dependency   */
};
]]></sourcecode></figure>

<t>Field requirements:</t>

<dl>
  <dt><spanx style="verb">name</spanx>:</dt>
  <dd>
    <t>The lowercased value <bcp14>MUST</bcp14> match the lowercased <spanx style="verb">name</spanx> field of the
intended dependency's <spanx style="verb">MMCOModuleInfo</spanx>.</t>
  </dd>
  <dt><spanx style="verb">min_version</spanx>:</dt>
  <dd>
    <t>Either NULL, the empty string, or a SemVer-ish version string.
When set, the resolved dependency's <spanx style="verb">version</spanx> <bcp14>MUST</bcp14> compare
greater-than-or-equal to <spanx style="verb">min_version</spanx> under <xref target="version-compare"/>.</t>
  </dd>
  <dt><spanx style="verb">optional</spanx>:</dt>
  <dd>
    <t>When non-zero, absence or version-mismatch of the dependency <bcp14>MUST
NOT</bcp14> cause the depending module to be marked unloadable; the host
<bcp14>MUST</bcp14> still attempt to load the depending module without the
dependency.</t>
  </dd>
</dl>

<t>The host <bcp14>MUST</bcp14> construct a directed acyclic graph from the union of
all modules' dependencies, <bcp14>MUST</bcp14> initialize modules in topological
order (so that every module sees its hard dependencies already
initialized in <spanx style="verb">mmco_init</spanx>), and <bcp14>MUST</bcp14> refuse to initialize any
module that participates in a cycle. The specific algorithm is
specified in <xref target="resolution"/>.</t>

</section>
<section anchor="version-compare"><name>Version Comparison</name>

<t>A version string is split on the characters <spanx style="verb">.</spanx>, <spanx style="verb">-</spanx>, <spanx style="verb">+</spanx>, and <spanx style="verb">_</spanx>,
yielding an ordered list of segments. Empty segments are removed.</t>

<t>To compare two segment lists <spanx style="verb">A</spanx> and <spanx style="verb">B</spanx>, walk them in parallel; for
each index <spanx style="verb">i</spanx>, compare the segments <spanx style="verb">A[i]</spanx> and <spanx style="verb">B[i]</spanx> (treating a
missing segment as the empty string). Segment comparison proceeds as
follows:</t>

<t><list style="symbols">
  <t>If both segments parse as non-negative integers, compare them
numerically.</t>
  <t>Otherwise compare them as Unicode strings, case-insensitively.</t>
</list></t>

<t>The first non-equal segment determines the result of the comparison.
If all segments compare equal, the lists are equal.</t>

<t>The empty version string (and NULL) compares equal to itself and is
treated as "less than" any non-empty version.</t>

<t>This algorithm is intentionally relaxed: it accepts common SemVer
inputs, "1.2.3a", "1.2.3-rc.1", "1.2.3+build.7", and dotted Java-style
versions, without requiring strict SemVer conformance.</t>

</section>
<section anchor="mmcocontext"><name>MMCOContext</name>

<t><spanx style="verb">mmco_init</spanx> receives a pointer to an <spanx style="verb">MMCOContext</spanx> instance owned by
the host. The first three fields of <spanx style="verb">MMCOContext</spanx> are normative
guard fields:</t>

<figure><sourcecode type="c"><![CDATA[
struct MMCOContext {
    uint32_t struct_size; /* host writes sizeof(MMCOContext)    */
    uint32_t abi_version; /* host writes MMCO_ABI_VERSION       */
    void    *module_handle;
    /* ... function pointers (see {{api-surface}}, informative) ... */
};
]]></sourcecode></figure>

<t>Field requirements:</t>

<dl>
  <dt><spanx style="verb">struct_size</spanx>:</dt>
  <dd>
    <t>The host <bcp14>MUST</bcp14> set this to <spanx style="verb">sizeof(MMCOContext)</spanx> as the host saw
the struct at compile time. Modules <bcp14>MAY</bcp14> use this to detect a
host built against a newer revision that grew <spanx style="verb">MMCOContext</spanx>
past the module's compile-time view, and refuse to dereference
function pointers that lie beyond the module's last known
field.</t>
  </dd>
  <dt><spanx style="verb">abi_version</spanx>:</dt>
  <dd>
    <t>The host <bcp14>MUST</bcp14> set this to <spanx style="verb">MMCO_ABI_VERSION</spanx>. Because the host
has already verified <spanx style="verb">mmco_module_info.abi_version</spanx> matches
before calling <spanx style="verb">mmco_init</spanx>, the two values are guaranteed equal
at this point. The redundancy is intentional: it gives a module
a single fail-safe assertion site at the very top of
<spanx style="verb">mmco_init</spanx>.</t>
  </dd>
  <dt><spanx style="verb">module_handle</spanx>:</dt>
  <dd>
    <t>Opaque host-owned cookie that identifies the calling module to
the host's API trampolines. Modules <bcp14>MUST</bcp14> treat this as opaque
and <bcp14>MUST</bcp14> pass it verbatim as the first argument to every
function pointer in <spanx style="verb">MMCOContext</spanx>. Hosts <bcp14>MUST</bcp14> guarantee that
<spanx style="verb">module_handle</spanx> is unique per module and stable for the
lifetime of the module's loaded state.</t>
  </dd>
</dl>

<t>The remaining fields are function pointers whose layout, names,
and semantics are part of the ABI defined by this revision but are
not enumerated normatively here. See <xref target="api-surface"/>.</t>

</section>
<section anchor="api-surface"><name>API Surface (Informative)</name>

<t>The full <spanx style="verb">MMCOContext</spanx> exposed to modules in
<spanx style="verb">MMCO_ABI_VERSION == 2</spanx> covers, at a minimum:</t>

<t><list style="symbols">
  <t>Sectioned logging (info, warn, error, debug).</t>
  <t>Hook registration and dispatch (see <xref target="hooks"/>).</t>
  <t>Per-module sandboxed settings and a read-only application
settings accessor.</t>
  <t>Instance, mod, world, account, and Java enumeration and mutation.</t>
  <t>Filesystem and archive helpers scoped to a per-module data
directory.</t>
  <t>HTTP GET / POST.</t>
  <t>UI builders for dialogs, pages, layouts, widgets, system-tray
icons, and main-window event filters.</t>
  <t>Launch modifiers (environment variables and wrapper commands)
scoped to the in-flight pre-launch hook.</t>
  <t>News-feed enumeration and management.</t>
</list></t>

<t>The exact signature and semantics of each function pointer in
<spanx style="verb">MMCOContext</spanx> are part of the host implementation rather than of
this format specification, and are therefore not enumerated
normatively in this document. They are, however, part of the
binary ABI identified by <spanx style="verb">MMCO_ABI_VERSION</spanx>: a host <bcp14>MUST NOT</bcp14>
change the order, count, or signature of any function pointer in
<spanx style="verb">MMCOContext</spanx> within a single ABI version. The hook payload
structures, by contrast, ARE normative for this revision and are
defined in <xref target="hook-payloads"/>.</t>

<t>Future revisions of this document <bcp14>MAY</bcp14> split the <spanx style="verb">MMCOContext</spanx>
specification into a companion reference.</t>

</section>
<section anchor="hooks"><name>Hooks</name>

<t>A module observes or modifies host behaviour by registering callback
functions against numeric hook identifiers. The current allocated
ranges, as of <spanx style="verb">MMCO_ABI_VERSION == 2</spanx>, are:</t>

<texttable>
      <ttcol align='left'>Range</ttcol>
      <ttcol align='left'>Purpose</ttcol>
      <c><spanx style="verb">0x0100–0x01FF</spanx></c>
      <c>Application lifecycle.</c>
      <c><spanx style="verb">0x0200–0x02FF</spanx></c>
      <c>Instance lifecycle.</c>
      <c><spanx style="verb">0x0300–0x03FF</spanx></c>
      <c>Settings.</c>
      <c><spanx style="verb">0x0400–0x04FF</spanx></c>
      <c>Content and mod management.</c>
      <c><spanx style="verb">0x0500–0x05FF</spanx></c>
      <c>Network.</c>
      <c><spanx style="verb">0x0600–0x06FF</spanx></c>
      <c>UI extension points.</c>
      <c><spanx style="verb">0x0700–0x07FF</spanx></c>
      <c>News.</c>
      <c><spanx style="verb">0x0800–0x08FF</spanx></c>
      <c>Authentication.</c>
</texttable>

<t>Hook identifiers in the range <spanx style="verb">0x0000–0x00FF</spanx> and <spanx style="verb">0xFF00–0xFFFF</spanx>
are reserved for future use. See <xref target="iana-hook"/> for the registry.</t>

<t>A registered hook callback has the signature:</t>

<figure><sourcecode type="c"><![CDATA[
typedef int (*MMCOHookCallback)(void     *module_handle,
                                uint32_t  hook_id,
                                void     *payload,
                                void     *user_data);
]]></sourcecode></figure>

<t>The callback return value carries a single piece of information,
"requested cancellation":</t>

<t><list style="symbols">
  <t>A return value of zero means "continue".</t>
  <t>A non-zero return value means "cancel".</t>
</list></t>

<t>The host <bcp14>MUST</bcp14> short-circuit hook dispatch on the first non-zero
return: when a callback returns non-zero, subsequently-registered
callbacks for the same hook identifier <bcp14>MUST NOT</bcp14> be invoked for the
same dispatch.</t>

<t>Whether cancellation has any externally-visible effect is a
property of the specific hook, not of the dispatcher. A hook
identifier is called "cancellable" if the host action that follows
the dispatch is contractually aborted when the dispatcher reports
cancellation. A hook identifier that is not cancellable is called
"observational": callbacks for an observational hook <bcp14>MAY</bcp14> return
non-zero, but the host <bcp14>MUST</bcp14> ignore the value for purposes of
aborting the surrounding action (it still short-circuits remaining
callbacks).</t>

<t>For <spanx style="verb">MMCO_ABI_VERSION == 2</spanx>, the cancellable hooks are:</t>

<texttable>
      <ttcol align='left'>Hook identifier</ttcol>
      <ttcol align='left'>Cancels</ttcol>
      <c><spanx style="verb">MMCO_HOOK_AUTH_REQUEST</spanx></c>
      <c>The in-flight authentication request.</c>
</texttable>

<t>All other hooks defined by this document are observational, even
those whose name contains "PRE". In particular,
<spanx style="verb">MMCO_HOOK_INSTANCE_PRE_LAUNCH</spanx> is observational: a non-zero
return short-circuits subsequent listeners but does not abort
the launch. Plugins that wish to abort a launch under this
revision <bcp14>MUST</bcp14> do so out-of-band (e.g. by raising a UI dialog
that prompts the user) before the launch reaches the pre-launch
hook.</t>

<t>The identifiers <spanx style="verb">MMCO_HOOK_CONTENT_PRE_DOWNLOAD</spanx> (<spanx style="verb">0x0400</spanx>) and
<spanx style="verb">MMCO_HOOK_NETWORK_PRE_REQUEST</spanx> (<spanx style="verb">0x0500</spanx>) are allocated in this
revision but the reference host does not yet dispatch them.
Hosts <bcp14>MAY</bcp14> dispatch them in future revisions; when dispatched,
they are intended to be cancellable. Plugins <bcp14>MAY</bcp14> register
against these identifiers under the current revision, but their
callbacks will not be invoked until the dispatch sites land in
a future host revision.</t>

<t>Future revisions of this document <bcp14>MAY</bcp14> promote currently-
observational hooks to cancellable status; doing so is
considered backward-compatible because callers that returned
zero continue to behave identically.</t>

<t>Payload pointers are owned by the host and valid only for the
duration of the callback invocation. Modules <bcp14>MUST</bcp14> copy any data
they wish to retain.</t>

<t>The complete list of hook identifiers and their payload structures
is defined normatively in <xref target="hook-payloads"/>.</t>

</section>
</section>
<section anchor="discovery"><name>Discovery</name>

<t>A host <bcp14>MUST</bcp14> scan a configurable, ordered list of directories for
candidate modules. The host <bcp14>MUST</bcp14> identify candidates by attempting
to open every regular file whose name ends in <spanx style="verb">MMCO_EXTENSION</spanx> and
which the operating-system loader accepts as a shared object.</t>

<t>The host <bcp14>MUST</bcp14> de-duplicate discovered modules by the lowercased
basename (with the trailing <spanx style="verb">MMCO_EXTENSION</spanx> stripped). When two
candidates resolve to the same identifier, the host <bcp14>MUST</bcp14> retain the
first one discovered in the configured directory order and <bcp14>MUST</bcp14>
unload the duplicate.</t>

<t>Recommended default directories (informative; per-platform):</t>

<t><list style="symbols">
  <t>ELF hosts: the directory <spanx style="verb">mmcmodules</spanx> alongside the host
binary, then <spanx style="verb">$HOME/.local/lib/mmcmodules</spanx>, then
<spanx style="verb">$HOME/.local/share/&lt;application&gt;/mmcmodules</spanx>, then
<spanx style="verb">/usr/local/lib/mmcmodules</spanx>, then <spanx style="verb">/usr/lib/mmcmodules</spanx>.</t>
  <t>Windows hosts: the directory <spanx style="verb">mmcmodules</spanx> alongside the host
binary, then a per-user <spanx style="verb">mmcmodules</spanx> directory inside the
platform's writable app-data location
(<spanx style="verb">%LOCALAPPDATA%\&lt;application&gt;\mmcmodules</spanx> in practice).</t>
  <t>macOS hosts: <spanx style="verb">Contents/Resources/mmcmodules</spanx> inside the
application bundle. The bundle location
<spanx style="verb">Contents/PlugIns/mmcmodules</spanx> is the conventional Apple choice
for plug-in code, but is unsuitable for MMCO because Apple's
<spanx style="verb">codesign --strict</spanx> validator walks <spanx style="verb">Contents/PlugIns/</spanx>
recursively and refuses to accept any Mach-O object that
carries trailing bytes past <spanx style="verb">__LINKEDIT</spanx> (which an MMCS
trailer does). Hosts on macOS therefore install MMCO modules
under <spanx style="verb">Contents/Resources/</spanx>, which <spanx style="verb">codesign</spanx> treats as opaque
data and seals via <spanx style="verb">_CodeSignature/CodeResources</spanx> without
attempting to parse the contents as code. The <spanx style="verb">Contents/MacOS</spanx>
directory is also unsuitable, because Apple treats every
non-main-binary Mach-O found there as a subcomponent of the
main executable and requires it to carry its own Apple
signature. Hosts <bcp14>MAY</bcp14> additionally probe the legacy locations
<spanx style="verb">Contents/PlugIns/mmcmodules</spanx> and <spanx style="verb">Contents/MacOS/mmcmodules</spanx>
as read-only fallbacks for installations that predate this
layout.</t>
</list></t>

<t>Search-path ordering is significant: candidates discovered in an
earlier directory take precedence over duplicates discovered in
a later directory (<xref target="discovery"/>, second paragraph). Hosts that
accept user-supplied extra directories <bcp14>SHOULD</bcp14> insert them ahead
of the built-in defaults so that user-installed overrides shadow
system-installed copies.</t>

<t>The host <bcp14>MUST NOT</bcp14> consult <spanx style="verb">LD_LIBRARY_PATH</spanx>, <spanx style="verb">DYLD_LIBRARY_PATH</spanx>,
<spanx style="verb">PATH</spanx>, or any similar environment variable for module
discovery, because doing so would allow an unprivileged process
to inject a module by side-effect on a privileged host invocation.</t>

</section>
<section anchor="loading"><name>Loading</name>

<t>For each candidate file, the host <bcp14>MUST</bcp14>:</t>

<t><list style="numbers" type="1">
  <t>Open the shared object via the operating-system dynamic loader
(<spanx style="verb">dlopen</spanx>, <spanx style="verb">LoadLibraryW</spanx>, or equivalent), with flags equivalent
to <spanx style="verb">RTLD_NOW | RTLD_LOCAL</spanx>. On ELF hosts, <spanx style="verb">RTLD_NODELETE</spanx> <bcp14>SHOULD</bcp14>
be set; see <xref target="rtld-nodelete-rationale"/> for the rationale.</t>
  <t>Resolve <spanx style="verb">mmco_module_info</spanx>. If the symbol is absent, or its
<spanx style="verb">magic</spanx> differs from <spanx style="verb">MMCO_MAGIC</spanx>, or its <spanx style="verb">abi_version</spanx> differs
from <spanx style="verb">MMCO_ABI_VERSION</spanx>, the host <bcp14>MUST</bcp14> close the library and
discard the candidate.</t>
  <t>Resolve <spanx style="verb">mmco_init</spanx> and <spanx style="verb">mmco_unload</spanx>. If either is absent, the
host <bcp14>MUST</bcp14> close the library and discard the candidate.</t>
  <t>Perform the MMCS trust pre-flight specified in <xref target="policy"/>. If
the pre-flight marks the module as unloadable, the host <bcp14>MUST</bcp14>
retain the loaded library handle (so its metadata can be
inspected by administrative tooling) but <bcp14>MUST NOT</bcp14> subsequently
invoke <spanx style="verb">mmco_init</spanx> on it.</t>
</list></t>

<t>After all candidates are processed and the dependency resolver
(<xref target="resolution"/>) has produced an order, the host <bcp14>MUST</bcp14> invoke
<spanx style="verb">mmco_init</spanx> exactly once on each enabled module, in resolver
order. If <spanx style="verb">mmco_init</spanx> returns non-zero, the host <bcp14>MUST</bcp14> mark the
module as not-initialized and skip it for the remainder of the
host's lifetime, per the requirements in <xref target="symbols"/>.</t>

<section anchor="rtld-nodelete-rationale"><name>Static-Storage Rationale</name>

<t>The <spanx style="verb">RTLD_NODELETE</spanx> recommendation in step 1 prevents the C
runtime from running the module's global destructors at process
exit (or at a subsequent <spanx style="verb">dlclose</spanx> call). This is required when
the module statically links any object whose destructor mutates
process-wide state shared with the host: such destructors would
run twice (once from the host binary's tear-down and once from
the module's) and corrupt the shared state on the second pass.</t>

<t>Modules that link only against the public MMCO SDK
(<xref target="api-surface"/>) and against shared libraries that the host
itself uses (e.g. Qt, libc, OpenSSL) are not subject to this
hazard, because they do not introduce duplicate definitions. The
reference implementation nevertheless applies <spanx style="verb">RTLD_NODELETE</spanx>
universally, on the grounds that:</t>

<t><list style="symbols">
  <t>The cost is bounded (a small amount of resident memory per
loaded module retained until process exit).</t>
  <t>It removes a load-time ordering hazard for plugin authors who
may, in good faith, statically link a helper library that
later turns out to be incompatible with destructor re-runs.</t>
</list></t>

<t>A host <bcp14>MAY</bcp14> omit <spanx style="verb">RTLD_NODELETE</spanx> if it can establish that no such
duplicate-static-state hazard exists in its plugin ecosystem.</t>

</section>
</section>
<section anchor="resolution"><name>Dependency Resolution</name>

<t>The host <bcp14>MUST</bcp14> resolve the load order using a topological sort over
the dependency DAG. Implementations are <bcp14>RECOMMENDED</bcp14> to use Kahn's
algorithm <xref target="KAHN-TOPO"/>. The algorithm operates as follows:</t>

<t><list style="numbers" type="1">
  <t>Build a name-to-index map over the discovered modules, keyed on
the lowercased <spanx style="verb">name</spanx> field.</t>
  <t>For each module M that is not already disabled, for each
declared dependency D of M:  <vspace blankLines='1'/>
a. If D is not present in the map, and D is non-optional, mark M
   disabled with reason <spanx style="verb">DependencyMissing</spanx>.
b. Else if the resolved D is already disabled, and D is
   non-optional, mark M disabled with reason <spanx style="verb">DependencyMissing</spanx>.
c. Else if the resolved D's <spanx style="verb">version</spanx> compares less than D's
   <spanx style="verb">min_version</spanx>, and D is non-optional, mark M disabled with
   reason <spanx style="verb">DependencyMissing</spanx>.
d. Else, add an edge from D to M in the DAG.</t>
  <t>Initialize a queue with every enabled module of in-degree zero.</t>
  <t>While the queue is non-empty: dequeue a module, append it to the
load order, and decrement the in-degree of each enabled
successor; enqueue successors that reach in-degree zero.</t>
  <t>Any enabled module not visited by the walk participates in a
cycle. The host <bcp14>MUST</bcp14> mark such modules disabled with reason
<spanx style="verb">DependencyCycle</spanx>.</t>
</list></t>

<t>The host <bcp14>MUST</bcp14> honour pre-existing disable flags (e.g. set by the
MMCS pre-flight or by user configuration) and <bcp14>MUST</bcp14> propagate
<spanx style="verb">DependencyMissing</spanx> to anything that depended on a disabled module.</t>

</section>
<section anchor="sandbox"><name>Per-Module Sandbox</name>

<t>The host <bcp14>MUST</bcp14> expose to every module a private, isolated view of
two host-managed resources: a settings namespace and a filesystem
directory. The intent is to give modules a stable place to keep
small amounts of state without colliding with other modules or
with the host's own configuration.</t>

<section anchor="module-id"><name>Module Identity</name>

<t>For the purposes of sandboxing, each module is identified by a
case-sensitive UTF-8 token derived from the on-disk file name:
take the basename of the module's file path, then strip the
<spanx style="verb">.mmco</spanx> suffix if present. This identifier (the "module id") is
distinct from the human-readable <spanx style="verb">name</spanx> field of
<spanx style="verb">MMCOModuleInfo</spanx>; the latter <bcp14>MAY</bcp14> contain spaces and is intended
for display, whereas the module id is filesystem-safe and
intended for namespacing.</t>

</section>
<section anchor="settings-sandbox"><name>Settings Sandbox</name>

<t>The host <bcp14>MUST</bcp14> namespace every per-module setting under a
host-internal key of the form <spanx style="verb">plugin.&lt;module_id&gt;.&lt;key&gt;</spanx>. A
module that requests the setting key <spanx style="verb">foo</spanx> <bcp14>MUST</bcp14> receive the
value of the host setting <spanx style="verb">plugin.&lt;module_id&gt;.foo</spanx>, and only
that value; it <bcp14>MUST NOT</bcp14> be able, through the per-module settings
API, to read or write any host setting outside its own
namespace.</t>

<t>The host <bcp14>MAY</bcp14> additionally expose a separate read-only accessor
for global application settings, distinct from the per-module
setter/getter. The reference implementation provides such an
accessor under the name <spanx style="verb">app_setting_get</spanx>.</t>

</section>
<section anchor="fs-sandbox"><name>Filesystem Sandbox</name>

<t>The host <bcp14>MUST</bcp14> allocate, on first request, a unique per-module
directory at a stable path of the form <spanx style="verb">&lt;base&gt;/plugin-data/&lt;module_id&gt;/</spanx>.
The choice of <spanx style="verb">&lt;base&gt;</spanx> is platform-specific:</t>

<t><list style="symbols">
  <t>ELF hosts: <spanx style="verb">$HOME/.local/share/&lt;application&gt;</spanx> is <bcp14>RECOMMENDED</bcp14>.</t>
  <t>Windows hosts: the platform's writable application-data
location (<spanx style="verb">%APPDATA%\&lt;application&gt;\</spanx> in practice).</t>
  <t>macOS hosts: <spanx style="verb">~/Library/Application Support/&lt;application&gt;</spanx> is
conventional.</t>
</list></t>

<t>The per-module data directory <bcp14>MUST</bcp14> exist when <spanx style="verb">mmco_init</spanx> is
invoked. The host <bcp14>MUST</bcp14> provide module-facing filesystem helpers
that resolve relative paths against the per-module directory.</t>

<t>A host <bcp14>MAY</bcp14> additionally provide unrestricted filesystem helpers
that take absolute paths; such helpers grant the same authority
as direct system calls from within the module and are intended
for plugins that legitimately need to operate outside their
sandbox (e.g. mod managers writing into instance directories).
Those helpers are outside the security boundary of <xref target="sandbox"/>
and are governed by the broader trust model in <xref target="security"/>.</t>

</section>
<section anchor="disable-list"><name>User-Disable List</name>

<t>The host <bcp14>MUST</bcp14> persist an end-user-controlled set of disabled
module names across launches. The reference implementation
stores this set under the host setting key <spanx style="verb">plugins.disabled</spanx>
as a comma-separated list of lowercased module names. The
host:</t>

<t><list style="symbols">
  <t><bcp14>MUST</bcp14> treat the comparison against discovered modules as
case-insensitive.</t>
  <t><bcp14>MUST</bcp14> accept either the lowercased <spanx style="verb">name</spanx> field of
<spanx style="verb">MMCOModuleInfo</spanx> or the module id (<xref target="module-id"/>) as a match
against the disable list.</t>
  <t><bcp14>MUST</bcp14> mark a matched module with disable reason
<spanx style="verb">UserDisabled</spanx>. The module is still loaded (so its metadata
is visible to administrative tooling) but its <spanx style="verb">mmco_init</spanx> is
not invoked.</t>
  <t><bcp14>SHOULD</bcp14> warn the user that toggling the disable list takes
effect on the next host restart, because modules are not
unloaded mid-session.</t>
</list></t>

</section>
</section>
<section anchor="shutdown"><name>Shutdown</name>

<t>During host shutdown, the host <bcp14>MUST</bcp14> call <spanx style="verb">mmco_unload</spanx> on every
initialized module in the reverse of the load order produced by
<xref target="resolution"/>. After all <spanx style="verb">mmco_unload</spanx> calls return, the host <bcp14>MAY</bcp14>
release the underlying shared-library handles. Modules <bcp14>SHOULD NOT</bcp14>
rely on the host calling <spanx style="verb">dlclose</spanx>, because <spanx style="verb">RTLD_NODELETE</spanx> may be
in effect.</t>

</section>
</section>
<section anchor="mmcs"><name>MMCS Composite Security</name>

<t>MMCS specifies how a detached OpenPGP signature is attached to an
MMCO file, how the host extracts and verifies it, and the
license-driven policy that decides whether a module is allowed to
load.</t>

<t>MMCS is layered cleanly on top of MMCO: it never modifies the MMCO
payload bytes that the operating system loader parses. An MMCO host
that does not implement MMCS <bcp14>MAY</bcp14> load any module whose license is
OSI-approved; conversely, an MMCS-aware host <bcp14>MUST</bcp14> refuse to load a
module whose trailer is present but does not verify.</t>

<section anchor="trailer"><name>Trailer Layout</name>

<t>When an MMCS trailer is present, it is appended verbatim to the end
of the MMCO payload and is structured as follows:</t>

<figure><artwork><![CDATA[
   payload_size                       file_size - 12
   +---------------------------------------+
   |   ASCII-armored detached OpenPGP      |
   |   signature, N bytes                  |
   +---------------------------------------+
   file_size - 12                    file_size - 4
   +---------------------------------------+
   |   uint64_t signature_size (= N), LE   |
   +---------------------------------------+
   file_size - 4                     file_size
   +---------------------------------------+
   |   uint32_t trailer_magic, LE          |
   +---------------------------------------+
]]></artwork></figure>

<t>Constants:</t>

<texttable>
      <ttcol align='left'>Constant</ttcol>
      <ttcol align='left'>Value</ttcol>
      <ttcol align='left'>Notes</ttcol>
      <c><spanx style="verb">MMCO_TRAILER_MAGIC</spanx></c>
      <c><spanx style="verb">0x53434D4D</spanx></c>
      <c>ASCII "MMCS", little-endian.</c>
</texttable>

<t>Both the <spanx style="verb">signature_size</spanx> field and the <spanx style="verb">trailer_magic</spanx> field <bcp14>MUST</bcp14>
be stored little-endian on disk regardless of the host architecture.</t>

<t>The signature itself <bcp14>MUST</bcp14> be an OpenPGP detached signature, as
defined by Section 5.2.3 (signature packets) and Section 11.4
(detached signatures) of <xref target="RFC4880"/> (or the equivalent sections
of <xref target="RFC9580"/>). The signature <bcp14>MAY</bcp14> be in ASCII-armored form
(Section 6 of <xref target="RFC4880"/>) or in binary form. Producers <bcp14>SHOULD</bcp14>
emit ASCII armor so that the trailer can be extracted and
inspected with standard text tools; verifiers <bcp14>MUST</bcp14> accept both
forms.</t>

<t>The signed data is exactly the contiguous byte range from offset
0 to <spanx style="verb">payload_size</spanx>; that is, the MMCO payload as written by the
linker, with no transformation, no canonicalisation, and no
inclusion of the trailer itself.</t>

<t>The combined size of the trailing footer is exactly 12 bytes
(<spanx style="verb">sizeof(uint64_t) + sizeof(uint32_t)</spanx>).</t>

</section>
<section anchor="extract"><name>Trailer Extraction</name>

<t>To extract an MMCS trailer from a file <spanx style="verb">F</spanx>, a host <bcp14>MUST</bcp14>:</t>

<t><list style="numbers" type="1">
  <t>Compute <spanx style="verb">file_size</spanx>. If <spanx style="verb">file_size &lt; 12</spanx>, no trailer is present;
the extraction terminates with status "absent".</t>
  <t>Read the final 12 bytes of <spanx style="verb">F</spanx> and parse them as
<spanx style="verb">(uint64_t signature_size, uint32_t magic)</spanx>, little-endian. If
<spanx style="verb">magic != MMCO_TRAILER_MAGIC</spanx>, no trailer is present;
terminate with status "absent".</t>
  <t>If <spanx style="verb">signature_size == 0</spanx> or
<spanx style="verb">signature_size &gt; file_size - 12</spanx>, the trailer is corrupt;
terminate with status "malformed".</t>
  <t>Compute <spanx style="verb">payload_size = file_size - 12 - signature_size</spanx>. Read
<spanx style="verb">payload_size</spanx> bytes from offset 0 (the payload) and the
following <spanx style="verb">signature_size</spanx> bytes (the signature). If either
short-reads, terminate with status "malformed".</t>
  <t>Otherwise, terminate with status "present", returning the
payload bytes and the signature bytes.</t>
</list></t>

<t>A trailer marked "malformed" <bcp14>MUST</bcp14> be treated by the policy
(<xref target="policy"/>) as equivalent to <spanx style="verb">BadSignature</spanx>.</t>

</section>
<section anchor="verify"><name>Signature Verification</name>

<t>A host <bcp14>MUST</bcp14> verify the extracted signature against the extracted
payload bytes using an OpenPGP <xref target="RFC4880"/> implementation
configured with a keyring of trusted public keys.</t>

<t>The keyring location is host-configurable. The reference
implementation exposes a host setting (named
<spanx style="verb">plugin.signing.keyring_path</spanx> in the reference INI schema) that
specifies an OpenPGP home directory; when the setting is unset or
the empty string, the implementation falls back to whatever
default the underlying OpenPGP backend uses (typically the
<spanx style="verb">GNUPGHOME</spanx> environment variable, falling back to <spanx style="verb">~/.gnupg</spanx>).</t>

<t>A host <bcp14>MAY</bcp14> further restrict trust beyond mere keyring
membership — for example, by requiring a particular trust level
or by pinning a specific fingerprint per module. Any such
restriction <bcp14>MUST</bcp14> be expressed as the <spanx style="verb">Untrusted</spanx> state in
<xref target="verify"/>, not as <spanx style="verb">BadSignature</spanx>, so that the license-driven
policy in <xref target="policy"/> treats the case uniformly.</t>

<t>The signed data passed to the OpenPGP verifier is exactly the
payload bytes recovered by <xref target="extract"/>: the contiguous byte
range from offset 0 to <spanx style="verb">payload_size</spanx>. The host <bcp14>MUST NOT</bcp14> apply
any line-ending or text canonicalisation. The OpenPGP <spanx style="verb">text-mode</spanx>
flag <bcp14>MUST NOT</bcp14> be set.</t>

<t>The result of verification <bcp14>MUST</bcp14> be classified into exactly one of
the following terminal states, as observed by the policy layer
(<xref target="policy"/>):</t>

<dl>
  <dt><spanx style="verb">Absent</spanx>:</dt>
  <dd>
    <t>No trailer is present in the file.</t>
  </dd>
  <dt><spanx style="verb">Valid</spanx>:</dt>
  <dd>
    <t>The signature parses correctly, verifies against the payload, and
was made by a key that is present in the trusted keyring with at
least the "valid trust" level.</t>
  </dd>
  <dt><spanx style="verb">Untrusted</spanx>:</dt>
  <dd>
    <t>The signature parses correctly and verifies against the payload,
but the signing key is not present in the trusted keyring (or is
present below the configured trust threshold).</t>
  </dd>
  <dt><spanx style="verb">BadSignature</spanx>:</dt>
  <dd>
    <t>The signature does not verify against the payload, or the
signature parses but is structurally invalid.</t>
  </dd>
  <dt><spanx style="verb">Malformed</spanx>:</dt>
  <dd>
    <t>The trailer footer matches <spanx style="verb">MMCO_TRAILER_MAGIC</spanx> but the trailer
cannot be parsed (e.g. <spanx style="verb">signature_size</spanx> exceeds file bounds).</t>
  </dd>
  <dt><spanx style="verb">Error</spanx>:</dt>
  <dd>
    <t>The verification backend is unavailable (e.g. the OpenPGP daemon
cannot be reached). This state <bcp14>MUST NOT</bcp14> be cached
(see <xref target="cache"/>).</t>
  </dd>
</dl>

<t>The host <bcp14>MUST</bcp14> treat <spanx style="verb">BadSignature</spanx> and <spanx style="verb">Malformed</spanx> identically for
policy purposes.</t>

</section>
<section anchor="policy"><name>License-Driven Policy</name>

<t>The MMCS verification policy is parameterised by:</t>

<t><list style="symbols">
  <t>The result of trailer extraction and signature verification
(<xref target="extract"/>, <xref target="verify"/>).</t>
  <t>Whether the module's <spanx style="verb">license</spanx> field resolves to an OSI-approved
open-source license under <xref target="spdx-eval"/>.</t>
</list></t>

<t>The policy matrix is:</t>

<texttable>
      <ttcol align='left'>&#160;</ttcol>
      <ttcol align='left'>Signature Valid</ttcol>
      <ttcol align='left'>Absent</ttcol>
      <ttcol align='left'>Untrusted</ttcol>
      <ttcol align='left'>BadSignature/Malformed</ttcol>
      <ttcol align='left'>Error</ttcol>
      <c>OSS license</c>
      <c>load</c>
      <c>load</c>
      <c>load</c>
      <c>refuse, <spanx style="verb">SignatureInvalid</spanx></c>
      <c>load</c>
      <c>Non-OSS / none</c>
      <c>load</c>
      <c>refuse, <spanx style="verb">SignatureRequired</spanx></c>
      <c>refuse, <spanx style="verb">SignatureRequired</spanx></c>
      <c>refuse, <spanx style="verb">SignatureInvalid</spanx></c>
      <c>refuse, <spanx style="verb">SignatureRequired</spanx></c>
</texttable>

<t>Justification:</t>

<t><list style="symbols">
  <t>A <spanx style="verb">Valid</spanx> signature is always sufficient: identity has been
cryptographically established and the host need not consult the
license.</t>
  <t>For OSS modules, source is publicly available and reviewable;
unsigned, untrusted, or backend-unavailable cases reduce to the
conventional risk model for OSI-approved software distribution
and are permitted.</t>
  <t>For non-OSS modules, identity attestation is required; any state
that fails to establish identity (including a backend outage)
<bcp14>MUST</bcp14> refuse the load.</t>
  <t><spanx style="verb">BadSignature</spanx> and <spanx style="verb">Malformed</spanx> are hard failures regardless of
license, because they indicate that an attacker may have tampered
with the trailer of a known-good non-OSS module. Allowing them
for OSS modules would create a downgrade attack in which a
proprietary module is repackaged under an OSS SPDX identifier
with an intentionally corrupt signature.</t>
</list></t>

<t>A module that is refused under this policy <bcp14>MUST</bcp14> be retained in the
host's loaded-but-disabled set, so that administrative tooling can
present a human-readable explanation. The host <bcp14>MUST NOT</bcp14> invoke
<spanx style="verb">mmco_init</spanx> on a refused module.</t>

</section>
<section anchor="spdx-eval"><name>SPDX Evaluation</name>

<t>The license check operates on the SPDX expression stored in the
module's <spanx style="verb">license</spanx> field. NULL and the empty string <bcp14>MUST</bcp14> be treated
as non-OSS.</t>

<t>The host <bcp14>MUST</bcp14> tokenise the expression as follows:</t>

<t><list style="numbers" type="1">
  <t>Convert the entire string to lowercase.</t>
  <t>Replace parenthesis characters with spaces.</t>
  <t>Split on whitespace runs. The tokens <spanx style="verb">or</spanx> and <spanx style="verb">and</spanx> are operator
tokens; they partition the remaining tokens into atoms.</t>
  <t>The token <spanx style="verb">with</spanx> is a non-operator token: it is concatenated
into the current atom together with the atom on either side, so
that <spanx style="verb">gpl-3.0-or-later with classpath-exception-2.0</spanx> becomes a
single atom rather than two.</t>
</list></t>

<t>An atom is considered OSS if it matches any identifier in the
OSS allow-list, or if the head of a <spanx style="verb">WITH</spanx>-prefixed atom matches an
identifier in the allow-list.</t>

<t>A module is OSS if at least one of its atoms is OSS.</t>

<t>The OSS allow-list <bcp14>MUST</bcp14> contain every identifier currently flagged
"OSI Approved" in the SPDX License List <xref target="SPDX-LICENSE-LIST"/>. The
allow-list <bcp14>MAY</bcp14> additionally contain a small set of widely-accepted
non-OSI libre identifiers (e.g. <spanx style="verb">cc0-1.0</spanx>, <spanx style="verb">unlicense</spanx>, <spanx style="verb">wtfpl</spanx>,
<spanx style="verb">vim</spanx>, <spanx style="verb">bsd-3-clause-clear</spanx>, <spanx style="verb">bsd-4-clause</spanx>). Implementations <bcp14>MUST
NOT</bcp14> remove identifiers from the allow-list, because doing so
retroactively breaks every module that ships under them.</t>

<t>The reference implementation's snapshot of the allow-list, taken
from SPDX License List version 3.24, is reproduced in <xref target="spdx-list"/>
of this document for unambiguous reproduction.</t>

</section>
<section anchor="cache"><name>Verification Cache</name>

<t>A host <bcp14>MAY</bcp14> maintain a persistent cache of verification results,
keyed on the tuple
<spanx style="verb">(absolute_path, file_size, file_mtime_milliseconds)</spanx>. Hosts that
maintain such a cache <bcp14>MUST</bcp14>:</t>

<t><list style="symbols">
  <t>Invalidate the entire cache whenever the host's trusted keyring
is changed, because the same payload bytes may legitimately
reach a different verdict under a different keyring.</t>
  <t>Refrain from caching the <spanx style="verb">Error</spanx> state. Transient backend
outages <bcp14>MUST NOT</bcp14> poison subsequent runs.</t>
  <t>Treat any read or write failure on the cache as a missing entry
rather than as a fatal error: cache faults <bcp14>MUST NOT</bcp14> prevent
verification from running on the slow path.</t>
</list></t>

<t>The cache is <bcp14>RECOMMENDED</bcp14> to live under the host's per-user
application-data directory (e.g.
<spanx style="verb">QStandardPaths::AppLocalDataLocation</spanx> on Qt-based hosts,
<spanx style="verb">$XDG_DATA_HOME/&lt;application&gt;/</spanx> on bare XDG hosts, or
<spanx style="verb">%LOCALAPPDATA%\&lt;application&gt;\</spanx> on Windows). The reference
implementation stores it as a file named
<spanx style="verb">plugin-signature-cache.json</spanx> in that directory.</t>

<t>The cache schema is informational and is documented here for
interoperability of administrative tooling. The reference
implementation uses JSON with the following shape:</t>

<figure><sourcecode type="json"><![CDATA[
{
  "schema": 1,
  "entries": [
    {
      "path":        "<absolute path>",
      "size":        <integer bytes>,
      "mtime_ms":    <integer milliseconds since epoch>,
      "state":       "Valid|Untrusted|BadSignature|Malformed|Absent",
      "detail":      "<free-form text>",
      "fingerprint": "<OpenPGP key fingerprint, uppercase hex>"
    }
  ]
}
]]></sourcecode></figure>

<t>The host <bcp14>MUST</bcp14> allow a cache bypass on demand (for administrative
"re-verify" operations). The reference implementation exposes
this through the host's plugins-management UI.</t>

</section>
<section anchor="signing"><name>Producing a Signed MMCO File</name>

<t>To produce a signed MMCO file from an unsigned payload <spanx style="verb">P</spanx>:</t>

<t><list style="numbers" type="1">
  <t>If <spanx style="verb">P</spanx> already ends in an MMCS trailer (as detected by reading
the final 12 bytes and matching <spanx style="verb">MMCO_TRAILER_MAGIC</spanx>), strip it
first, recovering the original payload bytes.</t>
  <t>Compute a detached, ASCII-armored OpenPGP signature <spanx style="verb">S</spanx> over the
stripped payload bytes, using the desired signing key.</t>
  <t>Write the concatenation <spanx style="verb">P || S || uint64_LE(len(S)) ||
uint32_LE(MMCO_TRAILER_MAGIC)</spanx> as the signed file.</t>
</list></t>

<t>This procedure is idempotent: applying it twice to the same file
with the same key yields a file whose signature covers the same
payload bytes (subject to OpenPGP signature non-determinism in the
timestamp field).</t>

<t>Tools that re-sign installed modules after the operating-system
installer has rewritten in-payload bytes (RPATH rewrites, debug
symbol stripping, code-signing surgery) <bcp14>MUST</bcp14> run after all such
rewrites complete. A signature computed before such rewrites will
always be invalidated.</t>

</section>
</section>
<section anchor="interactions"><name>Interactions</name>

<t>The host <bcp14>MUST</bcp14> execute the following sequence at startup, in order,
for each search directory:</t>

<t><list style="numbers" type="1">
  <t>Discover candidates (<xref target="discovery"/>).</t>
  <t>Open the shared library and read <spanx style="verb">mmco_module_info</spanx>
(<xref target="loading"/>).</t>
  <t>Validate <spanx style="verb">magic</spanx> and <spanx style="verb">abi_version</spanx>.</t>
  <t>Resolve <spanx style="verb">mmco_init</spanx>, <spanx style="verb">mmco_unload</spanx>.</t>
  <t>Extract the MMCS trailer (<xref target="extract"/>). Consult the cache
(<xref target="cache"/>) first; on miss, run signature verification and
memoise the terminal state (except <spanx style="verb">Error</spanx>).</t>
  <t>Apply the license-driven policy (<xref target="policy"/>) and, if it refuses
the module, mark it disabled.</t>
  <t>After all candidates have completed steps 1–6 across all
directories, run dependency resolution (<xref target="resolution"/>) over the
union, propagating disable states.</t>
  <t>Call <spanx style="verb">mmco_init</spanx> exactly once per enabled module in resolver
order.</t>
</list></t>

<t>During host shutdown, the inverse: call <spanx style="verb">mmco_unload</spanx> in reverse
resolver order, then release shared-library handles (subject to the
<spanx style="verb">RTLD_NODELETE</spanx> caveat in <xref target="loading"/>).</t>

<t>A host <bcp14>MUST NOT</bcp14> call <spanx style="verb">mmco_init</spanx> on any module marked disabled by
any step.</t>

</section>
<section anchor="iana"><name>IANA Considerations</name>

<t>This section requests two registrations and defines a third
internal registry.</t>

<section anchor="file-extension-and-magic-number-registration"><name>File-Extension and Magic-Number Registration</name>

<t>This document defines the file extension <spanx style="verb">.mmco</spanx> and the four-byte
magic number <spanx style="verb">0x4D, 0x4D, 0x43, 0x4F</spanx> (ASCII "MMCO") at offset 0 of
an MMCO file. Note that this magic number is in the host operating
system's shared-object header, not at offset 0 of the MMCO file
itself; offset 0 of the MMCO file is whatever the host OS's
shared-object format requires. The MMCO identity is instead
expressed via the embedded <spanx style="verb">mmco_module_info::magic</spanx> field. No
collision with existing offset-0 magic numbers is therefore
expected.</t>

<t>This document also defines the four-byte magic number
<spanx style="verb">0x4D, 0x4D, 0x43, 0x53</spanx> (ASCII "MMCS") as the trailing magic of an
MMCS trailer. Because this magic appears at the end of an MMCO
file, it does not collide with offset-0 registrations.</t>

</section>
<section anchor="iana-hook"><name>MMCO Hook Identifier Registry</name>

<t>This document defines an internal registry of MMCO hook identifiers.
Hook identifiers are 32-bit unsigned integers in the range
<spanx style="verb">0x0000–0xFFFF</spanx>. Allocations as of <spanx style="verb">MMCO_ABI_VERSION == 2</spanx>:</t>

<texttable>
      <ttcol align='left'>Range</ttcol>
      <ttcol align='left'>Status</ttcol>
      <ttcol align='left'>Reference</ttcol>
      <c><spanx style="verb">0x0000–0x00FF</spanx></c>
      <c>Reserved</c>
      <c>This document</c>
      <c><spanx style="verb">0x0100–0x01FF</spanx></c>
      <c>Allocated</c>
      <c>Application lifecycle</c>
      <c><spanx style="verb">0x0200–0x02FF</spanx></c>
      <c>Allocated</c>
      <c>Instance lifecycle</c>
      <c><spanx style="verb">0x0300–0x03FF</spanx></c>
      <c>Allocated</c>
      <c>Settings</c>
      <c><spanx style="verb">0x0400–0x04FF</spanx></c>
      <c>Allocated</c>
      <c>Content and mod management</c>
      <c><spanx style="verb">0x0500–0x05FF</spanx></c>
      <c>Allocated</c>
      <c>Network</c>
      <c><spanx style="verb">0x0600–0x06FF</spanx></c>
      <c>Allocated</c>
      <c>UI extension points</c>
      <c><spanx style="verb">0x0700–0x07FF</spanx></c>
      <c>Allocated</c>
      <c>News</c>
      <c><spanx style="verb">0x0800–0x08FF</spanx></c>
      <c>Allocated</c>
      <c>Authentication</c>
      <c><spanx style="verb">0x0900–0xFEFF</spanx></c>
      <c>Unassigned</c>
      <c>Future use</c>
      <c><spanx style="verb">0xFF00–0xFFFF</spanx></c>
      <c>Reserved</c>
      <c>Private experiments</c>
</texttable>

<t>New range allocations <bcp14>MUST</bcp14> be made in 256-identifier blocks aligned
on a multiple of <spanx style="verb">0x0100</spanx>. Allocation requires a published
description of the payload struct(s), the cancellation semantics
(for any identifier whose name contains "PRE"), and the lifecycle
constraints under which the host fires the hook.</t>

</section>
<section anchor="spdx-list"><name>SPDX OSI Allow-List Snapshot</name>

<t>This is a snapshot of the OSI-approved SPDX identifiers recognised
by the reference MMCS implementation, taken from SPDX License List
3.24. Identifiers are lowercase.</t>

<t><spanx style="verb">0bsd</spanx>, <spanx style="verb">aal</spanx>, <spanx style="verb">afl-1.1</spanx>, <spanx style="verb">afl-1.2</spanx>, <spanx style="verb">afl-2.0</spanx>, <spanx style="verb">afl-2.1</spanx>,
<spanx style="verb">afl-3.0</spanx>, <spanx style="verb">agpl-3.0</spanx>, <spanx style="verb">agpl-3.0-only</spanx>, <spanx style="verb">agpl-3.0-or-later</spanx>,
<spanx style="verb">apache-1.1</spanx>, <spanx style="verb">apache-2.0</spanx>, <spanx style="verb">apl-1.0</spanx>, <spanx style="verb">apsl-1.0</spanx>, <spanx style="verb">apsl-1.1</spanx>,
<spanx style="verb">apsl-1.2</spanx>, <spanx style="verb">apsl-2.0</spanx>, <spanx style="verb">artistic-1.0</spanx>, <spanx style="verb">artistic-1.0-cl8</spanx>,
<spanx style="verb">artistic-1.0-perl</spanx>, <spanx style="verb">artistic-2.0</spanx>, <spanx style="verb">bsd-1-clause</spanx>,
<spanx style="verb">bsd-2-clause</spanx>, <spanx style="verb">bsd-2-clause-patent</spanx>, <spanx style="verb">bsd-3-clause</spanx>,
<spanx style="verb">bsd-3-clause-lbnl</spanx>, <spanx style="verb">bsd-3-clause-modification</spanx>, <spanx style="verb">bsl-1.0</spanx>,
<spanx style="verb">cal-1.0</spanx>, <spanx style="verb">cal-1.0-combined-work-exception</spanx>, <spanx style="verb">catosl-1.1</spanx>,
<spanx style="verb">cddl-1.0</spanx>, <spanx style="verb">cddl-1.1</spanx>, <spanx style="verb">cecill-2.1</spanx>, <spanx style="verb">cern-ohl-p-2.0</spanx>,
<spanx style="verb">cern-ohl-s-2.0</spanx>, <spanx style="verb">cern-ohl-w-2.0</spanx>, <spanx style="verb">cnri-python</spanx>, <spanx style="verb">cpal-1.0</spanx>,
<spanx style="verb">cpl-1.0</spanx>, <spanx style="verb">cua-opl-1.0</spanx>, <spanx style="verb">ecl-1.0</spanx>, <spanx style="verb">ecl-2.0</spanx>, <spanx style="verb">efl-1.0</spanx>,
<spanx style="verb">efl-2.0</spanx>, <spanx style="verb">entessa</spanx>, <spanx style="verb">epl-1.0</spanx>, <spanx style="verb">epl-2.0</spanx>, <spanx style="verb">eudatagrid</spanx>,
<spanx style="verb">eupl-1.1</spanx>, <spanx style="verb">eupl-1.2</spanx>, <spanx style="verb">fair</spanx>, <spanx style="verb">frameworx-1.0</spanx>, <spanx style="verb">gpl-2.0</spanx>,
<spanx style="verb">gpl-2.0-only</spanx>, <spanx style="verb">gpl-2.0-or-later</spanx>, <spanx style="verb">gpl-3.0</spanx>, <spanx style="verb">gpl-3.0-only</spanx>,
<spanx style="verb">gpl-3.0-or-later</spanx>, <spanx style="verb">hpnd</spanx>, <spanx style="verb">intel</spanx>, <spanx style="verb">ipa</spanx>, <spanx style="verb">ipl-1.0</spanx>, <spanx style="verb">isc</spanx>,
<spanx style="verb">jam</spanx>, <spanx style="verb">lgpl-2.0</spanx>, <spanx style="verb">lgpl-2.0-only</spanx>, <spanx style="verb">lgpl-2.0-or-later</spanx>,
<spanx style="verb">lgpl-2.1</spanx>, <spanx style="verb">lgpl-2.1-only</spanx>, <spanx style="verb">lgpl-2.1-or-later</spanx>, <spanx style="verb">lgpl-3.0</spanx>,
<spanx style="verb">lgpl-3.0-only</spanx>, <spanx style="verb">lgpl-3.0-or-later</spanx>, <spanx style="verb">liliq-p-1.1</spanx>,
<spanx style="verb">liliq-r-1.1</spanx>, <spanx style="verb">liliq-rplus-1.1</spanx>, <spanx style="verb">lppl-1.3c</spanx>, <spanx style="verb">miros</spanx>, <spanx style="verb">mit</spanx>,
<spanx style="verb">mit-0</spanx>, <spanx style="verb">mit-modern-variant</spanx>, <spanx style="verb">motosoto</spanx>, <spanx style="verb">mpl-1.0</spanx>, <spanx style="verb">mpl-1.1</spanx>,
<spanx style="verb">mpl-2.0</spanx>, <spanx style="verb">mpl-2.0-no-copyleft-exception</spanx>, <spanx style="verb">ms-pl</spanx>, <spanx style="verb">ms-rl</spanx>,
<spanx style="verb">mulanpsl-2.0</spanx>, <spanx style="verb">multics</spanx>, <spanx style="verb">nasa-1.3</spanx>, <spanx style="verb">naumen</spanx>, <spanx style="verb">ncsa</spanx>, <spanx style="verb">nokia</spanx>,
<spanx style="verb">nposl-3.0</spanx>, <spanx style="verb">ntp</spanx>, <spanx style="verb">ofl-1.1</spanx>, <spanx style="verb">ofl-1.1-no-rfn</spanx>, <spanx style="verb">ofl-1.1-rfn</spanx>,
<spanx style="verb">oldap-2.8</spanx>, <spanx style="verb">oset-pl-2.1</spanx>, <spanx style="verb">osl-1.0</spanx>, <spanx style="verb">osl-2.0</spanx>, <spanx style="verb">osl-2.1</spanx>,
<spanx style="verb">osl-3.0</spanx>, <spanx style="verb">php-3.0</spanx>, <spanx style="verb">php-3.01</spanx>, <spanx style="verb">postgresql</spanx>, <spanx style="verb">python-2.0</spanx>,
<spanx style="verb">python-2.0.1</spanx>, <spanx style="verb">qpl-1.0</spanx>, <spanx style="verb">rpl-1.1</spanx>, <spanx style="verb">rpl-1.5</spanx>, <spanx style="verb">rpsl-1.0</spanx>,
<spanx style="verb">rscpl</spanx>, <spanx style="verb">simpl-2.0</spanx>, <spanx style="verb">sissl</spanx>, <spanx style="verb">sleepycat</spanx>, <spanx style="verb">spl-1.0</spanx>, <spanx style="verb">ucl-1.0</spanx>,
<spanx style="verb">upl-1.0</spanx>, <spanx style="verb">vsl-1.0</spanx>, <spanx style="verb">w3c</spanx>, <spanx style="verb">w3c-19980720</spanx>, <spanx style="verb">w3c-20150513</spanx>,
<spanx style="verb">watcom-1.0</spanx>, <spanx style="verb">xnet</spanx>, <spanx style="verb">zlib</spanx>, <spanx style="verb">zpl-2.0</spanx>, <spanx style="verb">zpl-2.1</spanx>.</t>

<t>Additionally, the reference implementation accepts the following
non-OSI but widely-accepted libre identifiers as OSS:</t>

<t><spanx style="verb">bsd-3-clause-clear</spanx>, <spanx style="verb">bsd-4-clause</spanx>, <spanx style="verb">cc0-1.0</spanx>, <spanx style="verb">cc-by-4.0</spanx>,
<spanx style="verb">cc-by-sa-4.0</spanx>, <spanx style="verb">unlicense</spanx>, <spanx style="verb">vim</spanx>, <spanx style="verb">wtfpl</spanx>.</t>

<t>This snapshot is informative. The normative requirement is in
<xref target="spdx-eval"/>: the allow-list <bcp14>MUST</bcp14> track the OSI-Approved column of
the SPDX License List, <bcp14>MUST</bcp14> be additive, and <bcp14>MAY</bcp14> include the
above-listed libre identifiers.</t>

</section>
</section>
<section anchor="security"><name>Security Considerations</name>

<section anchor="trust-model"><name>Trust Model</name>

<t>The MMCO host loads native code into its own address space. A
loaded module has full process authority; in particular, it can
read every file the host can read, open every socket the host can
open, and modify every host-owned data structure reachable through
the language runtime. MMCS therefore cannot, and does not, provide
post-load isolation. Its threat model is solely about authorising
the load decision.</t>

<t>MMCS authorises a load by tying the module bytes to an OpenPGP
identity. The host's trust root is its configured keyring; the
strength of the chain is exactly the strength of the user's process
for adding keys to that keyring. The host <bcp14>SHOULD</bcp14> document its
keyring location and <bcp14>SHOULD</bcp14> provide tooling that displays the
fingerprint of every signing key encountered.</t>

</section>
<section anchor="tamper-resistance"><name>Tamper Resistance</name>

<t>Because the MMCS trailer is appended to the operating system's
native shared-object format, it survives:</t>

<t><list style="symbols">
  <t>Read by the operating-system loader, which ignores trailing
bytes past the program-header-referenced sections.</t>
  <t>Hash verification by the host, which reads the file directly.</t>
</list></t>

<t>It does not survive operations that rewrite payload bytes:</t>

<t><list style="symbols">
  <t>ELF <spanx style="verb">strip(1)</spanx>, <spanx style="verb">patchelf</spanx>, <spanx style="verb">chrpath</spanx>, <spanx style="verb">install_name_tool</spanx>,
and other link-time rewriters that mutate sections covered by
the program header.</t>
  <t>Debug-symbol stripping during installation, when
<spanx style="verb">CMAKE_INSTALL_DO_STRIP=ON</spanx> or its equivalent is in effect.</t>
  <t>Repacking by debugger-friendly post-processing tools.</t>
</list></t>

<t>A producer <bcp14>MUST</bcp14> re-sign an MMCO file after any such rewrite,
and <bcp14>SHOULD</bcp14> arrange its installer to defer signing until all
rewrites have completed. The reference implementation
accomplishes this by attaching the trailer twice during a build:
once as a <spanx style="verb">POST_BUILD</spanx> step on the build artefact (so an
in-tree run sees a signed module), and once again from an
<spanx style="verb">install(CODE …)</spanx> block that runs after CMake has finished its
RPATH-rewriting and stripping on the installed file. Each
re-signing step strips any pre-existing MMCS trailer before
attaching the new one (see <xref target="signing"/>); the operation is
idempotent.</t>

<section anchor="interaction-with-platform-code-signing"><name>Interaction with Platform Code Signing</name>

<t>The MMCS trailer is incompatible with platform code-signing
schemes that themselves claim the tail of a shared object:</t>

<t><list style="symbols">
  <t>On macOS, <spanx style="verb">codesign(1)</spanx> writes its signature into the Mach-O
<spanx style="verb">__LINKEDIT</spanx> segment by extending the segment past its
original end. After <spanx style="verb">codesign</spanx> runs, any MMCS trailer
previously attached is no longer at end-of-file, breaking
extraction. Furthermore, <spanx style="verb">codesign --strict</spanx> (the default in
notarised builds) refuses to validate a Mach-O whose file
tail contains bytes not accounted for by the Mach-O load
commands.  <vspace blankLines='1'/>
The conflict has two practical consequences:  <list style="numbers" type="1">
      <t>An MMCO module on macOS <bcp14>MUST NOT</bcp14> be signed with both
MMCS and Apple <spanx style="verb">codesign</spanx> in the same file. A host <bcp14>MAY</bcp14>
choose either signing scheme; this document specifies
MMCS, and a host that chooses Apple <spanx style="verb">codesign</spanx> instead is
out of scope.</t>
      <t>An MMCO host on macOS <bcp14>MUST</bcp14> install module files into a
bundle directory that <spanx style="verb">codesign</spanx> does not walk
recursively in code mode. The bundle's
<spanx style="verb">Contents/Resources/</spanx> directory satisfies this
requirement; <spanx style="verb">Contents/PlugIns/</spanx> and <spanx style="verb">Contents/MacOS/</spanx> do
not (see <xref target="discovery"/>).</t>
    </list></t>
  <t>On Windows, Authenticode signatures live in the PE optional
header's <spanx style="verb">IMAGE_DIRECTORY_ENTRY_SECURITY</spanx> directory, which is
located by an offset stored elsewhere in the header. An MMCS
trailer appended after the Authenticode signature does not
by itself invalidate the Authenticode signature, but it does
enlarge the file past the signature's claimed extent and may
cause some Authenticode verifiers (notably WDAC) to reject
the file. Hosts that target Windows <bcp14>SHOULD</bcp14> pick exactly one
scheme per module.</t>
</list></t>

<t>A host <bcp14>MUST NOT</bcp14> attempt to recover from a <spanx style="verb">BadSignature</spanx> or
<spanx style="verb">Malformed</spanx> state by truncating the trailer and re-loading;
doing so would convert any verified-then-tampered module into
an apparently unsigned one and bypass <xref target="policy"/> for any
module whose declared license was downgraded to an OSS SPDX
identifier in the same tampering step.</t>

</section>
</section>
<section anchor="downgrade-attacks"><name>Downgrade Attacks</name>

<t>An attacker controlling distribution of a module can, in principle:</t>

<t><list style="numbers" type="1">
  <t>Replace a non-OSS module's <spanx style="verb">license</spanx> field with an OSS SPDX
identifier, attach no trailer, and rely on <xref target="policy"/> to admit
the module. This is mitigated by the host displaying the
declared license in administrative UI and by the user reviewing
that license before installing the module. It is NOT prevented
by MMCS, which does not encode license commitments
cryptographically.</t>
  <t>Wrap an unsigned non-OSS module in a forged trailer to convert
<spanx style="verb">Absent</spanx> into <spanx style="verb">BadSignature</spanx>. This is detected; <spanx style="verb">BadSignature</spanx>
is a hard refusal under <xref target="policy"/> regardless of license.</t>
  <t>Replace a <spanx style="verb">Valid</spanx> trailer with a trailer signed by a different
key in the user's trusted keyring. This is prevented by the
host displaying the fingerprint of the signing key and by the
user adding only keys they have verified out-of-band to their
keyring. MMCS does not authenticate which key <bcp14>SHOULD</bcp14> have
signed a given module; the <spanx style="verb">signing_key_id</spanx> field in
<spanx style="verb">MMCOModuleInfo</spanx> is informational.</t>
</list></t>

</section>
<section anchor="cache-poisoning"><name>Cache Poisoning</name>

<t>The verification cache (<xref target="cache"/>) is keyed on
<spanx style="verb">(path, size, mtime_ms)</spanx>. An attacker who can write to a module
file and reset its mtime can in principle reuse a previously cached
<spanx style="verb">Valid</spanx> verdict against new payload bytes. Mitigations:</t>

<t><list style="symbols">
  <t>The host <bcp14>SHOULD</bcp14> store the cache under a path the unprivileged
attacker cannot write to (e.g. the user's configuration
directory).</t>
  <t>A host <bcp14>MAY</bcp14> harden the cache key by including a strong digest of
the payload, at the cost of one full file read per launch.</t>
  <t>The host <bcp14>MUST</bcp14> provide a cache-bypass administrative command.</t>
</list></t>

</section>
<section anchor="backend-failure"><name>Backend Failure</name>

<t>When the OpenPGP backend is unavailable, the host receives <spanx style="verb">Error</spanx>.
<xref target="policy"/> requires that non-OSS modules be refused in this state.
This is intentional: a process that cannot establish identity for a
module that requires identity <bcp14>MUST NOT</bcp14> execute that module's code.
OSS modules are admitted in this state because the alternative is
to make the entire plugin system non-functional whenever the
OpenPGP daemon is missing (notably on stripped-down container
images), which would push users toward disabling MMCS entirely.</t>

</section>
<section anchor="static-constructors-and-rtldnodelete"><name>Static Constructors and RTLD_NODELETE</name>

<t>The reference host opens modules with <spanx style="verb">RTLD_NODELETE</spanx> on ELF
platforms, for the reasons detailed in
<xref target="rtld-nodelete-rationale"/>. This is a load-time decision that
prevents the C runtime from running a module's global
destructors at process exit (or at a subsequent <spanx style="verb">dlclose</spanx>).
Without this flag, a module that statically links any object
whose destructor mutates host-shared state would corrupt that
state during shutdown.</t>

<t>This is a correctness measure rather than a security measure;
it is documented in the security section because failing to
observe it manifests as exit-time heap corruption that an
adversary may be able to weaponise into a use-after-free.
Hosts on platforms without <spanx style="verb">RTLD_NODELETE</spanx> (notably Windows,
where <spanx style="verb">FreeLibrary</spanx> always runs destructors) <bcp14>SHOULD</bcp14> achieve
the same outcome architecturally — typically by ensuring that
plugin authors do not statically link libraries whose globals
the host also instantiates, and by exposing the host's own
copies of those globals through the API surface
(<xref target="api-surface"/>) instead.</t>

</section>
</section>
<section anchor="acknowledgements"><name>Acknowledgements</name>

<t>MMCO and MMCS were designed for, and are implemented in, the
MeshMC launcher of the Project Tick BSD/Linux distribution. The
authors acknowledge the prior art of the Linux kernel's signed
module facility (<spanx style="verb">modsign</spanx>), the macOS Mach-O code-signing trailer,
and the systemd Portable Service signature attached to disk images,
all of which informed the trailer layout.</t>

</section>


  </middle>

  <back>


<references title='References' anchor="sec-combined-references">

    <references title='Normative References' anchor="sec-normative-references">



<reference anchor="RFC2119">
  <front>
    <title>Key words for use in RFCs to Indicate Requirement Levels</title>
    <author fullname="S. Bradner" initials="S." surname="Bradner"/>
    <date month="March" year="1997"/>
    <abstract>
      <t>In many standards track documents several words are used to signify the requirements in the specification. These words are often capitalized. This document defines these words as they should be interpreted in IETF documents. This document specifies an Internet Best Current Practices for the Internet Community, and requests discussion and suggestions for improvements.</t>
    </abstract>
  </front>
  <seriesInfo name="BCP" value="14"/>
  <seriesInfo name="RFC" value="2119"/>
  <seriesInfo name="DOI" value="10.17487/RFC2119"/>
</reference>
<reference anchor="RFC8174">
  <front>
    <title>Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words</title>
    <author fullname="B. Leiba" initials="B." surname="Leiba"/>
    <date month="May" year="2017"/>
    <abstract>
      <t>RFC 2119 specifies common key words that may be used in protocol specifications. This document aims to reduce the ambiguity by clarifying that only UPPERCASE usage of the key words have the defined special meanings.</t>
    </abstract>
  </front>
  <seriesInfo name="BCP" value="14"/>
  <seriesInfo name="RFC" value="8174"/>
  <seriesInfo name="DOI" value="10.17487/RFC8174"/>
</reference>
<reference anchor="RFC4880">
  <front>
    <title>OpenPGP Message Format</title>
    <author fullname="J. Callas" initials="J." surname="Callas"/>
    <author fullname="L. Donnerhacke" initials="L." surname="Donnerhacke"/>
    <author fullname="H. Finney" initials="H." surname="Finney"/>
    <author fullname="D. Shaw" initials="D." surname="Shaw"/>
    <author fullname="R. Thayer" initials="R." surname="Thayer"/>
    <date month="November" year="2007"/>
    <abstract>
      <t>This document is maintained in order to publish all necessary information needed to develop interoperable applications based on the OpenPGP format. It is not a step-by-step cookbook for writing an application. It describes only the format and methods needed to read, check, generate, and write conforming packets crossing any network. It does not deal with storage and implementation questions. It does, however, discuss implementation issues necessary to avoid security flaws.</t>
      <t>OpenPGP software uses a combination of strong public-key and symmetric cryptography to provide security services for electronic communications and data storage. These services include confidentiality, key management, authentication, and digital signatures. This document specifies the message formats used in OpenPGP. [STANDARDS-TRACK]</t>
    </abstract>
  </front>
  <seriesInfo name="RFC" value="4880"/>
  <seriesInfo name="DOI" value="10.17487/RFC4880"/>
</reference>
<reference anchor="RFC9580">
  <front>
    <title>OpenPGP</title>
    <author fullname="P. Wouters" initials="P." role="editor" surname="Wouters"/>
    <author fullname="D. Huigens" initials="D." surname="Huigens"/>
    <author fullname="J. Winter" initials="J." surname="Winter"/>
    <author fullname="Y. Niibe" initials="Y." surname="Niibe"/>
    <date month="July" year="2024"/>
    <abstract>
      <t>This document specifies the message formats used in OpenPGP. OpenPGP provides encryption with public key or symmetric cryptographic algorithms, digital signatures, compression, and key management.</t>
      <t>This document is maintained in order to publish all necessary information needed to develop interoperable applications based on the OpenPGP format. It is not a step-by-step cookbook for writing an application. It describes only the format and methods needed to read, check, generate, and write conforming packets crossing any network. It does not deal with storage and implementation questions. It does, however, discuss implementation issues necessary to avoid security flaws.</t>
      <t>This document obsoletes RFCs 4880 ("OpenPGP Message Format"), 5581 ("The Camellia Cipher in OpenPGP"), and 6637 ("Elliptic Curve Cryptography (ECC) in OpenPGP").</t>
    </abstract>
  </front>
  <seriesInfo name="RFC" value="9580"/>
  <seriesInfo name="DOI" value="10.17487/RFC9580"/>
</reference>



    </references>

    <references title='Informative References' anchor="sec-informative-references">



<reference anchor="RFC5234">
  <front>
    <title>Augmented BNF for Syntax Specifications: ABNF</title>
    <author fullname="D. Crocker" initials="D." role="editor" surname="Crocker"/>
    <author fullname="P. Overell" initials="P." surname="Overell"/>
    <date month="January" year="2008"/>
    <abstract>
      <t>Internet technical specifications often need to define a formal syntax. Over the years, a modified version of Backus-Naur Form (BNF), called Augmented BNF (ABNF), has been popular among many Internet specifications. The current specification documents ABNF. It balances compactness and simplicity with reasonable representational power. The differences between standard BNF and ABNF involve naming rules, repetition, alternatives, order-independence, and value ranges. This specification also supplies additional rule definitions and encoding for a core lexical analyzer of the type common to several Internet specifications. [STANDARDS-TRACK]</t>
    </abstract>
  </front>
  <seriesInfo name="STD" value="68"/>
  <seriesInfo name="RFC" value="5234"/>
  <seriesInfo name="DOI" value="10.17487/RFC5234"/>
</reference>

<reference anchor="ELF" >
  <front>
    <title>Executable and Linkable Format (ELF) Specification, Version 1.2</title>
    <author >
      <organization>Tool Interface Standards (TIS) Committee</organization>
    </author>
    <date year="1995" month="May"/>
  </front>
</reference>
<reference anchor="MACHO" target="https://www.cs.miami.edu/home/burt/learning/Csc521.091/docs/MachOTopics.pdf">
  <front>
    <title>Mach-O Programming Topics</title>
    <author >
      <organization>Apple Inc.</organization>
    </author>
    <date year="n.d."/>
  </front>
</reference>
<reference anchor="PE" target="https://learn.microsoft.com/windows/win32/debug/pe-format">
  <front>
    <title>PE Format</title>
    <author >
      <organization>Microsoft Corporation</organization>
    </author>
    <date year="n.d."/>
  </front>
</reference>
<reference anchor="SPDX" target="https://spdx.github.io/spdx-spec/">
  <front>
    <title>SPDX Specification, Version 2.3</title>
    <author >
      <organization>Linux Foundation</organization>
    </author>
    <date year="n.d."/>
  </front>
</reference>
<reference anchor="SPDX-LICENSE-LIST" target="https://spdx.org/licenses/">
  <front>
    <title>SPDX License List</title>
    <author >
      <organization>Linux Foundation</organization>
    </author>
    <date year="n.d."/>
  </front>
</reference>
<reference anchor="OSI" target="https://opensource.org/licenses/">
  <front>
    <title>OSI Approved Licenses</title>
    <author >
      <organization>Open Source Initiative</organization>
    </author>
    <date year="n.d."/>
  </front>
</reference>
<reference anchor="POSIX" >
  <front>
    <title>IEEE Std 1003.1-2017, Standard for Information Technology -- Portable Operating System Interface (POSIX) Base Specifications, Issue 7</title>
    <author >
      <organization>IEEE / The Open Group</organization>
    </author>
    <date year="2017"/>
  </front>
</reference>
<reference anchor="KAHN-TOPO" >
  <front>
    <title>Topological sorting of large networks</title>
    <author initials="A. B." surname="Kahn" fullname="A. B. Kahn">
      <organization></organization>
    </author>
    <date year="1962"/>
  </front>
  <seriesInfo name="Communications of the ACM" value="5(11), pp. 558-562"/>
</reference>


    </references>

</references>


<?line 1436?>

<section anchor="impl-notes"><name>Implementation Notes (Informative)</name>

<section anchor="reference-constants"><name>Reference Constants</name>

<t>For unambiguous interoperability, the reference implementation
defines the following preprocessor constants. They are reproduced
here verbatim:</t>

<figure><sourcecode type="c"><![CDATA[
#define MMCO_MAGIC          0x4D4D434F  /* "MMCO"            */
#define MMCO_ABI_VERSION    2
#define MMCO_EXTENSION      ".mmco"
#define MMCO_FLAG_NONE      0x00000000

#define MMCO_TRAILER_MAGIC  0x53434D4D  /* "MMCS"            */
]]></sourcecode></figure>

<t>The reference implementation additionally exposes a four-nibble
version number for tooling convenience:</t>

<figure><sourcecode type="c"><![CDATA[
#define MMCO_VERSION        "8.0.0"
#define MMCO_VERNUM         0x08000000L
#define MMCO_VER_MAJOR      8
#define MMCO_VER_MINOR      0
#define MMCO_VER_REVISION   0
]]></sourcecode></figure>

<t>These are not normative; they describe the implementation's release
identity, not the format itself.</t>

</section>
<section anchor="reference-pseudocode-for-trailer-verification"><name>Reference Pseudocode for Trailer Verification</name>

<t>The following pseudocode summarises <xref target="extract"/> through <xref target="verify"/>:</t>

<figure><artwork><![CDATA[
function verify_file(path, keyring) -> (state, detail, fpr):
    if cache.has((path, size_of(path), mtime_ms_of(path))):
        return cache.get(...)
    f = open(path)
    if size_of(f) < 12:
        return ("Absent", "", "")
    seek(f, -12, end)
    sig_size, magic = read_u64_le_u32_le(f)
    if magic != 0x53434D4D:
        return ("Absent", "", "")
    if sig_size == 0 or sig_size > size_of(f) - 12:
        return ("Malformed", "malformed trailer", "")
    payload_size = size_of(f) - 12 - sig_size
    seek(f, 0)
    payload = read(f, payload_size)
    signature = read(f, sig_size)
    if len(payload) != payload_size or len(signature) != sig_size:
        return ("Malformed", "short read", "")
    (state, detail, fpr) = openpgp_verify_detached(
        signature, payload, keyring)
    if state != "Error":
        cache.put((path, size, mtime_ms), (state, detail, fpr))
    return (state, detail, fpr)
]]></artwork></figure>

</section>
<section anchor="cross-references-to-the-reference-implementation"><name>Cross-References to the Reference Implementation</name>

<t>For maintainers of independent implementations, the canonical
source files in the reference implementation are:</t>

<t><list style="symbols">
  <t><spanx style="verb">launcher/plugin/MMCOFormat.h</spanx> — ABI constants, <spanx style="verb">MMCOModuleInfo</spanx>,
<spanx style="verb">MMCODependency</spanx>, trailer magic.</t>
  <t><spanx style="verb">launcher/plugin/PluginAPI.h</spanx> — <spanx style="verb">MMCOContext</spanx> definition.</t>
  <t><spanx style="verb">launcher/plugin/PluginHooks.h</spanx> — hook identifier enum and
payload structures.</t>
  <t><spanx style="verb">launcher/plugin/PluginLoader.cpp</spanx> — discovery, loading, trust
pre-flight.</t>
  <t><spanx style="verb">launcher/plugin/PluginDependencyResolver.cpp</spanx> — Kahn's
algorithm, version comparison.</t>
  <t><spanx style="verb">launcher/plugin/PluginSignature.cpp</spanx> — trailer extraction,
OpenPGP verification, persistent cache, SPDX allow-list.</t>
  <t><spanx style="verb">launcher/plugin/PluginManager.cpp</spanx> — <spanx style="verb">MMCOContext</spanx> build-out,
hook dispatch, per-module sandboxing, lifecycle.</t>
  <t><spanx style="verb">scripts/mmco_sign.py</spanx> — idempotent signing of an MMCO file.</t>
  <t><spanx style="verb">cmake/MMCOSign.cmake</spanx> — build-time signing and install-time
re-signing.</t>
</list></t>

<t>These files are made available under the GPL-3.0-or-later license,
with an additional permission described in the MeshMC MMCO Module
Exception 1.0.</t>

</section>
<section anchor="reference-build-time-switches"><name>Reference Build-Time Switches</name>

<t>The reference implementation exposes the following build-time
configuration knobs, all of which are informative and have no
bearing on the on-the-wire format:</t>

<dl>
  <dt><spanx style="verb">MeshMC_PLUGIN_SIGNATURES</spanx> (CMake option):</dt>
  <dd>
    <t>Enables linkage against the GpgME C++ bindings and selects the
full MMCS verifier. When OFF, <spanx style="verb">PluginSignature.cpp</spanx> compiles
into a stub that reports every module's signature state as
<spanx style="verb">Error</spanx> — under <xref target="policy"/> this admits OSS modules and rejects
non-OSS modules. The option defaults OFF on toolchains where
upstream GpgME does not build (MSVC) and on macOS universal
builds (where Homebrew ships single-arch dylibs that cannot
link into a fat binary), and ON elsewhere.</t>
  </dd>
  <dt><spanx style="verb">MeshMC_PLUGIN_SIGNING_KEY</spanx> / <spanx style="verb">MeshMC_PLUGIN_SIGNING_HOMEDIR</spanx> (CMake</dt>
  <dd><t/></dd>
  <dt>cache variables):</dt>
  <dd>
    <t>Default GPG fingerprint and GnuPG home directory used by
<spanx style="verb">MMCOSign.cmake</spanx> when signing built modules. When empty, the
<spanx style="verb">POST_BUILD</spanx> signing step is skipped.</t>
  </dd>
  <dt><spanx style="verb">MeshMC_PLUGIN_SIGN_ALL</spanx> (CMake option):</dt>
  <dd>
    <t>When ON, every in-tree MMCO plugin target is signed automatically
using the above key.</t>
  </dd>
  <dt><spanx style="verb">MESHMC_SKIP_INSTALL_RESIGN</spanx> (environment variable, build-time):</dt>
  <dd>
    <t>When set to <spanx style="verb">1</spanx>, suppresses the install-time re-signing step
described in <xref target="tamper-resistance"/>. Useful for distribution
packagers who lack the upstream signing key. The installed
module will then carry a build-tree signature that has been
invalidated by the installer's RPATH / strip operations, and
will be rejected at load time as <spanx style="verb">BadSignature</spanx> per <xref target="policy"/>.</t>
  </dd>
</dl>

</section>
<section anchor="hook-payloads-impl"><name>Reference Hook Payload Definitions</name>

<t>The complete normative listing of hook identifiers and their
payload struct layouts is given as Appendix B in this document
(<xref target="hook-payloads"/>). The reference implementation's <spanx style="verb">PluginHooks.h</spanx>
header is the authoritative C declaration for those structs and
<bcp14>MUST</bcp14> be kept in sync with <xref target="hook-payloads"/> for every
<spanx style="verb">MMCO_ABI_VERSION</spanx> revision.</t>

</section>
</section>
<section anchor="hook-payloads"><name>Hook Payload Definitions</name>

<t>This appendix defines, normatively, every hook identifier
allocated as of <spanx style="verb">MMCO_ABI_VERSION == 2</spanx> and the C-language layout
of its payload struct. The host <bcp14>MUST</bcp14> pass a payload pointer that
points to a struct of the indicated type for the corresponding
hook identifier; the payload pointer <bcp14>MAY</bcp14> be NULL only for hooks
whose payload type is listed as "none".</t>

<section anchor="application-lifecycle-0x01000x01ff"><name>Application Lifecycle (<spanx style="verb">0x0100</spanx>–<spanx style="verb">0x01FF</spanx>)</name>

<texttable>
      <ttcol align='left'>Identifier</ttcol>
      <ttcol align='left'>Value</ttcol>
      <ttcol align='left'>Payload</ttcol>
      <ttcol align='left'>Cancellable</ttcol>
      <ttcol align='left'>Dispatched?</ttcol>
      <c><spanx style="verb">MMCO_HOOK_APP_INITIALIZED</spanx></c>
      <c><spanx style="verb">0x0100</spanx></c>
      <c>none</c>
      <c>no</c>
      <c>yes</c>
      <c><spanx style="verb">MMCO_HOOK_APP_SHUTDOWN</spanx></c>
      <c><spanx style="verb">0x0101</spanx></c>
      <c>none</c>
      <c>no</c>
      <c>yes</c>
</texttable>

</section>
<section anchor="instance-lifecycle-0x02000x02ff"><name>Instance Lifecycle (<spanx style="verb">0x0200</spanx>–<spanx style="verb">0x02FF</spanx>)</name>

<t>All four payloads are of type <spanx style="verb">MMCOInstanceInfo</spanx>:</t>

<figure><sourcecode type="c"><![CDATA[
struct MMCOInstanceInfo {
    const char *instance_id;
    const char *instance_name;
    const char *instance_path;
    const char *minecraft_version; /* MAY be NULL */
};
]]></sourcecode></figure>

<texttable>
      <ttcol align='left'>Identifier</ttcol>
      <ttcol align='left'>Value</ttcol>
      <ttcol align='left'>Payload</ttcol>
      <ttcol align='left'>Cancellable</ttcol>
      <ttcol align='left'>Dispatched?</ttcol>
      <c><spanx style="verb">MMCO_HOOK_INSTANCE_PRE_LAUNCH</spanx></c>
      <c><spanx style="verb">0x0200</spanx></c>
      <c><spanx style="verb">MMCOInstanceInfo*</spanx></c>
      <c>no</c>
      <c>yes</c>
      <c><spanx style="verb">MMCO_HOOK_INSTANCE_POST_LAUNCH</spanx></c>
      <c><spanx style="verb">0x0201</spanx></c>
      <c><spanx style="verb">MMCOInstanceInfo*</spanx></c>
      <c>no</c>
      <c>yes</c>
      <c><spanx style="verb">MMCO_HOOK_INSTANCE_CREATED</spanx></c>
      <c><spanx style="verb">0x0202</spanx></c>
      <c><spanx style="verb">MMCOInstanceInfo*</spanx></c>
      <c>no</c>
      <c>not yet</c>
      <c><spanx style="verb">MMCO_HOOK_INSTANCE_REMOVED</spanx></c>
      <c><spanx style="verb">0x0203</spanx></c>
      <c><spanx style="verb">MMCOInstanceInfo*</spanx></c>
      <c>no</c>
      <c>not yet</c>
</texttable>

<t>Note: <spanx style="verb">MMCO_HOOK_INSTANCE_PRE_LAUNCH</spanx> is observational despite
its name; see <xref target="hooks"/>. The host applies launch modifications
(environment variables and wrapper commands) submitted via the
side-channel API after the hook chain finishes, regardless of
the dispatch return value.</t>

</section>
<section anchor="settings-0x03000x03ff"><name>Settings (<spanx style="verb">0x0300</spanx>–<spanx style="verb">0x03FF</spanx>)</name>

<figure><sourcecode type="c"><![CDATA[
struct MMCOSettingChange {
    const char *key;
    const char *old_value;
    const char *new_value;
};
]]></sourcecode></figure>

<texttable>
      <ttcol align='left'>Identifier</ttcol>
      <ttcol align='left'>Value</ttcol>
      <ttcol align='left'>Payload</ttcol>
      <ttcol align='left'>Cancellable</ttcol>
      <ttcol align='left'>Dispatched?</ttcol>
      <c><spanx style="verb">MMCO_HOOK_SETTINGS_CHANGED</spanx></c>
      <c><spanx style="verb">0x0300</spanx></c>
      <c><spanx style="verb">MMCOSettingChange*</spanx></c>
      <c>no</c>
      <c>not yet</c>
</texttable>

</section>
<section anchor="content-mod-management-0x04000x04ff"><name>Content / Mod Management (<spanx style="verb">0x0400</spanx>–<spanx style="verb">0x04FF</spanx>)</name>

<figure><sourcecode type="c"><![CDATA[
struct MMCOContentEvent {
    const char *instance_id;
    const char *file_name;
    const char *url;
    const char *target_path;
};
]]></sourcecode></figure>

<texttable>
      <ttcol align='left'>Identifier</ttcol>
      <ttcol align='left'>Value</ttcol>
      <ttcol align='left'>Payload</ttcol>
      <ttcol align='left'>Cancellable</ttcol>
      <ttcol align='left'>Dispatched?</ttcol>
      <c><spanx style="verb">MMCO_HOOK_CONTENT_PRE_DOWNLOAD</spanx></c>
      <c><spanx style="verb">0x0400</spanx></c>
      <c><spanx style="verb">MMCOContentEvent*</spanx></c>
      <c>yes (when dispatched)</c>
      <c>not yet</c>
      <c><spanx style="verb">MMCO_HOOK_CONTENT_POST_DOWNLOAD</spanx></c>
      <c><spanx style="verb">0x0401</spanx></c>
      <c><spanx style="verb">MMCOContentEvent*</spanx></c>
      <c>no</c>
      <c>not yet</c>
</texttable>

</section>
<section anchor="network-0x05000x05ff"><name>Network (<spanx style="verb">0x0500</spanx>–<spanx style="verb">0x05FF</spanx>)</name>

<figure><sourcecode type="c"><![CDATA[
struct MMCONetworkEvent {
    const char *url;
    const char *method;     /* "GET", "POST", ...        */
    int         status_code; /* 0 for pre-request events */
};
]]></sourcecode></figure>

<texttable>
      <ttcol align='left'>Identifier</ttcol>
      <ttcol align='left'>Value</ttcol>
      <ttcol align='left'>Payload</ttcol>
      <ttcol align='left'>Cancellable</ttcol>
      <ttcol align='left'>Dispatched?</ttcol>
      <c><spanx style="verb">MMCO_HOOK_NETWORK_PRE_REQUEST</spanx></c>
      <c><spanx style="verb">0x0500</spanx></c>
      <c><spanx style="verb">MMCONetworkEvent*</spanx></c>
      <c>yes (when dispatched)</c>
      <c>not yet</c>
      <c><spanx style="verb">MMCO_HOOK_NETWORK_POST_REQUEST</spanx></c>
      <c><spanx style="verb">0x0501</spanx></c>
      <c><spanx style="verb">MMCONetworkEvent*</spanx></c>
      <c>no</c>
      <c>not yet</c>
</texttable>

</section>
<section anchor="ui-extension-points-0x06000x06ff"><name>UI Extension Points (<spanx style="verb">0x0600</spanx>–<spanx style="verb">0x06FF</spanx>)</name>

<figure><sourcecode type="c"><![CDATA[
struct MMCOUiMainReadyPayload {
    void *main_window;       /* opaque host UI handle    */
    void *news_toolbar;
    void *more_news_action;
    void *news_label_button;
};

struct MMCOMenuEvent {
    const char *context;     /* e.g. "main", "instance"  */
    void       *menu_handle; /* opaque host UI handle    */
};

struct MMCOInstancePagesEvent {
    const char *instance_id;
    const char *instance_name;
    const char *instance_path;
    void       *page_list_handle; /* opaque host UI handle */
    void       *instance_handle;  /* opaque host data handle */
};

struct MMCOGlobalSettingsPagesEvent {
    void *page_list_handle;       /* opaque host UI handle */
};
]]></sourcecode></figure>

<texttable>
      <ttcol align='left'>Identifier</ttcol>
      <ttcol align='left'>Value</ttcol>
      <ttcol align='left'>Payload</ttcol>
      <ttcol align='left'>Cancellable</ttcol>
      <ttcol align='left'>Dispatched?</ttcol>
      <c><spanx style="verb">MMCO_HOOK_UI_MAIN_READY</spanx></c>
      <c><spanx style="verb">0x0600</spanx></c>
      <c><spanx style="verb">MMCOUiMainReadyPayload*</spanx></c>
      <c>no</c>
      <c>yes</c>
      <c><spanx style="verb">MMCO_HOOK_UI_CONTEXT_MENU</spanx></c>
      <c><spanx style="verb">0x0601</spanx></c>
      <c><spanx style="verb">MMCOMenuEvent*</spanx></c>
      <c>no</c>
      <c>yes</c>
      <c><spanx style="verb">MMCO_HOOK_UI_INSTANCE_PAGES</spanx></c>
      <c><spanx style="verb">0x0602</spanx></c>
      <c><spanx style="verb">MMCOInstancePagesEvent*</spanx></c>
      <c>no</c>
      <c>yes</c>
      <c><spanx style="verb">MMCO_HOOK_UI_GLOBAL_SETTINGS_PAGES</spanx></c>
      <c><spanx style="verb">0x0603</spanx></c>
      <c><spanx style="verb">MMCOGlobalSettingsPagesEvent*</spanx></c>
      <c>no</c>
      <c>not yet</c>
</texttable>

<t>The opaque handle fields are pointers to host-internal UI
objects. Modules <bcp14>MUST NOT</bcp14> dereference them directly; they <bcp14>MUST</bcp14>
be passed only to host API functions that document them as
acceptable inputs.</t>

</section>
<section anchor="news-0x07000x07ff"><name>News (<spanx style="verb">0x0700</spanx>–<spanx style="verb">0x07FF</spanx>)</name>

<texttable>
      <ttcol align='left'>Identifier</ttcol>
      <ttcol align='left'>Value</ttcol>
      <ttcol align='left'>Payload</ttcol>
      <ttcol align='left'>Cancellable</ttcol>
      <ttcol align='left'>Dispatched?</ttcol>
      <c><spanx style="verb">MMCO_HOOK_NEWS_UPDATED</spanx></c>
      <c><spanx style="verb">0x0700</spanx></c>
      <c>none</c>
      <c>no</c>
      <c>yes</c>
</texttable>

</section>
<section anchor="authentication-0x08000x08ff"><name>Authentication (<spanx style="verb">0x0800</spanx>–<spanx style="verb">0x08FF</spanx>)</name>

<figure><sourcecode type="c"><![CDATA[
struct MMCOAuthRequestEvent {
    /* Read-only request snapshot */
    const char *url;
    const char *method;       /* "GET" | "POST" | ...     */
    const char *body;         /* MAY be NULL for GETs     */
    int         body_size;

    /* Mutable response slots */
    const char *redirect_url; /* set non-NULL to rewrite  */

    /* Header-injection helper */
    void *request_handle;
    int (*add_header)(void *request_handle,
                      const char *key,
                      const char *value);
};

struct MMCOSessionFillEvent {
    /* Read-only context */
    const char *account_id;
    int         account_is_msa;
    int         wants_online;

    /* Read-only current session view */
    const char *current_player_name;
    const char *current_uuid;
    const char *current_user_type;

    /* Mutable overwrites (NULL = leave alone) */
    const char *overwrite_access_token;
    const char *overwrite_session;
    const char *overwrite_player_name;
    const char *overwrite_uuid;
    const char *overwrite_user_type;
    const char *overwrite_client_token;

    /* Mutable user-properties append (NULL = none) */
    const char *extra_user_properties;
};
]]></sourcecode></figure>

<texttable>
      <ttcol align='left'>Identifier</ttcol>
      <ttcol align='left'>Value</ttcol>
      <ttcol align='left'>Payload</ttcol>
      <ttcol align='left'>Cancellable</ttcol>
      <ttcol align='left'>Dispatched?</ttcol>
      <c><spanx style="verb">MMCO_HOOK_AUTH_REQUEST</spanx></c>
      <c><spanx style="verb">0x0800</spanx></c>
      <c><spanx style="verb">MMCOAuthRequestEvent*</spanx></c>
      <c>yes</c>
      <c>yes</c>
      <c><spanx style="verb">MMCO_HOOK_SESSION_FILL</spanx></c>
      <c><spanx style="verb">0x0801</spanx></c>
      <c><spanx style="verb">MMCOSessionFillEvent*</spanx></c>
      <c>no</c>
      <c>yes</c>
</texttable>

<t>For <spanx style="verb">MMCO_HOOK_AUTH_REQUEST</spanx>, cancellation aborts the in-flight
authentication request and causes the calling authentication
step to fail with a protocol error.</t>

<t>For <spanx style="verb">MMCO_HOOK_SESSION_FILL</spanx>, the host copies every non-NULL
<spanx style="verb">overwrite_*</spanx> field into the in-flight session before launching;
NULL values leave the host-populated default in place. The
return value of the callback is reserved and <bcp14>SHOULD</bcp14> be zero.
String pointers placed in <spanx style="verb">overwrite_*</spanx> and <spanx style="verb">extra_user_properties</spanx>
are read by the host during the callback only; the host copies
their contents.</t>

</section>
<section anchor="reserved-ranges"><name>Reserved Ranges</name>

<t>Identifiers in the ranges <spanx style="verb">0x0000</spanx>–<spanx style="verb">0x00FF</spanx>, <spanx style="verb">0x0900</spanx>–<spanx style="verb">0xFEFF</spanx>,
and <spanx style="verb">0xFF00</spanx>–<spanx style="verb">0xFFFF</spanx> are not allocated by this revision. Hosts
<bcp14>MUST</bcp14> ignore registrations for unallocated identifiers (i.e.
accept the registration call and silently never invoke the
callback) so that newer modules remain loadable on older hosts.</t>

</section>
</section>


  </back>

<!-- ##markdown-source:
H4sIAAAAAAAAA92963IbSZIu+D+fIoY6x4pUI0FSl+pqqqrmsChKwhRFsgmq
qmvnjBEJZADIYSITlRdSaEpt8w6zD7C/9kH2UeZJ1j53j1sCJEs1PWNrK7Pu
AoHMuIeHh/vnn8dxHDVZk+sDtXU51+r9+6Mz9b5M21yro3KxLAtdNOps/K96
0qikSPHAkH+ps0aroZ60Vdas1JuyWiTNVpSMx5W+OVBbKGkXT29FaTkpkoU+
UGmVTJt4WZUorskm1/FiMSnxf3W8txdNkkbPymp1oLJiWkZp0ugD9Wzv2ddR
tqwOVFO1dfNsb+9Pe8+ipNLJgTpcLvNskjRZWdTRbVldz6qyXR6oQZHqpS5S
tH3YjhdZXWdlEV3r1W1ZpQeRUrFa5u0sK+jjgvpLH+t5UulU5dm4SqoVfXW2
1MX523P6PClTrepsVmTFjL4Ynr/+SxTVTVKkV0leFvpArXQdLbMD9c9NOemp
uqyaSk/rnqpXC3z4lyhK2mZeVtSMSCmlsqLGgPXVsK9e97foOx6wrfd6vtCN
Gib4/9ftIin457KaJUX2V+r6gdo65yFVl9nkmh/QiyTLD9SqLGZpOV+1xf/y
hr1fVmi+Um2VHah50yzrg93dzgO7UVTQpGY3Gm29eHP0bH//T/Lxm/0/vpCP
L775Zk8+/uklPkaYvvDNl8+e0+PHJ2/wH6XMojv+qCdtk4xzTcvrJCuu6Q9e
T2r7+OTNjhou9SSbykz31E+6wnyq/f4z7qwbUPyLMTpYz2WZq0HR6GqaTLQa
YpKSKq3V9uVguINFvMiaRmsug1fb/p/+9DLeexkp9f7w6N1Z2Nb3yWQen6nz
qpxVyWKRFTN1WS6zSf1QK7BGtRoUE5nYJqlmunGjfnt725/U/UWWLLK+Ttvd
ebnQu+O2anZznVRYabtH9eTls/3+3p/2d9NyUu+iIWdcdX+ZTiOlzo/Dpp4f
2x15f9PeZ5OqrMtpo47KallWNLybW0lN6S/MC/1Judi9zYq0vK3x3+fPdlM9
bme7Sx3z1EeK9kbYKnxz32Q+6z9/qK0nWdF+VG/KtkgfaGa9TD/2Z1kzb8f9
rKQ/43qpJ7vSnPhkcHR8OjyOTwbDyw1tO8kmuqi1Osnq5u/UGuyknIut0Yyz
4SCs+Gw4gCCryhuN9c9PPlQ5BJIalm01wbrKmow22uYmlEtd1PToWkPOz4aD
zvwMjo+P1bBJ1f7e3vP+fvxsb/+PPbtx1LSs1MBs7bJQl3oyL8q8nK1UzJLM
/DsvK97TZ0uNZVXM1HBVN3rh7cdtasCO+iGpdbgo6l5Q2KCuW63++NCQUMN3
FU4wGp23OAf8fY2eREr9ePjuNL48O+9s7MtyiW5kkyQngY32llOVYzBVoRsc
LfdMicjpw776oa9+TOZFKE2+fkZ/1rrKdA2xaN7cgvhpC9NjVNfMtTo8er91
oLZebu/v7/TUctlXL19+E7/8+tlWFMVxrJJx3VTJpImiy3lWq7SctAuccljk
2TTTtWpuSzUpSzvuPF21amudqvGKanmv6/n7oyhP2mIy15VqSpVm9aS80VVP
3SR5hub3SCDnZZKqZp5VabxMqmalClptdBJGfHDWKmlU1RaqyRb6IIpi1iK2
H9IldnoqUfOybmIpL10VySKbeCfvpCyaJCt0pW6zZq4SNc0+6lQdqcMfBirV
9aTKxuggOsQN+apWC90kadIkWEFGB5hkuu6pPJvqyWqSa6WLplqpZZkVTc2d
rNoCbacq9cemz10YbuhCoPSgE4XRD+JxghFOdZNM5jqNFOkJSdNWWjVVkuW6
UsmSWpRiwJOCh2ma5bqnmnKmm7npazOHNiKbNU6r7EYX6kZXdoeoZZlnE0xm
0qhUT7JU1+p2zkUkaoYXIiXDorJaLXVFhx1VjTntYwVpWi1mhSSVVnmy0pVO
D7j/WGF6mhU6VXVTZZMmX6myUE25xHpF8yMMX6FvdIXKZAXOtRqvGvqUNPQn
Zlq5NVmzLFgmVY3VU0eJUbxKWh19dYi5QMPwOI1TtljmGmudB+D94S8qmxVl
RTrrENMY1U2W57xiz4aDODFCFUIwZikoQ1K/UkmnhmHUreHD8FJVetrW2gya
SsyQ3s7L2s0rBrjStS6aaNw2Ki11rYqy4SlbqWSWZEXdqIRVWJ2qa73qd7dw
VqusaHh9JLVKVM0itNJTXeliokn+Zk61dQ3WFQkQGqemLPPJHBX2RMcVmSVr
fZlMrpOZruo+S5RFlqa5jqInEM1VmbYT9J5XB8sJZeUExqAOpMG0Lej5JMcl
wJMDalqVi6jW+TQ2Gzn1ZYeZCDVJ8lynbi/UfXWcTObe2k0iX1CEGjopiOru
7vjkzefPWJt0MveUqGp3d6TG0U/RIpmcDXvq/Fjd3Z0f8+M/sw6zw0tVf1yW
FXaCyJpaNxjXI+ju4zKvI0/sZE2tMkxD1qx69Felf20ztA0C6obVGv4l1ZMc
rY58kYTqS9qwMhQ8P8280voeadWPolNvCDEdOsWqKd0uW1blRNcY1wpnDv1Q
JwstqyBrVlFSu8ezBnPUV68z7PBxy/uzncy5CrRPT7HLpHeYDpZEtDhpQatl
0szVWDe3WhehPGY5UBY4X66lfzoy44bBxfhw0/q8k7FpSZ6x9PAqWIkARROT
yEhaI4A9eXt3J9eSz5/VNjZNU6NPGJey4l9xU/n8eSeSodNFisb4Qllh5/BC
iPNkVbaN2e88UdycfIWrYGKFdXILMRqI56zGoLZZPde1WkCXaspqFbvmyvxH
281qCR0kX2EQllWmm6Ra7dBWUuWS99n6e2q7LVJdRffKPKP1qbu7s+Hg8+ed
/v3qw7hs5vZEoBGos2KWa2XvgpEVSH11d4cL/OfPckzUNHrydR1+PWShRgcM
dqN3iOAFiD4oNlCG6EXaaLx+M4g9+7NK2wpjbjSWVS84Gnvu3F+pStdl3vLX
pM2YbUVVJkXy+XNU6VlWkwjFQqCZ1x8bXfD2XSSzbKKKdjHWRoLOy/Jatv40
01VUJcUMYuvurhbFAB3I6klbY9BRKjZ10mDCdE5lXBflbaFudXJdaDzVj6In
T9QF7zFMSa1OkmLWJjPNovharxSMF7XawsG01eP/qtMz+nxx/OcPg4vj1/g8
fHd4cmI/RPLE8N3Zh5PX7pN78+js/fvj09f88unZpQq+irbeH/6yxT3fOju/
HJydHp5sYWk0wRLCsm9KNca+aXS1rDQOusTKTBJU6oej8//n/9p/oe7u/kHs
CZ8/yx+wKHz+DC1GJqss8pX82cz1KsLmT7AUVJLnapIssybJMSe1qucYTsiq
fhQ9/WeMzL8cqG/Hk+X+i+/lC3Q4+NKMWfAljdn6N2sv8yBu+GpDNXY0g+87
Ix229/CX4G8z7t6X3/5jnhVaxfvf/OP3kShzulrcsz7umX2aVMyvyorot82n
CuaTZKlMI1Qw+vuxmVSbZ5L3wCU0Vb5VRtG7sm4OogO62JmDjYQqayIkq0UK
9tWAz55JUpS4V+WR6iiNqB1aFu/JrnIzzoqkglrG+j6qPTTCzx4KfXWY16VR
WhK1xSrWlpqUeV7+2maQ3v0oOvxhQAU4A6X6gcp3F+BXfDR3VIweNO120kBQ
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
KDFhP/p/AS8vIZxDIAEA

-->

</rfc>

