The life cycle of a certificate:
	* Generating a key pair.
	* Generating a CSR containing public key.
	* Submitting CSR to a CA.
	* Checking for response from CA.
	* Waiting for certificate to near expiration.
Administrative action can also add these states:
	* On hold
	* Revoked

We model that life cycle as a state machine.

Now with some arbitrarily-named states for our per-certificate state machine:
	* Generating a key pair.
	States: NEED_KEY_PAIR, GENERATING_KEY_PAIR [*], HAVE_KEY_PAIR
	* Generating a CSR containing public key.
	States: NEED_CSR, GENERATING_CSR [*], HAVE_CSR
	* Submitting CSR to a CA.
	States: NEED_TO_SUBMIT, SUBMITTING [*]
	* Saving certificate to the desired location and parsing it for the
	  information we think is interesting.
	States: NEED_TO_SAVE_CERT, SAVING_CERT[*], READING_CERT[*], SAVED_CERT
	* Rejected, very sad.
	States: REJECTED [*]
	* Waiting for certificate to near expiration.
	States: MONITORING
	* Don't know which CA to submit to.
	States: NEED_GUIDANCE [*]
	* Waiting for user input
	States: NEED_GUIDANCE [*]
	* On hold
	States: NEED_GUIDANCE [*]
	* Revoked
	States: NEED_GUIDANCE [*]
[*] Denotes states in which we have to wait for instructions from the user
    or completion of interaction with external systems.

State logic:
	NEED_KEY_PAIR:
		start-key-generation
		state_next = GENERATING_KEY_PAIR
		state_transition = now
		break
	GENERATING_KEY_PAIR:
		if starting-up
			state_next = NEED_KEY_PAIR
			state_transition = now
		else
			if keygen-finished
				if key-was-stored-successfully
					state_next = HAVE_KEY_PAIR
					state_transition = now
				else
					state_next = NEED_KEY_PAIR
					state_transition = now
			else
				state_next = GENERATING_KEY_PAIR
				state_transition = when-notified
		break
	HAVE_KEY_PAIR:
		state_next = NEED_CSR
		state_transition = now
		break

	NEED_CSR:
		if don't-have-a-full-template
			fill-in-template-values-based-on-defaults
		start-csr-generation-using-template-values
		state_next = GENERATING_CSR
		state_transition = now
		break
	GENERATING_CSR:
		if starting-up
			state_next = NEED_CSR
			state_transition = now
		else
			if csrgen-finished
				if csr-was-stored
					state_next = HAVE_CSR
					state_transition = now
				else
					state_next = NEED_CSR
					state_transition = now
			else
				state_next = GENERATING_CSR
				state_transition = when-notified
		break
	HAVE_CSR:
		state_next = NEED_TO_SUBMIT
		state_transition = now
		break

	NEED_TO_SUBMIT:
		start-csr-submission
		if csr-submission-started
			state_next = SUBMITTING
			state_transition = now
		else
			if don't-know-a-ca
				state_next = NEED_CA
				state_transition = now
		break

	SUBMITTING:
		if starting-up
			state_next = NEED_TO_SUBMIT
			state_transition = now
		else
			if csr-submission-attempt-completed
				if ca-issued-cert
					state_next = NEED_TO_SAVE_CERT
					state_transition = now
				elseif ca-rejected-us
					state_next = REJECTED
					state_transition = now
				elseif ca-is-unreachable
					store-ca-cookie
					state_next = NEED_TO_SUBMIT
					state_transition = later
				elseif ca-is-thinking-about-it
					store-ca-cookie
					state_next = NEED_TO_SUBMIT
					state_transition = soon
				else
					state_next = NEED_GUIDANCE
					state_transition = now
			else
				state_next = SUBMITTING 
				state_transition = when-notified
		break

	NEED_TO_SAVE_CERT:
		start-saving-cert
		state_next = SAVING_CERT
		state_transition = now
		break

	SAVING_CERT:
		if cert-save-completed:
			state_next = NEED_TO_READ_CERT
			state_transition = now
		break

	NEED_TO_READ_CERT:
		start-reading-cert
		state_next = READING_CERT
		state_transition = now
		break

	READING_CERT:
		if cert-read-completed:
			state_next = MONITORING
			state_transition = now
		break

	NEED_GUIDANCE:
		if have-guidance
			state_next = as-guided
			state_waitfor = now
		else
			state_next = NEED_GUIDANCE
			state_transition = timeout
		break
	
	REJECTED:
		state_next = REJECTED
		state_waitfor = ever
		break

	MONITORING:
		if certificate-uses-auto-renew(cert)
			if certificate-is-expired or
			   (expiration-time-is-below-renewal-threshold-value and
			    expiration-time-was-above-renewal-threshold-value)
				update-template-values-based-on-cert
				state_next = NEED_CSR
				state_transition = now
			else
				state_next = MONITORING
				state_transition = timeout
		else
			if certificate-is-expired
				state_next = NEED_GUIDANCE
				state_transition = now
			elseif (expiration-time-is-below-a-threshold-value and
			        expiration-time-was-above-a-threshold-value)
				notify-administrator
				store-last-checked-t(cert,now)
				store-last-notified-t(cert,exp,ttl)
				state_next = MONITORING
				state_transition = timeout
			else
				state_next = MONITORING
				state_transition = timeout
		break

Types of actions and user guidance:
	Reenroll-from-scratch ("request -g"):
		state_next = NEED_KEY_PAIR
		state_transition = now
	Submit-key ("request", if no csr or arguments alter it):
		state_next = NEED_CSR
		state_transition = now
	Submit-csr (automatic for "request")
		state_next = HAVE_CSR
		state_transition = now
	Resubmit-csr (need to add "resubmit")
		state_next = HAVE_CSR
		state_transition = now
	Start-Tracking-with-AutoRenew ("start-tracking"):
		add-cert-to-monitoring-list
		state_next = MONITORING
		state_transition = now
	Start-Tracking-without-AutoRenew ("start-tracking"):
		add-cert-to-monitoring-list
		state_next = MONITORING
		state_transition = now
	Cancel ("stop-tracking"):
		remove-cert-from-monitoring-list
	Status ("list"):
		dump-monitoring-list

Data we need to track for each certificate/task/dbentry:
	* Type of key pair to generate [or use default settings]
	  default: RSA,2048
	* Location of key pair [use-once default]
	  default: NSS,/etc/pki/nssdb,,Server-Key-default
	* Location of certificate [use-once default]
	  default: NSS,/etc/pki/nssdb,,Server-Cert-default
	* Cached certificate issuer/serial/subject/spki/expiration/host/email
	* The last time we checked if expiration was imminent.
	* Interesting TTL values [or use default settings]
	  default: 30*24*60*60,7*24*60*60,3*24*60*60,2*24*60*60,1*24*60*60
	* How to notify administrator [or use default settings]
	  syslog(LOG_AUTHPRIV?) or mail to root@?
	* CSR template information [or imported from existing certificate]
	  * subject (cn=host name)
	  * SANs¹
	    * DNS
	    * email
	    * principal name
	  * ku¹, eku¹
	  ¹ Encoded as extensionRequest attributes.
	* Certificate State (state_current)
	* Whether to autorenew-at-expiration [or use default settings]
	* Whether to start monitoring at issue [or use default settings]
	* Type and location of CA [or use default settings]
	* Value of CA cookie for in-progress submissions.
	* Date of submission for in-progress submissions.
