# AppSok 프로젝트 규칙

## 응답 언어

- 사용자가 다르게 요청하지 않는 한 한국어로 답변한다.
- 코드 식별자, 명령어, 파일 경로, Jenkins/ADB 용어는 원문 영문을 유지한다.

## 프로젝트 개요

- AppSok은 Jenkins Android artifact를 Mac에서 조회/다운로드하고 USB로 연결된 Android 기기에 ADB로 설치하는 Flutter macOS 앱이다.
- 현재 상태는 초기 scaffold이며, 실제 Jenkins 인증/다운로드/설치 연결 전 UI, 모델, 서비스 골격이 분리되어 있다.
- 보안 기본 방향은 사용자별 Jenkins API token을 macOS Keychain에 저장하고, 앱 번들에는 공용 secret을 넣지 않는 것이다.

## 기술 스택

- Flutter stable / Dart 3.11 계열
- macOS desktop target
- `http`: Jenkins Remote API 호출
- `flutter_secure_storage`: macOS Keychain 기반 credential 저장
- `webview_flutter`: Jenkins Web Login 후보
- `app_links`: `appsok://` deep link 후보. URL scheme과 package/bundle id의 소문자 `appsok`은 식별자용으로 유지하고, 사용자 표시명은 `AppSok`으로 통일한다.
- Dart `Process`: `adb devices`, `adb install`, `adb logcat` 실행

## 주요 구조

- `lib/main.dart`, `lib/src/app.dart`: 앱 진입점과 MaterialApp 구성
- `lib/src/features/**`: 화면 단위 feature
- `lib/src/models/**`: Jenkins build, ADB device 등 순수 모델
- `lib/src/services/**`: Jenkins, token storage, ADB 외부 연동
- `lib/src/theme/**`: 앱 전역 theme
- `macos/Runner/**`: macOS 표시 이름, entitlements, URL scheme 등 플랫폼 설정
- `test/**`: Flutter widget/unit 테스트

## 프로젝트 컨벤션

- UI는 feature별 폴더 아래에 두고, Jenkins/ADB 외부 호출은 `services`로 분리한다.
- Jenkins token, LDAP credential, private endpoint 원문은 tracked 파일에 기록하지 않는다.
- 앱 번들에 Jenkins 공용 API token이나 service account credential을 넣지 않는다.
- Jenkins API 호출은 사용자별 credential과 Jenkins 권한 모델을 기본 전제로 한다.
- ADB 명령은 `AdbService`를 통해 실행하고, 화면 코드에서 `Process`를 직접 호출하지 않는다.
- macOS entitlement, URL scheme, sandbox 변경은 `macos-platform` domain rule을 먼저 확인한다.
- split APK/APKS/AAB 지원은 아직 구현 범위가 아니므로 단일 APK 흐름과 분리해 설계한다.

## 검증 기준

- Dart/Flutter 코드 변경 후 기본 검증은 `flutter analyze`와 `flutter test`로 한다.
- macOS platform 파일 변경은 macOS host에서 `flutter run -d macos` 또는 `flutter build macos` 확인이 필요하다.
- local 테스트 환경의 기본 evidence는 standard remote Mac runner `toki@toki-labs.com` 기준으로 판단한다. 기본 checkout은 `$HOME/docker/services/code-server/data/volume/workspace/appsok`이다.
- Flutter web preview가 필요한 경우 workspace project-owned slot `13050`을 사용한다. 일반 Flutter unit/analyze/macOS build 검증은 public port를 사용하지 않는다.
- 현재 Linux/container checkout에서의 `git diff --check`, `flutter analyze`, `flutter test`는 편집 직후 preflight로 사용할 수 있지만, Flutter/macOS/ADB/runtime evidence가 필요한 완료 검증은 remote runner에서 수행한다.
- 2026-06-08 조회 기준 remote runner에는 Flutter, Xcode 26.0.1, Android SDK/ADB, macOS desktop device, Android emulator, valid codesigning identity가 있다. Notary credential profile은 확인되지 않았으므로 notarization 가능으로 단정하지 않는다.
- SSH password, Jenkins credential, signing key, notary credential 원문은 tracked 파일, task log, 최종 응답에 기록하지 않는다.

## 도메인 매핑

| 경로 패턴 | 도메인 | rules.md |
|----------|--------|----------|
| `lib/main.dart`, `lib/src/app.dart`, `lib/src/features/app_shell.dart`, `lib/src/models/pending_install.dart`, `lib/src/theme/**` | app-shell | `agent-ops/rules/project/domain/app-shell/rules.md` |
| `lib/src/features/builds/**`, `lib/src/features/settings/**`, `lib/src/models/jenkins_build.dart`, `lib/src/services/jenkins_client.dart`, `lib/src/services/jenkins_artifact_session.dart`, `lib/src/services/artifact_staging_service.dart`, `lib/src/services/token_store.dart` | artifact-flow | `agent-ops/rules/project/domain/artifact-flow/rules.md` |
| `lib/src/features/devices/**`, `lib/src/features/console/**`, `lib/src/models/adb_device.dart`, `lib/src/models/install_attempt_result.dart`, `lib/src/services/adb_service.dart` | device-console | `agent-ops/rules/project/domain/device-console/rules.md` |
| `macos/**` | macos-platform | `agent-ops/rules/project/domain/macos-platform/rules.md` |
| `scripts/build-certified-macos.sh`, `scripts/setup-appsok-ci-secrets.sh`, `scripts/upsert-jenkins-certified-job.sh`, `.sops.yaml`, `secrets/*.sops.json` | macos-platform | `agent-ops/rules/project/domain/macos-platform/rules.md` |

## 스킬 라우팅

현재 프로젝트 전용 skill은 없다. 반복되는 Jenkins/ADB 구현 절차가 안정화되면 `agent-ops/skills/project/` 아래에 추가한다.
