feat(#3298): scaffold boost-backend with ProviderManager, extension point, and security middleware#3466
feat(#3298): scaffold boost-backend with ProviderManager, extension point, and security middleware#3466fullsend-ai-coder[bot] wants to merge 4 commits into
Conversation
Missing ChangesetsThe following package(s) are changed by this PR but do not have a changeset:
See CONTRIBUTING.md for more information about how to add changesets. Changed Packages
|
|
|
🤖 Finished Review · ✅ Success · Started 5:14 AM UTC · Completed 5:31 AM UTC |
ReviewFindingsMedium
Low
Info
Previous runReviewReason: stale-head The review agent reviewed commit Previous run (2)ReviewFindingsHigh
Medium
Low
Info
Previous run (3)ReviewReason: stale-head The review agent reviewed commit Previous run (4)ReviewFindingsHigh
Medium
Low
Info
Previous run (5)ReviewFindingsHigh
Medium
Low
Info
Previous run (6)ReviewFindingsCritical
Medium
Low
|
5eaeee2 to
be2f52a
Compare
CI Feedback 🧐A test triggered by this PR failed. Here is an AI-generated analysis of the failure:
|
|
🤖 Finished Review · ✅ Success · Started 1:40 PM UTC · Completed 1:55 PM UTC |
be2f52a to
fc922ee
Compare
|
🤖 Finished Review · ✅ Success · Started 3:17 PM UTC · Completed 3:32 PM UTC |
|
🤖 Finished Review · ✅ Success · Started 2:54 PM UTC · Completed 3:07 PM UTC |
f8acc23 to
c3d4638
Compare
|
/fs-review |
|
🤖 Finished Review · ✅ Success · Started 3:09 PM UTC · Completed 3:24 PM UTC |
…oint, and security middleware Implements the core boost-backend plugin package: - ProviderManager: manages registered AI providers with hot-swap support (registerProvider, getActiveProvider, switchProvider) - boostProviderExtensionPoint: extension point in boost-node for provider modules to register their implementations - boostAiProviderServiceFactory: default service factory resolving to the active provider via ProviderManager - authorizeLifecycleAction: Express middleware implementing fine-grained permission check -> boost.admin fallback -> 403 pattern - validateSecurityMode: rejects 'none' with clear error, warns when development-only-no-auth is used in production (NODE_ENV=production) - Permission registration: all 23 boost permissions registered via permissionsRegistry.addPermissions() - Resource loader placeholders for agents and tools (store integration deferred to later issues) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Removes stale publishConfig entries (main, module, types) that backstage-cli repo fix strips for backend-plugin roles. Fixes the `yarn fix --check` CI gate. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add missing report.api.md for boost-backend (new package) - Update boost-node report.api.md with extension point exports - Deduplicate 5 lockfile entries (catalog-client, permission-node, backend-plugin-api, auth-node) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
8c8efe5 to
9bdd457
Compare
- Service factory now returns a lazy proxy that delegates chat, chatStream, and descriptor to providerManager.getActiveProvider() at invocation time, not resolution time. This fixes a race where provider modules register after the factory is resolved. - ProviderManager.getActiveProvider() now throws NotFoundError from @backstage/errors instead of plain Error, giving Backstage's error middleware a proper HTTP 404 status. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: gabemontero <gmontero@redhat.com>
|
🤖 Finished Review · ✅ Success · Started 6:38 PM UTC · Completed 6:54 PM UTC |
|
|
/fs-review |
|
🤖 Finished Review · ✅ Success · Started 6:57 PM UTC · Completed 7:13 PM UTC |
| "main": "src/index.ts", | ||
| "types": "src/index.ts", | ||
| "publishConfig": { | ||
| "access": "public" |
There was a problem hiding this comment.
[medium] missing-publishConfig
The boost-backend publishConfig only specifies access:public but omits main, module, types fields present in sibling packages. Without these, npm publish would expose src/index.ts instead of compiled dist/ output, making the published package unusable.
Suggested fix: Add main, module, and types fields to publishConfig matching the pattern used by boost-common and boost-node.
| * | ||
| * @internal | ||
| */ | ||
| const providerManager = new ProviderManager(); |
There was a problem hiding this comment.
[medium] race-condition
Module-level singleton ProviderManager shared between boostPlugin and boostAiProviderServiceFactory creates hidden coupling via module identity. In dynamic plugin scenarios the singleton identity can break. The augment plugin creates its manager inside registerInit instead.
Suggested fix: Wire ProviderManager through a plugin-scoped service ref or extension point instead of module closure.
| logger.info('Initializing boost backend plugin'); | ||
|
|
||
| // Validate security mode (rejects 'none', warns in production) | ||
| const securityMode = validateSecurityMode( |
There was a problem hiding this comment.
[medium] fail-open
The validated securityMode is computed and logged but never used to gate any behavior. No code path consults it to decide whether to apply or skip authorization middleware.
Suggested fix: Store securityMode in a location accessible to route handlers so it can gate authorization when routes are added.
| 'Security mode "none" is not a valid mode name. ' + | ||
| 'Use "development-only-no-auth" instead. ' + | ||
| `Valid modes: ${VALID_SECURITY_MODES.join(', ')}`, | ||
| ); |
There was a problem hiding this comment.
[medium] fail-open
When boost.security.mode is absent from config, validateSecurityMode defaults to development-only-no-auth. The sibling augment plugin defaults to the more secure plugin-only. A production deployment omitting this key would silently run without auth once the mode is wired up.
Suggested fix: Default to plugin-only or full when config is absent, requiring explicit opt-in to development-only-no-auth.
| */ | ||
| export class ProviderManager { | ||
| private activeProvider: AgenticProvider | undefined; | ||
| private readonly providers = new Map<string, AgenticProvider>(); |
There was a problem hiding this comment.
[medium] error-handling-idiom
registerProvider throws bare Error for duplicate IDs while getActiveProvider correctly uses NotFoundError. switchProvider also throws bare Error. The codebase convention is typed errors: ConflictError for duplicates, NotFoundError for missing providers.
Suggested fix: Use ConflictError in registerProvider and NotFoundError in switchProvider, both from @backstage/errors.



Implements the core boost-backend plugin package:
(registerProvider, getActiveProvider, switchProvider)
modules to register their implementations
active provider via ProviderManager
permission check -> boost.admin fallback -> 403 pattern
development-only-no-auth is used in production (NODE_ENV=production)
permissionsRegistry.addPermissions()
deferred to later issues)
Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com
Closes #3298
Post-script verification
feat/3298-boost-backend-scaffold)3036a95068caf62a3ac06568b0d21dbc25322ac9..HEAD)