fix(server): reserve parent/plan schema field keys (TASK-1912)#786
Merged
Conversation
A collection schema field keyed exactly "parent" or "plan" makes the parent-link extraction sites in handlers_items.go silently skip fields-JSON extraction, disabling subtask linking with no error anywhere. Reject newly-added occurrences of these keys on collection create/update (grandfathering keys already present in a prior schema), and add them to the web's reserved-key list so authors are steered away before hitting the 400.
Codex round 2: handleUpdateCollection's validation guard was skipped
whenever input.Schema was a non-nil pointer to "", so a PATCH with
{"schema": ""} stored the empty string verbatim and every later
item-create against that collection 500'd instead of the mutation
being rejected up front. Drop the empty-string carve-out so "" flows
into json.Unmarshal, fails, and returns the existing 400 "Invalid
schema JSON". Omitting the schema field entirely (nil) is unaffected.
Collaborator
Author
|
Go (SQLite) job failure is the pre-existing |
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.
Summary
A collection schema field literally keyed
parentorplanmakesschemaHasFieldreturn true, which silently skips fields-JSON parent-link extraction at all three sites (createhandlers_items.go:584, PATCH:851, list filter:2147) — disabling subtask linking for that collection with no error anywhere. Nothing prevented creating such a schema. Stage 1 of the IDEA-1746 parent-edge consolidation plan.Changes
parentorplan; collection update rejects them only when newly added — keys already present in the stored schema are grandfathered so existing workspaces keep working.Invalid schema JSON(previously stored unvalidated — a small contract tightening). PATCH{"schema": ""}is likewise rejected instead of stored verbatim, which previously poisoned the collection into 500s on later item creates (found in review round 2).parentandplanadded toRESERVED_FIELD_KEYSso the field editor steers authors away before the 400.Intentional asymmetry: server matching is exact + case-sensitive, mirroring
schemaHasField's plainf.Key == keycomparison; the web layer lowercases (stricter). Client-stricter-than-server is safe; "fixing" the server to case-insensitive would reject keys the extraction guard never skips on. There's a test assertingParentis NOT rejected, with a comment explaining why.Known limitations
This guard lives at the HTTP handler layer, not in
store.CreateCollection. Two server-side paths bypass it by design:store.SeedCollectionsFromTemplate(template seeding calls the store directly — repo grep confirms no shipped template uses these keys) andstore.ImportWorkspace(raw-SQL insert; imported bundles round-trip pre-existing schemas unchanged, matching the grandfathering spirit). Revisit if stage 2 of IDEA-1746 touches this area.Review
3 codex rounds with rotated framing: R1 (plain) CLEAN → R2 (contract lens) found the PATCH empty-string gap, fixed in e5e384f → R3 (pointer-vs-value lens) CLEAN. Converged.
Test plan
go test ./...(SQLite) — all packages, including 10 new subtests (reserved-key create/update, grandfathering, case-sensitivity control, malformed + empty-string schema, nil-schema untouched)make lint— 0 issuesmake test-pg(Postgres) — full suite greennpm run check(0 errors),npm test(89/89),npm run buildRefs: TASK-1912, IDEA-1746
https://claude.ai/code/session_01CL1pBjNpPUX6SWkuAuYXHS