Skip to content

feat(compiler): SYN015 — warn on localStorage/sessionStorage access that bypasses the storage capability model (?bs 0.7+)#178

Closed
marcelofarias wants to merge 1 commit into
mainfrom
botkowski/syn015-localstorage
Closed

feat(compiler): SYN015 — warn on localStorage/sessionStorage access that bypasses the storage capability model (?bs 0.7+)#178
marcelofarias wants to merge 1 commit into
mainfrom
botkowski/syn015-localstorage

Conversation

@marcelofarias

Copy link
Copy Markdown
Owner

Summary

  • Adds SYN015 to the compiler's syn-check pass: fires when localStorage.* or sessionStorage.* is accessed inside a ?bs 0.7+ fn body
  • Both Web Storage globals are synchronous same-origin key/value stores invisible to botscript's capability model: reads {} / writes {} labels cover declared resource identifiers, not the Web Storage API
  • Detection covers all member accesses (.getItem, .setItem, .removeItem, .clear, .length, etc.) on both globals, including optional-chain forms localStorage?.getItem(); excludes obj.localStorage.* (member on a local), bare references, fn/function/function* declarations named localStorage/sessionStorage, and unsafe {} / unsafe fn bodies

Closes the (SYN015) reference gap

Multiple previous PRs (#162 SYN016, #177 SYN024) referenced (SYN015) in diagnostic text and AGENTS.md without the code existing. This PR creates the code those references pointed at.

Completes the Web Storage trilogy

Check Storage mechanism
SYN015 localStorage / sessionStorage (synchronous, persistent/session-scoped)
SYN016 indexedDB (asynchronous, same-origin database)
SYN024 document.cookie (+ implicit network-side effect)

Test plan

  • Fires on localStorage.getItem(), .setItem(), .removeItem(), .clear(), .length
  • Fires on sessionStorage.getItem(), .setItem()
  • Fires on optional-chain localStorage?.getItem() / sessionStorage?.setItem()
  • Does NOT fire: obj.localStorage.*, bare localStorage, fn localStorage() declaration, function localStorage(), function* localStorage()
  • Suppressed inside unsafe {} blocks and unsafe fn bodies
  • Does NOT fire before ?bs 0.7
  • Warning severity, independent count per access
  • SYN015 in error-code allowlist, MCP server test updated

🤖 Generated with Claude Code

…hat bypasses the storage capability model (?bs 0.7+)

localStorage.* and sessionStorage.* accesses are synchronous same-origin
Web Storage operations invisible to botscript's capability model: reads {}
and writes {} labels cover declared resource identifiers, not the Web
Storage API globals. A fn that accesses either store has undeclared
persistent (localStorage) or session-scoped (sessionStorage) state
dependencies that callers cannot observe or audit from the fn header.

Detection: localStorage or sessionStorage ident not preceded by ./?.
(member-of-another-object guard), followed by . or ?. (confirming global
access, not a bare reference). fn/function/function* declarations named
localStorage/sessionStorage are excluded. unsafe {} blocks and unsafe fn
bodies are suppressed.

Wired through: error-codes, MCP explain + server test, AGENTS.md diagnostic
table, README.md explain row, and 21 tests covering both globals, optional
chains, unsafe suppression, version guard, and negative cases.

This closes the gap that multiple previous PRs (SYN016, SYN024) referenced
as (SYN015) without the code existing in the registry.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Ready to approve

The new diagnostic is implemented consistently with existing SYN checks and is fully wired through registry, MCP explainability, tests, and docs.

Note: this review does not count toward required approvals for merging.

Pull request overview

Adds missing diagnostic SYN015 to the compiler’s structural warning pass so botscript warns (at ?bs 0.7+) when a function body accesses localStorage.* / sessionStorage.*, which bypasses the reads {} / writes {} storage model, and wires the new code through registry/tests/MCP/docs.

Changes:

  • Implemented SYN015 detection in syn-check (with unsafe suppression + exclusions matching the SYN-series patterns).
  • Registered SYN015 in the compiler error-code registry and MCP “explain” content + known-codes assertions.
  • Added a dedicated SYN015 test suite and updated public docs to list the new code.
File summaries
File Description
packages/compiler/src/passes/syn-check.ts Adds SYN015 detection for localStorage.* / sessionStorage.* accesses within fn bodies at ?bs 0.7+.
packages/compiler/src/error-codes.ts Registers SYN015 with rule/idiom/rewrite/example text for explain and diagnostics metadata.
packages/compiler/tests/syn015-check.test.ts New tests covering positive/negative cases, optional chaining, unsafe suppression, and version gating.
packages/compiler/tests/error-codes.test.ts Adds SYN015 to the exhaustive allowlist for emitted diagnostics.
packages/mcp/src/explanations.ts Adds long-form SYN015 explanation + example fails/passes pair.
packages/mcp/tests/server.test.ts Adds SYN015 to the MCP server’s KNOWN_CODES assertion list.
AGENTS.md Documents SYN015 in the diagnostic-codes table alongside related SYN checks.
README.md Updates MCP explain tool documentation to include SYN015 in the supported-code list.

Copilot's findings

  • Files reviewed: 8/8 changed files
  • Comments generated: 0

Note

Your feedback helps us improve the quality of this feature.
Please use 👍 or 👎 to tell us whether this assessment is correct.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@marcelofarias

Copy link
Copy Markdown
Owner Author

Closing in favor of PR #162 which covers the same feature more comprehensively (including computed-property access ). Will fix PR #162's Copilot issue instead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants