Skip to content

Audit and align all Import<Asset> helpers on a canonical upsert key #138

@mmanciop

Description

@mmanciop

What

The six Import<Asset> helpers in internal/asset/ currently choose different fields for the upsert key passed to the underlying Update<Asset>(ctx, originOrId, ...) API call:

Asset Upsert key today Field source
Dashboard ID metadata.dash0extensions.id
Check rule ID top-level id field
Synthetic check ID metadata.labels."dash0.com/id"
View ID metadata.labels."dash0.com/id"
Notification channel origin metadata.labels."dash0.com/origin"
Spam filter (v1alpha1+2) origin (ID as fallback) metadata.labels."dash0.com/origin"

Four use ID, two use origin. The server URL parameter is uniformly originOrId, so it accepts either at the wire level — but whether a particular endpoint honors a brand-new user-supplied UUID on PUT (vs. silently generating one server-side) varies. The spam filter and notification channel endpoints reject user-supplied IDs and only accept origin as the user-controlled upsert key; the dashboard, view, check rule, and synthetic check endpoints currently accept both.

This issue tracks the audit and the alignment work.

Why

dash0 apply is a declarative tool; users expect "apply twice → same end state". Today that contract is upheld only by accident — for assets where the backend happens to honor user-supplied IDs on PUT. The spam filter divergence (discovered while wiring v1alpha2 into apply) showed that this assumption is not portable.

The CLAUDE.md note already articulates the semantic split: origin is "which system owns this asset" (a user-controlled label), while ID is the "external identifier used for upsert" — but the latter has just been observed to be server-managed for some asset types. If origin is the canonical upsert key across the board, the CLI should match that uniformly.

Aligning every Import* helper on a single rule (preferred: origin first, ID fallback) would:

  • make dash0 apply idempotent on the same field for every asset, removing per-asset gotchas;
  • match the principle that the user-controlled label, not the server-controlled id, is the right key for declarative workflows;
  • let the parity rule in docs/cli-naming-conventions.md be enforced uniformly across asset types.

Prerequisites

  • Confirm the backend contract via the dash0 monorepo. Specifically: for each asset type, does PUT /api/<asset>/{originOrId} honor a brand-new user-supplied UUID, or does it only honor origins / pre-existing IDs?
  • Once the contract is known per asset, pick the canonical key (most likely origin-first with ID fallback) and document the rule in docs/cli-naming-conventions.md next to the parity rule.

Acceptance criteria

  • One documented upsert-key rule per asset, justified against the backend contract.
  • ImportDashboard, ImportCheckRule, ImportSyntheticCheck, ImportView, ImportNotificationChannel, ImportSpamFilter, ImportSpamFilterV1Alpha2 all follow the same precedence (origin first, ID fallback, or the documented alternative — but uniform).
  • Existing apply roundtrip tests (test_apply_*_idempotency.sh) keep passing; new origin-keyed cases added to every asset so the contract is exercised.
  • docs/adding-commands.md step 4 (apply wiring) names the chosen upsert key so future asset additions follow the same rule by default.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions