Skip to content

[OPIK-7352] [BE] reject non-UUIDv7 referenced ids on ingest#7553

Merged
thiagohora merged 8 commits into
mainfrom
thiaghora/OPIK-7352-reject-non-v7-foreign-ids
Jul 22, 2026
Merged

[OPIK-7352] [BE] reject non-UUIDv7 referenced ids on ingest#7553
thiagohora merged 8 commits into
mainfrom
thiaghora/OPIK-7352-reject-non-v7-foreign-ids

Conversation

@thiagohora

@thiagohora thiagohora commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Details

Retention sweeps spans/traces via an id-range predicate that assumes the referenced id is a time-ordered UUIDv7 (SpanDAO orders spans by the trace_id range; TraceDAO by the id range). Ingest validated an entity's own id but not the ids it references, so a client could store e.g. a span with a non-UUIDv7 trace_id and have those rows ordered lexicographically instead of chronologically — deleted or retained against the wrong window. This validates referenced ids on ingest.

  • Scope rule: validate a referenced id iff the operation persists it to the entity's table. Ids used only to resolve/locate an existing association (e.g. a projectId on thread open/close, whose project_id was written at trace ingestion) or as a read source (dataset copy-from ids) are not validated.
  • Referenced ids use a not-in-future policy: version 7 required, future-dated rejected, past allowed (referencing an older entity — a late span on an old trace, a score on an old trace — is legitimate and common). Renames validateIdForUpdatevalidateIdNotInFuture and reuses it for both the update paths and referenced ids; adds null-safe validateIdNotInFutureIfPresent(Async) helpers.
  • Validated (each written to a column by its create/update): span traceId/parentSpanId (create, batch, update, batch-update, experiment-items bulk); feedback-score entity ids (single + batch) + sourceQueueId; trace/span/thread comment entity ids; attachment entity ids; guardrail entityId + secondaryId; assertion entityId; dataset-item traceId/spanId + batch datasetId; annotation-queue item ids; experiment projectId/optimizationId/datasetVersionId; and projectId on span/trace update + batch-update, optimization, alert, dashboard, prompt (+ version), annotation-queue, guardrail, assertion, feedback batch, automation-rule evaluators.
  • Version enforcement is always on (mirrors own-id validation); the not-in-future check is gated by the existing uuidValidation kill-switch (off in prod), so this ships dormant beyond the version check.
  • Out of scope / tracked separately: some clients emit v7 UUIDs whose embedded timestamp is far in the future; that pre-existing client-side issue is not remediated here for existing rows.

Change checklist

  • User facing
  • Documentation update

Issues

  • OPIK-7352

AI-WATERMARK

AI-WATERMARK: yes

  • Tools: Claude Code
  • Model(s): Claude Opus 4.8
  • Scope: implementation, prod data verification, and tests
  • Human verification: pending review

Testing

  • mvn -o compile / test-compile / spotless:apply clean.
  • Added SpansResourceTest cases (single and batch create): reject non-v7 traceId (400), reject future-dated traceId (400), reject non-v7 parentSpanId (400), and accept an old (past) v7 traceId (spans on old traces are valid). These exercise the shared validateIdNotInFuture mechanism used by every path here.
  • Resource integration tests do not run locally (ClickHouse healthcheck bootstrap quirk) — relying on CI.
  • Verified via read-only production queries that existing rows carry no non-v7 referenced ids on the validated paths, so enforcement rejects no legitimate existing data.
  • Follow-up: dedicated per-path tests for the non-span validated paths (they share the span-tested mechanism).

Documentation

No user-facing docs. The referenced-id validation policy (version 7 + not-in-future, past allowed) is documented in the IdGenerator javadoc.

thiagohora and others added 2 commits July 21, 2026 16:00
Retention sweeps spans/traces via an id-range predicate that assumes the
referenced id is a time-ordered UUIDv7 (SpanDAO orders by the trace_id
range; TraceDAO by the id range). Ingest validated an entity's own id but
not the ids it references, so a client could store a span with a
non-UUIDv7 trace_id and have those rows ordered lexicographically instead
of chronologically — deleted or retained against the wrong window.

Validate referenced ids on ingest with a not-in-future policy (version 7
required, future-dated rejected, past allowed — referencing older
entities such as late spans on old traces is legitimate). Renames
validateIdForUpdate -> validateIdNotInFuture and reuses it for both the
update paths and referenced ids; adds a public sync overload.

Covered paths: span traceId/parentSpanId (create, batch, update,
batch-update, and the experiment-items bulk path via batch create); single
and batch feedback-score entity ids; trace/span/thread comment entity ids;
attachment entity ids; dataset-item trace/span ids (batch, patch,
from-traces, from-spans); annotation-queue item ids.

Version enforcement is always on (mirrors own-id validation); the
not-in-future check is gated by the existing uuidValidation kill-switch.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Extends referenced-id validation to config-entity references (verify-then-
enforce: confirmed zero non-UUIDv7 ids across prod projects, datasets,
dataset_versions, prompts, prompt_versions, alerts, dashboards, webhooks,
automation_rules, and guardrails, so enforcement rejects no existing data).

Adds null-safe validateIdNotInFutureIfPresent(Async) helpers and validates:
projectId across span/trace update + batch-update, feedback scores (single
+ batch), guardrails, assertion results, annotation queues, experiments,
optimizations, alerts, automation-rule evaluators, prompts + prompt
versions, dashboards, and thread open/close; feedback/guardrail
sourceQueueId; guardrail secondaryId; experiment optimizationId +
datasetVersionId; dataset-item datasetId + copy-from ids. Upgrades the
guardrail/assertion referenced entityId from version-only to the shared
not-in-future policy.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@thiagohora
thiagohora requested a review from a team as a code owner July 21, 2026 14:30
@github-actions github-actions Bot added java Pull requests that update Java code Backend tests Including test files, or tests related like configuration. 🟡 size/M labels Jul 21, 2026
@github-actions

github-actions Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

⏱️ pre-commit per-hook timing

