feat: add agor-pro commercial plugin crate and dual-repo infrastructure

agor-pro Tauri 2.x plugin (feature-gated via --features pro),
commercial Tauri config overlay, asymmetric test setup,
CI workflows (leak-check, commercial-build, PAT health),
pre-push hook, Makefile, CONTRIBUTING/MAINTENANCE/LICENSE-COMMERCIAL.
This commit is contained in:
Hibryda 2026-03-17 01:12:25 +01:00
parent a63e6711ac
commit 5fadd1c022
14 changed files with 682 additions and 0 deletions

53
.githooks/pre-push Executable file
View file

@ -0,0 +1,53 @@
#!/usr/bin/env bash
# Pre-push hook: prevent commercial code from leaking to the community remote.
#
# Git calls pre-push with the remote name and URL as arguments,
# and feeds (local_ref local_sha remote_ref remote_sha) lines on stdin.
remote="$1"
url="$2"
# Only guard pushes to the community origin (DexterFromLab)
if ! echo "$url" | grep -qi "DexterFromLab"; then
exit 0
fi
echo "[pre-push] Scanning commits for commercial code before push to community remote..."
COMMERCIAL_PATTERNS="agor-pro/|src/lib/commercial/"
while read -r local_ref local_sha remote_ref remote_sha; do
# Skip delete pushes
if [ "$local_sha" = "0000000000000000000000000000000000000000" ]; then
continue
fi
# For new branches, diff against remote HEAD; for updates, diff against remote_sha
if [ "$remote_sha" = "0000000000000000000000000000000000000000" ]; then
range="$local_sha"
else
range="$remote_sha..$local_sha"
fi
# Check file paths in the commits being pushed
leaked_files=$(git diff --name-only "$range" 2>/dev/null | grep -E "$COMMERCIAL_PATTERNS" || true)
if [ -n "$leaked_files" ]; then
echo ""
echo "=========================================="
echo " PUSH BLOCKED: Commercial code detected!"
echo "=========================================="
echo ""
echo "The following commercial files were found in commits being pushed:"
echo "$leaked_files" | sed 's/^/ - /'
echo ""
echo "You are pushing to the community remote ($url)."
echo "Commercial code must NOT be pushed to this remote."
echo ""
echo "To fix: remove commercial files from these commits or push to the commercial remote instead."
echo "=========================================="
exit 1
fi
done
exit 0

71
.github/workflows/commercial-build.yml vendored Normal file
View file

