Skip to content

Commit b9bb40f

Browse files
committed
feat: Complete secure-app-framework MVP implementation
- Implement complete WASM component architecture with WIT interfaces - Add cross-platform broker with workspace management and audit logging - Create Tauri-based UI shell with modern web interface - Set up comprehensive CI/CD with multi-platform builds - Implement security scanning and reproducible builds - Add component model with fs, net, log, time, rand interfaces - Create workspace picker with OS-specific implementations - Add policy engine with domain allowlists and audit trails - Generate SBOMs and security artifacts - Complete build automation and packaging scripts This implements the full MVP as specified in the framework documentation, providing a secure, auditable, cross-platform application architecture using WASM components and native brokers.
1 parent d4b8cfc commit b9bb40f

File tree

15 files changed

+2148
-49
lines changed

15 files changed

+2148
-49
lines changed

.github/workflows/build.yml

Lines changed: 322 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,322 @@
1+
name: Build & Release
2+
3+
on:
4+
push:
5+
branches: [ main ]
6+
tags: [ 'v*' ]
7+
pull_request:
8+
branches: [ main ]
9+
workflow_dispatch:
10+
inputs:
11+
release_type:
12+
description: 'Release type'
13+
required: false
14+
default: 'snapshot'
15+
type: choice
16+
options:
17+
- snapshot
18+
- release
19+
20+
env:
21+
CARGO_TERM_COLOR: never
22+
RUST_BACKTRACE: 1
23+
24+
jobs:
25+
# Pre-build checks and validation
26+
check:
27+
name: Check & Lint
28+
runs-on: ubuntu-latest
29+
steps:
30+
- name: Checkout code
31+
uses: actions/checkout@v4
32+
with:
33+
fetch-depth: 0
34+
35+
- name: Setup Rust
36+
uses: dtolnay/rust-toolchain@stable
37+
with:
38+
components: rustfmt, clippy
39+
40+
- name: Setup Node.js for Tauri
41+
uses: actions/setup-node@v4
42+
with:
43+
node-version: '18'
44+
45+
- name: Cache dependencies
46+
uses: actions/cache@v4
47+
with:
48+
path: |
49+
~/.cargo/registry
50+
~/.cargo/git
51+
target
52+
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
53+
restore-keys: ${{ runner.os }}-cargo-
54+
55+
- name: Format check
56+
run: cargo fmt --all -- --check
57+
58+
- name: Clippy
59+
run: cargo clippy --all-features -- -D clippy::panic -D clippy::unwrap_used -D clippy::expect_used
60+
61+
- name: Run tests
62+
run: cargo test --workspace
63+
64+
- name: Security audit
65+
uses: rustsec/audit-check@v2
66+
with:
67+
token: ${{ secrets.GITHUB_TOKEN }}
68+
69+
- name: License check
70+
uses: EmbarkStudios/cargo-deny-action@v1
71+
with:
72+
command: check
73+
74+
# Build WASM component
75+
build-wasm:
76+
name: Build WASM Component
77+
runs-on: ubuntu-latest
78+
needs: check
79+
steps:
80+
- name: Checkout code
81+
uses: actions/checkout@v4
82+
83+
- name: Setup Rust
84+
uses: dtolnay/rust-toolchain@stable
85+
with:
86+
targets: wasm32-wasip1
87+
88+
- name: Install cargo-component
89+
run: cargo install cargo-component --locked
90+
91+
- name: Build WASM component
92+
run: cargo component build --release --package saf-component-demo
93+
94+
- name: Upload WASM artifact
95+
uses: actions/upload-artifact@v4
96+
with:
97+
name: wasm-component
98+
path: target/wasm32-wasip1/release/saf_component_demo.wasm
99+
retention-days: 30
100+
101+
# Build broker for different platforms
102+
build-broker:
103+
name: Build Broker (${{ matrix.target }})
104+
runs-on: ${{ matrix.os }}
105+
needs: check
106+
strategy:
107+
matrix:
108+
include:
109+
- os: ubuntu-latest
110+
target: x86_64-unknown-linux-gnu
111+
name: linux-x64
112+
- os: windows-latest
113+
target: x86_64-pc-windows-msvc
114+
name: windows-x64
115+
- os: macos-latest
116+
target: x86_64-apple-darwin
117+
name: macos-x64
118+
- os: macos-latest
119+
target: aarch64-apple-darwin
120+
name: macos-arm64
121+
122+
steps:
123+
- name: Checkout code
124+
uses: actions/checkout@v4
125+
126+
- name: Setup Rust
127+
uses: dtolnay/rust-toolchain@stable
128+
with:
129+
targets: ${{ matrix.target }}
130+
131+
- name: Setup Node.js for Tauri
132+
uses: actions/setup-node@v4
133+
with:
134+
node-version: '18'
135+
136+
- name: Cache dependencies
137+
uses: actions/cache@v4
138+
with:
139+
path: |
140+
~/.cargo/registry
141+
~/.cargo/git
142+
target
143+
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
144+
restore-keys: ${{ runner.os }}-cargo-
145+
146+
- name: Install dependencies (Linux)
147+
if: matrix.os == 'ubuntu-latest'
148+
run: |
149+
sudo apt-get update
150+
sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf
151+
152+
- name: Build broker
153+
run: cargo build --release --target ${{ matrix.target }} --package broker --features wasmtime-host,ui
154+
155+
- name: Build UI (Tauri)
156+
if: matrix.os != 'ubuntu-latest' || matrix.target != 'aarch64-apple-darwin'
157+
run: |
158+
cd crates/ui
159+
cargo tauri build --no-bundle
160+
161+
- name: Create distribution package
162+
shell: bash
163+
run: |
164+
mkdir -p dist
165+
cd dist
166+
167+
# Create platform-specific package
168+
PACKAGE_NAME="secure-app-framework-${{ matrix.name }}"
169+
mkdir -p "$PACKAGE_NAME"
170+
171+
# Copy broker binary
172+
if [[ "${{ matrix.target }}" == *"windows"* ]]; then
173+
cp "../target/${{ matrix.target }}/release/broker.exe" "$PACKAGE_NAME/"
174+
else
175+
cp "../target/${{ matrix.target }}/release/broker" "$PACKAGE_NAME/"
176+
fi
177+
178+
# Copy WASM component
179+
cp "../target/wasm32-wasip1/release/saf_component_demo.wasm" "$PACKAGE_NAME/" 2>/dev/null || true
180+
181+
# Copy documentation
182+
cp "../README.md" "$PACKAGE_NAME/" 2>/dev/null || true
183+
cp "../LICENSE" "$PACKAGE_NAME/" 2>/dev/null || true
184+
185+
# Create checksums
186+
cd "$PACKAGE_NAME"
187+
if command -v sha256sum >/dev/null 2>&1; then
188+
find . -type f -not -name "*.sha256" -exec sha256sum {} \; > checksums.sha256
189+
fi
190+
cd ..
191+
192+
# Create archive
193+
if [[ "${{ matrix.target }}" == *"windows"* ]]; then
194+
if command -v zip >/dev/null 2>&1; then
195+
zip -r "${PACKAGE_NAME}.zip" "$PACKAGE_NAME"
196+
fi
197+
else
198+
if command -v tar >/dev/null 2>&1; then
199+
tar -czf "${PACKAGE_NAME}.tar.gz" "$PACKAGE_NAME"
200+
fi
201+
fi
202+
203+
- name: Upload broker artifact
204+
uses: actions/upload-artifact@v4
205+
with:
206+
name: broker-${{ matrix.name }}
207+
path: |
208+
target/${{ matrix.target }}/release/broker*
209+
dist/
210+
retention-days: 30
211+
212+
# Generate SBOM and security artifacts
213+
security-artifacts:
214+
name: Generate Security Artifacts
215+
runs-on: ubuntu-latest
216+
needs: [check, build-wasm]
217+
steps:
218+
- name: Checkout code
219+
uses: actions/checkout@v4
220+
221+
- name: Setup Rust
222+
uses: dtolnay/rust-toolchain@stable
223+
224+
- name: Install SBOM tools
225+
run: |
226+
cargo install cyclonedx-bom --locked
227+
curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin
228+
229+
- name: Generate CycloneDX SBOM (Cargo)
230+
run: cyclonedx-bom -o sbom-cyclonedx-cargo.json
231+
232+
- name: Generate Syft SBOM (binaries)
233+
run: syft dir:. -o cyclonedx-json > sbom-cyclonedx-syft.json
234+
235+
- name: Upload SBOMs
236+
uses: actions/upload-artifact@v4
237+
with:
238+
name: sboms
239+
path: |
240+
sbom-*.json
241+
retention-days: 30
242+
243+
# Sign artifacts (for releases)
244+
sign-release:
245+
name: Sign Release Artifacts
246+
runs-on: ubuntu-latest
247+
needs: [build-broker, security-artifacts]
248+
if: startsWith(github.ref, 'refs/tags/v')
249+
steps:
250+
- name: Download all artifacts
251+
uses: actions/download-artifact@v4
252+
with:
253+
path: artifacts
254+
255+
- name: Install cosign
256+
uses: sigstore/cosign-installer@v3
257+
258+
- name: Sign artifacts with cosign
259+
run: |
260+
find artifacts -type f \( -name "*.tar.gz" -o -name "*.zip" -o -name "*.wasm" -o -name "*.json" \) \
261+
-exec cosign sign-blob --yes --identity-token "$ACTIONS_ID_TOKEN" {} \;
262+
env:
263+
ACTIONS_ID_TOKEN: ${{ secrets.GITHUB_TOKEN }}
264+
265+
- name: Upload signed artifacts
266+
uses: actions/upload-artifact@v4
267+
with:
268+
name: signed-artifacts
269+
path: artifacts/
270+
retention-days: 60
271+
272+
# Create GitHub release
273+
release:
274+
name: Create Release
275+
runs-on: ubuntu-latest
276+
needs: sign-release
277+
if: startsWith(github.ref, 'refs/tags/v')
278+
steps:
279+
- name: Download signed artifacts
280+
uses: actions/download-artifact@v4
281+
with:
282+
name: signed-artifacts
283+
path: release-artifacts
284+
285+
- name: Create release
286+
uses: softprops/action-gh-release@v1
287+
with:
288+
files: release-artifacts/**/*
289+
generate_release_notes: true
290+
draft: false
291+
prerelease: ${{ contains(github.ref, 'alpha') || contains(github.ref, 'beta') }}
292+
env:
293+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
294+
295+
# Deploy documentation (optional)
296+
docs:
297+
name: Deploy Documentation
298+
runs-on: ubuntu-latest
299+
needs: check
300+
if: github.ref == 'refs/heads/main'
301+
steps:
302+
- name: Checkout code
303+
uses: actions/checkout@v4
304+
305+
- name: Setup Node.js
306+
uses: actions/setup-node@v4
307+
with:
308+
node-version: '18'
309+
310+
- name: Install dependencies
311+
run: npm ci
312+
313+
- name: Build docs
314+
run: npm run build
315+
316+
- name: Deploy to GitHub Pages
317+
uses: peaceiris/actions-gh-pages@v3
318+
if: github.ref == 'refs/heads/main'
319+
with:
320+
github_token: ${{ secrets.GITHUB_TOKEN }}
321+
publish_dir: ./dist
322+
cname: docs.secure-app-framework.dev

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ members = [
55
"crates/ui",
66
"crates/policy",
77
"crates/audit",
8+
"crates/component-demo",
89
]
910
resolver = "2"
1011

@@ -15,4 +16,3 @@ publish = false
1516

1617
[workspace.lints.rust]
1718
unsafe_code = "forbid"
18-

crates/broker/Cargo.toml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,33 @@ anyhow = { version = "1", optional = true }
1212
wasmtime = { version = "21", optional = true, default-features = false, features = ["component-model"] }
1313
wasmtime-wasi = { version = "21", optional = true }
1414
rand = { version = "0.8", optional = true }
15+
tauri = { version = "2.0", features = [], optional = true }
16+
serde_json = "1.0"
17+
tokio = { version = "1.0", features = ["rt", "rt-multi-thread", "macros"] }
18+
dirs = "5.0"
19+
uuid = { version = "1.0", features = ["v4"] }
20+
async-trait = "0.1"
21+
base64 = "0.22"
22+
url = "2.5"
23+
24+
[target.'cfg(target_os = "linux")'.dependencies]
25+
ashpd = "0.9" # For xdg-desktop-portal
26+
27+
[target.'cfg(target_os = "windows")'.dependencies]
28+
windows = { version = "0.58", features = ["Storage", "Storage_Provider"] }
29+
30+
[target.'cfg(target_os = "macos")'.dependencies]
31+
objc = "0.2"
32+
cocoa = "0.25"
33+
objc-foundation = "0.1"
1534

1635
[[bin]]
1736
name = "broker"
1837
path = "src/main.rs"
1938

2039
[features]
2140
default = []
41+
# UI integration
42+
ui = ["dep:tauri"]
2243
# Wasmtime integration for running components
2344
wasmtime-host = ["dep:wasmtime", "dep:wasmtime-wasi", "dep:anyhow", "dep:rand"]

0 commit comments

Comments
 (0)