Roadmap and phases
The order in which Incico v3 is built, what each phase delivers, and what is explicitly deferred.
Updated: 18 September 2026
The whole design is implemented in phases, each ending with a working, tested increment. Phases are sequential where they depend on each other and parallel where they do not. Android and iOS proceeded side by side through phase 4; since 2026-09-18 iOS is paused and phases 5 to 7 are delivered on Android only (see Questions and answers, “Platform order”). The iOS phase 5 work waits, unmerged, on feature/phase-5-ios; when iOS resumes it catches up phase by phase against the same design, i18n keys and vectors, and then follows Android through its own phase 7.
Phase 0: Foundations (this design)
- Design documentation site (this site), all twenty questions answered.
- Repository layout,
CLAUDE.md, coding docs copied and adapted, CI skeleton,gitleaks. - Supabase staging project created, Auth providers configured, e-mail sender verified. The production project waits until phase 7: nothing before the beta needs it, and an idle project is one more place credentials could sit.
Phase 1: Backend core
Delivered 2026-09-12. Fifteen migrations, ten pgTAP files (610 assertions) and 125 Deno tests, all green, plus the deploy script and the backend CI workflow.
- Migrations for accounts, profiles, circles, detail types, all detail tables, connections, invitations, blocks, notifications, devices, audit, rate limits, search tokens, e-mail verifications and the disposable-domain list.
build_snapshot,refresh_snapshots_forandrefresh_reverse_snapshot, the invitation, block and connection functions, search tokens andsearch_profiles, the account-lifecycle functions and the sign-up hook.- pgTAP visibility matrix green. Seed data (Anna, Ben, Cara, one pending invitation).
- Edge functions
push-fanout,delete-account,export-account,verify-email-detailwith Deno tests; storage buckets and policies; the Vault-backed push trigger. deploy.ps1working against staging (incico-staging,ugdoylltwhcbegccqlje).
Deliberately left for later: scheduling expire_invitations with pg_cron (phase 4, when invitations get a user interface), a timed batching window on top of the push coalescing (once there is traffic to measure), and the production Supabase project (phase 7). Deleting a managed profile still sends no contact_removed, which phase 3 closes.
Phase 2: App skeletons
Delivered 2026-09-12. Android app skeleton (Kotlin 2.4.20, KSP 2.3.12, AGP 9.2.1, Gradle 9.4.1, Compose BOM 2025.12.00, Room 2.7.1, supabase-kt 3.8.0 over Ktor 3.5.1, navigation-compose 2.8.5, androidx.credentials 1.5.0 + googleid 1.1.1; 160 unit tests including Robolectric Compose semantics tests on SDK 35; lint 0 errors; CI .github/workflows/android.yml; emulator smoke against local Supabase green) and an iOS app skeleton (hand-written Xcode project, supabase-swift 2.55.2 the only package, deployment target 17.0, SWIFT_STRICT_CONCURRENCY = complete with SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor, team 47HUKYRBQZ, bundle id nl.sefaja.incico; 180+ unit tests and a smoke UI test green on iPhone 16 and iPad Pro 11-inch (M4) through mobile/ios/mac-run.ps1; CI .github/workflows/ios.yml), sharing design tokens, the 76-key i18n string set and fonts from mobile/design/.
- Android and iOS projects, design tokens, typography, component library (row, card, chip, sheet, header, tab bar, FAB, segmented control, empty state).
AppContainer, Supabase client, secure session storage, sign-in screen (e-mail, Google, Apple), universal links.- Local cache schema and sync-cursor delta fetch, Realtime subscription.
- Tablet shell with the width test, empty states.
Deliberately left for later: WorkManager/BGAppRefreshTask background refresh and FCM/APNs registration (phase 4), Coil (phase 3), release signing (keystore, App Store export) (phase 7), SwiftLint/SwiftFormat/detekt/ktlint (no Homebrew on the Mac mini), Google/Apple provider configuration on Supabase (needs client ids), docs/vectors golden files (phase 3), the medium-width rail expand affordance, and IncicoSizes tokens for the 10 dp circle dot and 40 dp avatar.
Phase 3: Onboarding and profile
Delivered 2026-09-13. Backend: migration 20260913100000_phase3_profile_rules (profiles.managed_relation, accounts.telemetry_consent, per-profile limit triggers raising too_many_details, the year-circles-subset check, delete_profile, replace_detail_type; 650 pgTAP assertions in eleven files) deployed to staging. Shared: mobile/design/countries.json, address-formats.json and phone-metadata.json (generated by tools/gen-phone-metadata.mjs), the golden vectors in docs/vectors/ and their checkers, a 278-key i18n set. Android: the guided onboarding flow, the Profile tab with the six category editors, custom types, the circle selector, e-mail verification, the photo pipeline (Coil 3.5.0, 1024 px cap, no upscale, EXIF dropped by re-encoding), managed profiles, the minimal PostHog client, startup routing and the incomplete-profile banner, an accessibility pass; 482 unit tests, lint clean, emulator smoke against local Supabase green. iOS: the same feature set on SwiftUI with its own phone and address formatters over the shared data, 490 unit tests on iPhone 16 and iPad Pro 11-inch (M4), the smoke UI test extended to run the ten-step guided flow, edit a phone and add and delete a managed profile against staging, and mac-run.ps1 now failing a UI run in which nothing passed.
- Onboarding flow (intro, names, phones, e-mails, addresses, dates, photos, telemetry consent).
- Profile tab: view and edit every detail category, custom types, circle assignment per detail, searchable toggles, photo upload with resize and EXIF strip.
- Multiple profiles (main + managed).
Deliberately left for later: instrumented Android journeys (the phase 7 E2E scenarios; phase 3 relies on the manual emulator pass recorded in test.md), driving the photo picker in the iOS UI test, addresses.district on the clients (no format uses it yet), the settings-side telemetry toggle (phase 6), and a copy of each guided step in Dutch reviewed by a native speaker.
Phase 4: Circles and contacts
Delivered 2026-09-14. Backend: migrations 20260914100000_phase4_contacts (hourly expire_invitations through pg_cron, invitations.reminded_at, remind_invitation, preview_circle over the shared snapshot_for_circle, search_token_for_name) and 20260914100100_invitation_parties (A69); 722 pgTAP assertions in thirteen files, 132 Deno tests; push-fanout sends Android a data-only message and iOS one alert with content-available (A57); golden vectors for search tokens and avatar colours. Shared: 494 canonical i18n keys. Android: the Circles tab with add, details, the sees-matrix, members, move and preview; the Contacts tab with groups, search, favourites and the index rail; find people, send, received and sent invitations with the reminder; the contact card from the served snapshot; the notifications list; Firebase push from build-time values, device registration, the fifteen-minute WorkManager refresh and the /n/{id} app link; tablet panes with selection state; an accessibility pass; 1084 unit tests, lint clean, a two-account emulator smoke against local Supabase. iOS: the same feature set on SwiftUI with APNs registration, BGAppRefreshTask, the tap router and the tablet overlay rules; 1138 unit tests on iPhone 16 and iPad Pro 11-inch (M4); the smoke UI test runs an invitation round trip between two staging accounts.
- Circles tab: list, add, edit (name, colour, notify toggle), what-this-circle-sees preview, members, reassign.
- Contacts tab: received, sent, favourites (move up/down, native drag on iOS), all; search; invite (circle + relation + message); accept/decline; contact card from snapshot; nickname; move circle; remove; block.
- Notifications list and push (FCM, APNs), deep link from a tap.
Deliberately left for later: real push delivery on staging until the FCM service account, the APNs key and the app-link certificate fingerprint exist (product owner); drag-and-drop reassignment, multi-select bulk actions, keyboard shortcuts, the calendar reminder, the changed-row highlight and the per-kind notification switches (phase 6); unblocking (phase 6 Settings); migrating off the deprecated FCM token callbacks and the Compose test-rule API (chores); instrumented Android journeys (phase 7).
Phase 5: Connected services
Delivered 2026-09-18 on Android; iOS paused. Backend: migration 20260915100000_phase5_services (sync_services, sync_links, cross_reference, profile_is_findable; 797 pgTAP assertions in sixteen files), the eight-bucket golden vectors in docs/vectors/sync-buckets.json, 665 i18n keys. Android: the device-contacts service with the prominent disclosure, the Google Contacts service over PKCE and the People API (behind INCICO_GOOGLE_CONTACTS_CLIENT_ID, blank until the product owner registers the client), the pure SyncPlanner, the cancel-safe SyncRunner, the cross-reference in batches of two hundred hashes, the Services tab, service details with its buckets, the sync progress screen, onboarding 2.3.1 to 2.3.3 and the fifteen-minute background job (A75). 1,517 unit tests, lint clean. The emulator gate is the end-to-end suite (see End-to-end test process): the services area (E-SVC-01 to 09 and E-ONB-04) passes, and building it found and fixed eight defects, among them a manual Link that never took effect, an Invite addressed to the viewer, a missing add action on the Services tab and a guided flow that skipped its own “All set”. iOS phase 5 waits on feature/phase-5-ios (tasks 0 to 13 of 15).
Deliberately left for later: Microsoft/Outlook (A77; Q5 decided without it); real Google Contacts against Google (needs the OAuth client); linking a hand-typed entry to a contact in a circle the service does not sync lands the entry in To delete — the To link bucket should offer only contacts in the service’s circles (to be settled in phase 6).
- Device contacts service (permission, prominent disclosure, read, reconcile, write with
allow_delete). - Google Contacts service (PKCE public clients, People API, incremental sync tokens).
- Cross-reference: hashed search of the address book against Incico, invite from results, resumable progress.
- Sync progress screen with cancel, buckets UI, per-service circles.
- Microsoft/Outlook prepared behind a feature flag (Graph
Contacts.ReadWrite), enabled if the questions page says so.
Phase 6: Settings, polish, compliance
- Settings: theme, language, contact detail preference, notifications, signed-in devices, privacy (telemetry toggle, export, delete), help (FAQ link, diagnostics), about (version, licences).
- Accessibility acceptance tests, dynamic type pass, RTL structural check.
- Store assets from UI tests, privacy labels, Data Safety form, account-deletion web page.
Phase 7: Beta and release
- Production Supabase project created and deployed to with
deploy.ps1 -Target production. - Internal testing (Play) and TestFlight with the
mobile_releasesgate. - The nine E2E scenarios green on both platforms.
- Staged rollout, then back-merge and retrospective.
Deferred (not in v3.0)
- Ads and the “supporter” purchase (design keeps a
entitlementshook but ships none). - SMS verification of phone numbers.
- Family auto-connect across a tree (v1); only a simple relation label remains.
- Web app; only the deletion/export page.
- German language.
- Business profiles / organisations (v1 mentioned searching “users/businesses”).
- Sharing a profile via link or QR (useful, but new scope; listed as a candidate for 3.1).