chore: stale Cardecky-Refs entfernt + apps/landing/ gelöscht
Some checks are pending
CI / validate (push) Waiting to run

- apps/landing/ entfernt (Cardecky-Marketing-Astro-Site, war nie
  deployed — der nginx-Block in landings.conf zeigte auf einen
  Pfad ohne Inhalt)
- Stale Doc-Kommentare in api+web: Cardecky → Wordeck wo passend
- fsrs.ts subIndexCount: image-occlusion + audio-front Cases raus
  (CardType-Enum hat sie nicht mehr — der throw wäre toter Code)
- fork.ts: image-occlusion-Sonderfall in subIndexCountFor weg
- cards-domain tests: schemas-Test prüft jetzt Wordeck-Typen + dass
  image-occlusion/audio-front ABGELEHNT werden
- cards-domain tests: image-occlusion-throw-Test entfernt
- api tests/cards.test.ts: 3 image-occlusion-Cases zu 1 negative
  Tested (422 expected, weil Schema sie verbietet)

51 Tests grün (cards-domain).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Till JS 2026-05-17 21:58:52 +02:00
parent 9b37243b1d
commit c77100e85a
33 changed files with 13 additions and 2348 deletions

View file

@ -15,7 +15,7 @@
*
* Fail-open im Original: bei mana-llm-Ausfall wurde `flag` gesetzt,
* damit ein menschlicher Reviewer es trotzdem sieht. Solange wir nur
* Cardecky-Decks publishen, ist der Stub `pass` ausreichend Cardecky
* Wordeck-Decks publishen, ist der Stub `pass` ausreichend Wordeck
* ist eine kuratierte Identität.
*/

View file

@ -146,11 +146,6 @@ export async function forkDeckForUser(
function subIndexCountFor(type: string, fields: Record<string, string>): number {
if (type === 'cloze') return subIndexCountForCloze(fields.text ?? '');
if (type === 'image-occlusion') {
// image-occlusion hat dynamische subIndexes via mask_regions —
// im Marketplace-Fork bisher nicht unterstützt. Default 1.
return 1;
}
return subIndexCount(type);
}

View file

@ -9,7 +9,7 @@ import { authorBlocks, authors, deckReports, publicDecks } from '../../db/schema
/**
* Moderation-Endpoints App-Review-Pflicht für User-Generated-Content
* (App-Store-Guideline 5.1.1(v)). Aus Cardecky-Native erreichbar als
* (App-Store-Guideline 5.1.1(v)). Aus Wordeck-Native erreichbar als
* Melden" und „Author blockieren".
*
* - `POST /decks/:slug/report` Meldung zu einem Deck. Idempotent

View file

@ -75,7 +75,7 @@ describe('cardsRouter — Input-Validation', () => {
expect(res.status).toBe(422);
});
it('POST mit image-occlusion ohne mask_regions ist 422', async () => {
it('POST mit image-occlusion ist 422 (CardType nicht mehr akzeptiert)', async () => {
const { app } = buildApp();
const res = await app.request('/api/v1/cards', {
method: 'POST',
@ -83,49 +83,12 @@ describe('cardsRouter — Input-Validation', () => {
body: JSON.stringify({
deck_id: 'd-1',
type: 'image-occlusion',
fields: { image_ref: 'm1' },
fields: { image_ref: 'm1', mask_regions: '[]' },
}),
});
expect(res.status).toBe(422);
});
it('POST mit image-occlusion mit kaputtem mask_regions ist 422', async () => {
const { app } = buildApp();
const res = await app.request('/api/v1/cards', {
method: 'POST',
headers: { 'X-User-Id': 'u-1', 'Content-Type': 'application/json' },
body: JSON.stringify({
deck_id: 'd-1',
type: 'image-occlusion',
fields: { image_ref: 'm1', mask_regions: 'not json' },
}),
});
expect(res.status).toBe(422);
const body = (await res.json()) as { issues: string[] };
expect(body.issues[0]).toMatch(/mask_regions/);
});
it('POST mit gültiger image-occlusion erreicht Deck-Lookup (404 bei stub)', async () => {
const { app } = buildApp();
const res = await app.request('/api/v1/cards', {
method: 'POST',
headers: { 'X-User-Id': 'u-1', 'Content-Type': 'application/json' },
body: JSON.stringify({
deck_id: 'd-1',
type: 'image-occlusion',
fields: {
image_ref: 'm1',
mask_regions: JSON.stringify([
{ id: 'r1', x: 0.1, y: 0.1, w: 0.1, h: 0.1 },
]),
},
}),
});
expect(res.status).toBe(404);
const body = (await res.json()) as { error: string };
expect(body.error).toBe('deck_not_found');
});
it('POST mit cloze-Card ohne text-Feld ist 422', async () => {
const { app } = buildApp();
const res = await app.request('/api/v1/cards', {