Skip to content

chore(deps): move onto @seamless-auth/types 0.16.0 - #135

Merged
Bccorb merged 1 commit into
mainfrom
chore/types-0-16-webauthn-error-code
Aug 30, 2026
Merged

chore(deps): move onto @seamless-auth/types 0.16.0#135
Bccorb merged 1 commit into
mainfrom
chore/types-0-16-webauthn-error-code

Conversation

@Bccorb

@Bccorb Bccorb commented Aug 30, 2026

Copy link
Copy Markdown
Contributor

Summary

Moves @seamless-auth/types from ^0.5.0 to ^0.16.0, and uses the union that
0.16.0 publishes.

0.16.0 adds WebAuthnErrorCode, a union of the machine-readable codes the auth
API returns as the whole of an error body's error field. PasskeyPolicyErrorCode
was a hand-maintained copy of three of those names, because when #132 was built
there was no upstream union to check it against. That issue asked for the same
Record exhaustiveness check the OAuth codes get, and settled for a copy with a
comment saying so ("checked against 0.15.0"). This replaces the copy with
Extract<WebAuthnErrorCode, ...>, so renaming or dropping any of the three
upstream resolves the type to never and stops the Record compiling.

Verified that guard rather than assuming it: simulating an upstream rename
produced TS2353 in errors.ts and TS2322 in the test.

The union is narrowed, not adopted whole

WebAuthnErrorCode spans every WebAuthn operation, so taking it whole would be
wrong. Checked against seamless-auth-api main:

Code Route Status
synced_passkey_not_allowed POST /webauthn/register/finish 403
authenticator_not_allowed POST /webauthn/register/finish 403
prf_required POST /webauthn/register/finish 403
attachment_not_allowed GET /webauthn/register/start 400
prf_output_not_allowed login/finish, step-up/webauthn/finish 400

The existing three are exactly the registration policy refusals: webauthn.ts
sends verdict.reason (typed AuthenticatorRefusal, the two policy codes) and
prf_required, both 403, from verifyWebAuthnRegistration.

The other two are different operations at a different status. prf_output_not_allowed
is a server-side guard against a client that fails to strip PRF output before
posting, so reporting it as a deployment policy refusal would point an integrator
at their config when the real cause is a client bug. Both are also unreachable
through this SDK today: the API only sends attachment_not_allowed when the
caller requests an attachment, and buildRegisterStartPath only ever sets
requestPrf and requirePrf; the SDK calls stripPrfResultsFromAssertion at
all three assertion sites. A test pins both as ignored so the narrowing is
enforced rather than only explained in a comment.

Rest of the range

No other changes were needed. The two breaking changes between 0.5.0 and 0.16.0,
RegistrationSuccessSchema.ttl becoming a number (0.6.0) and
DeviceReplacementRecoverySchema requiring proofing (0.9.0), are both unused
here. Everything else was additive. aaguid (0.12.0) reaches the public
Credential type for free through CredentialResponse, and
PublicSystemConfigResponse is still just { loginMethods }, so there is still
no way for a client to pre-check authenticator policy.

Related: fells-code/seamless-auth-api#183 covers the attachment gap noted
above, where the API accepts a parameter the SDK never sends. Not addressed here.

Type of Change

  • Refactor
  • Feature
  • Fix
  • Documentation
  • Test

Release Impact

  • Changeset added for adopter-facing package change
  • No package release expected

No changeset, matching c206f29 (chore(deps): move onto @seamless-auth/types 0.5.0),
which bumped the same dependency without one. Nothing here is adopter-facing: the
recognized codes, the return type, and the fallback to undefined are unchanged.
Say the word if you would rather it carried one.

Checklist

  • Tests pass
  • No breaking changes
  • Changeset summary is clear for SDK adopters
  • Docs updated (if needed)
  • Security implications considered

README needed no change: it documents the three registration refusal codes, which
is still the exact set this recognizes.

npm run typecheck, npm test (305 passing), npm run lint, npm run format:check
and npm run build all pass.

The release publishing WebAuthnErrorCode, a union of the machine-readable codes
the auth API sends as the whole of an error body's `error` field.

PasskeyPolicyErrorCode was a hand-maintained copy of three of those names,
because no upstream union existed to check it against (#132 asked for the same
Record exhaustiveness check the OAuth codes get, and settled for a copy). It is
now derived from the published union with Extract, so renaming or dropping any
of the three upstream resolves it to never and stops the Record compiling.

The union is narrowed rather than adopted whole. WebAuthnErrorCode spans every
WebAuthn operation, and the two codes left out are not registration policy
refusals: attachment_not_allowed is a 400 from register/start, and
prf_output_not_allowed a 400 from login and step-up finish. Reporting either as
a policy refusal would be wrong, so a test pins both as ignored.

Nothing changes for a caller. The recognized codes, the return type, and the
fallback to undefined are all as before.

The rest of the 0.5.0 to 0.16.0 range needed no changes here. Its two breaking
changes, RegistrationSuccessSchema.ttl becoming a number and
DeviceReplacementRecoverySchema requiring proofing, are both unused in this
package, and everything else was additive.

Verified with npm run typecheck, npm test (305 passing), npm run lint,
npm run format:check, and npm run build.
@Bccorb
Bccorb merged commit f77f829 into main Aug 30, 2026
3 checks passed
@Bccorb
Bccorb deleted the chore/types-0-16-webauthn-error-code branch August 30, 2026 21:37
Bccorb added a commit that referenced this pull request Aug 30, 2026
Closes #136.

GET /webAuthn/register/start accepts an attachment that narrows the browser
picker to one kind of authenticator, and nothing in this SDK could ask for it:
buildRegisterStartPath set only the PRF flags, so reaching the parameter meant
hand building the URL and reimplementing the PRF, metadata and error handling
registerPasskey already does.

registerPasskey now takes an optional attachment, and the bundled enrolment view
offers a "Use a security key instead" control that takes it. That is the path an
organisation handing someone an issued key needs, rather than leaving them to
recognise it in a browser dialog.

Omitting the option sends no query parameter, so the deployment's
authenticator_policy.attachment stays in charge and the default path is
unchanged. PasskeyAttachment is derived from AuthenticatorAttachmentPolicy with
Exclude rather than restating the two strings: `any` is a standing deployment
default, not something a single request can ask for, so the request type is that
policy minus that member. The API publishes no request-side union of its own.

PasskeyPolicyErrorCode gains attachment_not_allowed. It was left out in #135
because it was a 400 from register/start rather than a 403 from finish, and
because nothing in the SDK could provoke it. Sending the parameter is what makes
it reachable, and it is a refusal by authenticator_policy like the others, so it
belongs with them. prf_output_not_allowed stays out: it reports a client that
failed to strip PRF output, not a deployment refusing an authenticator.

The enrolment view now explains a refusal instead of showing the generic failure,
so a user told to reach for a security key can act on it.

Verified with npm run typecheck, npm test (315 passing), npm run lint,
npm run format:check, and npm run build.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant