ad2app-lib 1.49.0 → 1.59.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/analytics/index.d.ts +85 -2
- package/dist/analytics/index.js +26 -0
- package/dist/types/I_AccessDenial.d.ts +7 -0
- package/dist/types/I_AccessDenial.js +7 -0
- package/dist/types/agency-campaigns.d.ts +108 -5
- package/dist/types/agency-campaigns.js +111 -5
- package/dist/types/agency-pots.d.ts +518 -0
- package/dist/types/agency-pots.js +393 -0
- package/dist/types/agency-threads.d.ts +22 -1
- package/dist/types/agency.d.ts +93 -6
- package/dist/types/agency.js +70 -3
- package/dist/types/dealroom.d.ts +651 -0
- package/dist/types/dealroom.js +387 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.js +3 -0
- package/package.json +1 -1
- package/src/analytics/index.test.ts +23 -1
- package/src/analytics/index.ts +69 -2
- package/src/types/I_AccessDenial.ts +7 -0
- package/src/types/access-denial.test.ts +2 -1
- package/src/types/agency-campaigns.ts +187 -5
- package/src/types/agency-pots.test.ts +255 -0
- package/src/types/agency-pots.ts +751 -0
- package/src/types/agency-threads.ts +14 -3
- package/src/types/agency.ts +120 -7
- package/src/types/consumer-compat.test.ts +90 -0
- package/src/types/dealroom-audit1.test.ts +56 -0
- package/src/types/dealroom-wave2.test.ts +61 -0
- package/src/types/dealroom-wave3.test.ts +68 -0
- package/src/types/dealroom-wave4.test.ts +103 -0
- package/src/types/dealroom.test.ts +231 -0
- package/src/types/dealroom.ts +868 -0
- package/src/types/index.ts +4 -0
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Dealroom (spec 148): only what spec 175 has no concept of.
|
|
4
|
+
*
|
|
5
|
+
* The organization, membership, grant, campaign, offer loop, materials,
|
|
6
|
+
* threads and pots are 175's (`agency*.ts`); 148 adds unions there and keeps
|
|
7
|
+
* this file for the open listing, matching, the coarse creator row, its codes,
|
|
8
|
+
* the dormant money layer and the commission lane.
|
|
9
|
+
*
|
|
10
|
+
* The money types below are DORMANT: the backend refuses every money act with
|
|
11
|
+
* `dealroom-money-disabled` until the money release (FR-027). Their state
|
|
12
|
+
* lists mirror data-model.md's state machine exactly.
|
|
13
|
+
*
|
|
14
|
+
* See specs/148-dealroom/contracts/lib-types.md.
|
|
15
|
+
*/
|
|
16
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
17
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
18
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
19
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
20
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
21
|
+
};
|
|
22
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
23
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.DealroomCalendarQueryDto = exports.DEALROOM_CALENDAR_MAX_DAYS = exports.DEALROOM_CALENDAR_KINDS = exports.ReviewCommissionAdSpaceDto = exports.COMMISSION_AD_SPACE_DECISIONS = exports.COMMISSION_AD_SPACE_STATES = exports.COMMISSION_JOIN_STATES = exports.COMMISSION_MATERIAL_KINDS = exports.COMMISSION_LINK_MODES = exports.COMMISSION_LINK_STATES = exports.COMMISSION_OFFER_STATES = exports.COMMISSION_NETWORKS = exports.UpsertPayoutProfileDto = exports.PAYOUT_PROFILE_FIELDS = exports.DEAL_MONEY_ACTIONS = exports.StartDealPaymentDto = exports.DEAL_PAYMENT_METHODS = exports.CreateDealContractDto = exports.DEAL_SIGNATURE_LEVELS = exports.DEAL_CONTRACT_STATES = exports.DEAL_CONTRACT_SOURCES = exports.DEALROOM_MONEY_EVENT_KINDS = exports.PAYOUT_LEDGER_STATES = exports.PAYOUT_LEDGER_SOURCES = exports.PAYOUT_BILLING_VARIANTS = exports.DEAL_PAYOUT_STATES = exports.DEAL_MONEY_STATES = exports.DEALROOM_CODES = exports.ApplyToDealroomListingDto = exports.DEALROOM_LISTING_STATES = exports.DEALROOM_PROFILE_FIELDS = exports.isCampaignVisibility = exports.CAMPAIGN_VISIBILITIES = void 0;
|
|
27
|
+
const class_validator_1 = require("class-validator");
|
|
28
|
+
const agency_1 = require("./agency");
|
|
29
|
+
// ── Open listing ─────────────────────────────────────────────────────────────
|
|
30
|
+
/** `private` is every 175 campaign today (members only); `open` is listed in the feed to matching creators. */
|
|
31
|
+
exports.CAMPAIGN_VISIBILITIES = ['private', 'open'];
|
|
32
|
+
const isCampaignVisibility = (value) => exports.CAMPAIGN_VISIBILITIES.includes(value);
|
|
33
|
+
exports.isCampaignVisibility = isCampaignVisibility;
|
|
34
|
+
/** The profile fields whose absence makes the feed `profile_incomplete` (FR-026). */
|
|
35
|
+
exports.DEALROOM_PROFILE_FIELDS = ['country', 'niches'];
|
|
36
|
+
// ── The organization's side of a listing (US3) ──────────────────────────────
|
|
37
|
+
/**
|
|
38
|
+
* Derived, never stored: `draft` (175 isDraft) → `live` (open, not closed,
|
|
39
|
+
* before its deadline, a slot free) → `frozen` (live, and a creator has been
|
|
40
|
+
* invited or applied: only the deadline, the slots and closing may change) →
|
|
41
|
+
* `closed` (closed by the organization, past its deadline, or full).
|
|
42
|
+
*/
|
|
43
|
+
exports.DEALROOM_LISTING_STATES = ['draft', 'live', 'frozen', 'closed'];
|
|
44
|
+
// ── Applying (US4) ───────────────────────────────────────────────────────────
|
|
45
|
+
/**
|
|
46
|
+
* `POST /dealroom/listings/:campaignId/apply`. `scopes`: what the creator
|
|
47
|
+
* shares, a non-empty subset of the listing's `askedScopes`. An offer
|
|
48
|
+
* listing takes the opening price (`priceMinor` + `currency`); a pot listing
|
|
49
|
+
* takes the creator's own terms (`guaranteeMinor` + `ratePer1000Minor`).
|
|
50
|
+
*/
|
|
51
|
+
class ApplyToDealroomListingDto {
|
|
52
|
+
constructor(data) {
|
|
53
|
+
this.scopes = data?.scopes ?? [];
|
|
54
|
+
this.priceMinor = data?.priceMinor;
|
|
55
|
+
this.currency = data?.currency;
|
|
56
|
+
this.guaranteeMinor = data?.guaranteeMinor;
|
|
57
|
+
this.ratePer1000Minor = data?.ratePer1000Minor;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
exports.ApplyToDealroomListingDto = ApplyToDealroomListingDto;
|
|
61
|
+
__decorate([
|
|
62
|
+
(0, class_validator_1.IsArray)(),
|
|
63
|
+
(0, class_validator_1.ArrayNotEmpty)(),
|
|
64
|
+
(0, class_validator_1.IsIn)(agency_1.AGENCY_GRANT_SCOPES, { each: true }),
|
|
65
|
+
__metadata("design:type", Array)
|
|
66
|
+
], ApplyToDealroomListingDto.prototype, "scopes", void 0);
|
|
67
|
+
__decorate([
|
|
68
|
+
(0, class_validator_1.IsOptional)(),
|
|
69
|
+
(0, class_validator_1.IsInt)(),
|
|
70
|
+
(0, class_validator_1.Min)(0),
|
|
71
|
+
(0, class_validator_1.Max)(1000000000),
|
|
72
|
+
__metadata("design:type", Number)
|
|
73
|
+
], ApplyToDealroomListingDto.prototype, "priceMinor", void 0);
|
|
74
|
+
__decorate([
|
|
75
|
+
(0, class_validator_1.IsOptional)(),
|
|
76
|
+
(0, class_validator_1.IsString)(),
|
|
77
|
+
(0, class_validator_1.Matches)(/^[A-Z]{3}$/),
|
|
78
|
+
__metadata("design:type", String)
|
|
79
|
+
], ApplyToDealroomListingDto.prototype, "currency", void 0);
|
|
80
|
+
__decorate([
|
|
81
|
+
(0, class_validator_1.IsOptional)(),
|
|
82
|
+
(0, class_validator_1.IsInt)(),
|
|
83
|
+
(0, class_validator_1.Min)(0),
|
|
84
|
+
(0, class_validator_1.Max)(1000000000),
|
|
85
|
+
__metadata("design:type", Number)
|
|
86
|
+
], ApplyToDealroomListingDto.prototype, "guaranteeMinor", void 0);
|
|
87
|
+
__decorate([
|
|
88
|
+
(0, class_validator_1.IsOptional)(),
|
|
89
|
+
(0, class_validator_1.IsInt)(),
|
|
90
|
+
(0, class_validator_1.Min)(0),
|
|
91
|
+
(0, class_validator_1.Max)(1000000000),
|
|
92
|
+
__metadata("design:type", Number)
|
|
93
|
+
], ApplyToDealroomListingDto.prototype, "ratePer1000Minor", void 0);
|
|
94
|
+
// ── Codes ────────────────────────────────────────────────────────────────────
|
|
95
|
+
/** Refusal codes the frontend owes its own copy for (contracts/dealroom-api.md). */
|
|
96
|
+
exports.DEALROOM_CODES = {
|
|
97
|
+
OFFER_FILLED: 'dealroom-offer-filled',
|
|
98
|
+
LISTING_FROZEN: 'dealroom-listing-frozen',
|
|
99
|
+
NEAR_MATCH_NOT_APPLIABLE: 'dealroom-near-match-not-appliable',
|
|
100
|
+
PROFILE_INCOMPLETE: 'dealroom-profile-incomplete',
|
|
101
|
+
BRAND_DOOR_CLOSED: 'dealroom-brand-door-closed',
|
|
102
|
+
BRAND_NO_ROSTER: 'dealroom-brand-no-roster',
|
|
103
|
+
DELEGATE_FORBIDDEN: 'dealroom-delegate-forbidden',
|
|
104
|
+
DELEGATE_OWN_DEAL: 'dealroom-delegate-own-deal',
|
|
105
|
+
/** A delegate never writes the creator's grant consent: joining with an access request, or an apply that would create or widen the grant's reads. */
|
|
106
|
+
DELEGATE_CONSENT_FORBIDDEN: 'dealroom-delegate-consent-forbidden',
|
|
107
|
+
/** The money switch is off: every money route and act answers 404 with this code (FR-027). Means nothing else. */
|
|
108
|
+
MONEY_DISABLED: 'dealroom-money-disabled',
|
|
109
|
+
/** Money on, but a value the act needs is not configured yet (e.g. the deal's deposit %). 422. */
|
|
110
|
+
CONFIG_MISSING: 'dealroom-config-missing',
|
|
111
|
+
/** Money on, but the platform contract template is still waiting for counsel: upload your own. 422. */
|
|
112
|
+
TEMPLATE_PENDING: 'dealroom-template-pending',
|
|
113
|
+
/** An open listing needs the organization's logo first (US2). 400. */
|
|
114
|
+
LOGO_REQUIRED: 'dealroom-logo-required',
|
|
115
|
+
CONTRACT_UNSIGNED: 'dealroom-contract-unsigned',
|
|
116
|
+
DEPOSIT_REQUIRED: 'dealroom-deposit-required',
|
|
117
|
+
NOT_FUNDED: 'dealroom-not-funded',
|
|
118
|
+
/** Money release: the agreed amount is under the fee config's minimum deal. */
|
|
119
|
+
DEAL_BELOW_MINIMUM: 'dealroom-deal-below-minimum',
|
|
120
|
+
/** Money release: that money act is not open at the deal's current step. */
|
|
121
|
+
MONEY_WRONG_STEP: 'dealroom-money-wrong-step',
|
|
122
|
+
/** Money release: the deal already has a contract out for signature or signed. */
|
|
123
|
+
CONTRACT_EXISTS: 'dealroom-contract-exists',
|
|
124
|
+
/** Money release: no guarantee is configured, or the claim is not open yet. */
|
|
125
|
+
GUARANTEE_UNAVAILABLE: 'dealroom-guarantee-unavailable',
|
|
126
|
+
/** Commission lane (2026-10-07): the creator's Admitad Ad Space is still under admin review; no link yet. */
|
|
127
|
+
COMMISSION_AD_SPACE_PENDING: 'commission-ad-space-pending',
|
|
128
|
+
/** Commission lane (2026-10-07): the creator's Admitad Ad Space was rejected or suspended; no Admitad link. */
|
|
129
|
+
COMMISSION_AD_SPACE_UNAVAILABLE: 'commission-ad-space-unavailable',
|
|
130
|
+
/** Admin: that decision is not open from the Ad Space's state (a suspended or rejected Ad Space is never re-registered under a new id). */
|
|
131
|
+
COMMISSION_AD_SPACE_DECISION_CLOSED: 'commission-ad-space-decision-closed',
|
|
132
|
+
/** The network did not answer a join or a registration; nothing was written. */
|
|
133
|
+
COMMISSION_NETWORK_UNAVAILABLE: 'commission-network-unavailable',
|
|
134
|
+
};
|
|
135
|
+
// ── Money (DORMANT until the money release) ──────────────────────────────────
|
|
136
|
+
/**
|
|
137
|
+
* The deal's money state (FR-010), exactly data-model.md's machine:
|
|
138
|
+
*
|
|
139
|
+
* awaiting_material → material_submitted → deposit_paid → funded → approved → published
|
|
140
|
+
* deposit declined → closed_unviewed
|
|
141
|
+
* funded/approved, never published → refund_pending → refunded
|
|
142
|
+
* delivered, never funded → guarantee_claimed
|
|
143
|
+
*
|
|
144
|
+
* The payout after publication is its own column (DEAL_PAYOUT_STATES).
|
|
145
|
+
*/
|
|
146
|
+
exports.DEAL_MONEY_STATES = [
|
|
147
|
+
'awaiting_material',
|
|
148
|
+
'material_submitted',
|
|
149
|
+
'deposit_paid',
|
|
150
|
+
'funded',
|
|
151
|
+
'approved',
|
|
152
|
+
'published',
|
|
153
|
+
'closed_unviewed',
|
|
154
|
+
'refund_pending',
|
|
155
|
+
'refunded',
|
|
156
|
+
'guarantee_claimed',
|
|
157
|
+
];
|
|
158
|
+
exports.DEAL_PAYOUT_STATES = ['none', 'initiated', 'paid'];
|
|
159
|
+
/** Derived from 175's settlement form (`invoice` → faktura_vat, `contract` → umowa_o_dzielo); `international` is 148's. */
|
|
160
|
+
exports.PAYOUT_BILLING_VARIANTS = ['faktura_vat', 'umowa_o_dzielo', 'international'];
|
|
161
|
+
exports.PAYOUT_LEDGER_SOURCES = ['deal', 'pot', 'commission'];
|
|
162
|
+
/** Commission entries are `validated` only after the network pays us. */
|
|
163
|
+
exports.PAYOUT_LEDGER_STATES = ['earned', 'validated', 'paid'];
|
|
164
|
+
// ── Money release, wave 4 (DORMANT): contract step, deal money, payouts ──────
|
|
165
|
+
/** The contract, money and payout kinds this release writes into 175's event log (FR-008a). */
|
|
166
|
+
exports.DEALROOM_MONEY_EVENT_KINDS = [
|
|
167
|
+
'contract_sent',
|
|
168
|
+
'contract_signed',
|
|
169
|
+
'contract_declined',
|
|
170
|
+
'deposit_paid',
|
|
171
|
+
'deal_funded',
|
|
172
|
+
'deal_closed_unviewed',
|
|
173
|
+
'deal_refund_requested',
|
|
174
|
+
'deal_refunded',
|
|
175
|
+
'guarantee_claimed',
|
|
176
|
+
'payout_initiated',
|
|
177
|
+
'payout_paid',
|
|
178
|
+
];
|
|
179
|
+
exports.DEAL_CONTRACT_SOURCES = ['template', 'uploaded'];
|
|
180
|
+
/** `draft` again after a signer declines; `signed` once every party signed (the e-sign provider's word). */
|
|
181
|
+
exports.DEAL_CONTRACT_STATES = ['draft', 'sent', 'signed'];
|
|
182
|
+
/** SES by default, QES as an option (research R2; counsel point 3 may require QES for some documents). */
|
|
183
|
+
exports.DEAL_SIGNATURE_LEVELS = ['SES', 'QES'];
|
|
184
|
+
/**
|
|
185
|
+
* `POST /agency/campaigns/:id/members/:memberId/contract` (organization side).
|
|
186
|
+
* `template`: the form fields (deliverables default to the brief's, the rate is
|
|
187
|
+
* the agreed price). `uploaded`: the organization's own file, base64.
|
|
188
|
+
*/
|
|
189
|
+
class CreateDealContractDto {
|
|
190
|
+
constructor(data) {
|
|
191
|
+
this.source = data?.source ?? 'template';
|
|
192
|
+
this.signatureLevel = data?.signatureLevel;
|
|
193
|
+
this.deliverables = data?.deliverables;
|
|
194
|
+
this.draftDueAt = data?.draftDueAt;
|
|
195
|
+
this.liveByAt = data?.liveByAt;
|
|
196
|
+
this.licenceMonths = data?.licenceMonths;
|
|
197
|
+
this.paidPromoMonths = data?.paidPromoMonths;
|
|
198
|
+
this.fileName = data?.fileName;
|
|
199
|
+
this.fileBase64 = data?.fileBase64;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
exports.CreateDealContractDto = CreateDealContractDto;
|
|
203
|
+
__decorate([
|
|
204
|
+
(0, class_validator_1.IsIn)(exports.DEAL_CONTRACT_SOURCES),
|
|
205
|
+
__metadata("design:type", String)
|
|
206
|
+
], CreateDealContractDto.prototype, "source", void 0);
|
|
207
|
+
__decorate([
|
|
208
|
+
(0, class_validator_1.IsOptional)(),
|
|
209
|
+
(0, class_validator_1.IsIn)(exports.DEAL_SIGNATURE_LEVELS),
|
|
210
|
+
__metadata("design:type", String)
|
|
211
|
+
], CreateDealContractDto.prototype, "signatureLevel", void 0);
|
|
212
|
+
__decorate([
|
|
213
|
+
(0, class_validator_1.IsOptional)(),
|
|
214
|
+
(0, class_validator_1.IsArray)(),
|
|
215
|
+
(0, class_validator_1.ArrayMaxSize)(20),
|
|
216
|
+
(0, class_validator_1.IsString)({ each: true }),
|
|
217
|
+
(0, class_validator_1.MaxLength)(500, { each: true }),
|
|
218
|
+
__metadata("design:type", Array)
|
|
219
|
+
], CreateDealContractDto.prototype, "deliverables", void 0);
|
|
220
|
+
__decorate([
|
|
221
|
+
(0, class_validator_1.IsOptional)(),
|
|
222
|
+
(0, class_validator_1.IsDateString)(),
|
|
223
|
+
__metadata("design:type", String)
|
|
224
|
+
], CreateDealContractDto.prototype, "draftDueAt", void 0);
|
|
225
|
+
__decorate([
|
|
226
|
+
(0, class_validator_1.IsOptional)(),
|
|
227
|
+
(0, class_validator_1.IsDateString)(),
|
|
228
|
+
__metadata("design:type", String)
|
|
229
|
+
], CreateDealContractDto.prototype, "liveByAt", void 0);
|
|
230
|
+
__decorate([
|
|
231
|
+
(0, class_validator_1.IsOptional)(),
|
|
232
|
+
(0, class_validator_1.IsInt)(),
|
|
233
|
+
(0, class_validator_1.Min)(0),
|
|
234
|
+
(0, class_validator_1.Max)(120),
|
|
235
|
+
__metadata("design:type", Number)
|
|
236
|
+
], CreateDealContractDto.prototype, "licenceMonths", void 0);
|
|
237
|
+
__decorate([
|
|
238
|
+
(0, class_validator_1.IsOptional)(),
|
|
239
|
+
(0, class_validator_1.IsInt)(),
|
|
240
|
+
(0, class_validator_1.Min)(0),
|
|
241
|
+
(0, class_validator_1.Max)(120),
|
|
242
|
+
__metadata("design:type", Number)
|
|
243
|
+
], CreateDealContractDto.prototype, "paidPromoMonths", void 0);
|
|
244
|
+
__decorate([
|
|
245
|
+
(0, class_validator_1.IsOptional)(),
|
|
246
|
+
(0, class_validator_1.IsString)(),
|
|
247
|
+
(0, class_validator_1.MaxLength)(255),
|
|
248
|
+
__metadata("design:type", String)
|
|
249
|
+
], CreateDealContractDto.prototype, "fileName", void 0);
|
|
250
|
+
__decorate([
|
|
251
|
+
(0, class_validator_1.IsOptional)(),
|
|
252
|
+
(0, class_validator_1.IsString)(),
|
|
253
|
+
__metadata("design:type", String)
|
|
254
|
+
], CreateDealContractDto.prototype, "fileBase64", void 0);
|
|
255
|
+
/** Card (PaymentIntent, confirmed in the browser) or invoice (a Stripe invoice the organization pays by transfer). */
|
|
256
|
+
exports.DEAL_PAYMENT_METHODS = ['card', 'invoice'];
|
|
257
|
+
/** `POST /agency/campaigns/:id/members/:memberId/deal/deposit|fund`. Big sums go by invoice whatever is asked. */
|
|
258
|
+
class StartDealPaymentDto {
|
|
259
|
+
constructor(data) {
|
|
260
|
+
this.method = data?.method;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
exports.StartDealPaymentDto = StartDealPaymentDto;
|
|
264
|
+
__decorate([
|
|
265
|
+
(0, class_validator_1.IsOptional)(),
|
|
266
|
+
(0, class_validator_1.IsIn)(exports.DEAL_PAYMENT_METHODS),
|
|
267
|
+
__metadata("design:type", String)
|
|
268
|
+
], StartDealPaymentDto.prototype, "method", void 0);
|
|
269
|
+
/** The money acts a deal view may offer; the server decides which, per side and step. */
|
|
270
|
+
exports.DEAL_MONEY_ACTIONS = ['send_contract', 'pay_deposit', 'decline_deposit', 'fund', 'refund', 'claim_guarantee'];
|
|
271
|
+
/** What the first payout needs and is missing; the provider's KYC runs behind the form and is never a field. */
|
|
272
|
+
exports.PAYOUT_PROFILE_FIELDS = ['settlement_form', 'nip', 'tax_statement', 'intl_billing_data', 'iban', 'payout_currency'];
|
|
273
|
+
/**
|
|
274
|
+
* `PUT /dealroom/payouts/profile`. The track is NOT here: it is read from the
|
|
275
|
+
* 175 settlement form. `international` picks the international variant.
|
|
276
|
+
*/
|
|
277
|
+
class UpsertPayoutProfileDto {
|
|
278
|
+
constructor(data) {
|
|
279
|
+
this.international = data?.international;
|
|
280
|
+
this.nip = data?.nip;
|
|
281
|
+
this.taxStatement = data?.taxStatement;
|
|
282
|
+
this.intlBillingData = data?.intlBillingData;
|
|
283
|
+
this.iban = data?.iban ?? '';
|
|
284
|
+
this.payoutCurrency = data?.payoutCurrency ?? '';
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
exports.UpsertPayoutProfileDto = UpsertPayoutProfileDto;
|
|
288
|
+
__decorate([
|
|
289
|
+
(0, class_validator_1.IsOptional)(),
|
|
290
|
+
(0, class_validator_1.IsBoolean)(),
|
|
291
|
+
__metadata("design:type", Boolean)
|
|
292
|
+
], UpsertPayoutProfileDto.prototype, "international", void 0);
|
|
293
|
+
__decorate([
|
|
294
|
+
(0, class_validator_1.IsOptional)(),
|
|
295
|
+
(0, class_validator_1.IsString)(),
|
|
296
|
+
(0, class_validator_1.Matches)(/^[0-9]{10}$/),
|
|
297
|
+
__metadata("design:type", String)
|
|
298
|
+
], UpsertPayoutProfileDto.prototype, "nip", void 0);
|
|
299
|
+
__decorate([
|
|
300
|
+
(0, class_validator_1.IsOptional)(),
|
|
301
|
+
(0, class_validator_1.IsString)(),
|
|
302
|
+
(0, class_validator_1.MaxLength)(2000),
|
|
303
|
+
__metadata("design:type", String)
|
|
304
|
+
], UpsertPayoutProfileDto.prototype, "taxStatement", void 0);
|
|
305
|
+
__decorate([
|
|
306
|
+
(0, class_validator_1.IsOptional)(),
|
|
307
|
+
(0, class_validator_1.IsObject)(),
|
|
308
|
+
__metadata("design:type", Object)
|
|
309
|
+
], UpsertPayoutProfileDto.prototype, "intlBillingData", void 0);
|
|
310
|
+
__decorate([
|
|
311
|
+
(0, class_validator_1.IsString)(),
|
|
312
|
+
(0, class_validator_1.Matches)(/^[A-Z]{2}[0-9]{2}(?:\s?[A-Z0-9]){11,30}$/),
|
|
313
|
+
__metadata("design:type", String)
|
|
314
|
+
], UpsertPayoutProfileDto.prototype, "iban", void 0);
|
|
315
|
+
__decorate([
|
|
316
|
+
(0, class_validator_1.IsString)(),
|
|
317
|
+
(0, class_validator_1.Matches)(/^[A-Z]{3}$/),
|
|
318
|
+
__metadata("design:type", String)
|
|
319
|
+
], UpsertPayoutProfileDto.prototype, "payoutCurrency", void 0);
|
|
320
|
+
// ── Commission lane ──────────────────────────────────────────────────────────
|
|
321
|
+
exports.COMMISSION_NETWORKS = ['awin', 'admitad'];
|
|
322
|
+
exports.COMMISSION_OFFER_STATES = ['live', 'paused', 'gone'];
|
|
323
|
+
exports.COMMISSION_LINK_STATES = ['active', 'suspended'];
|
|
324
|
+
/**
|
|
325
|
+
* `subnetwork`: minted from OUR publisher account with the creator's own
|
|
326
|
+
* attribution (Awin `clickref` = creator id; Admitad = the creator's registered
|
|
327
|
+
* Ad Space). `deeplink`: the fallback while a network's subnetwork mode is off,
|
|
328
|
+
* a plain link to the programme on the network, carrying no attribution of ours.
|
|
329
|
+
*/
|
|
330
|
+
exports.COMMISSION_LINK_MODES = ['subnetwork', 'deeplink'];
|
|
331
|
+
/** An advertiser creative as the network feed carries it (2026-10-07). */
|
|
332
|
+
exports.COMMISSION_MATERIAL_KINDS = ['logo', 'banner', 'landing_preview', 'coupon'];
|
|
333
|
+
/** `POST /dealroom/commission/offers/:id/join`: what the join produced. */
|
|
334
|
+
exports.COMMISSION_JOIN_STATES = ['link', 'deeplink', 'ad_space_pending'];
|
|
335
|
+
// ── Commission lane: the Admitad Ad Space per creator (2026-10-07) ───────────
|
|
336
|
+
/**
|
|
337
|
+
* One static Ad Space per creator (Admitad Subnetwork Code of Conduct §3.1/§5):
|
|
338
|
+
* created `pending_review` on the first Admitad join, `registered` through the
|
|
339
|
+
* Partner networks API after an admin approves, or `rejected` / `suspended`.
|
|
340
|
+
* Its id is never rotated, deleted or reassigned.
|
|
341
|
+
*/
|
|
342
|
+
exports.COMMISSION_AD_SPACE_STATES = ['pending_review', 'registered', 'rejected', 'suspended'];
|
|
343
|
+
exports.COMMISSION_AD_SPACE_DECISIONS = ['approve', 'reject', 'suspend'];
|
|
344
|
+
/** `PATCH /admin/dealroom/commission/ad-spaces/:id`. */
|
|
345
|
+
class ReviewCommissionAdSpaceDto {
|
|
346
|
+
constructor(data) {
|
|
347
|
+
this.decision = data?.decision;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
exports.ReviewCommissionAdSpaceDto = ReviewCommissionAdSpaceDto;
|
|
351
|
+
__decorate([
|
|
352
|
+
(0, class_validator_1.IsIn)(exports.COMMISSION_AD_SPACE_DECISIONS),
|
|
353
|
+
__metadata("design:type", String)
|
|
354
|
+
], ReviewCommissionAdSpaceDto.prototype, "decision", void 0);
|
|
355
|
+
// ── The calendar (US9, T041) ─────────────────────────────────────────────────
|
|
356
|
+
/**
|
|
357
|
+
* What a deal date on the creator's calendar is. No second deadline store:
|
|
358
|
+
* `milestone` is a 175 milestone (`campaign-deadlines`, the creator's own or
|
|
359
|
+
* campaign-wide); the pot dates are the US9 schedule; `publish_at` is the
|
|
360
|
+
* agreed publication time (a pot entry's, or an offer deal's, T067).
|
|
361
|
+
*/
|
|
362
|
+
exports.DEALROOM_CALENDAR_KINDS = [
|
|
363
|
+
'milestone',
|
|
364
|
+
'application_deadline',
|
|
365
|
+
'materials_due',
|
|
366
|
+
'publication_due',
|
|
367
|
+
'publish_at',
|
|
368
|
+
'bonus_ends',
|
|
369
|
+
'keep_up_ends',
|
|
370
|
+
];
|
|
371
|
+
/** The calendar window: both ends required, at most DEALROOM_CALENDAR_MAX_DAYS apart. */
|
|
372
|
+
exports.DEALROOM_CALENDAR_MAX_DAYS = 400;
|
|
373
|
+
class DealroomCalendarQueryDto {
|
|
374
|
+
constructor(data) {
|
|
375
|
+
this.from = data?.from ?? '';
|
|
376
|
+
this.to = data?.to ?? '';
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
exports.DealroomCalendarQueryDto = DealroomCalendarQueryDto;
|
|
380
|
+
__decorate([
|
|
381
|
+
(0, class_validator_1.IsDateString)(),
|
|
382
|
+
__metadata("design:type", String)
|
|
383
|
+
], DealroomCalendarQueryDto.prototype, "from", void 0);
|
|
384
|
+
__decorate([
|
|
385
|
+
(0, class_validator_1.IsDateString)(),
|
|
386
|
+
__metadata("design:type", String)
|
|
387
|
+
], DealroomCalendarQueryDto.prototype, "to", void 0);
|
package/dist/types/index.d.ts
CHANGED
|
@@ -39,5 +39,7 @@ export * from "./scheduling";
|
|
|
39
39
|
export * from "./agent";
|
|
40
40
|
export * from "./agency";
|
|
41
41
|
export * from "./agency-campaigns";
|
|
42
|
+
export * from "./agency-pots";
|
|
42
43
|
export * from "./agency-threads";
|
|
44
|
+
export * from "./dealroom";
|
|
43
45
|
export * from "./I_AccessDenial";
|
package/dist/types/index.js
CHANGED
|
@@ -58,6 +58,9 @@ __exportStar(require("./agent"), exports);
|
|
|
58
58
|
// ── Agency domain (organizations, memberships, creator access grants, spec 175)
|
|
59
59
|
__exportStar(require("./agency"), exports);
|
|
60
60
|
__exportStar(require("./agency-campaigns"), exports);
|
|
61
|
+
__exportStar(require("./agency-pots"), exports);
|
|
61
62
|
__exportStar(require("./agency-threads"), exports);
|
|
63
|
+
// ── Dealroom (spec 148): what 175 has no concept of ──────────────────────────
|
|
64
|
+
__exportStar(require("./dealroom"), exports);
|
|
62
65
|
// ── Access control ────────────────────────────────────────────────────────────
|
|
63
66
|
__exportStar(require("./I_AccessDenial"), exports);
|
package/package.json
CHANGED
|
@@ -236,11 +236,33 @@ const EVENT_PROPERTY_WITNESS: { [E in keyof EventProperties]: EventProperties[E]
|
|
|
236
236
|
[EVENTS.AGENCY_CAMPAIGN_MILESTONE_CONFIRMED]: { organization_id: "org-1", actor_role: "owner", campaign_id: "c-1" },
|
|
237
237
|
[EVENTS.AGENCY_THREAD_STARTED]: { organization_id: "org-1", actor_role: "member", thread_id: "t-1" },
|
|
238
238
|
[EVENTS.AGENCY_THREAD_MESSAGE_SENT]: { organization_id: "org-1", actor_role: "creator", thread_id: "t-1" },
|
|
239
|
+
[EVENTS.AGENCY_POT_APPLIED]: { organization_id: "org-1", actor_role: "creator", campaign_id: "c-1" },
|
|
240
|
+
[EVENTS.AGENCY_POT_APPLICATION_DECIDED]: { organization_id: "org-1", actor_role: "member", campaign_id: "c-1", action: "accept" },
|
|
241
|
+
[EVENTS.AGENCY_POT_REFILLED]: { organization_id: "org-1", actor_role: "member", campaign_id: "c-1" },
|
|
242
|
+
[EVENTS.AGENCY_POT_MOVED]: { organization_id: "org-1", actor_role: "member", campaign_id: "c-1" },
|
|
243
|
+
[EVENTS.AGENCY_POT_PUBLISH_TIME_CONFIRMED]: { organization_id: "org-1", actor_role: "creator", campaign_id: "c-1" },
|
|
244
|
+
[EVENTS.AGENCY_POT_PUBLISHED]: { organization_id: "org-1", actor_role: "creator", campaign_id: "c-1" },
|
|
245
|
+
[EVENTS.AGENCY_POT_BONUS_HELD]: { organization_id: "org-1", actor_role: "member", campaign_id: "c-1", reason: "jump" },
|
|
246
|
+
[EVENTS.AGENCY_POT_BONUS_DECIDED]: { organization_id: "org-1", actor_role: "owner", campaign_id: "c-1", action: "cap" },
|
|
247
|
+
[EVENTS.AGENCY_POT_REMOVAL_DECIDED]: { organization_id: "org-1", actor_role: "owner", campaign_id: "c-1", decision: "withhold_base" },
|
|
248
|
+
[EVENTS.AGENCY_POT_EXPORTED]: { organization_id: "org-1", actor_role: "member", campaign_id: "c-1", format: "xlsx" },
|
|
249
|
+
[EVENTS.AGENCY_POT_FILE_UPLOADED]: { organization_id: "org-1", actor_role: "member", campaign_id: "c-1" },
|
|
250
|
+
// Dealroom (148)
|
|
251
|
+
[EVENTS.DEALROOM_FEED_VIEWED]: { state: "ok", listing_count: 3, broadened: true, near_match_count: 1 },
|
|
252
|
+
[EVENTS.DEALROOM_LISTING_OPENED]: { campaign_id: "c-1", organization_id: "org-1", kind: "offer" },
|
|
253
|
+
[EVENTS.DEALROOM_APPLIED]: { campaign_id: "c-1", organization_id: "org-1", kind: "pot", acting_grant_id: "g-1" },
|
|
254
|
+
[EVENTS.DEALROOM_BROADEN_TOGGLED]: { broadened: false },
|
|
255
|
+
[EVENTS.DEALROOM_NEAR_MATCH_SHOWN]: { campaign_id: "c-1", organization_id: "org-1", kind: "offer", gap: "followers" },
|
|
256
|
+
[EVENTS.DEALROOM_NEAR_MATCH_PROMOTED]: { campaign_id: "c-1", organization_id: "org-1", kind: "offer" },
|
|
257
|
+
[EVENTS.DEALROOM_CONNECT_FROM_NEAR_MATCH_CLICKED]: { campaign_id: "c-1", organization_id: "org-1", kind: "offer", platform: "tiktok" },
|
|
258
|
+
[EVENTS.DEALROOM_DELEGATION_CHANGED]: { organization_id: "org-1", actor_role: "creator", grant_id: "g-1", action: "granted" },
|
|
259
|
+
[EVENTS.DEALROOM_DEAL_MONEY_STATE_CHANGED]: { campaign_id: "c-1", organization_id: "org-1", kind: "offer", money_state: "deposit_paid" },
|
|
260
|
+
[EVENTS.DEALROOM_DEAL_PAYOUT_STATE_CHANGED]: { campaign_id: "c-1", organization_id: "org-1", kind: "offer", payout_state: "initiated" },
|
|
239
261
|
};
|
|
240
262
|
|
|
241
263
|
test("no agency event may carry the discover query — only whether it matched (FR-015)", () => {
|
|
242
264
|
const agencyEvents = Object.values(EVENTS).filter((name) => name.startsWith("agency_"));
|
|
243
|
-
assert.equal(agencyEvents.length,
|
|
265
|
+
assert.equal(agencyEvents.length, 40, "the 175 set is 15 roster events, 12 campaign-loop events (US7), 2 thread events (US8) and 11 pot events (US9)");
|
|
244
266
|
for (const name of agencyEvents) {
|
|
245
267
|
const props = EVENT_PROPERTY_WITNESS[name as keyof typeof EVENT_PROPERTY_WITNESS];
|
|
246
268
|
for (const key of Object.keys(props)) {
|
package/src/analytics/index.ts
CHANGED
|
@@ -10,7 +10,9 @@
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import type { AccessDenialCode } from "../types/I_AccessDenial";
|
|
13
|
-
import type { SponsoredTier } from "../types/agency";
|
|
13
|
+
import type { CreatorAccessGrantOrigin, SponsoredTier } from "../types/agency";
|
|
14
|
+
import type { AgencyCampaignKind, CampaignPlatform } from "../types/agency-campaigns";
|
|
15
|
+
import type { DealMoneyState, DealPayoutState } from "../types/dealroom";
|
|
14
16
|
|
|
15
17
|
/** Canonical PostHog event names. */
|
|
16
18
|
export const EVENTS = {
|
|
@@ -208,6 +210,32 @@ export const EVENTS = {
|
|
|
208
210
|
// Threads (175 US8). Never the message body: a conversation is not analytics.
|
|
209
211
|
AGENCY_THREAD_STARTED: 'agency_thread_started',
|
|
210
212
|
AGENCY_THREAD_MESSAGE_SENT: 'agency_thread_message_sent',
|
|
213
|
+
// Pot campaigns (175 US9). Never an amount: the pot's economics are the agency's.
|
|
214
|
+
AGENCY_POT_APPLIED: 'agency_pot_applied',
|
|
215
|
+
AGENCY_POT_APPLICATION_DECIDED: 'agency_pot_application_decided',
|
|
216
|
+
AGENCY_POT_REFILLED: 'agency_pot_refilled',
|
|
217
|
+
AGENCY_POT_MOVED: 'agency_pot_moved',
|
|
218
|
+
AGENCY_POT_PUBLISH_TIME_CONFIRMED: 'agency_pot_publish_time_confirmed',
|
|
219
|
+
AGENCY_POT_PUBLISHED: 'agency_pot_published',
|
|
220
|
+
AGENCY_POT_BONUS_HELD: 'agency_pot_bonus_held',
|
|
221
|
+
AGENCY_POT_BONUS_DECIDED: 'agency_pot_bonus_decided',
|
|
222
|
+
AGENCY_POT_REMOVAL_DECIDED: 'agency_pot_removal_decided',
|
|
223
|
+
AGENCY_POT_EXPORTED: 'agency_pot_exported',
|
|
224
|
+
AGENCY_POT_FILE_UPLOADED: 'agency_pot_file_uploaded',
|
|
225
|
+
// Dealroom (148): only what 175 has no event for. Offer, material and thread
|
|
226
|
+
// acts on a Dealroom deal reuse the AGENCY_CAMPAIGN_* / AGENCY_THREAD_* events.
|
|
227
|
+
DEALROOM_FEED_VIEWED: 'dealroom_feed_viewed',
|
|
228
|
+
DEALROOM_LISTING_OPENED: 'dealroom_listing_opened',
|
|
229
|
+
DEALROOM_APPLIED: 'dealroom_applied',
|
|
230
|
+
DEALROOM_BROADEN_TOGGLED: 'dealroom_broaden_toggled',
|
|
231
|
+
DEALROOM_NEAR_MATCH_SHOWN: 'dealroom_near_match_shown',
|
|
232
|
+
DEALROOM_NEAR_MATCH_PROMOTED: 'dealroom_near_match_promoted',
|
|
233
|
+
// The near-match's missing-platform nudge, clicked through to Connect (US11).
|
|
234
|
+
DEALROOM_CONNECT_FROM_NEAR_MATCH_CLICKED: 'dealroom_connect_from_near_match_clicked',
|
|
235
|
+
DEALROOM_DELEGATION_CHANGED: 'dealroom_delegation_changed',
|
|
236
|
+
// Money release (dormant until then): state moves, never an amount.
|
|
237
|
+
DEALROOM_DEAL_MONEY_STATE_CHANGED: 'dealroom_deal_money_state_changed',
|
|
238
|
+
DEALROOM_DEAL_PAYOUT_STATE_CHANGED: 'dealroom_deal_payout_state_changed',
|
|
211
239
|
} as const;
|
|
212
240
|
|
|
213
241
|
export type EventName = (typeof EVENTS)[keyof typeof EVENTS];
|
|
@@ -433,7 +461,7 @@ export interface AgencyEventProperties {
|
|
|
433
461
|
/** Present once a specific consent is the subject of the act. */
|
|
434
462
|
grant_id?: string;
|
|
435
463
|
actor_role: 'owner' | 'member' | 'creator' | 'admin' | 'system';
|
|
436
|
-
origin?:
|
|
464
|
+
origin?: CreatorAccessGrantOrigin;
|
|
437
465
|
terms_version?: string;
|
|
438
466
|
tier?: SponsoredTier;
|
|
439
467
|
/**
|
|
@@ -449,6 +477,17 @@ export interface AgencyCampaignEventProperties extends AgencyEventProperties {
|
|
|
449
477
|
campaign_id: string;
|
|
450
478
|
}
|
|
451
479
|
|
|
480
|
+
/**
|
|
481
|
+
* A Dealroom listing event (148): which listing, of which organization and
|
|
482
|
+
* kind. Never a price and never a follower count: what a creator saw and
|
|
483
|
+
* applied to, not what they earn.
|
|
484
|
+
*/
|
|
485
|
+
export interface DealroomListingEventProperties {
|
|
486
|
+
campaign_id: string;
|
|
487
|
+
organization_id: string;
|
|
488
|
+
kind: AgencyCampaignKind;
|
|
489
|
+
}
|
|
490
|
+
|
|
452
491
|
export interface EventProperties {
|
|
453
492
|
[EVENTS.LANDING_CTA_CLICKED]: {
|
|
454
493
|
location:
|
|
@@ -714,6 +753,34 @@ export interface EventProperties {
|
|
|
714
753
|
// Threads (175 US8): which thread, never its content.
|
|
715
754
|
[EVENTS.AGENCY_THREAD_STARTED]: AgencyEventProperties & { thread_id: string };
|
|
716
755
|
[EVENTS.AGENCY_THREAD_MESSAGE_SENT]: AgencyEventProperties & { thread_id: string };
|
|
756
|
+
[EVENTS.AGENCY_POT_APPLIED]: AgencyCampaignEventProperties;
|
|
757
|
+
[EVENTS.AGENCY_POT_APPLICATION_DECIDED]: AgencyCampaignEventProperties & { action: 'accept' | 'decline' };
|
|
758
|
+
[EVENTS.AGENCY_POT_REFILLED]: AgencyCampaignEventProperties;
|
|
759
|
+
[EVENTS.AGENCY_POT_MOVED]: AgencyCampaignEventProperties;
|
|
760
|
+
[EVENTS.AGENCY_POT_PUBLISH_TIME_CONFIRMED]: AgencyCampaignEventProperties;
|
|
761
|
+
[EVENTS.AGENCY_POT_PUBLISHED]: AgencyCampaignEventProperties;
|
|
762
|
+
[EVENTS.AGENCY_POT_BONUS_HELD]: AgencyCampaignEventProperties & { reason: 'jump' | 'paid_delivery' };
|
|
763
|
+
[EVENTS.AGENCY_POT_BONUS_DECIDED]: AgencyCampaignEventProperties & { action: 'approve' | 'cap' | 'message' };
|
|
764
|
+
[EVENTS.AGENCY_POT_REMOVAL_DECIDED]: AgencyCampaignEventProperties & { decision: 'keep_base' | 'withhold_base' };
|
|
765
|
+
[EVENTS.AGENCY_POT_EXPORTED]: AgencyCampaignEventProperties & { format: 'csv' | 'xlsx' | 'report' };
|
|
766
|
+
[EVENTS.AGENCY_POT_FILE_UPLOADED]: AgencyCampaignEventProperties;
|
|
767
|
+
// Dealroom (148).
|
|
768
|
+
[EVENTS.DEALROOM_FEED_VIEWED]: {
|
|
769
|
+
state: 'ok' | 'profile_incomplete';
|
|
770
|
+
listing_count: number;
|
|
771
|
+
broadened: boolean;
|
|
772
|
+
near_match_count?: number;
|
|
773
|
+
};
|
|
774
|
+
[EVENTS.DEALROOM_LISTING_OPENED]: DealroomListingEventProperties;
|
|
775
|
+
// `acting_grant_id` when a delegate applied for the creator.
|
|
776
|
+
[EVENTS.DEALROOM_APPLIED]: DealroomListingEventProperties & { acting_grant_id?: string };
|
|
777
|
+
[EVENTS.DEALROOM_BROADEN_TOGGLED]: { broadened: boolean };
|
|
778
|
+
[EVENTS.DEALROOM_NEAR_MATCH_SHOWN]: DealroomListingEventProperties & { gap: 'followers' | 'missing_platform' };
|
|
779
|
+
[EVENTS.DEALROOM_NEAR_MATCH_PROMOTED]: DealroomListingEventProperties;
|
|
780
|
+
[EVENTS.DEALROOM_CONNECT_FROM_NEAR_MATCH_CLICKED]: DealroomListingEventProperties & { platform: CampaignPlatform };
|
|
781
|
+
[EVENTS.DEALROOM_DELEGATION_CHANGED]: AgencyEventProperties & { action: 'granted' | 'revoked' };
|
|
782
|
+
[EVENTS.DEALROOM_DEAL_MONEY_STATE_CHANGED]: DealroomListingEventProperties & { money_state: DealMoneyState };
|
|
783
|
+
[EVENTS.DEALROOM_DEAL_PAYOUT_STATE_CHANGED]: DealroomListingEventProperties & { payout_state: DealPayoutState };
|
|
717
784
|
}
|
|
718
785
|
|
|
719
786
|
/** Canonical person property keys (set via identify / $set). */
|
|
@@ -64,6 +64,13 @@ export const ACCESS_DENIAL_CODES = {
|
|
|
64
64
|
AGENCY_SCOPE_NOT_GRANTED: "agency-scope-not-granted",
|
|
65
65
|
/** The consent screen is off in this environment (FR-020, the legal gate). */
|
|
66
66
|
AGENCY_CONSENT_DISABLED: "agency-consent-disabled",
|
|
67
|
+
/**
|
|
68
|
+
* The consent screen is on but this environment names no terms version, so
|
|
69
|
+
* no grant can be minted (FR-020). A deployment fault, said as a refusal
|
|
70
|
+
* rather than a 500 (spec 148 audit #1); the env gate requires the version
|
|
71
|
+
* wherever consent is switched on.
|
|
72
|
+
*/
|
|
73
|
+
AGENCY_TERMS_VERSION_MISSING: "agency-terms-version-missing",
|
|
67
74
|
/** The roster invite link expired, was rotated, or its organization is not approved. */
|
|
68
75
|
AGENCY_LINK_INVALID: "agency-link-invalid",
|
|
69
76
|
/** An admin may not decide on an organization they belong to (FR-017). */
|
|
@@ -87,7 +87,8 @@ test('every AGENCY code is namespaced, so a new domain cannot shadow an old wall
|
|
|
87
87
|
key.startsWith('AGENCY_'),
|
|
88
88
|
);
|
|
89
89
|
|
|
90
|
-
|
|
90
|
+
// Spec 148 audit #1 added agency-terms-version-missing.
|
|
91
|
+
assert.equal(agencyCodes.length, 15);
|
|
91
92
|
for (const [, value] of agencyCodes) {
|
|
92
93
|
assert.match(value, /^agency-/, `un-namespaced agency code: ${value}`);
|
|
93
94
|
}
|