Signup and the profile page now ask for a birth year instead of a full date of birth: a four-digit year between 1900 and the current year, as a type="number" input capped at today. Anything else — a short year, a full date pasted in, a year in the future — is discarded rather than stored, so a typo cannot leave a nonsense age on the record.
Storage, and the two open questions from the issue
New meta key, not a reused one. The year lives in us_birth_year. Reusing us_date_of_birth would have left one key holding two formats with no way to tell them apart.
No bulk migration.GuardianService handles the old key in two halves instead:
birthYear() falls back to the year of the old date when us_birth_year is absent, so a student added before this change still shows a birth year with no migration step.
setBirthYear() deletes us_date_of_birth on every save.
That deletion is load-bearing, not housekeeping. Without it, clearing the birth year on a student who predates the change would leave the old date behind for the fallback to read straight back — the year could never be cleared. There's a test pinning exactly that (testSavingAChildClearsTheLegacyDateOfBirth).
The consequence worth your explicit sign-off: this means a student's stored full date of birth is deleted the first time their record is saved. That's the intended direction — the studio stops holding data it no longer asks for — but it is data going away, so I'd rather flag it than have you find it. Nothing runs in bulk: dates for students nobody edits stay until someone does. If you want them all gone now, that's a one-line meta delete and I can add it to the installer's migration step; say the word.
Also renamed, since the meaning changed
child_dob → child_birth_year, children[<n>][dob] → children[<n>][birth_year], and the matching element ids and the us-family-child-dob CSS class. These are our own form fields posted by our own templates — not a saved contract like a block name — and leaving them called "dob" while they carry a year is the kind of thing that misleads someone six months from now. register.js's clone logic is index-generic and needed no change.
Verification
composer test (770 tests, up from 762), composer lint, composer cs all pass. New coverage: a data provider over six rejected inputs (not-a-year, 2015-04-02, 15, 20155, 1899, and a future year), the legacy-date read fallback, and the clear-on-save behaviour above.
No Schema.php change — this is user meta — so no USC_VERSION bump, per the rule in CLAUDE.md.
Closes #147.
Signup and the profile page now ask for a **birth year** instead of a full date of birth: a four-digit year between 1900 and the current year, as a `type="number"` input capped at today. Anything else — a short year, a full date pasted in, a year in the future — is discarded rather than stored, so a typo cannot leave a nonsense age on the record.
## Storage, and the two open questions from the issue
**New meta key, not a reused one.** The year lives in `us_birth_year`. Reusing `us_date_of_birth` would have left one key holding two formats with no way to tell them apart.
**No bulk migration.** `GuardianService` handles the old key in two halves instead:
- `birthYear()` falls back to the *year of* the old date when `us_birth_year` is absent, so a student added before this change still shows a birth year with no migration step.
- `setBirthYear()` deletes `us_date_of_birth` on every save.
That deletion is load-bearing, not housekeeping. Without it, clearing the birth year on a student who predates the change would leave the old date behind for the fallback to read straight back — the year could never be cleared. There's a test pinning exactly that (`testSavingAChildClearsTheLegacyDateOfBirth`).
**The consequence worth your explicit sign-off:** this means a student's stored full date of birth is deleted the first time their record is saved. That's the intended direction — the studio stops holding data it no longer asks for — but it is data going away, so I'd rather flag it than have you find it. Nothing runs in bulk: dates for students nobody edits stay until someone does. If you want them all gone now, that's a one-line meta delete and I can add it to the installer's migration step; say the word.
## Also renamed, since the meaning changed
`child_dob` → `child_birth_year`, `children[<n>][dob]` → `children[<n>][birth_year]`, and the matching element ids and the `us-family-child-dob` CSS class. These are our own form fields posted by our own templates — not a saved contract like a block name — and leaving them called "dob" while they carry a year is the kind of thing that misleads someone six months from now. `register.js`'s clone logic is index-generic and needed no change.
## Verification
`composer test` (770 tests, up from 762), `composer lint`, `composer cs` all pass. New coverage: a data provider over six rejected inputs (`not-a-year`, `2015-04-02`, `15`, `20155`, `1899`, and a future year), the legacy-date read fallback, and the clear-on-save behaviour above.
No `Schema.php` change — this is user meta — so no `USC_VERSION` bump, per the rule in CLAUDE.md.
Signup and the profile page now ask for a four-digit year between 1900 and
the current year. Anything else — a short year, a full date, a year in the
future — is discarded rather than stored, so a typo cannot leave a nonsense
age on the record.
The year lives in a new us_birth_year user meta rather than reusing
us_date_of_birth, which would have left one key holding two formats. The old
key is not migrated in bulk. Instead GuardianService handles it in two
halves: birthYear() falls back to the year of the old date when the new key
is absent, so a student added before this change still shows one, and
setBirthYear() deletes the old date on every save.
That deletion is what makes the fallback safe rather than merely tidy.
Without it, clearing the birth year on a student who predates the change
would leave the old date behind for the fallback to read straight back, and
the year could never be cleared at all.
Stored in user meta, so no Schema.php change and no USC_VERSION bump.
Closes#147
Co-Authored-By: Claude Opus 5 <[email protected]>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Closes #147.
Signup and the profile page now ask for a birth year instead of a full date of birth: a four-digit year between 1900 and the current year, as a
type="number"input capped at today. Anything else — a short year, a full date pasted in, a year in the future — is discarded rather than stored, so a typo cannot leave a nonsense age on the record.Storage, and the two open questions from the issue
New meta key, not a reused one. The year lives in
us_birth_year. Reusingus_date_of_birthwould have left one key holding two formats with no way to tell them apart.No bulk migration.
GuardianServicehandles the old key in two halves instead:birthYear()falls back to the year of the old date whenus_birth_yearis absent, so a student added before this change still shows a birth year with no migration step.setBirthYear()deletesus_date_of_birthon every save.That deletion is load-bearing, not housekeeping. Without it, clearing the birth year on a student who predates the change would leave the old date behind for the fallback to read straight back — the year could never be cleared. There's a test pinning exactly that (
testSavingAChildClearsTheLegacyDateOfBirth).The consequence worth your explicit sign-off: this means a student's stored full date of birth is deleted the first time their record is saved. That's the intended direction — the studio stops holding data it no longer asks for — but it is data going away, so I'd rather flag it than have you find it. Nothing runs in bulk: dates for students nobody edits stay until someone does. If you want them all gone now, that's a one-line meta delete and I can add it to the installer's migration step; say the word.
Also renamed, since the meaning changed
child_dob→child_birth_year,children[<n>][dob]→children[<n>][birth_year], and the matching element ids and theus-family-child-dobCSS class. These are our own form fields posted by our own templates — not a saved contract like a block name — and leaving them called "dob" while they carry a year is the kind of thing that misleads someone six months from now.register.js's clone logic is index-generic and needed no change.Verification
composer test(770 tests, up from 762),composer lint,composer csall pass. New coverage: a data provider over six rejected inputs (not-a-year,2015-04-02,15,20155,1899, and a future year), the legacy-date read fallback, and the clear-on-save behaviour above.No
Schema.phpchange — this is user meta — so noUSC_VERSIONbump, per the rule in CLAUDE.md.