diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 5db9990e2..5b9809dec 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -33,7 +33,7 @@ body: attributes: label: What happened? description: A clear description of the bug, including any error messages or unexpected output. - placeholder: e.g. provider crashed with X after running `eigeninference-provider serve` on a fresh M2 Air + placeholder: e.g. provider crashed with X after running `darkbloom-provider serve` on a fresh M2 Air validations: required: true @@ -52,7 +52,7 @@ body: description: Minimal steps that reliably trigger the bug. placeholder: | 1. Install v0.3.5 via the install.sh one-liner - 2. Run `eigeninference-provider serve --model llama-3.1-8b-instruct` + 2. Run `darkbloom-provider serve --model llama-3.1-8b-instruct` 3. Send a chat completion from the console UI 4. Observe the failure validations: @@ -63,7 +63,7 @@ body: attributes: label: Environment description: | - Anything relevant to reproducing this — provider version (`eigeninference-provider --version`), macOS version, Mac model + RAM, browser (for console UI bugs), etc. + Anything relevant to reproducing this — provider version (`darkbloom-provider --version`), macOS version, Mac model + RAM, browser (for console UI bugs), etc. placeholder: | - provider: v0.3.5 - macOS: 15.4 (Sequoia) @@ -75,7 +75,7 @@ body: id: logs attributes: label: Logs - description: Relevant log output. For provider crashes, include the last ~50 lines of `~/Library/Logs/eigeninference-provider/*.log`. Use code fences and redact anything sensitive. + description: Relevant log output. For provider crashes, include the last ~50 lines of `~/Library/Logs/darkbloom-provider/*.log`. Use code fences and redact anything sensitive. render: shell - type: checkboxes diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1ba051616..98ac2b94f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -110,20 +110,20 @@ jobs: -o /tmp/pbs-python.tar.gz # Extract for Rust linking (clean copy, no pip installs) - rm -rf /tmp/eigeninference-build-python - mkdir -p /tmp/eigeninference-build-python - tar xzf /tmp/pbs-python.tar.gz --strip-components=1 -C /tmp/eigeninference-build-python + rm -rf /tmp/darkbloom-build-python + mkdir -p /tmp/darkbloom-build-python + tar xzf /tmp/pbs-python.tar.gz --strip-components=1 -C /tmp/darkbloom-build-python # Extract for Python runtime (will get pip installs) tar xzf /tmp/pbs-python.tar.gz -C /tmp/ - mv /tmp/python /tmp/eigeninference-python + mv /tmp/python /tmp/darkbloom-python rm -f /tmp/pbs-python.tar.gz # Pre-download vllm-mlx source for pip install curl -fsSL -o /tmp/vllm-mlx-source.zip \ 'https://github.com/Gajesh2007/vllm-mlx/archive/refs/heads/main.zip' - /tmp/eigeninference-build-python/bin/python3.12 --version + /tmp/darkbloom-build-python/bin/python3.12 --version - name: Cache cargo registry + target uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0 @@ -148,10 +148,10 @@ jobs: # Task A: Rust provider ( set -e - export PYO3_PYTHON=/tmp/eigeninference-build-python/bin/python3.12 - export LIBRARY_PATH=/tmp/eigeninference-build-python/lib - export DYLD_LIBRARY_PATH=/tmp/eigeninference-build-python/lib - export RUSTFLAGS="-L native=/tmp/eigeninference-build-python/lib" + export PYO3_PYTHON=/tmp/darkbloom-build-python/bin/python3.12 + export LIBRARY_PATH=/tmp/darkbloom-build-python/lib + export DYLD_LIBRARY_PATH=/tmp/darkbloom-build-python/lib + export RUSTFLAGS="-L native=/tmp/darkbloom-build-python/lib" cd provider && cargo build --release ) > /tmp/rust-build.log 2>&1 & RUST_PID=$! @@ -168,7 +168,7 @@ jobs: # Task C: Python runtime (uv is ~10x faster than pip) ( set -e - PYTHON=/tmp/eigeninference-python/bin/python3.12 + PYTHON=/tmp/darkbloom-python/bin/python3.12 "$HOME/.local/bin/uv" pip install --python "$PYTHON" --quiet --no-cache-dir \ 'mlx-lm>=0.31.2' \ @@ -181,13 +181,13 @@ jobs: "$PYTHON" -c "from vllm_mlx.server import app; print('vllm-mlx server imports OK')" # Trim bloat - cd /tmp/eigeninference-python/lib/python*/site-packages + cd /tmp/darkbloom-python/lib/python*/site-packages rm -rf torch* gradio* opencv* cv2* pandas* pyarrow* \ sympy* networkx* mcp* miniaudio* pydub* datasets* - find /tmp/eigeninference-python -name __pycache__ -type d -exec rm -rf {} + 2>/dev/null || true - find /tmp/eigeninference-python -name "*.pyc" -delete 2>/dev/null || true - "$PYTHON" -m compileall -q /tmp/eigeninference-python/lib/python3.12/site-packages/ 2>/dev/null || true - rm -f /tmp/eigeninference-python/lib/python*/EXTERNALLY-MANAGED + find /tmp/darkbloom-python -name __pycache__ -type d -exec rm -rf {} + 2>/dev/null || true + find /tmp/darkbloom-python -name "*.pyc" -delete 2>/dev/null || true + "$PYTHON" -m compileall -q /tmp/darkbloom-python/lib/python3.12/site-packages/ 2>/dev/null || true + rm -f /tmp/darkbloom-python/lib/python*/EXTERNALLY-MANAGED ) > /tmp/python-build.log 2>&1 & PYTHON_PID=$! echo "Started Python runtime build (pid $PYTHON_PID)" @@ -195,7 +195,7 @@ jobs: # Task D: Swift macOS app (compile only — assembly happens after signing) ( set -e - cd app/EigenInference && swift build -c release + cd app/Darkbloom && swift build -c release ) > /tmp/app-build.log 2>&1 & APP_PID=$! echo "Started Swift app build (pid $APP_PID)" @@ -230,10 +230,10 @@ jobs: # ---- Provider tests in background ---- ( set -e - export PYO3_PYTHON=/tmp/eigeninference-build-python/bin/python3.12 - export LIBRARY_PATH=/tmp/eigeninference-build-python/lib - export DYLD_LIBRARY_PATH=/tmp/eigeninference-build-python/lib - export RUSTFLAGS="-L native=/tmp/eigeninference-build-python/lib" + export PYO3_PYTHON=/tmp/darkbloom-build-python/bin/python3.12 + export LIBRARY_PATH=/tmp/darkbloom-build-python/lib + export DYLD_LIBRARY_PATH=/tmp/darkbloom-build-python/lib + export RUSTFLAGS="-L native=/tmp/darkbloom-build-python/lib" cd provider && cargo test -- --skip proxy::tests --skip server::tests --skip coordinator::tests::test_coordinator_connect_register_and_receive ) > /tmp/test.log 2>&1 & TEST_PID=$! @@ -251,27 +251,27 @@ jobs: done } echo "Signing Python runtime Mach-Os..." - if ! sign_macho_tree /tmp/eigeninference-python; then + if ! sign_macho_tree /tmp/darkbloom-python; then echo "Python runtime codesign failed — retrying in 30s" sleep 30 - sign_macho_tree /tmp/eigeninference-python + sign_macho_tree /tmp/darkbloom-python fi echo "✓ Python runtime signed" # ---- Assemble provider bundle ---- - mkdir -p /tmp/eigeninference-bundle/bin /tmp/eigeninference-bundle/python + mkdir -p /tmp/darkbloom-bundle/bin /tmp/darkbloom-bundle/python - cp provider/target/release/darkbloom /tmp/eigeninference-bundle/bin/ - cp enclave/.build/release/eigeninference-enclave /tmp/eigeninference-bundle/bin/ + cp provider/target/release/darkbloom /tmp/darkbloom-bundle/bin/ + cp enclave/.build/release/darkbloom-enclave /tmp/darkbloom-bundle/bin/ # Copy SIGNED Python base to bundle (no site-packages). # These files are already signed from the runtime pass above. - cp -R /tmp/eigeninference-python/bin /tmp/eigeninference-bundle/python/ - cp -R /tmp/eigeninference-python/lib /tmp/eigeninference-bundle/python/ - rm -rf /tmp/eigeninference-bundle/python/lib/python3.12/site-packages + cp -R /tmp/darkbloom-python/bin /tmp/darkbloom-bundle/python/ + cp -R /tmp/darkbloom-python/lib /tmp/darkbloom-bundle/python/ + rm -rf /tmp/darkbloom-bundle/python/lib/python3.12/site-packages # Fix libpython linkage in darkbloom - PYTHON_LOAD_PATH=$(otool -L /tmp/eigeninference-bundle/bin/darkbloom | awk '/libpython3\.12\.dylib/ {print $1; exit}') + PYTHON_LOAD_PATH=$(otool -L /tmp/darkbloom-bundle/bin/darkbloom | awk '/libpython3\.12\.dylib/ {print $1; exit}') if [ -z "$PYTHON_LOAD_PATH" ]; then echo "ERROR: could not find libpython linkage in darkbloom" exit 1 @@ -279,34 +279,34 @@ jobs: install_name_tool -change \ "$PYTHON_LOAD_PATH" \ "@executable_path/../python/lib/libpython3.12.dylib" \ - /tmp/eigeninference-bundle/bin/darkbloom + /tmp/darkbloom-bundle/bin/darkbloom # Sign binaries (hardened runtime + entitlements) codesign --force --sign "$DEVELOPER_ID" \ --keychain "$KEYCHAIN_PATH" \ --entitlements scripts/entitlements.plist \ --options runtime \ - /tmp/eigeninference-bundle/bin/darkbloom + /tmp/darkbloom-bundle/bin/darkbloom codesign --force --sign "$DEVELOPER_ID" \ --keychain "$KEYCHAIN_PATH" \ --entitlements scripts/entitlements.plist \ --options runtime \ - /tmp/eigeninference-bundle/bin/eigeninference-enclave + /tmp/darkbloom-bundle/bin/darkbloom-enclave # Verify key signatures - codesign --verify --verbose /tmp/eigeninference-bundle/bin/darkbloom - codesign --verify --verbose /tmp/eigeninference-bundle/bin/eigeninference-enclave - codesign --verify --verbose /tmp/eigeninference-bundle/python/bin/python3.12 - codesign --verify --verbose /tmp/eigeninference-bundle/python/lib/libpython3.12.dylib + codesign --verify --verbose /tmp/darkbloom-bundle/bin/darkbloom + codesign --verify --verbose /tmp/darkbloom-bundle/bin/darkbloom-enclave + codesign --verify --verbose /tmp/darkbloom-bundle/python/bin/python3.12 + codesign --verify --verbose /tmp/darkbloom-bundle/python/lib/libpython3.12.dylib - cd /tmp && tar czf eigeninference-bundle-macos-arm64.tar.gz -C eigeninference-bundle . - echo "Bundle created: $(du -h /tmp/eigeninference-bundle-macos-arm64.tar.gz | cut -f1)" + cd /tmp && tar czf darkbloom-bundle-macos-arm64.tar.gz -C darkbloom-bundle . + echo "Bundle created: $(du -h /tmp/darkbloom-bundle-macos-arm64.tar.gz | cut -f1)" # ---- Compute Python hashes (stable — not affected by stapling) ---- # Binary and bundle hashes are computed AFTER notarization stapling # in the next step, since stapling modifies the Mach-O binaries. - PYTHON_BIN="/tmp/eigeninference-python/bin/python3.12" + PYTHON_BIN="/tmp/darkbloom-python/bin/python3.12" PYTHON_HASH=$(shasum -a 256 "$PYTHON_BIN" | cut -d' ' -f1) echo "Python hash: $PYTHON_HASH" echo "PYTHON_HASH=$PYTHON_HASH" >> "$GITHUB_ENV" @@ -318,14 +318,14 @@ jobs: # libpython rpath points at @executable_path/../python/lib/ which # doesn't exist in the bundle (site-packages stripped). Set # DYLD_LIBRARY_PATH so the binary can load libpython. - RUNTIME_HASH=$(DYLD_LIBRARY_PATH="/tmp/eigeninference-python/lib:/tmp/eigeninference-build-python/lib" \ - /tmp/eigeninference-bundle/bin/darkbloom hash-runtime "$PYTHON_LIB_DIR") + RUNTIME_HASH=$(DYLD_LIBRARY_PATH="/tmp/darkbloom-python/lib:/tmp/darkbloom-build-python/lib" \ + /tmp/darkbloom-bundle/bin/darkbloom hash-runtime "$PYTHON_LIB_DIR") echo "Runtime hash: $RUNTIME_HASH" echo "RUNTIME_HASH=$RUNTIME_HASH" >> "$GITHUB_ENV" # Create runtime tarballs - cd /tmp && tar czf eigeninference-python-macos-arm64.tar.gz -C eigeninference-python . - cd /tmp && tar czf eigeninference-site-packages.tar.gz -C "$SITE_PACKAGES_DIR" . + cd /tmp && tar czf darkbloom-python-macos-arm64.tar.gz -C darkbloom-python . + cd /tmp && tar czf darkbloom-site-packages.tar.gz -C "$SITE_PACKAGES_DIR" . # ---- Wait for provider tests ---- echo "Waiting for provider tests..." @@ -355,8 +355,8 @@ jobs: # ---- Task A: Notarize provider bundle (background) ---- ( set -e - ditto -c -k --keepParent /tmp/eigeninference-bundle /tmp/eigeninference-notarize.zip - xcrun notarytool submit /tmp/eigeninference-notarize.zip \ + ditto -c -k --keepParent /tmp/darkbloom-bundle /tmp/darkbloom-notarize.zip + xcrun notarytool submit /tmp/darkbloom-notarize.zip \ --apple-id "$APPLE_ID" \ --password "$APPLE_APP_PASSWORD" \ --team-id "$APPLE_TEAM_ID" \ @@ -366,9 +366,9 @@ jobs: echo "Started bundle notarization (pid $NOTARIZE_BUNDLE_PID)" # ---- Task B: Build macOS app + DMG (foreground, overlaps with notarize) ---- - APP_BIN=$(cd app/EigenInference && swift build -c release --show-bin-path)/EigenInference + APP_BIN=$(cd app/Darkbloom && swift build -c release --show-bin-path)/Darkbloom - APP_DIR="/tmp/EigenInference.app" + APP_DIR="/tmp/Darkbloom.app" CONTENTS="$APP_DIR/Contents" MACOS="$CONTENTS/MacOS" RESOURCES="$CONTENTS/Resources" @@ -381,12 +381,12 @@ jobs: - CFBundleNameEigenInference - CFBundleDisplayNameEigenInference + CFBundleNameDarkbloom + CFBundleDisplayNameDarkbloom CFBundleIdentifierio.darkbloom.provider CFBundleVersion${VERSION} CFBundleShortVersionString${VERSION} - CFBundleExecutableEigenInference + CFBundleExecutableDarkbloom CFBundlePackageTypeAPPL CFBundleIconFileAppIcon LSMinimumSystemVersion14.0 @@ -396,12 +396,12 @@ jobs: PLIST - cp "$APP_BIN" "$MACOS/EigenInference" - cp /tmp/eigeninference-bundle/bin/darkbloom "$MACOS/darkbloom" - cp /tmp/eigeninference-bundle/bin/eigeninference-enclave "$MACOS/eigeninference-enclave" 2>/dev/null || true + cp "$APP_BIN" "$MACOS/Darkbloom" + cp /tmp/darkbloom-bundle/bin/darkbloom "$MACOS/darkbloom" + cp /tmp/darkbloom-bundle/bin/darkbloom-enclave "$MACOS/darkbloom-enclave" 2>/dev/null || true # Copy already-signed Python runtime into app (skip re-signing individual files) - cp -a /tmp/eigeninference-python/. "$PYTHON_ROOT/" + cp -a /tmp/darkbloom-python/. "$PYTHON_ROOT/" # Sign app binaries (entitlements) for bin in "$MACOS"/*; do @@ -436,15 +436,15 @@ jobs: tail -5 /tmp/notarize-bundle.log # Staple notarization tickets to bundle binaries - xcrun stapler staple /tmp/eigeninference-bundle/bin/darkbloom || true - xcrun stapler staple /tmp/eigeninference-bundle/bin/eigeninference-enclave || true + xcrun stapler staple /tmp/darkbloom-bundle/bin/darkbloom || true + xcrun stapler staple /tmp/darkbloom-bundle/bin/darkbloom-enclave || true # Recreate bundle tarball with stapled binaries - cd /tmp && tar czf eigeninference-bundle-macos-arm64.tar.gz -C eigeninference-bundle . + cd /tmp && tar czf darkbloom-bundle-macos-arm64.tar.gz -C darkbloom-bundle . # Compute final hashes AFTER stapling (stapling modifies the binaries) - BINARY_HASH=$(shasum -a 256 /tmp/eigeninference-bundle/bin/darkbloom | cut -d' ' -f1) - BUNDLE_HASH=$(shasum -a 256 /tmp/eigeninference-bundle-macos-arm64.tar.gz | cut -d' ' -f1) + BINARY_HASH=$(shasum -a 256 /tmp/darkbloom-bundle/bin/darkbloom | cut -d' ' -f1) + BUNDLE_HASH=$(shasum -a 256 /tmp/darkbloom-bundle-macos-arm64.tar.gz | cut -d' ' -f1) echo "Binary hash (signed+stapled): $BINARY_HASH" echo "Bundle hash: $BUNDLE_HASH" echo "BINARY_HASH=$BINARY_HASH" >> "$GITHUB_ENV" @@ -465,9 +465,9 @@ jobs: # ---- Task D: Upload bundles to R2 (overlaps with DMG notarize) ---- # Wait on explicit PIDs — bare `wait` would also block on DMG notarize. PREFIX="s3://${R2_BUCKET}/releases/v${VERSION}" - aws s3 cp /tmp/eigeninference-bundle-macos-arm64.tar.gz "${PREFIX}/eigeninference-bundle-macos-arm64.tar.gz" --endpoint-url "$R2_ENDPOINT" --only-show-errors & UL1=$! - aws s3 cp /tmp/eigeninference-python-macos-arm64.tar.gz "${PREFIX}/eigeninference-python-macos-arm64.tar.gz" --endpoint-url "$R2_ENDPOINT" --only-show-errors & UL2=$! - aws s3 cp /tmp/eigeninference-site-packages.tar.gz "${PREFIX}/eigeninference-site-packages.tar.gz" --endpoint-url "$R2_ENDPOINT" --only-show-errors & UL3=$! + aws s3 cp /tmp/darkbloom-bundle-macos-arm64.tar.gz "${PREFIX}/darkbloom-bundle-macos-arm64.tar.gz" --endpoint-url "$R2_ENDPOINT" --only-show-errors & UL1=$! + aws s3 cp /tmp/darkbloom-python-macos-arm64.tar.gz "${PREFIX}/darkbloom-python-macos-arm64.tar.gz" --endpoint-url "$R2_ENDPOINT" --only-show-errors & UL2=$! + aws s3 cp /tmp/darkbloom-site-packages.tar.gz "${PREFIX}/darkbloom-site-packages.tar.gz" --endpoint-url "$R2_ENDPOINT" --only-show-errors & UL3=$! aws s3 cp /tmp/vllm-mlx-source.zip "${PREFIX}/vllm-mlx-source.zip" --endpoint-url "$R2_ENDPOINT" --only-show-errors & UL4=$! wait $UL1 $UL2 $UL3 $UL4 echo "All bundle uploads complete" @@ -510,7 +510,7 @@ jobs: R2_PUBLIC_URL: ${{ secrets.R2_PUBLIC_URL }} run: | VERSION="${GITHUB_REF_NAME#v}" - BUNDLE_URL="${R2_PUBLIC_URL}/releases/v${VERSION}/eigeninference-bundle-macos-arm64.tar.gz" + BUNDLE_URL="${R2_PUBLIC_URL}/releases/v${VERSION}/darkbloom-bundle-macos-arm64.tar.gz" TAG_MSG=$(git tag -l --format='%(contents:subject)%0a%(contents:body)' "$GITHUB_REF_NAME" 2>/dev/null || echo "") if [ -z "$TAG_MSG" ] || [ "$TAG_MSG" = $'\n' ]; then @@ -568,7 +568,7 @@ jobs: ``` NOTES gh release create "${{ github.ref_name }}" \ - /tmp/eigeninference-bundle-macos-arm64.tar.gz \ + /tmp/darkbloom-bundle-macos-arm64.tar.gz \ /tmp/Darkbloom.dmg \ --title "${{ github.ref_name }}" \ --notes-file /tmp/release-notes.md \ diff --git a/AGENTS.md b/AGENTS.md index 43f1ba8ef..c837b2452 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,6 +1,6 @@ -# EigenInference - Decentralized Private Inference +# Darkbloom - Decentralized Private Inference -EigenInference is a decentralized/private inference stack for Apple Silicon Macs. Consumers use OpenAI-compatible APIs, the coordinator handles routing/auth/billing/attestation, and providers run local text, transcription, and image workloads on macOS hardware. +Darkbloom is a decentralized/private inference stack for Apple Silicon Macs. Consumers use OpenAI-compatible APIs, the coordinator handles routing/auth/billing/attestation, and providers run local text, transcription, and image workloads on macOS hardware. ## Project Structure @@ -8,7 +8,7 @@ EigenInference is a decentralized/private inference stack for Apple Silicon Macs coordinator/ Go control plane ├── cmd/coordinator/ main service entrypoint ├── cmd/verify-attestation/ -│ └── main.go verifies attestation blobs from /tmp/eigeninference_attestation.json +│ └── main.go verifies attestation blobs from /tmp/darkbloom_attestation.json └── internal/ ├── api/ HTTP + WebSocket handlers │ ├── consumer.go OpenAI-compatible chat/completions/messages/transcriptions/images @@ -53,7 +53,7 @@ provider/ Rust provider agent for Apple Silicon Macs └── Cargo.toml default `python` feature enables in-process PyO3 inference image-bridge/ Python FastAPI image generation bridge -├── eigeninference_image_bridge/ +├── darkbloom_image_bridge/ │ ├── __main__.py │ ├── server.py OpenAI-compatible `/v1/images/generations` │ ├── drawthings_backend.py Draw Things gRPC backend adapter @@ -62,9 +62,9 @@ image-bridge/ Python FastAPI image generation bridge ├── requirements.txt └── tests/ pytest coverage for server/backend/integration -app/EigenInference/ SwiftUI macOS menu bar app -├── Sources/EigenInference/ -│ ├── EigenInferenceApp.swift +app/Darkbloom/ SwiftUI macOS menu bar app +├── Sources/Darkbloom/ +│ ├── DarkbloomApp.swift │ ├── StatusViewModel.swift │ ├── ProviderManager.swift │ ├── CLIRunner.swift @@ -79,13 +79,13 @@ app/EigenInference/ SwiftUI macOS menu bar app │ ├── MenuBarView.swift / SetupWizardView.swift │ ├── DoctorView.swift / LogViewerView.swift / ModelCatalogView.swift │ └── Resources/ -└── Tests/EigenInferenceTests/ +└── Tests/DarkbloomTests/ enclave/ Swift Secure Enclave helper + bridge binary -├── Sources/EigenInferenceEnclave/ enclave key + attestation library + FFI bridge -├── Sources/EigenInferenceEnclaveCLI/ `eigeninference-enclave` CLI (attest, sign, info) -├── Tests/EigenInferenceEnclaveTests/ -└── include/eigeninference_enclave.h +├── Sources/DarkbloomEnclave/ enclave key + attestation library + FFI bridge +├── Sources/DarkbloomEnclaveCLI/ `darkbloom-enclave` CLI (attest, sign, info) +├── Tests/DarkbloomEnclaveTests/ +└── include/darkbloom_enclave.h console-ui/ Next.js 16 / React 19 frontend ├── src/app/ chat, billing, images, models, stats, providers, settings, link, api-console, earn @@ -100,7 +100,7 @@ console-ui/ Next.js 16 / React 19 frontend scripts/ build, signing, install, and deploy helpers ├── build-bundle.sh provider/enclave/python/ffmpeg bundle builder (+ optional upload) -├── bundle-app.sh build EigenInference.app + DMG +├── bundle-app.sh build Darkbloom.app + DMG ├── install.sh end-user installer served from coordinator (hash + codesign verification) ├── sign-hardened.sh hardened runtime signing helper ├── admin.sh admin CLI (Privy auth, release mgmt, API calls) @@ -130,7 +130,7 @@ go build ./cmd/coordinator go build ./cmd/verify-attestation # Linux deployment build -GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o eigeninference-coordinator-linux ./cmd/coordinator +GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o darkbloom-coordinator-linux ./cmd/coordinator ``` ### Provider (Rust) @@ -156,7 +156,7 @@ PYTHONPATH=. pytest ### macOS App (Swift) ```bash -cd app/EigenInference +cd app/Darkbloom swift build -c release swift test ``` diff --git a/CLAUDE.md b/CLAUDE.md index c258e6149..52fa53499 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,4 +1,4 @@ -# EigenInference - Decentralized GPU Inference +# Darkbloom - Decentralized GPU Inference Decentralized inference network for Apple Silicon Macs. Providers offer GPU compute, consumers send OpenAI-compatible requests, the coordinator matches them. @@ -41,18 +41,18 @@ provider/ Rust — runs on Apple Silicon Macs ├── stt_server.py Local speech-to-text server script image-bridge/ Python FastAPI image generation bridge -├── eigeninference_image_bridge/ +├── darkbloom_image_bridge/ │ ├── server.py OpenAI-compatible /v1/images/generations │ └── drawthings_backend.py Draw Things gRPC backend adapter ├── requirements.txt └── tests/ -app/EigenInference/ Swift — macOS menu bar app (SwiftUI) -├── Sources/EigenInference/ -│ ├── EigenInferenceApp.swift App entry, menu bar setup +app/Darkbloom/ Swift — macOS menu bar app (SwiftUI) +├── Sources/Darkbloom/ +│ ├── DarkbloomApp.swift App entry, menu bar setup │ ├── StatusViewModel.swift Core state management │ ├── ProviderManager.swift Provider subprocess lifecycle -│ ├── CLIRunner.swift Launches eigeninference-provider +│ ├── CLIRunner.swift Launches darkbloom-provider │ ├── ConfigManager.swift TOML config read/write │ ├── SecurityManager.swift Trust level checks (SIP, SE, MDM, Secure Boot) │ ├── ModelManager.swift HuggingFace model scanning @@ -71,14 +71,14 @@ app/EigenInference/ Swift — macOS menu bar app (SwiftUI) │ ├── ModelCatalogView.swift Model browser with RAM fit indicators │ ├── GuideAvatar.swift Animated mascot (mood-based PNGs) │ └── Illustrations.swift Procedural Mac illustration -├── Tests/EigenInferenceTests/ +├── Tests/DarkbloomTests/ enclave/ Swift — Secure Enclave attestation CLI helper ├── Sources/ -│ ├── EigenInferenceEnclave/ Library (P-256 key gen, attestation blob, FFI bridge for Rust) -│ └── EigenInferenceEnclaveCLI/ CLI tool (attest, sign, info, wallet-address) -├── Tests/EigenInferenceEnclaveTests/ -└── include/eigeninference_enclave.h +│ ├── DarkbloomEnclave/ Library (P-256 key gen, attestation blob, FFI bridge for Rust) +│ └── DarkbloomEnclaveCLI/ CLI tool (attest, sign, info, wallet-address) +├── Tests/DarkbloomEnclaveTests/ +└── include/darkbloom_enclave.h console-ui/ Next.js 16 / React 19 frontend (chat, billing, models, images) ├── src/app/ Pages: chat (/), billing, images, models, stats, providers, settings, link, api-console, earn @@ -117,7 +117,7 @@ The `.external/` directory contains our fork of [vllm-mlx](https://github.com/Ga cd coordinator go test ./... # Cross-compile for the EigenCloud container (Linux amd64): -GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o eigeninference-coordinator-linux ./cmd/coordinator +GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o darkbloom-coordinator-linux ./cmd/coordinator ``` ### Provider (Rust) @@ -135,7 +135,7 @@ cargo build --release --no-default-features ### macOS App (Swift) ```bash -cd app/EigenInference +cd app/Darkbloom swift build -c release swift test ``` @@ -275,7 +275,7 @@ Always think from first principles. When fixing a bug or designing a feature: - Attestation tests need `AuthenticatedRootEnabled: true` in test blobs or the ARV check fails and overwrites earlier error messages (the checks run sequentially, last failure wins). - The `python` feature flag in the provider Cargo.toml links PyO3. Use `--no-default-features` when building for distribution to avoid Python linking issues. - The coordinator uses in-memory store by default. Provider state is lost on restart. Postgres store exists but is not used in production yet. -- Binary files like `coordinator/eigeninference-coordinator` and `coordinator/eigeninference-coordinator-linux` should NOT be committed to git (15MB+ each). +- Binary files like `coordinator/darkbloom-coordinator` and `coordinator/darkbloom-coordinator-linux` should NOT be committed to git (15MB+ each). - CI release workflow must compute binary SHA-256 hashes AFTER code signing, not before. Providers verify hashes of the signed binary. - Provider bundle semantics span multiple files: `scripts/build-bundle.sh`, `scripts/install.sh`, the Swift app launcher, and `LatestProviderVersion` in `coordinator/internal/api/server.go`. Keep them in sync. - Image generation changes span three places: coordinator consumer/provider handlers, provider proxying, and `image-bridge/`. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5c184f23e..28f7ac255 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -27,7 +27,7 @@ See [CLAUDE.md](CLAUDE.md) for the full layout and architectural decisions. The | `coordinator/` | Go | Central matchmaking server (runs on EigenCloud / GCP) | | `provider/` | Rust | Hardened daemon on Apple Silicon Macs | | `console-ui/` | Next.js 16 / React 19 | Web app (chat, billing, models) | -| `app/EigenInference/` | Swift / SwiftUI | macOS menu bar app for providers | +| `app/Darkbloom/` | Swift / SwiftUI | macOS menu bar app for providers | | `enclave/` | Swift | Secure Enclave attestation helper | | `image-bridge/` | Python / FastAPI | Image generation backend adapter | @@ -60,7 +60,7 @@ cd provider && PYO3_USE_ABI3_FORWARD_COMPATIBILITY=1 cargo test cd console-ui && npm install && npm test && npx eslint src/ # macOS app -cd app/EigenInference && swift test +cd app/Darkbloom && swift test # Enclave helper cd enclave && swift test diff --git a/README.md b/README.md index e34bdf5d7..545a28f68 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ from openai import OpenAI client = OpenAI( base_url="https://api.darkbloom.dev/v1", - api_key="eigeninference-..." + api_key="darkbloom-..." ) # Chat completion @@ -104,7 +104,7 @@ A native SwiftUI app is also available: ### Scheduling -Providers can configure time-based availability windows. Outside scheduled hours, the provider disconnects and shuts down the backend to free GPU memory. Configured in the app's Settings or directly in `~/.config/eigeninference/provider.toml`: +Providers can configure time-based availability windows. Outside scheduled hours, the provider disconnects and shuts down the backend to free GPU memory. Configured in the app's Settings or directly in `~/.config/darkbloom/provider.toml`: ```toml [schedule] @@ -158,7 +158,7 @@ Attestation data is publicly verifiable at `GET /v1/providers/attestation`. | Coordinator (`coordinator/`) | Go | Control plane: routing, attestation, billing, API | | Provider (`provider/`) | Rust | Inference agent: security, attestation, WebSocket client | | Console (`console-ui/`) | Next.js 16 | Web dashboard: chat, billing, provider verification | -| macOS App (`app/EigenInference/`) | Swift | Menu bar app: status, scheduling, earnings | +| macOS App (`app/Darkbloom/`) | Swift | Menu bar app: status, scheduling, earnings | | Secure Enclave (`enclave/`) | Swift | Hardware-bound P-256 identity | | Landing (`landing/`) | HTML | Static landing page | @@ -172,7 +172,7 @@ cd coordinator && go test ./... cd provider && cargo test # macOS App -cd app/EigenInference && swift build -c release +cd app/Darkbloom && swift build -c release # Console UI cd console-ui && npm install && npm run dev diff --git a/analytics/README.md b/analytics/README.md index 1d445c408..ce404e245 100644 --- a/analytics/README.md +++ b/analytics/README.md @@ -1,6 +1,6 @@ # Analytics -Standalone read-only analytics service for Darkbloom / EigenInference. +Standalone read-only analytics service for Darkbloom. This service is meant to sit beside the coordinator, not inside it. It serves public read models like: diff --git a/analytics/cmd/analytics/main.go b/analytics/cmd/analytics/main.go index f31719056..af019525e 100644 --- a/analytics/cmd/analytics/main.go +++ b/analytics/cmd/analytics/main.go @@ -10,10 +10,10 @@ import ( "syscall" "time" - "github.com/eigeninference/analytics/internal/config" - "github.com/eigeninference/analytics/internal/httpapi" - "github.com/eigeninference/analytics/internal/leaderboard" - "github.com/eigeninference/analytics/internal/pseudonym" + "github.com/darkbloom/analytics/internal/config" + "github.com/darkbloom/analytics/internal/httpapi" + "github.com/darkbloom/analytics/internal/leaderboard" + "github.com/darkbloom/analytics/internal/pseudonym" ) func main() { diff --git a/analytics/go.mod b/analytics/go.mod index b10de1964..20f34ea9d 100644 --- a/analytics/go.mod +++ b/analytics/go.mod @@ -1,4 +1,4 @@ -module github.com/eigeninference/analytics +module github.com/darkbloom/analytics go 1.25.0 diff --git a/analytics/internal/httpapi/server.go b/analytics/internal/httpapi/server.go index ccd214cc3..24f87365c 100644 --- a/analytics/internal/httpapi/server.go +++ b/analytics/internal/httpapi/server.go @@ -9,7 +9,7 @@ import ( "strings" "time" - "github.com/eigeninference/analytics/internal/leaderboard" + "github.com/darkbloom/analytics/internal/leaderboard" ) type Service interface { diff --git a/analytics/internal/httpapi/server_test.go b/analytics/internal/httpapi/server_test.go index cda93059b..cb8087fe8 100644 --- a/analytics/internal/httpapi/server_test.go +++ b/analytics/internal/httpapi/server_test.go @@ -9,8 +9,8 @@ import ( "testing" "time" - "github.com/eigeninference/analytics/internal/leaderboard" - "github.com/eigeninference/analytics/internal/pseudonym" + "github.com/darkbloom/analytics/internal/leaderboard" + "github.com/darkbloom/analytics/internal/pseudonym" ) func TestHealthz(t *testing.T) { diff --git a/analytics/internal/leaderboard/store_test.go b/analytics/internal/leaderboard/store_test.go index 58b2fc9d1..6e6230b64 100644 --- a/analytics/internal/leaderboard/store_test.go +++ b/analytics/internal/leaderboard/store_test.go @@ -5,7 +5,7 @@ import ( "testing" "time" - "github.com/eigeninference/analytics/internal/pseudonym" + "github.com/darkbloom/analytics/internal/pseudonym" ) func fixedNow() time.Time { diff --git a/app/EigenInference/Package.swift b/app/Darkbloom/Package.swift similarity index 55% rename from app/EigenInference/Package.swift rename to app/Darkbloom/Package.swift index b540a2838..1103f1165 100644 --- a/app/EigenInference/Package.swift +++ b/app/Darkbloom/Package.swift @@ -2,21 +2,21 @@ import PackageDescription let package = Package( - name: "EigenInference", + name: "Darkbloom", platforms: [.macOS(.v14)], dependencies: [], targets: [ .executableTarget( - name: "EigenInference", - path: "Sources/EigenInference", + name: "Darkbloom", + path: "Sources/Darkbloom", resources: [ .process("Resources"), ] ), .testTarget( - name: "EigenInferenceTests", - dependencies: ["EigenInference"], - path: "Tests/EigenInferenceTests" + name: "DarkbloomTests", + dependencies: ["Darkbloom"], + path: "Tests/DarkbloomTests" ), ] ) diff --git a/app/EigenInference/Sources/EigenInference/CLIRunner.swift b/app/Darkbloom/Sources/Darkbloom/CLIRunner.swift similarity index 100% rename from app/EigenInference/Sources/EigenInference/CLIRunner.swift rename to app/Darkbloom/Sources/Darkbloom/CLIRunner.swift diff --git a/app/EigenInference/Sources/EigenInference/ConfigManager.swift b/app/Darkbloom/Sources/Darkbloom/ConfigManager.swift similarity index 99% rename from app/EigenInference/Sources/EigenInference/ConfigManager.swift rename to app/Darkbloom/Sources/Darkbloom/ConfigManager.swift index 77e64dc63..d31d34876 100644 --- a/app/EigenInference/Sources/EigenInference/ConfigManager.swift +++ b/app/Darkbloom/Sources/Darkbloom/ConfigManager.swift @@ -6,7 +6,7 @@ /// /// TOML structure: /// [provider] -/// name = "eigeninference-mac16-1" +/// name = "darkbloom-mac16-1" /// memory_reserve_gb = 4 /// /// [backend] diff --git a/app/EigenInference/Sources/EigenInference/EigenInferenceApp.swift b/app/Darkbloom/Sources/Darkbloom/DarkbloomApp.swift similarity index 100% rename from app/EigenInference/Sources/EigenInference/EigenInferenceApp.swift rename to app/Darkbloom/Sources/Darkbloom/DarkbloomApp.swift diff --git a/app/EigenInference/Sources/EigenInference/DashboardView.swift b/app/Darkbloom/Sources/Darkbloom/DashboardView.swift similarity index 100% rename from app/EigenInference/Sources/EigenInference/DashboardView.swift rename to app/Darkbloom/Sources/Darkbloom/DashboardView.swift diff --git a/app/EigenInference/Sources/EigenInference/DesignSystem.swift b/app/Darkbloom/Sources/Darkbloom/DesignSystem.swift similarity index 100% rename from app/EigenInference/Sources/EigenInference/DesignSystem.swift rename to app/Darkbloom/Sources/Darkbloom/DesignSystem.swift diff --git a/app/EigenInference/Sources/EigenInference/DoctorView.swift b/app/Darkbloom/Sources/Darkbloom/DoctorView.swift similarity index 100% rename from app/EigenInference/Sources/EigenInference/DoctorView.swift rename to app/Darkbloom/Sources/Darkbloom/DoctorView.swift diff --git a/app/EigenInference/Sources/EigenInference/GuideAvatar.swift b/app/Darkbloom/Sources/Darkbloom/GuideAvatar.swift similarity index 100% rename from app/EigenInference/Sources/EigenInference/GuideAvatar.swift rename to app/Darkbloom/Sources/Darkbloom/GuideAvatar.swift diff --git a/app/EigenInference/Sources/EigenInference/IdleDetector.swift b/app/Darkbloom/Sources/Darkbloom/IdleDetector.swift similarity index 100% rename from app/EigenInference/Sources/EigenInference/IdleDetector.swift rename to app/Darkbloom/Sources/Darkbloom/IdleDetector.swift diff --git a/app/EigenInference/Sources/EigenInference/Illustrations.swift b/app/Darkbloom/Sources/Darkbloom/Illustrations.swift similarity index 100% rename from app/EigenInference/Sources/EigenInference/Illustrations.swift rename to app/Darkbloom/Sources/Darkbloom/Illustrations.swift diff --git a/app/EigenInference/Sources/EigenInference/LaunchAgentManager.swift b/app/Darkbloom/Sources/Darkbloom/LaunchAgentManager.swift similarity index 100% rename from app/EigenInference/Sources/EigenInference/LaunchAgentManager.swift rename to app/Darkbloom/Sources/Darkbloom/LaunchAgentManager.swift diff --git a/app/EigenInference/Sources/EigenInference/LogViewerView.swift b/app/Darkbloom/Sources/Darkbloom/LogViewerView.swift similarity index 100% rename from app/EigenInference/Sources/EigenInference/LogViewerView.swift rename to app/Darkbloom/Sources/Darkbloom/LogViewerView.swift diff --git a/app/EigenInference/Sources/EigenInference/MenuBarView.swift b/app/Darkbloom/Sources/Darkbloom/MenuBarView.swift similarity index 100% rename from app/EigenInference/Sources/EigenInference/MenuBarView.swift rename to app/Darkbloom/Sources/Darkbloom/MenuBarView.swift diff --git a/app/EigenInference/Sources/EigenInference/ModelCatalog.swift b/app/Darkbloom/Sources/Darkbloom/ModelCatalog.swift similarity index 100% rename from app/EigenInference/Sources/EigenInference/ModelCatalog.swift rename to app/Darkbloom/Sources/Darkbloom/ModelCatalog.swift diff --git a/app/EigenInference/Sources/EigenInference/ModelCatalogView.swift b/app/Darkbloom/Sources/Darkbloom/ModelCatalogView.swift similarity index 100% rename from app/EigenInference/Sources/EigenInference/ModelCatalogView.swift rename to app/Darkbloom/Sources/Darkbloom/ModelCatalogView.swift diff --git a/app/EigenInference/Sources/EigenInference/ModelManager.swift b/app/Darkbloom/Sources/Darkbloom/ModelManager.swift similarity index 100% rename from app/EigenInference/Sources/EigenInference/ModelManager.swift rename to app/Darkbloom/Sources/Darkbloom/ModelManager.swift diff --git a/app/EigenInference/Sources/EigenInference/NotificationManager.swift b/app/Darkbloom/Sources/Darkbloom/NotificationManager.swift similarity index 100% rename from app/EigenInference/Sources/EigenInference/NotificationManager.swift rename to app/Darkbloom/Sources/Darkbloom/NotificationManager.swift diff --git a/app/EigenInference/Sources/EigenInference/ProviderManager.swift b/app/Darkbloom/Sources/Darkbloom/ProviderManager.swift similarity index 100% rename from app/EigenInference/Sources/EigenInference/ProviderManager.swift rename to app/Darkbloom/Sources/Darkbloom/ProviderManager.swift diff --git a/app/EigenInference/Sources/EigenInference/Resources/AppIcon-full.png b/app/Darkbloom/Sources/Darkbloom/Resources/AppIcon-full.png similarity index 100% rename from app/EigenInference/Sources/EigenInference/Resources/AppIcon-full.png rename to app/Darkbloom/Sources/Darkbloom/Resources/AppIcon-full.png diff --git a/app/EigenInference/Sources/EigenInference/Resources/AppIcon.png b/app/Darkbloom/Sources/Darkbloom/Resources/AppIcon.png similarity index 100% rename from app/EigenInference/Sources/EigenInference/Resources/AppIcon.png rename to app/Darkbloom/Sources/Darkbloom/Resources/AppIcon.png diff --git a/app/EigenInference/Sources/EigenInference/Resources/MenuBarIcon.png b/app/Darkbloom/Sources/Darkbloom/Resources/MenuBarIcon.png similarity index 100% rename from app/EigenInference/Sources/EigenInference/Resources/MenuBarIcon.png rename to app/Darkbloom/Sources/Darkbloom/Resources/MenuBarIcon.png diff --git a/app/EigenInference/Sources/EigenInference/Resources/MenuBarIcon@2x.png b/app/Darkbloom/Sources/Darkbloom/Resources/MenuBarIcon@2x.png similarity index 100% rename from app/EigenInference/Sources/EigenInference/Resources/MenuBarIcon@2x.png rename to app/Darkbloom/Sources/Darkbloom/Resources/MenuBarIcon@2x.png diff --git a/app/EigenInference/Sources/EigenInference/Resources/guide-avatar-celebrating.png b/app/Darkbloom/Sources/Darkbloom/Resources/guide-avatar-celebrating.png similarity index 100% rename from app/EigenInference/Sources/EigenInference/Resources/guide-avatar-celebrating.png rename to app/Darkbloom/Sources/Darkbloom/Resources/guide-avatar-celebrating.png diff --git a/app/EigenInference/Sources/EigenInference/Resources/guide-avatar-concerned.png b/app/Darkbloom/Sources/Darkbloom/Resources/guide-avatar-concerned.png similarity index 100% rename from app/EigenInference/Sources/EigenInference/Resources/guide-avatar-concerned.png rename to app/Darkbloom/Sources/Darkbloom/Resources/guide-avatar-concerned.png diff --git a/app/EigenInference/Sources/EigenInference/Resources/guide-avatar-excited.png b/app/Darkbloom/Sources/Darkbloom/Resources/guide-avatar-excited.png similarity index 100% rename from app/EigenInference/Sources/EigenInference/Resources/guide-avatar-excited.png rename to app/Darkbloom/Sources/Darkbloom/Resources/guide-avatar-excited.png diff --git a/app/EigenInference/Sources/EigenInference/Resources/guide-avatar-explaining.png b/app/Darkbloom/Sources/Darkbloom/Resources/guide-avatar-explaining.png similarity index 100% rename from app/EigenInference/Sources/EigenInference/Resources/guide-avatar-explaining.png rename to app/Darkbloom/Sources/Darkbloom/Resources/guide-avatar-explaining.png diff --git a/app/EigenInference/Sources/EigenInference/Resources/guide-avatar-greeting.png b/app/Darkbloom/Sources/Darkbloom/Resources/guide-avatar-greeting.png similarity index 100% rename from app/EigenInference/Sources/EigenInference/Resources/guide-avatar-greeting.png rename to app/Darkbloom/Sources/Darkbloom/Resources/guide-avatar-greeting.png diff --git a/app/EigenInference/Sources/EigenInference/Resources/guide-avatar-thinking.png b/app/Darkbloom/Sources/Darkbloom/Resources/guide-avatar-thinking.png similarity index 100% rename from app/EigenInference/Sources/EigenInference/Resources/guide-avatar-thinking.png rename to app/Darkbloom/Sources/Darkbloom/Resources/guide-avatar-thinking.png diff --git a/app/EigenInference/Sources/EigenInference/Resources/guide-avatar.png b/app/Darkbloom/Sources/Darkbloom/Resources/guide-avatar.png similarity index 100% rename from app/EigenInference/Sources/EigenInference/Resources/guide-avatar.png rename to app/Darkbloom/Sources/Darkbloom/Resources/guide-avatar.png diff --git a/app/EigenInference/Sources/EigenInference/SecurityManager.swift b/app/Darkbloom/Sources/Darkbloom/SecurityManager.swift similarity index 99% rename from app/EigenInference/Sources/EigenInference/SecurityManager.swift rename to app/Darkbloom/Sources/Darkbloom/SecurityManager.swift index 93a918400..44a2d1ca4 100644 --- a/app/EigenInference/Sources/EigenInference/SecurityManager.swift +++ b/app/Darkbloom/Sources/Darkbloom/SecurityManager.swift @@ -101,7 +101,7 @@ final class SecurityManager: ObservableObject { let profiles = await CLIRunner.shell("profiles list 2>&1") let combined = (profiles.stdout + profiles.stderr).lowercased() if combined.contains("micromdm") || combined.contains("darkbloom") || - combined.contains("eigeninference") || + combined.contains("darkbloom") || combined.contains("com.github.micromdm") { return true } diff --git a/app/EigenInference/Sources/EigenInference/SettingsView.swift b/app/Darkbloom/Sources/Darkbloom/SettingsView.swift similarity index 100% rename from app/EigenInference/Sources/EigenInference/SettingsView.swift rename to app/Darkbloom/Sources/Darkbloom/SettingsView.swift diff --git a/app/EigenInference/Sources/EigenInference/SetupWizardView.swift b/app/Darkbloom/Sources/Darkbloom/SetupWizardView.swift similarity index 100% rename from app/EigenInference/Sources/EigenInference/SetupWizardView.swift rename to app/Darkbloom/Sources/Darkbloom/SetupWizardView.swift diff --git a/app/EigenInference/Sources/EigenInference/StatusViewModel.swift b/app/Darkbloom/Sources/Darkbloom/StatusViewModel.swift similarity index 99% rename from app/EigenInference/Sources/EigenInference/StatusViewModel.swift rename to app/Darkbloom/Sources/Darkbloom/StatusViewModel.swift index 0ed56c212..ce5de69d3 100644 --- a/app/EigenInference/Sources/EigenInference/StatusViewModel.swift +++ b/app/Darkbloom/Sources/Darkbloom/StatusViewModel.swift @@ -442,8 +442,8 @@ final class StatusViewModel: ObservableObject { /// Parse tracing-formatted output from the provider binary. /// /// The Rust binary uses `tracing` which outputs lines like: - /// 2026-03-24T10:00:00.123Z INFO eigeninference_provider: Connected to coordinator - /// 2026-03-24T10:00:01.234Z INFO eigeninference_provider: Received inference request: req-abc + /// 2026-03-24T10:00:00.123Z INFO darkbloom_provider: Connected to coordinator + /// 2026-03-24T10:00:01.234Z INFO darkbloom_provider: Received inference request: req-abc private func parseProviderOutput(_ line: String) { guard !line.isEmpty else { return } let lower = line.lowercased() diff --git a/app/EigenInference/Sources/EigenInference/TelemetryReporter.swift b/app/Darkbloom/Sources/Darkbloom/TelemetryReporter.swift similarity index 100% rename from app/EigenInference/Sources/EigenInference/TelemetryReporter.swift rename to app/Darkbloom/Sources/Darkbloom/TelemetryReporter.swift diff --git a/app/EigenInference/Sources/EigenInference/UpdateManager.swift b/app/Darkbloom/Sources/Darkbloom/UpdateManager.swift similarity index 100% rename from app/EigenInference/Sources/EigenInference/UpdateManager.swift rename to app/Darkbloom/Sources/Darkbloom/UpdateManager.swift diff --git a/app/EigenInference/Tests/EigenInferenceTests/CLIRunnerTests.swift b/app/Darkbloom/Tests/DarkbloomTests/CLIRunnerTests.swift similarity index 99% rename from app/EigenInference/Tests/EigenInferenceTests/CLIRunnerTests.swift rename to app/Darkbloom/Tests/DarkbloomTests/CLIRunnerTests.swift index b39f7862d..819e8f66a 100644 --- a/app/EigenInference/Tests/EigenInferenceTests/CLIRunnerTests.swift +++ b/app/Darkbloom/Tests/DarkbloomTests/CLIRunnerTests.swift @@ -2,7 +2,7 @@ import Testing import Foundation -@testable import EigenInference +@testable import Darkbloom @Suite("CLIRunner - Binary Resolution") struct CLIRunnerBinaryTests { diff --git a/app/EigenInference/Tests/EigenInferenceTests/ConfigManagerTests.swift b/app/Darkbloom/Tests/DarkbloomTests/ConfigManagerTests.swift similarity index 98% rename from app/EigenInference/Tests/EigenInferenceTests/ConfigManagerTests.swift rename to app/Darkbloom/Tests/DarkbloomTests/ConfigManagerTests.swift index 7ab21b3d4..90ea013f7 100644 --- a/app/EigenInference/Tests/EigenInferenceTests/ConfigManagerTests.swift +++ b/app/Darkbloom/Tests/DarkbloomTests/ConfigManagerTests.swift @@ -2,7 +2,7 @@ import Testing import Foundation -@testable import EigenInference +@testable import Darkbloom @Suite("ConfigManager - Default Values") struct ConfigDefaultTests { @@ -246,7 +246,7 @@ struct ConfigRoundTripTests { @Test("save and load round trip to temp directory") func saveLoadRoundTrip() throws { let tmpDir = FileManager.default.temporaryDirectory - .appendingPathComponent("eigeninference-test-\(UUID().uuidString)") + .appendingPathComponent("darkbloom-test-\(UUID().uuidString)") let tmpFile = tmpDir.appendingPathComponent("provider.toml") defer { diff --git a/app/EigenInference/Tests/EigenInferenceTests/EigenInferenceAppTests.swift b/app/Darkbloom/Tests/DarkbloomTests/DarkbloomAppTests.swift similarity index 98% rename from app/EigenInference/Tests/EigenInferenceTests/EigenInferenceAppTests.swift rename to app/Darkbloom/Tests/DarkbloomTests/DarkbloomAppTests.swift index 36b197651..3e46aeade 100644 --- a/app/EigenInference/Tests/EigenInferenceTests/EigenInferenceAppTests.swift +++ b/app/Darkbloom/Tests/DarkbloomTests/DarkbloomAppTests.swift @@ -1,4 +1,4 @@ -/// EigenInferenceAppTests — Unit tests for the EigenInference menu bar app. +/// DarkbloomAppTests — Unit tests for the Darkbloom menu bar app. /// /// Tests cover all components: /// - CLIRunner: binary resolution, command execution @@ -12,7 +12,7 @@ import Testing import Foundation -@testable import EigenInference +@testable import Darkbloom // MARK: - CLIRunner Tests @@ -396,7 +396,7 @@ struct OutputParsingTests { vm.isOnline = false // Simulate tracing output - vm.providerManager.lastOutputLine = "2026-03-24T10:00:00Z INFO eigeninference_provider: Connected to coordinator" + vm.providerManager.lastOutputLine = "2026-03-24T10:00:00Z INFO darkbloom_provider: Connected to coordinator" // Give Combine time to propagate // Since parseProviderOutput is called via Combine sink, we test the method directly diff --git a/app/EigenInference/Tests/EigenInferenceTests/TelemetryReporterTests.swift b/app/Darkbloom/Tests/DarkbloomTests/TelemetryReporterTests.swift similarity index 98% rename from app/EigenInference/Tests/EigenInferenceTests/TelemetryReporterTests.swift rename to app/Darkbloom/Tests/DarkbloomTests/TelemetryReporterTests.swift index 7460f5692..a357a5b4a 100644 --- a/app/EigenInference/Tests/EigenInferenceTests/TelemetryReporterTests.swift +++ b/app/Darkbloom/Tests/DarkbloomTests/TelemetryReporterTests.swift @@ -3,7 +3,7 @@ import Testing import Foundation -@testable import EigenInference +@testable import Darkbloom @Suite("TelemetryReporter") struct TelemetryReporterTests { diff --git a/app/EigenInference/Tests/EigenInferenceTests/UpdateManagerTests.swift b/app/Darkbloom/Tests/DarkbloomTests/UpdateManagerTests.swift similarity index 99% rename from app/EigenInference/Tests/EigenInferenceTests/UpdateManagerTests.swift rename to app/Darkbloom/Tests/DarkbloomTests/UpdateManagerTests.swift index 59a3a68f3..f189c5f4f 100644 --- a/app/EigenInference/Tests/EigenInferenceTests/UpdateManagerTests.swift +++ b/app/Darkbloom/Tests/DarkbloomTests/UpdateManagerTests.swift @@ -2,7 +2,7 @@ import Testing import Foundation -@testable import EigenInference +@testable import Darkbloom @Suite("UpdateManager - Version Comparison") struct UpdateManagerVersionTests { diff --git a/console-ui/__tests__/encryption.test.ts b/console-ui/__tests__/encryption.test.ts index a954c1641..6d6563550 100644 --- a/console-ui/__tests__/encryption.test.ts +++ b/console-ui/__tests__/encryption.test.ts @@ -2,6 +2,7 @@ import { describe, it, expect, beforeEach, afterEach, vi } from "vitest"; import nacl from "tweetnacl"; import { SEALED_CONTENT_TYPE, + LEGACY_SEALED_CONTENT_TYPE, ENCRYPTION_FLAG_KEY, clearCoordinatorKeyCache, getCoordinatorKey, @@ -214,6 +215,9 @@ describe("encryption — toggle persistence", () => { // Sanity-check the exported constant matches what the coordinator expects. describe("encryption — constants", () => { it("SEALED_CONTENT_TYPE matches the coordinator's media type", () => { - expect(SEALED_CONTENT_TYPE).toBe("application/eigeninference-sealed+json"); + expect(SEALED_CONTENT_TYPE).toBe("application/darkbloom-sealed+json"); + }); + it("LEGACY_SEALED_CONTENT_TYPE matches the pre-rename media type", () => { + expect(LEGACY_SEALED_CONTENT_TYPE).toBe("application/eigeninference-sealed+json"); }); }); diff --git a/console-ui/src/app/api/chat/route.ts b/console-ui/src/app/api/chat/route.ts index 7e9e35656..bbeaa21bf 100644 --- a/console-ui/src/app/api/chat/route.ts +++ b/console-ui/src/app/api/chat/route.ts @@ -4,7 +4,8 @@ export const runtime = "nodejs"; // Disable body parsing and response buffering for streaming export const dynamic = "force-dynamic"; -const SEALED_CT = "application/eigeninference-sealed+json"; +const SEALED_CT = "application/darkbloom-sealed+json"; +const LEGACY_SEALED_CT = "application/eigeninference-sealed+json"; const COORD_URL = process.env.NEXT_PUBLIC_COORDINATOR_URL || "https://api.darkbloom.dev"; @@ -12,7 +13,9 @@ export async function POST(req: NextRequest) { const coordUrl = COORD_URL; const apiKey = req.headers.get("x-api-key") || ""; const incomingCt = req.headers.get("content-type") || "application/json"; - const isSealed = incomingCt.toLowerCase().startsWith(SEALED_CT); + const isSealed = + incomingCt.toLowerCase().startsWith(SEALED_CT) || + incomingCt.toLowerCase().startsWith(LEGACY_SEALED_CT); // Forward the body bytes verbatim. For plaintext we keep the existing // JSON-roundtrip behavior (preserves the existing tests); for sealed we diff --git a/console-ui/src/components/providers/ThemeProvider.tsx b/console-ui/src/components/providers/ThemeProvider.tsx index 7791461d8..a3d3410bb 100644 --- a/console-ui/src/components/providers/ThemeProvider.tsx +++ b/console-ui/src/components/providers/ThemeProvider.tsx @@ -3,7 +3,7 @@ import { createContext, useContext, useEffect, useState } from "react"; import { migrateStorage } from "@/lib/migrate-storage"; -// Migrate old eigeninference_* localStorage keys to darkbloom_* before any +// Migrate old darkbloom_* localStorage keys to darkbloom_* before any // component reads them. Module-scope call ensures it runs once on bundle load. migrateStorage(); diff --git a/console-ui/src/lib/api.ts b/console-ui/src/lib/api.ts index 6a008a809..18b21d6f2 100644 --- a/console-ui/src/lib/api.ts +++ b/console-ui/src/lib/api.ts @@ -5,6 +5,7 @@ import { SEALED_CONTENT_TYPE, + LEGACY_SEALED_CONTENT_TYPE, clearCoordinatorKeyCache, getCoordinatorKey, isEncryptionEnabled, @@ -366,7 +367,8 @@ export async function streamChat( const errCt = res.headers.get("content-type") || ""; const errSealed = sealCtx && (res.headers.get("x-eigen-sealed") === "true" || - errCt.toLowerCase().startsWith(SEALED_CONTENT_TYPE)); + errCt.toLowerCase().startsWith(SEALED_CONTENT_TYPE) || + errCt.toLowerCase().startsWith(LEGACY_SEALED_CONTENT_TYPE)); if (errSealed && sealCtx) { try { const pt = unsealResponse(text, sealCtx.ephemPriv, sealCtx.coordPub); diff --git a/console-ui/src/lib/encryption.ts b/console-ui/src/lib/encryption.ts index baa3189fa..5ce9972af 100644 --- a/console-ui/src/lib/encryption.ts +++ b/console-ui/src/lib/encryption.ts @@ -3,7 +3,7 @@ // Mirror of coordinator/internal/api/sender_encryption.go. Senders fetch the // coordinator's long-lived X25519 public key from /v1/encryption-key, NaCl- // Box-seal each request body to it, and POST as -// Content-Type: application/eigeninference-sealed+json. +// Content-Type: application/darkbloom-sealed+json. // // Per-request: a fresh ephemeral X25519 keypair gives forward secrecy. The // coordinator seals its response back using the sender's ephemeral pubkey @@ -14,7 +14,8 @@ import nacl from "tweetnacl"; -export const SEALED_CONTENT_TYPE = "application/eigeninference-sealed+json"; +export const SEALED_CONTENT_TYPE = "application/darkbloom-sealed+json"; +export const LEGACY_SEALED_CONTENT_TYPE = "application/eigeninference-sealed+json"; export const ENCRYPTION_FLAG_KEY = "darkbloom_encrypt_to_coordinator"; const COORD_KEY_CACHE_KEY = "darkbloom_coord_enc_key_v2"; // v2: keyed-per-URL const COORD_KEY_TTL_MS = 60 * 60 * 1000; // 1 hour diff --git a/coordinator/cmd/coordinator/main.go b/coordinator/cmd/coordinator/main.go index f2c69ee33..a911cf2d8 100644 --- a/coordinator/cmd/coordinator/main.go +++ b/coordinator/cmd/coordinator/main.go @@ -1,4 +1,4 @@ -// Command coordinator runs the Darkbloom (EigenInference) coordinator control plane. +// Command coordinator runs the Darkbloom coordinator control plane. // // The coordinator is the central routing and trust layer in the Darkbloom network. // It accepts provider WebSocket connections, verifies their Secure Enclave @@ -12,6 +12,12 @@ // // Configuration (environment variables): // +// NOTE: Environment variable names intentionally retain the EIGENINFERENCE_ prefix. +// They have not been migrated to DARKBLOOM_ to avoid breaking production deployments +// that already have these vars configured in EigenCloud KMS and GCP Secret Manager. +// Forward migration: when you reconfigure all deployment environments, replace each +// EIGENINFERENCE_* name with the equivalent DARKBLOOM_* name and update this block. +// // EIGENINFERENCE_PORT - HTTP listen port (default: "8080") // EIGENINFERENCE_ADMIN_KEY - Pre-seeded API key for bootstrapping // EIGENINFERENCE_DATABASE_URL - PostgreSQL connection string (REQUIRED in @@ -38,19 +44,19 @@ import ( "strconv" - "github.com/eigeninference/coordinator/internal/api" - "github.com/eigeninference/coordinator/internal/attestation" - "github.com/eigeninference/coordinator/internal/auth" - "github.com/eigeninference/coordinator/internal/billing" - "github.com/eigeninference/coordinator/internal/datadog" - "github.com/eigeninference/coordinator/internal/e2e" - "github.com/eigeninference/coordinator/internal/mdm" - "github.com/eigeninference/coordinator/internal/payments" - "github.com/eigeninference/coordinator/internal/ratelimit" - "github.com/eigeninference/coordinator/internal/registry" - "github.com/eigeninference/coordinator/internal/saferun" - "github.com/eigeninference/coordinator/internal/store" - "github.com/eigeninference/coordinator/internal/telemetry" + "github.com/darkbloom/coordinator/internal/api" + "github.com/darkbloom/coordinator/internal/attestation" + "github.com/darkbloom/coordinator/internal/auth" + "github.com/darkbloom/coordinator/internal/billing" + "github.com/darkbloom/coordinator/internal/datadog" + "github.com/darkbloom/coordinator/internal/e2e" + "github.com/darkbloom/coordinator/internal/mdm" + "github.com/darkbloom/coordinator/internal/payments" + "github.com/darkbloom/coordinator/internal/ratelimit" + "github.com/darkbloom/coordinator/internal/registry" + "github.com/darkbloom/coordinator/internal/saferun" + "github.com/darkbloom/coordinator/internal/store" + "github.com/darkbloom/coordinator/internal/telemetry" ddtracer "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer" ) @@ -413,7 +419,7 @@ func main() { if mdmURL := os.Getenv("EIGENINFERENCE_MDM_URL"); mdmURL != "" { mdmKey := os.Getenv("EIGENINFERENCE_MDM_API_KEY") if mdmKey == "" { - mdmKey = "eigeninference-micromdm-api" // default + mdmKey = "eigeninference-micromdm-api" // legacy default } mdmClient := mdm.NewClient(mdmURL, mdmKey, logger) diff --git a/coordinator/cmd/coordinator/main_test.go b/coordinator/cmd/coordinator/main_test.go index 2ccb62774..c97da6cb8 100644 --- a/coordinator/cmd/coordinator/main_test.go +++ b/coordinator/cmd/coordinator/main_test.go @@ -5,7 +5,7 @@ import ( "log/slog" "testing" - "github.com/eigeninference/coordinator/internal/store" + "github.com/darkbloom/coordinator/internal/store" ) func TestSeedModelCatalogRemovesRetiredProviderModels(t *testing.T) { diff --git a/coordinator/cmd/verify-attestation/main.go b/coordinator/cmd/verify-attestation/main.go index 980e374d4..5dcd1bbe4 100644 --- a/coordinator/cmd/verify-attestation/main.go +++ b/coordinator/cmd/verify-attestation/main.go @@ -4,11 +4,11 @@ import ( "fmt" "os" - "github.com/eigeninference/coordinator/internal/attestation" + "github.com/darkbloom/coordinator/internal/attestation" ) func main() { - data, err := os.ReadFile("/tmp/eigeninference_attestation.json") + data, err := os.ReadFile("/tmp/darkbloom_attestation.json") if err != nil { fmt.Fprintf(os.Stderr, "read: %v\n", err) os.Exit(1) diff --git a/coordinator/deploy/start.sh b/coordinator/deploy/start.sh index 39727b5ac..08e1a2836 100644 --- a/coordinator/deploy/start.sh +++ b/coordinator/deploy/start.sh @@ -9,10 +9,18 @@ mkdir -p "$PERSIST/step-ca" "$PERSIST/micromdm" ln -sfn "$PERSIST" /data # ---- step-ca ---- +# Migrate legacy step-ca password if needed (existing VMs have eigeninference-step-ca). +if [ -f /data/step-ca/secrets/password ]; then + PW=$(cat /data/step-ca/secrets/password) + if [ "$PW" = "eigeninference-step-ca" ]; then + echo "Migrating step-ca password..." + echo "darkbloom-step-ca" > /data/step-ca/secrets/password + fi +fi if [ ! -d "/data/step-ca/config" ]; then echo "Initializing step-ca (first boot)..." mkdir -p /data/step-ca/secrets - echo "eigeninference-step-ca" > /data/step-ca/secrets/password + echo "darkbloom-step-ca" > /data/step-ca/secrets/password # Copy Apple attestation root CA and ACME template to persistent storage mkdir -p /data/step-ca/apple /data/step-ca/templates @@ -23,18 +31,30 @@ if [ ! -d "/data/step-ca/config" ]; then --name "Darkbloom CA" \ --dns "${DOMAIN:-localhost}" \ --address ":9000" \ - --provisioner "eigeninference-admin" \ + --provisioner "darkbloom-admin" \ --password-file /data/step-ca/secrets/password \ --deployment-type standalone \ --acme 2>&1 echo "step-ca initialized." # Patch ca.json: replace the default ACME provisioner with one configured - # for device-attest-01 (Apple Secure Enclave attestation). + # for device-attest-01 (Apple Secure Enclave attestation), and add a legacy + # alias provisioner so already-enrolled devices can still renew certs. echo "Configuring ACME device-attest-01 provisioner..." CA_JSON=/data/step-ca/config/ca.json - jq '(.authority.provisioners[] | select(.type == "ACME")) |= - { + ACME_PROV='{ + "type": "ACME", + "name": "darkbloom-acme", + "challenges": ["device-attest-01"], + "attestationFormats": ["apple"], + "forceCN": false, + "options": { + "x509": { + "templateFile": "/data/step-ca/templates/acme-device.tpl" + } + } + }' + LEGACY_ACME_PROV='{ "type": "ACME", "name": "eigeninference-acme", "challenges": ["device-attest-01"], @@ -45,8 +65,24 @@ if [ ! -d "/data/step-ca/config" ]; then "templateFile": "/data/step-ca/templates/acme-device.tpl" } } - }' "$CA_JSON" > /tmp/ca.json && mv /tmp/ca.json "$CA_JSON" - echo "ACME provisioner configured." + }' + jq --argjson acme "$ACME_PROV" --argjson legacy "$LEGACY_ACME_PROV" \ + '(.authority.provisioners[] | select(.type == "ACME")) |= $acme | + .authority.provisioners += [$legacy]' \ + "$CA_JSON" > /tmp/ca.json && mv /tmp/ca.json "$CA_JSON" + echo "ACME provisioner configured (darkbloom-acme + eigeninference-acme alias)." + + # Add eigeninference-admin as a JWK provisioner alias sharing the same key + # as darkbloom-admin, so existing clients using the old provisioner name + # can still sign certificate requests. + echo "Adding eigeninference-admin JWK provisioner alias..." + ADMIN_KEY=$(jq -r '.authority.provisioners[] | select(.type=="JWK" and .name=="darkbloom-admin") | .key' "$CA_JSON") + ADMIN_ENC_KEY=$(jq -r '.authority.provisioners[] | select(.type=="JWK" and .name=="darkbloom-admin") | .encryptedKey' "$CA_JSON") + LEGACY_JWK=$(jq -n --arg key "$ADMIN_KEY" --arg encKey "$ADMIN_ENC_KEY" \ + '{type: "JWK", name: "eigeninference-admin", key: $key, encryptedKey: $encKey}') + jq --argjson jwk "$LEGACY_JWK" '.authority.provisioners += [$jwk]' \ + "$CA_JSON" > /tmp/ca.json && mv /tmp/ca.json "$CA_JSON" + echo "JWK provisioner alias configured (darkbloom-admin + eigeninference-admin)." fi echo "Starting step-ca..." STEPPATH=/data/step-ca step-ca /data/step-ca/config/ca.json \ @@ -61,8 +97,12 @@ if [ -n "$MICROMDM_API_KEY" ]; then if [ -n "$MDM_PUSH_P12_B64" ] && [ ! -f /data/micromdm/push.crt ]; then echo "Decoding MDM push certificate from PKCS#12..." printf '%s' "$MDM_PUSH_P12_B64" | tr '_-' '/+' | base64 -d > /tmp/push.p12 + openssl pkcs12 -in /tmp/push.p12 -clcerts -nokeys -passin pass:darkbloom \ + -out /data/micromdm/push.crt 2>/dev/null || \ openssl pkcs12 -in /tmp/push.p12 -clcerts -nokeys -passin pass:eigeninference \ -out /data/micromdm/push.crt 2>/dev/null + openssl pkcs12 -in /tmp/push.p12 -nocerts -nodes -passin pass:darkbloom \ + -out /tmp/push_pkcs8.key 2>/dev/null || \ openssl pkcs12 -in /tmp/push.p12 -nocerts -nodes -passin pass:eigeninference \ -out /tmp/push_pkcs8.key 2>/dev/null openssl rsa -in /tmp/push_pkcs8.key -traditional -out /data/micromdm/push.key 2>/dev/null @@ -83,7 +123,7 @@ if [ -n "$MICROMDM_API_KEY" ]; then echo "Starting MicroMDM..." micromdm serve \ -server-url "https://${DOMAIN:-localhost}" \ - -api-key "${MICROMDM_API_KEY:-eigeninference-micromdm-api}" \ + -api-key "${MICROMDM_API_KEY:-${MICROMDM_API_KEY_FALLBACK:-darkbloom-micromdm-api}}" \ -filerepo /data/micromdm \ -config-path /data/micromdm \ -tls-cert /data/micromdm/server.crt \ @@ -98,9 +138,9 @@ if [ -n "$MICROMDM_API_KEY" ]; then if [ -f /data/micromdm/push.crt ] && [ ! -f /data/micromdm/.push_imported ]; then echo "Importing MDM push certificate..." mdmctl config set \ - -name eigeninference \ + -name darkbloom \ -server-url "https://localhost:9002" \ - -api-token "${MICROMDM_API_KEY:-eigeninference-micromdm-api}" \ + -api-token "${MICROMDM_API_KEY:-${MICROMDM_API_KEY_FALLBACK:-darkbloom-micromdm-api}}" \ -skip-verify mdmctl mdmcert upload \ -cert /data/micromdm/push.crt \ diff --git a/coordinator/go.mod b/coordinator/go.mod index 66c8461c2..63e254386 100644 --- a/coordinator/go.mod +++ b/coordinator/go.mod @@ -1,4 +1,4 @@ -module github.com/eigeninference/coordinator +module github.com/darkbloom/coordinator go 1.25.0 diff --git a/coordinator/internal/api/billing_earnings_test.go b/coordinator/internal/api/billing_earnings_test.go index ece96e3fd..2458e278d 100644 --- a/coordinator/internal/api/billing_earnings_test.go +++ b/coordinator/internal/api/billing_earnings_test.go @@ -8,7 +8,7 @@ import ( "testing" "time" - "github.com/eigeninference/coordinator/internal/store" + "github.com/darkbloom/coordinator/internal/store" ) type accountEarningsResponse struct { diff --git a/coordinator/internal/api/billing_handlers.go b/coordinator/internal/api/billing_handlers.go index 2216575a8..efcf25a44 100644 --- a/coordinator/internal/api/billing_handlers.go +++ b/coordinator/internal/api/billing_handlers.go @@ -22,10 +22,10 @@ import ( "strings" "time" - "github.com/eigeninference/coordinator/internal/auth" - "github.com/eigeninference/coordinator/internal/billing" - "github.com/eigeninference/coordinator/internal/payments" - "github.com/eigeninference/coordinator/internal/store" + "github.com/darkbloom/coordinator/internal/auth" + "github.com/darkbloom/coordinator/internal/billing" + "github.com/darkbloom/coordinator/internal/payments" + "github.com/darkbloom/coordinator/internal/store" "github.com/google/uuid" ) @@ -83,7 +83,7 @@ func (s *Server) handleStripeCreateSession(w http.ResponseWriter, r *http.Reques CustomerEmail: req.Email, Metadata: map[string]string{ "app": "darkbloom", - "platform": "eigeninference", + "platform": "darkbloom", "purchase_type": "inference_credits", "source": "coordinator", "coordinator_host": r.Host, diff --git a/coordinator/internal/api/billing_integration_test.go b/coordinator/internal/api/billing_integration_test.go index d782fdf52..706172e73 100644 --- a/coordinator/internal/api/billing_integration_test.go +++ b/coordinator/internal/api/billing_integration_test.go @@ -20,11 +20,11 @@ import ( "testing" "time" - "github.com/eigeninference/coordinator/internal/billing" - "github.com/eigeninference/coordinator/internal/payments" - "github.com/eigeninference/coordinator/internal/protocol" - "github.com/eigeninference/coordinator/internal/registry" - "github.com/eigeninference/coordinator/internal/store" + "github.com/darkbloom/coordinator/internal/billing" + "github.com/darkbloom/coordinator/internal/payments" + "github.com/darkbloom/coordinator/internal/protocol" + "github.com/darkbloom/coordinator/internal/registry" + "github.com/darkbloom/coordinator/internal/store" "nhooyr.io/websocket" ) diff --git a/coordinator/internal/api/cancellation_integration_test.go b/coordinator/internal/api/cancellation_integration_test.go index bd194d278..6444924e9 100644 --- a/coordinator/internal/api/cancellation_integration_test.go +++ b/coordinator/internal/api/cancellation_integration_test.go @@ -19,9 +19,9 @@ import ( "testing" "time" - "github.com/eigeninference/coordinator/internal/protocol" - "github.com/eigeninference/coordinator/internal/registry" - "github.com/eigeninference/coordinator/internal/store" + "github.com/darkbloom/coordinator/internal/protocol" + "github.com/darkbloom/coordinator/internal/registry" + "github.com/darkbloom/coordinator/internal/store" "nhooyr.io/websocket" ) diff --git a/coordinator/internal/api/consumer.go b/coordinator/internal/api/consumer.go index 584dda01a..5c733b70f 100644 --- a/coordinator/internal/api/consumer.go +++ b/coordinator/internal/api/consumer.go @@ -25,12 +25,12 @@ import ( "strings" "time" - "github.com/eigeninference/coordinator/internal/auth" - "github.com/eigeninference/coordinator/internal/e2e" - "github.com/eigeninference/coordinator/internal/payments" - "github.com/eigeninference/coordinator/internal/protocol" - "github.com/eigeninference/coordinator/internal/registry" - "github.com/eigeninference/coordinator/internal/store" + "github.com/darkbloom/coordinator/internal/auth" + "github.com/darkbloom/coordinator/internal/e2e" + "github.com/darkbloom/coordinator/internal/payments" + "github.com/darkbloom/coordinator/internal/protocol" + "github.com/darkbloom/coordinator/internal/registry" + "github.com/darkbloom/coordinator/internal/store" "github.com/google/uuid" "nhooyr.io/websocket" ) @@ -2092,7 +2092,7 @@ func (s *Server) handleListModels(w http.ResponseWriter, r *http.Request) { "id": m.ID, "object": "model", "created": 0, - "owned_by": "eigeninference", + "owned_by": "darkbloom", "metadata": metadata, }) } @@ -2139,7 +2139,7 @@ func (s *Server) handleRevokeKey(w http.ResponseWriter, r *http.Request) { Key string `json:"key"` } if err := json.NewDecoder(r.Body).Decode(&body); err != nil || body.Key == "" { - writeJSON(w, http.StatusBadRequest, errorResponse("bad_request", "provide {\"key\": \"eigeninference-...\"}")) + writeJSON(w, http.StatusBadRequest, errorResponse("bad_request", "provide {\"key\": \"darkbloom-...\"}")) return } @@ -2193,7 +2193,7 @@ func (s *Server) handleVersion(w http.ResponseWriter, r *http.Request) { if r.TLS == nil && !strings.Contains(r.Host, "darkbloom.dev") { scheme = "http" } - downloadURL := fmt.Sprintf("%s://%s/dl/eigeninference-bundle-macos-arm64.tar.gz", scheme, r.Host) + downloadURL := fmt.Sprintf("%s://%s/dl/darkbloom-bundle-macos-arm64.tar.gz", scheme, r.Host) resp = map[string]any{ "version": LatestProviderVersion, "download_url": downloadURL, diff --git a/coordinator/internal/api/consumer_test.go b/coordinator/internal/api/consumer_test.go index 6b6eeab21..99d279016 100644 --- a/coordinator/internal/api/consumer_test.go +++ b/coordinator/internal/api/consumer_test.go @@ -15,10 +15,10 @@ import ( "testing" "time" - "github.com/eigeninference/coordinator/internal/e2e" - "github.com/eigeninference/coordinator/internal/protocol" - "github.com/eigeninference/coordinator/internal/registry" - "github.com/eigeninference/coordinator/internal/store" + "github.com/darkbloom/coordinator/internal/e2e" + "github.com/darkbloom/coordinator/internal/protocol" + "github.com/darkbloom/coordinator/internal/registry" + "github.com/darkbloom/coordinator/internal/store" "golang.org/x/crypto/nacl/box" "nhooyr.io/websocket" ) diff --git a/coordinator/internal/api/device_auth.go b/coordinator/internal/api/device_auth.go index 778c85150..f71cb2ca8 100644 --- a/coordinator/internal/api/device_auth.go +++ b/coordinator/internal/api/device_auth.go @@ -19,8 +19,8 @@ import ( "strings" "time" - "github.com/eigeninference/coordinator/internal/auth" - "github.com/eigeninference/coordinator/internal/store" + "github.com/darkbloom/coordinator/internal/auth" + "github.com/darkbloom/coordinator/internal/store" ) const ( @@ -132,7 +132,7 @@ func (s *Server) handleDeviceToken(w http.ResponseWriter, r *http.Request) { writeJSON(w, http.StatusInternalServerError, errorResponse("server_error", "failed to generate token")) return } - rawToken := "eigeninference-pt-" + hex.EncodeToString(tokenBytes) + rawToken := "darkbloom-pt-" + hex.EncodeToString(tokenBytes) tokenHash := sha256Hash(rawToken) pt := &store.ProviderToken{ diff --git a/coordinator/internal/api/device_auth_test.go b/coordinator/internal/api/device_auth_test.go index 2bbddce1f..8d2a66ef4 100644 --- a/coordinator/internal/api/device_auth_test.go +++ b/coordinator/internal/api/device_auth_test.go @@ -12,9 +12,9 @@ import ( "testing" "time" - "github.com/eigeninference/coordinator/internal/auth" - "github.com/eigeninference/coordinator/internal/registry" - "github.com/eigeninference/coordinator/internal/store" + "github.com/darkbloom/coordinator/internal/auth" + "github.com/darkbloom/coordinator/internal/registry" + "github.com/darkbloom/coordinator/internal/store" ) func deviceTestServer() (*Server, store.Store) { @@ -166,8 +166,8 @@ func TestDeviceApproveAndTokenAuthorized(t *testing.T) { t.Errorf("status = %q, want authorized", tokenResp["status"]) } token := tokenResp["token"].(string) - if !strings.HasPrefix(token, "eigeninference-pt-") { - t.Errorf("token = %q, want eigeninference-pt- prefix", token) + if !strings.HasPrefix(token, "darkbloom-pt-") { + t.Errorf("token = %q, want darkbloom-pt- prefix", token) } if tokenResp["account_id"] != "acct-1" { t.Errorf("account_id = %q, want acct-1", tokenResp["account_id"]) diff --git a/coordinator/internal/api/edge_case_test.go b/coordinator/internal/api/edge_case_test.go index a571d4c0a..46009fec6 100644 --- a/coordinator/internal/api/edge_case_test.go +++ b/coordinator/internal/api/edge_case_test.go @@ -22,9 +22,9 @@ import ( "testing" "time" - "github.com/eigeninference/coordinator/internal/protocol" - "github.com/eigeninference/coordinator/internal/registry" - "github.com/eigeninference/coordinator/internal/store" + "github.com/darkbloom/coordinator/internal/protocol" + "github.com/darkbloom/coordinator/internal/registry" + "github.com/darkbloom/coordinator/internal/store" "nhooyr.io/websocket" ) diff --git a/coordinator/internal/api/enroll.go b/coordinator/internal/api/enroll.go index dae9610ff..161a22b02 100644 --- a/coordinator/internal/api/enroll.go +++ b/coordinator/internal/api/enroll.go @@ -53,7 +53,7 @@ func (s *Server) handleEnroll(w http.ResponseWriter, r *http.Request) { profile := generateCombinedProfile(req.SerialNumber, baseURL) w.Header().Set("Content-Type", "application/x-apple-aspen-config") - w.Header().Set("Content-Disposition", fmt.Sprintf(`attachment; filename="EigenInference-Enroll-%s.mobileconfig"`, req.SerialNumber)) + w.Header().Set("Content-Disposition", fmt.Sprintf(`attachment; filename="Darkbloom-Enroll-%s.mobileconfig"`, req.SerialNumber)) w.WriteHeader(http.StatusOK) w.Write([]byte(profile)) } @@ -110,13 +110,13 @@ func generateCombinedProfile(serialNumber, baseURL string) string { O - EigenInference + Darkbloom CN - EigenInference Identity + Darkbloom Identity @@ -130,7 +130,7 @@ func generateCombinedProfile(serialNumber, baseURL string) string { PayloadIdentifier io.darkbloom.enroll.scep PayloadOrganization - EigenInference + Darkbloom PayloadType com.apple.security.scep PayloadUUID @@ -153,7 +153,7 @@ func generateCombinedProfile(serialNumber, baseURL string) string { PayloadIdentifier io.darkbloom.enroll.mdm PayloadOrganization - EigenInference + Darkbloom PayloadType com.apple.mdm PayloadUUID @@ -187,9 +187,9 @@ func generateCombinedProfile(serialNumber, baseURL string) string { PayloadDescription Generates a hardware-bound key in the Secure Enclave. Apple verifies your device is genuine and a certificate is issued binding the key to your Mac. PayloadOrganization - EigenInference + Darkbloom DirectoryURL - %s/acme/eigeninference-acme/directory + %s/acme/darkbloom-acme/directory ClientIdentifier %s KeySize @@ -226,7 +226,7 @@ func generateCombinedProfile(serialNumber, baseURL string) string { PayloadIdentifier io.darkbloom.enroll.%s PayloadOrganization - EigenInference + Darkbloom PayloadType Configuration PayloadUUID diff --git a/coordinator/internal/api/enroll_test.go b/coordinator/internal/api/enroll_test.go index 98d198482..8f75187c4 100644 --- a/coordinator/internal/api/enroll_test.go +++ b/coordinator/internal/api/enroll_test.go @@ -9,8 +9,8 @@ import ( "strings" "testing" - "github.com/eigeninference/coordinator/internal/registry" - "github.com/eigeninference/coordinator/internal/store" + "github.com/darkbloom/coordinator/internal/registry" + "github.com/darkbloom/coordinator/internal/store" ) func TestGenerateCombinedProfile(t *testing.T) { @@ -24,7 +24,7 @@ func TestGenerateCombinedProfile(t *testing.T) { "https://api.darkbloom.dev/scep", "https://api.darkbloom.dev/mdm/checkin", "https://api.darkbloom.dev/mdm/connect", - "https://api.darkbloom.dev/acme/eigeninference-acme/directory", + "https://api.darkbloom.dev/acme/darkbloom-acme/directory", } for _, url := range expectedURLs { if !strings.Contains(profile, url) { @@ -90,7 +90,7 @@ func TestGenerateCombinedProfileDifferentDomains(t *testing.T) { if !strings.Contains(profile, tt.baseURL+"/mdm/connect") { t.Errorf("expected ServerURL with base %s", tt.baseURL) } - if !strings.Contains(profile, tt.baseURL+"/acme/eigeninference-acme/directory") { + if !strings.Contains(profile, tt.baseURL+"/acme/darkbloom-acme/directory") { t.Errorf("expected ACME DirectoryURL with base %s", tt.baseURL) } }) diff --git a/coordinator/internal/api/fullstack_integration_test.go b/coordinator/internal/api/fullstack_integration_test.go index 2a171630b..b38d4698a 100644 --- a/coordinator/internal/api/fullstack_integration_test.go +++ b/coordinator/internal/api/fullstack_integration_test.go @@ -38,10 +38,10 @@ import ( "testing" "time" - "github.com/eigeninference/coordinator/internal/e2e" - "github.com/eigeninference/coordinator/internal/protocol" - "github.com/eigeninference/coordinator/internal/registry" - "github.com/eigeninference/coordinator/internal/store" + "github.com/darkbloom/coordinator/internal/e2e" + "github.com/darkbloom/coordinator/internal/protocol" + "github.com/darkbloom/coordinator/internal/registry" + "github.com/darkbloom/coordinator/internal/store" "golang.org/x/crypto/nacl/box" "nhooyr.io/websocket" ) diff --git a/coordinator/internal/api/install.sh b/coordinator/internal/api/install.sh index 8a5555165..bbdd19570 100644 --- a/coordinator/internal/api/install.sh +++ b/coordinator/internal/api/install.sh @@ -82,29 +82,29 @@ echo "" echo "→ [2/7] Downloading Darkbloom v${VERSION}..." mkdir -p "$INSTALL_DIR" "$BIN_DIR" -curl -f#L "$BUNDLE_URL" -o "/tmp/eigeninference-bundle.tar.gz" +curl -f#L "$BUNDLE_URL" -o "/tmp/darkbloom-bundle.tar.gz" # Verify bundle hash -ACTUAL_HASH=$(shasum -a 256 /tmp/eigeninference-bundle.tar.gz | cut -d' ' -f1) +ACTUAL_HASH=$(shasum -a 256 /tmp/darkbloom-bundle.tar.gz | cut -d' ' -f1) if [ "$ACTUAL_HASH" != "$BUNDLE_HASH" ]; then echo "" echo " ✗ Bundle hash mismatch — download may be corrupted." echo " Expected: $BUNDLE_HASH" echo " Got: $ACTUAL_HASH" - rm -f /tmp/eigeninference-bundle.tar.gz + rm -f /tmp/darkbloom-bundle.tar.gz exit 1 fi echo "" echo " Hash verified ✓" echo " Installing binaries..." -tar xzf /tmp/eigeninference-bundle.tar.gz -C "$INSTALL_DIR" +tar xzf /tmp/darkbloom-bundle.tar.gz -C "$INSTALL_DIR" # Migrate older flat bundle layouts into the current install structure. [ -f "$INSTALL_DIR/darkbloom" ] && mv -f "$INSTALL_DIR/darkbloom" "$BIN_DIR/darkbloom" -[ -f "$INSTALL_DIR/eigeninference-enclave" ] && mv -f "$INSTALL_DIR/eigeninference-enclave" "$BIN_DIR/eigeninference-enclave" -chmod +x "$BIN_DIR/darkbloom" "$BIN_DIR/eigeninference-enclave" 2>/dev/null || true -rm -f /tmp/eigeninference-bundle.tar.gz +[ -f "$INSTALL_DIR/darkbloom-enclave" ] && mv -f "$INSTALL_DIR/darkbloom-enclave" "$BIN_DIR/darkbloom-enclave" +chmod +x "$BIN_DIR/darkbloom" "$BIN_DIR/darkbloom-enclave" 2>/dev/null || true +rm -f /tmp/darkbloom-bundle.tar.gz # Verify code signature (codesign is part of base macOS, no CLT needed) if codesign --verify --verbose "$BIN_DIR/darkbloom" 2>/dev/null; then @@ -128,7 +128,7 @@ if [ -f "$HOME/.bashrc" ] && [ ! -f "$HOME/.zshrc" ]; then fi if ! grep -q "\.darkbloom/bin" "$RC" 2>/dev/null; then # Remove old PATH entries from previous installs - sed -i '' '/\.dginf\/bin/d; /\.eigeninference\/bin/d; /alias eigeninf/d; /alias dginf/d; /# EigenInference/d; /# Darkbloom$/d' "$RC" 2>/dev/null || true + sed -i '' '/\.dginf\/bin/d; /\.darkbloom\/bin/d; /alias eigeninf/d; /alias dginf/d; /# Darkbloom/d; /# Darkbloom$/d' "$RC" 2>/dev/null || true cat >> "$RC" << 'SHELL' # Darkbloom @@ -177,13 +177,13 @@ else RUNTIME_INSTALLED=false # Try R2 release artifacts first (the canonical source). - if [ -n "$VERSION" ] && curl -f#L "$R2_CDN/releases/v${VERSION}/eigeninference-python-macos-arm64.tar.gz" -o "/tmp/eigeninference-python.tar.gz" 2>/dev/null; then + if [ -n "$VERSION" ] && curl -f#L "$R2_CDN/releases/v${VERSION}/darkbloom-python-macos-arm64.tar.gz" -o "/tmp/darkbloom-python.tar.gz" 2>/dev/null; then echo "" echo " Extracting Python runtime..." rm -rf "$INSTALL_DIR/python" mkdir -p "$INSTALL_DIR/python" - tar xzf /tmp/eigeninference-python.tar.gz -C "$INSTALL_DIR/python" - rm -f /tmp/eigeninference-python.tar.gz + tar xzf /tmp/darkbloom-python.tar.gz -C "$INSTALL_DIR/python" + rm -f /tmp/darkbloom-python.tar.gz RUNTIME_INSTALLED=true echo " Python runtime installed ✓" fi @@ -193,7 +193,7 @@ else if [ "$RUNTIME_INSTALLED" = false ] && [ -f "$PYTHON_BIN" ] && "$PYTHON_BIN" -c "print('ok')" 2>/dev/null; then echo " Downloading site-packages..." SITE_DIR="$INSTALL_DIR/python/lib/python3.12/site-packages" - if [ -n "$VERSION" ] && curl -fsSL "$R2_CDN/releases/v${VERSION}/eigeninference-site-packages.tar.gz" -o "/tmp/eigen-site-packages.tar.gz" 2>/dev/null; then + if [ -n "$VERSION" ] && curl -fsSL "$R2_CDN/releases/v${VERSION}/darkbloom-site-packages.tar.gz" -o "/tmp/eigen-site-packages.tar.gz" 2>/dev/null; then rm -rf "$SITE_DIR" mkdir -p "$SITE_DIR" tar xzf /tmp/eigen-site-packages.tar.gz -C "$SITE_DIR" @@ -223,7 +223,7 @@ if [ -f "$PYTHON_BIN" ] && ! "$PYTHON_BIN" -c "print('ok')" 2>/dev/null; then # Install packages from R2 site-packages tarball (same verified artifacts as CI) SITE_DIR="$INSTALL_DIR/python/lib/python3.12/site-packages" R2_CDN="${R2_CDN:-__DARKBLOOM_R2_SITE_PACKAGES_CDN_URL__}" - if [ -n "$VERSION" ] && curl -fsSL "$R2_CDN/releases/v${VERSION}/eigeninference-site-packages.tar.gz" -o "/tmp/eigen-site-packages.tar.gz" 2>/dev/null; then + if [ -n "$VERSION" ] && curl -fsSL "$R2_CDN/releases/v${VERSION}/darkbloom-site-packages.tar.gz" -o "/tmp/eigen-site-packages.tar.gz" 2>/dev/null; then rm -rf "$SITE_DIR" mkdir -p "$SITE_DIR" tar xzf /tmp/eigen-site-packages.tar.gz -C "$SITE_DIR" @@ -256,7 +256,7 @@ fi echo "" echo "→ [4/7] Setting up Secure Enclave identity..." -"$BIN_DIR/eigeninference-enclave" info >/dev/null 2>&1 \ +"$BIN_DIR/darkbloom-enclave" info >/dev/null 2>&1 \ && echo " Secure Enclave ✓ (P-256 key generated)" \ || echo " Secure Enclave ⚠ (not available on this hardware)" @@ -273,11 +273,11 @@ if [ "$ALREADY_ENROLLED" = true ]; then echo " Already enrolled ✓" elif [ -n "$SERIAL" ]; then echo " Requesting enrollment profile..." - rm -f "/tmp/EigenInference-Enroll-${SERIAL}.mobileconfig" 2>/dev/null + rm -f "/tmp/Darkbloom-Enroll-${SERIAL}.mobileconfig" 2>/dev/null if curl -fsSL -X POST "$COORD_URL/v1/enroll" \ -H "Content-Type: application/json" \ -d "{\"serial_number\": \"$SERIAL\"}" \ - -o "/tmp/EigenInference-Enroll-${SERIAL}.mobileconfig" 2>/dev/null; then + -o "/tmp/Darkbloom-Enroll-${SERIAL}.mobileconfig" 2>/dev/null; then echo "" echo " ┌──────────────────────────────────────────────────┐" echo " │ ACTION REQUIRED: Install the enrollment profile │" @@ -292,7 +292,7 @@ elif [ -n "$SERIAL" ]; then echo " └──────────────────────────────────────────────────┘" echo "" # Register the profile, then open System Settings to the install pane - open "/tmp/EigenInference-Enroll-${SERIAL}.mobileconfig" + open "/tmp/Darkbloom-Enroll-${SERIAL}.mobileconfig" sleep 1 open "x-apple.systempreferences:com.apple.Profiles-Settings.extension" @@ -443,7 +443,7 @@ else fi echo "" -if [ ! -f "$HOME/.config/eigeninference/auth_token" ]; then +if [ ! -f "$HOME/.config/darkbloom/auth_token" ] && [ ! -f "$HOME/.config/eigeninference/auth_token" ]; then echo " ┌──────────────────────────────────────────────┐" echo " │ Link your account to earn rewards: │" echo " │ │" diff --git a/coordinator/internal/api/install_sh_test.go b/coordinator/internal/api/install_sh_test.go index 485e0db2e..b0ac80671 100644 --- a/coordinator/internal/api/install_sh_test.go +++ b/coordinator/internal/api/install_sh_test.go @@ -8,8 +8,8 @@ import ( "strings" "testing" - "github.com/eigeninference/coordinator/internal/registry" - "github.com/eigeninference/coordinator/internal/store" + "github.com/darkbloom/coordinator/internal/registry" + "github.com/darkbloom/coordinator/internal/store" ) // TestInstallScriptTemplating verifies the coordinator substitutes diff --git a/coordinator/internal/api/integration_test.go b/coordinator/internal/api/integration_test.go index 27b788d68..6c3d0ced7 100644 --- a/coordinator/internal/api/integration_test.go +++ b/coordinator/internal/api/integration_test.go @@ -14,10 +14,10 @@ import ( "testing" "time" - "github.com/eigeninference/coordinator/internal/e2e" - "github.com/eigeninference/coordinator/internal/protocol" - "github.com/eigeninference/coordinator/internal/registry" - "github.com/eigeninference/coordinator/internal/store" + "github.com/darkbloom/coordinator/internal/e2e" + "github.com/darkbloom/coordinator/internal/protocol" + "github.com/darkbloom/coordinator/internal/registry" + "github.com/darkbloom/coordinator/internal/store" "nhooyr.io/websocket" ) diff --git a/coordinator/internal/api/invite_handlers.go b/coordinator/internal/api/invite_handlers.go index f868fc861..a403865c8 100644 --- a/coordinator/internal/api/invite_handlers.go +++ b/coordinator/internal/api/invite_handlers.go @@ -10,8 +10,8 @@ import ( "strings" "time" - "github.com/eigeninference/coordinator/internal/auth" - "github.com/eigeninference/coordinator/internal/store" + "github.com/darkbloom/coordinator/internal/auth" + "github.com/darkbloom/coordinator/internal/store" ) // requireAdminKey checks that the request is from an admin (either admin key or Privy admin). diff --git a/coordinator/internal/api/leaderboard.go b/coordinator/internal/api/leaderboard.go index 147744354..14d336860 100644 --- a/coordinator/internal/api/leaderboard.go +++ b/coordinator/internal/api/leaderboard.go @@ -7,7 +7,7 @@ import ( "strconv" "time" - "github.com/eigeninference/coordinator/internal/store" + "github.com/darkbloom/coordinator/internal/store" ) // parseLeaderboardWindow returns the cutoff time for the requested diff --git a/coordinator/internal/api/load_integration_test.go b/coordinator/internal/api/load_integration_test.go index f84c6b6fa..2af38f18f 100644 --- a/coordinator/internal/api/load_integration_test.go +++ b/coordinator/internal/api/load_integration_test.go @@ -15,9 +15,9 @@ import ( "testing" "time" - "github.com/eigeninference/coordinator/internal/protocol" - "github.com/eigeninference/coordinator/internal/registry" - "github.com/eigeninference/coordinator/internal/store" + "github.com/darkbloom/coordinator/internal/protocol" + "github.com/darkbloom/coordinator/internal/registry" + "github.com/darkbloom/coordinator/internal/store" "nhooyr.io/websocket" ) diff --git a/coordinator/internal/api/me_handlers.go b/coordinator/internal/api/me_handlers.go index e15c37a04..da1b10776 100644 --- a/coordinator/internal/api/me_handlers.go +++ b/coordinator/internal/api/me_handlers.go @@ -18,10 +18,10 @@ import ( "net/http" "time" - "github.com/eigeninference/coordinator/internal/attestation" - "github.com/eigeninference/coordinator/internal/protocol" - "github.com/eigeninference/coordinator/internal/registry" - "github.com/eigeninference/coordinator/internal/store" + "github.com/darkbloom/coordinator/internal/attestation" + "github.com/darkbloom/coordinator/internal/protocol" + "github.com/darkbloom/coordinator/internal/registry" + "github.com/darkbloom/coordinator/internal/store" ) // myReputation is the wire shape for a provider's reputation snapshot. diff --git a/coordinator/internal/api/model_catalog_filter.go b/coordinator/internal/api/model_catalog_filter.go index 857e35e77..6d7a9f3d9 100644 --- a/coordinator/internal/api/model_catalog_filter.go +++ b/coordinator/internal/api/model_catalog_filter.go @@ -3,7 +3,7 @@ package api import ( "strings" - "github.com/eigeninference/coordinator/internal/store" + "github.com/darkbloom/coordinator/internal/store" ) // IsRetiredProviderModel returns true for catalog entries that should never be diff --git a/coordinator/internal/api/multi_provider_test.go b/coordinator/internal/api/multi_provider_test.go index 169cde736..148b6a61d 100644 --- a/coordinator/internal/api/multi_provider_test.go +++ b/coordinator/internal/api/multi_provider_test.go @@ -19,9 +19,9 @@ import ( "testing" "time" - "github.com/eigeninference/coordinator/internal/protocol" - "github.com/eigeninference/coordinator/internal/registry" - "github.com/eigeninference/coordinator/internal/store" + "github.com/darkbloom/coordinator/internal/protocol" + "github.com/darkbloom/coordinator/internal/registry" + "github.com/darkbloom/coordinator/internal/store" "nhooyr.io/websocket" ) diff --git a/coordinator/internal/api/openai_compat_test.go b/coordinator/internal/api/openai_compat_test.go index 39a9febbb..b39b69d00 100644 --- a/coordinator/internal/api/openai_compat_test.go +++ b/coordinator/internal/api/openai_compat_test.go @@ -19,9 +19,9 @@ import ( "testing" "time" - "github.com/eigeninference/coordinator/internal/protocol" - "github.com/eigeninference/coordinator/internal/registry" - "github.com/eigeninference/coordinator/internal/store" + "github.com/darkbloom/coordinator/internal/protocol" + "github.com/darkbloom/coordinator/internal/registry" + "github.com/darkbloom/coordinator/internal/store" "nhooyr.io/websocket" ) diff --git a/coordinator/internal/api/provider.go b/coordinator/internal/api/provider.go index 4c0765cbb..0d3a4e462 100644 --- a/coordinator/internal/api/provider.go +++ b/coordinator/internal/api/provider.go @@ -33,13 +33,13 @@ import ( "sync" "time" - "github.com/eigeninference/coordinator/internal/attestation" - "github.com/eigeninference/coordinator/internal/e2e" - "github.com/eigeninference/coordinator/internal/payments" - "github.com/eigeninference/coordinator/internal/protocol" - "github.com/eigeninference/coordinator/internal/registry" - "github.com/eigeninference/coordinator/internal/saferun" - "github.com/eigeninference/coordinator/internal/store" + "github.com/darkbloom/coordinator/internal/attestation" + "github.com/darkbloom/coordinator/internal/e2e" + "github.com/darkbloom/coordinator/internal/payments" + "github.com/darkbloom/coordinator/internal/protocol" + "github.com/darkbloom/coordinator/internal/registry" + "github.com/darkbloom/coordinator/internal/saferun" + "github.com/darkbloom/coordinator/internal/store" "github.com/google/uuid" "nhooyr.io/websocket" ) @@ -532,7 +532,7 @@ func (s *Server) verifyChallengeResponse(providerID string, provider *registry.P // Verify the signature cryptographically using the provider's Secure // Enclave P-256 public key. The provider signs SHA-256(nonce + timestamp) - // with its SE key via eigeninference-enclave CLI. + // with its SE key via darkbloom-enclave CLI. if resp.Signature == "" { s.handleChallengeFailure(providerID, "empty signature") return diff --git a/coordinator/internal/api/provider_test.go b/coordinator/internal/api/provider_test.go index 4db3885f1..3418f384f 100644 --- a/coordinator/internal/api/provider_test.go +++ b/coordinator/internal/api/provider_test.go @@ -20,11 +20,11 @@ import ( "testing" "time" - "github.com/eigeninference/coordinator/internal/attestation" - "github.com/eigeninference/coordinator/internal/e2e" - "github.com/eigeninference/coordinator/internal/protocol" - "github.com/eigeninference/coordinator/internal/registry" - "github.com/eigeninference/coordinator/internal/store" + "github.com/darkbloom/coordinator/internal/attestation" + "github.com/darkbloom/coordinator/internal/e2e" + "github.com/darkbloom/coordinator/internal/protocol" + "github.com/darkbloom/coordinator/internal/registry" + "github.com/darkbloom/coordinator/internal/store" "nhooyr.io/websocket" ) diff --git a/coordinator/internal/api/ratelimit_middleware_test.go b/coordinator/internal/api/ratelimit_middleware_test.go index 32ea233b9..308caa367 100644 --- a/coordinator/internal/api/ratelimit_middleware_test.go +++ b/coordinator/internal/api/ratelimit_middleware_test.go @@ -6,7 +6,7 @@ import ( "net/http/httptest" "testing" - "github.com/eigeninference/coordinator/internal/ratelimit" + "github.com/darkbloom/coordinator/internal/ratelimit" ) // rateLimitConsumer must short-circuit when no limiter is configured so diff --git a/coordinator/internal/api/recover_middleware_test.go b/coordinator/internal/api/recover_middleware_test.go index 28e673845..23045e6ec 100644 --- a/coordinator/internal/api/recover_middleware_test.go +++ b/coordinator/internal/api/recover_middleware_test.go @@ -5,7 +5,7 @@ import ( "net/http/httptest" "testing" - "github.com/eigeninference/coordinator/internal/telemetry" + "github.com/darkbloom/coordinator/internal/telemetry" ) func TestRecoverMiddlewareCatchesPanic(t *testing.T) { diff --git a/coordinator/internal/api/release_handlers.go b/coordinator/internal/api/release_handlers.go index 7cdef4f30..4f3662cd7 100644 --- a/coordinator/internal/api/release_handlers.go +++ b/coordinator/internal/api/release_handlers.go @@ -6,8 +6,8 @@ import ( "net/http" "time" - "github.com/eigeninference/coordinator/internal/auth" - "github.com/eigeninference/coordinator/internal/store" + "github.com/darkbloom/coordinator/internal/auth" + "github.com/darkbloom/coordinator/internal/store" ) // handleRegisterRelease handles POST /v1/releases. diff --git a/coordinator/internal/api/routing_metrics_test.go b/coordinator/internal/api/routing_metrics_test.go index 58c0913d1..e9d1094be 100644 --- a/coordinator/internal/api/routing_metrics_test.go +++ b/coordinator/internal/api/routing_metrics_test.go @@ -12,11 +12,11 @@ import ( "testing" "time" - "github.com/eigeninference/coordinator/internal/datadog" - "github.com/eigeninference/coordinator/internal/protocol" - "github.com/eigeninference/coordinator/internal/ratelimit" - "github.com/eigeninference/coordinator/internal/registry" - "github.com/eigeninference/coordinator/internal/store" + "github.com/darkbloom/coordinator/internal/datadog" + "github.com/darkbloom/coordinator/internal/protocol" + "github.com/darkbloom/coordinator/internal/ratelimit" + "github.com/darkbloom/coordinator/internal/registry" + "github.com/darkbloom/coordinator/internal/store" ) // udpCollector listens on a random UDP port and collects DogStatsD packets. diff --git a/coordinator/internal/api/runtime_manifest_test.go b/coordinator/internal/api/runtime_manifest_test.go index af4a18616..bfaccd87b 100644 --- a/coordinator/internal/api/runtime_manifest_test.go +++ b/coordinator/internal/api/runtime_manifest_test.go @@ -6,9 +6,9 @@ import ( "testing" "time" - "github.com/eigeninference/coordinator/internal/protocol" - "github.com/eigeninference/coordinator/internal/registry" - "github.com/eigeninference/coordinator/internal/store" + "github.com/darkbloom/coordinator/internal/protocol" + "github.com/darkbloom/coordinator/internal/registry" + "github.com/darkbloom/coordinator/internal/store" ) func runtimeManifestTestServer(t *testing.T) (*Server, *store.MemoryStore) { diff --git a/coordinator/internal/api/scoring_integration_test.go b/coordinator/internal/api/scoring_integration_test.go index 1033e7f31..9b5a42abc 100644 --- a/coordinator/internal/api/scoring_integration_test.go +++ b/coordinator/internal/api/scoring_integration_test.go @@ -10,9 +10,9 @@ import ( "testing" "time" - "github.com/eigeninference/coordinator/internal/protocol" - "github.com/eigeninference/coordinator/internal/registry" - "github.com/eigeninference/coordinator/internal/store" + "github.com/darkbloom/coordinator/internal/protocol" + "github.com/darkbloom/coordinator/internal/registry" + "github.com/darkbloom/coordinator/internal/store" "nhooyr.io/websocket" ) diff --git a/coordinator/internal/api/security_test.go b/coordinator/internal/api/security_test.go index 948cb3e3e..f6a1330bb 100644 --- a/coordinator/internal/api/security_test.go +++ b/coordinator/internal/api/security_test.go @@ -13,9 +13,9 @@ import ( "testing" "time" - "github.com/eigeninference/coordinator/internal/protocol" - "github.com/eigeninference/coordinator/internal/registry" - "github.com/eigeninference/coordinator/internal/store" + "github.com/darkbloom/coordinator/internal/protocol" + "github.com/darkbloom/coordinator/internal/registry" + "github.com/darkbloom/coordinator/internal/store" "nhooyr.io/websocket" ) diff --git a/coordinator/internal/api/sender_encryption.go b/coordinator/internal/api/sender_encryption.go index 6d9855af6..3899ba0ba 100644 --- a/coordinator/internal/api/sender_encryption.go +++ b/coordinator/internal/api/sender_encryption.go @@ -2,7 +2,7 @@ // // Senders fetch the coordinator's long-lived X25519 public key from // GET /v1/encryption-key, NaCl-Box-seal their request body to it, and POST as -// Content-Type: application/eigeninference-sealed+json. The middleware below +// Content-Type: application/darkbloom-sealed+json. The middleware below // transparently decrypts the body so downstream handlers see plaintext, and // re-seals the response (both buffered JSON and SSE streams) using the // sender's ephemeral public key from the request envelope. @@ -52,7 +52,12 @@ import ( // SealedContentType is the media type senders set on encrypted requests. // The same media type is used on the response when the request was sealed. -const SealedContentType = "application/eigeninference-sealed+json" +const SealedContentType = "application/darkbloom-sealed+json" + +// LegacySealedContentType is the pre-rename media type. Accepted during the +// transition period so existing clients sending the old header are not +// silently dropped to plaintext. +const LegacySealedContentType = "application/eigeninference-sealed+json" // sealedRequestEnvelope is the on-the-wire shape of a sealed request body. type sealedRequestEnvelope struct { @@ -83,11 +88,12 @@ func isSealedContentType(ct string) bool { } mt, _, err := mime.ParseMediaType(ct) if err != nil { - // Permissive fallback: a malformed parameter shouldn't bypass the - // gate, so try a plain prefix match too. - return strings.EqualFold(strings.TrimSpace(strings.SplitN(ct, ";", 2)[0]), SealedContentType) + trimmed := strings.TrimSpace(strings.SplitN(ct, ";", 2)[0]) + return strings.EqualFold(trimmed, SealedContentType) || + strings.EqualFold(trimmed, LegacySealedContentType) } - return strings.EqualFold(mt, SealedContentType) + return strings.EqualFold(mt, SealedContentType) || + strings.EqualFold(mt, LegacySealedContentType) } // handleEncryptionKey publishes the coordinator's X25519 public key plus a @@ -111,7 +117,7 @@ func (s *Server) handleEncryptionKey(w http.ResponseWriter, r *http.Request) { } // sealedTransport wraps an inference handler so that requests sent with -// Content-Type: application/eigeninference-sealed+json are transparently +// Content-Type: application/darkbloom-sealed+json are transparently // decrypted before the handler sees them, and the handler's response is // transparently sealed before it goes out on the wire. // diff --git a/coordinator/internal/api/sender_encryption_test.go b/coordinator/internal/api/sender_encryption_test.go index 617af51dd..ed4599613 100644 --- a/coordinator/internal/api/sender_encryption_test.go +++ b/coordinator/internal/api/sender_encryption_test.go @@ -16,9 +16,9 @@ import ( "golang.org/x/crypto/nacl/box" - "github.com/eigeninference/coordinator/internal/e2e" - "github.com/eigeninference/coordinator/internal/registry" - "github.com/eigeninference/coordinator/internal/store" + "github.com/darkbloom/coordinator/internal/e2e" + "github.com/darkbloom/coordinator/internal/registry" + "github.com/darkbloom/coordinator/internal/store" ) const senderTestMnemonic = "praise warfare warrior rebuild raven garlic kite blast crew impulse pencil hidden" @@ -250,7 +250,7 @@ func TestSealedRequest_WrongKID(t *testing.T) { // TestSealedRequest_CaseInsensitiveContentType regression-guards the // reviewer-flagged bug: the gate was case-sensitive HasPrefix, so a client -// sending Application/EigenInference-Sealed+json would silently fall through +// sending Application/Darkbloom-Sealed+json would silently fall through // to the plaintext handler. RFC 7231 §3.1.1.1 says media types are // case-insensitive. func TestSealedRequest_CaseInsensitiveContentType(t *testing.T) { @@ -261,7 +261,7 @@ func TestSealedRequest_CaseInsensitiveContentType(t *testing.T) { req, _ := http.NewRequest(http.MethodPost, ts.URL+"/v1/chat/completions", bytes.NewReader(env)) // Mixed case + a charset parameter — both should be tolerated. - req.Header.Set("Content-Type", "Application/EigenInference-Sealed+JSON; charset=utf-8") + req.Header.Set("Content-Type", "Application/Darkbloom-Sealed+JSON; charset=utf-8") req.Header.Set("Authorization", "Bearer test-key") resp, err := http.DefaultClient.Do(req) if err != nil { @@ -279,6 +279,34 @@ func TestSealedRequest_CaseInsensitiveContentType(t *testing.T) { } } +// TestSealedRequest_LegacyContentType verifies that the pre-rename content +// type (application/eigeninference-sealed+json) is still accepted during the +// transition period so existing clients are not silently dropped to plaintext. +func TestSealedRequest_LegacyContentType(t *testing.T) { + ts, coordKey := newEncryptedTestServer(t) + + plaintext := []byte(`{"model":"qwen3.5-no-such-model","messages":[{"role":"user","content":"hi"}]}`) + env, _, ephemPriv := sealRequest(t, plaintext, coordKey.PublicKey, coordKey.KID) + + req, _ := http.NewRequest(http.MethodPost, ts.URL+"/v1/chat/completions", bytes.NewReader(env)) + req.Header.Set("Content-Type", LegacySealedContentType) + req.Header.Set("Authorization", "Bearer test-key") + resp, err := http.DefaultClient.Do(req) + if err != nil { + t.Fatal(err) + } + defer resp.Body.Close() + body, _ := io.ReadAll(resp.Body) + + if got := resp.Header.Get("Content-Type"); !strings.HasPrefix(strings.ToLower(got), SealedContentType) { + t.Fatalf("middleware did not engage on legacy content-type: ct=%q body=%s", got, body) + } + pt := unsealResponse(t, body, coordKey.PublicKey, ephemPriv) + if !bytes.Contains(pt, []byte("model_not_found")) { + t.Fatalf("expected model_not_found inside sealed response, got: %s", pt) + } +} + // TestSealedTransport_SSE exercises the per-event SSE sealing path directly, // without spinning up a real coordinator (the inference handlers don't have // a no-provider streaming branch we can hit without a fake provider). We diff --git a/coordinator/internal/api/server.go b/coordinator/internal/api/server.go index 303d71ced..ff1656ac6 100644 --- a/coordinator/internal/api/server.go +++ b/coordinator/internal/api/server.go @@ -34,17 +34,17 @@ import ( "sync" "time" - "github.com/eigeninference/coordinator/internal/auth" - "github.com/eigeninference/coordinator/internal/billing" - "github.com/eigeninference/coordinator/internal/datadog" - "github.com/eigeninference/coordinator/internal/e2e" - "github.com/eigeninference/coordinator/internal/mdm" - "github.com/eigeninference/coordinator/internal/payments" - "github.com/eigeninference/coordinator/internal/protocol" - "github.com/eigeninference/coordinator/internal/ratelimit" - "github.com/eigeninference/coordinator/internal/registry" - "github.com/eigeninference/coordinator/internal/store" - "github.com/eigeninference/coordinator/internal/telemetry" + "github.com/darkbloom/coordinator/internal/auth" + "github.com/darkbloom/coordinator/internal/billing" + "github.com/darkbloom/coordinator/internal/datadog" + "github.com/darkbloom/coordinator/internal/e2e" + "github.com/darkbloom/coordinator/internal/mdm" + "github.com/darkbloom/coordinator/internal/payments" + "github.com/darkbloom/coordinator/internal/protocol" + "github.com/darkbloom/coordinator/internal/ratelimit" + "github.com/darkbloom/coordinator/internal/registry" + "github.com/darkbloom/coordinator/internal/store" + "github.com/darkbloom/coordinator/internal/telemetry" ) // contextKey is an unexported type for context keys in this package. @@ -794,7 +794,7 @@ func (s *Server) routes() { // Consumer endpoints — API key auth required + per-account rate limit. // Inference endpoints are wrapped in sealedTransport so senders can opt into // sender→coordinator encryption by setting Content-Type: - // application/eigeninference-sealed+json (see sender_encryption.go). + // application/darkbloom-sealed+json (see sender_encryption.go). // rateLimitConsumer is chained inside requireAuth so the accountID is in // context. Read-only endpoints (GET /v1/models) skip rate limiting since // they're cheap and clients poll them. diff --git a/coordinator/internal/api/stats.go b/coordinator/internal/api/stats.go index a70562802..e79b4f438 100644 --- a/coordinator/internal/api/stats.go +++ b/coordinator/internal/api/stats.go @@ -5,7 +5,7 @@ import ( "net/http" "time" - "github.com/eigeninference/coordinator/internal/registry" + "github.com/darkbloom/coordinator/internal/registry" ) // handleStats returns aggregate platform statistics for the frontend dashboard. diff --git a/coordinator/internal/api/stress_test.go b/coordinator/internal/api/stress_test.go index 431e8bd74..63a28d5ea 100644 --- a/coordinator/internal/api/stress_test.go +++ b/coordinator/internal/api/stress_test.go @@ -21,11 +21,11 @@ import ( "testing" "time" - "github.com/eigeninference/coordinator/internal/billing" - "github.com/eigeninference/coordinator/internal/payments" - "github.com/eigeninference/coordinator/internal/protocol" - "github.com/eigeninference/coordinator/internal/registry" - "github.com/eigeninference/coordinator/internal/store" + "github.com/darkbloom/coordinator/internal/billing" + "github.com/darkbloom/coordinator/internal/payments" + "github.com/darkbloom/coordinator/internal/protocol" + "github.com/darkbloom/coordinator/internal/registry" + "github.com/darkbloom/coordinator/internal/store" "nhooyr.io/websocket" ) diff --git a/coordinator/internal/api/stripe_payouts.go b/coordinator/internal/api/stripe_payouts.go index 6f1e9101c..90f5b27f3 100644 --- a/coordinator/internal/api/stripe_payouts.go +++ b/coordinator/internal/api/stripe_payouts.go @@ -32,9 +32,9 @@ import ( "strings" "time" - "github.com/eigeninference/coordinator/internal/auth" - "github.com/eigeninference/coordinator/internal/billing" - "github.com/eigeninference/coordinator/internal/store" + "github.com/darkbloom/coordinator/internal/auth" + "github.com/darkbloom/coordinator/internal/billing" + "github.com/darkbloom/coordinator/internal/store" "github.com/google/uuid" ) diff --git a/coordinator/internal/api/stripe_payouts_test.go b/coordinator/internal/api/stripe_payouts_test.go index c8603a00c..6bc12cb5f 100644 --- a/coordinator/internal/api/stripe_payouts_test.go +++ b/coordinator/internal/api/stripe_payouts_test.go @@ -26,10 +26,10 @@ import ( "testing" "time" - "github.com/eigeninference/coordinator/internal/billing" - "github.com/eigeninference/coordinator/internal/payments" - "github.com/eigeninference/coordinator/internal/registry" - "github.com/eigeninference/coordinator/internal/store" + "github.com/darkbloom/coordinator/internal/billing" + "github.com/darkbloom/coordinator/internal/payments" + "github.com/darkbloom/coordinator/internal/registry" + "github.com/darkbloom/coordinator/internal/store" ) // stripePayoutsTestServer wires up a Server with an in-memory store and a diff --git a/coordinator/internal/api/telemetry_e2e_test.go b/coordinator/internal/api/telemetry_e2e_test.go index ac1a5496c..996aee8b2 100644 --- a/coordinator/internal/api/telemetry_e2e_test.go +++ b/coordinator/internal/api/telemetry_e2e_test.go @@ -13,8 +13,8 @@ import ( "testing" "time" - "github.com/eigeninference/coordinator/internal/protocol" - "github.com/eigeninference/coordinator/internal/telemetry" + "github.com/darkbloom/coordinator/internal/protocol" + "github.com/darkbloom/coordinator/internal/telemetry" ) // TestTelemetryE2E_FullPipeline drives the full coordinator-side telemetry diff --git a/coordinator/internal/api/telemetry_handlers.go b/coordinator/internal/api/telemetry_handlers.go index 44c73674b..733f50766 100644 --- a/coordinator/internal/api/telemetry_handlers.go +++ b/coordinator/internal/api/telemetry_handlers.go @@ -26,9 +26,9 @@ import ( "sync" "time" - "github.com/eigeninference/coordinator/internal/datadog" - "github.com/eigeninference/coordinator/internal/protocol" - "github.com/eigeninference/coordinator/internal/store" + "github.com/darkbloom/coordinator/internal/datadog" + "github.com/darkbloom/coordinator/internal/protocol" + "github.com/darkbloom/coordinator/internal/store" "github.com/google/uuid" ) diff --git a/coordinator/internal/api/telemetry_handlers_test.go b/coordinator/internal/api/telemetry_handlers_test.go index 0f8cb3099..58df45bf1 100644 --- a/coordinator/internal/api/telemetry_handlers_test.go +++ b/coordinator/internal/api/telemetry_handlers_test.go @@ -9,8 +9,8 @@ import ( "testing" "time" - "github.com/eigeninference/coordinator/internal/protocol" - "github.com/eigeninference/coordinator/internal/store" + "github.com/darkbloom/coordinator/internal/protocol" + "github.com/darkbloom/coordinator/internal/store" ) // --------------------------------------------------------------------------- diff --git a/coordinator/internal/api/test_helpers_test.go b/coordinator/internal/api/test_helpers_test.go index b90203d1e..fec155695 100644 --- a/coordinator/internal/api/test_helpers_test.go +++ b/coordinator/internal/api/test_helpers_test.go @@ -7,11 +7,11 @@ import ( "os" "testing" - "github.com/eigeninference/coordinator/internal/auth" - "github.com/eigeninference/coordinator/internal/billing" - "github.com/eigeninference/coordinator/internal/payments" - "github.com/eigeninference/coordinator/internal/registry" - "github.com/eigeninference/coordinator/internal/store" + "github.com/darkbloom/coordinator/internal/auth" + "github.com/darkbloom/coordinator/internal/billing" + "github.com/darkbloom/coordinator/internal/payments" + "github.com/darkbloom/coordinator/internal/registry" + "github.com/darkbloom/coordinator/internal/store" ) // testBillingServer creates a Server with mock billing enabled and returns it diff --git a/coordinator/internal/api/withdrawable_test.go b/coordinator/internal/api/withdrawable_test.go index 720775620..75bca9274 100644 --- a/coordinator/internal/api/withdrawable_test.go +++ b/coordinator/internal/api/withdrawable_test.go @@ -7,7 +7,7 @@ import ( "strings" "testing" - "github.com/eigeninference/coordinator/internal/store" + "github.com/darkbloom/coordinator/internal/store" ) // --- Store-level withdrawable balance tests --- diff --git a/coordinator/internal/auth/privy.go b/coordinator/internal/auth/privy.go index 7f787b4ff..7f8e23e8c 100644 --- a/coordinator/internal/auth/privy.go +++ b/coordinator/internal/auth/privy.go @@ -20,7 +20,7 @@ import ( "strings" "time" - "github.com/eigeninference/coordinator/internal/store" + "github.com/darkbloom/coordinator/internal/store" "github.com/golang-jwt/jwt/v5" "github.com/google/uuid" ) diff --git a/coordinator/internal/billing/billing.go b/coordinator/internal/billing/billing.go index 72ba605ce..5d375372a 100644 --- a/coordinator/internal/billing/billing.go +++ b/coordinator/internal/billing/billing.go @@ -12,8 +12,8 @@ package billing import ( "log/slog" - "github.com/eigeninference/coordinator/internal/payments" - "github.com/eigeninference/coordinator/internal/store" + "github.com/darkbloom/coordinator/internal/payments" + "github.com/darkbloom/coordinator/internal/store" ) // PaymentMethod identifies the payment rail used for a transaction. diff --git a/coordinator/internal/billing/billing_test.go b/coordinator/internal/billing/billing_test.go index 403b2c245..488db9992 100644 --- a/coordinator/internal/billing/billing_test.go +++ b/coordinator/internal/billing/billing_test.go @@ -5,8 +5,8 @@ import ( "os" "testing" - "github.com/eigeninference/coordinator/internal/payments" - "github.com/eigeninference/coordinator/internal/store" + "github.com/darkbloom/coordinator/internal/payments" + "github.com/darkbloom/coordinator/internal/store" ) func newTestService(t *testing.T) (*Service, store.Store) { diff --git a/coordinator/internal/billing/referral.go b/coordinator/internal/billing/referral.go index dd9b88266..ff349b578 100644 --- a/coordinator/internal/billing/referral.go +++ b/coordinator/internal/billing/referral.go @@ -7,8 +7,8 @@ import ( "strings" "unicode" - "github.com/eigeninference/coordinator/internal/payments" - "github.com/eigeninference/coordinator/internal/store" + "github.com/darkbloom/coordinator/internal/payments" + "github.com/darkbloom/coordinator/internal/store" ) // ReferralService manages the referral code system. diff --git a/coordinator/internal/billing/stripe.go b/coordinator/internal/billing/stripe.go index d205fb0b7..71dd02738 100644 --- a/coordinator/internal/billing/stripe.go +++ b/coordinator/internal/billing/stripe.go @@ -134,7 +134,7 @@ func (p *StripeProcessor) CreateCheckoutSession(req CheckoutSessionRequest) (*Ch func checkoutMetadata(metadata map[string]string) map[string]string { params := map[string]string{ "app": "darkbloom", - "platform": "eigeninference", + "platform": "darkbloom", "purchase_type": "inference_credits", "source": "coordinator", } diff --git a/coordinator/internal/billing/stripe_test.go b/coordinator/internal/billing/stripe_test.go index c4da14224..29c206e9f 100644 --- a/coordinator/internal/billing/stripe_test.go +++ b/coordinator/internal/billing/stripe_test.go @@ -55,7 +55,7 @@ func TestCreateCheckoutSessionAddsDashboardMetadata(t *testing.T) { expectedMetadata := map[string]string{ "app": "darkbloom", - "platform": "eigeninference", + "platform": "darkbloom", "purchase_type": "inference_credits", "source": "coordinator", "billing_session_id": "billing-session-123", diff --git a/coordinator/internal/e2e/coordinator_key.go b/coordinator/internal/e2e/coordinator_key.go index 47f7cbccc..e1684bea2 100644 --- a/coordinator/internal/e2e/coordinator_key.go +++ b/coordinator/internal/e2e/coordinator_key.go @@ -2,7 +2,7 @@ // uses to receive sealed requests from senders (consumer/console-ui). // // Senders fetch the public key from GET /v1/encryption-key, NaCl-Box-seal -// their request body to it, and POST as application/eigeninference-sealed+json. +// their request body to it, and POST as application/darkbloom-sealed+json. // Only the coordinator (which knows the private key) can decrypt. // // The private key is derived from the same BIP39 mnemonic used for billing, diff --git a/coordinator/internal/payments/payments.go b/coordinator/internal/payments/payments.go index a033599b3..b653b9f9e 100644 --- a/coordinator/internal/payments/payments.go +++ b/coordinator/internal/payments/payments.go @@ -18,7 +18,7 @@ import ( "sync" "time" - "github.com/eigeninference/coordinator/internal/store" + "github.com/darkbloom/coordinator/internal/store" ) // Payout is the persisted provider wallet payout record. diff --git a/coordinator/internal/payments/payments_test.go b/coordinator/internal/payments/payments_test.go index 6f9941049..31df8db33 100644 --- a/coordinator/internal/payments/payments_test.go +++ b/coordinator/internal/payments/payments_test.go @@ -3,7 +3,7 @@ package payments import ( "testing" - "github.com/eigeninference/coordinator/internal/store" + "github.com/darkbloom/coordinator/internal/store" ) func newTestLedger() *Ledger { diff --git a/coordinator/internal/registry/algorithm_scenarios_test.go b/coordinator/internal/registry/algorithm_scenarios_test.go index e854a73a6..cdb4033fc 100644 --- a/coordinator/internal/registry/algorithm_scenarios_test.go +++ b/coordinator/internal/registry/algorithm_scenarios_test.go @@ -38,7 +38,7 @@ import ( "testing" "time" - "github.com/eigeninference/coordinator/internal/protocol" + "github.com/darkbloom/coordinator/internal/protocol" ) // scenarioProvider builds a fully-attested provider with controllable diff --git a/coordinator/internal/registry/clamp_test.go b/coordinator/internal/registry/clamp_test.go index a72608ceb..4c650fd6f 100644 --- a/coordinator/internal/registry/clamp_test.go +++ b/coordinator/internal/registry/clamp_test.go @@ -6,7 +6,7 @@ import ( "os" "testing" - "github.com/eigeninference/coordinator/internal/protocol" + "github.com/darkbloom/coordinator/internal/protocol" ) func TestClampNonNeg(t *testing.T) { diff --git a/coordinator/internal/registry/queue_test.go b/coordinator/internal/registry/queue_test.go index 50009f603..df4f97f35 100644 --- a/coordinator/internal/registry/queue_test.go +++ b/coordinator/internal/registry/queue_test.go @@ -5,7 +5,7 @@ import ( "testing" "time" - "github.com/eigeninference/coordinator/internal/protocol" + "github.com/darkbloom/coordinator/internal/protocol" ) func TestEnqueueAndSize(t *testing.T) { diff --git a/coordinator/internal/registry/registry.go b/coordinator/internal/registry/registry.go index 499de8f8a..3fdaa1bcf 100644 --- a/coordinator/internal/registry/registry.go +++ b/coordinator/internal/registry/registry.go @@ -27,10 +27,10 @@ import ( "sync" "time" - "github.com/eigeninference/coordinator/internal/attestation" - "github.com/eigeninference/coordinator/internal/protocol" - "github.com/eigeninference/coordinator/internal/saferun" - "github.com/eigeninference/coordinator/internal/store" + "github.com/darkbloom/coordinator/internal/attestation" + "github.com/darkbloom/coordinator/internal/protocol" + "github.com/darkbloom/coordinator/internal/saferun" + "github.com/darkbloom/coordinator/internal/store" "nhooyr.io/websocket" ) diff --git a/coordinator/internal/registry/registry_bench_test.go b/coordinator/internal/registry/registry_bench_test.go index a4d4f2b59..2ca5a7af9 100644 --- a/coordinator/internal/registry/registry_bench_test.go +++ b/coordinator/internal/registry/registry_bench_test.go @@ -7,7 +7,7 @@ import ( "testing" "time" - "github.com/eigeninference/coordinator/internal/protocol" + "github.com/darkbloom/coordinator/internal/protocol" ) // makeProvider creates a realistic provider for benchmarks. diff --git a/coordinator/internal/registry/registry_test.go b/coordinator/internal/registry/registry_test.go index f25aea1ec..c819092cc 100644 --- a/coordinator/internal/registry/registry_test.go +++ b/coordinator/internal/registry/registry_test.go @@ -9,9 +9,9 @@ import ( "testing" "time" - "github.com/eigeninference/coordinator/internal/attestation" - "github.com/eigeninference/coordinator/internal/protocol" - "github.com/eigeninference/coordinator/internal/store" + "github.com/darkbloom/coordinator/internal/attestation" + "github.com/darkbloom/coordinator/internal/protocol" + "github.com/darkbloom/coordinator/internal/store" ) func testLogger() *slog.Logger { diff --git a/coordinator/internal/registry/scheduler.go b/coordinator/internal/registry/scheduler.go index 9f516df3f..f8282b916 100644 --- a/coordinator/internal/registry/scheduler.go +++ b/coordinator/internal/registry/scheduler.go @@ -5,7 +5,7 @@ import ( "math/rand" "time" - "github.com/eigeninference/coordinator/internal/protocol" + "github.com/darkbloom/coordinator/internal/protocol" ) const ( diff --git a/coordinator/internal/registry/scheduler_test.go b/coordinator/internal/registry/scheduler_test.go index d10768b01..7aa1e5f5d 100644 --- a/coordinator/internal/registry/scheduler_test.go +++ b/coordinator/internal/registry/scheduler_test.go @@ -4,8 +4,8 @@ import ( "testing" "time" - "github.com/eigeninference/coordinator/internal/attestation" - "github.com/eigeninference/coordinator/internal/protocol" + "github.com/darkbloom/coordinator/internal/attestation" + "github.com/darkbloom/coordinator/internal/protocol" ) func makeSchedulerProvider(t *testing.T, reg *Registry, id, model string, decodeTPS float64) *Provider { diff --git a/coordinator/internal/store/memory.go b/coordinator/internal/store/memory.go index 69544f0ef..71bde3458 100644 --- a/coordinator/internal/store/memory.go +++ b/coordinator/internal/store/memory.go @@ -195,7 +195,7 @@ func (s *MemoryStore) CreateKey() (string, error) { if _, err := rand.Read(b); err != nil { return "", err } - key := "eigeninference-" + hex.EncodeToString(b) + key := "darkbloom-" + hex.EncodeToString(b) s.mu.Lock() s.keys[key] = true @@ -210,7 +210,7 @@ func (s *MemoryStore) CreateKeyForAccount(accountID string) (string, error) { if _, err := rand.Read(b); err != nil { return "", err } - key := "eigeninference-" + hex.EncodeToString(b) + key := "darkbloom-" + hex.EncodeToString(b) s.mu.Lock() s.keys[key] = true diff --git a/coordinator/internal/store/postgres.go b/coordinator/internal/store/postgres.go index dbea9e43c..93b806a1a 100644 --- a/coordinator/internal/store/postgres.go +++ b/coordinator/internal/store/postgres.go @@ -479,7 +479,7 @@ func (s *PostgresStore) CreateKey() (string, error) { if _, err := rand.Read(b); err != nil { return "", fmt.Errorf("store: generate key: %w", err) } - raw := "eigeninference-" + hex.EncodeToString(b) + raw := "darkbloom-" + hex.EncodeToString(b) h := hashKey(raw) prefix := keyPrefix(raw) @@ -523,7 +523,7 @@ func (s *PostgresStore) CreateKeyForAccount(accountID string) (string, error) { if _, err := rand.Read(b); err != nil { return "", fmt.Errorf("store: generate key: %w", err) } - raw := "eigeninference-" + hex.EncodeToString(b) + raw := "darkbloom-" + hex.EncodeToString(b) h := hashKey(raw) prefix := keyPrefix(raw) diff --git a/coordinator/internal/store/postgres_test.go b/coordinator/internal/store/postgres_test.go index daaa37743..90e824c5c 100644 --- a/coordinator/internal/store/postgres_test.go +++ b/coordinator/internal/store/postgres_test.go @@ -68,8 +68,8 @@ func TestPostgresCreateKey(t *testing.T) { t.Fatalf("CreateKey: %v", err) } - if !strings.HasPrefix(key, "eigeninference-") { - t.Errorf("key %q does not have eigeninference- prefix", key) + if !strings.HasPrefix(key, "darkbloom-") { + t.Errorf("key %q does not have darkbloom- prefix", key) } if !s.ValidateKey(key) { diff --git a/coordinator/internal/store/store_test.go b/coordinator/internal/store/store_test.go index 338125c5e..537f7ff33 100644 --- a/coordinator/internal/store/store_test.go +++ b/coordinator/internal/store/store_test.go @@ -31,8 +31,8 @@ func TestCreateKey(t *testing.T) { t.Fatalf("CreateKey: %v", err) } - if !strings.HasPrefix(key, "eigeninference-") { - t.Errorf("key %q does not have eigeninference- prefix", key) + if !strings.HasPrefix(key, "darkbloom-") { + t.Errorf("key %q does not have darkbloom- prefix", key) } if !s.ValidateKey(key) { diff --git a/coordinator/internal/telemetry/emitter.go b/coordinator/internal/telemetry/emitter.go index 873bc4f78..aa2325c11 100644 --- a/coordinator/internal/telemetry/emitter.go +++ b/coordinator/internal/telemetry/emitter.go @@ -15,9 +15,9 @@ import ( "log/slog" "time" - "github.com/eigeninference/coordinator/internal/datadog" - "github.com/eigeninference/coordinator/internal/protocol" - "github.com/eigeninference/coordinator/internal/store" + "github.com/darkbloom/coordinator/internal/datadog" + "github.com/darkbloom/coordinator/internal/protocol" + "github.com/darkbloom/coordinator/internal/store" "github.com/google/uuid" ) diff --git a/deploy/datadog/apply-dev-dashboard.sh b/deploy/datadog/apply-dev-dashboard.sh index 6a95af9fb..732ea1b34 100755 --- a/deploy/datadog/apply-dev-dashboard.sh +++ b/deploy/datadog/apply-dev-dashboard.sh @@ -11,10 +11,17 @@ fetch_secret() { if ! command -v gcloud >/dev/null 2>&1; then return 1 fi - gcloud secrets versions access latest \ + local val + val=$(gcloud secrets versions access latest \ --project="$GCP_PROJECT" \ --secret="$name" \ - 2>/dev/null + 2>/dev/null) && printf '%s' "$val" && return + local legacy="${name/darkbloom-/eigeninference-}" + [ "$legacy" != "$name" ] && val=$(gcloud secrets versions access latest \ + --project="$GCP_PROJECT" \ + --secret="$legacy" \ + 2>/dev/null) && printf '%s' "$val" && return + return 1 } API_KEY="${DD_API_KEY:-}" @@ -22,15 +29,15 @@ APP_KEY="${DD_APPLICATION_KEY:-${DD_APP_KEY:-${DD_WRITE_KEY:-}}}" SITE="${DD_SITE:-}" if [[ -z "$API_KEY" ]]; then - API_KEY="$(fetch_secret eigeninference-dd-api-key || true)" + API_KEY="$(fetch_secret darkbloom-dd-api-key || true)" fi if [[ -z "$APP_KEY" ]]; then - APP_KEY="$(fetch_secret eigeninference-dd-app-key || true)" + APP_KEY="$(fetch_secret darkbloom-dd-app-key || true)" fi if [[ -z "$SITE" ]]; then - SITE="$(fetch_secret eigeninference-dd-site || true)" + SITE="$(fetch_secret darkbloom-dd-site || true)" fi SITE="${SITE:-datadoghq.com}" diff --git a/deploy/gcp/bootstrap.sh b/deploy/gcp/bootstrap.sh index 63531c177..953cb6418 100755 --- a/deploy/gcp/bootstrap.sh +++ b/deploy/gcp/bootstrap.sh @@ -16,14 +16,14 @@ # - Owner/Editor on the project (for initial bootstrap only; downgrade after) # # After running this, populate Secret Manager: -# - eigeninference-admin-key (openssl rand -hex 32) -# - eigeninference-release-key (openssl rand -hex 32) -# - eigeninference-solana-mnemonic (new BIP39 mnemonic for dev) -# - eigeninference-privy-app-id (dev Privy app) -# - eigeninference-privy-app-secret (dev Privy app) -# - eigeninference-privy-verification-key (dev Privy app) -# - eigeninference-micromdm-api-key (openssl rand -hex 32) -# - eigeninference-mdm-push-p12-b64 (base64url-encoded MDM push PKCS#12) +# - darkbloom-admin-key (openssl rand -hex 32) +# - darkbloom-release-key (openssl rand -hex 32) +# - darkbloom-solana-mnemonic (new BIP39 mnemonic for dev) +# - darkbloom-privy-app-id (dev Privy app) +# - darkbloom-privy-app-secret (dev Privy app) +# - darkbloom-privy-verification-key (dev Privy app) +# - darkbloom-micromdm-api-key (openssl rand -hex 32) +# - darkbloom-mdm-push-p12-b64 (base64url-encoded MDM push PKCS#12) set -euo pipefail @@ -183,16 +183,16 @@ POLICY fi } -create_secret eigeninference-admin-key -create_secret eigeninference-release-key -create_secret eigeninference-solana-mnemonic "$CMEK_SOLANA" -create_secret eigeninference-privy-app-id -create_secret eigeninference-privy-app-secret -create_secret eigeninference-privy-verification-key -create_secret eigeninference-database-url -create_secret eigeninference-micromdm-api-key -create_secret eigeninference-mdm-push-p12-b64 "$CMEK_MDM" -create_secret eigeninference-r2-cdn-url +create_secret darkbloom-admin-key +create_secret darkbloom-release-key +create_secret darkbloom-solana-mnemonic "$CMEK_SOLANA" +create_secret darkbloom-privy-app-id +create_secret darkbloom-privy-app-secret +create_secret darkbloom-privy-verification-key +create_secret darkbloom-database-url +create_secret darkbloom-micromdm-api-key +create_secret darkbloom-mdm-push-p12-b64 "$CMEK_MDM" +create_secret darkbloom-r2-cdn-url echo "==> Grant coord SA decrypt on the CMEK keys (scoped to the two keys only)" for K in "$KMS_KEY_MDM" "$KMS_KEY_SOLANA"; do @@ -206,7 +206,7 @@ done echo "==> Enabling Data Access audit logs for Secret Manager (logs every read)" # Data Access logs are OFF by default. Turn them on for Secret Manager so any -# read of eigeninference-mdm-push-p12-b64 shows up in Cloud Logging, and we +# read of darkbloom-mdm-push-p12-b64 shows up in Cloud Logging, and we # can alert on unexpected readers (anyone other than the coord SA). AUDIT_TMP=$(mktemp) gcloud projects get-iam-policy "$PROJECT" --format=json > "$AUDIT_TMP" @@ -233,7 +233,7 @@ echo "==> Scope Secret Manager access per-secret (tighter than project-level)" # simplicity. Override the MDM push cert secret specifically so only the coord # SA can read it — no human, no other service. Revoke here if we ever had wider # bindings. -gcloud secrets add-iam-policy-binding eigeninference-mdm-push-p12-b64 \ +gcloud secrets add-iam-policy-binding darkbloom-mdm-push-p12-b64 \ --member="serviceAccount:$COORD_SA_EMAIL" \ --role="roles/secretmanager.secretAccessor" \ --condition=None \ @@ -262,8 +262,8 @@ if ! gcloud sql users list --instance="$SQL_INSTANCE" --format='value(name)' | g CONN_NAME=$(gcloud sql instances describe "$SQL_INSTANCE" --format='value(connectionName)') # Coordinator connects via Cloud SQL Auth Proxy sidecar on the VM (see below). URL="postgres://${SQL_USER}:${PW}@127.0.0.1:5432/${SQL_DB}?sslmode=disable" - echo "$URL" | gcloud secrets versions add eigeninference-database-url --data-file=- - echo "==> DB URL stored in Secret Manager eigeninference-database-url" + echo "$URL" | gcloud secrets versions add darkbloom-database-url --data-file=- + echo "==> DB URL stored in Secret Manager darkbloom-database-url" fi echo "==> Creating persistent data disk for step-ca + MicroMDM state" @@ -322,8 +322,8 @@ cat <" \\ - | gcloud secrets versions add eigeninference-mdm-push-p12-b64 --data-file=- + | gcloud secrets versions add darkbloom-mdm-push-p12-b64 --data-file=- This secret is CMEK-encrypted with projects/$PROJECT/.../cryptoKeys/mdm-push-cert. IAM is scoped to only $COORD_SA_EMAIL — no humans, no other SAs. Target: rotate to a dev-specific cert within 30 days once Apple issues diff --git a/deploy/gcp/refresh-env.sh b/deploy/gcp/refresh-env.sh index 176aa8257..758fce55b 100644 --- a/deploy/gcp/refresh-env.sh +++ b/deploy/gcp/refresh-env.sh @@ -16,7 +16,11 @@ mkdir -p "$ENV_DIR" chmod 700 "$ENV_DIR" fetch() { - gcloud --quiet secrets versions access latest --secret="$1" 2>/dev/null || true + local val + val=$(gcloud --quiet secrets versions access latest --secret="$1" 2>/dev/null) && printf '%s' "$val" && return + local legacy="${1/darkbloom-/eigeninference-}" + [ "$legacy" != "$1" ] && val=$(gcloud --quiet secrets versions access latest --secret="$legacy" 2>/dev/null) && printf '%s' "$val" && return + true } cat > "$ENV_TMP" </dev/null || true + local val + val=$(gcloud --quiet secrets versions access latest --secret="$1" 2>/dev/null) && printf '%s' "$val" && return + local legacy="${1/darkbloom-/eigeninference-}" + [ "$legacy" != "$1" ] && val=$(gcloud --quiet secrets versions access latest --secret="$legacy" 2>/dev/null) && printf '%s' "$val" && return + true } cat > "$ENV_FILE" <] [--binary-hash ]` +- CLI tool: `darkbloom-enclave attest [--encryption-key ] [--binary-hash ]` ## Security Architecture @@ -144,7 +144,7 @@ SIP (System Integrity Protection) is the foundation of the security model. To di 2. Run `csrutil disable` 3. Reboot back to macOS -EigenInference checks SIP: +Darkbloom checks SIP: - At process startup (refuses to serve if disabled) - Before every inference request (defense-in-depth) - In every 5-minute challenge-response (coordinator detects if provider rebooted with SIP off) @@ -161,7 +161,7 @@ If SIP is found disabled at any point, the provider is immediately marked untrus ### MDM Integration -EigenInference uses Apple MDM (MicroMDM) to independently verify provider security posture: +Darkbloom uses Apple MDM (MicroMDM) to independently verify provider security posture: - **Enrollment:** Profile-based (`.mobileconfig`), minimal permissions (AccessRights=1041) - **SecurityInfo query returns:** @@ -275,7 +275,7 @@ User-verifiable attestation API Working GET /v1/providers/attestation — ## Inference -EigenInference runs inference **in-process** — no subprocess architecture. The Python MLX engine is embedded directly in the Rust process via PyO3. +Darkbloom runs inference **in-process** — no subprocess architecture. The Python MLX engine is embedded directly in the Rust process via PyO3. | Backend | Mode | Features | |---------|------|----------| diff --git a/docs/dev-environment.md b/docs/dev-environment.md index 5c503dcb7..115419309 100644 --- a/docs/dev-environment.md +++ b/docs/dev-environment.md @@ -13,7 +13,7 @@ The d-inference dev environment runs on Google Cloud (GCP project `sepolia-ai`, | Console UI | Vercel (separate "darkbloom-console-dev" project, built from `console-ui/`) | `https://console.dev.darkbloom.xyz` | | Database | Cloud SQL Postgres 16, instance `d-inference-dev-db`, `db-f1-micro`, accessed via cloud-sql-proxy sidecar on the VM | 127.0.0.1:5432 from inside the container | | Release bucket | Cloudflare R2 `d-inf-app-dev` | R2 CDN URL in env vars | -| Secrets | Google Secret Manager, prefix `eigeninference-*`. Fetched at VM boot into `/etc/d-inference/env` | see §Secrets | +| Secrets | Google Secret Manager, prefix `darkbloom-*`. Fetched at VM boot into `/etc/d-inference/env` | see §Secrets | | Mac fleet | 2–4 Macs with hostnames `dev-*` | listed in `deploy/provider-fleet/dev-inventory.txt` | | DNS | Vercel Domains: `api.dev.darkbloom.xyz` A → VM static IP; `console.dev.darkbloom.xyz` CNAME → Cloud Run | — | | Privy | Separate dev Privy app (not the prod one) | values in Secret Manager | @@ -37,16 +37,16 @@ The d-inference dev environment runs on Google Cloud (GCP project `sepolia-ai`, echo -n '' | gcloud secrets versions add --data-file=- ``` Values: - - `eigeninference-admin-key` — `openssl rand -hex 32` - - `eigeninference-release-key` — `openssl rand -hex 32` - - `eigeninference-solana-mnemonic` — generate a **new** BIP39 mnemonic (never reuse prod). Derive the Solana public key, fund it with a small amount of USDC on mainnet for end-to-end testing. - - `eigeninference-privy-app-id` — from the dev Privy app dashboard - - `eigeninference-privy-app-secret` — same - - `eigeninference-privy-verification-key` — same (JWKS JSON or PEM) - - `eigeninference-database-url` — already set by bootstrap if Cloud SQL was just created - - `eigeninference-micromdm-api-key` — `openssl rand -hex 32` (used by both MicroMDM and the coordinator's MDM client; they must match) - - `eigeninference-mdm-push-p12-b64` — base64url-encoded MDM push PKCS#12. Same Apple push cert prod uses (one cert per Apple Developer account). To encode: `base64 < push.p12 | tr '/+' '_-' | tr -d '\n='` - - `eigeninference-r2-cdn-url` — the public URL of the `d-inf-app-dev` R2 bucket (e.g. `https://pub-.r2.dev`). Used by the coordinator to template install.sh so dev providers pull artifacts from the dev bucket. + - `darkbloom-admin-key` — `openssl rand -hex 32` + - `darkbloom-release-key` — `openssl rand -hex 32` + - `darkbloom-solana-mnemonic` — generate a **new** BIP39 mnemonic (never reuse prod). Derive the Solana public key, fund it with a small amount of USDC on mainnet for end-to-end testing. + - `darkbloom-privy-app-id` — from the dev Privy app dashboard + - `darkbloom-privy-app-secret` — same + - `darkbloom-privy-verification-key` — same (JWKS JSON or PEM) + - `darkbloom-database-url` — already set by bootstrap if Cloud SQL was just created + - `darkbloom-micromdm-api-key` — `openssl rand -hex 32` (used by both MicroMDM and the coordinator's MDM client; they must match) + - `darkbloom-mdm-push-p12-b64` — base64url-encoded MDM push PKCS#12. Same Apple push cert prod uses (one cert per Apple Developer account). To encode: `base64 < push.p12 | tr '/+' '_-' | tr -d '\n='` + - `darkbloom-r2-cdn-url` — the public URL of the `d-inf-app-dev` R2 bucket (e.g. `https://pub-.r2.dev`). Used by the coordinator to template install.sh so dev providers pull artifacts from the dev bucket. 3. **DNS.** The bootstrap reserves a static external IP and prints it. On Vercel Domains: - `api.dev.darkbloom.xyz` A `` @@ -87,15 +87,15 @@ The d-inference dev environment runs on Google Cloud (GCP project `sepolia-ai`, | Env var in coordinator | Secret Manager name | Source | |---|---|---| -| `EIGENINFERENCE_ADMIN_KEY` | `eigeninference-admin-key` | generated once, stored | -| `EIGENINFERENCE_RELEASE_KEY` | `eigeninference-release-key` | generated once, also set in GH env `dev`→`RELEASE_KEY` | -| `EIGENINFERENCE_PRIVY_APP_ID` | `eigeninference-privy-app-id` | Privy dashboard (dev app) | -| `EIGENINFERENCE_PRIVY_APP_SECRET` | `eigeninference-privy-app-secret` | Privy dashboard | -| `EIGENINFERENCE_PRIVY_VERIFICATION_KEY` | `eigeninference-privy-verification-key` | Privy dashboard | -| `MNEMONIC` | `eigeninference-solana-mnemonic` | generated fresh for dev | -| `EIGENINFERENCE_DATABASE_URL` | `eigeninference-database-url` | bootstrap writes Cloud SQL conn string (via cloud-sql-proxy on 127.0.0.1:5432) | -| `MICROMDM_API_KEY` / `EIGENINFERENCE_MDM_API_KEY` | `eigeninference-micromdm-api-key` | same value for both — keep in sync | -| `MDM_PUSH_P12_B64` | `eigeninference-mdm-push-p12-b64` | Apple push cert (base64url-encoded PKCS#12) | +| `EIGENINFERENCE_ADMIN_KEY` | `darkbloom-admin-key` | generated once, stored | +| `EIGENINFERENCE_RELEASE_KEY` | `darkbloom-release-key` | generated once, also set in GH env `dev`→`RELEASE_KEY` | +| `EIGENINFERENCE_PRIVY_APP_ID` | `darkbloom-privy-app-id` | Privy dashboard (dev app) | +| `EIGENINFERENCE_PRIVY_APP_SECRET` | `darkbloom-privy-app-secret` | Privy dashboard | +| `EIGENINFERENCE_PRIVY_VERIFICATION_KEY` | `darkbloom-privy-verification-key` | Privy dashboard | +| `MNEMONIC` | `darkbloom-solana-mnemonic` | generated fresh for dev | +| `EIGENINFERENCE_DATABASE_URL` | `darkbloom-database-url` | bootstrap writes Cloud SQL conn string (via cloud-sql-proxy on 127.0.0.1:5432) | +| `MICROMDM_API_KEY` / `EIGENINFERENCE_MDM_API_KEY` | `darkbloom-micromdm-api-key` | same value for both — keep in sync | +| `MDM_PUSH_P12_B64` | `darkbloom-mdm-push-p12-b64` | Apple push cert (base64url-encoded PKCS#12) | Non-secret configuration is baked into `deploy/gcp/cloudbuild.yaml` via `--set-env-vars`. If you need to change one (e.g. flip `MIN_TRUST`), edit that file — the next deploy picks it up. diff --git a/docs/release-pipeline.md b/docs/release-pipeline.md index ce6d7ad80..f0bdff000 100644 --- a/docs/release-pipeline.md +++ b/docs/release-pipeline.md @@ -27,11 +27,11 @@ Apple-bound work (~15 min of ~20) is the critical floor that no amount of bigger **Target**: ~20 min → ~14–16 min. Biggest ROI, minimal infra. 1. **Share the signed Python tree between the provider bundle and the macOS app.** - Today we build Python twice: once for `/tmp/eigeninference-build-python` (libpython linkage for the Rust binary) and once for `$PYTHON_ROOT/` in the macOS app (full vllm-mlx runtime with `.so` signing). The second cycle re-signs every Python Mach-O individually. Build + sign once, reuse the signed tree for both consumers. + Today we build Python twice: once for `/tmp/darkbloom-build-python` (libpython linkage for the Rust binary) and once for `$PYTHON_ROOT/` in the macOS app (full vllm-mlx runtime with `.so` signing). The second cycle re-signs every Python Mach-O individually. Build + sign once, reuse the signed tree for both consumers. 2. **Cache the signed Python runtime across releases.** It only changes when `requirements.txt`, the vllm-mlx fork, or `PBS_PYTHON_VERSION` changes — maybe once a week. Key a cache on a hash of those inputs. Subsequent releases skip ~5 min of pip install + Mach-O signing. 3. **Conditional macOS app build.** - If a release commit doesn't touch `app/EigenInference/**`, skip building the DMG and reuse the previous release's DMG pointer in the registration payload. Saves ~7 min on provider-only releases. + If a release commit doesn't touch `app/Darkbloom/**`, skip building the DMG and reuse the previous release's DMG pointer in the registration payload. Saves ~7 min on provider-only releases. Implementation: all three are in-workflow changes plus one `actions/cache` entry. No new jobs. diff --git a/docs/release-runbook.md b/docs/release-runbook.md index b266876d5..40b826099 100644 --- a/docs/release-runbook.md +++ b/docs/release-runbook.md @@ -1,4 +1,4 @@ -# EigenInference Release Runbook +# Darkbloom Release Runbook How to build, release, and distribute provider binaries. Covers both the automated GitHub Actions pipeline and manual release process. @@ -48,11 +48,11 @@ git push origin master --tags The `.github/workflows/release.yml` workflow: 1. Builds `darkbloom` (Rust, `--no-default-features`) -2. Builds `eigeninference-enclave` (Swift) +2. Builds `darkbloom-enclave` (Swift) 3. Runs all tests (provider + coordinator) 4. Creates code-signed bundle tarball 5. Computes SHA-256 of binary and bundle -6. Uploads bundle to R2 at `releases/v0.2.1/eigeninference-bundle-macos-arm64.tar.gz` +6. Uploads bundle to R2 at `releases/v0.2.1/darkbloom-bundle-macos-arm64.tar.gz` 7. Registers the release with coordinator via `POST /v1/releases` (scoped key) 8. Creates a GitHub Release with the bundle attached @@ -88,24 +88,24 @@ swift build -c release ### 2. Create bundle ```bash -mkdir -p /tmp/eigeninference-bundle -cp provider/target/release/darkbloom /tmp/eigeninference-bundle/ -cp enclave/.build/release/eigeninference-enclave /tmp/eigeninference-bundle/ +mkdir -p /tmp/darkbloom-bundle +cp provider/target/release/darkbloom /tmp/darkbloom-bundle/ +cp enclave/.build/release/darkbloom-enclave /tmp/darkbloom-bundle/ # Code sign codesign --force --sign - --entitlements scripts/entitlements.plist \ - --options runtime /tmp/eigeninference-bundle/darkbloom + --options runtime /tmp/darkbloom-bundle/darkbloom codesign --force --sign - --entitlements scripts/entitlements.plist \ - --options runtime /tmp/eigeninference-bundle/eigeninference-enclave + --options runtime /tmp/darkbloom-bundle/darkbloom-enclave -cd /tmp && tar czf eigeninference-bundle-macos-arm64.tar.gz -C eigeninference-bundle . +cd /tmp && tar czf darkbloom-bundle-macos-arm64.tar.gz -C darkbloom-bundle . ``` ### 3. Compute hashes ```bash BINARY_HASH=$(shasum -a 256 provider/target/release/darkbloom | cut -d' ' -f1) -BUNDLE_HASH=$(shasum -a 256 /tmp/eigeninference-bundle-macos-arm64.tar.gz | cut -d' ' -f1) +BUNDLE_HASH=$(shasum -a 256 /tmp/darkbloom-bundle-macos-arm64.tar.gz | cut -d' ' -f1) echo "Binary: $BINARY_HASH" echo "Bundle: $BUNDLE_HASH" ``` @@ -114,8 +114,8 @@ echo "Bundle: $BUNDLE_HASH" ```bash VERSION="0.2.1" -aws s3 cp /tmp/eigeninference-bundle-macos-arm64.tar.gz \ - "s3://d-inf-releases/releases/v${VERSION}/eigeninference-bundle-macos-arm64.tar.gz" \ +aws s3 cp /tmp/darkbloom-bundle-macos-arm64.tar.gz \ + "s3://d-inf-releases/releases/v${VERSION}/darkbloom-bundle-macos-arm64.tar.gz" \ --endpoint-url "$R2_ENDPOINT" ``` @@ -133,7 +133,7 @@ curl -X POST https://api.darkbloom.dev/v1/releases \ \"platform\": \"macos-arm64\", \"binary_hash\": \"$BINARY_HASH\", \"bundle_hash\": \"$BUNDLE_HASH\", - \"url\": \"$R2_PUBLIC_URL/releases/v$VERSION/eigeninference-bundle-macos-arm64.tar.gz\" + \"url\": \"$R2_PUBLIC_URL/releases/v$VERSION/darkbloom-bundle-macos-arm64.tar.gz\" }" ``` diff --git a/docs/telemetry.md b/docs/telemetry.md index 466ec3011..45f210bf1 100644 --- a/docs/telemetry.md +++ b/docs/telemetry.md @@ -1,6 +1,6 @@ # Telemetry & Crash Reporting -EigenInference ships its own telemetry pipeline instead of depending on +Darkbloom ships its own telemetry pipeline instead of depending on Sentry / Datadog / Prometheus SaaS. Everything rides on infrastructure we already own: providers and the console post events over HTTPS to the coordinator, which persists them to Postgres. @@ -146,7 +146,7 @@ capped at 5 MB; the oldest half is rotated out on overflow. ### macOS App (Swift) -`app/EigenInference/Sources/EigenInference/TelemetryReporter.swift` is a +`app/Darkbloom/Sources/Darkbloom/TelemetryReporter.swift` is a singleton with a bounded 500-event buffer and debounced flush. - `AppDelegate` installs `NSSetUncaughtExceptionHandler` for fatal Obj-C diff --git a/enclave/Package.swift b/enclave/Package.swift index 84f0e44f4..d1874a514 100644 --- a/enclave/Package.swift +++ b/enclave/Package.swift @@ -2,18 +2,18 @@ import PackageDescription let package = Package( - name: "EigenInferenceEnclave", + name: "DarkbloomEnclave", platforms: [.macOS(.v13)], products: [ - .library(name: "EigenInferenceEnclave", type: .static, targets: ["EigenInferenceEnclave"]), - .executable(name: "eigeninference-enclave", targets: ["EigenInferenceEnclaveCLI"]), + .library(name: "DarkbloomEnclave", type: .static, targets: ["DarkbloomEnclave"]), + .executable(name: "darkbloom-enclave", targets: ["DarkbloomEnclaveCLI"]), ], targets: [ - .target(name: "EigenInferenceEnclave"), + .target(name: "DarkbloomEnclave"), .executableTarget( - name: "EigenInferenceEnclaveCLI", - dependencies: ["EigenInferenceEnclave"] + name: "DarkbloomEnclaveCLI", + dependencies: ["DarkbloomEnclave"] ), - .testTarget(name: "EigenInferenceEnclaveTests", dependencies: ["EigenInferenceEnclave"]), + .testTarget(name: "DarkbloomEnclaveTests", dependencies: ["DarkbloomEnclave"]), ] ) diff --git a/enclave/Sources/EigenInferenceEnclave/Attestation.swift b/enclave/Sources/DarkbloomEnclave/Attestation.swift similarity index 100% rename from enclave/Sources/EigenInferenceEnclave/Attestation.swift rename to enclave/Sources/DarkbloomEnclave/Attestation.swift diff --git a/enclave/Sources/EigenInferenceEnclave/Bridge.swift b/enclave/Sources/DarkbloomEnclave/Bridge.swift similarity index 78% rename from enclave/Sources/EigenInferenceEnclave/Bridge.swift rename to enclave/Sources/DarkbloomEnclave/Bridge.swift index 1b8fba6a4..1baa8d830 100644 --- a/enclave/Sources/EigenInferenceEnclave/Bridge.swift +++ b/enclave/Sources/DarkbloomEnclave/Bridge.swift @@ -6,13 +6,13 @@ /// /// Memory management convention: /// - Functions returning `UnsafeMutableRawPointer?` (identity objects) use -/// `Unmanaged.passRetained` — caller must eventually call `eigeninference_enclave_free()` +/// `Unmanaged.passRetained` — caller must eventually call `darkbloom_enclave_free()` /// - Functions returning `UnsafeMutablePointer?` (strings) use `strdup` -/// — caller must eventually call `eigeninference_enclave_free_string()` +/// — caller must eventually call `darkbloom_enclave_free_string()` /// - NULL return values indicate failure (Secure Enclave unavailable, invalid /// data, signing error, etc.) /// -/// The corresponding C header would be in include/eigeninference_enclave.h (not yet +/// The corresponding C header would be in include/darkbloom_enclave.h (not yet /// generated — the Rust side currently uses the symbols directly). /// /// Available operations: @@ -31,37 +31,37 @@ import Foundation /// Create a new Secure Enclave identity. Returns an opaque pointer. /// /// Generates a new P-256 key in the Secure Enclave. The pointer must be -/// freed with `eigeninference_enclave_free()` when no longer needed. +/// freed with `darkbloom_enclave_free()` when no longer needed. /// Returns NULL if the Secure Enclave is unavailable or key creation fails. -@_cdecl("eigeninference_enclave_create") -public func eigeninference_enclave_create() -> UnsafeMutableRawPointer? { +@_cdecl("darkbloom_enclave_create") +public func darkbloom_enclave_create() -> UnsafeMutableRawPointer? { guard SecureEnclave.isAvailable else { return nil } guard let identity = try? SecureEnclaveIdentity() else { return nil } return Unmanaged.passRetained(identity as AnyObject).toOpaque() } -/// Free an identity created by `eigeninference_enclave_create`. +/// Free an identity created by `darkbloom_enclave_create`. /// /// This releases the retained reference to the SecureEnclaveIdentity object. /// After calling this, the pointer must not be used again. -@_cdecl("eigeninference_enclave_free") -public func eigeninference_enclave_free(_ ptr: UnsafeMutableRawPointer) { +@_cdecl("darkbloom_enclave_free") +public func darkbloom_enclave_free(_ ptr: UnsafeMutableRawPointer) { Unmanaged.fromOpaque(ptr).release() } /// Check if the Secure Enclave is available on this device. /// Returns 1 if available, 0 if not. -@_cdecl("eigeninference_enclave_is_available") -public func eigeninference_enclave_is_available() -> Int32 { +@_cdecl("darkbloom_enclave_is_available") +public func darkbloom_enclave_is_available() -> Int32 { return SecureEnclave.isAvailable ? 1 : 0 } /// Get the public key as a base64-encoded, null-terminated C string. /// /// The public key is the raw P-256 point (64 bytes: X || Y), base64-encoded. -/// Caller must free the returned string with `eigeninference_enclave_free_string()`. -@_cdecl("eigeninference_enclave_public_key_base64") -public func eigeninference_enclave_public_key_base64( +/// Caller must free the returned string with `darkbloom_enclave_free_string()`. +@_cdecl("darkbloom_enclave_public_key_base64") +public func darkbloom_enclave_public_key_base64( _ ptr: UnsafeRawPointer ) -> UnsafeMutablePointer? { let identity = Unmanaged.fromOpaque(ptr) @@ -74,10 +74,10 @@ public func eigeninference_enclave_public_key_base64( /// /// The signing operation happens inside the Secure Enclave hardware. /// Returns the DER-encoded ECDSA signature as a base64 null-terminated C string. -/// Caller must free with `eigeninference_enclave_free_string()`. +/// Caller must free with `darkbloom_enclave_free_string()`. /// Returns NULL on failure (e.g., Secure Enclave unavailable, biometric denied). -@_cdecl("eigeninference_enclave_sign") -public func eigeninference_enclave_sign( +@_cdecl("darkbloom_enclave_sign") +public func darkbloom_enclave_sign( _ ptr: UnsafeRawPointer, _ dataPtr: UnsafePointer, _ dataLen: Int @@ -100,8 +100,8 @@ public func eigeninference_enclave_sign( /// - sigBase64: The DER-encoded signature (base64). /// /// Returns 1 if the signature is valid, 0 otherwise. -@_cdecl("eigeninference_enclave_verify") -public func eigeninference_enclave_verify( +@_cdecl("darkbloom_enclave_verify") +public func darkbloom_enclave_verify( _ pubKeyBase64: UnsafePointer, _ dataPtr: UnsafePointer, _ dataLen: Int, @@ -126,16 +126,16 @@ public func eigeninference_enclave_verify( /// Create a signed attestation blob containing hardware/software state. /// /// This is a convenience wrapper that calls -/// `eigeninference_enclave_create_attestation_with_key` with no encryption key. +/// `darkbloom_enclave_create_attestation_with_key` with no encryption key. /// /// Returns the signed attestation as a pretty-printed JSON C string. -/// Caller must free with `eigeninference_enclave_free_string()`. +/// Caller must free with `darkbloom_enclave_free_string()`. /// Returns NULL on failure. -@_cdecl("eigeninference_enclave_create_attestation") -public func eigeninference_enclave_create_attestation( +@_cdecl("darkbloom_enclave_create_attestation") +public func darkbloom_enclave_create_attestation( _ ptr: UnsafeRawPointer ) -> UnsafeMutablePointer? { - return eigeninference_enclave_create_attestation_with_key(ptr, nil) + return darkbloom_enclave_create_attestation_with_key(ptr, nil) } /// Create a signed attestation blob that binds an encryption public key. @@ -150,10 +150,10 @@ public func eigeninference_enclave_create_attestation( /// - encryptionKeyBase64: Optional base64-encoded X25519 public key to bind. /// /// Returns the signed attestation as a pretty-printed JSON C string. -/// Caller must free with `eigeninference_enclave_free_string()`. +/// Caller must free with `darkbloom_enclave_free_string()`. /// Returns NULL on failure. -@_cdecl("eigeninference_enclave_create_attestation_with_key") -public func eigeninference_enclave_create_attestation_with_key( +@_cdecl("darkbloom_enclave_create_attestation_with_key") +public func darkbloom_enclave_create_attestation_with_key( _ ptr: UnsafeRawPointer, _ encryptionKeyBase64: UnsafePointer? ) -> UnsafeMutablePointer? { @@ -180,8 +180,8 @@ public func eigeninference_enclave_create_attestation_with_key( /// /// This is the full-featured attestation generator used by the provider's FFI /// path. Both the encryption key and binary hash are optional (pass NULL to omit). -@_cdecl("eigeninference_enclave_create_attestation_full") -public func eigeninference_enclave_create_attestation_full( +@_cdecl("darkbloom_enclave_create_attestation_full") +public func darkbloom_enclave_create_attestation_full( _ ptr: UnsafeRawPointer, _ encryptionKeyBase64: UnsafePointer?, _ binaryHashHex: UnsafePointer? @@ -209,11 +209,11 @@ public func eigeninference_enclave_create_attestation_full( return strdup(jsonStr) } -/// Free a C string returned by any `eigeninference_enclave_*` function. +/// Free a C string returned by any `darkbloom_enclave_*` function. /// /// This calls the standard C `free()` on the pointer. Must be called for /// every non-NULL string returned by the FFI functions to avoid memory leaks. -@_cdecl("eigeninference_enclave_free_string") -public func eigeninference_enclave_free_string(_ ptr: UnsafeMutablePointer?) { +@_cdecl("darkbloom_enclave_free_string") +public func darkbloom_enclave_free_string(_ ptr: UnsafeMutablePointer?) { free(ptr) } diff --git a/enclave/Sources/EigenInferenceEnclave/SecureEnclaveIdentity.swift b/enclave/Sources/DarkbloomEnclave/SecureEnclaveIdentity.swift similarity index 97% rename from enclave/Sources/EigenInferenceEnclave/SecureEnclaveIdentity.swift rename to enclave/Sources/DarkbloomEnclave/SecureEnclaveIdentity.swift index 5033bf764..c0cb20cc6 100644 --- a/enclave/Sources/EigenInferenceEnclave/SecureEnclaveIdentity.swift +++ b/enclave/Sources/DarkbloomEnclave/SecureEnclaveIdentity.swift @@ -9,7 +9,7 @@ /// - Tamper-resistant signing operations /// - Device-bound identity (key cannot be cloned to another device) /// -/// This identity serves two purposes in EigenInference: +/// This identity serves two purposes in Darkbloom: /// 1. **Attestation signing**: The provider signs a hardware/software state /// blob with this key, proving its identity and security posture. /// 2. **Challenge-response**: The coordinator periodically challenges the @@ -31,7 +31,7 @@ import Foundation /// The private key never leaves the Secure Enclave. Only an opaque /// `dataRepresentation` can be persisted to reload the same key on the /// same device. This provides node identity and attestation signing for -/// the EigenInference provider agent, complementing the X25519 key used for E2E +/// the Darkbloom provider agent, complementing the X25519 key used for E2E /// encryption. public final class SecureEnclaveIdentity { private let privateKey: SecureEnclave.P256.Signing.PrivateKey diff --git a/enclave/Sources/EigenInferenceEnclaveCLI/WebSocketBridge.swift b/enclave/Sources/DarkbloomEnclaveCLI/WebSocketBridge.swift similarity index 100% rename from enclave/Sources/EigenInferenceEnclaveCLI/WebSocketBridge.swift rename to enclave/Sources/DarkbloomEnclaveCLI/WebSocketBridge.swift diff --git a/enclave/Sources/EigenInferenceEnclaveCLI/main.swift b/enclave/Sources/DarkbloomEnclaveCLI/main.swift similarity index 93% rename from enclave/Sources/EigenInferenceEnclaveCLI/main.swift rename to enclave/Sources/DarkbloomEnclaveCLI/main.swift index a34f3a4bc..cd73d3b2c 100644 --- a/enclave/Sources/EigenInferenceEnclaveCLI/main.swift +++ b/enclave/Sources/DarkbloomEnclaveCLI/main.swift @@ -1,5 +1,5 @@ import CryptoKit -import EigenInferenceEnclave +import DarkbloomEnclave import Foundation // MARK: - CLI Entry Point @@ -7,15 +7,15 @@ import Foundation /// Command-line tool for Secure Enclave attestation and diagnostics. /// /// Usage: -/// eigeninference-enclave attest [--encryption-key ] [--binary-hash ] -/// eigeninference-enclave info +/// darkbloom-enclave attest [--encryption-key ] [--binary-hash ] +/// darkbloom-enclave info /// /// All keys are ephemeral — a fresh P-256 key is created in the Secure Enclave /// for each invocation. No key material is persisted to disk. func printUsage() { let usage = """ - Usage: eigeninference-enclave [options] + Usage: darkbloom-enclave [options] Commands: attest Generate a signed attestation blob (ephemeral key) diff --git a/enclave/Tests/EigenInferenceEnclaveTests/AttestationTests.swift b/enclave/Tests/DarkbloomEnclaveTests/AttestationTests.swift similarity index 99% rename from enclave/Tests/EigenInferenceEnclaveTests/AttestationTests.swift rename to enclave/Tests/DarkbloomEnclaveTests/AttestationTests.swift index 807ee9755..6cabc8862 100644 --- a/enclave/Tests/EigenInferenceEnclaveTests/AttestationTests.swift +++ b/enclave/Tests/DarkbloomEnclaveTests/AttestationTests.swift @@ -2,7 +2,7 @@ import XCTest import CryptoKit -@testable import EigenInferenceEnclave +@testable import DarkbloomEnclave final class AttestationTests: XCTestCase { diff --git a/enclave/Tests/EigenInferenceEnclaveTests/SecureEnclaveTests.swift b/enclave/Tests/DarkbloomEnclaveTests/SecureEnclaveTests.swift similarity index 78% rename from enclave/Tests/EigenInferenceEnclaveTests/SecureEnclaveTests.swift rename to enclave/Tests/DarkbloomEnclaveTests/SecureEnclaveTests.swift index 07566f29b..4d70852db 100644 --- a/enclave/Tests/EigenInferenceEnclaveTests/SecureEnclaveTests.swift +++ b/enclave/Tests/DarkbloomEnclaveTests/SecureEnclaveTests.swift @@ -1,5 +1,5 @@ import XCTest -@testable import EigenInferenceEnclave +@testable import DarkbloomEnclave final class SecureEnclaveTests: XCTestCase { @@ -37,7 +37,7 @@ final class SecureEnclaveTests: XCTestCase { func testSignAndVerify() throws { let identity = try SecureEnclaveIdentity() - let message = "Hello, EigenInference!".data(using: .utf8)! + let message = "Hello, Darkbloom!".data(using: .utf8)! let signature = try identity.sign(message) XCTAssertFalse(signature.isEmpty) @@ -121,42 +121,42 @@ final class SecureEnclaveTests: XCTestCase { // MARK: - FFI bridge tests func testBridgeIsAvailable() { - let result = eigeninference_enclave_is_available() + let result = darkbloom_enclave_is_available() XCTAssertEqual(result, 1, "Secure Enclave should be available via FFI") } func testBridgeCreateAndFree() { - guard let ptr = eigeninference_enclave_create() else { + guard let ptr = darkbloom_enclave_create() else { XCTFail("Failed to create identity via FFI") return } // Get public key - guard let keyPtr = eigeninference_enclave_public_key_base64(ptr) else { - eigeninference_enclave_free(ptr) + guard let keyPtr = darkbloom_enclave_public_key_base64(ptr) else { + darkbloom_enclave_free(ptr) XCTFail("Failed to get public key via FFI") return } let pubKey = String(cString: keyPtr) - eigeninference_enclave_free_string(keyPtr) + darkbloom_enclave_free_string(keyPtr) XCTAssertFalse(pubKey.isEmpty) - eigeninference_enclave_free(ptr) + darkbloom_enclave_free(ptr) } func testBridgeSignAndVerify() { - guard let ptr = eigeninference_enclave_create() else { + guard let ptr = darkbloom_enclave_create() else { XCTFail("Failed to create identity") return } - defer { eigeninference_enclave_free(ptr) } + defer { darkbloom_enclave_free(ptr) } let message = "test message".data(using: .utf8)! // Sign let sigPtr = message.withUnsafeBytes { buf -> UnsafeMutablePointer? in - eigeninference_enclave_sign( + darkbloom_enclave_sign( ptr, buf.baseAddress!.assumingMemoryBound(to: UInt8.self), message.count @@ -169,8 +169,8 @@ final class SecureEnclaveTests: XCTestCase { let sigBase64 = String(cString: sigPtr) // Get public key - guard let keyPtr = eigeninference_enclave_public_key_base64(ptr) else { - eigeninference_enclave_free_string(sigPtr) + guard let keyPtr = darkbloom_enclave_public_key_base64(ptr) else { + darkbloom_enclave_free_string(sigPtr) XCTFail("Failed to get public key via FFI") return } @@ -178,7 +178,7 @@ final class SecureEnclaveTests: XCTestCase { // Verify let valid = message.withUnsafeBytes { buf -> Int32 in - eigeninference_enclave_verify( + darkbloom_enclave_verify( pubKeyBase64, buf.baseAddress!.assumingMemoryBound(to: UInt8.self), message.count, @@ -188,23 +188,23 @@ final class SecureEnclaveTests: XCTestCase { XCTAssertEqual(valid, 1, "FFI signature should verify") - eigeninference_enclave_free_string(sigPtr) - eigeninference_enclave_free_string(keyPtr) + darkbloom_enclave_free_string(sigPtr) + darkbloom_enclave_free_string(keyPtr) } func testBridgeCreateAttestation() throws { - guard let ptr = eigeninference_enclave_create() else { + guard let ptr = darkbloom_enclave_create() else { XCTFail("Failed to create identity") return } - defer { eigeninference_enclave_free(ptr) } + defer { darkbloom_enclave_free(ptr) } - guard let jsonPtr = eigeninference_enclave_create_attestation(ptr) else { + guard let jsonPtr = darkbloom_enclave_create_attestation(ptr) else { XCTFail("Failed to create attestation via FFI") return } let json = String(cString: jsonPtr) - eigeninference_enclave_free_string(jsonPtr) + darkbloom_enclave_free_string(jsonPtr) XCTAssertTrue(json.contains("publicKey")) XCTAssertTrue(json.contains("signature")) @@ -220,39 +220,39 @@ final class SecureEnclaveTests: XCTestCase { } func testBridgeEphemeralKeysDiffer() { - guard let ptr1 = eigeninference_enclave_create() else { + guard let ptr1 = darkbloom_enclave_create() else { XCTFail("Failed to create first ephemeral identity") return } - guard let ptr2 = eigeninference_enclave_create() else { - eigeninference_enclave_free(ptr1) + guard let ptr2 = darkbloom_enclave_create() else { + darkbloom_enclave_free(ptr1) XCTFail("Failed to create second ephemeral identity") return } - let key1Ptr = eigeninference_enclave_public_key_base64(ptr1)! - let key2Ptr = eigeninference_enclave_public_key_base64(ptr2)! + let key1Ptr = darkbloom_enclave_public_key_base64(ptr1)! + let key2Ptr = darkbloom_enclave_public_key_base64(ptr2)! let key1 = String(cString: key1Ptr) let key2 = String(cString: key2Ptr) - eigeninference_enclave_free_string(key1Ptr) - eigeninference_enclave_free_string(key2Ptr) - eigeninference_enclave_free(ptr1) - eigeninference_enclave_free(ptr2) + darkbloom_enclave_free_string(key1Ptr) + darkbloom_enclave_free_string(key2Ptr) + darkbloom_enclave_free(ptr1) + darkbloom_enclave_free(ptr2) XCTAssertNotEqual(key1, key2, "Two ephemeral SE keys must have different public keys") } func testBridgeEphemeralSignAndVerify() { - guard let ptr = eigeninference_enclave_create() else { + guard let ptr = darkbloom_enclave_create() else { XCTFail("Failed to create ephemeral identity") return } - defer { eigeninference_enclave_free(ptr) } + defer { darkbloom_enclave_free(ptr) } let message = "ephemeral challenge data".data(using: .utf8)! let sigPtr = message.withUnsafeBytes { buf -> UnsafeMutablePointer? in - eigeninference_enclave_sign( + darkbloom_enclave_sign( ptr, buf.baseAddress!.assumingMemoryBound(to: UInt8.self), message.count @@ -264,15 +264,15 @@ final class SecureEnclaveTests: XCTestCase { } let sigBase64 = String(cString: sigPtr) - guard let keyPtr = eigeninference_enclave_public_key_base64(ptr) else { - eigeninference_enclave_free_string(sigPtr) + guard let keyPtr = darkbloom_enclave_public_key_base64(ptr) else { + darkbloom_enclave_free_string(sigPtr) XCTFail("Failed to get ephemeral public key") return } let pubKeyBase64 = String(cString: keyPtr) let valid = message.withUnsafeBytes { buf -> Int32 in - eigeninference_enclave_verify( + darkbloom_enclave_verify( pubKeyBase64, buf.baseAddress!.assumingMemoryBound(to: UInt8.self), message.count, @@ -281,27 +281,27 @@ final class SecureEnclaveTests: XCTestCase { } XCTAssertEqual(valid, 1, "Ephemeral key signature must verify") - eigeninference_enclave_free_string(sigPtr) - eigeninference_enclave_free_string(keyPtr) + darkbloom_enclave_free_string(sigPtr) + darkbloom_enclave_free_string(keyPtr) } func testBridgeCreateAttestationFull() throws { - guard let ptr = eigeninference_enclave_create() else { + guard let ptr = darkbloom_enclave_create() else { XCTFail("Failed to create identity") return } - defer { eigeninference_enclave_free(ptr) } + defer { darkbloom_enclave_free(ptr) } let encKey = "dGVzdC1lbmNyeXB0aW9uLWtleQ==" let binHash = "abcd1234" - guard let jsonPtr = eigeninference_enclave_create_attestation_full( + guard let jsonPtr = darkbloom_enclave_create_attestation_full( ptr, encKey, binHash ) else { XCTFail("Failed to create full attestation via FFI") return } let json = String(cString: jsonPtr) - eigeninference_enclave_free_string(jsonPtr) + darkbloom_enclave_free_string(jsonPtr) XCTAssertTrue(json.contains("publicKey")) XCTAssertTrue(json.contains("signature")) diff --git a/enclave/include/eigeninference_enclave.h b/enclave/include/darkbloom_enclave.h similarity index 56% rename from enclave/include/eigeninference_enclave.h rename to enclave/include/darkbloom_enclave.h index b2e74b2cd..df69a18e1 100644 --- a/enclave/include/eigeninference_enclave.h +++ b/enclave/include/darkbloom_enclave.h @@ -1,5 +1,5 @@ -#ifndef EIGENINFERENCE_ENCLAVE_H -#define EIGENINFERENCE_ENCLAVE_H +#ifndef DARKBLOOM_ENCLAVE_H +#define DARKBLOOM_ENCLAVE_H #include @@ -8,41 +8,41 @@ extern "C" { #endif /* Opaque handle to a SecureEnclaveIdentity */ -typedef void* EigenInferenceEnclaveIdentity; +typedef void* DarkbloomEnclaveIdentity; /* * Check if the Secure Enclave is available on this device. * Returns 1 if available, 0 if not. */ -int32_t eigeninference_enclave_is_available(void); +int32_t darkbloom_enclave_is_available(void); /* * Create a new ephemeral identity in the Secure Enclave. * The key exists only while the returned handle is alive. * Returns NULL on failure (e.g., Secure Enclave unavailable). - * Caller must free with eigeninference_enclave_free(). + * Caller must free with darkbloom_enclave_free(). */ -EigenInferenceEnclaveIdentity eigeninference_enclave_create(void); +DarkbloomEnclaveIdentity darkbloom_enclave_create(void); /* - * Free an identity created by eigeninference_enclave_create(). + * Free an identity created by darkbloom_enclave_create(). */ -void eigeninference_enclave_free(EigenInferenceEnclaveIdentity identity); +void darkbloom_enclave_free(DarkbloomEnclaveIdentity identity); /* * Get the public key as a base64-encoded null-terminated string. - * Caller must free the returned string with eigeninference_enclave_free_string(). + * Caller must free the returned string with darkbloom_enclave_free_string(). */ -char* eigeninference_enclave_public_key_base64(EigenInferenceEnclaveIdentity identity); +char* darkbloom_enclave_public_key_base64(DarkbloomEnclaveIdentity identity); /* * Sign data with the Secure Enclave private key. * Returns the DER-encoded ECDSA signature as a base64 null-terminated string. - * Caller must free the returned string with eigeninference_enclave_free_string(). + * Caller must free the returned string with darkbloom_enclave_free_string(). * Returns NULL on failure. */ -char* eigeninference_enclave_sign( - EigenInferenceEnclaveIdentity identity, +char* darkbloom_enclave_sign( + DarkbloomEnclaveIdentity identity, const uint8_t* data, int data_len ); @@ -54,7 +54,7 @@ char* eigeninference_enclave_sign( * sig_base64: DER-encoded signature (base64) * Returns 1 if valid, 0 if invalid. */ -int32_t eigeninference_enclave_verify( +int32_t darkbloom_enclave_verify( const char* pub_key_base64, const uint8_t* data, int data_len, @@ -64,29 +64,29 @@ int32_t eigeninference_enclave_verify( /* * Create a signed attestation blob containing hardware/software state. * Returns a JSON null-terminated string. - * Caller must free the returned string with eigeninference_enclave_free_string(). + * Caller must free the returned string with darkbloom_enclave_free_string(). * Returns NULL on failure. */ -char* eigeninference_enclave_create_attestation(EigenInferenceEnclaveIdentity identity); +char* darkbloom_enclave_create_attestation(DarkbloomEnclaveIdentity identity); /* * Create a signed attestation blob with encryption key and binary hash binding. * encryptionKeyBase64: optional X25519 public key (base64), NULL to omit * binaryHashHex: optional SHA-256 hash of provider binary (hex), NULL to omit * Returns JSON null-terminated string. - * Caller must free the returned string with eigeninference_enclave_free_string(). + * Caller must free the returned string with darkbloom_enclave_free_string(). * Returns NULL on failure. */ -char* eigeninference_enclave_create_attestation_full( - EigenInferenceEnclaveIdentity identity, +char* darkbloom_enclave_create_attestation_full( + DarkbloomEnclaveIdentity identity, const char* encryptionKeyBase64, const char* binaryHashHex ); /* - * Free a string returned by any eigeninference_enclave_* function. + * Free a string returned by any darkbloom_enclave_* function. */ -void eigeninference_enclave_free_string(char* str); +void darkbloom_enclave_free_string(char* str); #ifdef __cplusplus } diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 000000000..66cbe6396 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,6 @@ +{ + "name": "d-inference", + "lockfileVersion": 3, + "requires": true, + "packages": {} +} diff --git a/provider/Cargo.toml b/provider/Cargo.toml index 095e42b4b..eedc77c77 100644 --- a/provider/Cargo.toml +++ b/provider/Cargo.toml @@ -2,7 +2,7 @@ name = "darkbloom" version = "0.4.7" edition = "2024" -description = "EigenInference provider agent for Apple Silicon Macs" +description = "Darkbloom provider agent for Apple Silicon Macs" [[bin]] name = "darkbloom" diff --git a/provider/build.rs b/provider/build.rs index 2e2645598..d6043e637 100644 --- a/provider/build.rs +++ b/provider/build.rs @@ -60,8 +60,8 @@ fn link_enclave_library() { let manifest_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR unset")); let enclave_dir = manifest_dir.join("../enclave"); - let enclave_sources = enclave_dir.join("Sources/EigenInferenceEnclave"); - let enclave_header = enclave_dir.join("include/eigeninference_enclave.h"); + let enclave_sources = enclave_dir.join("Sources/DarkbloomEnclave"); + let enclave_header = enclave_dir.join("include/darkbloom_enclave.h"); let enclave_package = enclave_dir.join("Package.swift"); println!("cargo:rerun-if-changed={}", enclave_package.display()); @@ -69,20 +69,11 @@ fn link_enclave_library() { println!("cargo:rerun-if-changed={}", enclave_header.display()); let status = Command::new("swift") - .args([ - "build", - "-c", - "release", - "--product", - "EigenInferenceEnclave", - ]) + .args(["build", "-c", "release", "--product", "DarkbloomEnclave"]) .current_dir(&enclave_dir) .status() - .expect("failed to invoke swift build for EigenInferenceEnclave"); - assert!( - status.success(), - "swift build failed for EigenInferenceEnclave" - ); + .expect("failed to invoke swift build for DarkbloomEnclave"); + assert!(status.success(), "swift build failed for DarkbloomEnclave"); let lib_dir = enclave_dir.join(".build/arm64-apple-macosx/release"); println!("cargo:rustc-link-search=native={}", lib_dir.display()); @@ -102,7 +93,7 @@ fn link_enclave_library() { toolchain_swift_lib.display() ); - println!("cargo:rustc-link-lib=static=EigenInferenceEnclave"); + println!("cargo:rustc-link-lib=static=DarkbloomEnclave"); println!("cargo:rustc-link-lib=framework=Foundation"); println!("cargo:rustc-link-lib=framework=Security"); println!("cargo:rustc-link-lib=framework=CryptoKit"); diff --git a/provider/src/config.rs b/provider/src/config.rs index 004b9b75b..97b8fc259 100644 --- a/provider/src/config.rs +++ b/provider/src/config.rs @@ -1,6 +1,6 @@ //! Provider configuration management. //! -//! Configuration is stored in TOML format at `~/.config/eigeninference/provider.toml` +//! Configuration is stored in TOML format at `~/.config/darkbloom/provider.toml` //! (or the platform-appropriate config directory). The config includes: //! - Provider identity (name, memory reserve) //! - Backend settings (type, port, model, continuous batching) @@ -66,7 +66,7 @@ pub struct CoordinatorSettings { impl ProviderConfig { pub fn default_for_hardware(hw: &HardwareInfo) -> Self { let name = format!( - "eigeninference-{}", + "darkbloom-{}", &hw.machine_model.replace(',', "-").to_lowercase() ); @@ -95,8 +95,23 @@ impl ProviderConfig { pub fn default_config_path() -> Result { let config_dir = dirs::config_dir() .context("could not determine config directory")? - .join("eigeninference"); - Ok(config_dir.join("provider.toml")) + .join("darkbloom"); + let path = config_dir.join("provider.toml"); + + if !path.exists() { + let legacy_path = dirs::config_dir() + .context("could not determine config directory")? + .join("eigeninference") + .join("provider.toml"); + if legacy_path.exists() { + if let Some(parent) = path.parent() { + let _ = std::fs::create_dir_all(parent); + } + let _ = std::fs::copy(&legacy_path, &path); + } + } + + Ok(path) } pub fn save(path: &Path, config: &ProviderConfig) -> Result<()> { @@ -147,7 +162,7 @@ mod tests { let hw = sample_hardware(); let config = ProviderConfig::default_for_hardware(&hw); - assert_eq!(config.provider.name, "eigeninference-mac16-1"); + assert_eq!(config.provider.name, "darkbloom-mac16-1"); assert_eq!(config.backend.port, 8100); assert!(config.backend.continuous_batching); } @@ -235,7 +250,7 @@ mod tests { 546, ); let config = ProviderConfig::default_for_hardware(&hw); - assert_eq!(config.provider.name, "eigeninference-mac16-1"); + assert_eq!(config.provider.name, "darkbloom-mac16-1"); assert_eq!(config.backend.port, 8100); assert_eq!(config.coordinator.heartbeat_interval_secs, 5); assert!(config.backend.continuous_batching); @@ -255,7 +270,7 @@ mod tests { 100, ); let config = ProviderConfig::default_for_hardware(&hw); - assert_eq!(config.provider.name, "eigeninference-mac15-3"); + assert_eq!(config.provider.name, "darkbloom-mac15-3"); assert_eq!(config.backend.port, 8100); assert_eq!(config.provider.memory_reserve_gb, 4); } @@ -272,7 +287,7 @@ mod tests { 200, ); let config = ProviderConfig::default_for_hardware(&hw); - assert_eq!(config.provider.name, "eigeninference-mac14-10"); + assert_eq!(config.provider.name, "darkbloom-mac14-10"); assert_eq!(config.backend.port, 8100); assert_eq!(config.coordinator.url, "ws://localhost:8080/ws/provider"); } diff --git a/provider/src/coordinator.rs b/provider/src/coordinator.rs index 1c7d5a383..b73e549f1 100644 --- a/provider/src/coordinator.rs +++ b/provider/src/coordinator.rs @@ -1,4 +1,4 @@ -//! WebSocket client for connecting to the EigenInference coordinator. +//! WebSocket client for connecting to the Darkbloom coordinator. //! //! This module manages the provider's connection to the coordinator: //! - WebSocket connection with automatic reconnection (exponential backoff) @@ -373,7 +373,7 @@ impl CoordinatorClient { // WebSocket ping to detect dead connections _ = ping_interval.tick() => { - if let Err(e) = write.send(Message::Ping("eigeninference".into())).await { + if let Err(e) = write.send(Message::Ping("darkbloom".into())).await { anyhow::bail!("Failed to send ping: {e}"); } } @@ -1222,12 +1222,7 @@ mod tests { .await .unwrap(); - // Read heartbeat or any response - if let Some(Ok(Message::Text(text))) = read.next().await { - received_messages.push(text.to_string()); - } - - // Send cancel + // Send cancel immediately after the inference request. let cancel = serde_json::json!({ "type": "cancel", "request_id": "test-req-1" @@ -1239,6 +1234,12 @@ mod tests { .await .unwrap(); + // Drain all messages until the connection closes (heartbeats may + // arrive before the inference_error, so collect everything). + while let Some(Ok(Message::Text(text))) = read.next().await { + received_messages.push(text.to_string()); + } + // Close let _ = write.send(Message::Close(None)).await; diff --git a/provider/src/inference.rs b/provider/src/inference.rs index 187b64f70..89efd2020 100644 --- a/provider/src/inference.rs +++ b/provider/src/inference.rs @@ -62,7 +62,7 @@ pub struct StreamToken { pub finish_reason: Option, } -const VLLM_ENGINE_STORE: &str = "_eigeninference_vllm_engines"; +const VLLM_ENGINE_STORE: &str = "_darkbloom_vllm_engines"; fn engine_cache_key_for(model_id: &str) -> String { let mut hasher = Sha256::new(); @@ -203,9 +203,9 @@ _BLOCKED = frozenset([ ]) _original_import = getattr( - builtins, '_eigeninference_original_import', builtins.__import__ + builtins, '_darkbloom_original_import', builtins.__import__ ) -builtins._eigeninference_original_import = _original_import +builtins._darkbloom_original_import = _original_import def _blocked_os_call(*args, **kwargs): raise PermissionError('os process control is blocked in private text mode') @@ -216,7 +216,7 @@ def _blocked_import(name, globals=None, locals=None, fromlist=(), level=0): raise ImportError( f"module {name!r} is blocked in private text mode" ) - return builtins._eigeninference_original_import( + return builtins._darkbloom_original_import( name, globals, locals, fromlist, level ) @@ -418,7 +418,7 @@ gc.collect() r#" import asyncio, builtins, json, traceback as _tb try: - engine = builtins._eigeninference_vllm_engines[engine_key] + engine = builtins._darkbloom_vllm_engines[engine_key] _req = json.loads(request_json) _messages = _req.get('messages', []) if not _messages and _req.get('input'): @@ -633,7 +633,7 @@ except Exception as _e: r#" import builtins, json, uuid, time, asyncio, re, traceback as _tb -engine = builtins._eigeninference_vllm_engines[engine_key] +engine = builtins._darkbloom_vllm_engines[engine_key] _req = json.loads(request_json) _messages = _req.get('messages', []) if not _messages and _req.get('input'): @@ -1092,8 +1092,8 @@ if hasattr(os, 'fork'): let cleanup = CString::new( r#"import builtins -if hasattr(builtins, '_eigeninference_original_import'): - builtins.__import__ = builtins._eigeninference_original_import +if hasattr(builtins, '_darkbloom_original_import'): + builtins.__import__ = builtins._darkbloom_original_import "#, ) .unwrap(); @@ -1116,7 +1116,7 @@ if hasattr(builtins, '_eigeninference_original_import'): #[test] fn test_python_runtime_roots_discovers_bundle_and_home_runtime() { let tmp = tempfile::tempdir().unwrap(); - let app_root = tmp.path().join("EigenInference.app"); + let app_root = tmp.path().join("Darkbloom.app"); let exe = app_root.join("Contents/MacOS/darkbloom"); let frameworks_python = app_root.join("Contents/Frameworks/python"); let resources_python = app_root.join("Contents/Resources/python"); diff --git a/provider/src/main.rs b/provider/src/main.rs index 256788570..47d7a46ba 100644 --- a/provider/src/main.rs +++ b/provider/src/main.rs @@ -679,8 +679,8 @@ fn ensure_chat_template( }; // Check local cache first (~/.darkbloom/templates/) - let eigeninference_dir = dirs::home_dir().unwrap_or_default().join(".darkbloom"); - let templates_dir = eigeninference_dir.join("templates"); + let darkbloom_dir = dirs::home_dir().unwrap_or_default().join(".darkbloom"); + let templates_dir = darkbloom_dir.join("templates"); let cached_template = templates_dir.join(format!("{template_name}.jinja")); if cached_template.exists() { @@ -890,7 +890,7 @@ fn fetch_runtime_manifest( fn ensure_python_verified(python_cmd: &str, coordinator_base: &str) -> bool { const PBS_PYTHON_URL: &str = "https://github.com/astral-sh/python-build-standalone/releases/download/20260408/cpython-3.12.13+20260408-aarch64-apple-darwin-install_only.tar.gz"; - let eigeninference_dir = dirs::home_dir().unwrap_or_default().join(".darkbloom"); + let darkbloom_dir = dirs::home_dir().unwrap_or_default().join(".darkbloom"); let manifest = fetch_runtime_manifest(coordinator_base); let expected_python_hashes: Vec = manifest .as_ref() @@ -931,8 +931,8 @@ fn ensure_python_verified(python_cmd: &str, coordinator_base: &str) -> bool { match serde_json::from_slice::(&output.stdout) { Ok(release) => release.get("url").and_then(|v| v.as_str()).map(|url| { url.replace( - "eigeninference-bundle-macos-arm64.tar.gz", - "eigeninference-python-macos-arm64.tar.gz", + "darkbloom-bundle-macos-arm64.tar.gz", + "darkbloom-python-macos-arm64.tar.gz", ) }), Err(_) => { @@ -946,7 +946,7 @@ fn ensure_python_verified(python_cmd: &str, coordinator_base: &str) -> bool { if let Some(download_url) = python_download_url { // Download to temp - let tmp_tarball = "/tmp/eigeninference-python-update.tar.gz"; + let tmp_tarball = "/tmp/darkbloom-python-update.tar.gz"; let download = std::process::Command::new("curl") .args([ "-fsSL", @@ -960,7 +960,7 @@ fn ensure_python_verified(python_cmd: &str, coordinator_base: &str) -> bool { if let Ok(output) = download { if output.status.success() { - let python_dir = eigeninference_dir.join("python"); + let python_dir = darkbloom_dir.join("python"); // Extract over existing Python dir tracing::info!("Extracting canonical Python runtime..."); @@ -999,7 +999,7 @@ fn ensure_python_verified(python_cmd: &str, coordinator_base: &str) -> bool { // Fallback: download python-build-standalone directly tracing::info!("Downloading portable Python from python-build-standalone..."); - let pbs_tmp = "/tmp/eigeninference-pbs-python.tar.gz"; + let pbs_tmp = "/tmp/darkbloom-pbs-python.tar.gz"; let pbs_ok = std::process::Command::new("curl") .args([ "-fsSL", @@ -1014,7 +1014,7 @@ fn ensure_python_verified(python_cmd: &str, coordinator_base: &str) -> bool { .unwrap_or(false); if pbs_ok { - let python_dir = eigeninference_dir.join("python"); + let python_dir = darkbloom_dir.join("python"); let _ = std::fs::remove_dir_all(&python_dir); let _ = std::fs::create_dir_all(&python_dir); // PBS tarball extracts to python/ — extract parent dir and it maps directly @@ -1057,7 +1057,7 @@ fn ensure_python_verified(python_cmd: &str, coordinator_base: &str) -> bool { if matches!(test, Ok(ref o) if o.status.success()) { tracing::info!("Using Homebrew Python 3.12 as fallback"); // Create a venv from Homebrew Python - let python_dir = eigeninference_dir.join("python"); + let python_dir = darkbloom_dir.join("python"); let _ = std::fs::remove_dir_all(&python_dir); let venv_ok = std::process::Command::new(brew_python) .args(["-m", "venv", "--copies", &python_dir.to_string_lossy()]) @@ -1154,15 +1154,14 @@ fn ensure_runtime_updated(python_cmd: &str, coordinator_base: &str) -> bool { ); let release_version = fetch_latest_release_version(coordinator_base); - let eigeninference_dir = dirs::home_dir().unwrap_or_default().join(".darkbloom"); - let site_packages_dir = eigeninference_dir.join("python/lib/python3.12/site-packages"); - let tmp_tarball = "/tmp/eigeninference-site-packages.tar.gz"; + let darkbloom_dir = dirs::home_dir().unwrap_or_default().join(".darkbloom"); + let site_packages_dir = darkbloom_dir.join("python/lib/python3.12/site-packages"); + let tmp_tarball = "/tmp/darkbloom-site-packages.tar.gz"; // Try R2 site-packages tarball first, fall back to vllm-mlx source zip. let mut downloaded = false; if !release_version.is_empty() { - let r2_url = - format!("{r2_cdn}/releases/v{release_version}/eigeninference-site-packages.tar.gz"); + let r2_url = format!("{r2_cdn}/releases/v{release_version}/darkbloom-site-packages.tar.gz"); tracing::info!("Downloading site-packages from R2 (release v{release_version})..."); downloaded = std::process::Command::new("curl") .args([ @@ -1181,8 +1180,8 @@ fn ensure_runtime_updated(python_cmd: &str, coordinator_base: &str) -> bool { if downloaded { // Extract to staging directory first — never delete current before verifying new tracing::info!("Replacing site-packages with canonical CI build..."); - let staging_dir = eigeninference_dir.join("python/lib/python3.12/site-packages-staging"); - let backup_dir = eigeninference_dir.join("python/lib/python3.12/site-packages-backup"); + let staging_dir = darkbloom_dir.join("python/lib/python3.12/site-packages-staging"); + let backup_dir = darkbloom_dir.join("python/lib/python3.12/site-packages-backup"); let _ = std::fs::remove_dir_all(&staging_dir); let _ = std::fs::remove_dir_all(&backup_dir); let _ = std::fs::create_dir_all(&staging_dir); @@ -1262,7 +1261,7 @@ fn ensure_runtime_updated(python_cmd: &str, coordinator_base: &str) -> bool { // Fallback: pip install just vllm-mlx source zip (older releases // may not have the site-packages tarball on R2). tracing::info!("Falling back to vllm-mlx source zip..."); - let tmp_zip = "/tmp/eigeninference-vllm-mlx-update.zip"; + let tmp_zip = "/tmp/darkbloom-vllm-mlx-update.zip"; let mut zip_downloaded = false; if !release_version.is_empty() { let r2_url = format!("{r2_cdn}/releases/v{release_version}/vllm-mlx-source.zip"); @@ -1853,7 +1852,7 @@ async fn cmd_install( if already_enrolled { println!(" ✓ Already enrolled in MDM — skipping"); } else { - let profile_path = std::env::temp_dir().join("EigenInference-Enroll.mobileconfig"); + let profile_path = std::env::temp_dir().join("Darkbloom-Enroll.mobileconfig"); println!(" Downloading enrollment profile..."); let client = reqwest::Client::new(); let resp = client.get(&profile_url).send().await?; @@ -2130,8 +2129,8 @@ async fn cmd_serve( #[cfg(unix)] { let my_pid = std::process::id(); - let eigeninference_dir = dirs::home_dir().unwrap_or_default().join(".darkbloom"); - let pid_file = eigeninference_dir.join("provider.pid"); + let darkbloom_dir = dirs::home_dir().unwrap_or_default().join(".darkbloom"); + let pid_file = darkbloom_dir.join("provider.pid"); // Check for an existing provider process if let Ok(old_pid_str) = std::fs::read_to_string(&pid_file) { @@ -2424,20 +2423,18 @@ async fn cmd_serve( } // Find bundled Python at ~/.darkbloom/python (standalone Python 3.12 + vllm-mlx) - let eigeninference_dir = dirs::home_dir().unwrap_or_default().join(".darkbloom"); - let bundled_python = eigeninference_dir.join("python/bin/python3.12"); + let darkbloom_dir = dirs::home_dir().unwrap_or_default().join(".darkbloom"); + let bundled_python = darkbloom_dir.join("python/bin/python3.12"); let python_cmd = if bundled_python.exists() { // Only set PYTHONHOME if this is a real standalone Python install // (not a symlink to uv/pyenv/system Python). Wrong PYTHONHOME causes // Python to fail to find its stdlib and crash silently. let is_standalone = !bundled_python.is_symlink() - && eigeninference_dir - .join("python/lib/python3.12/os.py") - .exists(); + && darkbloom_dir.join("python/lib/python3.12/os.py").exists(); if is_standalone { tracing::info!("Using bundled Python: {}", bundled_python.display()); unsafe { - std::env::set_var("PYTHONHOME", eigeninference_dir.join("python")); + std::env::set_var("PYTHONHOME", darkbloom_dir.join("python")); } } else { tracing::info!("Using Python at: {}", bundled_python.display()); @@ -4345,7 +4342,7 @@ async fn handle_inprocess_request( } } -/// Generate a Secure Enclave attestation by calling the eigeninference-enclave CLI tool. +/// Generate a Secure Enclave attestation by calling the darkbloom-enclave CLI tool. /// /// The attestation binds the X25519 encryption public key to the hardware /// identity, proving the same device controls both keys. @@ -4387,8 +4384,7 @@ async fn cmd_enroll(coordinator_url: String) -> Result<()> { } let bytes = resp.bytes().await?; - let profile_path = - std::env::temp_dir().join(format!("EigenInference-Enroll-{serial}.mobileconfig")); + let profile_path = std::env::temp_dir().join(format!("Darkbloom-Enroll-{serial}.mobileconfig")); std::fs::write(&profile_path, &bytes)?; // Register the profile and open System Settings to the Device Management pane @@ -4465,7 +4461,7 @@ async fn cmd_unenroll() -> Result<()> { // Clean up local data println!(); println!("Clean up local Darkbloom data? This removes:"); - println!(" - Config: ~/.config/eigeninference/"); + println!(" - Config: ~/.config/darkbloom/"); println!(" - Legacy key files in ~/.darkbloom/"); println!(" - Auth token: ~/.darkbloom/auth_token"); println!(); @@ -4474,6 +4470,7 @@ async fn cmd_unenroll() -> Result<()> { std::io::stdin().read_line(&mut input)?; if input.trim() == "yes" { let home = dirs::home_dir().unwrap_or_default(); + let _ = std::fs::remove_dir_all(home.join(".config/darkbloom")); let _ = std::fs::remove_dir_all(home.join(".config/eigeninference")); secure_enclave_key::cleanup_legacy_key_files(); let _ = std::fs::remove_file(home.join(".darkbloom/wallet_key")); @@ -4498,8 +4495,8 @@ async fn cmd_benchmark() -> Result<()> { println!(); // Find bundled Python - let eigeninference_dir = dirs::home_dir().unwrap_or_default().join(".darkbloom"); - let bundled_python = eigeninference_dir.join("python/bin/python3.12"); + let darkbloom_dir = dirs::home_dir().unwrap_or_default().join(".darkbloom"); + let bundled_python = darkbloom_dir.join("python/bin/python3.12"); let python_cmd = if bundled_python.exists() { bundled_python.to_string_lossy().to_string() } else { @@ -4635,7 +4632,7 @@ asyncio.run(main()) let mut child = std::process::Command::new(&python_cmd) .args(["-c", &bench_script]) - .env("PYTHONHOME", eigeninference_dir.join("python")) + .env("PYTHONHOME", darkbloom_dir.join("python")) .stdout(std::process::Stdio::piped()) .stderr(std::process::Stdio::piped()) .spawn()?; @@ -4682,14 +4679,14 @@ asyncio.run(main()) async fn cmd_status() -> Result<()> { let hw = hardware::detect()?; let home = dirs::home_dir().unwrap_or_default(); - let eigeninference_dir = home.join(".darkbloom"); + let darkbloom_dir = home.join(".darkbloom"); println!(); println!(" Darkbloom Provider Status"); println!(" ─────────────────────────────────────"); // Running state - let pid_path = eigeninference_dir.join("provider.pid"); + let pid_path = darkbloom_dir.join("provider.pid"); let is_running = if pid_path.exists() { if let Ok(pid_str) = std::fs::read_to_string(&pid_path) { if let Ok(pid) = pid_str.trim().parse::() { @@ -4712,7 +4709,7 @@ async fn cmd_status() -> Result<()> { // Try to read the current model from the log let serving_model = if is_running { - let log_path = eigeninference_dir.join("provider.log"); + let log_path = darkbloom_dir.join("provider.log"); if log_path.exists() { std::fs::read_to_string(&log_path).ok().and_then(|log| { log.lines() @@ -5166,12 +5163,12 @@ async fn cmd_doctor(coordinator_url: String) -> Result<()> { print!("3. Secure Enclave.............. "); #[cfg(target_os = "macos")] { - let enclave_ok = std::process::Command::new("eigeninference-enclave") + let enclave_ok = std::process::Command::new("darkbloom-enclave") .args(["info"]) .output() .or_else(|_| { let home = dirs::home_dir().unwrap_or_default(); - std::process::Command::new(home.join(".darkbloom/bin/eigeninference-enclave")) + std::process::Command::new(home.join(".darkbloom/bin/darkbloom-enclave")) .args(["info"]) .output() }) @@ -5181,8 +5178,8 @@ async fn cmd_doctor(coordinator_url: String) -> Result<()> { println!("✓ Available"); passed += 1; } else { - println!("✗ eigeninference-enclave not found"); - issues.push("Install eigeninference-enclave binary".to_string()); + println!("✗ darkbloom-enclave not found"); + issues.push("Install darkbloom-enclave binary".to_string()); } } #[cfg(not(target_os = "macos"))] @@ -5211,12 +5208,12 @@ async fn cmd_doctor(coordinator_url: String) -> Result<()> { // 5. Inference runtime (vllm-mlx / mlx-lm) print!("5. Inference runtime........... "); - let eigeninference_dir = dirs::home_dir().unwrap_or_default().join(".darkbloom"); - let bundled_python = eigeninference_dir.join("python/bin/python3.12"); + let darkbloom_dir = dirs::home_dir().unwrap_or_default().join(".darkbloom"); + let bundled_python = darkbloom_dir.join("python/bin/python3.12"); let (python_cmd, python_home) = if bundled_python.exists() { ( bundled_python.to_string_lossy().to_string(), - Some(eigeninference_dir.join("python")), + Some(darkbloom_dir.join("python")), ) } else { ("python3".to_string(), None) @@ -5699,9 +5696,9 @@ async fn cmd_start( } async fn cmd_stop() -> Result<()> { - let eigeninference_dir = dirs::home_dir().unwrap_or_default().join(".darkbloom"); - let pid_path = eigeninference_dir.join("provider.pid"); - let caffeinate_pid_path = eigeninference_dir.join("caffeinate.pid"); + let darkbloom_dir = dirs::home_dir().unwrap_or_default().join(".darkbloom"); + let pid_path = darkbloom_dir.join("provider.pid"); + let caffeinate_pid_path = darkbloom_dir.join("caffeinate.pid"); // Unload launchd service (stops the process and prevents auto-restart) if service::is_loaded() { @@ -5831,7 +5828,7 @@ async fn cmd_update(coordinator: String, force: bool) -> Result<()> { // Download the bundle println!(" Downloading update..."); - let tmp_path = "/tmp/eigeninference-bundle.tar.gz"; + let tmp_path = "/tmp/darkbloom-bundle.tar.gz"; let download = client.get(download_url).send().await?; if !download.status().is_success() { anyhow::bail!("Download failed: {}", download.status()); @@ -5854,34 +5851,31 @@ async fn cmd_update(coordinator: String, force: bool) -> Result<()> { } // Extract and install - let eigeninference_dir = dirs::home_dir() + let darkbloom_dir = dirs::home_dir() .ok_or_else(|| anyhow::anyhow!("cannot find home directory"))? .join(".darkbloom"); - let bin_dir = eigeninference_dir.join("bin"); + let bin_dir = darkbloom_dir.join("bin"); println!(" Installing..."); let status = std::process::Command::new("tar") - .args(["xzf", tmp_path, "-C", &eigeninference_dir.to_string_lossy()]) + .args(["xzf", tmp_path, "-C", &darkbloom_dir.to_string_lossy()]) .status()?; if !status.success() { anyhow::bail!("tar extraction failed"); } // Move binaries to bin dir + let _ = std::fs::rename(darkbloom_dir.join("darkbloom"), bin_dir.join("darkbloom")); let _ = std::fs::rename( - eigeninference_dir.join("darkbloom"), - bin_dir.join("darkbloom"), - ); - let _ = std::fs::rename( - eigeninference_dir.join("eigeninference-enclave"), - bin_dir.join("eigeninference-enclave"), + darkbloom_dir.join("darkbloom-enclave"), + bin_dir.join("darkbloom-enclave"), ); // Make executable #[cfg(unix)] { use std::os::unix::fs::PermissionsExt; - for name in &["darkbloom", "eigeninference-enclave"] { + for name in &["darkbloom", "darkbloom-enclave"] { let path = bin_dir.join(name); if path.exists() { let mut perms = std::fs::metadata(&path)?.permissions(); @@ -5897,10 +5891,10 @@ async fn cmd_update(coordinator: String, force: bool) -> Result<()> { .replace("wss://", "https://") .replace("ws://", "http://") .replace("/ws/provider", ""); - verify_installed_update_runtime(&eigeninference_dir, &coordinator_http, true)?; + verify_installed_update_runtime(&darkbloom_dir, &coordinator_http, true)?; // Verify manifest if included in bundle - let manifest_path = eigeninference_dir.join("manifest.json"); + let manifest_path = darkbloom_dir.join("manifest.json"); if manifest_path.exists() { println!(" Runtime manifest: present ✓"); } @@ -6011,8 +6005,8 @@ fn collect_python_core_signature_targets(dir: &std::path::Path, out: &mut Vec Result<()> { - let darkbloom_path = eigeninference_dir.join("bin/darkbloom"); +fn verify_python_core_signature_match(darkbloom_dir: &std::path::Path) -> Result<()> { + let darkbloom_path = darkbloom_dir.join("bin/darkbloom"); if !darkbloom_path.exists() { anyhow::bail!("updated darkbloom binary missing after install"); } @@ -6020,11 +6014,11 @@ fn verify_python_core_signature_match(eigeninference_dir: &std::path::Path) -> R let darkbloom_team = codesign_team_identifier(&darkbloom_path)?; let mut targets = Vec::new(); - let bundled_python = eigeninference_dir.join("python/bin/python3.12"); + let bundled_python = darkbloom_dir.join("python/bin/python3.12"); if bundled_python.exists() { targets.push(bundled_python); } - collect_python_core_signature_targets(&eigeninference_dir.join("python/lib"), &mut targets); + collect_python_core_signature_targets(&darkbloom_dir.join("python/lib"), &mut targets); targets.sort(); targets.dedup(); @@ -6062,13 +6056,13 @@ fn verify_python_core_signature_match(eigeninference_dir: &std::path::Path) -> R } fn verify_installed_update_runtime( - eigeninference_dir: &std::path::Path, + darkbloom_dir: &std::path::Path, coordinator_http: &str, stdout: bool, ) -> Result<()> { - let bundled_python = eigeninference_dir.join("python/bin/python3.12"); + let bundled_python = darkbloom_dir.join("python/bin/python3.12"); - if let Err(err) = verify_python_core_signature_match(eigeninference_dir) { + if let Err(err) = verify_python_core_signature_match(darkbloom_dir) { emit_update_warning( stdout, &format!(" ⚠ {err} — forcing canonical Python runtime reinstall"), @@ -6112,7 +6106,7 @@ fn verify_installed_update_runtime( if !ensure_python_verified(&python_cmd, coordinator_http) { anyhow::bail!("Python runtime could not be verified after update"); } - verify_python_core_signature_match(eigeninference_dir) + verify_python_core_signature_match(darkbloom_dir) .context("bundled Python core still failed signature validation after reinstall")?; if !ensure_runtime_updated(&python_cmd, coordinator_http) { anyhow::bail!("Python site-packages could not be verified after update"); @@ -6200,34 +6194,31 @@ async fn auto_update_check(coordinator_base_url: &str) -> Result { let tmp_path = "/tmp/darkbloom-auto-update.tar.gz"; std::fs::write(tmp_path, &bytes)?; - let eigeninference_dir = dirs::home_dir() + let darkbloom_dir = dirs::home_dir() .ok_or_else(|| anyhow::anyhow!("cannot find home directory"))? .join(".darkbloom"); - let bin_dir = eigeninference_dir.join("bin"); + let bin_dir = darkbloom_dir.join("bin"); let darkbloom_backup = backup_installed_binary(&bin_dir.join("darkbloom"))?; - let enclave_backup = backup_installed_binary(&bin_dir.join("eigeninference-enclave"))?; + let enclave_backup = backup_installed_binary(&bin_dir.join("darkbloom-enclave"))?; let status = std::process::Command::new("tar") - .args(["xzf", tmp_path, "-C", &eigeninference_dir.to_string_lossy()]) + .args(["xzf", tmp_path, "-C", &darkbloom_dir.to_string_lossy()]) .status()?; if !status.success() { anyhow::bail!("tar extraction failed"); } // Move binaries to bin dir + let _ = std::fs::rename(darkbloom_dir.join("darkbloom"), bin_dir.join("darkbloom")); let _ = std::fs::rename( - eigeninference_dir.join("darkbloom"), - bin_dir.join("darkbloom"), - ); - let _ = std::fs::rename( - eigeninference_dir.join("eigeninference-enclave"), - bin_dir.join("eigeninference-enclave"), + darkbloom_dir.join("darkbloom-enclave"), + bin_dir.join("darkbloom-enclave"), ); #[cfg(unix)] { use std::os::unix::fs::PermissionsExt; - for name in &["darkbloom", "eigeninference-enclave"] { + for name in &["darkbloom", "darkbloom-enclave"] { let path = bin_dir.join(name); if path.exists() { let mut perms = std::fs::metadata(&path)?.permissions(); @@ -6242,14 +6233,13 @@ async fn auto_update_check(coordinator_base_url: &str) -> Result { .replace("wss://", "https://") .replace("ws://", "http://") .replace("/ws/provider", ""); - if let Err(err) = verify_installed_update_runtime(&eigeninference_dir, &coordinator_http, false) - { + if let Err(err) = verify_installed_update_runtime(&darkbloom_dir, &coordinator_http, false) { tracing::error!( "Auto-update runtime verification failed after installing {latest}: {err}. Restoring previous binaries" ); restore_installed_binary(&bin_dir.join("darkbloom"), darkbloom_backup.as_deref())?; restore_installed_binary( - &bin_dir.join("eigeninference-enclave"), + &bin_dir.join("darkbloom-enclave"), enclave_backup.as_deref(), )?; anyhow::bail!("auto-update runtime verification failed: {err}"); @@ -6340,14 +6330,26 @@ async fn cmd_logs(lines: usize, watch: bool) -> Result<()> { fn auth_token_path() -> std::path::PathBuf { dirs::config_dir() .unwrap_or_else(|| std::path::PathBuf::from(".")) - .join("eigeninference") + .join("darkbloom") .join("auth_token") } /// Load the saved auth token, if any. fn load_auth_token() -> Option { let path = auth_token_path(); - std::fs::read_to_string(&path) + if let Some(token) = std::fs::read_to_string(&path) + .ok() + .map(|s| s.trim().to_string()) + .filter(|s| !s.is_empty()) + { + return Some(token); + } + + let legacy_path = dirs::config_dir() + .unwrap_or_else(|| std::path::PathBuf::from(".")) + .join("eigeninference") + .join("auth_token"); + std::fs::read_to_string(&legacy_path) .ok() .map(|s| s.trim().to_string()) .filter(|s| !s.is_empty()) diff --git a/provider/src/secure_enclave_key.rs b/provider/src/secure_enclave_key.rs index da9bcee29..5f5bf216f 100644 --- a/provider/src/secure_enclave_key.rs +++ b/provider/src/secure_enclave_key.rs @@ -33,20 +33,20 @@ use std::ffi::{CStr, CString, c_char, c_int, c_void}; #[cfg(target_os = "macos")] unsafe extern "C" { - fn eigeninference_enclave_create() -> *mut c_void; - fn eigeninference_enclave_free(identity: *mut c_void); - fn eigeninference_enclave_public_key_base64(identity: *const c_void) -> *mut c_char; - fn eigeninference_enclave_sign( + fn darkbloom_enclave_create() -> *mut c_void; + fn darkbloom_enclave_free(identity: *mut c_void); + fn darkbloom_enclave_public_key_base64(identity: *const c_void) -> *mut c_char; + fn darkbloom_enclave_sign( identity: *const c_void, data: *const u8, data_len: c_int, ) -> *mut c_char; - fn eigeninference_enclave_create_attestation_full( + fn darkbloom_enclave_create_attestation_full( identity: *const c_void, encryption_key_base64: *const c_char, binary_hash_hex: *const c_char, ) -> *mut c_char; - fn eigeninference_enclave_free_string(ptr: *mut c_char); + fn darkbloom_enclave_free_string(ptr: *mut c_char); } pub(crate) fn load_existing_x25519_secret() -> Result> { @@ -78,20 +78,20 @@ unsafe impl Sync for SecureEnclaveHandle {} impl SecureEnclaveHandle { #[cfg(target_os = "macos")] pub fn create() -> Result { - let ptr = unsafe { eigeninference_enclave_create() }; + let ptr = unsafe { darkbloom_enclave_create() }; if ptr.is_null() { return Err(anyhow!("Secure Enclave unavailable or key creation failed")); } - let pk_ptr = unsafe { eigeninference_enclave_public_key_base64(ptr) }; + let pk_ptr = unsafe { darkbloom_enclave_public_key_base64(ptr) }; if pk_ptr.is_null() { - unsafe { eigeninference_enclave_free(ptr) }; + unsafe { darkbloom_enclave_free(ptr) }; return Err(anyhow!("failed to retrieve Secure Enclave public key")); } let public_key_b64 = unsafe { CStr::from_ptr(pk_ptr) } .to_string_lossy() .into_owned(); - unsafe { eigeninference_enclave_free_string(pk_ptr) }; + unsafe { darkbloom_enclave_free_string(pk_ptr) }; Ok(Self { ptr, @@ -112,14 +112,14 @@ impl SecureEnclaveHandle { pub fn sign(&self, data: &[u8]) -> Result { use anyhow::Context; let data_len: c_int = data.len().try_into().context("data too large for FFI")?; - let sig_ptr = unsafe { eigeninference_enclave_sign(self.ptr, data.as_ptr(), data_len) }; + let sig_ptr = unsafe { darkbloom_enclave_sign(self.ptr, data.as_ptr(), data_len) }; if sig_ptr.is_null() { return Err(anyhow!("Secure Enclave signing failed")); } let sig = unsafe { CStr::from_ptr(sig_ptr) } .to_string_lossy() .into_owned(); - unsafe { eigeninference_enclave_free_string(sig_ptr) }; + unsafe { darkbloom_enclave_free_string(sig_ptr) }; Ok(sig) } @@ -142,7 +142,7 @@ impl SecureEnclaveHandle { .transpose()?; let json_ptr = unsafe { - eigeninference_enclave_create_attestation_full( + darkbloom_enclave_create_attestation_full( self.ptr, enc_key_c.as_ptr(), hash_c.as_ref().map_or(std::ptr::null(), |c| c.as_ptr()), @@ -154,7 +154,7 @@ impl SecureEnclaveHandle { let json_str = unsafe { CStr::from_ptr(json_ptr) } .to_string_lossy() .into_owned(); - unsafe { eigeninference_enclave_free_string(json_ptr) }; + unsafe { darkbloom_enclave_free_string(json_ptr) }; serde_json::value::RawValue::from_string(json_str).context("attestation JSON is not valid") } @@ -173,7 +173,7 @@ impl SecureEnclaveHandle { impl Drop for SecureEnclaveHandle { fn drop(&mut self) { if !self.ptr.is_null() { - unsafe { eigeninference_enclave_free(self.ptr) }; + unsafe { darkbloom_enclave_free(self.ptr) }; } } } @@ -193,16 +193,20 @@ pub fn legacy_key_files_present() -> Vec { } const LEGACY_KEY_FILES: &[&str] = &[ + ".eigeninference/enclave_key.data", + ".eigeninference/e2e_key.data", + ".eigeninference/e2e_key.provisioned", + ".eigeninference/e2e_key.sealed", + ".eigeninference/node_key", + ".eigeninference/enclave_e2e_ka.data", + ".dginf/enclave_e2e_ka.data", + ".dginf/node_key", ".darkbloom/enclave_key.data", ".darkbloom/e2e_key.data", ".darkbloom/e2e_key.provisioned", ".darkbloom/e2e_key.sealed", ".darkbloom/node_key", ".darkbloom/enclave_e2e_ka.data", - ".dginf/enclave_e2e_ka.data", - ".dginf/node_key", - ".eigeninference/enclave_e2e_ka.data", - ".eigeninference/node_key", ]; pub fn cleanup_legacy_key_files() { diff --git a/provider/src/security.rs b/provider/src/security.rs index 9bba55434..26b6235ae 100644 --- a/provider/src/security.rs +++ b/provider/src/security.rs @@ -299,7 +299,7 @@ pub fn check_mdm_enrolled() -> bool { // Positive signals let has_profile = combined.contains("micromdm") || combined.contains("com.github.micromdm") - || combined.contains("eigeninference") + || combined.contains("darkbloom") || combined.contains("attribute: profileidentifier"); // Negative signal let no_profiles = combined.contains("no configuration profiles"); @@ -587,7 +587,7 @@ pub fn compute_runtime_hashes(python_cmd: &str) -> RuntimeHashes { // Hash the Python binary itself let python_hash = hash_file(std::path::Path::new(python_cmd)); - let eigeninference_dir = dirs::home_dir().unwrap_or_default().join(".darkbloom"); + let darkbloom_dir = dirs::home_dir().unwrap_or_default().join(".darkbloom"); let runtime_hash = runtime_lib_dir_from_python_cmd(python_cmd) .filter(|lib_dir| lib_dir.exists()) .and_then(|lib_dir| { @@ -605,7 +605,7 @@ pub fn compute_runtime_hashes(python_cmd: &str) -> RuntimeHashes { }); // Hash templates in ~/.darkbloom/templates/ - let templates_dir = eigeninference_dir.join("templates"); + let templates_dir = darkbloom_dir.join("templates"); let mut template_hashes = std::collections::HashMap::new(); if templates_dir.exists() { for entry in std::fs::read_dir(&templates_dir).ok().into_iter().flatten() { @@ -671,7 +671,7 @@ pub fn verify_backend_integrity(binary_name: &str) -> Result { /// cannot be sniffed by tcpdump (unlike TCP localhost). pub fn backend_socket_path() -> std::path::PathBuf { let pid = std::process::id(); - std::path::PathBuf::from(format!("/tmp/eigeninference-backend-{pid}.sock")) + std::path::PathBuf::from(format!("/tmp/darkbloom-backend-{pid}.sock")) } /// Clean up the Unix socket file if it exists. @@ -851,7 +851,7 @@ mod tests { #[test] fn test_collect_files_recursive() { - let tmp = std::env::temp_dir().join("eigeninference_test_collect"); + let tmp = std::env::temp_dir().join("darkbloom_test_collect"); let _ = std::fs::remove_dir_all(&tmp); std::fs::create_dir_all(tmp.join("sub")).unwrap(); std::fs::write(tmp.join("a.py"), "# a").unwrap(); @@ -871,7 +871,7 @@ mod tests { #[test] fn test_collect_files_recursive_wildcard() { - let tmp = std::env::temp_dir().join("eigeninference_test_collect_wildcard"); + let tmp = std::env::temp_dir().join("darkbloom_test_collect_wildcard"); let _ = std::fs::remove_dir_all(&tmp); std::fs::create_dir_all(tmp.join("sub")).unwrap(); std::fs::write(tmp.join("a.py"), "# python").unwrap(); @@ -902,7 +902,7 @@ mod tests { #[test] fn test_collect_files_recursive_wildcard_vs_filtered() { - let tmp = std::env::temp_dir().join("eigeninference_test_wildcard_vs_filter"); + let tmp = std::env::temp_dir().join("darkbloom_test_wildcard_vs_filter"); let _ = std::fs::remove_dir_all(&tmp); std::fs::create_dir_all(&tmp).unwrap(); std::fs::write(tmp.join("code.py"), "# python").unwrap(); @@ -922,7 +922,7 @@ mod tests { #[test] fn test_hash_files_sorted_deterministic_with_mixed_types() { - let tmp = std::env::temp_dir().join("eigeninference_test_hash_mixed"); + let tmp = std::env::temp_dir().join("darkbloom_test_hash_mixed"); let _ = std::fs::remove_dir_all(&tmp); std::fs::create_dir_all(&tmp).unwrap(); std::fs::write(tmp.join("a.py"), "python code").unwrap(); @@ -968,7 +968,7 @@ mod tests { #[test] fn test_compute_runtime_hashes_with_temp_structure() { let _guard = env_lock().lock().unwrap(); - let tmp = std::env::temp_dir().join("eigeninference_test_runtime"); + let tmp = std::env::temp_dir().join("darkbloom_test_runtime"); let _ = std::fs::remove_dir_all(&tmp); // Create a mock directory structure @@ -1035,7 +1035,7 @@ mod tests { // Create a temp directory with known files, compute the hash using // our Rust implementation, and independently compute the expected // hash using the CI Python reference script. They MUST match. - let tmp = std::env::temp_dir().join("eigeninference_test_hash_parity"); + let tmp = std::env::temp_dir().join("darkbloom_test_hash_parity"); let _ = std::fs::remove_dir_all(&tmp); let lib_dir = tmp.join("python/lib/python3.12"); diff --git a/scripts/admin.sh b/scripts/admin.sh index 612c53079..4d2207292 100755 --- a/scripts/admin.sh +++ b/scripts/admin.sh @@ -1,7 +1,7 @@ #!/bin/bash set -euo pipefail -# EigenInference Admin CLI +# Darkbloom Admin CLI # # Authenticate with Privy and manage releases, models, and pricing. # @@ -48,7 +48,7 @@ authed_curl() { # ─── Commands ─────────────────────────────────────────────── cmd_login() { - echo "EigenInference Admin Login" + echo "Darkbloom Admin Login" echo "" read -p "Email: " EMAIL diff --git a/scripts/benchmark-light.py b/scripts/benchmark-light.py index 703d707bf..67806b3ec 100644 --- a/scripts/benchmark-light.py +++ b/scripts/benchmark-light.py @@ -6,7 +6,7 @@ import aiohttp BASE_URL = "https://api.darkbloom.dev/v1" -API_KEY = "eigeninference-e47e7299dc7d798ea1bcd706e0f780cb9a98536c7d2124a067f0e40e2b3b5b44" +API_KEY = "darkbloom-e47e7299dc7d798ea1bcd706e0f780cb9a98536c7d2124a067f0e40e2b3b5b44" MODELS = [ "mlx-community/gemma-4-26b-a4b-it-8bit", diff --git a/scripts/benchmark-models.py b/scripts/benchmark-models.py index d5ac3c15e..f68b53771 100644 --- a/scripts/benchmark-models.py +++ b/scripts/benchmark-models.py @@ -12,7 +12,7 @@ import argparse BASE_URL = "https://api.darkbloom.dev/v1" -API_KEY = "eigeninference-e47e7299dc7d798ea1bcd706e0f780cb9a98536c7d2124a067f0e40e2b3b5b44" +API_KEY = "darkbloom-e47e7299dc7d798ea1bcd706e0f780cb9a98536c7d2124a067f0e40e2b3b5b44" MODELS = [ "mlx-community/gemma-4-26b-a4b-it-8bit", diff --git a/scripts/build-bridge-app.sh b/scripts/build-bridge-app.sh index aaf833d47..6ccbe6fe7 100755 --- a/scripts/build-bridge-app.sh +++ b/scripts/build-bridge-app.sh @@ -7,7 +7,7 @@ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" PROJECT_DIR="$(dirname "$SCRIPT_DIR")" BUILD_DIR="$PROJECT_DIR/build" -APP_DIR="$BUILD_DIR/EigenInferenceBridge.app" +APP_DIR="$BUILD_DIR/DarkbloomBridge.app" CONTENTS="$APP_DIR/Contents" MACOS="$CONTENTS/MacOS" BUNDLE_ID="io.darkbloom.ws-bridge" @@ -23,7 +23,7 @@ rm -rf "$APP_DIR" mkdir -p "$MACOS" # Copy binary -cp .build/release/eigeninference-enclave "$MACOS/eigeninference-bridge" +cp .build/release/darkbloom-enclave "$MACOS/darkbloom-bridge" # Create Info.plist cat > "$CONTENTS/Info.plist" << PLIST @@ -32,11 +32,11 @@ cat > "$CONTENTS/Info.plist" << PLIST CFBundleExecutable - eigeninference-bridge + darkbloom-bridge CFBundleIdentifier ${BUNDLE_ID} CFBundleName - EigenInference Bridge + Darkbloom Bridge CFBundleVersion 1.0 CFBundleShortVersionString @@ -74,4 +74,4 @@ codesign --force --sign - \ echo "Built: $APP_DIR" echo "Bundle ID: $BUNDLE_ID" echo "" -echo "Run: $MACOS/eigeninference-bridge tls-bridge" +echo "Run: $MACOS/darkbloom-bridge tls-bridge" diff --git a/scripts/build-bundle.sh b/scripts/build-bundle.sh index 8d111d65e..4d0376d26 100755 --- a/scripts/build-bundle.sh +++ b/scripts/build-bundle.sh @@ -1,11 +1,11 @@ #!/bin/bash set -euo pipefail -# Build the EigenInference provider bundle tarball +# Build the Darkbloom provider bundle tarball # # Creates a self-contained tarball with: # darkbloom Rust CLI binary (no Python linking) -# eigeninference-enclave Swift Secure Enclave CLI +# darkbloom-enclave Swift Secure Enclave CLI # python/ Python 3.12 venv with vllm-mlx, mlx, transformers # # Usage: @@ -18,12 +18,12 @@ set -euo pipefail # - Python 3.12 installed # - Rust toolchain (cargo) # - Swift toolchain (swift) -# - SSH key at ~/.ssh/eigeninference-infra (for --upload) +# - SSH key at ~/.ssh/darkbloom-infra (for --upload) SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" PROJECT_DIR="$(dirname "$SCRIPT_DIR")" -BUNDLE_DIR="/tmp/eigeninference-bundle" -TARBALL="/tmp/eigeninference-bundle-macos-arm64.tar.gz" +BUNDLE_DIR="/tmp/darkbloom-bundle" +TARBALL="/tmp/darkbloom-bundle-macos-arm64.tar.gz" PBS_TAG="20260408" PBS_PYTHON_VERSION="3.12.13" PBS_URL="https://github.com/astral-sh/python-build-standalone/releases/download/${PBS_TAG}/cpython-${PBS_PYTHON_VERSION}+${PBS_TAG}-aarch64-apple-darwin-install_only.tar.gz" @@ -38,7 +38,7 @@ for arg in "$@"; do done echo "╔══════════════════════════════════════════════════╗" -echo "║ EigenInference Bundle Builder ║" +echo "║ Darkbloom Bundle Builder ║" echo "╚══════════════════════════════════════════════════╝" echo "" @@ -54,19 +54,19 @@ fi # ─── 2. Build Swift enclave CLI ─────────────────────────────── if [ "$SKIP_BUILD" = false ]; then - echo "2. Building eigeninference-enclave (Swift)..." + echo "2. Building darkbloom-enclave (Swift)..." cd "$PROJECT_DIR/enclave" swift build -c release 2>&1 | tail -3 - echo " ✓ eigeninference-enclave ($(du -h .build/release/eigeninference-enclave | cut -f1))" + echo " ✓ darkbloom-enclave ($(du -h .build/release/darkbloom-enclave | cut -f1))" echo "" else echo "2. Skipping Swift build (--skip-build)" echo "" fi -ENCLAVE_BIN="$PROJECT_DIR/enclave/.build/release/eigeninference-enclave" +ENCLAVE_BIN="$PROJECT_DIR/enclave/.build/release/darkbloom-enclave" if [ ! -f "$ENCLAVE_BIN" ]; then - echo " WARNING: eigeninference-enclave not found. Attestation will be unavailable." + echo " WARNING: darkbloom-enclave not found. Attestation will be unavailable." fi # ─── 3. Create portable Python 3.12 runtime with inference deps ────────── @@ -75,10 +75,10 @@ rm -rf "$BUNDLE_DIR" mkdir -p "$BUNDLE_DIR" echo " Downloading python-build-standalone ${PBS_PYTHON_VERSION}..." -curl -fsSL "$PBS_URL" -o /tmp/eigeninference-python.tar.gz +curl -fsSL "$PBS_URL" -o /tmp/darkbloom-python.tar.gz mkdir -p "$BUNDLE_DIR/python" -tar xzf /tmp/eigeninference-python.tar.gz --strip-components=1 -C "$BUNDLE_DIR/python" -rm -f /tmp/eigeninference-python.tar.gz +tar xzf /tmp/darkbloom-python.tar.gz --strip-components=1 -C "$BUNDLE_DIR/python" +rm -f /tmp/darkbloom-python.tar.gz PYTHON312="$BUNDLE_DIR/python/bin/python3.12" echo " Using $PYTHON312 ($("$PYTHON312" --version))" @@ -174,9 +174,9 @@ codesign --force --sign - --entitlements "$ENTITLEMENTS" --options runtime "$BUN echo " ✓ darkbloom (signed with hypervisor entitlement)" if [ -f "$ENCLAVE_BIN" ]; then - cp "$ENCLAVE_BIN" "$BUNDLE_DIR/bin/eigeninference-enclave" - codesign --force --sign - --entitlements "$ENTITLEMENTS" --options runtime "$BUNDLE_DIR/bin/eigeninference-enclave" - echo " ✓ eigeninference-enclave (signed)" + cp "$ENCLAVE_BIN" "$BUNDLE_DIR/bin/darkbloom-enclave" + codesign --force --sign - --entitlements "$ENTITLEMENTS" --options runtime "$BUNDLE_DIR/bin/darkbloom-enclave" + echo " ✓ darkbloom-enclave (signed)" fi echo "" @@ -251,33 +251,33 @@ echo "" # ─── 6. Create tarball ──────────────────────────────────────── echo "6. Creating tarball..." rm -f "$TARBALL" -cd /tmp && tar czf "$TARBALL" -C eigeninference-bundle . +cd /tmp && tar czf "$TARBALL" -C darkbloom-bundle . TARBALL_SIZE=$(du -h "$TARBALL" | cut -f1) echo " ✓ $TARBALL ($TARBALL_SIZE)" echo "" # ─── 7. Build macOS app + DMG ───────────────────────────────── echo "7. Building macOS app..." -cd "$PROJECT_DIR/app/EigenInference" +cd "$PROJECT_DIR/app/Darkbloom" swift build -c release 2>&1 | tail -3 -APP_BIN=$(swift build -c release --show-bin-path)/EigenInference +APP_BIN=$(swift build -c release --show-bin-path)/Darkbloom if [ -f "$APP_BIN" ]; then APP_BUILD_DIR="$PROJECT_DIR/build" - rm -rf "$APP_BUILD_DIR/EigenInference.app" - mkdir -p "$APP_BUILD_DIR/EigenInference.app/Contents/MacOS" "$APP_BUILD_DIR/EigenInference.app/Contents/Resources" + rm -rf "$APP_BUILD_DIR/Darkbloom.app" + mkdir -p "$APP_BUILD_DIR/Darkbloom.app/Contents/MacOS" "$APP_BUILD_DIR/Darkbloom.app/Contents/Resources" # Info.plist - cat > "$APP_BUILD_DIR/EigenInference.app/Contents/Info.plist" << 'PLIST' + cat > "$APP_BUILD_DIR/Darkbloom.app/Contents/Info.plist" << 'PLIST' - CFBundleNameEigenInference + CFBundleNameDarkbloom CFBundleIdentifierio.darkbloom.app CFBundleVersion0.1.0 CFBundleShortVersionString0.1.0 - CFBundleExecutableEigenInference + CFBundleExecutableDarkbloom CFBundlePackageTypeAPPL LSMinimumSystemVersion14.0 LSUIElement @@ -286,23 +286,23 @@ if [ -f "$APP_BIN" ]; then PLIST - cp "$APP_BIN" "$APP_BUILD_DIR/EigenInference.app/Contents/MacOS/EigenInference" - codesign --force --sign - --options runtime "$APP_BUILD_DIR/EigenInference.app/Contents/MacOS/EigenInference" 2>/dev/null - codesign --force --sign - --options runtime --no-strict "$APP_BUILD_DIR/EigenInference.app" 2>/dev/null + cp "$APP_BIN" "$APP_BUILD_DIR/Darkbloom.app/Contents/MacOS/Darkbloom" + codesign --force --sign - --options runtime "$APP_BUILD_DIR/Darkbloom.app/Contents/MacOS/Darkbloom" 2>/dev/null + codesign --force --sign - --options runtime --no-strict "$APP_BUILD_DIR/Darkbloom.app" 2>/dev/null # Create DMG - DMG_PATH="$APP_BUILD_DIR/EigenInference-latest.dmg" + DMG_PATH="$APP_BUILD_DIR/Darkbloom-latest.dmg" rm -f "$DMG_PATH" DMG_TMP="$APP_BUILD_DIR/dmg-staging" rm -rf "$DMG_TMP" mkdir -p "$DMG_TMP" - cp -a "$APP_BUILD_DIR/EigenInference.app" "$DMG_TMP/" + cp -a "$APP_BUILD_DIR/Darkbloom.app" "$DMG_TMP/" ln -s /Applications "$DMG_TMP/Applications" - hdiutil create -volname "EigenInference" -srcfolder "$DMG_TMP" -ov -format UDZO "$DMG_PATH" >/dev/null 2>&1 + hdiutil create -volname "Darkbloom" -srcfolder "$DMG_TMP" -ov -format UDZO "$DMG_PATH" >/dev/null 2>&1 rm -rf "$DMG_TMP" DMG_SIZE=$(du -h "$DMG_PATH" | cut -f1) - echo " ✓ EigenInference.app + DMG ($DMG_SIZE)" + echo " ✓ Darkbloom.app + DMG ($DMG_SIZE)" else echo " ⚠ Swift build failed — app not included" fi @@ -311,7 +311,7 @@ echo "" # ─── 8. Upload (optional) ──────────────────────────────────── if [ "$UPLOAD" = true ]; then echo "8. Uploading to server..." - SSH_KEY="$HOME/.ssh/eigeninference-infra" + SSH_KEY="$HOME/.ssh/darkbloom-infra" SERVER="ubuntu@34.197.17.112" if [ ! -f "$SSH_KEY" ]; then @@ -319,19 +319,19 @@ if [ "$UPLOAD" = true ]; then exit 1 fi - scp -i "$SSH_KEY" "$TARBALL" "$SERVER:/tmp/eigeninference-bundle-macos-arm64.tar.gz" + scp -i "$SSH_KEY" "$TARBALL" "$SERVER:/tmp/darkbloom-bundle-macos-arm64.tar.gz" ssh -i "$SSH_KEY" "$SERVER" ' - sudo cp /tmp/eigeninference-bundle-macos-arm64.tar.gz /var/www/html/dl/ - sudo chmod 644 /var/www/html/dl/eigeninference-bundle-macos-arm64.tar.gz + sudo cp /tmp/darkbloom-bundle-macos-arm64.tar.gz /var/www/html/dl/ + sudo chmod 644 /var/www/html/dl/darkbloom-bundle-macos-arm64.tar.gz ' echo " ✓ Bundle uploaded" # Upload DMG - if [ -f "$APP_BUILD_DIR/EigenInference-latest.dmg" ]; then - scp -i "$SSH_KEY" "$APP_BUILD_DIR/EigenInference-latest.dmg" "$SERVER:/tmp/EigenInference-latest.dmg" + if [ -f "$APP_BUILD_DIR/Darkbloom-latest.dmg" ]; then + scp -i "$SSH_KEY" "$APP_BUILD_DIR/Darkbloom-latest.dmg" "$SERVER:/tmp/Darkbloom-latest.dmg" ssh -i "$SSH_KEY" "$SERVER" ' - sudo cp /tmp/EigenInference-latest.dmg /var/www/html/dl/EigenInference-latest.dmg - sudo chmod 644 /var/www/html/dl/EigenInference-latest.dmg + sudo cp /tmp/Darkbloom-latest.dmg /var/www/html/dl/Darkbloom-latest.dmg + sudo chmod 644 /var/www/html/dl/Darkbloom-latest.dmg ' echo " ✓ App DMG uploaded" fi diff --git a/scripts/bundle-app.sh b/scripts/bundle-app.sh index c611c2f06..ef4750d6f 100755 --- a/scripts/bundle-app.sh +++ b/scripts/bundle-app.sh @@ -1,14 +1,14 @@ #!/bin/bash # -# Bundle EigenInference into a self-contained, code-signed macOS .app +# Bundle Darkbloom into a self-contained, code-signed macOS .app # -# Creates EigenInference.app containing: +# Creates Darkbloom.app containing: # Contents/ # Info.plist # MacOS/ -# EigenInference ← Swift menu bar app (main executable) +# Darkbloom ← Swift menu bar app (main executable) # darkbloom ← Rust CLI binary -# eigeninference-enclave ← Swift Secure Enclave CLI +# darkbloom-enclave ← Swift Secure Enclave CLI # Frameworks/ # python/ ← python-build-standalone 3.12 # bin/python3.12 @@ -49,7 +49,7 @@ done SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" PROJECT_DIR="$(dirname "$SCRIPT_DIR")" BUILD_DIR="$PROJECT_DIR/build" -APP_DIR="$BUILD_DIR/EigenInference.app" +APP_DIR="$BUILD_DIR/Darkbloom.app" CONTENTS="$APP_DIR/Contents" MACOS="$CONTENTS/MacOS" RESOURCES="$CONTENTS/Resources" @@ -84,9 +84,9 @@ cat > "$CONTENTS/Info.plist" << PLIST CFBundleName - EigenInference + Darkbloom CFBundleDisplayName - EigenInference + Darkbloom CFBundleIdentifier ${BUNDLE_ID} CFBundleVersion @@ -94,7 +94,7 @@ cat > "$CONTENTS/Info.plist" << PLIST CFBundleShortVersionString ${VERSION} CFBundleExecutable - EigenInference + Darkbloom CFBundlePackageType APPL CFBundleIconFile @@ -139,15 +139,15 @@ ENT # 3. Build Swift app # ───────────────────────────────────────────────────────── echo "2. Building Swift app..." -cd "$PROJECT_DIR/app/EigenInference" +cd "$PROJECT_DIR/app/Darkbloom" swift build -c release 2>&1 | tail -3 -APP_BIN=$(swift build -c release --show-bin-path)/EigenInference +APP_BIN=$(swift build -c release --show-bin-path)/Darkbloom if [ ! -f "$APP_BIN" ]; then - echo " ERROR: Swift build failed. Run: cd app/EigenInference && swift build -c release" + echo " ERROR: Swift build failed. Run: cd app/Darkbloom && swift build -c release" exit 1 fi -cp "$APP_BIN" "$MACOS/EigenInference" -echo " ✓ EigenInference ($(du -h "$MACOS/EigenInference" | cut -f1))" +cp "$APP_BIN" "$MACOS/Darkbloom" +echo " ✓ Darkbloom ($(du -h "$MACOS/Darkbloom" | cut -f1))" # ───────────────────────────────────────────────────────── # 4. Build + copy Rust provider @@ -167,15 +167,15 @@ echo " ✓ darkbloom ($(du -h "$MACOS/darkbloom" | cut -f1)) → also installe # ───────────────────────────────────────────────────────── # 5. Build + copy enclave CLI # ───────────────────────────────────────────────────────── -echo "4. Building eigeninference-enclave..." +echo "4. Building darkbloom-enclave..." cd "$PROJECT_DIR/enclave" swift build -c release 2>&1 | tail -3 -ENCLAVE_BIN=".build/release/eigeninference-enclave" +ENCLAVE_BIN=".build/release/darkbloom-enclave" if [ -f "$ENCLAVE_BIN" ]; then - cp "$ENCLAVE_BIN" "$MACOS/eigeninference-enclave" - echo " ✓ eigeninference-enclave ($(du -h "$MACOS/eigeninference-enclave" | cut -f1))" + cp "$ENCLAVE_BIN" "$MACOS/darkbloom-enclave" + echo " ✓ darkbloom-enclave ($(du -h "$MACOS/darkbloom-enclave" | cut -f1))" else - echo " ⚠ eigeninference-enclave not found (attestation will be unavailable)" + echo " ⚠ darkbloom-enclave not found (attestation will be unavailable)" fi # ───────────────────────────────────────────────────────── @@ -332,7 +332,7 @@ done # Sign the app bundle itself — use --no-strict to handle non-standard # framework layout (Python bundle is not a real macOS framework) -echo " Signing EigenInference.app..." +echo " Signing Darkbloom.app..." codesign --force --options runtime --no-strict \ --entitlements "$ENTITLEMENTS" \ --sign "$IDENTITY" \ @@ -352,7 +352,7 @@ if [ "$NOTARIZE" = "--notarize" ] && [ "$IDENTITY" != "-" ]; then echo "10. Notarizing..." # Create a zip for notarization - NOTARIZE_ZIP="$BUILD_DIR/EigenInference-notarize.zip" + NOTARIZE_ZIP="$BUILD_DIR/Darkbloom-notarize.zip" ditto -c -k --keepParent "$APP_DIR" "$NOTARIZE_ZIP" echo " Submitting to Apple..." @@ -408,7 +408,7 @@ fi # ───────────────────────────────────────────────────────── if [ "$UPLOAD" = true ] && [ -f "$DMG_PATH" ]; then echo "12. Uploading DMG..." - SSH_KEY="$HOME/.ssh/eigeninference-infra" + SSH_KEY="$HOME/.ssh/darkbloom-infra" SERVER="ubuntu@34.197.17.112" if [ ! -f "$SSH_KEY" ]; then @@ -434,12 +434,12 @@ echo "" echo "════════════════════════════════════════════════════" echo "" APP_SIZE=$(du -sh "$APP_DIR" | cut -f1) -echo " EigenInference.app $APP_SIZE" +echo " Darkbloom.app $APP_SIZE" echo "" echo " Contents:" -echo " MacOS/EigenInference SwiftUI menu bar app" +echo " MacOS/Darkbloom SwiftUI menu bar app" echo " MacOS/darkbloom Rust inference provider" -echo " MacOS/eigeninference-enclave Secure Enclave attestation" +echo " MacOS/darkbloom-enclave Secure Enclave attestation" echo " Resources/python/ Python 3.12 + MLX + vllm-mlx" echo "" echo " Security:" @@ -450,7 +450,7 @@ echo " SIP enforcement Any modification → won't launch" echo "" echo " Install:" echo " open $APP_DIR" -echo " # or drag EigenInference.app from DMG to /Applications" +echo " # or drag Darkbloom.app from DMG to /Applications" echo "" echo " Distribute:" if [ "$IDENTITY" = "-" ]; then diff --git a/scripts/deploy-acme.sh b/scripts/deploy-acme.sh index d30c6d590..f97d2b473 100755 --- a/scripts/deploy-acme.sh +++ b/scripts/deploy-acme.sh @@ -10,13 +10,13 @@ set -euo pipefail SERVER="ubuntu@34.197.17.112" -SSH="ssh -o ConnectTimeout=15 -i ~/.ssh/eigeninference-infra $SERVER" -SCP="scp -o ConnectTimeout=15 -i ~/.ssh/eigeninference-infra" +SSH="ssh -o ConnectTimeout=15 -i ~/.ssh/darkbloom-infra $SERVER" +SCP="scp -o ConnectTimeout=15 -i ~/.ssh/darkbloom-infra" echo "=== Step 1: Add ACME proxy to nginx ===" $SSH ' -if ! grep -q "/acme/" /etc/nginx/sites-enabled/eigeninference-mdm; then - sudo sed -i "/# SCEP/i\\\\n # step-ca ACME (device-attest-01)\\n location /acme/ {\\n proxy_pass https://127.0.0.1:9000;\\n proxy_ssl_verify off;\\n proxy_set_header Host api.darkbloom.dev;\\n }" /etc/nginx/sites-enabled/eigeninference-mdm +if ! grep -q "/acme/" /etc/nginx/sites-enabled/darkbloom-mdm; then + sudo sed -i "/# SCEP/i\\\\n # step-ca ACME (device-attest-01)\\n location /acme/ {\\n proxy_pass https://127.0.0.1:9000;\\n proxy_ssl_verify off;\\n proxy_set_header Host api.darkbloom.dev;\\n }" /etc/nginx/sites-enabled/darkbloom-mdm sudo nginx -t && sudo systemctl reload nginx echo "nginx: ACME proxy added" else @@ -35,7 +35,7 @@ echo "Enrollment profile updated" echo "" echo "=== Step 3: Verify ACME endpoint ===" -curl -s https://api.darkbloom.dev/acme/eigeninference-acme/directory | python3 -m json.tool +curl -s https://api.darkbloom.dev/acme/darkbloom-acme/directory | python3 -m json.tool echo "" echo "=== Done ===" diff --git a/scripts/install.sh b/scripts/install.sh index 7c64673d9..be599de72 100644 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -81,30 +81,30 @@ echo "" echo "→ [2/7] Downloading Darkbloom v${VERSION}..." mkdir -p "$INSTALL_DIR" "$BIN_DIR" -curl -f#L "$BUNDLE_URL" -o "/tmp/eigeninference-bundle.tar.gz" +curl -f#L "$BUNDLE_URL" -o "/tmp/darkbloom-bundle.tar.gz" # Verify bundle hash -ACTUAL_HASH=$(shasum -a 256 /tmp/eigeninference-bundle.tar.gz | cut -d' ' -f1) +ACTUAL_HASH=$(shasum -a 256 /tmp/darkbloom-bundle.tar.gz | cut -d' ' -f1) if [ "$ACTUAL_HASH" != "$BUNDLE_HASH" ]; then echo "" echo " ✗ Bundle hash mismatch — download may be corrupted." echo " Expected: $BUNDLE_HASH" echo " Got: $ACTUAL_HASH" - rm -f /tmp/eigeninference-bundle.tar.gz + rm -f /tmp/darkbloom-bundle.tar.gz exit 1 fi echo "" echo " Hash verified ✓" echo " Installing binaries..." -tar xzf /tmp/eigeninference-bundle.tar.gz -C "$INSTALL_DIR" +tar xzf /tmp/darkbloom-bundle.tar.gz -C "$INSTALL_DIR" # Migrate older flat bundle layouts into the current install structure. [ -f "$INSTALL_DIR/darkbloom" ] && mv -f "$INSTALL_DIR/darkbloom" "$BIN_DIR/darkbloom" -[ -f "$INSTALL_DIR/eigeninference-enclave" ] && mv -f "$INSTALL_DIR/eigeninference-enclave" "$BIN_DIR/eigeninference-enclave" +[ -f "$INSTALL_DIR/darkbloom-enclave" ] && mv -f "$INSTALL_DIR/darkbloom-enclave" "$BIN_DIR/darkbloom-enclave" -chmod +x "$BIN_DIR/darkbloom" "$BIN_DIR/eigeninference-enclave" 2>/dev/null || true -rm -f /tmp/eigeninference-bundle.tar.gz +chmod +x "$BIN_DIR/darkbloom" "$BIN_DIR/darkbloom-enclave" 2>/dev/null || true +rm -f /tmp/darkbloom-bundle.tar.gz # Verify code signature (codesign is part of base macOS, no CLT needed) if codesign --verify --verbose "$BIN_DIR/darkbloom" 2>/dev/null; then @@ -128,7 +128,7 @@ if [ -f "$HOME/.bashrc" ] && [ ! -f "$HOME/.zshrc" ]; then fi if ! grep -q "\.darkbloom/bin" "$RC" 2>/dev/null; then # Remove old PATH entries from previous installs - sed -i '' '/\.dginf\/bin/d; /\.eigeninference\/bin/d; /alias eigeninf/d; /alias dginf/d; /# EigenInference/d; /# Darkbloom$/d' "$RC" 2>/dev/null || true + sed -i '' '/\.dginf\/bin/d; /\.darkbloom\/bin/d; /alias eigeninf/d; /alias dginf/d; /# Darkbloom/d; /# Darkbloom$/d' "$RC" 2>/dev/null || true cat >> "$RC" << 'SHELL' # Darkbloom @@ -177,13 +177,13 @@ else RUNTIME_INSTALLED=false # Try R2 release artifacts first (the canonical source). - if [ -n "$VERSION" ] && curl -f#L "$R2_CDN/releases/v${VERSION}/eigeninference-python-macos-arm64.tar.gz" -o "/tmp/eigeninference-python.tar.gz" 2>/dev/null; then + if [ -n "$VERSION" ] && curl -f#L "$R2_CDN/releases/v${VERSION}/darkbloom-python-macos-arm64.tar.gz" -o "/tmp/darkbloom-python.tar.gz" 2>/dev/null; then echo "" echo " Extracting Python runtime..." rm -rf "$INSTALL_DIR/python" mkdir -p "$INSTALL_DIR/python" - tar xzf /tmp/eigeninference-python.tar.gz -C "$INSTALL_DIR/python" - rm -f /tmp/eigeninference-python.tar.gz + tar xzf /tmp/darkbloom-python.tar.gz -C "$INSTALL_DIR/python" + rm -f /tmp/darkbloom-python.tar.gz RUNTIME_INSTALLED=true echo " Python runtime installed ✓" fi @@ -193,11 +193,11 @@ else if [ "$RUNTIME_INSTALLED" = false ] && [ -f "$PYTHON_BIN" ] && "$PYTHON_BIN" -c "print('ok')" 2>/dev/null; then echo " Downloading site-packages..." SITE_DIR="$INSTALL_DIR/python/lib/python3.12/site-packages" - if [ -n "$VERSION" ] && curl -fsSL "$R2_CDN/releases/v${VERSION}/eigeninference-site-packages.tar.gz" -o "/tmp/eigen-site-packages.tar.gz" 2>/dev/null; then + if [ -n "$VERSION" ] && curl -fsSL "$R2_CDN/releases/v${VERSION}/darkbloom-site-packages.tar.gz" -o "/tmp/darkbloom-site-packages.tar.gz" 2>/dev/null; then rm -rf "$SITE_DIR" mkdir -p "$SITE_DIR" - tar xzf /tmp/eigen-site-packages.tar.gz -C "$SITE_DIR" - rm -f /tmp/eigen-site-packages.tar.gz + tar xzf /tmp/darkbloom-site-packages.tar.gz -C "$SITE_DIR" + rm -f /tmp/darkbloom-site-packages.tar.gz RUNTIME_INSTALLED=true echo " Site-packages installed from R2 ✓" fi @@ -225,11 +225,11 @@ if [ -f "$PYTHON_BIN" ] && ! "$PYTHON_BIN" -c "print('ok')" 2>/dev/null; then # Prefer the coordinator-served install.sh (templated) — this copy is # a direct-fetch fallback and stays pinned to the prod CDN defaults. R2_CDN="${R2_CDN:-https://pub-3d1cb668259340eeb2276e1d375c846d.r2.dev}" - if [ -n "$VERSION" ] && curl -fsSL "$R2_CDN/releases/v${VERSION}/eigeninference-site-packages.tar.gz" -o "/tmp/eigen-site-packages.tar.gz" 2>/dev/null; then + if [ -n "$VERSION" ] && curl -fsSL "$R2_CDN/releases/v${VERSION}/darkbloom-site-packages.tar.gz" -o "/tmp/darkbloom-site-packages.tar.gz" 2>/dev/null; then rm -rf "$SITE_DIR" mkdir -p "$SITE_DIR" - tar xzf /tmp/eigen-site-packages.tar.gz -C "$SITE_DIR" - rm -f /tmp/eigen-site-packages.tar.gz + tar xzf /tmp/darkbloom-site-packages.tar.gz -C "$SITE_DIR" + rm -f /tmp/darkbloom-site-packages.tar.gz echo " Packages installed from R2 ✓" else # Fallback: pip install from GitHub @@ -262,7 +262,7 @@ fi echo "" echo "→ [4/7] Setting up Secure Enclave identity..." -"$BIN_DIR/eigeninference-enclave" info >/dev/null 2>&1 \ +"$BIN_DIR/darkbloom-enclave" info >/dev/null 2>&1 \ && echo " Secure Enclave ✓ (P-256 key generated)" \ || echo " Secure Enclave ⚠ (not available on this hardware)" @@ -279,11 +279,11 @@ if [ "$ALREADY_ENROLLED" = true ]; then echo " Already enrolled ✓" elif [ -n "$SERIAL" ]; then echo " Requesting enrollment profile..." - rm -f "/tmp/EigenInference-Enroll-${SERIAL}.mobileconfig" 2>/dev/null + rm -f "/tmp/Darkbloom-Enroll-${SERIAL}.mobileconfig" 2>/dev/null if curl -fsSL -X POST "$COORD_URL/v1/enroll" \ -H "Content-Type: application/json" \ -d "{\"serial_number\": \"$SERIAL\"}" \ - -o "/tmp/EigenInference-Enroll-${SERIAL}.mobileconfig" 2>/dev/null; then + -o "/tmp/Darkbloom-Enroll-${SERIAL}.mobileconfig" 2>/dev/null; then echo "" echo " ┌──────────────────────────────────────────────────┐" echo " │ ACTION REQUIRED: Install the enrollment profile │" @@ -298,7 +298,7 @@ elif [ -n "$SERIAL" ]; then echo " └──────────────────────────────────────────────────┘" echo "" # Register the profile, then open System Settings to the install pane - open "/tmp/EigenInference-Enroll-${SERIAL}.mobileconfig" + open "/tmp/Darkbloom-Enroll-${SERIAL}.mobileconfig" sleep 1 open "x-apple.systempreferences:com.apple.Profiles-Settings.extension" @@ -450,7 +450,7 @@ else fi echo "" -if [ ! -f "$HOME/.config/eigeninference/auth_token" ]; then +if [ ! -f "$HOME/.config/darkbloom/auth_token" ] && [ ! -f "$HOME/.config/eigeninference/auth_token" ]; then echo " ┌──────────────────────────────────────────────┐" echo " │ Link your account to earn rewards: │" echo " │ │" diff --git a/scripts/load-test.py b/scripts/load-test.py index 8c0a946e1..7ea990c84 100644 --- a/scripts/load-test.py +++ b/scripts/load-test.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 """ -EigenInference network load test — escalating concurrency. +Darkbloom network load test — escalating concurrency. Usage: export EIGENINFERENCE_API_KEY="your-key" @@ -331,7 +331,7 @@ def print_summary(levels: list[LevelResult], model: str): async def main(): - parser = argparse.ArgumentParser(description="EigenInference escalating load test") + parser = argparse.ArgumentParser(description="Darkbloom escalating load test") parser.add_argument("--url", default="https://inference-test.openinnovation.dev/v1/chat/completions", help="Chat completions endpoint") parser.add_argument("--model", default="qwen3.5", @@ -357,7 +357,7 @@ async def main(): model = MODEL_ALIASES.get(args.model, args.model) - print(f"EigenInference Load Test") + print(f"Darkbloom Load Test") print(f" Model: {model}") print(f" Levels: {args.levels}") print(f" Reqs/level: {args.requests_per_level}") diff --git a/scripts/sign-hardened.sh b/scripts/sign-hardened.sh index 73bcbb284..a88cf22b5 100755 --- a/scripts/sign-hardened.sh +++ b/scripts/sign-hardened.sh @@ -1,6 +1,6 @@ #!/bin/bash # -# Sign EigenInference binaries with macOS Hardened Runtime. +# Sign Darkbloom binaries with macOS Hardened Runtime. # # Hardened Runtime is the CRITICAL piece that prevents debugger attachment # and memory inspection even with SIP enabled. Without it, our PT_DENY_ATTACH @@ -36,7 +36,7 @@ if [ ! -f "$ENTITLEMENTS" ]; then exit 1 fi -echo "=== EigenInference Hardened Runtime Signing ===" +echo "=== Darkbloom Hardened Runtime Signing ===" echo "Identity: $IDENTITY" echo "Entitlements: $ENTITLEMENTS" echo "" @@ -61,9 +61,9 @@ else fi # Sign enclave CLI binary -ENCLAVE_BIN="$PROJECT_DIR/enclave/.build/release/eigeninference-enclave" +ENCLAVE_BIN="$PROJECT_DIR/enclave/.build/release/darkbloom-enclave" if [ -f "$ENCLAVE_BIN" ]; then - echo "Signing eigeninference-enclave..." + echo "Signing darkbloom-enclave..." codesign --force --options runtime \ --entitlements "$ENTITLEMENTS" \ --sign "$IDENTITY" \ @@ -72,7 +72,7 @@ if [ -f "$ENCLAVE_BIN" ]; then codesign --verify --verbose=2 "$ENCLAVE_BIN" 2>&1 | head -5 echo "" else - echo "WARNING: eigeninference-enclave binary not found at $ENCLAVE_BIN" + echo "WARNING: darkbloom-enclave binary not found at $ENCLAVE_BIN" echo " Build first with: cd enclave && swift build -c release" echo "" fi diff --git a/tests/integration_test.py b/tests/integration_test.py index 4ad23fe3d..1a0e7d78e 100644 --- a/tests/integration_test.py +++ b/tests/integration_test.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 """ -EigenInference Integration Test Suite — Component 4 +Darkbloom Integration Test Suite — Component 4 Tests the full loop: Consumer SDK → Coordinator → Provider Agent → mlx-lm → MLX → GPU @@ -13,7 +13,7 @@ Prerequisites: - Coordinator binary: coordinator/bin/coordinator - - Provider binary: provider/target/release/eigeninference-provider + - Provider binary: provider/target/release/darkbloom-provider - SDK installed: pip install -e sdk/ - mlx-lm installed: pip install mlx-lm - Model downloaded: mlx-community/Qwen3.5-4B-MLX-4bit @@ -36,7 +36,7 @@ BASE = os.path.dirname(os.path.abspath(__file__)) ROOT = os.path.join(BASE, "..") COORDINATOR_BIN = os.path.join(ROOT, "coordinator", "bin", "coordinator") -PROVIDER_BIN = os.path.join(ROOT, "provider", "target", "release", "eigeninference-provider") +PROVIDER_BIN = os.path.join(ROOT, "provider", "target", "release", "darkbloom-provider") MODEL = "mlx-community/Qwen3.5-4B-MLX-4bit" COORDINATOR_PORT = 18080 @@ -340,8 +340,8 @@ def test_4_4_2_init_creates_config(): def test_4_5_1_sdk_models(api_key): """SDK client can list models.""" - from eigeninference import EigenInference - client = EigenInference(base_url=COORDINATOR_URL, api_key=api_key) + from darkbloom import Darkbloom + client = Darkbloom(base_url=COORDINATOR_URL, api_key=api_key) models = client.models.list() assert models.object == "list" client.close() @@ -349,9 +349,9 @@ def test_4_5_1_sdk_models(api_key): def test_4_5_2_sdk_no_provider_error(api_key): """SDK raises ProviderUnavailableError when no provider.""" - from eigeninference import EigenInference - from eigeninference.errors import ProviderUnavailableError - client = EigenInference(base_url=COORDINATOR_URL, api_key=api_key) + from darkbloom import Darkbloom + from darkbloom.errors import ProviderUnavailableError + client = Darkbloom(base_url=COORDINATOR_URL, api_key=api_key) try: client.chat.completions.create( model="nonexistent", @@ -365,9 +365,9 @@ def test_4_5_2_sdk_no_provider_error(api_key): def test_4_5_3_sdk_auth_error(): """SDK raises AuthenticationError with bad key.""" - from eigeninference import EigenInference - from eigeninference.errors import AuthenticationError - client = EigenInference(base_url=COORDINATOR_URL, api_key="bad-key") + from darkbloom import Darkbloom + from darkbloom.errors import AuthenticationError + client = Darkbloom(base_url=COORDINATOR_URL, api_key="bad-key") try: client.models.list() assert False, "Should have raised" @@ -582,7 +582,7 @@ def main(): global passed, failed, skipped print("\n" + "=" * 60) - print(" EigenInference Integration Test Suite — Component 4") + print(" Darkbloom Integration Test Suite — Component 4") print("=" * 60 + "\n") # Check prerequisites