Skip to content

test: add Postman e2e collection and runner for virtual key expiry validation and enforcement - #4888

Merged
akshaydeo merged 2 commits into
devfrom
07-03-tests_adds_harness_for_vk_expiry
Jul 3, 2026
Merged

test: add Postman e2e collection and runner for virtual key expiry validation and enforcement#4888
akshaydeo merged 2 commits into
devfrom
07-03-tests_adds_harness_for_vk_expiry

Conversation

@Pratham-Mishra04

Copy link
Copy Markdown
Collaborator

Summary

Adds an end-to-end Postman collection and Newman runner script for virtual key expiry functionality. This covers the full lifecycle of expires_at on virtual keys: create/update validation, persistence and retrieval semantics, and runtime enforcement at the governance layer for both inference and MCP tool execution.

Changes

  • Added bifrost-v1-vk-expiry.postman_collection.json with four test groups:
    • Setup: Creates a VK without expiry, discovers connected MCP clients, grants MCP access, and probes candidates to select a working tool for enforcement tests.
    • Create Validation: Asserts that past expiry timestamps are rejected with 400 and a "future" error message, and that future timestamps are accepted and echoed back correctly.
    • Update Semantics: Verifies setting, extending, and clearing expires_at via PUT; confirms that omitting expires_at in an update leaves the existing value unchanged; validates RFC3339 parsing including timezone offsets; and asserts that invalid timestamps return 400 with an RFC3339 error.
    • Enforcement: Confirms unexpired VKs pass governance, expired VKs return 403 with virtual_key_blocked and an "expired" reason, inactive takes precedence over expired in the rejection reason, reactivation alone does not un-expire a key, and clearing or extending expiry restores access. All enforcement checks cover both /v1/chat/completions and /v1/mcp/tool/execute.
    • Teardown: Deletes both VKs created during the run.
  • Added run-newman-vk-expiry-tests.sh to run the collection via Newman with support for --env, --verbose, --html, --json, and --bail flags, provider environment file resolution, and BIFROST_BASE_URL override.

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

# Install Newman if not already installed
npm install -g newman

# Run with the default OpenAI environment
cd tests/e2e/api
bash runners/individual/run-newman-vk-expiry-tests.sh

# Run with a specific provider environment
bash runners/individual/run-newman-vk-expiry-tests.sh --env openai

# Run with HTML and JSON reports
bash runners/individual/run-newman-vk-expiry-tests.sh --env openai --html --json

# Override the base URL
BIFROST_BASE_URL=http://localhost:9090 bash runners/individual/run-newman-vk-expiry-tests.sh

Expected outcome: all tests pass. Enforcement tests that depend on a connected MCP client with a safe probe tool are automatically skipped when no suitable client is available.

Screenshots/Recordings

N/A

Breaking changes

  • Yes
  • No

Related issues

Security considerations

The collection self-provisions and cleans up its own virtual keys. No credentials or secrets are embedded; provider API keys are supplied via the existing Postman environment files.

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

@Pratham-Mishra04
Pratham-Mishra04 requested a review from a team as a code owner July 3, 2026 12:10
@CLAassistant

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 sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

Pratham-Mishra04 commented Jul 3, 2026

Copy link
Copy Markdown
Collaborator Author

@coderabbitai

coderabbitai Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Adds a new Postman e2e collection for virtual-key expiry behavior covering creation validation, update semantics, runtime enforcement, and teardown, plus a companion Bash/Newman runner script that resolves environments, builds globals, executes the collection, and reports results.

Changes

Virtual Key Expiry E2E Tests

Layer / File(s) Summary
Collection metadata and Setup steps
tests/e2e/api/collections/bifrost-v1-vk-expiry.postman_collection.json
Defines collection variables and Setup steps: creates a VK, discovers MCP clients, grants access, and probes for a working tool.
Create Validation tests
tests/e2e/api/collections/bifrost-v1-vk-expiry.postman_collection.json
Tests creation-time expiry validation: rejecting past expiry and persisting future expiry.
Update Semantics tests
tests/e2e/api/collections/bifrost-v1-vk-expiry.postman_collection.json
Tests update-time expiry behavior including setting, extending, clearing, and rejecting invalid expiry values.
Enforcement tests and Teardown
tests/e2e/api/collections/bifrost-v1-vk-expiry.postman_collection.json
Tests runtime enforcement of expiry against inference and MCP execution, deactivation/reactivation interplay, and deletes created VKs in Teardown.
Newman runner script
tests/e2e/api/runners/individual/run-newman-vk-expiry-tests.sh
Adds a Bash script to validate prerequisites, resolve environment files, build Newman globals, and run the collection with reporting.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Newman
  participant BifrostAPI
  participant MCPTool
  Newman->>BifrostAPI: chat completion with unexpired VK
  BifrostAPI-->>Newman: 200 success
  Newman->>MCPTool: execute MCP tool with unexpired VK
  MCPTool-->>Newman: 200 success
  Newman->>BifrostAPI: set short expiry on VK
  Newman->>BifrostAPI: chat completion with expired VK
  BifrostAPI-->>Newman: 403 virtual_key_blocked (expired)
  Newman->>BifrostAPI: extend expiry into future
  Newman->>BifrostAPI: chat completion with extended VK
  BifrostAPI-->>Newman: 200 success
Loading

Suggested reviewers: akshaydeo, danpiths

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly summarizes the main change: adding a Postman e2e collection and runner for virtual key expiry validation.
Description check ✅ Passed The PR description follows the template well with summary, changes, testing, and security sections; only some noncritical fields are lightly filled.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 07-03-tests_adds_harness_for_vk_expiry

Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Confidence Score: 5/5

Safe to merge — adds test infrastructure only, no production code changes.

The change is purely additive test infrastructure. The collection logic is sound: timing relies on an absolute epoch anchor rather than a fixed sleep, teardown is guarded against missing VKs, and all enforcement assertions are backed by concrete HTTP fixtures. The one minor gap (MCP requests firing with an empty tool name instead of being skipped via pm.execution.skipRequest) produces spurious HTTP calls but never causes assertion failures or bail aborts.

No files require special attention.

Important Files Changed

Filename Overview
tests/e2e/api/collections/bifrost-v1-vk-expiry.postman_collection.json Full VK expiry lifecycle collection: Setup, Create Validation, Update Semantics, Enforcement, and Teardown. Logic is sound; timing window upgraded to 5 s expiry + 2 s anchor-based buffer. The three MCP execution requests fire unconditionally when mcp_tool_name is empty (spurious but harmless under bail).
tests/e2e/api/runners/individual/run-newman-vk-expiry-tests.sh Newman runner script with two-phase argument parsing, provider env resolution, BIFROST_BASE_URL override, globals injection from provider-capabilities.json, and HTML/JSON reporter flags. Cleanup trap is correctly scoped. No issues found.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant NW as Newman Runner
    participant API as Bifrost API
    participant GOV as Governance Layer
    participant PROV as Provider

    Note over NW,PROV: Setup
    NW->>API: POST /api/governance/virtual-keys (no expiry)
    API-->>NW: 200 vk_id, vk_value

    Note over NW,PROV: Create Validation
    NW->>API: POST /api/governance/virtual-keys (past expiry)
    API-->>NW: 400 future
    NW->>API: POST /api/governance/virtual-keys (future expiry)
    API-->>NW: 201 vk2_id

    Note over NW,PROV: Enforcement - expired
    NW->>API: PUT virtual-keys expires_at now+5s
    API-->>NW: 2xx
    NW->>NW: wait until epoch+2000ms
    NW->>GOV: POST /v1/chat/completions expired VK
    GOV-->>NW: 403 virtual_key_blocked

    Note over NW,PROV: Teardown
    NW->>API: DELETE virtual-keys vk_id
    API-->>NW: 2xx
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant NW as Newman Runner
    participant API as Bifrost API
    participant GOV as Governance Layer
    participant PROV as Provider

    Note over NW,PROV: Setup
    NW->>API: POST /api/governance/virtual-keys (no expiry)
    API-->>NW: 200 vk_id, vk_value

    Note over NW,PROV: Create Validation
    NW->>API: POST /api/governance/virtual-keys (past expiry)
    API-->>NW: 400 future
    NW->>API: POST /api/governance/virtual-keys (future expiry)
    API-->>NW: 201 vk2_id

    Note over NW,PROV: Enforcement - expired
    NW->>API: PUT virtual-keys expires_at now+5s
    API-->>NW: 2xx
    NW->>NW: wait until epoch+2000ms
    NW->>GOV: POST /v1/chat/completions expired VK
    GOV-->>NW: 403 virtual_key_blocked

    Note over NW,PROV: Teardown
    NW->>API: DELETE virtual-keys vk_id
    API-->>NW: 2xx
Loading

Reviews (2): Last reviewed commit: "tests: adds harness for vk expiry" | Re-trigger Greptile

Comment thread tests/e2e/api/collections/bifrost-v1-vk-expiry.postman_collection.json Outdated

@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 `@tests/e2e/api/collections/bifrost-v1-vk-expiry.postman_collection.json`:
- Around line 1171-1178: The prerequest delay in the Postman collection is a
no-op, so the expiry wait before the 403 checks is unreliable. Update the
prerequest script in the affected collection item to use a
blocking/runner-supported delay instead of setTimeout, and make sure the
subsequent request assertions for the expired virtual key (including the MCP
follow-up) still run after the wait.
🪄 Autofix (Beta)

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: 173f46c3-6236-46d9-9867-3244f07bf0a8

📥 Commits

Reviewing files that changed from the base of the PR and between 21eac0c and cee233a.

📒 Files selected for processing (2)
  • tests/e2e/api/collections/bifrost-v1-vk-expiry.postman_collection.json
  • tests/e2e/api/runners/individual/run-newman-vk-expiry-tests.sh

@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 07-03-tests_adds_harness_for_vk_expiry branch from cee233a to 729e296 Compare July 3, 2026 14:53
@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 07-03-feat_add_expiration_support_to_virtual_keys branch from 21eac0c to 041a823 Compare July 3, 2026 14:53

@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.

🧹 Nitpick comments (2)
tests/e2e/api/runners/individual/run-newman-vk-expiry-tests.sh (2)

195-195: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Minor: prefer find/stat over ls for report listing.

Purely cosmetic output (not parsed), so this is very low priority.

🤖 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 `@tests/e2e/api/runners/individual/run-newman-vk-expiry-tests.sh` at line 195,
The report listing in the Newman expiry test script uses ls, which should be
replaced with find/stat for more robust and predictable output. Update the
report listing logic in the shell script where the current ls -lh pipeline
appears so it enumerates files via find and formats sizes with stat while
preserving the same human-readable, non-parsed output.

Source: Linters/SAST tools


87-91: 🩺 Stability & Availability | 🔵 Trivial | 💤 Low value

Unguarded jq failure could hard-exit under set -e with a confusing error.

If jq fails (e.g., malformed provider-capabilities.json), the script exits immediately without the friendlier error messaging used elsewhere in the script (e.g., Lines 70-74, 77-80).

🛡️ Optional: guard the jq invocation
 if [ -f "$PROVIDER_CAPABILITIES_JSON" ] && command -v jq &>/dev/null; then
     GLOBALS_TMP=$(mktemp)
     trap 'rm -f "$GLOBALS_TMP"' EXIT