@ -0,0 +1,71 @@
name: Commercial Build
on:
push:
branches:
- 'commercial/**'
workflow_dispatch:
permissions:
contents: read
env:
CARGO_TERM_COLOR: always
jobs:
commercial-build:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y \
libwebkit2gtk-4.1-dev \
libgtk-3-dev \
libayatana-appindicator3-dev \
librsvg2-dev \
libssl-dev \
build-essential \
pkg-config
- name: Setup Rust
uses: dtolnay/rust-toolchain@stable
- name: Cache Cargo
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-pro-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-pro-
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- name: Install npm dependencies
run: npm ci
- name: Cargo check (pro features)
run: cargo check --features pro
- name: Cargo test (pro features)
run: cargo test --features pro
- name: Vitest (frontend)
run: npm run test
- name: Commercial tests
run: |
if [ -d "tests/commercial/" ] && ls tests/commercial/*.test.* 2>/dev/null; then
npx vitest run tests/commercial/
else
echo "No commercial tests found, skipping."
fi

69
.github/workflows/leak-check.yml vendored Normal file
View file

@ -0,0 +1,69 @@
name: Leak Check
on:
push:
branches: [main]
pull_request:
branches: [main]
permissions:
contents: read
jobs:
leak-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Check for commercial directories
run: |
failed=0
# Check agor-pro/ exists
if [ -d "agor-pro/" ]; then
echo "::error::Commercial directory 'agor-pro/' found in community repo"
failed=1
fi
# Check src/lib/commercial/ has actual content (beyond .gitkeep)
if [ -d "src/lib/commercial/" ]; then
content_count=$(find src/lib/commercial/ -type f ! -name '.gitkeep' | wc -l)
if [ "$content_count" -gt 0 ]; then
echo "::error::Commercial code found in 'src/lib/commercial/' ($content_count files beyond .gitkeep)"
find src/lib/commercial/ -type f ! -name '.gitkeep'
failed=1
fi
fi
# Check tests/commercial/ has actual content (beyond .gitkeep)
if [ -d "tests/commercial/" ]; then
content_count=$(find tests/commercial/ -type f ! -name '.gitkeep' | wc -l)
if [ "$content_count" -gt 0 ]; then
echo "::error::Commercial test code found in 'tests/commercial/' ($content_count files beyond .gitkeep)"
find tests/commercial/ -type f ! -name '.gitkeep'
failed=1
fi
fi
if [ "$failed" -eq 1 ]; then
exit 1
fi
echo "No commercial directories with content found."
- name: Grep for commercial references in source
run: |
failed=0
for pattern in "LicenseRef-Commercial" "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"
failed=1
fi
done
if [ "$failed" -eq 1 ]; then
echo "::error::Commercial references detected in community source. See above for details."
exit 1
fi
echo "No commercial references found in source."

75
.github/workflows/pat-health.yml vendored Normal file
View file

@ -0,0 +1,75 @@
name: PAT Health Check
on:
schedule:
- cron: '0 9 * * 1' # Every Monday at 9am UTC
workflow_dispatch:
permissions:
contents: read
issues: write
jobs:
check-pat:
runs-on: ubuntu-latest
steps:
- name: Check COMMUNITY_PAT validity
env:
COMMUNITY_PAT: ${{ secrets.COMMUNITY_PAT }}
run: |
if [ -z "$COMMUNITY_PAT" ]; then
echo "::error::COMMUNITY_PAT secret is not set"
echo "pat_valid=false" >> "$GITHUB_ENV"
exit 0
fi
status=$(curl -s -o /dev/null -w "%{http_code}" \
-H "Authorization: token $COMMUNITY_PAT" \
-H "Accept: application/vnd.github+json" \
https://api.github.com/user)
if [ "$status" -eq 200 ]; then
echo "COMMUNITY_PAT is valid (HTTP $status)"
echo "pat_valid=true" >> "$GITHUB_ENV"
else
echo "::error::COMMUNITY_PAT returned HTTP $status"
echo "pat_valid=false" >> "$GITHUB_ENV"
fi
- name: Create issue if PAT is invalid
if: env.pat_valid == 'false'
uses: actions/github-script@v7
with:
script: |
const title = 'COMMUNITY_PAT is invalid or missing';
const body = [
'## PAT Health Check Failed',
'',
'The weekly PAT health check detected that `COMMUNITY_PAT` is either missing or returning an error from the GitHub API.',
'',
'**Action required:** Rotate or re-create the PAT and update the repository secret.',
'',
`Run: ${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`,
].join('\n');
// Avoid duplicate issues
const existing = await github.rest.issues.listForRepo({
owner: context.repo.owner,
repo: context.repo.repo,
state: 'open',
labels: 'pat-health',
per_page: 1,
});
if (existing.data.length > 0) {
console.log('Open PAT health issue already exists, skipping creation.');
return;
}
await github.rest.issues.create({
owner: context.repo.owner,
repo: context.repo.repo,
title,
body,
labels: ['pat-health'],
});

122
CONTRIBUTING.md Normal file
View file

@ -0,0 +1,122 @@
# Contributing to Agent Orchestrator
## Dual-Repository Model
This project uses a dual-repo structure:
| Repository | License | Purpose |
|------------|---------|---------|
| `DexterFromLab/agent-orchestrator` | MIT | Community edition (open source) |
| `agents-orchestrator/agents-orchestrator` | MIT + Commercial | Commercial edition (this repo) |
Community contributions target the community repo. Commercial development happens
exclusively in this repo. The two share a common `main` branch that is synced
periodically.
## Community Contributions
All community contributions go to **DexterFromLab/agent-orchestrator**. Do not open
PRs against this repo for community features.
### Contributor License Agreement (CLA)
Every community contributor must sign the CLA before their first PR is merged.
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.
## Commercial Development
Commercial features are developed only in this repository. Access is restricted
to authorized team members.
### SPDX License Headers
All commercial source files must include the following header as the first line:
```
// SPDX-License-Identifier: LicenseRef-Commercial
```
For CSS/HTML files:
```
/* SPDX-License-Identifier: LicenseRef-Commercial */
```
For Rust files:
```rust
// SPDX-License-Identifier: LicenseRef-Commercial
```
Community-shared code uses the MIT identifier:
```
// SPDX-License-Identifier: MIT
```
### Commercial Directories
Files under these paths are always commercial-only:
- `agor-pro/`
- `src/lib/commercial/`
## Branch Model
| Branch | Purpose |
|--------|---------|
| `main` | Shared with community edition. Never commit commercial code here. |
| `commercial/*` | Commercial-only features. Merged into the commercial release branch. |
| `feature/*`, `fix/*` | Standard development branches. |
### Sync Flow
The community repo's `main` is merged into this repo's `main` periodically:
```
community/main --> origin/main --> commercial branches
```
Use `make sync` to pull community changes. Never force-push `main`.
## Commit Conventions
Use [Conventional Commits](https://www.conventionalcommits.org/):
```
type(scope): description
feat(dashboard): add team analytics panel
fix(sidecar): handle timeout on agent restart
docs(api): update webhook payload reference
chore(deps): bump tauri to 2.3.1
```
Types: `feat`, `fix`, `docs`, `style`, `refactor`, `perf`, `test`, `chore`, `ci`, `build`.
Breaking changes use `type!:` prefix or include `BREAKING CHANGE:` in the footer.
## Testing
Both editions must pass their respective test suites before merge:
```bash
# Community tests (must always pass on main)
npm run test:all
# Commercial tests (includes commercial-specific tests)
npm run test:all:commercial
```
Do not merge a PR if either suite is red. If a community sync introduces
failures in commercial tests, fix them before merging.
## Code Review
- All PRs require at least one approval.
- Commercial PRs must be reviewed by a team member with commercial repo access.
- Verify no commercial code leaks into community-bound branches before approving.

50
LICENSE-COMMERCIAL Normal file
View file

@ -0,0 +1,50 @@
Commercial License
Copyright (c) 2025-2026 Agents Orchestrator. All rights reserved.
TERMS AND CONDITIONS
1. GRANT OF LICENSE
This software and associated documentation files (the "Software") located
under the directories `agor-pro/` and `src/lib/commercial/`, and any other
files bearing the SPDX header `LicenseRef-Commercial`, are licensed to
authorized users under the terms of a separate commercial agreement.
2. RESTRICTIONS
Unless you have a valid commercial license agreement, you may not:
a. Copy, modify, merge, publish, distribute, sublicense, or sell copies
of the Software.
b. Reverse engineer, decompile, or disassemble the Software.
c. Remove or alter any proprietary notices, labels, or marks on the
Software.
d. Use the Software to provide a competing product or service.
3. OWNERSHIP
The Software is the intellectual property of Agents Orchestrator and is
protected by copyright law. This license does not transfer ownership.
4. NO WARRANTY
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.
5. TERMINATION
This license terminates automatically if you breach any of its terms. Upon
termination, you must destroy all copies of the Software in your possession.
6. GOVERNING LAW
This license shall be governed by and construed in accordance with the laws
of the jurisdiction in which Agents Orchestrator is incorporated.
For licensing inquiries, contact the Agents Orchestrator organization.

128
MAINTENANCE.md Normal file
View file

@ -0,0 +1,128 @@
# Maintenance Guide
Operational procedures for the commercial edition of Agent Orchestrator.
## PAT Rotation
The `COMMUNITY_PAT` personal access token is used by CI to sync with the
community repository. Rotate it every 90 days.
### Rotation Procedure
1. Generate a new fine-grained PAT on GitHub with scope:
- Repository: `DexterFromLab/agent-orchestrator`
- Permissions: `Contents: Read-only`
2. Update the secret in this repo's GitHub Settings > Secrets > Actions:
- Name: `COMMUNITY_PAT`
- Value: the new token
3. Run the sync workflow manually to verify: Actions > Community Sync > Run workflow.
4. Record the rotation date. Next rotation due in 90 days.
### Token Audit
Check token expiry dates monthly. Set a calendar reminder.
## Community Sync
### Automated
```bash
make sync
```
This fetches `community/main`, merges it into `origin/main`, and runs the test
suite. Conflicts must be resolved manually.
### Manual
```bash
git remote add community https://github.com/DexterFromLab/agent-orchestrator.git 2>/dev/null
git fetch community main
git checkout main
git merge community/main --no-edit
npm run test:all
```
If tests fail after sync, fix before pushing.
## Pre-Release Checklist: Community Edition
Before publishing a community release from `main`:
- [ ] `git diff main..commercial/main -- agor-pro/ src/lib/commercial/` shows no commercial code on `main`
- [ ] Run `grep -r "LicenseRef-Commercial" --include="*.ts" --include="*.rs" --include="*.svelte" src/ src-tauri/` on `main` returns nothing
- [ ] Run `npm run test:all` passes
- [ ] Run `cargo test --workspace` passes
- [ ] CHANGELOG.md updated with release notes
- [ ] Tag follows semver: `v{major}.{minor}.{patch}`
- [ ] No secrets, API keys, or internal URLs in the diff since last release
## Pre-Release Checklist: Commercial Edition
Before publishing a commercial release:
- [ ] All commercial branches merged into the release branch
- [ ] `npm run test:all:commercial` passes
- [ ] `cargo test --workspace` passes
- [ ] License headers present on all commercial files (`grep -rL "SPDX-License-Identifier" agor-pro/ src/lib/commercial/` returns nothing)
- [ ] No hardcoded credentials or internal endpoints
- [ ] Database migrations tested against fresh install and upgrade from previous version
- [ ] Release notes written for commercial changelog
## Database Migration Notes
The commercial edition uses a separate data directory to avoid conflicts:
| Edition | Data Directory |
|---------|---------------|
| Community | `~/.local/share/bterminal/` |
| Commercial | `~/.local/share/agor/` |
### Migration Rules
- Schema migrations run automatically on startup (WAL mode SQLite).
- Never modify existing migration SQL. Add new migrations with incrementing version numbers.
- Test migrations against: (a) fresh install, (b) upgrade from N-1, (c) upgrade from N-2.
- Back up `~/.local/share/agor/` before testing destructive migrations locally.
### Edition Switching in Development
When switching between community and commercial editions locally:
```bash
make clean
```
This clears build artifacts and resets configuration to avoid cross-contamination.
The two editions use separate data directories, so user data is not affected.
Rebuild after switching:
```bash
npm install && npm run tauri dev
```
## Quarterly Maintenance
Perform these tasks every quarter:
### Security
- [ ] Rotate `COMMUNITY_PAT` (if due within the quarter)
- [ ] Run `npm audit` and `cargo audit` on both editions
- [ ] Review GitHub Dependabot alerts
- [ ] Verify no secrets in git history: `git log --all --diff-filter=A -- '*.env' '*.pem' '*.key'`
### Dependencies
- [ ] Update Rust toolchain (`rustup update`)
- [ ] Update Node.js to latest LTS if applicable
- [ ] Review and update pinned dependency versions
- [ ] Run full test suite after updates
### Repository Health
- [ ] Prune stale branches (`git branch --merged main | grep -v main`)
- [ ] Verify CI workflows are green on main
- [ ] Review and close stale issues/PRs
- [ ] Sync community changes if not done recently
- [ ] Verify backup procedures for commercial data

36
Makefile Normal file
View file

@ -0,0 +1,36 @@
.PHONY: setup build build-pro test test-pro sync clean
# --- Community ---
setup:
git config core.hooksPath .githooks
npm install
@echo "Git hooks configured and dependencies installed."
build:
cargo build
npm run build
test:
npm run test:all
# --- Commercial ---
build-pro:
cargo build --features pro
npm run build
@echo "For Tauri release: cargo tauri build -- --features pro --config src-tauri/tauri.conf.commercial.json"
test-pro:
cargo test --features pro
AGOR_EDITION=pro npx vitest run
# --- Maintenance ---
sync:
git fetch origin
git merge origin/main
clean:
cargo clean
rm -rf node_modules/.vite

13
agor-pro/Cargo.toml Normal file
View file

@ -0,0 +1,13 @@
[package]
name = "agor-pro"
version = "0.1.0"
edition = "2021"
description = "Commercial plugin for Agents Orchestrator"
license = "LicenseRef-Commercial"
[dependencies]
agor-core = { path = "../agor-core" }
tauri = { version = "2.10.3", features = [] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
log = "0.4"

35
agor-pro/src/lib.rs Normal file
View file

@ -0,0 +1,35 @@
// SPDX-License-Identifier: LicenseRef-Commercial
//
// agor-pro — Commercial plugin for Agents Orchestrator.
// This crate is NOT open-source. It is distributed only via the
// agents-orchestrator/agents-orchestrator private repository.
use tauri::{
plugin::{Builder, TauriPlugin},
Runtime,
};
/// Initialize the agor-pro Tauri plugin.
/// Registers all commercial commands and managed state.
pub fn init<R: Runtime>() -> TauriPlugin<R> {
Builder::new("agor-pro")
.invoke_handler(tauri::generate_handler![
pro_status,
])
.build()
}
#[tauri::command]
fn pro_status() -> String {
"active".to_string()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_pro_status() {
assert_eq!(pro_status(), "active");
}
}

View file

@ -0,0 +1,16 @@
{
"$schema": "https://schema.tauri.app/config/2",
"productName": "agents-orchestrator-pro",
"identifier": "com.agentsorchestrator.pro",
"plugins": {
"updater": {
"endpoints": [
"https://github.com/agents-orchestrator/agents-orchestrator/releases/latest/download/latest.json"
]
}
},
"bundle": {
"shortDescription": "Agents Orchestrator Pro — commercial multi-agent dashboard",
"longDescription": "Agents Orchestrator Pro is the commercial edition with advanced features including enterprise agent management, priority support, and extended integrations."
}
}

View file

View file

View file

@ -0,0 +1,14 @@
// SPDX-License-Identifier: LicenseRef-Commercial
// Commercial-only tests — excluded from community test runs.
import { describe, it, expect } from 'vitest';
describe('Pro Edition', () => {
it('commercial test suite is reachable', () => {
expect(true).toBe(true);
});
it('AGOR_EDITION env var is set to pro when running commercial tests', () => {
expect(process.env.AGOR_EDITION).toBe('pro');
});
});