feat(ext): typed-item TS types mirroring relicario-core serde
This commit is contained in:
@@ -1,32 +1,202 @@
|
|||||||
/// Full credential entry (matches Rust Entry struct in relicario-core).
|
/// Typed-item shared TypeScript types.
|
||||||
export interface Entry {
|
///
|
||||||
name: string;
|
/// These mirror the Rust core's serde serialization. See
|
||||||
url?: string;
|
/// crates/relicario-core/src/item.rs, item_types/, and settings.rs
|
||||||
|
/// for the source shapes.
|
||||||
|
|
||||||
|
// --- IDs ---
|
||||||
|
|
||||||
|
export type ItemId = string; // 16-char hex
|
||||||
|
export type FieldId = string; // 16-char hex
|
||||||
|
export type AttachmentId = string; // 16-char hex (sha256 of plaintext, truncated)
|
||||||
|
|
||||||
|
// --- ItemType / ItemCore ---
|
||||||
|
|
||||||
|
// snake_case from serde rename_all
|
||||||
|
export type ItemType =
|
||||||
|
| 'login' | 'secure_note' | 'identity' | 'card' | 'key' | 'document' | 'totp';
|
||||||
|
|
||||||
|
// ItemCore is internally-tagged on "type":
|
||||||
|
// Login → { type: 'login', username, password, url, totp }
|
||||||
|
export type ItemCore =
|
||||||
|
| ({ type: 'login' } & LoginCore)
|
||||||
|
| ({ type: 'secure_note' } & SecureNoteCore)
|
||||||
|
| ({ type: 'identity' } & IdentityCore)
|
||||||
|
| ({ type: 'card' } & CardCore)
|
||||||
|
| ({ type: 'key' } & KeyCore)
|
||||||
|
| ({ type: 'document' } & DocumentCore)
|
||||||
|
| ({ type: 'totp' } & TotpCore);
|
||||||
|
|
||||||
|
// Optional fields use `?` because Rust #[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
// omits them from the JSON; serde_wasm_bindgen produces `undefined` on read.
|
||||||
|
|
||||||
|
export interface LoginCore {
|
||||||
username?: string;
|
username?: string;
|
||||||
password: string;
|
password?: string;
|
||||||
|
url?: string;
|
||||||
|
totp?: TotpConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SecureNoteCore { body: string; }
|
||||||
|
|
||||||
|
export interface IdentityCore {
|
||||||
|
full_name?: string;
|
||||||
|
address?: string;
|
||||||
|
phone?: string;
|
||||||
|
email?: string;
|
||||||
|
date_of_birth?: string; // "YYYY-MM-DD"
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CardCore {
|
||||||
|
number?: string;
|
||||||
|
holder?: string;
|
||||||
|
expiry?: { month: number; year: number };
|
||||||
|
cvv?: string;
|
||||||
|
pin?: string;
|
||||||
|
kind: CardKind;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type CardKind = 'credit' | 'debit' | 'gift' | 'loyalty' | 'other';
|
||||||
|
|
||||||
|
export interface KeyCore {
|
||||||
|
key_material: string;
|
||||||
|
label?: string;
|
||||||
|
public_key?: string;
|
||||||
|
algorithm?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DocumentCore {
|
||||||
|
filename: string;
|
||||||
|
mime_type: string;
|
||||||
|
primary_attachment: AttachmentId;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TotpCore {
|
||||||
|
config: TotpConfig;
|
||||||
|
issuer?: string;
|
||||||
|
label?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- TOTP ---
|
||||||
|
|
||||||
|
export type TotpKind = 'totp' | 'steam' | { hotp: { counter: number } };
|
||||||
|
|
||||||
|
export interface TotpConfig {
|
||||||
|
secret: number[]; // Vec<u8> → JSON number array
|
||||||
|
algorithm: 'sha1' | 'sha256' | 'sha512';
|
||||||
|
digits: number;
|
||||||
|
period_seconds: number;
|
||||||
|
kind: TotpKind;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Sections + custom fields ---
|
||||||
|
|
||||||
|
export interface Section {
|
||||||
|
name?: string;
|
||||||
|
fields: Field[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Field {
|
||||||
|
id: FieldId;
|
||||||
|
label: string;
|
||||||
|
kind: FieldKind;
|
||||||
|
value: FieldValue;
|
||||||
|
hidden_by_default: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type FieldKind =
|
||||||
|
| 'text' | 'multiline' | 'password' | 'concealed' | 'url' | 'email'
|
||||||
|
| 'phone' | 'date' | 'month_year' | 'totp' | 'reference';
|
||||||
|
|
||||||
|
// adjacently-tagged { tag: "kind", content: "value" }
|
||||||
|
export type FieldValue =
|
||||||
|
| { kind: 'text'; value: string }
|
||||||
|
| { kind: 'multiline'; value: string }
|
||||||
|
| { kind: 'password'; value: string }
|
||||||
|
| { kind: 'concealed'; value: string }
|
||||||
|
| { kind: 'url'; value: string }
|
||||||
|
| { kind: 'email'; value: string }
|
||||||
|
| { kind: 'phone'; value: string }
|
||||||
|
| { kind: 'date'; value: string }
|
||||||
|
| { kind: 'month_year'; value: { month: number; year: number } }
|
||||||
|
| { kind: 'totp'; value: TotpConfig }
|
||||||
|
| { kind: 'reference'; value: AttachmentId };
|
||||||
|
|
||||||
|
// --- Attachments + history ---
|
||||||
|
|
||||||
|
export interface AttachmentRef {
|
||||||
|
id: AttachmentId;
|
||||||
|
filename: string;
|
||||||
|
mime_type: string;
|
||||||
|
size: number;
|
||||||
|
created: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface FieldHistoryEntry {
|
||||||
|
value: string;
|
||||||
|
replaced_at: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AttachmentSummary {
|
||||||
|
id: AttachmentId;
|
||||||
|
filename: string;
|
||||||
|
mime_type: string;
|
||||||
|
size: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Item envelope ---
|
||||||
|
|
||||||
|
export interface Item {
|
||||||
|
id: ItemId;
|
||||||
|
title: string;
|
||||||
|
type: ItemType; // Rust r#type → JSON key "type"
|
||||||
|
tags: string[];
|
||||||
|
favorite: boolean;
|
||||||
|
group?: string;
|
||||||
notes?: string;
|
notes?: string;
|
||||||
totp_secret?: string;
|
created: number;
|
||||||
group?: string;
|
modified: number;
|
||||||
created_at: string;
|
trashed_at?: number;
|
||||||
updated_at: string;
|
core: ItemCore;
|
||||||
|
sections: Section[];
|
||||||
|
attachments: AttachmentRef[];
|
||||||
|
field_history: Record<FieldId, FieldHistoryEntry[]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Lightweight manifest entry for listing/searching without full decrypt.
|
// --- Manifest (schema_version 2) ---
|
||||||
export interface ManifestEntry {
|
|
||||||
name: string;
|
|
||||||
url?: string;
|
|
||||||
username?: string;
|
|
||||||
group?: string;
|
|
||||||
updated_at: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Encrypted manifest containing all entry metadata.
|
|
||||||
export interface Manifest {
|
export interface Manifest {
|
||||||
entries: Record<string, ManifestEntry>;
|
schema_version: number; // 2
|
||||||
version: number;
|
items: Record<ItemId, ManifestEntry>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Configuration for connecting to a git host.
|
export interface ManifestEntry {
|
||||||
|
id: ItemId;
|
||||||
|
type: ItemType;
|
||||||
|
title: string;
|
||||||
|
tags: string[];
|
||||||
|
favorite: boolean;
|
||||||
|
group?: string;
|
||||||
|
icon_hint?: string;
|
||||||
|
modified: number;
|
||||||
|
trashed_at?: number;
|
||||||
|
attachment_summaries: AttachmentSummary[];
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Vault settings (only the fields α touches) ---
|
||||||
|
// Full shape lives on the Rust side and in docs/superpowers/specs/2026-04-18-relicario-typed-items-design.md
|
||||||
|
// We leave retention/generator/caps opaque to α so we don't accidentally mutate them.
|
||||||
|
|
||||||
|
export interface VaultSettings {
|
||||||
|
trash_retention: unknown;
|
||||||
|
field_history_retention: unknown;
|
||||||
|
generator_defaults: unknown;
|
||||||
|
attachment_caps: unknown;
|
||||||
|
autofill_origin_acks: Record<string, number>;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Vault config (device-local) ---
|
||||||
|
|
||||||
export interface VaultConfig {
|
export interface VaultConfig {
|
||||||
hostType: 'gitea' | 'github';
|
hostType: 'gitea' | 'github';
|
||||||
hostUrl: string;
|
hostUrl: string;
|
||||||
@@ -34,20 +204,41 @@ export interface VaultConfig {
|
|||||||
apiToken: string;
|
apiToken: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Persisted setup state in chrome.storage.local.
|
|
||||||
export interface SetupState {
|
export interface SetupState {
|
||||||
config: VaultConfig | null;
|
config: VaultConfig | null;
|
||||||
imageBase64: string | null;
|
imageBase64: string | null;
|
||||||
isConfigured: boolean;
|
isConfigured: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// User-configurable credential capture settings.
|
// --- Device-local UX settings (chrome.storage.local — renamed from RelicarioSettings) ---
|
||||||
export interface RelicarioSettings {
|
|
||||||
|
export interface DeviceSettings {
|
||||||
captureEnabled: boolean;
|
captureEnabled: boolean;
|
||||||
captureStyle: 'bar' | 'toast';
|
captureStyle: 'bar' | 'toast';
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DEFAULT_SETTINGS: RelicarioSettings = {
|
export const DEFAULT_DEVICE_SETTINGS: DeviceSettings = {
|
||||||
captureEnabled: false,
|
captureEnabled: false,
|
||||||
captureStyle: 'bar',
|
captureStyle: 'bar',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// --- Generator request (matches Rust GeneratorRequest — tag="kind") ---
|
||||||
|
|
||||||
|
export type GeneratorRequest =
|
||||||
|
| { kind: 'bip39'; word_count: number; separator: string; capitalization: Capitalization }
|
||||||
|
| { kind: 'random'; length: number; classes: CharClasses; symbol_charset: SymbolCharset };
|
||||||
|
|
||||||
|
export type Capitalization = 'lower' | 'upper' | 'first_of_each' | 'title' | 'mixed';
|
||||||
|
export interface CharClasses { lower: boolean; upper: boolean; digits: boolean; symbols: boolean; }
|
||||||
|
export type SymbolCharset =
|
||||||
|
| { kind: 'safe_only' }
|
||||||
|
| { kind: 'extended' }
|
||||||
|
| { kind: 'custom'; value: string };
|
||||||
|
|
||||||
|
// Default used by the α popup "gen" button:
|
||||||
|
export const DEFAULT_PASSWORD_REQUEST: GeneratorRequest = {
|
||||||
|
kind: 'random',
|
||||||
|
length: 20,
|
||||||
|
classes: { lower: true, upper: true, digits: true, symbols: true },
|
||||||
|
symbol_charset: { kind: 'safe_only' },
|
||||||
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user