Skip to content

Deprecate exact; fold string equality into equals #50

Description

@jaronoff97

Summary

Fold string equality into the typed equals matcher and deprecate the
string-only exact match type. Today equality is split: exact (string) vs.
equals (Value, every non-string scalar). Once Value gains a string
variant, all equality — string and non-string — can be expressed through a
single equals, and exact becomes a backward-compatibility alias. This issue
tracks doing that deprecation correctly.

Context: the future-direction note was added in #49
(spec.md → "Typed and Comparison Matching"; proto/tero/policy/v1/shared.protoValue).

Target end state

  • equals: "checkout" is valid and means string equality (Value.string_value).
  • exact: "checkout" is exactly equivalent to equals: { string_value: "checkout" } and is deprecated (kept for compatibility, removed only in a future major version).
  • One mental model: exact and equals are the same concept, differing only by the value's type.

Required changes

Proto (shared.proto)

  • Add a string variant to Value: string string_value = 6; (additive → non-breaking).
  • Mark the exact fields in LogMatcher / MetricMatcher / TraceMatcher as deprecated ([deprecated = true] and a comment pointing to equals). Do not remove them — removal is breaking and must wait for a major version; the field numbers must stay reserved if ever removed.

Spec (spec.md)

  • Add string_value to the Value definition and to the equals description in all three match-type tables.
  • Update the "Two distinct types are used deliberately…" paragraph: Value now does have a string variant; only NumericValue remains restricted.
  • Flip the validation rule. It currently says a bare string under equals (e.g. equals: "foo") MUST be rejected. After this change, equals: "foo" MUST be accepted and map to string_value. (A string supplied to a comparison matcher is still rejected.)
  • Convert the "Future direction" callout into the active deprecation: exact is deprecated in favor of equals.

Semantics that must change carefully

  • case_insensitive. The spec currently says case_insensitive has no effect on equals (it applies only to the string match types). Once string equality lives in equals, case_insensitive MUST apply to equals when the value is string_value, and continue to have no effect for bool/int/double/bytes/hex values. This is the subtlest behavior change and needs an explicit rule + conformance coverage.
  • Bytes coercion. exact on a bytes-typed field is currently hex-coerced (a string literal is decoded as hex). That coercion MUST move to equals string_value: a string_value matched against a bytes-typed field is interpreted as hex, identical to today's exact-on-bytes behavior. Otherwise deprecating exact would regress ergonomic id matching (equals: "8a3f…" on TRACE_FIELD_SPAN_ID).
  • Equivalence is normative. State that exact: X and equals: { string_value: X } MUST produce identical results (including case_insensitive, negate, and bytes coercion), so implementations can treat exact as sugar for the string variant of equals.

Marshaling / canonical form

  • Decide the canonical output during the deprecation window. Recommendation: implementations SHOULD continue to accept both, and SHOULD emit equals (with string_value) when marshaling new/normalized policies, but MUST NOT rewrite stored exact on round-trip in a way that breaks older readers. Document the chosen policy so tools agree.

Conformance (usetero/policy-conformance)

  • Add cases: equals: "..." string equality; exactequals: {string_value} equivalence; case_insensitive on equals string; equals string on a bytes field (hex coercion); and a deprecated-exact-still-works case.

Downstream implementations

  • policy-go: accept string_value, route exact through the same path, apply case_insensitive/bytes-coercion to equals strings. (Relates to policy-go#69.)
  • policy-rs: same.

Backward compatibility & sequencing

  1. Now (minor): add string_value (additive), document exact as deprecated, accept equals strings everywhere exact worked. Old policies using exact keep working unchanged; old readers ignore string_value and would treat such a matcher as "no match condition set" → inert + reported compile error (fail-open), which is acceptable for clients that predate the change.
  2. Transition: tooling and generated policies prefer equals; exact emitted only for compatibility.
  3. Future (major): optionally remove exact, reserving its field numbers.

Open questions

  • Do we want string_value to also be reachable via plain scalar shorthand under equals (equals: "x"), which is the ergonomic win, vs. requiring equals: { string_value: "x" }? (Recommend: accept the bare-string shorthand — that is the whole point of unifying.)
  • Should exact get [deprecated = true] immediately (surfaces compiler warnings downstream) or only a doc-comment deprecation until the transition step?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions