@saasicat/spec 0.5.0 → 0.7.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.
@@ -659,7 +659,7 @@ paths:
659
659
  '200': { description: Activated }
660
660
 
661
661
  # ────────────────────────────────────────────────────────
662
- # Catalog V2 — Plan/Bundle/BusinessType/Marketing/Promotion + Discovery
662
+ # Catalog V2 — Plan/Bundle/Marketing/Promotion + Discovery
663
663
  # (CatalogModule, saas-platform-nest/src/catalog/*; DTO = SSOT for schemas)
664
664
  # ────────────────────────────────────────────────────────
665
665
 
@@ -675,10 +675,22 @@ paths:
675
675
  x-mfa-required: true
676
676
  requestBody:
677
677
  required: true
678
- content: { application/json: { schema: { $ref: '#/components/schemas/CatalogPlanCreate' } } }
678
+ content:
679
+ {
680
+ application/json:
681
+ { schema: { $ref: '#/components/schemas/CatalogPlanCreate' } },
682
+ }
679
683
  responses:
680
684
  '201': { description: Created }
681
- '422': { description: Validation, content: { application/json: { schema: { $ref: '#/components/schemas/ErrorResponse' } } } }
685
+ '422':
686
+ {
687
+ description: Validation,
688
+ content:
689
+ {
690
+ application/json:
691
+ { schema: { $ref: '#/components/schemas/ErrorResponse' } },
692
+ },
693
+ }
682
694
 
683
695
  /catalog/plans/tenant-counts:
684
696
  get:
@@ -710,7 +722,11 @@ paths:
710
722
  x-mfa-required: true
711
723
  requestBody:
712
724
  required: true
713
- content: { application/json: { schema: { $ref: '#/components/schemas/CatalogStampUpdate' } } }
725
+ content:
726
+ {
727
+ application/json:
728
+ { schema: { $ref: '#/components/schemas/CatalogStampUpdate' } },
729
+ }
714
730
  responses: { '200': { description: Updated } }
715
731
  delete:
716
732
  tags: [catalog]
@@ -726,7 +742,15 @@ paths:
726
742
  x-mfa-required: true
727
743
  responses:
728
744
  '200': { description: Purged }
729
- '422': { description: Still referenced, content: { application/json: { schema: { $ref: '#/components/schemas/ErrorResponse' } } } }
745
+ '422':
746
+ {
747
+ description: Still referenced,
748
+ content:
749
+ {
750
+ application/json:
751
+ { schema: { $ref: '#/components/schemas/ErrorResponse' } },
752
+ },
753
+ }
730
754
 
731
755
  /catalog/plans/{id}/versions:
732
756
  parameters: [{ name: id, in: path, required: true, schema: { type: string } }]
@@ -740,7 +764,11 @@ paths:
740
764
  x-mfa-required: true
741
765
  requestBody:
742
766
  required: true
743
- content: { application/json: { schema: { $ref: '#/components/schemas/CatalogPlanVersionDraft' } } }
767
+ content:
768
+ {
769
+ application/json:
770
+ { schema: { $ref: '#/components/schemas/CatalogPlanVersionDraft' } },
771
+ }
744
772
  responses: { '201': { description: Draft created } }
745
773
 
746
774
  /catalog/plan-versions/{id}:
@@ -755,7 +783,11 @@ paths:
755
783
  x-mfa-required: true
756
784
  requestBody:
757
785
  required: true
758
- content: { application/json: { schema: { $ref: '#/components/schemas/CatalogPlanVersionDraft' } } }
786
+ content:
787
+ {
788
+ application/json:
789
+ { schema: { $ref: '#/components/schemas/CatalogPlanVersionDraft' } },
790
+ }
759
791
  responses: { '200': { description: Updated } }
760
792
  delete:
761
793
  tags: [catalog]
@@ -775,10 +807,22 @@ paths:
775
807
  x-mfa-required: true
776
808
  requestBody:
777
809
  required: false
778
- content: { application/json: { schema: { $ref: '#/components/schemas/CatalogVersionPublish' } } }
810
+ content:
811
+ {
812
+ application/json:
813
+ { schema: { $ref: '#/components/schemas/CatalogVersionPublish' } },
814
+ }
779
815
  responses:
780
816
  '201': { description: Published }
