@venturewild/workspace 0.5.2 → 0.5.3
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/package.json
CHANGED
|
@@ -322,12 +322,50 @@ export function createBazaar({ baseDir, seedDir = SEED_DIR, rails = null } = {})
|
|
|
322
322
|
// The cross-user theme pool from the local rails cache, RE-VALIDATED on read —
|
|
323
323
|
// never trust the pool blindly (spike 2: 15/15 hostile bundles neutralized by
|
|
324
324
|
// normalizeTheme). A tampered cache file degrades to a clean bundle, not exec.
|
|
325
|
+
//
|
|
326
|
+
// Trust/ranking/payout fields are NEVER trusted from the pool (audit 2026-06-15):
|
|
327
|
+
// a producer could otherwise publish a theme that renders "Verified" with a
|
|
328
|
+
// perfect outcome score, 5 stars, and an inflated payout. We rebuild a clean card
|
|
329
|
+
// input keeping only display fields + the re-validated bundle, and RESET the
|
|
330
|
+
// trust signals so OUR provenanceFor derives the honest Class-A 'auto' verdict and
|
|
331
|
+
// a neutral outcome (local build-results then accrue). Display text is clamped.
|
|
332
|
+
function str(v, max) {
|
|
333
|
+
return typeof v === 'string' ? v.slice(0, max) : '';
|
|
334
|
+
}
|
|
325
335
|
function readRailsThemes() {
|
|
326
336
|
const raw = readJsonSafe(railsThemesFile, []);
|
|
327
337
|
if (!Array.isArray(raw)) return [];
|
|
328
338
|
return raw
|
|
329
339
|
.filter((r) => r && typeof r === 'object' && r.id && r.kind === 'theme')
|
|
330
|
-
.map((r) =>
|
|
340
|
+
.map((r) => {
|
|
341
|
+
const p = r.producer && typeof r.producer === 'object' ? r.producer : {};
|
|
342
|
+
return {
|
|
343
|
+
id: String(r.id).slice(0, 120),
|
|
344
|
+
kind: 'theme',
|
|
345
|
+
source: 'rails',
|
|
346
|
+
title: str(r.title, 80) || 'Untitled',
|
|
347
|
+
pitch: str(r.pitch, 200),
|
|
348
|
+
summary: str(r.summary, 400),
|
|
349
|
+
tags: Array.isArray(r.tags) ? r.tags.slice(0, 8).map((t) => String(t).slice(0, 24)) : [],
|
|
350
|
+
producer: {
|
|
351
|
+
name: str(p.name, 60) || 'A maker',
|
|
352
|
+
handle: str(p.handle, 40) || 'maker',
|
|
353
|
+
kind: 'maker',
|
|
354
|
+
},
|
|
355
|
+
theme: normalizeTheme(r.theme || {}),
|
|
356
|
+
// Remix lineage is safe to surface (it's just a pointer + label).
|
|
357
|
+
...(r.builtFrom && r.builtFrom.id
|
|
358
|
+
? { builtFrom: { id: String(r.builtFrom.id).slice(0, 120), title: str(r.builtFrom.title, 80) } }
|
|
359
|
+
: {}),
|
|
360
|
+
// RESET publisher-controlled trust/ranking/payout → our derivation governs.
|
|
361
|
+
outcomeScore: 0.7, // the new-listing prior (proven locally over time)
|
|
362
|
+
outcomeStats: { builds: 0, working: 0 },
|
|
363
|
+
rating: { stars: 0, count: 0 }, // no fake stars
|
|
364
|
+
reward: { model: 'one-time', unit: 'per apply', oneTimeValue: 1.5, perUseValue: 0 },
|
|
365
|
+
// No vetting/safetyBadge → provenanceFor derives Class-A 'auto'.
|
|
366
|
+
createdAt: typeof r.createdAt === 'number' ? r.createdAt : 0,
|
|
367
|
+
};
|
|
368
|
+
});
|
|
331
369
|
}
|
|
332
370
|
|
|
333
371
|
// Overwrite the local cache of the global theme pool (called by the main
|