Skip to content

Commit ed84554

Browse files
Merge pull request #288 from SheetMetalConnect/claude/add-licensing-feature-flags-e5g9i
Add open source licensing and feature flags
2 parents 422a4da + 6399524 commit ed84554

File tree

6 files changed

+79
-6
lines changed

6 files changed

+79
-6
lines changed

README.md

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,9 @@ docker run -p 8080:80 \
160160

161161
## License
162162

163-
**Business Source License 1.1 (BSL 1.1)**
163+
**Business Source License 1.1 (BSL 1.1)** - Source Available
164+
165+
This is an **open source repository** under the BSL 1.1 license, which allows source code access while preventing competitive SaaS offerings.
164166

165167
**TL;DR:** Use it, modify it, self-host it - all free. Just don't host it and charge others for access.
166168

@@ -172,6 +174,24 @@ docker run -p 8080:80 \
172174

173175
See [LICENSE](LICENSE) for full terms.
174176

177+
### External Components (Feature Flags)
178+
179+
Some features require external services that must be deployed separately:
180+
181+
| Feature | Service | Description | Feature Flag |
182+
|---------|---------|-------------|--------------|
183+
| Advanced CAD (PMI/MBD) | `services/eryxon3d` | Server-side CAD processing with PMI extraction | `advancedCAD` |
184+
185+
These external components are:
186+
- **Disabled by default** - must be explicitly enabled via feature flags in Organization Settings
187+
- **Self-hosted** - you deploy and control the service
188+
- **Optional** - core MES functionality works without them
189+
190+
To enable an external feature:
191+
1. Deploy the required service (see `services/` directory)
192+
2. Configure environment variables (see `.env.example`)
193+
3. Enable the feature flag in Admin → Settings → Organization Settings
194+
175195
---
176196

177197
## Contributing & Support

