refactor: 观测层双轴正交重构——spectra→observation、工具/API 收敛、安全韧性加固

将"以光谱为中心"的观测数据架构升级为 (Source × ProductType) 双轴正交模型,
光谱降级为与光变/测光/图像平级的产品类型之一;同步把分散的工具、API、缓存表
收敛为统一入口。新增 Gaia 光变曲线(EPOCH_PHOTOMETRY)支持。

【架构】services/spectra 整体替换为 services/observation(双轴正交)
- Source(LAMOST/Gaia/SDSS/DESI)× ProductType(Spectrum/LightCurve/Photometry/Image)
  正交组合,新增源/产品类型为纯加法(OCP)
- ObservationFetcher trait + ObservationRegistry:每个有效组合实现一个 fetcher,
  启动时注册;SDSS specobj/APOGEE 共用 key 按 subtype 二级路由
- cone 缓存逻辑模板方法化(trait 默认方法),消除各源 4 份重复代码
- 多文件 Artifact 模型:一个逻辑产物可含多文件(如 Gaia 光变 G/BP/RP 三波段各一 FITS)
- 统一编排 dispatch.rs:search(仅检索)/ download(检索+下载),支持坐标模式
  (cone→选源→下载)与标识符模式(直按 ID 下载)双输入

【Agent 工具整合】26 → 24
- 新增 find_observation:跨源×跨产品×双模式统一观测下载,取代 find_spectrum
- catalog_operation 升级为 6 合 1(search/describe/query/cone/export/lookup),
  取代独立的 query_vizier + cone_search
- citation_network + library_search 合并为 library.rs

【API 路由】
- 新增 /observation/{search,download,capabilities,list} 命名空间
- 移除 /catalog/{crossmatch,spectrum/download,spectrum/list}
- GET /observation/capabilities 暴露 registry 能力清单,前端动态渲染源/产品/版本
  下拉(不再硬编码各源支持矩阵)

【数据库迁移】
- 新表 observation_cache:新增 product 列 + artifacts_json(多文件产物),无 TTL
  (观测数据不可变,区别于 vizier_query_cache 的 7 天 TTL)
- 20260705140001:spectrum_cache 旧数据迁入 observation_cache,单文件→单元素 artifacts

【前端】
- 新 ObservationPanel(988 行):双视图(检索下载 / 缓存库),选项由 capabilities 动态生成
- 新 useObservation hook、ObservationResultCard、observation/constants、utils/apiError

【安全与韧性加固】
- sessions 锁 Mutex → RwLock(读多写少,降低争用)
- 新增 upload_rate_limiter;login_rate_limiter 容量保护(10000 上限,超限清最旧一半)
- bookmarklet API 密钥 SHA-1 → SHA-256;ADMIN_PASSWORD 长度上限 128
- *_TIMEOUT_SECS / EMBEDDING_DIM 非法值告警并回退默认;DB_POOL_SIZE 可配置(原硬编码 5)
- sqlite-vec 注册逻辑下沉至 utils::register_sqlite_vec_extension
This commit is contained in:
fmq
2026-07-07 01:34:02 +08:00
parent a156252bc3
commit 2f1fd19d74
71 changed files with 6229 additions and 4198 deletions
@@ -0,0 +1,23 @@
-- 观测数据下载缓存表(取代 spectrum_cache,支持多产品类型 + 多文件产物)
--
-- 与 spectrum_cache 的关键差异:
-- 1. 新增 product 列:区分 spectrum / lightcurve / photometry / image
-- 2. UNIQUE 加入 product:同一源的同一标识符可同时缓存光谱与光变
-- 3. file_path/file_format 改为 artifacts_json:一个逻辑产物可对应多个物理文件
-- (如 Gaia EPOCH_PHOTOMETRY 的 G/BP/RP 三波段各一个 FITS
-- 4. 观测数据不可变,无 expires_at(与 vizier_query_cache 的 TTL 缓存不同)
--
-- 兼容:spectrum_cache 旧数据由 20260705140001_migrate_spectrum_to_observation.sql 迁移
CREATE TABLE IF NOT EXISTS observation_cache (
id INTEGER PRIMARY KEY AUTOINCREMENT,
source TEXT NOT NULL, -- 'lamost' | 'gaia' | 'sdss' | 'desi' | ...
product TEXT NOT NULL, -- 'spectrum' | 'lightcurve' | 'photometry' | 'image'
source_id TEXT NOT NULL, -- obsid / source_id / plate-mjd-fiber / targetid...
ra REAL,
dec REAL,
artifacts_json TEXT NOT NULL, -- [{"path","format","size"}] 多文件产物
meta_json TEXT, -- z/class/band 等元信息
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
UNIQUE(source, product, source_id)
);
CREATE INDEX IF NOT EXISTS idx_obs_cache_source ON observation_cache(source, product, source_id);
@@ -0,0 +1,22 @@
-- 将 spectrum_cache 旧数据迁移到 observation_cache,并将单文件转成单元素 artifacts 数组
-- 仅当 spectrum_cache 存在且有数据时执行;迁移后旧表保留(由后续清理迁移删除)
INSERT OR IGNORE INTO observation_cache (source, product, source_id, ra, dec, artifacts_json, meta_json, created_at)
SELECT
source,
'spectrum' AS product,
source_id,
ra,
dec,
json_object(
'path', file_path,
'format', file_format,
'size', 0,
'band', NULL,
'original_name', NULL
) AS artifacts_json,
meta_json,
created_at
FROM spectrum_cache
WHERE EXISTS (
SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'spectrum_cache'
);