aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-10-10 10:01:56 +0200
committerChristophe Besson <cbesson@gmail.com>2026-10-10 10:01:56 +0200
commite29617c04ebe3097914fed02e6ce917f48a9dbd6 (patch)
treebbd9b6f5661c3bb2138e7ced6b0d031c1f5e2662
parent876f4a351f859201ca68fbf8d585c86905571686 (diff)
downloadmeshbay-e29617c04ebe3097914fed02e6ce917f48a9dbd6.tar.gz
test(node): a name an LGPL file declares itself is its own binding
The LGPL closure check excluded only names declared at the top level of the LGPL files, so keyring.js's `const state = () => ...`, local to createKeyring, read as a call to photo-sync.js's top-level `state` once that file was added. A name the file declares at any depth now shadows an AGPL global for that file. A real call into an AGPL module is still caught (checked by adding one to keyring.js). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
-rw-r--r--packages/meshbay-node/tests/test_licensing.py7
1 files changed, 7 insertions, 0 deletions
diff --git a/packages/meshbay-node/tests/test_licensing.py b/packages/meshbay-node/tests/test_licensing.py
index 68eb6bb..239633d 100644
--- a/packages/meshbay-node/tests/test_licensing.py
+++ b/packages/meshbay-node/tests/test_licensing.py
@@ -220,7 +220,14 @@ def test_the_lgpl_layer_depends_on_nothing_under_the_agpl():
if spec.startswith("node:") or "vendor" in spec:
continue
assert (f.parent / spec).resolve() in lgpl, f"{f.name} imports {spec}"
+ # A name the file declares itself, at any depth, is its own binding:
+ # keyring.js's `const state = () => ...` inside createKeyring was taken
+ # for photo-sync.js's top-level `state` once that file existed.
+ own = set(re.findall(
+ r"\b(?:function\*?\s+|const\s+|let\s+|var\s+|class\s+)([A-Za-z_$][\w$]*)", code))
for name, owner in agpl_globals.items():
+ if name in own:
+ continue
assert not re.search(rf"(?<![\w$.]){re.escape(name)}\s*\(", code), (
f"{f.name} calls {name}() from {owner}"
)