Skip to content
Draft
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
80 changes: 80 additions & 0 deletions .github/workflows/android-termius-study.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
name: Isolated API36 Termius official-channel study
on:
pull_request:
branches: [candidate/android-mobile-key-enrollment-20261008]
types: [opened, synchronize, reopened]
paths: [docs/research/termius-android/**, .github/workflows/android-termius-study.yml]
permissions:
contents: read
concurrency:
group: termius-study-${{ github.head_ref }}
cancel-in-progress: true
jobs:
study:
if: github.repository == 'Mafei/tabby' && github.event.pull_request.head.repo.full_name == 'Mafei/tabby' && github.head_ref == 'candidate/android-termius-runtime-study-20261009'
runs-on: ubuntu-24.04
timeout-minutes: 30
env:
# Existing explicit approval covers only this exact Android SDK agreement.
TABBY_ANDROID_SDK_LICENSE_APPROVED_SHA256: 1f8729233617b193fd619213792ae16a41b95d2bbbf525dfe66998252ba68b16
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
ref: ${{ github.event.pull_request.head.sha }}
- name: Disposable tool and evidence directories
run: |
printf 'ANDROID_HOME=%s/termius-study-sdk\nANDROID_SDK_ROOT=%s/termius-study-sdk\nANDROID_USER_HOME=%s/termius-study-user\nANDROID_AVD_HOME=%s/termius-study-avd\n' "$RUNNER_TEMP" "$RUNNER_TEMP" "$RUNNER_TEMP" "$RUNNER_TEMP" >> "$GITHUB_ENV"
mkdir -p study-artifacts
git rev-parse HEAD > study-artifacts/source-sha.txt
- name: Validate research consent and privacy guards
run: python3 -m unittest discover -s docs/research/termius-android -p 'test_*.py' -v
- name: Verify official Play image, ABI, approved agreements and install channel
id: preflight
run: python3 docs/research/termius-android/study.py preflight --output study-artifacts
- uses: actions/setup-java@v4
if: steps.preflight.outputs.can_install == 'true'
with:
distribution: temurin
java-version: 21
- uses: actions/setup-node@v4
if: steps.preflight.outputs.can_install == 'true'
with:
node-version: 24.19.0
- name: Install verified official SDK and Play image without accepting new terms
id: sdk
if: steps.preflight.outputs.can_install == 'true'
run: python3 docs/research/termius-android/study.py install --output study-artifacts
- name: Start only one disposable API36 emulator using existing KVM path
id: boot
if: steps.sdk.outcome == 'success'
run: |
trap 'python3 docs/research/termius-android/study.py diagnose --output study-artifacts' EXIT
node mobile/scripts/prepare-android-emulator.mjs --check-capacity
test -c /dev/kvm
study_runner_uid="$(id -u)"
sudo setfacl -m "u:${study_runner_uid}:rw" /dev/kvm
mkdir -p "$ANDROID_USER_HOME" "$ANDROID_AVD_HOME"
printf 'no\n' | "$ANDROID_HOME/cmdline-tools/latest/bin/avdmanager" create avd --force --name termius-study-api36 --package 'system-images;android-36;google_apis_playstore;x86_64' --device pixel_7
test -f "$ANDROID_AVD_HOME/termius-study-api36.avd/config.ini"
"$ANDROID_HOME/emulator/emulator" -no-window -no-audio -version
"$ANDROID_HOME/emulator/emulator" -avd termius-study-api36 -no-window -no-audio -no-snapshot -no-boot-anim -gpu software -accel on -memory 4096 -cores 4 -port 5554 -verbose > "$RUNNER_TEMP/termius-study-emulator.log" 2>&1 &
"$ANDROID_HOME/platform-tools/adb" start-server
node mobile/scripts/prepare-android-emulator.mjs --serial emulator-5554 --api 36
- name: Observe official install entry and stop at login, terms or permissions
if: always() && steps.sdk.outcome == 'success'
run: python3 docs/research/termius-android/study.py observe --output study-artifacts --boot-ready '${{ steps.boot.outcome == 'success' }}'
- name: Stop only the disposable emulator
if: always()
run: |
if [ -x "$ANDROID_HOME/platform-tools/adb" ]; then
"$ANDROID_HOME/platform-tools/adb" -s emulator-5554 emu kill || true
fi
- name: Upload bounded public research evidence
if: always()
uses: actions/upload-artifact@v4
with:
name: Termius-API36-Official-Study-${{ github.event.pull_request.head.sha }}
path: study-artifacts/
if-no-files-found: error
retention-days: 14
74 changes: 74 additions & 0 deletions docs/research/termius-android/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# Isolated Termius Android runtime study

This independent research candidate starts from sealed Android product
`5ebd250a499f6dff52f4713f84ebcbece09b81c7`. It changes no product source,
product acceptance gates, existing workflow, PR6, PR8 or desktop candidate.
The user authorized one API36 emulator study and its independent draft PR.
This does not authorize implementation of the proposed Termius-inspired UI.

The new workflow runs only for this fork's exact research head targeting the
sealed key-enrollment branch. It uses `contents: read`, checks out the exact PR
head, has a separate concurrency group, and runs one Ubuntu 24.04 KVM job.
It does not trigger the product Android matrix or merge/release anything.

## First run: verify official installation prerequisites

The proposed image is exactly
`system-images;android-36;google_apis_playstore;x86_64`, with Pixel 7 geometry.
This is a research image choice, not a change to the non-Play product matrix.
Official SDK repository metadata must confirm its stable package, API and ABI.
The existing SDK agreement SHA256
`1f8729233617b193fd619213792ae16a41b95d2bbbf525dfe66998252ba68b16`
is reused only after the exact published agreement text matches. The installer
has no `--licenses`, automatic agreement reply or alternative download route.
An added/changed agreement on a requested stable package is saved as public
license evidence and blocks SDK installation. The published catalogs also
contain unrelated preview packages; these are not selected or accepted, and
the report limits selected-package/permission evidence to channel-0 records.
SDK metadata/archives use Google's official repository and the
existing pinned command-line-tools checksum.

The official [Termius installation documentation](https://docs.termius.com/getting-started/download-termius)
points Android users to [Google Play](https://play.google.com/store/apps/details?id=com.server.auditor.ssh.client).
Public pages are checked without cookies, credentials or login. No unofficial
APK, application-package redistribution or account export is used.

If prerequisites pass, the job starts a fresh disposable API36 emulator using
the existing KVM/capacity/readiness path. It records API, ABI, screen size,
density and font scale, then opens only the official Play listing intent.
It never clicks Install, Sign in, Accept, purchase or a permission button.
The first run stops at the actual store/login/terms screen for review. A green
completed research job is not successful Termius installation or Android
product acceptance: consult `preflight.json` and `observation.json`.

## Evidence and later observation scope

CI artifacts bind the exact source SHA/tree, metadata hashes, selected
agreements and actual `adb screencap` capture times/dimensions/SHA256. Fresh AVD
data is never imported. A UI-tree privacy check rejects account-like text,
password fields and nonempty editable fields before storing a screenshot.
Screenshots receive pixel review after retrieval. No app logs, credential
inputs, account data, AVD snapshot or Termius APK are published.
The disposable emulator's startup diagnostic is limited to the last 160 lines
and 128 KiB, with authentication-related lines omitted. It collects no Android
logcat or application logs. This diagnostic does not relax the existing startup
deadline, real native focus checks or product acceptance requirements.

When official installation is possible within authorized boundaries, further
research should record Termius version/installer/ABI and observe Hosts, session
switching, IME open/closed, expanded/scrolling keys, paste, local preedit/input
placement, application Home and system Home behavior. These are **not yet
observed** by this first-run prerequisite harness. Account creation, credentials,
new terms, paid features and unapproved permissions remain stop points. Real
SSH hosts and the user's phone are excluded. Chinese IME behavior requires an
actual available IME and cannot be inferred from synthetic InputConnection
tests, marketing screenshots or iOS documentation.

The official [AVD documentation](https://developer.android.com/studio/run/managing-avds)
distinguishes Google APIs from Play Store images. The already completed
[official-image UI review](https://github.com/Mafei/tabby/pull/8) remains a design
artifact; Play listing images, actual emulator captures and our own design
screens must retain distinct labels. No absence of a visible editor in a static
image establishes how the app implements composition or input focus.

AI disclosure: fully vibe coded by an AI coding agent.
Loading
Loading