Skip to content

Latest commit

 

History

History
103 lines (73 loc) · 3.29 KB

File metadata and controls

103 lines (73 loc) · 3.29 KB

Contributing to Tethered

Setup

git clone https://github.com/shcherbak-ai/tethered.git
cd tethered
uv sync
uv run pre-commit install --hook-type pre-commit --hook-type commit-msg

Branching

The default branch is dev. All pull requests should target dev. The main branch is for releases only.

feature-branch → dev (PR) → main (release merge)

Running tests

uv run pytest tests/ -v

With coverage:

uv run pytest tests/ -v --cov

Linting and formatting

Pre-commit hooks run all checks automatically on every commit, but you can also run them manually:

uv run pre-commit run --all-files

Individual tools:

uv run ruff check .        # lint
uv run ruff check --fix .  # lint with auto-fix
uv run ruff format .       # format
uv run pyright src/        # type check
uv run interrogate src/ -v # docstring coverage
uv run bandit -c pyproject.toml -r src/  # security scan

Commit messages

This project uses Conventional Commits enforced by commitizen. The commit-msg hook validates every commit message automatically. Run uv run cz commit for an interactive session that guides you through the format.

Project structure

src/tethered/
    __init__.py    # Public API: activate(), deactivate(), EgressBlocked
    _policy.py     # AllowPolicy — pattern parsing and matching (pure logic)
    _core.py       # Audit hook, state management, IP-to-hostname resolution
tests/
    test_policy.py  # Unit tests for AllowPolicy (no network)
    test_core.py    # Integration tests with real sockets

Network safety in tests

IP addresses

Use only reserved, unroutable ranges for IP addresses in tests:

Range Name RFC
192.0.2.0/24 TEST-NET-1 RFC 5737
198.51.100.0/24 TEST-NET-2 RFC 5737
203.0.113.0/24 TEST-NET-3 RFC 5737
2001:db8::/32 Documentation IPv6 RFC 3849
127.0.0.0/8, ::1 Loopback

Never use real, routable IPs (e.g., 8.8.8.8, 93.184.215.14). Even in "allow" tests, TEST-NET addresses ensure no packets reach real servers.

Hostnames

Some integration tests need real DNS resolution to verify that allowed hostnames pass through correctly. Use dns.google or localhost for this. These are the only real hostnames permitted in tests — they perform only a harmless DNS lookup, no application-level connection is made.

Never use hostnames that could trigger unexpected connections to services with side effects (e.g., API endpoints, webhook URLs).

Code conventions

  • Zero runtime dependencies — stdlib only.
  • from __future__ import annotations in all modules.
  • Private modules prefixed with _.
  • Type hints on all public functions.
  • Python 3.10+ only — no syntax from 3.12+ (type statement) or 3.11+ (except*).

Testing conventions

  • Policy tests (test_policy.py): Pure logic, no audit hooks, no network. Bulk of coverage lives here.
  • Integration tests (test_core.py): Use real sockets. The _cleanup autouse fixture calls _reset_state() after each test.
  • Tests must not depend on external network availability for correctness.
  • Blocked connection tests verify EgressBlocked is raised before any packet leaves the machine.