update domain rules and workflow integration roadmap

This commit is contained in:
toki 2026-06-14 20:41:16 +09:00
parent c1c4c41886
commit b4400065a2
10 changed files with 97 additions and 49 deletions

View file

@ -1,32 +1,35 @@
---
domain: app-shell
last_rule_review_commit: no-commit
last_rule_updated_at: 2026-06-08
last_rule_review_commit: c1c4c41886f44727ad5b9297ec164198d1dd5bd9
last_rule_updated_at: 2026-06-14
---
# app-shell
## 목적 / 책임
AppSok의 전역 앱 구성, 기본 navigation shell, theme, 화면 간 진입 구조를 담당한다.
AppSok의 전역 앱 구성, startup session restore wiring, navigation shell, theme, feature 간 진입/상태 전달을 담당한다.
## 포함 경로
- `lib/main.dart` — Flutter 앱 실행 진입점
- `lib/src/app.dart``MaterialApp`과 전역 theme 연결
- `lib/src/features/app_shell.dart` — 빌드/디바이스/콘솔/설정 navigation shell
- `lib/src/models/pending_install.dart` — artifact-flow와 device-console 사이의 설치 대기 handoff 모델
- `lib/src/theme/` — 앱 전역 색상, typography, component theme
## 제외 경로
- `lib/src/features/builds/` — Jenkins artifact 조회/설치 흐름은 `artifact-flow` 책임
- `lib/src/features/devices/`, `lib/src/features/console/` — ADB device/logcat 흐름은 `device-console` 책임
- `lib/src/services/**` — 외부 연동과 runtime semantics는 각 service 소유 도메인 책임
- `macos/` — bundle, entitlement, URL scheme은 `macos-platform` 책임
## 주요 구성 요소
- `AppSokApp` — 앱 루트 widget
- `AppSokShell` — 좌측 navigation과 상단 상태 영역
- `AppSokShell` — 좌측 navigation, 상단 상태 영역, feature 간 설치 대기 상태 전달
- `PendingInstall` — staged APK를 device-console에 넘기는 cross-feature DTO
- `AppTheme` — AppSok Material 3 light theme
## 유지할 패턴
@ -34,13 +37,15 @@ AppSok의 전역 앱 구성, 기본 navigation shell, theme, 화면 간 진입
- 첫 화면은 실제 업무 화면이어야 하며 landing/marketing 화면으로 만들지 않는다.
- 사용자 표시명은 `AppSok`으로 통일한다. Dart package, URL scheme, bundle id처럼 소문자 식별자가 필요한 곳만 `appsok`을 유지한다.
- navigation item 추가 시 domain 경계를 먼저 정하고, shell에는 route/entry wiring만 둔다.
- shell은 Jenkins session, artifact staging, ADB loader/installer 같은 dependency를 주입·연결하되 실제 외부 호출 semantics는 service 도메인에 둔다.
- 설치 대기 상태와 staged file cleanup은 페이지 dispose에 끊기지 않도록 shell에서 소유한다.
- 버튼과 상태 표시는 icon을 우선 사용하고, 긴 설명성 문구는 화면 안에 넣지 않는다.
- 카드 반경은 8px 이하를 유지한다.
## 다른 도메인과의 경계
- **artifact-flow**: Jenkins 인증/빌드 목록 상태는 artifact-flow가 소유하고, shell은 연결 상태 요약만 표시한다.
- **device-console**: ADB 연결 상태 원천은 device-console이 소유하고, shell은 요약만 표시한다.
- **artifact-flow**: Jenkins 인증/빌드 목록/다운로드/staged APK 생성은 artifact-flow가 소유하고, shell은 loader와 install handoff만 연결한다.
- **device-console**: ADB 연결 상태, 설치 실행, logcat session은 device-console이 소유하고, shell은 device 선택과 pending install 전달만 조율한다.
- **macos-platform**: 앱 이름, URL scheme, entitlement 변경은 platform 설정에서 처리한다.
## 금지 사항

