mirror of
https://github.com/kuhyx/signal-bot.git
synced 2026-11-11 17:34:05 +01:00
Shelter cannot work on this phone, and it would not have helped anyway.
It cannot work: setting a Device Owner makes Android enable
no_add_managed_profile, no_add_private_profile and no_add_clone_profile on
every user, which kills Shelter, Island, Private Space and app cloning
alike. Verified on-device rather than inferred -- `pm create-user
--profileOf 0 --managed` returns "Cannot add user: no_add_managed_profile is
enabled". This is the Android 11 COMP deprecation, enforced in three places
in DevicePolicyManagerService and unchanged through Android 16.
It would not have helped: a second Signal *app* is not a second Signal
*account*. Every account needs its own phone number, so the second number
was always the real requirement -- and once you have one, signal-cli can
register it as a PRIMARY device with no phone app, no QR scan and no work
profile at all. That is strictly better than both the linked-device setup
and the Shelter plan: the bot cannot read personal DMs and never posts as
the account owner.
scripts/register_bot.sh drives that flow. It gates on signal-cli >= 0.14.7
rather than hoping: stable container tag 0.100 bundles 0.14.5, and on
2026-03-06 Signal made the post-quantum ratchet mandatory and de-registered
every account whose client lacked it -- a stale client is how a bot dies
silently months later. Verified that the recommended CI tag really does
bundle 0.14.7 instead of assuming it.
Rehearsed offline, not written blind. fake_signal grew /v1/accounts,
/v1/register/{number}, /v1/register/{number}/verify/{token} and
/v1/groups/{number}, so the whole runbook including every error path
(missing captcha, stray verify, wrong code, unregistered number, empty group
list, out-of-range and non-numeric picks) runs against the fake. The picker
was proven to resolve the group the user actually pointed at.
Prompts now read from $SIGNAL_TTY instead of /dev/tty directly. A hard-coded
/dev/tty made the interactive path untestable without a real terminal; the
seam is the same idea as the injected clock and transport on the Python side,
and is what let the picker be rehearsed at all.
live_smoke.sh and register_bot.sh share scripts/lib_signal.sh so the two
cannot drift, and shellcheck now runs with -x so the sourced lib is actually
linted from its callers.
201 tests, 100% branch coverage, all 23 gates green.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013yaBT45KhHqxTKVCTA87iy
59 lines
1.6 KiB
YAML
59 lines
1.6 KiB
YAML
name: CI
|
|
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
pull_request:
|
|
branches: [main]
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
jobs:
|
|
check:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: Install uv
|
|
uses: astral-sh/setup-uv@v5
|
|
|
|
- name: Set up Python
|
|
run: uv python install 3.14
|
|
|
|
- name: Install dependencies
|
|
run: |
|
|
uv venv .venv
|
|
uv pip install --python .venv/bin/python -e '.[dev]'
|
|
|
|
# Mirrors the no-noqa pre-commit hook. A suppression must not be able
|
|
# to reach main just because someone committed without hooks installed.
|
|
- name: block suppressions
|
|
run: |
|
|
if grep -rnEi '#\s*(noqa|type:\s*ignore|ruff:\s*noqa)' \
|
|
--include='*.py' signal_bot fake_signal tests; then
|
|
echo '::error::suppressions are not allowed; fix the finding or ask first'
|
|
exit 1
|
|
fi
|
|
|
|
- name: ruff format
|
|
run: .venv/bin/ruff format --check .
|
|
|
|
- name: ruff check (ALL rules)
|
|
run: .venv/bin/ruff check .
|
|
|
|
- name: mypy --strict
|
|
run: .venv/bin/mypy signal_bot fake_signal
|
|
|
|
- name: shellcheck
|
|
# --severity=style is the floor CI enforces; the local pre-commit hook
|
|
# uses the same flag so a version skew cannot pass locally and fail here.
|
|
run: shellcheck -x --severity=style run.sh scripts/*.sh
|
|
|
|
- name: pytest (100% branch coverage)
|
|
run: .venv/bin/python -m pytest -q
|
|
|
|
# The real bot against the fake Signal server. No account, no network.
|
|
- name: end-to-end
|
|
run: ./scripts/e2e.sh
|