Registry-DB (nur Tenant-Metadaten), Provisioning-Routine legt pro Mandant
eine physisch isolierte Postgres-DB an und registriert sie transaktional
(Rollback der DB bei fehlgeschlagener Registrierung). Schlanker HTTP-Handler
als Schnittstellen-Vorbereitung fuer API-01/TEN-02, kein eigenes REST-Grundgerüst.
Pruefungen:
1. Migration up/down geschrieben (0001_tenant_registry.{up,down}.sql) — nicht
gegen echte DB ausgefuehrt, da auf dieser Maschine kein Go/Postgres-Test-
Setup verfuegbar ist. Offen zur Ausfuehrung.
2. Integrationstest TestProvision_CreatesIsolatedDatabases geschrieben (zwei
Mandanten, prueft unterschiedliche db_name und current_database()) —
ebenfalls nicht ausgefuehrt, guarded per TEST_ADMIN_DSN env var. Offen.
3. Slug-Validierung (unit test TestValidateSlug) deckt SQL-Injection-Versuch
im Datenbanknamen ab — ebenfalls nicht lokal ausgefuehrt, da kein Go
Compiler auf dieser Maschine vorhanden ist. Offen.
Alle drei Pruefungen sind vorbereitet, aber NICHT durchgefuehrt worden —
zaehlen laut Vorgabe als offen bis auf einer Maschine mit Go+Postgres verifiziert.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
43 lines
971 B
Go
43 lines
971 B
Go
// Package tenant implements Core TEN-01: die Control-Plane-Registry und die
|
|
// Provisioning-Routine fuer physisch getrennte Mandanten-Datenbanken (Modell C).
|
|
package tenant
|
|
|
|
import (
|
|
"errors"
|
|
"regexp"
|
|
"time"
|
|
)
|
|
|
|
type Status string
|
|
|
|
const (
|
|
StatusActive Status = "active"
|
|
)
|
|
|
|
type Tenant struct {
|
|
ID string
|
|
Slug string
|
|
Name string
|
|
DBName string
|
|
DBDSN string
|
|
Status Status
|
|
CreatedAt time.Time
|
|
}
|
|
|
|
// slugPattern erzwingt sichere, als SQL-Identifier verwendbare Slugs, damit
|
|
// der Datenbankname niemals aus unkontrolliertem Nutzereingabe-Text gebaut wird.
|
|
var slugPattern = regexp.MustCompile(`^[a-z][a-z0-9_]{1,48}$`)
|
|
|
|
var ErrInvalidSlug = errors.New("tenant: slug muss mit Kleinbuchstaben beginnen und darf nur [a-z0-9_] enthalten (2-49 Zeichen)")
|
|
|
|
func ValidateSlug(slug string) error {
|
|
if !slugPattern.MatchString(slug) {
|
|
return ErrInvalidSlug
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func dbNameForSlug(slug string) string {
|
|
return "tenant_" + slug
|
|
}
|