Zum Inhalt springen

Technik

Ein Audit-Log für Preisfreigaben entwerfen: wer was freigegeben hat, nach welcher Regel

Von Jahangir Alam · 14. Oktober 2026 · 16 Min. Lesezeit

Zuletzt geprüft
Shopify-API
2026-10
Zielgruppe
Entwickler und Agenturen, die Rabatt- und Preisfreigaben auf einer Angebotsebene für Shopify bauen oder prüfen
Umfang
Der Audit-Datensatz für Preisfreigaben neben Shopify bei API 2026-10: was Shopifys Aktivitätsprotokoll, Timelines und Event-Objekte nicht enthalten, der Datensatz Feld für Feld (Angebotsversion und der Faktor des Angebotsrabatts, Richtlinienrevision und Eingaben, Akteur, Zeit, Ergebnis einschließlich übersprungener Schritte und Overrides), Entscheidungen in einer zustandsgeprüften Transaktion schreiben, append-only per Datenbank erzwingen, was eine Hash-Kette mit Verifikation und Verankerung beweist, Audit-Log, Outbox und Aktivitätsfeed trennen, Event Sourcing, Aufbewahrung und personenbezogene Daten

Eine Freigabe ist nur dann ein Nachweis, wenn Sie Monate später zeigen können, wer entschieden hat, auf Basis welcher genauen Zahlen, nach welcher Regel in ihrer damaligen Fassung und was mit jedem Schritt passiert ist – auch mit den übersprungenen. Shopifys Logs enthalten diesen Datensatz nicht: Das Aktivitätsprotokoll, die Timelines und die API-Events tragen weder Regel noch Schwelle noch Version. Eine Angebotsebene, die Rabatte zur Freigabe weiterleitet, muss also ihr eigenes Audit-Log führen, und die Designfragen sind konkret: was der Datensatz enthält, wie er geschrieben wird, wie er append-only bleibt und was eine Hash-Kette beweist und was nicht.

Diese Seite ist dieses Design, Feld für Feld, mit vereinfachtem Code. Freigabe-Workflows behandelt, wie man eine Freigaberichtlinie aufbaut, und die Freigabematrix, was sie verlangen sollte; hier geht es um den Datensatz, den diese Entscheidungen hinterlassen. Wo QuotWay das Beispiel ist, wird es so beschrieben, wie es heute funktioniert, und die Teile, die es noch nicht kann, werden klar benannt – das sind Empfehlungen, als solche gekennzeichnet.

Die Shopify-Fakten unten wurden am 14. Oktober 2026 bei API-Version 2026-10 gegen Shopifys eigene Seiten geprüft; die Quellen stehen am Ende.

Die Frage, die das Log beantworten muss

„Wer hat diesen Rabatt freigegeben, und nach welcher Regel?“ zerfällt in fünf Fragen, und der Datensatz braucht für jede einen Teil:

  1. Worauf? Die genaue Angebotsversion und ihre Zahlen – einschließlich der Wirkung eines Rabatts auf das ganze Angebot auf jede Position.
  2. Nach welcher Regel? Die Richtlinie, die gegriffen hat, der Zweig, der gegriffen hat, die Eingaben, die ihn greifen ließen, und die Richtlinie in ihrer damaligen Fassung.
  3. Wer? Die Person oder das System, die entschieden hat, in welcher Rolle, in wessen Auftrag und wer sonst hätte entscheiden können.
  4. Wann, und in welcher Reihenfolge? Serverzeit und die Reihenfolge, in der die Entscheidungen festgeschrieben wurden.
  5. Mit welchem Ergebnis? Freigabe, Ablehnung – und die Ergebnisse, die vergessen werden: ein übersprungener Schritt und warum, ein Override mit seiner Begründung, eine Kette, die von einer neuen Version abgelöst wurde, ein Timeout.

Was Shopify protokolliert, und was nicht

Shopify hat drei Logs, und keines davon ist ein Freigabedatensatz:

  • Das Aktivitätsprotokoll des Shops zeigt laut Shopify „recent actions taken by store owners and users“ (jüngste Aktionen von Shop-Inhabern und Nutzern) – ein Produkt löschen, eine Einstellung ändern, einer App Zugriff gewähren. Es ist nur zum Ansehen, es „can't be exported or downloaded“ (kann weder exportiert noch heruntergeladen werden) und es „displays a maximum of 250 results“ (zeigt höchstens 250 Ergebnisse).
  • Timelines an jeder Bestellung, jedem Bestellentwurf, jedem Kunden und jedem Bestandstransfer, dazu das eigene Aktivitätsprotokoll eines Rabatts auf seiner Seite.
  • Das Aktivitätsprotokoll der Nutzerverwaltung, das für berechtigte Nutzer festhält, „when a user or user role is created, edited or deleted“ (wann ein Nutzer oder eine Nutzerrolle angelegt, bearbeitet oder gelöscht wird).

Über die Admin API liefern die events eines Bestellentwurfs Event-Objekte mit einer Aktion, einer Nachricht, dem Urheber, der Angabe, ob ein Nutzer oder eine App sie ausgelöst hat, und einem Zeitstempel. Kein Feld trägt eine Richtlinie, eine Schwelle, eine Begründung oder die Version, auf deren Basis entschieden wurde. Und der auditTrail, der bei API 2026-10 für kontextbezogene Preise hinzugekommen ist, erklärt, wie ein Katalogpreis zustande kam – auch er ist kein Freigabedatensatz. Zu wissen, welches Shopify-Teammitglied gehandelt hat, erfordert außerdem eingeschränkten Zugriff (Build vs. Buy enthält die Scope-Regeln), also führt eine Angebotsebene ihre eigenen Freigeber-Identitäten.

Der Datensatz, Feld für Feld

Teil Felder Die Frage, die er später beantwortet Was ohne ihn schiefgeht
Gegenstand Angebot, ID und Nummer der Angebotsversion; die Summen der Version, der Angebotsrabatt und sein Faktor; der effektive Preis jeder Position „Was genau wurde freigegeben?“ Eine spätere Version wird für die freigegebene gehalten
Regel Richtlinien-ID und Revision; der getroffene Zweig; die berechneten Eingaben (Betrag und Währung, gemischter und tiefster Positionsrabatt, Anzahlung in %, Kunden-Tags) „Unter welcher Schwelle ging das durch?“ Eine bearbeitete Richtlinie macht die Vergangenheit unerklärbar
Akteur Akteur-ID und -Typ (Team, Käufer, System); die beim Start der Kette aufgelöste Menge der Freigebenden; Delegation von und an; E-Mail bei einem externen Freigebenden; Rolle zum damaligen Zeitpunkt „Durfte diese Person entscheiden?“ Ein Rollenwechsel schreibt um, wer hätte freigeben können
Zeit Serverzeit; die Commit-Reihenfolge „Was geschah zuerst?“ Gleichzeitige Entscheidungen lassen sich nicht ordnen
Ergebnis Freigabe, Ablehnung, Überspringen mit Grund, Override mit Begründung, abgelöst, abgebrochen, Timeout „Warum lief Schritt 2 nie?“ Ein übersprungener Schritt sieht aus wie ein fehlender

Worüber entschieden wurde – und die Falle des Angebotsrabatts

Verweisen Sie mit dem Datensatz auf eine unveränderliche Angebotsversion, nie auf das Angebot: Ein gesendeter Vorschlag ändert sich nicht, und eine Änderung ist eine neue Version, die jede noch laufende Freigabekette auf der alten ablöst (Vorschläge und Versionen). Die Versions-ID allein reicht aber nicht, denn die Zahlen, die eine Regel gesehen hat, wurden berechnet.

Hier ist der Fall, der zeigt, warum – aus demselben Grund, aus dem die Summe eines Käufers nie aus den Zeilen gebildet wird. Bis zum 30. September 2026 hat QuotWay Rabattbedingungen nur an den Positionspreisen gemessen, sodass ein Vorschlag mit allen Positionen zum vollen Preis und einem großen Rabatt auf das ganze Angebot keine Rabattfreigabe auslöste. Seitdem wird jede Position an dem gemessen, was der Käufer tatsächlich zahlt – ihrem Preis nach ihrem Anteil am Angebotsrabatt:

