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
    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