You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
SecretBytes saved into a 0.25 varchar column on Postgres is stored as escaped text with no error #785
A SecretBytes column created by Ferro 0.25 is varchar on Postgres (0.25 wrote every secret as the mask **********, so the column was text). Ferro 0.26 binds the real bytes. On Postgres, save() of b"\xff\x00k" into that old varchar column succeeds and stores the text \xff006b; a fetch returns SecretBytes of those seven characters, not the three bytes written. No error on either door.
classToken(Model):
id: int=Field(primary_key=True)
secret: SecretBytes# 0.25 created this as varchar on PostgresawaitToken(id=1, secret=SecretBytes(b"\xff\x00k")).save() # 0.26: stores '\xff006b', no errortoken=awaitToken.get(1)
token.secret.get_secret_value() # b'\\xff006b', not b'\xff\x00k'
connect(auto_migrate=True) does not report the column: the live type (varchar) and the declared type (bytea) differ, and the pass's type-change rung is migrate_updates/migrate_destructive, so a default connect says nothing.
Reproduced by the worker and independently by the reviewer on PR #784 (#784 (review)). The 0.26 upgrade notes state the fact; this issue is the code-side fix.
What a fix needs
AGENTS.md I-6: fail loudly. A binary declared column backed by a text live column is a type mismatch the pass already knows about (it plans the ALTER COLUMN ... TYPE for migrate_updates). The question is whether a save into a column whose live type cannot hold the declared type should refuse, and whether connect() should warn when it sees the mismatch and is not asked to fix it. Candidates, to grill:
connect(auto_migrate=True) emits a warning per column whose live type and declared type disagree in storage class (text vs binary), naming the rung that fixes it (ferro migrate up or migrate_updates).
The runtime refuses to bind a bytes value for a column the live schema says is text on Postgres. Costs a live-schema read on the bind path; probably the wrong door.
Nothing in src/, documented only (rejected: that is the current state, and the corruption is silent).
Out of scope here: the SQLite side (text affinity stores the blob as written, so the round trip holds; verify before closing).
Activity