Hook Description Result Duration
☕ spotless — java backend Format Java code 7.93s
Total (1 ran) 7.93s
⏭️ 40 skipped (no matching files changed)
Hook Description Result
🐍 trim trailing whitespace — python sdk Strip trailing whitespace ⏭️
🐍 fix end of files — python sdk Ensure files end in a newline ⏭️
🐍 ruff — python sdk Lint + autofix Python (ruff) ⏭️
🐍 ruff-format — python sdk Format Python code (ruff) ⏭️
🐍 mypy — python sdk Static type check ⏭️
🤖 trim trailing whitespace — optimizer Strip trailing whitespace ⏭️
🤖 fix end of files — optimizer Ensure files end in a newline ⏭️
🤖 check yaml — optimizer Validate YAML syntax ⏭️
🤖 check json — optimizer Validate JSON syntax ⏭️
🤖 check toml — optimizer Validate TOML syntax ⏭️
🤖 check for added large files — optimizer Block large files (>1MB) ⏭️
🔐 detect private key — optimizer Block committed private keys ⏭️
🤖 check for merge conflicts — optimizer Block merge-conflict markers ⏭️
🤖 check for case conflicts — optimizer Block case-only name clashes ⏭️
🤖 pyupgrade — optimizer Modernize Python syntax ⏭️
🤖 ruff — optimizer Lint + autofix Python (ruff) ⏭️
🤖 ruff-format — optimizer Format Python code (ruff) ⏭️
🤖 mypy — optimizer Static type check ⏭️
📓 nbstripout — optimizer notebooks Strip notebook output ⏭️
📝 markdownlint — optimizer Lint Markdown ⏭️
🔤 codespell — optimizer Fix common misspellings ⏭️
📊 radon cc — optimizer Cyclomatic-complexity gate ⏭️
📊 radon raw — optimizer Raw size metrics gate ⏭️
📊 xenon — optimizer Fail on complexity thresholds ⏭️
📊 lizard — optimizer Cyclomatic-complexity gate ⏭️
🧹 vulture — optimizer Find dead code ⏭️
🛡️ trim trailing whitespace — guardrails Strip trailing whitespace ⏭️
🛡️ fix end of files — guardrails Ensure files end in a newline ⏭️
🛡️ ruff — guardrails Lint + autofix Python (ruff) ⏭️
🛡️ ruff-format — guardrails Format Python code (ruff) ⏭️
🛡️ mypy — guardrails Static type check ⏭️
⚓ helm-docs Regenerate Helm chart README ⏭️
block non-public FE plugins Block non-public FE plugins ⏭️
🧪 pre-commit wrapper smoke tests Self-test the wrapper scripts ⏭️
🌐 eslint — frontend Lint + autofix JS/TS ⏭️
🌐 typecheck — frontend Whole-project tsc type check ⏭️
📘 eslint — typescript sdk Lint + autofix JS/TS ⏭️
📘 typecheck — typescript sdk Whole-project tsc type check ⏭️
⚙️ actionlint — github workflows Lint GitHub Actions workflows ⏭️
🐳 hadolint — dockerfiles Lint Dockerfiles ⏭️

@github-actions

github-actions Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Backend Tests - Integration Group 6

184 tests  +9   181 ✅ +9   3m 22s ⏱️ -6s
 40 suites +5     3 💤 ±0 
 40 files   +5     0 ❌ ±0 

Results for commit 7df5573. ± Comparison against base commit 4dc6b0c.

This pull request removes 10 and adds 19 tests. Note that renamed tests count towards both.
com.comet.opik.api.resources.v1.priv.PromptResourceProjectScopedPromptsTest ‑ createPromptWithExistingProjectName
com.comet.opik.api.resources.v1.priv.PromptResourceProjectScopedPromptsTest ‑ createPromptWithNonExistingProjectId
com.comet.opik.api.resources.v1.priv.PromptResourceProjectScopedPromptsTest ‑ createPromptWithNonExistingProjectName
com.comet.opik.api.resources.v1.priv.PromptResourceProjectScopedPromptsTest ‑ createPromptWithProjectId
com.comet.opik.api.resources.v1.priv.PromptResourceProjectScopedPromptsTest ‑ findPromptsByProjectId
com.comet.opik.domain.DeletionEventTest ‑ deleteBatchTracesCapturesDeletionEvents(boolean)[1]
com.comet.opik.domain.DeletionEventTest ‑ deleteBatchTracesCapturesDeletionEvents(boolean)[2]
com.comet.opik.domain.DeletionEventTest ‑ deleteTraceCapturesDeletionEvent
com.comet.opik.domain.DeletionEventTest ‑ deleteTraceThreadsCapturesDeletionEvents
com.comet.opik.domain.OptimizationProjectMigrationJobTest ‑ scheduledJobMigratesOrphanOptimizationViaExperiments
com.comet.opik.api.resources.v1.priv.InsightsViewsResourceTest$CreateInsightsView ‑ createInsightsViewForcesScope
com.comet.opik.api.resources.v1.priv.InsightsViewsResourceTest$CreateInsightsView ‑ createInsightsViewWithDefaultType
com.comet.opik.api.resources.v1.priv.InsightsViewsResourceTest$DeleteInsightsView ‑ batchDeleteInsightsViews
com.comet.opik.api.resources.v1.priv.InsightsViewsResourceTest$DeleteInsightsView ‑ deleteInsightsView
com.comet.opik.api.resources.v1.priv.InsightsViewsResourceTest$DeleteInsightsView ‑ deleteInsightsViewDoesNotAffectDashboard
com.comet.opik.api.resources.v1.priv.InsightsViewsResourceTest$FindInsightsViews ‑ findInsightsViewsOnlyReturnsInsightsScope
com.comet.opik.api.resources.v1.priv.InsightsViewsResourceTest$GetInsightsView ‑ getInsightsViewById
com.comet.opik.api.resources.v1.priv.InsightsViewsResourceTest$GetInsightsView ‑ getInsightsViewReturns404ForDashboard
com.comet.opik.api.resources.v1.priv.InsightsViewsResourceTest$UpdateInsightsView ‑ updateInsightsViewName
com.comet.opik.api.resources.v1.priv.InsightsViewsResourceTest$UpdateInsightsView ‑ updateInsightsViewReturns404ForDashboard
…

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Backend Tests - Integration Group 12

