From 5c4ba587fa52a62f9ec1ef9f2d13bec131cc0026 Mon Sep 17 00:00:00 2001 From: Mike Morgan Date: Thu, 15 Jan 2026 14:23:47 -0700 Subject: [PATCH 1/2] chore: adopt BSL 1.1 license for Cortex Linux core --- BSL_LICENSE.md | 126 +++++++++++++++++++++++++++++++++++++++++++++++++ LICENSE | 60 ++--------------------- README.md | 8 +++- 3 files changed, 138 insertions(+), 56 deletions(-) create mode 100644 BSL_LICENSE.md diff --git a/BSL_LICENSE.md b/BSL_LICENSE.md new file mode 100644 index 00000000..c8d77aff --- /dev/null +++ b/BSL_LICENSE.md @@ -0,0 +1,126 @@ +# Business Source License 1.1 + +## Parameters + +**Licensor:** +AI Venture Holdings LLC + +**Licensed Work:** +Cortex Linux +The Licensed Work is © 2026 AI Venture Holdings LLC. + +**Use Limitation:** +Usage is limited to one (1) System. Any use beyond one (1) System requires a +paid commercial license. + +**Additional Use Grant:** +You may use the Licensed Work on one (1) System for: +- Personal, non-commercial use +- Educational and academic research +- Evaluation purposes for up to thirty (30) days, including by for-profit entities +- Contributing to the Licensed Work + +**Change Date:** +January 15, 2032 + +**Change License:** +Apache License, Version 2.0 + +--- + +## Definitions + +**"System"** means a single: +- Physical machine, OR +- Virtual machine instance, OR +- Container host (not individual containers) + +Replacement of hardware (for example, a laptop upgrade or failed disk) does not +constitute an additional System, provided the original System is permanently +decommissioned. + +**"Production Use"** means use in any environment that: +- Serves customers or end users +- Generates revenue directly or indirectly +- Supports internal business operations beyond evaluation or testing + +--- + +## Terms + +The Licensor grants you the right to copy, modify, create derivative works, +redistribute, and make non-production use of the Licensed Work, subject to the +Use Limitation above. + +**Effective on the Change Date**, the Licensor grants you rights under the terms +of the Change License, and the rights granted in this License terminate. + +If your use of the Licensed Work does not comply with the requirements currently +in effect, you must purchase a commercial license from the Licensor or cease +using the Licensed Work. + +All copies of the original or modified Licensed Work must include: +- This License +- The applicable copyright notice + +This License does not grant permission to use the Licensor's trademarks, service +marks, or logos. + +The Licensed Work does not include proprietary enterprise, commercial, or managed +service components distributed separately by the Licensor. + +--- + +## Commercial Use + +**"Commercial Use"** includes any of the following: +1. Use on more than one (1) System +2. Any Production Use +3. Use beyond the thirty (30) day evaluation period +4. Offering a competing product or service +5. Providing managed services based on the Licensed Work +6. Selling, reselling, or sublicensing the Licensed Work + +**Commercial Use does NOT include:** +- Evaluation for up to thirty (30) days on one (1) System +- Contributing to the Licensed Work +- Personal, non-commercial use on one (1) System +- Educational or academic research on one (1) System + +For commercial licensing inquiries: +licensing@cortexlinux.com + +Pricing information: +https://cortexlinux.com/pricing + +--- + +## Termination + +This License automatically terminates upon any breach of its terms. Upon +termination, you must cease all use of the Licensed Work and destroy all copies +in your possession. + +Reinstatement is available if: +1. The breach is cured within thirty (30) days of discovery, or +2. A commercial license is purchased from the Licensor + +--- + +## Disclaimer + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +--- + +## Notice + +This license is based on the Business Source License 1.1, originally published by +MariaDB Corporation. +https://mariadb.com/bsl11/ diff --git a/LICENSE b/LICENSE index f7c642b3..79a6753a 100644 --- a/LICENSE +++ b/LICENSE @@ -1,57 +1,7 @@ -# Business Source License 1.1 +Cortex Linux is licensed under the Business Source License 1.1 (BSL 1.1). -## Parameters +See: +- BSL_LICENSE.md (full license text) +- https://cortexlinux.com/pricing (commercial licensing) -**Licensor:** AI Venture Holdings LLC - -**Licensed Work:** Cortex Linux v0.1.0 and later versions -The Licensed Work is (c) 2025 AI Venture Holdings LLC - -**Additional Use Grant:** You may use the Licensed Work for: -- Personal, non-commercial use -- Internal business operations (not offering as a service) -- Educational and research purposes -- Contributing to the Licensed Work - -**Change Date:** January 15, 2030 (4 years from release) - -**Change License:** Apache License, Version 2.0 - ---- - -## Terms - -The Licensor hereby grants you the right to copy, modify, create derivative works, redistribute, and make non-production use of the Licensed Work. - -**Effective on the Change Date**, the Licensor grants you rights under the terms of the Change License, and the rights granted above terminate. - -If your use of the Licensed Work does not comply with the requirements currently in effect as described in this License, you must purchase a commercial license from the Licensor, its affiliated entities, or authorized resellers, or you must refrain from using the Licensed Work. - -**All copies** of the original and modified Licensed Work must include: -- This License -- The copyright notice -- The Change Date and Change License - ---- - -## Commercial Use - -**"Commercial Use"** means using the Licensed Work to: -1. Offer a competing product or service -2. Provide managed services based on the Licensed Work -3. Sell, resell, or sublicense the Licensed Work - -For Commercial Use licensing, contact: licensing@cortexlinux.com - ---- - -## Disclaimer - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - ---- - -## Notice - -This license is based on the Business Source License 1.1, created by MariaDB Corporation. -For more information, see https://mariadb.com/bsl11/ +Effective January 15, 2032, Cortex Linux will be made available under the Apache License, Version 2.0. diff --git a/README.md b/README.md index 37407191..10297785 100644 --- a/README.md +++ b/README.md @@ -459,7 +459,13 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for detailed guidelines. ## License -Apache 2.0 - See [LICENSE](LICENSE) for details. +Cortex Linux is licensed under the **Business Source License 1.1 (BSL 1.1)**. + +- Free use: **one (1) system** for personal, educational, contribution, or evaluation (up to **30 days**, including for-profit evaluation) +- Commercial use: any additional systems, production use, managed services, or competing offerings require a commercial license +- Change Date: **January 15, 2032** → **Apache 2.0** + +See **BSL_LICENSE.md** for full terms. --- From 4aebfc04228c0241fa1d192360c9bac7a4ff9c4b Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Fri, 16 Jan 2026 06:51:38 +0000 Subject: [PATCH 2/2] [autofix.ci] apply automated fixes --- tests/test_licensing.py | 51 ++++++++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 18 deletions(-) diff --git a/tests/test_licensing.py b/tests/test_licensing.py index def55e4a..68f64c21 100644 --- a/tests/test_licensing.py +++ b/tests/test_licensing.py @@ -1,26 +1,27 @@ """Tests for cortex/licensing.py - License management and feature gating.""" import json -import pytest -from datetime import datetime, timezone, timedelta +from datetime import datetime, timedelta, timezone from pathlib import Path -from unittest.mock import patch, MagicMock +from unittest.mock import MagicMock, patch + +import pytest from cortex.licensing import ( + FEATURE_NAMES, + FEATURE_REQUIREMENTS, + LICENSE_FILE, + FeatureNotAvailableError, FeatureTier, LicenseInfo, - FEATURE_REQUIREMENTS, - FEATURE_NAMES, + _get_hostname, + activate_license, + check_feature, get_license_info, get_license_tier, - check_feature, require_feature, - activate_license, show_license_status, show_upgrade_prompt, - FeatureNotAvailableError, - LICENSE_FILE, - _get_hostname, ) @@ -143,19 +144,20 @@ class TestGetLicenseInfo: def reset_cache(self): """Reset license cache before each test.""" import cortex.licensing as lic + lic._cached_license = None yield lic._cached_license = None def test_returns_license_info(self): """Should return LicenseInfo object.""" - with patch.object(Path, 'exists', return_value=False): + with patch.object(Path, "exists", return_value=False): info = get_license_info() assert isinstance(info, LicenseInfo) def test_default_community_tier(self): """Should default to community tier when no license file.""" - with patch.object(Path, 'exists', return_value=False): + with patch.object(Path, "exists", return_value=False): info = get_license_info() assert info.tier == FeatureTier.COMMUNITY @@ -174,14 +176,14 @@ def test_reads_license_file(self, tmp_path): license_file = tmp_path / "license.key" license_file.write_text(json.dumps(license_data)) - with patch.object(lic, 'LICENSE_FILE', license_file): + with patch.object(lic, "LICENSE_FILE", license_file): info = get_license_info() assert info.tier == "pro" assert info.organization == "Test Org" def test_caches_result(self): """Should cache license info.""" - with patch.object(Path, 'exists', return_value=False): + with patch.object(Path, "exists", return_value=False): info1 = get_license_info() info2 = get_license_info() assert info1 is info2 @@ -194,6 +196,7 @@ class TestCheckFeature: def reset_cache(self): """Reset license cache before each test.""" import cortex.licensing as lic + lic._cached_license = None yield lic._cached_license = None @@ -201,6 +204,7 @@ def reset_cache(self): def test_community_features_allowed(self): """Community tier should access community features.""" import cortex.licensing as lic + lic._cached_license = LicenseInfo(tier=FeatureTier.COMMUNITY) # Unknown features default to community @@ -209,6 +213,7 @@ def test_community_features_allowed(self): def test_pro_feature_blocked_for_community(self): """Community tier should not access pro features.""" import cortex.licensing as lic + lic._cached_license = LicenseInfo(tier=FeatureTier.COMMUNITY) assert check_feature("cloud_llm", silent=True) is False @@ -216,6 +221,7 @@ def test_pro_feature_blocked_for_community(self): def test_pro_feature_allowed_for_pro(self): """Pro tier should access pro features.""" import cortex.licensing as lic + lic._cached_license = LicenseInfo(tier=FeatureTier.PRO) assert check_feature("cloud_llm", silent=True) is True @@ -223,6 +229,7 @@ def test_pro_feature_allowed_for_pro(self): def test_enterprise_feature_allowed_for_enterprise(self): """Enterprise tier should access all features.""" import cortex.licensing as lic + lic._cached_license = LicenseInfo(tier=FeatureTier.ENTERPRISE) assert check_feature("sso", silent=True) is True @@ -231,6 +238,7 @@ def test_enterprise_feature_allowed_for_enterprise(self): def test_shows_upgrade_prompt(self, capsys): """Should show upgrade prompt when feature blocked.""" import cortex.licensing as lic + lic._cached_license = LicenseInfo(tier=FeatureTier.COMMUNITY) check_feature("cloud_llm", silent=False) @@ -245,6 +253,7 @@ class TestRequireFeatureDecorator: def reset_cache(self): """Reset license cache before each test.""" import cortex.licensing as lic + lic._cached_license = None yield lic._cached_license = None @@ -252,6 +261,7 @@ def reset_cache(self): def test_allows_when_feature_available(self): """Should allow function call when feature available.""" import cortex.licensing as lic + lic._cached_license = LicenseInfo(tier=FeatureTier.PRO) @require_feature("cloud_llm") @@ -263,6 +273,7 @@ def test_func(): def test_raises_when_feature_blocked(self): """Should raise FeatureNotAvailableError when feature blocked.""" import cortex.licensing as lic + lic._cached_license = LicenseInfo(tier=FeatureTier.COMMUNITY) @require_feature("cloud_llm") @@ -297,6 +308,7 @@ class TestActivateLicense: def reset_cache(self): """Reset license cache before each test.""" import cortex.licensing as lic + lic._cached_license = None yield lic._cached_license = None @@ -314,8 +326,8 @@ def test_successful_activation(self, tmp_path): "organization": "Test Org", } - with patch.object(lic, 'LICENSE_FILE', license_file): - with patch('httpx.post', return_value=mock_response): + with patch.object(lic, "LICENSE_FILE", license_file): + with patch("httpx.post", return_value=mock_response): result = activate_license("test-key-123") assert result is True @@ -329,7 +341,7 @@ def test_failed_activation(self): "error": "Invalid key", } - with patch('httpx.post', return_value=mock_response): + with patch("httpx.post", return_value=mock_response): result = activate_license("invalid-key") assert result is False @@ -338,7 +350,7 @@ def test_network_error(self): """Should handle network errors gracefully.""" import httpx - with patch('httpx.post', side_effect=httpx.HTTPError("Network error")): + with patch("httpx.post", side_effect=httpx.HTTPError("Network error")): result = activate_license("test-key") assert result is False @@ -351,6 +363,7 @@ class TestShowLicenseStatus: def reset_cache(self): """Reset license cache before each test.""" import cortex.licensing as lic + lic._cached_license = None yield lic._cached_license = None @@ -358,6 +371,7 @@ def reset_cache(self): def test_shows_community_status(self, capsys): """Should show community tier status.""" import cortex.licensing as lic + lic._cached_license = LicenseInfo(tier=FeatureTier.COMMUNITY) show_license_status() @@ -369,6 +383,7 @@ def test_shows_community_status(self, capsys): def test_shows_pro_status(self, capsys): """Should show pro tier status.""" import cortex.licensing as lic + lic._cached_license = LicenseInfo( tier=FeatureTier.PRO, organization="Test Corp",