Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 85 additions & 0 deletions CONTEXT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# OnTime Front

This context defines product language for the OnTime Flutter app so analytics,
release, and feature discussions use the same terms.

## Language

**Product Usage Event**:
A named record that a user performed a product-relevant action, excluding raw personal content.
_Avoid_: User activity, tracking event, raw interaction log

**Analytics Purpose**:
The approved reason a Product Usage Event may be collected or used.
_Avoid_: Use case, tracking reason

**Experiment**:
A pseudonymous feature or configuration comparison used for product improvement.
_Avoid_: Personalization, marketing campaign, user targeting

**Deferred Analytics Purpose**:
An Analytics Purpose that is recognized but not active until a later privacy and consent review approves it.
_Avoid_: Future tracking, inactive use case

**Pseudonymous Analytics Subject**:
The non-directly-identifying actor associated with a Product Usage Event.
_Avoid_: User identity, personal identity, email identity

**Analytics Preference**:
The user's current choice about whether optional Product Usage Events may be collected.
_Avoid_: Tracking consent, privacy switch

**Help Improve OnTime**:
The user-facing name for the Analytics Preference.
_Avoid_: Tracking, marketing analytics, personalization

**Analytics Provider**:
An external service approved to receive Product Usage Events.
_Avoid_: Tracking vendor, analytics SDK

**Workflow Milestone Event**:
A Product Usage Event that marks completion or failure of a meaningful user workflow step.
_Avoid_: Tap event, raw navigation log, interaction trace

**Analytics Event Parameter**:
An allowlisted non-content value attached to a Product Usage Event.
_Avoid_: Event payload, arbitrary metadata, raw detail

## Relationships

- A **Product Usage Event** may describe a schedule, preparation, notification, alarm, onboarding, or account action without storing the user's raw schedule names, notes, place names, credentials, tokens, or free text.
- First-release **Product Usage Events** are **Workflow Milestone Events**, not every tap or raw navigation step.
- First-release **Workflow Milestone Events** cover analytics preference, onboarding, authentication, schedule, notification permission, alarm, and schedule-finish outcomes.
- A **Product Usage Event** may include **Analytics Event Parameters** such as workflow, result, stable error category, coarse count, coarse duration, platform, or app version.
- An **Analytics Event Parameter** must not contain user-authored text, direct identifiers, tokens, raw exception strings, request bodies, or response bodies.
- A **Product Usage Event** uses a stable snake_case name and includes a schema version.
- A changed **Product Usage Event** meaning requires a new event name or schema version.
- Active first-release **Analytics Purposes** are product improvement, debugging and operations, and experimentation.
- A first-release **Experiment** must not be used for marketing targeting, sensitive segmentation, or personalized treatment.
- Marketing and personalization are **Deferred Analytics Purposes**.
- A **Product Usage Event** belongs to a **Pseudonymous Analytics Subject**, using an internal user or analytics identifier for signed-in use and an installation identifier before sign-in.
- A **Pseudonymous Analytics Subject** must not be an email address, display name, OAuth identifier, FCM token, or raw personal content value.
- The first-release **Analytics Preference** is opt-out for active Analytics Purposes.
- A disabled **Analytics Preference** stops future optional Product Usage Events.
- Before sign-in, the **Analytics Preference** is installation-scoped.
- After sign-in, the **Analytics Preference** is account-scoped and should apply across the user's signed-in devices.
- Before sign-in, a **Product Usage Event** may be associated only with an installation-scoped **Pseudonymous Analytics Subject**.
- After sign-in, future **Product Usage Events** may be associated with a signed-in **Pseudonymous Analytics Subject**.
- After sign-out, future **Product Usage Events** return to an installation-scoped **Pseudonymous Analytics Subject**.
- Account deletion stops future user-linked **Product Usage Events** and may retain historical analytics only in aggregate or de-identified form.
- A first-release **Analytics Provider** may receive Product Usage Events only after privacy, Data Safety, retention, and deletion responsibilities are approved.

## Example dialogue

