Skip to content

feat: define the postcode field and its message catalogue - #4

Merged
MobileMage merged 6 commits into
mainfrom
feat/field
Oct 4, 2026
Merged

MobileMage merged 6 commits into
mainfrom
feat/field

Conversation

@MobileMage

Copy link
Copy Markdown
Collaborator

This defines the postcode field: a form input that reads a NIPOST
postcode as the user types, sends the canonical code with the form, and
can check the postcode or fill it in from the user's location. The web
field and its React wrapper come next in the js repo, and later fields
for Flutter and the native platforms follow the same contract.

field.md has an Interface section, so the field gets no public name
that the spec does not list. It gives the settings, the events, the
states and their order, a table of each failure with its state, message
and event code, and the rules for lookups and location requests. The
English text is a message catalogue in ARB, which Flutter reads as it
is, so every field can share one set of translations.

The field never shows a house address, from a lookup or from a search
near the user, because a user can type any postcode and a nearby
address often belongs to a neighbour. It sends no request without a
publishable key, refuses a secret key, and sends no second lookup for a
postcode it has already checked.

Autocomplete is left out of this version. The gateway took 10 to 14
seconds per call in our tests, so suggestions would arrive after the
user had typed the whole postcode.

Doc tests pin each rule, so the spec text and the catalogue cannot
drift apart. The spec version goes to 0.3.0.

Signed-off-by: MobileMage aidelojejoshua@gmail.com

The web field, and each UI field after it, needs one written contract
for its settings, events, states and text, so that every framework
behaves the same. The text lives here as a data file in the ARB
format, which Flutter reads as it is, so one translation serves each
field. A lookup never blocks the form, because the gateway's data is
new and a wrong answer must not stop an order. The standards and the
agents template now name the new interface file.

Signed-off-by: MobileMage <aidelojejoshua@gmail.com>
A review found that two fields built from field.md could differ. The
states overlapped, the error event had no rule for a failed location,
and the location fill did not say how far to truncate a fallback. So a
coarse fix with no unit could fill a whole area. The file now orders
the states, adds a table of failures, and spells out the fill, the
input limit, an empty key and when a lookup starts again.

The coarse location message counted the parts and gave the accuracy
as the cause. A precise fix with no unit also gives part of a
postcode, so the message now names no cause. The privacy section now
forbids the address of a reverse unit too, because the nearest unit
is often a neighbour's house.

Two legacy messages are shorter, so each catalogue line fits in 100
characters. The client size budget stays at 6 KB, the limit that the
client package already uses. Its build sits close to 5 KB, so the old
budget left no room for the next feature.

Signed-off-by: MobileMage <aidelojejoshua@gmail.com>
A second review found rules that two fields could still read in two
ways. The ordered states let an empty text match the row for typing,
so the idle state could never show. An empty text is now never a parse
error, and the file defines once when the field shows errors.

The rule against a repeat lookup did not say what the field forgets.
The field now remembers only a lookup that the gateway answered, so a
failed or cancelled lookup can run again. A change of a setting no
longer cancels a location request, and a change of the gateway address
alone starts no lookup. A field that leaves the page cancels its
requests and starts again from its text when it returns.

A location fill raises a change event only when the form value
changes, as typing does. The table of failures gains the case of a
device that reports no location, and the error event now points to
that table.

Signed-off-by: MobileMage <aidelojejoshua@gmail.com>
A third review found two rules that two fields could still read in two
ways. A change of the key during a location request could either stop
the request or send the reverse call with a secret key. A change of a
setting still never cancels the request, but a call that the field
sends after the change now follows the rules for the new key. So the
field never sends a secret key, and the table of failures gains that
case.

The file also says that a text that is not a whole postcode keeps no
lookup, so the same postcode typed again gets a new one. New doc tests
pin the rules that a later edit could drop without a failing test.

Signed-off-by: MobileMage <aidelojejoshua@gmail.com>
A lookup or a reverse call can throw an error that the client does not wrap, for example when the base address has no scheme. The failure table had no row for it, so a page would hear nothing. Both cases now end as a failed request and raise the error event with network_error.

Signed-off-by: MobileMage <aidelojejoshua@gmail.com>
main gained the new README look and a fix to the client size limit. The README keeps main's linked table and gains the rows for field.md and the message catalogues, and the size-limit line keeps the React wrapper's limit.

Signed-off-by: MobileMage <aidelojejoshua@gmail.com>
@MobileMage
MobileMage marked this pull request as ready for review October 4, 2026 00:53
@MobileMage
MobileMage merged commit 514c5b0 into main Oct 4, 2026
5 checks passed
@MobileMage
MobileMage deleted the feat/field branch October 4, 2026 00:53
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