Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Trust model

Every assumption the system relies on without proof is named, as an atom in some trust formula (rule 5 of AGENTS.md). This chapter lists what the architecture assumes, what this implementation adds, and what a light client trusts when sion verify prints a check mark.

What the architecture assumes

PropertyComes fromAssumes
Validity of the stateThe World ProofThe proof systems are sound (two independent stacks: either suffices), the specification is right, SHA3-256 is collision resistant
Ordering, finality, livenessCommitteesFewer than a third of each committee’s stake is Byzantine; partial synchrony for liveness
Censorship resistanceForced inclusion, rotation, samplingAt least one honest proposer; a committee that censors can be replaced
Data availabilitySampling and erasure codingEnough clients sample; the data root commits to a correct encoding (bound by the World Proof)
SignaturesML-DSA-44 and SLH-DSA togetherAt least one of the two families is unbroken
Knowledge (claims)The Assurance AlgebraNothing: a claim states the atoms it rests on, and each consumer prices them under its own policy

The trust formula of a dual proof, from the architecture:

specification ∧ sha3-256 ∧ ((stack A ∧ circuit A) ∨ (stack B ∧ circuit B))

What this implementation adds

These atoms are part of the formula of anything the devnet reports, on top of the architecture’s own. The list is copied from the repository’s implementation status.

AtomWhat it means
impl:replay-proofsWorld Proofs are checked by re-execution, so “proof finality” costs a verifier as much as executing; succinctness is assumed, not delivered
impl:shared-primitivesBoth proof stacks use the same hashing, Merkle, signature, Assurance Algebra and clearing-certificate code; a bug there is common-mode
impl:devnet-keysDevnet validator keys are derived from the chain name; anyone can derive them. A devnet secures nothing of value
impl:in-process-networksion devnet only: validators share a machine and a process; network faults are exercised only through the in-process fault injector and the consensus simulator. A network of sion node processes does not carry this atom
impl:reliable-handoverAt an epoch boundary each validator starts a new consensus session; a validator that has not reached the boundary finishes the old session from messages already sent, which the in-process network always delivers. A real network needs a drain period: on a network of processes, a validator that misses old-session messages at a boundary can stall
net:transport-ml-dsaNetworks: transport authentication rests on ML-DSA-44 alone (each node’s network key, presented as an RFC 7250 raw public key and pinned at both ends). A forger could impersonate a peer at the transport layer (delay, drop, eclipse), not sign consensus messages, which carry dual signatures
net:aws-lcNetworks: the TLS provider is aws-lc-rs, C code outside the workspace’s audit scope (the workspace’s own post-quantum code is pure Rust)
net:raw-public-keysNetworks: TLS authenticates nodes with RFC 7250 raw public keys (an ML-DSA-44 SubjectPublicKeyInfo, signed for in the handshake’s CertificateVerify), not the self-signed ML-DSA X.509 certificates the design proposed, and with no channel-binding fallback. Both ends pin the exact key, so no certificate path is validated; the handshake relies on rustls’s raw-public-key support, newer and less used than its certificate path
net:static-peersNetworks: peers come from a genesis file and a peer file of signed records, read when a node starts, not from the state. A validator that joins by staking is reachable only by nodes started with its record in their peer file
net:partial-synchronyNetworks: liveness needs message delays to become bounded after some time (assumed by the architecture; named because a real network now exercises it)
net:gateway-trusts-nodeNetworks: a gateway running alone learns committees and answers state queries from one node it trusts. A lying node can make it ask the wrong validators or show wrong balances; it cannot get a transaction certified that a committee did not approve
net:no-rejoinNetworks: a validator that stops cannot rejoin. Restarting in a session it signed in needs the consensus signing log, and catching up to a later session needs Pulse sync; neither is built, so it refuses to start rather than risk equivocation. Each stopped validator is a permanent fault; more than a third of the stake stopped halts the chain
impl:slashed-seatA slashed validator keeps its seat, and its weight in quorums, until the epoch ends
impl:active-floorValidators can leave until one remains: nothing keeps the active set large enough to tolerate a faulty member, so the operators of the other validators can leave a single validator forming every quorum
impl:evidence-scopeEquivocation evidence is not bound to this chain: a validator’s keys must not be used on another network
impl:lock-handoverCertificates are not drained when a lane committee changes: certificate finality for owned transactions holds within one committee’s term (an owner who double-signs could get the second spend certified by a fully replaced committee)
impl:hash-chain-beaconThe beacon is a hash-chain commit-reveal; the last validator to reveal can bias it by withholding (at the cost of being seen)
impl:public-amountsAmounts and balances are visible to everyone
impl:memory-indexThe ledger stores a memory log’s index root without checking it: a memory query proof is complete relative to that root, and nothing on the ledger yet acts on evidence that an index leaves an atom out
impl:unaudited-pq-cratesThe FIPS 203/204/205 implementations are unaudited pure-Rust crates
storage:no-replicationA storage proof shows that the provider could produce the challenged leaves during the round, not that it keeps a copy of its own: it could fetch them from another copy (or from the client) when challenged. Two deals with two providers are not proof of two copies
storage:raw-proofsEvery storage proof carries its challenged leaves and paths on the ledger, about 17 to 22 KiB a deal a round with 4 challenges. Proofs are not aggregated across deals or rounds, so ledger bandwidth bounds how many deals a network can keep
storage:no-retrievalGetting data back is not part of the protocol: a provider proves custody, and returning the data to its client is up to them
app:agent-searchThe agents the app finds for the device come from the node’s history of events, unproven, and only the Pulses the node still keeps: a node can leave out an agent the device backs, and the Agents tab would not show it. The standing and budget of every agent it shows are proven
app:first-use-pinThe app pins the chain identity of the first node it verifies (trust on first use) unless its user pins one first. A first use against a lying node pins the liar’s chain
app:plain-keyThe app keeps the device’s key unencrypted in its directory (mode 0600 on Unix), not in the platform’s keystore. Anything that can read the directory can spend
app:unproven-balancesThe balances the app shows come from the node unproven; its own receipts and the Pulses it verifies are proven
agent:local-policyAn agent runtime’s autonomy level, approvals (those people give for the rest of a session included), grants, taint, token budgets and its stop for a model going round in circles are enforced by the runtime on the machine it runs on. Only the agent’s charter (payees, limits, budget, expiry, suspension) is enforced by the ledger
agent:provider-sees-contextA model provider receives the conversation it is asked to continue, tool results included
agent:plain-sessionsAgent sessions, with their conversations and journals, are stored unencrypted under $SION_HOME/agents/sessions
agent:local-skill-checksThe runtime on the agent’s machine checks a skill’s bundle against its release when installing it, and takes a skill out of use when its release is no longer active at the start of each run. A session already running keeps the skill until it ends, and installed files changed on disk afterwards are not checked again
agent:eval-runsEvaluation runs are not proven. A verifier’s attestation that a version passes an evaluation set rests on its bond and the bounty’s adjudicator; with a model that varies between runs, another run can differ. The ledger refuses an attestation by the version’s author (specification v1.15), but not one by an account the author controls under another name: such an attestation is worth its own bond
agent:channel-tokenWhoever holds the machine’s channel token can start and continue the sessions of every profile on the machine, approvals included; whoever holds a profile’s own token, that profile’s, and approvals only with a token made for them; always within each profile’s autonomy and the agent’s charter. Tokens are kept as their hashes. The channel speaks plain HTTP
agent:gatewayAn agent gateway sees, and could change, the messages and answers it passes; it cannot act as an agent on the ledger, holding no key. It routes a profile’s messages only to a host that proved the key of the agent its tokens name for the profile, and checks the agent’s standing at most five seconds old, from the node it trusts: a message can reach an agent suspended within those seconds. It speaks plain HTTP unless put behind TLS
agent:messenger-identitySlack, Discord, Matrix, Signal, Telegram, WeChat, Zalo and X say who wrote a message: a bridge’s approvers are who the messenger says they are, and anyone who can write in an allowed chat talks to the profile
agent:telegram-chatsA Telegram bot trusts Telegram for who writes in the chats it answers; in a group chat, every member speaks for its owner, approvals included unless --approvers names who may decide
agent:pairingAn approved pairing code lets in the chat it was sent to, on that channel and profile, until revoked: the operator trusts that whoever gave them the code is the person they mean to let in, and the messenger for who writes in that chat afterwards (agent:messenger-identity). Codes are kept in a file only the operator’s user can read
agent:irc-nicksOn IRC, who wrote a message is the nick the server gives: on a network that does not hold nicks to accounts, anyone can take a nick that is free, approvals included where --approvers names nicks
agent:email-fromAn email is taken as from the address its From names only as far as the mail provider’s Authentication-Results show (DMARC passing for its domain, or DKIM or SPF passing for a domain aligned with it), read from the topmost results or the topmost of the server EMAIL_AUTHSERV_ID names: the provider is trusted to write its results above everything a sender wrote, and to check what it says it checked. With EMAIL_TRUST_FROM, From is taken as it is. Alignment is taken as one domain being the other or under it, not by the public suffix list
agent:imessage-handlesOn iMessage, who wrote a message is the handle Messages shows, as Apple’s service vouches for it; an SMS (through a paired iPhone) carries the number the phone network gives, which can be forged. imsg, run as the operator’s user with Full Disk Access, reads the whole Messages database for the bridge
agent:service-tokensA service’s tokens (sion agent service install --env) are kept in plain text in a file only the user reads (systemd’s environment file, or the launchd agent): whoever can read the user’s files can read them
release:signing-keysion update, and the installer, install a release only if its SHA256SUMS are signed by a key the program (or, for the installer, the repository’s scripts/release/allowed_signers) names: whoever holds that key, a secret the release workflow signs with, can publish what they install. ssh-keygen checks the signature; the installer’s first fetch trusts HTTPS and GitHub, and a build whose file names no key does not update itself
agent:webhooksA webhook (WhatsApp, LINE, SMS through Twilio) is taken as its service’s when it carries the service’s signature with the secret the operator gave. The signatures name no time, so a webhook copied on its way could be sent again later and is answered again once its id has left the last thousand remembered; the bridge listens on plain HTTP, and TLS is the operator’s proxy’s
agent:teams-tokensA Teams webhook is taken as the Bot Connector’s when its token is signed by a key login.botframework.com publishes (fetched over TLS, kept a day), issued by https://api.botframework.com for the bot’s app ID, within five minutes of its times, by a key endorsed for the activity’s channel, and naming the activity’s service URL, where the reply goes with the app’s token; who wrote a message is who the Bot Connector says (agent:messenger-identity)
agent:google-chat-tokensA Google Chat webhook is taken as Chat’s when its token is signed by a key Google publishes for chat@system.gserviceaccount.com, for the app’s project number (or, with the endpoint URL as audience, is Google’s ID token of the sender named, for that URL), within five minutes of its times; who wrote a message is who Chat says. With a service account’s key, the bridge signs its token requests with it: whoever reads the key file can act as the app
agent:dingtalk-streamDingTalk’s messages come over a connection the bridge opens to DingTalk with the app’s credentials, over TLS: who wrote a message is who DingTalk says, and a voice note says what DingTalk heard. Replies go to the session webhook the message names, which is DingTalk’s, or after it expires through the robot’s API
agent:feishu-tokenA Feishu or Lark webhook is taken as theirs when it carries the event subscription’s verification token: a secret in each event’s body, as Feishu sends it, not a signature, so whoever saw one event on its way could send others; unless the subscription has an Encrypt Key, with which events are encrypted and signed (SHA-256 over the time, a nonce, the key and the body) and one not signed with it is refused. The address’s check, which Feishu does not sign, is taken when it decrypts with the key and carries the token
agent:talk-signaturesA Nextcloud Talk webhook is taken as the server’s when it is signed with the bot’s secret (HMAC-SHA256 over a random value and the body) and names the server. The signature names no time: a webhook copied on its way could be sent again, and is answered again once its message has left the last thousand remembered
agent:wecom-callbacksA WeCom callback is taken as WeCom’s when it is signed with the callback’s token (SHA-1 over the token, the time, a nonce and the ciphertext) and decrypts with the EncodingAESKey to a message for the company. The signature names a time the bridge does not bound: a callback copied on its way could be sent again, and is answered again once its message has left the last thousand remembered. Who wrote it is who WeCom says
agent:qq-signaturesA QQ webhook is taken as QQ’s when it is signed with Ed25519 under the key both sides derive from the bot’s secret: whoever has the secret can sign events as QQ. The bridge signs the address’s check back with the same key, only a plain token and time, so that nothing it signs can pass for an event. Who wrote a message is who QQ says
agent:ntfy-topicsntfy names no writer: whoever may publish to a topic the bridge answers speaks for the operator there, approvals included unless --approvers names who may decide (ntfy names no one, so no one may). A topic on a server that asks who publishes, or one whose name nobody can guess, is the operator’s to keep
agent:phone-callersA phone call is taken as Twilio’s when each of its steps is signed with the account’s auth token for the public address Twilio was given; who calls is the number Twilio gives, which the phone network carries and which can be forged. What the caller said is what Twilio heard, and the reply is what Twilio speaks
agent:synology-chat-tokenA Synology Chat request is taken as the NAS’s when it carries the bot’s token: a secret in each request’s body, as Synology Chat sends it, not a signature, so whoever saw one request on its way could send others. Who wrote it is who the NAS says; replies go to the incoming URL the operator gives, on their own network
agent:simplex-clientSimpleX’s terminal client is trusted with the bot’s profile: its WebSocket API asks no password, so any program on the machine that reaches its port acts as the bot, and the bridge must be the client’s only program. Who wrote is the contact or member the client says, as it numbers them; SimpleX names no one beyond that
agent:nostr-relaysNostr’s relays carry the messages: one can withhold or delay them, not forge or read them, as every event is checked against its signature and a private message against who sealed it. Who wrote is the key that signed. An older message (NIP-04) shows the relays who writes to whom and when; a private one (NIP-17) hides both. NOSTR_PRIVATE_KEY speaks for the account, and signs the bridge in to the relays that ask
agent:home-assistantHome Assistant’s token (HOME_ASSISTANT_TOKEN) acts as the user it was made for: calling a service does whatever that user may, in the home itself. Calls are external calls, which autonomy L4 asks a person for; what Home Assistant says (names its users gave) taints a session as a web page does
agent:voiceThe services --hear and --speak name receive the voice notes and the replies spoken; the profile acts on what the transcription says was said, within its autonomy and the agent’s charter. A command: provider runs as the operator’s user, outside any sandbox
agent:local-schedulerScheduled jobs run only while sion agent scheduler runs on the machine (or a system timer calls it); a missed run happens once, late
agent:keyless-signerA keyless subagent is contained by the runtime that holds its nearest keyed ancestor’s keys: the ledger lets only that ancestor sign for it, and holds it to its own caveats, but a subagent that could make that runtime sign something else as the ancestor would act within the ancestor’s caveats, not its own. The runtime signs only for the session’s own tool calls
agent:sandboxCommands an agent runs (its shell, its skills’ scripts, MCP servers started in a sandbox) are contained only as far as the kernel’s namespaces (bubblewrap) or the container runtime (Docker) hold: an escape gives them the runtime’s user. Bubblewrap bounds how long a command runs and the size of each process, not how many processes it starts; Docker bounds those too. A container started by a runtime that is killed runs until its command ends
agent:sandbox-networkWith the network allowed, a sandboxed command reaches what that network reaches. Bubblewrap’s host network is the machine’s own, unfiltered: local services and a cloud’s metadata address included. The declared network gives commands none, and skills’ scripts only what their skills declare, through the egress proxy (agent:declared-hosts). A Docker network restricts only as its operator set it up: the runtime refuses Docker’s host and bridge networks by name and cannot check the rest
agent:shell-repeatsShell commands, skills’ scripts and file writes are not journaled: a command the model gives again runs again, so with the network a repeated command can repeat an action outside the machine
agent:workspace-contentWhat an agent reads from its own workspace (files, and the output of commands without the network) does not taint its session, even content it saved there from outside in an earlier session
agent:mcp-unsandboxedAn MCP server added without a sandbox runs as the operator’s user, with the environment variables its configuration names: it can do whatever that user can
agent:mcp-effectsWhat an MCP tool’s call does is what its server does. The runtime knows it only from the annotations reviewed with the tool, or from the effect its operator set: a tool that does more than it says (moves money elsewhere, say) is caught only by the review, and an agent’s charter does not bound money a tool moves outside the ledger. A pin shows that a tool’s definition is the one reviewed, not that its server’s code is
agent:consolidationA consolidated note is a model’s reading of the episodes it cites. The gates check that it cites episodes it was shown, that the notes it replaces exist, its kind and its size, not that it reads the episodes right. Each note links to its episodes and names the model and the consolidator, so it can be checked against them
agent:recall-localSession search reads the sessions kept on the machine the agent runs on. A hit’s check shows whether a stored session still hashes to the digest its episode recorded; a session never recorded (it did not finish, or ran without a memory log) is searched unchecked
memory:archive-keyA memory archive is encrypted under a key derived from its writer’s wallet seed: whoever holds the seed can open it, and on a devnet anyone who knows a named wallet’s name. A provider sees an archive’s size, which log it is of, and when it was made
storage:retrieval-replayA provider checks a retrieval request’s signature and expiry (at most five minutes ahead), not whether it was seen before: within that window a copied request retrieves the data again. Retrieval speaks plain HTTP unless put behind TLS
agent:storage-from-accountA storage deal an agent posts is paid from its account’s balance, the money it pays fees with, not from its charter’s budget: the charter’s caveats do not bound it
agent:skill-pre-approvalA skill a session has read pre-approves the calls its allowed-tools names until the session ends: where the autonomy level would ask a person, they run. A rule naming a command’s first words (Bash(git:*)) covers whatever that program can be told to do through its arguments, inside the sandbox. A pre-approval never covers a call the level refuses, spending, or a session that has read content from outside, and the agent cannot grant one, since it writes only a skill’s name, description and instructions: it comes from whoever placed the skill, or from the operator’s consent when installing its release
agent:session-allowanceA person who approves a call may allow, for the rest of the session, the same call again, or the calls of its tool a rule matches (shell(git status:*), as a skill’s allowed-tools writes it): those run without asking. A rule naming a command’s first words covers whatever that program can be told to do through its arguments, inside the sandbox. An allowance never covers a call the level refuses, spending, or a session that has read content from outside (and none is given while it has); it is given only by someone who may decide, kept with the session with who gave it, and withdrawn with /allowed off
agent:token-estimateA run’s token budget is held to an estimate of what each model call sends (a token for every three bytes, pictures as some text would be) and the most it may answer; the tokens a provider reports are counted as it reports them. A provider that counts more tokens for the same request (some scripts, pictures) can take a run past its budget by the difference, and a subagent’s tokens count once its run has ended
agent:quarantineIn quarantine, content from outside is held out of the agent’s conversation and read by a reader that has no tools, whose answer is held to a schema the agent gives. An answer of values (booleans, numbers, strings from an enum, strings of a strict format) does not taint the session, though it is only what the content made the reader say, and can be false; an answer with free text taints it. The strings an answer gives are matched in arguments exactly as given (four characters or more), so an argument the agent writes from one in another form is not caught. A browser’s pages, a desktop’s screens and the shell’s output are not held
agent:verifierA check the operator gives (--verify) runs in the agent’s sandbox, in its workspace, where the agent can change what the check reads or runs there (its tests, its scripts, a test runner’s settings). The check’s own files (--verify-files) are bound into the sandbox only while it runs, read-only, so the agent’s commands neither see nor change them, though a tool that reads files outside the workspace (an MCP server of the agent’s own) could. A check that passed shows that the command exited with status 0 then, not that the work is right, and a score is what the command printed
agent:task-checkA task’s check is fixed by the commitment in its spec when the task is posted, and sion task verify runs only the check committed, in a sandbox with no network, on a fresh copy of its files, attesting the output only if it exits with status 0. The ledger does not see the run: an attestation made without it (sion task attest) counts the same, so what keeps an attestation honest is still its verifier’s bond and the task’s adjudicator. A check passes what it was written to pass (one that looks only at an output’s form passes a wrong answer); it is not handed to the worker, but whoever the poster gives it to can pass it on
agent:comparisonA comparison (sion agent graph eval) measures a profile’s models on the set’s cases with their stand-in tools, not on its real tools, and its figures are what those runs did: its intervals treat every run as independent, though repeats of a case are not, so they are narrower than they would be over as many different cases. A template that beat both baselines on one set is offered by the router for any of the profile’s tasks, as the model judges them, until a later comparison on that set says otherwise
agent:judgeA judge (sion agent judge, --judge) is a model’s judgment of each step, not a check: it can be wrong, and what the steps quote can steer it, though it is told that they are data. Its calibration is its agreement with four labelled steps it was not shown, which says little about steps unlike them
agent:graph-replayA graph’s run is pinned to the digest of its graph in the run’s own file, which catches a graph changed after the run began, not one changed with its digest; a replay answers each node with what the run recorded, so it shows how the graph routes those answers, not that its models would answer the same again
agent:read-only-nodeA read-only node (read_only) gets the tools whose declared effect is to read: a tool that declares less than its calls can do is not held back (agent:mcp-effects)
agent:confidential-labelA session holds confidential content only as far as it is marked: by --confidential, by read_file under the paths named, or by a subagent’s report or a graph node’s input from a session that held some. The shell, scripts, MCP tools and the browser can read the same data without marking it, and a tool the operator contained is not held
agent:signed-decisionsA signed decision shows that the wallet’s keys signed it as recorded, not who held them; decisions made in chat apps are not signed, and a signature names the call by its key and the digest of its input, which a compacted session may no longer show
agent:imitated-notesOnly the runtime’s notes as it writes them are marked in a tool’s result, case aside; other words that claim the same are not. The mark informs the model: what holds a call is the policy, and approvals are kept in the session’s state, never read from text
agent:attack-testsThe attacks tested are the ones listed, against a scripted model that obeys every instruction it reads: they show what the runtime enforces without the model, not that no other attack gets through, and what got through in them gets through
agent:a2a-webhooksAn A2A task’s updates go to the webhooks its client registered, which the server checks only for being HTTPS addresses that resolve to public ones (unless the operator allows this machine’s network): whoever holds a token that reaches the profile can have its tasks’ states sent anywhere public, and a webhook is told the task as it stands, its reply included
agent:dream-quoteA note a dream keeps rests on the words of its session it quotes: that they are in the session’s transcript, as they are written there, shows that they were said in it (by the person, a tool or the agent itself), not that the note is true, nor that it says what they meant
agent:dream-testA dream’s test runs each held-out case with the core memory as it is and with the dream’s notes in mind, every note as if kept in view, and records the notes only if no case passes fewer times with them: it tests what its cases check and no more, and a model that differs from the agent’s (--eval-model) tests that model
agent:curated-logA curated log is written only with its curator’s key, so whoever holds that key decides what it says; the agents that keep it in mind (--shared-memory) see its notes as its local store on their machine shows them, and recall searches only their own logs
agent:declared-hostsThe egress proxy holds a skill’s scripts to the hosts their skill declares by the name a script asks for, at addresses that are public where they resolve on the machine. A declared host that forwards what it is sent, serves what others put there, or shares a front (a CDN) whose other sites a script can ask for inside the encrypted tunnel takes a script further. Behind an upstream proxy, a name the machine cannot resolve goes to that proxy, and its network decides where the name leads. With Docker, declared hosts are not filtered: the operator’s network decides
agent:secret-storeSkills’ secrets are kept encrypted under a key in a file beside them, readable only by the operator’s user: whoever can read that file can read them. A script that receives a secret can send it wherever its skill may connect, and can change it so that it is not cut out of what the model sees: the runtime removes the value as it is, not every encoding of it
agent:kept-credentialsThe credentials sion itself uses (models’ keys and addresses, speech services’ keys) that sion setup or sion agent credential add keeps are encrypted under the key in a file beside them, readable only by the operator’s user: whoever can read that file can read them, as whoever can read a process’s environment can read the variables it would otherwise be given. A variable set in the environment is used instead of a kept one
agent:mcp-remoteAn MCP server over HTTP runs elsewhere, under whoever runs it: it sees the arguments of every call made to it and answers what it likes. Over HTTPS its certificate shows only that it holds the name in its URL; plain HTTP, which the client allows to any address the operator gives, is as private as the networks it crosses. A header whose value names an environment variable (${VAR}) sends that value with every request
agent:mcp-oauthOAuth tokens for MCP servers are kept encrypted under the secrets’ key (agent:secret-store): whoever can read that key can act at that server as the person who consented, with the scopes granted, until the tokens expire or are revoked, and a refresh token renews them without the person. The login trusts the authorization server the server’s metadata names: it checks that the metadata names the server, that the authorization server’s own names it as issuer and that its answer comes back with the state and the issuer sent, and holds discovery and tokens to HTTPS at public addresses (plain HTTP when the MCP server is on this machine, private addresses when it is at one), but an authorization server of an attacker’s that a server names is caught only by the person reading the page they consent on. logout revokes tokens only where the authorization server takes revocations; elsewhere they stay valid until they expire
agent:browserThe browser is Chromium (or Chrome), contained by bubblewrap’s namespaces where it runs in them (its own sandbox is off there, as it cannot nest inside), with the machine’s managed browser policies; elsewhere by its own sandbox, as the operator’s user, and never as root. Without bubblewrap it reaches the egress proxy through a port on this machine’s loopback, which any program of the machine can use while it runs, the runtime’s upstream proxy and its credentials included
agent:browser-hostsA browser held to the hosts the operator names acts on their pages after reading them, as the autonomy level allows: a page there can lead the model to carry what it knows to that site, in an address, a form or a post, and a named host that forwards what it is sent, or serves what others put there, takes it further. Without named hosts, its actions after a page wait for a person
agent:browser-loginsA login is filled only into a field whose frame is of the login’s origin, as the browser knows it: a page of that origin can still send what is typed in it elsewhere, so a login is as safe as its site’s pages. The password is cut out of what the browser returns as it is, not in every form a page could show it in
agent:desktopA desktop’s programs are contained as its sandbox contains them, their address space unbounded under bubblewrap; the X server they share lets each read the others’ windows and send them input. A Docker desktop reaches what its Docker network reaches
impl:batch-size-feeA batch member’s fee floor splits the cost of checking signatures by the size its batch declares. A signer that declares 256 members and sends one pays about a fifth of the base fee for a signature check; validators bound this by checking cheap things first and taking batches whole
impl:insecure-sim-signaturesOnly when a devnet is started with --insecure-fast-signatures: validators sign with a simulation MAC. The chain identity records it, and light-client reports say so

What a light client trusts

A client pins one value, the chain identity, from a source it trusts. Everything below follows from it. Here is what each line of sion verify establishes, and what it still assumes:

LineEstablishesStill assumes
chain: … matches the pinned identityThe node serves the chain you pinned; validator keys derive their identifiersThe pin came from a source you trust
committees: followed from the pinned epoch 0 to epoch …Each later committee came from the state, certified by the committee before itEach of those committees had fewer than a third Byzantine stake
certificate: … of … stake signed (quorum …)More than two thirds of the epoch’s committee signed this headerFewer than a third of it is Byzantine (else a conflicting header may exist)
forced inclusion: …The committee certified how many forced intents are pending and overdueThe summary is certified, not proven: the World Proof proves the obligations but does not check the summary against them
receipts: …The node’s transactions are the certified order, and each receipt is in the receipts rootAs for the certificate
state: …An object or claim is in the certified state rootAs for the certificate, until the World Proof is checked. That it is still so: a proof shows the state at its Pulse, and a node can answer from an older one. The sion commands that read the ledger’s state this way (sion skill latest, say) refuse a proof from more than 16 Pulses before the latest certified Pulse they know of, but cannot know of a later Pulse that no source shows them
availability: … random shares … verifiedWithholding enough data to prevent reconstruction would have been caught with the stated probabilityYour samples are private and random
world proof: … re-verified by stack ["A", "B"]The transition from the previous state is valid, the data is what executedimpl:replay-proofs, impl:shared-primitives, the specification
lane certificates: …Every executed transaction locked its inputs with a quorum of its shard’s committee, from the proven validator setAs for the certificate

Without --chain, the first line reads NOT PINNED: learned from the node itself, and every other line is only as good as the node.

What the devnet does not protect

A devnet runs every validator in one process with keys anyone can derive. Whoever runs it can sign anything as any validator. It demonstrates the protocol; it secures nothing.