View file

@ -1,14 +1,14 @@
---
domain: artifact-flow
last_rule_review_commit: no-commit
last_rule_updated_at: 2026-06-08
last_rule_review_commit: c1c4c41886f44727ad5b9297ec164198d1dd5bd9
last_rule_updated_at: 2026-06-14
---
# artifact-flow
## 목적 / 책임
Jenkins 인증, build 목록 조회, artifact 선택/다운로드, 설치 요청 직전까지의 흐름을 담당한다.
Jenkins 인증, Web Login token 발급 bridge, session restore, job/build/artifact 조회, 다운로드 stream, APK staging/검증/cleanup, 설치 handoff 직전까지의 흐름을 담당한다.
## 포함 경로
@ -16,32 +16,45 @@ Jenkins 인증, build 목록 조회, artifact 선택/다운로드, 설치 요청
- `lib/src/features/settings/` — Jenkins base URL, job, 인증 방식 설정 UI
- `lib/src/models/jenkins_build.dart` — Jenkins build/artifact 모델
- `lib/src/services/jenkins_client.dart` — Jenkins Remote API 호출
- `lib/src/services/jenkins_artifact_session.dart` — 저장된 Jenkins session 복원과 조회/다운로드/staging facade
- `lib/src/services/artifact_staging_service.dart` — 다운로드된 APK 임시 staging, 검증, cleanup
- `lib/src/services/token_store.dart` — 사용자별 Jenkins credential 저장
## 제외 경로
- `lib/src/services/adb_service.dart` — 실제 설치 실행은 `device-console` 책임
- `lib/src/features/devices/`, `lib/src/features/console/` — 연결 기기와 logcat UI는 `device-console` 책임
- `lib/src/models/pending_install.dart` — staged APK를 device-console으로 넘기는 handoff DTO는 `app-shell` 책임
- `macos/Runner/` — Keychain, network entitlement, URL scheme은 `macos-platform` 책임
## 주요 구성 요소
- `BuildsPage` — Jenkins build/artifact 탐색 화면
- `JenkinsBuild`, `BuildArtifact` — build와 artifact 도메인 모델
- `SettingsPage`, `JenkinsWebLoginPage` — Jenkins URL 입력, Web Login, token 저장/clear UI와 injected ADB 진단 표시 surface
- `JenkinsJob`, `JenkinsBuild`, `BuildArtifact` — job, build, artifact 도메인 모델
- `JenkinsClient` — build 조회와 artifact 다운로드 HTTP client
- `TokenStore` — macOS Keychain credential 저장소 wrapper
- `DownloadTask`, `DownloadProgressEvent` — artifact 다운로드 stream과 취소 가능한 progress 이벤트
- `JenkinsArtifactSession`, `JenkinsSessionRestoreResult` — credential 복원, 권한 확인, 조회/다운로드/staging orchestration
- `ArtifactStagingService`, `StagedApk`, `ArtifactVerifyException` — APK staging, 확장자/크기 검증, cleanup
- `TokenStore`, `JenkinsSessionConfig` — macOS Keychain credential/session 저장소 wrapper
- `JenkinsCrumb`, `JenkinsGeneratedToken`, `JenkinsBridgeTokenResult` — Jenkins Web Login token bridge parsing 모델
## 유지할 패턴
- Jenkins credential은 사용자별로 저장하고, tracked 파일이나 앱 bundle에 secret을 넣지 않는다.
- Jenkins API 응답 parsing은 모델 factory 또는 전용 parser에 둔다.
- Jenkins URL path 조합은 context path를 보존하는 helper를 사용하고, 문자열 덧붙이기로 login/API 경로를 만들지 않는다.
- WebView token bridge는 same-origin fetch로 `whoAmI`, crumb, token 발급 응답을 확인하고, token 이름에는 secret을 넣지 않는다.
- `DownloadProgressEvent`는 누적 byte와 chunk byte를 함께 전달하고, 취소 시 stream을 닫아 partial staging이 남지 않게 한다.
- staging된 파일은 `.apk` 확장자와 non-empty 조건을 검증하고, 취소/오류/설치 완료/대기 취소 시 cleanup 경로를 유지한다.
- session 저장은 저장 직후 restore 검증까지 성공했을 때만 완료로 보고, 실패하면 저장값을 rollback한다.
- 다운로드 파일명과 build number, job, flavor, branch를 UI에서 함께 노출해 오설치 가능성을 낮춘다.
- Jenkins WebView 자동 token 발급을 구현할 때도 LDAP 비밀번호 원문을 앱 상태나 로그에 남기지 않는다.
## 다른 도메인과의 경계
- **device-console**: artifact-flow는 설치할 파일과 대상 요청만 넘기고, `adb install` 실행과 logcat 처리는 device-console에서 담당한다.
- **app-shell**: 로그인/동기화 상태 summary만 shell에 전달하고, 상세 상태와 오류는 artifact-flow 화면에서 관리한다.
- **device-console**: artifact-flow는 staged APK와 build/artifact metadata까지만 만들고, `adb install`, logcat, ADB 진단 타입/loader semantics는 device-console에서 담당한다.
- **app-shell**: 로그인/동기화 상태, loader, staged APK handoff만 shell에 전달하고, 상세 상태와 오류는 artifact-flow 화면/서비스에서 관리한다.
- **macos-platform**: 인증 callback deep link, sandbox/network 권한은 macos-platform과 함께 변경한다.
## 금지 사항
@ -49,3 +62,4 @@ Jenkins 인증, build 목록 조회, artifact 선택/다운로드, 설치 요청
- 공용 Jenkins API token, service account token을 소스/설정/README에 기록하지 않는다.
- Jenkins 권한 확인을 단순 boolean 로그인 상태만으로 대체하지 않는다.
- artifact URL을 외부 네트워크에 노출하거나 로그에 token 포함 URL을 출력하지 않는다.
- staged APK를 tracked 경로에 쓰거나 cleanup 없는 장기 캐시로 전환하지 않는다.