781
- '422': { description: 'Regression / validFrom / price gate', content: { application/json: { schema: { $ref: '#/components/schemas/ErrorResponse' } } } }
817
+ '422':
818
+ {
819
+ description: 'Regression / validFrom / price gate',
820
+ content:
821
+ {
822
+ application/json:
823
+ { schema: { $ref: '#/components/schemas/ErrorResponse' } },
824
+ },
825
+ }
782
826
 
783
827
  /catalog/plan-versions/{id}/terminate:
784
828
  parameters: [{ name: id, in: path, required: true, schema: { type: string } }]
@@ -788,7 +832,14 @@ paths:
788
832
  x-mfa-required: true
789
833
  requestBody:
790
834
  required: true
791
- content: { application/json: { schema: { $ref: '#/components/schemas/CatalogPlanVersionTerminate' } } }
835
+ content:
836
+ {
837
+ application/json:
838
+ {
839
+ schema:
840
+ { $ref: '#/components/schemas/CatalogPlanVersionTerminate' },
841
+ },
842
+ }
792
843
  responses: { '200': { description: Terminated } }
793
844
 
794
845
  # ── Bundles ──
@@ -803,7 +854,11 @@ paths:
803
854
  x-mfa-required: true
804
855
  requestBody:
805
856
  required: true
806
- content: { application/json: { schema: { $ref: '#/components/schemas/CatalogBundleCreate' } } }
857
+ content:
858
+ {
859
+ application/json:
860
+ { schema: { $ref: '#/components/schemas/CatalogBundleCreate' } },
861
+ }
807
862
  responses: { '201': { description: Created } }
808
863
 
809
864
  /catalog/bundles/{id}:
@@ -818,7 +873,11 @@ paths:
818
873
  x-mfa-required: true
819
874
  requestBody:
820
875
  required: true
821
- content: { application/json: { schema: { $ref: '#/components/schemas/CatalogBundleUpdate' } } }
876
+ content:
877
+ {
878
+ application/json:
879
+ { schema: { $ref: '#/components/schemas/CatalogBundleUpdate' } },
880
+ }
822
881
  responses: { '200': { description: Updated } }
823
882
  delete:
824
883
  tags: [catalog]
@@ -838,7 +897,11 @@ paths:
838
897
  x-mfa-required: true
839
898
  requestBody:
840
899
  required: true
841
- content: { application/json: { schema: { $ref: '#/components/schemas/CatalogBundleVersionDraft' } } }
900
+ content:
901
+ {
902
+ application/json:
903
+ { schema: { $ref: '#/components/schemas/CatalogBundleVersionDraft' } },
904
+ }
842
905
  responses: { '201': { description: Draft created } }
843
906
 
844
907
  /catalog/bundle-versions/{id}:
@@ -853,7 +916,11 @@ paths:
853
916
  x-mfa-required: true
854
917
  requestBody:
855
918
  required: true
856
- content: { application/json: { schema: { $ref: '#/components/schemas/CatalogBundleVersionDraft' } } }
919
+ content:
920
+ {
921
+ application/json:
922
+ { schema: { $ref: '#/components/schemas/CatalogBundleVersionDraft' } },
923
+ }
857
924
  responses: { '200': { description: Updated } }
858
925
  delete:
859
926
  tags: [catalog]
@@ -869,86 +936,22 @@ paths:
869
936
  x-mfa-required: true
870
937
  requestBody:
871
938
  required: false
872
- content: { application/json: { schema: { $ref: '#/components/schemas/CatalogVersionPublish' } } }
939
+ content:
940
+ {
941
+ application/json:
942
+ { schema: { $ref: '#/components/schemas/CatalogVersionPublish' } },
943
+ }
873
944
  responses:
874
945
  '201': { description: Published }
