대시보드
Morit Plugin4. 기능, 데이터, 사용자 제어

권한, 설정, 저장소, 알림

권한 목록

permission허용하는 작업
networkHost가 보호하는 외부 HTTPS/MCP 요청
user_data_readMorit 사용자 데이터 읽기
user_data_writeMorit 사용자 데이터 변경
attachments_read사용자가 선택한 첨부 파일 읽기
file_write사용자에게 반환할 파일 artifact 작성
ai_tool_callAI Tool 실행 경계 사용
notifications표시·예약·취소 알림 요청
backgroundHost scheduler에서 자동 실행
account_read필요한 계정 기본 정보 읽기
storage플러그인 전용 데이터 저장
ai_storageAI가 선언된 namespace를 표준 CRUD Tool로 읽거나 변경
credentialsCredential/Connection 사용

Manifest는 요청 가능한 최대 권한, capability와 UI extension은 실제 필요한 부분집합을 선언합니다. 사용자가 허용하지 않은 권한은 runtime에서 다시 차단됩니다. 화면을 볼 수 있다는 사실과 작업 권한은 동일하지 않습니다.

Settings

Settings는 default Instance에 저장되는 작은 사용자 환경설정입니다. UI Runtime state를 유지하려면 initial_state에 key를 선언하고 해당 control 또는 set_state에 persist: true를 사용합니다.

적합한 값:

  • 기본 기간, 정렬 방식, 표시 옵션
  • 알림 on/off와 사용자 선택 시간
  • 공개 school code처럼 민감하지 않은 외부 식별자

저장하면 안 되는 값:

  • OAuth access/refresh token, API key
  • 파일 원문이나 큰 목록
  • 다른 플러그인의 설정
  • 서버가 검증하지 않은 실행 코드

Settings 전체는 32 KiB 이하입니다. UI state의 client 저장 경계는 더 작을 수 있으므로 화면에 필요한 최소 key만 유지합니다.

Plugin Local Storage

storage는 사용자·Installation·Instance·namespace로 격리됩니다. 문자열, 숫자, boolean, JSON과 목록을 저장하며 package가 업데이트되어도 정책에 따라 유지됩니다. generation이 바뀐 오래된 실행은 새 상태를 쓸 수 없습니다.

삭제 시 data_policy가 일반 storage의 purge 또는 retain을 정합니다. credential, OAuth state, pending Host action은 별도 보안 수명주기를 따르며 일반 storage retention으로 보존하지 않습니다.

ai_storage는 설치/설정에서 한 번 허용한 뒤 매 CRUD 승인을 반복하지 않습니다. 그래도 Host는 현재 사용자·활성 Instance·허용 namespace와 read/read_write 범위를 매 호출 확인합니다. Manifest, CRUD 인자, quota, migration, 오류와 초기화는 Plugin Local Storage와 AI 접근을 참고하세요.

Network

외부 통신은 http_json, mcp_http, 지원되는 Host adapter를 통과합니다.

  • 공개 HTTPS만 허용
  • redirect 비허용
  • DNS/IP와 SSRF 정책 적용
  • Connector timeout 최대 30초
  • retry 최대 4회
  • Instance별 rate limit
  • credential은 Host가 요청 직전에 주입

endpoint, Authorization header, secret을 UI state나 capability 결과에 복사하지 않습니다.

Capability 결과 URL을 image 또는 avatar에 표시하는 경우에도 같은 권한 경계를 사용합니다. Manifest의 network 요청과 활성 Instance의 network grant가 모두 필요합니다. Flutter 앱은 외부 이미지를 직접 요청하지 않고 인증된 Host proxy를 호출하며, Host가 public HTTPS·SSRF·redirect·이미지 형식·512 KiB·4096 px·16 MP 제한을 적용합니다. 선언과 상세 제한은 UI Runtime v2, endpoint는 수명주기와 HTTP API를 참고하세요.

Notification Host action

Capability 결과의 data.host_actions는 Host가 서버에서 다시 확인하고 durable outbox에 기록합니다. 알림을 직접 OS API로 호출하지 않습니다.

json
{
  "type": "schedule_notification",
  "id": 41001,
  "key": "school_life:morning:2026-08-14",
  "title": "내일 학교 일정",
  "body": "1교시는 수학입니다.",
  "at_millis": 1786640400000,
  "category": "reminder",
  "visibility": "private",
  "silent": false,
  "actions": [
    {"id": "done", "type": "check", "label": "완료", "capability": "school_life.task.complete", "arguments": {"task_id": "42"}},
    {"id": "later", "type": "snooze", "label": "10분 후", "minutes": 10},
    {"id": "open", "type": "open_plugin", "label": "학교 생활", "target": "school_life.dashboard"},
    {"id": "reply", "type": "reply", "label": "답장", "capability": "school_life.task.reply", "arguments": {"task_id": "42"}}
  ]
}

지원 type:

  • show_notification: 즉시 표시
  • schedule_notification: at_millis에 예약
  • cancel_notification: 같은 id와 key 취소

공통 한도는 id 0~2,147,483,647, key 최대 240자, title 160자, body 500자, big_text 2,000자입니다. category는 general, reminder, progress, status, visibility는 private, public, secret입니다. 예약은 현재부터 최대 366일 안입니다.

