Skip to content

Security statement

Version 1, 2026-09-25. Changes to this page are listed at the end.

magnet is one binary on a machine. It compiles the model language to a Rust crate, simulates it, and serves the graphical editor to a browser on the same machine. There is no cloud compiler: models, source files and generated code never leave the machine they are on.

Two hosted services exist beside it, and neither is on the build path:

  • The dashboard, where an administrator manages seats. It talks to the identity provider for sign-in and to the licensing service for seats.
  • The licensing service, which holds the seats and answers magnet when a machine is activated or a license is renewed.

magnet gui and magnet serve start a server for the editor. It binds loopback only (127.0.0.1, port 7317 or an ephemeral one if that is taken); there is no flag to bind anything else.

Every start generates a fresh random token, written to the project’s .magnet/kernel.json readable by its owner only. Every data route (the WebSocket and the file endpoint) requires it and answers 403 without it.

Browser requests are also checked by origin: an Origin or Host header with any value other than 127.0.0.1, localhost or [::1] is refused, which is the standard answer to drive-by requests from other pages and to DNS rebinding.

The file endpoint serves only paths inside the project directory, checked after canonicalisation.

The server makes no outbound connections of its own.

magnet makes exactly these, and no others. There is no telemetry, no crash reporting and no analytics in the binary, the editor or the dashboard.

When To What is sent
magnet license activate the licensing service, api.keygen.sh the seat’s key as the credential; this machine’s fingerprint (a digest, below), its name and operating system
renewal, at most every thirty days the same the key and the machine’s id on the service; nothing else
magnet license deactivate the same the key and the machine’s id
magnet self-update the licensing service, then the release download from its storage nothing but the request, with no key: which version this magnet is, and the name of the archive for its platform
the install one-liner dashboard.magnetite.rs / get.magnetite.rs, then the release download nothing but the request; the response is the installer script and the release archive
the first magnet build on a machine the Rust package registry cargo’s own fetch of the public runtime crate; every later build runs offline
a git dependency in your Magnet.toml the host in your manifest your own git, with your own credentials and configuration; magnet carries no git credentials

The licensing calls carry Authorization: License <key> (the seat’s own key, never a credential of ours) over TLS 1.2 or later, with a fifteen-second timeout and no retries.

TLS trusts the operating system’s certificate store, so a proxy that inspects TLS with an enterprise root works without configuration, and the standard HTTPS_PROXY, HTTP_PROXY and NO_PROXY variables are honoured.

Verification is offline: the license on disk is checked before every command against a public key compiled into the binary and this machine’s fingerprint, and that path opens no socket. The crate that implements it is built without any networking dependency, and a test in the repository fails if one ever appears in its dependency graph.

A machine that cannot reach the licensing service keeps building until its license file expires, thirty days after its last renewal at most.

For a proxy allowlist:

  • api.keygen.sh on 443 for activation and renewal;
  • dashboard.magnetite.rs and get.magnetite.rs for installs and updates;
  • the Rust package registry for the first build, or a mirror of it configured in cargo;
  • whichever git hosts your own projects use.

A machine with none of those still runs magnet with a license file installed by hand: magnet license fingerprint prints what to send us, and magnet license install <file> installs the file that comes back. Neither opens a socket.

What leaves the machine, and where it is held

Section titled “What leaves the machine, and where it is held”
Data Sent to Held by
machine fingerprint (SHA-256 of the OS machine id), its name, OS the licensing service the licensing service, until the machine or its seat is removed
the seat holder’s email address, organization name written by the dashboard the licensing service, until the seat is removed
the identity provider’s ids for the user and organization written by the dashboard the licensing service and our database
sign-in credentials the identity provider the identity provider; we never see a password

The fingerprint is a digest of the operating system’s machine identifier (/etc/machine-id, the platform UUID, MachineGuid); the identifier itself is never sent. The digest is unsalted and stable for the life of an operating system install, so it tells one machine apart from every other: we treat it as personal data (pseudonymous, not anonymous), and it can be read, exported and erased like the rest.

A machine’s name is there so a holder can tell two machines on a seat apart. Unless you choose one with magnet license activate --name, it is the platform and the first six characters of the fingerprint (macos-3f9a1c), made of what the request already carries. The hostname is never sent: a laptop is as often as not named after its owner.

Nothing about the models, the source, the generated code, the project’s name or the machine’s other contents is ever transmitted.

Our own database holds organizations, subscriptions and an audit log of administrative actions (what was granted, revoked, issued or removed, by which user id, and when). The log records ids and never a person: it holds no email address and no machine name, and the database refuses one. It holds no passwords and no user table, because sign-in is the identity provider’s.

What is kept about a person, for how long, and how they read or erase it is on the privacy page.

In the user’s home directory, ~/.magnet/ (or MAGNET_HOME):

File What Permissions
license.lic the signed license file owner only
license.key the seat’s key, which renewal authenticates with owner only
bin/ the magnet binary and the shell PATH shim default

license.key is the key string a holder types once, not key material: the only key that verifies a certificate is the account’s public one, compiled into the binary and never read off a disk. It is kept because a certificate cannot renew itself (the service redacts the key inside the certificate it signs), so a machine that checks itself out again has to hold the credential it checks out with.

The installer appends one line to the shell’s startup file to put bin/ on the PATH. cargo keeps its own registry cache under ~/.cargo, as it does for any Rust build. Everything else magnet writes is inside the project:

  • the server’s token and log and the dependency checkouts under .magnet/;
  • the diagram layout under layout/;
  • the generated crates and their build output under target/.

license.lic contains its holder’s address and organization, as any license does. magnet license deactivate frees the machine’s slot on the service and deletes both files. magnet uninstall removes the binary and leaves them, so a reinstall does not consume a machine slot; delete ~/.magnet to remove everything.

