Conversation
…ments `makeJsonDocumentCodec.decode` ran the full schema over every stored document, so reads of an older-shaped document failed with `Missing key` before the repository's `jitM` could add the key -- breaking `find`, `filter`, `all` and `validateSample` on real production data. Decode now walks the stored document with `decodeWithSchema`, the decode counterpart of `encodeJson`: it iterates the document's own keys and only lifts JSON to native Encoded values (Date/Map/Set and app-native declarations). Keys that are absent stay absent, refinements and checks are not enforced, and a leaf that cannot be decoded passes through unchanged, so the repository's own decode -- which runs after `jitM` -- reports it with full path context. Writes keep using the strict whole-document codec. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@effect-app/cli
effect-app
@effect-app/eslint-codegen-model
@effect-app/eslint-shared-config
@effect-app/infra
@effect-app/vue
@effect-app/vue-components
commit: |
This was referenced Sep 16, 2026
Member
Author
|
Superseded by #896. Leniency is out: the owner's call is that nothing should be lenient. #896 rebuilds the fix on The root cause analysis in this PR still stands and is restated in #896. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
makeJsonDocumentCodec.decoderan the full schema over every stored document:It is called by Cosmos (
fromStored), SQL (parseRow) and Memory (decodeDoc) on every read —find,filter,all,validateSample— and it runs before the repository'sjitMmigration (mapFrom). So a document of an older shape, whichjitMexists precisely to migrate, now fails to read at all:Reproduced directly:
makeJsonDocumentCodec(Shop).decode({ id, name, createdAt })(novatRate) throws.This is not limited to
validateSample— it breaks normal reads of real production documents. Found via macs-holding/configurator, where all 7 DB Validation jobs (demo + prod) fail onShop.vatRate,User.permissionsandConfigurator.conditionGroups[].conditions[].rules[].groupId. Introduced by #874 ("native Date/Map/Set Encoded"), released in beta.323+.Fix
Decode at the store boundary is now lenient: it only lifts JSON back to native Encoded values (Date/Map/Set and app-native declarations) for the keys that are present.
decodeWithSchema/decodeJsoninStore/utils.tsis the decode counterpart of the existing value-drivenencodeJsonwalker and reuses its helpers (unwrapAst,astAtPath,elementAst,isPlainObject):_tagliteral, else by the first member that decodesReadonlyMap/ReadonlySetdeclarations reconstruct viatoCodecJsonrunSyncExit, so defects can't escape either), leaving the repository's own strict decode — which runs afterjitM— to report it with full path contextencodestill uses the strict whole-document codec: writes always carry a complete document.Tests
packages/infra/test/json-document-lenient.test.ts(8): complete document lowers Date/Set/Map/app-native declaration and preserves_etag; missing top-level key; missing key insidearray[].struct[].fieldwith siblings still lowered; tagged-union member resolution; unparseable leaf (null,"not-a-date") passes through; refinements not enforced;encodeKeys-renamed fields lower and missing renamed keys stay absent;encoderound-trip.packages/infra/test/repository-legacy-document.test.ts(3):repo.all,repo.findandrepo.validateSampleover a legacy document missingvatRatethatjitMfills.packages/infra: 284 passed / 26 skipped, 0 failures.pnpm checkandpnpm lintclean.Worth a follow-up (not in this PR)
jitMas a JSON value and reorder the pipeline tojitM → toCodecJson → schema, i.e. the store returns raw JSON documents and the repository decodes once after migrating.jitMis currently typed(pm: Encoded) => Encoded, which since feat: native Date/Map/Set Encoded; query adapters convert to JSON #874 promises nativeDate/Map/Setwhile jitMs are actually written against stored JSON. That would also make this lenient walker unnecessary for documents.encodeis strict, so a legacy-shaped document cannot be stored or re-saved at all — which makes Memory/Disk unusable for legacy fixtures (the repository test here needs its own store harness). Worth deciding whether writes should fail loudly or lower leniently.config.defaultValueson read, while Cosmos and SQL merge them on every read — so adefaultValuesmigration behaves differently in tests than in production.Note
defaultValuesonly ever fills absent keys, and a storednullcorrectly wins over a default —nullis a value, not a missing key. Configurator'sPreconfiguration.updatedAtfailure is therefore a genuine data/schema mismatch on that side, not something this PR should hide.🤖 Generated with Claude Code
Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.