@sguild/dispatcher 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +354 -0
- package/contracts/credit-reservation-funding-state/schema/payloads/reservation.funded-v1.json +59 -0
- package/contracts/credit-reservation-funding-state/schema/payloads/reservation.refunded-v1.json +80 -0
- package/contracts/credit-reservation-funding-state/schema/payloads/reservation.refunding-v1.json +74 -0
- package/contracts/credit-reservation-lock/schema/payloads/credit.consumed-v1.json +33 -0
- package/contracts/credit-reservation-lock/schema/payloads/credit.forfeited-v1.json +41 -0
- package/contracts/credit-reservation-lock/schema/payloads/credit.funded-v1.json +31 -0
- package/contracts/credit-reservation-lock/schema/payloads/credit.locked-v1.json +42 -0
- package/contracts/credit-reservation-lock/schema/payloads/credit.purchased-v1.json +39 -0
- package/contracts/credit-reservation-lock/schema/payloads/credit.released-v1.json +61 -0
- package/contracts/credit-reservation-lock/schema/payloads/credit.released-v2.json +77 -0
- package/contracts/credit-reservation-lock/schema/payloads/credit.reserved-v1.json +60 -0
- package/contracts/credit-reservation-lock/schema/payloads/customer.handoff-v1.json +35 -0
- package/contracts/event-envelope/schema/envelope-v1.json +79 -0
- package/contracts/event-types-registry.json +541 -0
- package/contracts/identity/schema/payloads/intake.amended-v1.json +124 -0
- package/contracts/identity/schema/payloads/intake.captured-v2.json +114 -0
- package/contracts/identity/schema/payloads/person.updated-v1.json +99 -0
- package/contracts/lead-lifecycle/schema/payloads/lead.attempt.exhausted-v1.json +36 -0
- package/contracts/lead-lifecycle/schema/payloads/lead.callback.scheduled-v1.json +39 -0
- package/contracts/lead-lifecycle/schema/payloads/lead.created-v1.json +50 -0
- package/contracts/lead-lifecycle/schema/payloads/lead.reached-v1.json +39 -0
- package/contracts/lead-lifecycle/schema/payloads/lead.stage.changed-v1.json +44 -0
- package/contracts/payment-flow/schema/payloads/payment.failed-v1.json +88 -0
- package/contracts/payment-flow/schema/payloads/payment.received-v1.json +69 -0
- package/contracts/refund-flow/schema/payloads/refund.completed-v1.json +75 -0
- package/contracts/refund-flow/schema/payloads/refund.initiated-v1.json +69 -0
- package/dist/config.d.ts +67 -0
- package/dist/config.js +81 -0
- package/dist/dispatcher-errors.d.ts +20 -0
- package/dist/dispatcher-errors.js +42 -0
- package/dist/dispatcher.d.ts +123 -0
- package/dist/dispatcher.js +171 -0
- package/dist/dlq.d.ts +173 -0
- package/dist/dlq.js +391 -0
- package/dist/fanout-drain.d.ts +11 -0
- package/dist/fanout-drain.js +31 -0
- package/dist/fanout.d.ts +144 -0
- package/dist/fanout.js +321 -0
- package/dist/inbox.d.ts +125 -0
- package/dist/inbox.js +120 -0
- package/dist/index.d.ts +36 -0
- package/dist/index.js +70 -0
- package/dist/internal/id.d.ts +38 -0
- package/dist/internal/id.js +78 -0
- package/dist/internal/pg-search-path.d.ts +34 -0
- package/dist/internal/pg-search-path.js +55 -0
- package/dist/internal/resolve-contract-path.d.ts +41 -0
- package/dist/internal/resolve-contract-path.js +65 -0
- package/dist/observability.d.ts +24 -0
- package/dist/observability.js +37 -0
- package/dist/postgres-consumer.d.ts +175 -0
- package/dist/postgres-consumer.js +561 -0
- package/dist/postgres-transport.d.ts +70 -0
- package/dist/postgres-transport.js +144 -0
- package/dist/producer-db.d.ts +80 -0
- package/dist/producer-db.js +115 -0
- package/dist/registry.d.ts +94 -0
- package/dist/registry.js +99 -0
- package/dist/signature.d.ts +44 -0
- package/dist/signature.js +79 -0
- package/dist/types.d.ts +107 -0
- package/dist/types.js +13 -0
- package/dist/validator.d.ts +60 -0
- package/dist/validator.js +171 -0
- package/package.json +48 -0
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://contracts.sguild/identity/schema/payloads/intake.captured-v2.json",
|
|
4
|
+
"title": "intake.captured payload v2",
|
|
5
|
+
"description": "Payload for the intake.captured event_type at schema_version 2. Growth emits this when a form_submission enters the intake flow. v2 adds visitor_id for pre-mint attribution stitching and carries the bundled source expansion for subscriber_promotion, partner_upload, manual_capture, and derived_match per the 2026-05-01 Platform-Growth attribution and subscriber-promotion threads. The envelope subject carries the fsm_<UUID v7> form_submission id; payload tenant_id mirrors the envelope tenant_id for producer-local validation and downstream warehouse convenience.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"required": [
|
|
9
|
+
"tenant_id",
|
|
10
|
+
"source",
|
|
11
|
+
"campaign_code",
|
|
12
|
+
"landing_url",
|
|
13
|
+
"submission",
|
|
14
|
+
"person_id",
|
|
15
|
+
"visitor_id"
|
|
16
|
+
],
|
|
17
|
+
"properties": {
|
|
18
|
+
"tenant_id": {
|
|
19
|
+
"type": "string",
|
|
20
|
+
"description": "Tenant discriminator. Mirrors the event envelope tenant_id. Per ADR-0001 this is tenancy, not organization_id."
|
|
21
|
+
},
|
|
22
|
+
"source": {
|
|
23
|
+
"type": "string",
|
|
24
|
+
"description": "Growth intake source. Known values include website_form, meta_lead_ad, subscriber_promotion, partner_upload, manual_capture, and derived_match. Flexible string by design; consumers SHALL tolerate unknown source values per the event-envelope consumer rules."
|
|
25
|
+
},
|
|
26
|
+
"campaign_code": {
|
|
27
|
+
"type": [
|
|
28
|
+
"string",
|
|
29
|
+
"null"
|
|
30
|
+
],
|
|
31
|
+
"description": "Growth campaign code, typically derived from utm_campaign. Null when no campaign attribution is present."
|
|
32
|
+
},
|
|
33
|
+
"landing_url": {
|
|
34
|
+
"type": [
|
|
35
|
+
"string",
|
|
36
|
+
"null"
|
|
37
|
+
],
|
|
38
|
+
"description": "Landing page URL or intake origin URL as observed by Growth. Null when unavailable."
|
|
39
|
+
},
|
|
40
|
+
"submission": {
|
|
41
|
+
"type": "object",
|
|
42
|
+
"additionalProperties": false,
|
|
43
|
+
"required": [
|
|
44
|
+
"first_name",
|
|
45
|
+
"last_name",
|
|
46
|
+
"phone",
|
|
47
|
+
"zip"
|
|
48
|
+
],
|
|
49
|
+
"properties": {
|
|
50
|
+
"first_name": {
|
|
51
|
+
"type": "string",
|
|
52
|
+
"minLength": 1,
|
|
53
|
+
"description": "Submitted given name."
|
|
54
|
+
},
|
|
55
|
+
"last_name": {
|
|
56
|
+
"type": "string",
|
|
57
|
+
"minLength": 1,
|
|
58
|
+
"description": "Submitted family name."
|
|
59
|
+
},
|
|
60
|
+
"phone": {
|
|
61
|
+
"type": "string",
|
|
62
|
+
"minLength": 1,
|
|
63
|
+
"description": "Submitted phone number in Growth's normalized display format. Platform normalizes before identity resolution."
|
|
64
|
+
},
|
|
65
|
+
"zip": {
|
|
66
|
+
"type": "string",
|
|
67
|
+
"pattern": "^[0-9]{5}$",
|
|
68
|
+
"description": "Submitted five-digit ZIP code."
|
|
69
|
+
},
|
|
70
|
+
"email": {
|
|
71
|
+
"type": [
|
|
72
|
+
"string",
|
|
73
|
+
"null"
|
|
74
|
+
],
|
|
75
|
+
"format": "email",
|
|
76
|
+
"description": "Optional submitted email. Present for subscriber-derived or email-bearing intakes when Growth has it."
|
|
77
|
+
},
|
|
78
|
+
"dob": {
|
|
79
|
+
"type": [
|
|
80
|
+
"string",
|
|
81
|
+
"null"
|
|
82
|
+
],
|
|
83
|
+
"format": "date",
|
|
84
|
+
"description": "Optional submitted date of birth when available. Platform treats DOB as identity input and does not redistribute it on the canonical Person contract."
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
"person_id": {
|
|
89
|
+
"type": [
|
|
90
|
+
"string",
|
|
91
|
+
"null"
|
|
92
|
+
],
|
|
93
|
+
"description": "Canonical Person id when Growth already knows the match, otherwise null until Platform emits intake.matched.",
|
|
94
|
+
"pattern": "^per_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
|
|
95
|
+
},
|
|
96
|
+
"visitor_id": {
|
|
97
|
+
"type": [
|
|
98
|
+
"string",
|
|
99
|
+
"null"
|
|
100
|
+
],
|
|
101
|
+
"minLength": 1,
|
|
102
|
+
"maxLength": 255,
|
|
103
|
+
"description": "Growth-owned non-canonical visitor identifier used by the warehouse semantic layer for pre-mint attribution stitching. Null is accepted during transition or when no visitor token is available."
|
|
104
|
+
},
|
|
105
|
+
"subscriber_row_id": {
|
|
106
|
+
"type": [
|
|
107
|
+
"string",
|
|
108
|
+
"null"
|
|
109
|
+
],
|
|
110
|
+
"description": "Optional Growth subscriber row back-reference for subscriber_promotion synthetic submissions. Growth currently uses sub_<UUID v7>; earlier thread prose mentioned gws_ as a candidate before the Growth schema reserved sub_.",
|
|
111
|
+
"pattern": "^sub_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://contracts.sguild/identity/schema/payloads/person.updated-v1.json",
|
|
4
|
+
"title": "person.updated payload v1",
|
|
5
|
+
"description": "Payload for the person.updated event_type at schema_version 1. Platform's identity service emits this when any canonical field on a Person changes: status transitions (active to archived, archived to active), name edits (given_name, family_name, display_name), or the is_minor flip from the daily invariant job. Producer SHALL emit inside the same Prisma transaction as the Person row update per ADR-0009 producer-transactional guarantee. Subscribers filter on changed_fields to skip irrelevant changes (e.g., a name-edit subscriber ignores status-only changes). prior_status is populated only when status is among the changed_fields, so archive consumers can detect the active to archived transition without a separate fetch.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"required": [
|
|
9
|
+
"tenant_id",
|
|
10
|
+
"person",
|
|
11
|
+
"changed_fields"
|
|
12
|
+
],
|
|
13
|
+
"properties": {
|
|
14
|
+
"tenant_id": {
|
|
15
|
+
"type": "string",
|
|
16
|
+
"description": "Tenant discriminator. Mirrors the event envelope tenant_id. Per ADR-0001 this is tenancy, not organization_id."
|
|
17
|
+
},
|
|
18
|
+
"person": {
|
|
19
|
+
"type": "object",
|
|
20
|
+
"additionalProperties": false,
|
|
21
|
+
"required": [
|
|
22
|
+
"person_id",
|
|
23
|
+
"status",
|
|
24
|
+
"alias_of",
|
|
25
|
+
"given_name",
|
|
26
|
+
"family_name",
|
|
27
|
+
"display_name",
|
|
28
|
+
"is_minor",
|
|
29
|
+
"created_at",
|
|
30
|
+
"updated_at"
|
|
31
|
+
],
|
|
32
|
+
"description": "The full post-update canonical Person, exactly matching the nine-field shape from contracts/identity/person-canonical-fields.md. Consumers MAY treat this as a refresh of their local Person cache without a follow-up fetch.",
|
|
33
|
+
"properties": {
|
|
34
|
+
"person_id": {
|
|
35
|
+
"type": "string",
|
|
36
|
+
"description": "per_<UUID v7> per ADR-0002.",
|
|
37
|
+
"pattern": "^per_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
|
|
38
|
+
},
|
|
39
|
+
"status": {
|
|
40
|
+
"type": "string",
|
|
41
|
+
"enum": ["active", "archived", "merged"],
|
|
42
|
+
"description": "Current canonical status. archived means preserve history, do not accept new relationships, stop comms per person-canonical-fields.md."
|
|
43
|
+
},
|
|
44
|
+
"alias_of": {
|
|
45
|
+
"type": ["string", "null"],
|
|
46
|
+
"description": "Canonical person_id when status is merged; null otherwise. Populated by mergePersons, never by this event's update path (status: merged is not a legal update target; merge has its own flow).",
|
|
47
|
+
"pattern": "^per_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
|
|
48
|
+
},
|
|
49
|
+
"given_name": {
|
|
50
|
+
"type": ["string", "null"],
|
|
51
|
+
"maxLength": 200
|
|
52
|
+
},
|
|
53
|
+
"family_name": {
|
|
54
|
+
"type": ["string", "null"],
|
|
55
|
+
"maxLength": 200
|
|
56
|
+
},
|
|
57
|
+
"display_name": {
|
|
58
|
+
"type": ["string", "null"],
|
|
59
|
+
"description": "When null, consumers fall back to given_name + family_name trimmed per the canonical-fields contract."
|
|
60
|
+
},
|
|
61
|
+
"is_minor": {
|
|
62
|
+
"type": "boolean",
|
|
63
|
+
"description": "Maintained as a Platform invariant by the daily runIsMinorInvariantJob; a flip from true to false fires its own person.updated."
|
|
64
|
+
},
|
|
65
|
+
"created_at": {
|
|
66
|
+
"type": "string",
|
|
67
|
+
"format": "date-time",
|
|
68
|
+
"description": "Wall-clock UTC at row creation."
|
|
69
|
+
},
|
|
70
|
+
"updated_at": {
|
|
71
|
+
"type": "string",
|
|
72
|
+
"format": "date-time",
|
|
73
|
+
"description": "Wall-clock UTC at the writeback transaction commit for this update. Consumers MAY compare against their cached updated_at for ordering."
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
"changed_fields": {
|
|
78
|
+
"type": "array",
|
|
79
|
+
"minItems": 1,
|
|
80
|
+
"uniqueItems": true,
|
|
81
|
+
"description": "The canonical fields that actually changed in this update. Always non-empty; the producer SHALL NOT emit on a no-op patch. Consumers filter handlers on this list (a Sales archive consumer subscribes to person.updated and short-circuits unless changed_fields includes status).",
|
|
82
|
+
"items": {
|
|
83
|
+
"type": "string",
|
|
84
|
+
"enum": [
|
|
85
|
+
"given_name",
|
|
86
|
+
"family_name",
|
|
87
|
+
"display_name",
|
|
88
|
+
"status",
|
|
89
|
+
"is_minor"
|
|
90
|
+
]
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
"prior_status": {
|
|
94
|
+
"type": ["string", "null"],
|
|
95
|
+
"enum": ["active", "archived", "merged", null],
|
|
96
|
+
"description": "The status value before this update, populated only when changed_fields includes status. Null otherwise. Lets archive consumers detect the active to archived transition without a separate fetch."
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://contracts.sguild/lead-lifecycle/schema/payloads/lead.attempt.exhausted-v1.json",
|
|
4
|
+
"title": "lead.attempt.exhausted payload v1",
|
|
5
|
+
"description": "Payload for the lead.attempt.exhausted event_type per contracts/lead-lifecycle/README.md §4.5. Emitted by Sales when the cadence's four-attempt cap is hit and the Lead transitions to the 'attempt_exhausted' terminal stage. The event is the explicit-decision artifact required by the coordination/domains/sales.md quality bar ('no Lead sits in the cadence past the four-attempt cap without an explicit decision'). Producer SHALL emit inside the same Prisma transaction that transitions the Lead. lead.stage.changed co-fires from the same transaction with transition_reason: cadence_runtime.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"required": [
|
|
9
|
+
"lead_id",
|
|
10
|
+
"final_attempt_at",
|
|
11
|
+
"exhausted_at",
|
|
12
|
+
"attempt_count"
|
|
13
|
+
],
|
|
14
|
+
"properties": {
|
|
15
|
+
"lead_id": {
|
|
16
|
+
"type": "string",
|
|
17
|
+
"description": "The Lead transitioning to attempt_exhausted. lead_<UUID v7 canonical> per ADR-0002.",
|
|
18
|
+
"pattern": "^lead_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
|
|
19
|
+
},
|
|
20
|
+
"final_attempt_at": {
|
|
21
|
+
"type": "string",
|
|
22
|
+
"format": "date-time",
|
|
23
|
+
"description": "Timestamp of the last unsuccessful attempt (the one that triggered the exhaustion). UTC."
|
|
24
|
+
},
|
|
25
|
+
"exhausted_at": {
|
|
26
|
+
"type": "string",
|
|
27
|
+
"format": "date-time",
|
|
28
|
+
"description": "When the transition fired. Sales' wall-clock at commit. UTC. Typically very close in time to final_attempt_at but distinct in principle."
|
|
29
|
+
},
|
|
30
|
+
"attempt_count": {
|
|
31
|
+
"type": "integer",
|
|
32
|
+
"description": "Number of attempts at exhaustion. Expected value 4 per the cadence cap in domains/sales.md; the field allows for future cadence-cap changes without a v2 schema bump.",
|
|
33
|
+
"minimum": 1
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://contracts.sguild/lead-lifecycle/schema/payloads/lead.callback.scheduled-v1.json",
|
|
4
|
+
"title": "lead.callback.scheduled payload v1",
|
|
5
|
+
"description": "Payload for the lead.callback.scheduled event_type per contracts/lead-lifecycle/README.md §4.4. Emitted by Sales when an operator explicitly schedules a callback for a Lead. Per coordination/domains/sales.md's 'no auto-callback queueing without explicit operator action' rule, this event always carries an operator identity in scheduled_by; system-driven scheduling is not a valid producer path. Producer SHALL emit inside the same Prisma transaction that creates the callback record. If the scheduling also moves the Lead's stage, lead.stage.changed co-fires from the same transaction with transition_reason: operator_action.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"required": [
|
|
9
|
+
"lead_id",
|
|
10
|
+
"scheduled_for",
|
|
11
|
+
"scheduled_at",
|
|
12
|
+
"scheduled_by"
|
|
13
|
+
],
|
|
14
|
+
"properties": {
|
|
15
|
+
"lead_id": {
|
|
16
|
+
"type": "string",
|
|
17
|
+
"description": "The Lead the callback is scheduled for. lead_<UUID v7 canonical> per ADR-0002.",
|
|
18
|
+
"pattern": "^lead_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
|
|
19
|
+
},
|
|
20
|
+
"scheduled_for": {
|
|
21
|
+
"type": "string",
|
|
22
|
+
"format": "date-time",
|
|
23
|
+
"description": "When the callback should happen. Operator-chosen target time, UTC."
|
|
24
|
+
},
|
|
25
|
+
"scheduled_at": {
|
|
26
|
+
"type": "string",
|
|
27
|
+
"format": "date-time",
|
|
28
|
+
"description": "When the operator scheduled the callback. Sales' wall-clock at commit. UTC."
|
|
29
|
+
},
|
|
30
|
+
"scheduled_by": {
|
|
31
|
+
"type": "string",
|
|
32
|
+
"description": "The operator who scheduled the callback. Required per the 'human-driven' framing in domains/sales.md. Sales-internal id format at v1.0.0 (carried as flexible string)."
|
|
33
|
+
},
|
|
34
|
+
"notes": {
|
|
35
|
+
"type": ["string", "null"],
|
|
36
|
+
"description": "Optional freeform notes attached to the callback by the scheduling operator. Subscribers MUST NOT treat notes as structured data; the field is a human-readable annotation only."
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://contracts.sguild/lead-lifecycle/schema/payloads/lead.created-v1.json",
|
|
4
|
+
"title": "lead.created payload v1",
|
|
5
|
+
"description": "Payload for the lead.created event_type per contracts/lead-lifecycle/README.md §4.1. Emitted by Sales when a new Lead opens. Two opening cases: from intake.captured (Growth's form-submission event; person_id null until Platform matches identity) or from intake.matched (Platform's Person-attachment event; person_id populated). Reactivations also fire lead.created with reactivated_from populated. Producer SHALL emit inside the same Prisma transaction that creates the Lead row per ADR-0009's producer-transactional-guarantee shape.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"required": [
|
|
9
|
+
"lead_id",
|
|
10
|
+
"source",
|
|
11
|
+
"stage",
|
|
12
|
+
"originating_intake_event_id",
|
|
13
|
+
"created_at"
|
|
14
|
+
],
|
|
15
|
+
"properties": {
|
|
16
|
+
"lead_id": {
|
|
17
|
+
"type": "string",
|
|
18
|
+
"description": "The new Lead's id. lead_<UUID v7 canonical> per ADR-0002.",
|
|
19
|
+
"pattern": "^lead_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
|
|
20
|
+
},
|
|
21
|
+
"source": {
|
|
22
|
+
"type": "string",
|
|
23
|
+
"description": "The Lead's intake source. Values reflect the source enumeration carried on the originating intake event (e.g., paid_search, organic, referral, partner_upload, subscriber_promotion, manual_capture, derived_match, reactivation). Flexible string at v1.0.0; tightening to a closed enum is a v1.1 candidate per §8 of the contract."
|
|
24
|
+
},
|
|
25
|
+
"stage": {
|
|
26
|
+
"type": "string",
|
|
27
|
+
"description": "Initial stage of the Lead. Typically 'new' for fresh intake-driven creations and 'pending_match' for intake.captured cases waiting on Platform's match. Flexible string at v1.0.0; tightening to a closed enum is a v1.1 candidate per §8 of the contract."
|
|
28
|
+
},
|
|
29
|
+
"person_id": {
|
|
30
|
+
"type": ["string", "null"],
|
|
31
|
+
"description": "The canonical Person this Lead attaches to. Null until Platform matches identity via intake.matched per ADR-0003 and the Identity Contract. per_<UUID v7 canonical>.",
|
|
32
|
+
"pattern": "^per_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
|
|
33
|
+
},
|
|
34
|
+
"originating_intake_event_id": {
|
|
35
|
+
"type": "string",
|
|
36
|
+
"description": "Correlation back to the intake event (intake.captured or intake.matched) that opened this Lead. evt_<UUID v7 canonical> per the event-envelope contract.",
|
|
37
|
+
"pattern": "^evt_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
|
|
38
|
+
},
|
|
39
|
+
"reactivated_from": {
|
|
40
|
+
"type": ["string", "null"],
|
|
41
|
+
"description": "If this Lead is a reactivation per 2026-05-02-growth-sales-lead-reactivation-confirmed, points at the prior Lead's id. Null for fresh-intake Leads. lead_<UUID v7 canonical>.",
|
|
42
|
+
"pattern": "^lead_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
|
|
43
|
+
},
|
|
44
|
+
"created_at": {
|
|
45
|
+
"type": "string",
|
|
46
|
+
"format": "date-time",
|
|
47
|
+
"description": "When the Lead opened. Sales' wall-clock at the moment the Lead row committed. UTC."
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://contracts.sguild/lead-lifecycle/schema/payloads/lead.reached-v1.json",
|
|
4
|
+
"title": "lead.reached payload v1",
|
|
5
|
+
"description": "Payload for the lead.reached event_type per contracts/lead-lifecycle/README.md §4.3. Emitted by Sales when an outbound call attempt connects to a real conversation with the Person (or with an authorized Guardian per the comms-routing rule in coordination/domains/sales.md). Voicemail, busy signal, no-answer, and disconnected number do NOT fire this event; they increment the cadence counter without producing lead.reached. Producer SHALL emit inside the same Prisma transaction that records the reach in the Lead's reach history.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"required": [
|
|
9
|
+
"lead_id",
|
|
10
|
+
"attempt_number",
|
|
11
|
+
"reached_at"
|
|
12
|
+
],
|
|
13
|
+
"properties": {
|
|
14
|
+
"lead_id": {
|
|
15
|
+
"type": "string",
|
|
16
|
+
"description": "The Lead reached. lead_<UUID v7 canonical> per ADR-0002.",
|
|
17
|
+
"pattern": "^lead_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
|
|
18
|
+
},
|
|
19
|
+
"attempt_number": {
|
|
20
|
+
"type": "integer",
|
|
21
|
+
"description": "Which attempt out of the four-attempt cap connected. 1-indexed.",
|
|
22
|
+
"minimum": 1,
|
|
23
|
+
"maximum": 4
|
|
24
|
+
},
|
|
25
|
+
"reached_at": {
|
|
26
|
+
"type": "string",
|
|
27
|
+
"format": "date-time",
|
|
28
|
+
"description": "When the call connected. Sales' wall-clock at the moment the reach was recorded. UTC."
|
|
29
|
+
},
|
|
30
|
+
"outcome": {
|
|
31
|
+
"type": ["string", "null"],
|
|
32
|
+
"description": "Post-reach disposition. Examples include 'qualified', 'callback_requested', 'not_interested', 'wrong_number', 'guardian_only', 'other'. Flexible string at v1.0.0; tightening to a closed enum is a v1.1 candidate per §8 of the contract once the disposition taxonomy stabilizes in production."
|
|
33
|
+
},
|
|
34
|
+
"operator_id": {
|
|
35
|
+
"type": ["string", "null"],
|
|
36
|
+
"description": "The operator who made the call. Sales-internal id format at v1.0.0 (carried as flexible string). Null only if the reach was recorded without operator attribution, which SHOULD be a rare path."
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://contracts.sguild/lead-lifecycle/schema/payloads/lead.stage.changed-v1.json",
|
|
4
|
+
"title": "lead.stage.changed payload v1",
|
|
5
|
+
"description": "Payload for the lead.stage.changed event_type per contracts/lead-lifecycle/README.md §4.2. Emitted by Sales on every Lead stage transition. The broad state-transition event; subscribers tracking stage progression read this rather than synthesizing it from the specialized events (lead.reached, lead.callback.scheduled, lead.attempt.exhausted), each of which may co-fire alongside lead.stage.changed when both apply. Producer SHALL emit inside the same Prisma transaction that updates the Lead row.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"required": [
|
|
9
|
+
"lead_id",
|
|
10
|
+
"from_stage",
|
|
11
|
+
"to_stage",
|
|
12
|
+
"transition_reason",
|
|
13
|
+
"transition_at"
|
|
14
|
+
],
|
|
15
|
+
"properties": {
|
|
16
|
+
"lead_id": {
|
|
17
|
+
"type": "string",
|
|
18
|
+
"description": "The Lead transitioning. lead_<UUID v7 canonical> per ADR-0002.",
|
|
19
|
+
"pattern": "^lead_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
|
|
20
|
+
},
|
|
21
|
+
"from_stage": {
|
|
22
|
+
"type": "string",
|
|
23
|
+
"description": "The Lead's stage before the transition. Flexible string at v1.0.0 (Sales' stage taxonomy is open-ended at this version); examples include 'new', 'pending_match', 'qualified', 'callback_scheduled', 'attempt_exhausted', 'handed_off'. Tightening to a closed enum is a v1.1 candidate per §8 of the contract."
|
|
24
|
+
},
|
|
25
|
+
"to_stage": {
|
|
26
|
+
"type": "string",
|
|
27
|
+
"description": "The Lead's stage after the transition. Flexible string at v1.0.0; same value space as from_stage."
|
|
28
|
+
},
|
|
29
|
+
"transition_reason": {
|
|
30
|
+
"type": "string",
|
|
31
|
+
"enum": ["operator_action", "cadence_runtime", "inbound_event"],
|
|
32
|
+
"description": "What drove the transition. 'operator_action' for human-driven (qualifying, scheduling a callback, etc.); 'cadence_runtime' for Sales' cadence runtime (incrementing attempt count, hitting the four-attempt cap); 'inbound_event' for transitions driven by a subscribed event (customer.handoff arriving and closing the Lead, intake.matched arriving with person_id)."
|
|
33
|
+
},
|
|
34
|
+
"transition_at": {
|
|
35
|
+
"type": "string",
|
|
36
|
+
"format": "date-time",
|
|
37
|
+
"description": "When the transition fired. Sales' wall-clock at commit. UTC."
|
|
38
|
+
},
|
|
39
|
+
"transitioned_by": {
|
|
40
|
+
"type": ["string", "null"],
|
|
41
|
+
"description": "Operator identity when transition_reason is 'operator_action'. Null for system-driven transitions ('cadence_runtime' and 'inbound_event'). Operator id format is Sales-internal at v1.0.0 (carried as flexible string)."
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://contracts.sguild/payment-flow/schema/payloads/payment.failed-v1.json",
|
|
4
|
+
"title": "payment.failed payload v1",
|
|
5
|
+
"description": "Payload for the payment.failed event_type per contracts/payment-flow/README.md §4.2. Emitted by Revenue at the writeback transaction commit when the provider has reported a payment failure and Revenue has recorded the failure as an external-actions row. The order does NOT flip to PAID on this event. Producer SHALL emit inside the same Prisma transaction as the external-actions row insert per ADR-0009. Subscribers: Sales (Lead reactivation routing differs by failure cause), Growth (funnel attribution), platform-warehouse. Delivery does not subscribe at v1; the order's status is unchanged so no Delivery-visible state changes.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"required": [
|
|
9
|
+
"order_id",
|
|
10
|
+
"person_id",
|
|
11
|
+
"payment_method",
|
|
12
|
+
"payment_path",
|
|
13
|
+
"amount_cents",
|
|
14
|
+
"currency",
|
|
15
|
+
"provider_ref",
|
|
16
|
+
"failed_at",
|
|
17
|
+
"failure_code",
|
|
18
|
+
"failure_reason"
|
|
19
|
+
],
|
|
20
|
+
"properties": {
|
|
21
|
+
"order_id": {
|
|
22
|
+
"type": "string",
|
|
23
|
+
"description": "The Revenue-owned Order the failed payment was attempted against. ord_<UUID v7>.",
|
|
24
|
+
"pattern": "^ord_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
|
|
25
|
+
},
|
|
26
|
+
"person_id": {
|
|
27
|
+
"type": "string",
|
|
28
|
+
"description": "The Person whose payment attempt failed. per_<UUID v7>.",
|
|
29
|
+
"pattern": "^per_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
|
|
30
|
+
},
|
|
31
|
+
"payment_method": {
|
|
32
|
+
"type": "string",
|
|
33
|
+
"description": "Payment method attempted per §4.3.",
|
|
34
|
+
"enum": [
|
|
35
|
+
"card",
|
|
36
|
+
"ach",
|
|
37
|
+
"cash",
|
|
38
|
+
"check",
|
|
39
|
+
"credit_balance"
|
|
40
|
+
]
|
|
41
|
+
},
|
|
42
|
+
"payment_path": {
|
|
43
|
+
"type": "string",
|
|
44
|
+
"description": "Writeback path per §4.1.",
|
|
45
|
+
"enum": [
|
|
46
|
+
"invoice_paid",
|
|
47
|
+
"active_charge"
|
|
48
|
+
]
|
|
49
|
+
},
|
|
50
|
+
"amount_cents": {
|
|
51
|
+
"type": "integer",
|
|
52
|
+
"description": "Amount of the attempted payment in the smallest currency unit.",
|
|
53
|
+
"minimum": 1
|
|
54
|
+
},
|
|
55
|
+
"currency": {
|
|
56
|
+
"type": "string",
|
|
57
|
+
"description": "ISO-4217 currency code.",
|
|
58
|
+
"pattern": "^[A-Z]{3}$"
|
|
59
|
+
},
|
|
60
|
+
"provider_ref": {
|
|
61
|
+
"type": "string",
|
|
62
|
+
"description": "Provider-side identifier for the failed attempt. Square payment id for paths that reached the provider; external-actions row id (ext_ prefix) for paths that failed before the provider call.",
|
|
63
|
+
"minLength": 1
|
|
64
|
+
},
|
|
65
|
+
"failed_at": {
|
|
66
|
+
"type": "string",
|
|
67
|
+
"format": "date-time",
|
|
68
|
+
"description": "Wall-clock UTC timestamp at the writeback transaction commit. Producer's clock."
|
|
69
|
+
},
|
|
70
|
+
"failure_code": {
|
|
71
|
+
"type": "string",
|
|
72
|
+
"description": "Failure cause per §4.4. Consumers route on this field; consumers SHALL treat unknown values as safe-to-ignore per §8. Phase-2 narrowing may add values without a major version bump.",
|
|
73
|
+
"enum": [
|
|
74
|
+
"card_declined",
|
|
75
|
+
"insufficient_funds",
|
|
76
|
+
"expired_card",
|
|
77
|
+
"network_error",
|
|
78
|
+
"provider_unavailable",
|
|
79
|
+
"other"
|
|
80
|
+
]
|
|
81
|
+
},
|
|
82
|
+
"failure_reason": {
|
|
83
|
+
"type": "string",
|
|
84
|
+
"description": "Free-form provider-side message. Consumers SHALL NOT parse this field; the format is provider-specific and may change without contract bump. Use failure_code for routing.",
|
|
85
|
+
"minLength": 1
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://contracts.sguild/payment-flow/schema/payloads/payment.received-v1.json",
|
|
4
|
+
"title": "payment.received payload v1",
|
|
5
|
+
"description": "Payload for the payment.received event_type per contracts/payment-flow/README.md §4.1. Emitted by Revenue at the writeback transaction commit for a successful payment. Producer SHALL emit inside the same Prisma transaction as the order-status update per ADR-0009. Subscribers: Sales (Lead reactivation close), Growth (funnel-close attribution), Delivery (awareness of credit availability), platform-warehouse.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"required": [
|
|
9
|
+
"order_id",
|
|
10
|
+
"person_id",
|
|
11
|
+
"payment_method",
|
|
12
|
+
"payment_path",
|
|
13
|
+
"amount_cents",
|
|
14
|
+
"currency",
|
|
15
|
+
"provider_ref",
|
|
16
|
+
"received_at"
|
|
17
|
+
],
|
|
18
|
+
"properties": {
|
|
19
|
+
"order_id": {
|
|
20
|
+
"type": "string",
|
|
21
|
+
"description": "The Revenue-owned Order this payment satisfies. ord_<UUID v7>.",
|
|
22
|
+
"pattern": "^ord_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
|
|
23
|
+
},
|
|
24
|
+
"person_id": {
|
|
25
|
+
"type": "string",
|
|
26
|
+
"description": "The Person who paid. Sourced from the Order's client per the Identity canonical surface. per_<UUID v7>.",
|
|
27
|
+
"pattern": "^per_[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
|
|
28
|
+
},
|
|
29
|
+
"payment_method": {
|
|
30
|
+
"type": "string",
|
|
31
|
+
"description": "Payment method per §4.3. Consumers SHALL treat unknown values as safe-to-ignore per §8.",
|
|
32
|
+
"enum": [
|
|
33
|
+
"card",
|
|
34
|
+
"ach",
|
|
35
|
+
"cash",
|
|
36
|
+
"check",
|
|
37
|
+
"credit_balance"
|
|
38
|
+
]
|
|
39
|
+
},
|
|
40
|
+
"payment_path": {
|
|
41
|
+
"type": "string",
|
|
42
|
+
"description": "Writeback path per §4.1. invoice_paid for the asynchronous webhook-driven path through runApplyInvoicePayment; active_charge for the synchronous path through runChargeOrder.",
|
|
43
|
+
"enum": [
|
|
44
|
+
"invoice_paid",
|
|
45
|
+
"active_charge"
|
|
46
|
+
]
|
|
47
|
+
},
|
|
48
|
+
"amount_cents": {
|
|
49
|
+
"type": "integer",
|
|
50
|
+
"description": "Amount of the payment in the smallest currency unit (cents for USD).",
|
|
51
|
+
"minimum": 1
|
|
52
|
+
},
|
|
53
|
+
"currency": {
|
|
54
|
+
"type": "string",
|
|
55
|
+
"description": "ISO-4217 currency code. USD at v1 in production.",
|
|
56
|
+
"pattern": "^[A-Z]{3}$"
|
|
57
|
+
},
|
|
58
|
+
"provider_ref": {
|
|
59
|
+
"type": "string",
|
|
60
|
+
"description": "Provider-side identifier for the payment per the funding-state external-reference rule. Square payment id for card/ach paths (sqpay_<id>); external-actions row id prefixed with ext_ for cash/check/credit_balance paths.",
|
|
61
|
+
"minLength": 1
|
|
62
|
+
},
|
|
63
|
+
"received_at": {
|
|
64
|
+
"type": "string",
|
|
65
|
+
"format": "date-time",
|
|
66
|
+
"description": "Wall-clock UTC timestamp at the writeback transaction commit. Producer's clock."
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|