Skip to content

About

C/S cross-device data access layer — one server endpoint routes to all your machines (Mac/PC/NAS/Linux). Read-only files + SQLite + vector search.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Local Data Bridge

一个 C/S 架构的跨设备数据接入层。任何消费方只认一个 Server 地址,Server 自动路由到对应设备拿数据回来。

适合「多台机器(Mac / Windows PC / NAS / Linux 小主机)各有本地数据,互相够不着」的场景——让知识库里的 agent、脚本、人,都能像查本地数据一样查所有设备的数据。

整理人:小虾子 · 日期:2026-06-27


1. 架构

                消费方(AI agent、脚本、人)
                          │
                     统一入口
                          │
                 ┌────────▼────────┐
                 │  Bridge Server   │   唯一入口:注册中心 + 心跳 + 路由转发
                 │  Ubuntu .33:9100 │
                 └──┬──────┬─────┬──┘
                    │      │     │
               ┌────▼┐ ┌──▼──┐ ┌▼────┐
               │Mac C│ │PC C │ │NAS C│   每台设备一个 Client
               └─────┘ └─────┘ └─────┘
角色 职责
Server 唯一入口:注册中心 + 心跳管理 + 配置管理 + 路由转发
Client 扫描本地数据源 → 注册到 Server → 执行 Server 下发的查询指令
消费方 只认 Server 地址,不关心数据在哪台机器

请求链路:消费方 → Server(REST)→ 路由定位 source/db 所在 Client → 转发到 Client /exec → Client 调用对应模块 → 结果原路返回。


2. 目录结构

local-data-bridge/
├── server/                 # Server 端
│   ├── server.py           # 启动入口
│   ├── app.py              # flask 应用(消费方 REST API + 注册/心跳端点)
│   ├── registry.py         # Client 注册表 + 心跳管理 + 数据源索引
│   ├── router.py           # source/db → Client 路由 + 转发
│   └── config.py           # server YAML 解析
├── client/                 # Client 端
│   ├── client.py           # 启动入口
│   ├── app.py              # flask 应用(POST /exec)
│   ├── executor.py         # 分发 (module, action) 到数据模块
│   ├── scanner.py          # 扫描配置构建模块 + 汇总上报源
│   ├── registration.py     # 注册 + 心跳后台线程
│   └── config.py           # client YAML 解析
├── modules/                # 数据模块(可扩展)
│   ├── files.py            # 文件:读 / 列 / 全文搜索
│   ├── sqlite.py           # SQLite:自动发现表结构 / 只读查询
│   └── _template.py        # 新模块模板(Phase 2 参考)
├── shared/                 # 公共层
│   ├── protocol.py         # 协议常量 + 统一响应 + 异常 + SQL 只读校验
│   ├── config.py           # YAML 加载工具
│   ├── auth.py             # token 认证
│   └── httpclient.py       # urllib 封装(转发 / 注册)
├── config/                 # 配置示例
│   ├── bridge-server.yaml
│   ├── bridge-client-mac.yaml
│   ├── bridge-client-pc.yaml
│   └── bridge-client-nas.yaml
├── tests/                  # 测试套件(266 用例,100% 覆盖)
├── requirements.txt
└── pyproject.toml          # pytest + coverage 配置

3. 安装

需要 Python 3.8+(仅依赖标准库 + Flask + PyYAML)。

pip install -r requirements.txt

开发/测试再装:

pip install pytest pytest-cov

4. 启动

Server(Ubuntu .33)

python server/server.py --config config/bridge-server.yaml
# 可覆盖:--host 0.0.0.0 --port 9100

Client(每台设备)

python client/client.py --config config/bridge-client-mac.yaml
# 可覆盖:--host 0.0.0.0 --port 9101 --no-register

各平台后台运行

平台 方式
macOS / Linux nohup python client/client.py --config ... > bridge.log 2>&1 &,或写 systemd unit(Type=simple + Restart=always)
Windows 任务计划程序(登录时启动,pythonw.exe 后台运行),或 start /b pythonw client\client.py --config ...
Synology NAS 任务计划(触发「开机」),或套件容器;注意 Python 版本需 3.8+

5. 配置

Server(bridge-server.yaml)

server:
  host: 0.0.0.0          # 内网监听;仅本机访问改 127.0.0.1
  port: 9100
  token: "bridge-secret-token-change-me"   # 消费方/Client 访问 Server 的凭证

auth:
  clients:                # 登记 Client 及其 client_token(Server 转发时携带)
    mac: "mac-client-token"
    pc: "pc-client-token"
    nas: "nas-client-token"

Client(bridge-client-*.yaml)

server:
  url: http://192.168.5.33:9100
  token: "bridge-secret-token-change-me"   # 与 Server 的 server.token 一致

client:
  identity: mac            # mac / pc / nas
  listen_host: 0.0.0.0
  listen_port: 9101        # 接收 Server 转发查询的端口
  client_token: "mac-client-token"   # 与 Server 的 auth.clients.<identity> 一致

modules:
  files:
    enabled: true
    mounts:
      - name: hermes
        path: /Users/jovi/.hermes
        access: read
  sqlite:
    enabled: true
    databases:
      - name: kanban
        path: /Users/jovi/.hermes/kanban/boards/backlog/kanban.db
        readonly: true

