核心功能: - ✅ Categories/Series双视图管理(category_view.rs + import_markdown.rs) - ✅ FUSE Multi-Volume支持(tree_type参数) - ✅ SSH/SFTP/SCP/rsync协议完整实现(4042行) - ✅ NFS/SMB Module Phase 1-3完成 - ✅ Archive Module Phase 1-4完成(2916行) - ✅ Download Center API完整实现 - ✅ S3兼容API实现(560行) Git配置修正: - ✅ 删除错误origin(gitea.momentry.ddns.net) - ✅ 删除m5max128(指向机器名) - ✅ 设置origin = m5max128gitea.momentry.ddns.net/admin/markbase - ✅ 设置m4minigitea = m4minigitea.momentry.ddns.net/warren/markbase 数据清理: - ✅ 删除38个临时SQLite(保留accusys.sqlite、demo.sqlite) - ✅ 删除.bak、test_*.bin、调试脚本等临时文件 - ✅ 删除临时目录(build/、download files/、raid_test/等) - ✅ 更新.gitignore排除临时文件 架构优化: - 52个文件修改,2434行新增,4739行删除 - Workspace成员整合(16个crate) - 数据库状态:accusys.sqlite保留(主demo测试) 远程同步: - ✅ 准备推送到m5max128gitea(远程Gitea) - ✅ 准备推送到m4minigitea(本地Gitea)
612 lines
15 KiB
Markdown
612 lines
15 KiB
Markdown
# MarkBaseFS System Extension Installer 实施方案
|
||
|
||
**日期:** 2026-05-24
|
||
**状态:** 阶段9暂停,待重新规划
|
||
**问题:** App Bundle结构不完整导致启动失败(错误163)
|
||
|
||
---
|
||
|
||
## 实施进度总结
|
||
|
||
### 已完成 ✅
|
||
|
||
1. **xcode-select配置**
|
||
- 配置成功: `/Applications/Xcode.app/Contents/Developer`(Xcode 26.5)
|
||
- 更新时间: 2026-05-24(已从Volume 1的Xcode 16.2更新)
|
||
|
||
2. **App Store Connect API Key创建**
|
||
- Key ID: `94FCMLS254`
|
||
- Issuer ID: `69a6de72-d392-47e3-e053-5b8c7c11a4d1`
|
||
- Private Key: `~/.appstoreconnect/AuthKey_94FCMLS254.p8`
|
||
|
||
3. **Notarization流程验证**
|
||
- Submission ID: `155b81b3-6f37-43c8-bcb7-75e3dd3ef3d2`
|
||
- 状态: Accepted ✅
|
||
- 验证: `source=Notarized Developer ID`
|
||
|
||
4. **Staple公证结果**
|
||
- 执行成功: `xcrun stapler staple`
|
||
- 验证通过: Gatekeeper accepted
|
||
|
||
---
|
||
|
||
### 失败项 ❌
|
||
|
||
1. **App启动失败(错误163)**
|
||
- 原因: App Bundle缺少必要的资源文件
|
||
- Resources目录为空(缺少Assets.xcassets等)
|
||
|
||
2. **使用VPN模板编译失败**
|
||
- getlantern/systemextensiondemo是VPN项目(不适用)
|
||
- 缺少provisioning profile和XCFramework
|
||
|
||
---
|
||
|
||
## 关键发现
|
||
|
||
### Notarization完整流程(已验证成功)
|
||
|
||
```bash
|
||
# 1. 创建API Key(App Store Connect网页操作)
|
||
# 2. 配置API Key文件
|
||
mkdir -p ~/.appstoreconnect
|
||
mv ~/Downloads/AuthKey_*.p8 ~/.appstoreconnect/
|
||
|
||
# 3. 创建配置文件
|
||
cat > ~/.appstoreconnect/api_key.json << 'EOF'
|
||
{
|
||
"key_id": "94FCMLS254",
|
||
"issuer_id": "69a6de72-d392-47e3-e053-5b8c7c11a4d1",
|
||
"key_filepath": "~/.appstoreconnect/AuthKey_94FCMLS254.p8"
|
||
}
|
||
EOF
|
||
|
||
# 4. 打包App
|
||
zip -r MarkBaseInstaller.zip MarkBaseInstaller.app
|
||
|
||
# 5. 提交Notarization
|
||
xcrun notarytool submit MarkBaseInstaller.zip \
|
||
--key-id 94FCMLS254 \
|
||
--issuer 69a6de72-d392-47e3-e053-5b8c7c11a4d1 \
|
||
--key ~/.appstoreconnect/AuthKey_94FCMLS254.p8 \
|
||
--wait
|
||
|
||
# 6. Staple公证结果
|
||
xcrun stapler staple MarkBaseInstaller.app
|
||
|
||
# 7. 验证
|
||
spctl -a -t exec -vv MarkBaseInstaller.app
|
||
```
|
||
|
||
### 错误163根本原因
|
||
|
||
**结论:** App Bundle结构不完整
|
||
|
||
**缺失文件:**
|
||
- Assets.xcassets(App图标等资源)
|
||
- MainMenu.xib或Storyboard(GUI配置)
|
||
- 正确的NSApplication初始化代码
|
||
|
||
---
|
||
|
||
## 解决方案对比
|
||
|
||
### 方案A: 使用Xcode GUI创建项目(推荐)
|
||
|
||
**优势:**
|
||
- ✅ 业界标准流程
|
||
- ✅ 自动生成完整App Bundle结构
|
||
- ✅ 自动处理签名和entitlements
|
||
- ✅ 内置System Extension capability
|
||
- ✅ 可直接Archive → Notarize → Staple
|
||
|
||
**步骤:**
|
||
|
||
#### 1. 创建Xcode项目(5分钟)
|
||
|
||
```
|
||
打开Xcode
|
||
→ File → New → Project
|
||
→ macOS → App
|
||
→ 配置:
|
||
- Product Name: MarkBaseInstaller
|
||
- Team: K3TDMD9Y6B
|
||
- Organization Identifier: com.momentry.markbase
|
||
- Bundle ID: com.momentry.markbase.installer(自动生成)
|
||
- Language: Swift
|
||
- Interface: SwiftUI(推荐)或Storyboard
|
||
```
|
||
|
||
#### 2. 配置System Extension Capability(2分钟)
|
||
|
||
```
|
||
Target → Signing & Capabilities
|
||
→ + Capability → System Extension
|
||
→ 自动添加entitlements:
|
||
- com.apple.developer.system-extension.install = true
|
||
```
|
||
|
||
#### 3. 修改Bundle ID(可选,若需要)
|
||
|
||
```
|
||
Target → General
|
||
→ Bundle Identifier: com.momentry.markbase.installer
|
||
```
|
||
|
||
#### 4. 复制Swift代码(3分钟)
|
||
|
||
**AppDelegate.swift(若使用Storyboard):**
|
||
|
||
```swift
|
||
import Cocoa
|
||
import SystemExtensions
|
||
|
||
class AppDelegate: NSObject, NSApplicationDelegate {
|
||
var window: NSWindow!
|
||
var statusLabel: NSTextField!
|
||
var installButton: NSButton!
|
||
|
||
func applicationDidFinishLaunching(_ aNotification: Notification) {
|
||
createWindow()
|
||
setupUI()
|
||
}
|
||
|
||
func createWindow() {
|
||
window = NSWindow(
|
||
contentRect: NSRect(x: 0, y: 0, width: 480, height: 300),
|
||
styleMask: [.titled, .closable, .miniaturizable],
|
||
backing: .buffered,
|
||
defer: false
|
||
)
|
||
window.title = "MarkBase Installer"
|
||
window.center()
|
||
window.makeKeyAndOrderFront(nil)
|
||
}
|
||
|
||
func setupUI() {
|
||
let contentView = window.contentView!
|
||
|
||
statusLabel = NSTextField(labelWithString: "Ready to install MarkBaseFS System Extension")
|
||
statusLabel.alignment = .center
|
||
contentView.addSubview(statusLabel)
|
||
|
||
installButton = NSButton(title: "Install System Extension", target: self, action: #selector(installExtension(_:)))
|
||
contentView.addSubview(installButton)
|
||
|
||
// Layout constraints...
|
||
}
|
||
|
||
@objc func installExtension(_ sender: NSButton) {
|
||
let request = OSSystemExtensionRequest.activationRequest(
|
||
forExtensionWithIdentifier: "com.momentry.markbase.fskit",
|
||
queue: .main
|
||
)
|
||
request.delegate = self
|
||
OSSystemExtensionManager.shared.submitRequest(request)
|
||
}
|
||
}
|
||
|
||
extension AppDelegate: OSSystemExtensionRequestDelegate {
|
||
func request(_ request: OSSystemExtensionRequest, didFinishWithResult result: OSSystemExtensionRequest.Result) {
|
||
// 处理成功
|
||
}
|
||
|
||
func request(_ request: OSSystemExtensionRequest, didFailWithError error: Error) {
|
||
// 处理失败
|
||
}
|
||
|
||
func requestNeedsUserApproval(_ request: OSSystemExtensionRequest) {
|
||
// 提示用户批准
|
||
}
|
||
|
||
func request(_ request: OSSystemExtensionRequest, actionForReplacingExtension existing: OSSystemExtensionProperties, withExtension ext: OSSystemExtensionProperties) -> OSSystemExtensionReplacementAction {
|
||
return .replace
|
||
}
|
||
}
|
||
```
|
||
|
||
**ContentView.swift(若使用SwiftUI):**
|
||
|
||
```swift
|
||
import SwiftUI
|
||
import SystemExtensions
|
||
|
||
struct ContentView: View {
|
||
@State private var statusMessage = "Ready to install MarkBaseFS System Extension"
|
||
@State private var isInstalling = false
|
||
|
||
var body: some View {
|
||
VStack(spacing: 20) {
|
||
Text(statusMessage)
|
||
.font(.headline)
|
||
.multilineTextAlignment(.center)
|
||
|
||
Button(action: installExtension) {
|
||
if isInstalling {
|
||
ProgressView()
|
||
.scaleEffect(0.8)
|
||
} else {
|
||
Text("Install System Extension")
|
||
}
|
||
}
|
||
.disabled(isInstalling)
|
||
.buttonStyle(.borderedProminent)
|
||
}
|
||
.padding()
|
||
.frame(width: 480, height: 300)
|
||
}
|
||
|
||
func installExtension() {
|
||
isInstalling = true
|
||
statusMessage = "Requesting installation..."
|
||
|
||
let request = OSSystemExtensionRequest.activationRequest(
|
||
forExtensionWithIdentifier: "com.momentry.markbase.fskit",
|
||
queue: .main
|
||
)
|
||
// Delegate implementation...
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 5. Build → Archive → Notarize(10分钟)
|
||
|
||
```bash
|
||
# Build
|
||
xcodebuild -project MarkBaseInstaller.xcodeproj \
|
||
-scheme MarkBaseInstaller \
|
||
-configuration Release \
|
||
clean build
|
||
|
||
# Archive
|
||
xcodebuild -project MarkBaseInstaller.xcodeproj \
|
||
-scheme MarkBaseInstaller \
|
||
-archivePath build/MarkBaseInstaller.xcarchive \
|
||
archive
|
||
|
||
# Export
|
||
xcodebuild -exportArchive \
|
||
-archivePath build/MarkBaseInstaller.xcarchive \
|
||
-exportPath build/export \
|
||
-exportOptionsPlist ExportOptions.plist
|
||
|
||
# ExportOptions.plist内容:
|
||
<?xml version="1.0" encoding="UTF-8"?>
|
||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||
<plist version="1.0">
|
||
<dict>
|
||
<key>method</key>
|
||
<string>developer-id</string>
|
||
<key>teamID</key>
|
||
<string>K3TDMD9Y6B</string>
|
||
</dict>
|
||
</plist>
|
||
|
||
# Notarize
|
||
xcrun notarytool submit build/export/MarkBaseInstaller.zip \
|
||
--key-id 94FCMLS254 \
|
||
--issuer 69a6de72-d392-47e3-e053-5b8c7c11a4d1 \
|
||
--key ~/.appstoreconnect/AuthKey_94FCMLS254.p8 \
|
||
--wait
|
||
|
||
# Staple
|
||
xcrun stapler staple build/export/MarkBaseInstaller.app
|
||
|
||
# 验证
|
||
spctl -a -t exec -vv build/export/MarkBaseInstaller.app
|
||
```
|
||
|
||
#### 6. 测试安装(2分钟)
|
||
|
||
```bash
|
||
# 启动App
|
||
open build/export/MarkBaseInstaller.app
|
||
|
||
# 点击Install按钮 → 用户批准
|
||
|
||
# 验证安装
|
||
systemextensionsctl list
|
||
# 预期输出:
|
||
# com.momentry.markbase.fskit (version 1.0) [activated]
|
||
```
|
||
|
||
**预估总时间:** 20-25分钟
|
||
|
||
---
|
||
|
||
### 方案B: 修复现有MarkBaseInstaller.app(困难)
|
||
|
||
**需要手动添加:**
|
||
|
||
1. **Assets.xcassets**
|
||
- 创建App图标资源
|
||
- 配置AppIcon.appiconset
|
||
|
||
2. **MainMenu.xib或Storyboard**
|
||
- 创建GUI界面
|
||
- 配置NSApplication初始化
|
||
|
||
3. **修复Info.plist**
|
||
- 添加NSMainNibFile配置
|
||
|
||
**预估时间:** 30-40分钟
|
||
|
||
**风险:** 高(可能仍遇到其他结构性问题)
|
||
|
||
---
|
||
|
||
### 方案C: 使用命令行创建最小App Bundle(实验性)
|
||
|
||
**步骤:**
|
||
|
||
```bash
|
||
# 1. 创建目录结构
|
||
mkdir -p MarkBaseInstaller_New.app/Contents/{MacOS,Resources}
|
||
|
||
# 2. 编译Swift代码
|
||
swiftc -o MarkBaseInstaller_New.app/Contents/MacOS/MarkBaseInstaller \
|
||
-target arm64-apple-macos14 \
|
||
-framework Cocoa \
|
||
-framework SystemExtensions \
|
||
AppDelegate.swift
|
||
|
||
# 3. 创建Info.plist
|
||
cat > MarkBaseInstaller_New.app/Contents/Info.plist << 'EOF'
|
||
<?xml version="1.0" encoding="UTF-8"?>
|
||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||
<plist version="1.0">
|
||
<dict>
|
||
<key>CFBundleIdentifier</key>
|
||
<string>com.momentry.markbase.installer</string>
|
||
<key>CFBundleName</key>
|
||
<string>MarkBase Installer</string>
|
||
<key>CFBundleExecutable</key>
|
||
<string>MarkBaseInstaller</string>
|
||
<key>CFBundlePackageType</key>
|
||
<string>APPL</string>
|
||
<key>LSMinimumSystemVersion</key>
|
||
<string>14.0</string>
|
||
<key>NSPrincipalClass</key>
|
||
<string>NSApplication</string>
|
||
</dict>
|
||
</plist>
|
||
EOF
|
||
|
||
# 4. 创建PkgInfo
|
||
echo -n "APPL????" > MarkBaseInstaller_New.app/Contents/PkgInfo
|
||
|
||
# 5. 签名
|
||
codesign --force --sign "Developer ID Application: Accusys,Inc (K3TDMD9Y6B)" \
|
||
--entitlements entitlements.plist \
|
||
--deep --options runtime \
|
||
MarkBaseInstaller_New.app
|
||
|
||
# 6. Notarize + Staple(流程同上)
|
||
```
|
||
|
||
**预估时间:** 15-20分钟
|
||
|
||
**风险:** 中(可能仍缺少GUI资源)
|
||
|
||
---
|
||
|
||
## 推荐选择
|
||
|
||
**推荐: 方案A(使用Xcode GUI)**
|
||
|
||
**理由:**
|
||
1. 最可靠(业界标准流程)
|
||
2. 最快速(自动处理所有配置)
|
||
3. 最安全(避免结构性问题)
|
||
4. 可维护(未来修改方便)
|
||
|
||
---
|
||
|
||
## API Key配置信息(已创建,可复用)
|
||
|
||
**Key ID:** `94FCMLS254`
|
||
**Issuer ID:** `69a6de72-d392-47e3-e053-5b8c7c11a4d1`
|
||
**Private Key路径:** `~/.appstoreconnect/AuthKey_94FCMLS254.p8`
|
||
|
||
**配置文件路径:** `~/.appstoreconnect/api_key.json`
|
||
|
||
---
|
||
|
||
## 开发者证书信息
|
||
|
||
**证书:** `Developer ID Application: Accusys,Inc (K3TDMD9Y6B)`
|
||
**Team ID:** `K3TDMD9Y6B`
|
||
**证书ID:** `EC458E4414308FDFE98616D2C0D90B684B5BD973`
|
||
|
||
---
|
||
|
||
## Xcode配置信息(已更新)
|
||
|
||
**Xcode路径:** `/Applications/Xcode.app`(主系统盘)
|
||
**Xcode版本:** 26.5 (Build 17F42)
|
||
**xcode-select:** 已配置到Xcode 26.5
|
||
**xcrun版本:** 72
|
||
**Swift版本:** 6.3.2
|
||
**Clang版本:** 21.0.0
|
||
**Target平台:** arm64-apple-macosx26.0
|
||
|
||
**更新说明:**
|
||
- 从Volume 1的Xcode 16.2更新到主系统盘的Xcode 26.5
|
||
- 与macOS 26.5完美匹配
|
||
- 内置最新FSKit支持和System Extension模板
|
||
|
||
---
|
||
|
||
## 磁盘配置信息
|
||
|
||
| 卷宗名称 | 挂载点 | 设备 | 类型 | 大小 |
|
||
|----------|--------|------|------|------|
|
||
| **KX_macOS_2T** | `/` | disk6s1s1 | 启动盘(外部2TB NVMe) | 1.9TB |
|
||
| **Volume 1** | `/Volumes/Volume 1` | disk2s3 | 内部SSD分区 | 122GB |
|
||
| **Volume 2** | `/Volumes/Volume 2` | disk3s3 | 内部SSD分区 | 122GB |
|
||
|
||
---
|
||
|
||
## 下次实施建议
|
||
|
||
### 开始步骤:
|
||
|
||
1. **打开Xcode GUI**(方案A)
|
||
2. **创建新项目**
|
||
3. **配置System Extension Capability**
|
||
4. **复制Swift代码**
|
||
5. **Build → Archive → Notarize → Staple**
|
||
6. **测试安装**
|
||
|
||
### 预估总时间:
|
||
|
||
- 方案A: 20-25分钟
|
||
- 方案B: 30-40分钟
|
||
- 方案C: 15-20分钟
|
||
|
||
---
|
||
|
||
## 注意事项
|
||
|
||
### ⚠️ API Key已创建,无需重新创建
|
||
|
||
**重要:**
|
||
- API Key配置已完成(Key ID + Issuer ID + Private Key)
|
||
- Private Key只能下载一次,已保存
|
||
- 下次实施时直接使用现有配置
|
||
|
||
### ⚠️ Notarization流程已验证成功
|
||
|
||
**重要:**
|
||
- Notarization流程正确(Submission ID已记录)
|
||
- Staple流程正确(验证通过)
|
||
- 下次实施时无需重新验证流程
|
||
|
||
### ⚠️ 错误163根本原因已明确
|
||
|
||
**重要:**
|
||
- 问题不是Notarization(公证成功)
|
||
- 问题不是签名(签名正确)
|
||
- **问题: App Bundle结构不完整**
|
||
|
||
---
|
||
|
||
## 参考文档
|
||
|
||
### Apple官方文档:
|
||
- System Extensions: https://developer.apple.com/documentation/systemextensions
|
||
- Notarization: https://developer.apple.com/documentation/security/notarizing_macos_software_before_distribution
|
||
|
||
### 开源参考:
|
||
- getlantern/systemextensiondemo(VPN项目,流程参考)
|
||
- knightsc/USBApp(DriverKit项目,结构参考)
|
||
|
||
---
|
||
|
||
## 实施记录详情
|
||
|
||
### Notarization提交记录
|
||
|
||
**Submission ID:** `155b81b3-6f37-43c8-bcb7-75e3dd3ef3d2`
|
||
**提交时间:** 2026-05-24 00:17
|
||
**处理状态:** Accepted ✅
|
||
**处理时间:** 约1分钟
|
||
|
||
**输出日志:**
|
||
```
|
||
Conducting pre-submission checks for MarkBaseInstaller.zip...
|
||
Initiating connection to the Apple notary service...
|
||
Successfully uploaded package
|
||
id: 155b81b3-6f37-43c8-bcb7-75e3dd3ef3d2
|
||
path: /Users/accusys/markbase/build/MarkBaseInstaller.zip
|
||
Waiting for processing to complete...
|
||
Current status: In Progress....Current status: In Progress....Current status: Accepted.....Processing complete!
|
||
id: 155b81b3-6f37-43c8-bcb7-75e3dd3ef3d2
|
||
status: Accepted
|
||
```
|
||
|
||
---
|
||
|
||
### 错误163详细记录
|
||
|
||
**错误代码:** POSIX error 163
|
||
**错误描述:** "Unknown error: 163" / "Launchd job spawn failed"
|
||
**触发场景:** 执行 `open MarkBaseInstaller.app`
|
||
|
||
**诊断过程:**
|
||
|
||
1. **检查二进制文件:** `otool -L`
|
||
- 结果: 链接正确(SystemExtensions.framework存在)
|
||
|
||
2. **检查main函数:** `nm | grep main`
|
||
- 结果: `_main`存在
|
||
|
||
3. **检查签名:** `codesign -dv`
|
||
- 结果: 签名正确(Developer ID Application)
|
||
|
||
4. **检查公证:** `spctl -a -t exec -vv`
|
||
- 结果: 公证正确(Notarized Developer ID)
|
||
|
||
5. **检查Resources目录:** `ls Contents/Resources/`
|
||
- 结果: **空目录** ❌
|
||
|
||
**根本原因:** App Bundle缺少必要的资源文件和GUI初始化配置
|
||
|
||
---
|
||
|
||
## 文件路径记录
|
||
|
||
| 文件类型 | 路径 |
|
||
|----------|------|
|
||
| **API Key配置** | `~/.appstoreconnect/api_key.json` |
|
||
| **Private Key** | `~/.appstoreconnect/AuthKey_94FCMLS254.p8` |
|
||
| **打包文件** | `/Users/accusys/markbase/build/MarkBaseInstaller.zip` |
|
||
| **App Bundle** | `/Users/accusys/markbase/tools/MarkBaseInstaller.app` |
|
||
| **模板项目** | `/Users/accusys/markbase/tools/systemextensiondemo/` |
|
||
| **Xcode路径** | `/Applications/Xcode.app`(Xcode 26.5)|
|
||
| **本实施方案** | `/Users/accusys/markbase/docs/IMPLEMENTATION_PLAN.md` |
|
||
|
||
---
|
||
|
||
---
|
||
|
||
## xcode-select配置记录(更新)
|
||
|
||
**配置时间:** 2026-05-24
|
||
**之前配置:** `/Volumes/Volume 1/Applications/Xcode_16.2.app`(Xcode 16.2)
|
||
**当前配置:** `/Applications/Xcode.app`(Xcode 26.5)
|
||
|
||
**配置命令:**
|
||
```bash
|
||
sudo xcode-select --switch /Applications/Xcode.app
|
||
```
|
||
|
||
**验证结果:**
|
||
```
|
||
xcode-select -p
|
||
/Applications/Xcode.app/Contents/Developer
|
||
|
||
xcodebuild -version
|
||
Xcode 26.5
|
||
Build version 17F42
|
||
|
||
xcrun --version
|
||
xcrun version 72
|
||
|
||
swift --version
|
||
swift-driver version: 1.148.6 Apple Swift version 6.3.2
|
||
Target: arm64-apple-macosx26.0
|
||
```
|
||
|
||
**关键变化:**
|
||
| 项目 | 之前 | 现在 |
|
||
|------|------|------|
|
||
| Xcode版本 | 16.2 | **26.5** ✅ |
|
||
| xcrun版本 | 70 | **72** ✅ |
|
||
| Swift版本 | - | **6.3.2** ✅ |
|
||
| Target | - | **macOS 26.0** ✅ |
|
||
|
||
---
|
||
|
||
**文档生成时间:** 2026-05-24 00:30
|
||
**状态:** 已更新xcode-select配置,待明天继续实施 |