297 tests   - 4   297 ✅  - 4   6m 2s ⏱️ -1s
 48 suites +1     0 💤 ±0 
 48 files   +1     0 ❌ ±0 

Results for commit f1e48d3. ± Comparison against base commit 4dc6b0c.

This pull request removes 51 and adds 47 tests. Note that renamed tests count towards both.
com.comet.opik.api.resources.v1.events.OnlineScoringSpanSamplerIntegrationTest ‑ redisProducerAndConsumerBaseFlowForSpans(Source, OnlineScoringSpanSampler)[1]
com.comet.opik.api.resources.v1.events.OnlineScoringSpanSamplerIntegrationTest ‑ redisProducerAndConsumerBaseFlowForSpans(Source, OnlineScoringSpanSampler)[2]
com.comet.opik.api.resources.v1.priv.RecentActivityResourceTest$GetRecentActivity ‑ doesNotReturnActivityFromOtherProjects
com.comet.opik.api.resources.v1.priv.RecentActivityResourceTest$GetRecentActivity ‑ returnsAllEntityTypesSortedByDate
com.comet.opik.api.resources.v1.priv.RecentActivityResourceTest$GetRecentActivity ‑ returnsEmptyForNewProject
com.comet.opik.api.resources.v1.priv.RecentActivityResourceTest$RequiredPermissionsTest ‑ passesRequiredPermissionsToAuthEndpoint
com.comet.opik.api.resources.v1.priv.RecentActivityResourceTest$RequiredPermissionsTest ‑ returnsForbiddenWhenPermissionDenied
com.comet.opik.domain.LocalRunnerReaperIntegrationTest$ReapDeadRunners ‑ cleansRunnerJobsSetOnReap
com.comet.opik.domain.LocalRunnerReaperIntegrationTest$ReapDeadRunners ‑ failsOrphanedActiveJobs
com.comet.opik.domain.LocalRunnerReaperIntegrationTest$ReapDeadRunners ‑ failsOrphanedPendingJobs
…
com.comet.opik.api.resources.v1.internal.UsageResourceTest$Usage ‑ datasetBiInfoTest
com.comet.opik.api.resources.v1.internal.UsageResourceTest$Usage ‑ experimentBiInfoTest
com.comet.opik.api.resources.v1.internal.UsageResourceTest$Usage ‑ mixedWorkspaceExcludesDemoData
com.comet.opik.api.resources.v1.internal.UsageResourceTest$Usage ‑ spanBiInfoTest
com.comet.opik.api.resources.v1.internal.UsageResourceTest$Usage ‑ spanBreakdownForWorkspace
com.comet.opik.api.resources.v1.internal.UsageResourceTest$Usage ‑ spansCountExcludingDemoData
com.comet.opik.api.resources.v1.internal.UsageResourceTest$Usage ‑ spansCountForWorkspace
com.comet.opik.api.resources.v1.internal.UsageResourceTest$Usage ‑ spansCountIncludesPostCutoffActivityInDemoProjects
com.comet.opik.api.resources.v1.internal.UsageResourceTest$Usage ‑ traceBiInfoTest
com.comet.opik.api.resources.v1.internal.UsageResourceTest$Usage ‑ tracesCountExcludingDemoData
…

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Backend Tests - Integration Group 13

325 tests   - 17   323 ✅  - 17   4m 37s ⏱️ - 1m 1s
 43 suites  -  3     2 💤 ± 0 
 43 files    -  3     0 ❌ ± 0 

Results for commit f1e48d3. ± Comparison against base commit 4dc6b0c.

This pull request removes 39 and adds 22 tests. Note that renamed tests count towards both.
com.comet.opik.api.resources.v1.internal.AnalyticsQueriesResourceTest ‑ executeQuery__whenBoundToWorkspaceProject__thenReturnsOnlyThatScope
com.comet.opik.api.resources.v1.internal.AnalyticsQueriesResourceTest ‑ executeQuery__whenInvalid__thenBadRequest(String, String)[1]
com.comet.opik.api.resources.v1.internal.AnalyticsQueriesResourceTest ‑ executeQuery__whenInvalid__thenBadRequest(String, String)[2]
com.comet.opik.api.resources.v1.internal.AnalyticsQueriesResourceTest ‑ executeQuery__whenInvalid__thenBadRequest(String, String)[3]
com.comet.opik.api.resources.v1.internal.AnalyticsQueriesResourceTest ‑ executeQuery__whenInvalid__thenBadRequest(String, String)[4]
com.comet.opik.api.resources.v1.internal.AnalyticsQueriesResourceTest ‑ executeQuery__whenInvalid__thenBadRequest(String, String)[5]
com.comet.opik.api.resources.v1.internal.AnalyticsQueriesResourceTest ‑ executeQuery__whenInvalid__thenBadRequest(String, String)[6]
com.comet.opik.api.resources.v1.internal.AnalyticsQueriesResourceTest ‑ executeQuery__whenInvalid__thenBadRequest(String, String)[7]
com.comet.opik.api.resources.v1.internal.AnalyticsQueriesResourceTest ‑ executeQuery__whenInvalid__thenBadRequest(String, String)[8]
com.comet.opik.api.resources.v1.internal.AnalyticsQueriesResourceTest ‑ executeQuery__whenInvalid__thenBadRequest(String, String)[9]
…
com.comet.opik.api.resources.v1.jobs.ProjectLastUpdatedFlushJobTest ‑ jobFlushesBufferedMarkerToProject
com.comet.opik.api.resources.v1.priv.AssertionResultsResourceTest ‑ multiProjectBatchResolvesIndependently
com.comet.opik.api.resources.v1.priv.AssertionResultsResourceTest ‑ nonV7EntityIdIsRejected
com.comet.opik.api.resources.v1.priv.AssertionResultsResourceTest ‑ traceAssertionsArePersistedAndRetrievableViaExperimentItems
com.comet.opik.api.resources.v1.priv.AssertionResultsResourceTest ‑ unsupportedEntityTypeIsRejected(EntityType)[1]
com.comet.opik.api.resources.v1.priv.AttachmentResourceTest ‑ directS3DownloadShouldFailTest
com.comet.opik.api.resources.v1.priv.AttachmentResourceTest ‑ directS3UploadShouldFailTest
com.comet.opik.api.resources.v1.priv.AttachmentResourceTest ‑ uploadAttachmentWithMultiPartPresignUrl
com.comet.opik.api.resources.v1.priv.DatasetExperimentE2ETest$FilterDatasetsByExperimentWith ‑ when__filteringByDatasetsWithExperimentsAfterAnExperimentIsDeleted__thenShouldReturnTheDatasetWithExperiments
com.comet.opik.api.resources.v1.priv.DatasetExperimentE2ETest$FilterDatasetsByExperimentWith ‑ when__filteringByDatasetsWithExperimentsAfterDeletingExperimentsButDatasetHasMore__thenShouldReturnTheDatasetWithExperiments
…

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Backend Tests - Integration Group 8

