From 340dcf9515027437aa725b470f4a4b689bba2163 Mon Sep 17 00:00:00 2001 From: diegosouzapw Date: Sat, 21 Feb 2026 09:05:59 -0300 Subject: [PATCH 1/2] feat(core): api key protection, provider blocking, windows fix, ui and docs --- .agent/workflows/issue-triage.md | 65 ++++++++++ .agent/workflows/update-docs.md | 41 +++++++ CHANGELOG.md | 18 +++ README.md | 1 + README.pt-BR.md | 1 + docs/FEATURES.md | 2 +- docs/USER_GUIDE.md | 2 +- src/app/(dashboard)/dashboard/combos/page.tsx | 4 +- .../settings/components/SecurityTab.tsx | 114 +++++++++++++++++- src/app/api/v1/models/route.ts | 26 +++- src/lib/db/migrationRunner.ts | 23 +++- 11 files changed, 287 insertions(+), 10 deletions(-) create mode 100644 .agent/workflows/issue-triage.md create mode 100644 .agent/workflows/update-docs.md diff --git a/.agent/workflows/issue-triage.md b/.agent/workflows/issue-triage.md new file mode 100644 index 0000000000..3bfda2f6e6 --- /dev/null +++ b/.agent/workflows/issue-triage.md @@ -0,0 +1,65 @@ +--- +description: How to respond to GitHub issues with insufficient information +--- + +# GitHub Issue Triage — Requesting More Information + +When analyzing a GitHub issue and the provided information is insufficient to diagnose or implement a fix, follow these steps: + +## 1. Identify Missing Information + +Check if the issue contains: + +- [ ] Clear description of the problem or feature +- [ ] Steps to reproduce (for bugs) +- [ ] Error messages / logs +- [ ] Environment details (OS, version, deployment method) +- [ ] Expected vs actual behavior +- [ ] Screenshots (if UI-related) + +## 2. Draft a Response (in English) + +Use this template structure, adapting to what's specifically missing: + +```markdown +Thanks for reporting this issue! 🙏 + +To help us investigate and fix this, could you please provide some more details? + +1. **Environment**: What OS are you running? How did you install OmniRoute (npm global, Docker, from source)? +2. **Steps to Reproduce**: What exact steps lead to this issue? +3. **Error Logs**: Can you share the full server logs? (Check the terminal or `logs/application/app.log`) +4. **Expected vs Actual**: What did you expect to happen, and what actually happened? +5. **Screenshots**: If this is a UI issue, a screenshot would be very helpful. + +This information will help us reproduce and fix the issue more quickly. Thank you! +``` + +## 3. Adapt the Template + +- Remove items that are already provided in the issue +- Add domain-specific questions based on the issue type: + - **OAuth/Auth issues**: Ask for provider name, auth flow used, token errors + - **Multi-account issues**: Ask how many accounts, which providers, dashboard screenshots + - **Startup/crash issues**: Ask for full startup logs, OS version, Node.js version + - **UI rendering issues**: Ask for browser name, screen resolution, screenshots + - **API issues**: Ask for request/response examples, curl commands used + +## 4. Post the Response + +// turbo +Post the response as a comment on the GitHub issue using the GitHub CLI: + +```bash +gh issue comment --repo diegosouzapw/OmniRoute --body "" +``` + +If `gh` CLI is not available, provide the response text to the user to post manually. + +## 5. Add Labels (optional) + +If applicable, add a `needs-info` label: + +```bash +gh issue edit --repo diegosouzapw/OmniRoute --add-label "needs-info" +``` diff --git a/.agent/workflows/update-docs.md b/.agent/workflows/update-docs.md new file mode 100644 index 0000000000..76be0579d9 --- /dev/null +++ b/.agent/workflows/update-docs.md @@ -0,0 +1,41 @@ +--- +description: How to automatically summarize recent changes and update README and CHANGELOG +--- + +# Update Documentation and Changelog Workflow + +When asked to run the `/update-docs` workflow or summarize recent changes into the documentation, follow these steps: + +## 1. Gather Recent Work Context + +1. **Review Task History**: Check the current `task.md`, `walkthrough.md`, and any `implementation_plan.md` in the agent's brain directory to understand exactly what features, bug fixes, and architectural changes were recently made. +2. **Identify Key Features**: Group the changes into logical categories: + - **New Features** (e.g. new settings, new endpoints, new UI components) + - **Bug Fixes** (e.g. layout fixes, crash resolutions, cross-platform fixes) + - **Security/Performance** (e.g. auth gating, new optimizations) + +## 2. Update the CHANGELOG.md + +1. If `CHANGELOG.md` does not exist in the root directory, create it. +2. Under the `## [Unreleased]` section (or create a new version header if releasing): + - Add a `### Added` section for new features. + - Add a `### Fixed` section for bug fixes. + - Summarize the recent work into bullet points, referencing GitHub issue numbers if applicable (e.g. `Fix Windows server startup crash (Issue #98)`). + +## 3. Update README.md (and translated versions like README_pt-BR.md) + +1. **Main Features List**: If a notable new feature was added (like a new security setting or API option), add it to the feature list section. +2. **Configuration/Settings**: If any new environment variables or dashboard settings were introduced, document them in the configuration or usage sections so users know how to enable them. +3. If there are translated versions of the README (like Portuguese), ensure those are updated equivalently. + +## 4. Update Technical Docs (docs/ directory) + +1. Use `list_dir` to inspect the `docs/` folder. +2. Determine which technical documents need updates. For example: + - If an API changed, update `docs/API_REFERENCE.md` or similar. + - If security settings changed, update `docs/SECURITY.md` or `docs/CONFIGURATION.md`. +3. Read the relevant files, update their content using `replace_file_content`, and briefly explain how the new feature works under the hood. + +## 5. Verify the Updates + +Ensure all markdown files are properly formatted and no existing sections were accidentally deleted. Present the changes to the user showing which files were updated. diff --git a/CHANGELOG.md b/CHANGELOG.md index c1f7594904..dca457ae6b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 --- +## [1.0.8] — 2026-02-21 + +> ### 🔒 API Security & Windows Support +> +> Adds API Endpoint Protection for `/models`, Windows server startup fixes, and UI improvements. + +### ✨ New Features + +- **API Endpoint Protection (`/models`)** — New Security Tab settings to optionally require an API key for the `/v1/models` endpoint (returns 404 when unauthorized) and to selectively block specific providers from appearing in the models list ([#100](https://github.com/diegosouzapw/OmniRoute/issues/100), [#96](https://github.com/diegosouzapw/OmniRoute/issues/96)) +- **Interactive Provider UI** — Blocked Providers setting features an interactive chip selector with visual badges for all available AI providers + +### 🐛 Bug Fixes + +- **Windows Server Startup** — Fixed `ERR_INVALID_FILE_URL_PATH` crash on Windows by safely wrapping `import.meta.url` resolution with a fallback to `process.cwd()` for globally installed npm packages ([#98](https://github.com/diegosouzapw/OmniRoute/issues/98)) +- **Combo buttons visibility** — Fixed layout overlap and tight spacing for the Quick Action buttons (Clone / Delete / Test) on the Combos page on narrower screens ([#95](https://github.com/diegosouzapw/OmniRoute/issues/95)) + +--- + ## [1.0.7] — 2026-02-20 > ### 🐛 Bugfix Release — OpenAI Compatibility, Custom Models & OAuth UX diff --git a/README.md b/README.md index 6a0bc0fab5..8d4c466b82 100644 --- a/README.md +++ b/README.md @@ -373,6 +373,7 @@ Access via: WhatsApp, Telegram, Slack, Discord, iMessage, Signal... | 🔒 **TLS Fingerprint Spoofing** | Bypass TLS-based bot detection via wreq-js | | 🌐 **IP Filtering** | Allowlist/blocklist for API access control | | 📊 **Editable Rate Limits** | Configurable RPM, min gap, and max concurrent at system level | +| 🛡 **API Endpoint Protection** | Auth gating + provider blocking for the `/models` endpoint | ### 📊 Observability & Analytics diff --git a/README.pt-BR.md b/README.pt-BR.md index d2e1bcbd1f..923204f51d 100644 --- a/README.pt-BR.md +++ b/README.pt-BR.md @@ -373,6 +373,7 @@ Acesso via: WhatsApp, Telegram, Slack, Discord, iMessage, Signal... | 🔒 **Spoofing de Fingerprint TLS** | Bypass de detecção de bot via TLS com wreq-js | | 🌐 **Filtragem de IP** | Allowlist/blocklist para controle de acesso à API | | 📊 **Rate Limits Editáveis** | RPM, gap mínimo e concorrência máxima configuráveis | +| 🛡 **Proteção de Endpoint API** | Gateway de Auth + bloqueio de provedores para o endpoint `/models` | ### 📊 Observabilidade e Analytics diff --git a/docs/FEATURES.md b/docs/FEATURES.md index d2bd088b79..d98dd70aae 100644 --- a/docs/FEATURES.md +++ b/docs/FEATURES.md @@ -46,7 +46,7 @@ Four modes for debugging API translations: **Playground** (format converter), ** ## ⚙️ Settings -General settings, system storage, backup management (export/import database), appearance (dark/light mode), security, routing, resilience, and advanced configuration. +General settings, system storage, backup management (export/import database), appearance (dark/light mode), security (includes API endpoint protection and custom provider blocking), routing, resilience, and advanced configuration. ![Settings Dashboard](screenshots/06-settings.png) diff --git a/docs/USER_GUIDE.md b/docs/USER_GUIDE.md index 2cf009be87..4b3fc42b09 100644 --- a/docs/USER_GUIDE.md +++ b/docs/USER_GUIDE.md @@ -610,7 +610,7 @@ The settings page is organized into 5 tabs for easy navigation: | Tab | Contents | | -------------- | ---------------------------------------------------------------------------------------------- | -| **Security** | Login/Password settings and IP Access Control (allowlist/blocklist) | +| **Security** | Login/Password settings, IP Access Control, API auth for `/models`, and Provider Blocking | | **Routing** | Global routing strategy (6 options), wildcard model aliases, fallback chains, combo defaults | | **Resilience** | Provider profiles, editable rate limits, circuit breaker status, policies & locked identifiers | | **AI** | Thinking budget configuration, global system prompt injection, prompt cache stats | diff --git a/src/app/(dashboard)/dashboard/combos/page.tsx b/src/app/(dashboard)/dashboard/combos/page.tsx index 3dcda4d1ab..acf0e8b093 100644 --- a/src/app/(dashboard)/dashboard/combos/page.tsx +++ b/src/app/(dashboard)/dashboard/combos/page.tsx @@ -409,14 +409,14 @@ function ComboCard({ {/* Actions */} -
+
-
+
+ ); + })} +
+ {blockedProviders.length > 0 && ( +

+ warning + {blockedProviders.length} provider{blockedProviders.length !== 1 ? "s" : ""} blocked + from /models +

+ )} +
+
+ +
diff --git a/src/app/api/v1/models/route.ts b/src/app/api/v1/models/route.ts index 4fe9bf1fe8..ad39b6df06 100644 --- a/src/app/api/v1/models/route.ts +++ b/src/app/api/v1/models/route.ts @@ -1,7 +1,8 @@ import { CORS_ORIGIN } from "@/shared/utils/cors"; import { PROVIDER_MODELS, PROVIDER_ID_TO_ALIAS } from "@/shared/constants/models"; import { AI_PROVIDERS } from "@/shared/constants/providers"; -import { getProviderConnections, getCombos, getAllCustomModels } from "@/lib/localDb"; +import { getProviderConnections, getCombos, getAllCustomModels, getSettings } from "@/lib/localDb"; +import { extractApiKey, isValidApiKey } from "@/sse/services/auth"; import { getAllEmbeddingModels } from "@omniroute/open-sse/config/embeddingRegistry.ts"; import { getAllImageModels } from "@omniroute/open-sse/config/imageRegistry.ts"; import { getAllRerankModels } from "@omniroute/open-sse/config/rerankRegistry.ts"; @@ -94,10 +95,28 @@ export async function OPTIONS() { * GET /v1/models - OpenAI compatible models list * Returns models from all active providers, combos, embeddings, and image models in OpenAI format */ -export async function GET() { +export async function GET(request: Request) { try { + // Issue #100: Optionally require API key for /models (security hardening) + // When enabled, unauthenticated requests get 404 to hide endpoint existence + let settings: Record = {}; + try { + settings = await getSettings(); + } catch {} + if (settings.requireAuthForModels === true) { + const apiKey = extractApiKey(request); + if (!apiKey || !(await isValidApiKey(apiKey))) { + return new Response("Not Found", { status: 404 }); + } + } + const { aliasToProviderId, providerIdToAlias } = buildAliasMaps(); + // Issue #96: Allow blocking specific providers from the models list + const blockedProviders: Set = new Set( + Array.isArray(settings.blockedProviders) ? settings.blockedProviders : [] + ); + // Get active provider connections let connections = []; let totalConnectionCount = 0; // Track if DB has ANY connections (even disabled) @@ -150,6 +169,9 @@ export async function GET() { const providerId = aliasToProviderId[alias] || alias; const canonicalProviderId = FALLBACK_ALIAS_TO_PROVIDER[alias] || providerId; + // Skip blocked providers (Issue #96) + if (blockedProviders.has(alias) || blockedProviders.has(canonicalProviderId)) continue; + // Only include models from providers with active connections if (!activeAliases.has(alias) && !activeAliases.has(canonicalProviderId)) { continue; diff --git a/src/lib/db/migrationRunner.ts b/src/lib/db/migrationRunner.ts index d8fbe7a71b..b18a8e7047 100644 --- a/src/lib/db/migrationRunner.ts +++ b/src/lib/db/migrationRunner.ts @@ -14,9 +14,26 @@ import path from "node:path"; import { fileURLToPath } from "node:url"; import type Database from "better-sqlite3"; -const __filename = fileURLToPath(import.meta.url); -const __dirname = path.dirname(__filename); -const MIGRATIONS_DIR = path.join(__dirname, "migrations"); +/** + * Resolve the migrations directory path safely across platforms. + * On Windows with global npm installs, `import.meta.url` may not be a valid + * `file://` URL, causing `fileURLToPath` to throw `ERR_INVALID_FILE_URL_PATH`. + */ +function resolveMigrationsDir(): string { + try { + const metaUrl = import.meta.url; + if (metaUrl && metaUrl.startsWith("file://")) { + const __filename = fileURLToPath(metaUrl); + return path.join(path.dirname(__filename), "migrations"); + } + } catch { + // fileURLToPath failed (e.g. Windows global install) — use fallback + } + // Fallback: resolve relative to cwd (works for both dev and global installs) + return path.join(process.cwd(), "src", "lib", "db", "migrations"); +} + +const MIGRATIONS_DIR = resolveMigrationsDir(); /** * Ensure the schema_migrations tracking table exists. From 1aa27ceefee485abc609f3d7cd353863bd3b76f9 Mon Sep 17 00:00:00 2001 From: diegosouzapw Date: Sat, 21 Feb 2026 09:11:14 -0300 Subject: [PATCH 2/2] chore(workflows): move agent workflows to global dir --- .agent/workflows/git-workflow.md | 54 -------------------------- .agent/workflows/issue-triage.md | 65 -------------------------------- .agent/workflows/update-docs.md | 41 -------------------- 3 files changed, 160 deletions(-) delete mode 100644 .agent/workflows/git-workflow.md delete mode 100644 .agent/workflows/issue-triage.md delete mode 100644 .agent/workflows/update-docs.md diff --git a/.agent/workflows/git-workflow.md b/.agent/workflows/git-workflow.md deleted file mode 100644 index 5d718a7678..0000000000 --- a/.agent/workflows/git-workflow.md +++ /dev/null @@ -1,54 +0,0 @@ ---- -description: Git workflow — NEVER commit directly to main. Always use feature branches. ---- - -# Git Workflow - -## ⚠️ CRITICAL RULE: NEVER commit directly to `main` - -## Steps - -1. **Before starting any work**, create a feature branch from `main`: - - ```bash - git checkout main && git pull origin main - git checkout -b feature/ - ``` - -2. **During development**, commit to the feature branch: - - ```bash - git add -A && git commit -m "(): " - ``` - -3. **Before pushing**, verify the build passes: - - ```bash - npm run build - ``` - -4. **When the feature is complete and verified**, push the branch and STOP: - - ```bash - git push origin feature/ - ``` - -5. **DO NOT** create a PR, merge, or push to `main`. Let the user handle that. - -## Branch naming convention - -- `feature/` — new features -- `fix/` — bugfixes -- `refactor/` — refactoring -- `docker/` — Docker / infrastructure changes -- `style/` — UI / CSS changes - -## Commit types - -- `feat` — new feature -- `fix` — bugfix -- `refactor` — code refactoring -- `style` — UI / CSS changes -- `docker` — Docker / infrastructure -- `docs` — documentation -- `chore` — maintenance diff --git a/.agent/workflows/issue-triage.md b/.agent/workflows/issue-triage.md deleted file mode 100644 index 3bfda2f6e6..0000000000 --- a/.agent/workflows/issue-triage.md +++ /dev/null @@ -1,65 +0,0 @@ ---- -description: How to respond to GitHub issues with insufficient information ---- - -# GitHub Issue Triage — Requesting More Information - -When analyzing a GitHub issue and the provided information is insufficient to diagnose or implement a fix, follow these steps: - -## 1. Identify Missing Information - -Check if the issue contains: - -- [ ] Clear description of the problem or feature -- [ ] Steps to reproduce (for bugs) -- [ ] Error messages / logs -- [ ] Environment details (OS, version, deployment method) -- [ ] Expected vs actual behavior -- [ ] Screenshots (if UI-related) - -## 2. Draft a Response (in English) - -Use this template structure, adapting to what's specifically missing: - -```markdown -Thanks for reporting this issue! 🙏 - -To help us investigate and fix this, could you please provide some more details? - -1. **Environment**: What OS are you running? How did you install OmniRoute (npm global, Docker, from source)? -2. **Steps to Reproduce**: What exact steps lead to this issue? -3. **Error Logs**: Can you share the full server logs? (Check the terminal or `logs/application/app.log`) -4. **Expected vs Actual**: What did you expect to happen, and what actually happened? -5. **Screenshots**: If this is a UI issue, a screenshot would be very helpful. - -This information will help us reproduce and fix the issue more quickly. Thank you! -``` - -## 3. Adapt the Template - -- Remove items that are already provided in the issue -- Add domain-specific questions based on the issue type: - - **OAuth/Auth issues**: Ask for provider name, auth flow used, token errors - - **Multi-account issues**: Ask how many accounts, which providers, dashboard screenshots - - **Startup/crash issues**: Ask for full startup logs, OS version, Node.js version - - **UI rendering issues**: Ask for browser name, screen resolution, screenshots - - **API issues**: Ask for request/response examples, curl commands used - -## 4. Post the Response - -// turbo -Post the response as a comment on the GitHub issue using the GitHub CLI: - -```bash -gh issue comment --repo diegosouzapw/OmniRoute --body "" -``` - -If `gh` CLI is not available, provide the response text to the user to post manually. - -## 5. Add Labels (optional) - -If applicable, add a `needs-info` label: - -```bash -gh issue edit --repo diegosouzapw/OmniRoute --add-label "needs-info" -``` diff --git a/.agent/workflows/update-docs.md b/.agent/workflows/update-docs.md deleted file mode 100644 index 76be0579d9..0000000000 --- a/.agent/workflows/update-docs.md +++ /dev/null @@ -1,41 +0,0 @@ ---- -description: How to automatically summarize recent changes and update README and CHANGELOG ---- - -# Update Documentation and Changelog Workflow - -When asked to run the `/update-docs` workflow or summarize recent changes into the documentation, follow these steps: - -## 1. Gather Recent Work Context - -1. **Review Task History**: Check the current `task.md`, `walkthrough.md`, and any `implementation_plan.md` in the agent's brain directory to understand exactly what features, bug fixes, and architectural changes were recently made. -2. **Identify Key Features**: Group the changes into logical categories: - - **New Features** (e.g. new settings, new endpoints, new UI components) - - **Bug Fixes** (e.g. layout fixes, crash resolutions, cross-platform fixes) - - **Security/Performance** (e.g. auth gating, new optimizations) - -## 2. Update the CHANGELOG.md - -1. If `CHANGELOG.md` does not exist in the root directory, create it. -2. Under the `## [Unreleased]` section (or create a new version header if releasing): - - Add a `### Added` section for new features. - - Add a `### Fixed` section for bug fixes. - - Summarize the recent work into bullet points, referencing GitHub issue numbers if applicable (e.g. `Fix Windows server startup crash (Issue #98)`). - -## 3. Update README.md (and translated versions like README_pt-BR.md) - -1. **Main Features List**: If a notable new feature was added (like a new security setting or API option), add it to the feature list section. -2. **Configuration/Settings**: If any new environment variables or dashboard settings were introduced, document them in the configuration or usage sections so users know how to enable them. -3. If there are translated versions of the README (like Portuguese), ensure those are updated equivalently. - -## 4. Update Technical Docs (docs/ directory) - -1. Use `list_dir` to inspect the `docs/` folder. -2. Determine which technical documents need updates. For example: - - If an API changed, update `docs/API_REFERENCE.md` or similar. - - If security settings changed, update `docs/SECURITY.md` or `docs/CONFIGURATION.md`. -3. Read the relevant files, update their content using `replace_file_content`, and briefly explain how the new feature works under the hood. - -## 5. Verify the Updates - -Ensure all markdown files are properly formatted and no existing sections were accidentally deleted. Present the changes to the user showing which files were updated.