Skip to content

feat: logs chain support in logstore (backend) - #6011

Open
impoiler wants to merge 115 commits into
devfrom
07-24-feat_show_logs_chain_backend
Open

impoiler wants to merge 115 commits into
devfrom
07-24-feat_show_logs_chain_backend

Conversation

@impoiler

Copy link
Copy Markdown
Contributor

Summary

Briefly explain the purpose of this PR and the problem it solves.

Changes

  • What was changed and why
  • Any notable design decisions or trade-offs

Type of change

  • Bug fix
  • Feature
  • Refactor
  • Documentation
  • Chore/CI

Affected areas

  • Core (Go)
  • Transports (HTTP)
  • Providers/Integrations
  • Plugins
  • UI (React)
  • Docs

How to test

Describe the steps to validate this change. Include commands and expected outcomes.

# Core/Transports
go version
go test ./...

# UI
cd ui
pnpm i || npm i
pnpm test || npm test
pnpm build || npm run build

If adding new configs or environment variables, document them here.

Screenshots/Recordings

If UI changes, add before/after screenshots or short clips.

Breaking changes

  • Yes
  • No

If yes, describe impact and migration instructions.

Related issues

Link related issues and discussions. Example: Closes #123

Security considerations

Note any security implications (auth, secrets, PII, sandboxing, etc.).

Checklist

  • I read docs/contributing/README.md and followed the guidelines
  • I added/updated tests where appropriate
  • I updated documentation where needed
  • I verified builds succeed (Go and UI)
  • I verified the CI pipeline passes locally if applicable

jeremym-tanium and others added 30 commits August 5, 2026 00:15
…iew maintenance (#5693)

* feat: support matview_refresh_interval "off" to disable logstore matview maintenance

The materialized views back only the dashboard UI. Deployments that run
Bifrost headless behind their own observability stack pay the REFRESH
MATERIALIZED VIEW CONCURRENTLY cost for views nothing reads, and the 5s
floor means the interval alone cannot turn maintenance off.

With "off" (or a non-positive duration) the logs store skips view
creation, the initial refresh, and the periodic refresher entirely.
matViewsReady stays false, so dashboard queries fall back to the raw
tables, and the runtime self-heal path cannot re-arm maintenance since
it only triggers from matview-path queries.

* fix: guard matview self-heal when maintenance is disabled

Review follow-up: carry the resolved disabled state onto the store so
triggerMatViewSelfHeal cannot recreate views the configuration says must
not exist, and make the schema/docs explicit that a zero duration also
disables (positive sub-5s values still clamp up).
<!-- This is an auto-generated comment: release notes by coderabbit.ai -->

* **Bug Fixes**
  * Improved token parameter compatibility handling to preserve alternative formats when the primary option is unsupported.

* **Chores**
  * Version updated to 2.0.0.
  * Enhanced load testing configuration for more reliable builds.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Summary

Briefly explain the purpose of this PR and the problem it solves.

## Changes

- What was changed and why
- Any notable design decisions or trade-offs

## Type of change

- [ ] Bug fix
- [ ] Feature
- [ ] Refactor
- [ ] Documentation
- [ ] Chore/CI

## Affected areas

- [ ] Core (Go)
- [ ] Transports (HTTP)
- [ ] Providers/Integrations
- [ ] Plugins
- [ ] UI (React)
- [ ] Docs

## How to test

Describe the steps to validate this change. Include commands and expected outcomes.

```sh
# Core/Transports
go version
go test ./...

# UI
cd ui
pnpm i || npm i
pnpm test || npm test
pnpm build || npm run build
```

If adding new configs or environment variables, document them here.

## Screenshots/Recordings

If UI changes, add before/after screenshots or short clips.

## Breaking changes

- [ ] Yes
- [ ] No

If yes, describe impact and migration instructions.

## Related issues

Link related issues and discussions. Example: Closes #123

## Security considerations

Note any security implications (auth, secrets, PII, sandboxing, etc.).

## Checklist

- [ ] I read `docs/contributing/README.md` and followed the guidelines
- [ ] I added/updated tests where appropriate
- [ ] I updated documentation where needed
- [ ] I verified builds succeed (Go and UI)
- [ ] I verified the CI pipeline passes locally if applicable
## Summary

Adds a `THIRD_PARTY_NOTICES.md` file to formally document third-party components used in Bifrost that carry license terms requiring explicit attribution — specifically MPL-2.0 licensed dependencies and embedded source code derived from external projects.

## Changes

- Introduces `THIRD_PARTY_NOTICES.md` to attribute:
  - Embedded source code in `framework/migrator/migrator.go` derived from `go-gormigrate/gormigrate` (MIT)
  - Go binary dependencies carrying MPL-2.0 terms: `github.com/cyphar/filepath-securejoin` and `github.com/hashicorp/go-version`
  - npm build-time devDependencies carrying MPL-2.0 terms: `lightningcss` (never shipped to end users) and `dompurify` (Apache-2.0 option elected)
- All MPL-2.0 components are used unmodified and combined as a "Larger Work" per MPL-2.0 Section 3.3; no Bifrost source files are themselves MPL-licensed.

## Type of change

- [ ] Bug fix
- [ ] Feature
- [ ] Refactor
- [x] Documentation
- [ ] Chore/CI

## Affected areas

- [ ] Core (Go)
- [ ] Transports (HTTP)
- [ ] Providers/Integrations
- [ ] Plugins
- [ ] UI (React)
- [x] Docs

## How to test

No functional changes — review the file contents to confirm accuracy of license attributions against the listed upstream repositories.

## Breaking changes

- [ ] Yes
- [x] No

## Related issues

N/A

## Security considerations

This change has no security implications. It is a legal/compliance attribution document only.

## Checklist

- [ ] I read `docs/contributing/README.md` and followed the guidelines
- [ ] I added/updated tests where appropriate
- [x] I updated documentation where needed
- [x] I verified builds succeed (Go and UI)
- [ ] I verified the CI pipeline passes locally if applicable
## Summary

Briefly explain the purpose of this PR and the problem it solves.

## Changes

- What was changed and why
- Any notable design decisions or trade-offs

## Type of change

- [ ] Bug fix
- [ ] Feature
- [ ] Refactor
- [ ] Documentation
- [ ] Chore/CI

## Affected areas

- [ ] Core (Go)
- [ ] Transports (HTTP)
- [ ] Providers/Integrations
- [ ] Plugins
- [ ] UI (React)
- [ ] Docs

## How to test

Describe the steps to validate this change. Include commands and expected outcomes.

```sh
# Core/Transports
go version
go test ./...

# UI
cd ui
pnpm i || npm i
pnpm test || npm test
pnpm build || npm run build
```

If adding new configs or environment variables, document them here.

## Screenshots/Recordings

If UI changes, add before/after screenshots or short clips.

## Breaking changes

- [ ] Yes
- [ ] No

If yes, describe impact and migration instructions.

## Related issues

Link related issues and discussions. Example: Closes #123

## Security considerations

Note any security implications (auth, secrets, PII, sandboxing, etc.).

## Checklist

- [ ] I read `docs/contributing/README.md` and followed the guidelines
- [ ] I added/updated tests where appropriate
- [ ] I updated documentation where needed
- [ ] I verified builds succeed (Go and UI)
- [ ] I verified the CI pipeline passes locally if applicable
## Summary

Briefly explain the purpose of this PR and the problem it solves.

## Changes

- What was changed and why
- Any notable design decisions or trade-offs

## Type of change

- [ ] Bug fix
- [ ] Feature
- [ ] Refactor
- [ ] Documentation
- [ ] Chore/CI

## Affected areas

- [ ] Core (Go)
- [ ] Transports (HTTP)
- [ ] Providers/Integrations
- [ ] Plugins
- [ ] UI (React)
- [ ] Docs

## How to test

Describe the steps to validate this change. Include commands and expected outcomes.

```sh
# Core/Transports
go version
go test ./...

# UI
cd ui
pnpm i || npm i
pnpm test || npm test
pnpm build || npm run build
```

If adding new configs or environment variables, document them here.

## Screenshots/Recordings

If UI changes, add before/after screenshots or short clips.

## Breaking changes

- [ ] Yes
- [ ] No

If yes, describe impact and migration instructions.

## Related issues

Link related issues and discussions. Example: Closes #123

## Security considerations

Note any security implications (auth, secrets, PII, sandboxing, etc.).

## Checklist

- [ ] I read `docs/contributing/README.md` and followed the guidelines
- [ ] I added/updated tests where appropriate
- [ ] I updated documentation where needed
- [ ] I verified builds succeed (Go and UI)
- [ ] I verified the CI pipeline passes locally if applicable
## Summary

Briefly explain the purpose of this PR and the problem it solves.

## Changes

- What was changed and why
- Any notable design decisions or trade-offs

## Type of change

- [ ] Bug fix
- [ ] Feature
- [ ] Refactor
- [ ] Documentation
- [ ] Chore/CI

## Affected areas

- [ ] Core (Go)
- [ ] Transports (HTTP)
- [ ] Providers/Integrations
- [ ] Plugins
- [ ] UI (React)
- [ ] Docs

## How to test

Describe the steps to validate this change. Include commands and expected outcomes.

```sh
# Core/Transports
go version
go test ./...

# UI
cd ui
pnpm i || npm i
pnpm test || npm test
pnpm build || npm run build
```

If adding new configs or environment variables, document them here.

## Screenshots/Recordings

If UI changes, add before/after screenshots or short clips.

## Breaking changes

- [ ] Yes
- [ ] No

If yes, describe impact and migration instructions.

## Related issues

Link related issues and discussions. Example: Closes #123

## Security considerations

Note any security implications (auth, secrets, PII, sandboxing, etc.).

## Checklist

- [ ] I read `docs/contributing/README.md` and followed the guidelines
- [ ] I added/updated tests where appropriate
- [ ] I updated documentation where needed
- [ ] I verified builds succeed (Go and UI)
- [ ] I verified the CI pipeline passes locally if applicable
…5759)

## Summary

Closes a race-condition security gap where an unauthenticated network caller could reach a freshly deployed, not-yet-configured Bifrost instance and create the first admin account before the real operator does. Previously, `PUT /api/config` was intentionally open when no admin account existed (zero-config UX), but this left a window of exposure on any publicly reachable host.

The fix introduces a one-time **setup token** — generated in-memory at startup when no admin account is configured, printed to the server's startup logs, and required alongside the username/password when creating the first admin account. The token is never persisted, is regenerated on every restart until an admin account exists, and is permanently invalidated once the first admin account is created.

## Changes

