|
| 1 | +# Copilot Instructions for httpSMS |
| 2 | + |
| 3 | +httpSMS is a service that turns an Android phone into an SMS gateway via an HTTP API. This is a monorepo with three components: |
| 4 | + |
| 5 | +- **`api/`** — Go backend (Fiber, GORM, PostgreSQL) |
| 6 | +- **`web/`** — Nuxt 2 frontend (Vue 2, Vuetify 2, TypeScript) |
| 7 | +- **`android/`** — Native Android app (Kotlin) |
| 8 | + |
| 9 | +## Build, Test, and Lint Commands |
| 10 | + |
| 11 | +### API (Go) |
| 12 | + |
| 13 | +```bash |
| 14 | +cd api |
| 15 | + |
| 16 | +# Development with hot-reload |
| 17 | +air |
| 18 | + |
| 19 | +# Build |
| 20 | +go build -o ./tmp/main.exe . |
| 21 | + |
| 22 | +# Run tests |
| 23 | +go test ./... |
| 24 | + |
| 25 | +# Run a single test |
| 26 | +go test ./pkg/services/ -run TestMessageService |
| 27 | + |
| 28 | +# Generate Swagger docs (required after changing API annotations) |
| 29 | +swag init --requiredByDefault --parseDependency --parseInternal |
| 30 | + |
| 31 | +# Pre-commit hooks run: go-fumpt, go-imports, go-lint, go-mod-tidy |
| 32 | +``` |
| 33 | + |
| 34 | +### Web (Nuxt/Vue) |
| 35 | + |
| 36 | +```bash |
| 37 | +cd web |
| 38 | + |
| 39 | +# Install dependencies |
| 40 | +pnpm install |
| 41 | + |
| 42 | +# Development server (port 3000) |
| 43 | +pnpm dev |
| 44 | + |
| 45 | +# Lint (eslint + stylelint + prettier) |
| 46 | +pnpm lint |
| 47 | + |
| 48 | +# Auto-fix lint issues |
| 49 | +pnpm lintfix |
| 50 | + |
| 51 | +# Run tests (Jest) |
| 52 | +pnpm test |
| 53 | + |
| 54 | +# Static site generation (production build) |
| 55 | +pnpm run generate |
| 56 | + |
| 57 | +# Regenerate TypeScript API models from Swagger |
| 58 | +pnpm api:models |
| 59 | +``` |
| 60 | + |
| 61 | +### Android (Kotlin) |
| 62 | + |
| 63 | +```bash |
| 64 | +cd android |
| 65 | + |
| 66 | +# Build |
| 67 | +./gradlew build |
| 68 | + |
| 69 | +# Debug APK |
| 70 | +./gradlew assembleDebug |
| 71 | + |
| 72 | +# Release APK |
| 73 | +./gradlew assembleRelease |
| 74 | +``` |
| 75 | + |
| 76 | +### Docker (full stack) |
| 77 | + |
| 78 | +```bash |
| 79 | +# Start all services (PostgreSQL, Redis, API, Web) |
| 80 | +docker compose up --build |
| 81 | +# API at localhost:8000, Web at localhost:3000 |
| 82 | +``` |
| 83 | + |
| 84 | +## Architecture |
| 85 | + |
| 86 | +### API — Layered Architecture with Event-Driven Processing |
| 87 | + |
| 88 | +The API uses a **DI container** (`pkg/di/container.go`) that lazily initializes all services as singletons. The layered architecture flows as: |
| 89 | + |
| 90 | +**Handlers → Services → Repositories → GORM/PostgreSQL** |
| 91 | + |
| 92 | +- **Handlers** (`pkg/handlers/`) — Fiber HTTP handlers. Each has a `RegisterRoutes()` method and embeds a base `handler` struct with standardized response methods (`responseBadRequest`, `responseNotFound`, etc.). |
| 93 | +- **Services** (`pkg/services/`) — Business logic. Orchestrate repositories and dispatch events. |
| 94 | +- **Repositories** (`pkg/repositories/`) — Data access via GORM. Interfaces defined alongside GORM implementations (prefixed `gorm*`). |
| 95 | +- **Validators** (`pkg/validators/`) — One validator per handler, return `url.Values` for field errors. |
| 96 | +- **Entities** (`pkg/entities/`) — Domain models, auto-migrated by GORM. |
| 97 | + |
| 98 | +**Event system**: Uses CloudEvents spec (`cloudevents/sdk-go`). Events defined in `pkg/events/` (31 event types). Listeners in `pkg/listeners/` process events either synchronously or via Google Cloud Tasks queue (emulator mode for local dev). |
| 99 | + |
| 100 | +**Entry point**: `main.go` loads `.env` in local mode, creates the DI container, and starts Fiber on `APP_PORT`. |
| 101 | + |
| 102 | +### Web — Nuxt 2 Static SPA |
| 103 | + |
| 104 | +- **State management**: Single Vuex store (`store/index.ts`) — actions make API calls via Axios, mutations update state, getters expose computed values. |
| 105 | +- **Components**: Use `vue-property-decorator` class syntax with `@Component`, `@Prop`, `@Watch` decorators. |
| 106 | +- **API client**: Axios configured in `plugins/axios.ts` with Firebase bearer token auth and `x-api-key` header support. |
| 107 | +- **API models**: TypeScript types in `models/` are auto-generated from the Swagger spec via `swagger-typescript-api`. |
| 108 | +- **Auth**: Firebase Authentication (Email/Password, Google, GitHub) with `auth` and `guest` middleware for route guards. |
| 109 | +- **Real-time**: Pusher.js for live message updates. |
| 110 | + |
| 111 | +### Android — Task-Oriented, Event-Driven |
| 112 | + |
| 113 | +- **No MVVM/Clean Architecture** — uses a flat package structure with Activities, Services, BroadcastReceivers, and WorkManager tasks. |
| 114 | +- **FCM integration**: `MyFirebaseMessagingService` receives push notifications → schedules `SendSmsWorker` via WorkManager → fetches message from API → sends SMS. |
| 115 | +- **Dual SIM support**: Independent settings per SIM via `Settings` singleton (SharedPreferences). |
| 116 | +- **HTTP client**: OkHttp with `x-api-key` authentication against the API. |
| 117 | +- **Encryption**: AES-256/CFB with SHA-256 key derivation (`Encrypter.kt`). |
| 118 | + |
| 119 | +## Key Conventions |
| 120 | + |
| 121 | +### API (Go) |
| 122 | + |
| 123 | +- **Error handling**: Use `github.com/palantir/stacktrace` — wrap errors with `stacktrace.Propagate(err, "context")` or `stacktrace.PropagateWithCode()`. Never return bare errors. |
| 124 | +- **Database queries**: Always use GORM query builder with context propagation (`repository.db.WithContext(ctx)`). No raw SQL. |
| 125 | +- **Route registration**: Each handler defines `RegisterRoutes()` called from the DI container. Routes follow REST conventions under `/v1/`. |
| 126 | +- **Middleware chain**: HTTP Logger → OpenTelemetry → CORS → Request Logger → Bearer Auth → API Key Auth. |
| 127 | +- **Observability**: All layers are instrumented with OpenTelemetry (Fiber, GORM, Redis). Pass `logger` and `tracer` to constructors. |
| 128 | +- **Code formatting**: `go-fumpt` (not `gofmt`), enforced via pre-commit hooks. |
| 129 | + |
| 130 | +### Web (Vue/TypeScript) |
| 131 | + |
| 132 | +- **Formatting**: No semicolons, single quotes, 2-space indentation (Prettier + ESLint). |
| 133 | +- **Component style**: Class-based with `vue-property-decorator`, not Options API (though some pages use `Vue.extend()`). |
| 134 | +- **Store pattern**: Actions handle async API calls and commit mutations. Access store from components via `this.$store`. |
| 135 | + |
| 136 | +### Android (Kotlin) |
| 137 | + |
| 138 | +- **API calls**: Use `HttpSmsApiService` singleton (static `create()` factory). OkHttp client with `x-api-key` header. |
| 139 | +- **Background work**: Use WorkManager for tasks that must survive process death. Direct `Thread { }` for lightweight background ops. |
| 140 | +- **State**: `Settings` object (SharedPreferences singleton) for all persistent state. |
| 141 | +- **Phone number formatting**: Use `libphonenumber` for E.164 format validation. |
0 commit comments