# System Architecture

## Runtime Components

- Telegram Bot: Aiogram polling process for all user interactions.
- Scheduler: APScheduler running inside the bot process.
- Storage Repository: Google Sheets API adapter.
- Health API: FastAPI process for VPS health/readiness checks.
- Google Sheets: Primary persistent storage.

## Deployment Architecture

```text
Ubuntu VPS
  docker compose
    activity-reminder-api
      -> FastAPI /health /ready
    activity-reminder-bot
      -> Aiogram polling
      -> APScheduler
      -> Google Sheets API
      -> Telegram Bot API
```

## API Design

### `GET /health`

Returns process liveness.

```json
{
  "status": "ok",
  "service": "activity-reminder-bot",
  "version": "0.1.0"
}
```

### `GET /ready`

Returns configuration readiness without revealing secret values.

```json
{
  "status": "needs_configuration",
  "telegram_configured": false,
  "google_sheets_configured": false,
  "timezone": "Asia/Jakarta",
  "worksheet": "Reminders"
}
```

## Google Sheets Integration

- Credentials are loaded from `GOOGLE_SERVICE_ACCOUNT_JSON_BASE64`.
- The spreadsheet is selected by `GOOGLE_SHEETS_SPREADSHEET_ID`.
- The worksheet defaults to `Sheet1`, so data appears on the first tab of a newly created spreadsheet.
- The repository ensures the header layout before append.
- Updates are row-based using the internal row number found during reads.

## Error Handling

- Invalid natural language input returns a safe user-facing message.
- Missing Google Sheets configuration blocks save operations.
- Scheduler skips scans when Google Sheets is not configured.
- Google API row parsing errors are logged and skipped instead of crashing the bot.
- Runtime readiness distinguishes liveness from missing configuration.

## Alarm Repeat Behavior

- Telegram cannot create a new phone notification without a new Telegram message.
- The bot repeats unfinished alarms by sending a new alarm message on an interval.
- When `ALARM_DELETE_PREVIOUS_MESSAGE=true`, the previous alarm message is deleted after the new one is sent, so the chat stays clean while the phone still receives repeated notifications.
- Repeats stop when the user taps done, snooze, reschedule, or delete, or when `ALARM_REPEAT_MAX_COUNT` is reached.

## Security Design

- No tokens or service account JSON are stored in source code.
- `.env.example` contains only placeholders.
- Service account JSON must be base64 encoded and kept in `.env`.
- API readiness never returns secret values.
- User data is filtered by Telegram user ID before search/list views.
- Delete uses confirmation before status is changed to `Dihapus`.

## Scalability Notes

- Google Sheets works well for low-to-medium personal reminder volume.
- APScheduler interval scanning is simple and reliable for a personal bot.
- For large multi-user usage, add PostgreSQL as a write-through cache and keep Sheets as export/audit storage.
