You basically got it right, however a few extra points...
There are several "start-up files" bash may run - some for backwards compatibility with the bourne-shell (sh), other depending on how you started bash: Did you log-in to X? Did you log-in to a TTY? Did you start bash in another (bash-)shell? Is bash running as a script (non-interactive)? Thus .bashrc is not always run, nor may it be the only start-up file. However, it's a good idea to "source" (read and execute) .bashrc in the other start-up files too, so the content of your .bashrc is always added. Use man bash and look especially on the part about how bash starts... the FILES-section also list the files bash uses, including all start-up files. For a more in-depth, try info bash.
In addition to you own start-up files, there are corresponding "default" global start-up files in /etc - these are typically read/executed by bash before your own start-up files. There also other programs that defines their own environment-variables in addition to those defined by bash,which may complement or even override those set by bash. Of particular note is X (the GUI), since it will set-up two different sets of environments, depending on whether X is started manually (with xinit or startx) from a VT, or is started by a "display manager" (eg. xdm or kdm) so you can log-in directly into X (X is started when you boot, and you got a dialog-box for username/password in X).
But before bash, X or any other programs starts, much of the environment - environment-variables - you'll be using, will have been set-up, for example by the login command. Much of this you can find in /etc/login.defs and other configuration-files. For example, the PATH-variable will be set-up - and will differ depending on whether you're root or a normal user.
So if you look at the various files and scripts that are ran as part of the boot, init and log-in process; you'll find most of all the variables you can list with env. Some however - like CWD (current working directory) - are set (and updated) automatically by the shell (bash) itself.
When you run a command, what happen is that bash use a system call called fork(). bash basically makes an identical copy of itself, with the exception that the child gets a new PID (Process ID) and that it's PPID (Parent PID) is that of it's "mother". Else they're identical - even including the environment-variables... assuming the variable in question was made inheritable by first exporting it. You now got two copies of bash. Then another system-call -exec() - is used, which basically replaces the bash-program "in memory" for the child bash-process, with another program - for example with ls, ps or mutt (whatever you typed)... but the environment-variables remains, so the new program inherits it's environment from bash. This child now controls your terminal (unless you put the command in the background with &) until it terminates, while your original bash-shell (basically) sleeps. When the command terminates, you return to your original bash-shell, which is ready for another command.