Skip to content

feat(boost): scaffold boost-common package with shared types, service ref, and permissions#3315

Closed
fullsend-ai-coder[bot] wants to merge 1 commit into
mainfrom
feat/boost-common-scaffold
Closed

feat(boost): scaffold boost-common package with shared types, service ref, and permissions#3315
fullsend-ai-coder[bot] wants to merge 1 commit into
mainfrom
feat/boost-common-scaffold

Conversation

@fullsend-ai-coder

Copy link
Copy Markdown
Contributor

Add the boost-common package as the foundational shared library for the Boost workspace. This package exports:

  • AgenticProvider interface and ProviderDescriptor/ProviderCapabilities types
  • NormalizedStreamEvent discriminated union for streaming contract
  • ConversationSummary, ConversationDetails, and InputItem conversation types
  • boostAiProviderServiceRef for cross-plugin AI provider consumption
  • 23 fine-grained Backstage permissions (10 agent, 5 tool, 1 infra, 5 functional, 2 top-level)
  • Resource types boost-agent and boost-tool
  • Conditional permission rule constants (IS_OWNER, IS_NOT_CREATOR, HAS_LIFECYCLE_STAGE)

No provider-specific types are included (task 1.6 verification).

Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com


Closes #3297

Post-script verification

  • Branch is not main/master (feat/boost-common-scaffold)
  • Secret scan passed (gitleaks — 5c9083af21efc8f88dad77d38493cb136d4ddb9a..HEAD)
  • Pre-commit hooks passed (authoritative run on runner)
  • Tests ran inside sandbox

… ref, and permissions

Add the boost-common package as the foundational shared library for the
Boost workspace. This package exports:

- AgenticProvider interface and ProviderDescriptor/ProviderCapabilities types
- NormalizedStreamEvent discriminated union for streaming contract
- ConversationSummary, ConversationDetails, and InputItem conversation types
- boostAiProviderServiceRef for cross-plugin AI provider consumption
- 23 fine-grained Backstage permissions (10 agent, 5 tool, 1 infra, 5 functional, 2 top-level)
- Resource types boost-agent and boost-tool
- Conditional permission rule constants (IS_OWNER, IS_NOT_CREATOR, HAS_LIFECYCLE_STAGE)

No provider-specific types are included (task 1.6 verification).

Closes #3297

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@fullsend-ai-coder fullsend-ai-coder Bot requested review from a team, durandom and gabemontero as code owners June 5, 2026 14:46
@rhdh-gh-app

rhdh-gh-app Bot commented Jun 5, 2026

Copy link
Copy Markdown

Missing Changesets

The following package(s) are changed by this PR but do not have a changeset:

  • @red-hat-developer-hub/backstage-plugin-boost-common

See CONTRIBUTING.md for more information about how to add changesets.

Changed Packages

Package Name Package Path Changeset Bump Current Version
@red-hat-developer-hub/backstage-plugin-boost-common workspaces/boost/plugins/boost-common none v0.1.0

@codecov

codecov Bot commented Jun 5, 2026

Copy link
Copy Markdown

⚠️ JUnit XML file not found

The CLI was unable to find any JUnit XML files to upload.
For more help, visit our troubleshooting guide.

@sonarqubecloud

sonarqubecloud Bot commented Jun 5, 2026

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
6.9% Duplication on New Code (required ≤ 3%)

See analysis details on SonarQube Cloud

@fullsend-ai-review

Copy link
Copy Markdown

Review

Findings

Medium

  • [test-inadequate] workspaces/boost/plugins/boost-common/src/types.test.ts:233 — The "no provider-specific types" test uses Object.keys(require('./types')) to check for unwanted exports. However, types.ts only exports TypeScript interfaces and type aliases, which are erased at compile time. At runtime, require('./types') yields an empty object {}, so Object.keys() always returns [] and this test passes trivially regardless of what type names are defined. This means the task 1.6 verification ("no provider-specific types in common package") is not actually being enforced.
    Remediation: Replace the runtime require-based check with a static analysis approach — e.g., use fs.readFileSync to scan the source text for forbidden prefixes in export declarations, or convert to a lint rule.

  • [dependency-declaration] workspaces/boost/plugins/boost-common/package.json@backstage/plugin-permission-common is listed under dependencies, but several established -common packages in this repo (lightspeed, bulk-import, extensions, adoption-insights) declare it as a peerDependency. For a common-library package that re-exports permission types, using peerDependencies avoids duplicate instances when consumed by other packages.
    Remediation: Move @backstage/plugin-permission-common to peerDependencies (and optionally keep in devDependencies for local development). Apply the same consideration to @backstage/backend-plugin-api.

Low

  • [api-contract] workspaces/boost/plugins/boost-common/src/permissions.ts:169boostAgentConfigurePermission is defined without a resourceType, unlike the other 7 agent lifecycle permissions that declare resourceType: BOOST_AGENT_RESOURCE_TYPE. The test explicitly asserts this is intentional, but the rationale is not documented. Without a resource type, conditional rules (IS_OWNER, HAS_LIFECYCLE_STAGE) cannot scope this permission to specific agents. See also: [rbac-violation] finding at this location.

  • [rbac-violation] workspaces/boost/plugins/boost-common/src/permissions.ts:169 — Same code as above from a security perspective: any user granted boost.agent.configure can configure ALL agents with no ownership-based scoping at the permission layer. If this is intentional (e.g., plugin-wide agent settings rather than per-agent configuration), document this in the JSDoc. See also: [api-contract] finding at this location.

  • [interface-design] workspaces/boost/plugins/boost-common/src/types.ts:186ConversationDetails duplicates all five fields from ConversationSummary instead of using extends ConversationSummary. If a field is added to ConversationSummary, ConversationDetails will silently drift. Use interface ConversationDetails extends ConversationSummary { messages: InputItem[]; }.

  • [naming-convention] workspaces/boost/plugins/boost-common/src/types.ts:72ResponseUsage uses snake_case property names (input_tokens, output_tokens, total_tokens) while every other interface uses camelCase. The augment-common package uses the same convention, suggesting upstream wire-format matching. Add a brief JSDoc note explaining the intentional divergence.

  • [type-safety] workspaces/boost/plugins/boost-common/src/permissions.ts:365 — The boostPermissions array is exported as a mutable array. Any consumer could accidentally mutate this shared constant. Add as const or type as readonly Permission[].

  • [naming-convention] workspaces/boost/AGENTS.md — AGENTS.md lists permission prefixes but does not mention the functional namespaces introduced here: boost.chat.*, boost.documents.*, boost.mcp.*, boost.config.*. These are authorized by the security spec but AGENTS.md should be updated.

  • [rbac-violation] workspaces/boost/plugins/boost-common/src/permissions.ts:42 — The JSDoc for boostAdminPermission states the middleware "falls back to this on fine-grained DENY." When implemented, ensure an explicit DENY is never overridden by the admin fallback.

Info

  • [test-inadequate] workspaces/boost/plugins/boost-common/src/types.test.ts:127 — The AgenticProvider mock test exercises chat but not chatStream. Consider adding a test verifying onEvent is called with the expected event sequence.

  • [backward-compatibility] workspaces/boost/plugins/boost-common/src/types.ts:21ProviderCapabilities has 11 required boolean fields. Adding a new capability will break existing provider implementations. Consider making future additions optional.

  • [traceability] PR correctly traces to issue boost-common — Shared types, service ref, and permission definitions (issue 1 of 15) #3297 and implements all tasks from the openspec. 23 permissions match the spec exactly, service ref matches design Decision 1, and no provider-specific types are present (satisfying task 1.6 and Decision 5).

@fullsend-ai-review fullsend-ai-review Bot added the requires-manual-review Review requires human judgment label Jun 5, 2026
@gabemontero

Copy link
Copy Markdown
Contributor

/fs-fix so the CI for this pull request is failing on the yarn install check ... you need to run yarn install and include the yarn.lock and node_module changes that result ..... please fix this; for reference, here is the CI output: yarn install --immutable
➤ YN0000: Yarn detected that the current workflow is executed from a public pull request. For safety the hardened mode has been enabled.
➤ YN0000: It will prevent malicious lockfile manipulations, in exchange for a slower install time. You can opt-out if necessary; check our documentation for more details.

➤ YN0000: · Yarn 4.12.0
➤ YN0000: ┌ Resolution step
Resolution step
➤ YN0000: └ Completed in 16s 861ms
➤ YN0000: ┌ Post-resolution validation
Post-resolution validation
➤ YN0028: -"@backstage/backend-plugin-api@npm:^1.7.0, @backstage/backend-plugin-api@npm:^1.9.1":
➤ YN0028: +"@backstage/backend-plugin-api@npm:^1.3.0, @backstage/backend-plugin-api@npm:^1.7.0, @backstage/backend-plugin-api@npm:^1.9.1":
➤ YN0028: -"@backstage/plugin-permission-common@npm:^0.9.9":
➤ YN0028: +"@backstage/plugin-permission-common@npm:^0.9.2, @backstage/plugin-permission-common@npm:^0.9.9":
➤ YN0028: +"@red-hat-developer-hub/backstage-plugin-boost-common@workspace:plugins/boost-common":
➤ YN0028: + version: 0.0.0-use.local
➤ YN0028: + resolution: "@red-hat-developer-hub/backstage-plugin-boost-common@workspace:plugins/boost-common"
➤ YN0028: + dependencies:
➤ YN0028: + "@backstage/backend-plugin-api": "npm:^1.3.0"
➤ YN0028: + "@backstage/cli": "npm:^0.34.5"
➤ YN0028: + "@backstage/plugin-permission-common": "npm:^0.9.2"
➤ YN0028: + languageName: unknown
➤ YN0028: + linkType: soft
➤ YN0028: +
➤ YN0028: The lockfile would have been modified by this install, which is explicitly forbidden.
➤ YN0000: └ Completed
➤ YN0000: · Failed with errors in 16s 955ms

@gabemontero

Copy link
Copy Markdown
Contributor

per discussion with @durandom in https://redhat-internal.slack.com/archives/C0AR8BTMSJH/p1780929700288199 I'm going to punt on use of fullsend for addressing #3297 for now

@gabemontero gabemontero closed this Jun 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

requires-manual-review Review requires human judgment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

boost-common — Shared types, service ref, and permission definitions (issue 1 of 15)

1 participant