mirror of
https://github.com/fsolla/teqo.git
synced 2026-11-12 22:13:05 +00:00
- /fotos/encontre + POST /api/fotos/selfie: só o vetor 128-d, sem imagem, sem score e sem nomes de terceiros; fail-closed pela flag photoAlbum.selfieSearchEnabled (default false) e pelos Consents por chave estável (busca-selfie-fotos/busca-selfie-indice, não seedados — a superfície nasce fechada até o aval jurídico/DPIA). - Índice A/C do gate (PR #1370): só quem aderiu é indexado; descriptors do acervo são transitórios. Collection faceSubject (admin-only, sem vínculo com Contact), vínculos matchedPhotos e marker faces.checkedKey no archivePhoto (modelo + enrolledAt). - Engine @vladmandic/face-api nos dois lados: browser lazy com modelos same-origin (copy-face-vision-assets no prebuild/predev/Docker) e CLI node-wasm sem tfjs-node. CLIs ops-only faces:enroll / faces:index --apply|--verify com guardas C231/C232. - Opt-out self-service por reconhecimento (leave-index) + canal de remoção do C233; rate limit próprio (namespace selfie:<hash>) e bounded body extraído do beacon. - UI portada classe-a-classe do design estendido (paridade certificada, tier primário); e2e frontendFotosSelfie (manifest+curado+projeto, engine stubada) e canário do engine real; runbook §C234, contrato em AGENTS-public.md e changelog. - Migration aditiva add_face_subject (SQL revisado); hard-stops aprovados na sessão.
113 lines
4.8 KiB
TypeScript
113 lines
4.8 KiB
TypeScript
// @vitest-environment node
|
|
|
|
import { existsSync, readdirSync } from 'node:fs'
|
|
import { join } from 'node:path'
|
|
|
|
import { describe, expect, it } from 'vitest'
|
|
|
|
import {
|
|
E2E_AFFECTED_MANIFEST,
|
|
E2E_CURATED_SPECS,
|
|
E2E_RISK_PREFIXES,
|
|
E2E_SMOKE_FALLBACK_SPEC,
|
|
} from '../../scripts/lib/e2e-affected-manifest.mjs'
|
|
|
|
const E2E_DIR = join(__dirname, '../e2e')
|
|
|
|
function specNamesOnDisk() {
|
|
return readdirSync(E2E_DIR)
|
|
.filter((file) => file.endsWith('.e2e.spec.ts'))
|
|
.map((file) => file.slice(0, -'.e2e.spec.ts'.length))
|
|
}
|
|
|
|
describe('E2E_AFFECTED_MANIFEST (OPS5)', () => {
|
|
it('only references specs that exist on disk', () => {
|
|
const onDisk = new Set(specNamesOnDisk())
|
|
for (const entry of E2E_AFFECTED_MANIFEST) {
|
|
for (const spec of entry.specs) {
|
|
expect(onDisk.has(spec), `${spec} (prefixes: ${entry.prefixes.join(', ')})`).toBe(true)
|
|
expect(existsSync(join(E2E_DIR, `${spec}.e2e.spec.ts`))).toBe(true)
|
|
}
|
|
}
|
|
})
|
|
|
|
it('keeps prefixes repo-relative and trailing-slash-clean', () => {
|
|
for (const entry of E2E_AFFECTED_MANIFEST) {
|
|
expect(entry.prefixes.length).toBeGreaterThan(0)
|
|
for (const prefix of entry.prefixes) {
|
|
expect(prefix.startsWith('src/')).toBe(true)
|
|
expect(prefix.endsWith('/'), `${prefix} — drop the trailing slash`).toBe(false)
|
|
}
|
|
}
|
|
})
|
|
|
|
it('covers every on-disk spec family that has a clear domain prefix', () => {
|
|
// Smoke/infrastructure specs are allowed to be unmapped (they run in full
|
|
// mode); this pins the reverse direction: no manifest entry is dead.
|
|
const mapped = new Set(E2E_AFFECTED_MANIFEST.flatMap((entry) => entry.specs))
|
|
expect(mapped.size).toBeGreaterThanOrEqual(10)
|
|
})
|
|
|
|
it('freezes the curated high-risk e2e set (OPS86 — deliberate growth only)', () => {
|
|
// The curated set is the never-zero answer for high-risk PR diffs; change
|
|
// it on purpose (cost of the PR CI high-risk path), not by drift.
|
|
expect(E2E_CURATED_SPECS).toEqual([
|
|
// OPS87 — deliberate: the permission-profile family moved to the
|
|
// browserless HTTP mode (same coverage, new spec name).
|
|
'campaignPermissionProfileHttp',
|
|
'campaignDemandVisibility',
|
|
'campaignAiTranscribe',
|
|
'campaignAgendaFeed',
|
|
'campaignNewsletter',
|
|
// C167 — deliberate: the cut public page/route contract is new and the
|
|
// migration makes every PR of this delivery high-risk (curated only).
|
|
'campaignSpeechCut',
|
|
// C191-runtime — deliberate: real-Chromium PNG smoke; the curated net is
|
|
// the only path that wakes it for a scripts/ (high-risk) diff.
|
|
'campaignChartPng',
|
|
// S19 — deliberate: the share-link OG/redirect contract is new and the
|
|
// migration makes every PR of this delivery high-risk (curated only).
|
|
'frontendShareLink',
|
|
// S21 — deliberate: the jingles page/player/download contract is new and
|
|
// the migration makes every PR of this delivery high-risk (curated only).
|
|
'frontendJingles',
|
|
// S27 — deliberate: the Central catalogue/piece page, the public media
|
|
// route and the vote share sheet are new contracts over the C211
|
|
// collection (curated only).
|
|
'frontendConteudos',
|
|
// C219 — deliberate: the recordings acervo gained its own search/facet
|
|
// contract and the migration makes every PR of this delivery high-risk
|
|
// (curated only).
|
|
'campaignSpeechAcervo',
|
|
// C233 — deliberate: the public photo album (approval gate, facets,
|
|
// overlay, media route) is a new contract and the migration makes every
|
|
// PR of this delivery high-risk (curated only).
|
|
'frontendFotos',
|
|
// C234 — deliberate: the selfie search page/endpoint (Consent
|
|
// fail-closed, only consented subjects, only approved photos) is a new
|
|
// contract and the migration makes every PR of this delivery high-risk
|
|
// (curated only).
|
|
'frontendFotosSelfie',
|
|
])
|
|
const onDisk = new Set(specNamesOnDisk())
|
|
for (const spec of E2E_CURATED_SPECS) {
|
|
expect(onDisk.has(spec), spec).toBe(true)
|
|
}
|
|
})
|
|
|
|
it('keeps every risk prefix covered by a manifest entry (OPS86 fail-closed net)', () => {
|
|
// The classifier fails closed when a risk-area file matches no entry; if
|
|
// the entries drift out of sync with the risk prefixes, that fail-closed
|
|
// fires on every diff in the area. Pin the pair together.
|
|
const mappedPrefixes = new Set(E2E_AFFECTED_MANIFEST.flatMap((entry) => entry.prefixes))
|
|
for (const prefix of E2E_RISK_PREFIXES) {
|
|
expect(mappedPrefixes.has(prefix), prefix).toBe(true)
|
|
}
|
|
})
|
|
|
|
it('the unmapped fallback smoke spec exists on disk (OPS86 never-zero)', () => {
|
|
// A rename of the smoke spec would turn the fallback into a CI
|
|
// "No tests found" failure.
|
|
expect(new Set(specNamesOnDisk()).has(E2E_SMOKE_FALLBACK_SPEC)).toBe(true)
|
|
})
|
|
})
|