Contract Activation Requested
A user saved a contract for activation. cna-nexus's activation consumer turns it ACTIVE and creates or updates the franchise unit it governs.
Overview
Fact: a contract was saved in the state ACTIVATING and its activation is requested. It is the hand-off between the API request and the background work.
When it is published. CNA NexusCNA NexusServicev1.0.0Franchise network back-office (franchises, economic groups, partners, contracts and amendments, document storage, AI doc...PublishesInviteUser, ContractActivationRequested +13SubscribesContractActivationRequested, AmendmentApplyRequested +4Ownercna-platformMapRepoView docs, in createContract and updateContract, right after the transaction that writes the contract with its financial terms, franchise data, address, territory and participants returns with status = ACTIVATING. Every update of a contract publishes it again, so the franchise aggregate is brought back in sync. Published after the write, not registered with afterCommit: if the producer fails, the contract stays ACTIVATING with no message.
What the consumer does. cna-nexus (contractActivationConsumer, group contract-activation):
- Loads the contract; a missing contract throws (logged and reported to Sentry).
- Idempotency guard:
ACTIVEorACTIVATION_FAILEDare skipped, so redelivery after success is harmless and a failed activation needs a manual retry. activateContract(contractId, userId): re-checksACTIVATING, then in one transaction sets the contractACTIVEwithactivatedAt, and projects it onto the franchise. The first activation of anOPENINGwith no franchise creates theFranchiseaggregate (unit, brand, address, territory, partners) and links the contract to it; any other case applies the contract snapshot onto the existing franchise. ARENEWALflips the previous active or expired contract toRENEWED. Field-level audit rows are written with theuserIdfrom the payload.- On failure: logs and sets the contract to
ACTIVATION_FAILED. Not rethrown, so Sentry is not notified from this path.
Follow-up messages. Inside the same transaction, via manager.afterCommit(): FranchiseCreated on the first activation of an opening, FranchiseUpdated otherwise (see the Franchise topic).
Kafka
Topic (aggregateRoot) | Contract |
Message key (routingKey) | payload.contractId |
| Contract owner | NEXUS |
metadata.event | ContractActivationRequested |
| Consumer group | contract-activation |
Payload schema
Source of truth
type ContractActivationRequestedPayload = { contractId: string; userId: string;};
export class ContractActivationRequested extends Event<ContractActivationRequestedPayload> { static readonly owner = "NEXUS"; static readonly aggregateRoot = "Contract"; static readonly routingKey = "contractId";}The class exists only in cna-nexus.
Known drift
- Docstrings in
createContract,createContractAndRelationsandupdateContractAndRelationssay a failed activation moves the contract toDRAFT; the consumer writesACTIVATION_FAILED. - Published without
afterCommit, unlike the Franchise events it triggers.
Custom properties
| Property | Value |
|---|---|
| Contract Ownerx-contract-owner | NEXUS |
| Kafka Topicx-kafka-topic | Contract |
| Message Keyx-message-key | contractId |
| Sourcex-source | cna-nexus api/app/events/nexus/contract/ContractActivationRequested.ts |
Contract id (UUID) in cna-nexus contract.contracts. Kafka message key.
User who saved the contract (authorization.users). Recorded as the author of the audit rows written by the activation.