In case it feels better, you could do something like this:
$ cat dune-project | rg package -A 5
(package
(name foo)
(version 1.1)
(synopsis "Short description")
(description "Longer description")
(depends
$ tree version/
version/
└── dune
1 directory, 1 file
$ cat version/dune
(library
(name version))
(rule
(action
(with-stdout-to
version.ml
(run echo "let v = \"%{version:foo}\""))))
$ tree bin/
bin/
├── dune
└── foo.ml
1 directory, 2 files
$ cat bin/dune
(executable
(public_name foo)
(libraries version))
↳[0]
$ cat bin/foo.ml
let () = print_endline Version.v
$ dune exec foo
1.1
using the version:<package> variable documented at Variables - Dune documentation
The dune subst approach feels right to me, so it’s not clear to me how to motivate a need for this, but you could of course write something if you feel motivated! You could also start a discussion on the dune repo if you think there’s a good case to be made for this kind of addition.