SPECIFICATION

.dpk (Dash Plugin Package) Format Specification v1

Version: 1.0.0 | Date: 2026-03-26 | Author: CTO Agent

Overview

.dpk는 The Universe 런처에서 사용하는 Dash 플러그인 배포 형식입니다.

ZIP 기반 컨테이너로, Skin(UI) + Skill(로직) + 메타데이터 + 서명을 하나의 파일로 패키징합니다.

APK가 아닌 .dpk를 사용하는 이유:

  • Compose UI를 호스트 프로세스에서 직접 렌더링 (IPC 없음)
  • Fusion (Dash 결합)을 위한 UI 합성 가능
  • 경량 (1~10MB vs APK 20MB+)
  • 즉시 설치, 재시작 불필요

  • Package Structure

    my-dash-1.0.0.dpk (ZIP)
    

    ├── MANIFEST.yaml # DASH.md 5-Layer 프론트매터 (필수)

    ├── classes.dex # Skill 비즈니스 로직 — R8 최적화 DEX (필수)

    ├── skins/ # @Composable UI 코드 (필수)

    │ └── SkinModule.jar # composable_entry 클래스 포함

    ├── res/ # 리소스 (선택)

    │ └── drawable/

    │ └── ic_dash.png

    ├── assets/ # 추가 에셋 (선택)

    ├── schemas/ # Protocol 메시지 스키마 (선택)

    │ └── MyData.v1.json

    ├── signature.sig # EdDSA 코드 서명 (필수)

    └── checksum.sha256 # 전체 파일 SHA-256 해시 (필수)

    필수 파일

    | 파일 | 설명 |

    |------|------|

    | MANIFEST.yaml | DASH-schema-v1.json 준수 5-Layer 정의 |

    | classes.dex | Skill 클래스 (DashSkill 인터페이스 구현) |

    | skins/ | 1개 이상의 @Composable JAR |

    | signature.sig | EdDSA (Ed25519) 서명 |

    | checksum.sha256 | 모든 파일의 SHA-256 해시 목록 |

    크기 제한

  • 전체 .dpk: 10MB 이하
  • classes.dex: 5MB 이하
  • 개별 리소스: 2MB 이하
  • 총 파일 수: 100개 이하

  • MANIFEST.yaml

    DASH-schema-v1.json을 준수하는 YAML 파일. docs/specs/DASH-template.md 참조.

    meta:
    

    id: com.example.my-dash

    name: My Dash

    version: 1.0.0

    category: utility

    keywords: [keyword1, keyword2]

    author: developer@example.com

    trigger:

    conditions:

    - type: always

    skin:

    sizes: [mini, standard]

    theme_aware: true

    composable_entry: MyDashSkin

    skill:

    entry: MyDashSkill

    permissions: [network]

    local_state: false

    allowed_apis: [weather_api]

    protocol:

    publish: []

    subscribe: []

    fusible_with: []

    imports: []


    Code Signing (EdDSA)

    서명 생성

    1. 개발자 키 생성 (Ed25519)

    openssl genpkey -algorithm Ed25519 -out developer.key

    openssl pkey -in developer.key -pubout -out developer.pub

    2. 서명 대상: signature.sig 제외한 모든 파일의 SHA-256

    find . -not -name 'signature.sig' -type f | sort | \

    xargs sha256sum > checksum.sha256

    3. EdDSA 서명

    openssl pkeyutl -sign -inkey developer.key \

    -in checksum.sha256 -out signature.sig

    서명 검증 (런타임)

    class DashSignatureVerifier(private val trustedPublicKeys: List) {
    
    

    fun verify(dpkFile: File): Boolean {

    val zip = ZipFile(dpkFile)

    val checksumEntry = zip.getEntry("checksum.sha256")

    val signatureEntry = zip.getEntry("signature.sig")

    val checksum = zip.getInputStream(checksumEntry).readBytes()

    val signature = zip.getInputStream(signatureEntry).readBytes()

    // Verify each file hash matches checksum.sha256

    if (!verifyFileHashes(zip, checksum)) return false

    // Verify EdDSA signature

    return trustedPublicKeys.any { publicKey ->

    val sig = Signature.getInstance("Ed25519")

    sig.initVerify(publicKey)

    sig.update(checksum)

    sig.verify(signature)

    }

    }

    }

    The Universe CA Chain

    The Universe Root CA (오프라인)
    

    └── Developer Signing CA (온라인)

    └── 개발자 인증서 (개인키로 .dpk 서명)


    Installation Flow

    1. 다운로드
    

    ├── Dash Store CDN: GET /store/dashes/{id}/download → Signed URL

    └── Play Store: Wrapper APK → assets/{name}.dpk 추출

  • 무결성 검증
  • ├── checksum.sha256 파일별 해시 확인

    └── signature.sig EdDSA 검증 (The Universe CA 체인)

  • 정적 분석 (보안)
  • ├── MANIFEST.yaml 스키마 검증 (validate-dash.sh)

    ├── permissions 검토 (DANGEROUS 이상 → 사용자 확인)

    └── DEX 바이트코드 기본 분석 (위험 API 호출 감지)

  • 설치
  • ├── ZIP 해제 → files/dashes/installed/{dash_id}/

    ├── Dash Registry Room DB 등록

    └── 라이프사이클: CREATED 상태

  • 로딩
  • ├── DexClassLoader로 classes.dex 로딩 (격리된 ClassLoader)

    ├── DashSkillContext 샌드박스 생성 (allowed_apis 강제)

    ├── @Composable 리플렉션 로딩 (composable_entry)

    └── 라이프사이클: INITIALIZED → ACTIVE

    설치 경로

    files/dashes/installed/{dash_id}/
    

    ├── MANIFEST.yaml

    ├── classes.dex

    ├── skins/

    ├── res/

    ├── assets/

    └── _meta/

    ├── installed_at.txt # ISO 8601 설치 일시

    ├── version.txt # 현재 설치 버전

    └── signature_valid.txt # true/false


    Play Store Distribution (Wrapper APK)

    .dpk를 Play Store에서도 배포하기 위한 래퍼 APK 전략:

    weather-dash-wrapper.apk
    

    ├── AndroidManifest.xml

    ├── assets/

    │ └── weather-dash-1.0.0.dpk

    └── src/

    └── InstallDashActivity.kt

    // 1. .dpk를 런처에 전달 (ContentProvider 또는 FileProvider)

    // 2. 런처가 설치 완료 확인

    // 3. Wrapper APK 자기 삭제 (선택적)

    사용자 플로우:

  • Play Store에서 "Weather Dash" 검색 → 설치
  • Wrapper APK 실행 → The Universe 런처에 .dpk 자동 전달
  • 런처가 .dpk 서명 검증 → 설치
  • Wrapper APK는 stub으로 남거나 자동 삭제

  • Developer Workflow

    1. 프로젝트 생성

    dash-cli create weather-dash

    cd weather-dash/

    2. 구조

    ls

    DASH.md # 5-Layer 정의

    src/

    WeatherDashSkin.kt # @Composable UI

    WeatherDashSkill.kt # 비즈니스 로직

    res/

    drawable/ic_weather.png

    3. 개발 (핫-리로드)

    dash-cli dev # 런처에 실시간 연결

    4. 검증

    dash-cli validate # DASH.md 스키마 검증

    dash-cli test # 단위 테스트 실행

    5. 빌드

    dash-cli build # → weather-dash-1.0.0.dpk 생성

    6. 배포

    dash-cli publish # Dash Store 업로드

    dash-cli wrap # Play Store Wrapper APK 생성


    Versioning

  • .dpk 파일명: {id}-{version}.dpk (예: weather-dash-1.0.0.dpk)
  • 버전: Semantic Versioning (MAJOR.MINOR.PATCH)
  • 업데이트: 설치된 .dpk 대체 (이전 버전 백업 유지, 롤백 가능)
  • 하위 호환: MANIFEST.yaml 스키마 버전에 따름 (docs/specs/versioning-policy.md 참조)

  • Security Sandbox

    ClassLoader 격리 (Phase 1~2)

    val dashClassLoader = DexClassLoader(
    

    dexPath = installedDexPath,

    optimizedDirectory = cacheDir,

    librarySearchPath = null, // 네이티브 라이브러리 차단

    parent = dashSdkClassLoader // Dash SDK 인터페이스만 노출

    )

  • Dash 코드는 호스트 앱의 클래스에 직접 접근 불가
  • Dash SDK 인터페이스(DashSkin, DashSkill, DashSkillContext)만 parent에서 제공
  • 파일 시스템: files/dashes/installed/{dash_id}/ 범위로 제한
  • Process 격리 (Phase 3+, 선택적)

    신뢰도가 낮은 Dash는 별도 프로세스에서 실행:

        android:name=".DashSkillService"

    android:process=":dash_sandbox"

    android:isolatedProcess="true" />

    ResourceQuota 강제

    data class ResourceQuota(
    

    val memoryMb: Int = 32, // 4~256MB

    val networkKbPerMin: Int = 512, // 0~10240 KB/min

    val cpuPercent: Int = 10 // 1~50%

    )

    Orchestrator가 실시간 모니터링, 초과 시 Dash 일시정지 또는 종료.


    Related Documents

  • docs/specs/DASH-schema-v1.json — 5-Layer JSON Schema
  • docs/specs/DASH-template.md — DASH.md 공식 템플릿
  • docs/specs/versioning-policy.md — 스키마 버전 정책
  • docs/specs/sample-dashes/weather-dash.md — Weather Dash 샘플
  • docs/research/security-sandbox-research.md — 보안 샌드박스 리서치
  • docs/research/runtime-plugin-research.md — 런타임 플러그인 리서치