Skip to content

test: add missing control-plane integration cases - #9

Merged
messagesgoel-blip merged 2 commits into
mainfrom
feat/control-plane-integration-negative-cases
Jul 28, 2026
Merged

test: add missing control-plane integration cases#9
messagesgoel-blip merged 2 commits into
mainfrom
feat/control-plane-integration-negative-cases

Conversation

@messagesgoel-blip

@messagesgoel-blip messagesgoel-blip commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator

Adds missing Control-plane integration scenarios:

  • duplicate submission -> 409
  • invalid signature -> 400
  • unknown issuer -> 400
  • schema validation failure -> 400
  • tenant binding (API key scoping)

Local verification:

@verilink/control-plane@0.1.0 test:integration
node --test --test-concurrency=1 --import tsx src/tests/integration/*.test.ts

▶ Attestation Flow Integration
✔ full attestation lifecycle: submit then list (295.126995ms)
{"level":50,"time":1785246197816,"service":"verilink-control-plane","err":{"type":"AppError","message":"attestation already submitted (duplicate token)","stack":"AppError: attestation already submitted (duplicate token)\n at (/srv/storage/repo/VeriLink/control-plane/src/domains/attestation/attestationService.ts:190:15)\n at process.processTicksAndRejections (node:internal/process/task_queues:104:5)\n at async withTransaction (/srv/storage/repo/VeriLink/control-plane/src/db/transaction.ts:17:20)\n at async Module.submitAttestation (/srv/storage/repo/VeriLink/control-plane/src/domains/attestation/attestationService.ts:186:12)\n at async Object.handler (/srv/storage/repo/VeriLink/control-plane/src/routes/attestations.ts:19:17)\n at async (/srv/storage/repo/VeriLink/control-plane/src/shared/http/defineHandler.ts:61:7)","code":"CONFLICT","status":409,"name":"AppError"},"code":"CONFLICT","msg":"attestation already submitted (duplicate token)"}
✔ duplicate submission returns 409 (191.049635ms)
{"level":50,"time":1785246197978,"service":"verilink-control-plane","err":{"type":"AppError","message":"signature verification failed: no candidate key verified the token","stack":"AppError: signature verification failed: no candidate key verified the token\n at Module.submitAttestation (/srv/storage/repo/VeriLink/control-plane/src/domains/attestation/attestationService.ts:76:11)\n at process.processTicksAndRejections (node:internal/process/task_queues:104:5)\n at async Object.handler (/srv/storage/repo/VeriLink/control-plane/src/routes/attestations.ts:19:17)\n at async (/srv/storage/repo/VeriLink/control-plane/src/shared/http/defineHandler.ts:61:7)","code":"BAD_REQUEST","status":400,"name":"AppError"},"code":"BAD_REQUEST","msg":"signature verification failed: no candidate key verified the token"}
✔ invalid signature rejection returns 400 (160.012702ms)
{"level":50,"time":1785246198140,"service":"verilink-control-plane","err":{"type":"AppError","message":"unknown issuer: vrl:p:87bbbd5a-da3e-4809-acd7-03c06865f2c0","stack":"AppError: unknown issuer: vrl:p:87bbbd5a-da3e-4809-acd7-03c06865f2c0\n at Module.submitAttestation (/srv/storage/repo/VeriLink/control-plane/src/domains/attestation/attestationService.ts:45:11)\n at process.processTicksAndRejections (node:internal/process/task_queues:104:5)\n at async Object.handler (/srv/storage/repo/VeriLink/control-plane/src/routes/attestations.ts:19:17)\n at async (/srv/storage/repo/VeriLink/control-plane/src/shared/http/defineHandler.ts:61:7)","code":"BAD_REQUEST","status":400,"name":"AppError"},"code":"BAD_REQUEST","msg":"unknown issuer: vrl:p:87bbbd5a-da3e-4809-acd7-03c06865f2c0"}
✔ unknown issuer rejection returns 400 (161.202703ms)
{"level":50,"time":1785246198296,"service":"verilink-control-plane","err":{"type":"AppError","message":"schema validation failed: Unknown attestation type: not_a_real_type","stack":"AppError: schema validation failed: Unknown attestation type: not_a_real_type\n at Module.submitAttestation (/srv/storage/repo/VeriLink/control-plane/src/domains/attestation/attestationService.ts:121:13)\n at process.processTicksAndRejections (node:internal/process/task_queues:104:5)\n at async Object.handler (/srv/storage/repo/VeriLink/control-plane/src/routes/attestations.ts:19:17)\n at async (/srv/storage/repo/VeriLink/control-plane/src/shared/http/defineHandler.ts:61:7)","code":"BAD_REQUEST","status":400,"name":"AppError"},"code":"BAD_REQUEST","msg":"schema validation failed: Unknown attestation type: not_a_real_type"}
✔ schema violation rejection returns 400 (156.365381ms)
{"level":50,"time":1785246198442,"service":"verilink-control-plane","err":{"type":"AppError","message":"Missing authentication","stack":"AppError: Missing authentication\n at authMiddleware (/srv/storage/repo/VeriLink/control-plane/src/middleware/auth.ts:55:10)\n at Layer.handle [as handle_request] (/srv/storage/repo/VeriLink/control-plane/node_modules/express/lib/router/layer.js:95:5)\n at trim_prefix (/srv/storage/repo/VeriLink/control-plane/node_modules/express/lib/router/index.js:328:13)\n at /srv/storage/repo/VeriLink/control-plane/node_modules/express/lib/router/index.js:286:9\n at router.process_params (/srv/storage/repo/VeriLink/control-plane/node_modules/express/lib/router/index.js:346:12)\n at next (/srv/storage/repo/VeriLink/control-plane/node_modules/express/lib/router/index.js:280:10)\n at router.handle (/srv/storage/repo/VeriLink/control-plane/node_modules/express/lib/router/index.js:175:3)\n at router (/srv/storage/repo/VeriLink/control-plane/node_modules/express/lib/router/index.js:47:12)\n at Layer.handle [as handle_request] (/srv/storage/repo/VeriLink/control-plane/node_modules/express/lib/router/layer.js:95:5)\n at trim_prefix (/srv/storage/repo/VeriLink/control-plane/node_modules/express/lib/router/index.js:328:13)","code":"UNAUTHORIZED","status":401,"name":"AppError"},"code":"UNAUTHORIZED","msg":"Missing authentication"}
✔ unauthorized request returns 401 (146.175777ms)
{"level":50,"time":1785246198599,"service":"verilink-control-plane","err":{"type":"AppError","message":"Missing required scope: attest:write","stack":"AppError: Missing required scope: attest:write\n at (/srv/storage/repo/VeriLink/control-plane/src/middleware/requireScope.ts:13:21)\n at Layer.handle [as handle_request] (/srv/storage/repo/VeriLink/control-plane/node_modules/express/lib/router/layer.js:95:5)\n at next (/srv/storage/repo/VeriLink/control-plane/node_modules/express/lib/router/route.js:149:13)\n at Route.dispatch (/srv/storage/repo/VeriLink/control-plane/node_modules/express/lib/router/route.js:119:3)\n at Layer.handle [as handle_request] (/srv/storage/repo/VeriLink/control-plane/node_modules/express/lib/router/layer.js:95:5)\n at /srv/storage/repo/VeriLink/control-plane/node_modules/express/lib/router/index.js:284:15\n at router.process_params (/srv/storage/repo/VeriLink/control-plane/node_modules/express/lib/router/index.js:346:12)\n at next (/srv/storage/repo/VeriLink/control-plane/node_modules/express/lib/router/index.js:280:10)\n at authenticateApiKey (/srv/storage/repo/VeriLink/control-plane/src/middleware/auth.ts:96:3)\n at process.processTicksAndRejections (node:internal/process/task_queues:104:5)","code":"FORBIDDEN","status":403,"name":"AppError"},"code":"FORBIDDEN","msg":"Missing required scope: attest:write"}
✔ insufficient scope returns 403 (161.398423ms)
✔ Attestation Flow Integration (1639.5218ms)
▶ Tenant Isolation Integration
✔ cross-tenant visibility: tenant B does not see tenant A participants attestations (297.623756ms)
✔ api-key tenant binding: tenant A cannot see tenant B attestations (210.920723ms)
✔ Tenant Isolation Integration (839.476248ms)
ℹ tests 9
ℹ suites 2
ℹ pass 9
ℹ fail 0
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 3064.128156 (Postgres on 127.0.0.1:15432).

Summary by CodeRabbit

  • Tests
    • Expanded attestation workflow coverage for duplicate submissions, invalid signatures, unknown issuers, and unsupported attestation types.
    • Added tenant-isolation coverage to verify that API keys can access only attestations belonging to their assigned tenant.
    • Added checks for correct error responses and filtered versus unfiltered attestation results.

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

Copy link
Copy Markdown

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

@cursor

cursor Bot commented Jul 28, 2026

Copy link
Copy Markdown

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

@messagesgoel-blip

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 56 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: eb874d50-2dee-4401-b1bb-75d1b7cdd107

📥 Commits

Reviewing files that changed from the base of the PR and between cdbb0fe and 2c17278.

📒 Files selected for processing (1)
  • control-plane/src/__tests__/integration/tenant-isolation.test.ts

Walkthrough

Integration coverage now tests attestation submission failure responses and verifies that API-key-based attestation listings remain isolated between tenants.

Changes

Attestation integration coverage

Layer / File(s) Summary
Submission failure scenarios
control-plane/src/__tests__/integration/attestation-flow.test.ts
Adds tests for duplicate submissions, invalid signatures, unknown issuers, and invalid attestation types with expected HTTP error statuses.
Tenant-scoped attestation listing
control-plane/src/__tests__/integration/tenant-isolation.test.ts
Verifies filtered and unfiltered attestation listings expose only records belonging to the requesting API key’s tenant.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

  • Numeracode/verilink#4: Adds the attestation and tenant-scoped control-plane behavior exercised by these tests.
  • Numeracode/verilink#6: Adds attestation validation and tenant-scoped listing behavior covered by the new integration assertions.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and accurately reflects the main change: adding missing control-plane integration test coverage.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/control-plane-integration-negative-cases

Warning

Review ran into problems

🔥 Problems

Git: Failed to clone repository. Please run the @coderabbitai full review command to re-trigger a full review. If the issue persists, set path_filters to include or exclude specific files.


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

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Add missing control-plane integration scenarios

🧪 Tests 🕐 10-20 Minutes

Grey Divider

AI Description

• Covers duplicate, signature, issuer, and schema rejection responses for attestation submission.
• Verifies API-key tenant scoping for filtered and unfiltered attestation listings.
Diagram

sequenceDiagram
  actor Test as Integration Tests
  participant DB as Test Database
  participant API as Control Plane
  participant Auth as API Key Auth
  participant Svc as Attestation Service
  Test->>DB: Seed tenant fixtures
  Test->>API: Submit or list
  API->>Auth: Validate key and scope
  Auth-->>API: Return tenant identity
  API->>Svc: Process request
  Svc->>DB: Verify and persist or query
  DB-->>Svc: Return scoped result
  alt Valid submission
    Svc-->>API: Created
    API-->>Test: HTTP 201
  else Invalid attestation
    Svc-->>API: Validation error
    API-->>Test: HTTP 400 or 409
  else Cross-tenant listing
    Svc-->>API: Tenant-filtered items
    API-->>Test: HTTP 200 scoped data
  end
Loading
High-Level Assessment

Endpoint-level integration tests are the appropriate approach because these scenarios span authentication, signature verification, schema validation, error translation, persistence, and tenant filtering. Unit-only or mocked tests would not provide equivalent confidence in the complete control-plane behavior.

Files changed (2) +184 / -0

Tests (2) +184 / -0
attestation-flow.test.tsCover attestation submission rejection paths +105/-0

Cover attestation submission rejection paths

• Adds integration scenarios asserting duplicate tokens return 409 and invalid signatures, unknown issuers, and unsupported attestation types return 400. Uses generated issuer identifiers and mismatched signing keys to exercise real verification paths.

control-plane/src/tests/integration/attestation-flow.test.ts

tenant-isolation.test.tsVerify API-key tenant binding across attestation listings +79/-0

Verify API-key tenant binding across attestation listings

• Seeds independent attestations for two tenants and verifies Tenant A's API key cannot retrieve Tenant B's data through an issuer filter. Also confirms an unfiltered request returns only the caller tenant's attestation.

control-plane/src/tests/integration/tenant-isolation.test.ts

@qodo-code-review

qodo-code-review Bot commented Jul 28, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (1) 📜 Skill insights (0)

Context used
✅ Compliance rules (platform): 15 rules

Grey Divider


Informational

1. TypeScript attestation tests added 📘 Rule violation § Compliance
Description
The PR adds attestation and tenant-isolation integration test logic in .ts files rather than Go.
This violates the requirement that all newly added or modified VeriLink source code use Go and the
Go toolchain.
Code

control-plane/src/tests/integration/attestation-flow.test.ts[R92-100]

+  it('duplicate submission returns 409', async () => {
+    const issuer = await seedIssuer(pool, tenantId);
+    const subject = await seedSubject(pool, tenantId);
+    const token = await signAttestationToken({
+      issuerId: issuer.id,
+      subjectId: subject.id,
+      privateKey: issuer.privateKey,
+      keyId: issuer.keyId,
+    });
Relevance

⭐ Low

Exact Go-only compliance finding for TypeScript test logic was rejected in the same integration-test
context.

PR-#7
PR-#6

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
PR Compliance ID 856631 requires all newly added or modified source code to use Go. The cited
regions add executable TypeScript integration test logic using it, await, and TypeScript-based
helpers, including tenant and API-key creation.

Rule 856631: All VeriLink repository source code must be written in Go
control-plane/src/tests/integration/attestation-flow.test.ts[92-194]
control-plane/src/tests/integration/tenant-isolation.test.ts[81-158]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
New attestation and API-key tenant-binding integration test scenarios are implemented in TypeScript, while the compliance rule requires modified repository source code to be written in Go.

## Issue Context
Move these integration tests to the Go test toolchain while preserving coverage for duplicate submissions, invalid signatures, unknown issuers, schema validation, and cross-tenant filtered and unfiltered listing assertions.

## Fix Focus Areas
- control-plane/src/__tests__/integration/attestation-flow.test.ts[92-194]
- control-plane/src/__tests__/integration/tenant-isolation.test.ts[81-158]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

To customize comments, go to the Qodo configuration screen, or learn more in the docs.

Qodo Logo

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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 `@control-plane/src/__tests__/integration/tenant-isolation.test.ts`:
- Around line 151-157: Strengthen the assertions for dataUnfiltered in the
tenant-isolation test by narrowing the item type to expose its issuer or tenant
identity, then verify the returned item belongs to issuerA and does not belong
to issuerB. Keep the existing ok, total, and item-count assertions unchanged.
🪄 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: ASSERTIVE

Plan: Pro

Run ID: e1c223e4-fd26-4740-ab46-6e13b445ca47

📥 Commits

Reviewing files that changed from the base of the PR and between cadc71e and cdbb0fe.

📒 Files selected for processing (2)
  • control-plane/src/__tests__/integration/attestation-flow.test.ts
  • control-plane/src/__tests__/integration/tenant-isolation.test.ts

Comment thread control-plane/src/__tests__/integration/tenant-isolation.test.ts
Co-authored-by: Cursor <cursoragent@cursor.com>
@messagesgoel-blip
messagesgoel-blip merged commit b2f7e2d into main Jul 28, 2026
5 checks passed
@messagesgoel-blip
messagesgoel-blip deleted the feat/control-plane-integration-negative-cases branch July 28, 2026 15:57
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.

1 participant