changeset 248:b8b6e726964a

[style] Use Dowa type aliases in C Co-authored-by: Copilot <[email protected]>
author MrJuneJune <me@mrjunejune.com>
date Tue, 04 Aug 2026 02:44:06 -0700
parents 70f2a3dafc1c
children c5129452493e
files .claude/skills/zenbu-bazel-c/SKILL.md .claude/skills/zenbu-hg-web/SKILL.md .claude/skills/zenbu-personal-site/SKILL.md .claude/skills/zenbu-seobeo-networking/SKILL.md mrjunejune/BUILD mrjunejune/latex_renderer.c mrjunejune/latex_renderer.h mrjunejune/main.c mrjunejune/test/latex_renderer_test.c
diffstat 9 files changed, 383 insertions(+), 63 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.claude/skills/zenbu-bazel-c/SKILL.md	Tue Aug 04 02:44:06 2026 -0700
@@ -0,0 +1,75 @@
+---
+name: zenbu-bazel-c
+description: Use this skill when working anywhere in the Zenbu monorepo, especially C/C++ libraries, Bazel targets, Mercurial workflow, shared assets, or cross-project dependencies.
+---
+
+# Zenbu Bazel/C Monorepo
+
+Use this skill to orient yourself before changing first-party code in this workspace.
+
+## What this repo is
+
+Zenbu is a Mercurial/Bazel monorepo for reusable C libraries, web servers, frontend bundles, and experiments. Prefer first-party libraries over adding new external dependencies.
+
+Important first-party packages:
+
+- `dowa`: core C utilities, arena allocation, strings, math, dynamic arrays/hash maps.
+- `seobeo`: HTTP/TCP/WebSocket/networking library.
+- `mrjunejune`: personal website and production server.
+- `hg-web`: Mercurial repository browser served by a C backend.
+- `markdown_converter`: markdown-to-HTML C/WASM converter.
+- `deita`: SQLite wrapper library.
+- `s3`: S3 presigned upload helper.
+- `gui_ze`: Bazel macros for bundling/copying web assets.
+
+Avoid broad searches in `third_party/`, Bazel output directories, virtualenvs, `node_modules`, and generated bundles unless the task specifically requires them.
+
+## Build and test commands
+
+Use Bazel targets from the repository root:
+
+```bash
+bazel build //seobeo:seobeo
+bazel test //seobeo:seobeo_client_test
+bazel test //seobeo:seobeo_websocket_test
+bazel test //seobeo:seobeo_websocket_server_test
+
+bazel build //mrjunejune:mrjunejune_server
+bazel test //mrjunejune/test:integration_test
+
+bazel build //hg-web:hg_web_server
+```
+
+For debug builds, prefer existing debug targets where present:
+
+```bash
+bazel build //mrjunejune:mrjunejune_server_debug -c dbg
+bazel build //seobeo:seobeo_debug -c dbg
+```
+
+If a change only touches docs or assistant skill files, Bazel verification is not required.
+
+## Coding conventions to preserve
+
+- Prefer Dowa's integer and boolean aliases (`uint8`, `uint16`, `uint32`,
+  `uint64`, `int8`, `int16`, `int32`, `int64`, and `boolean`) plus
+  `TRUE`/`FALSE` in first-party C. Do not introduce `<stdint.h>` `_t` aliases
+  or `<stdbool.h>` `bool` when a Dowa type already expresses the value.
+- C code generally uses `Dowa_Arena` for request-scoped allocations.
+- HTTP responses are usually `Seobeo_Request_Entry *resp = NULL` maps filled with `Dowa_HashMap_Push_Arena`.
+- Route handlers return response maps; streaming handlers receive `Seobeo_Handle *` directly.
+- Existing code favors explicit status/content-type/body response fields.
+- Use `Seobeo_Log` for seobeo-aware logging instead of introducing another logger.
+- Keep Bazel dependencies precise. Add deps to the smallest target that needs them.
+- Preserve platform-aware `select()` aliases for macOS/Linux targets.
+
+## Mercurial workflow
+
+This repo is not a Git repository. Use Mercurial commands if you need VCS status:
+
+```bash
+hg status
+hg diff
+```
+
+Do not create Git-specific metadata or workflows unless explicitly asked.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.claude/skills/zenbu-hg-web/SKILL.md	Tue Aug 04 02:44:06 2026 -0700
@@ -0,0 +1,70 @@
+---
+name: zenbu-hg-web
+description: Use this skill when changing hg-web, the Mercurial repository browser, including the C API server, hg proxying, React/TypeScript frontend, markdown rendering, graph views, or static asset bundle.
+---
+
+# Hg Web
+
+Use this skill for `hg-web/`, a GitHub-style Mercurial repository browser backed by a C server and a TypeScript frontend.
+
+## Structure
+
+- `hg-web/main.c`: C server, routes, Mercurial proxy APIs, wire protocol streaming.
+- `hg-web/src/main.tsx`: frontend entry.
+- `hg-web/src/components/`: React/TypeScript UI components.
+- `hg-web/src/index.html`, `index.css`, `base.css`: shell and styles.
+- `hg-web/BUILD`: Bun bundle, static assets, C server, and release bundle.
+- `hg-web/deploy.sh`: deployment entry point.
+
+The server depends on `//seobeo:seobeo`. The frontend bundle includes `markdown_converter:markdown_to_html_wasm` and `third_party/highlight:js`.
+
+## Backend model
+
+The C backend proxies to local `hg serve` at:
+
+```c
+#define HG_SERVE_HOST "127.0.0.1"
+#define HG_SERVE_PORT "4444"
+```
+
+Public endpoints include:
+
+- `GET /`
+- `GET /directories`
+- `GET /graph`
+- `GET /api/repo/list?path=...`
+- `GET /api/repo/file?path=...`
+- `GET /api/repo/readme?path=...`
+- `GET /api/graph/:graph_id?...`
+- `GET /repo` and `POST /repo` streaming Mercurial wire protocol proxy.
+
+Use `sanitize_path` and `Seobeo_Url_Decode` patterns for any path-derived endpoint. Never pass raw path input to an hg path.
+
+## Frontend model
+
+Prefer editing components under `hg-web/src/components/`. Keep API paths aligned with backend registrations in `main.c`. The frontend should be able to handle:
+
+- directory listings from `/api/repo/list`,
+- file contents from `/api/repo/file`,
+- README markdown rendering through the WASM markdown converter,
+- syntax highlighting through highlight.js,
+- graph data via `/api/graph/:graph_id`.
+
+## Build
+
+```bash
+bazel build //hg-web:hg_web_server
+bazel build //hg-web:hg_web_server_bundle
+```
+
+If changing shared networking behavior, also run the relevant seobeo tests.
+
+## Safety checklist
+
+- Prefer Dowa aliases (`uint8`, `uint32`, `boolean`, `TRUE`/`FALSE`) over
+  `<stdint.h>` `_t` types and `<stdbool.h>` `bool` in first-party C.
+- Preserve binary-safe streaming in `StreamHgWireProtocol`; Mercurial bundle data can contain null bytes.
+- Do not buffer large wire-protocol responses through the normal HTTP client path unless the task explicitly requires it.
+- Validate and sanitize all path and graph inputs.
+- Keep content types accurate: JSON for API listing responses, `text/plain` or source-specific content for file/graph proxy responses, `text/html` for the app shell.
+- If changing route names, update both backend registrations and frontend fetch/navigation code.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.claude/skills/zenbu-personal-site/SKILL.md	Tue Aug 04 02:44:06 2026 -0700
@@ -0,0 +1,71 @@
+---
+name: zenbu-personal-site
+description: Use this skill when updating the mrjunejune personal website, blog, resume, tools, notes/editor APIs, uploads, PWA assets, or deployment bundle.
+---
+
+# Mrjunejune Personal Site
+
+Use this skill for `mrjunejune/`, the personal website served by a C backend.
+
+## Structure
+
+- `mrjunejune/main.c`: C web server, routes, APIs, S3 upload URL generation, editor persistence, media conversion, WebSocket chat.
+- `mrjunejune/src/`: static site source files and HTML templates.
+- `mrjunejune/src/parts/`: shared HTML includes used by `{{...}}` template placeholders.
+- `mrjunejune/src/public/`: public assets, PWA files, media, generated JS, icons, resume PDF.
+- `mrjunejune/test/`: integration tests and snapshots.
+- `mrjunejune/BUILD`: Bazel build, bundle, asset movement, and test-visible filegroups.
+- `mrjunejune/.config` and `.config.development`: server configuration. Do not commit secrets.
+
+## How rendering works
+
+Handlers allocate a response body from `Dowa_Arena`, render an HTML file with `Seobeo_Render_Html_FilePath`, and return a response map:
+
+```c
+Seobeo_Request_Entry *resp = NULL;
+char *final_body = Dowa_Arena_Allocate(arena, 50 * 1024);
+Seobeo_Render_Html_FilePath(final_body, "/tools/index.html", arena);
+Dowa_HashMap_Push_Arena(resp, "body", final_body, arena);
+return resp;
+```
+
+The simple template renderer replaces `{{...}}` tokens with file contents loaded through `Seobeo_Web_LoadFile`.
+
+## Routes and features
+
+Existing route areas include:
+
+- Home, resume, tools, markdown-to-HTML, file converter, blog, talk/chat, notes, and editor pages.
+- Redirect helpers built with `CREATE_REDIRECT_HANDLER`.
+- File/media conversion APIs using `ffmpeg` and temporary files under `/tmp`.
+- S3 presigned upload URL API using `Authorization: Bearer <token>`.
+- Editor save/load APIs backed by `deita` SQLite.
+- WebSocket chat broadcasting through seobeo WebSocket server APIs.
+
+When adding pages, add the HTML/CSS/JS under `src/`, register a route in `main.c`, and update tests/snapshots if the route should be covered.
+
+## Build and test
+
+```bash
+bazel build //mrjunejune:mrjunejune_server
+bazel build //mrjunejune:mrjunejune_server_bundle
+bazel test //mrjunejune/test:integration_test
+```
+
+Use the debug server when investigating routing or networking:
+
+```bash
+bazel build //mrjunejune:mrjunejune_server_debug -c dbg
+```
+
+## Production-minded checklist
+
+- Use Dowa's fixed-width aliases and `boolean`/`TRUE`/`FALSE` in first-party C
+  instead of introducing `<stdint.h>` `_t` types or `<stdbool.h>` `bool`.
+- Keep auth-protected APIs strict: missing auth should be `401`, invalid token `403`, malformed JSON/input `400`, unavailable DB/S3/ffmpeg `500`.
+- Never hardcode secrets. Read configuration from `.config` or environment wiring already used by the Bazel target.
+- For uploads and downloads, validate filenames and content lengths before touching `/tmp`.
+- For binary responses, set `content-length` and avoid string-only operations on body bytes.
+- If a route is part of the public website, add or update snapshot coverage in `mrjunejune/test`.
+- Keep PWA changes consistent across `manifest.json`, `sw.js`, icons, and `PWA_SETUP.md`.
+- Reuse `seobeo`, `dowa`, `deita`, `s3`, and `markdown_converter` instead of adding parallel implementations.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.claude/skills/zenbu-seobeo-networking/SKILL.md	Tue Aug 04 02:44:06 2026 -0700
@@ -0,0 +1,105 @@
+---
+name: zenbu-seobeo-networking
+description: Use this skill when changing or extending seobeo, the C networking layer for HTTP clients, HTTP/static servers, routing, streaming, TLS, or WebSockets.
+---
+
+# Seobeo Networking
+
+Use this skill for the `seobeo/` networking library and any server code built on top of it.
+
+## Mental model
+
+`seobeo` is the shared C networking layer. It provides:
+
+- TCP server/client handles in `s_network.c`.
+- TLS helpers in `s_ssl.c`.
+- Static file and HTTP routing in `s_web.c`.
+- Curl-like HTTP client APIs in `s_http_client.c`.
+- WebSocket client/server support in `s_websocket*.c`.
+- Snapshot/test utilities in `snapshot_creator.c`.
+- Public API declarations in `seobeo/seobeo.h`.
+- Internal types in `seobeo/seobeo_internal.h`.
+
+Prefer using public APIs from `seobeo.h` in applications. Only reach into internals when modifying seobeo itself.
+
+## Common APIs
+
+HTTP client:
+
+```c
+Seobeo_Client_Request *p_req = Seobeo_Client_Request_Create("https://example.com/path");
+Seobeo_Client_Request_Set_Method(p_req, "GET");
+Seobeo_Client_Request_Add_Header_Array(p_req, "Accept: application/json");
+Seobeo_Client_Response *p_resp = Seobeo_Client_Request_Execute(p_req);
+Seobeo_Client_Request_Destroy(p_req);
+Seobeo_Client_Response_Destroy(p_resp);
+```
+
+HTTP routes:
+
+```c
+Seobeo_Router_Init();
+Seobeo_Router_Register("GET", "/api/example/:id", Handler);
+Seobeo_Web_Server_Start("site/src", "8080", SEOBEO_MODE_EDGE, 1);
+Seobeo_Router_Destroy();
+```
+
+Route handler shape:
+
+```c
+Seobeo_Request_Entry *Handler(Seobeo_Request_Entry *req, Dowa_Arena *arena)
+{
+  Seobeo_Request_Entry *resp = NULL;
+  Dowa_HashMap_Push_Arena(resp, "status", "200", arena);
+  Dowa_HashMap_Push_Arena(resp, "content-type", "application/json", arena);
+  Dowa_HashMap_Push_Arena(resp, "body", "{\"ok\":true}", arena);
+  return resp;
+}
+```
+
+WebSocket server:
+
+```c
+Seobeo_WebSocket_Server_Init();
+Seobeo_WebSocket_Server_Register("/chat", Chat_Handler, NULL);
+```
+
+## Build targets
+
+Choose the smallest library variant that matches the feature:
+
+- `//seobeo:seobeo_min`: TCP/SSL basics.
+- `//seobeo:seobeo_tcp_server`: HTTP server, no WebSocket, no SSL.
+- `//seobeo:seobeo_tcp_server_ws`: HTTP server with WebSocket.
+- `//seobeo:seobeo_tcp_client`: HTTP client.
+- `//seobeo:seobeo_tcp_client_ws`: HTTP client with WebSocket.
+- `//seobeo:seobeo`: full combined library.
+- `//seobeo:seobeo_debug`: full library with debug logging.
+
+## Tests
+
+Run the narrowest relevant tests first:
+
+```bash
+bazel test //seobeo:seobeo_client_test
+bazel test //seobeo:seobeo_websocket_test
+bazel test //seobeo:seobeo_websocket_server_test
+```
+
+For API changes, also build downstream users:
+
+```bash
+bazel build //mrjunejune:mrjunejune_server //hg-web:hg_web_server
+```
+
+## Safety checklist
+
+- Use Dowa aliases such as `uint8`, `uint32`, and `boolean` with
+  `TRUE`/`FALSE`; avoid adding `<stdint.h>` `_t` types or `<stdbool.h>` `bool`
+  to first-party C when the Dowa equivalent exists.
+- Keep binary bodies binary-safe: use explicit lengths and `Dowa_Arena_Copy`/`memcpy`, not `strlen`, when forwarding arbitrary bytes.
+- Destroy `Seobeo_Client_Request`, `Seobeo_Client_Response`, `Seobeo_Handle`, and WebSocket messages on owned paths.
+- Do not swallow network errors. Return explicit HTTP 4xx/5xx responses or propagate error codes.
+- Preserve keep-alive, content-length, and response header behavior when touching routing or streaming.
+- Be careful with request map keys: existing code uses keys such as `Body`, `Content-Length`, `Authorization`, `HTTP_Method`, `QueryString`, route params like `:filename`, and query-derived keys like `query_path`.
+- For WebSockets, respect RFC 6455 requirements: client frames masked, fragmentation handled, control frames handled, and close paths cleaned up.
--- a/mrjunejune/BUILD	Mon Aug 03 20:20:06 2026 -0700
+++ b/mrjunejune/BUILD	Tue Aug 04 02:44:06 2026 -0700
@@ -180,6 +180,7 @@
     "//config:linux_x86_64": ["//third_party/tectonic:runtime"],
     "//conditions:default": [],
   }),