- **Bootstrap token generation (`middlewares.go`):** `InitAuthMiddleware` generates a UUID setup token via `atomic.Pointer[string]` when no admin account is configured, logs it prominently to stdout, and exposes `CheckBootstrapToken` (constant-time comparison) and `ClearBootstrapToken` methods.
- **Token validation in the config handler (`config.go`):** `updateConfig` now calls `ValidateSetupToken` before allowing the first admin account to be created. Returns HTTP 403 if the token is missing or wrong.
- **Token cleared on first admin account creation (`server.go`):** `UpdateAuthConfig` calls `ClearBootstrapToken` after successfully persisting the first admin account, permanently closing the gate.
- **`setup_token`** **field added to** **`UpdateConfigRequest`:** The field is accepted in the request body but never persisted or returned by `GET /api/config`.
- **UI (`securityView.tsx`):** When no `auth_config` exists server-side (`isFirstTimeSetup`), a **Setup token** input field is shown below the password field. The token is validated client-side before submission and cleared from state after a successful save.
- **TypeScript types (`config.ts`):** `setup_token?: string` added to `BifrostConfig`.
- **OpenAPI schema (`config.yaml`):** `setup_token` documented on `UpdateConfigRequest`.
- **Docs:** A `<Warning>` block added to `security-best-practices.mdx` and a `<Note>` added to `setting-up-auth.mdx` explaining the setup token flow, where to find it, and that it only applies once.
- **Tests (`middlewares_test.go`):** Two new test cases cover the no-token-generated (pass-through) case and the validate-then-clear lifecycle.

## Type of change

- [ ] Bug fix
- [x] Feature
- [ ] Refactor
- [ ] Documentation
- [ ] Chore/CI

## Affected areas

- [x] Core (Go)
- [x] Transports (HTTP)
- [ ] Providers/Integrations
- [ ] Plugins
- [x] UI (React)
- [x] Docs

## How to test

**Manual flow:**

1. Start a fresh Bifrost instance with no existing admin account.
2. Check startup logs for the block beginning `No admin account is configured for this Bifrost instance yet.` and copy the setup token.
3. Open the dashboard → Security Settings. Confirm the **Setup token** field appears below the password field.
4. Attempt to save with auth enabled but without the setup token — expect a toast error.
5. Paste the correct token and save — expect success and the Setup token field to disappear on reload.
6. Confirm that `PUT /api/config` without the token returns HTTP 403 while no admin account exists.
7. Restart the server before completing setup and confirm a new token is printed.

```sh
# Core/Transports
go test ./transports/bifrost-http/handlers/...

# UI
cd ui
pnpm i
pnpm build
```

## Breaking changes

- [x] Yes
- [ ] No

Any automation or scripts that call `PUT /api/config` to create the first admin account on a fresh instance must now include `setup_token` in the request body. The token is available in the server's startup logs. Instances that already have an admin account configured are unaffected — the field is ignored once an admin account exists.

## Security considerations

- The setup token is generated with `uuid.NewString()` (crypto-random UUID), stored only in process memory, and compared with `crypto/subtle.ConstantTimeCompare` to prevent timing attacks.
- The token is never written to disk, never returned by any API endpoint, and is permanently invalidated after first use.
- Operators must have access to the process's stdout/log stream (`docker logs`, `kubectl logs`, or terminal) to retrieve the token, which is the same access level required to operate the host — this is the intended trust boundary.

## Checklist

- [x] I read `docs/contributing/README.md` and followed the guidelines
- [x] I added/updated tests where appropriate
- [x] I updated documentation where needed
- [x] I verified builds succeed (Go and UI)
- [ ] I verified the CI pipeline passes locally if applicablecg
## Summary

Briefly explain the purpose of this PR and the problem it solves.

## Changes

- What was changed and why
- Any notable design decisions or trade-offs

## Type of change

- [ ] Bug fix
- [ ] Feature
- [ ] Refactor
- [ ] Documentation
- [ ] Chore/CI

## Affected areas

- [ ] Core (Go)
- [ ] Transports (HTTP)
- [ ] Providers/Integrations
- [ ] Plugins
- [ ] UI (React)
- [ ] Docs

## How to test

Describe the steps to validate this change. Include commands and expected outcomes.

```sh
# Core/Transports
go version
go test ./...

# UI
cd ui
pnpm i || npm i
pnpm test || npm test
pnpm build || npm run build
```

If adding new configs or environment variables, document them here.

## Screenshots/Recordings

If UI changes, add before/after screenshots or short clips.

## Breaking changes

- [ ] Yes
- [ ] No

If yes, describe impact and migration instructions.

## Related issues

Link related issues and discussions. Example: Closes #123

## Security considerations

Note any security implications (auth, secrets, PII, sandboxing, etc.).

## Checklist

- [ ] I read `docs/contributing/README.md` and followed the guidelines
- [ ] I added/updated tests where appropriate
- [ ] I updated documentation where needed
- [ ] I verified builds succeed (Go and UI)
- [ ] I verified the CI pipeline passes locally if applicable
Loading a custom plugin `path` causes native code (a `.so`) to be `dlopen()`'d directly into the gateway process. Previously, this was allowed even when dashboard authentication was disabled or unconfigured — meaning any caller who could reach the management API could inject arbitrary native code. This PR closes that gap by requiring a genuinely authenticated admin session for any create or update operation that sets a non-builtin plugin `path`, and separately hardens the plugin downloader against SSRF.

- Added `BifrostContextKeyAuthBypassed` context key, set by the auth middleware exclusively when a request is let through because dashboard auth is disabled/unconfigured (distinct from `IsLocalAdminContextKey`, which is also set on real authenticated sessions).
- `createPlugin` and `updatePlugin` handlers now check `BifrostContextKeyAuthBypassed` and return `403` before any DB write when a non-builtin `path` is supplied without genuine authentication.
- Replaced the `fasthttp`-based plugin downloader with a `net/http` client backed by `network.SSRFSafeDialContext`, matching the SSRF hardening already applied to `core/providers/utils.FetchAndEncodeURL`. The new client: rejects non-`http`/`https` schemes before any network call, refuses connections to loopback, private, CGNAT, link-local, and unspecified addresses (including IPv4-in-IPv6 transition addresses) at dial time (not just DNS lookup time, so DNS rebinding doesn't bypass it), applies the same IP check to redirect targets, caps redirect depth at 5, and limits response body reads to 200 MB.
- Tests for `DownloadPlugin` now use a `useNonSSRFGuardedClient` helper that swaps in a plain dialer for the duration of each test (since `httptest` servers bind to loopback, which the production dialer correctly blocks). A new `TestDownloadPlugin_BlocksSSRFToLoopback` test verifies the production guard is active by default, and `TestDownloadPlugin_RejectsNonHTTPScheme` verifies `file://` and similar schemes are rejected before any network call.
- New handler tests cover all four cases: create with bypassed auth (expect 403, no DB write), create with real auth (expect 201, path stored), update with bypassed auth (expect 403, no DB write), and the existing config-merge behaviour.
- OpenAPI docs and the plugin sequencing guide updated to document the 403 response and the authentication requirement for `path`.
- Dependency bumps: `aws-sdk-go-v2/config` → v1.32.14, `aws-sdk-go-v2/service/s3` → v1.99.0, `aws-sdk-go-v2/internal/ini` → v1.8.6, `buger/jsonparser` → v1.2.0.

- [ ] Bug fix
- [ ] Feature
- [ ] Refactor
- [ ] Documentation
- [x] Chore/CI

> This is primarily a security hardening change.

- [x] Core (Go)
- [x] Transports (HTTP)
- [ ] Providers/Integrations
- [x] Plugins
- [ ] UI (React)
- [x] Docs

```sh
go test ./...

go test ./transports/bifrost-http/handlers/... -run TestCreatePlugin_RejectsCustomPathWhenAuthBypassed
go test ./transports/bifrost-http/handlers/... -run TestCreatePlugin_AllowsCustomPathWhenNotBypassed
go test ./transports/bifrost-http/handlers/... -run TestUpdatePlugin_RejectsCustomPathWhenAuthBypassed

go test ./framework/plugins/... -run TestDownloadPlugin_BlocksSSRFToLoopback
go test ./framework/plugins/... -run TestDownloadPlugin_RejectsNonHTTPScheme
```

To manually verify the 403 behaviour: start the gateway with no dashboard auth configured, then attempt `POST /api/plugins` with a `path` field pointing to a `.so`. The response should be `403` with a message instructing the operator to enable dashboard authentication first.

- [x] Yes
- [ ] No

Operators running with dashboard authentication disabled who were previously able to create or update custom plugin paths via the API will now receive a `403`. To restore the capability, enable dashboard authentication and authenticate before calling those endpoints.

- Closes an unauthenticated native code injection vector: without this change, any network-reachable caller could `dlopen()` an attacker-controlled `.so` into the gateway process when dashboard auth was off.
- The SSRF fix on the plugin downloader prevents a crafted plugin URL from causing the gateway to fetch from internal/metadata endpoints (e.g. cloud IMDS). The guard runs at dial time, not DNS resolution time, so DNS rebinding attacks do not bypass it.
- `BifrostContextKeyAuthBypassed` is intentionally separate from `IsLocalAdminContextKey` so that future handlers gating other high-risk operations can use the same signal without ambiguity.

- [x] I read `docs/contributing/README.md` and followed the guidelines
- [x] I added/updated tests where appropriate
- [x] I updated documentation where needed
- [x] I verified builds succeed (Go and UI)
- [x] I verified the CI pipeline passes locally if applicable
…5805)

* [fix]: clear stuck entity-assignment validation on virtual key sheet

Eager trigger on assignment-type changes left a refine error on entityType that selecting a team/customer never cleared; also align the assignment controls to items-start.

Co-authored-by: Cursor <cursoragent@cursor.com>

* [docs]: add before/after screenshots for virtual key entity-assignment fix

Co-authored-by: Cursor <cursoragent@cursor.com>

* [docs]: add on-submit validation screenshot for entity-assignment fix

Co-authored-by: Cursor <cursoragent@cursor.com>

* [chore]: remove PR screenshots from .github/assets

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
#5847)

## Summary

Provider-specific model IDs (e.g. Bedrock cross-region inference profiles, dated OpenAI/Anthropic snapshots) were creating separate metric series for what is logically the same model. This PR introduces a `NormalizeModelName` function that strips vendor/region prefixes, Bedrock version suffixes, and trailing date/version segments before model names are used as metric labels, preventing cardinality explosion in Prometheus and OTel metrics.

Additionally, pre-dispatch rejections where both provider and model are empty are now skipped entirely to avoid polluting metric series with empty labels.

## Changes

- Added `NormalizeModelName` in `core/schemas/utils.go` that:
  - Strips Bedrock region and vendor prefixes (e.g. `us.anthropic.`, `anthropic.`) using a regex that only matches letter/hyphen tokens, leaving digit-dotted names like `gpt-3.5-turbo` and `gemini-1.5-pro` untouched
  - Strips Bedrock version suffixes (e.g. `-v1:0`)
  - Delegates to the existing `BaseModelName` to strip trailing date/version segments
  - Preserves OpenAI fine-tune IDs (`ft:...`) as-is
  - Trims surrounding whitespace, collapsing blank input to `""`
- Applied `NormalizeModelName` to the model label in both the Prometheus plugin (`PostLLMHook`) and the OTel plugin (`buildSpanAttrs`, `buildContextAttrs`)
- Added early-return guards in both plugins when provider and model are both empty, skipping metric recording for pre-dispatch rejections
- Added a comprehensive test suite for `NormalizeModelName` covering Bedrock inference profiles, OpenAI dated snapshots, Anthropic dated names, digit-dotted names, fine-tune IDs, whitespace, and empty input

## Type of change

- [x] Bug fix
- [ ] Feature
- [ ] Refactor
- [ ] Documentation
- [ ] Chore/CI

## Affected areas

- [x] Core (Go)
- [ ] Transports (HTTP)
- [ ] Providers/Integrations
- [x] Plugins
- [ ] UI (React)
- [ ] Docs

## How to test

```sh
go test ./core/schemas/... -run TestNormalizeModelName -v
go test ./plugins/otel/...
go test ./plugins/telemetry/...
go test ./...
```

Expected: all tests pass, and metrics emitted for Bedrock inference profile model IDs (e.g. `us.anthropic.claude-opus-4-20250101-v1:0`) use the normalized label `claude-opus-4` rather than the full provider-specific string.

## Breaking changes

- [ ] Yes
- [x] No

## Related issues

## Security considerations

None. This change only affects metric label values and does not touch auth, secrets, or PII handling.

## Checklist

- [ ] I read `docs/contributing/README.md` and followed the guidelines
- [x] I added/updated tests where appropriate
- [ ] I updated documentation where needed
- [x] I verified builds succeed (Go and UI)
- [ ] I verified the CI pipeline passes locally if applicable
## Summary

Adds support for multi-valued team, customer, and business unit identity dimensions in telemetry and metrics. Previously, only a single scalar value per dimension was recorded. This PR introduces a `CanonicalEntitySet` utility that deduplicates, sorts, and comma-joins parallel id/name arrays into stable strings, ensuring the same set of entities always produces the same metric label value regardless of input ordering.

## Changes

- Added `CanonicalEntitySet` in `core/schemas/utils.go` that accepts index-aligned id/name slices, drops empty ids, deduplicates by id (keeping the first name), sorts by id, and returns comma-joined `(idsCSV, namesCSV)` strings.
- Added `canonicalentityset_test.go` covering empty input, single values, sorted/deduped sets, duplicate ids, missing names, and empty id filtering.
- Added `getStringSliceAttr` in the otel plugin to tolerate both `[]string` and `[]any` encodings of array-valued span attributes.
- Added `entitySetFromAttrs` and `entitySetFromContext` helpers in the otel plugin that resolve a dimension from the plural governance arrays when present, falling back to the scalar as a set of one.
- Added `canonicalEntitySet` helper in the telemetry plugin with the same fallback logic for the Prometheus path.
- Extended `BuildBifrostAttributes` to accept and emit `business_unit_id`/`business_unit_name` attributes alongside the existing team and customer dimensions.
- All label names remain singular (`team_id`, `customer_id`, `business_unit_id`) for dashboard backward-compatibility; the values are now canonical comma-joined sets.

## Type of change

- [ ] Bug fix
- [x] Feature
- [ ] Refactor
- [ ] Documentation
- [ ] Chore/CI

## Affected areas

- [x] Core (Go)
- [ ] Transports (HTTP)
- [ ] Providers/Integrations
- [x] Plugins
- [ ] UI (React)
- [ ] Docs

## How to test

```sh
go test ./core/schemas/... -run TestCanonicalEntitySet -v
go test ./plugins/otel/... ./plugins/telemetry/...
go test ./...
```

Verify that a request carrying multiple team ids (e.g. `["t1","t2"]`) produces a `team_id` label of `"t1,t2"` (sorted) in both Prometheus metrics and OTel span attributes, and that a single-team request continues to produce the same label format as before.

## Screenshots/Recordings

N/A

## Breaking changes

- [ ] Yes
- [x] No

The `BuildBifrostAttributes` function signature has changed (two new parameters added for `businessUnitIDs`/`businessUnitNames`, and scalar team/customer args replaced with their CSV equivalents). Any direct callers outside this repo will need to update their call sites.

## Related issues

N/A

## Security considerations

Label values are derived from governance context keys set server-side. No user-supplied PII is introduced beyond what was already present in the scalar team/customer labels.

## Checklist

- [ ] I read `docs/contributing/README.md` and followed the guidelines
- [x] I added/updated tests where appropriate
- [ ] I updated documentation where needed
- [x] I verified builds succeed (Go and UI)
- [ ] I verified the CI pipeline passes locally if applicable
## Summary

Several correctness fixes across model name normalization, OTel metrics alignment, and Prometheus active-request tracking. The common theme is preventing data loss or label pollution caused by edge-case inputs (fine-tune model IDs with date-like suffixes, mixed-type attribute arrays, spans with no provider/model, and pre-dispatch rejections that left active-request counters incremented).

## Changes

- **`NormalizeModelName` fine-tune short-circuit**: OpenAI fine-tune IDs prefixed with `ft:` are now returned immediately before `BaseModelName` is called, preventing a date-like custom suffix (e.g. `custom-20250514`) from being stripped as if it were a Bedrock version tag.
- **`getStringSliceAttr` index preservation**: When a `[]any` attribute value contains non-string elements, the slot is now kept as an empty string rather than being dropped. This keeps id and name arrays index-aligned so that `entitySetFromAttrs` can correctly pair and filter them.
- **OTel span filtering**: Spans with both an empty provider and an empty model are skipped before final-span selection in `recordMetricsFromTrace`, preventing empty-label metric series from being emitted.
- **`serviceInstanceID` as a package-level variable**: The hostname/fallback resolution is now computed once at startup and reused in both the resource attribute and as a `service_instance_id` datapoint label, so per-replica breakdown survives collector configurations that drop resource attributes.
- **Prometheus `ActiveRequests` decrement on pre-dispatch rejection**: `PostLLMHook` now decrements `ActiveRequests` before returning early for no-provider/no-model requests, fixing a counter leak introduced when `PreLLMHook` incremented it.
- **Key rotation event uses normalized model name**: `KeyRotationEventsTotal` now records the normalized `model` value instead of `originalModel`, keeping label values consistent with other metrics.

## Type of change

- [x] Bug fix
- [ ] Feature
- [ ] Refactor
- [ ] Documentation
- [ ] Chore/CI

## Affected areas

- [x] Core (Go)
- [ ] Transports (HTTP)
- [ ] Providers/Integrations
- [x] Plugins
- [ ] UI (React)
- [ ] Docs

## How to test

```sh
go test ./core/schemas/... ./plugins/otel/... ./plugins/telemetry/...
```

- `TestNormalizeModelName` covers the new `ft:gpt-4o-mini:acme:custom-20250514` case.
- `TestGetStringSliceAttr_AnyPreservesIndex` verifies that non-string elements produce an empty string at the correct index.
- `TestEntitySetFromAttrs_MixedAnyKeepsAlignment` verifies that a non-string ID element drops both that ID and its paired name without shifting remaining entries.

## Breaking changes

- [ ] Yes
- [x] No

## Related issues

## Security considerations

None.

## Checklist

