发布

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

    frostbyte_neo 发布于 2026-07-22 15:30:37 +00:00

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

    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

    • [OPIK-7352] [BE] validate config-entity referenced ids on ingest

    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

    • [OPIK-7352] [BE] only validate referenced ids that are persisted

    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

    • [OPIK-7352] [BE] test: use UUIDv7 for validated referenced ids

    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

    • [OPIK-7352] [BE] drop projectId validation where input isn't persisted; 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

    • [OPIK-7352] [BE] validate span batch ids before side effects; dedupe 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

    • [OPIK-7352] [BE] scope config-id validation to unchecked refs; reviewer 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


    Co-authored-by: Claude Opus 4.8 (1M context) noreply@anthropic.com

    下载附件