feat: return the passkey button to ready after an aborted explicit sign-in so it can be retried, and document that a new worker command type must be safe to lose while the fleet is still on the previous release

This commit is contained in:
Matthew Meszaros
2026-09-29 20:27:26 +02:00
parent 17a0ebfac0
commit 792b0506bc
2 changed files with 5 additions and 0 deletions
+2
View File
@@ -23,6 +23,8 @@ Schemas are derived from the Go structs (`internal/models/event_schema.go`), and
Two things follow. The registered document is the marshalled schema, not `Schema.String()`, which omits defaults and would throw the guarantee away. And the registry stays on `BACKWARD` rather than `FORWARD`: adding a field is safe under both, but adding a new event type adds a union branch, which `BACKWARD` accepts and `FORWARD` refuses. When a registration is refused and the subject's effective level is `FORWARD` or `FULL` (or their transitive forms), the publisher sets that subject to `BACKWARD` and registers again, so the registry key needs permission to change a subject's compatibility. Any other level, and any other refusal, is left as it is.
Nothing in this reaches production untested. `internal/app/eventschemas` lists every schema a release publishes and keeps the one the registry last accepted under `testdata/`. CI decodes the recorded schema with the new one, which is the registry's own `BACKWARD` check, and fails a change the registry would refuse. It also fails a compatible change that has not been recorded, so a schema change is always in the diff: run `make schemas` and commit the result. On release the backend registers every listed schema when it boots, and the fleet does not move to the release until that has succeeded.
The registry check covers the schema, not the rollout. Readers decode with the schema id each message carries, so a worker still on the previous release reads new fields fine, but a command type it has never heard of is logged and skipped. The backend rolls out before the fleet, so a new worker command type must be safe to lose while the fleet catches up: send it only to a worker whose reported version handles it, or have the backend retry it until one does.
</Callout>
The Rust tracking service follows both switches. It speaks Kafka only when compiled with its `kafka` cargo feature, which is what the `tracking:*-kafka` image is, and it encodes with `CODEC_PROVIDER` on either transport. So a Kafka deployment on `CODEC_PROVIDER=json` needs no Schema Registry at all, and `avro` there is refused at boot without `SCHEMA_REGISTRY_URL` rather than failing at the first published event.
+3
View File
@@ -414,6 +414,9 @@ export default function LoginPage() {
} else if (e.reason === "timeout") {
setPasskeyStatus("timeout");
toast.error("Safari didn't show a passkey prompt. Try again, or use password sign-in.");
} else {
// Aborted: nothing to explain, but the button has to be usable again.
setPasskeyStatus("ready");
}
} else {
setPasskeyStatus("error");