-    jq -n --rawfile cap "$PROVIDER_CAPABILITIES_JSON" '{id: "bifrost-provider-capabilities", name: "Provider capabilities", values: [{key: "provider_capabilities", value: $cap, type: "default", enabled: true}]}' > "$GLOBALS_TMP"
+    if ! jq -n --rawfile cap "$PROVIDER_CAPABILITIES_JSON" '{id: "bifrost-provider-capabilities", name: "Provider capabilities", values: [{key: "provider_capabilities", value: $cap, type: "default", enabled: true}]}' > "$GLOBALS_TMP"; then
+        echo -e "${RED}Error: Failed to build globals from $PROVIDER_CAPABILITIES_JSON${NC}"
+        exit 1
+    fi
 fi
🤖 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 `@tests/e2e/api/runners/individual/run-newman-vk-expiry-tests.sh` around lines
87 - 91, The jq invocation in run-newman-vk-expiry-tests.sh is unguarded, so a
malformed provider-capabilities.json can cause an immediate set -e exit without
the script’s usual friendly error handling. Update the existing block around
GLOBALS_TMP and the jq command to check jq’s exit status, then emit a clear
error message consistent with the surrounding setup/validation logic before
exiting; use the same style as the nearby capability-file checks so failures are
easier to diagnose.
🤖 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.

Nitpick comments:
In `@tests/e2e/api/runners/individual/run-newman-vk-expiry-tests.sh`:
- Line 195: The report listing in the Newman expiry test script uses ls, which
should be replaced with find/stat for more robust and predictable output. Update
the report listing logic in the shell script where the current ls -lh pipeline
appears so it enumerates files via find and formats sizes with stat while
preserving the same human-readable, non-parsed output.
- Around line 87-91: The jq invocation in run-newman-vk-expiry-tests.sh is
unguarded, so a malformed provider-capabilities.json can cause an immediate set
-e exit without the script’s usual friendly error handling. Update the existing
block around GLOBALS_TMP and the jq command to check jq’s exit status, then emit
a clear error message consistent with the surrounding setup/validation logic
before exiting; use the same style as the nearby capability-file checks so
failures are easier to diagnose.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: bc6772df-4abc-4b5c-b560-65daafbdf617

📥 Commits

Reviewing files that changed from the base of the PR and between cee233a and 729e296.

📒 Files selected for processing (2)
  • tests/e2e/api/collections/bifrost-v1-vk-expiry.postman_collection.json
  • tests/e2e/api/runners/individual/run-newman-vk-expiry-tests.sh
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/e2e/api/collections/bifrost-v1-vk-expiry.postman_collection.json

coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 3, 2026

akshaydeo commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Merge activity

  • Jul 3, 3:16 PM UTC: A user started a stack merge that includes this pull request via Graphite.
  • Jul 3, 3:18 PM UTC: @akshaydeo merged this pull request with Graphite.

@akshaydeo
akshaydeo changed the base branch from 07-03-feat_add_expiration_support_to_virtual_keys to graphite-base/4888 July 3, 2026 15:17
@akshaydeo
akshaydeo changed the base branch from graphite-base/4888 to dev July 3, 2026 15:17
@akshaydeo
akshaydeo dismissed coderabbitai[bot]’s stale review July 3, 2026 15:17

The base branch was changed.

