Files
offscale-mobile/scripts/ensure-core.sh
T
pastilhas ef3582f2aa init: OffScale — standalone MIT Tailscale/Headscale client
Extracted from the officer-suite monorepo into its own public repo. The app is
open source and free; the rest of the suite is not, so it could not stay in a
tree that ships an account layer.

What moved:

- apps/offscale/*                  -> repo root (App shell, app.json, assets)
- packages/officer-net/            -> modules/officer-net/, a `file:` dependency
- packages/core VPN closure        -> src/vpn/ (screen, hook, native bridge, invite)
- packages/core shared primitives  -> src/ui/ (theme, cards, tabs, backdrop, splash)
- scripts/build-{ios,android}.sh   -> scripts/, cut down to this one app

What deliberately did NOT move: the platform account layer. VpnScreen used to
render core's AppSettingsScreen, which drags in ServersSection -> servers.ts,
useAuth, api.ts, shared-session, install-guard, api-keys. None of that exists
here. src/settings/SettingsScreen.tsx is a fresh replacement rendering exactly
what VpnScreen passed it — the app's own sections plus About — with no Servers
tab, no Appearance control (the app is pinned to dark) and no sign-out.

The one platform reference left in the closure was a dead `import { request }
from './api'` in officer-net.ts, unused since enrollVpn() was removed. Gone. The
app now contacts nothing but the control server you point it at, its peers, and
the enrolment sidecar named inside an invite link you tapped.

Dependencies are pinned to the exact versions the monorepo has installed, not to
ranges: this repo starts from versions already proven to build, and an unpinned
install is a supply-chain decision nobody made. react-query, react-dom,
react-native-screens, expo-secure-store, track-player, expo-audio and
expo-file-system were all declared by the old app and imported by none of this
code, so they are not here.

NOTICE carries Tailscale's BSD-3 text, names the built artifacts that contain
their compiled code, and treats the trademark question separately — including
that src/ui/TailscaleMark.tsx reproduces their logo in the attribution strip.
2026-08-14 20:32:17 +01:00

72 lines
2.8 KiB
Bash
Executable File

#!/usr/bin/env bash
#
# Rebuild the vendored Tailscale core when the Go source is newer than the built artefact.
#
# . scripts/ensure-core.sh ios # or: android
#
# WHY THIS EXISTS
#
# Changing modules/officer-net/gocore requires rebuilding the core by hand, per platform, and nothing
# enforces it. Forgetting is silent until link or compile time, and the error names a symbol rather
# than the cause:
#
# Android e: Unresolved reference 'loginTo'
# iOS error: cannot find 'TailcoreSubnetRoutes' in scope
#
# iOS is the nastier of the two: the Go compiles cleanly and the failure arrives minutes later, in
# Swift, against a vendored xcframework whose headers are simply older than the source beside them.
#
# It compares mtimes rather than hashes: gomobile takes minutes, and a spurious rebuild is far cheaper
# than a stale one. The artefact is touched on success so an unchanged tree does not rebuild twice.
set -uo pipefail
_ec_platform="${1:?usage: ensure-core.sh <ios|android>}"
_ec_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
_ec_gocore="$_ec_root/modules/officer-net/gocore"
case "$_ec_platform" in
ios)
_ec_artifact="$_ec_root/modules/officer-net/ios/libs/TailCore.xcframework"
_ec_script="$_ec_root/modules/officer-net/scripts/build-libtailscale-ios.sh"
;;
android)
_ec_artifact="$_ec_root/modules/officer-net/android/libs/tailcore.aar"
_ec_script="$_ec_root/modules/officer-net/scripts/build-libtailscale-android.sh"
;;
*)
echo "!! ensure-core: unknown platform '$_ec_platform'" >&2
return 1 2>/dev/null || exit 1
;;
esac
# Newest input: any Go source, plus the module files that pin tailscale.com itself.
_ec_newest_src="$(find "$_ec_gocore" -type f \( -name '*.go' -o -name 'go.mod' -o -name 'go.sum' \) \
-exec stat -f '%m' {} + 2>/dev/null | sort -rn | head -1)"
if [[ -e "$_ec_artifact" ]]; then
# The xcframework is a directory, and its own mtime is what this script touches.
_ec_artifact_mtime="$(stat -f '%m' "$_ec_artifact" 2>/dev/null || echo 0)"
else
_ec_artifact_mtime=0
fi
if [[ -z "${_ec_newest_src:-}" ]]; then
echo "ensure-core: no Go sources found — skipping (is gocore missing?)" >&2
elif (( _ec_newest_src > _ec_artifact_mtime )); then
if (( _ec_artifact_mtime == 0 )); then
echo "==> core artefact missing for $_ec_platform — building it (a few minutes)"
else
echo "==> gocore is newer than the built core for $_ec_platform — rebuilding (a few minutes)"
fi
# gomobile lives in ~/go/bin, which is not on PATH in every shell.
if PATH="$PATH:$HOME/go/bin" "$_ec_script"; then
touch "$_ec_artifact" 2>/dev/null || true
echo "==> core rebuilt for $_ec_platform"
else
echo "!! core rebuild FAILED for $_ec_platform — the app build would link a stale core, stopping." >&2
return 1 2>/dev/null || exit 1
fi
else
echo "==> core is up to date for $_ec_platform"
fi