> **Dev:** "Should the analytics event include the schedule note so we can understand why users are late?"
> **Domain expert:** "No. A **Product Usage Event** can say a schedule was finished late, but it must not include the user's raw note."

## Flagged ambiguities

- "User activities" was used broadly; resolved: the canonical term is **Product Usage Event**, and raw personal content is out of scope.
- "Analytics" was used to include all possible purposes; resolved: marketing and personalization are deferred, not first-release purposes.
- "User identity" for analytics was ambiguous; resolved: analytics uses a **Pseudonymous Analytics Subject**, not directly identifying user data.
- "Consent" was ambiguous for analytics; resolved: first-release analytics is opt-out with a user-visible **Analytics Preference**.
- "Third party" was ambiguous for analytics; resolved: the canonical term is **Analytics Provider**.
- "Event taxonomy" was broad; resolved: first-release analytics tracks **Workflow Milestone Events** only.
- "Event payload" was too open-ended; resolved: events use allowlisted **Analytics Event Parameters** only.
52 changes: 52 additions & 0 deletions docs/Analytics-Event-Catalog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Analytics Event Catalog

This catalog defines the first-release Product Usage Events for OnTime. Events are Workflow Milestone Events only; they must not capture raw user-authored content, direct identifiers, tokens, request bodies, response bodies, raw exception strings, schedule names, notes, place names, or preparation step names.

## Common Parameters

All events include:

| Parameter | Meaning |
| --- | --- |
| `schema_version` | Event schema version. First release uses `1`. |
| `workflow` | Product workflow that produced the event. |
| `result` | Stable result category such as `success`, `failure`, `allowed`, `denied`, or `disabled`. |
| `platform` | Coarse app platform. |
| `app_version` | App version string. |

Optional parameters must be allowlisted per event and limited to stable categories, coarse counts, or coarse durations.

## First-Release Events

| Event | Owner Question | Trigger Point | Allowed Parameters |
| --- | --- | --- | --- |
| `analytics_preference_changed` | How many users keep optional analytics enabled? | Analytics Preference update succeeds. | `enabled`, `source` |
| `onboarding_completed` | How many users complete first setup? | Onboarding use case succeeds. | `preparation_step_count`, `spare_time_minutes` |
| `sign_up_completed` | How many users create accounts successfully? | Sign-up succeeds. | `auth_provider` |
| `login_completed` | How many users return successfully? | Sign-in succeeds. | `auth_provider` |
| `schedule_create_started` | Where does schedule creation begin? | Schedule create form initializes. | `source` |
| `schedule_created` | How often do users create schedules? | Schedule creation succeeds. | `preparation_mode`, `preparation_step_count`, `minutes_until_schedule` |
| `schedule_updated` | How often do users revise schedules? | Schedule update succeeds. | `preparation_changed`, `minutes_until_schedule` |
| `schedule_deleted` | How often are schedules removed? | Schedule deletion succeeds at a BLoC or use-case workflow boundary. | `minutes_until_schedule` |
| `notification_permission_result` | How often do users grant notification access? | Notification permission flow resolves. | `permission_result`, `source` |
| `alarm_opened` | How often do alarms bring users into the preparation flow? | Alarm launch payload opens a schedule route. | `launch_action`, `provider` |
| `alarm_failed` | Which alarm failures need attention? | Alarm status/reporting detects a stable failure category. | `error_code`, `provider` |
| `schedule_finished` | How often do users finish preparation on time? | Schedule finish succeeds. | `lateness_bucket`, `preparation_step_count`, `started_early` |

## Forbidden Fields

Never include:

- Email, display name, OAuth identifier, FCM token, access token, or refresh token.
- Schedule name, schedule note, place name, or preparation step name.
- User-authored free text.
- Raw exception message, stack trace, request body, response body, or arbitrary map.
- Exact location data or any permission-sensitive data not already approved for analytics.

## Change Control

- Event names use stable snake_case.
- Breaking meaning changes require a new event name or `schema_version` increment.
- New events require an owner question and explicit allowed parameters before implementation.
- First-release failure tracking is limited to `alarm_failed`; other failure events require stable error categories before implementation.
- Marketing and personalization events are out of scope until deferred purposes are approved.
105 changes: 105 additions & 0 deletions docs/Analytics-Preference-API.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# Analytics Preference API

