fix: keep writes inside the store's scope; refuse operator keys on writes - #15
Merged
Merged
Conversation
…ites - `_build_doc` raises ValueError when a key or value contradicts a field of the write filter (`on_write_filter`, else `filter`), instead of silently writing the doc outside the store's scope. Consistent writes are unchanged. - Keys used by `__setitem__`, `__delitem__`, MultipleDocs `__setitem__` (its `delete_many`) and the bulk-write mixin may not contain `$`-operators; keyword-only `allow_operators_in_write_keys=True` restores the old behaviour. Read keys (`s[k]`, `k in s`) still accept queries, always within the scope. - New helper `operator_field_names`. Closes #14 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- Write/delete keys also refuse regex values (re.Pattern, bson Regex). - MultipleDocs __setitem__ builds and validates all docs before delete_many. - Scope contradiction uses MongoDB (BSON) equality; `$eq`/`$in` scopes are checked by membership, other operator scopes are not checked. - Dotted scope fields refuse writes with a clear error. - Replace/delete queries are confined by on_write_filter as well as filter. - allow_operators_in_write_keys defaults to None so a class attribute works. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… writes Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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.
Closes #14
What changes
_build_docused to merge asdict(filter, **k, **v), so a key or value repeating a scope field with a different value wrote the doc outside the store's scope. It now raisesValueErrornaming the field, comparing as MongoDB does (BSON equality:Trueis not1, subdocument field order matters).$eq/$inscope fields are checked by membership; other operator scopes ($ne,$gt, ...) are not checked and such writes are let through (documented). Dotted scope fields refuse writes with a clear error (those writes produced literal dotted field names before). Writes that agree with the scope produce exactly the same documents as before.__setitem__(replace_one),__delitem__(delete_one),MongoCollectionMultipleDocsPersister.__setitem__(itsdelete_many) andMongoBulkWritesMixinnow go through_write_filter_for_key, which refuses keys containing$-prefixed field names or regex values (re.Pattern,bson.regex.Regex) at any depth. The check runs before any call to the collection;MongoCollectionMultipleDocsPersisteralso builds and validates every new doc before itsdelete_many, so a refused write deletes nothing. Keyword-onlyallow_operators_in_write_keys=True(constructor arg, or class attribute) restores the old behaviour.on_write_filtertoo (previously only byfilter), so a store stampingon_write_filter={"tenant": "a"}over an unscopedfiltercan no longer replace or delete another tenant's docs.s[k]/k in skeep accepting query keys (used byrecipes.disallow_sourced_interval_overlaps), and remain confined by the scope through$and.mongodol/tests/write_scope_test.py, using a recording stand-in for the collection (no server needed; hosted CI also runs the full suite against its MongoDB service).Compatibility
Behaviour changes for: writes that contradicted the scope; write/delete keys with operators or regexes; writes through dotted scope fields; and stores whose
on_write_filterstamps a field that older docs lack — replace/delete by key no longer matches those older docs (an upsert on an existing_idthen fails with a duplicate-key error, and MultipleDocs writes leave the old docs in place). mongodol has no fleet dependents.Review
Independent refute-review by a sub-agent found three blockers in the first version (regex keys still wiped the scope; MultipleDocs deleted before validating; operator scopes broke legitimate writes) plus several should-fixes. All were fixed in c16d08f; a re-review found no remaining blockers. Remaining known gaps: operator scopes other than
$eq/$infail open (documented); no test yet for the bulk-write mixin path.🤖 Generated with Claude Code