← Docs hub

SKIX Product Framework 공개 경계 검토 기록

상위 구조: 이 문서는 SKIX 제품 프레임워크 전체 중 외부 앱과 제품 기능 사이의 북향 API·신뢰 경계를 다룬다. 상태, 정책, 자원, lifecycle, Task 실행과 Domain Framework 전체 구성은 SKIX 리팩터링 프레임워크 설계안을 기준으로 본다.

현재 결정: Gateway는 별도 프로세스의 확정 구성요소가 아니다. 1차 단계에서는 DeviceAgent의 제품 Runtime Binder 진입점 안에 호출자 검증·계약 변환·결과 필터링 책임을 논리 모듈로 둔다. 별도 APK나 프로세스는 승인 파트너 공개, 독립 업데이트 또는 장애 격리가 필요할 때 검토한다.

1. 결정 요약

SKIX 제품 기능은 DeviceAgent 안에 이동, 청정, 환경, 화면, TTS, 보안, 예약, Vision, 업데이트 등으로 축적되어 있다. TaskManager는 이 기능을 Task와 Workflow 단위로 실행하고 상태, 순서, 취소, 실패, 완료 증거를 관리하는 실행 Core다.

공개 경계에는 시스템 앱과 승인된 파트너 앱이 사용할 안정된 API, 호출자 검증, 계약 변환과 결과 필터링이 필요하다. 이 문서에서 Gateway는 그 책임 묶음을 뜻한다. 1차 구현은 별도 서비스가 아니라 제품 Runtime Service 내부 모듈로 시작한다.

앱이 말하는 것: 어떤 기능을 어떤 조건으로 사용하고 싶은가
Gateway가 판단하는 것: 누가 어떤 API와 capability를 사용할 수 있는가
TaskManager가 관리하는 것: 허용된 실행을 언제, 어떤 순서로, 어떤 종료 상태까지 수행하는가
도메인이 수행하는 것: 이동, 청정, 화면, 측정과 같은 실제 기기 동작

SKIX Product Framework Gateway 계층 구조

이 설계에서 Gateway는 TaskManager를 우회하거나 대체하지 않는다. Gateway는 공개 API와 신뢰 경계, TaskManager는 실행 생명주기 경계다.

2. 현재 기반과 목표 상태

구분 확인된 기반 1차 목표
공통 호출 DeviceControlProxy와 IDeviceControl.sendModuleCommand(Bundle) 외부 앱이 raw Bundle과 문자열 메서드를 직접 다루지 않는 typed SDK
제품 실행 DeviceAgent.MainApi와 도메인 manager 도메인 Facade가 기존 구현을 감싸고 내부 변경을 외부 계약과 분리
Task 실행 MR6 task_manager 브랜치의 TaskManager, policy, executor, completion, event Gateway 요청을 검증된 Task 또는 Workflow로 변환하고 terminal 결과를 반환
Task client TaskManagerClient AAR 사내 시스템 앱과 Gateway가 사용하는 내부 실행 adapter로 제한
UI SKLauncher2의 Java, AppCompat, ViewBinding/DataBinding, XML resource와 공통 widget UI token, 공용 component, 시스템 surface 계약을 별도 AAR로 분리
외부 앱 보안 현재 체크아웃의 exported Binder와 일부 명령별 UID 검사 공통 서비스 권한, package·certificate 검증과 capability grant를 요청마다 적용

상태 표기 원칙은 다음과 같다.

표기 의미
현재 현재 체크아웃에서 직접 확인되는 API, 앱, 리소스
구현 기반 MR6의 task_manager 브랜치에서 확인되는 TaskManager와 AAR 구현
목표 아직 구현되지 않은 Product Framework Gateway, 파트너 정책, UI Foundation

현재 체크아웃과 TaskManager 구현 브랜치가 다르므로, 실제 리팩터링을 시작하기 전에 기준 브랜치를 하나로 정합하는 작업이 선행되어야 한다.

보안 기준선 주의: MR6의 task_manager 브랜치에는 DEVICE_CONTROL signature permission과 service 보호가 들어가지만, 현재 speaker_identification 체크아웃의 DeviceAgent service에는 같은 manifest permission이 보이지 않는다. 어느 상태가 출시 기준인지 먼저 정합하고, 별도 인증서 파트너에게는 두 경우 모두 기존 IDeviceControl Binder를 직접 공개하지 않는다.

3. 왜 Gateway와 TaskManager를 분리하는가