View file

@ -1,14 +1,14 @@
---
domain: device-console
last_rule_review_commit: no-commit
last_rule_updated_at: 2026-06-08
last_rule_review_commit: c1c4c41886f44727ad5b9297ec164198d1dd5bd9
last_rule_updated_at: 2026-06-14
---
# device-console
## 목적 / 책임
USB로 연결된 Android 기기 조회, APK 설치, logcat/ADB 콘솔 경험을 담당한다.
USB로 연결된 Android 기기 조회, APK 설치, ADB runtime 해석/진단, logcat/ADB 콘솔 경험을 담당한다.
## 포함 경로
@ -21,6 +21,7 @@ USB로 연결된 Android 기기 조회, APK 설치, logcat/ADB 콘솔 경험을
- `lib/src/services/jenkins_client.dart` — Jenkins API 호출은 `artifact-flow` 책임
- `lib/src/features/builds/` — artifact 선택과 다운로드는 `artifact-flow` 책임
- `lib/src/models/pending_install.dart` — 설치 대기 handoff DTO는 `app-shell` 책임이며 device-console은 입력으로만 소비
- `macos/` — sandbox, process 실행, USB 접근 정책은 `macos-platform` 책임
## 주요 구성 요소
@ -29,22 +30,30 @@ USB로 연결된 Android 기기 조회, APK 설치, logcat/ADB 콘솔 경험을
- `ConsolePage` — logcat console UI
- `AdbDevice` — serial/state/model/product metadata
- `AdbService` — ADB command 실행 wrapper
- `AdbRuntimeConfig`, `AdbRuntime` — bundled/custom/system ADB 선택과 `ADB_SERVER_PORT` 환경 구성
- `AdbLogcatSession` — running `adb logcat` process lifetime wrapper
- `AdbRuntimeDiagnostics` — ADB executable path/source/version/SHA-256 진단 결과
- `AdbInstallResult`, `AdbException` — 설치 결과와 ADB 오류 표현
## 유지할 패턴
- 화면 코드에서 `Process.run` 또는 `Process.start`를 직접 호출하지 않고 `AdbService`를 통한다.
- ADB runtime 선택은 custom path, bundled path, system fallback 순서를 유지하고, 기본 AppSok 전용 server port는 `5038`로 둔다.
- `adb devices -l` parsing은 다양한 state(`device`, `unauthorized`, `offline`)를 허용한다.
- 설치 결과는 exit code, stdout, stderr를 모두 보존해 사용자에게 원인 파악 정보를 제공한다.
- logcat stream은 pause/clear/filter 같은 UI 상태와 process lifetime을 분리해 설계한다.
- logcat stream은 pause/clear/filter 같은 UI 상태와 process lifetime을 분리하고, `AdbLogcatSession.stop`으로 process를 종료한다.
- 콘솔 UI는 오래 실행되는 logcat session에서 화면 보관 line 수를 제한하고 level/text filter를 UI 상태로만 관리한다.
- ADB 진단은 `adb version` timeout과 executable SHA-256 계산을 best-effort로 수행한다.
## 다른 도메인과의 경계
- **artifact-flow**: 설치할 APK 경로만 입력으로 받고 Jenkins 인증/다운로드 상태에는 의존하지 않는다.
- **app-shell**: 연결된 device 수와 ADB 상태 요약만 shell로 전달한다.
- **macos-platform**: 앱 sandbox 안에서 ADB binary 실행 가능 여부는 platform domain과 함께 검토한다.
- **artifact-flow**: 설치할 staged APK path와 metadata만 입력으로 받고 Jenkins 인증/다운로드 상태에는 의존하지 않는다. settings 화면에 ADB diagnostics panel이 있어도 진단 타입과 loader semantics는 device-console 소유다.
- **app-shell**: pending install과 선택 device handoff는 shell이 조율하고, device-console은 설치/logcat 요청을 수행한다.
- **macos-platform**: bundled ADB 리소스, sandbox, codesign, packaging 제약은 macos-platform에서 관리하고, runtime 선택과 command semantics는 device-console에서 관리한다.
## 금지 사항
- device serial, logcat 원문에 secret이 포함될 수 있으므로 불필요하게 tracked 파일에 저장하지 않는다.
- split APK/APKS/AAB 설치를 단일 APK 설치 흐름에 섞어 임시 처리하지 않는다.
- 무한 logcat stream을 dispose 없이 방치하지 않는다.
- 화면 widget에서 ADB binary 경로, environment, server port를 직접 구성하지 않는다.