370 tests  +1   368 ✅  - 1   5m 16s ⏱️ - 2m 33s
 31 suites ±0     2 💤 +2 
 31 files   ±0     0 ❌ ±0 

Results for commit f1e48d3. ± Comparison against base commit 4dc6b0c.

This pull request removes 70 and adds 71 tests. Note that renamed tests count towards both.
com.comet.opik.api.resources.v1.priv.DatasetsJsonUploadResourceTest ‑ uploadEmptyFile__rejected
com.comet.opik.api.resources.v1.priv.DatasetsJsonUploadResourceTest ‑ uploadEmptyJsonArray__rejected
com.comet.opik.api.resources.v1.priv.DatasetsJsonUploadResourceTest ‑ uploadGarbageAsJson__rejected
com.comet.opik.api.resources.v1.priv.DatasetsJsonUploadResourceTest ‑ uploadGarbageAsJsonl__rejected
com.comet.opik.api.resources.v1.priv.DatasetsJsonUploadResourceTest ‑ uploadJsonArray__invalidId__failsAsync
com.comet.opik.api.resources.v1.priv.DatasetsJsonUploadResourceTest ‑ uploadJsonArray__lowercaseFormat__accepted
com.comet.opik.api.resources.v1.priv.DatasetsJsonUploadResourceTest ‑ uploadJsonArray__nonObjectElement__failsAsync
com.comet.opik.api.resources.v1.priv.DatasetsJsonUploadResourceTest ‑ uploadJsonArray__preservesJsonTypes
com.comet.opik.api.resources.v1.priv.DatasetsJsonUploadResourceTest ‑ uploadJsonArray__reservedFieldsRouted
com.comet.opik.api.resources.v1.priv.DatasetsJsonUploadResourceTest ‑ uploadJsonArray__withBom
…
com.comet.opik.api.resources.v1.events.webhooks.AlertBucketServiceTest ‑ addEventToBucket__whenAddingToSameAlertAfterConfigChange__shouldUseOriginalWindow
com.comet.opik.api.resources.v1.events.webhooks.AlertBucketServiceTest ‑ addEventToBucket__whenConfigChanges__shouldCreateSeparateBucketsWithDifferentWindows
com.comet.opik.api.resources.v1.events.webhooks.AlertBucketServiceTest ‑ addEventToBucket__whenFirstEvent__shouldSetTtl
com.comet.opik.api.resources.v1.events.webhooks.AlertBucketServiceTest ‑ addEventToBucket__whenFirstEvent__shouldStoreWindowSizeFirstSeenAndWorkspaceId
com.comet.opik.api.resources.v1.events.webhooks.AlertBucketServiceTest ‑ addEventToBucket__whenSubsequentEvents__shouldNotRefreshTtl
com.comet.opik.api.resources.v1.events.webhooks.AlertBucketServiceTest ‑ addEventToBucket__whenSubsequentEvents__shouldPreserveOriginalWindowSize
com.comet.opik.api.resources.v1.events.webhooks.AlertBucketServiceTest ‑ deleteBucket__shouldRemoveBucketFromRedis
com.comet.opik.api.resources.v1.events.webhooks.AlertBucketServiceTest ‑ getBucketData__shouldReturnAllEventIdsAndPayloads
com.comet.opik.api.resources.v1.events.webhooks.AlertBucketServiceTest ‑ getBucketsReadyToProcess__afterConfigChange__shouldUseStoredWindowSizes
com.comet.opik.api.resources.v1.internal.AnalyticsQueriesResourceTest ‑ executeQuery__whenBoundToWorkspaceProject__thenReturnsOnlyThatScope
…

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Backend Tests - Integration Group 16

212 tests  +13   212 ✅ +13   5m 34s ⏱️ - 1m 51s
 26 suites ± 0     0 💤 ± 0 
 26 files   ± 0     0 ❌ ± 0 

Results for commit f1e48d3. ± Comparison against base commit 4dc6b0c.

