feat: publish NIRO Gen5W research overview and reviewed source examples
This commit is contained in:
commit
ccad0ed9f3
23 files changed
+1279
No files matched your search
@@ -0,0 +1,87 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Small publication gate, not a comprehensive security or licensing audit."""
|
||||
|
||||
import os
|
||||
from pathlib import Path
|
||||
import re
|
||||
import subprocess
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
ALLOWED = {
|
||||
".gitattributes", ".gitignore", "README.md", "RIGHTS.md", "LICENSE",
|
||||
"SECURITY.md", "docs/ARCHITECTURE_KO.md", "docs/FEATURES_KO.md",
|
||||
"docs/RESEARCH_KO.md", "docs/PUBLICATION_KO.md",
|
||||
"telemetry/java/com/chaegeon/niro/HscanRpmDecoder.java",
|
||||
"weather/java/com/chaegeon/niro/WeatherRefreshGate.java",
|
||||
"weather/java/com/chaegeon/niro/WeatherRefreshCounters.java",
|
||||
"backend/php/NiroMqttKeepalive.php", "backend/php/NiroRawSnappy.php",
|
||||
"navigation/archived/v038/patch_nav_vehicle_speed_source.py",
|
||||
"tests/java/HscanRpmDecoderTest.java", "tests/java/WeatherRefreshGateTest.java",
|
||||
"tests/java/WeatherRefreshCountersTest.java", "tests/php/NiroMqttKeepaliveTest.php",
|
||||
"tests/php/NiroRawSnappyTest.php", "tests/python/test_archived_speed_patch.py",
|
||||
"tools/run_tests.py", "tools/check_publication.py",
|
||||
}
|
||||
PATTERNS = {
|
||||
"private-key material": re.compile(rb"-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----"),
|
||||
"GitHub credential candidate": re.compile(rb"\b(?:ghp_[A-Za-z0-9]{30,}|github_pat_[A-Za-z0-9_]{50,})\b"),
|
||||
"literal bearer candidate": re.compile(rb"Bearer [A-Za-z0-9_./+~-]{24,}"),
|
||||
"phone-number candidate": re.compile(rb"(?<![A-Za-z0-9])01[016789](?:[ -]?[0-9]){7,8}(?![A-Za-z0-9])"),
|
||||
"private operational hostname": re.compile(rb"niro-gen5w\.tail[0-9a-z]+\.ts\.net|car\.chaegeon\.com"),
|
||||
}
|
||||
|
||||
|
||||
def git(*arguments):
|
||||
# Use the executable, not a shell function or a machine-specific wrapper.
|
||||
return subprocess.run(
|
||||
["git", *arguments], cwd=ROOT, check=True, stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE, encoding="utf-8",
|
||||
).stdout
|
||||
|
||||
|
||||
def main():
|
||||
errors = []
|
||||
files = []
|
||||
for directory, directories, names in os.walk(ROOT, followlinks=False):
|
||||
base = Path(directory)
|
||||
for name in list(directories):
|
||||
target = base / name
|
||||
relative = target.relative_to(ROOT).as_posix()
|
||||
if relative == ".git":
|
||||
directories.remove(name)
|
||||
elif target.is_symlink():
|
||||
errors.append("symlink directory: " + relative)
|
||||
directories.remove(name)
|
||||
for name in names:
|
||||
path = base / name
|
||||
relative = path.relative_to(ROOT).as_posix()
|
||||
files.append(relative)
|
||||
if path.is_symlink() or relative not in ALLOWED:
|
||||
errors.append("file is not approved: " + relative)
|
||||
continue
|
||||
content = path.read_bytes()
|
||||
if len(content) > 128 * 1024 or b"\0" in content:
|
||||
errors.append("binary or unexpectedly large file: " + relative)
|
||||
continue
|
||||
try:
|
||||
content.decode("utf-8")
|
||||
except UnicodeDecodeError:
|
||||
errors.append("non-UTF-8 file: " + relative)
|
||||
for description, pattern in PATTERNS.items():
|
||||
if pattern.search(content):
|
||||
# Do not reveal a matched secret or personal value in output.
|
||||
errors.append(description + ": " + relative)
|
||||
if (ROOT / ".git").exists():
|
||||
for relative in git("ls-files").splitlines():
|
||||
if relative not in ALLOWED:
|
||||
errors.append("unapproved tracked file: " + relative)
|
||||
for email in set(git("log", "--all", "--format=%ae%n%ce").splitlines()):
|
||||
if email and not email.endswith("@users.noreply.git.chaegeon.com"):
|
||||
errors.append("commit author/committer email needs privacy review")
|
||||
if errors:
|
||||
raise SystemExit("Publication checks failed:\n" + "\n".join(sorted(set(errors))))
|
||||
print("PASS: publication allowlist and basic privacy checks (" + str(len(files)) + " files)")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,48 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Run public synthetic tests locally; never contact a vehicle or network."""
|
||||
|
||||
import os
|
||||
from pathlib import Path
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
|
||||
|
||||
def run(*command):
|
||||
environment = dict(os.environ, PYTHONDONTWRITEBYTECODE="1")
|
||||
print("+ " + " ".join(str(part) for part in command), flush=True)
|
||||
subprocess.run(command, cwd=ROOT, env=environment, check=True)
|
||||
|
||||
|
||||
def main():
|
||||
missing = [name for name in ("javac", "java", "php") if not shutil.which(name)]
|
||||
if missing:
|
||||
raise SystemExit("Required local tools are missing: " + ", ".join(missing))
|
||||
run(sys.executable, "tools/check_publication.py")
|
||||
run(sys.executable, "-B", "-m", "unittest", "discover", "-s", "tests/python", "-v")
|
||||
sources = sorted(
|
||||
list((ROOT / "telemetry/java").rglob("*.java"))
|
||||
+ list((ROOT / "weather/java").rglob("*.java"))
|
||||
+ list((ROOT / "tests/java").glob("*.java"))
|
||||
)
|
||||
with tempfile.TemporaryDirectory(prefix="niro-gen5w-public-tests-") as temporary:
|
||||
run("javac", "-encoding", "UTF-8", "-d", temporary, *map(str, sources))
|
||||
for name in (
|
||||
"com.chaegeon.niro.HscanRpmDecoderTest",
|
||||
"WeatherRefreshGateTest",
|
||||
"com.chaegeon.niro.WeatherRefreshCountersTest",
|
||||
):
|
||||
run("java", "-cp", temporary, name)
|
||||
for source in sorted((ROOT / "backend/php").glob("*.php")):
|
||||
run("php", "-l", str(source))
|
||||
for test in sorted((ROOT / "tests/php").glob("*Test.php")):
|
||||
run("php", str(test))
|
||||
print("PASS: all public synthetic test programs completed")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in new issue
Block a user