Skip to content

Show a notice when a saved field value was rejected - #21

Open
masnwilliams wants to merge 1 commit into
hypeship/canonical-awaiting-inputfrom
hypeship/replace-existing-field-notice
Open

Show a notice when a saved field value was rejected#21
masnwilliams wants to merge 1 commit into
hypeship/canonical-awaiting-inputfrom
hypeship/replace-existing-field-notice

Conversation

@masnwilliams

@masnwilliams masnwilliams commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

summary

When a site explicitly rejects a stored credential, the pause records replace_existing on the field so the user can be told the saved value is no longer usable. Nothing rendered it: the canonical projection dropped the flag, and neither field type declared it, so the form re-rendered as an ordinary empty input with no indication of why it was asked again.

changes

  • declare replace_existing on ManagedAuthField and DiscoveredField
  • carry it in fieldsFromCanonical, which previously copied six keys and stopped
  • render a notice above the field hint, so a rejected field that also has a hint keeps both
  • add the fieldReplaceExistingNotice label and the inputReplaceNotice appearance slot

The notice uses the existing --kma-color-danger token and the same typography as .kma-input-hint; no new design values.

ordering

Based on #20, which introduces fieldsFromCanonical. Review that first; this diff is only the flag.

The API side ships in kernel/kernel#3094, which adds replace_existing to the DiscoveredField schema. Until that deploys the flag only arrives on canonical fields, which this handles; afterwards it arrives on both and both paths render.

tests

bun test, bun run typecheck, bun run build, and prettier --check all pass.

Four pure cases in state.test.ts:

  • canonical field with the flag reaches the rendered field
  • canonical field without it leaves the property unset rather than inventing false
  • legacy discovered_fields pass the flag through untouched, which is the path that goes live first
  • toStrictEqual on the whole projected field, not a subset. The existing tests use toMatchObject, which is why a dropped key passes unnoticed — this one fails if the projection forgets any property the form renders

The first and fourth were verified to fail with the fieldsFromCanonical line reverted; the legacy and unset cases stay green in both states.

Not covered: the render itself. The package has no DOM test setup, so UnifiedAuthForm has no test at any level and this change does not add one.


Note

Low Risk
UI copy and optional field metadata only; no auth, credential handling, or submission logic changes.

Overview
When the backend marks a field with replace_existing, the auth form now explains that the stored value was rejected and a new one is required, instead of showing a blank input with no context.

replace_existing is added on ManagedAuthField and DiscoveredField, forwarded through fieldsFromCanonical (it was previously dropped in projection), and honored on legacy discovered_fields. UnifiedAuthForm renders a danger-styled notice above the field hint when the flag is set.

Customers can customize copy via fieldReplaceExistingNotice and styling via the inputReplaceNotice appearance slot. state.test.ts adds coverage for canonical projection, legacy passthrough, and a strict toStrictEqual guard so future projection omissions fail tests.

Reviewed by Cursor Bugbot for commit 7ab0711. Bugbot is set up for automated code reviews on this repo. Configure here.

Managed-auth fields carry replace_existing when the site rejected the stored
credential. Carry it through the canonical projection and render a notice on
the field so the user knows a new value is required.
@vercel

vercel Bot commented Aug 1, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
managed-auth-react-demo Ready Ready Preview Aug 1, 2026 3:53pm

@masnwilliams
masnwilliams marked this pull request as ready for review August 2, 2026 18:41
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