Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
178 changes: 157 additions & 21 deletions .github/workflows/build-baseline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,17 @@ permissions:
contents: read

jobs:
build-windows:
name: gate / build / windows
runs-on: windows-latest
build-windows-native:
name: build / windows / amd64
runs-on: windows-2025
strategy:
fail-fast: false
permissions:
contents: read
env:
BANDSCOPE_ARTIFACT_OS: windows
BANDSCOPE_ARTIFACT_ARCH: amd64
BANDSCOPE_TARGET_TRIPLE: x86_64-pc-windows-msvc
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
Expand All @@ -39,31 +45,39 @@ jobs:
with:
version: "0.8.6"
- name: Install Rust stable
shell: bash
run: rustup toolchain install stable --profile minimal
- name: Add Windows target
run: rustup target add $env:BANDSCOPE_TARGET_TRIPLE --toolchain stable
- name: Install node dependencies
run: npm ci
- name: Sync Python dependencies
run: uv sync --project services/analysis-engine --group dev --frozen
- name: Build frontend
run: npm run build --workspace @bandscope/desktop
- name: Build native shell
run: cargo +stable build --manifest-path apps/desktop/src-tauri/Cargo.toml --release --locked
- name: Package Windows artifact
run: cargo +stable build --manifest-path apps/desktop/src-tauri/Cargo.toml --release --locked --target $env:BANDSCOPE_TARGET_TRIPLE
- name: Package Windows amd64 artifact
run: python scripts/release/package_desktop_artifact.py
- name: Upload Windows artifact
- name: Upload Windows amd64 artifact
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: bandscope-windows-${{ github.sha }}
name: bandscope-windows-amd64-${{ github.sha }}
path: |
artifacts/*.zip
artifacts/*.sha256
artifacts/*.manifest.txt
build-macos:
name: gate / build / macos
runs-on: macos-latest

build-windows-arm64:
name: build / windows / arm64
runs-on: windows-11-arm
strategy:
fail-fast: false
permissions:
contents: read
env:
BANDSCOPE_ARTIFACT_OS: windows
BANDSCOPE_ARTIFACT_ARCH: arm64
BANDSCOPE_TARGET_TRIPLE: aarch64-pc-windows-msvc
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
Expand All @@ -80,39 +94,159 @@ jobs:
version: "0.8.6"
- name: Install Rust stable
run: rustup toolchain install stable --profile minimal
- name: Add Windows arm target
run: rustup target add $env:BANDSCOPE_TARGET_TRIPLE --toolchain stable
- name: Install node dependencies
run: npm ci
- name: Sync Python dependencies
run: uv sync --project services/analysis-engine --group dev --frozen
- name: Build frontend
run: npm run build --workspace @bandscope/desktop
- name: Build native shell
run: cargo +stable build --manifest-path apps/desktop/src-tauri/Cargo.toml --release --locked
- name: Package macOS artifact
run: cargo +stable build --manifest-path apps/desktop/src-tauri/Cargo.toml --release --locked --target $env:BANDSCOPE_TARGET_TRIPLE
- name: Package Windows arm64 artifact
run: python scripts/release/package_desktop_artifact.py
- name: Upload Windows arm64 artifact
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: bandscope-windows-arm64-${{ github.sha }}
path: |
artifacts/*.zip
artifacts/*.sha256
artifacts/*.manifest.txt

gate-windows:
name: gate / build / windows
runs-on: ubuntu-latest
needs:
- build-windows-native
- build-windows-arm64
steps:
- name: Confirm both Windows architectures built
run: true

build-macos-native:
name: build / macos / amd64
runs-on: macos-15-intel
strategy:
fail-fast: false
permissions:
contents: read
env:
BANDSCOPE_ARTIFACT_OS: macos
BANDSCOPE_ARTIFACT_ARCH: amd64
BANDSCOPE_TARGET_TRIPLE: x86_64-apple-darwin
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: 22
cache: npm
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: "3.12"
- uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5
with:
version: "0.8.6"
- name: Install Rust stable
run: rustup toolchain install stable --profile minimal
- name: Add macOS Intel target
run: rustup target add "$BANDSCOPE_TARGET_TRIPLE" --toolchain stable
- name: Install node dependencies
run: npm ci
- name: Sync Python dependencies
run: uv sync --project services/analysis-engine --group dev --frozen
- name: Build frontend
run: npm run build --workspace @bandscope/desktop
- name: Build native shell
run: cargo +stable build --manifest-path apps/desktop/src-tauri/Cargo.toml --release --locked --target "$BANDSCOPE_TARGET_TRIPLE"
- name: Package macOS amd64 artifact
run: python3 scripts/release/package_desktop_artifact.py
- name: Upload macOS artifact
- name: Upload macOS amd64 artifact
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: bandscope-macos-${{ github.sha }}
name: bandscope-macos-amd64-${{ github.sha }}
path: |
artifacts/*.zip
artifacts/*.sha256
artifacts/*.manifest.txt

build-macos-arm64:
name: build / macos / arm64
runs-on: macos-15
strategy:
fail-fast: false
permissions:
contents: read
env:
BANDSCOPE_ARTIFACT_OS: macos
BANDSCOPE_ARTIFACT_ARCH: arm64
BANDSCOPE_TARGET_TRIPLE: aarch64-apple-darwin
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: 22
cache: npm
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: "3.12"
- uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5
with:
version: "0.8.6"
- name: Install Rust stable
run: rustup toolchain install stable --profile minimal
- name: Add macOS arm target
run: rustup target add "$BANDSCOPE_TARGET_TRIPLE" --toolchain stable
- name: Install node dependencies
run: npm ci
- name: Sync Python dependencies
run: uv sync --project services/analysis-engine --group dev --frozen
- name: Build frontend
run: npm run build --workspace @bandscope/desktop
- name: Build native shell
run: cargo +stable build --manifest-path apps/desktop/src-tauri/Cargo.toml --release --locked --target "$BANDSCOPE_TARGET_TRIPLE"
- name: Package macOS arm64 artifact
run: python3 scripts/release/package_desktop_artifact.py
- name: Upload macOS arm64 artifact
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: bandscope-macos-arm64-${{ github.sha }}
path: |
artifacts/*.zip
artifacts/*.sha256
artifacts/*.manifest.txt

gate-macos:
name: gate / build / macos
runs-on: ubuntu-latest
needs:
- build-macos-native
- build-macos-arm64
steps:
- name: Confirm both macOS architectures built
run: true

attach-windows-release-artifact:
name: release-artifact / windows
if: github.event_name == 'release'
runs-on: ubuntu-latest
needs:
- build-windows
- build-windows-native
- build-windows-arm64
permissions:
contents: write
steps:
- uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
with:
name: bandscope-windows-${{ github.sha }}
pattern: bandscope-windows-*-${{ github.sha }}
path: artifacts
- name: Attach Windows artifact to release
merge-multiple: true
- name: Attach Windows artifacts to release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
RELEASE_TAG: ${{ github.event.release.tag_name }}
Expand All @@ -123,15 +257,17 @@ jobs:
if: github.event_name == 'release'
runs-on: ubuntu-latest
needs:
- build-macos
- build-macos-native
- build-macos-arm64
permissions:
contents: write
steps:
- uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
with:
name: bandscope-macos-${{ github.sha }}
pattern: bandscope-macos-*-${{ github.sha }}
path: artifacts
- name: Attach macOS artifact to release
merge-multiple: true
- name: Attach macOS artifacts to release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
RELEASE_TAG: ${{ github.event.release.tag_name }}
Expand Down
6 changes: 4 additions & 2 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# ARCHITECTURE.md

Last updated: 2026-03-10
Last updated: 2026-03-11

## Brand source

Expand All @@ -22,6 +22,7 @@ Last updated: 2026-03-10

- Windows and macOS build security policy lives in `docs/security/cross-platform-build-policy.md`.
- Target-OS builds are merge gates and release-validation controls, not optional compatibility checks.
- Windows amd64 + arm64 and macOS amd64 + arm64 are all part of the protected-branch and release-validation build baseline.

## GitHub bootstrap source

Expand Down Expand Up @@ -86,6 +87,7 @@ Last updated: 2026-03-10
- Supply-chain controls are part of the bootstrap architecture, not a release-afterthought.
- Dependency review, audit, supply-chain inventory validation, and SBOM generation are expected protected-branch gates for both `develop` and `main`.
- Cross-platform Windows and macOS build coverage is part of the bootstrap security architecture.
- Release artifacts, checksums, and manifests should encode both OS and architecture so packaged binaries remain traceable.
- GitHub-facing setup is staged: no-git -> local-git -> GitHub-connected -> protected-branches with required checks.
- Shared contracts live in `packages/shared-types` so the UI can evolve without importing Python internals.
- Shared contracts should ultimately model section, role, cue, confidence, and export artifacts explicitly enough that desktop UI and analysis outputs do not invent their own parallel schemas.
Expand All @@ -96,7 +98,7 @@ Last updated: 2026-03-10

- `scripts/harness/quickcheck.sh` is the primary local verification entrypoint.
- `scripts/checks/check_rust.sh` is an opt-in local Rust/Tauri gate used when the host has the native desktop toolchain ready.
- CI mirrors the default sequence for JS and Python, and adds a dedicated macOS Rust check job.
- CI mirrors the default sequence for JS and Python, and adds dedicated Windows/macOS native build coverage for both amd64 and arm64 runners.
- Smoke-grade app verification is currently the React shell render plus Python engine health report.
- Security docs and checks are part of the default quickcheck path so design drift is caught early.
- Supply-chain docs, workflow pinning, and lockfile verification are part of the default quickcheck path so dependency drift is caught early.
Expand Down
16 changes: 11 additions & 5 deletions docs/security/cross-platform-build-policy.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

BandScope ships to Windows and macOS.
For that reason, Windows and macOS builds are security controls, not optional compatibility checks.
Each platform must be validated for both `amd64` and `arm64` packaging paths.

Cross-platform builds help catch:

Expand All @@ -14,21 +15,24 @@ Cross-platform builds help catch:

## Mandatory baseline

- every protected-branch change must build on Windows and macOS
- every release or tag validation must build on Windows and macOS
- every protected-branch change must build on Windows `amd64` + `arm64`
- every protected-branch change must build on macOS Intel + arm64
- every release or tag validation must build on the same four OS/architecture combinations
- build jobs must execute real dependency install, frontend build, native shell build, analysis engine packaging sanity, and artifact upload
- build jobs must remain merge gates on both `develop` and `main`
- workflow runner labels must be explicit and architecture-stable rather than `*-latest` shortcuts when the shortcut hides one architecture

## Required check names

- `gate / build / windows`
- `gate / build / macos`

These are intended required checks for both `develop` and `main`.
Each gate must represent both architectures for its OS.

## Release connection

- release validation must produce Windows and macOS artifacts
- release validation must produce Windows amd64, Windows arm64, macOS amd64, and macOS arm64 artifacts
- each artifact must have a checksum
- release artifacts should stay linkable to SBOM artifacts and supplemental inventory
- code signing and notarization readiness should be documented even if signing credentials are not present in CI yet
Expand All @@ -37,8 +41,10 @@ These are intended required checks for both `develop` and `main`.

Mark work as `BLOCKED` or `FAILED` if any of the following is missing:

- Windows build workflow path
- macOS build workflow path
- Windows amd64 build workflow path
- Windows arm64 build workflow path
- macOS amd64 build workflow path
- macOS arm64 build workflow path
- release or tag build coverage
- intended required checks recorded in repo docs
- actual branch protection enforcement when GitHub admin context is required but unavailable
Expand Down
5 changes: 5 additions & 0 deletions docs/security/github-required-checks.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ These are the merge-gate status checks that should be required on protected bran
- `gate / build / windows`
- `gate / build / macos`

`gate / build / windows` must cover both Windows `amd64` and Windows `arm64`.
`gate / build / macos` must cover both macOS Intel (`amd64`) and macOS `arm64`.

### `main`

- `CodeRabbit`
Expand Down Expand Up @@ -46,6 +49,7 @@ These controls are expressed by repo workflows and are expected to be connected
- `supply-chain-inventory`: supplemental validation baseline
- `gate / build / windows`: intended required check
- `gate / build / macos`: intended required check
- per-architecture desktop artifacts: required for Windows amd64/arm64 and macOS amd64/arm64
- release-time SBOM artifact retention: required baseline
- release-time supplemental inventory retention: required baseline

Expand All @@ -55,6 +59,7 @@ These controls are expressed by repo workflows and are expected to be connected
- CycloneDX JSON SBOM must be attached to the GitHub Release when the workflow runs on a Release event
- `supply-chain/supplemental-component-inventory.json` must be uploaded as a GitHub Actions artifact and attached to the GitHub Release on Release events
- packaged desktop artifacts and checksums should remain traceable from the same release record when the release workflow emits them
- release artifacts should include explicit OS/arch naming for Windows amd64, Windows arm64, macOS amd64, and macOS arm64

## Enforcement note

Expand Down
18 changes: 16 additions & 2 deletions scripts/checks/verify_supply_chain.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,16 +124,30 @@ def verify_workflow_coverage() -> list[str]:
"push",
"release:",
"tags:",
"windows-latest",
"macos-latest",
"windows-2025",
"windows-11-arm",
"macos-15-intel",
"macos-15",
"gate / build / windows",
"gate / build / macos",
"release-artifact / macos",
"release-artifact / windows",
"ubuntu-latest",
"bandscope-windows-amd64-${{ github.sha }}",
"bandscope-windows-arm64-${{ github.sha }}",
"bandscope-macos-amd64-${{ github.sha }}",
"bandscope-macos-arm64-${{ github.sha }}",
]:
if build and token not in build:
missing.append(f"build workflow missing token: {token}")
if build and "windows-latest" in build:
missing.append(
"build workflow should not rely on windows-latest for architecture coverage"
)
if build and "macos-latest" in build:
missing.append(
"build workflow should not rely on macos-latest for architecture coverage"
)
return missing


Expand Down
Loading
Loading