// Factor applied to every line: the buyer pays (subtotal - orderDiscount) / subtotal of each price.
function orderDiscountFactor(subtotal: Decimal, orderDiscount: Decimal): Decimal {
  if (subtotal.lte(0) || orderDiscount.lte(0)) return new Decimal(1);
  if (orderDiscount.gte(subtotal)) return new Decimal(0);
  return subtotal.minus(orderDiscount).div(subtotal);
}

function approvalInputs(version: VersionSnapshot) {
  const factor = orderDiscountFactor(version.subtotal, version.orderDiscount);
  let catalogTotal = new Decimal(0), paidTotal = new Decimal(0);
  let deepestLinePct: number | undefined;
  for (const line of version.lines) {
    const effective = line.finalPrice.times(factor);          // what the buyer actually pays
    catalogTotal = catalogTotal.plus(line.catalogPrice.times(line.quantity));
    paidTotal = paidTotal.plus(line.finalPrice.times(line.quantity));
    const base = line.baselinePrice ?? line.catalogPrice;
    if (base.gt(0)) {
      const pct = base.minus(effective).div(base).times(100).toNumber();
      deepestLinePct = Math.max(deepestLinePct ?? -Infinity, pct);
    }
  }
  const blendedPct = catalogTotal.isZero()
    ? undefined
    : catalogTotal.minus(paidTotal.times(factor)).div(catalogTotal).times(100).toNumber();
  return { factor, blendedPct, deepestLinePct };
}

Ein Datensatz, der nur die Positionspreise speichert, würde eine Kette zeigen, die „nicht hätte laufen dürfen“ – oder, vor der Änderung, einen Angebotsrabatt von 25 Prozent, der ohne Freigabe und ohne sichtbaren Grund durchging. Speichern Sie die berechneten Eingaben – den Faktor, den gemischten und den tiefsten Positionsrabatt – an der Kette, neben der Versions-ID. Das ist eine Empfehlung; QuotWay speichert heute die Version und einen kurzen Grund, nicht die Eingaben.

Welche Regel gegriffen hat, und welche Version davon

Eine Richtlinie, die an Ort und Stelle bearbeitet wird, löscht die Antwort auf „unter welcher Schwelle?“. Die Lösung ist eine Revision: bei jeder Bearbeitung hochzählen, alte Revisionen behalten und die Revision – oder eine Momentaufnahme der getroffenen Regel – beim Start der Kette an die Kette schreiben. Eine empfohlene Form, nicht QuotWays aktuelles Schema:

-- On the approval chain, written once when it starts:
policy_id         text   not null,
policy_revision   int    not null,   -- bumped on every policy edit; old revisions kept
matched_rule      jsonb  not null,   -- the scope and conditions as they were
inputs            jsonb  not null,   -- amount, currency, rate, blended %, deepest line %,
                                     -- order-discount factor, deposit %, customer tags
step_skips        jsonb  not null    -- [{ step, reason: "rule did not match" | "missing: customerTags" }]

QuotWay bearbeitet Richtlinien heute an Ort und Stelle und speichert die Richtlinien-ID plus einen kurzen Grund, der bei Wertregeln Betrag und Währung nennt; die Revision, die Eingaben und den Grund jedes übersprungenen Schritts festzuhalten, ist dort der nächste Schritt.

Wer entschieden hat

Lösen Sie die Freigebenden beim Start der Kette in konkrete Personen auf, damit ein späterer Rollenwechsel nicht ändern kann, wer hätte entscheiden können – QuotWay tut das. Halten Sie jede Entscheidung mit ID und Typ des Akteurs fest: Team, ein Freigebender auf Käuferseite (bei einem externen Freigebenden die E-Mail, unter der er gehandelt hat) oder system für eine automatische Entscheidung bei einem Timeout. Halten Sie eine Delegation als eigene Zeile fest, mit von wem und an wen. Und speichern Sie die Rolle des Freigebenden zum Entscheidungszeitpunkt, denn der Datensatz des Teammitglieds wird sich ändern (Team und Rollen).

Das Ergebnis, einschließlich der vergessenen

Freigabe und Ablehnung sind einfach. Der Datensatz braucht außerdem: einen Schritt, der übersprungen wurde, weil seine Bedingung nicht zutraf, mit dem Grund; einen Override, mit der Person und ihrer Begründung; eine Kette, die abgelöst wurde, weil eine neue Version gesendet wurde; eine abgebrochene Kette; und eine Entscheidung durch Timeout, mit dem System als Akteur und dem Grund. Ein übersprungener Schritt ohne Grund sieht genauso aus wie ein Schritt, der nie gelaufen ist.

Schreiben: eine Transaktion, an den Zustand gebunden

Zwei Freigebende können im selben Moment auf „Freigeben“ drücken. Schreiben Sie jede Entscheidung als neue Zeile und bewegen Sie den Schritt nur, wenn er noch aktiv ist – so landet genau eine Entscheidung, und die andere bekommt einen Konflikt –, und erledigen Sie den nächsten Schritt der Kette und das abschließende Event in derselben Transaktion. So schreibt QuotWay eine Entscheidung, vereinfacht:

await db.$transaction(async (tx) => {
  const step = await tx.approvalSteps.findUnique({ where: { id: stepId } });
  if (step.state !== "ACTIVE") throw new StepNotActive();
  if (actor.type !== "SYSTEM" && !step.approvers.includes(actor.id)
      && !(actor.email && step.approvers.includes(actor.email))
      && step.delegateId !== actor.id) throw new NotAnApprover();

  // 1. The decision is a new row, never an update.
  await tx.approvalDecisions.create({ data: {
    chainId: step.chainId, stepId, decision, rationale,
    actorId: actor.id, actorType: actor.type, actorEmail: actor.email,
  }});

  // 2. Move the step only if nobody beat us to it - 0 rows means a concurrent decision.
  await tx.approvalSteps.update({
    where: { id: stepId, state: "ACTIVE" },
    data: { state: next(decision), resolvedAt: new Date() },
  });

  // 3. Advance the chain; on a final verdict, append the quote event - same transaction.
  const outcome = advance(await tx.approvalSteps.findMany({ where: { chainId: step.chainId } }));
  if (outcome.terminal) await appendEvent(tx, { quoteId, type: verdictEvent(outcome), chainId: step.chainId });
});
// After commit: notify the next approvers, send the released proposal, dispatch webhooks.

Seiteneffekte – E-Mails, der freigegebene Vorschlag, Webhooks – passieren nach dem Commit, über eine Outbox, die in derselben Transaktion geschrieben wird. Der Beitrag zur idempotenten Umwandlung behandelt dieses Muster.

Append-only ist eine Eigenschaft der Datenbank, keine Konvention

„Die App aktualisiert nie eine Entscheidung“ ist eine Konvention. Machen Sie daraus eine Eigenschaft:

  • Entziehen Sie der Rolle, mit der sich die Anwendung verbindet, UPDATE und DELETE auf den Audit-Tabellen. In PostgreSQL wird der Tabelleneigentümer laut Dokumentation „is always treated as holding all grant options“ (immer so behandelt, als hielte er alle Grant-Optionen), also darf sich die App nicht als Eigentümer verbinden. Oder fügen Sie einen Trigger hinzu, der bei Update oder Delete einen Fehler wirft.
  • Keine Kaskaden in die Audit-Tabellen. Ein Fremdschlüssel mit ON DELETE CASCADE von einer Richtlinie oder einem Schritt in die Entscheidungen ist ein Löschen, das die Anwendung nie geschrieben hat. Das Löschen einer Richtlinie oder das Entfernen eines Schritts daraus darf vergangene Entscheidungen nicht mitnehmen – archivieren Sie die Richtlinie stattdessen.
  • Korrekturen sind neue Zeilen. Auf eine falsche Entscheidung antwortet eine kompensierende Entscheidung, nie eine Bearbeitung.