+  deps = ["//dowa:dowa"],
   visibility = ["//mrjunejune/test:__pkg__"],
 )
 
--- a/mrjunejune/latex_renderer.c	Mon Aug 03 20:20:06 2026 -0700
+++ b/mrjunejune/latex_renderer.c	Tue Aug 04 02:44:06 2026 -0700
@@ -12,7 +12,6 @@
 #include <limits.h>
 #include <poll.h>
 #include <signal.h>
-#include <stdbool.h>
 #include <stddef.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -68,7 +67,7 @@
   };
 }
 
-static bool write_all(int fd, const uint8_t *data, size_t size)
+static boolean write_all(int fd, const uint8 *data, size_t size)
 {
   while (size > 0)
   {
@@ -77,12 +76,12 @@
     {
       if (errno == EINTR)
         continue;
-      return false;
+      return FALSE;
     }
     data += written;
     size -= (size_t)written;
   }
-  return true;
+  return TRUE;
 }
 
 static int remove_tree(const char *path, unsigned depth)
@@ -127,7 +126,7 @@
   return result == 0 ? rmdir(path) : result;
 }
 
-static bool set_limit(int resource, rlim_t value)
+static boolean set_limit(int resource, rlim_t value)
 {
   struct rlimit limit = {
     .rlim_cur = value,
@@ -136,18 +135,18 @@
   return setrlimit(resource, &limit) == 0;
 }
 
-static bool add_landlock_path_rule(
+static boolean add_landlock_path_rule(
     int ruleset_fd,
     const char *path,
-    uint64_t access,
-    bool required)
+    uint64 access,
+    boolean required)
 {
   int path_fd = open(path, O_PATH | O_CLOEXEC);
   if (path_fd < 0)
     return !required && errno == ENOENT;
 
   struct stat status;
-  bool ok = fstat(path_fd, &status) == 0;
+  boolean ok = fstat(path_fd, &status) == 0;
   if (ok && !S_ISDIR(status.st_mode))
   {
     access &= LANDLOCK_ACCESS_FS_EXECUTE |
@@ -170,26 +169,26 @@
   return ok;
 }
 
-static bool add_landlock_tree_rules(
+static boolean add_landlock_tree_rules(
     int ruleset_fd,
     const char *path,
-    uint64_t access,
+    uint64 access,
     unsigned depth)
 {
   if (depth > 32 ||
-      !add_landlock_path_rule(ruleset_fd, path, access, true))
-    return false;
+      !add_landlock_path_rule(ruleset_fd, path, access, TRUE))
+    return FALSE;
 
   struct stat status;
   if (lstat(path, &status) != 0)
-    return false;
+    return FALSE;
   if (!S_ISDIR(status.st_mode))
-    return true;
+    return TRUE;
 
   DIR *directory = opendir(path);
   if (!directory)
-    return false;
-  bool ok = true;
+    return FALSE;
+  boolean ok = TRUE;
   struct dirent *entry;
   while (ok && (entry = readdir(directory)) != NULL)
   {
@@ -215,7 +214,7 @@
   return ok;
 }
 
-static bool apply_filesystem_sandbox(
+static boolean apply_filesystem_sandbox(
     const char *job_directory,
     const char *compiler,
     const char *cache_directory,
@@ -227,13 +226,13 @@
       0,
       LANDLOCK_CREATE_RULESET_VERSION);
   if (abi < 1)
-    return false;
+    return FALSE;
 
-  uint64_t read_access =
+  uint64 read_access =
       LANDLOCK_ACCESS_FS_EXECUTE |
       LANDLOCK_ACCESS_FS_READ_FILE |
       LANDLOCK_ACCESS_FS_READ_DIR;
-  uint64_t write_access =
+  uint64 write_access =
       LANDLOCK_ACCESS_FS_WRITE_FILE |
       LANDLOCK_ACCESS_FS_REMOVE_DIR |
       LANDLOCK_ACCESS_FS_REMOVE_FILE |
@@ -258,15 +257,15 @@
       sizeof(ruleset),
       0);
   if (ruleset_fd < 0)
-    return false;
+    return FALSE;
 
-  bool ok = true;
+  boolean ok = TRUE;
   if (ok)
     ok = add_landlock_path_rule(
         ruleset_fd,
         compiler,
         LANDLOCK_ACCESS_FS_EXECUTE | LANDLOCK_ACCESS_FS_READ_FILE,
-        true);
+        TRUE);
   if (ok)
     ok = add_landlock_tree_rules(
         ruleset_fd,
@@ -284,19 +283,19 @@
         ruleset_fd,
         "/dev/null",
         LANDLOCK_ACCESS_FS_READ_FILE | LANDLOCK_ACCESS_FS_WRITE_FILE,
-        true);
+        TRUE);
   if (ok)
     ok = add_landlock_path_rule(
         ruleset_fd,
         "/dev/urandom",
         LANDLOCK_ACCESS_FS_READ_FILE,
-        false);
+        FALSE);
   if (ok)
     ok = add_landlock_path_rule(
         ruleset_fd,
         job_directory,
         read_access | write_access,
-        true);
+        TRUE);
   if (ok)
     ok = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) == 0;
   if (ok)
@@ -308,10 +307,10 @@
   return ok;
 }
 
-static bool apply_network_sandbox(void)
+static boolean apply_network_sandbox(void)
 {
   if (LATEX_AUDIT_ARCH == 0)
-    return false;
+    return FALSE;
 
   struct sock_filter filters[64];
   size_t count = 0;
@@ -469,7 +468,7 @@
     int output_fd,
     char *diagnostics,
     size_t diagnostics_size,
-    bool *timed_out)
+    boolean *timed_out)
 {
   int flags = fcntl(output_fd, F_GETFL, 0);
   if (flags >= 0)
@@ -477,7 +476,7 @@
 
   size_t used = 0;
   int child_status = 0;
-  bool child_done = false;
+  boolean child_done = FALSE;
   struct timespec start;
   clock_gettime(CLOCK_MONOTONIC, &start);
 
@@ -499,7 +498,7 @@
     pid_t waited = waitpid(child, &child_status, WNOHANG);
     if (waited == child)
     {
-      child_done = true;
+      child_done = TRUE;
       break;
     }
     if (waited < 0 && errno != EINTR)
@@ -509,12 +508,12 @@
     clock_gettime(CLOCK_MONOTONIC, &now);
     if (elapsed_seconds(&start, &now) >= LATEX_WALL_TIMEOUT_SECONDS)
     {
-      *timed_out = true;
+      *timed_out = TRUE;
       kill(-child, SIGKILL);
       while (waitpid(child, &child_status, 0) < 0 && errno == EINTR)
       {
       }
-      child_done = true;
+      child_done = TRUE;
       break;
     }
 
@@ -542,21 +541,21 @@
   return child_status;
 }
 
