Guard browser storage behind OPFS

This commit is contained in:
cnc
2026-06-02 07:11:41 +08:00
parent 0db23b4a5d
commit dab7b9e2ef
4 changed files with 17 additions and 0 deletions

View File

@@ -16,6 +16,10 @@ Hard rules:
LinuxCNC source before implementation.
- Browser-side wasm filesystem behavior must use OPFS-backed storage. Do not
add browser filesystem paths that bypass OPFS.
- Browser app and wasm bridge code must not persist CNC programs, LinuxCNC
parameter files, or mirrored workspace files through non-OPFS browser storage
APIs such as Local Storage, IndexedDB, File Picker writes, WebKit filesystem
APIs, or FileReader-backed import paths.
Allowed project code:
@@ -61,6 +65,8 @@ Efficiency rules:
permission to expand the pass into another workstream.
- Do not add a smoke-only behavior path when the LinuxCNC-backed route already
exists; add coverage to the source-backed route instead.
- Keep browser filesystem guardrails negative as well as positive: require the
OPFS bridge and reject browser app/wasm storage APIs that could bypass it.
- Smoke tests are verification guardrails. They must not be expanded with new
functional CNC behavior unless that behavior is directly routed to, copied
from, or checked against the relevant LinuxCNC source in the same narrow

View File

@@ -504,6 +504,9 @@ grep -F 'cached `nm --defined-only` symbol export signatures' docs/linuxcnc-sour
grep -F 'Cache wasm blocker analyzer output' docs/linuxcnc-source-policy.md >/dev/null
grep -F 'signature must include the blocker wrapper script, analyzer script' docs/linuxcnc-source-policy.md >/dev/null
grep -F 'sha256sum test-linuxcnc-wasm-blockers.sh' test-linuxcnc-wasm-blockers.sh >/dev/null
grep -F 'browser app/wasm code must not add filesystem persistence outside OPFS' test-native.sh >/dev/null
grep -F 'browser app/wasm code must not add filesystem persistence outside OPFS' test-linuxcnc-wasm-cmake-safe-probe.sh >/dev/null
grep -F 'reject browser app/wasm storage APIs that could bypass it' docs/linuxcnc-source-policy.md >/dev/null
grep -F 'Persistent native, source-link, source-syntax, and wasm-safe CMake probe' docs/linuxcnc-source-policy.md >/dev/null
grep -F 'copies and byte-compares `cnc_sim.js` and `cnc_sim.wasm` under' docs/linuxcnc-source-policy.md >/dev/null
grep -F '`CNC_SIM_BUILD_JOBS` must be a positive integer and defaults to `8`.' docs/linuxcnc-source-policy.md >/dev/null

View File

@@ -753,6 +753,10 @@ grep -F -- './test-web-wasm-node-smoke.sh' build-wasm.sh >/dev/null
grep -F -- './test-web-wasm-browser-smoke.sh' build-wasm.sh >/dev/null
grep -F 'const opfsOptions = options.opfs ?? (isOpfsAvailable() ? {} : false)' web/src/wasm-core.js >/dev/null
grep -F 'OPFS cannot be disabled in browser contexts with OPFS support' web/src/wasm-core.js >/dev/null
if grep -R -n -E 'localStorage|sessionStorage|indexedDB|showOpenFilePicker|showSaveFilePicker|webkitRequestFileSystem|FileReader' web/src; then
echo "browser app/wasm code must not add filesystem persistence outside OPFS" >&2
exit 1
fi
grep -F 'async function opfsEntryExists(workspacePath, relativePath)' web/src/wasm-core.js >/dev/null
grep -F 'async function statOpfsEntry(workspacePath, relativePath)' web/src/wasm-core.js >/dev/null
grep -F 'async function readOpfsDirectoryTree(workspacePath, relativePath, relativeRoot = "")' web/src/wasm-core.js >/dev/null

View File

@@ -227,6 +227,10 @@ grep -F '"parameters/rs274ngc.var"' web/test-browser-wasm-smoke-opfs-parameter-s
grep -F '"parameters/rs274ngc.var.bak"' web/test-browser-wasm-smoke-opfs-parameter-sections.js >/dev/null
grep -F 'const opfsOptions = options.opfs ?? (isOpfsAvailable() ? {} : false)' web/src/wasm-core.js >/dev/null
grep -F 'OPFS cannot be disabled in browser contexts with OPFS support' web/src/wasm-core.js >/dev/null
if grep -R -n -E 'localStorage|sessionStorage|indexedDB|showOpenFilePicker|showSaveFilePicker|webkitRequestFileSystem|FileReader' web/src; then
echo "browser app/wasm code must not add filesystem persistence outside OPFS" >&2
exit 1
fi
grep -F 'LinuxCNC source basis: rs274ngc_pre.cc restore_parameters() reads the' web/src/wasm-core.js >/dev/null
grep -F 'before replacing the main file and managing filename + ".bak".' web/src/wasm-core.js >/dev/null
grep -F 'await removeOpfsEntry(workspacePath, `${path}.new`, false);' web/src/wasm-core.js >/dev/null