This pull request removes 17 and adds 30 tests. Note that renamed tests count towards both.
com.comet.opik.api.resources.v1.priv.AttachmentResourceMinIOTest ‑ deleteTraceDeletesTraceAndSpanAttachments(Consumer)[1]
com.comet.opik.api.resources.v1.priv.AttachmentResourceMinIOTest ‑ deleteTraceDeletesTraceAndSpanAttachments(Consumer)[2]
com.comet.opik.api.resources.v1.priv.AttachmentResourceMinIOTest ‑ invalidBaseUrlFormatReturnsError
com.comet.opik.api.resources.v1.priv.AttachmentResourceMinIOTest ‑ uploadAttachmentWithMultiPartPresignUrl
com.comet.opik.api.resources.v1.priv.LlmProviderApiKeyResourceBuiltinProviderTest ‑ testBatchDelete_ignoresBuiltinProvider
com.comet.opik.api.resources.v1.priv.LlmProviderApiKeyResourceBuiltinProviderTest ‑ testFindProviders_builtinProviderHasCorrectConfiguration
com.comet.opik.api.resources.v1.priv.LlmProviderApiKeyResourceBuiltinProviderTest ‑ testFindProviders_builtinProviderHasReadOnlyTrue
com.comet.opik.api.resources.v1.priv.LlmProviderApiKeyResourceBuiltinProviderTest ‑ testFindProviders_builtinProviderIsAddedAtEnd
com.comet.opik.api.resources.v1.priv.LlmProviderApiKeyResourceBuiltinProviderTest ‑ testFindProviders_includesVirtualBuiltinProvider_whenEnabled
com.comet.opik.api.resources.v1.priv.LlmProviderApiKeyResourceBuiltinProviderTest ‑ testFindProviders_userProvidersHaveReadOnlyFalse
…
com.comet.opik.api.resources.v1.events.WebhookSubscriberLoggingTest ‑ processEvent_whenSuccessfulWebhook_shouldSendRequestAndCreateLogs
com.comet.opik.api.resources.v1.events.WebhookSubscriberLoggingTest ‑ processEvent_whenWebhookFails_shouldRetryAndCreateErrorLogs
com.comet.opik.api.resources.v1.priv.DashboardsResourceFindProjectDashboardsTest ‑ findProjectDashboardsByNameSearch
com.comet.opik.api.resources.v1.priv.DashboardsResourceFindProjectDashboardsTest ‑ findProjectDashboardsNoFiltersReturnsAll
com.comet.opik.api.resources.v1.priv.DashboardsResourceFindProjectDashboardsTest ‑ findProjectDashboardsWithDefaultParameters
com.comet.opik.api.resources.v1.priv.DashboardsResourceFindProjectDashboardsTest ‑ findProjectDashboardsWithEmptyResult
com.comet.opik.api.resources.v1.priv.DashboardsResourceFindProjectDashboardsTest ‑ findProjectDashboardsWithFilters(Function, Function)[1]
com.comet.opik.api.resources.v1.priv.DashboardsResourceFindProjectDashboardsTest ‑ findProjectDashboardsWithFilters(Function, Function)[2]
com.comet.opik.api.resources.v1.priv.DashboardsResourceFindProjectDashboardsTest ‑ findProjectDashboardsWithFilters(Function, Function)[3]
com.comet.opik.api.resources.v1.priv.DashboardsResourceFindProjectDashboardsTest ‑ findProjectDashboardsWithPagination
…

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Backend Tests - Integration Group 7

1 584 tests   - 7   1 584 ✅  - 7   6m 57s ⏱️ -20s
   14 suites  - 5       0 💤 ±0 
   14 files    - 5       0 ❌ ±0 

Results for commit f1e48d3. ± Comparison against base commit 4dc6b0c.

This pull request removes 19 and adds 12 tests. Note that renamed tests count towards both.
com.comet.opik.api.resources.v1.priv.InsightsViewsResourceTest$CreateInsightsView ‑ createInsightsViewForcesScope
com.comet.opik.api.resources.v1.priv.InsightsViewsResourceTest$CreateInsightsView ‑ createInsightsViewWithDefaultType
com.comet.opik.api.resources.v1.priv.InsightsViewsResourceTest$DeleteInsightsView ‑ batchDeleteInsightsViews
com.comet.opik.api.resources.v1.priv.InsightsViewsResourceTest$DeleteInsightsView ‑ deleteInsightsView
com.comet.opik.api.resources.v1.priv.InsightsViewsResourceTest$DeleteInsightsView ‑ deleteInsightsViewDoesNotAffectDashboard
com.comet.opik.api.resources.v1.priv.InsightsViewsResourceTest$FindInsightsViews ‑ findInsightsViewsOnlyReturnsInsightsScope
com.comet.opik.api.resources.v1.priv.InsightsViewsResourceTest$GetInsightsView ‑ getInsightsViewById
com.comet.opik.api.resources.v1.priv.InsightsViewsResourceTest$GetInsightsView ‑ getInsightsViewReturns404ForDashboard
com.comet.opik.api.resources.v1.priv.InsightsViewsResourceTest$UpdateInsightsView ‑ updateInsightsViewName
com.comet.opik.api.resources.v1.priv.InsightsViewsResourceTest$UpdateInsightsView ‑ updateInsightsViewReturns404ForDashboard
…
com.comet.opik.api.resources.v1.priv.GuardrailsResourceTest ‑ getTraceStats_containsGuardrails
com.comet.opik.api.resources.v1.priv.GuardrailsResourceTest ‑ testCreateGuardrails_findTraces
com.comet.opik.api.resources.v1.priv.GuardrailsResourceTest ‑ testCreateGuardrails_getTraceById
com.comet.opik.api.resources.v1.priv.PromptResourceProjectScopedPromptsTest ‑ createPromptWithExistingProjectName
com.comet.opik.api.resources.v1.priv.PromptResourceProjectScopedPromptsTest ‑ createPromptWithNonExistingProjectId
com.comet.opik.api.resources.v1.priv.PromptResourceProjectScopedPromptsTest ‑ createPromptWithNonExistingProjectName
com.comet.opik.api.resources.v1.priv.PromptResourceProjectScopedPromptsTest ‑ createPromptWithProjectId
com.comet.opik.api.resources.v1.priv.PromptResourceProjectScopedPromptsTest ‑ findPromptsByProjectId
com.comet.opik.domain.DeletionEventTest ‑ deleteBatchTracesCapturesDeletionEvents(boolean)[1]
com.comet.opik.domain.DeletionEventTest ‑ deleteBatchTracesCapturesDeletionEvents(boolean)[2]
…

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Backend Tests - Integration Group 1

426 tests  ±0   426 ✅ ±0   10m 32s ⏱️ -42s
 25 suites ±0     0 💤 ±0 
 25 files   ±0     0 ❌ ±0 

Results for commit 7a47cac. ± Comparison against base commit 4dc6b0c.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Backend Tests - Integration Group 14

650 tests  ±0   650 ✅ ±0   7m 5s ⏱️ -10s
 22 suites +2     0 💤 ±0 
 22 files   +2     0 ❌ ±0 

Results for commit f1e48d3. ± Comparison against base commit 4dc6b0c.

