Skip to content

stdio, keyboard, compact UI, package manifest, and more - #667

Open
KenVanHoeylandt wants to merge 3 commits into
mainfrom
develop
Open

KenVanHoeylandt wants to merge 3 commits into
mainfrom
develop

Conversation

@KenVanHoeylandt

@KenVanHoeylandt KenVanHoeylandt commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • New Features

    • App listings now filter out packages incompatible with the device’s platform, device ID, or available memory.
    • Packages can specify minimum RAM requirements.
    • Terminal emulation supports scroll regions, line insertion and deletion within those regions, and improved cursor positioning.
  • Bug Fixes

    • Enter keys consistently produce newlines across supported keyboards; the T-Lora Pager symbol layout also has updated key mappings.
    • App terminal input handles carriage returns as newlines, and terminal I/O and signal operations behave more consistently.
    • Improved app loading and memory handling on ESP devices.
  • Style

    • Adjusted compact UI spacing, including the T-Lora Pager layout and power-off buttons.

@coderabbitai

coderabbitai Bot commented Sep 30, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

📝 Walkthrough

Walkthrough

The changes add app-aware libc adapters and platform wrappers, package compatibility checks based on device and RAM requirements, and ESP ELF loader wrappers. They also implement terminal scroll regions, change Enter mappings to line feed, update T-Lora Pager configuration, and adjust selected UI layouts.

Priority: ➖ Normal

Merge Risk: 🔵 Low · up to cd1e5

Out-of-range App Hub RAM metadata can reach an undefined numeric conversion before validation. Add the localized bounds check; the established merge risk is otherwise low.

Security Architecture Review

Security architecture risk: 🔵 Low · up to cd1e5

The inspected application-call paths preserve important descriptor and signal controls. No material security regression was established, but native-call fallback and concurrent teardown remain incompletely resolved, so the changes should not be treated as risk-free.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — The inspected security-relevant scope is application-instance state and native libc authority within the POSIX host and ESP runtime. App-supplied descriptor numbers and signal arguments reach shared dispatch; a routing mistake could address a native descriptor with the same number or process-wide signal state. No tenant-wide, remote-service, IAM, or secret-authority expansion was established by this inspection.

Security Findings and Attack Paths

  • observed — A bound app stream with no window size returns an unsupported result, causing the shared window-size handler to report unhandled and the platform wrapper to invoke real ioctl with the same descriptor number. This is a concrete fallback path, not a verified vulnerability: the selected request queries window size, native interoperability is supported, and a material security impact or PR-induced exposure increase was not established.

Trust Boundaries and Controls

  • observed — Descriptor provenance retains previously used slots so closed app descriptors cannot ordinarily fall through to matching native descriptor numbers. App signal state is ledger-owned and mutex-protected. App identity is task-local on ESP and thread-local on POSIX; these controls depend on executing with a valid current-instance identity.

Resilience and Maintainability Implications

  • observed — Stream operations retain active-use accounting, and unsubscribe drains operations before destroying stream synchronization state. These mechanisms support failure containment around close and cleanup. Identity is cleared before runtime unload, however, and the inspected POSIX unload invokes dlclose; app-controlled unload callbacks and independent tasks were not fully traced through that transition.

Hardening Proposals

  • proposed — Consider distinguishing unsupported app-owned operations from genuine native-descriptor fallback, with explicit tests for unset window-size providers and descriptor-number collisions. Document and validate whether app-created tasks and unload callbacks may invoke libc after app identity is cleared. These are hardening proposals, not established PR regressions.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.18% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 109 functions across 48 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title identifies several major changes, including stdio, keyboard behavior, compact UI, and package manifests. It is broad but remains related to the changeset.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Autopilot is currently an internal CodeRabbit preview.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 3


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: 6f53bc68-097f-4166-bfa0-27b0776d3984

📥 Commits

Reviewing files that changed from the base of the PR and between 25bcb20 and d467e67.

