Hacktoberfest 2026:维护者为十月标记出来的 issue,仍然开放、适合新手。 浏览 Hacktoberfest issue

Connection registry is process-global: a multi-project server reuses one project's warehouse config (and, since #1204, its resolved store path) for another

未关闭
#1,237 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

还没有人认领这个 Issue。

评估

难度
4/5
预计耗时
3-5 天
新手友好度
38/100
Issue 类型
缺陷
描述清晰度
描述清楚
活跃度
活跃
技术栈
sql, typescript
领域
backend, databases

调研方向

从 packages/opencode/src/altimate/native/connections/registry.ts 开始,重点查看模块作用域的 configs/connectors/pending/loaded 声明,以及 load()、ensureLoaded()、resolveStorePaths()、get()、list()、test()、add()、remove()、reload() 和 reset()。issue 所说的 done 意味着 registry 状态按 Instance.directory/InstanceState 进行作用域隔离,并且当一个 instance 消失时会清理缓存的 connector,而不是在整个进程范围内共享。

由索引模型根据 Issue 内容生成。

描述

Summary

The native connection registry keeps its entire loaded-config state at module scope, with a one-shot loaded latch. In a long-lived server process that handles requests for more than one project directory, the first request's load() wins permanently — every later request for a different project reuses the first project's connection configs and connectors, and never reads the second project's own .altimate-code/connections.json.

If two projects define a connection under the same name (a plausible default such as warehouse or local), project B's sql_execute silently runs against project A's database.

Where

packages/opencode/src/altimate/native/connections/registry.ts:

registry.ts:24  let configs = new Map<string, ConnectionConfig>()
registry.ts:27  const connectors = new Map<string, Connector>()
registry.ts:30  const pending = new Map<string, Promise<Connector>>()
registry.ts:33  let loaded = false

load() (:85-103) clears and repopulates configs from Instance.directory-relative config files, then latches loaded = true at :103. ensureLoaded() (:107) is a no-op once the latch is set. In a server that serves multiple project directories from one process, the first load() result is reused for all subsequent projects — including connection names, credentials, and (see below) resolved absolute store paths.

Pre-existing, but recently made worse

This sharing mechanism is pre-existing — confirmed by diffing origin/main before PR #1204 (commit d9292ecfe7): the identical module-scope configs/connectors/loaded pattern with the identical one-shot latch already existed (keyed off process.cwd() instead of Instance.directory). #1204 did not create it.

What #1204 (merged as 1caa234ff9) changed is the failure mode. Before #1204, a leaked config's relative store path was resolved lazily at connect() time against the then-current process.cwd() — ambiguous, and in a server that never chdirs this usually just errored or opened nothing meaningful. After #1204, resolveStorePaths() (:109-129, called at :175 and :620) pre-resolves and caches an already-absolute store path into configs at first-load time. So the same pre-existing leak now hands project B's request a deterministic absolute path to project A's real store — project B silently reads and writes project A's actual data rather than failing ambiguously.

The leak mechanism is old; the escalation from "fails ambiguously" to "silent cross-project read/write" landed with #1204.

Scope of impact

  • Not triggered by normal single-project CLI usage (one process serves one project; the registry only ever holds that project's config).
  • Triggered when a long-lived process serves multiple project directories through this registry and same-named connections exist across them.

Minimal fix (needs its own design PR)

Move configs, connectors, pending, and loaded off module scope into InstanceState, keyed by Instance.directory, with connector cleanup wired into the instance finalizer so cached native handles (DuckDB/SQLite file locks, SSH tunnels) are closed when an instance goes away rather than leaking for the process lifetime. ensureLoaded() / load() / get() / list() / test() / add() / remove() / reload() / reset() all need to read/write the current instance's slice rather than the shared module map — a real refactor, not a patch.

Citations

registry.ts:24,27,30,33 (module state), :69-75 (projectRoot()), :85-103 (load()), :107 (ensureLoaded()), :109-129 (resolveStorePaths()), :175 and :620 (call sites).

Surfaced by review threads on #1204 (cubic + codex + coderabbitai all flagged the same pattern, "make registry state instance-scoped"). #1204 merged before these were addressed; this issue tracks the follow-up.

主要语言
TypeScript
星标
813
派生
134
平均合并
2 天 2 小时
30 天内合并 PR
67

贡献指南

打开贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

AltimateAI/altimate-code 的其他 Issue

查看 AltimateAI/altimate-code 的全部 Issue

相似的 Issue

更多 TypeScript Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。