QuotWay schreibt Entscheidungen als neue Zeilen und bearbeitet sie nie, aber heute können seine Entscheidungsdatensätze noch zusammen mit der Richtlinie oder dem Schritt entfernt werden, zu dem sie gehören. Diese Löschungen zu unterbinden, ist die Korrektur, die es braucht; bis dahin bezeichnet es die Historie nicht als append-only.

Hash-Ketten: was sie beweisen und was nicht

Eine Hash-Kette speichert in jeder Zeile den Hash der vorherigen Zeile, sodass das Bearbeiten oder Löschen einer Zeile jeden späteren Hash bricht. QuotWay schreibt seine Angebots-Events auf diese Weise, mit der Zeile der Integrations-Outbox in derselben Transaktion:

async function appendEvent(tx: Tx, e: EventInput) {
  const prev = await tx.auditEvents.findFirst({
    where: { quoteId: e.quoteId }, orderBy: { createdAt: "desc" }, select: { hash: true },
  });
  const createdAt = new Date();
  const hash = sha256((prev?.hash ?? "") + "|" + canonicalJson({ ...e, createdAt: createdAt.toISOString() }));
  const row = await tx.auditEvents.create({ data: { ...e, createdAt, prevHash: prev?.hash ?? null, hash } });
  await tx.outbox.create({ data: toPublicEvent(row) });   // commits or rolls back with the event
  return row;
}
// canonicalJson = JSON with object keys sorted recursively, so the hash is reproducible.

Was sie beweist, hängt von drei weiteren Dingen ab, und keines davon gibt es umsonst. Jemand muss die Kette verifizieren – jeden Hash der Reihe nach neu berechnen. Der neueste Hash muss irgendwo verankert sein, wo der Schreibende ihn nicht umschreiben kann, denn wer die ganze Tabelle umschreiben kann, kann auch die ganze Kette neu berechnen; NISTs Leitfaden zum Log-Management empfiehlt, Digests sicher zu speichern, zum Beispiel „on read-only media“ (auf schreibgeschützten Medien). Und Anhänge müssen serialisiert werden, sonst können zwei Schreibende die Kette verzweigen. Eine empfohlene Form – kein QuotWay-Code:

// Serialise appends per quote so two writers can't fork the chain:
await tx.$executeRaw`SELECT pg_advisory_xact_lock(hashtext(${quoteId}))`;

// Verify: recompute every hash in order; the first mismatch is where the record changed.
function verify(rows: AuditRow[]): { ok: true } | { ok: false; at: string } {
  let prev = "";
  for (const r of rows) {                 // ordered by a per-quote sequence, not by timestamp
    if ((r.prevHash ?? "") !== prev) return { ok: false, at: r.id };
    if (sha256(prev + "|" + canonicalJson(fieldsOf(r))) !== r.hash) return { ok: false, at: r.id };
    prev = r.hash;
  }
  return { ok: true };
}
// Anchor: copy the latest hash per quote to storage the app can't rewrite (a write-once bucket).

QuotWays Events tragen den Hash des Events davor; das Verifizieren und Verankern der Kette ist noch nicht gebaut, deshalb bezeichnet es den Datensatz nicht als manipulationssicher. Die Logging-Empfehlungen von OWASP sagen dasselbe in einer Zeile: „Build in tamper detection so you know if a record has been modified or deleted“ (Bauen Sie Manipulationserkennung ein, damit Sie wissen, ob ein Datensatz verändert oder gelöscht wurde) – und Erkennung braucht einen Verifizierer.

Ein zweites, engeres Siegel lohnt sich: QuotWay speichert einen Annahme-Hash über die angenommenen Positionen – die Versions-ID und für jede Position ID, Menge, Stückpreis und Summe – und zeigt ihn auf dem Umwandlungsbildschirm, der Shopify-Bestellkarte und dem Bestätigungs-PDF, sodass sich die Bestellung genau auf das zurückführen lässt, was der Käufer angenommen hat.

Drei Logs, drei Aufgaben

Audit-Log Integrations-Outbox Aktivitätsfeed
Leser Ein Prüfer, ein Streitfall, Sie in einem Jahr Andere Systeme (ERP, CRM, Webhooks) Menschen auf einem Dashboard
Inhalt Jede Entscheidung, vollständig Ergebnisse, zur Zustellung Eine kuratierte Auswahl
Personenbezogene Daten Nur, was die Entscheidung braucht Keine Anzeigenamen
Aufbewahrung So lange wie das Angebot, das sie autorisiert Bis zur Zustellung, dann kurz Kurz
Veränderbarkeit Append-only Einmal geschrieben, zugestellt, abgelaufen Eine Projektion – frei neu aufbaubar

OWASP rät, Audit- und Transaktionsspuren getrennt von anderem Logging zu halten, und die Tabelle zeigt, warum: Ein Speicher kann nicht drei Leser mit drei Aufbewahrungsfristen bedienen. Die Angebotsarchitektur legt das Prüfprotokoll aus demselben Grund in die Angebotsebene. In QuotWay trägt die Outbox nur Freigabe-Ergebnisse und keine personenbezogenen Daten, und der Aktivitätsfeed im Dashboard ist eine kuratierte Liste, die keine Freigabe-Events enthält.

Event Sourcing oder ein Audit-Log?

Event Sourcing speichert „the full series of actions taken on an object in an append-only store“ (die vollständige Folge der Aktionen an einem Objekt in einem append-only Speicher) und baut den Zustand daraus wieder auf. Microsofts Leitfaden nennt es „a complex pattern that introduces significant trade-offs“ (ein komplexes Muster mit erheblichen Zielkonflikten) und merkt an: „for most systems... traditional data management is sufficient“ (für die meisten Systeme genügt herkömmliche Datenhaltung); Martin Fowlers ursprüngliche Beschreibung sagt, ein Audit-Log sei ein Nebenprodukt, das man „could also do... with more regular logging mechanisms“ (auch mit gewöhnlicheren Logging-Mechanismen umsetzen könnte). Für „wer hat das freigegeben, nach welcher Regel“ genügt eine append-only Entscheidungstabelle neben gewöhnlichen Tabellen. Eine Angebotsebene neben Shopify eignet sich auch schlecht für vollständiges Replay: Das Wiederabspielen von Events würde Shopify erneut berühren, und externe Systeme „don't know the difference between real processing and replays“ (kennen den Unterschied zwischen echter Verarbeitung und Replays nicht).

Aufbewahrung und personenbezogene Daten

Minimieren Sie beim Schreiben: Eine append-only Zeile lässt sich später nicht bereinigen. OWASP zählt Sitzungskennungen, Access Tokens und sensible personenbezogene Daten zu dem, was nicht geloggt werden sollte, und NIST rät: „avoid recording unneeded sensitive data“ (keine unnötigen sensiblen Daten aufzeichnen). Führen Sie Personen über ihre ID und ihre Kontaktdaten an anderer Stelle – Microsofts Leitfaden nennt das, oder das Verschlüsseln personenbezogener Daten mit einem personenbezogenen Schlüssel, den Sie vernichten können, als Antwort auf Löschanfragen in einem append-only Speicher. Bewahren Sie die Entscheidungen so lange auf wie das Angebot, das sie autorisieren; die Frist ergibt sich aus Ihren eigenen Pflichten, und wir nennen keine. Die Checkliste für das Security-Review enthält die Fragen, die Sie einem Anbieter zu Logs und personenbezogenen Daten stellen sollten.

Die Frage Monate später beantworten

„Wer hat die 18 Prozent auf Angebot QW-1042, Version 3, freigegeben, und nach welcher Regel?“ Mit dem Datensatz oben:

  1. Finden Sie die Kette an Version 3 – nicht am Angebot, das spätere Versionen haben kann.
  2. Lesen Sie die Regel der Kette: die Richtlinie und ihre Revision und die Eingaben, auf die sie zutraf – ein gemischter Rabatt von 18,4 Prozent einschließlich eines Faktors von 0,95 für den Angebotsrabatt, gegen eine Schwelle von 15 Prozent.
  3. Lesen Sie die Entscheidungen in Commit-Reihenfolge: Schritt 1 um 10:02 von einer Vertriebsleitung freigegeben; Schritt 2 übersprungen, weil seine Bedingung (Anzahlung unter 20 Prozent) nicht zutraf; Schritt 3 von der Freigabeperson in der Finanzabteilung freigegeben, an die er delegiert war.
  4. Prüfen Sie, ob der Annahme-Hash an der Bestellung zu den angenommenen Positionen von Version 3 passt.

Jetzt ändern Sie eine Sache: Die Schwelle der Richtlinie wurde letzten Monat auf 20 Prozent angehoben. Ohne die Revision an der Kette liest sich Schritt 2 als „würde heute nicht auslösen“, und niemand kann sagen, warum er damals lief. Mit ihr ist die Antwort eine Zeile.

Eine Checkliste für Ihren eigenen Aufbau

  • Jede Entscheidung ist eine neue Zeile; nichts aktualisiert oder löscht eine.
  • Die Datenbankrolle der App kann auf den Audit-Tabellen kein UPDATE oder DELETE ausführen, und nichts kaskadiert in sie hinein.
  • Jede Kette verweist auf eine unveränderliche Angebotsversion, nicht auf das Angebot.
  • Jede Kette speichert die Richtlinienrevision (oder eine Momentaufnahme der Regel) und die berechneten Eingaben – einschließlich des Faktors für den Angebotsrabatt.
  • Freigebende werden beim Start der Kette aufgelöst; die Rolle zum Entscheidungszeitpunkt wird gespeichert.
  • Eine Delegation ist eine Zeile mit von und an; externe Freigebende werden mit der Identität festgehalten, unter der sie gehandelt haben.
  • Übersprungene Schritte tragen ihren Grund; Overrides tragen die Person und die Begründung; Timeouts werden mit dem System als Akteur festgehalten.
  • Zwei gleichzeitige Entscheidungen: Genau eine landet.
  • Seiteneffekte laufen nach dem Commit, über eine Outbox in derselben Transaktion.
  • Wenn Sie eine Hash-Kette führen: Anhänge sind serialisiert, ein Verifizierer läuft, und der neueste Hash ist außerhalb der Reichweite des Schreibenden verankert.
  • Audit-Log, Outbox und Aktivitätsfeed sind getrennte Speicher mit getrennter Aufbewahrung.
  • Keine Tokens, Sitzungs-IDs oder personenbezogenen Daten, die die Entscheidung nicht braucht.

Sie bewerten eine App, statt selbst zu bauen? Dieselbe Liste funktioniert als Fragenkatalog; die Bewertungs-Checkliste enthält den Audit-Log-Test, und Build vs. Buy rechnet vor, was dieser Teil im Eigenbau kostet.

Wo das in QuotWay steckt

Freigabe-Workflows für Händler und Freigabeketten auf Käuferseite gibt es ab Professional, und sie gelten für Angebote; parallele und bedingte Schritte, Timeouts, Eskalation und Delegation gibt es mit Enterprise (Freigabe-Workflows, Tarife). Eine Kette gehört zu einer Angebotsversion, und eine neue Version löst sie ab. Freigebende werden beim Start der Kette aufgelöst; jede Entscheidung wird als neue Zeile mit dem Akteur, seinem Typ und der Begründung geschrieben, und von zwei gleichzeitigen Entscheidungen landet eine. Angebots-Events tragen den Hash des Events davor, und der Annahme-Hash wird auf der Shopify-Bestellkarte angezeigt. Angebotsdatensätze, einschließlich ihrer Events und Annahme-Hashes, werden standardmäßig 7 Jahre aufbewahrt. Wie die Durchsetzung von Freigaben funktioniert behandelt, was eine Freigabe blockiert. Seit dem 30. September 2026 messen Rabattbedingungen jede Position an ihrem Preis nach ihrem Anteil am Angebotsrabatt. Freigabe-Webhooks der Enterprise-API tragen nur die Ergebnisse von Ketten, ohne personenbezogene Daten (die Freigabefunktion).

Häufige Fragen

Was sollte ein Audit-Log für Preisfreigaben festhalten?

Die Angebotsversion und ihre Zahlen, die Regel und ihre Revision mit den Eingaben, die sie greifen ließen, wer entschieden hat und in wessen Auftrag, wann, und das Ergebnis – einschließlich übersprungener Schritte mit ihrem Grund und Overrides mit ihrer Begründung.

Hat Shopify ein Audit-Log für Rabattfreigaben?

Nein. Shopify hat ein Aktivitätsprotokoll des Shops, Timelines an Bestellungen und Bestellentwürfen, das eigene Aktivitätsprotokoll eines Rabatts und ein Protokoll der Nutzerverwaltung. Keines davon speichert eine Regel, eine Schwelle oder die Version, auf deren Basis entschieden wurde.

Sollte ein Audit-Log unveränderlich sein?

Append-only: Korrekturen sind neue Zeilen. Erzwingen Sie das in der Datenbank – entziehen Sie der Rolle der Anwendung Update und Delete oder nutzen Sie einen Trigger – und halten Sie kaskadierende Löschungen aus den Audit-Tabellen heraus.

Reicht eine Hash-Kette, um ein Audit-Log manipulationssicher zu machen?

Nicht allein. Sie zeigt Manipulation nur, wenn jemand die Kette verifiziert und der neueste Hash dort gespeichert ist, wo der Schreibende ihn nicht ändern kann; andernfalls kann jeder, der die Tabelle umschreiben kann, jeden Hash neu berechnen.

Event Sourcing oder ein Audit-Log?

Ein Audit-Log, es sei denn, Sie müssen den Zustand aus der Historie wieder aufbauen. Event Sourcing bringt erhebliche Zielkonflikte mit sich, und das Wiederabspielen von Events verträgt sich nicht mit externen Systemen wie Shopify.

Zählt ein Rabatt auf das ganze Angebot für die Rabattfreigabe?

Das sollte er: Messen Sie jede Position an ihrem Preis nach ihrem Anteil am Angebotsrabatt und speichern Sie den verwendeten Faktor. QuotWay tut das seit dem 30. September 2026.

Was passiert mit dem Datensatz, wenn sich die Freigaberichtlinie später ändert?

Hat die Kette nur die Richtlinien-ID gespeichert, können Sie nicht mehr erkennen, welche Schwelle galt. Speichern Sie beim Start der Kette die Revision der Richtlinie oder eine Momentaufnahme der getroffenen Regel.

Wie lange sollten Freigabedatensätze aufbewahrt werden?

So lange wie das Angebot, das sie autorisieren, festgelegt durch Ihre eigenen Pflichten. Wir nennen keine gesetzliche Frist.

Was ist der Unterschied zwischen einem Audit-Log und einem Aktivitätsfeed?

Der Aktivitätsfeed ist eine kuratierte, lesbare Zusammenfassung für ein Dashboard. Das Audit-Log ist der vollständige Datensatz, der als Nachweis aufbewahrt wird. Sie haben unterschiedliche Leser, Inhalte und Aufbewahrungsfristen, also halten Sie sie in getrennten Speichern.

Quellen

Gelesen am 14. Oktober 2026:

Das Verhalten von QuotWay ist aus dem Quellcode der App beschrieben, gelesen am 14. Oktober 2026; der Code ist vereinfacht, interne Bezeichner sind entfernt.

Verwandte Artikel

So funktioniert QuotWay in Ihrem Shop.

Wir möchten Analyse-Cookies setzen, um zu verstehen, wie die Website genutzt wird. Sie sind nicht erforderlich – eine Ablehnung ändert nichts an der Funktion der Website, und Sie können Ihre Entscheidung jederzeit ändern auf unserer Datenschutzseite.