Skip to content
Browse documentation
Decided

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_for and refresh_reverse_snapshot, the invitation, block and connection functions, search tokens and search_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-detail with Deno tests; storage buckets and policies; the Vault-backed push trigger.
  • deploy.ps1 working 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_releases gate.
  • 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 entitlements hook 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).