Skip to content

v4.0.1

Choose a tag to compare

@BATEMAN4 BATEMAN4 released this 31 Jul 18:21
· 148 commits to main since this release
54de763

A follow-up to 4.0.0 covering the three items deferred out of the post-release review. No breaking changes.

Tool effects are declared, never inferred

Effects drive authorization — the inspector and builder profiles, and capability allowlists — but they were guessed from the tool's name:

const EXTERNAL_TOOL = /(asset|marketplace|image_generate|pollinations|wally|publish|import_rbxm|export_rbxm)/;

That was wrong in both directions. It over-declared: export_rbxm asks Studio for bytes and writes them to disk, yet was marked as reaching the network while its actual local write went undeclared. And it under-declared, which is the dangerous half: a new tool that genuinely reaches the network inherits no network.external unless its name happens to match, and a capability policy would wave it through.

ToolDefinition.effects is now required, so an omission is a compile error rather than a silent guess. All 209 tools declare their own. They were seeded from the previously computed values so nothing could quietly lose an effect; exactly three changed, each verified by reading the handler:

tool before after
export_rbxm studio.read, network.external studio.read, local.files.write
get_asset_provenance studio.read, network.external
import_rbxm studio.write, network.external studio.write, local.files.read, network.external

Syncback recovery snapshot honours the project's ignore paths

The native syncback rollback snapshot now skips paths the project declares through globIgnorePaths and syncbackRules.ignorePaths, and both lists are part of the plan hash so changing them invalidates a preview. Rojo evaluates them per path relative to the project directory and refuses to write to a match, so those files cannot need restoring.

The snapshot is deliberately not narrowed to the dry run's reported paths: rojo syncback --list is human-readable output rather than a machine contract, and any path a parse missed would be unrecoverable after a partial failure. The 5000-file / 100 MiB ceiling stays, and its message now names both ignore lists as the way out.

ESLint 10

eslint and @eslint/js move to 10 together; typescript-eslint 8.65 already declares ESLint 10 support. Two rules new to recommended were fixed rather than switched off:

  • preserve-caught-error — 17 rethrows discarded the original failure when wrapping it. They now carry { cause }, so an errno or a timeout stays readable underneath the BloxForge-level message.
  • no-useless-assignment — 8 initializers whose value no code path could observe.

Full detail in CHANGELOG.md.