That's a good summary, Brian.
I'm sure you would have intended to include variables (of all types) in there.
You'd treat them in a similar manner to code locations (jumps etc), by adding each instance to an array of variable definitions during the first pass, and then resolving them to actual addresses in the second pass (unless you force the writer to define all variables ahead of all code, which has been preferred, historically, simply to make the assembler simpler!).
But while I'm on, I'll add some further thoughts:
A more advanced assember would provide for including library functions, linking to other modules and providing 'hooks' to allow the code to be linked-to by other modules.
I'd also recommend making provision for debugging. At a minimum, that would just be a report of locations allocated to variables and labels in alphabetical sequence, and in more advanced debuggers, it would even insert code for breakpoints and provide access to variables through a user interface.
Then there's the option to include 'compiler directives' which can pre-define default sizes for variables, debug options, force global addresses, force standards for label and variable names, force array space in the absence of dimensions and inhibit certain instructions (eg interrupt mask control).
It might sound like a lot of extra work, but the time taken to write these additional features can be easily recouped by a faster (and less stressfull ! ) development time.
There are plenty of texts and resources out there to assist the assembler-author, but I must add my personal view that writing and using one's own assembler is a very excellent way to improve one's knowledge and skill in programming a particular device (though it might make you unpopular with your colleagues and future programmers who have to maintain your code!)
There seems to be a temptation for any programmer who writes their own assembler to 'invent' new instructions or new procedures. This can be done for private use, though I think should be resisted for wider circulation (just think about the chaos arising from someone who wnays to create a 'test and set' instruction by turning off and on the interrupt without checking its status beforehand).