feat: Wcp.FeatureFlags extension and extension infrastructure consolidation#4950
feat: Wcp.FeatureFlags extension and extension infrastructure consolidation#4950
Conversation
Co-authored-by: adrians5j <5121148+adrians5j@users.noreply.github.com>
…gn export naming Co-authored-by: adrians5j <5121148+adrians5j@users.noreply.github.com>
| tags: { runtimeContext: "app-build", appName: "api" }, | ||
| multiple: true, | ||
| paramsSchema, | ||
| async build(params, ctx) { |
There was a problem hiding this comment.
This sux. rather use render method like
packages/cognito/src/Cognito.tsx:14
this easily allows you to reuse existing Api.BuildParam and Admin.BuildParams. @copilot
There was a problem hiding this comment.
Refactored in e76b322. Moved Wcp.Feature to packages/project-aws/src/wcp.tsx and rewrote it using the render method pattern — it now simply renders <Api.BuildParam> and <Admin.BuildParam> with the wcp.feature.{name} param key, delegating all file-generation to the existing build logic. Removed all custom ts-morph/fs code.
….Feature Co-authored-by: adrians5j <5121148+adrians5j@users.noreply.github.com>
| constructor(private license: ILicense) {} | ||
| constructor( | ||
| private license: ILicense, | ||
| private buildParams?: IBuildParams |
There was a problem hiding this comment.
Fixed in c9cb6fa — WcpContextImpl is back to its original form with no ? and no BuildParams.
|
|
||
| canUsePrivateFiles(): boolean { | ||
| return this.license.canUsePrivateFiles(); | ||
| return this.license.canUsePrivateFiles() && this.isFeatureEnabled("privateFiles"); |
There was a problem hiding this comment.
Instead of directly involving BuildParams here, let's rather do an intermediary abstraction, called maybe something like WcpFeatureSwitcher. Or maybe you make a better name for the abstraction. IDK any other name.
Then, let's use open/closed principle. Instead of modifying, let's rather create a WcpContext decorator, which adds this extra WcpFeatureSwitcher layer of functionality.
There was a problem hiding this comment.
Done in c9cb6fa. Introduced WcpFeatureOverrides abstraction (packages/api-core/src/features/wcp/WcpFeatureOverride/) that reads wcp.feature.{name} build params, and a WcpContextWithFeatureOverrides decorator (WcpContext/decorators/) that wraps WcpContext and applies the overrides to all canUse* methods — without touching WcpContextImpl at all. Registered via WcpFeature.ts.
…hFeatureOverrides decorator Co-authored-by: adrians5j <5121148+adrians5j@users.noreply.github.com>
|
You know what... I just made up my mind.. Instead of writing multiple <Wcp.Feature name="teams" enabled={false} />
<Wcp.Feature name="workflows" enabled={false} />`.. let's rather have smt like <Wcp.FeatureFlags features={{ advancedAccessControLayer: { enabled: false, options: { teams: false }} }} />Basically the same structure of license I mentioned, which then gets merged with this config here. The most important thing when doing the merge ofc is preventing users from allowng a feature via this comp, and being able to use it, despite real fetched license saying the feat is not allowed. @copilot |
The comment appears to have been truncated — the code block didn't come through. Could you share the full suggestion? |
|
pasting comment again You know what... I just made up my mind.. Instead of writing multiple <Wcp.Feature name="teams" enabled={false} />
<Wcp.Feature name="workflows" enabled={false} />`.. let's rather have smt like <Wcp.FeatureFlags features={{ advancedAccessControLayer: { enabled: false, options: { teams: false }} }} />Basically the same structure of license I mentioned, which then gets merged with this config here. The most important thing when doing the merge ofc is preventing users from allowng a feature via this comp, and being able to use it, despite real fetched license saying the feat is not allowed. @copilot |
Still getting a truncated code block — the content after |
|
pasting comment again You know what... I just made up my mind.. Instead of writing multiple <Wcp.Feature name="teams" enabled={false} /> <Wcp.FeatureFlags features={{ advancedAccessControLayer: { enabled: false, options: { teams: false }} }} /> Basically the same structure of license I mentioned, which then gets merged with this config here. The most important thing when doing the merge ofc is preventing users from allowng a feature via this comp, and being able to use it, despite real fetched license saying the feat is not allowed. @copilot |
|
update PR body.. I made soem changes @copilot |
|
let's write PR body from scratch @copilot |
Done — PR body rewritten from scratch. |
|
/e2e |
|
Cypress E2E tests have been initiated (for more information, click here). ✨ |
|
/e2e |
|
Cypress E2E tests have been initiated (for more information, click here). ✨ |
|
/e2e |
|
Cypress E2E tests have been initiated (for more information, click here). ✨ |
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: adrians5j <5121148+adrians5j@users.noreply.github.com> Co-authored-by: Adrian Smijulj <adrian1358@gmail.com> Co-authored-by: adrians5j <adrian@webiny.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: adrians5j <5121148+adrians5j@users.noreply.github.com> Co-authored-by: Adrian Smijulj <adrian1358@gmail.com> Co-authored-by: adrians5j <adrian@webiny.com>
Adds a
Wcp.FeatureFlagsextension that lets users override WCP feature flags at the project-config level (webiny.config.tsx), independently of the fetched WCP license. Useful for disabling licensed features in dev/staging environments while keeping them active in production.Usage
The
featuresprop mirrors the WCP license structure. Supported keys:multiTenancyenabledadvancedPublishingWorkflowenabledadvancedAccessControlLayerenabled,options.teams,options.privateFiles,options.folderLevelPermissionsauditLogsenabledrecordLockingenabledfileManageroptions.threatDetectionUsers can only disable features — attempting to enable a feature the WCP license does not permit has no effect (overrides are ANDed with the license value).
Changes
New:
Wcp.FeatureFlagsextension (packages/project/src/extensions/FeatureFlags.tsx)packages/projectusing therendermethod pattern (same asCognito.tsx)FeatureFlags.tsx(generic — future non-WCP feature flags can be added here)renderoutputs two build params —<ApiBuildParam paramName="FeatureFlags" value={{ wcp: features }} />and<AdminBuildParam paramName="FeatureFlags" value={{ wcp: features }} />— delegating all file-generation to the existing build infrastructure"FeatureFlags"build param key as{ wcp: { ... } }IFeatureFlagsshape from@webiny/feature-flagsexport const Wcp = { FeatureFlags: ... }(consistent withEnvVar.tspattern)Wcp.FeatureFlags.definpackages/project/src/extensions/index.tsNew:
IFeatureFlagsinterface (packages/feature-flags/src/index.ts)@webiny/*dependencies — easy to include inpackages/project,packages/api-core, andpackages/app-adminIFeatureFlags { wcp?: { ... } }— extensible top-level interface for all feature flag namespacesNew:
FeatureFlagsfeature (packages/api-core)packages/api-core/src/features/wcp/WcpFeatureFlags/—FeatureFlagsImplclass (abstraction:FeatureFlagsAbstraction) readsbuildParams.get<IFeatureFlags>("FeatureFlags")and maps WCP feature names to their nested path under.wcp; registered asWcpFeatureFlagsFeatureWcpContextWithFeatureFlagsDecorator(WcpContextWithFeatureFlagsDecorator.ts) — decorator (open/closed principle) that wrapsWcpContextand appliesFeatureFlagschecks to allcanUse*methods viaWcpContextWithFeatureFlagsDecoratorImpl;WcpContextImplis unchangedUpdated: Admin WCP feature checks respect feature flags
Wcp.tsx(packages/app-admin) — allCanUse*components read the"FeatureFlags"build param typed asIFeatureFlagsviauseContainer()and AND the result with the license checkConsolidated: Extension primitives moved to
packages/projectpackages/api-core/src/extensions/BuildParam.ts→packages/project/src/extensions/ApiBuildParam.tspackages/api-core/src/extensions/GenericExtension.ts→packages/project/src/extensions/ApiExtension.tspackages/app-admin/src/extensions/AdminBuildParam.ts→packages/project/src/extensions/AdminBuildParam.tspackages/app-admin/src/extensions/AdminExtension.ts→packages/project/src/extensions/AdminExtension.tspackages/app-admin/src/extensions/index.ts,packages/api-core/src/extensions/index.ts, and the entirepackages/api-core/src/extensions/eventHandlers/folder deleted — event handler registration is now handled entirely viaApi.Extensionpackages/project-aws/src/security.tsdeleted —Security.*event handler namespace removed; useApi.Extensioninsteadpackages/project-awsupdated to importBuildParam,AdminBuildParam,AdminExtension, andApiExtensionfrom@webiny/projectExports
Wcpexported viapackages/project/src/exports/extensions.ts→packages/project-aws/src/exports/extensions.ts→packages/webiny/src/extensions.ts💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.