Skip to main content
You use the draft v0.1 lifecycle to separate intake and non-binding estimates from reviewed, binding quotes. The implementation is reference, not production. You can inspect the canonical state table in the lifecycle schema; spec/lifecycle.ts reads that table rather than maintaining a second set of edges.

Collect and validate answers

You begin at INITIATED, issue a manifest at MANIFEST_ISSUED, then receive answers at PAYLOAD_SUBMITTED. A priced Estimate remains non-binding in either review mode. If inputs are incomplete, move to MUTATION_REQUIRED and collect a resubmission at PAYLOAD_SUBMITTED. Validated inputs move to VALIDATED_PENDING_REVIEW. For laser removal, you must use the separate unpriced manual-review result when intake gates fail, not invent a priced Estimate.

Review before issuing a quote

From VALIDATED_PENDING_REVIEW, you can request changes through MUTATION_REQUIRED, decline through DECLINED, or issue QUOTED after artist review. At QUOTED, you provide a binding Quote with valid_until. You retain its price range, sessions, deposit policies, confidence, assumptions and audit trail. You supply the validity period as a business setting; the protocol imposes no default validity period.

Record the outcome

From QUOTED, you can move only to ACCEPTED, DECLINED or EXPIRED. Those states are terminal in this draft; you do not add a checkout-handoff state. The transition helper rejects illegal edges. To enter QUOTED or ACCEPTED, you provide a valid deadline that has not passed. To enter EXPIRED, the current time must be strictly later than valid_until. To accept, you obtain explicit client approval of the payment amount, currency and policies before external handoff. The helper checks approved: true, an exact amount match and an exact ordered policy match against a nonempty deposit policy list. You must also enforce the binding’s currency and other request-validation requirements; the helper alone is not complete payment authorization.

Keep payment outside the quote lifecycle

You use external checkout for payment processing. The provider is merchant of record, and UQP never holds funds. You mark a deposit paid only after trusted processor confirmation, never from client self-report. Use polling in the REST, MCP or GraphQL reference flows. You should not hold calls open while waiting for review; webhook delivery is deferred in the local reference.