fix(auth): enforce model lockout for noauth synthetic connection - #13527
Closed
KooshaPari wants to merge 813 commits into
Closed
KooshaPari wants to merge 813 commits into
KooshaPari wants to merge 813 commits into
Conversation
* chore(tooling): modernize stack — 16 PRs shipped 16 PRs: - PR-A: ESLint → oxlint (3s on 3148 files) - PR-B: cacheLayer.ts → lru-cache@11 (9/9 tests) - PR-C: bcryptjs → @node-rs/argon2 OWASP Argon2id (6/6 tests) - PR-D: chalk → picocolors - PR-E: opossum shadow adapter marker - PR-F: crypto.timingSafeEqual (2 CVE-class fixes) - PR-G: KeyvQuotaStore + factory wiring (6/6 tests) - PR-H: rateLimitHeaders.ts extract (baseline) - PR-I: delete dead workflowFSM.ts (-340 LOC) - PR-K: learnedLimitStore.ts extract (202 LOC) - PR-L: oxfmt drop-in (replaces Prettier) - PR-N: rateLimiter.ts ioredis → keyv-backed store - PR-O: drop Qdrant from docker-compose - PR-Q: MITM → in-process Worker - PR-T: vitest consolidation (environmentMatchGlobs) Net: +1,095 / -425 LOC across 18 files. 21/21 tests pass. 0 TS errors. * fix(types): restore OmniRoute core typecheck * fix(security): refresh vulnerable runtime dependencies * chore(identity): establish canonical fork identity SSOT (#437) - .fork-identity.json: SSOT for fork name, version, release channel, capabilities - src/lib/identity/forkIdentity.ts: TS reader with module-level cache - src/app/api/identity/route.ts: GET /api/identity → NextResponse.json - package.json: identity:check, identity:diff scripts PR-stack totals: 21+ modernization PRs, 4 decomposition extractions, 90 tests. * chore(release): release readiness + branch archaeology + fail-open CI check - docs/RELEASE_READINESS.md: provenance, modernization stack, decompositions, CI matrix, GH backlog - docs/BRANCH_ARCHAEOLOGY.md: fork lineage, branch history, modernization timeline - scripts/check-fail-open.sh: #436 residual fail-open path detector - scripts/check-fail-open.ts: similar pattern for TS - package.json: identity:check, identity:diff, check:fail-open, ci:startup-determinism scripts Closes #436, #440, #444, #446 partial (CI check covers the fail-open subset) * chore(tooling): add oxfmt drop-in formatter - .oxfmtrc.json: Prettier-compatible config (100 col, singleQuote:false) - package.json: fmt:oxfmt, fmt:check, lint:oxlint scripts - oxfmt@0.59.0 installed as devDep * fix: correct brace structure in startMitm (manager.ts:647-715,718) Lines 647-715 were at 4-space indentation instead of 6-space inside the } else { block, misaligning ~69 lines as module-level scope. The closing brace at line 718 was also at 0-space. This caused TS1053 'export not at module level' cascade. TypeScript diagnostics now report semantically correct errors (missing local module refs) instead of parse-level failures. * feat: add device-code OAuth + opossum shadow adapter PR-R: Add device-code OAuth fallback path to inAppLoginService.ts - Tries device-code flow before Playwright (avoids headful browser) - Uses ../lib/deviceCodeProviders.ts with tryDeviceCodeForProvider() - Falls back to Playwright on device-code unavailability PR-P: Opossum shadow adapter in circuitBreaker.ts - CIRCUIT_BREAKER_OPOSSUM_SHADOW=1 env gate - Passive observer mode — records state-transition divergences - __getOpossumShadowStats() for telemetry/dashboard - __resetOpossumShadowStats() for test isolation * fix: add missing petals.ts + docs image stubs blocking npm publish - Copied petals.ts from .worktrees/token-permissions/open-sse/config/ to open-sse/config/ (missing monorepo workspace file) - Replaced 4 dead image asset references in journey-traceability.md with HTML comments * fix: add YAML frontmatter to 3 security docs + install missing @opentelemetry/* packages Docs frontmatter was blocking fumadocs-mdx build (title: Invalid input). OTEL packages were missing from node_modules causing TS2307 module-not-found. Both were preexisting infrastructure gaps, not caused by release system changes. * fix(ci): wire Electrobun lockfile and latency test fixture * ci(ts7): restore current-main strict gate * ci: pin apps quality actions and Bun setup * fix(desktop): compile BFF directly for ignored scripts * fix(mitm): remove stray closing brace in manager.ts Balances manager.ts to 195 opens/195 closes; unblocks prepublish webpack build. * fix(ci): install BFF dependencies for macOS desktop build * fix(ci): install API contracts before desktop bundling * fix(desktop): align packaged Bun entrypoint with launcher * fix(desktop): bundle Svelte renderer server * ci(desktop): verify bundled renderer output * fix(deps): synchronize npm lockfile with package manifest (#482) Co-authored-by: KooshaPari <koosha@example.com> * fix(deps): keep lockfile aligned with manifest * fix(ci): install API contract dependencies * fix(ci): install shared contracts before app checks * fix: tighten desktop readiness and keyv sqlite adapter --------- Co-authored-by: KooshaPari <koosha@example.com>
Co-authored-by: KooshaPari <koosha@example.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Co-authored-by: KooshaPari <koosha@example.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Bumps [undici](https://github.com/nodejs/undici) to 8.10.0 and updates ancestor dependencies and [undici](https://github.com/nodejs/undici). These dependencies need to be updated together. Updates `undici` from 8.5.0 to 8.10.0 - [Release notes](https://github.com/nodejs/undici/releases) - [Commits](nodejs/undici@v8.5.0...v8.10.0) Updates `undici` from 7.28.0 to 7.29.0 - [Release notes](https://github.com/nodejs/undici/releases) - [Commits](nodejs/undici@v8.5.0...v8.10.0) Updates `undici` from 6.27.0 to 6.28.0 - [Release notes](https://github.com/nodejs/undici/releases) - [Commits](nodejs/undici@v8.5.0...v8.10.0) --- updated-dependencies: - dependency-name: undici dependency-version: 8.10.0 dependency-type: direct:production - dependency-name: undici dependency-version: 7.29.0 dependency-type: indirect - dependency-name: undici dependency-version: 6.28.0 dependency-type: indirect ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [undici](https://github.com/nodejs/undici) from 7.28.0 to 7.29.0. - [Release notes](https://github.com/nodejs/undici/releases) - [Commits](nodejs/undici@v7.28.0...v7.29.0) --- updated-dependencies: - dependency-name: undici dependency-version: 7.29.0 dependency-type: indirect ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [hono](https://github.com/honojs/hono) from 4.12.31 to 4.13.0. - [Release notes](https://github.com/honojs/hono/releases) - [Commits](honojs/hono@v4.12.31...v4.13.0) --- updated-dependencies: - dependency-name: hono dependency-version: 4.13.0 dependency-type: indirect ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: KooshaPari <koosha@example.com>
Bumps [fast-uri](https://github.com/fastify/fast-uri) from 3.1.4 to 3.1.5. - [Release notes](https://github.com/fastify/fast-uri/releases) - [Commits](fastify/fast-uri@v3.1.4...v3.1.5) --- updated-dependencies: - dependency-name: fast-uri dependency-version: 3.1.5 dependency-type: indirect ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: KooshaPari <koosha@example.com>
* docs: add Phenotype fork execution contract * docs: add concrete acceptance clauses to fork contract * docs: record Node24 dependency gate evidence * docs: record sqlite compatibility research
Bumps [js-yaml](https://github.com/nodeca/js-yaml) from 4.3.0 to 4.3.1. - [Changelog](https://github.com/nodeca/js-yaml/blob/4.3.1/CHANGELOG.md) - [Commits](nodeca/js-yaml@4.3.0...4.3.1) --- updated-dependencies: - dependency-name: js-yaml dependency-version: 4.3.1 dependency-type: indirect ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [js-yaml](https://github.com/nodeca/js-yaml) from 4.3.0 to 5.2.3. - [Changelog](https://github.com/nodeca/js-yaml/blob/master/CHANGELOG.md) - [Commits](nodeca/js-yaml@4.3.0...5.2.3) --- updated-dependencies: - dependency-name: js-yaml dependency-version: 5.2.3 dependency-type: indirect ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [postcss](https://github.com/postcss/postcss) to 8.5.26 and updates ancestor dependency [next](https://github.com/vercel/next.js). These dependencies need to be updated together. Updates `postcss` from 8.5.14 to 8.5.26 - [Release notes](https://github.com/postcss/postcss/releases) - [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md) - [Commits](postcss/postcss@8.5.14...8.5.26) Updates `next` from 16.2.11 to 16.3.0 - [Release notes](https://github.com/vercel/next.js/releases) - [Commits](vercel/next.js@v16.2.11...v16.3.0) --- updated-dependencies: - dependency-name: postcss dependency-version: 8.5.26 dependency-type: indirect - dependency-name: next dependency-version: 16.3.0 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [mermaid](https://github.com/mermaid-js/mermaid) from 11.15.0 to 11.16.1. - [Release notes](https://github.com/mermaid-js/mermaid/releases) - [Commits](https://github.com/mermaid-js/mermaid/compare/mermaid@11.15.0...mermaid@11.16.1) --- updated-dependencies: - dependency-name: mermaid dependency-version: 11.16.1 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
* chore(governance): rebase mergify config request-review fixes onto main * fix(desktop): target fork-owned Electron releases * ci: align workflows with selected action policy * fix(governance): replace silent try/catch with explicit log.error in 5 modules (#506) Builds on PR #505 (quota keystore type-drift fix). The audit of that PR revealed 5 additional silent fail-open catch patterns across `src/` and `open-sse/` that hide the same class of bug: a TypeScript compile error or missing module is silently swallowed at runtime, falling back to a default with no operator-visible signal. This commit replaces those silent catches with explicit `log.error` calls that surface the actual error to monitoring. Fallback behavior is preserved (each fallback is intentional, but it must be LOUD). Changes: 1. `src/lib/quota/storeFactory.ts:67-77` — `readDbSettings` now logs the actual error when `getSettings()` fails or `@/lib/db/settings` import fails. Same root cause as the previously-fixed Keyv/Redis catches. 2. `src/lib/quota/storeFactory.ts:138-147` — Redis driver catch upgraded from `log.warn` to `log.error`. Includes the configured Redis URL with the password segment redacted (`:***@`). 3. `src/lib/resilience/anomalyHook.ts` — `getProviderManagerRegistry` now logs the actual error when `@/engine/providers` fails to load. Empty Map fallback retained (resilience must continue running), but the failure is now visible in monitoring. 4. `open-sse/services/tierResolver.ts` — `setTierConfig` now logs the actual error when `../../src/lib/db/tierConfig` fails to load. `DEFAULT_TIER_CONFIG` fallback retained (pricing must continue), but the failure is now visible. 5. `open-sse/config/credentialLoader.ts` — `resolveCredentialsPath` now uses `log.error` (pino) instead of `console.warn`. Includes both the original error and the fallback path. Security-sensitive path; must keep working, but the failure must be loud. 6. `.gitignore` — exclude `.agileplus/` and `agileplus-*.db*` (local AgilePlus DB state, regenerated from `.md` specs via `agileplus specify`). The DB contains transient per-machine state and shouldn't be in version control. Verification: - TSC: 0 NEW errors (8 pre-existing quota keystore errors remain, those are what PR #505 fixes; this PR is independent of PR #505) - Vitest quota suite: 18/18 pass (6 keyv + 4 contract + 8 e2e) - Node:test factory: 6/6 pass - Resilience tests: 61 pass / 1 pre-existing flake (resilience-provider-cooldown-api-3556.test.ts: "rejects providerCooldown max below min" — verified pre-existing by reverting only anomalyHook.ts and reproducing the same failure) Out of scope (filed as separate bugs): - `src/lib/resilience/anomalyHook.ts:13` imports `isFeatureFlagEnabled` from `@/lib/featureFlags`, but the module lives at `src/lib/db/featureFlags.ts`. The file is currently unloadable from tests; this PR doesn't touch the import because that's a separate bug. - The Resilience subagent identified but did not fix the `tsconfig.typecheck-core.json` doesn't include `src/lib/resilience/` files — separate follow-up. Co-authored-by: KooshaPari <koosha@example.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(governance): broken featureFlags imports + 3 silent fail-opens + extras test (#507) Continuation of the governance-debt cleanup started in PRs #505 and #506. Six independent fixes, each addressing a class of silent-failure pattern that the audits surfaced. Changes: 1. **`src/lib/resilience/anomalyHook.ts:12`** — Broken import path. `isFeatureFlagEnabled` was imported from `@/lib/featureFlags`, but the module lives at `@/shared/utils/featureFlags`. This bug was masked because `tsconfig.typecheck-core.json` does not include `src/lib/resilience/` and no test loads the module successfully. After the fix, the module loads and exports the expected surface. 2. **`src/server-init.ts:128`** — Same broken import path. The surrounding try/catch at lines 130-139 silently swallowed the import failure. Fix: correct the path AND upgrade the catch log from `warn` to `error` (matches PR #506 pattern). 3. **`src/lib/versionManager/processManager.ts:155`** — `getProcessInfo` catch returned `{pid, alive: true}` after `ps`/readFile failures, which lies when the process is actually gone. Fix: catch now logs the error and returns `{pid, alive: false}` (honest about not being able to read process state). 4. **`src/server/ws/liveServer.ts:479`** — `loadAuthModule().catch(() => {})` silently swallowed initial auth module load failures, allowing the WS server to come up without auth configured. Fix: catch now logs `log.error`; fallback behavior preserved per the existing comment ("handler retries the import lazily"). 5. **`src/lib/machineToken.ts:1-10`** — Crypto-relevant: empty catch around `require("node-machine-id")` silently fell back to `() => ""`, which collapses HMAC inputs to a constant. Fix: catch now logs `log.error` with security-context message, gated by a `fallbackLogged` flag so the log fires only once per process (avoiding log spam from any downstream reload). 6. **`tests/unit/quota/keyvQuotaStoreExtras.test.ts`** (new) — Closes spec §8.2 reachability test gap. 5 sanity tests for the `recordPlanUsage` / `upsertProviderPlan` / `listProviderPlans` / `setPools` / `getPool` surface on KeyvQuotaStore. Note: this branch is based on `origin/agent/migration-version-collision-fix` (pre-PR-#505), so the methods live directly on KeyvQuotaStore. When PR #505 lands, update the test to import from `keyvQuotaStoreExtras.ts` instead. Verification: - TSC error count: 8 unchanged (all pre-existing quota keystore errors that PR #505 fixes; this PR is independent of #505) - Vitest extras test: 5/5 pass - Node:test combined (processManager + machineToken + WS): 47/47 pass - All success-path behavior preserved; only catch/fallback paths now log Out of scope (separate PRs): - Promote Keyv to "embedded default" driver (spec §10) - Pre-existing e2e failure at `tests/e2e/quota-store.e2e.ts:117` (poolUsageWithDimensions shape mismatch — fixed in PR #505) Co-authored-by: KooshaPari <koosha@example.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(security): log 3 crypto-relevant silent catches (rebased onto canonical base) (#509) This branch has been surgically rebased onto origin/agent/migration-version-collision-fix to remove accidental contamination from PR #507's branch base. In all three cases, the empty-string return collapses HMAC/HMAC-SHA256 inputs into a constant-key value, so security-relevant operations on the fallback path produce identical tokens regardless of input. Fixes: 1. src/lib/machineToken.ts:44 - getMachineTokenSync catch: log.error + return "" 2. src/lib/machineToken.ts:62 - getLegacyCliTokenSync catch: log.error + return "" 3. src/lib/db/encryption.ts:87-95 - getLegacyDynamicKey catch: added pino logger (createLogger("db:encryption")) + log.error instead of returning null silently 4. (incidental) src/lib/machineToken.ts module-load catch: also gains log.error so the new runtime catches have a 'log' constant to reference. This subsumes PR #507's machineToken.ts hunk. NOTE: PR #507 will need its machineToken.ts hunk resolved when it merges (this branch already provides the 'log' logger constant it tries to add). Verification: - TSC: 8 unchanged (pre-existing quota keystore errors, PR #505 territory) - Targeted machineToken + encryption unit tests pass - All success-path behaviors preserved Co-authored-by: KooshaPari <koosha@example.com> * fix(security): 4 audit findings + migrate encryption.ts to pino (#510) Completes the audit-driven governance work that PR #509 started. Eight independent fixes: Security fixes (audit findings F5, F6, F9, F10): 1. src/lib/cloudSync.ts:47-56 — HMAC verification fail-open when CLOUD_SYNC_SECRET is unset. Now returns false (fail-closed) when a sigHeader is present but cannot be verified, instead of accepting any response. Legacy unverified mode (no sigHeader) is preserved. 2. src/lib/oauth/providers/antigravity.ts:101 — fetch() of userInfo during OAuth was swallowed silently, causing downstream code to use default projectId/tierId. Now logs warn with structured context. 3. open-sse/services/autoRefreshDaemon.ts:77,80 — periodic credential refresh errors were silently swallowed, allowing expired tokens to persist undetected. Now logs error per cycle. 4. src/lib/vscode/serviceTierVariants.ts:184 — request body parse failures during tier-rewrite were silently no-op'd. Now logs warn. Refactor: 5. src/lib/db/encryption.ts — migrated ~7 console.* calls to pino logger (encryptionLog). Following the PR #509 pattern of createLogger("db:encryption"). The catch fallback behavior is preserved exactly; only logging changes. Out of scope: - encryption.ts:144-148 plaintext fallback (separate spec at plans/encryption-failclosed-spec.md, deferred for design discussion) - src/lib/db/*.ts console.* migration for other files (separate PR) Co-authored-by: KooshaPari <koosha@example.com> * fix(governance): log empty catches in binaryManager + db/adapters (#512) 22 silent fail-open sites in the version manager + SQLite adapter layer were just swallows. Per the audit: - src/lib/versionManager/binaryManager.ts (6 catches): symlink/rollback/ remove errors were silent; filesystem permission bugs were invisible - src/lib/db/adapters/sqljsAdapter.ts (6 catches): save/close errors were silent; DB corruption during shutdown was undetectable - src/lib/db/adapters/betterSqliteAdapter.ts (1 catch): same pattern - src/lib/db/adapters/nodeSqliteAdapter.ts (2 catches): same pattern - src/lib/db/adapters/nodeSqliteShared.ts (7 catches): same pattern All 22 catches now log structured error context. Behavior unchanged - only logging added. Per AGENTS.md, no encryption keys or raw secrets are logged. TSC: 8 unchanged Tests: existing pass (any new behavior is logging-only) Co-authored-by: KooshaPari <koosha@example.com> * ci: pin cross-platform Rust toolchain * docs(plans): track 2 governance specs for future implementation (#511) Two deferred-implementation specs are now tracked in version control so the work product is preserved and discoverable. 1. plans/encryption-failclosed-spec.md (883 lines) — Hardening encryption.ts:144-148 (the silent plaintext fallback). Compares 3 design options with detailed tradeoffs. Recommended: C+A (startup canary + runtime throw). Registered as AgilePlus feature 'encryption-failclosed'. 2. plans/keyv-as-embedded-default-spec.md (698 lines) — Promote Keyv from optional driver to embedded default for fresh installs. Includes backwards-compat plan, config migration, and rollout sequence. Registered as AgilePlus feature 'keyv-as-embedded-default'. These specs intentionally do NOT include code changes — they are design-only and gate on answering the open questions before implementation. See spec section 9 for each spec's open questions. Co-authored-by: KooshaPari <koosha@example.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> * wip: auto-commit daemon 2026-08-06T09:18:52Z (#505) Co-authored-by: Airlock Bot <airlock@phenoforge.local> * refactor(db): migrate console.* to pino in src/lib/db/ (#522) Follows the PR #506/#507/#509/#510 pattern of replacing console.* with createLogger("db:<subsystem>") to provide structured logging across the SQLite persistence layer. Files modified (~155 callsites across 17 files): - src/lib/db/adapters/driverFactory.ts - src/lib/db/adapters/sqljsAdapter.ts - src/lib/db/apiKeys.ts - src/lib/db/backup.ts - src/lib/db/cleanup.ts (~30 sites) - src/lib/db/core.ts (~30 sites) - src/lib/db/migrationRunner.ts (~22 sites, removed test-suppressing local console wrapper) - src/lib/db/models.ts - src/lib/db/optimizationSettings.ts - src/lib/db/providers.ts - src/lib/db/quotaPools.ts - src/lib/db/quotaSnapshots.ts - src/lib/db/schemaColumns.ts (~35 sites) - src/lib/db/sessionAccountAffinity.ts - src/lib/db/settings.ts - src/lib/db/settings/cacheMetrics.ts - src/lib/db/stateReset.ts Per AGENTS.md guidance, never log SQLite encryption keys or raw secrets; all logger calls redact sensitive material. Behavior preservation: - All success-path behavior unchanged - Only the logging mechanism changes - Targeted tests pass One console.error preserved in core.ts:migrateFromJson because tests/unit/db-core-migration.test.ts overrides console.error to detect the failure; both console.error and log.error are emitted so the test passes and pino is the canonical sink. Co-authored-by: KooshaPari <koosha@example.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> * ci: use cache-pinned Trunk action --------- Co-authored-by: KooshaPari <koosha@example.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: Airlock Bot <airlock@phenoforge.local>
…ollowup) (#526) * chore(governance): rebase mergify config request-review fixes onto main * fix(desktop): target fork-owned Electron releases * ci: align workflows with selected action policy * fix(governance): replace silent try/catch with explicit log.error in 5 modules (#506) Builds on PR #505 (quota keystore type-drift fix). The audit of that PR revealed 5 additional silent fail-open catch patterns across `src/` and `open-sse/` that hide the same class of bug: a TypeScript compile error or missing module is silently swallowed at runtime, falling back to a default with no operator-visible signal. This commit replaces those silent catches with explicit `log.error` calls that surface the actual error to monitoring. Fallback behavior is preserved (each fallback is intentional, but it must be LOUD). Changes: 1. `src/lib/quota/storeFactory.ts:67-77` — `readDbSettings` now logs the actual error when `getSettings()` fails or `@/lib/db/settings` import fails. Same root cause as the previously-fixed Keyv/Redis catches. 2. `src/lib/quota/storeFactory.ts:138-147` — Redis driver catch upgraded from `log.warn` to `log.error`. Includes the configured Redis URL with the password segment redacted (`:***@`). 3. `src/lib/resilience/anomalyHook.ts` — `getProviderManagerRegistry` now logs the actual error when `@/engine/providers` fails to load. Empty Map fallback retained (resilience must continue running), but the failure is now visible in monitoring. 4. `open-sse/services/tierResolver.ts` — `setTierConfig` now logs the actual error when `../../src/lib/db/tierConfig` fails to load. `DEFAULT_TIER_CONFIG` fallback retained (pricing must continue), but the failure is now visible. 5. `open-sse/config/credentialLoader.ts` — `resolveCredentialsPath` now uses `log.error` (pino) instead of `console.warn`. Includes both the original error and the fallback path. Security-sensitive path; must keep working, but the failure must be loud. 6. `.gitignore` — exclude `.agileplus/` and `agileplus-*.db*` (local AgilePlus DB state, regenerated from `.md` specs via `agileplus specify`). The DB contains transient per-machine state and shouldn't be in version control. Verification: - TSC: 0 NEW errors (8 pre-existing quota keystore errors remain, those are what PR #505 fixes; this PR is independent of PR #505) - Vitest quota suite: 18/18 pass (6 keyv + 4 contract + 8 e2e) - Node:test factory: 6/6 pass - Resilience tests: 61 pass / 1 pre-existing flake (resilience-provider-cooldown-api-3556.test.ts: "rejects providerCooldown max below min" — verified pre-existing by reverting only anomalyHook.ts and reproducing the same failure) Out of scope (filed as separate bugs): - `src/lib/resilience/anomalyHook.ts:13` imports `isFeatureFlagEnabled` from `@/lib/featureFlags`, but the module lives at `src/lib/db/featureFlags.ts`. The file is currently unloadable from tests; this PR doesn't touch the import because that's a separate bug. - The Resilience subagent identified but did not fix the `tsconfig.typecheck-core.json` doesn't include `src/lib/resilience/` files — separate follow-up. Co-authored-by: KooshaPari <koosha@example.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(governance): broken featureFlags imports + 3 silent fail-opens + extras test (#507) Continuation of the governance-debt cleanup started in PRs #505 and #506. Six independent fixes, each addressing a class of silent-failure pattern that the audits surfaced. Changes: 1. **`src/lib/resilience/anomalyHook.ts:12`** — Broken import path. `isFeatureFlagEnabled` was imported from `@/lib/featureFlags`, but the module lives at `@/shared/utils/featureFlags`. This bug was masked because `tsconfig.typecheck-core.json` does not include `src/lib/resilience/` and no test loads the module successfully. After the fix, the module loads and exports the expected surface. 2. **`src/server-init.ts:128`** — Same broken import path. The surrounding try/catch at lines 130-139 silently swallowed the import failure. Fix: correct the path AND upgrade the catch log from `warn` to `error` (matches PR #506 pattern). 3. **`src/lib/versionManager/processManager.ts:155`** — `getProcessInfo` catch returned `{pid, alive: true}` after `ps`/readFile failures, which lies when the process is actually gone. Fix: catch now logs the error and returns `{pid, alive: false}` (honest about not being able to read process state). 4. **`src/server/ws/liveServer.ts:479`** — `loadAuthModule().catch(() => {})` silently swallowed initial auth module load failures, allowing the WS server to come up without auth configured. Fix: catch now logs `log.error`; fallback behavior preserved per the existing comment ("handler retries the import lazily"). 5. **`src/lib/machineToken.ts:1-10`** — Crypto-relevant: empty catch around `require("node-machine-id")` silently fell back to `() => ""`, which collapses HMAC inputs to a constant. Fix: catch now logs `log.error` with security-context message, gated by a `fallbackLogged` flag so the log fires only once per process (avoiding log spam from any downstream reload). 6. **`tests/unit/quota/keyvQuotaStoreExtras.test.ts`** (new) — Closes spec §8.2 reachability test gap. 5 sanity tests for the `recordPlanUsage` / `upsertProviderPlan` / `listProviderPlans` / `setPools` / `getPool` surface on KeyvQuotaStore. Note: this branch is based on `origin/agent/migration-version-collision-fix` (pre-PR-#505), so the methods live directly on KeyvQuotaStore. When PR #505 lands, update the test to import from `keyvQuotaStoreExtras.ts` instead. Verification: - TSC error count: 8 unchanged (all pre-existing quota keystore errors that PR #505 fixes; this PR is independent of #505) - Vitest extras test: 5/5 pass - Node:test combined (processManager + machineToken + WS): 47/47 pass - All success-path behavior preserved; only catch/fallback paths now log Out of scope (separate PRs): - Promote Keyv to "embedded default" driver (spec §10) - Pre-existing e2e failure at `tests/e2e/quota-store.e2e.ts:117` (poolUsageWithDimensions shape mismatch — fixed in PR #505) Co-authored-by: KooshaPari <koosha@example.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(security): log 3 crypto-relevant silent catches (rebased onto canonical base) (#509) This branch has been surgically rebased onto origin/agent/migration-version-collision-fix to remove accidental contamination from PR #507's branch base. In all three cases, the empty-string return collapses HMAC/HMAC-SHA256 inputs into a constant-key value, so security-relevant operations on the fallback path produce identical tokens regardless of input. Fixes: 1. src/lib/machineToken.ts:44 - getMachineTokenSync catch: log.error + return "" 2. src/lib/machineToken.ts:62 - getLegacyCliTokenSync catch: log.error + return "" 3. src/lib/db/encryption.ts:87-95 - getLegacyDynamicKey catch: added pino logger (createLogger("db:encryption")) + log.error instead of returning null silently 4. (incidental) src/lib/machineToken.ts module-load catch: also gains log.error so the new runtime catches have a 'log' constant to reference. This subsumes PR #507's machineToken.ts hunk. NOTE: PR #507 will need its machineToken.ts hunk resolved when it merges (this branch already provides the 'log' logger constant it tries to add). Verification: - TSC: 8 unchanged (pre-existing quota keystore errors, PR #505 territory) - Targeted machineToken + encryption unit tests pass - All success-path behaviors preserved Co-authored-by: KooshaPari <koosha@example.com> * fix(security): 4 audit findings + migrate encryption.ts to pino (#510) Completes the audit-driven governance work that PR #509 started. Eight independent fixes: Security fixes (audit findings F5, F6, F9, F10): 1. src/lib/cloudSync.ts:47-56 — HMAC verification fail-open when CLOUD_SYNC_SECRET is unset. Now returns false (fail-closed) when a sigHeader is present but cannot be verified, instead of accepting any response. Legacy unverified mode (no sigHeader) is preserved. 2. src/lib/oauth/providers/antigravity.ts:101 — fetch() of userInfo during OAuth was swallowed silently, causing downstream code to use default projectId/tierId. Now logs warn with structured context. 3. open-sse/services/autoRefreshDaemon.ts:77,80 — periodic credential refresh errors were silently swallowed, allowing expired tokens to persist undetected. Now logs error per cycle. 4. src/lib/vscode/serviceTierVariants.ts:184 — request body parse failures during tier-rewrite were silently no-op'd. Now logs warn. Refactor: 5. src/lib/db/encryption.ts — migrated ~7 console.* calls to pino logger (encryptionLog). Following the PR #509 pattern of createLogger("db:encryption"). The catch fallback behavior is preserved exactly; only logging changes. Out of scope: - encryption.ts:144-148 plaintext fallback (separate spec at plans/encryption-failclosed-spec.md, deferred for design discussion) - src/lib/db/*.ts console.* migration for other files (separate PR) Co-authored-by: KooshaPari <koosha@example.com> * fix(governance): log empty catches in binaryManager + db/adapters (#512) 22 silent fail-open sites in the version manager + SQLite adapter layer were just swallows. Per the audit: - src/lib/versionManager/binaryManager.ts (6 catches): symlink/rollback/ remove errors were silent; filesystem permission bugs were invisible - src/lib/db/adapters/sqljsAdapter.ts (6 catches): save/close errors were silent; DB corruption during shutdown was undetectable - src/lib/db/adapters/betterSqliteAdapter.ts (1 catch): same pattern - src/lib/db/adapters/nodeSqliteAdapter.ts (2 catches): same pattern - src/lib/db/adapters/nodeSqliteShared.ts (7 catches): same pattern All 22 catches now log structured error context. Behavior unchanged - only logging added. Per AGENTS.md, no encryption keys or raw secrets are logged. TSC: 8 unchanged Tests: existing pass (any new behavior is logging-only) Co-authored-by: KooshaPari <koosha@example.com> * ci: pin cross-platform Rust toolchain * docs(plans): track 2 governance specs for future implementation (#511) Two deferred-implementation specs are now tracked in version control so the work product is preserved and discoverable. 1. plans/encryption-failclosed-spec.md (883 lines) — Hardening encryption.ts:144-148 (the silent plaintext fallback). Compares 3 design options with detailed tradeoffs. Recommended: C+A (startup canary + runtime throw). Registered as AgilePlus feature 'encryption-failclosed'. 2. plans/keyv-as-embedded-default-spec.md (698 lines) — Promote Keyv from optional driver to embedded default for fresh installs. Includes backwards-compat plan, config migration, and rollout sequence. Registered as AgilePlus feature 'keyv-as-embedded-default'. These specs intentionally do NOT include code changes — they are design-only and gate on answering the open questions before implementation. See spec section 9 for each spec's open questions. Co-authored-by: KooshaPari <koosha@example.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> * wip: auto-commit daemon 2026-08-06T09:18:52Z (#505) Co-authored-by: Airlock Bot <airlock@phenoforge.local> * refactor(db): migrate console.* to pino in src/lib/db/ (#522) Follows the PR #506/#507/#509/#510 pattern of replacing console.* with createLogger("db:<subsystem>") to provide structured logging across the SQLite persistence layer. Files modified (~155 callsites across 17 files): - src/lib/db/adapters/driverFactory.ts - src/lib/db/adapters/sqljsAdapter.ts - src/lib/db/apiKeys.ts - src/lib/db/backup.ts - src/lib/db/cleanup.ts (~30 sites) - src/lib/db/core.ts (~30 sites) - src/lib/db/migrationRunner.ts (~22 sites, removed test-suppressing local console wrapper) - src/lib/db/models.ts - src/lib/db/optimizationSettings.ts - src/lib/db/providers.ts - src/lib/db/quotaPools.ts - src/lib/db/quotaSnapshots.ts - src/lib/db/schemaColumns.ts (~35 sites) - src/lib/db/sessionAccountAffinity.ts - src/lib/db/settings.ts - src/lib/db/settings/cacheMetrics.ts - src/lib/db/stateReset.ts Per AGENTS.md guidance, never log SQLite encryption keys or raw secrets; all logger calls redact sensitive material. Behavior preservation: - All success-path behavior unchanged - Only the logging mechanism changes - Targeted tests pass One console.error preserved in core.ts:migrateFromJson because tests/unit/db-core-migration.test.ts overrides console.error to detect the failure; both console.error and log.error are emitted so the test passes and pino is the canonical sink. Co-authored-by: KooshaPari <koosha@example.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> * ci: use cache-pinned Trunk action * fix(governance): log empty catches + weak peer-dep fallbacks (audit followup) Continues the audit-driven governance cleanup that PRs #506, #507, #509, #510, #512, #522, #525 started. This batch addresses the remaining empty catches and weak peer-dependency fallbacks in plugins, embeddings, oauth, monitoring, and combo paths. Empty catches fixed (~6 sites): - src/lib/plugins/loader.ts:200, 301 (plugin load/cleanup) - src/lib/plugins/manager.ts:151, 270 (plugin staging cleanup) - src/lib/embeddings/service.ts:50, 73 (embedding combo lookup) - src/lib/credentialHealth/scheduler.ts:122 (credential health sweep) - src/lib/usage/usageStats.ts:301 (usage stats) - src/lib/oauth/providers/kimi-coding.ts:44 (OAuth provider init) Weak peer-dep fallbacks fixed (~10 sites): - src/lib/a2a/skills/providerDiscovery.ts:388 (MCP module load) - open-sse/rpc/dispatchEdges.ts:189, 199, 209 (FFI/UDS transport — HIGH RISK, used log.error not warn) - src/lib/monitoring/providerHealthAutopilot.ts:262 (quota monitor) - open-sse/services/combo.ts:2222 (fetchCodexQuota) - open-sse/services/combo/quotaStrategies.ts:431 (getRuntimeProviderProfile) - open-sse/handlers/chatCore/codexFailover.ts:19 (provider connection) - open-sse/handlers/chatCore/comboContextCache.ts:57 (proxy config) All conversions preserve existing behavior (return null/false/etc.). Only logging is added — no semantic change. Test results unchanged from baseline. TSC: 8 unchanged (pre-existing quota keystore errors, PR #505 territory). --------- Co-authored-by: KooshaPari <koosha@example.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: Airlock Bot <airlock@phenoforge.local>
* chore(governance): rebase mergify config request-review fixes onto main * fix(desktop): target fork-owned Electron releases * ci: align workflows with selected action policy * fix(governance): replace silent try/catch with explicit log.error in 5 modules (#506) Builds on PR #505 (quota keystore type-drift fix). The audit of that PR revealed 5 additional silent fail-open catch patterns across `src/` and `open-sse/` that hide the same class of bug: a TypeScript compile error or missing module is silently swallowed at runtime, falling back to a default with no operator-visible signal. This commit replaces those silent catches with explicit `log.error` calls that surface the actual error to monitoring. Fallback behavior is preserved (each fallback is intentional, but it must be LOUD). Changes: 1. `src/lib/quota/storeFactory.ts:67-77` — `readDbSettings` now logs the actual error when `getSettings()` fails or `@/lib/db/settings` import fails. Same root cause as the previously-fixed Keyv/Redis catches. 2. `src/lib/quota/storeFactory.ts:138-147` — Redis driver catch upgraded from `log.warn` to `log.error`. Includes the configured Redis URL with the password segment redacted (`:***@`). 3. `src/lib/resilience/anomalyHook.ts` — `getProviderManagerRegistry` now logs the actual error when `@/engine/providers` fails to load. Empty Map fallback retained (resilience must continue running), but the failure is now visible in monitoring. 4. `open-sse/services/tierResolver.ts` — `setTierConfig` now logs the actual error when `../../src/lib/db/tierConfig` fails to load. `DEFAULT_TIER_CONFIG` fallback retained (pricing must continue), but the failure is now visible. 5. `open-sse/config/credentialLoader.ts` — `resolveCredentialsPath` now uses `log.error` (pino) instead of `console.warn`. Includes both the original error and the fallback path. Security-sensitive path; must keep working, but the failure must be loud. 6. `.gitignore` — exclude `.agileplus/` and `agileplus-*.db*` (local AgilePlus DB state, regenerated from `.md` specs via `agileplus specify`). The DB contains transient per-machine state and shouldn't be in version control. Verification: - TSC: 0 NEW errors (8 pre-existing quota keystore errors remain, those are what PR #505 fixes; this PR is independent of PR #505) - Vitest quota suite: 18/18 pass (6 keyv + 4 contract + 8 e2e) - Node:test factory: 6/6 pass - Resilience tests: 61 pass / 1 pre-existing flake (resilience-provider-cooldown-api-3556.test.ts: "rejects providerCooldown max below min" — verified pre-existing by reverting only anomalyHook.ts and reproducing the same failure) Out of scope (filed as separate bugs): - `src/lib/resilience/anomalyHook.ts:13` imports `isFeatureFlagEnabled` from `@/lib/featureFlags`, but the module lives at `src/lib/db/featureFlags.ts`. The file is currently unloadable from tests; this PR doesn't touch the import because that's a separate bug. - The Resilience subagent identified but did not fix the `tsconfig.typecheck-core.json` doesn't include `src/lib/resilience/` files — separate follow-up. Co-authored-by: KooshaPari <koosha@example.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(governance): broken featureFlags imports + 3 silent fail-opens + extras test (#507) Continuation of the governance-debt cleanup started in PRs #505 and #506. Six independent fixes, each addressing a class of silent-failure pattern that the audits surfaced. Changes: 1. **`src/lib/resilience/anomalyHook.ts:12`** — Broken import path. `isFeatureFlagEnabled` was imported from `@/lib/featureFlags`, but the module lives at `@/shared/utils/featureFlags`. This bug was masked because `tsconfig.typecheck-core.json` does not include `src/lib/resilience/` and no test loads the module successfully. After the fix, the module loads and exports the expected surface. 2. **`src/server-init.ts:128`** — Same broken import path. The surrounding try/catch at lines 130-139 silently swallowed the import failure. Fix: correct the path AND upgrade the catch log from `warn` to `error` (matches PR #506 pattern). 3. **`src/lib/versionManager/processManager.ts:155`** — `getProcessInfo` catch returned `{pid, alive: true}` after `ps`/readFile failures, which lies when the process is actually gone. Fix: catch now logs the error and returns `{pid, alive: false}` (honest about not being able to read process state). 4. **`src/server/ws/liveServer.ts:479`** — `loadAuthModule().catch(() => {})` silently swallowed initial auth module load failures, allowing the WS server to come up without auth configured. Fix: catch now logs `log.error`; fallback behavior preserved per the existing comment ("handler retries the import lazily"). 5. **`src/lib/machineToken.ts:1-10`** — Crypto-relevant: empty catch around `require("node-machine-id")` silently fell back to `() => ""`, which collapses HMAC inputs to a constant. Fix: catch now logs `log.error` with security-context message, gated by a `fallbackLogged` flag so the log fires only once per process (avoiding log spam from any downstream reload). 6. **`tests/unit/quota/keyvQuotaStoreExtras.test.ts`** (new) — Closes spec §8.2 reachability test gap. 5 sanity tests for the `recordPlanUsage` / `upsertProviderPlan` / `listProviderPlans` / `setPools` / `getPool` surface on KeyvQuotaStore. Note: this branch is based on `origin/agent/migration-version-collision-fix` (pre-PR-#505), so the methods live directly on KeyvQuotaStore. When PR #505 lands, update the test to import from `keyvQuotaStoreExtras.ts` instead. Verification: - TSC error count: 8 unchanged (all pre-existing quota keystore errors that PR #505 fixes; this PR is independent of #505) - Vitest extras test: 5/5 pass - Node:test combined (processManager + machineToken + WS): 47/47 pass - All success-path behavior preserved; only catch/fallback paths now log Out of scope (separate PRs): - Promote Keyv to "embedded default" driver (spec §10) - Pre-existing e2e failure at `tests/e2e/quota-store.e2e.ts:117` (poolUsageWithDimensions shape mismatch — fixed in PR #505) Co-authored-by: KooshaPari <koosha@example.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(security): log 3 crypto-relevant silent catches (rebased onto canonical base) (#509) This branch has been surgically rebased onto origin/agent/migration-version-collision-fix to remove accidental contamination from PR #507's branch base. In all three cases, the empty-string return collapses HMAC/HMAC-SHA256 inputs into a constant-key value, so security-relevant operations on the fallback path produce identical tokens regardless of input. Fixes: 1. src/lib/machineToken.ts:44 - getMachineTokenSync catch: log.error + return "" 2. src/lib/machineToken.ts:62 - getLegacyCliTokenSync catch: log.error + return "" 3. src/lib/db/encryption.ts:87-95 - getLegacyDynamicKey catch: added pino logger (createLogger("db:encryption")) + log.error instead of returning null silently 4. (incidental) src/lib/machineToken.ts module-load catch: also gains log.error so the new runtime catches have a 'log' constant to reference. This subsumes PR #507's machineToken.ts hunk. NOTE: PR #507 will need its machineToken.ts hunk resolved when it merges (this branch already provides the 'log' logger constant it tries to add). Verification: - TSC: 8 unchanged (pre-existing quota keystore errors, PR #505 territory) - Targeted machineToken + encryption unit tests pass - All success-path behaviors preserved Co-authored-by: KooshaPari <koosha@example.com> * fix(security): 4 audit findings + migrate encryption.ts to pino (#510) Completes the audit-driven governance work that PR #509 started. Eight independent fixes: Security fixes (audit findings F5, F6, F9, F10): 1. src/lib/cloudSync.ts:47-56 — HMAC verification fail-open when CLOUD_SYNC_SECRET is unset. Now returns false (fail-closed) when a sigHeader is present but cannot be verified, instead of accepting any response. Legacy unverified mode (no sigHeader) is preserved. 2. src/lib/oauth/providers/antigravity.ts:101 — fetch() of userInfo during OAuth was swallowed silently, causing downstream code to use default projectId/tierId. Now logs warn with structured context. 3. open-sse/services/autoRefreshDaemon.ts:77,80 — periodic credential refresh errors were silently swallowed, allowing expired tokens to persist undetected. Now logs error per cycle. 4. src/lib/vscode/serviceTierVariants.ts:184 — request body parse failures during tier-rewrite were silently no-op'd. Now logs warn. Refactor: 5. src/lib/db/encryption.ts — migrated ~7 console.* calls to pino logger (encryptionLog). Following the PR #509 pattern of createLogger("db:encryption"). The catch fallback behavior is preserved exactly; only logging changes. Out of scope: - encryption.ts:144-148 plaintext fallback (separate spec at plans/encryption-failclosed-spec.md, deferred for design discussion) - src/lib/db/*.ts console.* migration for other files (separate PR) Co-authored-by: KooshaPari <koosha@example.com> * fix(governance): log empty catches in binaryManager + db/adapters (#512) 22 silent fail-open sites in the version manager + SQLite adapter layer were just swallows. Per the audit: - src/lib/versionManager/binaryManager.ts (6 catches): symlink/rollback/ remove errors were silent; filesystem permission bugs were invisible - src/lib/db/adapters/sqljsAdapter.ts (6 catches): save/close errors were silent; DB corruption during shutdown was undetectable - src/lib/db/adapters/betterSqliteAdapter.ts (1 catch): same pattern - src/lib/db/adapters/nodeSqliteAdapter.ts (2 catches): same pattern - src/lib/db/adapters/nodeSqliteShared.ts (7 catches): same pattern All 22 catches now log structured error context. Behavior unchanged - only logging added. Per AGENTS.md, no encryption keys or raw secrets are logged. TSC: 8 unchanged Tests: existing pass (any new behavior is logging-only) Co-authored-by: KooshaPari <koosha@example.com> * ci: pin cross-platform Rust toolchain * docs(plans): track 2 governance specs for future implementation (#511) Two deferred-implementation specs are now tracked in version control so the work product is preserved and discoverable. 1. plans/encryption-failclosed-spec.md (883 lines) — Hardening encryption.ts:144-148 (the silent plaintext fallback). Compares 3 design options with detailed tradeoffs. Recommended: C+A (startup canary + runtime throw). Registered as AgilePlus feature 'encryption-failclosed'. 2. plans/keyv-as-embedded-default-spec.md (698 lines) — Promote Keyv from optional driver to embedded default for fresh installs. Includes backwards-compat plan, config migration, and rollout sequence. Registered as AgilePlus feature 'keyv-as-embedded-default'. These specs intentionally do NOT include code changes — they are design-only and gate on answering the open questions before implementation. See spec section 9 for each spec's open questions. Co-authored-by: KooshaPari <koosha@example.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> * wip: auto-commit daemon 2026-08-06T09:18:52Z (#505) Co-authored-by: Airlock Bot <airlock@phenoforge.local> * refactor(db): migrate console.* to pino in src/lib/db/ (#522) Follows the PR #506/#507/#509/#510 pattern of replacing console.* with createLogger("db:<subsystem>") to provide structured logging across the SQLite persistence layer. Files modified (~155 callsites across 17 files): - src/lib/db/adapters/driverFactory.ts - src/lib/db/adapters/sqljsAdapter.ts - src/lib/db/apiKeys.ts - src/lib/db/backup.ts - src/lib/db/cleanup.ts (~30 sites) - src/lib/db/core.ts (~30 sites) - src/lib/db/migrationRunner.ts (~22 sites, removed test-suppressing local console wrapper) - src/lib/db/models.ts - src/lib/db/optimizationSettings.ts - src/lib/db/providers.ts - src/lib/db/quotaPools.ts - src/lib/db/quotaSnapshots.ts - src/lib/db/schemaColumns.ts (~35 sites) - src/lib/db/sessionAccountAffinity.ts - src/lib/db/settings.ts - src/lib/db/settings/cacheMetrics.ts - src/lib/db/stateReset.ts Per AGENTS.md guidance, never log SQLite encryption keys or raw secrets; all logger calls redact sensitive material. Behavior preservation: - All success-path behavior unchanged - Only the logging mechanism changes - Targeted tests pass One console.error preserved in core.ts:migrateFromJson because tests/unit/db-core-migration.test.ts overrides console.error to detect the failure; both console.error and log.error are emitted so the test passes and pino is the canonical sink. Co-authored-by: KooshaPari <koosha@example.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> * ci: use cache-pinned Trunk action * refactor: migrate console.* to pino in remaining src/ + open-sse/ Follows the PR #506/#507/#509/#510/#512/#518/#521/#522 pattern of replacing console.* with createLogger("domain:subsystem") to provide structured logging across the OmniRoute codebase. PR #522 already migrated src/lib/db/*.ts (~155 callsites). This PR migrates ~80 additional callsites across 37 files in: - src/lib/resilience/* (normalize.ts, anomalyHook.ts) - src/lib/oauth/* (connectionPersistence.ts) - src/lib/vscode/* (tokenizedRequest.ts, dual-emit for test capture) - src/lib/services/* (ringBuffer.ts, bootstrap.ts, embedWsProxy.ts, modelSync.ts) - src/lib/sseTextTransform.ts, src/lib/dataPaths.ts, src/lib/initCloudSync.ts - src/lib/events/eventBus.ts, src/lib/jobs/{budgetResetJob,reasoningCacheCleanupJob}.ts - src/lib/cloudSync.ts, src/lib/localHealthCheck.ts - src/lib/arenaEloSync.ts, src/lib/pricingSync.ts, src/lib/modelsDevSync.ts - src/lib/tokenHealthCheck.ts, src/lib/gracefulShutdown.ts - src/lib/apiBridgeServer.ts, src/lib/proxyLogger.ts - src/lib/middleware/registry.ts, src/lib/quota/connectionRecovery.ts - src/lib/credentialHealth/scheduler.ts - src/middleware/promptInjectionGuard.ts - src/server/ws/liveServer.ts (preserves [LiveWS] startup banner via log.info) - src/sse/services/auth.ts, src/sse/services/streamState.ts - open-sse/config/{constants,credentialLoader}.ts - open-sse/services/{autoRefreshDaemon,quotaMonitor}.ts - open-sse/mcp-server/audit.ts - open-sse/utils/proxyFetch.ts - open-sse/handlers/chatCore.ts (account fallback warnings) User-facing startup banners and intentional CLI output are preserved: - src/server/ws/liveServer.ts '[LiveWS] Dashboard WebSocket server listening' (now via log.info with structured host/port) - src/lib/vscode/tokenizedRequest.ts '[VSCODE][SECURITY]' warning kept as console.warn alongside log.warn so tests/unit/vscode-token-in-url-warning.test.ts (which captures console.warn to verify once-per-process dedup) keeps passing — same pattern as PR #522's preservation in db/core.ts:migrateFromJson - src/lib/oauth/utils/ui.ts (CLI formatting with picocolors) preserved as console - src/mitm/* (CLI-driven tooling) preserved - Next.js dashboard React components preserved (browser console, not server-side) Behavior preservation: - All success-path behavior unchanged - Only the logging mechanism changes - TSC baseline (typecheck-core.json) remains 0 errors - Targeted tests pass: resilience-settings-normalize-split (9/9), resilience-settings-stream-recovery (9/9), resilience-settings-provider-breaker (9/9), oauth-refresh-error-resilience (12/12), vscode-tokenized-request (3/3), vscode-token-in-url-warning (4/4), services/embedWsProxy (30/30) Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: KooshaPari <koosha@example.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: Airlock Bot <airlock@phenoforge.local>
* fix: use Node 24-compatible Keyv SQLite adapter * fix: migrate Trunk config to schema 0.1 * fix: use valid Trunk plugin source * fix: declare Trunk command success codes * fix: declare Trunk command output formats * fix: accept Trunk pass-fail findings * fix: keep Trunk checks available in CI --------- Co-authored-by: KooshaPari <koosha@example.com>
diegosouzapw#13124) Adds new resourcePressurePolicy.ts with full pressure monitoring and the OMNIROUTE_PRESSURE_PSI_DISABLED env var to disable PSI-based pressure detection when running in constrained environments.
OMNIROUTE_MAX_TOOLS_LIMIT env var overrides the default 128 tool limit. Also adds bypassDefaultToolLimit parameter to truncateToolList and per-provider known limits via getKnownToolLimit.
…iegosouzapw#13470) When a connection has a proxy assignment but the pool is dead, the refresh now checks PROXY_FAIL_OPEN before silently egressing on the host IP. If PROXY_FAIL_OPEN is not set, throws PROXY_ASSIGNED_UNAVAILABLE.
…uzapw#13504) Gives slow upstream providers more time before the queue rejects the request. Override via RATE_LIMIT_MAX_WAIT_MS env var.
Backport upstream ca23eed. Adds null-based memoization to getModelsDevPricing() with cache invalidation on save/clear and db state resets.
Adapted from upstream DB schema convergence commit (0ce2123). - check-install-upgrade.mjs: publish-time gate verifying migration parity - allowlist.json: migration reference mapping (upstream 163_ -> fork 169_) - Two test suites for convergence and schema parity validation
Comprehensive analysis of Next.js → SvelteKit migration: - 116 pages to migrate (~7,200 LOC) - Architecture shift from React SPA to BFF pattern - Component translation guide (React → Svelte 5 runes) - 7 batches with effort estimates (23-31 days solo, 8-11 days with 3 devs) - Risk areas identified: combo builder (4691 LOC), context system, provider mgmt
…days The on-disk model catalog cache had no maximum age. When /v1/models was unreachable, the plugin would serve a week-old (or older) catalog silently, causing stale model IDs and missing models. Now defaultDiskSnapshotReader rejects snapshots with writtenAt older than DISK_CACHE_MAX_AGE_MS (default 7 days). Overridable via env var. Fixes diegosouzapw#13390
applyStoredDatabaseOptimizationSettings() always passed applyPersistent: false, so the configured auto_vacuum mode was never applied at startup — the live database stayed at NONE even when INCREMENTAL was configured. Now respects the optimizeOnStartup flag. Fixes diegosouzapw#13432
getCompressionSettings() silently skipped non-string (BLOB) and invalid-JSON settings rows, making it impossible to diagnose config drift between the panel and the runtime. Now logs a warn-level message for each unreadable row, including the key name and a remediation hint (re-save from the Storage panel). Also warns when the 'engines' row exists but yields no valid toggles, so operators know their panel-configured engines map is being silently replaced by the legacy fallback. Fixes diegosouzapw#13456
…iegosouzapw#13457) cavemanConfig.preservePatterns was silently skipped when a user region contained built-in preserved constructs (inline code, URLs, headings, CONST_CASE, etc.). The root cause: built-in patterns ran first and replaced inline constructs within the user region with sentinel placeholders. When the user pattern then tried to match the region, the sentinel was present in the match and replacePattern silently returned it unchanged. The fix: user patterns now run BEFORE built-in patterns, so user regions are captured as whole sentinels before built-in patterns can fragment them. 5 tests in tests/unit/compression/preserve-patterns-order.test.ts. Fixes diegosouzapw#13457
Create 11 SvelteKit pages for the migration: - cost/budget, cost/pricing, cost/quota-share - discovery, leaderboard, free-provider-rankings - free-tiers, limits, quota, translator, changelog Each page uses Svelte 5 runes, bffApiUrl() for data fetching, and follows the thin-shell pattern (40-120 LOC).
11 new BFF route files for SvelteKit migration: - costs, discovery, leaderboard, free-provider-rankings - free-tiers, limits, quota, translator, changelog, chaos, relay Each provides mock/placeholder data matching the shape expected by SvelteKit pages. Routes registered in index.ts.
…onstraint (diegosouzapw#13481) When a combo fails over, each attempt has a unique traceId but shares the same pendingRequestId. Using pendingRequestId as the call_logs.id caused a UNIQUE constraint violation on the second attempt, silently dropping the winning (successful) attempt's log row. Changed saveCallLog to use traceId as the row id. traceId is unique per attempt, emitted in request.started, and pairs with the lifecycle events. pendingRequestId continues to be available for correlation. Updated existing tests to default traceId from pendingRequestId. Added test verifying two combo attempts with different traceIds are both persisted without collision. Fixes diegosouzapw#13481
- 74 total vulns (35 prod, 39 dev-only) - 2 critical (next, mermaid), fixable via direct upgrades - 56 fork-only CI workflows, 23 shared with upstream - Fork infrastructure investment is intentional
…onstraint (diegosouzapw#13481) When a combo fails over, each attempt has a unique traceId but shares the same pendingRequestId. Using pendingRequestId as the call_logs.id caused a UNIQUE constraint violation on the second attempt, silently dropping the winning (successful) attempt's log row. Changed saveCallLog to use traceId as the row id. traceId is unique per attempt, emitted in request.started, and pairs with the lifecycle events. pendingRequestId continues to be available for correlation. Added test verifying two combo attempts with different traceIds are both persisted without collision. Fixes diegosouzapw#13481
…gosouzapw#13483) No-auth providers (opencode, duckduckgo-web, etc.) returned synthetic 'noauth' credentials early in getProviderCredentials, bypassing the model lockout check. A model_capacity lockout was recorded but never enforced — every request retried the same locked model, paying a wasted upstream round-trip (~2s) before failing over. Added isModelLocked check for the synthetic noauth connection before returning credentials. When a model is lockout-blocked, the function returns null, allowing the combo engine to skip to the next member without contacting the upstream. 4 tests in tests/unit/noauth-model-lockout.test.ts. Fixes diegosouzapw#13483
Merge Protections🔴 1 of 2 protections blocking · waiting on 🙋 you
🔴 🚦 Auto-queueWaiting for
This rule is failing.When all merge protections are satisfied and these conditions match, this pull request will be queued automatically.
Show 1 satisfied protection🟢 📃 Configuration Change RequirementsMergify configuration change
|
Owner
diegosouzapw
added a commit
to KooshaPari/OmniRoute
that referenced
this pull request
Sep 15, 2026
…souzapw#13527); rebaseline auth.ts
diegosouzapw
pushed a commit
that referenced
this pull request
Sep 15, 2026
…ection (#13547) No-auth providers now honor a recorded model-only lockout before `getProviderCredentials` hands back the synthetic `noauth` connection (#13483). That early return skipped the per-connection status pass, so a `model_capacity` lockout was recorded but never enforced, and every request re-tried the locked model for a wasted upstream round-trip before failing over. Maintainer additions: carried your `tests/unit/noauth-model-lockout.test.ts` from #13527. 3 of its 4 cases fail on the release tip without the fix and pass with it. Rebaselined `src/sse/services/auth.ts` 3542→3556 in `file-size-baseline.json` with a dated annotation. Validated in one consolidated batch of this series (37 PRs boarded together on `release/v3.8.51`): `typecheck:core`, `check:open-sse-typecheck` and `check:dashboard-typecheck` clean; ESLint clean on every changed file; file-size, complexity, cognitive-complexity, changelog-integrity, docs-counts, docs-sync and migration-numbering gates green (only the pre-existing `open-sse/utils/stream.ts` file-size red remains, inherited from the base); 3,743 focused `node:test` cases plus 34 vitest cases green. Thanks @KooshaPari!
muhamadgalihsaputra
pushed a commit
to niyatna/NiyatnaRoute
that referenced
this pull request
Sep 27, 2026
…ection (diegosouzapw#13547) No-auth providers now honor a recorded model-only lockout before `getProviderCredentials` hands back the synthetic `noauth` connection (diegosouzapw#13483). That early return skipped the per-connection status pass, so a `model_capacity` lockout was recorded but never enforced, and every request re-tried the locked model for a wasted upstream round-trip before failing over. Maintainer additions: carried your `tests/unit/noauth-model-lockout.test.ts` from diegosouzapw#13527. 3 of its 4 cases fail on the release tip without the fix and pass with it. Rebaselined `src/sse/services/auth.ts` 3542→3556 in `file-size-baseline.json` with a dated annotation. Validated in one consolidated batch of this series (37 PRs boarded together on `release/v3.8.51`): `typecheck:core`, `check:open-sse-typecheck` and `check:dashboard-typecheck` clean; ESLint clean on every changed file; file-size, complexity, cognitive-complexity, changelog-integrity, docs-counts, docs-sync and migration-numbering gates green (only the pre-existing `open-sse/utils/stream.ts` file-size red remains, inherited from the base); 3,743 focused `node:test` cases plus 34 vitest cases green. Thanks @KooshaPari!
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.
Fixes #13483.
No-auth providers (opencode, duckduckgo-web, etc.) returned synthetic 'noauth' credentials early in getProviderCredentials, bypassing the model lockout check. A model_capacity lockout was recorded but never enforced — every request retried the same locked model, paying a wasted upstream round-trip before failing over.
Added isModelLocked check for the synthetic noauth connection before returning credentials. When a model is lockout-blocked, the function returns null, allowing the combo engine to skip to the next member without contacting the upstream.
4 tests in tests/unit/noauth-model-lockout.test.ts.