Android 12 이상, Morit 1.7.37 이상에서는 사용자가 설정 → 알림 → 정확한 시간 알림에서 기기 권한을 허용하면 시간 알림에 정확한 예약을 사용합니다. 미허용 상태에서도 예약할 수 있지만 Android가 전달을 늦출 수 있습니다. 이 권한은 기기별 설정이며 Plugin의 notifications 권한과 Android 알림 표시 권한도 필요합니다. Plugin은 권한을 자동 승인하지 않고 필요한 설정을 안내합니다.

scheduled는 예약 접수를 뜻합니다. 시스템 제한, 앱 강제 중지, 이후의 네트워크·AI 처리까지 포함해 초 단위 전달을 보장한다고 표시하지 않습니다.

알림당 action은 최대 4개이며 check, capability, snooze, open_plugin, reply를 지원합니다. check/custom/reply는 현재 Instance에 선언된 Tool·Skill capability만 실행하고, 클릭 순간 enabled, generation, permission, Connection을 다시 검사합니다. reply text는 Host가 제한된 argument로만 넣습니다. event token과 action ID로 중복 클릭을 제거하고 성공한 event만 ACK합니다. capability가 Storage를 변경하면 같은 storage revision 신호로 열린 UI를 갱신합니다.

progress:

json
{
  "current": 3,
  "max": 10,
  "indeterminate": false
}

max는 11,000,000이고 current는 0max입니다. 진행 알림은 실제 작업 상태와 일치해야 하며 완료된 뒤 ongoing 상태로 남기지 않습니다.

Durable delivery

Host는 pending action을 lease한 뒤 플랫폼 gateway에 전달하고 결과를 ACK합니다. 앱이 중단되어도 lease가 만료되면 재전달할 수 있으므로 key를 안정적인 중복 제거 키로 만듭니다. 권한 철회, Instance disable/delete, package generation 변경은 해당 owner의 pending action을 폐기합니다.

알림 gateway는 Android에만 있습니다. 지원되지 않는 환경에서 알림 실패를 원본 데이터 저장 성공으로 위장하지 않되, 알림 하나 때문에 읽기 화면 전체를 깨뜨리지 않습니다.

Background

Background capability는 background 권한과 15~10,080분의 interval_minutes가 필요합니다. Host는 enabled, granted permission, generation, 연결 상태를 확인한 뒤 실행합니다. 앱이 꺼져 있을 때 정확한 시각 실행을 보장하는 cron으로 설명하지 않습니다. 사용자에게 주기, 마지막 실행, 오류, 끄기 동작을 settings에서 제공합니다.

SDK 1.7.13의 알림 표시 정책

기존 알림과 예약은 기본적으로 기존 방식을 유지합니다. 새 알림의 host action에 delivery_policy: "contextual"을 지정하거나 사용자가 플러그인 상세의 알림 표시에서 종류별 설정을 활성화하면 아래 기본값을 적용합니다.

category30일 알림함Android
general보관표시하지 않음
reminder보관앱 밖에서만 표시
progress보관하지 않음앱 밖에서 무음, 같은 id/key 갱신
status보관하지 않음앱 밖에서만 표시

사용자는 각 종류의 보관과 Android 표시를 변경할 수 있습니다. OS 권한·채널 차단은 항상 우선합니다. 자동 실행은 OS 권한 팝업을 띄우지 않습니다. 권한 요청은 사용자가 알림 설정을 저장할 때 수행합니다. 알림함은 기존 Morit 동기화·읽음·만료 경로를 사용하며 앱이 같은 알림을 다시 받더라도 중복 등록하지 않습니다. 예약 알림의 30일 보관은 예정 시각부터 계산합니다. AI 채팅 완료 알림의 기존 정책은 바꾸지 않습니다.

id와 key는 설치 인스턴스 내에서 안정적으로 유지하세요. key의 상한은 240자입니다. 체크·답장·열기·다시 알림 버튼은 기존 규격을 유지합니다. _delivery는 호스트가 생성하는 내부 필드이므로 플러그인 결과에 직접 넣지 않습니다. 종류별 사용자 설정 _notification_policy도 플러그인이 변경하지 않습니다.

정책 동기화와 예약 수명

SDK 1.7.14 Host는 최초 진입·앱 복귀·전경 30초 조회에서 최신 설치 목록과 알림 설정을 Android에 먼저 반영한 후 대기 중 작업을 실행합니다. 정책을 기본값으로 되돌린 경우도 반영합니다. 서버 목록에서 제거되거나 비활성화되거나 알림 권한이 철회된 설치의 네이티브 예약은 취소됩니다. 목록 조회가 실패하면 빈 목록으로 간주하여 예약을 지우지 않습니다.

기존 미래 예약의 push 설정을 never로 바꿔도 예약 정보는 유지합니다. 실제 전달 시 최신 정책을 읽으므로 예정 시간 전에 다시 허용하면 해당 예약을 사용할 수 있습니다. 이미 전달되었거나 취소된 이벤트를 재발행하지 않습니다. 다른 기기에서 바꾼 설정은 해당 기기가 서버에 다시 연결되어 동기화할 때 적용됩니다. 오프라인 기기에 원격 변경을 즉시 적용한다고 보장하지 않습니다. 이미 저장된 알림함 기록은 소급 삭제하지 않습니다.

예약과 알림 버튼은 저장된 이벤트 토큰으로 대조합니다. 취소·재예약 전의 이벤트나 오래된 버튼은 무시하며, 버튼 동작은 intent의 임의 payload가 아니라 현재 저장된 action을 사용합니다.