anchor.diff:      {ok, atm_value:expanded()}.
   expand(_AtmWorkflowExecutionAuth, Value) ->
       {ok, Value}.
  +
  +
  +%%%===================================================================
  +%%% Internal functions
  +%%%===================================================================
  +
  +
  +%% @private
  +-spec check_implicit_measurement_constraints(non_neg_integer(), atm_value:expanded()) ->
  +    ok | no_return().
  +check_implicit_measurement_constraints(Index, #{
  +    <<"tsName">> := TsName,
  +    <<"timestamp">> := Timestamp,
  +    <<"value">> := MeasurementValue
  +}) ->
  +    is_binary(TsName) orelse throw({unverified_constraints, #{
  +        ?FIELD_PATH(Index, <<"tsName">>) => <<"String">>
  +    }}),
  +
  +    (is_integer(Timestamp) andalso Timestamp > 0) orelse throw({unverified_constraints, #{
  +        ?FIELD_PATH(Index, <<"timestamp">>) => <<"Non negative integer">>
  +    }}),
  +
  +    is_number(MeasurementValue) orelse throw({unverified_constraints, #{
  +        ?FIELD_PATH(Index, <<"value">>) => <<"Number">>
  +    }}),
  +
  +    ok.
  
positive.code:     atm_data_type:value_constraints()
  ) ->
      ok | no_return().
  assert_meets_constraints(_AtmWorkflowExecutionAuth, _Value, _ValueConstraints) ->
      %% TODO validate fields
      ok.
  
  
  %%%===================================================================
  
negative.code: -behaviour(atm_data_validator).
  -behaviour(atm_data_compressor).
  
  -include_lib("ctool/include/errors.hrl").
  
  %% atm_data_validator callbacks
  -export([assert_meets_constraints/3]).
  
  %% atm_data_compressor callbacks
  -export([compress/1, expand/2]).
  
  
  -define(DATA_TYPE, atm_time_series_measurements_type).
  
  -define(FIELD_PATH(__INDEX, __KEY), str_utils:format_bin("[~B].~s", [__INDEX, __KEY])).
  
  
  %%%===================================================================
  