Commit Graph
46 Commits
Author SHA1 Message Date
MUH. IQRAM BAHRING 25df5e6a9d chore(guards): add durable markers so fixes aren't silently dropped
Introduce AGENTS.md (root, primary agent instruction file) documenting six
hard-won fixes with explicit DO NOT / WHY, plus executable enforcement so a
future AI cannot delete or reintroduce them:

1. package-lock.json must be generated with npm 10 (Docker's npm 10.9.8).
   npm 11 drops the top-level @emnapi/core + @emnapi/runtime entries npm 10
   needs, breaking the tag-triggered Docker build at `npm ci` (happened on
   v1.0.14). Add scripts/verify-lockfile-npm10.mjs + .npmrc + a Dockerfile
   fail-fast check + a CI step + tests/unit/lockfile-npm10-guard.test.js.
   Also re-fix the lockfile itself (regenerated with npm 10.9.8).
2. Tests must never write to the real ~/.9router DB (isolateDataDir).
3. Hidden providers must not leak into Usage (usageProviders !p.hidden).
4. codebuddy-intl connection test + OAuth identity.
5. Fork-only features that must survive upstream syncs.
6. Upstream sync procedure.

Each marker cross-references AGENTS.md and the covering test. CLAUDE.md now
points to AGENTS.md at the top. Verified: build ok, guard script passes,
full suite leaves the real DB count unchanged (38), 0 new regressions.
2026-09-19 12:52:19 +08:00
MUH. IQRAM BAHRING 9c37af90a9 test(harness): isolate DATA_DIR so tests never write to the real DB
Root cause of fake connections in Usage (zed-live-*@example.com,
guard-*@example.com, zed "Account N", kimchi-nope): route-level tests
(zed-live-models, zed-native-auth) call createProviderConnection, which
persists to $DATA_DIR/db/data.sqlite. With DATA_DIR unset — the default
for `npx vitest run` — that resolved to the user's real ~/.9router DB,
appending test rows on every run. Both files documented "RUN WITH AN
ISOLATED DB" but never enforced it.

Add tests/setup/isolateDataDir.js (wired via vitest setupFiles) that
points DATA_DIR at a throwaway temp dir before src/lib/dataDir.js is
imported. Opt out with RUN_REAL=1 or an explicit DATA_DIR (used by the
*.real.test.js suites that read live credentials).

Verified: a full suite run now leaves the real DB byte-count unchanged;
new guard test tests/unit/test-data-dir-isolation.test.js locks it in.
2026-09-19 12:37:57 +08:00
MUH. IQRAM BAHRING 9d7821bdcc fix(usage): stop leaking hidden noAuth providers (devin-cli, mimo-free)
The Usage page auto-adds every noAuth free provider so connectionless
providers (opencode) still appear. It did not filter the registry's
hidden flag, so devin-cli and mimo-free — both category:"free" with
noAuth:true and hidden:true — showed up in Usage despite having no
connection and being absent from the Providers page (which does filter
hidden).

Extract the list assembly into buildUsageProviderList (shared/utils/
usageProviders.js) and skip hidden free providers there. Behavior for
visible noAuth providers (opencode) and dedup of active connections is
unchanged; covered by tests/unit/usage-provider-list.test.js.
2026-09-19 12:21:14 +08:00
MUH. IQRAM BAHRING 604b4d85d5 fix(codebuddy-intl): probe token in connection test + name OAuth by identity
Two bugs on codebuddy-intl connections:

1. Test Connection always failed with "Provider test not supported":
   codebuddy-intl was missing from OAUTH_TEST_CONFIG, so testOAuthConnection
   bailed before probing. Add a real probe against the Keycloak realm's
   userinfo endpoint (URL derived from the token's iss claim), and wire
   refreshable so an expired token is rotated via refreshCodebuddyIntlToken.

2. OAuth logins were named "Account N" with no email: mapTokens returned no
   identity, even though the access token is a Keycloak JWT carrying
   email/name claims. Extract email + displayName in mapTokens (new shared
   extractDisplayNameFromAccessToken helper) so fresh logins are named and
   deduped by identity.

Also add a run-once backfill (backfillCodeBuddyIntlIdentity) invoked from
GET /api/providers and /api/providers/client to self-heal existing rows
(backfill email/displayName, rename the generic "Account N" placeholder).

Verified live: the real connection now returns valid:true and the row is
renamed to the account email.
2026-09-19 12:14:21 +08:00
MUH. IQRAM BAHRING 1884e3a063 test(cline): align auth-header test with upstream WorkOS-JWT-only prefixing
Upstream f6e7cabe stopped workos:-prefixing opaque tokens (ClinePass API
keys like clp_...), so getClineAccessToken now only prefixes WorkOS JWTs.
The fork's test asserted the old unconditional-prefix behavior.
2026-09-19 11:47:15 +08:00
MUH. IQRAM BAHRING 9342aa5fb9 chore(version): bump app version to 1.0.14 (upstream v0.5.81 sync) 2026-09-19 11:36:17 +08:00
MUH. IQRAM BAHRING 0ac771bad8 merge: sync upstream v0.5.81 into MIBP fork
# Conflicts:
#	.gitignore
#	Dockerfile
#	open-sse/handlers/chatCore.js
#	open-sse/providers/registry/cline.js
#	open-sse/providers/registry/index.js
#	open-sse/services/usage.js
#	open-sse/utils/streamHandler.js
#	package.json
#	src/app/(dashboard)/dashboard/profile/page.js
#	src/app/(dashboard)/dashboard/providers/[id]/page.js
2026-09-19 11:35:34 +08:00
MUH. IQRAM BAHRING b0505067b2 feat(providers): add Cline free-tier models and sync Freebuff catalog
- Cline: 6 free models, cline-cli product headers, API-key auth,
  {data} envelope unwrap, workos: prefix handling
- Freebuff: muse-spark 1.3 → 1.2 (upstream withdrawal 2026-09-07),
  DeepSeek V4.1 Flash rename
2026-09-11 12:21:35 +08:00
MUH. IQRAM BAHRING 8b34cfaa44 chore(version): update app version to 1.0.12 2026-09-07 22:28:20 +08:00
MUH. IQRAM BAHRING 9c17c5f96c feat(freebuff): enhance Freebucks handling and pricing logic across services 2026-09-07 22:26:28 +08:00
MUH. IQRAM BAHRING eedfdf982b chore(version): align app version to fork release cadence (1.0.11) 2026-09-06 00:45:19 +08:00
MUH. IQRAM BAHRING 06c66d8df8 ci(docker): pin node:22-alpine by digest so npm cannot drift under npm ci 2026-09-05 23:55:33 +08:00
MUH. IQRAM BAHRING a2c6187aed chore(deps): resync lockfile with npm 10 (docker npm ci missing @emnapi 1.11.3) 2026-09-05 23:55:33 +08:00
MUH. IQRAM BAHRING c378f2dc90 Merge remote-tracking branch 'upstream/master' 2026-09-05 23:20:53 +08:00
MUH. IQRAM BAHRING 9cd61d585c feat(freebuff): update model catalog + fable offer claims 2026-09-05 23:18:42 +08:00
MUH. IQRAM BAHRING cdbdcd3448 ci(docker): pin actions by SHA, add concurrency, exclude tests from build context 2026-08-30 23:47:01 +08:00
MUH. IQRAM BAHRING eaf204b83c Merge remote-tracking branch 'upstream/master'
# Conflicts:
#	open-sse/handlers/chatCore.js
#	open-sse/providers/registry/index.js
#	open-sse/services/usage.js
2026-08-30 23:23:48 +08:00
MUH. IQRAM BAHRING 2d6673db61 docs: rewrite README for MIBP fork (docker + manual install) 2026-08-15 08:35:36 +08:00
MUH. IQRAM BAHRING 470c8ca72c fix(docker): regenerate platform-complete lockfile (npm 10, clean resolve) 2026-08-15 08:14:03 +08:00
MUH. IQRAM BAHRING 76b139b32c fix(docker): restore lockfile (npm 10) + npm ci for reliable builds 2026-08-15 08:07:59 +08:00
MUH. IQRAM BAHRING 3d10fd9611 chore(docker): follow upstream — untrack package-lock, use npm install 2026-08-15 04:25:18 +08:00
MUH. IQRAM BAHRING c895410510 chore(deps): sync package lock 2026-08-15 04:11:54 +08:00
MUH. IQRAM BAHRING f555236545 merge: update from decolua/9router upstream (SAML, providers, opencode session headers) 2026-08-15 03:54:03 +08:00
MUH. IQRAM BAHRING df8c4ccb81 fix: improve provider routing and assignments 2026-08-15 03:47:18 +08:00
MUH. IQRAM BAHRING d00205511a feat(docs): add screenshots + beginner install guide, MIBP Edition credits 2026-08-07 12:48:39 +08:00
MUH. IQRAM BAHRING 7929464427 fix: restore platform-complete package-lock for linux npm ci 2026-08-07 09:32:23 +08:00
MUH. IQRAM BAHRING 56f46aa433 chore(ci): disable gitbook pages workflow for fork, add healthcheck + geo env docs
gitbook-pages.yml deployed to upstream org's 9router.github.io which a fork
cannot (no GH_PAGES_DEPLOY_KEY) — renamed to .yml.disabled. Dockerfile gains
a /api/health HEALTHCHECK. .env.example documents the new pool geostrobes
env knobs (POOL_GEO_PROBE_DISABLED, GEO_PROBE_URL).
2026-08-07 08:35:49 +08:00
MUH. IQRAM BAHRING 3844f04cb5 fix(profile): move Check Size Memory button beside Import Backup 2026-08-07 08:20:27 +08:00
MUH. IQRAM BAHRING 1f4813c786 feat(profile): Check Size Memory button + English geo-probe hint
New /api/system/memory reports db + data-dir sizes and in-memory state
(fitness/geo registries, freebuff session/cooldown counts); profile page
'Local Mode' card gets a Check Size Memory button rendering the summary.
Geo-probe toggle hint localized to English.
2026-08-07 08:11:44 +08:00
MUH. IQRAM BAHRING 37d03aa0d5 feat(proxy-fitness): on/off toggle for egress geo probe
Header toggle in Proxy Fitness persists settings.poolGeoProbeEnabled
(default on); the probe scheduler reads it each pass and skips when off.
The env POOL_GEO_PROBE_DISABLED remains a hard override. Smart rotation is
unaffected — it runs off the fitness registry from real request failures.
2026-08-07 08:01:55 +08:00
MUH. IQRAM BAHRING a443834f53 feat(proxy-fitness): multi-endpoint egress geo probe chain
Try ipwho.is -> ip-api.com -> ipapi.co -> ipinfo.io in order so a
rate-limited/broken provider falls through to the next; ipinfo (most
quota-bound) is last. Normalize each payload to {ip,country,region,city,org},
keep 15s timeout per endpoint, and support GEO_PROBE_URL to replace the
chain with a single custom endpoint.
2026-08-07 07:45:54 +08:00
MUH. IQRAM BAHRING 3c4bd4f1e5 feat(proxy-fitness): throttle egress geo probe + aggregate failure log
Refuse re-probing failures too fast: 500/429 failures get a 2h backoff,
other errors 30m (flapping relays/quota stops hammering ipinfo every pass,
passes every 30 min instead of 15). One-line summary per pass
(geo N/M · fail: rate×a server×b) replaces the per-pool error wall.
New env POOL_GEO_PROBE_DISABLED=1 turns the feature off.
2026-08-07 07:16:29 +08:00
MUH. IQRAM BAHRING c1bbe446de chore: drop full error stack traces from chat error logs
Shorten the ✗ ERROR 502 / stream ERROR lines to the message only; the
multi-KB next-dev stack trace polluted the console on every provider error.
2026-08-07 06:39:54 +08:00
MUH. IQRAM BAHRING fa679a676d docs(cloud): raise nginx client_max_body_size for large-context payloads
nginx default 1m rejects multi-MB chat bodies (1M-token prompts) with
413 before they reach 9Router; set 128m in the documented site config.
2026-08-07 05:40:18 +08:00
MUH. IQRAM BAHRING 2a1e192734 feat(api): advertise context_window on /v1/models from capabilities 2026-08-07 04:56:40 +08:00
MUH. IQRAM BAHRING 041e039793 chore: strip per-request DEBUG logs from chat path
Remove [DBG:STREAM] chunk/pipe/EOF instrumentation and [DBG:SSE] flush +
fetch success lines that spam the dev console every request. Keep the stream
stall watchdog and the fetch-error (✖) diagnostics.
2026-08-07 04:24:54 +08:00
MUH. IQRAM BAHRING ad43a267ac chore: re-sync package-lock 2026-08-07 04:04:35 +08:00
MUH. IQRAM BAHRING a0bf2e3f96 fix(token-refresh): stop dead-token retry loop, lift block on refresh success
Unrecoverable refresh errors (invalid_grant/invalid_request) are persisted as
a refreshBlocked marker so the background scheduler stops hammering the
provider every 5 minutes and surfaces re-login required; the marker is lifted
automatically when a later refresh succeeds. Cooldown maps gained lazy pruning.
2026-08-07 03:51:38 +08:00
MUH. IQRAM BAHRING b75d665fa5 feat(proxy-fitness): egress geo probe + unstable detection + state sweeper
Background probe fetches ipinfo through each pool itself (provider-agnostic
transport), fills an egress IP/country cache (TTL 1h, 8-IP history) and flags
flapping relays as unstable. Periodic state sweeper (10 min) prunes expired
fitness marks, stale geo/ip-history and Freebuff session/cooldown state;
schedulers skip non-server runtimes. Unit tests for the geo cache.
2026-08-07 03:51:29 +08:00
MUH. IQRAM BAHRING fd22290a34 feat(proxy-fitness): pool fitness registry + Smart rotation + pool-scoped retry
Pool/IP fitness registry (globalThis-backed, provider::model scopes, 5-min
cooldown, provider::* wildcard) fed by pool-scoped failures: freebuff
limited-IP / model-locked gates and opencode free per-IP limits. chatCore
retries a failed pool via another pool without locking the account; new
Smart rotation strategy (per-connection + no-auth providers) skips unfit
pools. Proxy Fitness dashboard page: active-block table with provider/IP
filters, per-record Clear and provider-scoped Clear All; egress column via
pool geo enrichment. Unit tests for the registry.
2026-08-07 03:51:19 +08:00
MUH. IQRAM BAHRING 90ff8191ff fix: lock Docker dependencies and remove test credential 2026-08-06 04:10:58 +08:00
MUH. IQRAM BAHRING d05b84d377 chore: prepare fork docker deployment 2026-08-06 03:11:31 +08:00
MUH. IQRAM BAHRING eca3b9c3dc fix: add FREEBUFF_CONFIG export to oauth constants
- Export FREEBUFF_CONFIG from src/lib/oauth/constants/oauth.js
- Fixes build error: 'Export FREEBUFF_CONFIG doesn't exist in target module'
2026-08-06 01:05:20 +08:00
MUH. IQRAM BAHRING de5fb415a7 feat: register Freebuff provider in all index files
- Add Freebuff to providers registry (open-sse/providers/registry/index.js)
- Register FreebuffExecutor (open-sse/executors/index.js)
- Add Freebuff OAuth config (src/lib/oauth/providers/index.js)
- Register Freebuff usage handler (open-sse/services/usage.js)

This enables Freebuff provider to appear in dashboard and be fully functional.
2026-08-06 00:54:04 +08:00
MUH. IQRAM BAHRING b15b0c930a docs: add upstream sync instructions to README 2026-08-06 00:35:29 +08:00
MUH. IQRAM BAHRING 8343d54bf2 feat: add Freebuff provider and fix dompurify security vulnerabilities
- Add Freebuff provider integration (executor, registry, OAuth, usage tracking)
- Upgrade monaco-editor to ^0.56.0
- Add dompurify ^3.4.13 with override to fix security vulnerabilities
- Add Freebuff provider icon and test files
2026-08-06 00:30:06 +08:00