Files
2026-09-17 17:53:51 +02:00

99 lines
7.2 KiB
Markdown

# iOS Advanced Parental Controls
**v0.1: shared family policies, maths rewards, and native iPhone enforcement scaffolding.**
The parent interface is a standards-based web dashboard, usable from a Mac or phone. Each child's iPhone runs **Family Quests**, a SwiftUI companion using FamilyControls, ManagedSettings, and a DeviceActivity monitor extension. A self-hosted Python API owns policy inheritance, pairing, grading, and the reward ledger.
**This is a development MVP, not a production child-safety product.** The backend and pure Swift quota logic have been exercised here. The iOS app has not been built with an Apple SDK or tested on a physical iPhone. Signing, CI, provisioning, and distribution are deliberately left to the repository owner.
## Included
- One household, multiple child profiles, one active iPhone per child. Shared rules with sparse per-child overrides and revision conflict detection.
- Daily entertainment allowance, configurable allowed hours, and capped daily bonuses. Example: five correct arithmetic answers earn ten usage minutes.
- Server-generated addition/subtraction challenges, server-side grading, expiring attempts, and transactional, idempotent reward issuance.
- Single-use pairing/configuration codes, scoped device tokens, parent cookie sessions, revocation, Keychain storage, and explicit device acknowledgements.
- Native app selection and shielding, usage-threshold monitoring, custom shield UI, and a Close action. Cached rules and expired-bonus handling do not require the backend to run continuously.
- Docker/Compose, pinned Python dependencies, XcodeGen specification, tests, and a physical-device acceptance checklist. No build pipeline or signing secrets.
## Start the backend and parent dashboard
Python 3.12+ is required for local development (tested with 3.13). Docker uses Python 3.13.
```sh
git clone git@github.com:felixfoertsch/ios-advanced-parental-controls.git
cd ios-advanced-parental-controls
cp .env.example .env
python3 -c 'import secrets; print(secrets.token_urlsafe(32))'
# Put the generated value into APC_ADMIN_TOKEN in .env.
# Set APC_ORIGIN to the exact browser origin, e.g. https://family.example.net.
docker compose up --build
```
The default loopback dashboard is `http://localhost:8000`. Sign in using `APC_ADMIN_TOKEN`. Add child profiles; there are **no seeded real children, credentials, or family records**.
For a non-Docker development process:
```sh
make bootstrap
set -a; . ./.env; set +a
make serve
```
`make serve` binds only to loopback. For physical phones, put the service behind your HTTPS reverse proxy, use a certificate trusted by the phone, and set `APC_ORIGIN` to that HTTPS origin. Compose also binds to host loopback; attach your proxy appropriately. There is no automatic TLS/proxy configuration. The native Release app refuses plain HTTP; Debug permits HTTP only on loopback, not arbitrary LAN addresses.
## Generate and build the iPhone project
On the Mac build server, install XcodeGen (2.42+) and use an Xcode version suitable for the device OS. The deployment target is iOS 18.0; no unverified iOS 27-specific API is assumed.
```sh
cp ios/Config/Local.xcconfig.example ios/Config/Local.xcconfig
# Set your development team, bundle prefix, and App Group in Local.xcconfig.
make ios-project
xcodebuild -project ios/AdvancedParentalControls.xcodeproj \
-scheme FamilyQuests -configuration Debug \
-destination 'generic/platform=iOS' build
```
The generated project contains the app, DeviceActivity monitor, Shield Configuration, and Shield Action targets. It is intentionally not checked into git; `ios/project.yml` is the source of truth. Configure **Family Controls and the same App Group on all four App IDs/profiles**. Read [Apple setup](docs/APPLE_SETUP.md) before attempting an install or archive. Icons, distribution privacy declarations, entitlement approval, and signing are still owner tasks.
In the web dashboard, create a pairing code. On the child's phone, enter the HTTPS server origin and code, obtain guardian approval, and select **individual entertainment apps**. Leave Family Quests, Phone, messaging needed for safety, and school apps accessible. Whole categories and websites are intentionally rejected in v0. Later selection changes need a new configuration code from the parent dashboard.
## Tests
```sh
make bootstrap
make test # Python API tests + Swift package tests + JS syntax
# Optional real Chromium DOM / real ASGI-backend smoke test, without a network deployment:
.venv/bin/pip install playwright==1.57.0
.venv/bin/playwright install chromium
.venv/bin/python scripts/browser_smoke.py
```
For an existing Chromium installation, set `CHROMIUM_PATH=/path/to/chromium` for the smoke script. `APC_SCREENSHOT=/path/to/screenshot.png` optionally captures its synthetic family dashboard. This script bridges browser fetches to TestClient; it is not a deployed HTTP/TLS or real-device test.
Initial verification: **21 Python tests, 10 Swift tests, browser/ASGI smoke, JavaScript syntax, Swift syntax, and plist/YAML checks passed.** The networking Swift source was also type-checked with Linux Foundation. **Xcode generation/build, Docker image execution, and physical Screen Time behavior were not validated in this environment.** See [acceptance checklist](docs/ACCEPTANCE.md).
## Important v0 boundaries
Rules sync when the child app opens, returns to the foreground, or the child taps Sync. There is no APNs/background remote sync yet. The parent sees the last reported revision and status, not a promise of immediate enforcement. A stricter native Apple restriction can still block an app after this app grants credit.
Time credits are **usage allowance**, not a wall-clock unlock period. The native monitor registers a ladder of cumulative thresholds, including the daily cap. Earning a normal reward does not restart monitoring. Exact remaining usage is not exposed as a fake live countdown. DeviceActivity callback reliability and cumulative counting after a policy/selection change require physical testing.
One same-day allowed window applies every day. There are no separate weekend rules, multi-device pooled budgets, manual chores, learning-app integrations, Android agent, cloud accounts, telemetry dashboards, or native Screen Time-settings import. The family timezone becomes immutable after the first reward in v0 to prevent accidental double-day issuance; proper timezone migration is deferred.
## Repository map
```text
backend/src/apc/ API, SQLite persistence, validation, parent web dashboard
backend/tests/ API, authorization, concurrency, cap and timezone tests
packages/PolicyCore/ Platform-independent Swift policy/quota logic and tests
ios/App/ SwiftUI companion, API client, Keychain credentials
ios/Shared/ App Group state and Apple enforcement adapter
ios/Monitor/ DeviceActivity callbacks
ios/Shield*/ Shield presentation and Close action
ios/project.yml Reproducible XcodeGen project specification
docs/ Architecture, Apple setup, acceptance and security notes
```
The API schema is served at `/openapi.json`; its v0 return envelopes are described in [architecture](docs/ARCHITECTURE.md). Read [security and operations](docs/SECURITY.md) before putting real family data into the service.