JacobLinCool / JacobLinCool/particeps

Ship the minimum iOS participant trust-core vertical slice

Open
#21 0 comments 0 reactions 0 assignees View on GitHub
area: ios P3
Dominant language
Kotlin
Stars
0
Forks
0
PR merge metrics
No merged PRs in 30d

Description

> **Renamed by #23.** This issue was written while the project was called Android Data
> Collector. Its terminology has been updated to the Particeps identity now in force. The
> old spellings are rejected inputs, not an earlier dialect.

## Summary

Ship the smallest trustworthy iOS participant application that can import a signed iOS configuration, obtain consent, collect the first supported events, preserve an encrypted study lifecycle, export/upload ciphertext, and delete it locally.

This vertical slice intentionally supports only app lifecycle, `battery_state.v1`, and `temporal_context.v1`. Android-only usage, network, keyboard, and other collectors must be rejected when required; there is no fallback or substitution.

## Requirements

### Import, trust, and enrollment

- Import local `.partcfg` artifacts through Files/document picker and import immutable signed join links/QR through #15.
- Verify Protocol v1 framing, artifact digest, Ed25519 signature, signer fingerprint, platform target, minimum client version, configuration ID, and required capabilities before creating study state.
- Present signer fingerprint, platform-specific collector/access disclosure, destinations, consent text, and study lifecycle before explicit acceptance.
- Generate a fresh random `participant_instance_id` for every accepted import. Preserve any assigned participant ID only inside the encrypted study data.
- Reject import while another study is active and clear all staged bytes after success or failure.
- Do not poll for configuration changes, register for remote commands, or accept silent replacement.

### Encrypted study state

- Generate a per-study AES key and store it in Keychain using a this-device-only accessibility class appropriate to the documented background/lock behavior.
- Store research events in encrypted append-only files with authenticated sequencing and crash-consistent recovery.
- Exclude ciphertext, staged imports/exports, and upload outbox files from iCloud backup and device migration.
- Keep all cleartext research payloads ephemeral and protected by iOS data-protection classes.
- Implement local deletion and withdrawal by deleting the Keychain key first (crypto-shredding), then removing ciphertext and staged/outbox files; report best-effort file cleanup honestly.
- Add no analytics, crash payload collection, or undeclared storage/network destination.

### Lifecycle and supported collectors

- Implement start, pause, resume, finish, withdraw, manual export, automatic receiver upload, and local delete.
- Record bounded encrypted observable lifecycle events with global sequence, wall time, continuous/boot context, producer platform/version, and configuration provenance.
- Implement iOS-appropriate `battery_state.v1` and `temporal_context.v1` producers using the shared registry semantics and explicit platform-specific availability/quality notes.
- Record app foreground/background/suspension/recovery evidence that is actually observable.
- Represent background suspension and unavailable-delivery intervals as explicit quality gaps/limitations. Do not claim Android-equivalent cadence, delivery, power behavior, or sensor completeness.
- Unsupported required collectors fail before consent; optional unsupported behavior follows the exact Protocol v1 rule and is visible, never silently substituted.

### Export and automatic upload

- Produce manual `.partexp` exports compatible with Kotlin, Swift, and Python conformance tests.
- Implement a no-backup, durable, single-item encrypted upload outbox with exact byte replay, fixed length/digest/range/configuration metadata, strict receipt matching, disabled redirects, bounded retries, and watermark/reclaim recovery consistent with #9.
- Upload only to the signed receiver destination in #12.
- Respect iOS background execution limits: automatic upload is best effort and must safely resume later without regenerating the staged bundle.
- Never include assigned participant identity, answers, configuration contents, or decrypted payloads in URLs, notifications, logs, or cleartext upload headers.

### Participant experience

- Provide clear native screens for study state, supported collection, access state, storage/upload status, pause/resume, export, finish, withdraw, and delete.
- Make destructive withdrawal/delete confirmation explicit and explain crypto-shredding/data already exported or uploaded.
- Support English and Traditional Chinese application copy and accessible controls.
- Do not add APNs, server commands, remote configuration, telemetry, advertising identifiers, or extra network destinations.

## Acceptance criteria

- Files and join-link imports verify the same Protocol v1 artifact and produce fresh participant-instance IDs.
- Wrong platform, minimum version, signer, digest, configuration, or required capability fails before consent/storage creation.
- Start/pause/resume/finish/withdraw/delete recover correctly across lock, reboot, process kill, storage errors, and repeated UI actions.
- Pause/withdraw barriers prevent later collector callbacks from being appended.
- Keychain/key-loss and deletion tests prove ciphertext becomes cryptographically unrecoverable after key deletion; backup inspection shows study/outbox material is excluded.
- App lifecycle, battery, and temporal events cross-decrypt in Kotlin/Python and materialize through #14 with correct platform provenance.
- Suspension/background gaps are explicit and no UI, export, or documentation claims Android-equivalent cadence.
- Manual export and automatic upload survive response loss, process death, reboot, and background expiration without changing staged bytes or advancing an unacknowledged watermark.
- Unsupported Android-only required collectors are rejected with no fallback.
- Network inspection proves the app contacts only the signed join artifact during import and signed receiver during upload, with no APNs commands, analytics, telemetry, or remote configuration.

## Documentation

Add the iOS participant guide, platform capability/limitation matrix, consent copy, lifecycle/storage design, Keychain and backup-exclusion model, upload/background-execution behavior, deletion/withdrawal semantics, threat model, test matrix, and App Store privacy disclosures.

## Dependencies

Blocked by #12 (receiver), #15 (signed join links), #16 (battery/temporal schemas), and #20 (Swift Protocol v1 and platform authoring).

Contributor guide

Open the contributing guide

Research direction

Start with dependencies #12, #15, #16, and #20, then read the Protocol v1 requirements and Kotlin/Python conformance expectations. Map the iOS participant slice across import, encrypted lifecycle, collectors, export/upload, UI, and documentation before implementation. Done means the listed acceptance criteria pass, including cross-platform event checks, recovery, deletion, network, and backup tests.

Written by the indexing model from the issue text.

Assessment

Tech stack
ios, kotlin, python, swift
Domain
documentation, mobile-dev, security, testing-qa
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.