Security statement
Version 1, 2026-09-25. Changes to this page are listed at the end.
The shape of the product
Section titled “The shape of the product”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
magnetwhen a machine is activated or a license is renewed.
The local server
Section titled “The local server”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.
Every network connection
Section titled “Every network connection”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.shon 443 for activation and renewal;dashboard.magnetite.rsandget.magnetite.rsfor 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.
Files written outside the project
Section titled “Files written outside the project”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.
Licensing
Section titled “Licensing”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.
Installation and updates
Section titled “Installation and updates”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.
Dependencies and supply chain
Section titled “Dependencies and supply chain”- Every crate of ours is
#![forbid(unsafe_code)]; the compiler refuses the crate if anyunsafeblock 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
magnetbinary and aNOTICEfile 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 generated code
Section titled “The generated code”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.
What we do not claim
Section titled “What we do not claim”- 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.
Subprocessors
Section titled “Subprocessors”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 |
Reporting a vulnerability
Section titled “Reporting a vulnerability”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
magnetbinary 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.
Changes to this page
Section titled “Changes to this page”- Version 1, 2026-09-25. First published version.
- 2026-10-07. Where
magnetwrites inside a project, stated by directory; the version command’s name. No change to what is sent or held.