A seat is one person’s license, and its key is the only credential magnet ever holds. A seat runs on at most two machines at once; a third activation is refused with a message that points to the dashboard, where its holder removes one.

Activating puts a signed license file on the machine, good for thirty days and renewed in the background when it is due; every command verifies that file offline, against the public key in the binary and this machine’s fingerprint, before it does anything.

What follows from verifying offline is accepted, and stated here rather than found:

  • a revoked seat keeps working on a machine until that machine’s file runs out, thirty days at most;
  • the fingerprint identifies an operating system install and is not a hardware attestation;
  • a server started before an expiry keeps running until it is restarted, because the check runs when a command starts.

Releases are built by our continuous-integration pipeline from a tagged commit, for four targets, and every archive is signed there with a release key of ours (Ed25519). Its private half is the pipeline’s, and is not held by the service that stores the archives; the public half is compiled into magnet.

An update is accepted only if we signed it: magnet self-update asks the licensing service which release is newer, downloads that release’s archive for its own platform, and verifies the signature over the whole file against the compiled-in key before anything is unpacked, and it runs no script.

The service that stores the archive does not hold the key, so neither it, its storage, nor anything on the network path can make magnet install a file we did not publish. Rolling the key is itself a release.

A first install rests on TLS, because there is no magnet on the machine yet to check a signature with. The one-liner fetches a short script from the hub over TLS 1.2 or later and runs it, as every curl … | sh installer does. The script reads the whole response before running any of it, so an empty or failed download is an error and not a silent no-op.

A review that wants more downloads the archive and its signature by hand and checks them against the public key, which we supply on request; from the first self-update on, the paragraph above applies.

  • Every crate of ours is #![forbid(unsafe_code)]; the compiler refuses the crate if any unsafe block appears.
  • Third-party dependencies are pinned by a committed lockfile and built with --locked; the pipeline refuses a build whose lockfile has drifted.
  • On every change, the pipeline checks all dependencies against:
    • an allow-list of licenses (permissive only; nothing copyleft reaches the binary or can be near generated output);
    • the Rust advisory database;
    • a source policy that refuses unknown registries and unknown git sources.
  • TLS is a Rust implementation with the operating system’s roots; no C TLS library is linked into the binary.
  • Every release carries a CycloneDX 1.5 SBOM of the magnet binary and a NOTICE file of third-party attribution, both regenerated from the lockfile by the pipeline, not by hand; neither is committed, because a copy in the tree could only be a staler one. Both are attached to the release they describe.

The crate magnet build writes is #![no_std], compiles warning-free under -D warnings with no lint suppressed, and depends on one published crate (the public runtime) plus whatever a custom block declares. Its contents are a function of the project’s sources and the magnet version alone; nothing from the machine, the clock or the network enters it.

The pipeline builds the same generated crate for a bare-metal ARM target and for WebAssembly on every change, which is how the “no platform assumptions” property is kept.

The model language has:

  • no allocation;
  • no pointers;
  • no unsafe;
  • no unbounded loops;
  • no recursion: recursion, direct or mutual and across files, is rejected by a dedicated check.

The one seam is extern, by which a project brings in a custom block written in Rust; that Rust is yours, compiled into the generated crate, and is reviewed as any hand-written code is.

These properties hold by the grammar today; a test suite that asserts each of them as a property, so the claim is checked rather than stated, is planned and listed below.

  • No third-party audit, SOC 2 or ISO 27001 report exists. The controls above are documented and testable, not attested.
  • Binaries are not yet signed with an operating-system code-signing identity; macOS and Windows will warn on first run.
  • The language’s sandbox properties are enforced by its grammar and its checks, and not yet asserted by a dedicated test suite.
  • The dashboard, its database and the documentation site run in a single region in the European Union (the Netherlands) with a hosting provider; there is no multi-region failover. An outage of the licensing service delays activations and renewals and stops nothing that is already licensed.
  • Revocation reaches a machine at its next renewal, up to thirty days after the seat is revoked.

Services that process data on our behalf. This is the one place on this page a provider is named, because a subprocessor list has to say who they are.

Role Provider What it holds Where
identity provider Clerk sign-in for the dashboard: accounts, sessions, organization membership United States
licensing service Keygen seats, seat holders’ addresses and organization names, machine fingerprints and names; release archives United States
hosting Railway the dashboard, its database, the documentation site, and their request logs European Union (the Netherlands)
source and builds GitHub the repository and the pipeline that builds releases; no customer data United States

Write to security@magnetite.rs. Say:

  • what you found;
  • how to reproduce it;
  • which version (magnet version) or which page of the dashboard.

If it involves a customer’s data or a live seat, say so in the first line. Please do not open a public issue for it, and do not test against seats, organizations or accounts that are not yours.

  • We acknowledge within two business days, with a named contact.
  • We say what we found and when a fix will ship; a fix for a confirmed vulnerability in the CLI or the dashboard goes out as the next release.
  • We ask for ninety days before public disclosure, or sooner once the fix has shipped, and credit the reporter in the release notes unless asked not to. There is no bounty programme.

In scope:

  • the magnet binary and the code it generates;
  • the dashboard, the hub behind it, and the installer scripts;
  • the documentation site.

The identity provider, the licensing service and the hosting provider have their own disclosure programmes, and a problem in one of them that reaches our customers is still something we want to hear about.

Supported versions: fixes land on the newest release, and a prerelease (-alpha.n) receives them as the next prerelease. Nothing older is patched; update with magnet self-update or the installer.

  • Version 1, 2026-09-25. First published version.
  • 2026-10-07. Where magnet writes inside a project, stated by directory; the version command’s name. No change to what is sent or held.