View file

@ -1,34 +1,44 @@
---
domain: macos-platform
last_rule_review_commit: no-commit
last_rule_updated_at: 2026-06-08
last_rule_review_commit: c1c4c41886f44727ad5b9297ec164198d1dd5bd9
last_rule_updated_at: 2026-06-14
---
# macos-platform
## 목적 / 책임
macOS desktop target의 bundle metadata, entitlement, URL scheme, runner 설정을 담당한다.
macOS desktop target의 bundle metadata, entitlement, URL scheme, runner 설정, bundled ADB resource packaging, certified build/signing/notarization tooling을 담당한다.
## 포함 경로
- `macos/Runner/Info.plist` — bundle metadata와 `appsok://` URL scheme
- `macos/Runner/Configs/` — product name, bundle identifier, build config
- `macos/Runner/AppDelegate.swift`, `macos/Runner/MainFlutterWindow.swift`, `macos/Runner/Base.lproj/` — macOS app/window/menu runner wiring
- `macos/Runner/*.entitlements` — sandbox/network 권한
- `macos/Runner/Resources/adb-runtime/` — bundled ADB runtime metadata와 NOTICE
- `macos/Runner.xcodeproj/`, `macos/Runner.xcworkspace/` — Xcode project/workspace 설정
- `macos/Flutter/GeneratedPluginRegistrant.swift` — Flutter plugin 등록
- `scripts/build-certified-macos.sh` — Flutter gate, Developer ID signing, notarization, final zip 생성
- `scripts/setup-appsok-ci-secrets.sh` — SOPS age key, encrypted CI secret, notary profile setup
- `.sops.yaml`, `secrets/*.sops.json` — encrypted CI signing/notary input 설정과 암호화 payload
## 제외 경로
- `lib/src/services/jenkins_client.dart` — network 호출 자체는 `artifact-flow` 책임
- `lib/src/services/adb_service.dart` — ADB command wrapper는 `device-console` 책임
- `lib/src/theme/` — 시각 스타일은 `app-shell` 책임
- `agent-test/` — 검증 명령 라우팅은 테스트 룰 책임
## 주요 구성 요소
- `AppInfo.xcconfig` — macOS 앱 표시 이름과 bundle id
- `Info.plist` — URL scheme 등록
- `DebugProfile.entitlements`, `Release.entitlements` — sandbox와 network client 권한
- `Runner.xcodeproj` build phase — pinned Android platform-tools `adb`를 app bundle resource로 복사하고 adhoc sign
- `GeneratedPluginRegistrant.swift``app_links`, `flutter_secure_storage_darwin`, `webview_flutter_wkwebview` plugin 등록
- `build-certified-macos.sh` — release build, bundled `adb` signing, app signing, notarization/staple/assessment packaging
- `setup-appsok-ci-secrets.sh` — SOPS-encrypted CI input 생성과 `notarytool` profile 저장
## 유지할 패턴
@ -36,14 +46,19 @@ macOS desktop target의 bundle metadata, entitlement, URL scheme, runner 설정
- bundle identifier는 `com.tokilabs.appsok` 기준으로 관리한다.
- URL scheme은 식별자 규칙상 `appsok://`을 유지한다.
- Jenkins 호출에는 network client entitlement가 필요하다.
- Release entitlement는 필요 권한만 유지하고, Debug/Profile 권한과 차이가 있으면 목적을 명확히 둔다.
- bundled ADB는 `source.properties`의 pinned `Pkg.Revision`과 실제 `adb version`을 맞춘 뒤 app resource로 복사한다.
- app bundle 안의 `adb-runtime/adb`는 app signing/notarization 전에 별도로 codesign 검증한다.
- CI signing/notary secret은 SOPS-encrypted payload와 macOS Keychain profile로만 다루고 raw password/key를 tracked 문서나 로그에 남기지 않는다.
- 배포 전에는 sandbox 상태에서 ADB binary 실행과 USB 접근 가능 여부를 macOS host에서 검증한다.
- macOS build/signing 검증은 local container가 아니라 standard remote Mac runner `toki@toki-labs.com``$HOME/docker/services/code-server/data/volume/workspace/appsok` checkout을 기준으로 한다.
- 원격에는 valid codesigning identity가 확인되어 있지만, notary credential profile은 별도 확인 전까지 미확정으로 둔다.
- certified build script는 `flutter analyze`, `flutter test`, `flutter build macos` gate 이후 signing/notarization/package 순서를 유지한다.
- 원격에는 valid codesigning identity가 확인되어 있지만, notary credential profile은 profile availability 확인 전까지 미확정으로 둔다.
## 다른 도메인과의 경계
- **artifact-flow**: deep link payload가 Jenkins job/build/artifact를 가리킬 수 있으나 parsing/권한 확인은 artifact-flow에서 담당한다.
- **device-console**: ADB 실행 권한과 packaging 제약은 macos-platform에서 관리하고, command semantics는 device-console에서 관리한다.
- **device-console**: bundled ADB resource, sandbox, codesign, packaging 제약은 macos-platform에서 관리하고, runtime 선택과 command semantics는 device-console에서 관리한다.
- **app-shell**: 앱 이름과 window metadata는 platform 설정에서 관리하고, 화면 layout은 app-shell에서 관리한다.
## 금지 사항
@ -51,3 +66,4 @@ macOS desktop target의 bundle metadata, entitlement, URL scheme, runner 설정
- entitlement를 넓힐 때 사유 없이 sandbox를 해제하지 않는다.
- macOS 설정 파일을 Flutter 자동 생성물과 충돌하는 방식으로 수동 대량 편집하지 않는다.
- notarization, signing, MDM 배포 전제를 확인하지 않고 배포 가능하다고 단정하지 않는다.
- SOPS key, keychain password, Apple ID password, notary credential 원문을 tracked 파일, task log, 최종 응답에 기록하지 않는다.