875
- '422': { description: 'Regression / validFrom / price gate', content: { application/json: { schema: { $ref: '#/components/schemas/ErrorResponse' } } } }
876
-
877
- # ── Business types ──
878
- /catalog/business-types:
879
- get:
880
- tags: [catalog]
881
- summary: List business-type roots
882
- responses: { '200': { description: List } }
883
- post:
884
- tags: [catalog]
885
- summary: Create a business-type root
886
- x-mfa-required: true
887
- requestBody:
888
- required: true
889
- content: { application/json: { schema: { $ref: '#/components/schemas/CatalogBusinessTypeCreate' } } }
890
- responses: { '201': { description: Created } }
891
-
892
- /catalog/business-types/{id}:
893
- parameters: [{ name: id, in: path, required: true, schema: { type: string } }]
894
- get:
895
- tags: [catalog]
896
- summary: Business-type root detail
897
- responses: { '200': { description: Detail } }
898
- patch:
899
- tags: [catalog]
900
- summary: Update a business-type root
901
- x-mfa-required: true
902
- requestBody:
903
- required: true
904
- content: { application/json: { schema: { $ref: '#/components/schemas/CatalogStampUpdate' } } }
905
- responses: { '200': { description: Updated } }
906
- delete:
907
- tags: [catalog]
908
- summary: Soft-delete a business-type root
909
- x-mfa-required: true
910
- responses: { '200': { description: Deleted } }
911
-
912
- /catalog/business-types/{id}/versions:
913
- parameters: [{ name: id, in: path, required: true, schema: { type: string } }]
914
- get:
915
- tags: [catalog]
916
- summary: List business-type versions
917
- responses: { '200': { description: List } }
918
- post:
919
- tags: [catalog]
920
- summary: Create a business-type version draft (bundle composition)
921
- x-mfa-required: true
922
- requestBody:
923
- required: true
924
- content: { application/json: { schema: { $ref: '#/components/schemas/CatalogBusinessTypeVersionDraft' } } }
925
- responses: { '201': { description: Draft created } }
926
-
927
- /catalog/business-type-versions/{id}:
928
- parameters: [{ name: id, in: path, required: true, schema: { type: string } }]
929
- get:
930
- tags: [catalog]
931
- summary: Business-type version detail
932
- responses: { '200': { description: Detail } }
933
- patch:
934
- tags: [catalog]
935
- summary: Update a business-type version draft
936
- x-mfa-required: true
937
- requestBody:
938
- required: true
939
- content: { application/json: { schema: { $ref: '#/components/schemas/CatalogBusinessTypeVersionDraft' } } }
940
- responses: { '200': { description: Updated } }
941
-
942
- /catalog/business-type-versions/{id}/publish:
943
- parameters: [{ name: id, in: path, required: true, schema: { type: string } }]
944
- post:
945
- tags: [catalog]
946
- summary: Publish a business-type version
947
- x-mfa-required: true
948
- requestBody:
949
- required: false
950
- content: { application/json: { schema: { $ref: '#/components/schemas/CatalogBusinessTypeVersionPublish' } } }
951
- responses: { '201': { description: Published } }
946
+ '422':
947
+ {
948
+ description: 'Regression / validFrom / price gate',
949
+ content:
950
+ {
951
+ application/json:
952
+ { schema: { $ref: '#/components/schemas/ErrorResponse' } },
953
+ },
954
+ }
952
955
 
953
956
  # ── Marketing projections + settings ──
954
957
  /catalog/marketing-projections:
@@ -958,11 +961,20 @@ paths:
958
961
  responses: { '200': { description: List } }
959
962
  post:
960
963
  tags: [catalog]
961
- summary: Create a marketing projection (plan/bundle/business type, locale-specific)
964
+ summary: Create a marketing projection (plan/bundle, locale-specific)
962
965
  x-mfa-required: true
963
966
  requestBody:
964
967
  required: true
965
- content: { application/json: { schema: { $ref: '#/components/schemas/CatalogMarketingProjectionCreate' } } }
968
+ content:
969
+ {
970
+ application/json:
971
+ {
972
+ schema:
973
+ {
974
+ $ref: '#/components/schemas/CatalogMarketingProjectionCreate',
975
+ },
976
+ },
977
+ }
966
978
  responses: { '201': { description: Created } }
967
979
 
968
980
  /catalog/marketing-projections/{id}:
@@ -977,7 +989,16 @@ paths:
977
989
  x-mfa-required: true
978
990
  requestBody:
979
991
  required: true
980
- content: { application/json: { schema: { $ref: '#/components/schemas/CatalogMarketingProjectionUpdate' } } }
992
+ content:
993
+ {
994
+ application/json:
995
+ {
996
+ schema:
997
+ {
998
+ $ref: '#/components/schemas/CatalogMarketingProjectionUpdate',
999
+ },
1000
+ },
1001
+ }
981
1002
  responses: { '200': { description: Updated } }
