feat(vault): seat_group cache columns + retrofit migrations#3
Open
Jakegogo wants to merge 43 commits into
Open
feat(vault): seat_group cache columns + retrofit migrations#3Jakegogo wants to merge 43 commits into
Jakegogo wants to merge 43 commits into
Conversation
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
[aikey-cli] skip claim/delivery for group VKs during sync (no static material → was a spurious 403 + "0 downloaded"); project seat_group_id + parsed group_accounts into the internal team-records emit for the /user web. Refs: - CLI sync group-VK delivery 403 bugfix: https://github.com/aikeylabs/workflow/blob/3eb36d250c0f02ed28ba4753b6fa468d1fcf1b59/CI/bugfix/2026-06-26-cli-sync-group-vk-delivery-403.md - seat-group / OAuth account pool requirement spec: https://github.com/aikeylabs/workflow/blob/3eb36d250c0f02ed28ba4753b6fa468d1fcf1b59/CI/requirements/2026-06-23-oauth-account-pool.md
… group-VK fixes [aikey-cli] connectivity probe handles group VKs — empty VK-level provider_code falls back to supported_providers, and group VKs are no longer skipped on absent local ciphertext (material is proxy-side via channel ③). Refs: - group-VK connectivity-test 503 bugfix: https://github.com/aikeylabs/workflow/blob/9dbdc448e094f7719d9cceb2e4138fe68e015276/CI/bugfix/2026-06-26-vault-test-group-vk-and-error-code.md - seat-group / OAuth pool requirement spec: https://github.com/aikeylabs/workflow/blob/9dbdc448e094f7719d9cceb2e4138fe68e015276/CI/requirements/2026-06-23-oauth-account-pool.md
… loopback probe hijack [aikey-cli] group VKs carry no local key material by design — exempt them in `aikey use` and key_material_reachable (was a misleading "key not delivered"); by-alias VK cache lookup now tries GROUP columns first (seat_group_id was always None on the alias path); loopback probes bypass any external HTTP proxy (NO_PROXY 127.0.0.1) so a non-loopback proxy can't hijack 127.0.0.1 to the wrong aikey-proxy → false 401 (affects all VKs behind such a proxy). Refs: - group-VK + loopback-hijack + path-strip root-cause chain (§78+): https://github.com/aikeylabs/workflow/blob/6306efcd67b597c44e3c87a0e16da61bd6bd9514/CI/bugfix/2026-06-26-vault-test-group-vk-and-error-code.md - seat-group / OAuth pool requirement spec: https://github.com/aikeylabs/workflow/blob/6306efcd67b597c44e3c87a0e16da61bd6bd9514/CI/requirements/2026-06-23-oauth-account-pool.md
[aikey-cli] rename vault cache column / fields seat_group_id → oauth_group_id + retrofit migration; sync/probe/use paths updated. Refs: - oauth_group rename plan (旧→新 mapping, P1–P7): https://github.com/aikeylabs/roadmap20260320/blob/b8f2ab45258cc310f3b90eb03b6b931dcf8e66c6/技术实现/阶段7-企业生产版/20260626-oauth_group-重命名重构-分阶段实施计划.md - seat-group / OAuth pool requirement spec: https://github.com/aikeylabs/workflow/blob/7fc6a809a6af982c001188449dead5cbc3df7682/CI/requirements/2026-06-23-oauth-account-pool.md
…s / test names / trial migrate) [aikey-cli] comment-only seat-group → oauth-group cleanup (field names already renamed). Refs: - oauth_group rename plan (旧→新 mapping, P1–P7): https://github.com/aikeylabs/roadmap20260320/blob/d5280ecb78d50d2539da97123d8b9a6957e74eb2/技术实现/阶段7-企业生产版/20260626-oauth_group-重命名重构-分阶段实施计划.md
[aikey-cli] connectivity persistence/runtime updates Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… web double-slash white-screen) resolve_browse_base_url now trims a trailing slash from both the AIKEY_WEB_URL override and the control_url fallback. A stored control_url like `http://host:3000/` joined with the leading-slash deep-link path `/go/<alias>` produced `http://host:3000//go/overview`; the browser reads the leading `//` as a PROTOCOL-RELATIVE URL (`http://go/...`) and history.replaceState rejects it with a cross-origin SecurityError → SPA white-screen. Normalizing at READ time also fixes installs that already stored a trailing-slash control_url, with no re-login or migration. This is the root-cause fix; aikey-control's collapseLeadingSlashes is the front-end defense-in-depth. Adds regression test. Refs: - ak web double-slash SecurityError bugfix: https://github.com/aikeylabs/workflow/blob/2b72651400abb27b90684b500d736fa231c68d16/CI/bugfix/2026-06-30-ak-web-double-slash-securityerror.md Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…s proxy [aikey-cli] _internal query merges group snapshot with live runtime (login_status/current_routed) for vault Refs: - Enterprise OAuth-pool user guide: https://github.com/aikeylabs/workflow/blob/edca0c93c646713c09c6893a76560c2df8a71edb/Docs/enterprise-delivery/OAuth账号池-使用引导.md - Update spec (vault login-status + current-routed): https://github.com/aikeylabs/roadmap20260320/blob/d3bfe4840becdd5bb9a60143577b184613678875/技术实现/update/20260630-保管库-登录态与当前路由账号实时显示.md - Update spec (seat-enroll auto-issue group VK): https://github.com/aikeylabs/roadmap20260320/blob/d3bfe4840becdd5bb9a60143577b184613678875/技术实现/update/20260630-席位组-入组自动签发组VK.md
…l-resp guard [aikey-cli] simplify any_chat_ok branch in connectivity runtime (behavior-equivalent) Refs: - Bugfix: proxy buildBaseEvent nil-resp panic: https://github.com/aikeylabs/workflow/blob/38364749b315fae856c6e7e896799c2aa3e95130/CI/bugfix/20260701-proxy-buildBaseEvent-nil-resp-panic.md - Bugfix: team-oauth still-syncing misleading copy: https://github.com/aikeylabs/workflow/blob/38364749b315fae856c6e7e896799c2aa3e95130/CI/bugfix/20260630-团队oauth-still-syncing-误导文案.md
…K disambiguation [aikey-cli] client cache carries group_alias so aikey use / vault can label which group each VK belongs to Refs: - Spec: RW8 reversal (self-add email+password): https://github.com/aikeylabs/roadmap20260320/blob/342a092b7865b07e16f406d75c763f0b830d1c37/技术实现/update/20260701-员工OAuth自助录入-反转RW8-email密码版.md - Spec: multi-OAuth-group one-VK-each + group-name passthrough: https://github.com/aikeylabs/roadmap20260320/blob/342a092b7865b07e16f406d75c763f0b830d1c37/技术实现/update/20260701-多OAuth组-每组一VK可选与组名透传.md - Bugfix: proxy detachedTransport drops window-cap pre-cut: https://github.com/aikeylabs/workflow/blob/edbb75c0b09b6e8a8f92627068d6a9c60750716c/CI/bugfix/20260701-proxy-detachedTransport-drops-window-cap-precut-dead.md
…ce of truth [aikey-cli] rework merge_group_accounts_live so login_status/current_routed reflect the unified routed pick Refs: - Bugfix: route-drift (part 2, split-truth → poolroute): https://github.com/aikeylabs/workflow/blob/c957d8ae791377abba7b9300ab55cf1a61cdf5e3/CI/bugfix/20260701-分配引擎默认开启-修复加号后路由漂移.md
… usage audit [aikey-cli] reboot PID-reuse lockout fix: pidfile-derived "running" states only produced when the configured port is actually held, so a leftover pidfile whose low PID got reused by a boot daemon falls to read-only OrphanedPort instead of locking the user out; +e2e reboot/PID-reuse cases Refs: - Bugfix: proxy orphaned lockout on reboot PID reuse: https://github.com/aikeylabs/workflow/blob/40eaa28ac5a7ed959fd7306f9c728b3fcc944e07/CI/bugfix/2026-07-01-proxy-orphaned-lockout-reboot-pid-reuse.md
…andoff, install entry unification statusline: pool-account login-required line (reads proxy bypass state, offline-by-design); browser launch via rundll32 on Windows (cmd /c start splits URLs at '&') Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…degraded state surfaces to statusline [aikey-cli] statusline surfaces a "control-plane sync degraded" row (reads proxy sync-health.json, renders live outage duration) + a group-login-required row at receipt-less exit points so a dead sync rail can't stay invisible Refs: - Spec: control-plane SyncRail framework design: https://github.com/aikeylabs/roadmap20260320/blob/ed04caeca75a932f53921f7a3c6ef12b8fa95780/技术实现/update/20260703-控制面同步框架SyncRail-技术方案.md - Spec: group routing-override self-heal persistence + settings linkage: https://github.com/aikeylabs/roadmap20260320/blob/ed04caeca75a932f53921f7a3c6ef12b8fa95780/技术实现/update/20260703-组路由override自愈持久化与settings联动.md - Spec: OAuth group-member login prompt (CLI + login_url): https://github.com/aikeylabs/roadmap20260320/blob/ed04caeca75a932f53921f7a3c6ef12b8fa95780/技术实现/update/20260703-OAuth组成员登录提示-CLI显示与login_url.md
…pe 503, pool cooldown persistence, chk_mpb_target guard [aikey-cli] aikey service status / aikey web status commands + local-server probe; doctor/project feature coverage; account cache prune; README (en/zh) Refs: - Requirement: aikey service-status command: https://github.com/aikeylabs/workflow/blob/fe705f43504cb9eaf9d50516984561dce71d37bd/CI/requirements/2026-07-03-service-status-command.md
…egradation [aikey-cli] group-VK usability by routed-account login state (RoutedState: LoggedIn/NeedsLogin/NoCandidate → active/needs_login/inactive, 待登录防呆); help-text reorg + `aikey status`; commands_service status_summary fix Refs: - Spec: 组VK待登录状态防呆: https://github.com/aikeylabs/roadmap20260320/blob/845685224f712c9c1e511f13f8d32d3032b8d567/技术实现/update/20260703-组VK待登录状态防呆.md
…+ cross-app menu fallback [aikey-cli] Kimi CLI shell integration; codex probe-model self-healing (codex_last_model, self-heals across codex-cli upgrades); unified local-origin console; kimi receipt observability events Refs: - Bugfix: kimi-config-hooks-duplicate-key: https://github.com/aikeylabs/workflow/blob/dceaf38d54b507bfe2145c48fd3713aeea4f4ac9/CI/bugfix/2026-07-04-kimi-config-hooks-duplicate-key.md - Spec: web统一origin本地网关: https://github.com/aikeylabs/roadmap20260320/blob/15c9ff4cb3ddafaf06a960c1fd1e02a344bda2cf/技术实现/update/20260703-web统一origin-本地网关方案.md
/v1/auth/cli/login/exchange returns {access_token,refresh_token,...} with no
status field; the CLI reused the poll DTO (status required) so serde failed with
'missing field status' and the copy-paste fallback login never wrote the vault.
Parse exchange with a dedicated statusless DTO, normalized to approved
client-side. Server protocol unchanged.
Bugfix: workflow/CI/bugfix/2026-07-06-cli-login-token-exchange-missing-status.md
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Codex into OAuth account pool: mechanism + dynamic scheduling + pricing/login fixes
…ervice path) launchd / systemd / the new Windows ScheduledTask all run exactly `aikey proxy start --foreground` with no TTY, but this dispatch only consulted the TTL-gated session cache (try_get) before falling into the interactive prompt — so a boot-after-idle service start hung/errored instead of unlocking. L9 fix A (try_get_unattended, 2026-06-11) was wired into ensure_proxy_for_use only; this extends the same no-TTY raw-store read + verify-then-invalidate discipline to the explicit command, and fails fast with actionable guidance when no credential source exists (previously the no-TTY prompt could hang a service task forever). Env vars (AIKEY_MASTER_PASSWORD / AK_TEST_PASSWORD) keep precedence; interactive behavior is byte-identical. Found by 2026-07-07 Windows/Mac parity audit (P1-1 leg). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…dows/Mac parity (alpha4) [aikey-cli] binding-material guard + bind audit (WARN on write-fail); web unlock-state CLI side; profile-activation / ui-select / shell-integration adjustments Refs: - Spec: 绑定材料守卫 + Web 解锁态全量 sync: https://github.com/aikeylabs/roadmap20260320/blob/6dfff14/技术实现/update/20260706-绑定材料守卫与Web解锁态全量sync.md - Designpattern: web-read-triggers-nonblocking-sync: https://github.com/aikeylabs/workflow/blob/260d6d4c52036d36c12bc8e360ad4861bc7d59cd/CI/designpattern/web-read-triggers-nonblocking-sync.md
Two unguarded stdin reads in `aikey login` hung forever when the process
was spawned without a terminal (script / service / web bridge):
1. The Control Panel URL prompt — now behaves like json_mode with no
TTY: takes the default and says so, instead of reading a silent pipe.
2. The post-expiry "Paste token" fallback — the poll loop runs the full
server-issued expires_in window (~1h), then `if !json_mode` dropped
into read_line with no TTY check. This is the exact shape of the live
`aikey login` process found hung >1h on the Windows box. Now gated on
stdin being a terminal; the existing non-interactive error path
("Use --token for non-interactive login") takes over.
Parity audit 2026-07-07 P2-5. Interactive behavior unchanged.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…dows/Mac parity (alpha4) [aikey-cli] app install + watch command adjustments (Windows/Mac parity)
Live incident (2026-07-07, Windows box): a proxy started from an admin/SSH (elevated) session is healthy, with pidfile + sidecar meta correctly naming it — yet every NORMAL console's status / ensure-running / wrapper preflight reported "orphaned (port held by something we cannot manage)" and refused to route. Reproduced 100%: same second, same pid — elevated probe says running(healthy), Medium-IL probe says orphaned. Any customer who installs from an admin PowerShell hits this on every regular terminal afterwards. Root cause: Windows process_alive treated EVERY OpenProcess failure as "process dead", but ERROR_ACCESS_DENIED means "exists, no permission" (an elevated process's DACL grants only Administrators+SYSTEM; the filtered token's Administrators group is deny-only). The unix branch already handles the analogous EPERM as alive — the Windows port simply dropped that semantic. Layer 1 then took classify_dead_pid → port held by the "dead" pid → OrphanedPort/PortHeldByExternal, whose hint sent users hunting a nonexistent rogue listener. Fix, in three aligned pieces: - process_alive (Windows): ERROR_ACCESS_DENIED → alive (EPERM parity). - New proxy_proc::process_open_denied() — one neutral interface, per-OS bodies (EPERM / ERROR_ACCESS_DENIED) — so the decision tree can tell "identity UNVERIFIABLE (permission)" from "verified NOT ours". - New OrphanReason::OwnershipUnverifiablePermission + quorum path: when identity is unverifiable by permission but the readable evidence agrees (meta parses ∧ meta.pid == pidfile pid ∧ port owner == pid ∧ /health 200) classify Running — status shows the truth and preflight routes again. Anything short of the quorum → OrphanedPort with an elevation-aware hint (manage/stop from an elevated terminal, then `aikey proxy start` here), never the misleading external-holder text. birth_token stays uncompared (that is the very permission denied); kill paths remain physically blocked by the same OS permission, so the weaker classification cannot make Layer 2 signal a stranger. Fences: hint-wording pins, quorum-miss classification, unix EPERM alignment probe against pid 1, open-denied-false-for-self. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… rules The regression pins from the 2026-07-01 fix caught it immediately: the new open-denied path classified a recycled PRIVILEGED pid (init/launchd after reboot — exactly an open-denied pid) with a FREE port as OrphanedPort, re-introducing the start/stop lockout. Rework classify_permission_denied_pid to be port-occupancy first, mirroring classify_alive_unowned_pid: port free → Crashed (recoverable); held by a third pid → PortHeldByExternal naming the real listener; only when the denied pid itself holds the port does the elevated-proxy quorum run. Fences updated + new arm test. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Lateral sweep of the 2026-07-07 window-flash class: this was the only in-tree spawn that both omits window suppression and creates a LONG-LIVED console-subsystem child (aikey-proxy). If the spawning aikey process ever runs console-less (web-bridge / doctor auto-restart / service contexts), the proxy would materialize a persistent terminal window on the desktop. CREATE_NO_WINDOW composes with the existing CREATE_NEW_PROCESS_GROUP and — unlike the deliberately-rejected DETACHED_PROCESS — keeps handle inheritance, so the stderr→startup-log redirection is unaffected. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Lateral sweep of the P2-5 hang class (unguarded io::stdin().read_line on a silent-but-open stdin) found two live HANG-RISK sites; both now bail cleanly when stdin is not a terminal: 1. ui_select fallback_select / fallback_multi_select — the fallback is entered precisely when stderr is NOT a tty, then read stdin unconditionally. A scripted `aikey use` / `aikey auth login` with no explicit argument hung forever. Returns Cancelled with an actionable hint; piped-selection was never a supported contract (all documented automation passes explicit args, and interactive pickers elsewhere are already gated on stdin tty — see `aikey add`). 2. prompt_display_identity — the device_code OAuth flow reaches this prompt with no earlier tty-gated read to fail first. Skips (display name is optional; --alias remains the non-interactive path). Found by the 2026-07-07 lateral sweep; interactive behavior unchanged. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The vault deliberately has no migration ledger — schema convergence = replaying the whole idempotent baseline (CREATE TABLE IF NOT EXISTS / guarded ALTER / INSERT OR IGNORE). Several of those statements are real write attempts that take SQLite's write lock even when they no-op, and the pre-dispatch hook ran the replay on EVERY command. Humans never noticed; the web console's `_internal` bridge children (several per vault-page load + background polls) queued on that write lock — live Windows measurements: 52ms solo vs 1.2-3.3s under normal background concurrency, 2.7-7.2s at the endpoint, i.e. "the vault page crawls". The schema can only change when the binary changes, so convergence is now once-per-build instead of once-per-command: - config['schema.replayed_by'] records "<version>:<git revision>" of the build that last replayed (revision included so dirty dev builds sharing a version string still re-replay after rebuild). - Pre-dispatch does a READ-ONLY probe of that marker (no write lock); match → skip, anything else (legacy vault, other build, unreadable) → full replay + stamp. First contact of every existing install replays once and then fast-paths. - `aikey db upgrade` still force-replays unconditionally (the manual self-heal escape hatch) and stamps; `aikey db rollback` clears the marker so the next command re-converges, preserving pre-marker semantics for same-binary rollbacks. Trade-off (user-approved 2026-07-07): content self-heal drops from every-command to once-per-build; hand-damaged vault rows between upgrades now need `aikey db upgrade`. Installer stays responsible for server DBs only — vault stays CLI-owned because it doesn't exist at install time and binaries can arrive without the installer (online update / rollback / manual replacement). Fences: marker lifecycle (replay → SkippedFresh → foreign-marker replay → clear re-arms) + legacy no-marker vault converges once then skips. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…r comment
`aikey env` stopped listing the codex/kimi configs it had injected. Root
cause is a reader/writer truth-source split: the injectors migrated to
structural toml_edit writes that emit NO `# BEGIN aikey` marker comments
(kimi keyed on the hook-command tail, codex_merge/codex_remove keyed on
our keys), but injected_provider_toml_paths still detected by marker
text. Live trigger: codex CLI re-serializes config.toml on its own
writes and drops ALL comments — on 2026-07-06 it washed out the legacy
marker while every aikey key survived, and the listing went blank.
Detection now keys on the same semantic identity the REMOVE paths use:
- codex: codex_content_has_aikey mirrors codex_remove's predicates
([model_providers.aikey] / model_provider=="aikey" / openai_base_url
ending in /openai); a lockstep test pins the equivalence so display
("wired") and `aikey unuse` ("what gets stripped") can never disagree
again.
- kimi: KIMI_HOOK_COMMAND_MARKER (the established semantic key).
- AIKEY_BEGIN still honored for legacy never-rewritten files.
Verified live against the real ~/.codex/config.toml that reproduced the
report. Note: write/remove paths were already structural — this was a
display-only blindness, no stale-config risk.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Completes the 2026-07-07 marker-blindness fix class for the kimi side. Three readers each had their own AIKEY_BEGIN comment-marker checks, which go blind once kimi CLI re-serializes its config (dropping all comments): - `aikey env` listing (fixed in the previous commit, now routed through the shared predicate), - `kimi_status` / `aikey statusline status` — reported "not wired" on a wired install, - `uninstall_kimi_hook`'s gate — the real correctness bug: it returned NothingToRemove and SKIPPED removal entirely while the hook stayed wired (the structural removal underneath keys on the hook-command tail and would have worked fine). New kimi_content_has_aikey (hook-command tail + both legacy markers) is the single truth source for all three; kimi_status gains a pure core (kimi_content_status) so the semantics are unit-testable. One test guards the shared predicate plus the exact-command leg. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… readiness fixes [aikey-cli] account + ui-select adjustments (Windows/Mac parity) Refs: - Spec: windows-mac parity audit: https://github.com/aikeylabs/roadmap20260320/blob/6b3bcc0/技术实现/开源版本方案/20260707-windows-mac-parity-audit.md
…n WAL Live Windows regression of the marker fix itself: opening a WAL database with SQLITE_OPEN_READ_ONLY depends on adopting the -shm mapping — the same fragile step behind the Go readers' CANTOPEN(14) class. The RO probe failed routinely on the live box, every command fell through to the full replay, and the write-lock convoy came right back (measured with the marker binary deployed: `_internal rules` median 1.5s, min 53ms ≈ solo-replay cost — the fast path was never taken, while `aikey version` held a rock-steady 25-31ms floor). Probe now uses a default-mode connection: no -shm adoption, still SELECT-only, and WAL readers never block on writers so it remains contention-free; busy_timeout(1s) guards the non-WAL edge. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Two fixes from the 2026-07-07 encoding sweep (zh-CN Windows focus): 1. New crate::strip_bom applied at the three read→serde sites (install-state.json via detect_edition, project config, global config). Shipped PS 5.1 trial installers wrote install-state.json WITH a UTF-8 BOM; serde rejects BOM at byte 0 and the `.ok()?` swallowed the error — a whole trial install silently read as "not installed". Writers are being fixed, but BOM'd files already exist on customer machines, so readers must tolerate them forever. Regression test: detect_edition_tolerates_utf8_bom. 2. H2 guard in the PowerShell $PROFILE wiring: never byte-append UTF-8 onto a profile that isn't valid UTF-8 (UTF-16LE profiles are common on PS 5.1 via `>` redirection). Appending corrupted the file — PS decodes it all as UTF-16, the block turns to garbage, every new session can throw — and since the marker check can't read UTF-16 either, repeated runs kept appending. Now fails safe with a one-line conversion command and re-run guidance. (Full decode-splice-rewrite is a follow-up; the installer's Get-Content/Set-Content path was already safe.) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ot sync THE vault-page latency root cause, pinned by startup profiling on the live Windows box: `std::thread::spawn` itself cost ~1.2s there — endpoint AV (Norton) intercepts OS thread creation. Every short-lived `_internal` bridge child called try_background_snapshot_sync, whose in-process SYNC_IN_PROGRESS flag is useless across processes, so every bridge call paid the 1.2s BEFORE the sync's own sync_version fast-check could even run. (Earlier suspects — schema replay write-lock convoy, RO-probe WAL failure — were contributors at most: profiler showed 7ms→1683ms across this single call.) Fix per user decision (2026-07-07): KEEP the implicit async sync — it exists so OAuth-pool material changes propagate promptly — and gate the thread spawn on a cross-process debounce file (~/.aikey/run/snapshot-sync-last-attempt, 30s window). Hot path is a sub-ms stat+read; one process per window pays the spawn and runs the existing sync_version-compare logic unchanged. State file follows enhancement-not-dependency: missing/corrupt/future-clock all read as stale (sync runs); write failures ignored. Live A/B on the Windows box (deployed + verified): - `_internal rules`: 1.1-1.5s per call → 57-103ms after first-in-window - /api/user/vault/status+list concurrent (browser shape): 4.6-5.5s → 264-270ms Fence: debounce lifecycle (fresh/suppressed/elapsed/corrupt/clock-skew). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
[aikey-cli] shell-integration adjustment (Windows/Mac parity)
…r worked there Evidence-based revision of the earlier "keep it for OAuth-pool freshness" decision, with the freshness objection factually resolved: 1. A bridge child exits ~50ms after dispatch, killing the detached sync thread before its first HTTP round-trip completes — the implicit sync from `_internal` has NEVER delivered a sync. It only paid the thread-creation cost: ~1.2s under endpoint AV (Norton, profiled live), i.e. the entire vault-page latency. 2. Web freshness is genuinely delivered by the server-side explicit trigger (CRUDHandlers.triggerBackgroundSnapshotSync → `_internal query snapshot_sync`, which runs the sync inside the handler and completes) — unaffected. Interactive commands keep the implicit thread+debounce path. 3. A detached worker PROCESS was built, measured, and rejected: AV taxes spawning our unsigned binary the same way (~1.4s — the earlier "process spawn is ~30ms" datum was for signed cmd.exe and does not transfer), plus the parent inherited waits on the worker's 21s connect timeout when the team server is unreachable. Live A/B on the Windows box after deploy: - first-hit `_internal rules` (debounce cleared): 1.2-1.4s → 52-54ms - cold-open status+list concurrent (the exact user scenario of opening the vault page after idle): 4.6-5.5s → 291-325ms Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
aikey use writes the shell hook into $PROFILE.CurrentUserAllHosts, but the path was hardcoded as <home>\Documents\... — while PowerShell itself derives $PROFILE from the FOLDERID_Documents KNOWN FOLDER, which can be redirected (Parallels/VMware shared profiles, OneDrive folder redirection, roaming profiles). On such machines the hook landed in a profile PowerShell never reads: active.env vars silently reached no shell, and the post-use hint (. $PROFILE.CurrentUserAllHosts) died with CommandNotFoundException (Parallels box, 2026-07-08: interactive Documents = C:\Mac\Home\Documents). Compat layer only (user decision): documents_known_folder() asks SHGetKnownFolderPath(FOLDERID_Documents) — the same API PowerShell's own resolution bottoms out in — and its two profile candidates go FIRST. The hardcoded <home>\Documents candidates are kept unchanged as fallbacks (API failure; hooks written by older builds must stay findable). On non-redirected machines the known folder equals <home>\Documents and dedup collapses the list to exactly the old one — zero behavior change for machines that already work. The value is read live per invocation on purpose: on Parallels it is session-dependent (interactive sessions see the redirected path, SSH sessions the local default); resolving in the same session the user's shells run in is what makes write and read locations agree. Verification: cargo check --target x86_64-pc-windows-gnu green; host cargo test --lib shell_integration 149 passed; deployed to the Parallels test box via make restart-personal-win (binary hash matched). Interactive acceptance (aikey use -> new window sees OPENAI_API_KEY) is tracked in workflow/CI/bugfix/2026-07-08-powershell-profile-documents-redirect.md. Co-authored-by: Michael <jake@michael.MBP> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…n direct-jump + 信创 OS support [aikey-cli] main.rs adjustment
…v1-128k default [aikey-cli] moonshot-v1-128k default (8k breaks kimi-cli: system prompt ~12.4K > 8192); commands_account/proxy + profile-activation test; provider_registry.yaml Refs: - Spec: moonshot 默认模型 8k→128k: https://github.com/aikeylabs/roadmap20260320/blob/051ecf5/技术实现/update/20260708-moonshot-默认模型-8k-改-128k.md
…flight) + egress two-lane refinement [aikey-cli] proxy lifecycle fixes — early-SIGTERM kills startup, port-drift blocked by OrphanedPort preflight, WARN on drift-meta write-fail; proxy status shows start time Refs: - Bugfix: early-sigterm-kills-proxy-startup: https://github.com/aikeylabs/workflow/blob/8a922c0/CI/bugfix/2026-07-08-early-sigterm-kills-proxy-startup.md - Bugfix: port-drift-blocked-by-orphanedport-preflight: https://github.com/aikeylabs/workflow/blob/8a922c0/CI/bugfix/2026-07-08-port-drift-blocked-by-orphanedport-preflight.md - Spec: proxy-status 显示启动时间: https://github.com/aikeylabs/roadmap20260320/blob/1b5f896/技术实现/update/20260708-proxy-status-显示启动时间.md
…r; Windows hook fixes [aikey-cli] warn (stderr) when CLI configs still route through aikey but the hook/env channel is unwired (codex would fail on missing OPENAI_API_KEY); hook.bash bootstrap + hook.ps1 ASCII fence; shell_integration unix/windows + hook_op Refs: - Spec: hook 接线可见性升级: https://github.com/aikeylabs/roadmap20260320/blob/ea17cea9b20a733104d868098bfa1a1953b15864/技术实现/update/20260710-hook接线可见性升级.md - Requirement: hook-wiring-visibility: https://github.com/aikeylabs/workflow/blob/847b502ac807ed85ddb7e051328a95120fef7566/CI/requirements/2026-07-10-hook-wiring-visibility.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of the seat_group (席位组 / OAuth account pool) feature.
managed_virtual_keys_cache adds seat_group_id/group_accounts/routing_config; extra preserved across sync (fence test).
🤖 Generated with Claude Code