📒 Files selected for processing (69)
  • Buildscripts/TactilitySDK/TactilitySDK.esp32.cmake
  • Buildscripts/TactilitySDK/TactilitySDK.posix.cmake
  • CMakeLists.txt
  • Devices/cl32/source/cl32_v2_keyboard.cpp
  • Devices/lilygo-tdeck-max/lilygo,tdeck-max.dts
  • Devices/lilygo-tdeck-pro/lilygo,tdeck-pro.dts
  • Devices/lilygo-tlora-pager/CMakeLists.txt
  • Devices/lilygo-tlora-pager/device.properties
  • Devices/lilygo-tlora-pager/lilygo,tlora-pager.dts
  • Devices/lilygo-tlora-pager/module.yaml
  • Devices/lilygo-tlora-pager/source/module.cpp
  • Documentation/ideas.md
  • Drivers/m5stack-module/source/cardputer_keyboard.cpp
  • Modules/app-esp32-module/CMakeLists.txt
  • Modules/app-esp32-module/source/app_esp32_loader_service.cpp
  • Modules/app-esp32-module/source/elf_cache.cpp
  • Modules/app-esp32-module/source/elf_relocate.cpp
  • Modules/app-esp32-module/source/stdio_wrap.cpp
  • Modules/app-module/CMakeLists.txt
  • Modules/app-module/include/app/dir.h
  • Modules/app-module/include/app/file.h
  • Modules/app-module/include/app/io.h
  • Modules/app-module/include/app/libc.h
  • Modules/app-module/include/app/package_manifest.h
  • Modules/app-module/include/poll.h
  • Modules/app-module/include/sys/ioctl.h
  • Modules/app-module/private/app/private/fd_table.h
  • Modules/app-module/private/app/private/ledger.h
  • Modules/app-module/private/app/private/stdio_wrap.h
  • Modules/app-module/source/fd_table.cpp
  • Modules/app-module/source/io.cpp
  • Modules/app-module/source/libc.cpp
  • Modules/app-module/source/module.cpp
  • Modules/app-module/source/package_compatibility.cpp
  • Modules/app-module/source/package_manifest_parsing_v3.cpp
  • Modules/app-module/source/scheduler.cpp
  • Modules/app-module/source/stdio_wrap.cpp
  • Modules/app-module/source/stream.cpp
  • Modules/app-module/tests/CMakeLists.txt
  • Modules/app-module/tests/source/execute_test.cpp
  • Modules/app-module/tests/source/io_test.cpp
  • Modules/app-module/tests/source/package_manifest_test.cpp
  • Modules/app-posix-module/CMakeLists.txt
  • Modules/app-posix-module/private/app_posix/stdio_wrap.h
  • Modules/app-posix-module/source/stdio_wrap.cpp
  • Modules/app-posix-module/source/stdio_wrap_apple.cpp
  • Modules/app-posix-module/source/stdio_wrap_elf.cpp
  • Modules/app-posix-module/tests/CMakeLists.txt
  • Modules/app-posix-module/tests/source/libc_test.cpp
  • Modules/c-symbols-module/source/module.cpp
  • Modules/posix-symbols-module/source/module.cpp
  • Tactility/Private/Tactility/app/apphub/AppHubEntry.h
  • Tactility/Source/app/apphub/AppHubApp.cpp
  • Tactility/Source/app/apphub/AppHubEntry.cpp
  • Tactility/Source/app/applist/AppList.cpp
  • Tactility/Source/app/apppackagelist/AppPackageList.cpp
  • Tactility/Source/app/fileselection/FileSelection.cpp
  • Tactility/Source/app/inputdialog/InputDialog.cpp
  • Tactility/Source/app/poweroff/PowerOff.cpp
  • Tactility/Source/app/shell/LineEditor.cpp
  • Tactility/Source/app/terminal/vterm/vterm.c
  • Tactility/Source/lvgl/wrappers/obj.cpp
  • Tactility/Tests/Source/AppHubEntryTest.cpp
  • Tactility/Tests/Source/VtermTest.cpp
  • TactilityKernel/include/tactility/drivers/keyboard.h
  • TactilityKernel/include/tactility/memory.h
  • TactilityKernel/source/drivers/keyboard.cpp
  • TactilityKernel/source/memory.cpp
  • TactilityKernel/source/symbols.c
💤 Files with no reviewable changes (8)
  • Modules/app-module/tests/source/execute_test.cpp
  • Devices/lilygo-tlora-pager/CMakeLists.txt
  • Devices/lilygo-tlora-pager/source/module.cpp
  • Modules/app-module/include/app/file.h
  • Modules/app-module/include/app/io.h
  • Modules/app-module/source/stdio_wrap.cpp
  • Modules/app-module/private/app/private/stdio_wrap.h
  • Modules/app-module/tests/source/io_test.cpp

Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 3 remain after this review.

Comment thread Tactility/Source/app/apphub/AppHubEntry.cpp
Comment thread Tactility/Source/app/terminal/vterm/vterm.c Outdated
Comment thread Tactility/Source/app/terminal/vterm/vterm.c Outdated

@coderabbitai coderabbitai Bot 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.

Caution

Some comments are outside the diff and can’t be posted inline due to GitHub limitations.

⚠️ Outside diff range comments (3)

🟡 Minor · Handle closed app descriptors before the real ioctl() fallback. · libc.cpp:51-64

Modules/app-module/source/libc.cpp:51-64
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Handle closed app descriptors before the real ioctl() fallback.

app_io_ioctl() returns ERROR_NOT_FOUND for a closed descriptor, so app_libc_try_window_size() returns false. Both platform wrappers then call the real ioctl(). A reused real descriptor can produce a window size instead of the required EBADF.

Use get_app_fd_state() in the shared adapter. Returning true for the closed state prevents the fallback in both wrappers.

Suggested fix
-    if (request != TIOCGWINSZ || arg == nullptr) {
+    if (request != TIOCGWINSZ) {
         return false;
     }
+    const AppFdState state = get_app_fd_state(fd);
+    if (state == AppFdState::Closed) {
+        errno = EBADF;
+        return true;
+    }
+    if (arg == nullptr || state == AppFdState::NotAppFd) {
+        return false;
+    }
     AppWindowSize size {};
🟡 Minor · Route ESP32 kill() through the app-scoped helper. · stdio_wrap.cpp:112-120

Modules/app-esp32-module/source/stdio_wrap.cpp:112-120
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Route ESP32 kill() through the app-scoped helper.

kill() is exported to apps, but the ESP32 boundary defines no kill() wrapper and the linker adds no --wrap=kill option. An app call can therefore reach the platform kill() symbol without calling app_libc_try_kill(). This violates the app contract, which requires -1 with errno == ENOSYS.

Suggested fix
 #include <signal.h>
+#include <sys/types.h>
 #include <sys/poll.h>
 #include <sys/stat.h>
 #include <termios.h>
@@
 _sig_func_ptr signal(int sig, _sig_func_ptr handler) {
     AppLibcSignalHandler previous;
     if (app_libc_try_signal(sig, handler, &previous)) {
         return previous;
     }
     errno = ENOSYS;
     return SIG_ERR;
 }
 
+int kill(pid_t pid, int sig) {
+    int result;
+    if (app_libc_try_kill(static_cast<int>(pid), sig, &result)) {
+        return result;
+    }
+    errno = ENOSYS;
+    return -1;
+}
+
 // Called by an app, newlib's exit() would reach _exit(), which aborts the whole device
🟡 Minor · Reject fractional requiresRam values before integer conversion. · AppHubEntry.cpp:104-109

Tactility/Source/app/apphub/AppHubEntry.cpp:104-109
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Reject fractional requiresRam values before integer conversion.

AppHubEntry::requiresRam is an integer megabyte count. readInt32 currently accepts any JSON number and truncates it before isCompatible validates the range. Therefore, 1.5 becomes 1 and can pass compatibility on a device with less than 1.5 MiB available. -0.5 becomes 0, bypasses the negative-value check, and is accepted as no RAM requirement.

Reject non-integral values in readInt32. parseEntry already rejects the entry when this reader returns false.

Suggested fix
 #include <cJSON.h>
+#include <cmath>
 #include <string>
 #include <vector>
@@
-        output = static_cast<int32_t>(buffer);
+        if (buffer != std::trunc(buffer)) {
+            LOG_E(TAG, "%s is not an integer", key);
+            return false;
+        }
+        output = static_cast<int32_t>(buffer);

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: dd0d4a9f-b8af-49c1-a960-add4a84b3d59

📥 Commits

Reviewing files that changed from the base of the PR and between d467e67 and 2239938.

📒 Files selected for processing (4)
  • Tactility/Source/app/apphub/AppHubEntry.cpp
  • Tactility/Source/app/terminal/vterm/vterm.c
  • Tactility/Tests/Source/AppHubEntryTest.cpp
  • Tactility/Tests/Source/VtermTest.cpp
🚧 Files skipped from review as they are similar to previous changes (3)
  • Tactility/Tests/Source/AppHubEntryTest.cpp
  • Tactility/Tests/Source/VtermTest.cpp
  • Tactility/Source/app/apphub/AppHubEntry.cpp

Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 2 remain after this review.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: f4a119a4-a504-449a-9ab3-9f93a3c149a1

📥 Commits

Reviewing files that changed from the base of the PR and between 2239938 and cd1e53c.

📒 Files selected for processing (7)
  • Modules/app-esp32-module/source/stdio_wrap.cpp
  • Modules/app-module/include/app/libc.h
  • Modules/app-module/source/libc.cpp
  • Modules/app-posix-module/source/stdio_wrap.cpp
  • Modules/app-posix-module/tests/source/libc_test.cpp
  • Tactility/Private/Tactility/json/Reader.h
  • Tactility/Tests/Source/AppHubEntryTest.cpp

Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 2 remain after this review.

Comment thread Tactility/Private/Tactility/json/Reader.h
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.

1 participant