Spaces:
Running
Running
| /** | |
| * Pure visibility decision for the mobile JS-app catalog. | |
| * | |
| * Split out of `index.js` so the fail-closed policy - the load-bearing | |
| * App Store guideline 1.2 logic - is unit-testable without booting the | |
| * Express server (importing `index.js` calls `app.listen`). | |
| * | |
| * Fail-closed contract | |
| * ββββββββββββββββββββ | |
| * An app is visible in the mobile catalog ONLY when one of: | |
| * - it is a curated official app (moderation skipped), or | |
| * - it carries an explicit `allow` moderation verdict. | |
| * | |
| * Everything else is hidden: | |
| * - `isBlocked` (manual block-list killswitch) -> hidden, | |
| * - `block` verdict (clear violation) -> hidden, | |
| * - `review` verdict (LLM unsure) -> hidden, | |
| * - no verdict yet (cold / pending) -> hidden. | |
| * | |
| * The consequence is that a brand-new Space never appears before the | |
| * regex+LLM pipeline has explicitly cleared it, and a transient LLM | |
| * outage (or a missing HF_TOKEN) keeps unmoderated apps out of the | |
| * catalog rather than leaking them. | |
| */ | |
| /** | |
| * @typedef {Object} ModerationVerdict | |
| * @property {'allow'|'block'|'review'} decision | |
| * @property {string|null} [category] | |
| * @property {string} [reason] | |
| * @property {string} [source] | |
| */ | |
| /** | |
| * @typedef {Object} VisibilityResult | |
| * @property {boolean} visible | |
| * @property {string} source | |
| * @property {'allow'|'block'|'review'} decision | |
| * @property {string|null} category | |
| * @property {string} reason | |
| */ | |
| /** | |
| * Decide whether a JS app is visible, and why. | |
| * | |
| * @param {{isBlocked?: boolean, isOfficial?: boolean}} app | |
| * @param {ModerationVerdict|null|undefined} verdict cached moderation | |
| * verdict for `app`, or null/undefined when none exists yet. | |
| * @returns {VisibilityResult} | |
| */ | |
| export function decideVisibility(app, verdict) { | |
| if (app.isBlocked) { | |
| return { | |
| visible: false, | |
| source: 'blocklist', | |
| decision: 'block', | |
| category: null, | |
| reason: 'manual block-list', | |
| }; | |
| } | |
| if (app.isOfficial) { | |
| return { | |
| visible: true, | |
| source: 'official', | |
| decision: 'allow', | |
| category: 'none', | |
| reason: 'official app (moderation skipped)', | |
| }; | |
| } | |
| if (verdict) { | |
| return { | |
| // Fail-closed: only an explicit `allow` is visible. `block` and | |
| // `review` (LLM unsure) are both quarantined. | |
| visible: verdict.decision === 'allow', | |
| source: verdict.source || 'llm', | |
| decision: verdict.decision, | |
| category: verdict.category ?? null, | |
| reason: verdict.reason, | |
| }; | |
| } | |
| // No verdict yet (cold / pending classification) - fail closed: | |
| // hide until the moderation batch has explicitly cleared the app. | |
| return { | |
| visible: false, | |
| source: 'pending', | |
| decision: 'review', | |
| category: null, | |
| reason: 'awaiting moderation (fail-closed)', | |
| }; | |
| } | |