refactor(big-bang): cards → wordeck im gesamten Code-Layer
Some checks are pending
CI / validate (push) Waiting to run
Some checks are pending
CI / validate (push) Waiting to run
Phase 2 des cards→wordeck Big-Bang-Rebrand:
- 4 package.json: @cards/* → @wordeck/*
- packages/cards-domain/ → packages/wordeck-domain/
- 41+12 Files: from '@cards/domain' → '@wordeck/domain'
- pgSchema('cards') → pgSchema('wordeck') (Drizzle-Schema)
- 17 Files: process.env.CARDS_* → process.env.WORDECK_*
- docker-compose Service-Names: cards-* → wordeck-*
- docker-compose Volume: /Volumes/ManaData/cards → wordeck
- env-vars in compose: CARDS_DB_PASSWORD/_API_VERSION/_DSGVO_SERVICE_KEY etc. → WORDECK_*
- Log-Prefixes + Error-Strings + manifest-id 'cards' → 'wordeck'
- CORS-Origin cardecky.mana.how → wordeck.com
- .env.production.example umbenannt + S3-Key entfernt (kein MinIO mehr)
Type-Check 0 Errors in api+domain+web, 51/51 Domain-Tests grün.
DB-Rename + Container/Volume-Rename auf mana-server folgen in nächstem
Commit nach Verzeichnis-Rename.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
c77100e85a
commit
372832d266
90 changed files with 213 additions and 3716 deletions
|
|
@ -1,9 +1,9 @@
|
|||
{
|
||||
"name": "@cards/api",
|
||||
"name": "@wordeck/api",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"description": "Cards-API — Hono+Bun-Backend für die Greenfield-Cards-App. Spricht mana-Plattform-Services über HTTP.",
|
||||
"description": "Cards-API \u2014 Hono+Bun-Backend f\u00fcr die Greenfield-Cards-App. Spricht mana-Plattform-Services \u00fcber HTTP.",
|
||||
"scripts": {
|
||||
"dev": "bun run --hot src/index.ts",
|
||||
"start": "bun run src/index.ts",
|
||||
|
|
@ -20,7 +20,7 @@
|
|||
"drizzle:bootstrap-tracking": "bun run scripts/bootstrap-drizzle-tracking.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@cards/domain": "workspace:*",
|
||||
"@wordeck/domain": "workspace:*",
|
||||
"drizzle-orm": "0.38",
|
||||
"hono": "^4.6.0",
|
||||
"jose": "^6.2.3",
|
||||
|
|
|
|||
|
|
@ -4,4 +4,4 @@
|
|||
|
||||
import { pgSchema } from 'drizzle-orm/pg-core';
|
||||
|
||||
export const cardsSchema = pgSchema('cards');
|
||||
export const cardsSchema = pgSchema('wordeck');
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import { cardsSchema } from './_schema.ts';
|
|||
/**
|
||||
* Decks — Sammlungen von Karten. Eine Karte gehört zu genau einem Deck.
|
||||
* `fsrs_settings` ist ein JSONB-Slot für per-Deck-Overrides der globalen
|
||||
* FSRS-Defaults (siehe @cards/domain `FsrsSettings`).
|
||||
* FSRS-Defaults (siehe @wordeck/domain `FsrsSettings`).
|
||||
*/
|
||||
export const decks = cardsSchema.table(
|
||||
'decks',
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ import { marketplaceSchema } from './_schema.ts';
|
|||
import { authors } from './authors.ts';
|
||||
|
||||
/**
|
||||
* Spiegelt `CardType` aus `@cards/domain`. Enum lebt im
|
||||
* Spiegelt `CardType` aus `@wordeck/domain`. Enum lebt im
|
||||
* `marketplace`-pgSchema (nicht im default `public`), damit
|
||||
* drizzle-kit-Push mit `schemaFilter: ['cards', 'marketplace']`
|
||||
* keine spurious CREATE-TYPE-Versuche macht.
|
||||
|
|
@ -125,7 +125,7 @@ export const publicDeckCards = marketplaceSchema.table(
|
|||
versionId: uuid('version_id')
|
||||
.notNull()
|
||||
.references(() => publicDeckVersions.id, { onDelete: 'cascade' }),
|
||||
// Spiegelt @cards/domain CardType.
|
||||
// Spiegelt @wordeck/domain CardType.
|
||||
type: cardTypeEnum('type').notNull(),
|
||||
// Free-form key/value bag.
|
||||
// basic / basic-reverse / type-in: { front, back }
|
||||
|
|
@ -135,7 +135,7 @@ export const publicDeckCards = marketplaceSchema.table(
|
|||
// SHA-256 über canonical(type, fields). Subscriber nutzen den
|
||||
// Hash für per-Karten-Smart-Merge — unveränderte Karten behalten
|
||||
// ihren FSRS-State über Versions-Pulls hinweg. **Identisch zur
|
||||
// Berechnung in `@cards/domain` `cardContentHash`** — das ist der
|
||||
// Berechnung in `@wordeck/domain` `cardContentHash`** — das ist der
|
||||
// SoT, dieser Hash ist nur die persistierte Form.
|
||||
contentHash: text('content_hash').notNull(),
|
||||
},
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ app.use(
|
|||
if (/^https?:\/\/localhost(:\d+)?$/.test(origin)) return origin;
|
||||
if (/^https?:\/\/127\.0\.0\.1(:\d+)?$/.test(origin)) return origin;
|
||||
}
|
||||
if (origin === 'https://cardecky.mana.how') return origin;
|
||||
if (origin === 'https://wordeck.com') return origin;
|
||||
return null;
|
||||
},
|
||||
allowHeaders: ['Content-Type', 'X-User-Id', 'Authorization', 'X-Service-Key'],
|
||||
|
|
@ -83,15 +83,15 @@ app.route('/api/v1/marketplace/decks', marketplaceDecksRouter());
|
|||
|
||||
app.get('/', (c) =>
|
||||
c.json({
|
||||
app: 'cards',
|
||||
version: process.env.CARDS_API_VERSION ?? '0.0.0',
|
||||
app: 'wordeck',
|
||||
version: process.env.WORDECK_API_VERSION ?? '0.0.0',
|
||||
see: '/.well-known/mana-app.json',
|
||||
})
|
||||
);
|
||||
|
||||
const port = Number(process.env.CARDS_API_PORT ?? 3081);
|
||||
const port = Number(process.env.WORDECK_API_PORT ?? 3081);
|
||||
|
||||
console.log(`[cards-api] listening on http://localhost:${port}`);
|
||||
console.log(`[wordeck-api] listening on http://localhost:${port}`);
|
||||
|
||||
export default {
|
||||
port,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
* Per-Version-Content-Hash. Pro Karte wird `cardContentHash` aus
|
||||
* `@cards/domain` benutzt (gemeinsame Source-of-Truth zwischen privatem
|
||||
* `@wordeck/domain` benutzt (gemeinsame Source-of-Truth zwischen privatem
|
||||
* Lern-Stack und Marketplace) — pro Version hashen wir die geordnete
|
||||
* Liste von Karten-Hashes plus deren Ordinal-Position.
|
||||
*
|
||||
|
|
@ -17,7 +17,7 @@
|
|||
* privaten `cards.cards.content_hash` matchen können soll.
|
||||
*/
|
||||
|
||||
import { cardContentHash } from '@cards/domain';
|
||||
import { cardContentHash } from '@wordeck/domain';
|
||||
|
||||
export interface OrderedCardForHash {
|
||||
type: string;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { newReview } from '@cards/domain';
|
||||
import { newReview } from '@wordeck/domain';
|
||||
|
||||
export function makeInitialReviewRows(params: {
|
||||
userId: string;
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { and, eq, sql } from 'drizzle-orm';
|
|||
import type { CardsDb } from '../db/connection.ts';
|
||||
import { cards, decks } from '../db/schema/index.ts';
|
||||
|
||||
const APP_BASE_URL = process.env.CARDS_PUBLIC_URL ?? 'https://cardecky.mana.how';
|
||||
const APP_BASE_URL = process.env.WORDECK_PUBLIC_URL ?? 'https://cardecky.mana.how';
|
||||
|
||||
export type SearchHit = {
|
||||
id: string;
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ export function tierAtLeast(have: Tier, need: Tier): boolean {
|
|||
const MANA_AUTH_URL = process.env.MANA_AUTH_URL ?? 'https://auth.mana.how';
|
||||
// Fail-secure: opt-in, nicht opt-out. Vergessene env-var ⇒ Bypass AUS.
|
||||
// Tests setzen die Variable via vitest.config.ts → tests/setup.ts.
|
||||
const ALLOW_DEV_STUB = process.env.CARDS_AUTH_DEV_STUB === 'true';
|
||||
const ALLOW_DEV_STUB = process.env.WORDECK_AUTH_DEV_STUB === 'true';
|
||||
|
||||
let jwksCache: ReturnType<typeof createRemoteJWKSet> | null = null;
|
||||
function getJwks() {
|
||||
|
|
@ -118,7 +118,7 @@ export function getUserId(c: Context<{ Variables: AuthVars }>): string {
|
|||
* Tier-Gate für Premium-Features. Nutze als Hono-Middleware:
|
||||
* r.post('/premium-thing', requireTier('beta'), async (c) => …)
|
||||
* Liefert 403 wenn der eingeloggte User nicht mindestens den
|
||||
* verlangten Tier hat. Aktuell auf cards-api nicht aktiv genutzt
|
||||
* verlangten Tier hat. Aktuell auf wordeck-api nicht aktiv genutzt
|
||||
* (Cards-MVP ist tier-frei für authentifizierte User), aber das
|
||||
* Plumbing ist da für künftige Premium-Pfade (z.B. AI-Bulk-Convert).
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import type { MiddlewareHandler } from 'hono';
|
|||
* service-zu-service-Calls.
|
||||
*
|
||||
* Heute (Phase 5): vergleicht `X-Service-Key`-Header per
|
||||
* constant-time-Compare gegen `process.env.CARDS_DSGVO_SERVICE_KEY`.
|
||||
* constant-time-Compare gegen `process.env.WORDECK_DSGVO_SERVICE_KEY`.
|
||||
*
|
||||
* Phase F-1: ersetzt durch Verifikation gegen mana-auth's
|
||||
* `apps.app_service_keys` Tabelle (caller-App = `mana-admin`).
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import {
|
|||
cardContentHash,
|
||||
subIndexCount,
|
||||
subIndexCountForCloze,
|
||||
} from '@cards/domain';
|
||||
} from '@wordeck/domain';
|
||||
|
||||
import { makeInitialReviewRows } from '../lib/reviews.ts';
|
||||
import { toCardDto } from '../lib/dto.ts';
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { eq } from 'drizzle-orm';
|
|||
import { Hono } from 'hono';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { cardContentHash, subIndexCount } from '@cards/domain';
|
||||
import { cardContentHash, subIndexCount } from '@wordeck/domain';
|
||||
|
||||
import { makeInitialReviewRows } from '../lib/reviews.ts';
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { and, eq, isNotNull, isNull, ne } from 'drizzle-orm';
|
|||
import { sql } from 'drizzle-orm';
|
||||
import { Hono } from 'hono';
|
||||
|
||||
import { DeckCreateSchema, DeckUpdateSchema } from '@cards/domain';
|
||||
import { DeckCreateSchema, DeckUpdateSchema } from '@wordeck/domain';
|
||||
|
||||
import { getDb, type CardsDb } from '../db/connection.ts';
|
||||
import { cards, decks, publicDecks } from '../db/schema/index.ts';
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ export async function buildUserExport(db: CardsDb, userId: string) {
|
|||
user_id: userId,
|
||||
exported_at: new Date().toISOString(),
|
||||
app: 'wordeck',
|
||||
app_version: process.env.CARDS_API_VERSION ?? '0.0.0',
|
||||
app_version: process.env.WORDECK_API_VERSION ?? '0.0.0',
|
||||
data: {
|
||||
decks: decksRows.map((d) => ({
|
||||
...d,
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ healthRoute.get('/healthz/details', async (c) => {
|
|||
{
|
||||
status: allOk ? 'ok' : 'degraded',
|
||||
app: 'wordeck',
|
||||
version: process.env.CARDS_API_VERSION ?? '0.0.0',
|
||||
version: process.env.WORDECK_API_VERSION ?? '0.0.0',
|
||||
uptime_s: Math.floor(process.uptime()),
|
||||
checks: {
|
||||
db: dbProbe,
|
||||
|
|
@ -38,8 +38,8 @@ healthRoute.get('/healthz/details', async (c) => {
|
|||
healthRoute.get('/version', (c) =>
|
||||
c.json({
|
||||
app: 'wordeck',
|
||||
version: process.env.CARDS_API_VERSION ?? '0.0.0',
|
||||
build: process.env.CARDS_BUILD_SHA ?? 'dev',
|
||||
version: process.env.WORDECK_API_VERSION ?? '0.0.0',
|
||||
build: process.env.WORDECK_BUILD_SHA ?? 'dev',
|
||||
})
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { and, eq } from 'drizzle-orm';
|
|||
import { Hono } from 'hono';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { cardContentHash } from '@cards/domain';
|
||||
import { cardContentHash } from '@wordeck/domain';
|
||||
|
||||
import { getDb, type CardsDb } from '../../db/connection.ts';
|
||||
import {
|
||||
|
|
@ -34,7 +34,7 @@ import { hashVersionCards } from '../../lib/marketplace/version-hash.ts';
|
|||
*
|
||||
* Geschichte: ported aus
|
||||
* `cards-decommission-base:services/cards-server/src/{routes,services}/decks.ts`,
|
||||
* mit Greenfield-Anpassungen (Hashing über `@cards/domain`,
|
||||
* mit Greenfield-Anpassungen (Hashing über `@wordeck/domain`,
|
||||
* AI-Mod-Stub statt mana-llm-Call, Auth-Vars-Shape).
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import {
|
|||
newReview,
|
||||
subIndexCount,
|
||||
subIndexCountForCloze,
|
||||
} from '@cards/domain';
|
||||
} from '@wordeck/domain';
|
||||
|
||||
import { getDb, type CardsDb } from '../../db/connection.ts';
|
||||
import { cards, decks, reviews } from '../../db/schema/index.ts';
|
||||
|
|
@ -42,7 +42,7 @@ import { computeDiff } from '../../lib/marketplace/diff.ts';
|
|||
* Architektur-Begründung:
|
||||
* - **content_hash-basierter Dedupe** ist die Smart-Merge-Magic:
|
||||
* `cards.cards.content_hash` matcht `marketplace.deck_cards.content_hash`,
|
||||
* identisch berechnet via `@cards/domain.cardContentHash`.
|
||||
* identisch berechnet via `@wordeck/domain.cardContentHash`.
|
||||
* Unveränderte Karten = identisches Hash → schon da → Insert
|
||||
* übersprungen → FSRS bleibt.
|
||||
* - **Removed-Cards bleiben lokal**: anders als das alte Dexie-Sync
|
||||
|
|
@ -305,7 +305,7 @@ export function forkRouter(deps: MarketplaceForkDeps = {}): Hono<{ Variables: Au
|
|||
// Marketplace-Karte). Unveränderte Karten existieren schon
|
||||
// privat — wir können den Insert sicher überspringen, weil
|
||||
// (deck_id, content_hash) im privaten cards.cards einzigartig
|
||||
// ist (gleiche Hash-Funktion via @cards/domain).
|
||||
// ist (gleiche Hash-Funktion via @wordeck/domain).
|
||||
// Removed-Cards bleiben lokal (server-authoritative User-Choice).
|
||||
const now = new Date();
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { and, asc, desc, eq } from 'drizzle-orm';
|
|||
import { Hono } from 'hono';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { cardContentHash } from '@cards/domain';
|
||||
import { cardContentHash } from '@wordeck/domain';
|
||||
|
||||
import { getDb, type CardsDb } from '../../db/connection.ts';
|
||||
import {
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import {
|
|||
GradeReviewInputSchema,
|
||||
gradeReview,
|
||||
type Review as DomainReview,
|
||||
} from '@cards/domain';
|
||||
} from '@wordeck/domain';
|
||||
|
||||
import { getDb, type CardsDb } from '../db/connection.ts';
|
||||
import { cards, decks, reviews } from '../db/schema/index.ts';
|
||||
|
|
|
|||
|
|
@ -3,13 +3,13 @@ import { Hono } from 'hono';
|
|||
import {
|
||||
SEARCH_ENVELOPE_VERSION,
|
||||
type SearchResultEnvelope,
|
||||
} from '@cards/domain';
|
||||
} from '@wordeck/domain';
|
||||
|
||||
import { getDb, type CardsDb } from '../db/connection.ts';
|
||||
import { authMiddleware, type AuthVars } from '../middleware/auth.ts';
|
||||
import { searchUserCards } from '../lib/search.ts';
|
||||
|
||||
const APP_VERSION = process.env.CARDS_API_VERSION ?? '0.0.0';
|
||||
const APP_VERSION = process.env.WORDECK_API_VERSION ?? '0.0.0';
|
||||
|
||||
export type SearchDeps = { db?: CardsDb };
|
||||
|
||||
|
|
@ -43,7 +43,7 @@ export function searchRouter(deps: SearchDeps = {}): Hono<{ Variables: AuthVars
|
|||
const envelope: SearchResultEnvelope = {
|
||||
envelope_version: SEARCH_ENVELOPE_VERSION,
|
||||
query: q,
|
||||
app: 'cards',
|
||||
app: 'wordeck',
|
||||
app_version: APP_VERSION,
|
||||
results: hits.map((h) => ({
|
||||
id: h.id,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { Hono } from 'hono';
|
||||
|
||||
import { parseEnvelope, validatePayloadForType } from '@cards/domain';
|
||||
import { parseEnvelope, validatePayloadForType } from '@wordeck/domain';
|
||||
|
||||
import manifest from '../../../../app-manifest.json' with { type: 'json' };
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import {
|
|||
cardContentHash,
|
||||
subIndexCount,
|
||||
subIndexCountForCloze,
|
||||
} from '@cards/domain';
|
||||
} from '@wordeck/domain';
|
||||
|
||||
import { makeInitialReviewRows } from '../lib/reviews.ts';
|
||||
|
||||
|
|
@ -17,8 +17,8 @@ import { authMiddleware, type AuthVars } from '../middleware/auth.ts';
|
|||
import { ulid } from '../lib/ulid.ts';
|
||||
import { searchUserCards } from '../lib/search.ts';
|
||||
|
||||
const APP_BASE_URL = process.env.CARDS_PUBLIC_URL ?? 'https://wordeck.com';
|
||||
const APP_VERSION = process.env.CARDS_API_VERSION ?? '0.0.0';
|
||||
const APP_BASE_URL = process.env.WORDECK_PUBLIC_URL ?? 'https://wordeck.com';
|
||||
const APP_VERSION = process.env.WORDECK_API_VERSION ?? '0.0.0';
|
||||
|
||||
export type ToolsDeps = { db?: CardsDb };
|
||||
|
||||
|
|
@ -132,7 +132,7 @@ export function toolsRouter(deps: ToolsDeps = {}): Hono<{ Variables: AuthVars }>
|
|||
})),
|
||||
total: hits.length,
|
||||
took_ms: tookMs,
|
||||
app: 'cards',
|
||||
app: 'wordeck',
|
||||
app_version: APP_VERSION,
|
||||
base_url: APP_BASE_URL,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
const CREDITS_URL = process.env.MANA_CREDITS_URL ?? 'https://credits.mana.how';
|
||||
|
||||
function authHeader(): Record<string, string> {
|
||||
const key = process.env.CARDS_MANA_SERVICE_KEY;
|
||||
const key = process.env.WORDECK_MANA_SERVICE_KEY;
|
||||
if (!key) return {};
|
||||
return { 'X-Service-Key': key };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
*/
|
||||
|
||||
const LLM_URL = process.env.MANA_LLM_URL ?? 'https://llm.mana.how';
|
||||
const LLM_API_KEY = process.env.CARDS_LLM_API_KEY ?? '';
|
||||
const LLM_API_KEY = process.env.WORDECK_LLM_API_KEY ?? '';
|
||||
|
||||
export interface ChatMessage {
|
||||
role: 'system' | 'user' | 'assistant';
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { newReview, subIndexCount } from '@cards/domain';
|
||||
import type { QuotePayload, TextPayload, LinkPayload } from '@cards/domain';
|
||||
import { newReview, subIndexCount } from '@wordeck/domain';
|
||||
import type { QuotePayload, TextPayload, LinkPayload } from '@wordeck/domain';
|
||||
|
||||
import type { CardsDb } from '../db/connection.ts';
|
||||
import { cards, reviews } from '../db/schema/index.ts';
|
||||
|
|
@ -15,7 +15,7 @@ export type HandlerResult = {
|
|||
resulting_id: string;
|
||||
};
|
||||
|
||||
const APP_BASE_URL = process.env.CARDS_PUBLIC_URL ?? 'https://wordeck.com';
|
||||
const APP_BASE_URL = process.env.WORDECK_PUBLIC_URL ?? 'https://wordeck.com';
|
||||
|
||||
/**
|
||||
* Legt eine basic-Karte mit (front,back) im Inbox-Deck an, inkl.
|
||||
|
|
|
|||
|
|
@ -4,18 +4,18 @@ import { Hono } from 'hono';
|
|||
import { dsgvoRouter } from '../src/routes/dsgvo.ts';
|
||||
import type { CardsDb } from '../src/db/connection.ts';
|
||||
|
||||
const ORIG_ENV = process.env.CARDS_DSGVO_SERVICE_KEY;
|
||||
const ORIG_ENV = process.env.WORDECK_DSGVO_SERVICE_KEY;
|
||||
const TEST_KEY = 'msk_test_dsgvo_key_42';
|
||||
|
||||
beforeEach(() => {
|
||||
process.env.CARDS_DSGVO_SERVICE_KEY = TEST_KEY;
|
||||
process.env.WORDECK_DSGVO_SERVICE_KEY = TEST_KEY;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
if (ORIG_ENV === undefined) {
|
||||
delete process.env.CARDS_DSGVO_SERVICE_KEY;
|
||||
delete process.env.WORDECK_DSGVO_SERVICE_KEY;
|
||||
} else {
|
||||
process.env.CARDS_DSGVO_SERVICE_KEY = ORIG_ENV;
|
||||
process.env.WORDECK_DSGVO_SERVICE_KEY = ORIG_ENV;
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -98,7 +98,7 @@ describe('dsgvoRouter — Service-Key-Gate', () => {
|
|||
|
||||
describe('dsgvoRouter — Key-not-configured Pfad', () => {
|
||||
it('Wenn ENV fehlt → 500 service_key_not_configured', async () => {
|
||||
delete process.env.CARDS_DSGVO_SERVICE_KEY;
|
||||
delete process.env.WORDECK_DSGVO_SERVICE_KEY;
|
||||
const { app } = buildApp();
|
||||
const res = await app.request('/api/v1/dsgvo/export?user_id=u-1', {
|
||||
headers: { 'X-Service-Key': 'whatever' },
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
import { cardContentHash } from '@cards/domain';
|
||||
import { cardContentHash } from '@wordeck/domain';
|
||||
|
||||
import { hashVersionCards } from '../src/lib/marketplace/version-hash.ts';
|
||||
|
||||
|
|
@ -38,7 +38,7 @@ describe('hashVersionCards', () => {
|
|||
expect(inOrder).toBe(reversedInput);
|
||||
});
|
||||
|
||||
it('uses cardContentHash for per-card identity (consumes @cards/domain SoT)', async () => {
|
||||
it('uses cardContentHash for per-card identity (consumes @wordeck/domain SoT)', async () => {
|
||||
// Smoke: changing fields without changing the type must change the
|
||||
// per-card hash (cardContentHash semantics) and therefore the
|
||||
// version hash.
|
||||
|
|
|
|||
|
|
@ -4,6 +4,6 @@
|
|||
// Aktiviert den X-User-Id-Dev-Stub für Tests, weil die Suiten ohne
|
||||
// echten mana-auth-JWKS laufen. In Produktion ist der Stub fail-secure
|
||||
// AUS (siehe apps/api/src/middleware/auth.ts).
|
||||
if (process.env.CARDS_AUTH_DEV_STUB === undefined) {
|
||||
process.env.CARDS_AUTH_DEV_STUB = 'true';
|
||||
if (process.env.WORDECK_AUTH_DEV_STUB === undefined) {
|
||||
process.env.WORDECK_AUTH_DEV_STUB = 'true';
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue