Extension Marketplace Server
This module handles the extension marketplace functionality, including extension registry management, installation lifecycle, and publisher actions.
Extension Lifecycle Management
Overview
Publishers should generally not be able to completely unregister extensions that users have already installed, but there are nuanced approaches to handle extension lifecycle scenarios while balancing publisher needs, user expectations, and platform security.
Recommended Approach: Soft Deprecation vs Hard Removal
1. Publisher Actions Available
{
"_id": ObjectId("67c2c30f860196612c58b082"),
"extensionID": "stackflow1/builder-extension",
"publisher": "stackflow1",
"status": "active",
"deprecation": {
"isDeprecated": false,
"deprecatedAt": null,
"reason": null,
"replacementExtension": null,
"endOfLifeDate": null,
"migrationGuide": null
},
"publisherActions": {
"canDeprecate": true,
"canSuspendNewInstalls": true,
"canRemoveFromMarketplace": true,
"canForceUninstall": false
},
"versions": [
{
"version": "1.0.0",
"status": "active",
"yankedAt": null,
"yankedReason": null
}
]
}
2. Enhanced installedExtensions with Lifecycle Management
{
"_id": ObjectId("67c2c30f860196612c58b080"),
"tenantId": "default",
"registryRef": ObjectId("67c2c30f860196612c58b082"),
"extensionID": "stackflow1/builder-extension",
"installedVersion": "1.0.0",
"status": "installed",
"lifecycle": {
"registryStatus": "active",
"isOrphaned": false,
"deprecationWarningShown": false,
"autoUpdateBlocked": false,
"lastRegistryCheck": ISODate("2025-03-01T11:00:00.000+0000")
},
"policies": {
"allowOrphanedExecution": true,
"requireSecurityUpdates": true,
"autoRemoveDeprecated": false,
"deprecationGracePeriod": 90
}
}
Publisher Actions and Their Effects
1. Deprecate Extension (Recommended)
db.extensionRegistry.updateOne(
{ extensionID: 'stackflow1/builder-extension' },
{
$set: {
status: 'deprecated',
deprecation: {
isDeprecated: true,
deprecatedAt: new Date(),
reason: 'maintenance',
replacementExtension: 'stackflow1/builder-v2',
endOfLifeDate: new Date(Date.now() + 365 * 24 * 60 * 60 * 1000),
migrationGuide: 'https://docs.example.com/migration-guide',
},
},
},
);
db.installedExtensions.updateMany(
{ extensionID: 'stackflow1/builder-extension' },
{
$set: {
status: 'deprecated-installed',
'lifecycle.registryStatus': 'deprecated',
},
},
);
2. Suspend New Installations
db.extensionRegistry.updateOne(
{ extensionID: 'stackflow1/builder-extension' },
{
$set: {
status: 'suspended',
suspension: {
suspendedAt: new Date(),
reason: 'security-review',
allowExistingInstalls: true,
estimatedResolution: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000),
},
},
},
);
3. Remove from Marketplace (Registry remains for installed extensions)
db.extensionRegistry.updateOne(
{ extensionID: 'stackflow1/builder-extension' },
{
$set: {
status: 'removed',
marketplaceVisibility: 'hidden',
removal: {
removedAt: new Date(),
reason: 'discontinued',
keepForInstalledUsers: true,
},
},
},
);
db.installedExtensions.updateMany(
{ extensionID: 'stackflow1/builder-extension' },
{
$set: {
status: 'orphaned',
'lifecycle.isOrphaned': true,
'lifecycle.registryStatus': 'removed',
},
},
);
4. Emergency Removal (Admin-only, rare cases)
db.extensionRegistry.updateOne(
{ extensionID: 'stackflow1/builder-extension' },
{
$set: {
status: 'emergency-removed',
emergencyRemoval: {
removedAt: new Date(),
removedBy: 'platform-admin',
reason: 'security-vulnerability',
forceUninstall: true,
notificationSent: true,
},
},
},
);
db.installedExtensions.updateMany(
{ extensionID: 'stackflow1/builder-extension' },
{
$set: {
status: 'force-disabled',
'settings.systemEnabled': false,
'settings.effectiveEnabled': false,
'runtime.activationState': 'disabled-by-admin',
},
},
);
User Experience for Different Scenarios
1. Deprecated Extension
interface DeprecationWarning {
type: 'deprecation';
message: 'Builder Extension is deprecated and will stop working on March 1, 2026';
actions: [
{ label: 'View Migration Guide'; url: 'https://docs.example.com/migration' },
{ label: 'Install Replacement'; extensionID: 'stackflow1/builder-v2' },
{ label: 'Dismiss'; action: 'dismiss' },
];
}
2. Suspended Extension
interface SuspensionNotice {
type: 'suspension';
message: 'Builder Extension is under security review. Updates suspended temporarily.';
estimatedResolution: '2025-03-08T00:00:00Z';
}
3. Orphaned Extension (Removed from marketplace)
interface OrphanedWarning {
type: 'orphaned';
message: 'Builder Extension is no longer maintained. No updates will be available.';
actions: [
{ label: 'Find Alternatives'; action: 'browse-alternatives' },
{ label: 'Keep Using'; action: 'accept-risk' },
{ label: 'Uninstall'; action: 'uninstall' },
];
}
Administrative Policies
{
"extensionPolicies": {
"orphanedExtensions": {
"allowExecution": true,
"showWarnings": true,
"autoRemoveAfterDays": null
},
"deprecatedExtensions": {
"allowNewActivations": true,
"gracePeriodDays": 90,
"forceRemovalAfterEOL": false
},
"suspendedExtensions": {
"allowContinuedUse": true,
"disableAfterDays": null
},
"securityPolicies": {
"respectEmergencyDisables": true,
"allowManualOverride": false
}
}
}
Query Examples
Get Extensions Needing User Attention
db.installedExtensions.aggregate([
{
$match: {
tenantId: 'default',
'lifecycle.registryStatus': { $in: ['deprecated', 'suspended', 'removed'] },
},
},
{
$lookup: {
from: 'extensionRegistry',
localField: 'registryRef',
foreignField: '_id',
as: 'registry',
},
},
{
$project: {
extensionID: 1,
status: 1,
lifecycle: 1,
deprecation: '$registry.deprecation',
suspension: '$registry.suspension',
},
},
]);
Best Practices
Publishers Should:
- Use deprecation for planned discontinuation
- Provide migration guides and alternatives
- Give reasonable notice periods (6-12 months)
- Only request emergency removal for serious issues
Platform Should:
- Require admin approval for emergency removals
- Maintain registry entries for installed extensions
- Provide clear user notifications
- Allow organizational policies to override defaults
Users Should:
- Receive clear warnings about extension status changes
- Have time to migrate to alternatives
- Retain control over their installed extensions
- Be able to accept risks of using orphaned extensions
This approach balances publisher needs, user expectations, and platform security while avoiding the disruption of completely removing extensions that users depend on.