docs(core): replace the dangling SECURITY_FIX_SUMMARY @see with its rationale - #6339
Merged
os-support-ai merged 1 commit intoAug 25, 2026
Merged
Conversation
…ationale `SimpleExpressionEvaluator`'s doc block pointed at https://github.com/objectstack-ai/objectui/blob/main/SECURITY_FIX_SUMMARY.md. That file was deleted in ea72f18 — a 20-file bulk removal of the root-level PR #300 / v0.4.0 summaries, 6742 deletions and zero insertions, so the content was dropped outright rather than migrated. The link has 404'd since. Reading `git show ea72f18^:SECURITY_FIX_SUMMARY.md` shows the doc block already repeats most of what it carried (the operator list, the LIMITATIONS list verbatim). One thing it carried is NOT in the doc block and is load-bearing: the parser exists because CodeQL flagged the previous `new Function(...contextKeys, "'use strict'; return (…)")` as "Unsafe code constructed from library input". That makes the ban on dynamic code execution a remediation constraint a future maintainer must not trade away for expressiveness or speed, not a style preference. That sentence is now inline, and the provenance points at the immutable git object instead of a `main` blob path that no longer resolves. Comment-only: `SimpleExpressionEvaluator` is not exported, so nothing changes in the emitted `.d.ts`, and no behaviour, type or API surface moves.
Contributor
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
This was referenced Aug 25, 2026
os-support-ai
marked this pull request as ready for review
August 25, 2026 14:28
os-support-ai
deleted the
claude/issue-6275-validation-engine-dangling-see
branch
August 25, 2026 14:40
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.
Fixes #6275
SimpleExpressionEvaluator's doc block inpackages/core/src/validation/validators/object-validation-engine.tspointed at aSECURITY_FIX_SUMMARY.mdthat has not existed since January. This replaces the dead@seewith the load-bearing reasoning that file carried.Premise table — re-measured on
origin/main@79ebf30d1(the card was written againstc38162d7c;mainmoved 30+ commits)@seesits atobject-validation-engine.ts:221grep -n SECURITY_FIX_SUMMARY <file>→221: * @see https://github.com/objectstack-ai/objectui/blob/main/SECURITY_FIX_SUMMARY.mdSECURITY_FIX_SUMMARY.mdexists nowhere in the treegit ls-tree -r --name-only HEAD | grep -i SECURITY_FIX_SUMMARY→ 0 hitspackages/andapps/grep -rnover both, excludingnode_modules/dist→ count1;git grepover all tracked files agreesAll three held. One subsidiary claim in the card body did not — see "Two card claims that did not survive measurement" below.
The three-way choice, and the evidence from
ea72f1886Chosen: fold the load-bearing sentence into the doc block, then drop the dead
@see. (Not "repoint" — nothing to repoint at. Not "just delete" — the reference was not redundant.)Evidence the content was dropped, not moved:
Zero insertions. The commit — "Delete obsolete files and documentation related to PR #300 and v0.4.0 release; remove security fix summary and CRM app fix scripts" — is a bulk removal of 20 root-level summary docs (
ARCHITECTURE_EVALUATION.md,RELEASE_SUMMARY_v0.4.0.md,SECURITY_FIX_SUMMARY.md, …). Nothing was written anywhere in the same commit, so there is no successor path to repoint at, and no ADR or docs page anywhere in the tree covers it (git grep -il codeql -- content/ docs/→ empty).Evidence the reference was not redundant — from
git show ea72f1886^:SECURITY_FIX_SUMMARY.md:Most of what it carried is already in the doc block — the operator list, and the LIMITATIONS list reproduced there verbatim. One thing is not, and is the reason the parser has the shape it has:
The doc block said what the code does ("without using eval() or new Function()") but never why it must stay that way. A maintainer who wanted chained comparisons or more speed had, in the file, no reason not to reach for
new Function()— the ban read as taste. That is the sentence now inlined. The provenance line points atgit show ea72f1886^:SECURITY_FIX_SUMMARY.md, an immutable git object, rather than anothermainblob path that can rot the same way.Two card claims that did not survive measurement
Neither changes the disposition — both are recorded so the record is accurate.
The card says the
@seewas "the only pointer the doc block offers for the security rationale behind this evaluator's fail-open polarity". The deleted file contains zero mention of polarity or fail-open — its whole subject is the injection fix. The polarity rationale was already inline in the doc block (theNOT CELparagraph, ending "…fails OPEN — the same outcome the server produces for an un-evaluable predicate"), and is untouched here.The card says "this dead link ships in the released package's type declarations". It ships, but not there. Measured by building the package (
tsc) and reading the emitted output:dist/validation/validators/object-validation-engine.d.tsSimpleExpressionEvaluatoris not exported, sotscemits no declaration for it; the only occurrence of the name is a passing mention inside the module-level doc blockdist/validation/validators/object-validation-engine.jstscpreserves comments, andpackage.jsonfiles: ["dist", …]publishes itSo the dead link did reach consumers, in the published JavaScript. This is what decides the changeset form below.
Changeset
node scripts/check-changeset-presence.mjsis followed by its own verdict line, not by memory:Empty frontmatter, deliberately. The change is comment-only on a class that is not exported: no behaviour, no type surface, no API. Nothing a consumer can import, call or depend on moves. The counterweight is concrete —
.changeset/config.jsonputs all 43 packages in onefixedgroup, so any non-empty bump versions the entire monorepo for a comment. If a reviewer reads the published-.jscomment as user-visible enough to warrant a release line, this flips topatchwith a one-line edit; the measurement above is the fact that decides it. Nevermajor(check-changeset-no-major.mjs✅).Gates
Gate set derived by reading the CI job step lists under
.github/workflows/— every workflow'son:block parsed for apull_requesttrigger and its path filter, then each firing job'srun:steps read. Verdict lines below are the gates' own; exit codes captured before any pipe (cmd > file 2>&1; EXIT=$?), never throughtail.Union re-run after the final commit, at
ad39293c9:check-changeset-presence(changeset-presence.yml)✅ 1 source file(s) … declares 1 changeset(s) … EMPTY frontmatter … a complete answer to this gate.check-changeset-no-major(changeset-guard.yml)✅ No changeset declares a `major` bump.check-changeset-fixed(ci.yml)✅ All workspace packages are in the changeset fixed group.check-control-bytes(control-bytes.yml)✅ check-control-bytes: OK (scanned 5225 tracked text file(s); skipped 85 binary).check-doc-component-types(doc-component-types.yml)✅ Every documented component type is registered.check-doc-fence-languages(doc-fence-languages.yml)✅ check:doc-fences — every TypeScript block in 223 document(s) is fenced ts/tsx/typescript …check-doc-links(docs-links.yml)Links are valid across 17 scan roots.— blind, see belowcheck-shell-escape-residue(shell-escape-residue.yml)✅ check-shell-escape-residue: OK (4/4 root(s) resolved …)check-skills-paths(skills-paths.yml)✅ check-skills-paths: OK (93/94 stated path(s) resolve …)check-vi-mock-specifiers(vi-mock-specifiers.yml)✅ check-vi-mock-specifiers: OK (3748 tracked source file(s) …)check-lint-coverage(lint.yml)✅ lint coverage: 46/46 packages linted, 0 with outstanding errors (0 total).check-entry-guard(lint.yml)✓ check:entry-guard: 47 scripts/ file(s) — no entry guard outside the baseline …check-cross-repo-closer-outcome(lint.yml)check-cross-repo-closer-outcome: OK (105 assertions over 18 scenarios …)check-pre-install-import-graph(pre-install-import-graph.yml)✅ check-pre-install-import-graph: OK — 16 pre-install step(s) in 15 job(s) …check-type-check-coverage(ci.yml)✅ test type-check coverage: 41/41 packages compile their tests, 0 declared debt …turbo run lint --filter=@object-ui/core(lint.yml)✖ 515 problems (0 errors, 515 warnings)— all warnings pre-existing, none on the changed linesturbo run type-check --filter=@object-ui/core(ci.yml)Tasks: 5 successful, 5 totalvitest run packages/core/(ci.yml test shards)Test Files 100 passed (100) · Tests 2023 passed (2023)Gates that are structurally blind to this change
check-doc-links.mjs(docs-links.yml) — blind, and its green run above is not evidence for this PR. Not a judgement call: its walker isscripts/check-doc-links.mjs:650→if (!/\.(md|mdx)$/.test(entry.name)) continue;so a
.tsfile cannot enter the population at all. Worth noting the near-miss the issue flagged: the gate does already know how to decide this exact URL shape —https://github.com/objectstack-ai/objectui/(blob|tree)/main/<path>is a case it handles for markdown (check-doc-links.mjs:154). The link was undecidable only because of where it was written, not what it was. Widening the population to@seeURLs in TS source is explicitly out of scope here (triage: "separate call, not minted this round") and is not attempted.vitest run packages/core/(100 files, 2023 tests) passes, but a comment-only diff cannot move any assertion — it is a regression guard, not evidence the link is fixed.readme-exports,performance-budget,doc-snippet-types. They fire on these paths and are left to CI: none can observe a comment. The bundle budget sees no byte change in any minified artifact; the export surface is unchanged (nothing was exported before or after).The only evidence that the defect is fixed is the direct measurement:
blob/main/SECURITY_FIX_SUMMARY.mdoccurrences acrosspackages/+apps/went1 → 0, and the injected text (CodeQL,Unsafe code constructed from library input,ea72f1886) is present exactly once each on disk.Narrowing declared
lint,type-checkandtestwere run filtered to@object-ui/corerather than across all 46 packages. Three pieces of evidence that the narrowing excludes nothing:pnpm exec eslint . --format jsoninsidepackages/corereports 195 files linted, and the changed file is in that set (checked by path, not assumed).--format json— 0 errors, 515 warnings, of which 17 are on the changed file and all pre-date this PR.project:/projectServicein the single rooteslint.config.js), so this diff cannot move any untouched file's verdict. Independently, the diff changes only comment bytes in a non-exported class, so no type, value or module-graph fact crosses a package boundary.check-lint-coverageandcheck-type-check-coverageabove still ran repo-wide and confirm 46/46 and 41/41 clean.Scope
Fix confined to
packages/core(T3 — sibling agents holdpackages/plugin-form#5034 andpackages/plugin-map#5977; no file overlap). The sweep was not widened (T1): the repo-widegrepfound this to be the onlySECURITY_FIX_SUMMARYreference, and no other dangling@seeor doc link was repaired here.content/docs/releases/untouched.Generated by Claude Code