View file

@ -55,10 +55,11 @@
| 경로 패턴 | 도메인 | rules.md |
|----------|--------|----------|
| `lib/main.dart`, `lib/src/app.dart`, `lib/src/features/app_shell.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/token_store.dart` | artifact-flow | `agent-ops/rules/project/domain/artifact-flow/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/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`, `.sops.yaml`, `secrets/*.sops.json` | macos-platform | `agent-ops/rules/project/domain/macos-platform/rules.md` |
## 스킬 라우팅

View file

@ -11,7 +11,7 @@ Teams deep link와 설치 이력 작업으로 들어가기 전에, 원격 Mac ru
## 상태
[검토중]
[완료]
## 승격 조건
@ -63,15 +63,15 @@ Teams deep link와 설치 이력 작업으로 들어가기 전에, 원격 Mac ru
## 완료 리뷰
- 상태: 요청
- 상태: 승인
- 요청일: 2026-06-14
- 완료 근거:
- 원격 Mac runner에서 Flutter/Xcode/codesigning readiness, `flutter analyze`, `flutter test`, `flutter build macos`를 통과했다.
- Developer ID signing, Apple notarization, stapling, Gatekeeper assessment, 최종 ZIP checksum 기록을 완료했다.
- SOPS secret setup과 인증 빌드 반복 실행 절차를 스크립트, 문서, 테스트로 남겼다.
- 리뷰 필요:
- [ ] 사용자가 완료 결과를 확인했다
- [ ] archive 이동을 승인했다
- [x] 사용자가 완료 결과를 확인했다
- [x] archive 이동을 승인했다
- 리뷰 코멘트: 전체화면 전용 검증은 제품 목표가 아니므로 완료 조건에서 제외한다. 일반 창 기반 업무 흐름 확인은 각 후속 기능 Milestone의 smoke에서 필요할 때 다룬다.
## 범위 제외
@ -111,6 +111,7 @@ Teams deep link와 설치 이력 작업으로 들어가기 전에, 원격 Mac ru
- 반복 실행 명령: `scripts/build-certified-macos.sh`.
- 2026-06-14 docs/test: `docs/macos-certified-build.md``test/certified_macos_scripts_test.dart`를 추가해 secret setup, certified build command, bundled `adb` signing 순서, notarization/stapling/Gatekeeper 기준을 남겼다.
- 2026-06-14 verification: `flutter test test/certified_macos_scripts_test.dart` PASS, `flutter analyze` PASS, `git diff --check` PASS.
- 2026-06-14 code-level closure review: `APPSOK_CI_SECRET_FILE` override 시 `.sops.yaml` creation rule이 기본 경로에 고정되는 작은 이슈를 수정했고, `bash -n scripts/setup-appsok-ci-secrets.sh scripts/build-certified-macos.sh`, `flutter test`, `flutter analyze`, `git diff --check` PASS.
- 선행 작업: ADB 콘솔과 logcat
- 후속 작업: Teams deep link 설치 진입
- 확인 필요: 사용자 완료 확인과 archive 이동 승인.

