@tolinax/ayoune-interfaces 2026.63.0 → 2026.65.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.
@@ -384,6 +384,7 @@ export declare enum aMN {
384
384
  KPITemplates = "KPITemplates",
385
385
  Leads = "Leads",
386
386
  LinkPortalClicks = "LinkPortalClicks",
387
+ LinkPortals = "LinkPortals",
387
388
  LinkPortalViews = "LinkPortalViews",
388
389
  LoadingLists = "LoadingLists",
389
390
  Localizations = "Localizations",
@@ -412,6 +413,10 @@ export declare enum aMN {
412
413
  MarketBudgetsByIndustries = "MarketBudgetsByIndustries",
413
414
  IndustryKPIs = "IndustryKPIs",
414
415
  MarketResearches = "MarketResearches",
416
+ MarketplaceApps = "MarketplaceApps",
417
+ MarketplaceBundles = "MarketplaceBundles",
418
+ MarketplaceInstallations = "MarketplaceInstallations",
419
+ MarketplaceReviews = "MarketplaceReviews",
415
420
  Markets = "Markets",
416
421
  MaterialCommissionings = "MaterialCommissionings",
417
422
  MeetingLocations = "MeetingLocations",
@@ -531,6 +536,7 @@ export declare enum aMN {
531
536
  Repositories = "Repositories",
532
537
  Requirements = "Requirements",
533
538
  ResearchBudgets = "ResearchBudgets",
539
+ ResellerDefaultBundles = "ResellerDefaultBundles",
534
540
  Retrospectives = "Retrospectives",
535
541
  ReturnOrders = "ReturnOrders",
536
542
  RewardLogs = "RewardLogs",
@@ -388,6 +388,7 @@ var aMN;
388
388
  aMN["KPITemplates"] = "KPITemplates";
389
389
  aMN["Leads"] = "Leads";
390
390
  aMN["LinkPortalClicks"] = "LinkPortalClicks";
391
+ aMN["LinkPortals"] = "LinkPortals";
391
392
  aMN["LinkPortalViews"] = "LinkPortalViews";
392
393
  aMN["LoadingLists"] = "LoadingLists";
393
394
  aMN["Localizations"] = "Localizations";
@@ -416,6 +417,10 @@ var aMN;
416
417
  aMN["MarketBudgetsByIndustries"] = "MarketBudgetsByIndustries";
417
418
  aMN["IndustryKPIs"] = "IndustryKPIs";
418
419
  aMN["MarketResearches"] = "MarketResearches";
420
+ aMN["MarketplaceApps"] = "MarketplaceApps";
421
+ aMN["MarketplaceBundles"] = "MarketplaceBundles";
422
+ aMN["MarketplaceInstallations"] = "MarketplaceInstallations";
423
+ aMN["MarketplaceReviews"] = "MarketplaceReviews";
419
424
  aMN["Markets"] = "Markets";
420
425
  aMN["MaterialCommissionings"] = "MaterialCommissionings";
421
426
  aMN["MeetingLocations"] = "MeetingLocations";
@@ -535,6 +540,7 @@ var aMN;
535
540
  aMN["Repositories"] = "Repositories";
536
541
  aMN["Requirements"] = "Requirements";
537
542
  aMN["ResearchBudgets"] = "ResearchBudgets";
543
+ aMN["ResellerDefaultBundles"] = "ResellerDefaultBundles";
538
544
  aMN["Retrospectives"] = "Retrospectives";
539
545
  aMN["ReturnOrders"] = "ReturnOrders";
540
546
  aMN["RewardLogs"] = "RewardLogs";
@@ -4699,6 +4699,30 @@ const modelsAndRights = [
4699
4699
  updateBy: "_id",
4700
4700
  availableInSDK: false,
4701
4701
  },
4702
+ {
4703
+ plural: "LinkPortals",
4704
+ singular: "LinkPortal",
4705
+ module: "marketing",
4706
+ right: "marketing.linkportals",
4707
+ readOnly: false,
4708
+ importable: false,
4709
+ allowDuplicate: true,
4710
+ updateBy: "_id",
4711
+ availableInSDK: true,
4712
+ sdkOperations: ["find", "findOne", "insert", "update"],
4713
+ searchable: true,
4714
+ searchableFields: ["slug", "title", "customDomain"],
4715
+ labelKey: "marketing.linkportal.label",
4716
+ labelPluralKey: "marketing.linkportals.label",
4717
+ descriptionKey: "marketing.linkportals.description",
4718
+ piiLevel: "none",
4719
+ events: ["created", "updated", "deleted"],
4720
+ entityActions: [
4721
+ { name: "publish", verb: "POST", emits: "published", icon: "publish", labelKey: "marketing.linkportals.actions.publish" },
4722
+ { name: "unpublish", verb: "POST", emits: "unpublished", icon: "unpublished", labelKey: "marketing.linkportals.actions.unpublish" },
4723
+ { name: "duplicate", verb: "POST", emits: "duplicated", icon: "content_copy", labelKey: "marketing.linkportals.actions.duplicate" },
4724
+ ],
4725
+ },
4702
4726
  {
4703
4727
  plural: "LinkPortalViews",
4704
4728
  singular: "LinkPortalView",
@@ -7933,6 +7957,136 @@ const modelsAndRights = [
7933
7957
  updateBy: "_id",
7934
7958
  availableInSDK: false,
7935
7959
  },
7960
+ // ─── Marketplace (Phase 1 Foundation — 25. April 2026) ─────────────
7961
+ // Five entities model the cross-customer app-distribution mechanism:
7962
+ // MarketplaceApps — public listing entity (publisher-owned)
7963
+ // MarketplaceBundles — versioned content bundle attached to an app
7964
+ // MarketplaceInstallations — 1:1 customer ↔ app install record
7965
+ // MarketplaceReviews — customer-submitted 1-5 star reviews
7966
+ // ResellerDefaultBundles — reseller's auto-install bundles for new customers
7967
+ //
7968
+ // All five belong to the "marketplace" module. Actions beyond CRUD are
7969
+ // declared below; the marketplace-api service (Phase 2) hosts them at
7970
+ // POST /{entity}/:id/actions/{action}. See marketplace-mvm-plan.md.
7971
+ {
7972
+ plural: "MarketplaceApps",
7973
+ singular: "MarketplaceApp",
7974
+ module: "marketplace",
7975
+ right: "marketplace.apps",
7976
+ readOnly: false,
7977
+ importable: false,
7978
+ allowDuplicate: false,
7979
+ updateBy: "_id",
7980
+ availableInSDK: true,
7981
+ sdkOperations: ["find", "findOne", "insert", "update", "aggregate", "count"],
7982
+ piiLevel: "low",
7983
+ searchable: true,
7984
+ searchableFields: ["name", "slug", "description", "category", "industry", "tags"],
7985
+ actions: [
7986
+ { title: "PUBLISH", action: "publish", availability: "single", method: "POST", icon: "publish" },
7987
+ { title: "ARCHIVE", action: "archive", availability: "single", method: "POST", icon: "archive" },
7988
+ { title: "REVIEW_APPROVE", action: "review-approve", availability: "single", method: "POST", icon: "check_circle" },
7989
+ { title: "REVIEW_REJECT", action: "review-reject", availability: "single", method: "POST", icon: "block", dangerous: true },
7990
+ { title: "INSTALL", action: "install", availability: "single", method: "POST", icon: "download" },
7991
+ ],
7992
+ entityActions: [
7993
+ { name: "publish", verb: "POST", emits: "published", icon: "publish", labelKey: "marketplace.apps.actions.publish" },
7994
+ { name: "archive", verb: "POST", emits: "archived", icon: "archive", labelKey: "marketplace.apps.actions.archive" },
7995
+ { name: "review-approve", verb: "POST", emits: "approved", icon: "check_circle", labelKey: "marketplace.apps.actions.review-approve" },
7996
+ { name: "review-reject", verb: "POST", emits: "rejected", icon: "block", dangerous: true, labelKey: "marketplace.apps.actions.review-reject" },
7997
+ { name: "install", verb: "POST", emits: "installed", icon: "download", labelKey: "marketplace.apps.actions.install" },
7998
+ ],
7999
+ },
8000
+ {
8001
+ plural: "MarketplaceBundles",
8002
+ singular: "MarketplaceBundle",
8003
+ module: "marketplace",
8004
+ right: "marketplace.bundles",
8005
+ readOnly: false,
8006
+ importable: false,
8007
+ allowDuplicate: false,
8008
+ updateBy: "_id",
8009
+ availableInSDK: true,
8010
+ sdkOperations: ["find", "findOne", "insert", "update", "aggregate", "count"],
8011
+ piiLevel: "low",
8012
+ searchable: true,
8013
+ searchableFields: ["version", "bundleType", "changelog"],
8014
+ actions: [
8015
+ { title: "PUBLISH", action: "publish", availability: "single", method: "POST", icon: "publish" },
8016
+ { title: "FORK", action: "fork", availability: "single", method: "POST", icon: "fork_right" },
8017
+ { title: "FROM_PUBLISHER", action: "from-publisher", availability: "single", method: "POST", icon: "cloud_download" },
8018
+ ],
8019
+ entityActions: [
8020
+ { name: "publish", verb: "POST", emits: "published", icon: "publish", labelKey: "marketplace.bundles.actions.publish" },
8021
+ { name: "fork", verb: "POST", emits: "forked", icon: "fork_right", labelKey: "marketplace.bundles.actions.fork" },
8022
+ { name: "from-publisher", verb: "POST", emits: "imported", icon: "cloud_download", labelKey: "marketplace.bundles.actions.from-publisher" },
8023
+ ],
8024
+ },
8025
+ {
8026
+ plural: "MarketplaceInstallations",
8027
+ singular: "MarketplaceInstallation",
8028
+ module: "marketplace",
8029
+ right: "marketplace.installations",
8030
+ readOnly: false,
8031
+ importable: false,
8032
+ allowDuplicate: false,
8033
+ updateBy: "_id",
8034
+ availableInSDK: true,
8035
+ sdkOperations: ["find", "findOne", "aggregate", "count"],
8036
+ piiLevel: "low",
8037
+ searchable: true,
8038
+ searchableFields: ["status", "bundleVersion"],
8039
+ actions: [
8040
+ { title: "INSTALL", action: "install", availability: "single", method: "POST", icon: "download" },
8041
+ { title: "UNINSTALL", action: "uninstall", availability: "single", method: "POST", icon: "delete_sweep", dangerous: true },
8042
+ { title: "PAUSE", action: "pause", availability: "single", method: "POST", icon: "pause_circle" },
8043
+ { title: "RESUME", action: "resume", availability: "single", method: "POST", icon: "play_circle" },
8044
+ { title: "UPDATE", action: "update", availability: "single", method: "POST", icon: "system_update_alt" },
8045
+ ],
8046
+ entityActions: [
8047
+ { name: "install", verb: "POST", emits: "installed", icon: "download", labelKey: "marketplace.installations.actions.install" },
8048
+ { name: "uninstall", verb: "POST", emits: "uninstalled", icon: "delete_sweep", dangerous: true, labelKey: "marketplace.installations.actions.uninstall" },
8049
+ { name: "pause", verb: "POST", emits: "paused", icon: "pause_circle", labelKey: "marketplace.installations.actions.pause" },
8050
+ { name: "resume", verb: "POST", emits: "resumed", icon: "play_circle", labelKey: "marketplace.installations.actions.resume" },
8051
+ { name: "update", verb: "POST", emits: "updated", icon: "system_update_alt", labelKey: "marketplace.installations.actions.update" },
8052
+ ],
8053
+ },
8054
+ {
8055
+ plural: "MarketplaceReviews",
8056
+ singular: "MarketplaceReview",
8057
+ module: "marketplace",
8058
+ right: "marketplace.reviews",
8059
+ readOnly: false,
8060
+ importable: false,
8061
+ allowDuplicate: false,
8062
+ updateBy: "_id",
8063
+ availableInSDK: true,
8064
+ sdkOperations: ["find", "findOne", "insert", "update", "aggregate", "count"],
8065
+ piiLevel: "low",
8066
+ searchable: true,
8067
+ searchableFields: ["comment", "publisherReply"],
8068
+ actions: [
8069
+ { title: "PUBLISHER_REPLY", action: "publisher-reply", availability: "single", method: "POST", icon: "reply" },
8070
+ ],
8071
+ entityActions: [
8072
+ { name: "publisher-reply", verb: "POST", emits: "replied", icon: "reply", labelKey: "marketplace.reviews.actions.publisher-reply" },
8073
+ ],
8074
+ },
8075
+ {
8076
+ plural: "ResellerDefaultBundles",
8077
+ singular: "ResellerDefaultBundle",
8078
+ module: "marketplace",
8079
+ right: "marketplace.resellerdefaultbundles",
8080
+ readOnly: false,
8081
+ importable: false,
8082
+ allowDuplicate: false,
8083
+ updateBy: "_id",
8084
+ availableInSDK: true,
8085
+ sdkOperations: ["find", "findOne", "insert", "update", "aggregate", "count"],
8086
+ piiLevel: "low",
8087
+ searchable: true,
8088
+ searchableFields: ["notes"],
8089
+ },
7936
8090
  // ─── Desktop Client module — states + rights per view ──────────────
7937
8091
  // desktopclient is a module in its own right (module: "desktopclient").
7938
8092
  // Each nav entry in the desktop client IS a state — registered via
@@ -1,6 +1,8 @@
1
1
  import { IDefaultFields } from "./IDefaultFields";
2
2
  import { ITax } from "./ITax";
3
3
  import { IFreeFields } from "./IFreeFields";
4
+ import { IaYOUneContract } from "./IaYOUneContract";
5
+ import { IShare } from "./IShare";
4
6
  interface MachineUtilization {
5
7
  machine: ObjectId;
6
8
  name?: string;
@@ -44,8 +46,8 @@ export interface IAssignment extends IDefaultFields, IFreeFields {
44
46
  internalDeclined?: boolean;
45
47
  internalDeclinedReason?: string;
46
48
  ayouneApproval?: string;
47
- ayouneContract: any;
48
- shares: any[];
49
+ ayouneContract?: IaYOUneContract;
50
+ shares?: IShare[];
49
51
  editors?: ObjectId[];
50
52
  team?: ObjectId[];
51
53
  agent?: string;
@@ -0,0 +1,197 @@
1
+ import { IDefaultFields } from "./IDefaultFields";
2
+ /**
3
+ * Discriminator for polymorphic ILinkPortalBlock.data shape.
4
+ *
5
+ * Phase 1 (Migration-Compat) — Pflicht-Set, deckt das gesamte Legacy
6
+ * `Settings.linkPortal`-Universum (groups/links/persons/customArea/headers/social) ab.
7
+ * Phase 2 — Schema-Slots, Renderer kommt on-demand. Der link-portal-Service
8
+ * rendert Phase-2-Blöcke heute mit `mixin-unsupported` (silent-skip + Logger-Warn),
9
+ * damit ein eingestellter Block keinen Render-Crash auslöst.
10
+ */
11
+ export type LinkPortalBlockType = "header" | "link" | "group" | "person" | "customHtml" | "vcard" | "qr" | "social" | "text" | "image" | "gallery" | "video" | "audio" | "pdf" | "map" | "faq" | "embed" | "newsletter" | "contactForm" | "booking" | "tipJar" | "product" | "countdown" | "divider" | "spacer";
12
+ export interface ILinkPortalVisibility {
13
+ devices?: ("mobile" | "tablet" | "desktop")[];
14
+ geo?: {
15
+ include?: string[];
16
+ exclude?: string[];
17
+ };
18
+ schedule?: {
19
+ from?: Date;
20
+ to?: Date;
21
+ };
22
+ abTest?: {
23
+ variant: string;
24
+ weight: number;
25
+ };
26
+ }
27
+ export interface ILinkPortalGating {
28
+ type: "password" | "email" | "age" | "login" | "paywall";
29
+ config: Record<string, any>;
30
+ }
31
+ /**
32
+ * Polymorpher Page-Block. `type` ist der Discriminator, `data` die
33
+ * type-spezifische Payload (siehe LinkPortalBlockData* unten).
34
+ *
35
+ * `translations[lang]` shadowed Felder aus `data` für die jeweilige Sprache.
36
+ * Nicht übersetzte Felder fallen auf `data` zurück (Default-Locale-Pfad in
37
+ * `clients/link-portal/src/lib/i18nBlock.ts` → `pickLocalized`).
38
+ */
39
+ export interface ILinkPortalBlock {
40
+ _id: ObjectId;
41
+ type: LinkPortalBlockType;
42
+ position: number;
43
+ visibility?: ILinkPortalVisibility;
44
+ gating?: ILinkPortalGating;
45
+ data: Record<string, any>;
46
+ translations?: {
47
+ [lang: string]: {
48
+ [field: string]: any;
49
+ };
50
+ };
51
+ metadata?: {
52
+ og?: {
53
+ title?: string;
54
+ description?: string;
55
+ image?: string;
56
+ };
57
+ };
58
+ isDraft?: boolean;
59
+ }
60
+ export interface LinkPortalBlockDataHeader {
61
+ title: string;
62
+ description?: string;
63
+ }
64
+ export interface LinkPortalBlockDataLink {
65
+ title: string;
66
+ tagLine?: string;
67
+ icon?: string;
68
+ link: string;
69
+ adult?: boolean;
70
+ }
71
+ export interface LinkPortalBlockDataGroup {
72
+ headerText?: string;
73
+ description?: string;
74
+ /** Children werden im selben Block-Array über `parentId` referenziert
75
+ * (flach für DB-Indizierbarkeit). Falls echtes Nesting gewünscht wird,
76
+ * kann der Adapter es in `children: ILinkPortalBlock[]` materialisieren. */
77
+ childIds?: ObjectId[];
78
+ }
79
+ export interface LinkPortalBlockDataPerson {
80
+ personRef: ObjectId;
81
+ description?: string;
82
+ tagLine?: string;
83
+ role?: string;
84
+ }
85
+ export interface LinkPortalBlockDataCustomHtml {
86
+ title?: string;
87
+ content: string;
88
+ }
89
+ export interface LinkPortalBlockDataVcard {
90
+ headerText?: string;
91
+ }
92
+ export interface LinkPortalBlockDataQr {
93
+ headerText?: string;
94
+ target?: string;
95
+ }
96
+ export interface LinkPortalBlockDataSocial {
97
+ headerText?: string;
98
+ links: {
99
+ provider: string;
100
+ url: string;
101
+ }[];
102
+ }
103
+ export interface ILinkPortalTheme {
104
+ backgroundMode: "gradient" | "image" | "video" | "solid";
105
+ color1: string;
106
+ color2: string;
107
+ fontColor: string;
108
+ backgroundImage?: string;
109
+ backgroundVideo?: string;
110
+ buttonColor1: string;
111
+ buttonColor2: string;
112
+ buttonFontColor: string;
113
+ buttonStyle?: "fill" | "outline" | "soft" | "gradient" | "glass";
114
+ buttonRadius?: number;
115
+ avatarShape?: "circle" | "square" | "rounded";
116
+ fontFamily?: string;
117
+ /** Premium-Slot. Wird nur bei publizierten Portals mit erlaubtem Right gerendert. */
118
+ customCss?: string;
119
+ }
120
+ export interface ILinkPortalBranding {
121
+ logo?: string;
122
+ logoLight?: string;
123
+ favicon?: string;
124
+ showLogo?: boolean;
125
+ showClaim?: boolean;
126
+ /** Sprach-Map: { de: '…', en: '…' } */
127
+ claimText?: {
128
+ [lang: string]: string;
129
+ };
130
+ }
131
+ export interface ILinkPortalMetadata {
132
+ /** Pro-Sprache OG-Tags. Fallback: `defaultLanguage`. */
133
+ og?: {
134
+ [lang: string]: {
135
+ title?: string;
136
+ description?: string;
137
+ image?: string;
138
+ };
139
+ };
140
+ schemaOrg?: Record<string, any>;
141
+ sitemap?: {
142
+ include: boolean;
143
+ priority?: number;
144
+ };
145
+ }
146
+ export interface ILinkPortalAnalyticsPixel {
147
+ provider: "meta" | "tiktok" | "ga4" | "google-ads" | "pinterest" | "snap";
148
+ id: string;
149
+ }
150
+ export interface ILinkPortalAnalyticsWebhook {
151
+ event: "view" | "click" | "gate-pass";
152
+ url: string;
153
+ }
154
+ export interface ILinkPortalAnalytics {
155
+ pixels?: ILinkPortalAnalyticsPixel[];
156
+ utmInherit?: boolean;
157
+ webhooks?: ILinkPortalAnalyticsWebhook[];
158
+ }
159
+ /**
160
+ * Optionale Migrations-Audit-Spur. Wird vom Renderer ignoriert, dient
161
+ * Stichproben + Hard-Remove-Phase G als verifizierbare Quelle.
162
+ */
163
+ export interface ILinkPortalLegacyTrace {
164
+ sourceSettingsId?: ObjectId;
165
+ migratedAt?: Date;
166
+ /** Verbatim Backup des originalen Settings.linkPortal-Sub-Docs. NIE löschen vor Phase G. */
167
+ raw?: Record<string, any>;
168
+ }
169
+ export interface ILinkPortal extends IDefaultFields {
170
+ _customerID: ObjectId;
171
+ _clientID?: ObjectId[];
172
+ _subID?: ObjectId[];
173
+ /** Globally unique Identifier (URL-Segment unter link.sb/<slug>/...). */
174
+ slug: string;
175
+ /** Optionaler Custom-Domain (FQDN). Unique sparse. */
176
+ customDomain?: string;
177
+ /** Interner Anzeigename in der Admin-Liste (nicht öffentlich gerendert). */
178
+ title: string;
179
+ /** Beschreibung (intern). */
180
+ description?: string;
181
+ status: "draft" | "published" | "scheduled";
182
+ publishAt?: Date;
183
+ unpublishAt?: Date;
184
+ /** ISO 639-1 (z.B. "de"). Fallback für Block-Translations. */
185
+ defaultLanguage: string;
186
+ /** Liste aller in diesem Portal aktivierten Sprachen. */
187
+ supportedLanguages: string[];
188
+ theme: ILinkPortalTheme;
189
+ branding: ILinkPortalBranding;
190
+ metadata: ILinkPortalMetadata;
191
+ analytics: ILinkPortalAnalytics;
192
+ /** Optionales Page-Level-Gate (vor jedem Block). */
193
+ pageGating?: ILinkPortalGating;
194
+ /** Polymorpher Block-Stream. Reihenfolge ergibt sich aus block.position. */
195
+ blocks: ILinkPortalBlock[];
196
+ legacy?: ILinkPortalLegacyTrace;
197
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -8,4 +8,10 @@ export interface ILinkPortalClick extends IaYOUneTrackingParams, IGeoIPLocationT
8
8
  _subID?: ObjectId[];
9
9
  _linkID?: ObjectId;
10
10
  channel?: string;
11
+ /** Reference to the LinkPortal entity (chapter 1.72). Sparse — pre-migration clicks lack this. */
12
+ _linkPortalID?: ObjectId;
13
+ /** Reference to the specific block clicked (chapter 1.72). Replaces legacy `_linkID`. */
14
+ _blockID?: ObjectId;
15
+ /** Resolved render-language at click time (ISO 639-1). Sparse — pre-i18n clicks lack this. */
16
+ lang?: string;
11
17
  }
@@ -7,4 +7,8 @@ export interface ILinkPortalView extends IaYOUneTrackingParams, IGeoIPLocationTr
7
7
  _clientID: ObjectId[];
8
8
  _subID: ObjectId[];
9
9
  channel: string;
10
+ /** Reference to the LinkPortal entity (chapter 1.72). Sparse — pre-migration views lack this. */
11
+ _linkPortalID?: ObjectId;
12
+ /** Resolved render-language for the visit (ISO 639-1). Sparse — pre-i18n views lack this. */
13
+ lang?: string;
10
14
  }
@@ -0,0 +1,46 @@
1
+ import { IDefaultFields } from "./IDefaultFields";
2
+ export type MarketplaceAppPublisher = "tolinax" | "reseller" | "customer";
3
+ export type MarketplaceAppStatus = "draft" | "review" | "published" | "archived" | "rejected";
4
+ export type MarketplaceAppSubscriptionInterval = "month" | "year" | null;
5
+ /**
6
+ * Public listing entity for the aYOUne Marketplace. An `IMarketplaceApp`
7
+ * is the publisher-facing product record; its content (templates, products,
8
+ * automations, ...) is attached via one or more `IMarketplaceBundle`s.
9
+ *
10
+ * Ownership is multi-tenant: `_customerID` is always the publisher customer.
11
+ * Tolinax-published apps use the tolinax customer as `_customerID` and
12
+ * `publisher: "tolinax"`. Resellers publish apps scoped to their own
13
+ * customer record with `publisher: "reseller"`. Customers can publish
14
+ * their own private apps for re-use within related customers.
15
+ */
16
+ export interface IMarketplaceApp extends IDefaultFields {
17
+ /** Owner / publisher customer (required, multi-tenant scoping field) */
18
+ _customerID: ObjectId;
19
+ /** The user within the publisher customer that pushed Publish */
20
+ _publisherUserID?: ObjectId;
21
+ publisher: MarketplaceAppPublisher;
22
+ name: string;
23
+ /** URL-safe slug, unique per `_customerID` via compound index */
24
+ slug: string;
25
+ description?: string;
26
+ /** e.g. "vertical", "integration", "addon" */
27
+ category?: string;
28
+ /** Optional industry tag for discovery (e.g. "dental", "construction") */
29
+ industry?: string;
30
+ tags?: string[];
31
+ /** URLs (uploaded via media-api) */
32
+ screenshots?: string[];
33
+ iconUrl?: string;
34
+ /** 0 = free. In EUR cents to avoid floating-point drift. */
35
+ price?: number;
36
+ subscriptionInterval?: MarketplaceAppSubscriptionInterval;
37
+ /** Basis points for publisher share. Default 7000 (= 70%). */
38
+ revenueShareBps?: number;
39
+ status: MarketplaceAppStatus;
40
+ publishedAt?: Date;
41
+ /** Human-readable reason shown to publisher when status === "rejected" */
42
+ rejectionReason?: string;
43
+ /** Tolinax-internal review metadata (hidden from reseller/customer UIs) */
44
+ reviewedBy?: ObjectId;
45
+ reviewedAt?: Date;
46
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,42 @@
1
+ import { IDefaultFields } from "./IDefaultFields";
2
+ export type MarketplaceBundleType = "vertical" | "addon" | "integration";
3
+ export type MarketplaceBundleContentType = "mail" | "emailtemplate" | "product" | "wallboard" | "automationtemplate" | "automation";
4
+ /**
5
+ * "clone" (default) = deep-copy the entity into the installer customer on
6
+ * install, after which the copy lives its own life.
7
+ *
8
+ * "reference" = the installer's customer references the publisher's entity
9
+ * directly (used for read-mostly catalog items and license-constrained
10
+ * integrations). Not all content types support referencing; the install
11
+ * action decides at runtime.
12
+ */
13
+ export type MarketplaceBundleCopyStrategy = "clone" | "reference";
14
+ export interface IMarketplaceBundleContent {
15
+ entityType: MarketplaceBundleContentType;
16
+ /** Points to the source entity in the publisher customer's DB */
17
+ _entityID: ObjectId;
18
+ /** Default: "clone" */
19
+ copyStrategy?: MarketplaceBundleCopyStrategy;
20
+ /** Optional human-readable label for the admin-v2 bundle editor */
21
+ label?: string;
22
+ }
23
+ /**
24
+ * A versioned bundle of content attached to a `IMarketplaceApp`. Installing
25
+ * an app means installing one bundle (the current `publishedAt`-latest one).
26
+ * New bundle versions for the same `_app` flip `updateAvailable=true` on
27
+ * existing installations.
28
+ */
29
+ export interface IMarketplaceBundle extends IDefaultFields {
30
+ /** Publisher customer (same as the parent app's `_customerID`) */
31
+ _customerID: ObjectId;
32
+ /** -> IMarketplaceApp._id */
33
+ _app: ObjectId;
34
+ bundleType: MarketplaceBundleType;
35
+ /** Semver-ish, e.g. "1.0.0". Compared lexicographically for update detection. */
36
+ version: string;
37
+ contents: IMarketplaceBundleContent[];
38
+ /** Optional release notes shown on the install-update modal */
39
+ changelog?: string;
40
+ /** Bumped on every publish — drives "Update available" detection */
41
+ publishedAt?: Date;
42
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,46 @@
1
+ import { IDefaultFields } from "./IDefaultFields";
2
+ import { IaYOUneContract } from "./IaYOUneContract";
3
+ export type MarketplaceInstallationStatus = "pending" | "active" | "paused" | "revoked";
4
+ /**
5
+ * IDs of the copied entities in the installer customer, grouped by
6
+ * collection. Only populated for content entries with
7
+ * `copyStrategy: "clone"` — "reference"-strategy entries are resolved live
8
+ * against the publisher customer and do not appear here.
9
+ */
10
+ export interface IMarketplaceInstallationCopiedIds {
11
+ mails?: ObjectId[];
12
+ emailtemplates?: ObjectId[];
13
+ products?: ObjectId[];
14
+ wallboards?: ObjectId[];
15
+ automations?: ObjectId[];
16
+ automationtemplates?: ObjectId[];
17
+ }
18
+ /**
19
+ * 1:1 installation record: one customer ↔ one app. Unique via
20
+ * `(_customerID, _app)` compound index. Tracks which bundle version is
21
+ * active, whether an update is available, and the Stripe subscription (for
22
+ * paid apps).
23
+ *
24
+ * The optional `ayouneContract` marker is reserved for an opt-in blockchain
25
+ * audit layer. It is written once on install and never read by current
26
+ * code — removing it later requires a migration, so it stays for now.
27
+ */
28
+ export interface IMarketplaceInstallation extends IDefaultFields {
29
+ /** Installer (target) customer */
30
+ _customerID: ObjectId;
31
+ /** Source (reseller / Tolinax) customer — shortcut to the app's owner */
32
+ _publisherCustomerID: ObjectId;
33
+ _app: ObjectId;
34
+ _bundle: ObjectId;
35
+ /** Snapshot of `IMarketplaceBundle.version` at install time */
36
+ bundleVersion: string;
37
+ status: MarketplaceInstallationStatus;
38
+ installedAt?: Date;
39
+ copiedEntityIds: IMarketplaceInstallationCopiedIds;
40
+ /** Set to true when a newer bundle version is published for the same app */
41
+ updateAvailable?: boolean;
42
+ /** Set when the app has `price > 0` and a Stripe subscription backs it */
43
+ _stripeSubscriptionID?: string;
44
+ /** Dormant blockchain-audit marker — set on install, never read today */
45
+ ayouneContract?: IaYOUneContract;
46
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,17 @@
1
+ import { IDefaultFields } from "./IDefaultFields";
2
+ /**
3
+ * Customer-submitted review for an installed `IMarketplaceApp`. The
4
+ * publisher can reply once per review via `PUT /marketplacereviews/:id`
5
+ * (only `publisherReply` + `publisherRepliedAt` writable from the
6
+ * publisher side).
7
+ */
8
+ export interface IMarketplaceReview extends IDefaultFields {
9
+ /** Reviewer customer */
10
+ _customerID: ObjectId;
11
+ _app: ObjectId;
12
+ /** 1-5 integer */
13
+ rating: number;
14
+ comment?: string;
15
+ publisherReply?: string;
16
+ publisherRepliedAt?: Date;
17
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,17 @@
1
+ import { IDefaultFields } from "./IDefaultFields";
2
+ /**
3
+ * Reseller-scoped default-bundle configuration. Allows a reseller customer
4
+ * to pre-configure a set of bundles that are auto-installed whenever they
5
+ * onboard a new sub-customer. The `order` field controls install sequence
6
+ * when multiple defaults apply.
7
+ */
8
+ export interface IResellerDefaultBundle extends IDefaultFields {
9
+ /** Reseller customer (owner of the default configuration) */
10
+ _customerID: ObjectId;
11
+ _bundle: ObjectId;
12
+ _app: ObjectId;
13
+ autoInstallOnCustomerCreate: boolean;
14
+ /** Lower = installed earlier */
15
+ order?: number;
16
+ notes?: string;
17
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -1005,7 +1005,18 @@ interface ISupportPortal {
1005
1005
  roadMapProjects: ObjectId[];
1006
1006
  seo: SEOAttributes;
1007
1007
  }
1008
- interface ILinkPortal {
1008
+ /**
1009
+ * @deprecated Use the standalone `LinkPortals` collection (see `ILinkPortal`).
1010
+ *
1011
+ * Lives only as `ISetting.linkPortal` for the dual-read window described in
1012
+ * `docs/migration/concept/migration-concept.md` chapter 1.72. The link-portal
1013
+ * service auto-migrates customers reading this sub-doc into a fresh
1014
+ * `LinkPortals` document on first request, then continues to serve from the
1015
+ * new collection. Hard-removal happens in Phase G after a 30+ day cool-down.
1016
+ *
1017
+ * Renamed from `ILinkPortal` to free that name for the new entity interface.
1018
+ */
1019
+ interface ILinkPortalLegacy {
1009
1020
  title: string;
1010
1021
  description: string;
1011
1022
  style: LinkPortalStyle;
@@ -1065,7 +1076,8 @@ export interface ISetting extends IDefaultFields {
1065
1076
  products: ProductsSettings;
1066
1077
  slides: SlidesSettings;
1067
1078
  customerportal: ISettingCustomerPortal;
1068
- linkPortal: ILinkPortal;
1079
+ /** @deprecated Migrated to standalone `LinkPortals` collection in chapter 1.72. */
1080
+ linkPortal: ILinkPortalLegacy;
1069
1081
  supportPortal: ISupportPortal;
1070
1082
  warehouse?: IWarehouseSettings;
1071
1083
  [x: string]: any;
@@ -404,6 +404,7 @@ export * from "./IKPINewsletterType";
404
404
  export * from "./IKPITemplate";
405
405
  export * from "./ILabel";
406
406
  export * from "./ILead";
407
+ export * from "./ILinkPortal";
407
408
  export * from "./ILinkPortalClick";
408
409
  export * from "./ILinkPortalView";
409
410
  export * from "./ILoadingList";
@@ -434,6 +435,10 @@ export * from "./IMarketBudget";
434
435
  export * from "./IMarketBudgetByIndustry";
435
436
  export * from "./IIndustryKPI";
436
437
  export * from "./IMarketResearch";
438
+ export * from "./IMarketplaceApp";
439
+ export * from "./IMarketplaceBundle";
440
+ export * from "./IMarketplaceInstallation";
441
+ export * from "./IMarketplaceReview";
437
442
  export * from "./IMaterial";
438
443
  export * from "./IMaterialCommissioning";
439
444
  export * from "./IMeeting";
@@ -565,6 +570,7 @@ export * from "./IRepository";
565
570
  export * from "./IRequirement";
566
571
  export * from "./IRequirementSchema";
567
572
  export * from "./IResearchBudget";
573
+ export * from "./IResellerDefaultBundle";
568
574
  export * from "./IRetrospective";
569
575
  export * from "./IReturnOrder";
570
576
  export * from "./IRewardLog";
@@ -420,6 +420,7 @@ __exportStar(require("./IKPINewsletterType"), exports);
420
420
  __exportStar(require("./IKPITemplate"), exports);
421
421
  __exportStar(require("./ILabel"), exports);
422
422
  __exportStar(require("./ILead"), exports);
423
+ __exportStar(require("./ILinkPortal"), exports);
423
424
  __exportStar(require("./ILinkPortalClick"), exports);
424
425
  __exportStar(require("./ILinkPortalView"), exports);
425
426
  __exportStar(require("./ILoadingList"), exports);
@@ -450,6 +451,10 @@ __exportStar(require("./IMarketBudget"), exports);
450
451
  __exportStar(require("./IMarketBudgetByIndustry"), exports);
451
452
  __exportStar(require("./IIndustryKPI"), exports);
452
453
  __exportStar(require("./IMarketResearch"), exports);
454
+ __exportStar(require("./IMarketplaceApp"), exports);
455
+ __exportStar(require("./IMarketplaceBundle"), exports);
456
+ __exportStar(require("./IMarketplaceInstallation"), exports);
457
+ __exportStar(require("./IMarketplaceReview"), exports);
453
458
  __exportStar(require("./IMaterial"), exports);
454
459
  __exportStar(require("./IMaterialCommissioning"), exports);
455
460
  __exportStar(require("./IMeeting"), exports);
@@ -581,6 +586,7 @@ __exportStar(require("./IRepository"), exports);
581
586
  __exportStar(require("./IRequirement"), exports);
582
587
  __exportStar(require("./IRequirementSchema"), exports);
583
588
  __exportStar(require("./IResearchBudget"), exports);
589
+ __exportStar(require("./IResellerDefaultBundle"), exports);
584
590
  __exportStar(require("./IRetrospective"), exports);
585
591
  __exportStar(require("./IReturnOrder"), exports);
586
592
  __exportStar(require("./IRewardLog"), exports);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tolinax/ayoune-interfaces",
3
- "version": "2026.63.0",
3
+ "version": "2026.65.0",
4
4
  "description": "Houses TypeScript interfaces for aYOUne",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",