@akshaydeo
akshaydeo merged commit 4f94fe1 into dev Jul 3, 2026
9 of 11 checks passed
@akshaydeo
akshaydeo deleted the 07-03-tests_adds_harness_for_vk_expiry branch July 3, 2026 15:18
yangtuooc added a commit to yangtuooc/bifrost that referenced this pull request Jul 4, 2026
* 'dev' of https://github.com/maximhq/bifrost:
  ipv6 support (maximhq#4895)
  docs: add virtual key expiry support docs (maximhq#4889)
  test: add Postman e2e collection and runner for virtual key expiry validation and enforcement (maximhq#4888)
  feat: add expiry field to virtual keys (maximhq#4887)
  fix: converts thinking to disabled if tool choice is required for deepseek (maximhq#4861)
  chore: adds docs for deepseek provider (maximhq#4854)
  chore: adds tests for deepseek provider (maximhq#4853)
  feat: adds deepseek provider (maximhq#4852)
  fix: cost for image generation or image edit streaming (maximhq#4802)
  feat: add `BedrockMantleKeyConfig` support to key hashing, schema/table mapping, and sensitive field clearing (maximhq#4886)
  fix: skip O(N) reference refresh on request-time rate-limit/budget reset (maximhq#4883)
  refactor: simplify Responses lifecycle permissions to require explicit per-verb flags and expose them in UI (maximhq#4880)
  fix: append datasheet models for incomplete list models call (maximhq#4879)

# Conflicts:
#	ui/app/workspace/providers/fragments/allowedRequestsFields.tsx
#	ui/app/workspace/virtual-keys/views/virtualKeyDetailsSheet.tsx
#	ui/app/workspace/virtual-keys/views/virtualKeySheet.tsx
#	ui/app/workspace/virtual-keys/views/virtualKeysTable.tsx
#	ui/components/ui/datePickerWithRange.tsx
akhsaul pushed a commit to akhsaul/bifrost that referenced this pull request Aug 27, 2026
…lidation and enforcement (maximhq#4888)

## Summary

Adds an end-to-end Postman collection and Newman runner script for virtual key expiry functionality. This covers the full lifecycle of `expires_at` on virtual keys: create/update validation, persistence and retrieval semantics, and runtime enforcement at the governance layer for both inference and MCP tool execution.

## Changes

- Added `bifrost-v1-vk-expiry.postman_collection.json` with four test groups:
  - **Setup**: Creates a VK without expiry, discovers connected MCP clients, grants MCP access, and probes candidates to select a working tool for enforcement tests.
  - **Create Validation**: Asserts that past expiry timestamps are rejected with 400 and a "future" error message, and that future timestamps are accepted and echoed back correctly.
  - **Update Semantics**: Verifies setting, extending, and clearing `expires_at` via PUT; confirms that omitting `expires_at` in an update leaves the existing value unchanged; validates RFC3339 parsing including timezone offsets; and asserts that invalid timestamps return 400 with an RFC3339 error.
  - **Enforcement**: Confirms unexpired VKs pass governance, expired VKs return 403 with `virtual_key_blocked` and an "expired" reason, inactive takes precedence over expired in the rejection reason, reactivation alone does not un-expire a key, and clearing or extending expiry restores access. All enforcement checks cover both `/v1/chat/completions` and `/v1/mcp/tool/execute`.
  - **Teardown**: Deletes both VKs created during the run.
- Added `run-newman-vk-expiry-tests.sh` to run the collection via Newman with support for `--env`, `--verbose`, `--html`, `--json`, and `--bail` flags, provider environment file resolution, and `BIFROST_BASE_URL` override.

## Type of change

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

## Affected areas

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

## How to test

```sh
# Install Newman if not already installed
npm install -g newman

# Run with the default OpenAI environment
cd tests/e2e/api
bash runners/individual/run-newman-vk-expiry-tests.sh

# Run with a specific provider environment
bash runners/individual/run-newman-vk-expiry-tests.sh --env openai

# Run with HTML and JSON reports
bash runners/individual/run-newman-vk-expiry-tests.sh --env openai --html --json

# Override the base URL
BIFROST_BASE_URL=http://localhost:9090 bash runners/individual/run-newman-vk-expiry-tests.sh
```

Expected outcome: all tests pass. Enforcement tests that depend on a connected MCP client with a safe probe tool are automatically skipped when no suitable client is available.

## Screenshots/Recordings

N/A

## Breaking changes

- [ ] Yes
- [x] No

## Related issues

## Security considerations

The collection self-provisions and cleans up its own virtual keys. No credentials or secrets are embedded; provider API keys are supplied via the existing Postman environment files.

## 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
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.

3 participants