kisenon
Agent-Safe Change Control

Maskierte Forks

Geben Sie einem Agenten (oder einem Menschen) die Form der Produktion und nichts von ihrer PII — Maskierungsrichtlinien, die eingebaute Funktionsbibliothek und wie maskierte Branches und Sandboxes versiegelt bleiben, bis die Maske committet.

MASK ist die Agent-Safe Change Control-Bahn für sensible Daten: sie übergibt einem Agenten einen Fork mit der Form der Produktion und nichts von ihrer PII. Sie funktioniert auf zwei Arten — maskierte Branches (für Menschen: Dev, CI, Auftragnehmer) und maskierte Sandboxes (für Agenten). Beide werden unten behandelt.

Datenmaskierung anonymisiert sensible Spalten in dem Moment, in dem ein Branch erstellt wird. Sie hängen eine Maskierungsrichtlinie an den Branch-Erstellungsaufruf an, und die passenden Spalten des neuen Branches werden irreversibel umgeschrieben — gehasht, genullt, gekürzt oder ersetzt — bevor der Branch überhaupt erreichbar ist. Der Eltern-Branch wird niemals modifiziert.

Sie würden dazu greifen, um produktionsförmige Daten an Entwicklung, CI oder einen Auftragnehmer zu übergeben, ohne die darin enthaltene PII zu übergeben: echte Tabellenformen, echte Zeilenzahlen, gefälschte E-Mails.

Wie es funktioniert

Eine Maskierungsrichtlinie ist ein projektbezogener, benannter Satz von Regeln. Jede Regel gleicht Spalten per Muster ab und benennt eine eingebaute Maskierungsfunktion:

FeldBedeutung
schema_patternSchemanamen-Muster (% oder * = beliebig, _ = ein Zeichen). Standard ist *.
table_patternTabellennamen-Muster.
column_patternSpaltennamen-Muster.
masking_fnEine der eingebauten Funktionen unten.
fn_argsFunktionsargumente (nur mask_constant nimmt eins: value).

Zur Branch-Erstellungszeit, wenn eine masking_policy_id angegeben ist:

  1. Der Branch forkt wie üblich von seinem Elternteil (copy-on-write — sofort).
  2. Der Branch tritt in den masking-Zustand ein. Kein Endpunkt wird bereitgestellt und der Proxy verweigert Verbindungen zu ihm: es gibt kein Fenster, in dem die vor-maskierten Daten gelesen werden können.
  3. Ein Maskierungs-Worker verbindet sich mit dem Compute des Branches als Least-Privilege-Rolle, entdeckt das Schema, gleicht Ihre Regeln dagegen ab und führt jedes Rewrite in einer einzigen Transaktion aus.
  4. Der Branch landet in ready und seine Endpunkte kommen hoch — nun nur noch maskierte Daten liefernd. Bei jedem Fehler landet der Branch in failed und bleibt versiegelt; löschen Sie ihn und versuchen Sie es erneut.

Regel-Eingaben werden als Daten behandelt, niemals als SQL: Bezeichner werden gequotet und Argumentwerte werden bei der Ausführung als Parameter gebunden, sodass ein feindlicher Spaltenname oder eine Konstante nicht aus dem Rewrite ausbrechen kann.

Eingebaute Funktionen

FunktionEffekt
mask_emailmd5(value)@masked.invalid
mask_nameName_ + ein 8-Zeichen-Hash-Präfix
mask_nullNULL (Spalte muss nullbar sein)
mask_constantEin fester Wert, den Sie angeben (fn_args.value)
mask_ssn_partial***-**-1234 — behält die letzten 4 Ziffern
mask_credit_card****-****-****-1234 — behält die letzten 4 Ziffern
mask_ip0.0.0.0
mask_date_yearBehält das Jahr, kürzt auf den 1. Januar
mask_hashmd5(value)
mask_shuffleHash-basiertes Verwürfeln (vollständiges Zeichen-Shuffle ist geplant)
mask_phoneEine synthetische +1-555-XXXX-Nummer
mask_uuidEine frische zufällige UUID

Der Katalog wird auch von der API bereitgestellt:

curl -s https://api.kisenon.com/v1/masking-functions \
  -H "Authorization: Bearer $KISENON_API_KEY"

Richtlinien verwalten

Öffnen Sie in der Konsole Project settings → Data masking, um eine Richtlinie zu erstellen: benennen Sie sie, fügen Sie Regeln hinzu (Musterspalten + ein Funktions-Dropdown) und speichern Sie. Dieselbe Oberfläche existiert auf der API:

curl -s -X POST \
  https://api.kisenon.com/v1/projects/$PROJECT_ID/masking-policies \
  -H "Authorization: Bearer $KISENON_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "dev-safe",
    "rules": [
      {"table_pattern": "users", "column_pattern": "email", "masking_fn": "mask_email"},
      {"table_pattern": "users", "column_pattern": "phone", "masking_fn": "mask_null"},
      {"table_pattern": "%", "column_pattern": "%ssn%", "masking_fn": "mask_ssn_partial"}
    ]
  }'

Erstellen Sie dann einen maskierten Branch, indem Sie die Richtlinie zu einem normalen Branch-Erstellungsaufruf hinzufügen:

curl -s -X POST \
  https://api.kisenon.com/v1/projects/$PROJECT_ID/branches \
  -H "Authorization: Bearer $KISENON_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "masked-dev", "masking_policy_id": "'$POLICY_ID'"}'

Der Branch meldet state: "masking", während das Rewrite läuft; beobachten Sie, wie es auf ready umschlägt in der Konsole (live, über den Projekt- Event-Stream) oder durch Pollen von GET /v1/branches/{id}.

Maskierte Sandboxes (für Agenten)

Dieselben Richtlinien maskieren den Sandbox-Fork eines Agenten, sodass ein Agent gegen die Form der Produktion arbeitet und niemals ihre PII sieht. Hängen Sie eine Richtlinie bei der Erstellung an:

keon sandbox create --project <id> --masking-policy <policy-id>

Die Maske läuft, bevor die Sandbox aktiviert wird. Die Sandbox meldet masked: true und ihre masking_policy_id, und während sie noch creating ist, zeigt ein masking-Fortschrittsobjekt (state, phase, rules_total, rules_completed, rows_affected_so_far, error) das voranschreitende Rewrite.

Setzen Sie eine Pro-Projekt-Untergrenze, sodass jede Sandbox standardmäßig maskiert ist:

keon projects update <id> --sandbox-masking-policy <policy-id>   # or: none

Eine --masking-policy pro Anfrage überschreibt den Projekt-Standard, aber sie kann sich niemals aus einem Mandat abmelden — eine Verteidigung gegen einen Agenten, der sich aus der Maskierung herausredet. Das Setzen des Mandats ist nur Owner/Admin; Schlüssel mit Agenten- Fähigkeit werden abgelehnt (403).

Fail-closed durch Konstruktion. Die Endpunkte eines maskierten Forks werden in einem Maskierungszustand geboren — der Proxy verweigert Verbindungen (SQLSTATE 57P05), bis das Rewrite committet. Schlägt der Maskierungsschritt fehl oder ist er nicht verkabelt, schlägt die Erstellung fail-closed fehl: für einen unmaskierten Fork wird niemals eine URL ausgestellt. Der Maskierungs-Worker verbindet sich als Least-Privilege-Rolle kisenon_masker (niemals ein Superuser), hält kein Cluster-RBAC, und sein Pro-Lauf-Passwort wird niemals persistiert oder geloggt.

Zwei erwähnenswerte Vorbehalte:

  • DML gegen maskierte Werte wird auf dem Elternteil beim Replay nicht matchen. Eine Anweisung wie UPDATE … WHERE email = 'a1b2@masked.invalid' zielt auf einen maskierten Wert, der auf main nicht existiert. Schema-Bahn-Arbeit ist wertunabhängig und promotet sauber; wertabhängiges DML ist nicht die Aufgabe für einen maskierten Fork.
  • Fremdschlüssel bleiben durchgesetzt. Maskierung deaktiviert User-Trigger (ALTER TABLE … DISABLE TRIGGER USER), nicht Trigger der referenziellen Integrität. Das Maskieren einer Spalte innerhalb einer Fremdschlüsselbeziehung kann daher auf einen RI- Fehler treffen und den Fork fail-closed fehlschlagen lassen, statt die Referenz still zu brechen.
  • v1 maskiert nur die main-Datenbank.

Gut zu wissen

  • Maskierung ist einmalig, bei der Erstellung. Das Bearbeiten einer Richtlinie berührt niemals Branches, die bereits mit ihr erstellt wurden — sie behalten die Datenform, mit der sie geboren wurden. Erstellen Sie den Branch neu, um die neuen Regeln anzuwenden.
  • Eine in Verwendung befindliche Richtlinie kann nicht gelöscht werden. Das Löschen einer Richtlinie, mit der ein lebender Branch erstellt wurde, gibt 409 policy_in_use zurück; löschen Sie diese Branches zuerst.
  • Nicht passende Regeln werden übersprungen, nicht fatal. Wenn Ihr Schema abgedriftet ist und ein Muster nichts matcht, wird der Branch trotzdem fertiggestellt — prüfen Sie die Regel- Muster, wenn eine Spalte, die Sie maskiert erwarteten, noch echte Datenform hat.
  • Typ-Fehlanpassungen lassen den Branch fehlschlagen. Eine Regel, die eine Spalte matcht, deren Funktion sie nicht umschreiben kann (etwa mask_email auf einem integer), bricht die gesamte Maske ab — der Branch landet in failed und wird niemals halb-maskiert exponiert.