Path: business objects, records and views | 缺项 (no item clears a number or date field and reads the stored value back) | P2
Filing gate: ① a defect with a named landing site: packages/objectql/src/validation/record-validator.ts (if (isMissing(value)) return null; at :629 and :1109 on origin/main), plus the write path that stores what the validator let through. Finding class (a), a declared type the write door does not enforce. Filed and graded by the triage seat (objectstack-wide, seat post #6015, session_01W89enF2dYV7K4N2Fbfj33f) while answering pm:retriage on objectstack-ai/objectui#10813. ⛔ Not a claim.
Grade: bug · priority:p2 · domain:engine · area:records · pm:queue. Priority rule 1 (data integrity): a number, boolean or temporal column holds a value that is not of its type.
The reading (objectui#10813's dev report 5858799523 and at-tier review 5859057830, re-read by the releasing seat on objectstack 17bd3187)
- objectui's edit form sends a cleared date, datetime or time box as
'' (runtime probe, flat, modal and drawer routes). A cleared number box sends null.
- The validator counts
'' as missing (isMissing), and returns before its invalid_number / invalid_boolean checks. So '' skips every type check. The number branch also omits progress and summary, which are in NUMERIC_VALUE_TYPES.
- Nothing rewrites it. driver-sql's
formatInput has no numeric or boolean arm, and temporalStorageForm returns '' unchanged. SQLite, sqlite-wasm and turso keep it as TEXT, and the memory and mongodb drivers store it verbatim.
- On PostgreSQL a non-numeric string bound to an integer column is refused (
invalid input syntax for type integer, driver-sql changelog). So the same clear behaves differently per backend.
Direction (triage, decided here)
Normalise '' → null at the write door for every non-string-typed column: the numeric types (NUMERIC_VALUE_TYPES, including progress and summary), boolean, date, datetime and time.
- The validator already reads
'' as missing on these columns. Normalising makes storage agree with the platform's own reading of a blank.
- No producer breaks: objectui's date and time fields, CSV blanks and API clients that send
'' all keep working, and every backend stores the same null.
- String-stored columns (text, lookup ids, select values) are ⛔ untouched. The spec's value round-trip fixture pins
str_empty (「empty string must not become null」), and what 「is empty」 means for them is a separate spec question, filed as its own decision card.
Execution notes
- One rule at the write door (engine and REST create/update, including batch), before type validation, keyed on the field's declared type. ⛔ No driver copy.
- Add
progress and summary to the number branch's type checks.
- Stored rows. Census the stored
'' in non-string-typed columns on the conformance backends. Propose a repair (a migrate step, or a documented one-off) in the PR, and do not run it on any deployment from this card.
- Pin it on memory, SQLite and PostgreSQL, through the engine and REST: a cleared number, date and boolean store
null; a text field's '' stays '' (the str_empty control); a valid value is unchanged.
- Once this lands, objectui#10813's widget can drop its
'' member for typed columns without re-scoping a stored rule. Post the back-link there.
Refs: objectstack-ai/objectui#10813 · objectstack-ai/objectui#10790 · PR objectstack-ai/objectui#10834 (closed, branch kept).
Path: business objects, records and views | 缺项 (no item clears a number or date field and reads the stored value back) | P2
Filing gate: ① a defect with a named landing site:
packages/objectql/src/validation/record-validator.ts(if (isMissing(value)) return null;at:629and:1109onorigin/main), plus the write path that stores what the validator let through. Finding class (a), a declared type the write door does not enforce. Filed and graded by the triage seat (objectstack-wide, seat post #6015,session_01W89enF2dYV7K4N2Fbfj33f) while answeringpm:retriageon objectstack-ai/objectui#10813. ⛔ Not a claim.Grade:
bug·priority:p2·domain:engine·area:records·pm:queue. Priority rule 1 (data integrity): a number, boolean or temporal column holds a value that is not of its type.The reading (objectui#10813's dev report
5858799523and at-tier review5859057830, re-read by the releasing seat on objectstack17bd3187)''(runtime probe, flat, modal and drawer routes). A cleared number box sendsnull.''as missing (isMissing), and returns before itsinvalid_number/invalid_booleanchecks. So''skips every type check. The number branch also omitsprogressandsummary, which are inNUMERIC_VALUE_TYPES.formatInputhas no numeric or boolean arm, andtemporalStorageFormreturns''unchanged. SQLite, sqlite-wasm and turso keep it as TEXT, and the memory and mongodb drivers store it verbatim.invalid input syntax for type integer, driver-sql changelog). So the same clear behaves differently per backend.Direction (triage, decided here)
Normalise
''→nullat the write door for every non-string-typed column: the numeric types (NUMERIC_VALUE_TYPES, includingprogressandsummary), boolean,date,datetimeandtime.''as missing on these columns. Normalising makes storage agree with the platform's own reading of a blank.''all keep working, and every backend stores the same null.str_empty(「empty string must not become null」), and what 「is empty」 means for them is a separate spec question, filed as its own decision card.Execution notes
progressandsummaryto the number branch's type checks.''in non-string-typed columns on the conformance backends. Propose a repair (amigratestep, or a documented one-off) in the PR, and do not run it on any deployment from this card.null; a text field's''stays''(thestr_emptycontrol); a valid value is unchanged.''member for typed columns without re-scoping a stored rule. Post the back-link there.Refs: objectstack-ai/objectui#10813 · objectstack-ai/objectui#10790 · PR objectstack-ai/objectui#10834 (closed, branch kept).