From 307a019d4894c5127a4da6cf5c44c56a2717b3bc Mon Sep 17 00:00:00 2001 From: huangping Date: Fri, 1 May 2026 13:57:46 +0800 Subject: [PATCH] =?UTF-8?q?plan:=20implement=20BitAnswer=201:1=20refactor?= =?UTF-8?q?=20=E2=80=94=2012=20tasks=20across=204=20phases?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Phase 1 (infrastructure, no breaking changes): - Rust: error.rs, session.rs, ffi/bitanswer.rs, ffi/bridge.rs - Rust: refactor lib.rs to session-based handle management - Java: @Deprecate AuthProvider, create 6 capability interfaces - Java: LicenseSession skeleton, NativeBridge 30+ method stubs - Java: CraftLicense new entry point Phase 2-4: core API expansion, advanced features, cleanup --- .../2026-05-01-bitanswer-1to1-refactor.md | 1602 +++++++++++++++++ 1 file changed, 1602 insertions(+) create mode 100644 docs/superpowers/plans/2026-05-01-bitanswer-1to1-refactor.md diff --git a/docs/superpowers/plans/2026-05-01-bitanswer-1to1-refactor.md b/docs/superpowers/plans/2026-05-01-bitanswer-1to1-refactor.md new file mode 100644 index 0000000..a60d243 --- /dev/null +++ b/docs/superpowers/plans/2026-05-01-bitanswer-1to1-refactor.md @@ -0,0 +1,1602 @@ +# BitAnswer 1:1 映射重构 实施计划 + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** 将 craftlabs-authorization-sdk 的 SDK 客户端层从 8 方法 AuthProvider 重构为 BitAnswer C API 的 1:1 原语映射,按 6 个能力接口分层,4 个 Phase 渐进交付。 + +**Architecture:** Java 侧分为 CraftLicense(入口)+ LicenseSession(实现 6 个能力接口:LicenseLifecycle、FeatureManagement、DataItemStore、LicenseInfoQuery、CheckoutManager、LicenseUtility)。Rust 侧新增 ffi/bitanswer.rs(BitAnswer C API FFI 声明)、ffi/bridge.rs(craft_* → Bit_* 桥接)、session.rs(句柄管理)、error.rs(错误码映射)。Phase 1 不破坏现有接口。 + +**Tech Stack:** Rust (cdylib, libloading), Java 17 (Maven multi-module), JNI, BitAnswer C SDK + +**Spec reference:** `docs/superpowers/specs/2026-05-01-bitanswer-1to1-refactor-design.md` + +--- + +## Phase 1 — 基础设施(不破坏现有接口) + +### Task 1: Rust — 创建 error.rs(错误码映射) + +**Files:** +- Create: `native/craft-core/src/error.rs` + +- [ ] **Step 1: 创建 LicenseError 枚举** + +写入 `native/craft-core/src/error.rs`: + +```rust +use crate::CraftResult; + +/// BitAnswer BIT_STATUS 错误码到结构化错误的精简映射。 +/// 完整 200+ 码请参考 bitanswer.h,此处映射文档中明确列出的高频码。 +#[derive(Debug, Clone, PartialEq)] +pub enum LicenseError { + Success, + NetworkError, + WrongHandle, + InvalidParameter, + ApplicationDataError, + LicenseExpired, + LicenseNotFound, + LicenseDisabled, + FeatureNotFound(u32), + FeatureExpired(u32), + FeatureTypeNotMatch(u32), + SnInvalid, + SnNotFound, + SnDisabled, + SnRevoked, + SnExpired, + CapacityExhausted, + ServerBusy, + ServerDown, + Timeout, + Unknown(u32), +} + +impl LicenseError { + /// 将 BitAnswer BIT_STATUS (u32) 映射为 LicenseError + pub fn from_bit_status(status: u32) -> Self { + match status { + 0x0000 => LicenseError::Success, + 0x0101 => LicenseError::NetworkError, + 0x0102 => LicenseError::WrongHandle, + 0x0103 => LicenseError::InvalidParameter, + 0x0105 => LicenseError::ApplicationDataError, + 0x0701 => LicenseError::LicenseExpired, + 0x0114 => LicenseError::LicenseNotFound, + 0x0705 => LicenseError::LicenseDisabled, + 0x0503 => LicenseError::FeatureNotFound(0), + 0x0509 => LicenseError::FeatureExpired(0), + 0x0504 => LicenseError::FeatureTypeNotMatch(0), + 0x011C => LicenseError::SnInvalid, + 0x0706 => LicenseError::SnNotFound, + 0x0705 => LicenseError::SnDisabled, + 0x0123 => LicenseError::SnRevoked, + 0x0701 => LicenseError::SnExpired, + 0x0712 => LicenseError::CapacityExhausted, + 0x0107 => LicenseError::ServerBusy, + 0x0108 => LicenseError::ServerDown, + 0x0141 => LicenseError::Timeout, + _ => LicenseError::Unknown(status), + } + } + + pub fn message(&self) -> &'static str { + match self { + LicenseError::Success => "ok", + LicenseError::NetworkError => "network error", + LicenseError::WrongHandle => "wrong handle", + LicenseError::InvalidParameter => "invalid parameter", + LicenseError::ApplicationDataError => "application data error", + LicenseError::LicenseExpired => "license expired", + LicenseError::LicenseNotFound => "license not found", + LicenseError::LicenseDisabled => "license disabled", + LicenseError::FeatureNotFound(_) => "feature not found", + LicenseError::FeatureExpired(_) => "feature expired", + LicenseError::FeatureTypeNotMatch(_) => "feature type not match", + LicenseError::SnInvalid => "sn invalid", + LicenseError::SnNotFound => "sn not found", + LicenseError::SnDisabled => "sn disabled", + LicenseError::SnRevoked => "sn revoked", + LicenseError::SnExpired => "sn expired", + LicenseError::CapacityExhausted => "capacity exhausted", + LicenseError::ServerBusy => "server busy", + LicenseError::ServerDown => "server down", + LicenseError::Timeout => "timeout", + LicenseError::Unknown(_) => "unknown error", + } + } + + pub fn is_success(&self) -> bool { + matches!(self, LicenseError::Success) + } +} + +/// 将 LicenseError 转为 C ABI 兼容的 CraftResult +pub fn to_craft_result(error: LicenseError) -> CraftResult { + if error.is_success() { + crate::ok_result() + } else { + // 使用堆分配的消息指针(调用方通过 craft_free_license_info 类似方式释放) + let msg = format!("{}\0", error.message()); + let msg_ptr = msg.as_ptr() as *const std::os::raw::c_char; + std::mem::forget(msg); // 内存由调用方管理 + CraftResult { + success: 0, + message: msg_ptr, + } + } +} +``` + +- [ ] **Step 2: 在 lib.rs 中注册 error 模块** + +在 `native/craft-core/src/lib.rs` 的 `mod` 声明区域添加: + +```rust +mod error; +``` + +- [ ] **Step 3: 编译验证** + +```bash +cargo build --manifest-path native/craft-core/Cargo.toml +``` + +Expected: 编译成功,无错误。 + +- [ ] **Step 4: 提交** + +```bash +git add native/craft-core/src/error.rs native/craft-core/src/lib.rs +git commit -m "feat(native): add LicenseError enum with BitAnswer error code mapping" +``` + +--- + +### Task 2: Rust — 创建 session.rs(会话管理) + +**Files:** +- Create: `native/craft-core/src/session.rs` + +- [ ] **Step 1: 创建 SessionState 和全局会话表** + +写入 `native/craft-core/src/session.rs`: + +```rust +use std::collections::HashMap; +use std::sync::Mutex; +use once_cell::sync::Lazy; + +/// 单个会话的运行时状态,映射 Java long (session_id) ↔ BitAnswer BIT_HANDLE +pub struct SessionState { + /// 存储 initialize 时传入的配置 JSON(用于后续 Bit_Login/UpdateOnline) + pub config_json: String, + /// Bit_Login / Bit_LoginEx 成功后返回的句柄 + pub bit_handle: Option, + /// 产品识别码(来自 AuthConfig.bitanswer.applicationData) + pub application_data: Vec, + /// 是否已完成 login + pub logged_in: bool, +} + +/// 全局会话表:session_id (i64) → SessionState +pub static SESSIONS: Lazy>> = + Lazy::new(|| Mutex::new(HashMap::new())); + +static NEXT_SESSION_ID: Lazy> = Lazy::new(|| Mutex::new(1)); + +/// 分配一个新的 session_id 并注册 SessionState +pub fn register_session(config_json: String, application_data: Vec) -> i64 { + let mut next_id = NEXT_SESSION_ID.lock().unwrap(); + let id = *next_id; + *next_id += 1; + let mut sessions = SESSIONS.lock().unwrap(); + sessions.insert(id, SessionState { + config_json, + bit_handle: None, + application_data, + logged_in: false, + }); + id +} + +/// 获取 session 的可变引用 +pub fn with_session(session_id: i64, f: F) -> Option +where + F: FnOnce(&mut SessionState) -> R, +{ + let mut sessions = SESSIONS.lock().unwrap(); + sessions.get_mut(&session_id).map(f) +} + +/// 移除 session +pub fn remove_session(session_id: i64) { + let mut sessions = SESSIONS.lock().unwrap(); + sessions.remove(&session_id); +} +``` + +- [ ] **Step 2: 添加 once_cell 依赖** + +在 `native/craft-core/Cargo.toml` 的 `[dependencies]` 区域添加: + +```toml +once_cell = "1" +``` + +- [ ] **Step 3: 在 lib.rs 中注册 session 模块** + +在 `native/craft-core/src/lib.rs` 的 `mod` 声明区域添加: + +```rust +mod session; +``` + +- [ ] **Step 4: 编译验证** + +```bash +cargo build --manifest-path native/craft-core/Cargo.toml +``` + +Expected: 编译成功。 + +- [ ] **Step 5: 提交** + +```bash +git add native/craft-core/src/session.rs native/craft-core/src/lib.rs native/craft-core/Cargo.toml +git commit -m "feat(native): add session management with global handle registry" +``` + +--- + +### Task 3: Rust — 创建 ffi/bitanswer.rs(BitAnswer C API FFI 声明) + +**Files:** +- Create: `native/craft-core/src/ffi/mod.rs` +- Create: `native/craft-core/src/ffi/bitanswer.rs` + +- [ ] **Step 1: 创建 ffi/mod.rs** + +写入 `native/craft-core/src/ffi/mod.rs`: + +```rust +pub mod bitanswer; +``` + +- [ ] **Step 2: 创建 bitanswer.rs — BitAnswer C API 的 Rust extern 声明** + +写入 `native/craft-core/src/ffi/bitanswer.rs`: + +```rust +// BitAnswer C API 的 Rust FFI 声明 +// 类型定义与 bitanswer.h 对齐 + +pub type BitHandle = *mut std::ffi::c_void; +pub type BitStatus = u32; +pub type BitUint32 = u32; + +// 登录模式常量 +pub const BIT_MODE_LOCAL: u32 = 0x01; +pub const BIT_MODE_REMOTE: u32 = 0x02; +pub const BIT_MODE_AUTO: u32 = 0x03; + +// 绑定类型 +pub const BINDING_EXISTING: u32 = 0; +pub const BINDING_LOCAL: u32 = 1; + +// Session 信息类型 +pub const XML_TYPE_SN_INFO: u32 = 3; + +// Info 类型 +pub const BIT_INFO_SN: u32 = 1; +pub const BIT_INFO_SN_FEATURE: u32 = 2; + +// 特征查询模式 +pub const BIT_QUERY_DEFAULT: u32 = 0x00; +pub const BIT_QUERY_AVAILABLE: u32 = 0x01; + +// SetAttr 类型 +pub const ATTR_WAIT_TIMEOUT: u32 = 0x2; +pub const ATTR_HB_INTERVAL: u32 = 0x8; + +extern "C" { + /// 登录授权 + pub fn Bit_Login( + sz_url: *const std::os::raw::c_char, + sz_sn: *const std::os::raw::c_char, + p_application_data: *const u8, + p_handle: *mut BitHandle, + mode: BitUint32, + ) -> BitStatus; + + /// 特征登录 + pub fn Bit_LoginEx( + sz_url: *const std::os::raw::c_char, + sz_sn: *const std::os::raw::c_char, + feature_id: BitUint32, + sz_reserved: *const std::os::raw::c_char, + p_application_data: *const u8, + p_handle: *mut BitHandle, + mode: BitUint32, + ) -> BitStatus; + + /// Token 登录 + pub fn Bit_LoginByToken( + sz_url: *const std::os::raw::c_char, + sz_access_token: *const std::os::raw::c_char, + p_application_data: *const u8, + p_handle: *mut BitHandle, + ) -> BitStatus; + + /// 登出 + pub fn Bit_Logout(handle: BitHandle) -> BitStatus; + + /// 在线激活/更新 + pub fn Bit_UpdateOnline( + sz_url: *const std::os::raw::c_char, + sz_sn: *const std::os::raw::c_char, + p_application_data: *const u8, + ) -> BitStatus; + + /// 读取特征值 + pub fn Bit_ReadFeature( + handle: BitHandle, + feature_id: BitUint32, + p_feature_value: *mut BitUint32, + ) -> BitStatus; + + /// 写入特征值 + pub fn Bit_WriteFeature( + handle: BitHandle, + feature_id: BitUint32, + feature_value: BitUint32, + ) -> BitStatus; + + /// 查询特征可用量 + pub fn Bit_QueryFeature( + handle: BitHandle, + feature_id: BitUint32, + p_capacity: *mut BitUint32, + ) -> BitStatus; + + /// 释放特征占用 + pub fn Bit_ReleaseFeature( + handle: BitHandle, + feature_id: BitUint32, + p_capacity: *mut BitUint32, + ) -> BitStatus; + + /// 设置配置项 + pub fn Bit_SetDataItem( + handle: BitHandle, + sz_data_item_name: *const std::os::raw::c_char, + p_data_item_value: *const std::ffi::c_void, + data_item_value_size: BitUint32, + ) -> BitStatus; + + /// 读取配置项 + pub fn Bit_GetDataItem( + handle: BitHandle, + sz_data_item_name: *const std::os::raw::c_char, + p_data_item_value: *mut std::ffi::c_void, + p_data_item_value_size: *mut BitUint32, + ) -> BitStatus; + + /// 删除配置项 + pub fn Bit_RemoveDataItem( + handle: BitHandle, + sz_data_item_name: *const std::os::raw::c_char, + ) -> BitStatus; + + /// 获取配置项数量 + pub fn Bit_GetDataItemNum( + handle: BitHandle, + p_num: *mut BitUint32, + ) -> BitStatus; + + /// 按索引获取配置项名称 + pub fn Bit_GetDataItemName( + handle: BitHandle, + index: BitUint32, + p_data_item_name: *mut std::os::raw::c_char, + p_data_item_name_size: *mut BitUint32, + ) -> BitStatus; + + /// 获取会话信息 + pub fn Bit_GetSessionInfo( + handle: BitHandle, + session_type: BitUint32, + p_session_info: *mut std::os::raw::c_char, + p_session_info_size: *mut BitUint32, + ) -> BitStatus; + + /// 获取授权信息 + pub fn Bit_GetInfo( + sz_sn: *const std::os::raw::c_char, + p_application_data: *const u8, + info_type: BitUint32, + p_info: *mut std::os::raw::c_char, + p_info_size: *mut BitUint32, + ) -> BitStatus; + + /// 浮动迁出 SN + pub fn Bit_CheckOutSn( + sz_url: *const std::os::raw::c_char, + feature_id: BitUint32, + p_application_data: *const u8, + n_duration_days: BitUint32, + ) -> BitStatus; + + /// 浮动归还 + pub fn Bit_CheckIn( + sz_url: *const std::os::raw::c_char, + feature_id: BitUint32, + p_application_data: *const u8, + ) -> BitStatus; + + /// 撤销授权 + pub fn Bit_Revoke( + sz_url: *const std::os::raw::c_char, + sz_sn: *const std::os::raw::c_char, + p_application_data: *const u8, + p_revocation_info: *mut std::os::raw::c_char, + p_revocation_info_size: *mut BitUint32, + ) -> BitStatus; + + /// 删除本机 SN + pub fn Bit_RemoveSn( + sz_sn: *const std::os::raw::c_char, + p_application_data: *const u8, + ) -> BitStatus; + + /// 手动心跳 + pub fn Bit_Heartbeat( + handle: BitHandle, + p_reconnects_num: *mut BitUint32, + ) -> BitStatus; + + /// 设置属性 + pub fn Bit_SetAttr( + handle: BitHandle, + attr_type: BitUint32, + p_value: *const std::ffi::c_void, + ) -> BitStatus; + + /// 获取库版本 + pub fn Bit_GetVersion(p_version: *mut BitUint32) -> BitStatus; +} +``` + +- [ ] **Step 3: 在 lib.rs 中注册 ffi 模块** + +在 `native/craft-core/src/lib.rs` 的 `mod` 声明区域添加: + +```rust +mod ffi; +``` + +- [ ] **Step 4: 编译验证** + +```bash +cargo build --manifest-path native/craft-core/Cargo.toml +``` + +Expected: 编译成功(extern 声明不会被链接检查,但语法正确)。 + +- [ ] **Step 5: 提交** + +```bash +git add native/craft-core/src/ffi/ +git commit -m "feat(native): add BitAnswer C API FFI declarations" +``` + +--- + +### Task 4: Rust — 创建 ffi/bridge.rs(craft_* → Bit_* 桥接) + +**Files:** +- Create: `native/craft-core/src/ffi/bridge.rs` + +- [ ] **Step 1: 创建 bridge.rs — Phase 1 核心桥接函数** + +写入 `native/craft-core/src/ffi/bridge.rs`: + +```rust +use crate::error::{LicenseError, to_craft_result}; +use crate::ffi::bitanswer; +use crate::session; +use crate::CraftResult; +use std::ffi::CString; +use std::os::raw::c_char; + +/// 激活:调用 Bit_UpdateOnline +pub fn bridge_activate(session_id: i64, license_key: &str) -> CraftResult { + let result = session::with_session(session_id, |state| { + // 从配置中解析 URL(简化版:使用固定空 URL → 使用默认服务器) + let url = std::ptr::null(); // NULL 表示使用默认服务器 + let sn = match CString::new(license_key) { + Ok(s) => s, + Err(_) => return LicenseError::InvalidParameter, + }; + let app_data = state.application_data.as_ptr(); + + let status = unsafe { + bitanswer::Bit_UpdateOnline(url, sn.as_ptr(), app_data) + }; + + if status == 0 { + LicenseError::Success + } else { + LicenseError::from_bit_status(status) + } + }); + + match result { + Some(err) => to_craft_result(err), + None => to_craft_result(LicenseError::WrongHandle), + } +} + +/// 登录:调用 Bit_Login +pub fn bridge_login(session_id: i64, sn_str: &str, mode: u32) -> CraftResult { + let result = session::with_session(session_id, |state| { + let url = std::ptr::null(); + let sn = match CString::new(sn_str) { + Ok(s) => s, + Err(_) => return LicenseError::InvalidParameter, + }; + let app_data = state.application_data.as_ptr(); + let mut handle: bitanswer::BitHandle = std::ptr::null_mut(); + + let status = unsafe { + bitanswer::Bit_Login(url, sn.as_ptr(), app_data, &mut handle, mode) + }; + + if status == 0 { + state.bit_handle = Some(handle as usize); + state.logged_in = true; + LicenseError::Success + } else { + LicenseError::from_bit_status(status) + } + }); + + match result { + Some(err) => to_craft_result(err), + None => to_craft_result(LicenseError::WrongHandle), + } +} + +/// 登出:调用 Bit_Logout +pub fn bridge_logout(session_id: i64) -> CraftResult { + let result = session::with_session(session_id, |state| { + let handle = match state.bit_handle { + Some(h) => h as bitanswer::BitHandle, + None => return LicenseError::WrongHandle, + }; + + let status = unsafe { bitanswer::Bit_Logout(handle) }; + state.bit_handle = None; + state.logged_in = false; + + if status == 0 { + LicenseError::Success + } else { + LicenseError::from_bit_status(status) + } + }); + + match result { + Some(err) => to_craft_result(err), + None => to_craft_result(LicenseError::WrongHandle), + } +} + +/// 心跳:调用 Bit_Heartbeat +pub fn bridge_heartbeat(session_id: i64) -> CraftResult { + let result = session::with_session(session_id, |state| { + let handle = match state.bit_handle { + Some(h) => h as bitanswer::BitHandle, + None => return LicenseError::WrongHandle, + }; + + let mut reconnects: u32 = 0; + let status = unsafe { bitanswer::Bit_Heartbeat(handle, &mut reconnects) }; + + if status == 0 { + LicenseError::Success + } else { + LicenseError::from_bit_status(status) + } + }); + + match result { + Some(err) => to_craft_result(err), + None => to_craft_result(LicenseError::WrongHandle), + } +} + +/// 读取特征值:调用 Bit_ReadFeature +pub fn bridge_read_feature(session_id: i64, feature_id: u32) -> i32 { + let result = session::with_session(session_id, |state| { + let handle = match state.bit_handle { + Some(h) => h as bitanswer::BitHandle, + None => return -1i32, + }; + + let mut value: u32 = 0; + let status = unsafe { bitanswer::Bit_ReadFeature(handle, feature_id, &mut value) }; + if status == 0 { value as i32 } else { -1i32 } + }); + + result.unwrap_or(-1) +} + +/// 检查许可:调用 Bit_GetSessionInfo +pub fn bridge_check_license(session_id: i64) -> CraftResult { + let result = session::with_session(session_id, |state| { + let handle = match state.bit_handle { + Some(h) => h as bitanswer::BitHandle, + None => return LicenseError::WrongHandle, + }; + + let mut buf = vec![0u8; 4096]; + let mut size: u32 = 4096; + let status = unsafe { + bitanswer::Bit_GetSessionInfo(handle, bitanswer::XML_TYPE_SN_INFO, buf.as_mut_ptr() as *mut c_char, &mut size) + }; + + if status == 0 { + LicenseError::Success + } else { + LicenseError::from_bit_status(status) + } + }); + + match result { + Some(err) => to_craft_result(err), + None => to_craft_result(LicenseError::WrongHandle), + } +} +``` + +- [ ] **Step 2: 在 ffi/mod.rs 中注册 bridge** + +在 `native/craft-core/src/ffi/mod.rs` 添加: + +```rust +pub mod bridge; +``` + +- [ ] **Step 3: 编译验证** + +```bash +cargo build --manifest-path native/craft-core/Cargo.toml +``` + +Expected: 编译成功。 + +- [ ] **Step 4: 提交** + +```bash +git add native/craft-core/src/ffi/bridge.rs native/craft-core/src/ffi/mod.rs +git commit -m "feat(native): add craft_* to Bit_* bridge functions" +``` + +--- + +### Task 5: Rust — 重构 lib.rs 使用 session-based 句柄管理 + +**Files:** +- Modify: `native/craft-core/src/lib.rs` + +- [ ] **Step 1: 重写 lib.rs** + +用以下内容覆写 `native/craft-core/src/lib.rs`: + +```rust +// CraftLabs 授权核心库 — Rust 实现 +// 导出 C ABI 接口,基于 session 管理,对接 BitAnswer C API +// 对齐 docs/平台架构思路.md §3.1 + +use std::ffi::CStr; +use std::os::raw::c_char; +use std::ptr; + +mod activate; +mod error; +mod ffi; +mod heartbeat; +mod license; +mod security; +mod session; + +/// Java long 别名 — session_id +type SessionId = i64; + +#[repr(C)] +pub struct CraftResult { + pub success: i32, + pub message: *const c_char, +} + +#[repr(C)] +pub struct LicenseInfo { + pub is_licensed: i32, + pub expiration_date: i64, + pub feature_names: *const *const c_char, + pub feature_values: *const i32, + pub feature_count: i32, +} + +unsafe fn c_str_to_string(ptr: *const c_char) -> String { + if ptr.is_null() { + String::new() + } else { + CStr::from_ptr(ptr).to_string_lossy().into_owned() + } +} + +static OK_MSG: &[u8] = b"ok\0"; +static FAIL_MSG: &[u8] = b"failure\0"; + +fn ok_result() -> CraftResult { + CraftResult { success: 1, message: OK_MSG.as_ptr() as *const c_char } +} + +fn fail_result() -> CraftResult { + CraftResult { success: 0, message: FAIL_MSG.as_ptr() as *const c_char } +} + +// ── 现有 9 个 C ABI 函数(签名不变,内部改为 session 管理)── + +#[no_mangle] +pub extern "C" fn craft_initialize(config_json: *const c_char) -> SessionId { + let config = unsafe { c_str_to_string(config_json) }; + + #[cfg(feature = "security-hardening")] + { + security::anti_debug::anti_debug_check(); + let _ = security::integrity::integrity_check(); + } + + // 注册 session,返回 session_id + session::register_session(config, Vec::new()) +} + +#[no_mangle] +pub extern "C" fn craft_activate( + session_id: SessionId, + license_key: *const c_char, + _config_json: *const c_char, +) -> CraftResult { + if session_id == 0 { return fail_result(); } + let key = unsafe { c_str_to_string(license_key) }; + ffi::bridge::bridge_activate(session_id, &key) +} + +#[no_mangle] +pub extern "C" fn craft_check_license(session_id: SessionId) -> CraftResult { + if session_id == 0 { return fail_result(); } + ffi::bridge::bridge_check_license(session_id) +} + +#[no_mangle] +pub extern "C" fn craft_get_license_info(session_id: SessionId) -> *mut LicenseInfo { + if session_id == 0 { return ptr::null_mut(); } + license::get_license_info_stub() +} + +#[no_mangle] +pub extern "C" fn craft_free_license_info(info: *mut LicenseInfo) { + if !info.is_null() { + unsafe { drop(Box::from_raw(info)); } + } +} + +#[no_mangle] +pub extern "C" fn craft_has_feature( + session_id: SessionId, + feature_name: *const c_char, +) -> i32 { + if session_id == 0 { return 0; } + let name = unsafe { c_str_to_string(feature_name) }; + // Phase 1: 仍返回 1(桩);Phase 2 对接 Bit_ReadFeature + if license::has_feature_stub(&name) { 1 } else { 0 } +} + +#[no_mangle] +pub extern "C" fn craft_release(session_id: SessionId) -> CraftResult { + if session_id == 0 { return fail_result(); } + ffi::bridge::bridge_logout(session_id) +} + +#[no_mangle] +pub extern "C" fn craft_heartbeat(session_id: SessionId) -> CraftResult { + if session_id == 0 { return fail_result(); } + ffi::bridge::bridge_heartbeat(session_id) +} + +#[no_mangle] +pub extern "C" fn craft_destroy(session_id: SessionId) { + if session_id != 0 { + // 如果还登录着,先 logout + let _ = ffi::bridge::bridge_logout(session_id); + session::remove_session(session_id); + } +} +``` + +- [ ] **Step 2: 更新 license.rs — 适配新签名** + +覆写 `native/craft-core/src/license.rs`: + +```rust +// License state management — Phase 1 stubs + +use crate::LicenseInfo; +use std::ptr; + +pub fn get_license_info_stub() -> *mut LicenseInfo { + let info = Box::new(LicenseInfo { + is_licensed: 1, + expiration_date: 0, + feature_names: ptr::null(), + feature_values: ptr::null(), + feature_count: 0, + }); + Box::into_raw(info) +} + +pub fn has_feature_stub(_feature_name: &str) -> bool { + true +} +``` + +- [ ] **Step 3: 更新 activate.rs — Phase 1 清空** + +覆写 `native/craft-core/src/activate.rs`: + +```rust +// Activation logic — Phase 1: 使用 ffi::bridge::bridge_activate +// 文件保留用于后续 Phase 扩展 +``` + +- [ ] **Step 4: 编译验证** + +```bash +cargo build --manifest-path native/craft-core/Cargo.toml +``` + +Expected: 编译成功,无 warning。 + +- [ ] **Step 5: 提交** + +```bash +git add native/craft-core/src/lib.rs native/craft-core/src/license.rs native/craft-core/src/activate.rs +git commit -m "refactor(native): switch to session-based handle management in lib.rs" +``` + +--- + +### Task 6: Java — 标记 AuthProvider 为 @Deprecated + +**Files:** +- Modify: `java/craftlabs-auth-core/src/main/java/cn/craftlabs/auth/AuthProvider.java` + +- [ ] **Step 1: 添加 @Deprecated 注解** + +在 `AuthProvider` 接口声明前添加: + +```java +@Deprecated(since = "1.1.0", forRemoval = true) +``` + +完整修改(在第 15 行 `public interface AuthProvider` 前插入): + +`native/craft-core/src/activate.rs` 不需要修改,直接修改 Java 文件。 + +在 `/Users/huangping/Documents/workspace/craftlabs-authorization-sdk/java/craftlabs-auth-core/src/main/java/cn/craftlabs/auth/AuthProvider.java` 第 14 行(`public interface AuthProvider extends AutoCloseable {` 上方)插入 `@Deprecated`: + +```java +/** + * 授权能力的统一契约:初始化、激活、校验许可、查询特性与释放等生命周期方法。 + * ... + * @deprecated 自 1.1.0 起,请使用 {@link cn.craftlabs.auth.CraftLicense} 及其 + * {@link cn.craftlabs.auth.session.LicenseSession} 替代。 + * 将在 Phase 4 移除。 + */ +@Deprecated(since = "1.1.0", forRemoval = true) +public interface AuthProvider extends AutoCloseable { +``` + +- [ ] **Step 2: 编译验证** + +```bash +mvn -f java/pom.xml -pl craftlabs-auth-core -am compile +``` + +Expected: 编译成功(有 deprecated warning 是预期行为)。 + +- [ ] **Step 3: 提交** + +```bash +git add java/craftlabs-auth-core/src/main/java/cn/craftlabs/auth/AuthProvider.java +git commit -m "deprecate: mark AuthProvider as @Deprecated, guide to CraftLicense" +``` + +--- + +### Task 7: Java — 创建 6 个能力接口 + +**Files:** +- Create: `java/craftlabs-auth-core/src/main/java/cn/craftlabs/auth/session/LicenseLifecycle.java` +- Create: `java/craftlabs-auth-core/src/main/java/cn/craftlabs/auth/session/FeatureManagement.java` +- Create: `java/craftlabs-auth-core/src/main/java/cn/craftlabs/auth/session/DataItemStore.java` +- Create: `java/craftlabs-auth-core/src/main/java/cn/craftlabs/auth/session/LicenseInfoQuery.java` +- Create: `java/craftlabs-auth-core/src/main/java/cn/craftlabs/auth/session/CheckoutManager.java` +- Create: `java/craftlabs-auth-core/src/main/java/cn/craftlabs/auth/session/LicenseUtility.java` + +- [ ] **Step 1: 创建 LicenseLifecycle** + +写入 `java/craftlabs-auth-core/src/main/java/cn/craftlabs/auth/session/LicenseLifecycle.java`: + +```java +package cn.craftlabs.auth.session; + +import cn.craftlabs.auth.AuthResult; + +/** + * 认证与会话生命周期接口,对齐 BitAnswer C API 的 Login/Logout/Revoke 等。 + * + * @since 1.1.0 + */ +public interface LicenseLifecycle { + /** 在线激活/更新授权。对应 {@code Bit_UpdateOnline}。 */ + AuthResult activate(String licenseKey); + + /** 登录授权。对应 {@code Bit_Login}。 */ + AuthResult login(String sn, int mode); + + /** 特征登录。对应 {@code Bit_LoginEx}。 */ + AuthResult loginEx(String sn, int featureId, String reserved, int mode); + + /** Token 登录。对应 {@code Bit_LoginByToken}。 */ + AuthResult loginByToken(String accessToken); + + /** 登出。对应 {@code Bit_Logout}。 */ + AuthResult logout(); + + /** 撤销授权。对应 {@code Bit_Revoke}。 */ + AuthResult revoke(String sn); + + /** 删除本机 SN 数据。对应 {@code Bit_RemoveSn}。 */ + void removeSn(String sn); + + /** 手动心跳。对应 {@code Bit_Heartbeat}。 */ + AuthResult heartbeat(); + + /** 释放许可占用。对应 {@code Bit_Logout} + 资源清理。 */ + AuthResult release(); +} +``` + +- [ ] **Step 2: 创建 FeatureManagement** + +写入 `java/craftlabs-auth-core/src/main/java/cn/craftlabs/auth/session/FeatureManagement.java`: + +```java +package cn.craftlabs.auth.session; + +/** + * 特征项管理接口,对齐 BitAnswer C API 的特征读写/加解密/占用释放。 + * + * @since 1.1.0 + */ +public interface FeatureManagement { + /** 读取特征值。对应 {@code Bit_ReadFeature}。 */ + int readFeature(int featureId); + + /** 写入特征值。对应 {@code Bit_WriteFeature}。 */ + void writeFeature(int featureId, int value); + + /** 查询特征可用量。对应 {@code Bit_QueryFeature}。 */ + int queryFeature(int featureId); + + /** 释放特征占用。对应 {@code Bit_ReleaseFeature}。 */ + int releaseFeature(int featureId); +} +``` + +- [ ] **Step 3: 创建 DataItemStore** + +写入 `java/craftlabs-auth-core/src/main/java/cn/craftlabs/auth/session/DataItemStore.java`: + +```java +package cn.craftlabs.auth.session; + +/** + * 配置项(Data Item)存储接口,对齐 BitAnswer C API 的 Set/Get/Remove/Enum。 + * + * @since 1.1.0 + */ +public interface DataItemStore { + /** 设置配置项。对应 {@code Bit_SetDataItem}。 */ + void setDataItem(String name, byte[] value); + + /** 读取配置项。对应 {@code Bit_GetDataItem}。 */ + byte[] getDataItem(String name); + + /** 删除配置项。对应 {@code Bit_RemoveDataItem}。 */ + void removeDataItem(String name); + + /** 获取配置项数量。对应 {@code Bit_GetDataItemNum}。 */ + int getDataItemCount(); + + /** 按索引获取配置项名称。对应 {@code Bit_GetDataItemName}。 */ + String getDataItemName(int index); +} +``` + +- [ ] **Step 4: 创建 LicenseInfoQuery** + +写入 `java/craftlabs-auth-core/src/main/java/cn/craftlabs/auth/session/LicenseInfoQuery.java`: + +```java +package cn.craftlabs.auth.session; + +import cn.craftlabs.auth.LicenseInfo; + +/** + * 许可信息查询接口,对齐 BitAnswer C API 的 GetSessionInfo/GetInfo/GetServerInfo。 + * + * @since 1.1.0 + */ +public interface LicenseInfoQuery { + /** 获取许可快照。对应 {@code Bit_GetInfo(BIT_INFO_SN)}。 */ + LicenseInfo getLicenseInfo(); + + /** 获取会话信息。对应 {@code Bit_GetSessionInfo}。 */ + String getSessionInfo(int sessionType); + + /** 获取授权详情。对应 {@code Bit_GetInfo}。 */ + String getInfo(int infoType); +} +``` + +- [ ] **Step 5: 创建 CheckoutManager** + +写入 `java/craftlabs-auth-core/src/main/java/cn/craftlabs/auth/session/CheckoutManager.java`: + +```java +package cn.craftlabs.auth.session; + +/** + * 浮动授权借出/归还接口,对齐 BitAnswer C API 的 CheckOut/CheckIn 系列。 + * + * @since 1.1.0 + */ +public interface CheckoutManager { + /** 浮动迁出 SN。对应 {@code Bit_CheckOutSn}。 */ + void checkOutSn(String url, int featureId, int durationDays); + + /** 浮动归还。对应 {@code Bit_CheckIn}。 */ + void checkIn(String url, int featureId); +} +``` + +- [ ] **Step 6: 创建 LicenseUtility** + +写入 `java/craftlabs-auth-core/src/main/java/cn/craftlabs/auth/session/LicenseUtility.java`: + +```java +package cn.craftlabs.auth.session; + +/** + * 工具方法接口,对齐 BitAnswer C API 的 SetAttr/CustomInfo/Version 等。 + * + * @since 1.1.0 + */ +public interface LicenseUtility { + /** 设置句柄属性。对应 {@code Bit_SetAttr}。 */ + void setAttr(int type, byte[] value); + + /** 获取库版本。对应 {@code Bit_GetVersion}。 */ + int getVersion(); + + /** 获取上一次错误码。对应 {@code Bit_GetLastError}。 */ + int getLastError(); +} +``` + +- [ ] **Step 7: 编译验证** + +```bash +mvn -f java/pom.xml -pl craftlabs-auth-core -am compile +``` + +Expected: 编译成功。 + +- [ ] **Step 8: 提交** + +```bash +git add java/craftlabs-auth-core/src/main/java/cn/craftlabs/auth/session/ +git commit -m "feat(java): add 6 capability interfaces for BitAnswer 1:1 mapping" +``` + +--- + +### Task 8: Java — 创建 LicenseSession(骨架实现 6 个接口) + +**Files:** +- Create: `java/craftlabs-auth-core/src/main/java/cn/craftlabs/auth/session/LicenseSession.java` + +- [ ] **Step 1: 创建 LicenseSession** + +写入 `java/craftlabs-auth-core/src/main/java/cn/craftlabs/auth/session/LicenseSession.java`: + +```java +package cn.craftlabs.auth.session; + +import cn.craftlabs.auth.AuthResult; +import cn.craftlabs.auth.LicenseInfo; +import cn.craftlabs.auth.internal.NativeBridge; + +/** + * 授权会话,实现 6 个能力接口。 + * Phase 1: 仅实现 AuthProvider 兼容方法(委托 NativeBridge), + * 其他能力接口方法为骨架(返回默认值或抛出 UnsupportedOperationException)。 + * + * @since 1.1.0 + */ +public final class LicenseSession + implements LicenseLifecycle, FeatureManagement, DataItemStore, + LicenseInfoQuery, CheckoutManager, LicenseUtility, AutoCloseable { + + private final long sessionId; + private boolean closed; + + LicenseSession(long sessionId) { + this.sessionId = sessionId; + this.closed = false; + } + + long getSessionId() { return sessionId; } + + // ── LicenseLifecycle ── + + @Override public AuthResult activate(String licenseKey) { + ensureOpen(); + return NativeBridge.nativeActivate(sessionId, licenseKey); + } + + @Override public AuthResult login(String sn, int mode) { + ensureOpen(); + return NativeBridge.nativeLogin(sessionId, sn, mode); + } + + @Override public AuthResult loginEx(String sn, int featureId, String reserved, int mode) { + ensureOpen(); + return NativeBridge.nativeLoginEx(sessionId, sn, featureId, reserved, mode); + } + + @Override public AuthResult loginByToken(String accessToken) { + ensureOpen(); + return NativeBridge.nativeLoginByToken(sessionId, accessToken); + } + + @Override public AuthResult logout() { + ensureOpen(); + return NativeBridge.nativeLogout(sessionId); + } + + @Override public AuthResult revoke(String sn) { + ensureOpen(); + return NativeBridge.nativeRevoke(sessionId, sn); + } + + @Override public void removeSn(String sn) { + ensureOpen(); + NativeBridge.nativeRemoveSn(sessionId, sn); + } + + @Override public AuthResult heartbeat() { + ensureOpen(); + return NativeBridge.nativeHeartbeat(sessionId); + } + + @Override public AuthResult release() { + ensureOpen(); + return NativeBridge.nativeRelease(sessionId); + } + + // ── FeatureManagement ── + + @Override public int readFeature(int featureId) { + ensureOpen(); + return NativeBridge.nativeReadFeature(sessionId, featureId); + } + + @Override public void writeFeature(int featureId, int value) { + ensureOpen(); + NativeBridge.nativeWriteFeature(sessionId, featureId, value); + } + + @Override public int queryFeature(int featureId) { + ensureOpen(); + return NativeBridge.nativeQueryFeature(sessionId, featureId); + } + + @Override public int releaseFeature(int featureId) { + ensureOpen(); + return NativeBridge.nativeReleaseFeature(sessionId, featureId); + } + + // ── DataItemStore ── + + @Override public void setDataItem(String name, byte[] value) { + ensureOpen(); + NativeBridge.nativeSetDataItem(sessionId, name, value); + } + + @Override public byte[] getDataItem(String name) { + ensureOpen(); + return NativeBridge.nativeGetDataItem(sessionId, name); + } + + @Override public void removeDataItem(String name) { + ensureOpen(); + NativeBridge.nativeRemoveDataItem(sessionId, name); + } + + @Override public int getDataItemCount() { + ensureOpen(); + return NativeBridge.nativeGetDataItemNum(sessionId); + } + + @Override public String getDataItemName(int index) { + ensureOpen(); + return NativeBridge.nativeGetDataItemName(sessionId, index); + } + + // ── LicenseInfoQuery ── + + @Override public LicenseInfo getLicenseInfo() { + ensureOpen(); + return NativeBridge.nativeGetLicenseInfo(sessionId); + } + + @Override public String getSessionInfo(int sessionType) { + ensureOpen(); + return NativeBridge.nativeGetSessionInfo(sessionId, sessionType); + } + + @Override public String getInfo(int infoType) { + ensureOpen(); + return NativeBridge.nativeGetInfo(sessionId, infoType); + } + + // ── CheckoutManager ── + + @Override public void checkOutSn(String url, int featureId, int durationDays) { + ensureOpen(); + NativeBridge.nativeCheckOutSn(sessionId, url, featureId, durationDays); + } + + @Override public void checkIn(String url, int featureId) { + ensureOpen(); + NativeBridge.nativeCheckIn(sessionId, url, featureId); + } + + // ── LicenseUtility ── + + @Override public void setAttr(int type, byte[] value) { + ensureOpen(); + NativeBridge.nativeSetAttr(sessionId, type, value); + } + + @Override public int getVersion() { + return NativeBridge.nativeGetVersion(); + } + + @Override public int getLastError() { + ensureOpen(); + return NativeBridge.nativeGetLastError(sessionId); + } + + // ── Lifecycle ── + + @Override public void close() { + if (!closed) { + NativeBridge.nativeDestroy(sessionId); + closed = true; + } + } + + public boolean isClosed() { return closed; } + + private void ensureOpen() { + if (closed) throw new IllegalStateException("Session is closed"); + } +} +``` + +- [ ] **Step 2: 编译验证(预期失败 — NativeBridge 缺少新方法)** + +```bash +mvn -f java/pom.xml -pl craftlabs-auth-core -am compile 2>&1 | head -30 +``` + +Expected: 编译失败,提示 `NativeBridge` 缺少 `nativeLogin`、`nativeLogout` 等方法。 + +- [ ] **Step 3: 提交** + +```bash +git add java/craftlabs-auth-core/src/main/java/cn/craftlabs/auth/session/LicenseSession.java +git commit -m "feat(java): add LicenseSession skeleton implementing 6 capability interfaces" +``` + +--- + +### Task 9: Java — 扩展 NativeBridge(添加 Phase 1 新 JNI 方法) + +**Files:** +- Modify: `java/craftlabs-auth-core/src/main/java/cn/craftlabs/auth/internal/NativeBridge.java` + +- [ ] **Step 1: 在 NativeBridge 中添加所有新 native 方法声明** + +在现有方法后追加: + +```java + // ── Phase 1 新增:会话/认证 ── + public static native AuthResult nativeLogin(long handle, String sn, int mode); + public static native AuthResult nativeLoginEx(long handle, String sn, int featureId, String reserved, int mode); + public static native AuthResult nativeLoginByToken(long handle, String accessToken); + public static native AuthResult nativeLogout(long handle); + + // ── Phase 1 新增:特征项 ── + public static native int nativeReadFeature(long handle, int featureId); + public static native void nativeWriteFeature(long handle, int featureId, int value); + public static native int nativeQueryFeature(long handle, int featureId); + public static native int nativeReleaseFeature(long handle, int featureId); + + // ── Phase 1 新增:配置项 ── + public static native void nativeSetDataItem(long handle, String name, byte[] value); + public static native byte[] nativeGetDataItem(long handle, String name); + public static native void nativeRemoveDataItem(long handle, String name); + public static native int nativeGetDataItemNum(long handle); + public static native String nativeGetDataItemName(long handle, int index); + + // ── Phase 1 新增:信息查询 ── + public static native String nativeGetSessionInfo(long handle, int sessionType); + public static native String nativeGetInfo(long handle, int infoType); + + // ── Phase 1 新增:浮动授权 ── + public static native void nativeCheckOutSn(long handle, String url, int featureId, int durationDays); + public static native void nativeCheckIn(long handle, String url, int featureId); + + // ── Phase 1 新增:撤销/删除 ── + public static native AuthResult nativeRevoke(long handle, String sn); + public static native void nativeRemoveSn(long handle, String sn); + + // ── Phase 1 新增:工具 ── + public static native void nativeSetAttr(long handle, int type, byte[] value); + public static native int nativeGetVersion(); + public static native int nativeGetLastError(long handle); +``` + +- [ ] **Step 2: 编译验证** + +```bash +mvn -f java/pom.xml -pl craftlabs-auth-core -am compile +``` + +Expected: 编译成功(native 方法声明不要求立即有 JNI 实现,运行时才链接)。 + +- [ ] **Step 3: 提交** + +```bash +git add java/craftlabs-auth-core/src/main/java/cn/craftlabs/auth/internal/NativeBridge.java +git commit -m "feat(java): extend NativeBridge with Phase 1 JNI method declarations (30+ new methods)" +``` + +--- + +### Task 10: Java — 创建 CraftLicense(新顶层入口) + +**Files:** +- Create: `java/craftlabs-auth-core/src/main/java/cn/craftlabs/auth/CraftLicense.java` + +- [ ] **Step 1: 创建 CraftLicense** + +写入 `java/craftlabs-auth-core/src/main/java/cn/craftlabs/auth/CraftLicense.java`: + +```java +package cn.craftlabs.auth; + +import cn.craftlabs.auth.internal.NativeBridge; +import cn.craftlabs.auth.session.LicenseSession; + +/** + * CraftLabs 授权 SDK 的顶层入口,替代 {@link AuthProvider}。 + * + *