두 계층을 합치면 TaskManager가 앱 인증, API 버전, UI surface, 파트너 계약까지 소유하게 된다. 그러면 실행 Core가 제품 배포와 파트너 정책에 종속된다. 반대로 Gateway가 queue와 Workflow 실행을 다시 구현하면 실행 상태의 소유자가 두 곳이 되어 취소, timeout, 완료 판정이 갈라진다.

책임 Product Framework Gateway TaskManager Core
호출자 식별 Binder UID, package, signing certificate 확인 검증된 source와 principal만 수신
권한 capability grant, 사용자 동의 요구, API별 제한 기기 상태, 자원, priority, queue admission
계약 public request를 내부 Task/Workflow로 변환 Task/Workflow schema 검증과 실행
버전 SDK/API 버전 협상, deprecated API 차단 내부 task contract version 처리
상태 조회 public snapshot과 event 필터링 task record, progress, terminal event 생성
UI 공용 UI token과 surface route 제공 UI 전환이 Task일 때 실행과 완료만 관리
실행 직접 실행하지 않음 queue, 순서, timeout, retry, cancel, compensation 관리

3.1 실행 API 관계

SkixFrameworkClient.submit(ActionRequest)
  -> Gateway: caller identity + capability grant + API version
  -> GatewayTaskAdapter: public capability/operation을 TaskSubmitRequest로 변환
  -> TaskManagerClient: submitTask 또는 submitWorkflow
  -> TaskManager: admission, queue, execution, completion
  -> GatewayResultMapper: 내부 reason/event를 public result/event로 정규화
  -> Partner app: TaskHandle, progress, terminal result

TaskManagerClient.sendRaw(Bundle)와 임의 taskMethod는 내부 호환용으로 남기고 파트너 SDK에는 노출하지 않는다. 파트너는 Gateway가 공개한 capability와 operation만 조합할 수 있다.

3.2 조회와 UI는 Task로 강제하지 않는다

모든 API를 TaskManager에 넣는 것은 과설계다.

요청 종류 권장 경로 이유
현재 배터리, 위치, 공기질 조회 Gateway State API 실행 생명주기가 없는 read-only snapshot
이동, 청정, 설정 변경 Gateway Action API -> TaskManager 실행 허용, 취소, 완료 증거가 필요
여러 단계 기능 Gateway Workflow API -> TaskManager 단계 의존관계와 실패 정책이 필요
Task 진행 관찰 Gateway Event API -> TaskManager event caller별 필터와 안정된 public event 필요
제품 화면 열기 Gateway Surface API -> UI Surface Router Activity와 Fragment 클래스명을 공개하지 않기 위함
테마와 공용 widget UI Foundation AAR 앱 프로세스 안에서 렌더링되는 정적 UI 자산

4. 권장 계층

4.1 Consumer Layer

소비자 접근 방식 허용 범위
SKIX 시스템 앱 Public SDK 우선, 필요한 내부 기능만 Internal SDK 전체 제품 capability 중 앱 역할에 필요한 범위
승인 파트너 앱 Partner SDK와 Gateway만 사용 인증서별 grant가 있는 capability
미승인 일반 앱 직접 제어 API 없음 허용된 공개 Intent 또는 사용자 주도 화면만 선택적으로 제공

시스템 앱도 장기적으로 Public SDK를 우선 사용해야 파트너 경로와 동일한 API가 실제 제품에서 검증된다. 단, 공장 검사, 복구, emergency처럼 외부에 공개할 수 없는 기능은 Internal SDK로 분리한다.

4.2 SDK Layer

후보 모듈 책임 공개 대상
skix-framework-contract request, result, event, capability descriptor, reason code 시스템 앱과 승인 파트너
skix-framework-client Gateway bind, Binder death 복구, async callback, API 협상 시스템 앱과 승인 파트너
skix-ui-tokens 의미 기반 color, typography, spacing, shape, motion token UI를 만드는 앱
skix-ui-components 버튼, popup, progress, status, empty/error view UI를 만드는 앱
skix-ui-surfaces 제품 화면 ID와 launch argument 계약 화면 진입이 허용된 앱
skix-framework-testkit fake Gateway, capability fixture, Task event simulator 파트너와 사내 개발·검증
taskmanagerclient raw TaskManager adapter와 내부 constants DeviceAgent, Gateway, 승인된 사내 시스템 구성요소만

UI AAR와 실행 AAR를 분리한다. 테마 변경 때문에 기기 실행 SDK가 재배포되거나, Device API 변경 때문에 모든 UI 리소스를 다시 검증하는 결합을 피하기 위해서다.