This document defines the frontend contract needed before implementing OnTime analytics preference sync. It covers only the account-scoped preference for signed-in users; pre-login installation-scoped preference remains local to the app.

## Scope

- The preference controls optional Product Usage Events for active Analytics Purposes.
- The first release uses opt-out analytics and exposes the setting as Help Improve OnTime.
- Disabled preference stops future optional Product Usage Events.
- Marketing and personalization remain deferred and are not enabled by this API.

## Endpoints

### Get Analytics Preference

```http
GET /users/me/analytics-preference
Authorization: Bearer <access token>
```

Successful response:

```json
{
"data": {
"enabled": true,
"updatedAt": "2026-05-26T12:00:00Z"
}
}
```

### Update Analytics Preference

```http
PUT /users/me/analytics-preference
Authorization: Bearer <access token>
Content-Type: application/json

{
"enabled": false
}
```

Successful response:

```json
{
"data": {
"enabled": false,
"updatedAt": "2026-05-26T12:00:05Z"
}
}
```

## Field Semantics

| Field | Type | Required | Meaning |
| --- | --- | --- | --- |
| `enabled` | boolean | Yes | Whether optional Product Usage Events may be collected for the signed-in account. |
| `updatedAt` | ISO-8601 UTC string | Yes | Server time when the account-scoped preference was last changed. |

## Default Value

- The backend default for existing and newly created signed-in accounts is config-gated.
- The initial config default is `enabled: false` until privacy policy, hosted policy page, Google Play Data Safety, and release approval are complete.
- After approval, the backend may flip the config default to `enabled: true` without changing the API contract.
- An explicit user-saved `enabled` value always wins over the config default.
- The frontend must still treat unknown or load-failed preference state as disabled for optional Product Usage Events.

## Frontend Behavior

1. Before sign-in, the app stores the Analytics Preference locally for the installation.
2. After sign-in, the app loads `GET /users/me/analytics-preference`.
3. After the user changes Help Improve OnTime, the app calls `PUT /users/me/analytics-preference`.
4. If `enabled` is `false`, the app disables Firebase Analytics collection and does not emit future optional Product Usage Events.
5. On sign-out, the app clears the Firebase Analytics user association and returns to the local installation-scoped preference.
6. On account deletion, the app stops future user-linked Product Usage Events and clears the Firebase Analytics user association.

## Failure Behavior

- If loading the signed-in account preference fails, provider collection remains disabled until the preference is loaded successfully.
- If updating the signed-in account preference fails, the app keeps the previous confirmed value and does not emit `analytics_preference_changed`.
- If local installation preference and signed-in account preference conflict, the app uses the stricter value until the user explicitly changes the account preference.
- Unknown preference state is treated as disabled for optional Product Usage Events.

## Backend Handoff Scope

The backend task should be limited to account-scoped Analytics Preference sync:

- Backend issue: DevKor-github/OnTime-back#318.
- Add `GET /users/me/analytics-preference`.
- Add `PUT /users/me/analytics-preference`.
- Persist `enabled` and `updatedAt` for the signed-in account.
- Define the default account value for existing and newly created users.
- Confirm account deletion behavior for historical analytics as aggregate or de-identified retention.
- Confirm privacy policy and Google Play Data Safety updates before release.

The backend task does not need to define Firebase event names, Flutter BLoC instrumentation, local pre-login preference storage, or UI copy.

## Privacy And Release Requirements

- Do not include email, name, OAuth identifiers, FCM token, schedule names, schedule notes, place names, preparation step names, request bodies, response bodies, raw exception strings, or free text in analytics events or preference API payloads.
- Update the privacy policy and Google Play Data Safety worksheet before releasing Firebase Analytics.
- Historical analytics after account deletion may be retained only in aggregate or de-identified form.
- Production analytics is enabled by default only for production builds; debug, local development, tests, and Widgetbook collection require an explicit override.
Loading
Loading