View file

@ -14,10 +14,10 @@ MVP 설치 흐름을 Teams/Jenkins 알림과 연결하고, 반복 설치와 실
완료, 검토중, 진행중, 계획, 스케치 순서로 두어 아래로 갈수록 미래 작업에 가까워지게 정렬한다.
스케치 Milestone은 아직 구현 가능한 계획이 아니므로 계획 Milestone보다 아래에 둔다.
- [검토중] macOS 빌드 CI와 인증 빌드
- 경로: `agent-roadmap/phase/workflow-integration/milestones/macos-build-ci.md`
- [완료] macOS 빌드 CI와 인증 빌드
- 경로: `agent-roadmap/archive/phase/workflow-integration/milestones/macos-build-ci.md`
- 요약: Teams deep link와 설치 이력 작업 전에 원격 Mac build/CI baseline과 Developer ID notarized 인증 빌드 절차를 확정한다.
- [계획] Teams deep link 설치 진입
- [진행중] Teams deep link 설치 진입
- 경로: `agent-roadmap/phase/workflow-integration/milestones/teams-deep-link.md`
- 요약: Teams/Jenkins 메시지의 `appsok://` 링크로 특정 job/build/artifact 설치 화면에 바로 진입한다.
- [계획] 설치 세션 이력과 오류 리포트

View file

@ -11,7 +11,7 @@ Teams/Jenkins 알림에 포함된 `appsok://` 링크를 클릭하면 AppSok이
## 상태
[계획]
[진행중]
## 승격 조건
@ -77,4 +77,5 @@ Teams/Jenkins가 만들고 AppSok이 해석할 URL 형식을 정한다.
- 작업 현황:
- 2026-06-14: `ADB 콘솔과 logcat` 완료 후 다음 활성 Milestone으로 지정했다.
- 2026-06-14: macOS build/CI와 인증 빌드 gate를 먼저 확인하기 위해 `macOS 빌드 CI와 인증 빌드` 뒤로 순서를 조정했다.
- 2026-06-14: `macOS 빌드 CI와 인증 빌드` 완료 승인 및 archive 이동 후 다음 활성 Milestone으로 지정했다.
- 확인 필요: Teams payload 형식, Jenkins 알림 템플릿 변경 가능 여부

View file

@ -35,18 +35,6 @@ prompt_plain() {
printf -v "$var" '%s' "$value"
}
prompt_secret() {
local label="$1"
local var="$2"
local value
printf "%s: " "$label" > /dev/tty
stty -echo < /dev/tty
IFS= read -r value < /dev/tty
stty echo < /dev/tty
printf "\n" > /dev/tty
printf -v "$var" '%s' "$value"
}
mkdir -p "$(dirname "$AGE_KEY")" "$(dirname "$SECRET_FILE")"
if [ ! -f "$AGE_KEY" ]; then
@ -60,9 +48,17 @@ if [ -z "$AGE_RECIPIENT" ]; then
exit 1
fi
SOPS_PATH_REGEX="$(SECRET_FILE="$SECRET_FILE" python3 - <<'PY'
import os
import re
print(re.escape(os.environ["SECRET_FILE"]) + "$")
PY
)"
cat > .sops.yaml <<YAML
creation_rules:
- path_regex: secrets/appsok\\.ci\\.sops\\.json$
- path_regex: $SOPS_PATH_REGEX
age: "$AGE_RECIPIENT"
YAML

View file

@ -10,8 +10,13 @@ void main() {
expect(script, contains(r'age-keygen -o "$AGE_KEY"'));
expect(
script,
contains(r'path_regex: secrets/appsok\\.ci\\.sops\\.json$'),
contains(r'SOPS_PATH_REGEX="$(SECRET_FILE="$SECRET_FILE"'),
);
expect(
script,
contains(r'print(re.escape(os.environ["SECRET_FILE"]) + "$")'),
);
expect(script, contains(r'path_regex: $SOPS_PATH_REGEX'));
expect(
script,
contains(r'sops --filename-override "$SECRET_FILE" -e "$tmp"'),