This pull request removes 41 and adds 41 tests. Note that renamed tests count towards both.
com.comet.opik.api.resources.v1.priv.OllieStateResourceTest ‑ deleteSucceedsWhenNoState
com.comet.opik.api.resources.v1.priv.OllieStateResourceTest ‑ downloadReturns404WhenNoState
com.comet.opik.api.resources.v1.priv.OllieStateResourceTest ‑ uploadDownloadDeleteOllieState
com.comet.opik.api.resources.v1.priv.OllieStateResourceTest ‑ uploadRejectsNonGzipData
com.comet.opik.api.resources.v1.priv.OllieStateResourceTest ‑ uploadReplacesExistingState
com.comet.opik.domain.AlertProjectMigrationServiceTest ‑ allProjectsDeletedAlertAssignedToDefault
com.comet.opik.domain.AlertProjectMigrationServiceTest ‑ envExcludedWorkspacesAreNotMigrated
com.comet.opik.domain.AlertProjectMigrationServiceTest ‑ malformedScopeProjectIdTreatedAsWorkspaceWide
com.comet.opik.domain.AlertProjectMigrationServiceTest ‑ missingDefaultProjectIsAutoCreatedDuringMigration
com.comet.opik.domain.AlertProjectMigrationServiceTest ‑ multiProjectAlertSplitByProject
…
com.comet.opik.api.resources.v1.events.OnlineScoringSpanSamplerIntegrationTest ‑ redisProducerAndConsumerBaseFlowForSpans(Source, OnlineScoringSpanSampler)[1]
com.comet.opik.api.resources.v1.events.OnlineScoringSpanSamplerIntegrationTest ‑ redisProducerAndConsumerBaseFlowForSpans(Source, OnlineScoringSpanSampler)[2]
com.comet.opik.api.resources.v1.priv.DashboardsResourceProjectScopedTest ‑ createDashboardWithExistingProjectName
com.comet.opik.api.resources.v1.priv.DashboardsResourceProjectScopedTest ‑ createDashboardWithNonExistingProjectId
com.comet.opik.api.resources.v1.priv.DashboardsResourceProjectScopedTest ‑ createDashboardWithNonExistingProjectName
com.comet.opik.api.resources.v1.priv.DashboardsResourceProjectScopedTest ‑ createDashboardWithProjectId
com.comet.opik.api.resources.v1.priv.DashboardsResourceProjectScopedTest ‑ findDashboardsByProjectId
com.comet.opik.api.resources.v1.priv.DatasetsJsonUploadResourceTest ‑ uploadEmptyFile__rejected
com.comet.opik.api.resources.v1.priv.DatasetsJsonUploadResourceTest ‑ uploadEmptyJsonArray__rejected
com.comet.opik.api.resources.v1.priv.DatasetsJsonUploadResourceTest ‑ uploadGarbageAsJson__rejected
…

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Backend Tests - Integration Group 2

282 tests  ±0   282 ✅ ±0   13m 27s ⏱️ -22s
 20 suites ±0     0 💤 ±0 
 20 files   ±0     0 ❌ ±0 

Results for commit 7df5573. ± Comparison against base commit 4dc6b0c.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Backend Tests - Integration Group 11

 39 files  + 1   39 suites  +1   7m 56s ⏱️ -33s
306 tests  - 10  306 ✅  - 10  0 💤 ±0  0 ❌ ±0 
268 runs   - 48  268 ✅  - 48  0 💤 ±0  0 ❌ ±0 

Results for commit 7df5573. ± Comparison against base commit 4dc6b0c.

This pull request removes 15 and adds 5 tests. Note that renamed tests count towards both.
com.comet.opik.api.resources.v1.internal.UsageResourceTest$Usage ‑ datasetBiInfoTest
com.comet.opik.api.resources.v1.internal.UsageResourceTest$Usage ‑ experimentBiInfoTest
com.comet.opik.api.resources.v1.internal.UsageResourceTest$Usage ‑ mixedWorkspaceExcludesDemoData
com.comet.opik.api.resources.v1.internal.UsageResourceTest$Usage ‑ spanBiInfoTest
com.comet.opik.api.resources.v1.internal.UsageResourceTest$Usage ‑ spanBreakdownForWorkspace
com.comet.opik.api.resources.v1.internal.UsageResourceTest$Usage ‑ spansCountExcludingDemoData
com.comet.opik.api.resources.v1.internal.UsageResourceTest$Usage ‑ spansCountForWorkspace
com.comet.opik.api.resources.v1.internal.UsageResourceTest$Usage ‑ spansCountIncludesPostCutoffActivityInDemoProjects
com.comet.opik.api.resources.v1.internal.UsageResourceTest$Usage ‑ traceBiInfoTest
com.comet.opik.api.resources.v1.internal.UsageResourceTest$Usage ‑ tracesCountExcludingDemoData
…
com.comet.opik.domain.OptimizationProjectMigrationJobTest ‑ scheduledJobMigratesOrphanOptimizationViaExperiments
com.comet.opik.infrastructure.bi.DailyUsageReportJobTest$CredentialsEnabledScenario ‑ test
com.comet.opik.infrastructure.bi.DailyUsageReportJobTest$NoCredentialsEnabledScenario ‑ dailyUsageReportExcludesDemoData
com.comet.opik.infrastructure.bi.DailyUsageReportJobTest$NoCredentialsEnabledScenario ‑ dailyUsageReportMixedDataExcludesOnlyDemo
com.comet.opik.infrastructure.bi.DailyUsageReportJobTest$NoCredentialsEnabledScenario ‑ test

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Backend Tests - Integration Group 9

520 tests  +16   519 ✅ +16   10m 25s ⏱️ -29s
 40 suites  -  1     1 💤 ± 0 
 40 files    -  1     0 ❌ ± 0 

Results for commit 7df5573. ± Comparison against base commit 4dc6b0c.

This pull request removes 17 and adds 33 tests. Note that renamed tests count towards both.
com.comet.opik.api.resources.v1.priv.AttachmentResourceTest ‑ directS3DownloadShouldFailTest
com.comet.opik.api.resources.v1.priv.AttachmentResourceTest ‑ directS3UploadShouldFailTest
com.comet.opik.api.resources.v1.priv.AttachmentResourceTest ‑ uploadAttachmentWithMultiPartPresignUrl
com.comet.opik.api.resources.v1.priv.DashboardsResourceProjectScopedTest ‑ createDashboardWithExistingProjectName
com.comet.opik.api.resources.v1.priv.DashboardsResourceProjectScopedTest ‑ createDashboardWithNonExistingProjectId
com.comet.opik.api.resources.v1.priv.DashboardsResourceProjectScopedTest ‑ createDashboardWithNonExistingProjectName
com.comet.opik.api.resources.v1.priv.DashboardsResourceProjectScopedTest ‑ createDashboardWithProjectId
com.comet.opik.api.resources.v1.priv.DashboardsResourceProjectScopedTest ‑ findDashboardsByProjectId
com.comet.opik.api.resources.v1.priv.ProjectOptimizationsResourceTest$RequiredPermissionsTest ‑ findOptimizationsByProjectPassesRequiredPermissionsToAuthEndpoint
com.comet.opik.api.resources.v1.priv.ProjectOptimizationsResourceTest$RequiredPermissionsTest ‑ findOptimizationsByProjectReturnsForbiddenWhenPermissionDenied
…
com.comet.opik.api.resources.v1.priv.AssertionResultsResourceTest ‑ multiProjectBatchResolvesIndependently
com.comet.opik.api.resources.v1.priv.AssertionResultsResourceTest ‑ nonV7EntityIdIsRejected
com.comet.opik.api.resources.v1.priv.AssertionResultsResourceTest ‑ traceAssertionsArePersistedAndRetrievableViaExperimentItems
com.comet.opik.api.resources.v1.priv.AssertionResultsResourceTest ‑ unsupportedEntityTypeIsRejected(EntityType)[1]
com.comet.opik.api.resources.v1.priv.AuthenticationResourceTest$ApiKey ‑ checkAccessForDefaultWorkspace__whenApiKeyIsPresent__thenReturnProperResponse(String, int, String)[1]
com.comet.opik.api.resources.v1.priv.AuthenticationResourceTest$ApiKey ‑ checkAccessForDefaultWorkspace__whenApiKeyIsPresent__thenReturnProperResponse(String, int, String)[2]
com.comet.opik.api.resources.v1.priv.AuthenticationResourceTest$ApiKey ‑ checkAccessForDefaultWorkspace__whenApiKeyIsPresent__thenReturnProperResponse(String, int, String)[3]
com.comet.opik.api.resources.v1.priv.AuthenticationResourceTest$ApiKey ‑ checkAccess__whenApiKeyIsPresent__thenReturnProperResponse(String, int, String)[1]
com.comet.opik.api.resources.v1.priv.AuthenticationResourceTest$ApiKey ‑ checkAccess__whenApiKeyIsPresent__thenReturnProperResponse(String, int, String)[2]
com.comet.opik.api.resources.v1.priv.AuthenticationResourceTest$ApiKey ‑ checkAccess__whenApiKeyIsPresent__thenReturnProperResponse(String, int, String)[3]
…

♻️ This comment has been updated with latest results.

Comment thread apps/opik-backend/src/main/java/com/comet/opik/domain/AssertionResultService.java Outdated
Comment thread apps/opik-backend/src/main/java/com/comet/opik/domain/SpanService.java Outdated
@github-actions

github-actions Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Backend Tests - Integration Group 4

1 823 tests  +21   1 823 ✅ +21   9m 18s ⏱️ +2s
   19 suites + 2       0 💤 ± 0 
   19 files   + 2       0 ❌ ± 0 

Results for commit f1e48d3. ± Comparison against base commit 4dc6b0c.

This pull request removes 49 and adds 70 tests. Note that renamed tests count towards both.
com.comet.opik.api.resources.v1.events.DatasetEventListenerTest ‑ when__newOptimizationIsCreated__shouldBeSavedInTheDatabase
com.comet.opik.api.resources.v1.events.DatasetEventListenerTest ‑ when__optimizationIsDeleted__lastCreatedOptimizationDateShouldBeUpdated_
com.comet.opik.api.resources.v1.events.DatasetEventListenerTest$CreateExperimentEvent ‑ when__newExperimentIsCreated__shouldBeSavedInTheDatabase
com.comet.opik.api.resources.v1.events.DatasetEventListenerTest$DeleteExperimentEvent ‑ when__experimentIsDeleted__lastCreatedExperimentDateShouldBeUpdated
com.comet.opik.api.resources.v1.events.DatasetEventListenerTest$DeleteExperimentEvent ‑ when__experimentIsDeleted__lastCreatedExperimentDateShouldBeUpdated_
com.comet.opik.api.resources.v1.events.TraceThreadOnlineScoringSamplerListenerIntegrationTest ‑ processesThreadsWithSdkOrNullSource(Source, TraceThreadOnlineScoringSamplerListener)[1]
com.comet.opik.api.resources.v1.events.TraceThreadOnlineScoringSamplerListenerIntegrationTest ‑ processesThreadsWithSdkOrNullSource(Source, TraceThreadOnlineScoringSamplerListener)[2]
com.comet.opik.api.resources.v1.events.TraceThreadOnlineScoringSamplerListenerIntegrationTest ‑ skipsNonSdkThreads(Source, TraceThreadOnlineScoringSamplerListener)[1]
com.comet.opik.api.resources.v1.events.TraceThreadOnlineScoringSamplerListenerIntegrationTest ‑ skipsNonSdkThreads(Source, TraceThreadOnlineScoringSamplerListener)[2]
com.comet.opik.api.resources.v1.events.TraceThreadOnlineScoringSamplerListenerIntegrationTest ‑ skipsNonSdkThreads(Source, TraceThreadOnlineScoringSamplerListener)[3]
…
com.comet.opik.api.resources.v1.priv.AgentInsightsJobsResourceTest ‑ create__firstThenConflict
com.comet.opik.api.resources.v1.priv.AgentInsightsJobsResourceTest ‑ create__projectMissing__returns404
com.comet.opik.api.resources.v1.priv.AgentInsightsJobsResourceTest ‑ cronSweep__triggersJobsWithTraces
com.comet.opik.api.resources.v1.priv.AgentInsightsJobsResourceTest ‑ get__afterCreateAndWhenAbsent
com.comet.opik.api.resources.v1.priv.AgentInsightsJobsResourceTest ‑ reportFailure__createAndRead
com.comet.opik.api.resources.v1.priv.AgentInsightsJobsResourceTest ‑ reportFailure__invalidBody__returns422(String, ReportFailure)[1]
com.comet.opik.api.resources.v1.priv.AgentInsightsJobsResourceTest ‑ reportFailure__invalidBody__returns422(String, ReportFailure)[2]
com.comet.opik.api.resources.v1.priv.AgentInsightsJobsResourceTest ‑ reportFailure__invalidBody__returns422(String, ReportFailure)[3]
com.comet.opik.api.resources.v1.priv.AgentInsightsJobsResourceTest ‑ reportFailure__unsupportedType__returns400
com.comet.opik.api.resources.v1.priv.AgentInsightsJobsResourceTest ‑ runFailure__multipleFailures__latestSurfaced
…

♻️ This comment has been updated with latest results.

thiagohora and others added 3 commits July 21, 2026 17:10
Refine scope to the rule: validate a referenced id iff the operation
persists it to the entity's table. Drop validation where the id is not
written by the operation:

- Thread open/close: projectId only resolves/locates an already-existing
  thread (its project_id was written at trace ingestion), so nothing is
  persisted here.
- Dataset item batch copy-from ids: only a read source for carry-forward
  rows, never stored as version lineage.

All create/update paths that write the referenced id to a column keep their
validation (spans trace_id/parent_span_id, feedback/comment/attachment/
guardrail/assertion entity ids, dataset-item trace/span + dataset ids,
annotation-queue items, and projectId/optimizationId/datasetVersionId/
sourceQueueId on the rows that store them).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Existing tests assigned random v4 UUIDs to referenced ids that are now
validated as UUIDv7 (guardrail secondaryId, experiment optimizationId /
datasetVersionId). Switch that test data to generator.generate() so the
tests exercise the intended paths (the invalid-version conflict test now
uses a v7-but-nonexistent id, preserving its 409 expectation).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…d; fix test data

Address reviewer + CI findings:

- Remove projectId validation in GuardrailsService and AssertionResultService:
  both resolve the project by name and overwrite projectId with the resolved
  project.id() before persistence, so the client-supplied projectId is never
  stored — validating it only breaks clients that send arbitrary project ids.
- Fix remaining test data to use current UUIDv7 (never v4 or future-dated) for
  validated referenced ids: span traceId, dataset-item trace/span ids,
  annotation-queue item ids, feedback sourceQueueId, alert projectId,
  automation-rule projectIds, experiment optimizationId. 404/409 negative
  tests use a v7-but-nonexistent id to preserve their intent.
- Strengthen createWithOldTraceIdSucceeds to round-trip and assert the old
  traceId is persisted verbatim; add a batch non-v7 parentSpanId rejection test.

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

Addresses reviewer findings:

- create(SpanBatch) validated traceId/parentSpanId inside bindSpanToProjectAndId,
  which runs AFTER deleteAutoStrippedAttachments + project getOrCreate — so a bad
  batch could delete attachments / create projects before failing 400. Move the id
  checks up front (before any side effect) so a rejected batch never mutates state.
- Extract a shared validateSpanReferences(traceId, parentSpanId) helper used by every
  span write path (single/batch create, single/batch update) so the reference-id
  rules can't drift between them.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
andrescrz
andrescrz previously approved these changes Jul 22, 2026

@andrescrz andrescrz left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Some comments, but no blockers.

Comment thread apps/opik-backend/src/main/java/com/comet/opik/domain/IdGenerator.java Outdated
Comment thread apps/opik-backend/src/main/java/com/comet/opik/domain/ExperimentService.java Outdated
…er fixes

Address reviewer feedback (andrescrz):

- Drop UUIDv7 validation on referenced config ids that are already existence-checked
  (so a bad id fails with the proper 404/409, not 400): projectId on span/trace update,
  prompt, experiment, optimization, dashboard (all go through validateProjectIdExists /
  resolveProjectIdOrCreate / get); feedback-batch projectId (overwritten by the
  name-resolved project); datasetVersionId (FK-checked) and datasetId (findById).
- Keep it where the ref is persisted WITHOUT an existence check, so a UUIDv4 orphan
  can't be ingested: alert projectId, annotation-queue projectId, automation-rule
  projectIds, experiment optimizationId, feedback sourceQueueId.
- Move validateIdNotInFutureIfPresent(Async) bodies out of the IdGenerator interface
  into IdGeneratorImpl.
- Tests: route added generators through TestIdGeneratorFactory (static final) instead of
  local TimeBasedEpochGenerator fields; parameterize the span invalid-reference tests.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@thiagohora
thiagohora requested a review from andrescrz July 22, 2026 13:56
@thiagohora
thiagohora merged commit 3e57379 into main Jul 22, 2026
74 of 76 checks passed
@thiagohora
thiagohora deleted the thiaghora/OPIK-7352-reject-non-v7-foreign-ids branch July 22, 2026 15:30
thiagohora added a commit that referenced this pull request Jul 22, 2026
…d validation

Resolve the semantic overlap after merging main (#7553): unify IdGenerator on
the merged API — implement validateIdNotInFuture / validateIdNotInFutureAsync
(and the IfPresent variants) and drop the superseded validateIdForUpdate*.
Own-id validateId stays workspace-tagged for the audit metric; referenced-id
validateIdNotInFuture falls back to UNKNOWN on the sync path and resolves the
workspace from the reactive context on the async path.

Keep #7553's fail-fast (validate before side effects) for span batches, now run
inside deferContextual so the batch's own ids attribute to the request workspace;
bindSpanToProjectAndId no longer re-validates. Trace batches keep validating in
bindTraceToProjectAndId with the workspace threaded through.

Update the async test to the renamed methods.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
thiagohora added a commit that referenced this pull request Jul 22, 2026
bindTraceToProjectAndId validated own ids only after deleteAutoStrippedAttachments
and project getOrCreate, so a bad trace id in a batch still mutated state before
failing (unlike spans, which #7553 validates fail-fast). Hoist trace own-id
validation into a leading deferContextual that runs before any side effect and
attributes the audit metric to the request workspace, and stop re-validating in
bindTraceToProjectAndId — mirroring create(SpanBatch).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Backend java Pull requests that update Java code 🟠 size/L tests Including test files, or tests related like configuration.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants