v1.2.1 ·
workspace:* on npm: the publish guard
v1.2.0 went to npm and could not be installed. Anyone who ran npm i -g @rasensio/aidlc got EUNSUPPORTEDPROTOCOL and nothing else.
The cause was one line of metadata. In a pnpm workspace, a package that depends on a sibling writes the dependency as workspace:*. That means "the copy in this repository" and nothing outside it. pnpm publish knows this and swaps in a real version number on the way out. npm publish does not. It uploads workspace:* as written, and npm's installer has no idea what it is.
The release ran, the tag was pushed, and the tarball on the registry was broken. Nothing in the build, the tests or the release script had an opinion about which client did the publishing.
The fix, and the fix for the fix
The immediate repair was boring. I republished the same code with the right client and deprecated the broken version so nobody would install it by accident. That took minutes. @rasensio/aidlc@1.2.1 is byte for byte the same code as 1.2.0, published correctly, and 1.2.0 is deprecated with a pointer to it.
The harder question was how to stop it happening twice. I had three answers.
A note in the release docs saying "use pnpm publish" feels like a fix and is not one. The mistake was reaching for the wrong command under time pressure, and a document does not step in at that moment.
Automating the release so the right command is the only one that runs is better. But it covers only the path through the script. A publish typed by hand in a terminal still slips past it.
So I made the wrong publish refuse to happen. A guard now runs from prepublishOnly, looks at the publishing environment, and aborts if the client would upload an unresolved workspace: spec. It fires however the publish was started, and it runs before the build and the tests. No tarball exists by the time it says no.
Why this has no lifecycle record
There is no instance behind this post, which is why it is hand-written. The whole thing happened in under two hours between v1.2.0 and v1.2.1, with no ideation, no requirements and no design. For a broken publish that is the right size of response. It is also why the trail has a gap here: the lifecycle records what goes through it, and a same-day incident fix did not.