Commit Graph
138 Commits
Author SHA1 Message Date
chick a6867bc9cb docs(ios): §7 配对实现修订——--pair 窗口、agent 生成 bearer、握手后全量上报 2026-09-16 11:43:52 +08:00
chick 99752bd355 docs(ios): 中继实现修订——长轮询替 WSS、响应方向临时×临时、agent 本机登录 2026-09-16 09:15:26 +08:00
chick 95c653b3d3 docs(ios): 双通道(内网直通 + 公网中继)设计稿
- 拓扑:每节点一个 agent,只出站连中继,出口硬编码回环,把 SSRF 爆炸半径从整个内网收缩到单节点
- 信封:Ed25519 签名覆盖 nodeID/reqID/ek 防改投与错配,临时-静态 DH 加密,并写准前向安全的实际边界
- 授权:中继不得授权任何事,危险写确认改由手机产生、agent 校验,说明服务端签发令牌为何不可搬用
- iOS:引入 InstanceEndpoint 与 NodeTransport,origin 同时承担目标/去重键/Cookie 绑定三职的迁移路径
- 复用既有 ProblemDetails、FRESHNESS_STATUSES 与 server/proxy 策略,并要求策略抽为共享 JSON 防漂移
2026-09-15 14:55:45 +08:00
chick 802ddd1102 release(ios): 0.2.2 构建 10 修消息卡空洞、标签胶囊假宽与表单标题层级
- 消息卡片删除按钮移出正文行,改用 overlay 悬在右侧,44pt 点击区不再把行撑高
- 批量标签胶囊由等宽栅格改为流式布局,新增 AIFlowLayout 并让节点页复用同一实现
- 设置页应用信息补「构建」一行,版本号全程不带括号
- 添加实例与发送消息两张表单表统一行内标题,去掉大标题留下的空白带
- 节点空态文案改为「节点未返回设备信息」,与量表条实际返回的数据不矛盾
- 图标石墨底、面板阴影与插槽统一压暖 3~4 级,全图 0 蓝色像素
2026-09-15 13:03:23 +08:00
chick c3d17b3daf release(ios): 0.2.2 构建 9 修复消息发送遮挡并中性化石墨灰阶
- 消息中心发送入口从被标签栏盖住的底部操作条移到导航栏右侧,发信恢复可用
- 停用态主按钮保留主色淡底与同色描边,与次级按钮拉开层级
- 消息行删除改安静线性图标,去掉一屏红块
- 缺数据读数统一为短横,卡片延迟补空格单位
- 中性灰阶改为严格 R=G=B,浅色主题不再读出冷调;图标石墨底同步去蓝
- 详情页延迟量表改用与卡片同一算法,身份信息值改为右对齐
- 标签加号按钮与输入框同高同圆角
2026-09-15 08:19:18 +08:00
chick 9ad0c46088 release(ios): 0.2.2 构建 8 中性化批量标签禁用态并去蓝化图标底色
- FleetTagBatchSheet:无勾选时标签胶囊不再走 Button 禁用态(系统会压成灰块,像加载
  失败),改为中性标签原样渲染;覆盖度文案留空,图标改 tag;新建标签输入与按钮置灰
  并补一句「勾选节点后即可新建标签并批量贴上」。
- 应用图标:底色与插槽从偏青绿的石墨(R>G=B,亮壁纸上读作蓝)改为严格等值中性灰
  20/19/10,金色跨度拉大(#FADD98 -> #C78D2F)去掉芥末黄塑料感;AppIcon.svg 同步。
- 版本号:marketing 0.2.2 不带括号,构建号 7 -> 8;文档里 0.2.x (N) 一律改写为
  「0.2.x 构建 N」,README 与现行说明同步。
2026-09-15 05:07:03 +08:00
chick 36ce791215 polish(ios): 中性化标签与方向胶囊并收紧详情头部间距
- AITag 拆为两类:不传状态色时是中性归类胶囊(tile 底、发丝描边、墨字,可带 10pt 图标),
  传状态色时才用 14% 色雾与 30% 描边。颜色只服务状态语义。
- 详情页标签改用 AITag(tag, systemImage: "tag"),与节点卡片同一枚形状;头部 VStack 间距
  14 -> 12,读数格 minHeight 62 -> 56,加载完成后不再明显小于下方卡片。
- 消息中心「收件 / 发件」由绿/墨配色改回中性胶囊配 arrow.down.left / arrow.up.right,
  绿色重新只表示健康状态。
- 批量标签表在无勾选时给出「先在节点列表勾选要归类的节点」,不再留空白行。
- 文档:0.2.2 增量记录与校验值更新为 0e4ffb74…;版本号后不再带括号,
  0.2.0/0.2.1/0.2.2 与 README、现行说明统一改写为「0.2.x 构建 N」。
2026-09-15 03:56:31 +08:00
chick eb880e0d14 release(ios): 0.2.2 移除分组改用标签归类并完成石墨配色重构
- 删除分组实体:分组视图/编辑器/仓储与 groupId 全部移除,升级首启清理
  instance-groups.json 与 fleet.groupMode
- 新增批量标签表:三态覆盖度(未贴 / N/M / 全部),整批加减与新建标签
- 配色重构,全应用零蓝色:石墨墨色承担主操作与选中态,颜色只留给状态语义;
  浅色改中性冷灰,深色改低明度石墨三层
- 选中态改实心主色 + onPrimary,替换不可读的低透明度色雾(主题块、图例胶囊)
- 应用图标重做为扁平石墨底 + 黄铜 SIM 面板,参数化光栅化脚本与参考稿
- 运行概览:检测进度并入副标题,读数栅格固定八格两行并保留不可用占位
- 实例详情:仪表改两列发丝线栅格,缺数据留轨道,修掉头部高度回弹;
  补齐设备名称/存储总量/可用存储/使用率四个字段名
- 版本号显示去掉括号,设置页只显示 0.2.2
- 文档:新增 docs/ios-native-0.2.2.md,同步 ios-native.md 与两处 README
2026-09-15 02:23:24 +08:00
chick ec3ffb9db3 docs(ios): 同步 0.2.x 实况文档与规划记录 2026-09-14 18:22:23 +08:00
chick 3607eddc9f release(ios): 发布 0.2.1 并重构图标与界面细节
- 应用图标改用与 Web favicon 同源的扁平标记,金色 SIM 卡体加三格递增信号,29pt 下仍可读
- 标签统一为胶囊形状,提高深色主题下的描边权重,避免标签在暗色下消失
- 消息卡片与详情分区卡片收紧行距,单屏信息密度明显提升
- 详情头部指标精简为 4 行,数据模块改为单条读数
- 批量选择勾选框移出名称区域,工具栏控件统一为等高 34pt
- 分组编辑器改为点选即生效,移除说明文字与常驻禁用按钮
2026-09-14 16:30:39 +08:00
chick 27687868ef fix(ios): unify toolbar controls and release build 3 2026-09-13 01:15:41 +08:00
chick 2ff23d1fb0 fix(ios): improve fleet overview and app identity
- Show stable group health in a fixed 2x2 metric grid
- Add link-chain state to fleet cards and parse hardware/control/SIM/cellular
- Replace the wrapped icon with a full-bleed app icon
- Bump the IPA build number
2026-09-13 00:46:26 +08:00
chick 409345cba3 docs(ios): document the 0.2.0 release 2026-09-12 17:18:54 +08:00
chick e01a105645 feat(ios): simplify navigation and ship 0.2.0
Move diagnostics into settings, remove the app-local notification module, unify the global theme switcher, refine privacy copy and the instance detail experience, and rebuild the app icon.
2026-09-12 17:10:02 +08:00
chick 20632be86a feat(ios): unify action hierarchy and surfaces
Refine primary and toolbar actions, align row buttons, normalize status surfaces, and split storage from destructive cleanup. Verified with Swift tests and the simulator build.
2026-09-12 16:15:57 +08:00
chick 0f2866a853 feat(ios): refine native interface and app icon
Unify bottom actions, selection controls, navigation structure, spacing, and theme colors across iOS pages. Replace the app icon with a higher-contrast native-style asset and include its source SVG.
2026-09-12 14:09:02 +08:00
chick 31b2f33d15 feat(ios): refine adaptive theme and unified controls 2026-09-10 03:19:03 +08:00
chick c841748971 feat(ios): unify list cards and loading states 2026-09-10 01:35:12 +08:00
chick 995206ac23 feat(ios): refine native ui controls 2026-09-09 11:14:39 +08:00
chick c568e496b2 feat(ios): add native settings and storage controls 2026-09-09 02:06:34 +08:00
chick 9c3186252b feat(ios): add cross-instance log center 2026-09-09 01:53:40 +08:00
chick cf187e42fa feat(ios): add cross-instance notification center 2026-09-09 01:13:45 +08:00
chick 84ec3678c0 feat(ios): add device details and reliable ipa build 2026-09-09 00:46:28 +08:00
chick 7778693807 feat(ios): add cross-instance message center 2026-09-09 00:18:56 +08:00
chick 54eb8dcb86 feat(ios): add native app foundation and unsigned ipa build 2026-09-09 00:05:51 +08:00
chick fda3e11f1e docs: add iOS native IPA foundation plan 2026-09-08 21:22:38 +08:00
chick 1caf6985ff docs: add iOS native IPA design 2026-09-08 20:57:54 +08:00
chick 001659ed91 style(web): unify panel, group and state controls
Standardize panel actions, group filters, segmented modes, workbench tabs, message filters, identity controls and privacy toggles on the shared button scale. Add cascade-aware tests so stale compact sizes and low-contrast states cannot return.
2026-09-08 19:58:10 +08:00
chick bfe5025943 style(web): close control-system gaps found in the deep sweep 2026-09-08 08:02:01 +08:00
chick c0adbcbc8a style(web): unify accessible control system 2026-09-08 01:00:22 +08:00
chick 61a5aee48d fix(events): close review gaps found in the follow-up sweep
- deletion flow emitted job/instance envelopes before the transaction that
  closed the job rows; subscribers refetching on the notification saw
  status 'running' with no further event. Emits now happen after commit,
  including the failure path
- interrupted-deletion sweep now emits job envelopes with the job's real
  request_id (it previously stayed silent while the secure-execution sweep
  already emitted)
- verified during the sweep: backup restore validation re-derives the
  expected schema via migrateDatabase, so migration 18 is automatically
  covered; no tables reference audit_events or operation_preparations, so
  the retention deletes cannot trip FK constraints
2026-09-07 05:57:35 +08:00
chick 70e598208a perf,feat(events),ops: third optimization pass
Overview cold start:
- InstanceResourceService persists every live fetch into status_snapshots
  (category 'resources') and serves a snapshot younger than 2 minutes
  before calling upstream, so the first fleet overview after a restart
  costs zero device requests; instance deletion cleans up via FK cascade

Bounded retention for the four fastest-growing tables (15-minute sweep):
- connection_logs: one row per probe per beat had no automatic cleanup
- audit_events: new pruneBefore (90d)
- operation_preparations: every prepare/retry attempt inserted a row,
  terminal rows now expire after 7 days
- notification_queue: terminal rows pruned after 30 days

SSE events now cover instance lifecycle:
- create/update emit instance envelopes from the routes; the two-phase
  delete emits a job envelope on every terminal transition plus an
  instance envelope when the node actually disappears, so fleet and
  instance views invalidate in real time

Linux ops:
- 'install.sh unit' writes systemd user units for API and gateway with
  Restart=on-failure, 0600 secret injection, and
  MULTI_SIMADMIN_SYSTEMD_UNIT wired so console self-update restarts via
  systemctl -- closing the self-update loop on Linux
2026-09-07 02:43:11 +08:00
chick c1be714ba4 perf,feat(events),hardening: second review pass
Fleet overview N+1:
- InstanceResourceService gains a 30s TTL cache with single-flight
  coalescing; the overview no longer fires six live upstream requests per
  device on every render (plus the re-login storm), while the per-device
  detail route probes live via force:true

Event journal becomes live:
- job terminal transitions (manual executions and the interrupted sweep)
  now append to the journal, so /api/v1/events SSE feeds the frontend's
  invalidation controller that was built but never received events
- journal pruning moves off the append hot path (was an unindexable
  full-table json_extract scan per insert) onto the retention timer

Console auth hardening:
- scrypt upgraded from N=16384 to N=2^16 (OWASP interactive guidance);
  a new password_kdf column records the derivation per row and legacy
  hashes rehash transparently on the next successful login without
  invalidating sessions (migration 18)

Legacy stack:
- instance URL validation blocks IPv4-compatible IPv6 after WHATWG
  canonicalization (::a9fe:a9fe metadata, ::7f00:1 loopback slipped past)
- status polls cool down auto-login for 60s after a failed attempt so a
  stale saved password cannot hammer the device into an account lockout

Build hygiene:
- web bundle splits app (410kB) from vendor (212kB) so framework code
  stays cacheable across releases; stale root package-lock.json removed
  (pnpm is the only lockfile)
2026-09-07 02:20:41 +08:00
chick 29a0eee854 style: apply prettier to the repo's declared format surface 2026-09-07 01:59:24 +08:00
chick 2977f75129 fix: apply security and correctness review findings across both stacks
Legacy panel:
- upstream body reads now carry their own deadline and a 10 MB byte budget;
  a stalled modem can no longer hang /api/status fan-out forever nor OOM
  the proxy (request headers alone had the timeout, bodies had none)
- add X-Frame-Options DENY / CSP frame-ancestors none / nosniff; the panel
  (delete-instance and confirmed-write dialogs) is no longer clickjackable
- only send a JSON content-type when the API console request has a body, so
  payload-less dangerous writes stop failing with 400 and burning the
  one-use confirmation token
- register a form-urlencoded parser (the proxy branch was unreachable) and
  drop the multipart parser that buffered up to 60 MB before rejecting;
  bodyLimit drops to 2 MB; framework-level 415 keeps the stable error body
- remove /api/sms/send from readable paths: GET bypassed the write
  confirmation for a send endpoint
- /api/instances/:id/login maps upstream failures to a stable 502 instead
  of leaking raw error text
- guard MULTI_SIMADMIN_TIMEOUT_MS parsing (NaN aborted every request);
  prune dead code (buildClients, cookie expando no-op)

Control plane:
- deleting a notification channel detaches it from rules instead of leaving
  dangling ids that made every referencing rule unreadable and silently
  dropped future notifications; rule reads tolerate unknown ids
- startup sweep resets notification_queue rows stranded in 'sending' by a
  crash (mirrors the sms outbox sweep); terminal outbox rows are pruned on
  the retention timer
- /api/v1/metrics no longer emits operator-assigned node names on the
  session-free scrape; login limiter map is bounded and pruned; Secure
  cookie honors the gateway-declared x-forwarded-proto
- webhook delivery sets redirect: manual (signed payloads are not replayed)
- SMTP envelope sender is validated against CR/LF smuggling
- scheduled reboots with delaySeconds != 3 fail fast at the dispatcher with
  a clear reason instead of burning every retry; contract narrowed to the
  pinned baseline
2026-09-07 01:57:47 +08:00
chick 236e78327c feat(console-update): systemd restart launcher for Linux supervision
Linux deployments under a systemd unit can now use the online update
panel: MULTI_SIMADMIN_SYSTEMD_UNIT (+ optional _SCOPE=user|system) hands
the restart to systemctl; createPlatformRestartLauncher picks launchd on
macOS and systemd on Linux, degrading to 'unsupported' otherwise.
2026-09-07 01:38:23 +08:00
chick 3c5971e167 feat(installer): support Linux hosts with XDG data root and ss port probe
- platform gate accepts Darwin and Linux; other platforms are refused
- default install root follows each platform's convention
  (~/Library/Application Support vs ~/.local/share)
- LAN IP discovery uses ip -4/hostname -I on Linux, ipconfig on macOS
- port occupancy checks fall back from lsof to ss
- API process gets MULTI_SIMADMIN_SECRET_BACKEND pinned per platform
- README documents the per-platform secret storage
2026-09-07 01:36:04 +08:00
chick e4c4bce75b feat(secrets): add a 0600 file secret backend so production runs on Linux
The production composition hardwired the macOS Keychain (/usr/bin/security),
which made Linux deployment impossible. Now:

- SecretStore gains a stable provider identity persisted in
  secret_references.provider; services stop hardcoding 'macos-keychain'
- shared reference codec (secret-reference.ts) understands both
  keychain:// and secret-file:// references
- FileSecretStore: single 0600 JSON map under the data root, atomic
  temp+rename writes, serialized in-process, same validation envelope
- production composition picks the backend via
  MULTI_SIMADMIN_SECRET_BACKEND (default: Keychain on darwin, file store
  elsewhere) and readiness probes the matching backend
2026-09-07 01:32:07 +08:00
chick c57dc81e42 fix: finish cross-platform test parity while keeping POSIX deployment semantics
- cutover readState: enforce 0600 mode bits only on POSIX (Windows ACLs
  govern access; chmod is a no-op there)
- backup activation: skip the read-only-handle fsync on win32; the staged
  rename-over-open-WAL tests keep running on the POSIX deployment targets
- test-fixtures: normalize fixture paths to POSIX separators before
  comparing with manifest entries
2026-09-07 01:18:44 +08:00
chick 96dd9e2ba6 chore: pin LF line endings via .gitattributes
Windows checkouts previously materialized CRLF, breaking every pinned
sha256 snapshot check in operation-registry and test-fixtures.
2026-09-07 01:10:19 +08:00
chick 4f42a6f835 fix: make cutover restart argv upgrade-safe and tests platform-honest
- cutover-orchestrator: restart via 'node --import tsx' (matching install.sh)
  instead of a hardcoded .pnpm/tsx@4.22.4 loader path that breaks on tsx bumps
- production-gateway: use process.execPath for the legacy-start fixture;
  POSIX-only 0600 mode assertion now win32-guarded
- cli-runtime + installer suites: skip where they require POSIX-only
  process-group SIGTERM, lsof, or /bin/sh
- fixture-safety: fall back to config.example.json when config.json is absent
  on a fresh clone
2026-09-07 01:09:49 +08:00
chick eed134a25c fix: honor underscore-unused convention and make durability fsyncs cross-platform
- eslint: respect the repo's existing _-prefix convention for unused vars
- phase-one-blockers: derive projectRoot via import.meta.dirname so Windows
  checkouts stop producing C:\C:\... paths
- backup/release-evidence/cutover-orchestrator: skip POSIX-only directory
  fsync on win32 and fsync read-only handles through a writable handle
2026-09-07 01:07:16 +08:00
chick f6319374cd feat(web): add console update panel, system maintenance path and connection settings UI
- Add online update workflow with plan, backup and install states.

- Expose maintenance paths, component backup jobs and connection authorization modes.

- Align auth and automation screens with the fused control plane.
2026-09-07 00:45:44 +08:00
chick 6d251dab7b feat(web): fuse Hub device modules into instance panels with SMS aggregation
- Consolidate cellular, eSIM, network and device module interactions.

- Add aggregate SMS workflows and identity-aware action controls.

- Extend SMSC privacy handling and module action icons.
2026-09-07 00:45:38 +08:00
chick 864e1bd90c feat(web): rebuild fleet page with Hub-style identity guard and context actions
- Surface device identity state, carrier details and upstream link health.

- Add fleet-level identity monitoring and restart/baseband context actions.

- Apply consistent notification scoping across fleet views.
2026-09-07 00:45:28 +08:00
chick 635527dd26 feat(api): integrate identity, notification scope and connection settings into control plane
- Wire identity, metrics and update services into the assembled API.

- Add connection authorization modes and scoped console authorization.

- Preserve notification group IDs for filtered delivery.

- Extend maintenance, backup, resource and module flows with runtime metadata and upstream safety.
2026-09-07 00:45:18 +08:00
chick 7168e9dba2 feat(api): add online console update with pre-install backup
- Add console update planning, download validation and staged installation.

- Create a component backup before applying online updates.

- Expose controlled update routes from the production control plane.
2026-09-07 00:44:58 +08:00
chick 961eb928c4 feat(api): add device identity guard and Prometheus metrics
- Persist device identity observations and expose fleet identity summaries.

- Block device control actions when identity verification fails.

- Add metrics collection and a Prometheus scrape endpoint.
2026-09-07 00:44:51 +08:00
chick 8406f14469 feat(contracts,automation): add multi-group scopes, SMS macros and operator registry
- Allow scheduled operations to resolve multiple device groups.

- Add reusable SMS time and random-value macros.

- Add China operator PLMN metadata shared by API and UI.
2026-09-07 00:44:33 +08:00
chick 8b7df8cb65 fix(instances): release the hub binding before forgetting a node
Deletion now follows the published contract: prepare returns the one-time
token and the console spends it on DELETE /api/v1/instances/:id with
If-Match, where the generic execute endpoint had been rejecting it as an
operation the safe transport cannot replay.

An online device is told to release its own binding first. A refusal keeps
the record and reports UNBIND_FAILED on the job item so the console can say
why the node is still there; a node that never answers a heartbeat is
forgotten locally.
2026-09-05 19:52:27 +08:00