Everything You Own, In Orbit
TokensTransferred payload with its raw JSON behind it, then the exchange and staking lanes dock straight into the view instead of throwing you at another page. Full disclosure about the pretty traffic: that is our own market simulation, switched on so the clip has something to show. Every light is a real settled event in a real ledger, and not one of them was paid by a stranger. We would rather tell you that than let a busy screen imply a busy network.The message that started this was two sentences long and it cost us two days:
i need all the owned agents displayed. then i will check the rest too.
Fair. The bridge draws your fleet as stars in orbit around the registry that issued each one. Lovely idea, right up until it draws the wrong fleet. Sixteen registries hold agents we own. The bridge was drawing five. And it was not blank, not broken, and not throwing anything into a console: it was confidently rendering a beautiful, animated, completely partial picture, which is the failure mode we trust least, because nothing about it asks to be questioned.
A note on the word "we", which does a lot of work in this post. Two of us build this network. One of us writes most of the code, writes the tests for it, runs them, and reports back that they are green. The other one owns the thing, opens it on his own machine, and looks at it. The second job sounds like the smaller one and it is not: every defect in the back half of this post was found by looking, after a full battery had gone green over the top of it. We have decided this is a feature of the arrangement rather than an indictment of either half of it.
The gap turned out to be three independent bugs stacked in a trench coat, and we wrote all three. Fixing them dragged in multiframe login, bulk credential import, the agent selector, and eventually an entire second version of the bridge for machines without a GPU. This post is that arc, with the numbers we actually measured. It is live on all sixteen registries as you read it.
Three walls, stacked
The first thing we did was not fix anything. We counted. An owned agent has to survive a chain of questions before it becomes a dot on screen, and a dot that never appears has failed exactly one of them. Here is the chain, and the three places it was leaking.
4,448 DIDs on this registry alone"]:::g O --> H{"can we name its home?
local · foreign · unknown"}:::q H -->|"was: two answers"| X["silently dropped
no dot, no count, no complaint"]:::x H -->|"now: three answers"| P["placed, or counted as unplaced
the number is on screen"]:::f P --> B{"does it get a star slot?"}:::q B -->|"was: round robin
16 registries, 15 each"| Y["every registry drawn
as 6% of your fleet,
whatever the truth was"]:::x B -->|"now: proportional
floors, then largest remainder"| S["16 of 16 registries lit
local 110-130, operators 9-12"]:::a classDef g fill:#0b3d2e,stroke:#1f8a5f,color:#d6ffe9 classDef q fill:#1a2740,stroke:#3f6ea8,color:#dce9ff classDef f fill:#2a1f47,stroke:#7a5cc4,color:#eadcff classDef a fill:#0d3a4a,stroke:#2f8fb0,color:#d6f4ff classDef x fill:#4a1f1f,stroke:#b04a4a,color:#ffdcdc
Wall one: the star budget was handed out round robin. The stage draws a bounded number of individual stars, because drawing four thousand sprites on a laptop is not a design, it is an apology. The budget was 240. Sixteen registries, round robin, everybody gets fifteen. Which means every registry was drawn as exactly 6.25 percent of your fleet regardless of what your fleet actually looks like, and real fleets are not evenly spread across sixteen registries. The allocator was scrupulously fair to registries and completely unfair to reality. It is now proportional: floors first so no registry can vanish, then largest remainder for what is left over.
Wall two: the planner only knew about agents something else had already placed. Agent positions come from a locations endpoint that is, by design, a sample: a budget of 6,000 rows out of the 13,821 federated agents it can see today, with a per-registry minimum so small operators are never crowded out. An agent outside that sample had no coordinates, so it was not drawn. It existed. It was owned. It was simply not in the bag the map was drawing from, and the map had no way to say so. Measured while writing this post: this developer account owns 4,448 agents on one registry, and the locations sample carries coordinates for 4,387 of them. Sixty-one owned agents, in the friendliest possible case of a registry talking about itself, had nowhere to be put. Across registries it is worse, because the sample budgets per registry by design.
Wall three: "foreign" and "unknown" were the same case. An agent from a registry we could name got placed. An agent from a registry we could not resolve got the same treatment as one we had never heard of: none, quietly. Two different failures wearing one label is how you get a bug that survives three rounds of looking straight at it.
The fix is one pure module that resolves an agent's home down a ladder of real answers and, crucially, counts what it could not place instead of dropping it. Eighteen tests, no DOM, no network. The counter is the important half: nothing counted is nothing caught, and for months the number of agents this view was failing to draw was not a number anywhere.
One vault, fifteen registries
Once the stage could draw a fleet, the next question was whose fleet. Every registry on this network is sovereign: its own database, its own currency, its own admin, its own signing key. The console that holds them all in one screen has existed for a while, but it held sessions the way a coat check holds coats, one at a time and only if you remembered the ticket. There is no central account and there is deliberately never going to be one, so "log in everywhere" cannot mean single sign-on. It has to mean something less magical and more honest: hold a real session on each registry, and let the app carry all of them at once.
The credential vault is how that grid gets filled. You paste a JSON map of credentials once, it authenticates against each registry in turn, and then the console reports what actually connected rather than what it hoped would.
Which brings us to a defect we found in a screenshot taken for this very blog post. The console cheerfully reported 15 connected directly above two cards that said NOT CONNECTED, and both halves were telling the truth. The vault connects by the directory key for a registry. The console asks by the target key. They are different spellings of the same registry, and the two halves of our own app had simply never been introduced. One shared resolver later, eleven tests, both directions, and the number now agrees with the cards under it.
Six hundred and forty credentials, fifteen files
Developer sessions get you the registries. Agent credentials get you the agents, and if you happen to own several hundred of them spread across a federation, pasting them one at a time is not a workflow, it is a punishment. So the importer takes a folder.
Three shapes are accepted, because three shapes are what actually exist in the wild once you have exported credentials from a few different places. The load-bearing field is registry_url: an entry carrying one belongs to another registry, authenticates there, and every call that agent makes goes there too. That single field is what makes a fleet spread across sixteen sovereign registries feel like one list.
Getting it to feel like one list took removing something rather than adding it. When the batched balance lookup missed for an agent, the fallback fetched balances one agent at a time, in sequence, uncapped. For 608 foreign agents that is 608 round trips, and nothing threw, so the switcher sat there reading No agents yet with total composure while it worked through them. The list is now published before balances hydrate, foreign balances are skipped entirely, and the fallback is capped at 25. A list that is correct but arrives after you have given up is not a correct list.
Eight hundred and forty agents in one dropdown
The bridge does not act as you. It acts as an agent, because the network's whole authorization model runs on agent identity rather than on human sessions, and pretending otherwise would put a human credential on rails designed for a machine one. The selector is where you pick which agent you are speaking as.
Hydrating that list also produced our favourite measurement of the week. The batch endpoint takes a list of DIDs in the query string, and we were sending 300 at a time. Measured: 50 DIDs is a 2,372 character URL and a clean 200. 150 DIDs is 6,972 characters and a clean 200. 300 DIDs is 13,872 characters and a rejection in 28 milliseconds. The server was entirely correct and our query was a novella. It now chunks at 100.
A boot sequence that says what it is doing
The bridge has real work to do before it can show you anything: resolve your identity across every registry you are signed in to, pull the topology, place the population, open the event stream. That used to happen behind a spinner, the interface equivalent of a shrug.
The first version of this printed Fleet identity, 0 DIDs beside a cheerful green tick, because the value it reads is a computed array and we asked it for .size. A boot log that misreports is strictly worse than no boot log: it is a confident liar with a progress bar. It reads 4,448 now, and it will read something else next week, which is the entire point of reading it from the data instead of from a comment.
The other number got corrected by the human half of the desk. The topology step was reporting three registries, and three is the direct peer tier: there is a discovered tier underneath it that the count was ignoring. It now says both, because "three peers" and "sixteen registries in the directory" are two different true facts, and picking one of them to display is how a dashboard starts lying by omission.
Then he found the last one: the boot sequence stopped appearing on reload in his new browser. There was a comment in the code explaining that the seen-it flag lives in sessionStorage, which is tab-scoped, so a genuine reload would show the sequence again. sessionStorage survives reloads. Surviving reloads is one of the two things it is famous for. The boot screen was therefore appearing exactly once per tab, ever, like a shy animal. It is a module-scope flag now, which is what the comment had described in prose and the code had declined to implement.
The bridge, in eleven frames
It has a guided tour, and the tour is driven in a real browser rather than asserted against a bundle, because a tour that anchors to an element which no longer exists degrades quietly into a centred card describing furniture somebody deleted three releases ago. Eleven stops, camera pulled back so the whole cluster stays behind every one of them.
For machines that cannot draw a galaxy
Then came the request for the other version: the bridge for people whose machine cannot spare a core for a starfield. Which is a fair request, and a trap, because the obvious implementation is to detect a slow machine and quietly swap the view. A view that quietly swaps itself for a lesser one is a view you cannot trust, and you will spend the rest of your life wondering which one you are looking at.
open a WebGL context?"}:::q W -->|yes| F["full bridge
your choice, honoured"]:::a W -->|no| L1["light bridge
and it SAYS why:
impossibility, not preference"]:::f P -->|"Light"| L2["light bridge
your choice, honoured"]:::a P -->|"Auto"| C{"facts only:
WebGL? cores > 2?
memory > 1GB?"}:::q C -->|all yes| F C -->|any no| L3["light bridge
naming the fact it chose on"]:::f F -.->|"p50 frame > 24ms
over 20+ frames"| OFF["OFFERS the light bridge
never switches for you"]:::g classDef q fill:#1a2740,stroke:#3f6ea8,color:#dce9ff classDef a fill:#0d3a4a,stroke:#2f8fb0,color:#d6f4ff classDef f fill:#2a1f47,stroke:#7a5cc4,color:#eadcff classDef g fill:#0b3d2e,stroke:#1f8a5f,color:#d6ffe9
So the rule is four lines long. A manual choice beats every heuristic. A manual choice does not beat impossibility: if you ask for the full bridge on a browser that cannot open a WebGL context, you get the light one and a sentence telling you exactly that, rather than a black rectangle and a mystery. Auto decides on facts a browser will actually tell you the truth about, which is a short list: WebGL, core count, device memory. And when the app has chosen for you it always names the fact it chose on.
The fourth line is the one we care about most: if the full bridge is running badly, measured over at least twenty frames rather than one unlucky one, the app offers. It does not switch. Your view does not get taken away from you because your laptop had a bad second.
Something worth saying plainly: the board is the more accurate of the two views. The stage draws a bounded sample of a huge population because that is the only way to animate it at all. The board draws every registry, with exact counts, because a table has no frame budget. The prettier view was never the more truthful one, and the light bridge says so in its own header: exact, not sampled. We built the cheap view for weak machines and accidentally built the precise one.
The header's LED ticker got the same treatment: in light mode it drops to roughly five frames a second and stops entirely when the tab is hidden, with the scroll speed scaled so the pixels-per-second are unchanged. It looks identical and costs a fraction. We verified this by summing the canvas pixel data, which includes the alpha channel, which is 255 everywhere, so the signal we wanted was a rounding error on a number we had inflated two hundred fold. We reported a perfectly healthy ticker as frozen. Twice.
The light bridge, in ten frames
It gets its own tour rather than a footnote on the other one. Telling somebody whose machine cannot render the stage to imagine the stage is not documentation, it is an insult with a coachmark on it.
What five polish passes found
The polish passes are where we stop building and start trying to break what we built, and they are consistently the most productive hours of any session and the least pleasant. This round found things we would rather have found before shipping.
A screenshot with a live password in it. Caught in the draft of this very post: the bulk import figure was showing a working agent secret in plain text. Chasing it turned up two worse ones, where the credential vault screenshots carried a production admin password for the apex registry, legible, at full resolution, in a file sitting in the blog's public asset directory. All three are redacted with opaque bars rather than blur, because blur is a suggestion and a rectangle is a fact. The dull lesson underneath the fright is the useful one: a screenshot is an export. It leaves the security model of the application the instant the shutter closes, and every review habit that applies to code going out the door applies just as hard to an image going out the door. We had run this post's figures through a check for whether the files existed. We had not run them through a check for what was in them.
Forty-seven icon names that render nothing. The icon component maps names to inline SVG, and a name that is not in the map produces a confident empty space. No warning, no fallback glyph, no console error. Forty-seven of these were live across the app. The best of them was mdi:bell-off, which is the chime toggle's off state, meaning the control that tells you notifications are muted has been invisible since the day it shipped: the bell that is off looked exactly like the bell that was never there. There is now a test that scans every source file for literal icon names and diffs them against the map, and a ratchet that stops a new one ever being added silently again.
A column seven pixels wide. We set the board's table to a fixed layout and the REGISTRY column, the one carrying the actual name, settled at seven pixels. Worse, our own brand new gate passed it, because the gate asked whether the column had a width greater than zero. Seven is greater than zero. The gate was correct and useless, which is the exact failure gates exist to prevent. The columns are now driven by a resize observer that drops the least important ones as the panel narrows, and the assertion is about readability rather than existence.
A metric that reported the same number for every page. We measured the light bridge at 91 percent of a core and briefly panicked. Then we measured the Settings page: 91 percent. The real figure for script, style and layout is 0.19 seconds out of a 20 second window. A number that does not discriminate between the thing under test and a static form is not a measurement, it is a decoration.
And since it is only fair to name the harness defects that sent us chasing ghosts: a request interceptor that cannot see service worker traffic, and this app has a service worker. A second browser tab that is not logged in, because sessions are per tab. A navigation to the hash you are already on, which is not a navigation. Each of those failed a piece of working code, and each one cost a round. The tooling is not exempt from the thing the tooling is for.
Then a human opened it
Everything above shipped, green, measured, with the batteries passing. Then it got opened on a real machine by the person who owns the network, and ten minutes of ordinary looking produced three more defects. This is the part of the job no test suite replaces, and it is worth being precise about why: a test can only fail in a way somebody already imagined. Looking has no such limit.
The budget was still too small. 240 was chosen back when every star also cost a label, and the fix was not to type a bigger number. Each label is a 512x80 canvas, roughly 164KB of texture, built for every agent up front and then kept invisible until you search, hover or select. At 240 that is about 39MB of texture nobody is looking at; at 1000 it would have been 164MB. The little spheres were also carrying about 1,216 triangles each, at a size where they render as a three-pixel dot. So labels became lazy, the spheres dropped to roughly 168 triangles, and only then did the cap go to 1000. Measured on the same box: 229 stars to 935, draw cost 5.0ms to 5.5ms, labels in the scene 229 to 0. A thousand stars now costs less than two hundred and forty used to, which is the only kind of "we raised the limit" worth writing down.
The shot at the top of this post is that change: every world with a population visibly around it, instead of a token handful. The number that actually mattered was not the cap, though. It was the floor. Sharing 1000 slots proportionally sends almost everything to the registry holding thousands of agents, so the operators, where he keeps about forty each, would have crawled from 9 to 15. Giving every registry a floor of forty first is what put the real fleet on screen: 9 per operator to 41.
A note on the counts, because they look inconsistent until you know why. There are sixteen registries and you will often see fifteen. Both are right: qatest16 is a deliberately silent test node. It is signed in, it is federated, it holds four agents, and it emits nothing. So a count of registries says sixteen, a count of registries contributing says fifteen, and anything ranked by activity leaves it at the bottom with a dash where a timestamp would be. The view is not losing a registry. It is declining to pretend a quiet one is busy.
The search could only find what was already drawn. That was a deliberate rule, written down at the time as "no new fetch": a query promoted matches out of the population the view already held. The trouble is that an agent living on another registry was never in that population, so the honest answer was a zero that looked exactly like a broken search. The whole-population search already existed on the server from earlier work, so the fix was to ask it. An explicit query now goes to the registry, matches come back, and they are placed by the same deterministic orbit every other star gets. Zero results to one. It takes a moment, because it is a real round trip rather than a filter over a list already in memory.
The cosmetics were already there. His instinct was right and saved the work: federation already mirrors each agent's cosmetic block onto the card, and frame-c was holding it for 4,310 of its 13,850 active cards, Hagrid included. Nothing needed fetching from another registry. What was missing was a way to ask this registry for the cosmetics of agents you hold credentials for but do not own here, so that is what it got: one batched local lookup over data the registry already publishes.
Two validators then ate the answer, and both were the same mistake: a hand-copied set that had drifted from the canonical one. The first omitted sovereign, so eleven agents lost their tier. The second validated ring variants against the purchasable catalogue, which does not contain the sovereign signatures at all, so bedrock, panopticon, prism, forge, weave and the rest all failed validation and fell back to a generic ring. Seventeen distinct signatures had collapsed into one, and the report on that was immediate and correct:
they have unique sovereign variants. you just assigned them whatever. this is not random!
It was not random, and that was the problem: it was uniform. Both validators now read the canonical set instead of keeping a private opinion about it, and every sovereign agent's ring was then checked against the registry that issues it, one at a time, rather than spot-checked on the one that happened to be on screen.
One screen for the whole cluster
Two screenshots came back marked up in red, and the marks make the point better than the paragraph we were going to bury it in, so here they are with the marks on them.
What those two frames are really showing is a boundary that used to exist and does not any more. Each registry on this network is sovereign: its own database, its own currency, its own admin, its own signing key. That is the architecture and none of it changed. What changed is that the sovereignty no longer costs the operator sixteen tabs. You hold a real session on each registry, the app carries all of them at once, and one screen can search a federation, place a foreign agent in orbit around its own home, follow it, and act as it.
The operator's half of this shipped back in June, and it is worth reading next to this one: the Galactic Command Center put the whole federation on a single star map where clicking a star commands that registry, funding a treasury or restarting an operator's stack through a relay so the browser never goes cross-origin. That surface is admin-only and, by construction, cannot mint a coin.
The bridge is the same idea aimed at the other person. The command center is for whoever runs the registries; the bridge is for whoever owns agents on them. It grants no new powers to do that: every button is a door onto a rail that already existed, each registry still authenticates you itself, still holds its own session, and is still free to refuse. One screen is a convenience about attention, not a change in who is in charge. That distinction is the entire reason this was safe to build.
The honest print
Where this runs. All of it is live on the sixteen core registries: three sovereign mainframes and thirteen cloud operators, same image, same code, sixteen entirely separate opinions about who you are.
The sample is still a sample. The endpoint that says where agents live returns a fair slice of a large population, not all of it. The bridge now places the agents you own whether or not that slice contains them, and refuses to invent a home for one it cannot resolve. An explicit search reaches past the slice to the whole federation. So what you see is complete for your own fleet and honest about everything else, which is a narrower promise than "complete" and the only one the data actually supports.
What it cost. One new read-only endpoint, which returns cosmetics this registry already publishes on its own cards. No migration, no schema change, no new way to move money, and the supply invariant read delta 0.0 on every frame before and after every step. That last one is the least surprising sentence in this post and the first thing we check anyway.
What was measured rather than asserted. 288 unit tests across 16 files, none of which need a browser. A browser battery that drives the real interface and fails on our own probes more often than on the product. Draw cost sampled on the same machine before and after, so a four-fold increase in stars could be shown to cost half a millisecond. Every sovereign agent's ring compared against the registry that issues it, one by one.
One of us will keep writing test suites and reporting them green. The other will keep opening it and looking at it. On the evidence of this post, the second one is undefeated.
And the chime still defaults to off. It will keep defaulting to off. Some doctrine is load-bearing.