v0.12.1
Patch Changes
-
2acea63: Stop reading a
401from/loginas "no such account", and stop claiming an account
exists when the instance will not say.POST /loginno longer answers401. An identifier with no usable account, which used
to cover unknown, unverified, and no-permitted-method, now gets200and a decoy pre-auth
token so the response cannot be used to test whether an account exists. Two branches in
completeLoginread that401and are now unreachable: the "not verified yet" message
and "No account was found for X". Both are removed, because there is no longer an answer
for them to read.The messages that surrounded them were making a claim the CLI can no longer support. "A
code was sent to X" is now "If an account exists for X, a code is on its way", and "This
account cannot use email otp login" is now phrased as what the instance offered, since
that method list comes back for an unknown identifier too.An unknown identifier therefore runs the ordinary flow and fails at the code step. That is
the intended behaviour and not something the CLI can shortcut, so the final error now says
so: it names the identifier and points at registering, instead of "Could not verify a
code" with no explanation of the likeliest reason.423is now reported on its own terms, with how long to wait when the instance says.
Previously it fell through to "Login request failed (423)". It is also the one answer left
that does imply an account exists, which is a deliberate and documented tradeoff on the
API side.Adds
verify/harness/api/loginEnumeration.spec.tsto the conformance matrix, pinning the
guarantee against a running instance: an unknown identifier gets the same status and the
same fields as a registered one, the same identifier keeps the same subject and the same
method list across attempts, the OTP send reports success and sends nothing, the verify
fails the way a wrong code fails, and a credential id that cannot exist is refused
identically for both.The
loginMethodsassertion is the one worth reading. It is deliberately not equality
between one account and one decoy: that list is filtered by what an account can do, and a
decoy's capabilities are derived per identifier, so any two can legitimately differ. What
must hold is that a real account's list is one a decoy can also produce, which is what
makes a narrow list stop being proof of existence. The spec asserts that over a sample. -
c3c9d57: Give
seamless verifya build cache in CI, and stop paying for provenance attestations
nothing reads.The conformance job spends nearly all of its time building Docker images, and none of it
running tests. On the run that prompted this,Run seamless verifywas 28m02s and the
tests inside it took 23.7 seconds. Every image is rebuilt from scratch on every run,
because CI has no Docker layer cache, and the host-side npm caches do nothing for a build
that happens inside Docker.seamless verifynow layers an extra compose file over the base one when
SEAMLESS_VERIFY_COMPOSE_OVERRIDEis set. CI points it atverify/docker-compose.cache.yml,
which attaches atype=ghabuild cache scoped per service, and per web template for the
react image since each template is different source. Nothing changes for a local run: the
variable is unset, the base compose file is used as it always was, andtype=ghawould be
an error outside Actions anyway.The Dockerfiles were already ordered for this. Each installs dependencies from a lockfile
before copying source, so a source change leaves the expensive layer intact and only a
lockfile change invalidates it.Also sets
BUILDX_NO_DEFAULT_ATTESTATIONSin the workflow. The images are thrown away when
the job ends, so the provenance attestation buys nothing, and on that same run
resolving provenance for metadata filetook 301s by itself. -
20f8e66: Follow the React SDK's passkey enrollment through the removal of its naming step.
@seamless-auth/reactused to open a "Name This Device" modal after "Register Passkey" was
pressed, and the harness typed into it before the WebAuthn ceremony would start. That view is
gone from the SDK, soregisterWithPasskeywaited 30 seconds for a placeholder that no longer
renders and then timed out, failingreact/passkeyRegister.spec.tsandreact/passkeyLogin.spec.ts
(which registers before it signs back in).The helper now stops at the button, which is where the ceremony begins. This tracks the SDK
release that drops the modal, so a--localrun against an older React checkout, or a published
run before that release lands on npm, will fail on the modal this no longer dismisses.