src/components/admin/FeatureFlagsSettings.tsx

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
AlertCircle,
1515
CalendarClock,
1616
UserCheck,
17+
Box,
1718
} from 'lucide-react';
1819
import {
1920
useFeatureFlags,
@@ -33,6 +34,7 @@ const ICON_MAP: Record<string, React.ComponentType<{ className?: string }>> = {
3334
AlertCircle,
3435
CalendarClock,
3536
UserCheck,
37+
Box,
3638
};
3739

3840
// Category labels and order
@@ -42,6 +44,11 @@ const CATEGORIES = [
4244
{ key: 'admin', labelKey: 'featureFlags.categories.admin' },
4345
] as const;
4446

47+
// External services category (shown separately with warning)
48+
49+
// Feature flags that require external services
50+
const EXTERNAL_SERVICE_FLAGS = ['advancedCAD'] as const;
51+
4552
interface FeatureFlagItemProps {
4653
meta: FeatureFlagMeta;
4754
enabled: boolean;
@@ -52,14 +59,16 @@ interface FeatureFlagItemProps {
5259
function FeatureFlagItem({ meta, enabled, onToggle, disabled }: FeatureFlagItemProps) {
5360
const { t } = useTranslation();
5461
const Icon = ICON_MAP[meta.icon] || Activity;
62+
const isExternalService = EXTERNAL_SERVICE_FLAGS.includes(meta.key as typeof EXTERNAL_SERVICE_FLAGS[number]);
5563

5664
return (
5765
<div
5866
className={cn(
5967
'group flex items-center justify-between rounded-lg border p-4 transition-all duration-200',
6068
enabled
6169
? 'border-primary/30 bg-primary/5 hover:border-primary/50'
62-
: 'border-border/50 bg-muted/30 hover:border-border'
70+
: 'border-border/50 bg-muted/30 hover:border-border',
71+
isExternalService && 'border-dashed'
6372
)}
6473
>
6574
<div className="flex items-center gap-4">
@@ -81,6 +90,11 @@ function FeatureFlagItem({ meta, enabled, onToggle, disabled }: FeatureFlagItemP
8190
)}>
8291
{t(meta.labelKey)}
8392
</span>
93+
{isExternalService && (
94+
<Badge variant="outline" className="text-[10px] px-1.5 py-0 border-amber-500/50 text-amber-600">
95+
External
96+
</Badge>
97+
)}
8498
{enabled && (
8599
<Badge variant="secondary" className="text-[10px] px-1.5 py-0 bg-primary/20 text-primary border-0">
86100
{t('featureFlags.enabled')}
@@ -90,6 +104,11 @@ function FeatureFlagItem({ meta, enabled, onToggle, disabled }: FeatureFlagItemP
90104
<p className="text-sm text-muted-foreground">
91105
{t(meta.descriptionKey)}
92106
</p>
107+
{isExternalService && (
108+
<p className="text-xs text-amber-600/80 mt-1">
109+
{t('featureFlags.externalServiceNote')}
110+
</p>
111+
)}
93112
</div>
94113
</div>
95114
<Switch

src/hooks/useFeatureFlags.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ import { useTranslation } from 'react-i18next';
77
/**
88
* Feature flag definitions for Eryxon MES
99
* Each flag controls visibility of a major module or feature group
10+
*
11+
* Note: Some features require external services (marked below).
12+
* These are optional components that must be separately deployed.
13+
* See docs/SELF_HOSTING_GUIDE.md for deployment instructions.
1014
*/
1115
export interface FeatureFlags {
1216
// Core modules (always enabled - listed for reference)
@@ -24,10 +28,14 @@ export interface FeatureFlags {
2428
issues: boolean; // Issues tracking
2529
capacity: boolean; // Capacity planning
2630
assignments: boolean; // Assignments management
31+
32+
// External service features (require separate deployment)
33+
advancedCAD: boolean; // PMI/MBD extraction - requires eryxon3d service (services/eryxon3d)
2734
}
2835

2936
/**
30-
* Default feature flags - all features enabled by default
37+
* Default feature flags - core features enabled, external services disabled by default
38+
* External service features (advancedCAD) require separate deployment and are opt-in
3139
*/
3240
export const DEFAULT_FEATURE_FLAGS: FeatureFlags = {
3341
analytics: true,
@@ -38,6 +46,8 @@ export const DEFAULT_FEATURE_FLAGS: FeatureFlags = {
3846
issues: true,
3947
capacity: true,
4048
assignments: true,
49+
// External service features - disabled by default (require separate deployment)
50+
advancedCAD: false,
4151
};
4252

4353
/**
@@ -108,6 +118,14 @@ export const FEATURE_FLAG_METADATA: FeatureFlagMeta[] = [
108118
icon: 'UserCheck',
109119
category: 'operations',
110120
},
121+
// External service features
122+
{
123+
key: 'advancedCAD',
124+
labelKey: 'featureFlags.advancedCAD.label',
125+
descriptionKey: 'featureFlags.advancedCAD.description',
126+
icon: 'Box',
127+
category: 'admin',
128+
},
111129
];
112130

113131
/**
@@ -201,6 +219,7 @@ export function useFeatureFlags() {
201219
issues: false,
202220
capacity: false,
203221
assignments: false,
222+
advancedCAD: false,
204223
};
205224
updateFlags.mutate(allDisabled);
206225
};

src/i18n/locales/de/admin.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,11 @@
401401
"assignments": {
402402
"label": "Zuweisungen",
403403
"description": "Arbeitszuweisungen und Bedienerplanung"
404-
}
404+
},
405+
"advancedCAD": {
406+
"label": "Erweiterte CAD (PMI/MBD)",
407+
"description": "Serverseitige CAD-Verarbeitung mit PMI/MBD-Extraktion. Erfordert externen eryxon3d-Service."
408+
},
409+
"externalServiceNote": "Diese Funktion erfordert einen externen Dienst. Siehe Self-Hosting-Anleitung für Bereitstellungsanweisungen."
405410
}
406411
}

src/i18n/locales/en/admin.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -488,6 +488,11 @@
488488
"assignments": {
489489
"label": "Assignments",
490490
"description": "Work assignments and operator scheduling"
491-
}
491+
},
492+
"advancedCAD": {
493+
"label": "Advanced CAD (PMI/MBD)",
494+
"description": "Server-side CAD processing with PMI/MBD extraction. Requires external eryxon3d service."
495+
},
496+
"externalServiceNote": "This feature requires an external service. See the Self-Hosting Guide for deployment instructions."
492497
}
493498
}

src/i18n/locales/nl/admin.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -647,6 +647,11 @@
647647
"assignments": {
648648
"label": "Toewijzingen",
649649
"description": "Werktoewijzingen en operator planning"
650-
}
650+
},
651+
"advancedCAD": {
652+
"label": "Geavanceerde CAD (PMI/MBD)",
653+
"description": "Server-side CAD-verwerking met PMI/MBD-extractie. Vereist externe eryxon3d-service."
654+
},
655+
"externalServiceNote": "Deze functie vereist een externe service. Zie de Self-Hosting Guide voor implementatie-instructies."
651656
}
652657
}

0 commit comments

Comments
 (0)