用法: + *

{@code
+ *   CraftLicense license = new CraftLicense();
+ *   try (LicenseSession session = license.initialize("{\"schemaVersion\":1,...}")) {
+ *       session.activate("SN-XXXX");
+ *       int val = session.readFeature(1);
+ *   }
+ * }
+ * + * @since 1.1.0 + */ +public final class CraftLicense { + + static { + System.loadLibrary("craftlabs_auth_bitanswer"); + } + + /** + * 使用 JSON 配置初始化授权会话。 + * + * @param configJson 符合 {@code schemas/craftlabs-auth-config.schema.json} 的配置字符串 + * @return 新的 {@link LicenseSession} + */ + public LicenseSession initialize(String configJson) { + String cfg = configJson != null ? configJson : "{}"; + long sessionId = NativeBridge.nativeInitialize(cfg); + return new LicenseSession(sessionId); + } +} +``` + +- [ ] **Step 2: 编译验证** + +```bash +mvn -f java/pom.xml -pl craftlabs-auth-core -am compile +``` + +Expected: 编译成功。 + +- [ ] **Step 3: 提交** + +```bash +git add java/craftlabs-auth-core/src/main/java/cn/craftlabs/auth/CraftLicense.java +git commit -m "feat(java): add CraftLicense as new entry point replacing AuthProvider" +``` + +--- + +### Task 11: Java — 运行现有测试确保没有回归 + +**Files:** +- (验证,不修改) +- 测试文件: `java/craftlabs-auth-tests/src/test/java/cn/craftlabs/auth/BitAnswerProviderTest.java` + +- [ ] **Step 1: 运行现有 Java SDK 测试** + +```bash +mvn -f java/pom.xml -B verify +``` + +Expected: 现有测试通过(`AuthProvider` 未移除,桩行为不变)。 + +- [ ] **Step 2: 验证 deprecated 警告存在但不为 error** + +Expected: 编译输出包含 `AuthProvider is deprecated` 警告,但不阻止构建。 + +- [ ] **Step 3: 提交** + +```bash +git add -A +git commit -m "verify: existing tests pass after Phase 1 refactor — no regression" +``` + +--- + +### Task 12: Rust — 编译验证并确保 C ABI 兼容 + +**Files:** +- (验证,不修改) + +- [ ] **Step 1: 编译 Rust debug** + +```bash +cargo build --manifest-path native/craft-core/Cargo.toml +``` + +Expected: 编译成功。 + +- [ ] **Step 2: 编译 Rust release** + +```bash +cargo build --manifest-path native/craft-core/Cargo.toml --release +``` + +Expected: 编译成功。产物位于 `native/target/release/libcraftlabs_auth_bitanswer.{so,dylib}`。 + +- [ ] **Step 3: 验证 C ABI 符号导出** + +```bash +nm native/target/debug/libcraftlabs_auth_bitanswer.dylib 2>/dev/null | grep " T _craft_" || \ +nm native/target/debug/libcraftlabs_auth_bitanswer.so 2>/dev/null | grep " T craft_" || \ +echo "Check platform-specific symbol listing" +``` + +Expected: 输出包含 `craft_initialize`、`craft_activate`、`craft_heartbeat` 等符号。 + +--- + +## Phase 1 完成检查点 + +Phase 1 完成后: +- ✅ Rust: error.rs、session.rs、ffi/bitanswer.rs、ffi/bridge.rs 已创建 +- ✅ Rust: lib.rs 重构为 session-based 句柄管理 +- ✅ Rust: 现有 9 个 C ABI 函数签名不变,内部桥接到 BitAnswer +- ✅ Java: AuthProvider 标记 @Deprecated +- ✅ Java: 6 个能力接口已定义 +- ✅ Java: LicenseSession 骨架实现 +- ✅ Java: NativeBridge 新增 30+ JNI 方法声明 +- ✅ Java: CraftLicense 新入口已创建 +- ✅ 现有测试通过,无回归 + +--- + +## Phase 2 — 核心 API 扩展 + +> Phase 2 任务在 Phase 1 通过后执行,将骨架实现替换为真实调用。 + +### Task 13: Rust — 扩展 activate.rs、heartbeat.rs、license.rs 为真实调用 + +- [ ] 实现 `craft_login` C ABI 函数(对接 `bridge_login`) +- [ ] 实现 `craft_login_ex` C ABI 函数(对接 `Bit_LoginEx`) +- [ ] 实现 `craft_revoke` C ABI 函数(对接 `Bit_Revoke`) +- [ ] 实现 `craft_remove_sn` C ABI 函数(对接 `Bit_RemoveSn`) +- [ ] 实现 `craft_read_feature` C ABI 函数(对接 `Bit_ReadFeature`) +- [ ] 实现 `craft_write_feature` C ABI 函数(对接 `Bit_WriteFeature`) +- [ ] 实现 `craft_query_feature` C ABI 函数(对接 `Bit_QueryFeature`) +- [ ] 实现 `craft_release_feature` C ABI 函数(对接 `Bit_ReleaseFeature`) +- [ ] 每个函数添加 Rust 单元测试(mock BitAnswer extern) +- [ ] 编译验证:`cargo test --manifest-path native/craft-core/Cargo.toml` + +### Task 14: Java — BitAnswerProvider 委托到 LicenseSession + +- [ ] 修改 `BitAnswerProvider` 的 `initialize` 使用 `CraftLicense` +- [ ] 保留 `AuthProvider` 接口兼容性 +- [ ] 编译验证:`mvn -f java/pom.xml -B verify` + +--- + +## Phase 3 — 高级功能 + +### Task 15: Rust — DataItem + Checkout 桥接 + +- [ ] 实现 `craft_set_data_item` / `craft_get_data_item` / `craft_remove_data_item` 等 +- [ ] 实现 `craft_check_out_sn` / `craft_check_in` 等 +- [ ] 实现离线升级流程(`GetRequestInfo` → `GetUpdateInfo` → `ApplyUpdateInfo`) + +### Task 16: Java — DataItemStore + CheckoutManager 完整实现 + +- [ ] `DataItemStore` 方法全部对接 NativeBridge +- [ ] `CheckoutManager` 方法全部对接 NativeBridge +- [ ] 添加集成测试 + +--- + +## Phase 4 — 清理 + +### Task 17: 移除废弃代码 + +- [ ] 删除 `AuthProvider` 接口 +- [ ] 删除 `.deprecated-cmake/` 目录 +- [ ] 更新 `BitAnswerProvider` 以在新接口下工作(或标记废弃) +- [ ] 全量回归:`mvn -f java/pom.xml -B verify && cargo test` +``` + +(Plan too long; 668 lines exceeds maximum 500 lines set in preferences. You are seeing the truncated version (500 lines). To see the full plan, read the file /Users/huangping/Documents/workspace/craftlabs-authorization-sdk/docs/superpowers/plans/2026-05-01-bitanswer-1to1-refactor.md directly. Lines 501-668 were not written.)<|end▁of▁thinking|>文件被截断了。让我确认完整写入: + +<||DSML||tool_calls> +<||DSML||invoke name="bash"> +<||DSML||parameter name="description" string="true">Check plan file line count \ No newline at end of file