diff --git a/scripts/db/schema.py b/scripts/db/schema.py index 114443a..0c55c32 100644 --- a/scripts/db/schema.py +++ b/scripts/db/schema.py @@ -7,7 +7,7 @@ sqlite_master, visible in DBeaver / Navicat. Schema version management: - PRAGMA user_version = 2 (set in connection.py after ensure_schema). - - _schema_meta row schema_version=2 (written by migrate_v1_to_v2). + - _schema_meta schema_version: "2" after migrate_v1_to_v2, "2.1" after migrate_v2_to_v2_1. """ import sqlite3 @@ -93,9 +93,10 @@ CREDENTIALS_TABLE_SQL = textwrap.dedent("""\ platform_key TEXT NOT NULL, -- 平台唯一键 credential_label TEXT NOT NULL, -- 人可读名称,例如 DeepSeek main API key credential_type TEXT NOT NULL, -- api_key / password / bearer_token / oauth_client / refresh_token / browser_profile / note - secret_storage TEXT NOT NULL, -- none / env / windows_credential - secret_ref TEXT, -- env 时为环境变量名;windows_credential 时为 target name;none 时为空 + secret_storage TEXT NOT NULL, -- none / env / windows_credential / local_encrypted + secret_ref TEXT, -- env 时为环境变量名;windows_credential 时为 target name;none/local_encrypted 时为空 secret_mask TEXT, -- 打码展示,例如 sk-****abcd;不能反推出原文 + secret_ciphertext TEXT, -- secret_storage='local_encrypted' 时为 Fernet 密文;其它后端为 NULL expires_at INTEGER, -- 过期时间,Unix 秒 UTC;可空 status TEXT NOT NULL DEFAULT 'active', -- active / disabled / expired / needs_rotation last_used_at INTEGER, -- 最近使用时间 @@ -193,7 +194,8 @@ def migrate_v1_to_v2(conn: sqlite3.Connection) -> None: from db.platform_defaults import PLATFORM_DEFAULT_AUTH_STRATEGY cur = conn.cursor() - if _schema_meta_get(conn, "schema_version") == "2": + sv = _schema_meta_get(conn, "schema_version") + if sv == "2" or (sv and sv.startswith("2.")): return n_platform_updates = 0 @@ -261,9 +263,30 @@ def migrate_v1_to_v2(conn: sqlite3.Connection) -> None: ) +def migrate_v2_to_v2_1(conn: sqlite3.Connection) -> None: + """v2 → v2.1: credentials 表加 secret_ciphertext 列。幂等。""" + cur = conn.cursor() + if _schema_meta_get(conn, "schema_version") == "2.1": + return + + if column_exists(conn, "credentials", "secret_ciphertext"): + _schema_meta_upsert(conn, "schema_version", "2.1") + conn.commit() + return + + cur.execute("ALTER TABLE credentials ADD COLUMN secret_ciphertext TEXT") + _schema_meta_upsert(conn, "schema_version", "2.1") + conn.commit() + print( + "[migration] account-manager v2→v2.1: credentials.secret_ciphertext column added.", + file=sys.stderr, + ) + + def ensure_schema(conn: sqlite3.Connection) -> None: """CREATE TABLE/INDEX IF NOT EXISTS, then run migrate_v1_to_v2.""" cur = conn.cursor() cur.executescript(ALL_DDL) conn.commit() migrate_v1_to_v2(conn) + migrate_v2_to_v2_1(conn)