managarten/services/mana-credits/src/lib/validation.ts
Till JS 2514831a3b chore(matrix): scrub final matrix references after subsystem removal
The matrix subsystem was removed in a prior commit. This commit cleans
up the small leftovers that grep found:

- docker-compose.macmini.yml: dropped the "Matrix Stack" port-range
  comment, the "matrix" category from the naming convention, and a
  stale watchtower comment about Matrix notifications.
- packages/credits/src/operations.ts: removed AI_BOT_CHAT credit
  operation type and its definition. It was the billing entry for "Chat
  with AI via Matrix bot" — no callers left.
- services/mana-credits gifts schema + service + validation: removed the
  targetMatrixId column / param / Zod field. The corresponding
  PostgreSQL column was dropped manually with
  `ALTER TABLE gifts.gift_codes DROP COLUMN target_matrix_id` on prod.
- docker/grafana/dashboards/{master,system}-overview.json: removed the
  `up{job="synapse"}` panel queries — they would have shown No Data
  forever now that Synapse is gone.

Production-side cleanup performed in parallel (not in this commit):
- Stopped + removed mana-matrix-{synapse,element,web,bot} containers
- Removed mana-matrix-bot:local, matrix-web:latest,
  matrixdotorg/synapse:latest, vectorim/element-web:latest images (~3 GB)
- Removed mana-matrix-bots-data Docker volume
- Removed /Volumes/ManaData/matrix/ media store (4.3 MB)
- DROP DATABASE matrix; DROP DATABASE synapse; on Postgres

Cosmetic leftovers intentionally untouched:
- Eisenhower matrix in todo (LayoutMode 'matrix') — productivity concept
- ${{ matrix.service }} in .github/workflows — GitHub Actions strategy
- services/mana-media/apps/api/dist/.../matrix/* — stale build output
  (not in git, regenerated next mana-media build)
2026-04-08 16:39:42 +02:00

94 lines
2.9 KiB
TypeScript

/**
* Zod schemas for request body validation.
*/
import { z } from 'zod';
// ─── Credits ────────────────────────────────────────────────
export const useCreditsSchema = z.object({
amount: z.number().positive(),
appId: z.string().min(1),
description: z.string().min(1),
creditSource: z
.object({
type: z.literal('guild'),
guildId: z.string().min(1),
})
.optional(),
idempotencyKey: z.string().optional(),
metadata: z.record(z.unknown()).optional(),
});
export const purchaseCreditsSchema = z.object({
packageId: z.string().uuid(),
});
export const createPaymentLinkSchema = z.object({
packageId: z.string().uuid(),
quantity: z.number().int().positive().default(1),
});
// ─── Guild ──────────────────────────────────────────────────
export const fundGuildPoolSchema = z.object({
amount: z.number().positive(),
idempotencyKey: z.string().optional(),
});
export const setSpendingLimitSchema = z.object({
dailyLimit: z.number().int().positive().nullable().optional(),
monthlyLimit: z.number().int().positive().nullable().optional(),
});
// ─── Gifts ──────────────────────────────────────────────────
export const createGiftSchema = z.object({
totalCredits: z.number().int().positive().min(1).max(10000),
type: z.enum(['simple', 'personalized', 'split', 'first_come', 'riddle']).default('simple'),
totalPortions: z.number().int().positive().max(100).default(1),
targetEmail: z.string().email().optional(),
riddleQuestion: z.string().max(200).optional(),
riddleAnswer: z.string().optional(),
message: z.string().max(500).optional(),
expirationDays: z.number().int().positive().optional(),
});
export const redeemGiftSchema = z.object({
riddleAnswer: z.string().optional(),
sourceAppId: z.string().optional(),
});
// ─── Internal (Service-to-Service) ──────────────────────────
export const internalUseCreditsSchema = z.object({
userId: z.string().min(1),
amount: z.number().positive(),
appId: z.string().min(1),
description: z.string().min(1),
creditSource: z
.object({
type: z.literal('guild'),
guildId: z.string().min(1),
})
.optional(),
idempotencyKey: z.string().optional(),
metadata: z.record(z.unknown()).optional(),
});
export const internalRefundSchema = z.object({
userId: z.string().min(1),
amount: z.number().positive(),
description: z.string().min(1),
appId: z.string().default('system'),
metadata: z.record(z.unknown()).optional(),
});
export const internalInitSchema = z.object({
userId: z.string().min(1),
});
export const internalRedeemPendingSchema = z.object({
userId: z.string().min(1),
email: z.string().email(),
});