# Project plan — datafy_app (Datafy Ai)

Evidence date: 2026-10-18.

Source repository: `git@bitbucket.org:overdrive/datafy_app.git`.

Inspected revision: `main` at `dba98cc7aa6f9868140511a98ef37240887539d0` (`dba98cc`, 2026-01-19 08:59:26 +0200, Jaco Brits, "latest update"). `origin/HEAD` is `main`. No other remote branches were present.

The scan-host path `~/projects/sonar_scan/repos/datafy_app` was not on this machine. The tree below was read from that git revision. OVER-79's recorded tip matches this commit.

This plan describes what the repository contains. It does not decide what the product should become.

There was no `silicon_ark/datafy_app/` directory before this document set. `README.md` is the Flutter default plus one sentence that FlutterFlow projects run on the Flutter stable channel. It does not state a customer problem.

## Product

The user-facing name is **Datafy Ai** (`lib/main.dart` title, `ios/Runner/Info.plist` `CFBundleName`, `README.md` heading). The Android launcher label and the iOS display name are **Datafy**. The Dart package is `datafy_ai`. Android application id, namespace, and iOS bundle id are `coza.datafy.web`. `pubspec.yaml` version is `1.0.54+84`.

Provenance of the names and version: **Implemented**.

The implemented client is a retail field app. A signed-in person picks a brand from `customer_user` rows linked to their user id, then works stores: tasks, promotions, KaChing challenges, and surveys. Representatives initialise PowerSync on the dashboard. Anyone whose stored role is not exactly `Rep` is sent down the admin screens, which query Supabase directly.

Provenance of that purpose: **Inferred** from routes, schema, and screen behaviour. A signed product statement is **Unknown / Requires Confirmation**.

## Objectives

No project-plan file in the repository states objectives. The following are inferred from what the app does:

1. Let a signed-in person select a brand (customer) they are linked to.
2. Let a Rep work that brand's stores, including through a local PowerSync database.
3. Let a non-Rep use a parallel set of admin screens against Supabase.
4. Record sign-in and some task activity in `user_activity`, including a GPS string.
5. Run SonarQube when `main` changes.

Provenance: **Inferred**, except item 5, which is **Implemented** in `bitbucket-pipelines.yml`. Whether any of items 1–4 are the approved product goals is **Unknown / Requires Confirmation**.

## Branch reality

| Line | Tip | Date | What it is |
|---|---|---|---|
| `main` (default; `origin/HEAD`) | `dba98cc` | 2026-01-19 | Current tree. 5 commits total |

| Commit | Date | Subject | Size (git shortstat) |
|---|---|---|---|
| `2e6f31d` | 2024-04-22 | Initial commit | 1 file, 50 insertions (`.gitignore` only) |
| `4c76ef1` | 2024-04-22 | sonar-project.properties created online with Bitbucket | pipeline metadata |
| `3ea2b20` | 2024-04-22 | bitbucket-pipelines.yml created online with Bitbucket | pipeline metadata |
| `5d266b4` | 2024-04-22 | alpha deploy | 203 files, 375840 insertions |
| `dba98cc` | 2026-01-19 | latest update | 432 files changed, 151556 insertions, 716 deletions |

There are no tags on the inspected clone. History between April 2024 and January 2026 is not split into intermediate commits. What changed inside `dba98cc` beyond "the tree grew" was not diffed file by file. Provenance: **Implemented** (git history).

## Scope in the repository

In scope of what is implemented on `main`:

- A Flutter app (Dart SDK `>=3.0.0 <4.0.0`, package version `1.0.54+84`) with `android/`, `ios/`, and `web/` project folders.
- GoRouter screens for login, brand selection, rep work, and a parallel admin set. 51 page widgets export a `routeName`.
- Supabase client at `https://datafy.appmonitor.co.za` (implicit auth flow) and generated table bindings.
- A vendored PowerSync FlutterFlow library at `dependencies/power_sync_b0w5r9`, pointed at `https://67c1c2c9586c8d282a0669f2.powersync.journeyapps.com`.
- Custom actions for GPS, survey upsert, PDF export, WhatsApp share, and task pictures.
- Bitbucket Pipelines: SonarQube on `main` only.
- English and Afrikaans locale entries. Afrikaans string values that were sampled are empty.

Out of scope of the code that was found, or not present as a committed application:

- A written product requirements document, business-rule catalogue, or architecture description inside the application repository.
- Supabase SQL, Row Level Security, database functions, and Edge Functions. The client calls PostgREST tables that live in the Supabase project, not in this repository.
- A store-release pipeline (Fastlane, Play, TestFlight). Android `release` is configured to sign with the debug keystore. See Discrepancies.
- Automated tests of product behaviour. `test/widget_test.dart` pumps `MyApp` and asserts nothing.
- The scan-host names `private_keys/` and `sonarqube_scan.bat`. Those paths are not in `git ls-files` at `dba98cc`.

## System architecture

```text
Flutter client (Android, iOS, web; path URL strategy)
  → GoRouter (lib/flutter_flow/nav/nav.dart)
  → FFAppState (flutter_secure_storage)
  → Supabase at https://datafy.appmonitor.co.za
      → Auth (email/password, implicit flow)
      → PostgREST tables (app_user, customer_user, task, …)
      → Storage buckets "uploads" and "profile" (public URLs)
  → PowerSync (Rep dashboard calls initializePowerSync)
      → local SQLite schema embedded in lib/main.dart
      → sync service https://67c1c2c9586c8d282a0669f2.powersync.journeyapps.com
  → Geolocator (permission and GPS-service checks at sign-in)
```

