There is no need for any doubt.
RFC7234 Section 5.2.1.1 includes an example max-age=5
which is of course greater than zero.
The definition is also clear (emphasis mine):
The "max-age" request directive indicates that the client is unwilling to accept a response whose age is greater than the specified number of seconds.
"The specified number of seconds" can be any non-negative integer (defined in Section 1.2.1).
So the answer is a definite yes.
Additionally, the definition I quoted above also explains the cache behavior in your scenario.
But before I get to that, I should correct the following:
Server tells user agent that the resource requested should be revalidated after 2 minutes.
Incorrect.
The max-age=120
directive means that the server tells all caches, not the user agent, that the response must be considered stale after 2 minutes.
From Section 5.2.2.8 (emphasis mine):
The "max-age" response directive indicates that the response is to be considered stale after its age is greater than the specified number of seconds.
As you can see, there is no revalidation requirement.
If there are no requests to the same resource until 10 minutes later, there won't be any revalidation until 10 minutes later.
Also, from Section 5.2 (emphasis mine):
The "Cache-Control" header field is used to specify directives for caches along the request/response chain.
Just caches, not user agent.
Each participant in the request/response chain receives the same response with the same Cache-Control header, but the intended recipients of the Cache-Control header are just caches.
Remember, just because you receive it, doesn't mean it is for you.
For the rest of your scenario, your assessment is correct.
I'll quote it here:
After 1 minute and few seconds, User agent makes another request, specifying a max-age
of 1 minute:
...
From what I understand, this request should bypass the user agent cache.
Why?
Because at the time of the request, the age of the stored response is more than 60 seconds.
It should be obvious that if the age of a stored response is, say, 65 seconds, it cannot be used to satisfy a request with a max-age=60
directive.
Thus, the cache simply obeys the directive it receives.
In fact, any standards compliant HTTP cache whether integrated in a browser or separate is required to obey the directive it receives, as stated in Section 5.2 (uppercase emphasis from source, not mine):
A cache MUST obey the requirements of the Cache-Control directives defined in this section.
Based on what you described, the custom caching mechanism you have at work seems to be standards compliant.
So, my complements to the developers, particularly if by "custom" you mean "developed in house".