Windows 路径用正斜杠 / 或双反斜杠 \\;中文路径全链路 UTF-8。


6. API(消费方视角)

所有请求发往 Server,携带 Authorization: Bearer <server.token>(/health 除外)。

基础

Method Path 说明
GET /health Server 状态 + 所有 Client 在线状态(无需认证)
GET /sources 所有数据源(哪些在线哪些离线)

文件

Method Path 说明
GET /files/{source}?path=xxx&offset=0&limit=100 读文件(按行分页)
GET /files/{source}/list?path=xxx 列目录(名称/类型/大小/修改时间)
GET /files/{source}/search?q=xxx&path=xxx 全文搜索(返回文件+行号+匹配行)

SQLite

Method Path 说明
GET /sqlite 所有数据库列表
GET /sqlite/{db}/tables 列出表(自动从 sqlite_master 发现)
GET /sqlite/{db}/schema/{table} 建表语句 + 字段(PRAGMA table_info)
POST /sqlite/{db} 执行只读查询,body:{"sql": "SELECT ..."}

示例

# 读文件
curl -H "Authorization: Bearer bridge-secret-token-change-me" \
     "http://192.168.5.33:9100/files/hermes?path=notes.md"

# 列目录
curl -H "Authorization: Bearer ..." \
     "http://192.168.5.33:9100/files/hermes/list?path=sub"

# 全文搜索
curl -H "Authorization: Bearer ..." \
     "http://192.168.5.33:9100/files/hermes/search?q=关键词&path="

# 查 SQLite
curl -X POST -H "Authorization: Bearer ..." -H "Content-Type: application/json" \
     -d '{"sql":"SELECT id,title,status FROM tasks LIMIT 10"}' \
     "http://192.168.5.33:9100/sqlite/kanban"
# → {"status":"ok","data":{"columns":["id","title","status"],"rows":[[1,"t1","pending"],...]}}

错误处理

场景 HTTP 返回
Client 离线 503 {"error":"source offline","client":"pc"}
数据源不存在 404 {"error":"source not found"}
SQL 非 SELECT 400 {"error":"only SELECT allowed"}
认证失败 401 {"error":"unauthorized"}
文件不存在 404 {"error":"file not found"}
路径穿越 400 {"error":"path traversal not allowed"}

7. 关键设计

  • 配置驱动:挂载什么、暴露什么,改 YAML 不改代码。
  • 模块化:文件 / SQLite 各自独立,按 enabled 加载。Phase 2 加新模块不需改核心——参照 modules/_template.py 实现模块协议(name + execute(action, params) + 可选 list_sources()),在 client/scanner.py 的 build_modules 注册一行即可。
  • 自动发现:SQLite 挂上即扫 sqlite_master,无需手写 schema;Client 启动即注册所有源。
  • 只读优先:Phase 1 全部只读。SQLite 双重防护——语义层 is_readonly_select(只允许 SELECT/WITH 单语句、关键字黑名单)+ 运行时 mode=ro 只读连接兜底。文件严格防路径穿越(.. 拒绝 + resolve() 后校验仍在挂载根内)。
  • 热插拔:Client 断线 → Server 连接失败即返 503;超 90s 无心跳标记 offline;Client 重连自动重新注册恢复服务。
  • 内网安全:Server 只绑内网;统一 token 认证(hmac.compare_digest 常量时间比较)。
  • 跨平台:pathlib.Path 统一路径、全链路 UTF-8、不依赖 grep/find(搜索用 pathlib + re)、HTTP 转发用标准库 urllib。

8. 测试

pytest                       # 全部测试
pytest --cov                 # 带覆盖率(目标 98%+)
  • 266 个用例,行+分支覆盖率 100%。
  • 单元测试:shared/*、modules/*、server/registry、server/router(注入 fake HTTP)、client/*。
  • 集成测试(tests/test_integration.py):真实 Server + Client(werkzeug make_server)端到端验证——注册、文件读/列/搜、SQLite 查询、断开 503、重连恢复、SQL 注入拦截、路径穿越拦截、认证。

9. 验收标准对照

标准 状态 说明
Server python server.py 启动监听 9100 ✅ python server/server.py --config config/bridge-server.yaml
Client 自动注册,Server 显示 online ✅ /health 返回 client 在线状态
经 Server 查 SQLite 返回数据 ✅ POST /sqlite/{db}
经 Server 读文件返回内容 ✅ GET /files/{source}?path=
Client 断开 → 503,重连恢复 ✅ 集成测试 test_offline_returns_503_* / test_reconnect_*
Windows Client 注册与被查 ✅ 纯 Python 标准库 + Flask,跨平台一致
SQL 注入防护:非 SELECT 拒绝 ✅ is_readonly_select + mode=ro 双重
跨平台同代码可跑 ✅ pathlib + UTF-8 + 标准库

10. Phase 2 预留

下列接口已在设计中预留,Phase 1 不实现:本地 CLI 转发(lark-cli / xurl)、本地 Python 服务(GA4 报告)、HTTP API 代理。新增时按 modules/_template.py 的模块协议实现,并在 client/scanner.py:build_modules 注册即可,核心代码无需改动。

About

C/S cross-device data access layer — one server endpoint routes to all your machines (Mac/PC/NAS/Linux). Read-only files + SQLite + vector search.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages