Skip to content

feat(boost): combined spec updates, auth pivot, dev scaffold, and entity provider fixes #3647

Description

@gabemontero

This issue covers spec updates, an auth pivot, dev scaffold additions, and entity provider fixes for the boost workspace — combined into a single change.

1. Staged-issues bookkeeping

Add the GitHub issue URL for issue 16 (#3597) to workspaces/boost/staged-issues.md in the boost-skills-routes section.

2. Auth pivot: RFC 8693 → OAuth2 Client Credentials

Pivot Kagenti authentication from per-user RFC 8693 token exchange to service-account OAuth2 Client Credentials Grant across all specification, openspec, and config schema files.

Config key changes

Old keys (remove):

  • boost.kagenti.auth.tokenExchange.enabled
  • boost.kagenti.auth.tokenExchange.audience
  • boost.kagenti.auth.tokenExchange.userTokenHeader

New keys (add):

  • boost.kagenti.auth.tokenEndpoint — Keycloak token endpoint URL
  • boost.kagenti.auth.clientId — OAuth2 client ID for service-account
  • boost.kagenti.auth.clientSecret — OAuth2 client secret (visibility: secret)
  • boost.kagenti.auth.tokenExpiryBufferSeconds — Seconds before expiry to refresh (default: 60)

Files to update

Specifications (3):

  • workspaces/boost/specifications/boost-context.md — Update principle 10 from "Per-User Identity Delegation" to "Service-Account Keycloak Authentication"; update augment lesson; update security PRD summary line
  • workspaces/boost/specifications/prd/security-safety-governance.md — Replace all RFC 8693 / token exchange references with Client Credentials Grant / KeycloakTokenManager throughout (capability 3, security mode table, architecture diagram, traceability table, customer context)
  • workspaces/boost/specifications/prd/platform-operations-deployment.md — Update Kagenti Auth line in configurable categories (line ~189)

OpenSpec (7):

  • workspaces/boost/openspec/changes/security-safety-governance/design.md — Update decision 4 and risks
  • workspaces/boost/openspec/changes/security-safety-governance/proposal.md — Update identity/auth section and key file reference
  • workspaces/boost/openspec/changes/security-safety-governance/tasks.md — Update section 7 tasks and section 10 verification tasks
  • workspaces/boost/openspec/changes/security-safety-governance/specs/access-control/spec.md — Replace all token exchange scenarios with service-account auth scenarios (token acquisition, streaming lifecycle, 401 retry with max-1-retry constraint, user identity propagation via X-Backstage-User header, Kagenti REST API endpoints)
  • workspaces/boost/openspec/changes/platform-operations-deployment/specs/runtime-config/spec.md — Update token exchange config table to Keycloak service-account fields
  • workspaces/boost/openspec/changes/platform-operations-deployment/tasks.md — Update task 2.5 wording
  • workspaces/boost/openspec/changes/pluggable-ai-platform-architecture/design.md — Update non-goal to note service-account auth adopted instead

Config/code (3):

  • workspaces/boost/plugins/boost-backend/config.d.ts — Replace tokenExchange nested object with flat tokenEndpoint, clientId, clientSecret, tokenExpiryBufferSeconds fields under kagenti.auth
  • workspaces/boost/plugins/boost-backend/src/config/schemas.ts — Bump BOOST_CONFIG_SCHEMA_VERSION to 2, replace tokenExchange.* field entries with new flat field entries, add sensitive: true to clientSecret
  • workspaces/boost/plugins/boost-backend/src/config/schemas.test.ts — Update test expectations for new field names; add validation tests for tokenExpiryBufferSeconds (valid integers accepted, negative rejected, non-integer rejected, undefined returns undefined)

Generated (1):

  • workspaces/boost/plugins/boost-backend/report.api.md — Regenerate via yarn build:api-reports

Staged issues (1):

  • workspaces/boost/staged-issues.md — Update issue 13 section: header, description, task list, spec references

Key design decisions

  • tokenExpiryBufferSeconds schema is .number().int().min(0).optional() with no .default(60)RuntimeConfigResolver returns raw YAML values that bypass Zod defaults, so the consumer (KeycloakTokenManager) must apply configValue ?? 60
  • clientSecret field has sensitive: true and @visibility secret in config.d.ts
  • Max-1-retry on 401: "if the retried request also returns 401, the error is propagated to the caller"

3. Spec adjustments for working dev environment

workspaces/boost/specifications/boost-context.md

  • Add boost-responses-api-toolkit and boost-toolscope to the workspace structure tree
  • Update the paragraph describing the packages to mention toolscope (zero Backstage deps) and responses-api-toolkit (minimal Backstage deps)
  • Add new "Local Development" section with:
    • Host Packages: Explains packages/app and packages/backend as standard Backstage scaffolding, not product code
    • Metrics Compatibility Shim: Documents the no-op metricsServiceRef factory needed because backend-defaults doesn't provide one yet (as of Backstage 1.52)
    • TLS and IDE Environment Caveats: NODE_TLS_REJECT_UNAUTHORIZED=0 for self-signed OpenShift route certs; IDE subprocess env var gotcha

workspaces/boost/specifications/prd/platform-operations-deployment.md

  • Add boost-responses-api-toolkit and boost-toolscope rows to the workspace package table

4. Backend code changes for integration testing

New files

workspaces/boost/app-config.yaml — Development-mode app-config with:

  • Guest auth provider
  • SQLite in-memory database
  • boost.security.mode: 'development-only-no-auth'
  • boost.providers.llamastack and boost.providers.kagenti config with env var defaults pointing at a dev cluster
  • boost.kagenti entity provider config with auth settings (tokenEndpoint, clientId, clientSecret from env vars)
  • NOTE: All default URLs use :- syntax for env var fallback, not hardcoded values

workspaces/boost/packages/backend/ — Host backend package:

  • package.json with dependencies on backend-defaults, plugin-proxy-backend, plugin-auth-backend, plugin-auth-backend-module-guest-provider, plugin-catalog-backend, plugin-catalog-backend-module-logs, plugin-permission-backend, plugin-permission-backend-module-allow-all-policy, and all boost plugins
  • src/index.ts with:
    • No-op metricsServiceRef factory shim (catalog-backend depends on it, backend-defaults doesn't provide it yet — uses @backstage/backend-plugin-api/alpha)
    • Registration of all core Backstage plugins + all boost plugins (boost-backend, boost-backend-module-llamastack, boost-backend-module-kagenti, kagenti-entity-provider, llamastack-entity-provider)
  • .eslintrc.js extending @backstage/cli/config/eslint.backend

workspaces/boost/scripts/load-secrets.sh — Shell script to load dev secrets from K8s:

  • Reads KAGENTI_CLIENT_SECRET, KAGENTI_CLIENT_ID, KAGENTI_TOKEN_ENDPOINT, KAGENTI_BASE_URL, KAGENTI_NAMESPACE, BOOST_MODEL from a K8s secret
  • Sets NODE_TLS_REJECT_UNAUTHORIZED=0
  • Masks sensitive values in output (<set> for secrets)

Modified files

workspaces/boost/plugins/kagenti-entity-provider/src/providers/kagentiAuth.ts (new file) — KeycloakAuthClient class:

  • OAuth2 Client Credentials Grant token acquisition
  • Token caching with expiry buffer
  • getBearerToken() returns cached token or fetches fresh one
  • Uses node:buffer for base64 encoding (NOT btoa which is browser-only in older Node)

workspaces/boost/plugins/kagenti-entity-provider/src/types.ts — Add KagentiEntityProviderConfig.auth optional field with tokenEndpoint, clientId, clientSecret

workspaces/boost/plugins/kagenti-entity-provider/src/module.ts — Read auth config from boost.kagenti.auth.*, construct KeycloakAuthClient when all 3 auth fields are present, pass to entity providers

workspaces/boost/plugins/kagenti-entity-provider/src/providers/KagentiAgentEntityProvider.ts:

  • Accept optional KeycloakAuthClient in constructor
  • Fetch bearer token before namespace loop and add Authorization header
  • Use correct API URL: GET /api/v1/agents?namespace={ns} (NOT /a2a/)
  • Handle response shape: { items: AgentCard[] } OR AgentCard[] via unwrapItems helper

workspaces/boost/plugins/kagenti-entity-provider/src/providers/KagentiToolEntityProvider.ts:

  • Same auth and URL pattern as agent provider
  • GET /api/v1/tools?namespace={ns}
  • Same unwrapItems response handling

workspaces/boost/plugins/kagenti-entity-provider/src/providers/entityHelpers.ts — Add unwrapItems<T>() helper function to handle both { items: T[] } and T[] response shapes from Kagenti API

workspaces/boost/plugins/kagenti-entity-provider/src/providers/KagentiAgentEntityProvider.test.ts and KagentiToolEntityProvider.test.ts — Add tests for Keycloak auth integration (bearer token header, auth failure handling)

workspaces/boost/plugins/boost-backend/src/mcp/routes.ts and workspaces/boost/plugins/boost-backend/src/skills/routes.ts — Add TODO comments noting future cross-reference with catalog for MCP/skill access (not functional changes, just markers)

yarn.lock

The yarn.lock will need regenerating after the dependency changes in packages/backend/package.json. Run yarn install in the boost workspace.

Verification

After all changes:

  1. cd workspaces/boost && yarn tsc — no type errors
  2. cd workspaces/boost && yarn test --watchAll=false — all tests pass
  3. cd workspaces/boost && yarn build:api-reports — report.api.md up to date
  4. cd workspaces/boost && yarn lint — clean

Security constraints

  • The only references to "augment" or "Augment" should be at the high level, introductory phase, where we acknowledge that boost is a clean room re-implementation of augment (e.g., specifications/boost-context.md provenance notes and "Augment lesson" callouts)
  • Do not reference any specific customer names in code or openspecs

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions