You're vulnerable to a chunk-level replay attack, where Mallory (the man-in-the-middle) can mix and match chunks from different files, to produce a file that appears to be from Bob but which Bob never wrote.
- Bob sends two messages to Sarah. Let's say the first message comes in chunks A1 and A2, and the second message comes in chunks B1 and B2.
- Mallory intercepts both messages. She then constructs the new message A1+B2.
- Mallory sends the forged message to Sarah. The boxes open with Bob's key, and the sequence numbers look good.
Since Mallory can forge a message, this scheme fails to provide authenticity.
You could fix this problem in a couple ways. One way would be to put another token inside each chunk, next to the position bytes, that's shared by all the chunks and unique for each message. Then in addition to verifying the position, the receiver would have to check that this identifier matched the previous chunks.
Another approach would be to use NaCl's nonce to do this for you. (Since after all, a "unique token for each message" is sort of what a nonce is.) If you use 16 random bytes (shared by all the chunks) plus an 8-byte counter as your nonce, you can avoid nonce reuse and also prevent the chunk-swapping replay attack. This saves you some space because you only have to transmit the 16 random bytes once, and it's also safer: a forged plaintext will never be decrypted at all, so it's impossible for an implementation to somehow forget to check the tokens. This sort of use case is why NaCl was designed with a large nonce.
Edit: Adam Langley has a post on this: https://www.imperialviolet.org/2015/05/16/aeads.html