-static bool read_pdf(
+static boolean read_pdf(
     const char *path,
-    uint8_t **data,
+    uint8 **data,
     size_t *size)
 {
   int fd = open(path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW);
   if (fd < 0)
-    return false;
+    return FALSE;
 
   struct stat status;
-  bool ok = fstat(fd, &status) == 0 &&
+  boolean ok = fstat(fd, &status) == 0 &&
       S_ISREG(status.st_mode) &&
       status.st_size > 4 &&
       status.st_size <= LATEX_PDF_MAX_BYTES;
-  uint8_t *content = NULL;
+  uint8 *content = NULL;
   if (ok)
   {
     content = malloc((size_t)status.st_size);
@@ -573,7 +572,7 @@
       continue;
     if (count <= 0)
     {
-      ok = false;
+      ok = FALSE;
       break;
     }
     offset += (size_t)count;
@@ -584,19 +583,19 @@
       memcmp(content, "%PDF-", 5) != 0)
   {
     free(content);
-    return false;
+    return FALSE;
   }
   *data = content;
   *size = offset;
-  return true;
+  return TRUE;
 }
 
-static bool resolve_runtime_path(
+static boolean resolve_runtime_path(
     const char *relative_path,
     char resolved[PATH_MAX])
 {
   if (realpath(relative_path, resolved))
-    return true;
+    return TRUE;
 
   const char *runfiles = getenv("RUNFILES_DIR");
   const char *workspace = getenv("TEST_WORKSPACE");
@@ -613,7 +612,7 @@
     if (length >= 0 &&
         (size_t)length < sizeof(candidate) &&
         realpath(candidate, resolved))
-      return true;
+      return TRUE;
   }
 
   char executable[PATH_MAX];
@@ -622,7 +621,7 @@
       executable,
       sizeof(executable) - 1);
   if (executable_length <= 0)
-    return false;
+    return FALSE;
   executable[executable_length] = '\0';
 
   char *last_slash = strrchr(executable, '/');
@@ -638,12 +637,12 @@
     if (length >= 0 &&
         (size_t)length < sizeof(candidate) &&
         realpath(candidate, resolved))
-      return true;
+      return TRUE;
   }
 
   char *package = strstr(executable, "/mrjunejune/");
   if (!package)
