HyperPixel blank screen, provenance-keyed shell apps, store-scene key grants, service-user unpack + hosted signing, embedded editor origins - #456
Conversation
… grants, service-user unpack + hosted signing, embedded editor origins Five open items from docs/todo.md and docs/security-todo.md: - Vannituba (HyperPixel 2r on a Buildroot image) rendered nothing: the legacy framebuffer driver's setup built a Python venv for two backlight scripts, and a Buildroot image has no python3, so setup failed before the driver ran. The backlight (GPIO 19) is now driven in-process through lgpio; the vendor tree, the setup step and the identical turnOn/turnOff scripts are gone from the driver (the native inkyHyperPixel2r driver keeps its own). - The two process-spawning apps (chromiumScreenshot, rstpSnapshot) are refused for any scene carrying origin.storeSceneId, whichever control plane installed it (frameos/spawn_guard.nim), unless the local admin allowed "shell apps for store scenes" through the on-panel ceremony (same endpoint as the LAN elevation, scope "shellApps", stored beside it). Whatever the scene's origin, the URL handed to Chromium/ffmpeg must be http(s)/rtsp(s) with a host that passes the private-network policy when it is on. Scenes carry storeOrigin from the JSON's origin block onto the runtime scene. - Store scenes on a self-hosted frame no longer receive every service key they declare: get_frame_json ships a group declared only by store-origin scenes when the owner granted it (frame.service_setting_groups, migration e1f2a3b4c5d6, Frame settings → "Service keys for store scenes"). Owner- authored scenes keep declaration-as-grant. - frameos-cloud-update unpacks the CI-uploaded archive as the service user (runuser tar --no-same-owner --no-same-permissions into a directory that user owns) instead of as root. ESP32 firmware built on the self-hosted runner is no longer signed there: the GitHub-hosted github-release job signs every frameos-*.bin lacking a .minisig alongside the Linux archives and refuses to publish an unsigned asset. - The iframe-hosted embedded editor accepts messages only from its parent window and only from a declared origin (?parentOrigin= on the iframe URL, else the referrer origin), replies to that origin instead of '*', and honours previewProxyUrl only when same-origin (embedOrigins.ts); the frameos-editor host helper names its origin on the iframe URL. Preview worker isolation is deliberately not in this batch — the proxy rides the app's session cookie, which an opaque-origin worker cannot send; noted in docs/security-todo.md. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Un8Q6ih58FbBd7WoDQtZ24
…c release image hands it a Frame stand-in Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Un8Q6ih58FbBd7WoDQtZ24
ESP32 firmware sizeBuilt from d814272 by this run; compared with the latest release v2026.9.10.
Breakdown by subsystem —
|
| Subsystem | This PR | v2026.9.10 | Δ |
|---|---|---|---|
| FrameOS core (Nim) | 404,262 | 403,856 | +406 (+0.1%) |
| QuickJS | 356,328 | 356,328 | ±0 |
| FrameOS apps (Nim) | 317,919 | 317,923 | -4 (-0.0%) |
| pixie | 301,065 | 301,065 | ±0 |
| Wi-Fi stack | 295,300 | 295,300 | ±0 |
| Nim stdlib | 248,937 | 248,937 | ±0 |
| ESP-IDF misc | 178,045 | 178,045 | ±0 |
| Embedded font | 146,358 | 146,358 | ±0 |
| mbedTLS + certificates | 132,539 | 132,539 | ±0 |
| String pool (attributed to efuse) | 131,977 | 131,977 | ±0 |
| lwIP / HTTP / WebSocket | 126,594 | 126,594 | ±0 |
| libc / libm / newlib | 116,259 | 116,259 | ±0 |
| fos_* firmware shell (C) | 115,920 | 115,920 | ±0 |
| Storage (SPIFFS / FatFS / SD / NVS) | 94,136 | 94,136 | ±0 |
| Nim packages (chrono, zippy, chroma, qrgen, ...) | 72,031 | 72,031 | ±0 |
| Display drivers (C) | 63,416 | 63,416 | ±0 |
| Crypto (monocypher) | 35,149 | 35,149 | ±0 |
| Total mapped flash | 3,136,235 | 3,135,833 | +402 (+0.0%) |
Inside each subsystem
FrameOS core (Nim) — 404,262
| Part | This PR | v2026.9.10 | Δ |
|---|---|---|---|
frameos/js_runtime |
102,114 | 102,114 | ±0 |
frameos/interpreter.nim |
97,352 | 97,229 | +123 (+0.1%) |
frameos/utils |
89,574 | 89,574 | ±0 |
embedded_main.nim |
18,347 | 18,347 | ±0 |
lib/tz.nim |
16,875 | 16,875 | ±0 |
embedded_runtime.nim |
15,056 | 15,052 | +4 (+0.0%) |
frameos/planner.nim |
9,605 | 9,605 | ±0 |
frameos_nim_glue.c.obj |
9,569 | 9,569 | ±0 |
frameos/types.nim |
7,893 | 7,869 | +24 (+0.3%) |
frameos/values.nim |
6,901 | 6,901 | ±0 |
frameos/apps.nim |
6,046 | 6,046 | ±0 |
frameos/spool.nim |
5,678 | 5,678 | ±0 |
embedded_scene.nim |
4,945 | 4,945 | ±0 |
frameos/app_config.nim |
2,871 | 2,871 | ±0 |
frameos/reboot_reason.nim |
2,628 | 2,628 | ±0 |
frameos/node_config.nim |
2,590 | 2,590 | ±0 |
frameos/app_capabilities.nim |
2,493 | 2,493 | ±0 |
fos_netguard.c.obj |
2,092 | 2,092 | ±0 |
frameos/runtime_diagnostics.nim |
763 | 763 | ±0 |
fos_version.c.obj |
324 | 324 | ±0 |
frameos/cloud |
255 | — | +255 |
frameos/ids.nim |
133 | 133 | ±0 |
frameos/channels.nim |
118 | 118 | ±0 |
frameos/hal |
40 | 40 | ±0 |
QuickJS — 356,328
| Part | This PR | v2026.9.10 | Δ |
|---|---|---|---|
quickjs.c.obj |
283,813 | 283,813 | ±0 |
libunicode.c.obj |
50,174 | 50,174 | ±0 |
libregexp.c.obj |
13,995 | 13,995 | ±0 |
dtoa.c.obj |
5,681 | 5,681 | ±0 |
cutils.c.obj |
2,141 | 2,141 | ±0 |
fos_qjs_glue.c.obj |
449 | 449 | ±0 |
fos_quickjs_tz.c.obj |
75 | 75 | ±0 |
FrameOS apps (Nim) — 317,919
| Part | This PR | v2026.9.10 | Δ |
|---|---|---|---|
apps/data/icalJson |
50,265 | 50,265 | ±0 |
apps/render/calendar |
30,666 | 30,666 | ±0 |
apps/render/chart |
21,541 | 21,541 | ±0 |
apps/data/immich |
17,538 | 17,538 | ±0 |
apps/data/wikicommons |
17,114 | 17,114 | ±0 |
apps/data/openaiImage |
13,926 | 13,926 | ±0 |
apps/data/unsplash |
11,056 | 11,056 | ±0 |
apps/data/beRecycle |
10,749 | 10,749 | ±0 |
apps/data/weather |
10,210 | 10,210 | ±0 |
apps/render/split |
9,648 | 9,648 | ±0 |
apps/data/localImage |
9,190 | 9,190 | ±0 |
apps/data/eventsToAgenda |
9,088 | 9,092 | -4 (-0.0%) |
apps/data/googlePhotos |
9,068 | 9,072 | -4 (-0.0%) |
apps/apps.nim |
8,636 | 8,636 | ±0 |
apps/render/zoomPan |
8,552 | 8,552 | ±0 |
apps/data/openaiText |
7,353 | 7,353 | ±0 |
apps/data/haSensor |
7,291 | 7,291 | ±0 |
apps/data/xmlToJson |
5,420 | 5,420 | ±0 |
apps/render/text |
5,415 | 5,415 | ±0 |
apps/render/svg |
5,176 | 5,176 | ±0 |
apps/render/image |
4,510 | 4,510 | ±0 |
apps/data/rotateImage |
3,457 | 3,457 | ±0 |
apps/logic/setAsState |
3,441 | 3,441 | ±0 |
apps/data/downloadImage |
3,333 | 3,337 | -4 (-0.1%) |
apps/render/gradient |
3,173 | 3,173 | ±0 |
apps/data/qr |
3,114 | 3,114 | ±0 |
apps/data/downloadUrl |
3,065 | 3,065 | ±0 |
apps/data/frameOSGallery |
3,006 | 3,006 | ±0 |
apps/render/color |
2,804 | 2,804 | ±0 |
apps/data/newImage |
2,636 | 2,636 | ±0 |
apps/data/resizeImage |
2,534 | 2,534 | ±0 |
apps/data/log |
2,283 | 2,283 | ±0 |
apps/render/opacity |
2,272 | 2,272 | ±0 |
apps/data/prettyJson |
2,213 | 2,213 | ±0 |
apps/data/parseJson |
1,844 | 1,844 | ±0 |
apps/data/clock |
1,839 | 1,831 | +8 (+0.4%) |
apps/logic/nextSleepDuration |
1,639 | 1,639 | ±0 |
apps/logic/ifElse |
1,476 | 1,476 | ±0 |
apps/logic/breakIfRendering |
1,378 | 1,378 | ±0 |
pixie — 301,065
| Part | This PR | v2026.9.10 | Δ |
|---|---|---|---|
pixie/fontformats/opentype.nim |
55,507 | 55,507 | ±0 |
pixie/fileformats/webp.nim |
37,525 | 37,525 | ±0 |
pixie/fileformats/svg.nim |
37,203 | 37,203 | ±0 |
pixie/paths.nim |
32,570 | 32,570 | ±0 |
pixie/fileformats/jpeg.nim |
25,338 | 25,338 | ±0 |
pixie/fileformats/png.nim |
22,849 | 22,849 | ±0 |
pixie/images.nim |
15,787 | 15,787 | ±0 |
pixie/fonts.nim |
11,019 | 11,019 | ±0 |
pixie/paints.nim |
9,889 | 9,889 | ±0 |
pixie/fileformats/bmp.nim |
8,234 | 8,234 | ±0 |
pixie/common.nim |
7,416 | 7,416 | ±0 |
pixie/blends.nim |
6,540 | 6,540 | ±0 |
pixie/fileformats/gif.nim |
5,929 | 5,929 | ±0 |
pixie/inflatestream.nim |
5,325 | 5,325 | ±0 |
pixie.nim |
5,248 | 5,248 | ±0 |
pixie/fileformats/webp_vp8_tables.nim |
3,881 | 3,881 | ±0 |
pixie/fileformats/ppm.nim |
3,681 | 3,681 | ±0 |
pixie/contexts.nim |
3,038 | 3,038 | ±0 |
pixie/fileformats/qoi.nim |
2,686 | 2,686 | ±0 |
pixie/internal.nim |
754 | 754 | ±0 |
pixie/rgb565.nim |
381 | 381 | ±0 |
pixie/fontformats/svgfont.nim |
215 | 215 | ±0 |
pixie/decodebudget.nim |
50 | 50 | ±0 |
Wi-Fi stack — 295,300
| Part | This PR | v2026.9.10 | Δ |
|---|---|---|---|
libnet80211.a |
136,168 | 136,168 | ±0 |
libpp.a |
62,146 | 62,146 | ±0 |
libwpa_supplicant.a |
54,900 | 54,900 | ±0 |
libphy.a |
34,176 | 34,176 | ±0 |
libesp_wifi.a |
4,788 | 4,788 | ±0 |
libesp_phy.a |
2,541 | 2,541 | ±0 |
libesp_coex.a |
291 | 291 | ±0 |
libcore.a |
287 | 287 | ±0 |
libespnow.a |
3 | 3 | ±0 |
Nim stdlib — 248,937
| Part | This PR | v2026.9.10 | Δ |
|---|---|---|---|
pure/collections/tables.nim |
70,556 | 70,556 | ±0 |
system.nim |
46,665 | 46,665 | ±0 |
pure/unicode.nim |
17,405 | 17,405 | ±0 |
pure/times.nim |
16,984 | 16,984 | ±0 |
pure/json.nim |
13,414 | 13,414 | ±0 |
std/private/dragonbox.nim |
10,351 | 10,351 | ±0 |
pure/strutils.nim |
8,473 | 8,473 | ±0 |
pure/parsexml.nim |
5,975 | 5,975 | ±0 |
pure/algorithm.nim |
5,368 | 5,368 | ±0 |
pure/base64.nim |
5,302 | 5,302 | ±0 |
pure/hashes.nim |
4,114 | 4,114 | ±0 |
pure/xmlparser.nim |
3,567 | 3,567 | ±0 |
pure/parsejson.nim |
3,553 | 3,553 | ±0 |
std/formatfloat.nim |
3,508 | 3,508 | ±0 |
pure/uri.nim |
3,225 | 3,225 | ±0 |
pure/collections/sets.nim |
3,211 | 3,211 | ±0 |
pure/streams.nim |
2,820 | 2,820 | ±0 |
pure/strformat.nim |
2,641 | 2,641 | ±0 |
std/syncio.nim |
2,355 | 2,355 | ±0 |
pure/xmltree.nim |
2,051 | 2,051 | ±0 |
pure/lexbase.nim |
1,805 | 1,805 | ±0 |
pure/parseutils.nim |
1,757 | 1,757 | ±0 |
system/exceptions.nim |
1,598 | 1,598 | ±0 |
pure/strtabs.nim |
1,568 | 1,568 | ±0 |
pure/pathnorm.nim |
1,332 | 1,332 | ±0 |
pure/options.nim |
1,118 | 1,118 | ±0 |
std/private/ospaths2.nim |
1,032 | 1,032 | ±0 |
pure/collections/lists.nim |
983 | 983 | ±0 |
system/dollars.nim |
891 | 891 | ±0 |
pure/random.nim |
835 | 835 | ±0 |
std/private/digitsutils.nim |
651 | 651 | ±0 |
pure/math.nim |
650 | 650 | ±0 |
std/oserrors.nim |
637 | 637 | ±0 |
std/private/osdirs.nim |
580 | 580 | ±0 |
std/monotimes.nim |
401 | 401 | ±0 |
std/private/oscommon.nim |
329 | 329 | ±0 |
std/envvars.nim |
250 | 250 | ±0 |
std/private/decode_helpers.nim |
240 | 240 | ±0 |
std/private/ossymlinks.nim |
187 | 187 | ±0 |
pure/bitops.nim |
162 | 162 | ±0 |
pure/os.nim |
99 | 99 | ±0 |
std/private/osfiles.nim |
96 | 96 | ±0 |
std/assertions.nim |
87 | 87 | ±0 |
core/macros.nim |
69 | 69 | ±0 |
system/iterators.nim |
33 | 33 | ±0 |
system/ctypes.nim |
9 | 9 | ±0 |
ESP-IDF misc — 178,045
| Part | This PR | v2026.9.10 | Δ |
|---|---|---|---|
libesp_hw_support.a |
37,650 | 37,650 | ±0 |
libhal.a |
21,464 | 21,464 | ±0 |
libfreertos.a |
17,194 | 17,194 | ±0 |
libesp_system.a |
13,780 | 13,780 | ±0 |
libesp_driver_uart.a |
11,627 | 11,627 | ±0 |
libheap.a |
8,656 | 8,656 | ±0 |
libesp_driver_i2c.a |
8,062 | 8,062 | ±0 |
libesp_driver_spi.a |
7,756 | 7,756 | ±0 |
libconsole.a |
5,733 | 5,733 | ±0 |
libjson.a |
4,940 | 4,940 | ±0 |
libesp_driver_gpio.a |
3,890 | 3,890 | ±0 |
libbootloader_support.a |
3,813 | 3,813 | ±0 |
libxtensa.a |
3,691 | 3,691 | ±0 |
libesp_driver_usb_serial_jtag.a |
3,408 | 3,408 | ±0 |
libesp_ringbuf.a |
3,322 | 3,322 | ±0 |
libesp_event.a |
3,241 | 3,241 | ±0 |
libesp_mm.a |
2,451 | 2,451 | ±0 |
libapp_update.a |
2,422 | 2,422 | ±0 |
libesp_psram.a |
2,329 | 2,329 | ±0 |
libesp_timer.a |
2,326 | 2,326 | ±0 |
libsoc.a |
2,315 | 2,315 | ±0 |
libesp_adc.a |
2,289 | 2,289 | ±0 |
liblog.a |
1,375 | 1,375 | ±0 |
libpthread.a |
1,365 | 1,365 | ±0 |
libesp_security.a |
1,050 | 1,050 | ±0 |
libesp_rom.a |
902 | 902 | ±0 |
libesp_app_format.a |
507 | 507 | ±0 |
libxt_hal.a |
437 | 437 | ±0 |
libesp_common.a |
26 | 26 | ±0 |
libesp_pm.a |
24 | 24 | ±0 |
Embedded font — 146,358
| Part | This PR | v2026.9.10 | Δ |
|---|---|---|---|
assets/fonts.nim |
146,358 | 146,358 | ±0 |
mbedTLS + certificates — 132,539
| Part | This PR | v2026.9.10 | Δ |
|---|---|---|---|
libmbedcrypto.a |
71,391 | 71,391 | ±0 |
libmbedtls.a |
45,803 | 45,803 | ±0 |
libmbedx509.a |
7,084 | 7,084 | ±0 |
libesp-tls.a |
6,709 | 6,709 | ±0 |
libesp_https_server.a |
1,552 | 1,552 | ±0 |
String pool (attributed to efuse) — 131,977
| Part | This PR | v2026.9.10 | Δ |
|---|---|---|---|
esp_efuse_utility.c.obj |
130,931 | 130,931 | ±0 |
esp_efuse_rtc_calib.c.obj |
566 | 566 | ±0 |
esp_efuse_table.c.obj |
268 | 268 | ±0 |
esp_efuse_api.c.obj |
151 | 151 | ±0 |
esp_efuse_startup.c.obj |
61 | 61 | ±0 |
lwIP / HTTP / WebSocket — 126,594
| Part | This PR | v2026.9.10 | Δ |
|---|---|---|---|
liblwip.a |
78,301 | 78,301 | ±0 |
libhttp_parser.a |
10,350 | 10,350 | ±0 |
libesp_http_server.a |
10,016 | 10,016 | ±0 |
libtcp_transport.a |
8,237 | 8,237 | ±0 |
libespressif__esp_websocket_client.a |
6,826 | 6,826 | ±0 |
libesp_http_client.a |
6,620 | 6,620 | ±0 |
libesp_netif.a |
6,244 | 6,244 | ±0 |
libc / libm / newlib — 116,259
| Part | This PR | v2026.9.10 | Δ |
|---|---|---|---|
libc.a |
76,467 | 76,467 | ±0 |
libm.a |
31,563 | 31,563 | ±0 |
libnewlib.a |
6,609 | 6,609 | ±0 |
libstdc++.a |
1,476 | 1,476 | ±0 |
libgcc.a |
98 | 98 | ±0 |
libcxx.a |
46 | 46 | ±0 |
fos_ firmware shell (C)* — 115,920
| Part | This PR | v2026.9.10 | Δ |
|---|---|---|---|
fos_http.c.obj |
21,968 | 21,968 | ±0 |
fos_cloud.c.obj |
17,837 | 17,837 | ±0 |
fos_console.c.obj |
13,498 | 13,498 | ±0 |
fos_client.c.obj |
10,483 | 10,483 | ±0 |
fos_scenes.c.obj |
7,459 | 7,459 | ±0 |
fos_settings.c.obj |
6,511 | 6,511 | ±0 |
fos_ota.c.obj |
5,775 | 5,775 | ±0 |
fos_config.c.obj |
5,755 | 5,755 | ±0 |
fos_assets.c.obj |
3,282 | 3,282 | ±0 |
fos_wifi.c.obj |
3,201 | 3,201 | ±0 |
fos_cloud_contract.c.obj |
2,896 | 2,896 | ±0 |
fos_sd_probe.c.obj |
2,753 | 2,753 | ±0 |
fos_assets_sd.c.obj |
2,480 | 2,480 | ±0 |
fos_schedule.c.obj |
2,339 | 2,339 | ±0 |
fos_buttons.c.obj |
2,139 | 2,139 | ±0 |
fos_status_screen.c.obj |
2,049 | 2,049 | ±0 |
main.c.obj |
1,673 | 1,673 | ±0 |
fos_tz.c.obj |
1,381 | 1,381 | ±0 |
fos_battery.c.obj |
1,140 | 1,140 | ±0 |
fos_framebuffer.c.obj |
483 | 483 | ±0 |
fos_power.c.obj |
241 | 241 | ±0 |
fos_battery_filter.c.obj |
214 | 214 | ±0 |
fos_wake.c.obj |
184 | 184 | ±0 |
fos_board.c.obj |
179 | 179 | ±0 |
Storage (SPIFFS / FatFS / SD / NVS) — 94,136
| Part | This PR | v2026.9.10 | Δ |
|---|---|---|---|
libspiffs.a |
20,380 | 20,380 | ±0 |
libfatfs.a |
20,133 | 20,133 | ±0 |
libspi_flash.a |
14,168 | 14,168 | ±0 |
libnvs_flash.a |
13,745 | 13,745 | ±0 |
libsdmmc.a |
13,013 | 13,013 | ±0 |
libvfs.a |
6,196 | 6,196 | ±0 |
libesp_driver_sdspi.a |
3,858 | 3,858 | ±0 |
libesp_partition.a |
1,960 | 1,960 | ±0 |
libesp_vfs_console.a |
678 | 678 | ±0 |
libnvs_sec_provider.a |
5 | 5 | ±0 |
Nim packages (chrono, zippy, chroma, qrgen, ...) — 72,031
| Part | This PR | v2026.9.10 | Δ |
|---|---|---|---|
QRgen 3.1.0 |
22,036 | 22,036 | ±0 |
chrono 0.3.1 |
15,514 | 15,514 | ±0 |
zippy 0.10.19 |
15,272 | 15,272 | ±0 |
chroma 1.0.0 |
14,916 | 14,916 | ±0 |
checksums 0.2.1 |
3,371 | 3,371 | ±0 |
flatty 0.3.4 |
533 | 533 | ±0 |
jsony 1.1.5 |
272 | 272 | ±0 |
bumpy 1.1.3 |
117 | 117 | ±0 |
Display drivers (C) — 63,416
| Part | This PR | v2026.9.10 | Δ |
|---|---|---|---|
(everything else) |
20,623 | 20,623 | ±0 |
frameos_panel_table.c.obj |
6,685 | 6,685 | ±0 |
EPD_13in3e.c.obj |
1,796 | 1,796 | ±0 |
EPD_3in7.c.obj |
1,508 | 1,508 | ±0 |
EPD_5in79.c.obj |
1,445 | 1,445 | ±0 |
EPD_2in7.c.obj |
1,259 | 1,259 | ±0 |
EPD_4in2.c.obj |
1,246 | 1,246 | ±0 |
EPD_7in3e.c.obj |
1,208 | 1,208 | ±0 |
DEV_Config_esp.c.obj |
1,180 | 1,180 | ±0 |
EPD_4in2_V2.c.obj |
1,172 | 1,172 | ±0 |
DEV_Debug.c.obj |
1,159 | 1,159 | ±0 |
EPD_4in26.c.obj |
1,110 | 1,110 | ±0 |
| 29 smaller rows | 23,025 | 23,025 | ±0 |
Crypto (monocypher) — 35,149
| Part | This PR | v2026.9.10 | Δ |
|---|---|---|---|
monocypher.c.obj |
31,920 | 31,920 | ±0 |
monocypher-ed25519.c.obj |
3,229 | 3,229 | ±0 |
Biggest movers (per object)
| Object | Δ | This PR | Baseline |
|---|---|---|---|
frameos/interpreter.nim |
+123 | 97,352 | 97,229 |
frameos/types.nim |
+24 | 7,893 | 7,869 |
embedded_runtime.nim |
+4 | 15,056 | 15,052 |
apps/data/googlePhotos/app.nim |
-4 | 7,477 | 7,481 |
apps/data/eventsToAgenda/app.nim |
-4 | 7,130 | 7,134 |
Largest 30 objects
| Object | Subsystem | This PR | v2026.9.10 | Δ |
|---|---|---|---|---|
quickjs.c.obj |
QuickJS | 283,813 | 283,813 | ±0 |
assets/fonts.nim |
Embedded font | 146,358 | 146,358 | ±0 |
esp_efuse_utility.c.obj |
String pool (attributed to efuse) | 130,931 | 130,931 | ±0 |
frameos/interpreter.nim |
FrameOS core (Nim) | 97,352 | 97,229 | +123 (+0.1%) |
nim/lib/pure/collections/tables.nim |
Nim stdlib | 70,556 | 70,556 | ±0 |
frameos/js_runtime/app_runtime.nim |
FrameOS core (Nim) | 61,502 | 61,502 | ±0 |
pkgs/pixie-6.1.0/pixie/fontformats/opentype.nim |
pixie | 55,507 | 55,507 | ±0 |
libunicode.c.obj |
QuickJS | 50,174 | 50,174 | ±0 |
nim/lib/system.nim |
Nim stdlib | 46,665 | 46,665 | ±0 |
apps/data/icalJson/ical.nim |
FrameOS apps (Nim) | 44,568 | 44,568 | ±0 |
pkgs/pixie-6.1.0/pixie/fileformats/webp.nim |
pixie | 37,525 | 37,525 | ±0 |
pkgs/pixie-6.1.0/pixie/fileformats/svg.nim |
pixie | 37,203 | 37,203 | ±0 |
frameos/utils/image.nim |
FrameOS core (Nim) | 34,374 | 34,374 | ±0 |
pkgs/pixie-6.1.0/pixie/paths.nim |
pixie | 32,570 | 32,570 | ±0 |
monocypher.c.obj |
Crypto (monocypher) | 31,920 | 31,920 | ±0 |
frameos/js_runtime/runtime.nim |
FrameOS core (Nim) | 30,094 | 30,094 | ±0 |
pkgs/pixie-6.1.0/pixie/fileformats/jpeg.nim |
pixie | 25,338 | 25,338 | ±0 |
apps/render/calendar/app.nim |
FrameOS apps (Nim) | 23,618 | 23,618 | ±0 |
pkgs/pixie-6.1.0/pixie/fileformats/png.nim |
pixie | 22,849 | 22,849 | ±0 |
fos_http.c.obj |
fos_* firmware shell (C) | 21,968 | 21,968 | ±0 |
apps/render/chart/app.nim |
FrameOS apps (Nim) | 18,940 | 18,940 | ±0 |
embedded_main.nim |
FrameOS core (Nim) | 18,347 | 18,347 | ±0 |
x509_crt_bundle.S.obj |
mbedTLS + certificates | 17,928 | 17,928 | ±0 |
frameos/utils/status_screen.nim |
FrameOS core (Nim) | 17,923 | 17,923 | ±0 |
fos_cloud.c.obj |
fos_* firmware shell (C) | 17,837 | 17,837 | ±0 |
nim/lib/pure/unicode.nim |
Nim stdlib | 17,405 | 17,405 | ±0 |
nim/lib/pure/times.nim |
Nim stdlib | 16,984 | 16,984 | ±0 |
lib/tz.nim |
FrameOS core (Nim) | 16,875 | 16,875 | ±0 |
apps/data/immich/app.nim |
FrameOS apps (Nim) | 15,991 | 15,991 | ±0 |
pkgs/pixie-6.1.0/pixie/images.nim |
pixie | 15,787 | 15,787 | ±0 |
Flash = .text + .rodata from the linker map via esp_idf_size; "Inside each subsystem" splits every bucket one level down (the Nim core by directory, apps by app, packages by package, ESP-IDF by archive) over all objects, not just the largest. "String pool (attributed to efuse)" is the linker's merged string-literal pool for the whole image, not efuse code — see docs/esp32-image-size.md.
Five items from the todo files, in one branch (one commit-message section each):
chromiumScreenshot/rstpSnapshotrefused for store-origin scenes however they arrived, unless the local admin allows it via the on-panel ceremony (POST /api/network/local-access,scope: "shellApps"); their target URL must be http(s)/rtsp(s) with a host that passes the LAN policy when on.frame.service_setting_groups, migration, new settings section). Owner-authored scenes unchanged.frameos-cloud-updateunpacks as the service user, not root; ESP32 images from the self-hosted runner are signed in the GitHub-hosted release job (which now refuses any unsigned asset).previewProxyUrl; host helper passes?parentOrigin=.Not done here, deliberately: preview-worker origin isolation — the proxy relies on the app's session cookie, which an opaque-origin worker cannot send; the proxy needs a per-preview token first (recorded in
docs/security-todo.md).Verified: Nim suites (spawn guard, local access, both apps, scenes, interpreter errors, hub verbs, driver),
nim checkof the runtime, backend suites (frame model incl. new grant tests, drivers, release drivers, deploy workflow, frames API: 221), frontendtsc, auth-web lint/typecheck/build, the embedded-editor and frame-settings shared-SPA suites, theframeos-editorhelper test, shell and YAML syntax of the ops script and workflow, single alembic head.Not verified on hardware: the HyperPixel backlight toggle on a real Pi (the test drives the hook).
🤖 Generated with Claude Code
https://claude.ai/code/session_01Un8Q6ih58FbBd7WoDQtZ24