982
1003
  delete:
983
1004
  tags: [catalog]
@@ -996,7 +1017,14 @@ paths:
996
1017
  x-mfa-required: true
997
1018
  requestBody:
998
1019
  required: true
999
- content: { application/json: { schema: { $ref: '#/components/schemas/CatalogMarketingSettingsUpdate' } } }
1020
+ content:
1021
+ {
1022
+ application/json:
1023
+ {
1024
+ schema:
1025
+ { $ref: '#/components/schemas/CatalogMarketingSettingsUpdate' },
1026
+ },
1027
+ }
1000
1028
  responses: { '200': { description: Set } }
1001
1029
 
1002
1030
  # ── Promotions ──
@@ -1011,7 +1039,11 @@ paths:
1011
1039
  x-mfa-required: true
1012
1040
  requestBody:
1013
1041
  required: true
1014
- content: { application/json: { schema: { $ref: '#/components/schemas/CatalogPromotionCreate' } } }
1042
+ content:
1043
+ {
1044
+ application/json:
1045
+ { schema: { $ref: '#/components/schemas/CatalogPromotionCreate' } },
1046
+ }
1015
1047
  responses: { '201': { description: Created } }
1016
1048
 
1017
1049
  /catalog/promotions/{id}:
@@ -1026,7 +1058,11 @@ paths:
1026
1058
  x-mfa-required: true
1027
1059
  requestBody:
1028
1060
  required: true
1029
- content: { application/json: { schema: { $ref: '#/components/schemas/CatalogPromotionUpdate' } } }
1061
+ content:
1062
+ {
1063
+ application/json:
1064
+ { schema: { $ref: '#/components/schemas/CatalogPromotionUpdate' } },
1065
+ }
1030
1066
  responses: { '200': { description: Updated } }
1031
1067
  delete:
1032
1068
  tags: [catalog]
@@ -1036,13 +1072,28 @@ paths:
1036
1072
 
1037
1073
  # ── Feature / quota / capability catalog (discovery maintenance) ──
1038
1074
  /catalog/capabilities:
1039
- get: { tags: [catalog], summary: List discovered capabilities, responses: { '200': { description: List } } }
1075
+ get:
1076
+ {
1077
+ tags: [catalog],
1078
+ summary: List discovered capabilities,
1079
+ responses: { '200': { description: List } },
1080
+ }
1040
1081
 
1041
1082
  /catalog/features:
1042
- get: { tags: [catalog], summary: List feature catalog entries, responses: { '200': { description: List } } }
1083
+ get:
1084
+ {
1085
+ tags: [catalog],
1086
+ summary: List feature catalog entries,
1087
+ responses: { '200': { description: List } },
1088
+ }
1043
1089
 
1044
1090
  /catalog/quotas:
1045
- get: { tags: [catalog], summary: List quota catalog entries, responses: { '200': { description: List } } }
1091
+ get:
1092
+ {
1093
+ tags: [catalog],
1094
+ summary: List quota catalog entries,
1095
+ responses: { '200': { description: List } },
1096
+ }
1046
1097
 
1047
1098
  /catalog/features/{key}:
1048
1099
  parameters: [{ name: key, in: path, required: true, schema: { type: string } }]
@@ -1052,7 +1103,11 @@ paths:
1052
1103
  x-mfa-required: true
1053
1104
  requestBody:
1054
1105
  required: true
1055
- content: { application/json: { schema: { $ref: '#/components/schemas/CatalogEntryBaseUpdate' } } }
1106
+ content:
1107
+ {
1108
+ application/json:
1109
+ { schema: { $ref: '#/components/schemas/CatalogEntryBaseUpdate' } },
1110
+ }
1056
1111
  responses: { '200': { description: Updated } }
1057
1112
 
1058
1113
  /catalog/features/{key}/review:
@@ -1063,7 +1118,11 @@ paths:
1063
1118
  x-mfa-required: true
1064
1119
  requestBody:
1065
1120
  required: true
1066
- content: { application/json: { schema: { $ref: '#/components/schemas/CatalogEntryReview' } } }
1121
+ content:
1122
+ {
1123
+ application/json:
1124
+ { schema: { $ref: '#/components/schemas/CatalogEntryReview' } },
1125
+ }
1067
1126
  responses: { '200': { description: Set } }
1068
1127
 
1069
1128
  /catalog/features/{key}/i18n:
@@ -1074,7 +1133,11 @@ paths:
1074
1133
  x-mfa-required: true
1075
1134
  requestBody:
1076
1135
  required: true
1077
- content: { application/json: { schema: { $ref: '#/components/schemas/CatalogEntryI18nUpdate' } } }
1136
+ content:
1137
+ {
1138
+ application/json:
1139
+ { schema: { $ref: '#/components/schemas/CatalogEntryI18nUpdate' } },
1140
+ }
1078
1141
  responses: { '200': { description: Set } }
1079
1142
 
1080
1143
  /catalog/quotas/{key}:
@@ -1085,7 +1148,11 @@ paths:
1085
1148
  x-mfa-required: true
1086
1149
  requestBody:
1087
1150
  required: true
1088
- content: { application/json: { schema: { $ref: '#/components/schemas/CatalogEntryBaseUpdate' } } }
1151
+ content:
1152
+ {
1153
+ application/json:
1154
+ { schema: { $ref: '#/components/schemas/CatalogEntryBaseUpdate' } },
1155
+ }
1089
1156
  responses: { '200': { description: Updated } }
1090
1157
 
1091
1158
  /catalog/quotas/{key}/review:
@@ -1096,7 +1163,11 @@ paths:
1096
1163
  x-mfa-required: true
1097
1164
  requestBody:
1098
1165
  required: true
1099
- content: { application/json: { schema: { $ref: '#/components/schemas/CatalogEntryReview' } } }
1166
+ content:
1167
+ {
1168
+ application/json:
1169
+ { schema: { $ref: '#/components/schemas/CatalogEntryReview' } },
1170
+ }
1100
1171
  responses: { '200': { description: Set } }
1101
1172
 
1102
1173
  /catalog/quotas/{key}/i18n:
@@ -1107,7 +1178,11 @@ paths:
1107
1178
  x-mfa-required: true
1108
1179
  requestBody:
1109
1180
  required: true
1110
- content: { application/json: { schema: { $ref: '#/components/schemas/CatalogEntryI18nUpdate' } } }
1181
+ content:
1182
+ {
1183
+ application/json:
1184
+ { schema: { $ref: '#/components/schemas/CatalogEntryI18nUpdate' } },
1185
+ }
1111
1186
  responses: { '200': { description: Set } }
1112
1187
 
1113
1188
  /catalog/discovery/sync:
@@ -1117,15 +1192,30 @@ paths:
1117
1192
  x-mfa-required: true
1118
1193
  requestBody:
1119
1194
  required: true
1120
- content: { application/json: { schema: { $ref: '#/components/schemas/CatalogDiscoverySync' } } }
1195
+ content:
1196
+ {
1197
+ application/json:
1198
+ { schema: { $ref: '#/components/schemas/CatalogDiscoverySync' } },
1199
+ }
1121
1200
  responses: { '200': { description: Synchronized } }
1122
1201
 
1123
1202
  # ── Discovery (scan/status, outside /catalog) ──
1124
1203
  /discovery:
1125
- get: { tags: [catalog], summary: Current discovery snapshot/status, responses: { '200': { description: Snapshot } } }
1204
+ get:
1205
+ {
1206
+ tags: [catalog],
1207
+ summary: Current discovery snapshot/status,
1208
+ responses: { '200': { description: Snapshot } },
1209
+ }
1126
1210
 
1127
1211
  /discovery/rescan:
1128
- post: { tags: [catalog], summary: Re-run the discovery scan, x-mfa-required: true, responses: { '200': { description: Scanned } } }
1212
+ post:
1213
+ {
1214
+ tags: [catalog],
1215
+ summary: Re-run the discovery scan,
1216
+ x-mfa-required: true,
1217
+ responses: { '200': { description: Scanned } },
1218
+ }
1129
1219
 
1130
1220
  components:
1131
1221
  securitySchemes:
@@ -1155,9 +1245,14 @@ components:
1155
1245
  type: object
1156
1246
  required: [projectKey, planKey, label]
1157
1247
  properties:
1158
- projectKey: { type: string, pattern: '^[a-z][a-z0-9-]*$', description: 'kebab-case' }
1248
+ projectKey:
1249
+ { type: string, pattern: '^[a-z][a-z0-9-]*$', description: 'kebab-case' }
1159
1250
  planKey:
1160
- { type: string, pattern: '^[A-Z][A-Z0-9_]*$', description: 'SCREAMING_SNAKE, no hyphen' }
1251
+ {
1252
+ type: string,
1253
+ pattern: '^[A-Z][A-Z0-9_]*$',
1254
+ description: 'SCREAMING_SNAKE, no hyphen',
1255
+ }
1161
1256
  label: { type: string, minLength: 1, maxLength: 120 }
1162
1257
  description: { type: string, maxLength: 2000 }
1163
1258
  icon: { type: string, maxLength: 64 }
@@ -1178,7 +1273,11 @@ components:
1178
1273
  additionalProperties: { type: number }
1179
1274
  description: 'camelCase keys, e.g. {"members": 150}'
1180
1275
  monthlyNet:
1181
- { type: string, pattern: '^\d+(\.\d{1,2})?$', description: 'EUR decimal string, not cents' }
1276
+ {
1277
+ type: string,
1278
+ pattern: '^\d+(\.\d{1,2})?$',
1279
+ description: 'EUR decimal string, not cents',
1280
+ }
1182
1281
  yearlyNet: { type: string, pattern: '^\d+(\.\d{1,2})?$' }
1183
1282
  marketed: { type: boolean }
1184
1283
  changeNote: { type: string, maxLength: 2000 }
@@ -1191,8 +1290,7 @@ components:
1191
1290
  required: [projectKey, bundleKey, label]
1192
1291
  properties:
1193
1292
  projectKey: { type: string, pattern: '^[a-z][a-z0-9-]*$' }
1194
- bundleKey:
1195
- { type: string, pattern: '^[A-Z][A-Z0-9_]*$', description: 'no hyphen' }
1293
+ bundleKey: { type: string, pattern: '^[A-Z][A-Z0-9_]*$', description: 'no hyphen' }
1196
1294
  label: { type: string, minLength: 1, maxLength: 120 }
1197
1295
  description: { type: string, maxLength: 2000 }
1198
1296
  icon: { type: string, maxLength: 64 }
@@ -1211,12 +1309,16 @@ components:
1211
1309
  additionalProperties: { type: number }
1212
1310
  compatibility:
1213
1311
  type: object
1214
- description: 'both empty/omitted = freely bookable everywhere (E5)'
1312
+ description: 'empty/omitted = bookable with every plan'
1215
1313
  properties:
1216
- businessTypeKeys: { type: array, items: { type: string } }
1217
1314
  planIds: { type: array, items: { type: string } }
1218
1315
  monthlyNet:
1219
- { type: string, pattern: '^\d+(\.\d{1,2})?$', nullable: true, description: 'EUR string; null = override resolution' }
1316
+ {
1317
+ type: string,
1318
+ pattern: '^\d+(\.\d{1,2})?$',
1319
+ nullable: true,
1320
+ description: 'EUR string; null = override resolution',
1321
+ }
1220
1322
  yearlyNet: { type: string, pattern: '^\d+(\.\d{1,2})?$', nullable: true }
1221
1323
  marketed: { type: boolean }
1222
1324
  changeNote: { type: string, maxLength: 2000 }
@@ -1228,9 +1330,19 @@ components:
1228
1330
  type: object
1229
1331
  description: 'Applies to plan-versions AND bundle-versions /publish'
1230
1332
  properties:
1231
- forceRegressive: { type: boolean, description: 'Publish a regressive diff anyway (MFA)' }
1232
- allowZeroPrice: { type: boolean, description: 'Allow publishing despite a price of 0.00 (special contracts only)' }
1233
- validFrom: { type: string, nullable: true, description: 'Required if the draft carries no validFrom' }
1333
+ forceRegressive:
1334
+ { type: boolean, description: 'Publish a regressive diff anyway (MFA)' }
1335
+ allowZeroPrice:
1336
+ {
1337
+ type: boolean,
1338
+ description: 'Allow publishing despite a price of 0.00 (special contracts only)',
1339
+ }
1340
+ validFrom:
1341
+ {
1342
+ type: string,
1343
+ nullable: true,
1344
+ description: 'Required if the draft carries no validFrom',
1345
+ }
1234
1346
  validUntil: { type: string, nullable: true }
1235
1347
 
1236
1348
  CatalogMarketingProjectionCreate:
@@ -1238,7 +1350,7 @@ components:
1238
1350
  required: [projectKey, targetType, targetVersionId, displayLabel, description]
1239
1351
  properties:
1240
1352
  projectKey: { type: string, pattern: '^[a-z][a-z0-9-]*$' }
1241
- targetType: { type: string, enum: [PLAN, BUNDLE, BUSINESS_TYPE] }
1353
+ targetType: { type: string, enum: [PLAN, BUNDLE] }
1242
1354
  targetVersionId: { type: string }
1243
1355
  locale: { type: string, pattern: '^[a-z]{2}(-[A-Z]{2})?$', default: de }
1244
1356
  displayLabel: { type: string, minLength: 1, maxLength: 120 }
@@ -1263,7 +1375,7 @@ components:
1263
1375
 
1264
1376
  CatalogStampUpdate:
1265
1377
  type: object
1266
- description: 'Root update for plan OR business type'
1378
+ description: 'Root update for a plan'
1267
1379
  properties:
1268
1380
  label: { type: string, minLength: 1, maxLength: 120 }
1269
1381
  description: { type: string, maxLength: 2000, nullable: true }
@@ -1309,42 +1421,6 @@ components:
1309
1421
  priority: { type: integer, minimum: 0, maximum: 10000 }
1310
1422
  highlight: { type: boolean }
1311
1423
 
1312
- CatalogBusinessTypeCreate:
1313
- type: object
1314
- required: [projectKey, businessTypeKey, label]
1315
- properties:
1316
- projectKey: { type: string, pattern: '^[a-z][a-z0-9-]*$' }
1317
- businessTypeKey: { type: string, pattern: '^[A-Z][A-Z0-9_]*$', description: 'SCREAMING_SNAKE' }
1318
- label: { type: string, minLength: 1, maxLength: 120 }
1319
- description: { type: string, maxLength: 2000 }
1320
- icon: { type: string, maxLength: 64 }
1321
- sortOrder: { type: integer, minimum: 0, maximum: 10000 }
1322
-
1323
- CatalogBusinessTypeVersionDraft:
1324
- type: object
1325
- required: [bundles]
1326
- properties:
1327
- bundles:
1328
- type: array
1329
- minItems: 1
1330
- items:
1331
- type: object
1332
- required: [bundleVersionId]
1333
- properties:
1334
- bundleVersionId: { type: string, format: uuid }
1335
- sortOrder: { type: integer, minimum: 0, maximum: 10000 }
1336
- quotaOverrides: { type: object, additionalProperties: { type: number } }
1337
- monthlyNet: { type: string, pattern: '^\d+(\.\d{1,2})?$', nullable: true }
1338
- yearlyNet: { type: string, pattern: '^\d+(\.\d{1,2})?$', nullable: true }
1339
- marketed: { type: boolean }
1340
- changeNote: { type: string, maxLength: 2000 }
1341
- baseVersionId: { type: string, format: uuid, nullable: true }
1342
-
1343
- CatalogBusinessTypeVersionPublish:
1344
- type: object
1345
- properties:
1346
- forceRegressive: { type: boolean }
1347
-
1348
1424
  CatalogEntryReview:
1349
1425
  type: object
1350
1426
  required: [discoveryStatus]
@@ -1370,7 +1446,13 @@ components:
1370
1446
  label: { type: string, maxLength: 120 }
1371
1447
  description: { type: string, maxLength: 2000, nullable: true }
1372
1448
  icon: { type: string, maxLength: 64, nullable: true, description: 'feature only' }
1373
- tier: { type: string, maxLength: 40, nullable: true, description: 'feature only, logical group' }
1449
+ tier:
1450
+ {
1451
+ type: string,
1452
+ maxLength: 40,
1453
+ nullable: true,
1454
+ description: 'feature only, logical group',
1455
+ }
1374
1456
 
1375
1457
  CatalogDiscoverySync:
1376
1458
  type: object
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@saasicat/spec",
3
- "version": "0.5.0",
3
+ "version": "0.7.0",
4
4
  "description": "Language-neutral spec of the SaaS platform: JSON Schemas, OpenAPI contract, Prisma fragments, acceptance scenarios.",
5
5
  "type": "module",
6
6
  "main": "./index.cjs",