import { readFile } from 'node:fs/promises'; import { test } from 'node:test'; import assert from 'node:assert/strict'; const sourceUrl = new URL('../cloud-functions/saas-voc-gateway.js', import.meta.url); test('managed cloud source defines the required handler and an explicit action allowlist', async () => { const source = await readFile(sourceUrl, 'utf8'); assert.match(source, /async function handler\(request, response\)/); assert.match(source, /const ACTIONS = new Set/); assert.match(source, /cloud_action_not_allowed/); assert.doesNotMatch(source, /new Parse\.Query\(input\.|new Parse\.Query\(params\./); }); test('managed cloud source enforces authentication, workspace membership, roles and product scope before master-key access', async () => { const source = await readFile(sourceUrl, 'utf8'); assert.match(source, /if \(!activeRequest\.user\)/); assert.match(source, /VocWorkspaceMember/); assert.match(source, /viewer_write_forbidden/); assert.match(source, /productIds/); assert.match(source, /product_scope_denied/); assert.match(source, /useMasterKey: true/); }); test('managed domestic snapshot preserves the frontend dataset contract and computes empty-safe totals', async () => { const source = await readFile(sourceUrl, 'utf8'); assert.match(source, /dailyTotals/); assert.match(source, /mappingGroups/); assert.match(source, /quality:/); assert.match(source, /conversionRate: total\.visitors \? /); assert.match(source, /reviewCount: reviews\.length/); }); test('managed reads normalize Parse identifiers into frontend business identifiers', async () => { const source = await readFile(sourceUrl, 'utf8'); assert.match(source, /function presentReadItem\(action, item\)/); assert.match(source, /output\.id = output\.publicId \|\| output\.objectId/); assert.match(source, /output\.reviewId = output\.reviewId \|\| output\.reviewKey/); assert.match(source, /listing\.products\.list/); }); test('managed handler serializes shared request context and clears it after execution', async () => { const source = await readFile(sourceUrl, 'utf8'); assert.match(source, /let functionQueue = Promise\.resolve\(\)/); assert.match(source, /await previous/); assert.match(source, /activeRequest = null/); assert.match(source, /activeResponse = null/); }); test('managed cloud source rejects arbitrary upstream forwarding and redacts secret-shaped fields', async () => { const source = await readFile(sourceUrl, 'utf8'); assert.doesNotMatch(source, /fetch\s*\(\s*input\./); assert.match(source, /token\|secret\|password\|credential\|authorization\|master/i); assert.doesNotMatch(source, /PARSE_MASTER_KEY\s*=\s*['"][^'"]+['"]/); assert.match(source, /const UPSTREAM_PATHS = \{/); assert.match(source, /upstream_path_not_allowed/); assert.match(source, /new URL\(path\.replace/); assert.match(source, /const UPSTREAM_OPERATIONS = \{/); assert.match(source, /upstream_operation_not_allowed/); assert.match(source, /upstream_timeout/); assert.match(source, /function normalizeUpstreamPath\(value\)/); assert.ok(source.includes("if (!/^https:\\/\\//i.test(base)")); }); test('managed score jobs persist the worker contract and create queue items before publishing the job', async () => { const source = await readFile(sourceUrl, 'utf8'); assert.match(source, /async function resolveListingScoreSources/); assert.match(source, /async function createListingScoreItems/); assert.match(source, /VocListingScoreItem/); assert.match(source, /const rubricVersion = input\.rubricVersion \|\| \(jdVocEnabled \? 'jd-voc-v0\.5'/); assert.match(source, /rubricVersion, includeAiSuggestions: scoringMode === 'ai'/); assert.match(source, /jd_voc_disabled/); assert.match(source, /\.run\$/); assert.match(source, /processed: 0, succeeded: 0, partial: 0, blocked: 0, failed: 0/); assert.match(source, /status: sources\.length \? 'initializing' : 'completed'/); assert.match(source, /await createIdempotent\('VocListingScoreJob'[\s\S]*await createListingScoreItems/); assert.match(source, /activateListingScoreJob/); assert.match(source, /function presentListingJob\(/); assert.match(source, /function presentListingJobItem\(/); }); test('managed task mutations preserve persisted payloads and reject duplicate active competitor refreshes', async () => { const source = await readFile(sourceUrl, 'utf8'); assert.match(source, /function storageData\(params, workspaceId\)/); assert.match(source, /storageData\(params, workspaceId\)/); assert.match(source, /activeRunQuery\.containedIn\('status', \['queued', 'running'\]\)/); assert.match(source, /competitor_listing_refresh_running/); }); test('managed aggregate reads expand linked competitor scope and paginate beyond one Parse page', async () => { const source = await readFile(sourceUrl, 'utf8'); assert.match(source, /\['VocProduct', 'VocCompetitorListingSnapshot', 'VocCompetitorListingChange'\]/); assert.match(source, /const competitorIds = relations\.map/); assert.match(source, /const products = await readAll\('VocProduct'/); assert.match(source, /const sources = await readAllWhere\('VocListingSourceSnapshot'/); assert.match(source, /const scores = await readAllWhere\('VocListingCurrentScore'/); assert.match(source, /const changes = await readAllWhere\('VocCompetitorListingChange'/); assert.match(source, /async function readAllWhere\(/); assert.match(source, /readAllWhere\('VocListingSourceSnapshot'/); assert.match(source, /const READ_FILTER_FIELDS = \{/); assert.match(source, /function applyReadFilters\(query, className, params\)/); assert.match(source, /query\.contains\('title', params\.search/); }); test('deployment documentation exposes a separate Function registry credential boundary', async () => { const deployment = await readFile(new URL('../docs/cloud-functions-deployment.md', import.meta.url), 'utf8'); assert.match(deployment, /FUNCTION_REGISTRY_SERVER_URL/); assert.match(deployment, /FUNCTION_REGISTRY_APP_ID/); assert.match(deployment, /FUNCTION_REGISTRY_MASTER_KEY/); });