Skip to content

应用服务接口约定(v0.1) ​

CLI(pn)和桌面 App 都通过同一个服务层操作保险库:Rust crate passno-service,对外是一个 PassnoService trait。桌面端用 Tauri command 暴露同名方法(snake_case),前端 TypeScript 接口和下面的定义一一对应(camelCase 字段)。

改这份约定要同时改 Rust 和 TypeScript 两边,并更新本文。

类型 ​

rust
pub struct Status { pub initialized: bool, pub locked: bool, pub vault_path: String, pub item_count: u32 }

pub struct InitResult {
    pub secret_key: String,          // 例如 "A3-K7Q2PZ-…",只在这里显示一次
    pub emergency_kit_markdown: String,
}

pub enum ItemKind { Login, Password, SecureNote, Card, Identity, SshKey, ApiCredential, Document, Wifi, Custom }

pub struct ItemSummary {
    pub id: String, pub kind: ItemKind, pub title: String,
    pub subtitle: String,            // 登录类条目显示用户名,卡片显示尾号,其他为空
    pub primary_url: Option<String>, pub tags: Vec<String>,
    pub favorite: bool, pub archived: bool, pub vault: String,
    pub updated_at: i64,             // Unix 秒
    pub has_totp: bool,
}

pub struct ItemFilter {
    pub query: Option<String>, pub kind: Option<ItemKind>, pub tag: Option<String>,
    pub vault: Option<String>, pub include_archived: bool, pub favorites_only: bool,
}

pub enum FieldType { Text, Concealed, Email, Url, Phone, Date, MonthYear, Address, Menu, Reference, File, Totp, SshKey }

pub struct FieldView {
    pub id: String, pub label: String, pub section: Option<String>,
    pub field_type: FieldType, pub designation: Option<String>, // "username" | "password"
    pub value: Option<String>,       // 隐藏类字段(Concealed / Totp / SshKey)为 None,要用 reveal_field 取
    pub concealed: bool,
}

pub struct Item {
    pub summary: ItemSummary, pub urls: Vec<String>, pub fields: Vec<FieldView>,
    pub notes: Option<String>, pub created_at: i64,
    pub password_history_count: u32,
}

pub struct ItemDraft {
    pub kind: ItemKind, pub title: String, pub urls: Vec<String>,
    pub fields: Vec<FieldDraft>, pub notes: Option<String>, pub tags: Vec<String>, pub favorite: bool,
}
pub struct FieldDraft { pub id: Option<String>, pub label: String, pub section: Option<String>,
                        pub field_type: FieldType, pub designation: Option<String>, pub value: String }

pub enum GeneratorKind { Random, Passphrase, Pin }
pub struct GeneratorOptions {
    pub kind: GeneratorKind, pub length: u32,     // Random/Pin 是字符数,Passphrase 是单词数
    pub uppercase: bool, pub digits: bool, pub symbols: bool, pub avoid_ambiguous: bool,
    pub separator: Option<String>, pub capitalize: bool,
    pub for_domain: Option<String>,               // 有值时套用 PMR 网站规则
}
pub struct Generated { pub password: String, pub entropy_bits: f64, pub strength: Strength, pub rules_applied: Option<String> }
pub enum Strength { Weak, Fair, Strong, VeryStrong }

pub struct TotpCode { pub code: String, pub period: u32, pub remaining: u32 }

pub enum ImportFormat { OnePux, OnePasswordCsv, AppleCsv }
pub struct ImportPreview {
    pub format: ImportFormat, pub accounts: u32, pub vaults: Vec<String>, pub items: u32,
    pub attachments: u32, pub by_kind: Vec<(ItemKind, u32)>,
    pub not_migrated: Vec<String>,   // 用户能看懂的说明,例如"通行密钥(1Password 桌面版导不出)"
    pub warnings: Vec<String>,
}
pub enum DuplicatePolicy { Skip, KeepBoth }
pub struct ImportReport { pub imported: u32, pub skipped_duplicates: u32, pub downgraded_fields: Vec<String>, pub errors: Vec<String> }

pub struct Stats { pub total: u32, pub weak: u32, pub reused: u32, pub missing_totp_where_supported: u32 }

方法 ​

方法说明错误
status() -> Status不需要解锁—
init(master_password) -> InitResult新建保险库,生成 Secret KeyAlreadyInitialized、WeakPassword
unlock(master_password, secret_key: Option)secret_key 为 None 时从本机的 SecretKeyStore 读取WrongPassword、SecretKeyMissing
lock()清空内存里的密钥—
list_items(filter) -> Vec<ItemSummary>按 updated_at 倒序Locked
get_item(id) -> Item隐藏类字段的值为 NoneLocked、NotFound
reveal_field(item_id, field_id) -> String只有本人操作的界面和交互式终端可以调用Locked、NotFound
create_item(draft) -> String返回新 idLocked、Invalid
update_item(id, draft)修改密码时,旧值进历史Locked、NotFound、Invalid
delete_item(id) / restore_item(id)软删除,进回收站Locked、NotFound
generate(options) -> Generated不需要解锁Invalid
totp(item_id) -> TotpCodeLocked、NotFound、NoTotp
import_preview(path, format) -> ImportPreview只读,不写保险库Locked、ParseError
import_commit(path, format, policy) -> ImportReport幂等:同一来源的 UUID 不会重复导入Locked、ParseError
stats() -> StatsLocked

错误 ​

rust
pub enum ServiceError {
    NotInitialized, AlreadyInitialized, Locked, WrongPassword, SecretKeyMissing, WeakPassword,
    NotFound, Invalid(String), NoTotp, ParseError(String), Io(String), Internal(String),
}

CLI 退出码对应:

错误退出码
Invalid2
Locked / WrongPassword / SecretKeyMissing3
NotFound5
其余1

Tauri 侧: 返回 { code: "Locked", message: "…" },前端按 code 处理。

文档对应提交 80b7c2d · 由仓库 docs/ 自动生成