d58afe562d
Externalizing the integration templates (#1492/#1493) and the UI bundle
(#1501/#1503) was done to reduce the Microsoft `Wacatac.B!ml` surface. It did
not work: across dry runs the flagged artifact count stayed at ~3 and the
detections merely moved between artifacts.
Dissection of run 31286803592 shows there is no structural cause to fix. The
verdicts split across every axis at once — linux-amd64 (dynamic) flagged while
linux-amd64-portable (static) is clean, but linux-arm64 (dynamic) clean while
linux-arm64-portable (static) is flagged. The two macOS binaries have identical
segment structure and split clean/flagged. Siblings from one build landed in
different variant buckets (.B vs .C). Entropy is low everywhere
(code_vectors.bin 4.166, grammar tables 3.464 bits/byte, against 7.5-8.0 for
packed payloads), so the packed-payload hypothesis is excluded too.
So the complexity bought nothing, and installation goes back to being
self-contained: one binary that carries its own UI and agent integration
templates, with no adjacent data file that has to resolve before `install`
works. Only the UI-capable composition ships from now on, under the historical
unsuffixed archive name.
Removed: src/ui/asset_pack.{c,h}, asset_pack_stub.c, asset_manifest_stub.c,
scripts/pack-ui-assets.mjs, src/cli/integration_assets.{c,h},
assets/cbm-integrations.json, scripts/gen-integrations-hash.sh, the
--verify-runtime-assets probe (nothing adjacent left to verify), and the
composition gates A6/A7 whose property is now deliberately inverted.
Restored: scripts/embed-frontend.sh, src/ui/embedded_{assets.h,stub.c}, the
compiled-in hook/adapter template bodies, and the embed/EMBED_OBJS build path.
Kept from the reverted commits, re-applied by hand where a wholesale file
restore would have dropped them:
- cbm_module_path_utf8() in both self-path sites. GetModuleFileNameA renders
through the ANSI code page and mangles non-ASCII install paths.
- the /__cbm/ui-readiness HMAC proof, secure_random and cbm_hmac_sha256, so
`daemon start --open` still waits for a genuine CBM listener.
- X-Content-Type-Options: nosniff on served assets.
- the MinGW noexecstack gate, -lbcrypt, and the cppcheck/zip CI fixes.
Archives are now codebase-memory-mcp-<os>-<arch>[-portable] with exactly four
members (binary, LICENSE, installer, THIRD_PARTY_NOTICES.md). That restores the
names every static package manifest already points at — aur, chocolatey,
homebrew, scoop, winget and glama were all broken by the -ui- rename.
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
195 lines
5.8 KiB
Bash
Executable File
195 lines
5.8 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# embed-frontend.sh — Convert built frontend assets into linkable object files.
|
|
#
|
|
# Usage: scripts/embed-frontend.sh <dist_dir> <output_dir>
|
|
#
|
|
# For each file in dist_dir, creates:
|
|
# 1. An object file via `ld -r -b binary` (raw bytes, zero bloat)
|
|
# 2. A generated embedded_assets.c with a lookup table
|
|
#
|
|
# Symbols created per file: _binary_<mangled_name>_start, _binary_<mangled_name>_end
|
|
# On macOS, these get a leading underscore: __binary_<mangled_name>_start
|
|
|
|
set -euo pipefail
|
|
|
|
DIST_DIR="${1:?Usage: embed-frontend.sh <dist_dir> <output_dir>}"
|
|
OUTPUT_DIR="${2:?Usage: embed-frontend.sh <dist_dir> <output_dir>}"
|
|
|
|
# Clean old embedded objects (asset hashes change on each build)
|
|
rm -rf "$OUTPUT_DIR"
|
|
mkdir -p "$OUTPUT_DIR"
|
|
|
|
# Detect platform — Linux uses ld -r -b binary, everything else uses xxd+cc
|
|
IS_LINUX=false
|
|
if [[ "$(uname -s)" == "Linux" ]] && ! [[ "$(uname -s)" =~ MINGW|MSYS ]]; then
|
|
IS_LINUX=true
|
|
fi
|
|
|
|
# Content-type detection
|
|
content_type_for() {
|
|
local f="$1"
|
|
case "$f" in
|
|
*.html) echo "text/html" ;;
|
|
*.js) echo "application/javascript" ;;
|
|
*.css) echo "text/css" ;;
|
|
*.json) echo "application/json" ;;
|
|
*.svg) echo "image/svg+xml" ;;
|
|
*.png) echo "image/png" ;;
|
|
*.ico) echo "image/x-icon" ;;
|
|
*.woff2) echo "font/woff2" ;;
|
|
*.woff) echo "font/woff" ;;
|
|
*.map) echo "application/json" ;;
|
|
*) echo "application/octet-stream" ;;
|
|
esac
|
|
}
|
|
|
|
# Mangle filename to valid C symbol: replace non-alnum with _
|
|
mangle() {
|
|
echo "$1" | sed 's/[^a-zA-Z0-9]/_/g'
|
|
}
|
|
|
|
# Collect all files
|
|
FILES=()
|
|
while IFS= read -r -d '' file; do
|
|
FILES+=("$file")
|
|
done < <(find "$DIST_DIR" -type f -print0 | sort -z)
|
|
|
|
if [[ ${#FILES[@]} -eq 0 ]]; then
|
|
echo "Error: no files found in $DIST_DIR" >&2
|
|
exit 1
|
|
fi
|
|
|
|
echo "Embedding ${#FILES[@]} files from $DIST_DIR"
|
|
|
|
# Generate object files
|
|
OBJ_FILES=()
|
|
for file in "${FILES[@]}"; do
|
|
rel="${file#$DIST_DIR/}"
|
|
mangled=$(mangle "$rel")
|
|
obj="$OUTPUT_DIR/embed_${mangled}.o"
|
|
|
|
if $IS_LINUX; then
|
|
# Linux: ld -r -b binary (zero bloat, ELF only)
|
|
abs_obj="$(cd "$(dirname "$0")/.." && pwd)/$obj"
|
|
(cd "$DIST_DIR" && ld -r -b binary -o "$abs_obj" "$rel")
|
|
else
|
|
# macOS/Windows/MSYS2: generate C byte array + cc (no xxd dependency)
|
|
local_c="$OUTPUT_DIR/embed_${mangled}.c"
|
|
local_sym="_binary_${mangled}"
|
|
|
|
echo "/* Generated from $rel */" > "$local_c"
|
|
echo "const unsigned char ${local_sym}_data[] = {" >> "$local_c"
|
|
# Use od (POSIX) to generate hex bytes — works everywhere without xxd/vim
|
|
od -An -tx1 -v < "$file" | tr -s ' ' '\n' | grep -v '^$' | sed 's/^/0x/; s/$/,/' | paste -sd' ' - | fold -s -w 76 | sed 's/^/ /' >> "$local_c"
|
|
echo "};" >> "$local_c"
|
|
echo "const unsigned int ${local_sym}_size = sizeof(${local_sym}_data);" >> "$local_c"
|
|
|
|
${CC:-cc} -c -O2 -o "$obj" "$local_c"
|
|
rm -f "$local_c"
|
|
fi
|
|
|
|
OBJ_FILES+=("$obj")
|
|
echo " $rel -> $obj"
|
|
done
|
|
|
|
# Generate embedded_assets.c
|
|
ASSETS_C="src/ui/embedded_assets.c"
|
|
cat > "$ASSETS_C" <<'HEADER'
|
|
/*
|
|
* embedded_assets.c — Generated file mapping URL paths to embedded bytes.
|
|
* DO NOT EDIT — regenerated by scripts/embed-frontend.sh
|
|
*/
|
|
#include "ui/embedded_assets.h"
|
|
#include <string.h>
|
|
|
|
HEADER
|
|
|
|
# Declare extern symbols
|
|
for file in "${FILES[@]}"; do
|
|
rel="${file#$DIST_DIR/}"
|
|
mangled=$(mangle "$rel")
|
|
sym="_binary_${mangled}"
|
|
|
|
if ! $IS_LINUX; then
|
|
echo "extern const unsigned char ${sym}_data[];" >> "$ASSETS_C"
|
|
echo "extern const unsigned int ${sym}_size;" >> "$ASSETS_C"
|
|
else
|
|
echo "extern const unsigned char ${sym}_start[];" >> "$ASSETS_C"
|
|
echo "extern const unsigned char ${sym}_end[];" >> "$ASSETS_C"
|
|
fi
|
|
done
|
|
|
|
echo "" >> "$ASSETS_C"
|
|
echo "cbm_embedded_file_t CBM_EMBEDDED_FILES[] = {" >> "$ASSETS_C"
|
|
|
|
for file in "${FILES[@]}"; do
|
|
rel="${file#$DIST_DIR/}"
|
|
mangled=$(mangle "$rel")
|
|
sym="_binary_${mangled}"
|
|
ct=$(content_type_for "$rel")
|
|
|
|
# URL path: /index.html for root, /assets/... for assets
|
|
url_path="/$rel"
|
|
|
|
if ! $IS_LINUX; then
|
|
echo " {\"$url_path\", ${sym}_data, 0, \"$ct\"}," >> "$ASSETS_C"
|
|
else
|
|
echo " {\"$url_path\", ${sym}_start, 0, \"$ct\"}," >> "$ASSETS_C"
|
|
fi
|
|
done
|
|
|
|
echo "};" >> "$ASSETS_C"
|
|
echo "const int CBM_EMBEDDED_FILE_COUNT = ${#FILES[@]};" >> "$ASSETS_C"
|
|
|
|
# Generate size fixup
|
|
if $IS_LINUX; then
|
|
# Linux: compute size from start/end pointers (ld -r -b binary symbols)
|
|
cat >> "$ASSETS_C" <<'SIZEINIT'
|
|
|
|
static void __attribute__((constructor)) init_embedded_sizes(void) {
|
|
cbm_embedded_file_t *files = CBM_EMBEDDED_FILES;
|
|
SIZEINIT
|
|
|
|
for i in "${!FILES[@]}"; do
|
|
rel="${FILES[$i]#$DIST_DIR/}"
|
|
mangled=$(mangle "$rel")
|
|
sym="_binary_${mangled}"
|
|
echo " files[$i].size = (unsigned int)(${sym}_end - ${sym}_start);" >> "$ASSETS_C"
|
|
done
|
|
|
|
echo "}" >> "$ASSETS_C"
|
|
else
|
|
# macOS/Windows: use explicit _size vars from xxd-generated C arrays
|
|
cat >> "$ASSETS_C" <<'SIZEINIT'
|
|
|
|
static void __attribute__((constructor)) init_embedded_sizes(void) {
|
|
cbm_embedded_file_t *files = CBM_EMBEDDED_FILES;
|
|
SIZEINIT
|
|
|
|
for i in "${!FILES[@]}"; do
|
|
rel="${FILES[$i]#$DIST_DIR/}"
|
|
mangled=$(mangle "$rel")
|
|
sym="_binary_${mangled}"
|
|
echo " files[$i].size = ${sym}_size;" >> "$ASSETS_C"
|
|
done
|
|
|
|
echo "}" >> "$ASSETS_C"
|
|
fi
|
|
|
|
# Add lookup function
|
|
cat >> "$ASSETS_C" <<'LOOKUP'
|
|
|
|
const cbm_embedded_file_t *cbm_embedded_lookup(const char *path) {
|
|
for (int i = 0; i < CBM_EMBEDDED_FILE_COUNT; i++) {
|
|
if (strcmp(CBM_EMBEDDED_FILES[i].path, path) == 0) {
|
|
return &CBM_EMBEDDED_FILES[i];
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
LOOKUP
|
|
|
|
echo "Generated $ASSETS_C with ${#FILES[@]} embedded files"
|
|
echo "Object files in $OUTPUT_DIR:"
|
|
printf ' %s\n' "${OBJ_FILES[@]}"
|