screen-locker/stronglift_replacement/workout_app/lib/sandbox/sandbox_http.dart
Krzysztof kuhy Rudnicki b37b7559d8
Some checks failed
dependency freshness / dependencies on newest stable (push) Waiting to run
md-naming / markdown naming convention (push) Waiting to run
pre-commit / pre-commit (${{ matrix.group }}) (flutter, flutter-analyze, ) (push) Waiting to run
pre-commit / pre-commit (${{ matrix.group }}) (mypy, mypy, ) (push) Waiting to run
pre-commit / pre-commit (${{ matrix.group }}) (pylint, pylint, ) (push) Waiting to run
pre-commit / pre-commit (${{ matrix.group }}) (rest, , mypy,pylint,flutter-analyze) (push) Waiting to run
Tests / test (push) Waiting to run
Tests / lock-popup-safety (push) Waiting to run
Tests / flutter test (shard ${{ matrix.shard }}) (0) (push) Waiting to run
Tests / flutter test (shard ${{ matrix.shard }}) (1) (push) Waiting to run
Tests / flutter test (shard ${{ matrix.shard }}) (2) (push) Waiting to run
Tests / flutter test (shard ${{ matrix.shard }}) (3) (push) Waiting to run
Tests / flutter test (shard ${{ matrix.shard }}) (4) (push) Waiting to run
Tests / flutter test (shard ${{ matrix.shard }}) (5) (push) Waiting to run
Tests / flutter test (shard ${{ matrix.shard }}) (6) (push) Waiting to run
Tests / flutter test (shard ${{ matrix.shard }}) (7) (push) Waiting to run
Tests / flutter test (shard ${{ matrix.shard }}) (8) (push) Waiting to run
Tests / flutter test (shard ${{ matrix.shard }}) (9) (push) Waiting to run
Tests / flutter-coverage (push) Blocked by required conditions
Tests / web-coverage (push) Waiting to run
repo-contract / repo contract (push) Waiting to run
release-apk / release (APK) (push) Has been cancelled
workout poke moves to tcp/8774: 8773 is book-guard's desktop wrapper, whose window the poke server had been answering since 2026-10-09 (phone app rebuilt, selftest default, contract doc)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KrBEzjPRdx5oyp8NtTLW5F
2026-10-10 09:38:21 +02:00

55 lines
2.1 KiB
Dart

/// Network refusal for the sandbox flavor.
library;
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:workout_app/services/pc_poke_wire.dart';
/// Makes every `dart:io` HTTP connection fail before a socket is opened --
/// except the workout poke to the configured PC.
///
/// Installed as `HttpOverrides.global` by `main` in the sandbox. Firebase and
/// GitHub sync both go through `package:http`, whose IO client is built from
/// `HttpClient()` and therefore from these overrides — one seam, not one
/// guard per service. A refused connection surfaces as a normal sync failure
/// in the UI, which is the honest answer: the sandbox is offline by design.
///
/// The single exception is `http://<pokeHost>:8774/v1/workout`, so a sandbox
/// workout can time the PC round trip. The PC verifies the signed
/// `"sandbox": true` and never writes or credits it. Firebase and GitHub are
/// https on 443 and can never match.
class SandboxHttpOverrides extends HttpOverrides {
/// The PC host the poke may reach; set by `PcPairing` whenever the host is
/// loaded or saved. Null means no exception at all.
static String? pokeHost;
/// Whether [uri] is exactly the poke endpoint on the configured PC.
static bool allows(Uri uri) =>
pokeHost != null &&
uri.scheme == 'http' &&
uri.host == pokeHost &&
uri.port == kPcPokePort &&
uri.path == kPcPokePath;
@override
HttpClient createHttpClient(SecurityContext? context) {
return super.createHttpClient(context)
..connectionFactory = (uri, proxyHost, proxyPort) {
if (proxyHost == null && allows(uri)) {
debugPrint(
'WorkoutSandbox: allowing the PC poke to ${uri.host}:${uri.port}',
);
return Socket.startConnect(uri.host, uri.port);
}
debugPrint(
'WorkoutSandbox: refused network connection to ${uri.host} — the '
'sandbox never talks to Firebase or GitHub.',
);
throw const SocketException(
'sandbox flavor: network disabled by design',
);
};
}
}