4.3 공개 API와 신뢰 경계

1차 구현은 DeviceAgent 프로세스의 제품 Runtime Binder 진입점 안에 아래 책임을 둔다. 동일 프로세스라도 호출자 UID·인증서 검증과 공개 계약 변환은 기존 raw command 처리보다 앞에서 수행한다. 별도 인증서 파트너가 늘어나거나 독립 배포·장애 격리가 필요해지면 이 책임 묶음을 별도 privileged service로 옮길 수 있다.

구성요소 책임
Caller Identity Resolver Binder.getCallingUid()를 package와 signing certificate로 해석
Partner Entitlement Registry 승인 package, certificate digest, API 범위, capability grant 보관
API Version Negotiator SDK와 Framework의 지원 버전을 비교하고 호환 API 선택
Capability Registry 공개 capability, operation, 필수 parameter, 위험 등급 제공
State Gateway DeviceAgent 상태를 public snapshot으로 필터링하고 freshness 표시
Task Adapter Action/Workflow를 TaskSubmitRequest와 TaskWorkflowRequest로 변환
Event Gateway Task event를 호출자 소유권과 구독 범위에 맞게 필터링
Result Mapper 내부 reason code와 Bundle을 안정된 public result로 정규화
UI Surface Router 공개 surface ID를 SKLauncher2의 명시적 화면 계약으로 연결

Gateway는 요청마다 호출자 UID를 다시 검증한다. 연결 시 한 번 확인한 package 문자열이나 앱이 요청에 넣은 source 값은 신뢰하지 않는다.

4.4 Execution and Domain Layer

TaskManager는 공개 앱 API를 알 필요가 없다. Gateway가 보낸 내부 계약을 기존 방식으로 처리한다.

TaskManager Core
  -> admission / policy / resource
  -> queue / priority / workflow / scheduler
  -> lifecycle / timeout / cancel / compensation
  -> executor registry
  -> completion watcher / event / reason

Executor는 도메인 Facade를 호출하고 Facade가 현재 DeviceAgent 구현과 peer agent를 감싼다.

