From 28b0cd5c9cef43cb67b3aa0c91ca2613612c0af8 Mon Sep 17 00:00:00 2001 From: "(Itz_Me)" Date: Tue, 9 Jun 2026 05:07:15 +0000 Subject: [PATCH] Add APK build workflow and upgrade README - .github/workflows/build-apk.yml: CI on push/PR to main, v* tags, and manual dispatch. Java 17 + Flutter 3.22.2, codegen, analyze + test gates, builds per-ABI and universal release APKs (Supabase creds via --dart-define secrets), uploads artifact, and publishes to a GitHub Release on tags. - README.md: full rewrite with badges, table of contents, feature tour, APK download instructions, architecture map, build/CI docs, and security model. Co-Authored-By: Claude Opus 4.8 --- .github/workflows/build-apk.yml | 87 ++++++++++++ README.md | 240 +++++++++++++++++++++++--------- 2 files changed, 260 insertions(+), 67 deletions(-) create mode 100644 .github/workflows/build-apk.yml diff --git a/.github/workflows/build-apk.yml b/.github/workflows/build-apk.yml new file mode 100644 index 0000000..f01b428 --- /dev/null +++ b/.github/workflows/build-apk.yml @@ -0,0 +1,87 @@ +name: Build APK + +# Builds the Aether Android APK on every push/PR to main and on demand. +# Pushing a tag like `v1.0.0` (or a manual run with "release") also publishes +# the APKs to a GitHub Release. +# +# Supabase credentials are injected at build time via --dart-define and must be +# configured as repository secrets (Settings -> Secrets and variables -> Actions): +# SUPABASE_URL, SUPABASE_ANON_KEY + +on: + push: + branches: [main] + tags: ['v*'] + pull_request: + branches: [main] + workflow_dispatch: + inputs: + release: + description: 'Attach APKs to a GitHub Release' + type: boolean + default: false + +env: + FLUTTER_VERSION: '3.22.2' + +jobs: + build: + name: Build release APK + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Java + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: '17' + + - name: Set up Flutter + uses: subosito/flutter-action@v2 + with: + flutter-version: ${{ env.FLUTTER_VERSION }} + channel: stable + cache: true + + - name: Install dependencies + run: flutter pub get + + - name: Generate code (freezed / riverpod / isar / json) + run: dart run build_runner build --delete-conflicting-outputs + + - name: Analyze + run: dart analyze + + - name: Test + run: flutter test + + - name: Build split-per-ABI release APKs + run: | + flutter build apk --release --split-per-abi \ + --dart-define=SUPABASE_URL="${{ secrets.SUPABASE_URL }}" \ + --dart-define=SUPABASE_ANON_KEY="${{ secrets.SUPABASE_ANON_KEY }}" + + - name: Build universal release APK + run: | + flutter build apk --release \ + --dart-define=SUPABASE_URL="${{ secrets.SUPABASE_URL }}" \ + --dart-define=SUPABASE_ANON_KEY="${{ secrets.SUPABASE_ANON_KEY }}" + + - name: Upload APK artifacts + uses: actions/upload-artifact@v4 + with: + name: aether-apk + path: build/app/outputs/flutter-apk/*.apk + if-no-files-found: error + retention-days: 30 + + - name: Publish to GitHub Release + if: startsWith(github.ref, 'refs/tags/v') || inputs.release + uses: softprops/action-gh-release@v2 + with: + files: build/app/outputs/flutter-apk/*.apk + generate_release_notes: true + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/README.md b/README.md index 703fe5f..6e203a8 100644 --- a/README.md +++ b/README.md @@ -1,34 +1,80 @@ -# Aether +
-> Modern social communication with customizable identity, music presence, and secure messaging. +# ✦ Aether -Aether is a username-based social messenger — **not** a WhatsApp clone. It combines -Signal-Protocol end-to-end encrypted messaging with expressive, customizable profiles, -Instagram-style stories, Discord-style notes, and Spotify-style music presence, all wrapped -in a glassmorphism UI on a pure AMOLED dark base. +### Modern social communication with customizable identity, music presence, and secure messaging. -Built with Flutter + Supabase. Created by **(Itz_Me) / KairoCloud**. +Aether is a **username-based social messenger** — *not* a WhatsApp clone. It fuses +Signal-Protocol end-to-end encrypted chat with expressive customizable profiles, +Instagram-style stories, Discord-style notes, and Spotify-style music presence — +all wrapped in a glassmorphism UI on a pure-AMOLED dark base. + +[![Build APK](https://github.com/KairoCloud/Aether/actions/workflows/build-apk.yml/badge.svg)](https://github.com/KairoCloud/Aether/actions/workflows/build-apk.yml) +![Flutter](https://img.shields.io/badge/Flutter-3.22-02569B?logo=flutter&logoColor=white) +![Dart](https://img.shields.io/badge/Dart-3.4-0175C2?logo=dart&logoColor=white) +![Supabase](https://img.shields.io/badge/Supabase-Postgres-3FCF8E?logo=supabase&logoColor=white) +![E2EE](https://img.shields.io/badge/E2EE-Signal%20Protocol-7C3AED) +![Platform](https://img.shields.io/badge/Platform-Android%20%7C%20iOS-0A0A0F) + +Crafted by **(Itz_Me) / KairoCloud** + +
--- -## Features - -- **End-to-end encrypted messaging** — Signal Protocol (`libsignal_protocol_dart`), X3DH session - setup, one-time prekey replenishment. Ciphertext only ever leaves the device; private keys - live in secure storage; decrypted plaintext is cached locally in Isar. -- **Realtime chat** — per-chat Supabase channel: live message inserts, typing indicators, read - receipts (✓ / ✓✓ / blue ✓✓), reactions, replies, pin, edit, delete, cursor pagination. -- **Voice messages** — hold-to-record with live waveform + slide-to-cancel; playback with - waveform seekbar and 1×/1.5×/2× speed. -- **Media** — image / video / file sharing with full-screen preview. -- **Profiles** — parallax banner, avatar with animated music ring, badges, bio, social links, - 8 accent presets + custom hex (propagates through the whole app). -- **Friends** — search (with mutual counts), requests, accept/block, privacy-aware visibility. -- **Stories** — image & text stories, full-screen viewer (animated progress bars, hold-to-pause, - swipe-to-dismiss, reactions, "seen by"), 24h auto-expiry. -- **Notes** — 60-char status notes with optional music, 24h expiry, home strip. -- **Music presence** — manual status with animated equalizer + album art. -- **Notifications** — FCM push + local notifications, presence, unread badges. +## Table of contents + +- [Highlights](#highlights) +- [Feature tour](#feature-tour) +- [Download the APK](#download-the-apk) +- [Tech stack](#tech-stack) +- [Architecture](#architecture) +- [Getting started](#getting-started) +- [Building locally](#building-locally) +- [CI / APK workflow](#ci--apk-workflow) +- [Quality gates & conventions](#quality-gates--conventions) +- [Security model](#security-model) +- [Roadmap & known limitations](#roadmap--known-limitations) +- [License](#license) + +--- + +## Highlights + +🔒 **End-to-end encrypted** — real Signal Protocol, not a hand-rolled cipher. +🎨 **Yours to theme** — 8 accent presets + custom hex that re-skins the entire app live. +🎵 **Music presence** — animated equalizer + album art, on your profile and your notes. +📖 **Stories & notes** — full-screen viewer and 60-char status notes, both auto-expiring at 24h. +🪟 **Glassmorphism** — consistent blurred-glass surfaces over a `#0A0A0F` AMOLED base. +⚡ **Realtime** — messages, typing, and read receipts arrive without a refresh. + +--- + +## Feature tour + +| Area | What you get | +|---|---| +| **Messaging** | Signal Protocol E2EE · realtime delivery · typing indicators · read receipts (✓ / ✓✓ / blue ✓✓) · reactions, replies, pin, edit, delete · 30-message cursor pagination | +| **Voice** | Hold-to-record with live waveform + slide-to-cancel · playback with waveform seekbar and 1× / 1.5× / 2× speed | +| **Media** | Image / video / file sharing with full-screen, zoomable previews | +| **Profiles** | Parallax banner · avatar with animated music ring · badges · bio · social links · accent color that propagates app-wide | +| **Friends** | Debounced search with mutual counts · requests · accept / decline / block · privacy-aware visibility | +| **Stories** | Image & text stories · animated progress bars · tap-to-navigate · hold-to-pause · swipe-to-dismiss · reactions · "seen by" · 24h expiry | +| **Notes** | 60-char status with optional music · home strip · expand sheet with equalizer | +| **Music status** | Manual song/artist/art entry · animated equalizer · blurred album-art backdrop | +| **Notifications** | FCM push + local notifications · presence · unread badges | + +--- + +## Download the APK + +CI builds release APKs on every push to `main`. + +- **Latest build:** open the [**Build APK** workflow](https://github.com/KairoCloud/Aether/actions/workflows/build-apk.yml) → pick the most recent run → download the `aether-apk` artifact. +- **Tagged releases:** push a `v*` tag (e.g. `v1.0.0`) and the APKs are attached to a [GitHub Release](https://github.com/KairoCloud/Aether/releases) automatically. + +> The workflow produces per-ABI APKs (`arm64-v8a`, `armeabi-v7a`, `x86_64`) plus a universal APK. +> For most modern phones, install the **arm64-v8a** one. --- @@ -36,35 +82,44 @@ Built with Flutter + Supabase. Created by **(Itz_Me) / KairoCloud**. | Layer | Choice | |---|---| -| Framework | Flutter (stable) | +| Framework | Flutter (stable, 3.22+) | | State | `flutter_riverpod` + `riverpod_annotation` (codegen) | -| Routing | `go_router` | +| Routing | `go_router` with auth + profile guards | | Models | `freezed` + `json_serializable` | -| Local DB | `isar` (Signal stores + plaintext cache) | -| Backend | Supabase (Postgres + Auth + Realtime + Storage + Edge Functions) | +| Local DB | `isar` — Signal stores + decrypted-text cache | +| Backend | Supabase — Postgres · Auth · Realtime · Storage · Edge Functions | | Encryption | `libsignal_protocol_dart` | | Push | `firebase_messaging` + `flutter_local_notifications` | -| Audio | `just_audio` (playback), `record` (capture) | +| Audio | `just_audio` (playback) · `record` (capture) | +| Fonts | `Sora` (headings) + `DM Sans` (body) via `google_fonts` | --- ## Architecture -Feature-first Clean Architecture. Each feature has `data/` (repositories, datasources), -`domain/` (entities, repository interfaces), and `presentation/` (screens, widgets, providers). -Shared building blocks live under `lib/core/` (theme, constants, widgets, services, utils, db). +Feature-first **Clean Architecture**. Every feature owns its `data/` (repositories, +datasources), `domain/` (entities, repository interfaces), and `presentation/` +(screens, widgets, Riverpod providers). Shared building blocks live in `lib/core/`. ``` lib/ -├── core/ # theme, constants, widgets, services (supabase, encryption, media, -│ # notifications), db (isar), utils, animations -├── models/ # Freezed data models (AppUser, Message, Story, Note, ...) -├── providers/ # global Riverpod providers (auth, user, theme, preferences) -├── features/ # auth, home, chats, friends, profile, social, notifications, settings -└── routes/ # go_router config + guards +├── core/ +│ ├── animations/ transitions + reusable effect configs +│ ├── constants/ colors, sizes, strings, route names +│ ├── db/ Isar collections + service +│ ├── services/ supabase, encryption, media, notifications, storage +│ ├── theme/ AMOLED theme + AetherColors ThemeExtension (accent) +│ ├── utils/ validators, color/hex, debounce, formatters +│ └── widgets/ 14 reusable glassmorphism components +├── models/ Freezed models (AppUser, Message, Story, Note, ...) +├── providers/ global providers (auth, user, theme, preferences) +├── features/ auth · home · chats · friends · profile · social +│ · notifications · settings · media +└── routes/ go_router config + guards + supabase/ -├── migrations/ # schema, RLS, RPCs, storage policies -└── functions/ # send-notification, clean-expired (Deno edge functions) +├── migrations/ schema · indexes · RLS · RPCs · storage policies (0001–0008) +└── functions/ send-notification · clean-expired (Deno edge functions) ``` --- @@ -72,55 +127,106 @@ supabase/ ## Getting started ### Prerequisites -- Flutter SDK (3.22+) -- A Supabase project -- (Optional) A Firebase project for push notifications +- Flutter SDK **3.22+** +- A **Supabase** project +- *(Optional)* A **Firebase** project for push notifications -### 1. Install dependencies +### 1 · Backend +Run the SQL migrations in `supabase/migrations/` **in order** (`0001` → `0008`) against your +Supabase project, then deploy the edge functions in `supabase/functions/` and set their secrets +(`SUPABASE_URL`, `SUPABASE_SERVICE_ROLE_KEY`, and `FIREBASE_SERVICE_ACCOUNT` for push). + +### 2 · Dependencies & codegen ```bash flutter pub get dart run build_runner build --delete-conflicting-outputs ``` -### 2. Apply the database schema -Run the SQL migrations in `supabase/migrations/` in order (`0001` → `0008`) against your -Supabase project, then deploy the edge functions in `supabase/functions/`. - -### 3. Configure secrets (never hardcoded) -Provide Supabase credentials at build/run time via `--dart-define`: +### 3 · Run (secrets are never hardcoded) ```bash flutter run \ --dart-define=SUPABASE_URL=https://YOUR_PROJECT.supabase.co \ --dart-define=SUPABASE_ANON_KEY=YOUR_ANON_KEY ``` -### 4. (Optional) Push notifications -Add your platform Firebase config (`google-services.json` / `GoogleService-Info.plist` and -`firebase_options.dart`). Without it, notifications are silently disabled — the app still runs. +### 4 · Push notifications *(optional)* +Add your platform Firebase config (`google-services.json` / `GoogleService-Info.plist` and a +generated `firebase_options.dart`). Without it, notifications are silently disabled and the app +still runs. --- -## Quality gates +## Building locally ```bash -dart analyze # 0 issues -flutter test # unit tests for models, mappers, utils +# Universal release APK +flutter build apk --release \ + --dart-define=SUPABASE_URL=... --dart-define=SUPABASE_ANON_KEY=... + +# Smaller, per-architecture APKs +flutter build apk --release --split-per-abi \ + --dart-define=SUPABASE_URL=... --dart-define=SUPABASE_ANON_KEY=... +``` +Output lands in `build/app/outputs/flutter-apk/`. + +--- + +## CI / APK workflow + +`.github/workflows/build-apk.yml` runs on every push/PR to `main`, on `v*` tags, and on manual +dispatch. Each run: + +1. sets up Java 17 + Flutter 3.22.2, +2. installs deps and runs **codegen**, +3. gates on `dart analyze` + `flutter test`, +4. builds per-ABI **and** universal release APKs, +5. uploads them as the `aether-apk` artifact, and +6. on a `v*` tag (or a manual run with *release* checked) attaches them to a GitHub Release. + +**Required repository secrets** (Settings → Secrets and variables → Actions): + +| Secret | Purpose | +|---|---| +| `SUPABASE_URL` | Your Supabase project URL | +| `SUPABASE_ANON_KEY` | Supabase anon/publishable key | + +> Builds are **unsigned** (debug-signed) by default. To ship a Play Store build, add a release +> keystore + signing config and wire it into `android/app/build.gradle`. + +--- + +## Quality gates & conventions + +```bash +dart analyze # 0 issues +flutter test # unit tests: models, RPC mappers, validators, hashing ``` -Project conventions (enforced): sound null-safety, Freezed on every model, `@riverpod` providers, -constants in `lib/core/constants/`, `ListView.builder` for dynamic lists, 300-line file cap, -no plaintext logging, no custom crypto. +Enforced throughout: sound null-safety · `@freezed` on every model · `@riverpod` providers · +constants in `lib/core/constants/` · `ListView.builder` for dynamic lists · **300-line file cap** · +`const` everywhere allowed · **no plaintext logging** · **no custom crypto**. + +--- + +## Security model + +- **Text messages are end-to-end encrypted.** Supabase only ever stores ciphertext; the identity + private key never leaves `flutter_secure_storage`; decrypted text is cached on-device in Isar + (the Signal ratchet only allows decrypting a message once). +- **Row Level Security** is enabled on **every** table. Cross-table checks (chat membership, + friendship, blocks) go through `SECURITY DEFINER` helper functions to prevent policy recursion. +- **One-time prekeys** are claimed atomically server-side and replenished when low. +- **No secrets in source** — all credentials are injected via `--dart-define` / CI secrets. --- -## Security notes +## Roadmap & known limitations -- **Text messages are end-to-end encrypted.** Supabase stores ciphertext only. -- **Row Level Security** is enabled on every table; cross-table checks use `SECURITY DEFINER` - helper functions to prevent policy recursion. -- **Known limitations** (tracked for future work): media blobs are transport-encrypted (HTTPS + - RLS) but not E2E-encrypted; group messaging is not yet E2E (1:1 only); presence has no - background teardown/heartbeat. +- 📎 **Media is not E2E-encrypted** — blobs are transport-encrypted (HTTPS + RLS), text is E2EE. +- 👥 **1:1 E2EE only** — group sender-key encryption is not yet implemented. +- 🟢 **Presence has no background teardown** — online status is set on app open; a heartbeat / + lifecycle teardown is pending. +- 🔔 **Push requires Firebase config** — disabled gracefully until added. ---