Cloudflare Workers上で動作するRust/workers-rs版APIです。D1、Accounts Service Binding、Developer CA Service Bindingを使用し、アプリ本体は保存しません。
App
├─ Build GitHub Releases上の固定MPKGと機械検証結果
├─ Submission Buildとストア情報・申告・非公開審査情報の組
├─ Review 管理者による変更不能な判断履歴
└─ Availability available / developer_unpublished / removed
Build登録だけではApp審査へ提出されません。MPKG Reviewerによる機械検証がvalidになったBuildを選び、SubmissionのDraftを作成し、確認後に提出します。
POST /v1/developer/apps/{package_id}/releases
Authorization: Bearer <Accounts tokenまたはConsole delegation token>
X-Developer-ID: <32桁小文字UUIDv7 Developer ID>
Content-Type: application/json
{
"version": "1.2.0",
"repository": "example/texteditor",
"release_tag": "v1.2.0",
"asset": "texteditor-1.2.0-x86_64.mpkg",
"certificate_id": "<Developer Certificate ID>",
"changelog": "変更内容"
}DeveloperCAがtokenからAccountとactive・verified Developer Memberを確定し、roleがowner/admin/developerの場合だけ許可します。AccountsはそのAccountの保存済みGitHub grantでpush/maintain/admin権限、公開済み固定tag、完全一致.mpkg assetを確認します。viewer、request内Account ID、latestは拒否します。
Developer CAのstatusが有効で内部Developer IDと一致するときだけ、serial、Subject/Issuer key identity、Certificate Developer ID、発行経路をBuildへ固定します。Reviewer reportはこれらすべてと一致しなければ受理しません。report受理時とSubmission承認時にもstatusを再確認します。
1 Appに割り当てられるcurrent Certificateは1つです。現在のCertificateがDeveloperCAでrevokedになった場合だけ、PATCH /v1/developer/apps/{bundle_id}/certificateで新しいactive Certificateへ置換できます。過去BuildのCertificate記録は削除しません。
Package IDはorg.mochios.*へ限定しません。com.example.paint、io.github.user.tool、dev.tas0.volumeのような2 segment以上の小文字reverse-domain形式を共有Certificate crateで検証します。
Draft
↓ 開発者が提出
Submitted
↓ 管理者が審査開始
In Review
├─ Approved
├─ Changes Required 新しいSubmissionで再提出
├─ More Information Required 同じSubmissionへ回答してIn Reviewへ戻る
└─ Rejected
Approved時にBuildの機械検証とDeveloper Certificateを再確認します。公開済みVersionと同じVersionは新規公開できませんが、Changes Requiredへの修正は公開前なら同じVersionで再提出できます。Developer UnpublishedまたはRemovedからの再公開はre_review Submissionが必要です。
ストア情報は承認済みSubmissionを公開スナップショットとして読み出します。Developer Consoleで次のDraft用情報を編集しても、承認されるまで公開中の表示は変わりません。公開クライアントは固定SHA-256とdownload URLを取得し、GitHub Releasesから直接MPKGを取得します。
mochiOS IDのactive sessionをBearer tokenとして使い、初回取得時に次を呼び出します。
POST /v1/apps/{bundle_id}/acquisitions
Authorization: Bearer <mochiOS ID session token>取得履歴はapp_acquisitionsへappend-onlyで保存します。AvailableなAppだけ新規取得できます。Developer UnpublishedまたはRemovedになった後は新規取得を拒否し、公開中に取得済みだった同じAccountだけGET /v1/apps/{bundle_id}/downloadで再ダウンロードできます。Packageのセキュリティ停止中は取得済みでもダウンロードできません。
公開状態とRemoved理由はGET /v1/apps/{bundle_id}/statusで取得できます。Developerが自ら非公開にした理由は公開しません。
常駐Reviewerは専用tokenで次のendpointを呼び出します。
POST /v1/reviewer/releases/claim
X-Reviewer-Token: <REVIEWER_TOKEN>未検証Releaseがある場合は、作成日時が最も古い1件へ10分間の一意なvalidation attempt leaseを設定して200で返します。Queueが空、または全対象が別Runnerの有効なlease中の場合は204 No Contentです。取得とlease設定は単一SQLで実行されるため、複数Runner間で同じReleaseをclaimしません。
Runnerは返されたvalidation_attempt_idを成功・失敗reportへ含めます。処理中にRunnerが停止した場合はlease期限後に再取得されます。APIのREVIEWER_TOKENとRunnerのAPPSTORE_REVIEWER_TOKENは同じ値を設定します。
Build検証、Submission判断、追加情報、Appeal、公開停止・削除、Package緊急停止の通知は、append-onlyのaudit_logsから生成します。通知本文を別テーブルへ複製せず、既読状態だけをnotification_readsへAccount単位で保存します。
GET /v1/developer/notifications
POST /v1/developer/notifications/{notification_id}/read
POST /v1/developer/notifications/read-all
GET /v1/developer/apps/{bundle_id}/history
GET /v1/admin/notifications
POST /v1/admin/notifications/{notification_id}/read
POST /v1/admin/notifications/read-all
GET /v1/admin/releases/{release_id}/history
Developer向けAPIは認証中のDeveloperに属するRelease/Packageだけを返し、運営者向けAPIはADMIN_TOKENと管理Account IDを要求します。既読状態はDeveloper単位ではなくAccount単位なので、同じDeveloperの各メンバーが個別に管理できます。
download_failedとreviewer_internal_errorは運用障害として分類し、開発者へ再提出を要求しません。Package、署名、Certificate、GitHub assetの不整合は開発者の対応が必要な検証結果として表示します。
cd api
cargo test --all-targets
cargo clippy --all-targets -- -D warnings
npx wrangler d1 migrations apply mochios-app-store --local
npx wrangler devnpx wrangler secret put APPSTORE_SERVICE_TOKEN
npx wrangler secret put ADMIN_TOKEN
npx wrangler secret put REVIEWER_TOKEN
npx wrangler d1 migrations apply mochios-app-store --remote
npx wrangler deployAPPSTORE_SERVICE_TOKENはAccounts内部API用、ADMIN_TOKENはConsole審査BFF用、REVIEWER_TOKENはMPKG Reviewer専用です。Developer秘密鍵、Offline Root秘密鍵、Online Intermediate秘密鍵はAppStoreへ設定しません。
公開済みパッケージは管理APIから一時停止/再開できます。停止中はストア一覧、詳細、Release一覧、ダウンロードから除外され、新しいReleaseも登録できません。Releaseの失効とは別の可逆なインシデント対応です。
6時間ごとのscheduled integrity checkは公開ReleaseのDeveloperCA statusとGitHub repository/Release/Asset identityを再確認します。不整合や到達不能はfail closedで新規downloadを停止します。管理APIから即時整合性確認と再検証要求も行えます。