@ingenx-io/valets-schema-mcp-server 0.2.3 → 0.2.5

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.
Files changed (76) hide show
  1. package/README.md +26 -0
  2. package/data/docs/collections/firestore-paths.md +32 -20
  3. package/data/docs/enums/app-status.md +24 -0
  4. package/data/docs/enums/attention-status.md +2 -2
  5. package/data/docs/enums/booking-status.md +2 -2
  6. package/data/docs/enums/customer-payment-status.md +2 -2
  7. package/data/docs/enums/customer-payment-target-type.md +2 -2
  8. package/data/docs/enums/delivery-type.md +2 -2
  9. package/data/docs/enums/deployment-link-type.md +2 -2
  10. package/data/docs/enums/event-status.md +2 -2
  11. package/data/docs/enums/fulfillment-status.md +2 -2
  12. package/data/docs/enums/loyalty-transaction-type.md +2 -2
  13. package/data/docs/enums/notification-channel.md +2 -2
  14. package/data/docs/enums/notification-entity-type.md +2 -2
  15. package/data/docs/enums/notification-status.md +2 -2
  16. package/data/docs/enums/order-status.md +2 -2
  17. package/data/docs/enums/outbound-message-format.md +2 -2
  18. package/data/docs/enums/outbound-message-purpose.md +2 -2
  19. package/data/docs/enums/outbound-message-status.md +2 -2
  20. package/data/docs/enums/payment-method.md +2 -2
  21. package/data/docs/enums/payment-proof-status.md +2 -2
  22. package/data/docs/enums/payment-status.md +2 -2
  23. package/data/docs/enums/pending-issue.md +2 -2
  24. package/data/docs/enums/return-status.md +2 -2
  25. package/data/docs/enums/session-status.md +2 -2
  26. package/data/docs/enums/site-status.md +2 -2
  27. package/data/docs/enums/stocktake-frequency.md +2 -2
  28. package/data/docs/enums/stocktake-item-status.md +2 -2
  29. package/data/docs/enums/stocktake-status.md +2 -2
  30. package/data/docs/enums/ticket-status.md +2 -2
  31. package/data/docs/enums/waba-label.md +2 -2
  32. package/data/docs/enums/whatsapp-button-sub-type.md +2 -2
  33. package/data/docs/enums/whatsapp-template-component.md +2 -2
  34. package/data/docs/enums/whatsapp-template-status.md +2 -2
  35. package/data/docs/index.md +9 -5
  36. package/data/docs/models/allowed-user.md +7 -7
  37. package/data/docs/models/analytics-backfill.md +7 -7
  38. package/data/docs/models/analytics-daily.md +6 -6
  39. package/data/docs/models/analytics-event.md +7 -7
  40. package/data/docs/models/analytics-hourly.md +6 -6
  41. package/data/docs/models/app-payment.md +200 -0
  42. package/data/docs/models/app.md +561 -0
  43. package/data/docs/models/booking-version.md +2 -2
  44. package/data/docs/models/booking.md +127 -127
  45. package/data/docs/models/customer-payment-allocation.md +20 -20
  46. package/data/docs/models/customer-payment.md +23 -23
  47. package/data/docs/models/customer.md +11 -11
  48. package/data/docs/models/event.md +22 -22
  49. package/data/docs/models/loyalty-config.md +4 -4
  50. package/data/docs/models/loyalty-reward.md +3 -3
  51. package/data/docs/models/loyalty-status.md +6 -6
  52. package/data/docs/models/loyalty-transaction.md +2 -2
  53. package/data/docs/models/magic-link-request.md +9 -9
  54. package/data/docs/models/metrics-current.md +169 -37
  55. package/data/docs/models/metrics-daily.md +172 -40
  56. package/data/docs/models/metrics-monthly.md +172 -40
  57. package/data/docs/models/notification-record.md +3 -3
  58. package/data/docs/models/order-item.md +6 -6
  59. package/data/docs/models/order.md +78 -78
  60. package/data/docs/models/sale.md +18 -18
  61. package/data/docs/models/site-payment.md +2 -2
  62. package/data/docs/models/site.md +2 -2
  63. package/data/docs/models/stocktake-item.md +4 -4
  64. package/data/docs/models/stocktake.md +5 -5
  65. package/data/docs/models/ticket.md +3 -3
  66. package/data/docs/models/user.md +249 -0
  67. package/data/docs/models/whatsapp-inbound-message.md +2 -2
  68. package/data/docs/models/whatsapp-outbound-lifecycle-event.md +2 -2
  69. package/data/docs/models/whatsapp-outbound-message.md +6 -6
  70. package/data/docs/models/whatsapp-template.md +2 -2
  71. package/data/static/cookbook.json +150 -0
  72. package/data/static/llms.txt +179 -33
  73. package/data/static/openapi.yaml +626 -60
  74. package/data/static/schemas.json +680 -69
  75. package/index.js +32 -0
  76. package/package.json +1 -1
@@ -20,6 +20,16 @@ info:
20
20
  paths: {}
21
21
  components:
22
22
  schemas:
23
+ AppStatus:
24
+ type: string
25
+ enum:
26
+ - ACTIVE
27
+ - INACTIVE
28
+ - EXPIRED
29
+ - ARCHIVED
30
+ description: 'Lifecycle status for an App (formerly Site — renamed per decision
31
+ #40 / D44). Drives whether the app is reachable and whether analytics/payments
32
+ flow.'
23
33
  AttentionStatus:
24
34
  type: string
25
35
  enum:
@@ -345,7 +355,9 @@ components:
345
355
  - _seconds
346
356
  - _nanoseconds
347
357
  additionalProperties: false
348
- description: Firestore Timestamp serialized representation
358
+ description: 'Firestore Timestamp Admin SDK form: { _seconds, _nanoseconds
359
+ }. See types/firestore.ts for REST API v1 and client SDK serialization notes
360
+ (#10).'
349
361
  AllowedUser:
350
362
  type: object
351
363
  properties:
@@ -360,10 +372,11 @@ components:
360
372
  type: string
361
373
  x-immutable: true
362
374
  description: (Immutable) FK → Company document ID.
363
- siteId:
375
+ appId:
364
376
  type: string
365
377
  x-immutable: true
366
- description: (Immutable) FK → Site document ID (D40 sub-tenant scope).
378
+ description: (Immutable) FK → App document ID (D40 sub-tenant scope, renamed
379
+ per D44).
367
380
  contact:
368
381
  type: string
369
382
  description: Email or E.164 phone number. Canonical identifier for this
@@ -388,7 +401,7 @@ components:
388
401
  description: RFC3339Nano UTC when payment was completed.
389
402
  required:
390
403
  - companyId
391
- - siteId
404
+ - appId
392
405
  - contact
393
406
  - tier
394
407
  - amount
@@ -396,7 +409,7 @@ components:
396
409
  - transactionId
397
410
  - paidAt
398
411
  additionalProperties: false
399
- description: 'AllowedUser model (D40 / ING-304). Collection: companies/{companyId}/sites/{siteId}/allowed_users/{contactId}.
412
+ description: 'AllowedUser model (D40 / ING-304). Collection: companies/{companyId}/apps/{appId}/allowed_users/{contactId}.
400
413
  Authoritative paid-access allowlist. Upsert semantics — tier upgrades overwrite.
401
414
  Source of truth for access checks and referral code resolution.'
402
415
  AllowedUserCreate:
@@ -407,7 +420,7 @@ components:
407
420
  may be set once at creation.
408
421
  required:
409
422
  - companyId
410
- - siteId
423
+ - appId
411
424
  - contact
412
425
  - tier
413
426
  - amount
@@ -433,7 +446,7 @@ components:
433
446
  type: string
434
447
  x-immutable: true
435
448
  description: (Immutable) FK → Company document ID.
436
- siteId:
449
+ appId:
437
450
  type: string
438
451
  x-immutable: true
439
452
  description: (Immutable) FK → Site document ID (D40).
@@ -501,7 +514,7 @@ components:
501
514
  description: (Read-only) When the run reached a terminal status.
502
515
  required:
503
516
  - companyId
504
- - siteId
517
+ - appId
505
518
  - status
506
519
  - from
507
520
  - to
@@ -511,7 +524,7 @@ components:
511
524
  - triggeredBy
512
525
  - startedAt
513
526
  additionalProperties: false
514
- description: 'AnalyticsBackfill run (D42 / ING-304). Collection: companies/{companyId}/sites/{siteId}/analytics_backfills/{runId}.
527
+ description: 'AnalyticsBackfill run (D42 / ING-304). Collection: companies/{companyId}/apps/{appId}/analytics_backfills/{runId}.
515
528
  Tracks admin-triggered rollup backfill jobs; supports dry-run.'
516
529
  AnalyticsBackfillCreate:
517
530
  allOf:
@@ -521,7 +534,7 @@ components:
521
534
  may be set once at creation.
522
535
  required:
523
536
  - companyId
524
- - siteId
537
+ - appId
525
538
  - status
526
539
  - from
527
540
  - to
@@ -607,7 +620,7 @@ components:
607
620
  type: string
608
621
  x-immutable: true
609
622
  description: (Immutable) FK → Company document ID.
610
- siteId:
623
+ appId:
611
624
  type: string
612
625
  x-immutable: true
613
626
  description: (Immutable) FK → Site document ID (D40).
@@ -641,11 +654,11 @@ components:
641
654
  - errors
642
655
  - eventCounts
643
656
  - companyId
644
- - siteId
657
+ - appId
645
658
  - date
646
659
  - computedAt
647
660
  additionalProperties: false
648
- description: 'AnalyticsDaily rollup (D42 / ING-304). Collection: companies/{companyId}/sites/{siteId}/analytics_daily/{YYYY-MM-DD}.
661
+ description: 'AnalyticsDaily rollup (D42 / ING-304). Collection: companies/{companyId}/apps/{appId}/analytics_daily/{YYYY-MM-DD}.
649
662
  Idempotent set/merge — reruns overwrite. Fall back to raw analytics_events
650
663
  for uncovered slices.'
651
664
  AnalyticsDailyCreate:
@@ -666,7 +679,7 @@ components:
666
679
  - errors
667
680
  - eventCounts
668
681
  - companyId
669
- - siteId
682
+ - appId
670
683
  - date
671
684
  AnalyticsDailyUpdate:
672
685
  allOf:
@@ -687,10 +700,11 @@ components:
687
700
  type: string
688
701
  x-immutable: true
689
702
  description: (Immutable) FK → Company document ID.
690
- siteId:
703
+ appId:
691
704
  type: string
692
705
  x-immutable: true
693
- description: (Immutable) FK → Site document ID (D40 sub-tenant scope).
706
+ description: (Immutable) FK → App document ID (D40 sub-tenant scope, renamed
707
+ per D44).
694
708
  eventId:
695
709
  type: string
696
710
  x-immutable: true
@@ -806,7 +820,7 @@ components:
806
820
  additionalProperties: {}
807
821
  required:
808
822
  - companyId
809
- - siteId
823
+ - appId
810
824
  - eventId
811
825
  - eventName
812
826
  - timestamp
@@ -816,7 +830,7 @@ components:
816
830
  - properties
817
831
  - context
818
832
  additionalProperties: false
819
- description: 'AnalyticsEvent model (D40 / ING-304). Collection: companies/{companyId}/sites/{siteId}/analytics_events/{eventId}.
833
+ description: 'AnalyticsEvent model (D40 / ING-304). Collection: companies/{companyId}/apps/{appId}/analytics_events/{eventId}.
820
834
  Append-only, immutable product/behavior event stream. Event names are free
821
835
  strings; canonical vocabulary in CANONICAL_ANALYTICS_EVENT_NAMES.'
822
836
  AnalyticsEventCreate:
@@ -827,7 +841,7 @@ components:
827
841
  may be set once at creation.
828
842
  required:
829
843
  - companyId
830
- - siteId
844
+ - appId
831
845
  - eventId
832
846
  - eventName
833
847
  - timestamp
@@ -913,7 +927,7 @@ components:
913
927
  type: string
914
928
  x-immutable: true
915
929
  description: (Immutable) FK → Company document ID.
916
- siteId:
930
+ appId:
917
931
  type: string
918
932
  x-immutable: true
919
933
  description: (Immutable) FK → Site document ID (D40).
@@ -952,12 +966,12 @@ components:
952
966
  - errors
953
967
  - eventCounts
954
968
  - companyId
955
- - siteId
969
+ - appId
956
970
  - date
957
971
  - hour
958
972
  - computedAt
959
973
  additionalProperties: false
960
- description: 'AnalyticsHourly rollup (D42 / ING-304). Collection: companies/{companyId}/sites/{siteId}/analytics_hourly/{YYYY-MM-DD-HH}.
974
+ description: 'AnalyticsHourly rollup (D42 / ING-304). Collection: companies/{companyId}/apps/{appId}/analytics_hourly/{YYYY-MM-DD-HH}.
961
975
  Scheduled-CF writer; idempotent set/merge.'
962
976
  AnalyticsHourlyCreate:
963
977
  allOf:
@@ -977,7 +991,7 @@ components:
977
991
  - errors
978
992
  - eventCounts
979
993
  - companyId
980
- - siteId
994
+ - appId
981
995
  - date
982
996
  - hour
983
997
  AnalyticsHourlyUpdate:
@@ -986,6 +1000,265 @@ components:
986
1000
  description: Write payload for partial update (PATCH) of a AnalyticsHourly document.
987
1001
  All fields optional. Fields marked `readOnly` or `x-immutable` must not be
988
1002
  sent.
1003
+ App:
1004
+ type: object
1005
+ properties:
1006
+ id:
1007
+ readOnly: true
1008
+ description: (Read-only) Firestore document ID, auto-generated.
1009
+ type:
1010
+ - string
1011
+ - 'null'
1012
+ companyId:
1013
+ type: string
1014
+ x-immutable: true
1015
+ description: (Immutable) FK → Company document ID. Scopes all app sub-collections.
1016
+ name:
1017
+ type: string
1018
+ description: Human-readable app name shown in dashboards.
1019
+ description:
1020
+ description: Optional freeform description.
1021
+ type:
1022
+ - string
1023
+ - 'null'
1024
+ status:
1025
+ $ref: '#/components/schemas/AppStatus'
1026
+ description: Lifecycle status (D41/D44). Clients filter by ACTIVE.
1027
+ x-note: ACTIVE = live and serving traffic. INACTIVE = intentionally disabled
1028
+ by operators. EXPIRED = past expiresAt (derived when isExpired is true;
1029
+ may also be stored explicitly). ARCHIVED = soft-deleted; retained for
1030
+ audit but not listed by default.
1031
+ x-see:
1032
+ decisions:
1033
+ - D41
1034
+ - D44
1035
+ x-when: Written by operators via dashboard or by server triggers (expiration).
1036
+ Clients filter by ACTIVE.
1037
+ deploymentLinks:
1038
+ type: array
1039
+ items:
1040
+ type: object
1041
+ properties:
1042
+ label:
1043
+ type: string
1044
+ description: Human-readable label shown in dashboards (e.g. "Production",
1045
+ "Staging").
1046
+ url:
1047
+ type: string
1048
+ description: Absolute URL or store link.
1049
+ type:
1050
+ $ref: '#/components/schemas/DeploymentLinkType'
1051
+ description: Link category — drives icon/handler selection.
1052
+ x-note: Lowercase by convention — deployment link types are display-oriented
1053
+ labels, not lifecycle states.
1054
+ x-see:
1055
+ decisions:
1056
+ - D41
1057
+ isPrimary:
1058
+ description: If true, this link is used as the canonical deployment
1059
+ URL for the App.
1060
+ type: boolean
1061
+ required:
1062
+ - label
1063
+ - url
1064
+ - type
1065
+ additionalProperties: false
1066
+ description: Deployment link entry embedded on App.deploymentLinks[] (D41).
1067
+ description: Ordered list of deployment URLs (web, mobile, PWA, store links).
1068
+ expiresAt:
1069
+ anyOf:
1070
+ - $ref: '#/components/schemas/FirestoreTimestamp'
1071
+ - type: 'null'
1072
+ description: Optional expiration timestamp. When set and elapsed, `isExpired`
1073
+ flips true and status typically moves to EXPIRED.
1074
+ isExpired:
1075
+ readOnly: true
1076
+ description: (Read-only) Derived — true when `expiresAt` is in the past.
1077
+ Maintained by server trigger.
1078
+ type:
1079
+ - boolean
1080
+ - 'null'
1081
+ createdAt:
1082
+ anyOf:
1083
+ - $ref: '#/components/schemas/FirestoreTimestamp'
1084
+ - type: 'null'
1085
+ readOnly: true
1086
+ description: (Read-only) Server-generated creation timestamp.
1087
+ updatedAt:
1088
+ anyOf:
1089
+ - $ref: '#/components/schemas/FirestoreTimestamp'
1090
+ - type: 'null'
1091
+ readOnly: true
1092
+ description: (Read-only) Server-generated update timestamp.
1093
+ createdBy:
1094
+ type: string
1095
+ x-immutable: true
1096
+ description: (Immutable) FK → User/staff UID who created the app.
1097
+ analyticsEnabled:
1098
+ type: boolean
1099
+ description: Feature flag — when false, clients should not emit analytics
1100
+ events for this app.
1101
+ lastAnalyticsSync:
1102
+ anyOf:
1103
+ - $ref: '#/components/schemas/FirestoreTimestamp'
1104
+ - type: 'null'
1105
+ readOnly: true
1106
+ description: (Read-only) Last time the analytics rollup pipeline refreshed
1107
+ `cachedMetrics`.
1108
+ cachedMetrics:
1109
+ readOnly: true
1110
+ denormalized: true
1111
+ x-note: Updated by the rollup pipeline (D42). Readers should treat this
1112
+ as a hint; authoritative counts live in analytics_daily/analytics_hourly.
1113
+ x-see:
1114
+ decisions:
1115
+ - D41
1116
+ - D42
1117
+ description: (Read-only, Denormalized) Cached metrics snapshot for quick
1118
+ dashboard rendering.
1119
+ type:
1120
+ - object
1121
+ - 'null'
1122
+ properties:
1123
+ totalEvents:
1124
+ type: integer
1125
+ minimum: -9007199254740991
1126
+ maximum: 9007199254740991
1127
+ description: All-time event count cached on the App.
1128
+ totalPageViews:
1129
+ type: integer
1130
+ minimum: -9007199254740991
1131
+ maximum: 9007199254740991
1132
+ description: All-time `page_view` + `screen_view` count.
1133
+ totalSessions:
1134
+ type: integer
1135
+ minimum: -9007199254740991
1136
+ maximum: 9007199254740991
1137
+ description: All-time distinct session count.
1138
+ totalOrders:
1139
+ type: integer
1140
+ minimum: -9007199254740991
1141
+ maximum: 9007199254740991
1142
+ description: All-time order count attributed to this app (via `Order.appId`,
1143
+ D43).
1144
+ lastEventAt:
1145
+ $ref: '#/components/schemas/FirestoreTimestamp'
1146
+ description: Timestamp of the most recent analytics event seen for this
1147
+ app.
1148
+ required:
1149
+ - totalEvents
1150
+ - totalPageViews
1151
+ - totalSessions
1152
+ - totalOrders
1153
+ additionalProperties: false
1154
+ required:
1155
+ - companyId
1156
+ - name
1157
+ - status
1158
+ - deploymentLinks
1159
+ - createdBy
1160
+ - analyticsEnabled
1161
+ additionalProperties: false
1162
+ description: 'App model (D41 / ING-304). Collection: companies/{companyId}/apps/{appId}.
1163
+ Per-company product surface. Sub-collections (magic_link_requests, allowed_users,
1164
+ payments, analytics_events, analytics_daily, analytics_hourly, analytics_backfills)
1165
+ live under this document per D40/D42.'
1166
+ AppCreate:
1167
+ allOf:
1168
+ - $ref: '#/components/schemas/App'
1169
+ description: Write payload for creating a new App document. Fields marked `readOnly`
1170
+ are server-set and must not be included. Fields marked `x-immutable` may be
1171
+ set once at creation.
1172
+ required:
1173
+ - companyId
1174
+ - name
1175
+ - status
1176
+ - deploymentLinks
1177
+ - createdBy
1178
+ - analyticsEnabled
1179
+ AppUpdate:
1180
+ allOf:
1181
+ - $ref: '#/components/schemas/App'
1182
+ description: Write payload for partial update (PATCH) of a App document. All
1183
+ fields optional. Fields marked `readOnly` or `x-immutable` must not be sent.
1184
+ AppPayment:
1185
+ type: object
1186
+ properties:
1187
+ id:
1188
+ readOnly: true
1189
+ description: (Read-only) Firestore document ID, auto-generated.
1190
+ type:
1191
+ - string
1192
+ - 'null'
1193
+ companyId:
1194
+ type: string
1195
+ x-immutable: true
1196
+ description: (Immutable) FK → Company document ID.
1197
+ appId:
1198
+ type: string
1199
+ x-immutable: true
1200
+ description: (Immutable) FK → App document ID (D40 sub-tenant scope, renamed
1201
+ from siteId per D44).
1202
+ contact:
1203
+ type: string
1204
+ description: Email or E.164 phone number. Matches AllowedUser.contact.
1205
+ sessionId:
1206
+ type: string
1207
+ description: Payment provider checkout session ID (e.g. Wave). Usable for
1208
+ dedup across dual writes.
1209
+ transactionId:
1210
+ type: string
1211
+ description: Payment provider transaction ID.
1212
+ tier:
1213
+ type: string
1214
+ description: Access tier. Free string per app (ING-304 open question).
1215
+ amount:
1216
+ type: number
1217
+ description: Amount paid. Generalized from amount_xof per D40 decision.
1218
+ currency:
1219
+ default: XOF
1220
+ description: Currency code (ISO 4217). Defaults to XOF for legacy SR-Single
1221
+ parity.
1222
+ type: string
1223
+ paidAt:
1224
+ $ref: '#/components/schemas/FirestoreTimestamp'
1225
+ description: RFC3339Nano UTC when payment was completed.
1226
+ required:
1227
+ - companyId
1228
+ - appId
1229
+ - contact
1230
+ - sessionId
1231
+ - transactionId
1232
+ - tier
1233
+ - amount
1234
+ - currency
1235
+ - paidAt
1236
+ additionalProperties: false
1237
+ description: 'AppPayment model (D40 / ING-304). Collection: companies/{companyId}/apps/{appId}/payments/{paymentId}.
1238
+ Immutable append-only transaction ledger. Distinct from AllowedUser (access
1239
+ state) and CustomerPayment (D22 — customer-level billing).'
1240
+ AppPaymentCreate:
1241
+ allOf:
1242
+ - $ref: '#/components/schemas/AppPayment'
1243
+ description: Write payload for creating a new AppPayment document. Fields marked
1244
+ `readOnly` are server-set and must not be included. Fields marked `x-immutable`
1245
+ may be set once at creation.
1246
+ required:
1247
+ - companyId
1248
+ - appId
1249
+ - contact
1250
+ - sessionId
1251
+ - transactionId
1252
+ - tier
1253
+ - amount
1254
+ - currency
1255
+ - paidAt
1256
+ AppPaymentUpdate:
1257
+ allOf:
1258
+ - $ref: '#/components/schemas/AppPayment'
1259
+ description: Write payload for partial update (PATCH) of a AppPayment document.
1260
+ All fields optional. Fields marked `readOnly` or `x-immutable` must not be
1261
+ sent.
989
1262
  Booking:
990
1263
  type: object
991
1264
  properties:
@@ -1062,13 +1335,17 @@ components:
1062
1335
  type: boolean
1063
1336
  _deletedAt:
1064
1337
  $ref: '#/components/schemas/FirestoreTimestamp'
1065
- description: Firestore Timestamp serialized representation
1338
+ description: 'Firestore Timestamp Admin SDK form: { _seconds,
1339
+ _nanoseconds }. See types/firestore.ts for REST API v1 and
1340
+ client SDK serialization notes (#10).'
1066
1341
  _deletedBy:
1067
1342
  description: FK → User/staff UID who soft-deleted this item.
1068
1343
  type: string
1069
1344
  _lastModifiedAt:
1070
1345
  $ref: '#/components/schemas/FirestoreTimestamp'
1071
- description: Firestore Timestamp serialized representation
1346
+ description: 'Firestore Timestamp Admin SDK form: { _seconds,
1347
+ _nanoseconds }. See types/firestore.ts for REST API v1 and
1348
+ client SDK serialization notes (#10).'
1072
1349
  _lastModifiedBy:
1073
1350
  description: FK → User/staff UID who last modified this item.
1074
1351
  type: string
@@ -1133,7 +1410,9 @@ components:
1133
1410
  type: string
1134
1411
  additionalProperties:
1135
1412
  $ref: '#/components/schemas/FirestoreTimestamp'
1136
- description: Firestore Timestamp serialized representation
1413
+ description: 'Firestore Timestamp Admin SDK form: { _seconds,
1414
+ _nanoseconds }. See types/firestore.ts for REST API v1 and client
1415
+ SDK serialization notes (#10).'
1137
1416
  slotStatusUpdatedBy:
1138
1417
  type: object
1139
1418
  propertyNames:
@@ -1145,13 +1424,17 @@ components:
1145
1424
  type: boolean
1146
1425
  _deletedAt:
1147
1426
  $ref: '#/components/schemas/FirestoreTimestamp'
1148
- description: Firestore Timestamp serialized representation
1427
+ description: 'Firestore Timestamp Admin SDK form: { _seconds, _nanoseconds
1428
+ }. See types/firestore.ts for REST API v1 and client SDK serialization
1429
+ notes (#10).'
1149
1430
  _deletedBy:
1150
1431
  description: FK → User/staff UID who soft-deleted this item.
1151
1432
  type: string
1152
1433
  _lastModifiedAt:
1153
1434
  $ref: '#/components/schemas/FirestoreTimestamp'
1154
- description: Firestore Timestamp serialized representation
1435
+ description: 'Firestore Timestamp Admin SDK form: { _seconds, _nanoseconds
1436
+ }. See types/firestore.ts for REST API v1 and client SDK serialization
1437
+ notes (#10).'
1155
1438
  _lastModifiedBy:
1156
1439
  description: FK → User/staff UID who last modified this item.
1157
1440
  type: string
@@ -1313,13 +1596,17 @@ components:
1313
1596
  type: boolean
1314
1597
  _deletedAt:
1315
1598
  $ref: '#/components/schemas/FirestoreTimestamp'
1316
- description: Firestore Timestamp serialized representation
1599
+ description: 'Firestore Timestamp Admin SDK form: { _seconds, _nanoseconds
1600
+ }. See types/firestore.ts for REST API v1 and client SDK serialization
1601
+ notes (#10).'
1317
1602
  _deletedBy:
1318
1603
  description: FK → User/staff UID who soft-deleted this item.
1319
1604
  type: string
1320
1605
  _lastModifiedAt:
1321
1606
  $ref: '#/components/schemas/FirestoreTimestamp'
1322
- description: Firestore Timestamp serialized representation
1607
+ description: 'Firestore Timestamp Admin SDK form: { _seconds, _nanoseconds
1608
+ }. See types/firestore.ts for REST API v1 and client SDK serialization
1609
+ notes (#10).'
1323
1610
  _lastModifiedBy:
1324
1611
  description: FK → User/staff UID who last modified this item.
1325
1612
  type: string
@@ -1372,7 +1659,9 @@ components:
1372
1659
  anyOf:
1373
1660
  - $ref: '#/components/schemas/FirestoreTimestamp'
1374
1661
  - type: 'null'
1375
- description: Firestore Timestamp serialized representation
1662
+ description: 'Firestore Timestamp Admin SDK form: { _seconds, _nanoseconds
1663
+ }. See types/firestore.ts for REST API v1 and client SDK serialization
1664
+ notes (#10).'
1376
1665
  paymentProofUrl:
1377
1666
  description: URL to uploaded payment proof image/document.
1378
1667
  type:
@@ -1388,7 +1677,9 @@ components:
1388
1677
  anyOf:
1389
1678
  - $ref: '#/components/schemas/FirestoreTimestamp'
1390
1679
  - type: 'null'
1391
- description: Firestore Timestamp serialized representation
1680
+ description: 'Firestore Timestamp Admin SDK form: { _seconds, _nanoseconds
1681
+ }. See types/firestore.ts for REST API v1 and client SDK serialization
1682
+ notes (#10).'
1392
1683
  paymentProofAddedBy:
1393
1684
  description: FK → User/staff UID who uploaded the payment proof.
1394
1685
  type:
@@ -1403,7 +1694,9 @@ components:
1403
1694
  anyOf:
1404
1695
  - $ref: '#/components/schemas/FirestoreTimestamp'
1405
1696
  - type: 'null'
1406
- description: Firestore Timestamp serialized representation
1697
+ description: 'Firestore Timestamp Admin SDK form: { _seconds, _nanoseconds
1698
+ }. See types/firestore.ts for REST API v1 and client SDK serialization
1699
+ notes (#10).'
1407
1700
  paymentProofRejectionReason:
1408
1701
  type:
1409
1702
  - string
@@ -1426,7 +1719,9 @@ components:
1426
1719
  anyOf:
1427
1720
  - $ref: '#/components/schemas/FirestoreTimestamp'
1428
1721
  - type: 'null'
1429
- description: Firestore Timestamp serialized representation
1722
+ description: 'Firestore Timestamp Admin SDK form: { _seconds, _nanoseconds
1723
+ }. See types/firestore.ts for REST API v1 and client SDK serialization
1724
+ notes (#10).'
1430
1725
  cancelledByRole:
1431
1726
  type:
1432
1727
  - string
@@ -1633,7 +1928,9 @@ components:
1633
1928
  properties:
1634
1929
  timestamp:
1635
1930
  $ref: '#/components/schemas/FirestoreTimestamp'
1636
- description: Firestore Timestamp serialized representation
1931
+ description: 'Firestore Timestamp Admin SDK form: { _seconds, _nanoseconds
1932
+ }. See types/firestore.ts for REST API v1 and client SDK serialization
1933
+ notes (#10).'
1637
1934
  type:
1638
1935
  type: string
1639
1936
  description: Communication channel (e.g. phone, email, meeting).
@@ -1750,7 +2047,9 @@ components:
1750
2047
  description: Currency code. Locked to XOF (West African CFA franc) for now.
1751
2048
  paymentDate:
1752
2049
  $ref: '#/components/schemas/FirestoreTimestamp'
1753
- description: Firestore Timestamp serialized representation
2050
+ description: 'Firestore Timestamp Admin SDK form: { _seconds, _nanoseconds
2051
+ }. See types/firestore.ts for REST API v1 and client SDK serialization
2052
+ notes (#10).'
1754
2053
  paymentMethod:
1755
2054
  $ref: '#/components/schemas/PaymentMethod'
1756
2055
  description: Unified payment method set with African + global methods (D02).
@@ -1894,7 +2193,9 @@ components:
1894
2193
  anyOf:
1895
2194
  - $ref: '#/components/schemas/FirestoreTimestamp'
1896
2195
  - type: 'null'
1897
- description: Firestore Timestamp serialized representation
2196
+ description: 'Firestore Timestamp Admin SDK form: { _seconds, _nanoseconds
2197
+ }. See types/firestore.ts for REST API v1 and client SDK serialization
2198
+ notes (#10).'
1898
2199
  createdBy:
1899
2200
  type: string
1900
2201
  x-immutable: true
@@ -1967,12 +2268,16 @@ components:
1967
2268
  - 'null'
1968
2269
  startDate:
1969
2270
  $ref: '#/components/schemas/FirestoreTimestamp'
1970
- description: Firestore Timestamp serialized representation
2271
+ description: 'Firestore Timestamp Admin SDK form: { _seconds, _nanoseconds
2272
+ }. See types/firestore.ts for REST API v1 and client SDK serialization
2273
+ notes (#10).'
1971
2274
  endDate:
1972
2275
  anyOf:
1973
2276
  - $ref: '#/components/schemas/FirestoreTimestamp'
1974
2277
  - type: 'null'
1975
- description: Firestore Timestamp serialized representation
2278
+ description: 'Firestore Timestamp Admin SDK form: { _seconds, _nanoseconds
2279
+ }. See types/firestore.ts for REST API v1 and client SDK serialization
2280
+ notes (#10).'
1976
2281
  status:
1977
2282
  $ref: '#/components/schemas/EventStatus'
1978
2283
  description: Event lifecycle status (D32). SCREAMING_SNAKE per D04. MIG-09
@@ -2417,10 +2722,11 @@ components:
2417
2722
  type: string
2418
2723
  x-immutable: true
2419
2724
  description: (Immutable) FK → Company document ID.
2420
- siteId:
2725
+ appId:
2421
2726
  type: string
2422
2727
  x-immutable: true
2423
- description: (Immutable) FK → Site document ID (D40 sub-tenant scope).
2728
+ description: (Immutable) FK → App document ID (D40 sub-tenant scope, renamed
2729
+ per D44).
2424
2730
  email:
2425
2731
  type: string
2426
2732
  description: Populated if identifier is email; empty string if phone. Mutually
@@ -2472,7 +2778,7 @@ components:
2472
2778
  description: RFC3339Nano UTC at verify time.
2473
2779
  required:
2474
2780
  - companyId
2475
- - siteId
2781
+ - appId
2476
2782
  - email
2477
2783
  - phone
2478
2784
  - ip
@@ -2483,7 +2789,7 @@ components:
2483
2789
  - referredBy
2484
2790
  - requestedAt
2485
2791
  additionalProperties: false
2486
- description: 'MagicLinkRequest model (D40 / ING-304). Collection: companies/{companyId}/sites/{siteId}/magic_link_requests/{requestId}.
2792
+ description: 'MagicLinkRequest model (D40 / ING-304). Collection: companies/{companyId}/apps/{appId}/magic_link_requests/{requestId}.
2487
2793
  Authentication audit log — every request is logged regardless of outcome.
2488
2794
  Two-stage write: Log() then LogVerify().'
2489
2795
  MagicLinkRequestCreate:
@@ -2494,7 +2800,7 @@ components:
2494
2800
  may be set once at creation.
2495
2801
  required:
2496
2802
  - companyId
2497
- - siteId
2803
+ - appId
2498
2804
  - email
2499
2805
  - phone
2500
2806
  - ip
@@ -2652,6 +2958,62 @@ components:
2652
2958
  readOnly: true
2653
2959
  description: (Read-only) Sum of amount for ACTIVE + MONTHLY recurring payments.
2654
2960
  Always full recalc.
2961
+ escalatedOrdersCount:
2962
+ readOnly: true
2963
+ x-note: Absent on tenants whose metrics/current was last written before
2964
+ aggregator v2. Backfill required for universal presence (#8).
2965
+ description: (Read-only, Optional) Orders currently in an escalated state.
2966
+ Present once the current aggregator rewrites the document.
2967
+ type:
2968
+ - integer
2969
+ - 'null'
2970
+ minimum: -9007199254740991
2971
+ maximum: 9007199254740991
2972
+ staleOrdersCount:
2973
+ readOnly: true
2974
+ x-note: Absent on tenants whose metrics/current was last written before
2975
+ aggregator v2. Backfill required for universal presence (#8).
2976
+ description: (Read-only, Optional) Orders that have been in an incomplete
2977
+ status beyond the stale threshold.
2978
+ type:
2979
+ - integer
2980
+ - 'null'
2981
+ minimum: -9007199254740991
2982
+ maximum: 9007199254740991
2983
+ staleBookingsCount:
2984
+ readOnly: true
2985
+ x-note: Absent on tenants whose metrics/current was last written before
2986
+ aggregator v2. Backfill required for universal presence (#8).
2987
+ description: (Read-only, Optional) Bookings that have been in an incomplete
2988
+ status beyond the stale threshold.
2989
+ type:
2990
+ - integer
2991
+ - 'null'
2992
+ minimum: -9007199254740991
2993
+ maximum: 9007199254740991
2994
+ onHoldOrdersCount:
2995
+ readOnly: true
2996
+ x-note: Absent on tenants whose metrics/current was last written before
2997
+ aggregator v2. Backfill required for universal presence (#8).
2998
+ description: (Read-only, Optional) Orders currently in an on-hold state.
2999
+ type:
3000
+ - integer
3001
+ - 'null'
3002
+ minimum: -9007199254740991
3003
+ maximum: 9007199254740991
3004
+ paymentsByMethod:
3005
+ readOnly: true
3006
+ x-note: Always {} until the first real payment is recorded. Present on all
3007
+ tenants once rewritten by current aggregator (#8).
3008
+ description: (Read-only, Optional) Map of PaymentMethod → total amount for
3009
+ the current day. Empty map {} until first payment.
3010
+ type:
3011
+ - object
3012
+ - 'null'
3013
+ propertyNames:
3014
+ type: string
3015
+ additionalProperties:
3016
+ type: number
2655
3017
  computedForDay:
2656
3018
  type: string
2657
3019
  readOnly: true
@@ -2845,6 +3207,62 @@ components:
2845
3207
  readOnly: true
2846
3208
  description: (Read-only) Sum of amount for ACTIVE + MONTHLY recurring payments.
2847
3209
  Always full recalc.
3210
+ escalatedOrdersCount:
3211
+ readOnly: true
3212
+ x-note: Absent on tenants whose metrics/current was last written before
3213
+ aggregator v2. Backfill required for universal presence (#8).
3214
+ description: (Read-only, Optional) Orders currently in an escalated state.
3215
+ Present once the current aggregator rewrites the document.
3216
+ type:
3217
+ - integer
3218
+ - 'null'
3219
+ minimum: -9007199254740991
3220
+ maximum: 9007199254740991
3221
+ staleOrdersCount:
3222
+ readOnly: true
3223
+ x-note: Absent on tenants whose metrics/current was last written before
3224
+ aggregator v2. Backfill required for universal presence (#8).
3225
+ description: (Read-only, Optional) Orders that have been in an incomplete
3226
+ status beyond the stale threshold.
3227
+ type:
3228
+ - integer
3229
+ - 'null'
3230
+ minimum: -9007199254740991
3231
+ maximum: 9007199254740991
3232
+ staleBookingsCount:
3233
+ readOnly: true
3234
+ x-note: Absent on tenants whose metrics/current was last written before
3235
+ aggregator v2. Backfill required for universal presence (#8).
3236
+ description: (Read-only, Optional) Bookings that have been in an incomplete
3237
+ status beyond the stale threshold.
3238
+ type:
3239
+ - integer
3240
+ - 'null'
3241
+ minimum: -9007199254740991
3242
+ maximum: 9007199254740991
3243
+ onHoldOrdersCount:
3244
+ readOnly: true
3245
+ x-note: Absent on tenants whose metrics/current was last written before
3246
+ aggregator v2. Backfill required for universal presence (#8).
3247
+ description: (Read-only, Optional) Orders currently in an on-hold state.
3248
+ type:
3249
+ - integer
3250
+ - 'null'
3251
+ minimum: -9007199254740991
3252
+ maximum: 9007199254740991
3253
+ paymentsByMethod:
3254
+ readOnly: true
3255
+ x-note: Always {} until the first real payment is recorded. Present on all
3256
+ tenants once rewritten by current aggregator (#8).
3257
+ description: (Read-only, Optional) Map of PaymentMethod → total amount for
3258
+ the current day. Empty map {} until first payment.
3259
+ type:
3260
+ - object
3261
+ - 'null'
3262
+ propertyNames:
3263
+ type: string
3264
+ additionalProperties:
3265
+ type: number
2848
3266
  computedForDay:
2849
3267
  type: string
2850
3268
  readOnly: true
@@ -3044,6 +3462,62 @@ components:
3044
3462
  readOnly: true
3045
3463
  description: (Read-only) Sum of amount for ACTIVE + MONTHLY recurring payments.
3046
3464
  Always full recalc.
3465
+ escalatedOrdersCount:
3466
+ readOnly: true
3467
+ x-note: Absent on tenants whose metrics/current was last written before
3468
+ aggregator v2. Backfill required for universal presence (#8).
3469
+ description: (Read-only, Optional) Orders currently in an escalated state.
3470
+ Present once the current aggregator rewrites the document.
3471
+ type:
3472
+ - integer
3473
+ - 'null'
3474
+ minimum: -9007199254740991
3475
+ maximum: 9007199254740991
3476
+ staleOrdersCount:
3477
+ readOnly: true
3478
+ x-note: Absent on tenants whose metrics/current was last written before
3479
+ aggregator v2. Backfill required for universal presence (#8).
3480
+ description: (Read-only, Optional) Orders that have been in an incomplete
3481
+ status beyond the stale threshold.
3482
+ type:
3483
+ - integer
3484
+ - 'null'
3485
+ minimum: -9007199254740991
3486
+ maximum: 9007199254740991
3487
+ staleBookingsCount:
3488
+ readOnly: true
3489
+ x-note: Absent on tenants whose metrics/current was last written before
3490
+ aggregator v2. Backfill required for universal presence (#8).
3491
+ description: (Read-only, Optional) Bookings that have been in an incomplete
3492
+ status beyond the stale threshold.
3493
+ type:
3494
+ - integer
3495
+ - 'null'
3496
+ minimum: -9007199254740991
3497
+ maximum: 9007199254740991
3498
+ onHoldOrdersCount:
3499
+ readOnly: true
3500
+ x-note: Absent on tenants whose metrics/current was last written before
3501
+ aggregator v2. Backfill required for universal presence (#8).
3502
+ description: (Read-only, Optional) Orders currently in an on-hold state.
3503
+ type:
3504
+ - integer
3505
+ - 'null'
3506
+ minimum: -9007199254740991
3507
+ maximum: 9007199254740991
3508
+ paymentsByMethod:
3509
+ readOnly: true
3510
+ x-note: Always {} until the first real payment is recorded. Present on all
3511
+ tenants once rewritten by current aggregator (#8).
3512
+ description: (Read-only, Optional) Map of PaymentMethod → total amount for
3513
+ the current day. Empty map {} until first payment.
3514
+ type:
3515
+ - object
3516
+ - 'null'
3517
+ propertyNames:
3518
+ type: string
3519
+ additionalProperties:
3520
+ type: number
3047
3521
  computedForDay:
3048
3522
  type: string
3049
3523
  readOnly: true
@@ -3263,9 +3737,11 @@ components:
3263
3737
  - createdAt
3264
3738
  additionalProperties: false
3265
3739
  description: 'NotificationRecord — backend-written, multi-channel notification
3266
- audit log (GH#48). Paths: companies/{cid}/notifications/{id} (always) and
3267
- companies/{cid}/orders/{oid}/notifications/{id} (dual-write when relatedEntity.type=order).
3268
- Consumers read only. Distinct from WhatsappOutboundMessage (GH#43).'
3740
+ audit log (GH#48). Paths: companies/{cid}/notification_records/{id} (always)
3741
+ and companies/{cid}/orders/{oid}/notification_records/{id} (dual-write when
3742
+ relatedEntity.type=order). Consumers read only. Distinct from WhatsappOutboundMessage
3743
+ (GH#43). Collection renamed from notifications → notification_records per
3744
+ decision #55 (2026-05-30).'
3269
3745
  Order:
3270
3746
  type: object
3271
3747
  properties:
@@ -3282,20 +3758,22 @@ components:
3282
3758
  type: string
3283
3759
  x-immutable: true
3284
3760
  description: (Immutable) FK → Company document ID. Scopes all queries.
3285
- siteId:
3761
+ appId:
3286
3762
  x-immutable: true
3287
- x-note: 'D43 / ADR-003: optional site attribution. Absent/null means company-wide
3288
- (legacy). When set, the order is attributed to a specific site for analytics
3289
- and site-scoped dashboards. No migration existing orders keep null.
3290
- Flat path; Order continues to live at `companies/{companyId}/orders/{orderId}`.'
3763
+ x-note: 'D43 / ADR-003: optional app attribution (renamed from siteId per
3764
+ D44). Absent/null means company-wide (legacy). When set, the order is
3765
+ attributed to a specific app for analytics and app-scoped dashboards.
3766
+ No migration — existing orders keep null. Flat path; Order continues to
3767
+ live at `companies/{companyId}/orders/{orderId}`.'
3291
3768
  x-see:
3292
3769
  decisions:
3293
3770
  - D43
3294
- x-when: 'Set at order creation when the client knows which site the order
3771
+ - D44
3772
+ x-when: 'Set at order creation when the client knows which app the order
3295
3773
  originated from (e.g. SR Single, Lifesense). Leave null for legacy/company-wide
3296
- orders. Composite index: (companyId, siteId, createdAt).'
3297
- description: (Immutable, Optional) FK → Site document ID (D43 / ADR-003).
3298
- null = company-wide.
3774
+ orders. Composite index: (companyId, appId, createdAt).'
3775
+ description: (Immutable, Optional) FK → App document ID (D43 / ADR-003,
3776
+ renamed from siteId per D44). null = company-wide.
3299
3777
  type:
3300
3778
  - string
3301
3779
  - 'null'
@@ -3485,7 +3963,9 @@ components:
3485
3963
  readOnly: true
3486
3964
  orderDate:
3487
3965
  $ref: '#/components/schemas/FirestoreTimestamp'
3488
- description: Firestore Timestamp serialized representation
3966
+ description: 'Firestore Timestamp Admin SDK form: { _seconds, _nanoseconds
3967
+ }. See types/firestore.ts for REST API v1 and client SDK serialization
3968
+ notes (#10).'
3489
3969
  PROCESSING_ON:
3490
3970
  anyOf:
3491
3971
  - $ref: '#/components/schemas/FirestoreTimestamp'
@@ -3530,7 +4010,9 @@ components:
3530
4010
  anyOf:
3531
4011
  - $ref: '#/components/schemas/FirestoreTimestamp'
3532
4012
  - type: 'null'
3533
- description: Firestore Timestamp serialized representation
4013
+ description: 'Firestore Timestamp Admin SDK form: { _seconds, _nanoseconds
4014
+ }. See types/firestore.ts for REST API v1 and client SDK serialization
4015
+ notes (#10).'
3534
4016
  shippingCost:
3535
4017
  type:
3536
4018
  - number
@@ -3617,7 +4099,9 @@ components:
3617
4099
  description: Payment method used (D02).
3618
4100
  paymentDate:
3619
4101
  $ref: '#/components/schemas/FirestoreTimestamp'
3620
- description: Firestore Timestamp serialized representation
4102
+ description: 'Firestore Timestamp Admin SDK form: { _seconds, _nanoseconds
4103
+ }. See types/firestore.ts for REST API v1 and client SDK serialization
4104
+ notes (#10).'
3621
4105
  referenceNumber:
3622
4106
  description: Payment reference (receipt number, transaction ID, etc.).
3623
4107
  type: string
@@ -3895,7 +4379,9 @@ components:
3895
4379
  - 'null'
3896
4380
  purchaseDate:
3897
4381
  $ref: '#/components/schemas/FirestoreTimestamp'
3898
- description: Firestore Timestamp serialized representation
4382
+ description: 'Firestore Timestamp Admin SDK form: { _seconds, _nanoseconds
4383
+ }. See types/firestore.ts for REST API v1 and client SDK serialization
4384
+ notes (#10).'
3899
4385
  createdAt:
3900
4386
  anyOf:
3901
4387
  - $ref: '#/components/schemas/FirestoreTimestamp'
@@ -4631,6 +5117,86 @@ components:
4631
5117
  description: Write payload for partial update (PATCH) of a Ticket document.
4632
5118
  All fields optional. Fields marked `readOnly` or `x-immutable` must not be
4633
5119
  sent.
5120
+ User:
5121
+ type: object
5122
+ properties:
5123
+ id:
5124
+ readOnly: true
5125
+ description: (Read-only) Firebase Auth UID. Matches the Firestore document
5126
+ ID.
5127
+ type:
5128
+ - string
5129
+ - 'null'
5130
+ displayName:
5131
+ description: User display name from Firebase Auth or manually set.
5132
+ type:
5133
+ - string
5134
+ - 'null'
5135
+ email:
5136
+ description: Email address. Present for email/Google auth users.
5137
+ type:
5138
+ - string
5139
+ - 'null'
5140
+ phoneE164:
5141
+ x-note: 'E.164 format with leading + (e.g. +2250777471485). Canonical phone
5142
+ identity field (decision #27). Distinct from wa_id (Meta conversation
5143
+ key). Server must normalize at write time: 8-digit CI local → prepend
5144
+ +225.'
5145
+ x-when: Set when the user authenticated via phone (WhatsApp OTP) or when
5146
+ a staff member's phone is known. Required for WhatsApp OTP lookup — add
5147
+ a Firestore composite index on phoneE164.
5148
+ description: E.164-normalized phone number (e.g. +2250777471485). Canonical
5149
+ phone identity field; used for WhatsApp OTP lookup via indexed query.
5150
+ type:
5151
+ - string
5152
+ - 'null'
5153
+ companyId:
5154
+ x-immutable: true
5155
+ description: (Immutable) FK → Company document ID. Present for staff accounts
5156
+ scoped to a company.
5157
+ type:
5158
+ - string
5159
+ - 'null'
5160
+ role:
5161
+ description: Staff role within the company (e.g. admin, manager, staff).
5162
+ Application-defined.
5163
+ type:
5164
+ - string
5165
+ - 'null'
5166
+ isActive:
5167
+ description: Whether this user account is active. Inactive accounts are
5168
+ denied access.
5169
+ type:
5170
+ - boolean
5171
+ - 'null'
5172
+ createdAt:
5173
+ anyOf:
5174
+ - $ref: '#/components/schemas/FirestoreTimestamp'
5175
+ - type: 'null'
5176
+ readOnly: true
5177
+ description: (Read-only) When the user document was created.
5178
+ updatedAt:
5179
+ anyOf:
5180
+ - $ref: '#/components/schemas/FirestoreTimestamp'
5181
+ - type: 'null'
5182
+ readOnly: true
5183
+ description: (Read-only) When the user document was last updated.
5184
+ additionalProperties: false
5185
+ description: 'User / staff account. Collection: users/{uid}. Document ID is
5186
+ always the Firebase Auth UID (decision #27). phoneE164 is the canonical E.164
5187
+ phone field for OTP lookup. Legacy phone-keyed documents must be migrated
5188
+ to uid-keyed docs with phoneE164 set.'
5189
+ UserCreate:
5190
+ allOf:
5191
+ - $ref: '#/components/schemas/User'
5192
+ description: Write payload for creating a new User document. Fields marked `readOnly`
5193
+ are server-set and must not be included. Fields marked `x-immutable` may be
5194
+ set once at creation.
5195
+ UserUpdate:
5196
+ allOf:
5197
+ - $ref: '#/components/schemas/User'
5198
+ description: Write payload for partial update (PATCH) of a User document. All
5199
+ fields optional. Fields marked `readOnly` or `x-immutable` must not be sent.
4634
5200
  WhatsappInboundMessage:
4635
5201
  type: object
4636
5202
  properties: