Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
61 changes: 61 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# VCS / editor
.git
.github
.gitignore
.gitmodules
.prettierrc
.idea
.vscode
.DS_Store

# Markdown / docs
*.md
!README.md
LICENSE

# Node / TS caches
**/node_modules
frontend/dist
**/build
**/out
**/.cache
**/.turbo
**/.vite
**/*.tsbuildinfo
**/*.log

# Env
.env
.env.local
.env.*.local

# Backend sources not needed for frontend build, but package.json is needed
# for workspace resolution during bun install.
backend/src
backend/worker-configuration.d.ts
backend/wrangler.jsonc

# WASM SOURCES — we only need the pre-built dist/binary outputs.
# Source checkouts include large vendored OpenSSL copies, Rust target dirs, etc.
# WASM native build artifacts (Rust/Emscripten) — only src/dist/binary/pkg needed
wasm/openssl/vendor
wasm/openssl/target
wasm/openssl/precompiled
wasm/libcurl-wasm/client/build
wasm/libcurl-wasm/client/out
wasm/libcurl-wasm/client/fragments
wasm/libcurl-wasm/server
wasm/zsign-wasm/native
wasm/zsign-wasm/build
wasm/zsign-wasm/test

# Tests / scripts not needed at runtime
dependencies/webmuxd/src/__tests__
scripts

# Docker meta
Dockerfile
.dockerignore

# Frontend public anisette libs are shipped via Vite public/ handling —
# keep them, but strip other platform natives if present.
55 changes: 55 additions & 0 deletions .github/workflows/docker-publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
name: Docker Image

on:
push:
branches: [main]
tags: ["v*"]
pull_request:
branches: [main]

env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}

jobs:
build-and-push:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write

steps:
- uses: actions/checkout@v4
with:
submodules: recursive

- uses: docker/setup-buildx-action@v3

- name: Log in to GHCR
if: github.event_name != 'pull_request'
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=ref,event=branch
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=sha

- name: Build and push
uses: docker/build-push-action@v6
with:
context: .
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
42 changes: 40 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,41 @@
# Dependencies
node_modules/
lib/
.idea/
.pnp/
.pnp.js

# Build outputs
dist/
build/
out/
*.tsbuildinfo
# webmuxd package compiled output
dependencies/webmuxd/lib/

# Caches
.cache/
.turbo/
.vite/
.parcel-cache/

# Editor / IDE
.idea/
.vscode/
!.vscode/extensions.json
*.swp
*.swo
.DS_Store

# Logs + env
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
.env
.env.local
.env.*.local

# Misc
coverage/
.wrangler/
repomix-output.xml
26 changes: 16 additions & 10 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,30 +1,36 @@
# AGENTS Guide

## Communication
- Reply to user in Chinese.
- Keep source code, identifiers, and comments in English.

## Package Manager

- Use `bun` for all Node.js dependency and script operations.

## Project Layout

- Core npm package source: `dependencies/webmuxd/src/`
- High-level iMobileDevice interactions: `dependencies/webmuxd/src/core/imobiledevice-client.ts`
- Browser demo app: `frontend/`
- Cloudflare Workers demo backend: `backend/`
- OpenSSL Rust/WASM project: `wasm/openssl/`
- Frontend React app: `frontend/src/`
- Frontend entry: `frontend/src/main.tsx` → `App.tsx`
- Frontend components: `frontend/src/components/`
- Frontend business logic: `frontend/src/lib/` (storage, pair-record, account-session) + `frontend/src/flows/` (pair, login, sign, install)
- Cloudflare Workers backend: `backend/`
- WASM packages: `wasm/openssl/`, `wasm/libcurl-wasm/`, `wasm/zsign-wasm/`

## Key Rule: Avoid Logic Duplication

- Do not re-implement usbmux/lockdown/AFC/InstProxy protocol logic in `frontend`.
- `frontend/src/main.ts` must consume workspace package exports from `webmuxd`.
- Frontend must consume workspace package exports from `webmuxd` via the vite alias.
- If behavior changes are needed, modify `dependencies/webmuxd/` first, then wire it in frontend.