- [ ] I read `docs/contributing/README.md` and followed the guidelines
- [x] I added/updated tests where appropriate
- [ ] I updated documentation where needed
- [x] I verified builds succeed (Go and UI)
- [ ] I verified the CI pipeline passes locally if applicable
…cing overrides OpenAPI spec (#5852)

## Summary

Extends the Pricing Overrides API with user-scoped override support, pagination/search on the list endpoint, and a significantly expanded set of priceable fields covering new token tiers, cache variants, image quality/size tiers, and OCR costs.

## Changes

- Introduced a shared `PricingOverrideScopeKind` schema component, replacing inline enum definitions across `PricingOverride`, `CreatePricingOverrideRequest`, `UpdatePricingOverrideRequest`, and the list query parameter. The enum now includes three new `user*` scopes: `user`, `user_provider`, and `user_provider_key`. Resolution priority is documented: `virtual_key*` > `user*` > `provider`/`global`, with more-specific matches winning within a family.
- Added `user_id` field to override request/response schemas and as a query filter on the list endpoint, required when using `user*` scopes.
- Updated `provider_id` and `provider_key_id` descriptions to reflect their applicability to the new `user_provider` and `user_provider_key` scopes.
- Added pagination and search to the list endpoint via `limit`, `offset`, and `search` query parameters. When any of these are present, the response switches to a paginated shape with `total_count`, `limit`, and `offset` fields alongside the existing `count`. The non-paginated path remains backward-compatible.
- Expanded `PricingPatch` with many new pricing fields, organized into logical sections:
  - **Text**: `input/output_cost_per_token_flex`, `input/output_cost_per_token_fast` (Anthropic research preview, flat rate with no tiering)
  - **128k tier**: `input_cost_per_image/video/audio_above_128k_tokens`
  - **200k tier**: priority variants for input and output
  - **272k tier**: standard, priority, and flex variants for input and output
  - **Cache**: flex, priority, fast, and 272k-tier variants; `cache_creation_input_token_cost_above_1hr` and its 200k/fast variants
  - **Image**: `premium_image` combined tiers at 512px and 1024px, `input_cost_per_image_token`
  - **Other**: `inference_geo_us_multiplier` (Anthropic data-residency), `ocr_cost_per_page`, `annotation_cost_per_page`

## Type of change

- [ ] Bug fix
- [x] Feature
- [ ] Refactor
- [ ] Documentation
- [ ] Chore/CI

## Affected areas

- [ ] Core (Go)
- [ ] Transports (HTTP)
- [ ] Providers/Integrations
- [ ] Plugins
- [ ] UI (React)
- [x] Docs

## How to test

Verify the updated OpenAPI spec is valid and that the new fields and parameters appear correctly:

```sh
# Validate the OpenAPI spec
npx @redocly/cli lint docs/openapi/openapi.yaml

# Confirm new scope kinds are present
grep -E "user|user_provider|user_provider_key" docs/openapi/openapi.yaml

# Confirm pagination parameters are present on the list endpoint
grep -E "limit|offset|search" docs/openapi/paths/management/governance.yaml
```

## Breaking changes

- [ ] Yes
- [x] No

The list endpoint response gains new optional fields (`total_count`, `limit`, `offset`) and the non-paginated path continues to behave as before. Existing `scope_kind` enum values are unchanged; new values are additive.

## Related issues

## Security considerations

The new `user_id` scoping field allows pricing overrides to be applied per user. Ensure that `user_id` values are validated against authenticated session context server-side and are not accepted from untrusted input without authorization checks.

## Checklist

- [ ] I read `docs/contributing/README.md` and followed the guidelines
- [ ] I added/updated tests where appropriate
- [x] I updated documentation where needed
- [ ] I verified builds succeed (Go and UI)
- [ ] I verified the CI pipeline passes locally if applicable
… custom pricing docs (#5853)

## Summary

Expands the custom pricing documentation to cover new user-scoped overrides, additional pricing fields (fast-mode, OCR, premium images, extended cache creation/read tiers), and updated API behavior including paginated list responses and a corrected `PUT` verb for updates.

## Changes

- Added three new scope kinds — `user`, `user_provider`, and `user_provider_key` — to the scope hierarchy, table, and field reference, positioned between the virtual-key family and the provider/global scopes
- Clarified scope resolution order: virtual-key family is checked before user family, which is checked before provider/global scopes
- Updated the `scope_kind` enum in the config field reference to include all `user*` variants and added the `user_id` conditional field
- Corrected the update endpoint verb from `PATCH` to `PUT` and added a note that omitted fields are merged from the existing record
- Added pagination support to the list endpoint (`limit`, `offset`, `search` query params) with documentation of the paginated response shape and all supported query filters
- Added new pricing patch fields: `input_cost_per_token_fast`, `output_cost_per_token_fast`, and their cache counterparts (`cache_creation_input_token_cost_fast`, `cache_read_input_token_cost_fast`, `cache_creation_input_token_cost_above_1hr_fast`)
- Added extended cache creation/read tier fields for flex and 272k+ context windows, 1hr+ TTL entries, and 200k+ context with 1hr+ TTL
- Added premium image output cost fields and per-resolution premium image variants
- Added `input_cost_per_image_above_128k_tokens` for image input above 128k context
- Added `inference_geo_us_multiplier` for data-residency cost multipliers
- Added a new OCR costs section covering `ocr_cost_per_page` and `annotation_cost_per_page`

## Type of change

- [ ] Bug fix
- [ ] Feature
- [ ] Refactor
- [x] Documentation
- [ ] Chore/CI

## Affected areas

- [ ] Core (Go)
- [ ] Transports (HTTP)
- [ ] Providers/Integrations
- [ ] Plugins
- [ ] UI (React)
- [x] Docs

## How to test

Review the rendered documentation to confirm:
- The scope hierarchy diagram and table include all three `user*` scope kinds in the correct position
- The update example uses `PUT` and includes the merge-patch note
- The list example shows the paginated query and documents all supported filters
- All new pricing fields appear in their respective sections with accurate descriptions

## Breaking changes

- [ ] Yes
- [x] No

## Security considerations

None. This is a documentation-only change.

## Checklist

- [ ] I read `docs/contributing/README.md` and followed the guidelines
- [ ] I added/updated tests where appropriate
- [x] I updated documentation where needed
- [ ] I verified builds succeed (Go and UI)
- [ ] I verified the CI pipeline passes locally if applicable
…errides (#5854)

## Summary

Adds support for two new image resolution-based pricing tiers — images above 2048×2048 pixels and images above 4096×4096 pixels — to the custom pricing override system.

## Changes

- Added `output_cost_per_image_above_2048_and_2048_pixels` and `output_cost_per_image_above_4096_and_4096_pixels` fields to the `PricingOverridePatch` interface in `governance.ts`
- Exposed these new fields in the pricing override sheet UI under the "image" group, positioned alongside the existing resolution-based pricing fields

## Type of change

- [ ] Bug fix
- [x] Feature
- [ ] Refactor
- [ ] Documentation
- [ ] Chore/CI

## Affected areas

- [ ] Core (Go)
- [ ] Transports (HTTP)
- [ ] Providers/Integrations
- [ ] Plugins
- [x] UI (React)
- [ ] Docs

## How to test

Navigate to the custom pricing overrides sheet for an image-capable model and verify that the new "Output / image (>2048px)" and "Output / image (>4096px)" fields appear in the image pricing section and accept numeric cost values.

```sh
cd ui
pnpm i || npm i
pnpm test || npm test
pnpm build || npm run build
```

## Screenshots/Recordings

Verify the two new fields appear between the existing `>1024px` and `low quality` image pricing fields in the override sheet.

## Breaking changes

- [ ] Yes
- [x] No

## Related issues

## Security considerations

No security implications. These are additive pricing configuration fields with no impact on auth, secrets, or PII.

## Checklist

- [ ] I read `docs/contributing/README.md` and followed the guidelines
- [ ] I added/updated tests where appropriate
- [ ] I updated documentation where needed
- [ ] I verified builds succeed (Go and UI)
- [ ] I verified the CI pipeline passes locally if applicable
## Summary

Resolves merge conflicts in `core/go.sum` that were left over from merging the path normalization auth bypass fix (#5763).

## Changes

- Removed leftover `<<<<<<< HEAD`, `=======`, and `>>>>>>> e0057ff` conflict markers from `core/go.sum`
- Retained the correct `go.mod` hash lines for `aws-sdk-go-v2/config`, `aws-sdk-go-v2/internal/ini`, and `aws-sdk-go-v2/service/s3` that were dropped during the conflict

## Type of change

- [x] Bug fix
- [ ] Feature
- [ ] Refactor
- [ ] Documentation
- [ ] Chore/CI

## Affected areas

- [x] Core (Go)
- [ ] Transports (HTTP)
- [ ] Providers/Integrations
- [ ] Plugins
- [ ] UI (React)
- [ ] Docs

## How to test

```sh
cd core
go mod verify
go test ./...
```

## Breaking changes

- [ ] Yes
- [x] No

## Related issues

Closes #5763

## Security considerations

No security implications. This is a cleanup of unresolved merge conflict markers in the dependency lockfile.

## Checklist

- [ ] I read `docs/contributing/README.md` and followed the guidelines
- [ ] I added/updated tests where appropriate
- [ ] I updated documentation where needed
- [x] I verified builds succeed (Go and UI)
- [ ] I verified the CI pipeline passes locally if applicable
…ntle) (#5867)

## Summary

Fixes detection of GPT-5 series models so that reasoning effort support is correctly identified regardless of where "gpt-5" appears in the model name string (e.g., fine-tuned or versioned variants like `ft:gpt-5-...`).

## Changes

- Replaced `strings.HasPrefix` with `strings.Contains` when checking if a model belongs to the GPT-5 series, allowing model names that include "gpt-5" in positions other than the start to be correctly recognized as reasoning models.

## Type of change

- [x] Bug fix
- [ ] Feature
- [ ] Refactor
- [ ] Documentation
- [ ] Chore/CI

## Affected areas

- [x] Core (Go)
- [ ] Transports (HTTP)
- [x] Providers/Integrations
- [ ] Plugins
- [ ] UI (React)
- [ ] Docs

## How to test

```sh
go test ./core/providers/openai/...
```

Verify that model names such as `ft:gpt-5-mini` or other variants containing "gpt-5" not at the start of the string are correctly identified as reasoning models and have `reasoning.effort` applied.

## Breaking changes

- [ ] Yes
- [x] No

## Related issues

## Security considerations

None.

## Checklist

- [ ] I read `docs/contributing/README.md` and followed the guidelines
- [ ] I added/updated tests where appropriate
- [ ] I updated documentation where needed
- [ ] I verified builds succeed (Go and UI)
- [ ] I verified the CI pipeline passes locally if applicable
…thods (#5462)

The Vertex cached content methods (create/list/retrieve/update/delete) all
authenticate via the shared vertexAuthHeaders helper, which unconditionally
fetched an OAuth token from the key credentials and overwrote the Authorization
header. This mirrors the pre-fix Embedding behaviour and prevents callers from
supplying their own bearer token via context extra headers (e.g. a proxy that
holds short-lived credentials out of band).

Make vertexAuthHeaders take the API-key query-parameter path when the key
carries a value — the same escape hatch the Gemini generation endpoints already
use — leaving any Authorization header set from context extra headers intact.

Signed-off-by: Charlie Gildawie <charlieg@monzo.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Akshay Deo <akshay@akshaydeo.com>
## Summary

Adds a dedicated **MCP Guardrails** section to the guardrails documentation, explaining how guardrails apply at the tool-execution boundary for MCP targets, including phase behavior, UI field descriptions, and provider compatibility notes.

## Changes

- Replaced the brief inline mention of MCP rule behavior in the Architecture section with a cross-reference link to the new dedicated section.
- Added a new `## MCP Guardrails` section covering:
  - How `input`, `output`, and `both` phases apply at the tool-execution boundary.
  - A table describing the flow and block behavior for each phase.
  - Guidance on selecting MCP clients, tools, and tool arguments when creating rules.
  - A note clarifying that all supported guardrail providers work with MCP rules and that redaction support follows the same provider constraints as LLM rules.
  - Cross-references to existing sections for rule configuration and CEL expression examples.
- Added a screenshot (`ui-mcp-guardrail-rule.png`) showing the MCP guardrail rule editor in the UI.

## Type of change

- [ ] Bug fix
- [ ] Feature
- [ ] Refactor
- [x] Documentation
- [ ] Chore/CI

## Affected areas

- [ ] Core (Go)
- [ ] Transports (HTTP)
- [ ] Providers/Integrations
- [ ] Plugins
- [ ] UI (React)
- [x] Docs

## How to test

Navigate to the rendered guardrails documentation page and verify:
- The Architecture section links to `#mcp-guardrails` instead of containing inline MCP text.
- The new MCP Guardrails section renders correctly with the phase table, screenshot, and note.
- The screenshot image loads without errors.

## Screenshots/Recordings

The new section includes a screenshot of the MCP guardrail rule editor (`ui-mcp-guardrail-rule.png`).

## Breaking changes

- [ ] Yes
- [x] No

## Related issues

## Security considerations

None. Documentation-only change.

## Checklist

- [ ] I read `docs/contributing/README.md` and followed the guidelines
- [ ] I added/updated tests where appropriate
- [x] I updated documentation where needed
- [ ] I verified builds succeed (Go and UI)
- [ ] I verified the CI pipeline passes locally if applicable
* feat: send HTTP/2 PING keepalives on the Bedrock provider

When enforce_http2 is set, configure http.HTTP2Config.SendPingTimeout so the
client sends PING frames while a streaming or unary response is idle, keeping
a long-lived connection from being closed by an intermediary idle timeout
(which the AWS EventStream decoder would otherwise surface as an "unexpected
EOF"). The interval is configurable via network_config
http2_keepalive_interval_in_seconds (default 30s).

* fix: expose Bedrock HTTP/2 keepalive interval in Helm values schema

Mirror http2_ping_interval_in_seconds into the chart values.schema.json
networkConfig def so Helm deployments can set it.

* fix: make Bedrock HTTP/2 keepalive ping opt-in (0 = disabled)

There was no HTTP/2 ping keepalive before this change, so the 30s
default-fill was an arbitrary imposition. Treat 0 as disabled (matching
net/http's own SendPingTimeout semantics) and only send pings when a
positive interval is configured, keeping enforce_http2 orthogonal to
keepalive.

* fix: declare http2_ping_interval_in_seconds in UI NetworkConfig types

The TS NetworkConfig interface and its three Zod mirrors (providerForm's
NetworkConfigSchema, and schemas.ts's networkConfigSchema /
networkFormConfigSchema) were missing the field added alongside
enforce_http2 in the Go schema, so a value round-tripped through those
validators would be silently stripped.

* fix: cap http2_ping_interval_in_seconds at 3600s in provider form schema

Matches the sibling stream_idle_timeout_in_seconds / keep_alive_timeout_in_seconds
bounds in the same schema, and the 3600s ceiling already enforced in
ui/lib/types/schemas.ts. Without it, a value above 3600 could pass this
schema but fail the shared one later.

* fix: clamp Bedrock HTTP/2 ping interval to avoid int64 overflow

http2_ping_interval_in_seconds is converted to time.Duration via
* time.Second in the Bedrock transport; a value above ~9.2 billion
seconds overflows int64 silently. Clamp in CheckAndSetDefaults (same
pattern as MaxConnsPerHost) and cap the config.schema.json /
values.schema.json bounds accordingly.

Also extends TestBedrockTransportHTTP2Config to assert transport.HTTP2
across all three enforce_http2 x interval gate combinations, which the
existing test never exercised.

* fix: align http2_ping_interval_in_seconds ceiling with UI and sibling fields

The prior overflow-safety fix (5c45ef3) capped this at the raw int64
overflow boundary (9223372036) in the Go constant and both JSON
schemas, but the UI's three Zod mirrors already capped it at 3600 —
matching the sibling stream_idle_timeout_in_seconds /
keep_alive_timeout_in_seconds fields, which cap at 3600 everywhere
including config.schema.json. Align all six copies on 3600: a config
value between 3601 and 9223372036 passed the backend but would fail
the UI's validation on round-trip.
## Summary

`candidates[0].safetyRatings`, `candidates[0].avgLogprobs`, and the native Gemini `responseId` were silently dropped when a Gemini/Vertex response passed through Bifrost's OpenAI-shaped Responses schema. Because Bifrost's schema has no fields for these values, they need to be round-tripped via `ProviderExtraFields` and restored on egress. This fix covers both the non-streaming (`generateContent`) and streaming (`streamGenerateContent`) paths.

Closes #5843

## Changes

- **`responses.go`** **— non-streaming path**: `ToResponsesBifrostResponsesResponse` now stashes `responseId`, `safetyRatings`, and `avgLogprobs` into `ProviderExtraFields` when converting inbound Gemini responses to Bifrost format. `ToGeminiResponsesResponse` reads them back out and restores them onto the outbound `GenerateContentResponse`.
- **`responses.go`** **— streaming path**: `GeminiResponsesStreamState` gains `SafetyRatings` and `AvgLogprobs` fields. `ToBifrostResponsesStream` captures these from the terminal chunk (the only chunk that carries them, alongside `finishReason`). `closeGeminiOpenItems` writes them into `ProviderExtraFields` on the `response.completed` event. `ToGeminiResponsesStreamResponse` restores them onto the outbound stream chunk.
- **`extractGeminiSafetyRatings`** **/** **`extractGeminiAvgLogprobs`**: Two helper functions handle both the in-memory pointer form (normal path) and the JSON-decoded `[]interface{}`/`map` form that can appear after a JSON round-trip.
- **`gemini_test.go`**: Regression test `TestGenAISafetyRatingsAvgLogprobsResponseIDStreamRoundTrip` covers the non-streaming round-trip, asserting all three fields survive `ToResponsesBifrostResponsesResponse` → `ToGeminiResponsesResponse`.
- **`safetyratingsstream_test.go`**: New test file with `TestGeminiSafetyRatingsAvgLogprobsResponseIDStreamRoundTrip`, which drives a two-chunk stream through the full forward (`ToBifrostResponsesStream`) and reverse (`ToGeminiResponsesStreamResponse`) conversion loop and asserts `safetyRatings`, `avgLogprobs`, and `responseId` are present on the terminal chunk.
- **`SKILL.md`**: The investigate-issue skill now enforces AGENTS.md's "red before green" rule for Bug-classified issues — tests are written and confirmed failing before any fix code is applied, and the todo list ordering reflects this sequence.

## Type of change

- [x] Bug fix

## Affected areas

- [x] Core (Go)
- [x] Providers/Integrations

## How to test

```sh
go test ./core/providers/gemini/... -run TestGenAISafetyRatingsAvgLogprobsResponseIDStreamRoundTrip
go test ./core/providers/gemini/... -run TestGeminiSafetyRatingsAvgLogprobsResponseIDStreamRoundTrip
go test ./core/providers/gemini/...
```

Both new tests should pass. The streaming test validates that `safetyRatings`, `avgLogprobs`, and `responseId` appear on the `response.completed` chunk after a two-chunk stream round-trip. The non-streaming test validates the same fields survive a single `GenerateContentResponse` → Bifrost → `GenerateContentResponse` round-trip.

## Breaking changes

- [x] No

## Related issues

Closes #5843

## Security considerations

None. The change only preserves existing provider-supplied metadata through an internal schema boundary; no new data is introduced or exposed.

## Checklist

- [ ] I read `docs/contributing/README.md` and followed the guidelines
- [x] I added/updated tests where appropriate
- [ ] I updated documentation where needed
- [x] I verified builds succeed (Go and UI)
- [ ] I verified the CI pipeline passes locally if applicable
* [test]: Bedrock provider - cover encrypted reasoning replay

Affected packages:
- core/providers/bedrock/ - add a failing regression test for empty-summary encrypted reasoning replay

* [fix]: Bedrock provider - preserve encrypted reasoning replay

Affected packages:
- core/providers/bedrock/ - map encrypted Responses reasoning to the native Bedrock signature field
- core/ - document the user-facing fix
* feat: support matview_refresh_interval "off" to disable logstore matview maintenance (#5693)

* feat: support matview_refresh_interval "off" to disable logstore matview maintenance

The materialized views back only the dashboard UI. Deployments that run
Bifrost headless behind their own observability stack pay the REFRESH
MATERIALIZED VIEW CONCURRENTLY cost for views nothing reads, and the 5s
floor means the interval alone cannot turn maintenance off.

With "off" (or a non-positive duration) the logs store skips view
creation, the initial refresh, and the periodic refresher entirely.
matViewsReady stays false, so dashboard queries fall back to the raw
tables, and the runtime self-heal path cannot re-arm maintenance since
it only triggers from matview-path queries.

* fix: guard matview self-heal when maintenance is disabled

Review follow-up: carry the resolved disabled state onto the store so
triggerMatViewSelfHeal cannot recreate views the configuration says must
not exist, and make the schema/docs explicit that a zero duration also
disables (positive sub-5s values still clamp up).

* V2.0.0 (#4365)

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->

## Summary by CodeRabbit

* **Bug Fixes**
  * Improved token parameter compatibility handling to preserve alternative formats when the primary option is unsupported.

* **Chores**
  * Version updated to 2.0.0.
  * Enhanced load testing configuration for more reliable builds.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

* gomod fixes (#5731)

## Summary

Briefly explain the purpose of this PR and the problem it solves.

## Changes

- What was changed and why
- Any notable design decisions or trade-offs

## Type of change

- [ ] Bug fix
- [ ] Feature
- [ ] Refactor
- [ ] Documentation
- [ ] Chore/CI

## Affected areas

- [ ] Core (Go)
- [ ] Transports (HTTP)
- [ ] Providers/Integrations
- [ ] Plugins
- [ ] UI (React)
- [ ] Docs

## How to test

Describe the steps to validate this change. Include commands and expected outcomes.

```sh
# Core/Transports
go version
go test ./...

# UI
cd ui
pnpm i || npm i
pnpm test || npm test
pnpm build || npm run build
```

If adding new configs or environment variables, document them here.

## Screenshots/Recordings

If UI changes, add before/after screenshots or short clips.

## Breaking changes

- [ ] Yes
- [ ] No

If yes, describe impact and migration instructions.

## Related issues

Link related issues and discussions. Example: Closes #123

## Security considerations

Note any security implications (auth, secrets, PII, sandboxing, etc.).

## Checklist

- [ ] I read `docs/contributing/README.md` and followed the guidelines
- [ ] I added/updated tests where appropriate
- [ ] I updated documentation where needed
- [ ] I verified builds succeed (Go and UI)
- [ ] I verified the CI pipeline passes locally if applicable

* third party notice (#5735)

## Summary

Adds a `THIRD_PARTY_NOTICES.md` file to formally document third-party components used in Bifrost that carry license terms requiring explicit attribution — specifically MPL-2.0 licensed dependencies and embedded source code derived from external projects.

## Changes

- Introduces `THIRD_PARTY_NOTICES.md` to attribute:
  - Embedded source code in `framework/migrator/migrator.go` derived from `go-gormigrate/gormigrate` (MIT)
  - Go binary dependencies carrying MPL-2.0 terms: `github.com/cyphar/filepath-securejoin` and `github.com/hashicorp/go-version`
  - npm build-time devDependencies carrying MPL-2.0 terms: `lightningcss` (never shipped to end users) and `dompurify` (Apache-2.0 option elected)
- All MPL-2.0 components are used unmodified and combined as a "Larger Work" per MPL-2.0 Section 3.3; no Bifrost source files are themselves MPL-licensed.

## Type of change

- [ ] Bug fix
- [ ] Feature
- [ ] Refactor
- [x] Documentation
- [ ] Chore/CI

## Affected areas

- [ ] Core (Go)
- [ ] Transports (HTTP)
- [ ] Providers/Integrations
- [ ] Plugins
- [ ] UI (React)
- [x] Docs

## How to test

No functional changes — review the file contents to confirm accuracy of license attributions against the listed upstream repositories.

## Breaking changes

- [ ] Yes
- [x] No

## Related issues

N/A

## Security considerations

This change has no security implications. It is a legal/compliance attribution document only.

## Checklist

- [ ] I read `docs/contributing/README.md` and followed the guidelines
- [ ] I added/updated tests where appropriate
- [x] I updated documentation where needed
- [x] I verified builds succeed (Go and UI)
- [ ] I verified the CI pipeline passes locally if applicable

* feat(mcp-guardrails): add MCP log redaction changes (#5744)

## Summary

Briefly explain the purpose of this PR and the problem it solves.

## Changes

- What was changed and why
- Any notable design decisions or trade-offs

## Type of change

- [ ] Bug fix
- [ ] Feature
- [ ] Refactor
- [ ] Documentation
- [ ] Chore/CI

## Affected areas

- [ ] Core (Go)
- [ ] Transports (HTTP)
- [ ] Providers/Integrations
- [ ] Plugins
- [ ] UI (React)
- [ ] Docs

## How to test

Describe the steps to validate this change. Include commands and expected outcomes.

```sh
# Core/Transports
go version
go test ./...

# UI
cd ui
pnpm i || npm i
pnpm test || npm test
pnpm build || npm run build
```

If adding new configs or environment variables, document them here.

## Screenshots/Recordings

If UI changes, add before/after screenshots or short clips.

## Breaking changes

- [ ] Yes
- [ ] No

If yes, describe impact and migration instructions.

## Related issues

Link related issues and discussions. Example: Closes #123

## Security considerations

Note any security implications (auth, secrets, PII, sandboxing, etc.).

## Checklist

- [ ] I read `docs/contributing/README.md` and followed the guidelines
- [ ] I added/updated tests where appropriate
- [ ] I updated documentation where needed
- [ ] I verified builds succeed (Go and UI)
- [ ] I verified the CI pipeline passes locally if applicable

* feat(mcp-guardrails): ui changes (#5745)

## Summary

Briefly explain the purpose of this PR and the problem it solves.

## Changes

- What was changed and why
- Any notable design decisions or trade-offs

## Type of change

- [ ] Bug fix
- [ ] Feature
- [ ] Refactor
- [ ] Documentation
- [ ] Chore/CI

## Affected areas

- [ ] Core (Go)
- [ ] Transports (HTTP)
- [ ] Providers/Integrations
- [ ] Plugins
- [ ] UI (React)
- [ ] Docs

## How to test

Describe the steps to validate this change. Include commands and expected outcomes.

```sh
# Core/Transports
go version
go test ./...

# UI
cd ui
pnpm i || npm i
pnpm test || npm test
pnpm build || npm run build
```

If adding new configs or environment variables, document them here.

## Screenshots/Recordings

If UI changes, add before/after screenshots or short clips.

## Breaking changes

- [ ] Yes
- [ ] No

If yes, describe impact and migration instructions.

## Related issues

Link related issues and discussions. Example: Closes #123

## Security considerations

Note any security implications (auth, secrets, PII, sandboxing, etc.).

## Checklist

- [ ] I read `docs/contributing/README.md` and followed the guidelines
- [ ] I added/updated tests where appropriate
- [ ] I updated documentation where needed
- [ ] I verified builds succeed (Go and UI)
- [ ] I verified the CI pipeline passes locally if applicable

* added plugin logs in mcp logs (#5746)

## Summary

Briefly explain the purpose of this PR and the problem it solves.

## Changes

- What was changed and why
- Any notable design decisions or trade-offs

## Type of change

- [ ] Bug fix
- [ ] Feature
- [ ] Refactor
- [ ] Documentation
- [ ] Chore/CI

## Affected areas

- [ ] Core (Go)
- [ ] Transports (HTTP)
- [ ] Providers/Integrations
- [ ] Plugins
- [ ] UI (React)
- [ ] Docs

## How to test

Describe the steps to validate this change. Include commands and expected outcomes.

```sh
# Core/Transports
go version
go test ./...

# UI
cd ui
pnpm i || npm i
pnpm test || npm test
pnpm build || npm run build
```

If adding new configs or environment variables, document them here.

## Screenshots/Recordings

If UI changes, add before/after screenshots or short clips.

## Breaking changes

- [ ] Yes
- [ ] No

If yes, describe impact and migration instructions.

## Related issues

Link related issues and discussions. Example: Closes #123

## Security considerations

Note any security implications (auth, secrets, PII, sandboxing, etc.).

## Checklist

- [ ] I read `docs/contributing/README.md` and followed the guidelines
- [ ] I added/updated tests where appropriate
- [ ] I updated documentation where needed
- [ ] I verified builds succeed (Go and UI)
- [ ] I verified the CI pipeline passes locally if applicable

* dependabot alert fixes (#5756)

## Summary

Bumps several Go dependencies to their latest patch/minor versions across all modules in the repository.

## Changes

- `github.com/aws/aws-sdk-go-v2/service/s3`: `v1.97.3` → `v1.99.0`
- `github.com/aws/aws-sdk-go-v2/config`: `v1.32.11` → `v1.32.14`
- `github.com/aws/aws-sdk-go-v2/internal/ini`: `v1.8.5` → `v1.8.6`
- `github.com/weaviate/weaviate`: `v1.36.5` → `v1.38.0`
- `github.com/buger/jsonparser`: `v1.1.2` → `v1.2.0`
- `github.com/go-openapi/spec`: `v0.22.2` → `v0.22.3`
- `github.com/google/cel-go`: `v0.28.1` → `v0.29.0`
- `github.com/stretchr/objx`: `v0.5.3` added as an indirect dependency

## Type of change

- [ ] Bug fix
- [ ] Feature
- [ ] Refactor
- [ ] Documentation
- [x] Chore/CI

## Affected areas

- [x] Core (Go)
- [x] Transports (HTTP)
- [ ] Providers/Integrations
- [x] Plugins
- [ ] UI (React)
- [ ] Docs

## How to test

```sh
go test ./...
```

## Breaking changes

- [ ] Yes
- [x] No

## Related issues

## Security considerations

None. All changes are dependency version bumps with no security-sensitive modifications.

## Checklist

- [ ] I read `docs/contributing/README.md` and followed the guidelines
- [ ] I added/updated tests where appropriate
- [ ] I updated documentation where needed
- [ ] I verified builds succeed (Go and UI)
- [ ] I verified the CI pipeline passes locally if applicable

* mcp guardrails : config,helm and docs changes (#5758)

* adds first time setup token to avoid opening new setup to the world (#5759)

## Summary

Closes a race-condition security gap where an unauthenticated network caller could reach a freshly deployed, not-yet-configured Bifrost instance and create the first admin account before the real operator does. Previously, `PUT /api/config` was intentionally open when no admin account existed (zero-config UX), but this left a window of exposure on any publicly reachable host.

The fix introduces a one-time **setup token** — generated in-memory at startup when no admin account is configured, printed to the server's startup logs, and required alongside the username/password when creating the first admin account. The token is never persisted, is regenerated on every restart until an admin account exists, and is permanently invalidated once the first admin account is created.

## Changes

- **Bootstrap token generation (`middlewares.go`):** `InitAuthMiddleware` generates a UUID setup token via `atomic.Pointer[string]` when no admin account is configured, logs it prominently to stdout, and exposes `CheckBootstrapToken` (constant-time comparison) and `ClearBootstrapToken` methods.
- **Token validation in the config handler (`config.go`):** `updateConfig` now calls `ValidateSetupToken` before allowing the first admin account to be created. Returns HTTP 403 if the token is missing or wrong.
- **Token cleared on first admin account creation (`server.go`):** `UpdateAuthConfig` calls `ClearBootstrapToken` after successfully persisting the first admin account, permanently closing the gate.
- **`setup_token`** **field added to** **`UpdateConfigRequest`:** The field is accepted in the request body but never persisted or returned by `GET /api/config`.
- **UI (`securityView.tsx`):** When no `auth_config` exists server-side (`isFirstTimeSetup`), a **Setup token** input field is shown below the password field. The token is validated client-side before submission and cleared from state after a successful save.
- **TypeScript types (`config.ts`):** `setup_token?: string` added to `BifrostConfig`.
- **OpenAPI schema (`config.yaml`):** `setup_token` documented on `UpdateConfigRequest`.
- **Docs:** A `<Warning>` block added to `security-best-practices.mdx` and a `<Note>` added to `setting-up-auth.mdx` explaining the setup token flow, where to find it, and that it only applies once.
- **Tests (`middlewares_test.go`):** Two new test cases cover the no-token-generated (pass-through) case and the validate-then-clear lifecycle.

## Type of change

- [ ] Bug fix
- [x] Feature
- [ ] Refactor
- [ ] Documentation
- [ ] Chore/CI

## Affected areas

- [x] Core (Go)
- [x] Transports (HTTP)
- [ ] Providers/Integrations
- [ ] Plugins
- [x] UI (React)
- [x] Docs

## How to test

**Manual flow:**

1. Start a fresh Bifrost instance with no existing admin account.
2. Check startup logs for the block beginning `No admin account is configured for this Bifrost instance yet.` and copy the setup token.
3. Open the dashboard → Security Settings. Confirm the **Setup token** field appears below the password field.
4. Attempt to save with auth enabled but without the setup token — expect a toast error.
5. Paste the correct token and save — expect success and the Setup token field to disappear on reload.
6. Confirm that `PUT /api/config` without the token returns HTTP 403 while no admin account exists.
7. Restart the server before completing setup and confirm a new token is printed.

```sh
# Core/Transports
go test ./transports/bifrost-http/handlers/...

# UI
cd ui
pnpm i
pnpm build
```

## Breaking changes

- [x] Yes
- [ ] No

Any automation or scripts that call `PUT /api/config` to create the first admin account on a fresh instance must now include `setup_token` in the request body. The token is available in the server's startup logs. Instances that already have an admin account configured are unaffected — the field is ignored once an admin account exists.

## Security considerations

- The setup token is generated with `uuid.NewString()` (crypto-random UUID), stored only in process memory, and compared with `crypto/subtle.ConstantTimeCompare` to prevent timing attacks.
- The token is never written to disk, never returned by any API endpoint, and is permanently invalidated after first use.
- Operators must have access to the process's stdout/log stream (`docker logs`, `kubectl logs`, or terminal) to retrieve the token, which is the same access level required to operate the host — this is the intended trust boundary.

## Checklist

- [x] I read `docs/contributing/README.md` and followed the guidelines
- [x] I added/updated tests where appropriate
- [x] I updated documentation where needed
- [x] I verified builds succeed (Go and UI)
- [ ] I verified the CI pipeline passes locally if applicablecg

* brings back onboarding widget (#5784)

## Summary

Briefly explain the purpose of this PR and the problem it solves.

## Changes

- What was changed and why
- Any notable design decisions or trade-offs

## Type of change

- [ ] Bug fix
- [ ] Feature
- [ ] Refactor
- [ ] Documentation
- [ ] Chore/CI

## Affected areas

- [ ] Core (Go)
- [ ] Transports (HTTP)
- [ ] Providers/Integrations
- [ ] Plugins
- [ ] UI (React)
- [ ] Docs

## How to test

Describe the steps to validate this change. Include commands and expected outcomes.

```sh
# Core/Transports
go version
go test ./...

# UI
cd ui
pnpm i || npm i
pnpm test || npm test
pnpm build || npm run build
```

If adding new configs or environment variables, document them here.

## Screenshots/Recordings

If UI changes, add before/after screenshots or short clips.

## Breaking changes

- [ ] Yes
- [ ] No

If yes, describe impact and migration instructions.

## Related issues

Link related issues and discussions. Example: Closes #123

## Security considerations

Note any security implications (auth, secrets, PII, sandboxing, etc.).

## Checklist

- [ ] I read `docs/contributing/README.md` and followed the guidelines
- [ ] I added/updated tests where appropriate
- [ ] I updated documentation where needed
- [ ] I verified builds succeed (Go and UI)
- [ ] I verified the CI pipeline passes locally if applicable

* path normalization auth bypass (#5763)

## Summary

Loading a custom plugin `path` causes native code (a `.so`) to be `dlopen()`'d directly into the gateway process. Previously, this was allowed even when dashboard authentication was disabled or unconfigured — meaning any caller who could reach the management API could inject arbitrary native code. This PR closes that gap by requiring a genuinely authenticated admin session for any create or update operation that sets a non-builtin plugin `path`, and separately hardens the plugin downloader against SSRF.

## Changes

- Added `BifrostContextKeyAuthBypassed` context key, set by the auth middleware exclusively when a request is let through because dashboard auth is disabled/unconfigured (distinct from `IsLocalAdminContextKey`, which is also set on real authenticated sessions).
- `createPlugin` and `updatePlugin` handlers now check `BifrostContextKeyAuthBypassed` and return `403` before any DB write when a non-builtin `path` is supplied without genuine authentication.
- Replaced the `fasthttp`-based plugin downloader with a `net/http` client backed by `network.SSRFSafeDialContext`, matching the SSRF hardening already applied to `core/providers/utils.FetchAndEncodeURL`. The new client: rejects non-`http`/`https` schemes before any network call, refuses connections to loopback, private, CGNAT, link-local, and unspecified addresses (including IPv4-in-IPv6 transition addresses) at dial time (not just DNS lookup time, so DNS rebinding doesn't bypass it), applies the same IP check to redirect targets, caps redirect depth at 5, and limits response body reads to 200 MB.
- Tests for `DownloadPlugin` now use a `useNonSSRFGuardedClient` helper that swaps in a plain dialer for the duration of each test (since `httptest` servers bind to loopback, which the production dialer correctly blocks). A new `TestDownloadPlugin_BlocksSSRFToLoopback` test verifies the production guard is active by default, and `TestDownloadPlugin_RejectsNonHTTPScheme` verifies `file://` and similar schemes are rejected before any network call.
- New handler tests cover all four cases: create with bypassed auth (expect 403, no DB write), create with real auth (expect 201, path stored), update with bypassed auth (expect 403, no DB write), and the existing config-merge behaviour.
- OpenAPI docs and the plugin sequencing guide updated to document the 403 response and the authentication requirement for `path`.
- Dependency bumps: `aws-sdk-go-v2/config` → v1.32.14, `aws-sdk-go-v2/service/s3` → v1.99.0, `aws-sdk-go-v2/internal/ini` → v1.8.6, `buger/jsonparser` → v1.2.0.

## Type of change

- [ ] Bug fix
- [ ] Feature
- [ ] Refactor
- [ ] Documentation
- [x] Chore/CI

> This is primarily a security hardening change.

## Affected areas

- [x] Core (Go)
- [x] Transports (HTTP)
- [ ] Providers/Integrations
- [x] Plugins
- [ ] UI (React)
- [x] Docs

## How to test

```sh
# Run all tests
go test ./...

# Specifically verify the new plugin handler guards
go test ./transports/bifrost-http/handlers/... -run TestCreatePlugin_RejectsCustomPathWhenAuthBypassed
go test ./transports/bifrost-http/handlers/... -run TestCreatePlugin_AllowsCustomPathWhenNotBypassed
go test ./transports/bifrost-http/handlers/... -run TestUpdatePlugin_RejectsCustomPathWhenAuthBypassed

# Verify SSRF guard on plugin downloader
go test ./framework/plugins/... -run TestDownloadPlugin_BlocksSSRFToLoopback
go test ./framework/plugins/... -run TestDownloadPlugin_RejectsNonHTTPScheme
```

To manually verify the 403 behaviour: start the gateway with no dashboard auth configured, then attempt `POST /api/plugins` with a `path` field pointing to a `.so`. The response should be `403` with a message instructing the operator to enable dashboard authentication first.

## Breaking changes

- [x] Yes
- [ ] No

Operators running with dashboard authentication disabled who were previously able to create or update custom plugin paths via the API will now receive a `403`. To restore the capability, enable dashboard authentication and authenticate before calling those endpoints.

## Security considerations

- Closes an unauthenticated native code injection vector: without this change, any network-reachable caller could `dlopen()` an attacker-controlled `.so` into the gateway process when dashboard auth was off.
- The SSRF fix on the plugin downloader prevents a crafted plugin URL from causing the gateway to fetch from internal/metadata endpoints (e.g. cloud IMDS). The guard runs at dial time, not DNS resolution time, so DNS rebinding attacks do not bypass it.
- `BifrostContextKeyAuthBypassed` is intentionally separate from `IsLocalAdminContextKey` so that future handlers gating other high-risk operations can use the same signal without ambiguity.

## Checklist

- [x] I read `docs/contributing/README.md` and followed the guidelines
- [x] I added/updated tests where appropriate
- [x] I updated documentation where needed
- [x] I verified builds succeed (Go and UI)
- [x] I verified the CI pipeline passes locally if applicable

* go mod fixes (#5789)

## Summary

Briefly explain the purpose of this PR and the problem it solves.

## Changes

- What was changed and why
- Any notable design decisions or trade-offs

## Type of change

- [ ] Bug fix
- [ ] Feature
- [ ] Refactor
- [ ] Documentation
- [ ] Chore/CI

## Affected areas

- [ ] Core (Go)
- [ ] Transports (HTTP)
- [ ] Providers/Integrations
- [ ] Plugins
- [ ] UI (React)
- [ ] Docs

## How to test

Describe the steps to validate this change. Include commands and expected outcomes.

```sh
# Core/Transports
go version
go test ./...

# UI
cd ui
pnpm i || npm i
pnpm test || npm test
pnpm build || npm run build
```

If adding new configs or environment variables, document them here.

## Screenshots/Recordings

If UI changes, add before/after screenshots or short clips.

## Breaking changes

- [ ] Yes
- [ ] No

If yes, describe impact and migration instructions.

## Related issues

Link related issues and discussions. Example: Closes #123

## Security considerations

Note any security implications (auth, secrets, PII, sandboxing, etc.).

## Checklist

- [ ] I read `docs/contributing/README.md` and followed the guidelines
- [ ] I added/updated tests where appropriate
- [ ] I updated documentation where needed
- [ ] I verified builds succeed (Go and UI)
- [ ] I verified the CI pipeline passes locally if applicable

* [fix]: clear stuck entity-assignment validation on virtual key sheet (#5805)

* [fix]: clear stuck entity-assignment validation on virtual key sheet

Eager trigger on assignment-type changes left a refine error on entityType that selecting a team/customer never cleared; also align the assignment controls to items-start.

Co-authored-by: Cursor <cursoragent@cursor.com>

* [docs]: add before/after screenshots for virtual key entity-assignment fix

Co-authored-by: Cursor <cursoragent@cursor.com>

* [docs]: add on-submit validation screenshot for entity-assignment fix

Co-authored-by: Cursor <cursoragent@cursor.com>

* [chore]: remove PR screenshots from .github/assets

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>

* test(anthropic): cover message request extra params

* perf(anthropic): avoid copying known request fields

---------

Signed-off-by: Akshay Deo <akshay@akshaydeo.com>
Co-authored-by: jeremym-tanium <jeremy.maness@tanium.com>
Co-authored-by: Akshay Deo <akshay@akshaydeo.com>
Co-authored-by: Madhu Shantan <madhushantangot@gmail.com>
Co-authored-by: CMWR421 <182079927+CMWR421@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
## Summary

Bumps several transitive dependencies to newer versions to address potential security vulnerabilities and keep lockfiles up to date.

## Changes

- `ip-address` upgraded from `10.2.0` to `10.3.1` in the `temperature` and `test-tools-server` MCP example lockfiles
- `nanoid` upgraded from `3.3.12` to `3.3.16` in the `ui` and TypeScript integration test lockfiles
- `postcss` upgraded from `8.5.15` to `8.5.24` in the `ui` and TypeScript integration test lockfiles
- `golang.org/x/net` upgraded from `v0.33.0` to `v0.55.0` in the `realtime-test` script
- Removed erroneous `"peer": true` flags from several packages in the TypeScript integration test lockfile, correcting their classification as direct or dev dependencies

## Type of change

- [ ] Bug fix
- [ ] Feature
- [ ] Refactor
- [ ] Documentation
- [x] Chore/CI

## Affected areas

- [x] Core (Go)
- [ ] Transports (HTTP)
- [ ] Providers/Integrations
- [ ] Plugins
- [x] UI (React)
- [ ] Docs

## How to test

```sh
# UI
cd ui
npm i
npm run build

# TypeScript integrations
cd tests/integrations/typescript
npm i
npm test
```

## Breaking changes

- [ ] Yes
- [x] No

## Security considerations

`golang.org/x/net` v0.33.0 contained known vulnerabilities. Upgrading to v0.55.0 resolves those. The `nanoid` and `postcss` upgrades similarly address reported issues in the older patch versions.

## Checklist

- [x] I read `docs/contributing/README.md` and followed the guidelines
- [ ] I added/updated tests where appropriate
- [ ] I updated documentation where needed
- [x] I verified builds succeed (Go and UI)
- [ ] I verified the CI pipeline passes locally if applicable
* fix(core): carry tool-result is_error through the chat completions surface

The chat-surface neutral format had no carrier for a failed tool
execution: ChatToolMessage held only tool_call_id, so an Anthropic
tool_result's is_error was dropped on replay (acknowledged in #190), and
the Bedrock Converse converter hard-coded every toolResult to
status "success". The sibling Responses surface already preserves the
marker (via ResponsesToolMessage.Error / status "incomplete", #1580);
this brings the chat surface to parity.

- schemas: add ChatToolMessage.IsError (*bool, is_error, omitempty)
- anthropic: map IsError onto the tool_result block's is_error
- bedrock: derive Converse toolResult status ("error"/"success") from
  IsError instead of hard-coding "success"
- openai, huggingface: strip is_error before serialization — the OpenAI
  wire has no such field and OpenAI-compatible providers reject unknown
  message parameters (same failure class as the Responses-path
  "input[N].error" incident #1580 fixed). Cohere/Gemini/etc. build
  their wire structs by explicit field mapping and need no strip.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EEbNA7pmJy67SgZFsM3Sno

* test(core): cover explicit is_error:false in the tool-message round trip

The round-trip test asserted only is_error:true and the absent case, so an
implementation that collapsed an explicit false into "unspecified" would
still pass. Because IsError is a *bool, false and nil are distinct states
and the converters read them differently — Bedrock folds false into status
"success" (same as nil), Anthropic emits is_error:false on the wire.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* chore(core): add changelog entry for tool-result is_error fix

The contributing guide (docs/contributing/raising-a-pr.mdx) requires a
changelog.md entry for each package a PR modifies, and core/changelog.md
is what .github/workflows/scripts/release-core.sh reads to generate
release notes — without an entry this fix would ship unlisted.

Follows the format used in the file itself (leading dash, bare `fix:`,
author link) rather than the bracketed `[fix]:` form the doc shows; no
existing entry uses brackets.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WLAk8e2G5WLiFMqGafaxVP

* docs(core): document ConvertBifrostMessagesToOpenAIMessages and refresh HF sanitizer doc

The exported OpenAI message converter had no doc comment, which is what put
this PR's docstring coverage at 66.67% against the 80% threshold. Its two
non-obvious behaviours — signature stripping on over-long tool call IDs and
the is_error drop — are now stated, along with the no-mutation guarantee.

sanitizeMessagesForHuggingFace's comment claimed it removed unsupported
ChatAssistantMessage fields; this PR also made it strip ChatToolMessage
is_error, so the comment no longer matched the body.

Comments only, no behaviour change.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WLAk8e2G5WLiFMqGafaxVP

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Added a roots_only filter for log searches to show top-level entries without duplicate fallback children.
    • Root results now include aggregated child count, cost, and token usage.
    • Added support for the roots_only query parameter in HTTP log searches.
  • Bug Fixes

    • Corrected parent relationships for fallback LLM attempts.
    • Prevented self-referencing and filtered-out parent entries from producing incorrect results.

Walkthrough

Adds a roots_only log search filter. Root-only queries exclude matching child rows, promote children with hidden parents, attach child aggregates, and bypass materialized views. HTTP parsing, fallback parent assignment, and SQLite coverage were added.

Changes

Roots-only log search

Layer / File(s) Summary
Search contracts and request wiring
framework/logstore/tables.go, transports/bifrost-http/handlers/logging.go, plugins/logging/main.go
SearchFilters accepts RootsOnly. Log exposes transient child aggregate fields. The HTTP handler parses roots_only, and fallback requests use the primary request as their parent.
Root filtering and aggregation
framework/logstore/rdb.go, framework/logstore/matviews.go
Root-only filtering preserves self-referencing and missing-parent rows, promotes children whose parents are outside the filtered scope, and uses dialect-specific queries. Returned roots include filtered child count, cost, and token totals. Materialized views are excluded.
Roots-only behavior validation
framework/logstore/rdb_rootsonly_test.go
SQLite tests cover root selection, aggregates, self-references, parent filters, scopes, child retrieval, parent promotion, and materialized-view eligibility.

Estimated code review effort: 4 (Complex) | ~45 minutes

Suggested reviewers: akshaydeo, pratham-mishra04

Sequence Diagram(s)

sequenceDiagram
  participant HTTPHandler
  participant RDBLogStore
  participant Database
  HTTPHandler->>RDBLogStore: SearchLogs with RootsOnly
  RDBLogStore->>Database: Apply root filtering
  RDBLogStore->>Database: Load child count, cost, and token aggregates
  Database-->>RDBLogStore: Root rows and aggregates
  RDBLogStore-->>HTTPHandler: Filtered logs with aggregate fields
``

</details>

<!-- walkthrough_end -->
<!-- pre_merge_checks_walkthrough_start -->

<details>
<summary>🚥 Pre-merge checks | ✅ 2 | ❌ 3</summary>

### ❌ Failed checks (3 warnings)

|         Check name         | Status     | Explanation                                                                                                                            | Resolution                                                                                                                            |
| :------------------------: | :--------- | :------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------ |
|      Description check     | ⚠️ Warning | The description contains only the unfilled template and does not document the implementation, testing, affected areas, or decisions.   | Complete the Summary, Changes, Type, Affected areas, How to test, Breaking changes, Related issues, Security, and Checklist sections. |
|     Linked Issues check    | ⚠️ Warning | The PR implements log-chain and roots-only logstore behavior, but issue `#123` requires provider File APIs such as POST /v1/files.       | Implement the File APIs requested in `#123`, or link the correct log-chain issue and update the PR scope.                               |
| Out of Scope Changes check | ⚠️ Warning | All summarized changes concern log chains and roots-only log filtering, which are unrelated to the linked File APIs objective in `#123`. | Remove the unrelated logstore changes, or replace or update the linked issue so the stated objective matches the PR scope.            |

<details>
<summary>✅ Passed checks (2 passed)</summary>

|     Check name     | Status   | Explanation                                                                                                |
| :----------------: | :------- | :--------------------------------------------------------------------------------------------------------- |
|     Title check    | ✅ Passed | The title clearly summarizes the main change: backend log-chain support in the logstore.                   |
| Docstring Coverage | ✅ Passed | No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. |

</details>

</details>

<!-- pre_merge_checks_walkthrough_end -->
<!-- finishing_touch_checkbox_start -->

<details>
<summary>✨ Finishing Touches</summary>

<details>
<summary>📝 Generate docstrings</summary>

- [ ] <!-- {"checkboxId": "7962f53c-55bc-4827-bfbf-6a18da830691"} --> Create stacked PR
- [ ] <!-- {"checkboxId": "3e1879ae-f29b-4d0d-8e06-d12b7ba33d98"} --> Commit on current branch

</details>
<details>
<summary>🧪 Generate unit tests (beta)</summary>

- [ ] <!-- {"checkboxId": "f47ac10b-58cc-4372-a567-0e02b2c3d479", "radioGroupId": "utg-output-choice-group-unknown_comment_id"} -->   Create PR with unit tests
- [ ] <!-- {"checkboxId": "6ba7b810-9dad-11d1-80b4-00c04fd430c8", "radioGroupId": "utg-output-choice-group-unknown_comment_id"} -->   Commit unit tests in branch `07-24-feat_show_logs_chain_backend`

</details>

</details>

<!-- finishing_touch_checkbox_end -->
<!-- tips_start -->

---




<sub>Comment `@coderabbitai help` to get the list of available commands.</sub>

<!-- tips_end -->
Loading

impoiler commented Aug 10, 2026

Copy link
Copy Markdown
Contributor Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

@impoiler impoiler mentioned this pull request Aug 10, 2026
18 tasks
@impoiler
impoiler marked this pull request as ready for review August 10, 2026 07:35
@impoiler impoiler self-assigned this Aug 10, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@framework/logstore/rdb.go`:
- Around line 914-918: Update the aggregate attachment condition around
attachChildAggregates so it runs only when filters.RootsOnly is true and
filters.ParentRequestID is empty. Preserve the existing error propagation and
skip aggregate attachment for ParentRequestID-specific queries.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 456da20e-8948-4485-9c8f-42b4cd7cd052

📥 Commits

Reviewing files that changed from the base of the PR and between c90f9c3 and c1bd494.

📒 Files selected for processing (6)
  • framework/logstore/matviews.go
  • framework/logstore/rdb.go
  • framework/logstore/rdb_rootsonly_test.go
  • framework/logstore/tables.go
  • plugins/logging/main.go
  • transports/bifrost-http/handlers/logging.go

Comment thread framework/logstore/rdb.go
Comment on lines +914 to +918
if filters.RootsOnly {
if err := s.attachChildAggregates(ctx, logs, filters); err != nil {
return nil, err
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Honor ParentRequestID precedence for aggregates.

Line 914 attaches child aggregates when both filters are set. applyFilters correctly ignores RootsOnly when ParentRequestID is non-empty, but this post-query step still changes the response. Only attach aggregates for a roots-only list query without ParentRequestID.

Proposed fix
-if filters.RootsOnly {
+if filters.RootsOnly && filters.ParentRequestID == "" {
 	if err := s.attachChildAggregates(ctx, logs, filters); err != nil {
 		return nil, err
 	}
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if filters.RootsOnly {
if err := s.attachChildAggregates(ctx, logs, filters); err != nil {
return nil, err
}
}
if filters.RootsOnly && filters.ParentRequestID == "" {
if err := s.attachChildAggregates(ctx, logs, filters); err != nil {
return nil, err
}
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@framework/logstore/rdb.go` around lines 914 - 918, Update the aggregate
attachment condition around attachChildAggregates so it runs only when
filters.RootsOnly is true and filters.ParentRequestID is empty. Preserve the
existing error propagation and skip aggregate attachment for
ParentRequestID-specific queries.

@CLAassistant

CLAassistant commented Aug 20, 2026

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
3 out of 4 committers have signed the CLA.

✅ AdityaPainuli
✅ G-XD
✅ impoiler
❌ Pratham-Mishra04
You have signed the CLA already but the status is still pending? Let us recheck it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Files API Support