@mohasinac/appkit 4.36.0 → 4.37.1
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/_internal/server/features/site-settings/adapters.d.ts +2 -2
- package/dist/_internal/server/features/site-settings/adapters.js +25 -1
- package/dist/_internal/shared/features/site-settings/types.d.ts +12 -0
- package/dist/features/tester/seed-data/_money-flows.js +13 -5
- package/dist/features/tester/seed-data/index.d.ts +1 -0
- package/dist/features/tester/seed-data/index.js +1 -0
- package/dist/features/tester/seed-data/tester-responses-seed-data.d.ts +2 -0
- package/dist/features/tester/seed-data/tester-responses-seed-data.js +95 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -0
- package/dist/seed/index.d.ts +1 -1
- package/dist/seed/index.js +6 -1
- package/package.json +1 -1
- package/scripts/seed-cli.mjs +14 -1
|
@@ -37,9 +37,9 @@ import type { PublicSiteSettings } from "../../../shared/features/site-settings/
|
|
|
37
37
|
* was traced to a call site; anything without one belongs in the private list,
|
|
38
38
|
* because an unused public field is pure attack surface.
|
|
39
39
|
*/
|
|
40
|
-
export declare const PUBLIC_SITE_SETTINGS_FIELDS: readonly ["contact", "payment", "listings", "notificationChannels", "announcementBar", "navConfig", "actionConfig", "background", "watermark"];
|
|
40
|
+
export declare const PUBLIC_SITE_SETTINGS_FIELDS: readonly ["contact", "payment", "listings", "notificationChannels", "announcementBar", "navConfig", "actionConfig", "background", "watermark", "disabledRoutes"];
|
|
41
41
|
/** Everything else, with the reason it stays server-side. */
|
|
42
|
-
export declare const PRIVATE_SITE_SETTINGS_FIELDS: readonly ["id", "createdAt", "updatedAt", "credentials", "emailSettings", "legalPages", "commissions", "emi", "gst", "laborRate", "adSettings", "integrations", "platformLimits", "auctionConfig", "
|
|
42
|
+
export declare const PRIVATE_SITE_SETTINGS_FIELDS: readonly ["id", "createdAt", "updatedAt", "credentials", "emailSettings", "legalPages", "commissions", "emi", "gst", "laborRate", "adSettings", "integrations", "platformLimits", "auctionConfig", "siteName", "tagline", "motto", "logo", "favicon", "seo", "socialLinks", "features", "shipping", "returns", "faq", "aboutContent", "navbarConfig", "footerConfig", "theme", "featuredResults", "messaging"];
|
|
43
43
|
export interface ToPublicSiteSettingsOptions {
|
|
44
44
|
/**
|
|
45
45
|
* The resolved marker → wordmark → text watermark chain. Injected because
|
|
@@ -13,6 +13,26 @@ export const PUBLIC_SITE_SETTINGS_FIELDS = [
|
|
|
13
13
|
"actionConfig", // useAuthGate
|
|
14
14
|
"background", // DashboardLayoutClient (background.light / .dark)
|
|
15
15
|
"watermark", // MediaVideo, as the fallback behind effectiveWatermark
|
|
16
|
+
/*
|
|
17
|
+
* src/proxy.ts — the admin "disable a nav item and that route 404s" gate.
|
|
18
|
+
*
|
|
19
|
+
* 🛑 It was PRIVATE until 2026-09-13, justified by "read by
|
|
20
|
+
* app/[locale]/layout.tsx (RSC)". That was true once and stopped being true in
|
|
21
|
+
* Root Cause #82, which moved the gate OUT of the root layout (a dynamic API
|
|
22
|
+
* there made every page on the site uncacheable) and into the proxy. The
|
|
23
|
+
* proxy cannot do a Firestore read on the Edge, so it fetches
|
|
24
|
+
* /api/site-settings over HTTP — where a private field simply does not exist.
|
|
25
|
+
*
|
|
26
|
+
* The gate has therefore been a silent no-op ever since: getDisabledRoutes()
|
|
27
|
+
* reads `body.data.disabledRoutes`, gets undefined, and returns []. It fails
|
|
28
|
+
* OPEN, so nothing 404s that should not; the admin capability just does
|
|
29
|
+
* nothing. The stale comment on the private entry was the only trace.
|
|
30
|
+
*
|
|
31
|
+
* Publishing it is the right call rather than reverting the move: it is a
|
|
32
|
+
* list of route paths an admin has switched off, not a secret, and the
|
|
33
|
+
* alternative is putting a per-request Firestore read back on the Edge.
|
|
34
|
+
*/
|
|
35
|
+
"disabledRoutes",
|
|
16
36
|
];
|
|
17
37
|
/** Everything else, with the reason it stays server-side. */
|
|
18
38
|
export const PRIVATE_SITE_SETTINGS_FIELDS = [
|
|
@@ -30,7 +50,6 @@ export const PRIVATE_SITE_SETTINGS_FIELDS = [
|
|
|
30
50
|
"integrations", // analytics/tag IDs are injected server-side into markup, not fetched by the client
|
|
31
51
|
"platformLimits", // server-enforced caps; no client reader
|
|
32
52
|
"auctionConfig", // read by AuctionDetailPageView, a Server Component doing its own settings read
|
|
33
|
-
"disabledRoutes", // read by app/[locale]/layout.tsx (RSC) to gate routing
|
|
34
53
|
"siteName", // delivered as an SSR prop / rendered server-side
|
|
35
54
|
"tagline", // admin chrome only
|
|
36
55
|
"motto", // rendered server-side
|
|
@@ -81,6 +100,11 @@ export function toPublicSiteSettings(doc, opts) {
|
|
|
81
100
|
actionConfig: doc.actionConfig,
|
|
82
101
|
background: doc.background,
|
|
83
102
|
watermark: doc.watermark,
|
|
103
|
+
// Defaulted to [] rather than passed through: src/proxy.ts fails OPEN on a
|
|
104
|
+
// missing value, so an absent field and an empty list already behave the
|
|
105
|
+
// same — but emitting `undefined` would drop the key from the JSON entirely
|
|
106
|
+
// and leave the next person wondering whether the projection ran at all.
|
|
107
|
+
disabledRoutes: doc.disabledRoutes ?? [],
|
|
84
108
|
effectiveWatermark: opts?.effectiveWatermark,
|
|
85
109
|
};
|
|
86
110
|
}
|
|
@@ -44,6 +44,18 @@ export interface PublicSiteSettings {
|
|
|
44
44
|
actionConfig?: SiteSettingsDocument["actionConfig"];
|
|
45
45
|
background?: SiteSettingsDocument["background"];
|
|
46
46
|
watermark?: SiteSettingsDocument["watermark"];
|
|
47
|
+
/**
|
|
48
|
+
* Routes an admin has switched off. Read by `src/proxy.ts`, which rewrites a
|
|
49
|
+
* disabled path to the 404 page.
|
|
50
|
+
*
|
|
51
|
+
* 🛑 Not optional, and always emitted (defaulted to `[]`). The proxy fetches
|
|
52
|
+
* this over HTTP and fails OPEN on a missing value, so the difference between
|
|
53
|
+
* "no routes disabled" and "the field never arrived" is invisible at runtime —
|
|
54
|
+
* which is exactly how this capability sat dead after Root Cause #82 moved the
|
|
55
|
+
* gate out of the root layout. A key that is always present makes the two
|
|
56
|
+
* distinguishable from the wire alone.
|
|
57
|
+
*/
|
|
58
|
+
disabledRoutes: string[];
|
|
47
59
|
/** Derived, not a stored field — the resolved marker → wordmark → text chain. */
|
|
48
60
|
effectiveWatermark?: MediaVideoWatermark;
|
|
49
61
|
}
|
|
@@ -155,16 +155,24 @@ export const moneyFlowsPages = [
|
|
|
155
155
|
{
|
|
156
156
|
pageKey: "auction-win-to-payment",
|
|
157
157
|
pageLabel: "Win an auction → get notified → pay",
|
|
158
|
-
href: "/auctions/auction-
|
|
158
|
+
href: "/auctions/auction-money-flows-closing",
|
|
159
159
|
cases: [
|
|
160
160
|
{
|
|
161
161
|
key: "winning-bid-recorded",
|
|
162
162
|
label: "Placing the highest bid on a closing auction records you as the winner",
|
|
163
163
|
roles: ["buyer"],
|
|
164
|
-
|
|
164
|
+
// Batch-scoped fixture, seeded by
|
|
165
|
+
// seed-data/fixtures/money-flows__auction-win-to-payment.mjs and closing
|
|
166
|
+
// ~3 minutes after this batch starts.
|
|
167
|
+
//
|
|
168
|
+
// It used to cite auction-tester-sandbox-cycle-1, which 46 OTHER
|
|
169
|
+
// citations need LIVE — one fixture with two contradictory
|
|
170
|
+
// requirements, so this case could never pass its final step and the
|
|
171
|
+
// rig notes recorded it as unpassable-by-design.
|
|
172
|
+
startPage: "/auctions/auction-money-flows-closing",
|
|
165
173
|
steps: [
|
|
166
174
|
STEP_SIGNIN_BUYER,
|
|
167
|
-
"Open /auctions/auction-
|
|
175
|
+
"Open /auctions/auction-money-flows-closing, which starts at ₹15,000 with a ₹1,000 increment and closes about three minutes from now.",
|
|
168
176
|
"Note the current bid and the end time.",
|
|
169
177
|
"Enter 16000 as the bid amount.",
|
|
170
178
|
"Click 'Place Bid'.",
|
|
@@ -180,7 +188,7 @@ export const moneyFlowsPages = [
|
|
|
180
188
|
roles: ["buyer"],
|
|
181
189
|
startPage: "/user/notifications",
|
|
182
190
|
steps: [
|
|
183
|
-
"Sign in as the buyer who won auction-
|
|
191
|
+
"Sign in as the buyer who won auction-money-flows-closing.",
|
|
184
192
|
"Open the notifications bell in the header.",
|
|
185
193
|
"Find the auction-won notification.",
|
|
186
194
|
"Read its text.",
|
|
@@ -197,7 +205,7 @@ export const moneyFlowsPages = [
|
|
|
197
205
|
roles: ["buyer"],
|
|
198
206
|
startPage: "/user/orders",
|
|
199
207
|
steps: [
|
|
200
|
-
"Sign in as the buyer who won auction-
|
|
208
|
+
"Sign in as the buyer who won auction-money-flows-closing.",
|
|
201
209
|
"Open /user/orders.",
|
|
202
210
|
"Locate the won auction.",
|
|
203
211
|
"Click its payment call to action.",
|
|
@@ -9,3 +9,4 @@ export { bidsTesterSeedData } from "./bids-tester-seed-data";
|
|
|
9
9
|
export { cartsTesterSeedData } from "./carts-tester-seed-data";
|
|
10
10
|
export { ordersTesterSeedData } from "./orders-tester-seed-data";
|
|
11
11
|
export { offersTesterSeedData } from "./offers-tester-seed-data";
|
|
12
|
+
export { testerResponsesSeedData } from "./tester-responses-seed-data";
|
|
@@ -9,3 +9,4 @@ export { bidsTesterSeedData } from "./bids-tester-seed-data";
|
|
|
9
9
|
export { cartsTesterSeedData } from "./carts-tester-seed-data";
|
|
10
10
|
export { ordersTesterSeedData } from "./orders-tester-seed-data";
|
|
11
11
|
export { offersTesterSeedData } from "./offers-tester-seed-data";
|
|
12
|
+
export { testerResponsesSeedData } from "./tester-responses-seed-data";
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* WHY: Three `admin/bug-hunter-rewards` cases need a tester submission that
|
|
3
|
+
* ALREADY EXISTS before the tester arrives — you cannot test "confirm this
|
|
4
|
+
* reported bug" or "reopen this confirmed case" against an empty inbox.
|
|
5
|
+
*
|
|
6
|
+
* `testerChecklistResponses` is DERIVED tier, so a run wipes it at setup
|
|
7
|
+
* and on a fresh project there are genuinely zero submissions. That is
|
|
8
|
+
* correct — stale verdicts from a previous run must not leak into the next
|
|
9
|
+
* one — but it left those three cases permanently unrunnable. Measured
|
|
10
|
+
* 2026-09-11: 0 pass / 0 fail / 5 blocked on that page, with both
|
|
11
|
+
* calibration controls answered correctly, so the batch was trustworthy and
|
|
12
|
+
* the emptiness was real.
|
|
13
|
+
*
|
|
14
|
+
* The fix is NOT to stop wiping the collection. It is to restore these
|
|
15
|
+
* fixtures after the wipe — `SEED_TRANSACTIONAL` in
|
|
16
|
+
* tester/scripts/lib/collections.mjs is a RESTORE list, orthogonal to the
|
|
17
|
+
* delete tiers, so a collection can be both wiped and re-seeded.
|
|
18
|
+
*
|
|
19
|
+
* WHAT: Two response documents against the two demo-fixture checklist items that
|
|
20
|
+
* already live in the catalogue.
|
|
21
|
+
*
|
|
22
|
+
* 🛑 THE DOC ID IS DETERMINISTIC: `${testerId}__${checklistItemId}`.
|
|
23
|
+
* That is the same id the live answer path computes, and it is what makes an
|
|
24
|
+
* answer an UPSERT rather than a duplicate — `set({merge:true})`, never
|
|
25
|
+
* `add()`. Generating a random id here would (a) create a second, competing
|
|
26
|
+
* response for the same (tester, case) pair the moment a real tester answers,
|
|
27
|
+
* and (b) break idempotency, so every `appkit-seed load` would pile up
|
|
28
|
+
* another copy — Root Cause #25 exactly.
|
|
29
|
+
*
|
|
30
|
+
* @tag domain:tester
|
|
31
|
+
* @tag layer:seed
|
|
32
|
+
* @tag access:server-only
|
|
33
|
+
* @tag consumers:appkit/scripts/seed-cli.mjs, seed/manifest.ts
|
|
34
|
+
* @tag sideEffects:none
|
|
35
|
+
*/
|
|
36
|
+
/** The seeded QA persona that the demo fixtures credit as "Mock User 18". */
|
|
37
|
+
const TESTER_ID = "user-tester-qa";
|
|
38
|
+
const TESTER_NAME = "Mock User 18";
|
|
39
|
+
/** Same shape the answer route computes — see the callout above. */
|
|
40
|
+
const responseId = (testerId, checklistItemId) => `${testerId}__${checklistItemId}`;
|
|
41
|
+
const DEMO_V1 = "checklist-admin-bug-hunter-rewards-demo-fixture";
|
|
42
|
+
const DEMO_V2 = "checklist-admin-bug-hunter-rewards-demo-fixture-v2";
|
|
43
|
+
const seededAt = new Date("2026-08-18T09:30:00.000Z");
|
|
44
|
+
export const testerResponsesSeedData = [
|
|
45
|
+
/*
|
|
46
|
+
* The ALREADY-CONFIRMED submission. The v1 catalogue item carries
|
|
47
|
+
* bugConfirmed:true / bugHunterId:"user-tester-qa" / bugHunterName:"Mock User
|
|
48
|
+
* 18", and until now there was no response row behind that credit — so
|
|
49
|
+
* /admin/tester-feedback showed "No feedback submitted yet" while the
|
|
50
|
+
* leaderboard showed a confirmed bug. This is the missing half.
|
|
51
|
+
*
|
|
52
|
+
* Backs: confirm-bug-idempotent (needs a row that is already confirmed) and
|
|
53
|
+
* reopen-case (needs the v1 credit to be visible from a real submission).
|
|
54
|
+
*
|
|
55
|
+
* `status: "reviewed"` because an admin has already acted on it.
|
|
56
|
+
*/
|
|
57
|
+
{
|
|
58
|
+
id: responseId(TESTER_ID, DEMO_V1),
|
|
59
|
+
testerId: TESTER_ID,
|
|
60
|
+
testerDisplayName: TESTER_NAME,
|
|
61
|
+
checklistItemId: DEMO_V1,
|
|
62
|
+
groupKey: "admin",
|
|
63
|
+
pageKey: "bug-hunter-rewards",
|
|
64
|
+
phase: 1,
|
|
65
|
+
answer: "no",
|
|
66
|
+
comment: "Seed fixture — the reported bug behind the v1 demo case. Already confirmed and credited, then reopened as v2. Exists so an admin can see what a confirmed submission looks like without waiting for a real tester to file one.",
|
|
67
|
+
status: "reviewed",
|
|
68
|
+
createdAt: seededAt,
|
|
69
|
+
updatedAt: seededAt,
|
|
70
|
+
},
|
|
71
|
+
/*
|
|
72
|
+
* The UNCONFIRMED submission, against the active v2 retest. This is the row
|
|
73
|
+
* "Mark as Bug" is meant to be tried on end-to-end.
|
|
74
|
+
*
|
|
75
|
+
* 🛑 status MUST stay "new" and the case MUST stay un-confirmed, or the
|
|
76
|
+
* confirm-bug case has nothing left to do — it would open an already-confirmed
|
|
77
|
+
* row and correctly report that it could not perform its own steps. A fixture
|
|
78
|
+
* that pre-completes the thing under test is worse than no fixture, because it
|
|
79
|
+
* looks like coverage.
|
|
80
|
+
*/
|
|
81
|
+
{
|
|
82
|
+
id: responseId(TESTER_ID, DEMO_V2),
|
|
83
|
+
testerId: TESTER_ID,
|
|
84
|
+
testerDisplayName: TESTER_NAME,
|
|
85
|
+
checklistItemId: DEMO_V2,
|
|
86
|
+
groupKey: "admin",
|
|
87
|
+
pageKey: "bug-hunter-rewards",
|
|
88
|
+
phase: 1,
|
|
89
|
+
answer: "no",
|
|
90
|
+
comment: "Seed fixture — a fresh 'No' on the reopened v2 case, deliberately NOT yet confirmed. This is the row to try Mark as Bug against.",
|
|
91
|
+
status: "new",
|
|
92
|
+
createdAt: seededAt,
|
|
93
|
+
updatedAt: seededAt,
|
|
94
|
+
},
|
|
95
|
+
];
|
package/dist/index.d.ts
CHANGED
|
@@ -594,6 +594,7 @@ export { eventEntriesSeedData } from "./seed/index";
|
|
|
594
594
|
export { eventsSeedData } from "./seed/index";
|
|
595
595
|
export { faqSeedData } from "./seed/index";
|
|
596
596
|
export { testerChecklistSeedData } from "./seed/index";
|
|
597
|
+
export { testerResponsesSeedData } from "./seed/index";
|
|
597
598
|
export { storesTesterSeedData } from "./seed/index";
|
|
598
599
|
export { categoriesTesterSeedData } from "./seed/index";
|
|
599
600
|
export { productsTesterSeedData } from "./seed/index";
|
package/dist/index.js
CHANGED
|
@@ -1189,6 +1189,8 @@ export { faqSeedData } from "./seed/index";
|
|
|
1189
1189
|
// [SERVER-ONLY]-Server-only — uses Node.js, Next.js server internals, or third-party server SDKs (auth, email, payment, shipping).
|
|
1190
1190
|
// testerChecklistSeedData - Model for tester checklist seed data.
|
|
1191
1191
|
export { testerChecklistSeedData } from "./seed/index";
|
|
1192
|
+
// testerResponsesSeedData - Seeded tester submissions behind the bug-hunter demo fixtures.
|
|
1193
|
+
export { testerResponsesSeedData } from "./seed/index";
|
|
1192
1194
|
// [SERVER-ONLY]-Server-only — uses Node.js, Next.js server internals, or third-party server SDKs (auth, email, payment, shipping).
|
|
1193
1195
|
// storesTesterSeedData - Model for the shared tester sandbox store seed data.
|
|
1194
1196
|
export { storesTesterSeedData } from "./seed/index";
|
package/dist/seed/index.d.ts
CHANGED
|
@@ -78,7 +78,7 @@ export { historySeedData } from "./history-seed-data";
|
|
|
78
78
|
export { groupedListingsSeedData } from "./grouped-listings-seed-data";
|
|
79
79
|
export { scammersSeedData } from "./scammers-seed-data";
|
|
80
80
|
export { supportTicketsSeedData } from "./support-tickets-seed-data";
|
|
81
|
-
export { testerChecklistSeedData, storesTesterSeedData, categoriesTesterSeedData, productsTesterSeedData, blogTesterSeedData, eventsTesterSeedData, couponsTesterSeedData, bidsTesterSeedData, cartsTesterSeedData, ordersTesterSeedData, } from "../features/tester/seed-data";
|
|
81
|
+
export { testerChecklistSeedData, testerResponsesSeedData, storesTesterSeedData, categoriesTesterSeedData, productsTesterSeedData, blogTesterSeedData, eventsTesterSeedData, couponsTesterSeedData, bidsTesterSeedData, cartsTesterSeedData, ordersTesterSeedData, } from "../features/tester/seed-data";
|
|
82
82
|
export { productFeaturesSeedData } from "./product-features-seed-data";
|
|
83
83
|
export { offersSeedData } from "./offers-seed-data";
|
|
84
84
|
export { payoutMethodsSeedData, shippingConfigsSeedData, analyticsCardsSeedData, analyticsAlertsSeedData, storeCategoriesSeedData, listingTemplatesSeedData, moderationQueueSeedData, reportsSeedData, itemRequestsSeedData, storeWhatsAppConfigSeedData, storeGoogleConfigSeedData, } from "./store-extensions-seed-data";
|
package/dist/seed/index.js
CHANGED
|
@@ -69,7 +69,12 @@ export { scammersSeedData } from "./scammers-seed-data";
|
|
|
69
69
|
export { supportTicketsSeedData } from "./support-tickets-seed-data";
|
|
70
70
|
// Tester sandbox seed fixtures live in ../features/tester/seed-data (isolated from this
|
|
71
71
|
// folder on purpose) — re-exported here so every other seed consumer keeps one import surface.
|
|
72
|
-
export { testerChecklistSeedData,
|
|
72
|
+
export { testerChecklistSeedData,
|
|
73
|
+
// 🛑 Adding a tester seed export means FOUR hops, not one: the tester barrel,
|
|
74
|
+
// THIS re-export, appkit/src/index.ts, and seed-cli's own import. Missing the
|
|
75
|
+
// middle two is silent — seed-cli logs "no seed data, skipping" and the run
|
|
76
|
+
// continues, which is exactly what happened on the first attempt here.
|
|
77
|
+
testerResponsesSeedData, storesTesterSeedData, categoriesTesterSeedData, productsTesterSeedData, blogTesterSeedData, eventsTesterSeedData, couponsTesterSeedData, bidsTesterSeedData, cartsTesterSeedData, ordersTesterSeedData, } from "../features/tester/seed-data";
|
|
73
78
|
export { productFeaturesSeedData } from "./product-features-seed-data";
|
|
74
79
|
export { offersSeedData } from "./offers-seed-data";
|
|
75
80
|
// S-STORE Extensions (Tier S-STORE) — 11 new collections
|
package/package.json
CHANGED
package/scripts/seed-cli.mjs
CHANGED
|
@@ -192,7 +192,7 @@ const {
|
|
|
192
192
|
wishlistsSeedData, historySeedData,
|
|
193
193
|
groupedListingsSeedData,
|
|
194
194
|
scammersSeedData, productFeaturesSeedData,
|
|
195
|
-
testerChecklistSeedData, cartsTesterSeedData, offersTesterSeedData,
|
|
195
|
+
testerChecklistSeedData, testerResponsesSeedData, cartsTesterSeedData, offersTesterSeedData,
|
|
196
196
|
supportTicketsSeedData, catalogueSeedData,
|
|
197
197
|
shipmentsSeedData, shipmentLotsSeedData, shipmentItemsSeedData,
|
|
198
198
|
storesTesterSeedData, categoriesTesterSeedData, productsTesterSeedData,
|
|
@@ -210,6 +210,7 @@ const {
|
|
|
210
210
|
GROUPED_LISTINGS_COLLECTION, SCAMMER_COLLECTION,
|
|
211
211
|
WISHLIST_COLLECTION, HISTORY_COLLECTION, PRODUCT_FEATURES_COLLECTION,
|
|
212
212
|
TESTER_CHECKLIST_ITEM_COLLECTION,
|
|
213
|
+
TESTER_CHECKLIST_RESPONSE_COLLECTION,
|
|
213
214
|
// PII field/index constants (plain data, still in the main barrel — the
|
|
214
215
|
// crypto functions themselves come from appkitServer above)
|
|
215
216
|
USER_PII_FIELDS, USER_PII_INDEX_MAP,
|
|
@@ -266,6 +267,17 @@ const COLLECTION_MAP = {
|
|
|
266
267
|
scammerProfiles: SCAMMER_COLLECTION,
|
|
267
268
|
productFeatures: PRODUCT_FEATURES_COLLECTION,
|
|
268
269
|
testerChecklistItems: TESTER_CHECKLIST_ITEM_COLLECTION,
|
|
270
|
+
/*
|
|
271
|
+
* Tester submissions. DERIVED tier in the tester's own map (wiped at setup so
|
|
272
|
+
* a prior run's verdicts never leak into the next), AND listed in
|
|
273
|
+
* SEED_TRANSACTIONAL so these two demo fixtures are restored afterwards —
|
|
274
|
+
* that list is a RESTORE list, orthogonal to the delete tiers.
|
|
275
|
+
*
|
|
276
|
+
* Without the fixtures, three admin/bug-hunter-rewards cases have nothing to
|
|
277
|
+
* confirm or reopen and can only report blocked. Measured 2026-09-11:
|
|
278
|
+
* 0 pass / 0 fail / 5 blocked, both controls correct.
|
|
279
|
+
*/
|
|
280
|
+
testerChecklistResponses: TESTER_CHECKLIST_RESPONSE_COLLECTION,
|
|
269
281
|
};
|
|
270
282
|
|
|
271
283
|
const SEED_DATA_MAP = {
|
|
@@ -325,6 +337,7 @@ const SEED_DATA_MAP = {
|
|
|
325
337
|
scammerProfiles: scammersSeedData,
|
|
326
338
|
productFeatures: productFeaturesSeedData,
|
|
327
339
|
testerChecklistItems: testerChecklistSeedData,
|
|
340
|
+
testerChecklistResponses: testerResponsesSeedData,
|
|
328
341
|
};
|
|
329
342
|
|
|
330
343
|
const ALL_COLLECTIONS = Object.keys(COLLECTION_MAP);
|