## Build & Validate
- Root build: `bun run build`

- WASM dist (always run before frontend): `bun run build:wasm:dist`
- Dev server: `bun run dev`
- Frontend build: `bun run build:frontend`
- Root lint: `bun run lint`
- Root test: `bun run test`
- Frontend build: `cd frontend && bun run build`
- Frontend tests: `bun run test:frontend`

## Change Style

- Keep changes minimal, focused, and consistent with existing style.
- Prefer removing dead code over keeping legacy paths.
29 changes: 29 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Multi-stage Docker build for the sideload.js frontend.

# --- Stage 1: build ---
FROM oven/bun:1.3-alpine AS build
WORKDIR /app

# Copy manifests first for dependency layer caching.
COPY package.json bun.lock ./
COPY frontend/package.json frontend/
COPY backend/package.json backend/
COPY dependencies/webmuxd/package.json dependencies/webmuxd/
COPY wasm/openssl/package.json wasm/openssl/
COPY wasm/libcurl-wasm/package.json wasm/libcurl-wasm/
COPY wasm/zsign-wasm/package.json wasm/zsign-wasm/
COPY wasm/zsign-wasm/js/package.json wasm/zsign-wasm/js/

RUN bun install --frozen-lockfile --ignore-scripts

# Copy all sources (filtered by .dockerignore).
COPY . .

# Build WASM dist bundles (src→dist copies) then frontend.
RUN bun run build:wasm:dist && cd frontend && bun run build

# --- Stage 2: serve ---
FROM nginx:1.29-alpine
COPY nginx.conf /etc/nginx/conf.d/default.conf
COPY --from=build /app/frontend/dist /usr/share/nginx/html
EXPOSE 3000
58 changes: 52 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,59 @@
# Sideload.js

A pure frontend signing infrastructure.
Browser-based IPA signing and installation. Pair an iOS device over WebUSB, sign with your Apple Developer account, and install — all from a single web page.

## Install
## Quick Start

```bash
bun install --ignore-scripts
bun run dev
```

<!-- TODO: deploy to cf flow -->
Deploy to Cloudflare worker.
Open `http://localhost:5173`.

## Technology
## Project Structure

1. when signing
| Path | Purpose |
|---|---|
| `frontend/` | React + Tailwind SPA (Vite) |
| `backend/` | Cloudflare Workers relay |
| `dependencies/webmuxd/` | WebUSB usbmux/lockdown protocol library |
| `wasm/openssl/` | OpenSSL WASM (TLS + pair record generation) |
| `wasm/libcurl-wasm/` | libcurl WASM (Apple API HTTP via WISP proxy) |
| `wasm/zsign-wasm/` | zsign WASM (IPA re-signing) |
| `scripts/` | WASM native build scripts (Rust + Emscripten) |

## Build

```bash
# WASM dist bundles (copies pre-built src→dist, no compiler needed)
bun run build:wasm:dist

# Frontend production build (runs wasm:dist automatically)
bun run build:frontend

# Full WASM recompile from source (requires Rust, Emscripten, precompiled OpenSSL)
bun run build:wasm
```

## Docker

```bash
bun run build:wasm:dist # ensure WASM dists exist
docker build -t sideload-web .
docker run -p 3000:3000 sideload-web
```

## Test

```bash
bun run test # webmuxd unit tests
bun run test:frontend # frontend vitest suite (141 tests)
```

## Credits

- [libimobiledevice](https://github.com/libimobiledevice/libimobiledevice)
- [webmuxd](https://github.com/hack-different/webmuxd)
- [zsign](https://github.com/nicehash/zsign)
- [openssl-wasm](https://github.com/nicehash/openssl-wasm)
29 changes: 0 additions & 29 deletions README.zh.md

This file was deleted.

Loading
Loading