-    return false;
+    return FALSE;
   *package = '\0';
   int length = snprintf(
       candidate,
@@ -656,7 +655,7 @@
       realpath(candidate, resolved) != NULL;
 }
 
-Latex_Render_Result Latex_Render(const uint8_t *source, size_t source_size)
+Latex_Render_Result Latex_Render(const uint8 *source, size_t source_size)
 {
   if (!source || source_size == 0)
     return result_with_message(
@@ -755,7 +754,7 @@
         "Unable to allocate compiler diagnostics.");
   }
 
-  bool timed_out = false;
+  boolean timed_out = FALSE;
   int child_status = wait_for_compiler(
       child,
       output_pipe[0],
@@ -841,7 +840,7 @@
 #include <stdlib.h>
 #include <string.h>
 
-Latex_Render_Result Latex_Render(const uint8_t *source, size_t source_size)
+Latex_Render_Result Latex_Render(const uint8 *source, size_t source_size)
 {
   (void)source;
   (void)source_size;
--- a/mrjunejune/latex_renderer.h	Mon Aug 03 20:20:06 2026 -0700
+++ b/mrjunejune/latex_renderer.h	Tue Aug 04 02:44:06 2026 -0700
@@ -1,8 +1,7 @@
 #ifndef MRJUNEJUNE_LATEX_RENDERER_H
 #define MRJUNEJUNE_LATEX_RENDERER_H
 
-#include <stddef.h>
-#include <stdint.h>
+#include "dowa/dowa.h"
 
 #define LATEX_SOURCE_MAX_BYTES (64 * 1024)
 #define LATEX_PDF_MAX_BYTES (4 * 1024 * 1024)
@@ -19,12 +18,12 @@
 
 typedef struct {
   Latex_Render_Status status;
-  uint8_t *pdf_data;
+  uint8 *pdf_data;
   size_t pdf_size;
   char *diagnostics;
 } Latex_Render_Result;
 
-Latex_Render_Result Latex_Render(const uint8_t *source, size_t source_size);
+Latex_Render_Result Latex_Render(const uint8 *source, size_t source_size);
 void Latex_Render_Result_Destroy(Latex_Render_Result *result);
 
 #endif
--- a/mrjunejune/main.c	Mon Aug 03 20:20:06 2026 -0700
+++ b/mrjunejune/main.c	Tue Aug 04 02:44:06 2026 -0700
@@ -14,7 +14,7 @@
 #define UUID_LEN 37
 
 volatile sig_atomic_t stop_server = 0;
-static _Atomic uint32_t counter = 0;
+static _Atomic uint32 counter = 0;
 static _Atomic boolean g_latex_rendering = FALSE;
 
 // Media Processing Context for background threads
@@ -360,7 +360,7 @@
     return LatexErrorResponse(arena, 429, "The LaTeX compiler is busy. Try again shortly.");
 
   Latex_Render_Result render = Latex_Render(
-      (const uint8_t *)((Seobeo_Request_Entry *)body_kv)->value,
+      (const uint8 *)((Seobeo_Request_Entry *)body_kv)->value,
       (size_t)parsed_length);
   atomic_store(&g_latex_rendering, FALSE);
   if (render.status != LATEX_RENDER_OK)
--- a/mrjunejune/test/latex_renderer_test.c	Mon Aug 03 20:20:06 2026 -0700
+++ b/mrjunejune/test/latex_renderer_test.c	Tue Aug 04 02:44:06 2026 -0700
@@ -32,7 +32,7 @@
       "Hello from the sandbox. $x^2 + y^2 = z^2$\n"
       "\\end{document}\n";
   Latex_Render_Result result = Latex_Render(
-      (const uint8_t *)valid,
+      (const uint8 *)valid,
       strlen(valid));
   if (result.status != LATEX_RENDER_OK)
     fprintf(stderr, "%s\n", result.diagnostics ? result.diagnostics : "unknown error");
@@ -46,7 +46,7 @@
       "\\begin{document}\n"
       "\\notarealcommand\n"
       "\\end{document}\n";
-  result = Latex_Render((const uint8_t *)invalid, strlen(invalid));
+  result = Latex_Render((const uint8 *)invalid, strlen(invalid));
   assert(result.status == LATEX_RENDER_COMPILE_ERROR);
   assert(result.diagnostics);
   assert(strstr(result.diagnostics, "Undefined control sequence"));
@@ -57,7 +57,7 @@
       "\\begin{document}\n"
       "\\input{/etc/passwd}\n"
       "\\end{document}\n";
-  result = Latex_Render((const uint8_t *)host_read, strlen(host_read));
+  result = Latex_Render((const uint8 *)host_read, strlen(host_read));
   assert(result.status == LATEX_RENDER_COMPILE_ERROR);
   assert(result.diagnostics);
   assert(!strstr(result.diagnostics, "root:x:"));
@@ -80,13 +80,13 @@
       "\\end{document}\n",
       shell_path);
   result = Latex_Render(
-      (const uint8_t *)shell_escape,
+      (const uint8 *)shell_escape,
       strlen(shell_escape));
   assert(result.status == LATEX_RENDER_OK);
   assert(access(shell_path, F_OK) != 0);
   Latex_Render_Result_Destroy(&result);
 
-  uint8_t oversized[LATEX_SOURCE_MAX_BYTES + 1] = {0};
+  uint8 oversized[LATEX_SOURCE_MAX_BYTES + 1] = {0};
   memset(oversized, 'x', sizeof(oversized));
   result = Latex_Render(oversized, sizeof(oversized));
   assert(result.status == LATEX_RENDER_INVALID_INPUT);
@@ -97,7 +97,7 @@
       "\\begin{document}\n"
       "\\loop\\iftrue\\repeat\n"
       "\\end{document}\n";
-  result = Latex_Render((const uint8_t *)infinite, strlen(infinite));
+  result = Latex_Render((const uint8 *)infinite, strlen(infinite));
   assert(result.status == LATEX_RENDER_TIMEOUT);
   Latex_Render_Result_Destroy(&result);