#!/usr/bin/env bash set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" ABI_VERSION="sdxl-c-v1" LINK_MODE="imported" BACKEND_DIR="$PROJECT_ROOT/external/SilentDragonXLite/lib" BACKEND_SOURCE_DIR="" BUILD_BACKEND_DIR="" BACKEND_DEPENDENCY_DIR="" BACKEND_DEPENDENCY_OVERRIDE_REQUESTED=false OUT_DIR="$PROJECT_ROOT/build/lite-backend" PLATFORM="" RUST_TARGET="" CARGO_TARGET_DIR_VALUE="${CARGO_TARGET_DIR:-}" ARTIFACT_PATH="" BUILD_ARTIFACT=true BUILDER="${DRAGONX_LITE_BACKEND_BUILDER:-local}" JOBS="${JOBS:-}" SOURCE_DATE_EPOCH_VALUE="${SOURCE_DATE_EPOCH:-}" REPRODUCIBLE=false SIGNATURE_REQUIRED=false SIGNATURE_FILE="" SIGNATURE_FORMAT="" SIGNATURE_VERIFICATION_TOOL="" SIGNATURE_VERIFICATION_COMMAND="" SIGNATURE_KEY_FINGERPRINT="" SIGNATURE_CERTIFICATE_IDENTITY="" SIGNATURE_CERTIFICATE_ISSUER="" SIGNATURE_TRANSPARENCY_LOG_URL="" SIGNATURE_VERIFIED_SHA256="" SIGNATURE_POLICY_NAME="dragonx-lite-backend-signature-policy-v1" SIGNATURE_POLICY_DEFINED_MANIFEST_VALUE=true SIGNATURE_REQUIRED_MANIFEST_VALUE=false SIGNATURE_METADATA_PROVIDED=false SIGNATURE_VERIFICATION_PERFORMED=false SIGNATURE_VERIFICATION_STATUS="not-provided" SIGNATURE_FILE_SHA256="" REQUIRED_SYMBOLS=( litelib_wallet_exists litelib_initialize_new litelib_initialize_new_from_phrase litelib_initialize_existing litelib_execute litelib_rust_free_string litelib_check_server_online litelib_shutdown ) EXTRA_CARGO_ARGS=() EXTRA_REMAP_PATH_PREFIXES=() usage() { cat <// //lite-backend-symbols.txt //lite-backend-artifact-manifest.json The script captures symbols, checksums, and optional read-only signature verification metadata only. It does not load the library, resolve function pointers, call SDXL, sign, upload, or publish artifacts. EOF } info() { printf '[lite-backend] %s\n' "$*"; } warn() { printf '[lite-backend] warning: %s\n' "$*" >&2; } die() { printf '[lite-backend] ERROR: %s\n' "$*" >&2; exit 1; } absolute_path() { local path="$1" if [[ "$path" = /* ]]; then printf '%s\n' "$path" else printf '%s/%s\n' "$PWD" "$path" fi } host_platform() { case "$(uname -s)" in Linux) printf 'linux\n' ;; Darwin) printf 'macos\n' ;; MINGW*|MSYS*|CYGWIN*) printf 'windows\n' ;; *) die "unsupported host platform: $(uname -s)" ;; esac } normalize_platform() { case "$1" in linux|Linux) printf 'linux\n' ;; windows|win|Win|Windows) printf 'windows\n' ;; macos|mac|darwin|Darwin) printf 'macos\n' ;; "") host_platform ;; *) die "unsupported platform: $1" ;; esac } while [[ $# -gt 0 ]]; do case "$1" in --platform) [[ $# -ge 2 ]] || die "--platform requires a value" PLATFORM="$(normalize_platform "$2")" shift 2 ;; --rust-target) [[ $# -ge 2 ]] || die "--rust-target requires a value" RUST_TARGET="$2" shift 2 ;; --cargo-target-dir) [[ $# -ge 2 ]] || die "--cargo-target-dir requires a value" CARGO_TARGET_DIR_VALUE="$(absolute_path "$2")" shift 2 ;; --backend-dir) [[ $# -ge 2 ]] || die "--backend-dir requires a value" BACKEND_DIR="$(absolute_path "$2")" shift 2 ;; --silentdragonxlitelib-dir) [[ $# -ge 2 ]] || die "--silentdragonxlitelib-dir requires a value" BACKEND_DEPENDENCY_DIR="$(absolute_path "$2")" BACKEND_DEPENDENCY_OVERRIDE_REQUESTED=true shift 2 ;; --out-dir) [[ $# -ge 2 ]] || die "--out-dir requires a value" OUT_DIR="$(absolute_path "$2")" shift 2 ;; --artifact) [[ $# -ge 2 ]] || die "--artifact requires a value" ARTIFACT_PATH="$(absolute_path "$2")" BUILD_ARTIFACT=false shift 2 ;; --no-build) BUILD_ARTIFACT=false shift ;; --reproducible) REPRODUCIBLE=true shift ;; --remap-path-prefix) [[ $# -ge 2 ]] || die "--remap-path-prefix requires FROM=TO" [[ "$2" == *=* ]] || die "--remap-path-prefix requires FROM=TO" EXTRA_REMAP_PATH_PREFIXES+=("$2") shift 2 ;; --builder) [[ $# -ge 2 ]] || die "--builder requires a value" BUILDER="$2" shift 2 ;; --signature-required) SIGNATURE_REQUIRED=true shift ;; --signature-file|--signature-path) [[ $# -ge 2 ]] || die "$1 requires a value" SIGNATURE_FILE="$(absolute_path "$2")" shift 2 ;; --signature-format) [[ $# -ge 2 ]] || die "--signature-format requires a value" SIGNATURE_FORMAT="$2" shift 2 ;; --signature-verification-tool|--signature-tool) [[ $# -ge 2 ]] || die "$1 requires a value" SIGNATURE_VERIFICATION_TOOL="$2" shift 2 ;; --signature-verification-command) [[ $# -ge 2 ]] || die "--signature-verification-command requires a value" SIGNATURE_VERIFICATION_COMMAND="$2" shift 2 ;; --signature-key-fingerprint) [[ $# -ge 2 ]] || die "--signature-key-fingerprint requires a value" SIGNATURE_KEY_FINGERPRINT="$2" shift 2 ;; --signature-certificate-identity) [[ $# -ge 2 ]] || die "--signature-certificate-identity requires a value" SIGNATURE_CERTIFICATE_IDENTITY="$2" shift 2 ;; --signature-certificate-issuer) [[ $# -ge 2 ]] || die "--signature-certificate-issuer requires a value" SIGNATURE_CERTIFICATE_ISSUER="$2" shift 2 ;; --signature-transparency-log-url) [[ $# -ge 2 ]] || die "--signature-transparency-log-url requires a value" SIGNATURE_TRANSPARENCY_LOG_URL="$2" shift 2 ;; --signature-verified-sha256) [[ $# -ge 2 ]] || die "--signature-verified-sha256 requires a value" SIGNATURE_VERIFIED_SHA256="$2" shift 2 ;; -j|--jobs) [[ $# -ge 2 ]] || die "--jobs requires a value" JOBS="$2" shift 2 ;; --cargo-arg) [[ $# -ge 2 ]] || die "--cargo-arg requires a value" EXTRA_CARGO_ARGS+=("$2") shift 2 ;; -h|--help) usage exit 0 ;; *) die "unknown option: $1" ;; esac done PLATFORM="$(normalize_platform "$PLATFORM")" BACKEND_SOURCE_DIR="$BACKEND_DIR" BUILD_BACKEND_DIR="$BACKEND_SOURCE_DIR" if [[ "$PLATFORM" == "windows" && -z "$RUST_TARGET" ]]; then RUST_TARGET="x86_64-pc-windows-gnu" fi if [[ "$PLATFORM" == "macos" && -z "$RUST_TARGET" && "$(host_platform)" != "macos" ]]; then die "macOS artifacts require --rust-target when not running on macOS" fi if [[ "$BUILD_ARTIFACT" == false && -z "$ARTIFACT_PATH" ]]; then die "--no-build requires --artifact" fi backend_dependency_path_from_cargo() { local cargo_toml="$1" awk ' /^[[:space:]]*silentdragonxlitelib[[:space:]]*=/ { original = $0 path = $0 sub(/.*path[[:space:]]*=[[:space:]]*"/, "", path) sub(/".*/, "", path) if (path != original) print path exit } ' "$cargo_toml" } canonical_dependency_path() { local path="$1" if [[ -d "$path" ]]; then (cd "$path" && pwd -P) else absolute_path "$path" fi } validate_backend_dependency_source() { [[ -n "$BACKEND_DEPENDENCY_DIR" ]] || return if [[ ! -f "$BACKEND_DEPENDENCY_DIR/Cargo.toml" ]]; then if [[ "$BUILD_ARTIFACT" == true || "$BACKEND_DEPENDENCY_OVERRIDE_REQUESTED" == true ]]; then die "Cargo.toml not found in $BACKEND_DEPENDENCY_DIR" fi warn "Cargo.toml not found in silentdragonxlitelib source: $BACKEND_DEPENDENCY_DIR" return fi if ! grep -Eq '^[[:space:]]*name[[:space:]]*=[[:space:]]*"silentdragonxlitelib"' "$BACKEND_DEPENDENCY_DIR/Cargo.toml"; then if [[ "$BUILD_ARTIFACT" == true || "$BACKEND_DEPENDENCY_OVERRIDE_REQUESTED" == true ]]; then die "dependency path does not look like silentdragonxlitelib: $BACKEND_DEPENDENCY_DIR" fi warn "dependency path does not look like silentdragonxlitelib: $BACKEND_DEPENDENCY_DIR" fi } prepare_backend_source() { BUILD_BACKEND_DIR="$BACKEND_SOURCE_DIR" if [[ "$BACKEND_DEPENDENCY_OVERRIDE_REQUESTED" == false ]]; then if [[ -f "$BACKEND_SOURCE_DIR/Cargo.toml" ]]; then local configured_dependency_path configured_dependency_path="$(backend_dependency_path_from_cargo "$BACKEND_SOURCE_DIR/Cargo.toml")" if [[ -n "$configured_dependency_path" ]]; then if [[ "$configured_dependency_path" = /* ]]; then BACKEND_DEPENDENCY_DIR="$(canonical_dependency_path "$configured_dependency_path")" warn "backend Cargo.toml uses an absolute silentdragonxlitelib path; use --silentdragonxlitelib-dir for portable builders" else BACKEND_DEPENDENCY_DIR="$(canonical_dependency_path "$BACKEND_SOURCE_DIR/$configured_dependency_path")" info "using relative silentdragonxlitelib dependency at $BACKEND_DEPENDENCY_DIR" fi validate_backend_dependency_source fi fi return fi [[ -f "$BACKEND_SOURCE_DIR/Cargo.toml" ]] || die "Cargo.toml not found in $BACKEND_SOURCE_DIR" validate_backend_dependency_source [[ "$BACKEND_DEPENDENCY_DIR" != *\"* ]] || die "--silentdragonxlitelib-dir path cannot contain a double quote" local prepared_root="$OUT_DIR/.prepared-backend/$PLATFORM" [[ "$prepared_root" == */.prepared-backend/* ]] || die "refusing unsafe prepared backend path: $prepared_root" rm -rf "$prepared_root" mkdir -p "$prepared_root" ln -s "$BACKEND_SOURCE_DIR/src" "$prepared_root/src" [[ -f "$BACKEND_SOURCE_DIR/Cargo.lock" ]] && ln -s "$BACKEND_SOURCE_DIR/Cargo.lock" "$prepared_root/Cargo.lock" [[ -d "$BACKEND_SOURCE_DIR/.cargo" ]] && ln -s "$BACKEND_SOURCE_DIR/.cargo" "$prepared_root/.cargo" [[ -d "$BACKEND_SOURCE_DIR/libsodium-mingw" ]] && ln -s "$BACKEND_SOURCE_DIR/libsodium-mingw" "$prepared_root/libsodium-mingw" [[ -f "$BACKEND_SOURCE_DIR/silentdragonxlitelib.h" ]] && ln -s "$BACKEND_SOURCE_DIR/silentdragonxlitelib.h" "$prepared_root/silentdragonxlitelib.h" local replacement="silentdragonxlitelib = { path = \"$BACKEND_DEPENDENCY_DIR\" }" awk -v replacement="$replacement" ' BEGIN { replaced = 0 } /^[[:space:]]*silentdragonxlitelib[[:space:]]*=/ { print replacement replaced = 1 next } { print } END { if (replaced != 1) exit 42 } ' "$BACKEND_SOURCE_DIR/Cargo.toml" > "$prepared_root/Cargo.toml" \ || die "failed to prepare backend Cargo.toml with portable silentdragonxlitelib path" BUILD_BACKEND_DIR="$prepared_root" info "prepared backend source at $BUILD_BACKEND_DIR with silentdragonxlitelib from $BACKEND_DEPENDENCY_DIR" } prepare_backend_source artifact_kind() { local name="${1##*/}" case "$name" in *.a|*.lib) printf 'static-library\n' ;; *.so|*.dylib|*.dll) printf 'shared-library\n' ;; *) printf 'unknown\n' ;; esac } cargo_output_candidates() { local cargo_target_root="$BUILD_BACKEND_DIR/target" if [[ -n "$CARGO_TARGET_DIR_VALUE" ]]; then cargo_target_root="$CARGO_TARGET_DIR_VALUE" fi local base="$cargo_target_root/release" if [[ -n "$RUST_TARGET" ]]; then base="$cargo_target_root/$RUST_TARGET/release" fi case "$PLATFORM" in linux) printf '%s\n' "$base/libsilentdragonxlite.a" "$base/silentdragonxlite.a" "$base/libsilentdragonxlite.so" ;; windows) printf '%s\n' "$base/silentdragonxlite.lib" "$base/libsilentdragonxlite.a" "$base/silentdragonxlite.dll" ;; macos) printf '%s\n' "$base/libsilentdragonxlite.a" "$base/silentdragonxlite.a" "$base/libsilentdragonxlite.dylib" "$base/silentdragonxlite.dylib" ;; esac } source_revision_for() { local dir="$1" local revision_file for revision_file in "$dir/DRAGONX_SOURCE_REVISION" "$dir/../DRAGONX_SOURCE_REVISION"; do if [[ -f "$revision_file" ]]; then sed -n '1p' "$revision_file" return fi done if git -C "$dir" rev-parse --is-inside-work-tree >/dev/null 2>&1; then git -C "$dir" rev-parse HEAD 2>/dev/null || printf 'unknown' else printf 'unknown' fi } default_source_date_epoch() { if git -C "$PROJECT_ROOT" rev-parse --is-inside-work-tree >/dev/null 2>&1; then git -C "$PROJECT_ROOT" log -1 --format=%ct 2>/dev/null || printf '0' else printf '0' fi } append_rustflag() { local rustflag="$1" if [[ -n "${RUSTFLAGS:-}" ]]; then export RUSTFLAGS="${RUSTFLAGS} ${rustflag}" else export RUSTFLAGS="$rustflag" fi } append_rust_path_remap() { local from_path="$1" local to_path="$2" [[ -n "$from_path" && -n "$to_path" ]] || return append_rustflag "--remap-path-prefix=${from_path}=${to_path}" } apply_reproducible_rustflags() { local cargo_target_root="$BUILD_BACKEND_DIR/target" if [[ -n "$CARGO_TARGET_DIR_VALUE" ]]; then cargo_target_root="$CARGO_TARGET_DIR_VALUE" fi append_rust_path_remap "$PROJECT_ROOT" "/dragonx-project" append_rust_path_remap "$BACKEND_SOURCE_DIR" "/dragonx-lite-backend" if [[ "$BUILD_BACKEND_DIR" != "$BACKEND_SOURCE_DIR" ]]; then append_rust_path_remap "$BUILD_BACKEND_DIR" "/dragonx-lite-backend" fi append_rust_path_remap "$BACKEND_DEPENDENCY_DIR" "/dragonx-lite-backend-dependency" for path_remap in "${EXTRA_REMAP_PATH_PREFIXES[@]}"; do append_rustflag "--remap-path-prefix=${path_remap}" done local cargo_home="${CARGO_HOME:-}" if [[ -z "$cargo_home" && -n "${HOME:-}" ]]; then cargo_home="$HOME/.cargo" fi if [[ -n "$cargo_home" && -d "$cargo_home" ]]; then append_rust_path_remap "$cargo_home" "/cargo-home" fi append_rust_path_remap "$cargo_target_root" "/dragonx-lite-cargo-target" } build_with_cargo() { command -v cargo >/dev/null 2>&1 || die "cargo was not found" [[ -f "$BUILD_BACKEND_DIR/Cargo.toml" ]] || die "Cargo.toml not found in $BUILD_BACKEND_DIR" if [[ -z "$SOURCE_DATE_EPOCH_VALUE" ]]; then SOURCE_DATE_EPOCH_VALUE="$(default_source_date_epoch)" fi export CARGO_INCREMENTAL=0 export SOURCE_DATE_EPOCH="$SOURCE_DATE_EPOCH_VALUE" if [[ -n "$CARGO_TARGET_DIR_VALUE" ]]; then export CARGO_TARGET_DIR="$CARGO_TARGET_DIR_VALUE" fi if [[ "$REPRODUCIBLE" == true ]]; then apply_reproducible_rustflags fi if [[ "$PLATFORM" == "windows" && -d "$BUILD_BACKEND_DIR/libsodium-mingw" ]]; then export SODIUM_LIB_DIR="$BUILD_BACKEND_DIR/libsodium-mingw" fi local cargo_cmd=(cargo build --locked --lib --release) if [[ -n "$RUST_TARGET" ]]; then cargo_cmd+=(--target "$RUST_TARGET") fi if [[ -n "$JOBS" ]]; then cargo_cmd+=(-j "$JOBS") fi cargo_cmd+=("${EXTRA_CARGO_ARGS[@]}") info "building backend in $BUILD_BACKEND_DIR" (cd "$BUILD_BACKEND_DIR" && "${cargo_cmd[@]}") while IFS= read -r candidate; do if [[ -f "$candidate" ]]; then ARTIFACT_PATH="$candidate" return fi done < <(cargo_output_candidates) die "cargo finished, but no expected backend artifact was found under $BUILD_BACKEND_DIR/target" } select_nm_tool() { if [[ "$PLATFORM" == "windows" ]] && command -v x86_64-w64-mingw32-nm >/dev/null 2>&1; then printf 'x86_64-w64-mingw32-nm\n' return fi if command -v llvm-nm >/dev/null 2>&1; then printf 'llvm-nm\n' return fi if command -v nm >/dev/null 2>&1; then printf 'nm\n' return fi die "no symbol inventory tool found; install nm, llvm-nm, or x86_64-w64-mingw32-nm" } compute_sha256() { local file="$1" if command -v sha256sum >/dev/null 2>&1; then sha256sum "$file" | awk '{print $1}' elif command -v shasum >/dev/null 2>&1; then shasum -a 256 "$file" | awk '{print $1}' else die "sha256sum or shasum is required" fi } json_escape() { local value="$1" value="${value//\\/\\\\}" value="${value//\"/\\\"}" value="${value//$'\n'/\\n}" value="${value//$'\r'/}" value="${value//$'\t'/\\t}" printf '"%s"' "$value" } json_array() { local first=true printf '[' for value in "$@"; do if [[ "$first" == true ]]; then first=false else printf ',' fi json_escape "$value" done printf ']' } json_array_from_file() { local file="$1" local values=() if [[ -f "$file" ]]; then mapfile -t values < "$file" fi json_array "${values[@]}" } signature_metadata_requested() { [[ "$SIGNATURE_REQUIRED" == true || \ -n "$SIGNATURE_FILE" || \ -n "$SIGNATURE_FORMAT" || \ -n "$SIGNATURE_VERIFICATION_TOOL" || \ -n "$SIGNATURE_VERIFICATION_COMMAND" || \ -n "$SIGNATURE_KEY_FINGERPRINT" || \ -n "$SIGNATURE_CERTIFICATE_IDENTITY" || \ -n "$SIGNATURE_CERTIFICATE_ISSUER" || \ -n "$SIGNATURE_TRANSPARENCY_LOG_URL" || \ -n "$SIGNATURE_VERIFIED_SHA256" ]] } validate_signature_metadata() { SIGNATURE_REQUIRED_MANIFEST_VALUE=false if [[ "$SIGNATURE_REQUIRED" == true ]]; then SIGNATURE_REQUIRED_MANIFEST_VALUE=true fi if ! signature_metadata_requested; then return fi [[ -n "$SIGNATURE_FILE" ]] || die "signature metadata requires --signature-file" [[ -f "$SIGNATURE_FILE" ]] || die "signature file does not exist: $SIGNATURE_FILE" [[ -n "$SIGNATURE_FORMAT" ]] || die "signature metadata requires --signature-format" case "$SIGNATURE_FORMAT" in minisign|gpg|sigstore|external|other) ;; *) die "unsupported --signature-format: $SIGNATURE_FORMAT" ;; esac [[ -n "$SIGNATURE_VERIFICATION_TOOL" ]] || die "signature metadata requires --signature-verification-tool" [[ -n "$SIGNATURE_VERIFIED_SHA256" ]] || die "signature metadata requires --signature-verified-sha256" [[ "$SIGNATURE_VERIFIED_SHA256" == "$SHA256_DIGEST" ]] || die "signature verified SHA-256 does not match artifact SHA-256" if [[ -z "$SIGNATURE_KEY_FINGERPRINT" && -z "$SIGNATURE_CERTIFICATE_IDENTITY" ]]; then die "signature metadata requires --signature-key-fingerprint or --signature-certificate-identity" fi SIGNATURE_METADATA_PROVIDED=true SIGNATURE_VERIFICATION_PERFORMED=true SIGNATURE_VERIFICATION_STATUS="verified" SIGNATURE_FILE_SHA256="$(compute_sha256 "$SIGNATURE_FILE")" } if [[ "$BUILD_ARTIFACT" == true ]]; then build_with_cargo fi if [[ -z "$SOURCE_DATE_EPOCH_VALUE" ]]; then SOURCE_DATE_EPOCH_VALUE="$(default_source_date_epoch)" fi [[ -f "$ARTIFACT_PATH" ]] || die "artifact not found: $ARTIFACT_PATH" KIND="$(artifact_kind "$ARTIFACT_PATH")" [[ "$KIND" != "unknown" ]] || die "artifact kind is unsupported: $ARTIFACT_PATH" PLATFORM_OUT_DIR="$OUT_DIR/$PLATFORM" mkdir -p "$PLATFORM_OUT_DIR" ARTIFACT_NAME="$(basename "$ARTIFACT_PATH")" ARTIFACT_OUTPUT="$PLATFORM_OUT_DIR/$ARTIFACT_NAME" if [[ "$(absolute_path "$ARTIFACT_PATH")" != "$(absolute_path "$ARTIFACT_OUTPUT")" ]]; then cp -p "$ARTIFACT_PATH" "$ARTIFACT_OUTPUT" fi SYMBOLS_FILE="$PLATFORM_OUT_DIR/lite-backend-symbols.txt" RAW_SYMBOLS_FILE="$PLATFORM_OUT_DIR/lite-backend-symbols.raw.txt" NM_TOOL="$(select_nm_tool)" info "capturing exported symbols with $NM_TOOL" if ! "$NM_TOOL" -g --defined-only "$ARTIFACT_OUTPUT" > "$RAW_SYMBOLS_FILE" 2> "$PLATFORM_OUT_DIR/lite-backend-symbols.err.txt"; then die "symbol inventory failed; see $PLATFORM_OUT_DIR/lite-backend-symbols.err.txt" fi awk '{print $NF}' "$RAW_SYMBOLS_FILE" \ | sed 's/^_//' \ | grep -E '^(litelib_[A-Za-z0-9_]*|blake3_PW)$' \ | sort -u > "$SYMBOLS_FILE" || true [[ -s "$SYMBOLS_FILE" ]] || die "no SDXL C ABI symbols were found in $ARTIFACT_OUTPUT" MISSING_SYMBOLS=() for required in "${REQUIRED_SYMBOLS[@]}"; do if ! grep -Fxq "$required" "$SYMBOLS_FILE"; then MISSING_SYMBOLS+=("$required") fi done if [[ ${#MISSING_SYMBOLS[@]} -ne 0 ]]; then printf '%s\n' "${MISSING_SYMBOLS[@]}" > "$PLATFORM_OUT_DIR/lite-backend-missing-symbols.txt" die "artifact is missing required symbols; see $PLATFORM_OUT_DIR/lite-backend-missing-symbols.txt" fi SHA256_DIGEST="$(compute_sha256 "$ARTIFACT_OUTPUT")" validate_signature_metadata ARTIFACT_SIZE_BYTES="$(wc -c < "$ARTIFACT_OUTPUT" | tr -d ' ')" PROJECT_REVISION="$(source_revision_for "$PROJECT_ROOT")" BACKEND_REVISION="$(source_revision_for "$BACKEND_SOURCE_DIR")" BACKEND_DEPENDENCY_REVISION="" if [[ -n "$BACKEND_DEPENDENCY_DIR" ]]; then BACKEND_DEPENDENCY_REVISION="$(source_revision_for "$BACKEND_DEPENDENCY_DIR")" fi ARTIFACT_SET_ID="$PLATFORM-${SHA256_DIGEST:0:16}" REPRODUCIBLE_MANIFEST_VALUE=false if [[ "$BUILD_ARTIFACT" == true && "$REPRODUCIBLE" == true ]]; then REPRODUCIBLE_MANIFEST_VALUE=true fi PORTABLE_DEPENDENCY_OVERRIDE_MANIFEST_VALUE=false if [[ "$BACKEND_DEPENDENCY_OVERRIDE_REQUESTED" == true ]]; then PORTABLE_DEPENDENCY_OVERRIDE_MANIFEST_VALUE=true fi FILE_DESCRIPTION="unknown" if command -v file >/dev/null 2>&1; then FILE_DESCRIPTION="$(file -b "$ARTIFACT_OUTPUT")" fi MANIFEST_FILE="$PLATFORM_OUT_DIR/lite-backend-artifact-manifest.json" { printf '{\n' printf ' "schema": "dragonx.lite.backend-artifact.v1",\n' printf ' "generated_by": "scripts/build-lite-backend-artifact.sh",\n' printf ' "read_only_inventory": true,\n' printf ' "artifact_mutation_requested": false,\n' printf ' "upload_requested": false,\n' printf ' "signing_requested": false,\n' printf ' "publication_requested": false,\n' printf ' "signature_verification": {\n' printf ' "policy_name": '; json_escape "$SIGNATURE_POLICY_NAME"; printf ',\n' printf ' "policy_defined": %s,\n' "$SIGNATURE_POLICY_DEFINED_MANIFEST_VALUE" printf ' "required_for_release": %s,\n' "$SIGNATURE_REQUIRED_MANIFEST_VALUE" printf ' "metadata_read_only": true,\n' printf ' "metadata_provided": %s,\n' "$SIGNATURE_METADATA_PROVIDED" printf ' "verification_performed": %s,\n' "$SIGNATURE_VERIFICATION_PERFORMED" printf ' "verification_status": '; json_escape "$SIGNATURE_VERIFICATION_STATUS"; printf ',\n' printf ' "signature_format": '; json_escape "$SIGNATURE_FORMAT"; printf ',\n' printf ' "signature_path": '; json_escape "$SIGNATURE_FILE"; printf ',\n' printf ' "signature_file_sha256": '; json_escape "$SIGNATURE_FILE_SHA256"; printf ',\n' printf ' "verification_tool": '; json_escape "$SIGNATURE_VERIFICATION_TOOL"; printf ',\n' printf ' "verification_command": '; json_escape "$SIGNATURE_VERIFICATION_COMMAND"; printf ',\n' printf ' "key_fingerprint": '; json_escape "$SIGNATURE_KEY_FINGERPRINT"; printf ',\n' printf ' "certificate_identity": '; json_escape "$SIGNATURE_CERTIFICATE_IDENTITY"; printf ',\n' printf ' "certificate_issuer": '; json_escape "$SIGNATURE_CERTIFICATE_ISSUER"; printf ',\n' printf ' "transparency_log_url": '; json_escape "$SIGNATURE_TRANSPARENCY_LOG_URL"; printf ',\n' printf ' "verified_artifact_sha256": '; json_escape "$SIGNATURE_VERIFIED_SHA256"; printf '\n' printf ' },\n' printf ' "abi_version": '; json_escape "$ABI_VERSION"; printf ',\n' printf ' "link_mode": '; json_escape "$LINK_MODE"; printf ',\n' printf ' "platform": '; json_escape "$PLATFORM"; printf ',\n' printf ' "rust_target": '; json_escape "$RUST_TARGET"; printf ',\n' printf ' "artifact": {\n' printf ' "path": '; json_escape "$ARTIFACT_OUTPUT"; printf ',\n' printf ' "kind": '; json_escape "$KIND"; printf ',\n' printf ' "size_bytes": %s,\n' "$ARTIFACT_SIZE_BYTES" printf ' "sha256": '; json_escape "$SHA256_DIGEST"; printf ',\n' printf ' "file_description": '; json_escape "$FILE_DESCRIPTION"; printf '\n' printf ' },\n' printf ' "symbol_inventory": {\n' printf ' "tool": '; json_escape "$NM_TOOL"; printf ',\n' printf ' "symbols_path": '; json_escape "$SYMBOLS_FILE"; printf ',\n' printf ' "raw_symbols_path": '; json_escape "$RAW_SYMBOLS_FILE"; printf ',\n' printf ' "required_symbols": '; json_array "${REQUIRED_SYMBOLS[@]}"; printf ',\n' printf ' "exported_symbols": '; json_array_from_file "$SYMBOLS_FILE"; printf ',\n' printf ' "missing_required_symbols": []\n' printf ' },\n' printf ' "provenance": {\n' printf ' "owner_ready": true,\n' printf ' "metadata_provided": true,\n' printf ' "source": '; json_escape "$BACKEND_SOURCE_DIR"; printf ',\n' printf ' "cargo_build_source": '; json_escape "$BUILD_BACKEND_DIR"; printf ',\n' printf ' "portable_dependency_override": %s,\n' "$PORTABLE_DEPENDENCY_OVERRIDE_MANIFEST_VALUE" printf ' "silentdragonxlitelib_source": '; json_escape "$BACKEND_DEPENDENCY_DIR"; printf ',\n' printf ' "builder": '; json_escape "$BUILDER"; printf ',\n' printf ' "source_revision": '; json_escape "$BACKEND_REVISION"; printf ',\n' printf ' "silentdragonxlitelib_revision": '; json_escape "$BACKEND_DEPENDENCY_REVISION"; printf ',\n' printf ' "project_revision": '; json_escape "$PROJECT_REVISION"; printf ',\n' printf ' "artifact_set_id": '; json_escape "$ARTIFACT_SET_ID"; printf ',\n' printf ' "source_date_epoch": '; json_escape "$SOURCE_DATE_EPOCH_VALUE"; printf ',\n' printf ' "reproducible": %s,\n' "$REPRODUCIBLE_MANIFEST_VALUE" printf ' "redacted": true\n' printf ' }\n' printf '}\n' } > "$MANIFEST_FILE" info "artifact: $ARTIFACT_OUTPUT" info "symbols: $SYMBOLS_FILE" info "manifest: $MANIFEST_FILE" info "sha256: $SHA256_DIGEST" cat <