Founder Sales Pipeline Correctness: Stage Events, Evidence Predicates, and Reopen Semantics
CRM boards show only an opportunity’s current column, hiding concurrent moves, late synchronization, and incorrectly marked wins. This article models stage changes as immutable events, accepts transitions with versioned evidence predicates and CAS, and keeps Won, Lost, and Reopen traceable.
Key Points
- Topic Focus: AI、DevOps、独立开发
- Suitable for: indie hackers, full-stack engineers, AI application developers
- Core value: quickly understand background, practical paths, common pitfalls, and engineering advice
A founder drags an opportunity from “Demoed” to “Verbal Commitment,” while a sales assistant moves it back to “Contacted” based on a late-arriving email. Minutes later, a finance webhook marks the same company as Won. The final dashboard contains only a green cell, but it cannot explain who accepted the transition or on what evidence, nor can it distinguish a duplicate synchronization, the correction of an accidental action, or a new sales cycle reopened by the customer in the next quarter. Calculating forecasts directly from the current-stage field flattens all these conflicts together.
AI Willingness-to-Pay Interviews validate problems, budgets, and commitments, while Developer Launch Holdout Experiments measure incremental marketing impact. This article starts after a sales opportunity has already been created and addresses only the correctness of stage facts and transition evidence. It is not a customer-acquisition attribution ledger, nor does it treat a single sales status as ground truth for product demand.
Define Evidence with stagePolicy.v1, Not Colors
Publish an immutable sales.stagePolicy.v1 that defines the meaning, allowed predecessors, required evidence predicates, maximum evidence age, probability display rules, terminal-state properties, and authorized roles for every stable stage ID. The RFC 8174 keywords MUST and SHOULD have binding meaning only when a specification explicitly adopts them. Internal policies must likewise distinguish “recommended” from “reject if missing” instead of relying on UI asterisks.
schema: sales.stagePolicy.v1
policy: founder-sales@9
stage: commercial-commitment
allowedFrom: [qualified, solution-validated]
requires:
- economicBuyerIdentified@2
- priceScopeAcknowledged@3
- decisionDateConfirmed@1
maxEvidenceAgeDays: 21
terminal: false
authorizedRoles: [account-owner, founder]
Evidence references immutable artifacts: meeting-note summaries, quote digests, confirmations from a customer domain, procurement tickets, or payment receipts. It also records the collecting principal, occurredAt, recordedAt, visibility, and revocation status. External CRMs commonly represent the stage, closed status, and won status as current fields, but a vendor’s data model cannot replace the company’s own acceptance rules. The synchronizer must record the connector and field mapping generation. Forecast amounts must also bind the currency, quantity, term, and quote version rather than storing only an editable number.
The Current Stage Is Only a Projection of Immutable Events
Every command generates an opportunityStageEvent.v1 containing the opportunityId, salesCycleId, event ID, expected sequence, from/to stages, policy digest, evidence root, actor, occurredAt, and recordedAt. CloudEvents can serve as the exchange envelope, but its specification does not guarantee business ordering or exactly-once delivery. Consumers deduplicate by source and id, and divergent content under the same identity enters IDENTITY_CONFLICT. Event-Driven Architecture covers delivery patterns; this ledger governs an individual stage fact.
An opportunity flow might be DISCOVERED -> QUALIFIED -> SOLUTION_VALIDATED -> COMMERCIAL_COMMITMENT -> WON, with transitions to LOST also allowed from approved stages. A transition request begins as PROPOSED, becomes VALIDATED when its evidence is complete, becomes STALE_COMMAND when its concurrent version does not match, and becomes EVIDENCE_DISPUTED when its evidence conflicts. The only acceptance point is the storage layer, which uses CAS within a single transaction to match the current sequence and policy generation, append the event, update the projection, write the outbox, and return a stageTransitionReceipt.v1. A drag animation, an HTTP 200 response, or an updated third-party CRM does not constitute acceptance.
An external API can use RFC 9110 strong ETags and If-Match to send back the projection version observed by the client. A failed condition should return a conflict instead of overwriting data. HTTP conditional requests protect only that resource version; the database must still commit the event and projection atomically. The projection can be rebuilt from the event stream at any time and its digest compared. Database Change Data Capture can propagate accepted events to analytics systems, but it cannot recover lost history from an overwritten current row.
WON and LOST are terminal states for a particular salesCycleId and cannot be left through ordinary dragging. If the original event was factually incorrect, an authorized person appends a stageCorrection.v1 that binds the original receipt, a reason, and two-person approval; the old event remains in place. If the customer makes another purchase three months later, create a new cycle and link its prior outcome instead of rewriting the old close date. Payment reversals, contract cancellations, and delivery failures are separate post-close business events and must not silently change a historical Won into Lost.
Inject Concurrent Moves and Late Synchronization
Run exercises in which two users simultaneously move an opportunity from sequence 17 to different stages, redeliver a CRM webhook, have an offline client submit one day late, reverse the ordering of occurredAt and recordedAt, inject divergent content under the same event ID, revoke evidence after validation, switch the stage policy, omit a currency mapping, attempt an ordinary reopen from a terminal state, and make the outbox succeed while the projection update fails. Exactly one CAS is expected to win, and the atomic transaction must prevent partial acceptance. Unknown mappings and disputed evidence must not enter the production pipeline.
Operations CSV Imports can support historical opportunity migration, but every row must first be mapped to a staging candidate and then promoted under the same transition rules; it must not overwrite the current stage directly. Gates require every production transition to have a policy digest, actor, and evidence root; event and projection sequences must agree 100% of the time; duplicate events must create zero new transitions; zero instances of divergent content under the same identity may be accepted; and zero illegal edges or terminal states without evidence may be accepted. The projection digest produced by replaying the complete event stream must match 100%. At least 99% of valid interactions must return a deterministic accepted, rejected, or stale result within 500 ms; UNKNOWN does not count as success.
Begin rollout by reading changes from the existing CRM and building a shadow event stream. For four consecutive weeks, compare only the projections, funnel counts, and stage age. Then route 10% of newly created, noncritical opportunities through the new write path while retaining the old CRM as the display fallback. Assign cohorts stably by opportunity ID; the same opportunity must never have two primary writers. If projection divergence exceeds 0.1%, a terminal state is overwritten through an ordinary update even once, or an outbox gap is found, disable the new command entry point and switch the read alias back to the old fields while continuing to capture events for repair. Only after exercising concurrency, corrections, and reopening through a new cycle should forecast queries gradually move to the event projection.
Related
Related Content
Article
What Is Vibe Coding? Will It Change How Programmers Work?
Technical trends, engineering practices, and an indie developer perspective on Vibe Coding, AI, and independent development.
Article
From Copilot to Codex: AI Coding Tools Enter the Agent Era
Technical trends, engineering practices, and indie-developer perspectives around AI, AI Agents, and Vibe Coding.
Article
Complete Technology Stack Analysis for LLM Application Development
Covers tech trends, engineering practices, and indie developer perspectives around large models, RAG, and AI.
Article
Security Risks of AI Code Generation: Don't Blindly Trust Vibe Coding
Around Vibe Coding and AI: technology trends, engineering practices, and an indie developer's perspective.