도메인 Facade 현재 연결 후보
Mobility moving/*, device/item/amr/*, AMRAgent
Cleaning cleaning/*, AirQualityManager, MCU fan
Environment 공기질, 온습도, filter, sensor 상태
Interaction TTS, Eye LED, 화면, 대화·LLM 상태
Health Vital Signs 앱 세션과 완료·취소 증거
Security and LiveView WSS, streaming, privacy, security 상태
Schedule and Routine 제품 schedule, Welcome, deferred Task
Vision and Perception VisionAgent, 의미 관찰, 카메라 정책
System and Maintenance 설정, 네트워크, OTA, 오류, 부품과 사용 시간

Facade는 기존 기능을 복사하지 않는다. 입력 정규화, 정책 전처리, 실행 호출, 완료 증거 변환만 소유한다.

5. 파트너 공개 API 초안

아래 이름은 계약 검토를 위한 후보이며 구현 완료 API가 아니다.

SkixFrameworkClient client = SkixFramework.connect(context);

FrameworkInfo info = client.getFrameworkInfo();
List<CapabilityDescriptor> capabilities = client.getCapabilities();
DeviceSnapshot snapshot = client.getDeviceSnapshot(StateQuery.basic());

TaskHandle handle = client.submitAction(
        ActionRequest.builder("mobility.move")
                .requestId("partner-req-001")
                .put("targetRoom", "안방")
                .build()
);

TaskSubscription subscription = client.observeTask(
        handle.getTaskId(),
        event -> renderProgress(event)
);

Workflow는 raw taskMethod 배열이 아니라 공개 capability operation의 조합으로 받는다.

WorkflowRequest workflow = WorkflowRequest.builder("inspect-and-clean")
        .addStep(ActionStep.of("mobility.move").put("targetRoom", "거실"))
        .addStep(ActionStep.of("cleaning.startBasic").afterPrevious())
        .addStep(ActionStep.of("mobility.returnToStation").afterPrevious())
        .failurePolicy(FailurePolicy.STOP_AND_REPORT)
        .build();

TaskHandle handle = client.submitWorkflow(workflow);

5.1 파트너가 설정할 수 없는 값

파트너 앱이 다음 값을 직접 결정하게 하면 내부 안전 정책을 우회할 수 있다.

비공개 필드 처리 방식
forceTaskManager Gateway가 항상 관리 실행으로 고정
raw taskMethod capability operation을 통해서만 내부 매핑
source Gateway가 검증된 principal에 따라 PARTNER로 설정
emergency priority 외부 요청 금지. 별도 제품 정책과 사용자 동의가 있는 API만 승격
bypassCallerPolicy 외부 계약에서 제거
임의 queue, cancel method, compensation method Capability Registry와 Task policy가 결정
내부 completion key Gateway와 domain adapter가 상관관계 ID로 생성

5.2 Public 결과 모델

모델 최소 필드
TaskHandle requestId, taskId, acceptedAt, initialState
TaskEvent taskId, eventType, progress, stage, timestamp, reason
TaskResult taskId, terminalState, resultCode, reasonCode, data
DeviceSnapshot stateVersion, capturedAt, freshness, 허용된 domain state
CapabilityDescriptor capabilityId, operations, riskTier, requiredConsent, schemaVersion

내부 클래스명, exception stack, MCU code, raw Bundle은 partner result에 그대로 노출하지 않는다. 운영 추적용 traceId는 허용된 범위에서만 반환한다.

6. 인증서가 다른 승인 파트너의 접근 모델

기존 signature permission 하나만으로는 별도 인증서 파트너를 안전하게 지원할 수 없다. 파트너 Gateway는 Android permission 선언만 믿지 않고 service 내부에서 호출자 신원을 검증해야 한다.

6.1 권장 검증 순서

  1. Binder.getCallingUid()로 실제 호출 UID를 얻는다.
  2. PackageManager.getPackagesForUid()로 UID에 연결된 package를 확인한다.
  3. 설치된 package의 signing certificate digest를 읽는다.
  4. 읽기 전용 Framework policy에 등록된 package와 certificate 조합을 비교한다.
  5. API version, capability grant, risk tier, 사용자 동의 조건을 검증한다.
  6. 검증된 principal 정보를 Gateway 내부에서 생성하고 Task 요청에 주입한다.
  7. 모든 API 호출과 Task event 구독에서 소유권을 다시 확인한다.

파트너가 전송한 package name, source, certificate 문자열은 신원 증거로 사용하지 않는다. shared UID가 있는 경우 연결된 모든 package와 signing lineage를 검증하거나 v1에서 거절한다.

6.2 권한 단계

단계 예시 허용 정책
Internal platform-signed SKIX 앱 내부 capability를 역할별로 부여
Partner 별도 인증서의 승인 앱 package + certificate + capability allowlist
Public Surface Only 제한된 일반 앱 명시적 사용자 동작으로 열리는 화면만 제공
Denied 미등록 앱 bind 또는 모든 API 호출 거절, 감사 event 기록

인증서 교체는 signing lineage와 정책 version을 가진 별도 승인 절차로 관리한다. OTA로 policy를 갱신할 때는 rollback과 이전 SDK 호환성을 함께 검증한다.

7. SKLauncher2 UI Foundation 분리안

현재 SKLauncher2에는 공용 후보인 RoundedConstraintLayout, AirBotSwitch, AirBotSideBar, AirBotToastView, AirClearProgressBar, AlertView, typography style, color, font, animation resource가 있다. 그대로 복사해 공개하는 것이 아니라 재사용 가능성 기준으로 분류한다.

분류 추출 기준 예시
Token 화면이나 도메인 이름 없이 의미로 표현 가능 colorStatusError, spacePanel, motionProgress
Primitive Component DeviceAgent 호출과 Activity 생명주기를 소유하지 않음 switch, option group, status view, progress view
Pattern Component 일관된 확인, 오류, 진행 UX를 제공 task progress, cancel confirmation, unavailable state
Product Surface 제품 기능과 내비게이션을 소유 청정, 이동, 바이탈, 설정 화면
App Internal 특정 Fragment, repository, 화면 전용 binding에 종속 SKLauncher2 안에 유지

UI component는 Device API를 직접 호출하지 않는다. 사용자 action을 callback으로 올리고 앱이 Framework Client를 호출한다. Task 진행 UI는 TaskEvent를 입력받아 표현만 담당한다.

7.1 UI API 예시

<com.skix.ui.components.TaskProgressView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:statusStyle="compact" />
taskProgressView.render(TaskUiModel.from(taskEvent));
surfaceClient.open(SkixSurface.VITAL_SIGN, SurfaceArgs.empty());

파트너 앱은 SKLauncher2의 Activity나 Fragment 클래스명을 직접 알지 않는다. surfaceId, arguments schema, result contract만 사용한다.

8. 기존 경로와 호환 운영

초기 전환에서 기존 MQTT, PUI, SKLauncher2, IoT, 내부 앱 호출을 일괄 변경하지 않는다.

경로 초기 운영 전환 방향
기존 sendModuleCommand(Bundle) Legacy lane 유지 새 기능부터 typed Facade와 Gateway 적용
TaskManagerClient AAR 사내 내부 adapter로 유지 Gateway가 실행 요청을 전달하는 표준 내부 client
SKLauncher2 직접 호출 기존 기능 보존 공용 UI와 신규 실행부터 SDK로 전환
IoT/MQTT 단일 명령 기존 payload 유지 Task 성격이 필요한 요청만 task envelope 추가
승인 파트너 앱 기존 Binder 직접 접근 금지 Gateway와 Partner SDK만 사용

같은 물리 자원을 사용하는 legacy 실행과 managed Task가 동시에 들어오면 TaskManager의 ingress와 자원 정책으로 단계적으로 편입한다. Legacy를 즉시 Task로 강제하지 않되, 이동, 청정, 카메라처럼 충돌 비용이 큰 도메인부터 managed concurrency로 전환한다.

9. 단계별 리팩터링 운영안

Phase 0. 기준선과 카탈로그

완료 기준은 호출·상태·이벤트·보안 owner가 없는 기능이 inventory에 남지 않는 것이다.

Phase 1. Read-only 공개 API

이 단계에서 보안 경계와 SDK 연결을 검증하고 물리 동작 회귀 위험을 분리한다.

Phase 2. 저위험 Action과 TaskManager 연결

Phase 3. UI Foundation

Phase 4. 이동·청정과 제한 Workflow

Phase 5. 파트너 Pilot과 운영

10. 검증 항목

영역 필수 시험
신원 승인 certificate 허용, 미승인·변조·package 불일치 거절
권한 capability별 allow/deny, user consent, emergency 우회 거절
API 호환 SDK 구버전 협상, capability 미지원, deprecated API 처리
Task 연계 Action과 Workflow가 TaskManager에 한 번만 등록되는지 확인
생명주기 progress, cancel, timeout, binder death, terminal event 전달
상태 snapshot freshness, 민감 필드 제거, event 소유권 필터
UI theme/resource collision, 접근성, 다국어, Task 상태 표현
Legacy 기존 DeviceControlProxy, MQTT, SKLauncher2 동작 parity
실기기 이동·청정·화면·TTS 등 도메인별 실행과 물리 완료 증거

11. 1차 의사결정

항목 결정
Framework 배치 AOSP frameworks/base가 아니라 SKIX namuh Product Framework Layer
공개 경계 배치 1차는 DeviceAgent 제품 Runtime Binder 내부 논리 모듈. 파트너 보안·독립 OTA·장애 격리 근거가 있을 때 별도 privileged service 검토
TaskManager 관계 Gateway가 Task/Workflow를 생성하고 TaskManager가 실행 생명주기를 독점
파트너 범위 별도 인증서의 사전 승인 파트너 앱 포함
공개 실행 계약 raw method가 아니라 capability + operation
UI 전략 SKLauncher2 전체 공유가 아니라 token, component, surface 계약 분리
호환 전략 기존 경로 유지, 신규 기능 우선 적용, 도메인별 점진 전환

12. 다음 검토 항목

  1. 승인 파트너 범위와 장애 격리 요구가 별도 process 비용을 정당화하는지 측정한다.
  2. v1 파트너에게 공개할 capability 범위를 read-only, UI, TTS, 이동, 청정 중에서 선정한다.
  3. 파트너 인증서 allowlist를 system image, signed policy package, 관리 서버 중 어디서 갱신할지 결정한다.
  4. SKLauncher2에서 가장 먼저 추출할 token과 component 10개를 선정한다.
  5. 기존 TaskManagerClient의 sendRaw와 전체 constants를 Internal API로 분류할 방식을 결정한다.

연결 문서

Keyboard shortcuts

⌘K / Ctrl+KOpen command palette
/Focus search
g hGo to home
g pGo to projects
g sGo to sessions
j / kNext / prev row (tables)
?Show this help
EscClose dialogs

Structured queries

Mix key:value filters with free text in the palette:

type:sessionOnly session pages
project:llm-wikiFilter by project name (substring)
model:claudeFilter by model name (substring)
date:>2026-03-01Sessions after a date
date:<2026-04-01Sessions before a date
tags:rustPages mentioning a tag/topic
sort:dateSort results by date (newest first)

Example: type:session project:llm-wiki date:>2026-04 sort:date