Admin screens that were sampled (`dashboard_admin_widget.dart`) query Supabase with `queryRows`. They do not call `initializePowerSync`. The Rep dashboard does, on first load (`dashboard_widget.dart`).

Provenance: **Implemented**.

## Major components

| Component | Where | Role |
|---|---|---|
| App entry | `lib/main.dart` | Loads `environment.json`, sets the PowerSync URL and schema, starts Supabase, builds `MyApp` |
| Router | `lib/flutter_flow/nav/nav.dart` | `/` shows Brands when logged in, otherwise Login. `requireAuth` defaults to false and no route sets it true |
| Auth screens | `lib/pages/includes/auth/` | Email and mobile-number sign-in, both via `signInWithEmail`. These are the screens `lib/index.dart` exports |
| Brand picker | `lib/pages/rep/dashboard/brands/` | Lists `customer_user` for the current uid |
| Rep work | `lib/pages/rep/` | Stores, tasks, promos, KaChing, surveys, dashboard |
| Admin work | `lib/pages/admin/` | Parallel screens for the same areas |
| Nav | `lib/pages/includes/nav_bar/` | Home and notifications only when role is exactly `Rep` |
| PowerSync library | `dependencies/power_sync_b0w5r9/` | Local database, write, and connectivity widgets |
| Generated Supabase rows | `lib/backend/supabase/database/tables/` | One Dart file per table or view name |
| Custom actions | `lib/custom_code/actions/` | GPS, surveys, PDFs, WhatsApp, attachments |

## Milestones visible in git

| When | Evidence | Reading |
|---|---|---|
| 2024-04-22 | Initial commit, then Sonar and pipeline files, then `alpha deploy` (203 files) | First application drop landed the same day as the empty repo |
| 2026-01-19 | `latest update` (432 files) | The current product tree. No commit message describes the product change |

No milestone document exists in the repository. Anything beyond those two drops is **Unknown**.

## Known dependencies

Runtime (from `pubspec.yaml`, versions as pinned there):

- Flutter / Dart SDK `>=3.0.0 <4.0.0`
- `supabase_flutter` 2.9.0, `go_router` 12.1.3, `powersync` 1.14.1
- `geolocator` 14.0.1, `image_picker` 1.1.2, `flutter_secure_storage` 10.0.0-beta.4
- Path packages `ff_commons`, `ff_theme`, and `power_sync_b0w5r9` under `dependencies/`
- `sign_in_with_apple` is a dependency. The routed login widget that was read uses email/password only. Whether Apple sign-in is reachable from a screen is **Unknown / Requires Confirmation**

External systems the client calls by URL:

- Supabase `https://datafy.appmonitor.co.za`
- PowerSync `https://67c1c2c9586c8d282a0669f2.powersync.journeyapps.com`
- SonarQube host `https://scan.appmonitor.co.za` (pipeline / `sonar-project.properties`, not the app)
- Public object URLs on the Supabase `uploads` bucket, on `https://alb.datafyapp.co.za`, and on FlutterFlow Google Storage

No AWS API Gateway URL was found under `lib/`. GenAI columns exist on `task` and `product_images`. The service that fills them is not in this repository.

## Current project status

**Implemented** and committed on `main` as of 2026-01-19. The pipeline that runs is analysis, not deployment. Whether this revision is what stores install is **Unknown / Requires Confirmation**.

Silicon Ark already documents a different remote, `flutter_app`, as Datafy Ai: package `datafy_ai`, application id `coza.datafy.web`, version `1.0.79+100103` on `develop` at `7d30344` (2026-04-13). That set is newer than this repository's `1.0.54+84`. This repository does not mention `flutter_app`. Whether `flutter_app` replaced `datafy_app` is **Unknown / Requires Confirmation**. Behaviour written for `flutter_app` is not a requirement of this repository.

Other Silicon Ark sets (`datafy_web`, `datafy_powersync`, `datafy-supabase-functions`, `datafy_lambda`) share table names or the Supabase host. This tree does not declare those repositories as dependencies.

## Discrepancies

| Topic | What the repo shows | What needs a human |
|---|---|---|
| Sibling client | `flutter_app` is a later Datafy Ai package with the same application id | Confirm which repository is the shipping app |
| Version strings | `pubspec.yaml` `1.0.54+84`; `assets/environment_values/environment.json` `appVersion` `1.0.38`. `VersionTable` maps `version.app_version` and is not referenced by screens that were searched | Confirm which version users are told about |
| Auth gate | `FFRoute.requireAuth` exists and is never set true. Only `/` chooses Login vs Brands | Confirm whether deep links should require a session |
| Admin activity | A non-Rep brand tap writes `user_activity.customer_id` as `1`, not `FFAppState().selectedCustomer` | Confirm whether that literal is intended |
| In-store promo write | SQL text says `UPDATE store_promos`. PowerSync schema and the Dart table are `store_promo` | Confirm whether the write hits a real table |
| Scan-host extras | OVER-79 listed `private_keys/` and `sonarqube_scan.bat`. Not in git at this commit | Confirm they are local-only and should stay that way |
| Release signing | `signingConfigs.release` reads `key.properties`, then `buildTypes.release` uses `signingConfigs.debug` | Confirm the shipped Android binary is debug-signed on purpose |
| Afrikaans | Locale `af` is registered. Sampled strings are empty | Confirm whether Afrikaans is in progress or abandoned |
| Tracked tool output | `git ls-files` includes `.dart_tool/` build artefacts (583 tracked paths total) | Confirm whether those files should remain in git |

Secrets that are present in source (the Supabase anon key in `lib/backend/supabase/supabase.dart`) are not copied into this document.
