From 5836fb7d80bd8a438b09bf71f5a475c55f944b48 Mon Sep 17 00:00:00 2001 From: Hibryda Date: Sun, 22 Mar 2026 04:39:07 +0100 Subject: [PATCH] =?UTF-8?q?feat:=20community=20export=20workflow=20?= =?UTF-8?q?=E2=80=94=20strip=20script,=20leak-check=20hardening,=20CLA=20d?= =?UTF-8?q?ocs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - scripts/strip-commercial.sh: removes agor-pro/, commercial files, SPDX headers - leak-check.yml: added LICENSE-COMMERCIAL, SPDX header, and feature flag checks - CONTRIBUTING.md: external contributor guide, commercial content table, sync docs --- .github/workflows/leak-check.yml | 41 +++++++++- CONTRIBUTING.md | 56 ++++++++++++-- scripts/strip-commercial.sh | 127 +++++++++++++++++++++++++++++++ 3 files changed, 218 insertions(+), 6 deletions(-) create mode 100755 scripts/strip-commercial.sh diff --git a/.github/workflows/leak-check.yml b/.github/workflows/leak-check.yml index f8f13ff..9ae636a 100644 --- a/.github/workflows/leak-check.yml +++ b/.github/workflows/leak-check.yml @@ -50,11 +50,32 @@ jobs: fi echo "No commercial directories with content found." + - name: Check for commercial license file + run: | + if [ -f "LICENSE-COMMERCIAL" ]; then + echo "::error::LICENSE-COMMERCIAL found in community repo" + exit 1 + fi + echo "No commercial license file found." + + - name: Check for LicenseRef-Commercial SPDX headers + run: | + files=$(grep -rl "LicenseRef-Commercial" \ + --include="*.ts" --include="*.svelte" --include="*.rs" \ + --include="*.toml" --include="*.css" \ + src/ src-tauri/src/ agor-core/ 2>/dev/null || true) + if [ -n "$files" ]; then + echo "::error::Files with LicenseRef-Commercial SPDX headers found:" + echo "$files" + exit 1 + fi + echo "No LicenseRef-Commercial headers found." + - name: Grep for commercial references in source run: | failed=0 - for pattern in "LicenseRef-Commercial" "agor-pro" "agor_pro"; do + for pattern in "agor-pro" "agor_pro"; do if grep -r --include="*.ts" --include="*.svelte" --include="*.rs" --include="*.toml" \ "$pattern" src/ src-tauri/src/ 2>/dev/null; then echo "::error::Found '$pattern' reference in source code" @@ -67,3 +88,21 @@ jobs: exit 1 fi echo "No commercial references found in source." + + - name: Check for commercial feature flags in package.json + run: | + failed=0 + if grep -q '"commercial\|:pro"' package.json 2>/dev/null; then + echo "::error::Commercial feature flags found in package.json" + grep '"commercial\|:pro"' package.json + failed=1 + fi + if grep -q 'agor-pro' package.json 2>/dev/null; then + echo "::error::agor-pro dependency found in package.json" + grep 'agor-pro' package.json + failed=1 + fi + if [ "$failed" -eq 1 ]; then + exit 1 + fi + echo "No commercial feature flags in package.json." diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9e0725a..f723fa2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -18,6 +18,20 @@ periodically. All community contributions go to **DexterFromLab/agent-orchestrator**. Do not open PRs against this repo for community features. +### How to Contribute + +1. Fork the community repo at `DexterFromLab/agent-orchestrator` +2. Create a feature branch from `main` +3. Make your changes and commit using conventional commits +4. Open a pull request against `DexterFromLab/agent-orchestrator` `main` +5. Sign the CLA when prompted by the bot on your first PR +6. Address review feedback +7. Once approved, a maintainer will merge your PR + +Do **not** fork or open PRs against `agents-orchestrator/agents-orchestrator` for +community contributions. That repository contains commercial code and access is +restricted. + ### Contributor License Agreement (CLA) Every community contributor must sign the CLA before their first PR is merged. @@ -25,13 +39,30 @@ CLA signing is automated via [CLA-assistant.io](https://cla-assistant.io/) on the community repository. The bot will prompt you on your first PR. The CLA grants the project maintainers a perpetual, irrevocable license to use -your contribution in both the community and commercial editions. +your contribution in both the community and commercial editions. You retain full +ownership of your code. See [CLA.md](CLA.md) for the full agreement text. ## Commercial Development Commercial features are developed only in this repository. Access is restricted to authorized team members. +### What Content Is Commercial-Only + +The following paths and markers identify commercial-only content: + +| Marker | Description | +|--------|-------------| +| `agor-pro/` | Commercial feature modules | +| `src/lib/commercial/` | Commercial frontend components | +| `tests/commercial/` | Commercial test suites | +| `LICENSE-COMMERCIAL` | Commercial license file | +| `LicenseRef-Commercial` SPDX header | Any file with this header | +| `test:all:commercial` script | Commercial test runner | + +This content is automatically stripped during community sync and never appears in +the community repository. + ### SPDX License Headers All commercial source files must include the following header as the first line: @@ -58,12 +89,27 @@ Community-shared code uses the MIT identifier: // SPDX-License-Identifier: MIT ``` -### Commercial Directories +## Community Sync Workflow -Files under these paths are always commercial-only: +The community repo is kept in sync with this repo via an automated workflow: -- `agor-pro/` -- `src/lib/commercial/` +1. **Trigger**: Manual dispatch or on release tag publication +2. **Strip**: `scripts/strip-commercial.sh` removes all commercial content +3. **Verify**: Automated checks ensure no commercial references remain +4. **Push**: A sync branch is pushed to `DexterFromLab/agent-orchestrator` +5. **Merge**: A maintainer reviews and merges the sync PR + +To preview what would be stripped locally: + +```bash +# Dry run — shows what files would be removed (modifies working tree) +bash scripts/strip-commercial.sh +# Reset after preview +git checkout . +``` + +The leak-check CI workflow runs on every push and PR to `main`, verifying that no +commercial content has been accidentally committed to community-bound code. ## Branch Model diff --git a/scripts/strip-commercial.sh b/scripts/strip-commercial.sh new file mode 100755 index 0000000..cecfdfc --- /dev/null +++ b/scripts/strip-commercial.sh @@ -0,0 +1,127 @@ +#!/usr/bin/env bash +# strip-commercial.sh — Remove all commercial content from the repository. +# Safe to run locally to preview what would be stripped. +# Used by .github/workflows/community-sync.yml for automated sync. + +set -euo pipefail + +REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" +cd "$REPO_ROOT" + +removed=() +echo "=== Stripping commercial content from: $REPO_ROOT ===" + +# 1. Remove commercial directories +for dir in agor-pro; do + if [ -d "$dir" ]; then + rm -rf "$dir" + removed+=("$dir/ (directory)") + echo "Removed directory: $dir/" + fi +done + +# 2. Remove commercial files in src/lib/commercial/ (keep .gitkeep) +if [ -d "src/lib/commercial" ]; then + while IFS= read -r -d '' file; do + rm -f "$file" + removed+=("$file") + echo "Removed file: $file" + done < <(find src/lib/commercial/ -type f ! -name '.gitkeep' -print0 2>/dev/null) +fi + +# 3. Remove commercial files in tests/commercial/ (keep .gitkeep) +if [ -d "tests/commercial" ]; then + while IFS= read -r -d '' file; do + rm -f "$file" + removed+=("$file") + echo "Removed file: $file" + done < <(find tests/commercial/ -type f ! -name '.gitkeep' -print0 2>/dev/null) +fi + +# 4. Remove LICENSE-COMMERCIAL +if [ -f "LICENSE-COMMERCIAL" ]; then + rm -f "LICENSE-COMMERCIAL" + removed+=("LICENSE-COMMERCIAL") + echo "Removed file: LICENSE-COMMERCIAL" +fi + +# 5. Remove files with LicenseRef-Commercial SPDX headers (outside node_modules) +while IFS= read -r -d '' file; do + if head -5 "$file" | grep -q "LicenseRef-Commercial"; then + rm -f "$file" + removed+=("$file") + echo "Removed SPDX-commercial file: $file" + fi +done < <(find . -type f \( -name '*.ts' -o -name '*.svelte' -o -name '*.rs' -o -name '*.css' \) \ + ! -path '*/node_modules/*' ! -path '*/target/*' -print0 2>/dev/null) + +# 6. Strip commercial references from package.json (pro scripts/deps) +if [ -f "package.json" ]; then + if command -v node >/dev/null 2>&1; then + node -e " + const fs = require('fs'); + const pkg = JSON.parse(fs.readFileSync('package.json', 'utf8')); + let changed = false; + if (pkg.scripts) { + for (const key of Object.keys(pkg.scripts)) { + if (key.includes('commercial') || key.includes(':pro')) { + delete pkg.scripts[key]; + changed = true; + } + } + } + if (pkg.dependencies) { + for (const key of Object.keys(pkg.dependencies)) { + if (key.includes('agor-pro')) { + delete pkg.dependencies[key]; + changed = true; + } + } + } + if (pkg.devDependencies) { + for (const key of Object.keys(pkg.devDependencies)) { + if (key.includes('agor-pro')) { + delete pkg.devDependencies[key]; + changed = true; + } + } + } + if (changed) { + fs.writeFileSync('package.json', JSON.stringify(pkg, null, 2) + '\n'); + console.log('Cleaned commercial references from package.json'); + } + " + else + echo "Warning: node not available, skipping package.json cleanup" + fi +fi + +# Summary +echo "" +echo "=== Strip complete ===" +echo "Files removed: ${#removed[@]}" +for f in "${removed[@]}"; do + echo " - $f" +done + +# Final verification +echo "" +echo "=== Verification ===" +remaining=$(grep -rl "LicenseRef-Commercial" --include="*.ts" --include="*.svelte" \ + --include="*.rs" --include="*.toml" --include="*.css" \ + . 2>/dev/null | grep -v node_modules | grep -v target || true) + +if [ -n "$remaining" ]; then + echo "WARNING: LicenseRef-Commercial references still found in:" + echo "$remaining" + exit 1 +else + echo "No LicenseRef-Commercial references remain." +fi + +if [ -d "agor-pro" ]; then + echo "WARNING: agor-pro/ directory still exists" + exit 1 +fi + +echo "All commercial content stripped successfully."