Memories / Dokumentation

Auf dieser Seite

Autorisierungs-Center

Selbstverwaltete Konten und SMTP

Übergeben Sie im gehosteten Modus --auth-config /etc/memories-center/auth.toml (oder setzen Sie MEMORIES_CENTER_AUTH_CONFIG). Siehe deploy/center/auth.example.toml. Ohne Auth-Konfiguration behält Center sein ausschließlich tokenbasiertes Verhalten bei. Mit einer Konfiguration wird die Kontoanmeldung aktiviert; die Registrierung ist standardmäßig deaktiviert und auf den E-Mail-Modus eingestellt.

registration_enabled = true
registration_mode = "email" # or "username"
max_accounts = 10000

[smtp]
host = "smtp.example.com"
port = 587
tls = "starttls" # required STARTTLS; "tls" for implicit TLS, commonly port 465
from = "Memories <noreply@example.com>"
username = "smtp-user"
password_env = "MEMORIES_CENTER_SMTP_PASSWORD"

SMTP-Passwörter werden aus der angegebenen Umgebungsvariablen gelesen. Bewahren Sie diese Variable in der geschützten Dienstumgebung auf, niemals in Argumenten, URLs, der Versionsverwaltung oder der Browserkonfiguration. Ein Relay ohne Authentifizierung kann username weglassen; TLS mit Zertifikatsprüfung bleibt verpflichtend. Eine ungültige Konfiguration verhindert den Start. Fehlendes SMTP deaktiviert die E-Mail-Registrierung; ein Transportfehler gibt 503 zurück und erstellt kein Konto. Die öffentliche Konfigurationsantwort enthält niemals SMTP-Einstellungen.

Setzen Sie registration_enabled = false, um neue Registrierungen zu schließen, ohne bestehende Konten zu deaktivieren. Setzen Sie registration_mode = "username" für eine Registrierung mit Benutzername/Passwort ohne E-Mail; lassen Sie [smtp] weg, wenn es nicht verwendet wird. Starten Sie nach Änderungen der Einstellungen neu. Bestehende Konten beider Arten können sich nach einem Moduswechsel weiterhin anmelden.

Öffentliche Endpunkte (JSON, maximaler Anfrageinhalt 4 KiB):

Endpunkt Inhalt / Verhalten
GET /v1/auth/config Verfügbarkeit der Anmeldung, Verfügbarkeit/Modus der Registrierung, Mindestlänge des Passworts, Sitzungsdauer
POST /v1/auth/register E-Mail-Modus: {identity,locale?} sendet einen Code. Benutzernamenmodus: {identity,password} erstellt ein Konto
POST /v1/auth/verify {identity,code,password} weist die Inhaberschaft des Postfachs nach und erstellt ein Konto
POST /v1/auth/login {identity,password} gibt eine auf einen Berechtigungsumfang beschränkte Bearer-Berechtigung für eine Stunde zurück
POST /v1/auth/logout Bearer-Autorisierung; widerruft diese ablaufende Berechtigung und ihre Nachfolger

Bei E-Mail-Adressen und Benutzernamen werden äußere Leerzeichen entfernt und die ASCII-Groß-/Kleinschreibung vereinheitlicht. Die E-Mail-Registrierung akzeptiert ausschließlich ASCII-Postfachadressen. Benutzernamen bestehen aus 3-64 ASCII-Buchstaben, Ziffern, Bindestrichen oder Unterstrichen. Passwörter umfassen 12-256 UTF-8-Bytes und werden als gesalzene Argon2id-PHC-Datensätze gespeichert (64 MiB, 3 Durchläufe, Parallelität 1). Die Hash-Berechnung erfolgt außerhalb der Tresorsperre mit höchstens zwei gleichzeitigen Workern. Benutzer können bei der Registrierung keinen Tresor, Berechtigungsumfang oder keine Rolle wählen: Jeder erhält einen zufälligen unabhängigen gehosteten Tresor.

Verifizierungscodes enthalten 256 zufällige Bits, laufen nach 15 Minuten ab und sind nur einmal verwendbar. Im Serverspeicher werden nur Hashes gehalten; ein Neustart macht ausstehende Codes ungültig. Wiederholte Sendeanfragen innerhalb dieses Zeitfensters geben dieselbe allgemeine Annahmebestätigung zurück, ohne eine weitere E-Mail zu senden; versuchen Sie es nach Ablauf erneut. Passwörter werden bei der Verifizierung gewählt, nicht beim Anfordern der E-Mail. Ausstehende Registrierungen sind auf 1024 begrenzt. Das optionale locale wählt Betreff und Text der E-Mail: en, zh-CN, zh-TW, ja, fr, de oder es. Regionale Varianten verwenden ihre Basissprache; zh-Hant, zh-HK und zh-MO wählen traditionelles Chinesisch, während ein ausdrückliches zh-Hans vereinfachtes Chinesisch wählt. Fehlende oder nicht unterstützte Gebietsschemas fallen für bestehende API-Clients auf Englisch zurück. Das Gebietsschema gilt pro Anfrage und wird nicht im Konto gespeichert. Ein Sprachwechsel während einer ausstehenden Verifizierung sendet keine weitere E-Mail und umgeht nicht die Ratenbegrenzung. Er ändert weder die Identitätsnormalisierung noch die Verifizierung. Authentifizierungsversuche unterliegen einer globalen Obergrenze von 60/Minute und Grenzen pro Identität von 3 Registrierungsanfragen oder 10 Anmelde-/Verifizierungsversuchen pro 15 Minuten. Diese prozesslokalen Grenzen werden bei einem Neustart zurückgesetzt und können bei einem Angriff zu einer Dienstverweigerung führen; verwenden Sie bei Bereitstellungen mit höherem Volumen einen vorgeschalteten Dienst zur Missbrauchsbekämpfung. Sie vertrauen keinen vom Client gelieferten IP-Headern.

Bestehende dauerhafte Mitgliedstoken werden weiterhin unterstützt. Das Format members.json enthält jetzt optionale Kontoanmeldedaten: Schützen Sie seine Sicherungen wie Passwortdatenbanken. Alte Center-Builds können Kontodatensätze nicht lesen; ein Rollback nach der Registrierung erfordert eine kompatible Binärdatei oder eine passende Datensicherung von vor dem Upgrade (wobei spätere Daten verworfen würden). Passwortzurücksetzung, Postfachänderungen und Wiederherstellung per E-Mail sind nicht implementiert. Das Löschen eines Mitglieds durch den Administrator deaktiviert die Anmeldung und macht Sitzungen ungültig.

Ein Center ist eine externe Steuerungsebene für die Autorisierung, die Registrierungs- und Fähigkeitstickets an Memories-Endpunkte verteilt (CLI, Desktop-Daemon, Mobilgeräte und andere Clients mit gemeinsamer Konfiguration).

Gehostete Center unterstützen auch Memories Web, einen Browserclient für Erinnerungen, Karten und Dateien. Neue Builds stellen ihn unter /app/ bereit. Um eine Verbindung von der öffentlichen Website herzustellen, erlauben Sie ausdrücklich --web-origin https://memories.ivjn.us (oder MEMORIES_CENTER_WEB_ORIGINS). Bei Verwendung derselben Origin ist keine CORS-Einstellung erforderlich; die bestehende Mitglieds-/Berechtigungsautorisierung gilt weiterhin. Einrichtung und Grenzen werden in der Anleitung beschrieben.

Regeln

  1. Endpunkte können ein oder mehrere Center in config.toml konfigurieren ([[centers]]).
  2. Wenn irgendein Center konfiguriert ist, wird der Endpunkt vom Center verwaltet: - Lokales Selbst-Bootstrapping ist verboten (memories init / restore). - Die Geräteerstellung verwendet ein vom Center signiertes Bootstrap-Ticket (memories center enroll). - Das lokale Ausstellen von MCP-Berechtigungen ist verboten; importieren Sie stattdessen vom Center signierte Berechtigungstickets.
  3. Das kryptografische Entsperren des Gerätetresors bleibt lokal (Gerätepasswort). Ein ausschließlich ticketbasiertes Center erhält niemals Gerätetresorschlüssel oder Geheimnisse im Klartext. Der optionale gehostete Modus besitzt stattdessen einen separaten Servertresor mit einem vom Betreiber gehaltenen Schlüssel (siehe unten). Ein optionales signiertes Entsperrticket autorisiert ein lokales Entsperren mit Passwort; es enthält weder das Passwort noch Geräteschlüssel.
  4. Mehrere Center können aufgeführt werden; ein Ticket muss anhand von id und public_key des Centers verifiziert werden, das es ausgestellt hat.
  5. Listener-Token, Signiergeheimnisse des Centers und Administratortoken werden niemals in TOML gespeichert.

Berechtigungsumfänge

MCP-Berechtigungstickets enthalten einen ausdrücklichen scope (Berechtigungsstufe). Bezeichner im Übertragungsformat / in der Konfiguration verwenden snake_case; CLI und HTTP akzeptieren auch menschenlesbare Aliasse.

Umfang Aliasse (Beispiele) Erlaubt
allow_all allow all, all, full Vollständiger Satz von Operationen, die diese Berechtigungsschnittstelle autorisieren kann (heute: Lesen + Erstellen/Aktualisieren + Löschen gewöhnlicher Assets; reserviert für zukünftige erhöhte, durch das Center kontrollierte Fähigkeiten auf derselben Schnittstelle)
read r Auflisten / Abrufen / Suchen / Retrieval / RAG-Lesen / gewöhnlicher Graph — keine Änderungen
write w Nur Erstellen/Aktualisieren gewöhnlicher Erinnerungen und Karten (kein Lesen, kein Löschen)
read_write read+write, rw Lesen + Erstellen/Aktualisieren
read_write_delete read+write+delete, rwd Lesen + Erstellen/Aktualisieren + Löschen gewöhnlicher Erinnerungen/Karten

Hinweise:

  • write ist absichtlich auf das Schreiben beschränkt, damit Center Agenten mit eng begrenzten Berechtigungen ausstellen können. Bevorzugen Sie read_write, wenn der Agent auch suchen oder lesen muss.
  • Löschen umfasst gewöhnliche Löschungen (nicht privat, Erinnerung/Karte), die für MCP-Aufrufer durchgesetzt werden; das Löschen privater Inhalte/Anmeldedaten erfordert weiterhin eine lokale Rechteerhöhung und bleibt außerhalb der MCP-Berechtigungen.
  • Alte Tickets, die nur das alte Feld write: bool enthalten (kein scope): write: false → read, write: true → read_write.
  • Neue Tickets ohne ausdrücklichen Umfang erhalten bei der Ausstellung standardmäßig read (CLI / memories-center HTTP).
  • Diese Einschränkungen für gewöhnliche Assets/Rechteerhöhung beschreiben Daemon-MCP, nicht gehostete Tresor-RPCs. Gehostete Berechtigungen umfassen auch private Karten, Anhänge und geschützte Profile; ihre genauen Befugnisse werden unten beschrieben. Diese Funktion erhöht keine Daemon-MCP-Rechte, auch wenn ihr Umfang allow_all ist.

Der lokale Ticketimport prüft jetzt die Admin/Owner-Mitgliedschaft und die Rollen-/Umfangsobergrenze, nicht nur Schreibzugriff, und erfordert keine Rechteerhöhung im Terminal. Siehe Tresorautorisierung für lokales Delegations-, Anfrage-, Zugriffs- und Audit-Verhalten sowie die schrittweise Center/CLI/MCP-Einführung.

Einordnung im Bedrohungsmodell

Aspekt Verhalten
Geräteregistrierung Center entscheidet, welche Geräte einen Store initialisieren dürfen
MCP- / Agentenberechtigungen Center stellt zeitlich begrenzte Berechtigungstickets mit Umfängen aus; Endpunkte importieren sie
Vertraulichkeit des Gerätetresors Weiterhin Argon2 + lokale Store-Verschlüsselung; ein ausschließlich ticketbasiertes Center ist eine Richtlinieninstanz, keine Schlüsselhinterlegung
Vertraulichkeit des gehosteten Tresors Serverseitig verschlüsselter Store; Hostbetreiber halten das Passwort und können sämtlichen gehosteten Klartext lesen; keine Ende-zu-Ende-Verschlüsselung
Kompromittierter Center-Signierschlüssel Angreifer kann Geräte registrieren / Berechtigungen für diese Center-ID ausstellen — Schlüssel rotieren und veralteten public_key von Endpunkten entfernen
Kompromittierter Center-Administrator Kann zeitlich begrenzte Geräteentsperrtickets ausstellen, den gehosteten Store sperren und gehostete Mitglieder anlegen/aktualisieren/entfernen; kann einen ausschließlich ticketbasierten Geräte-Store ohne dessen lokales Passwort nicht entschlüsseln
Kompromittierter Endpunkt Hält Tresormaterial nach dem Entsperren; Center kann bereits auf der Festplatte befindlichen Chiffretext nicht widerrufen (wie heute)

Endpunktkonfiguration

[[centers]]
id = "corp"
url = "https://center.example.com"
public_key = "…"   # from `memories center public-key` or memories-center /v1/public-key
mode = "ticket"    # default: enrollment/grants/unlock tickets only

[[centers]]
id = "team"
url = "http://127.0.0.1:9191"   # loopback http allowed for local Center
public_key = "…"

Center-URLs außerhalb von Loopback müssen https:// verwenden. URLs für SaaS-Anbindung/direkte CLI-Aufrufe dürfen nur Origins sein, ohne Benutzerinformationen, Pfade, Abfragen oder Fragmente; die Konfiguration im Ticketmodus behält die bestehende URL-Kompatibilität bei.

SaaS-Clientanbindung

Setzen Sie genau ein konfiguriertes Center auf mode = "saas", um dessen gehostetes Inhaltsbackend anstelle eines parallelen lokalen Tresors zu verwenden:

[[centers]]
id = "corp"
url = "https://center.example.com"
public_key = "…"
mode = "saas"

Speisen Sie MEMORIES_CENTER_TOKEN="…" in die Daemon-Umgebung ein: Dies ist ein gehostetes Mitglied, eine statische Berechtigung oder ein zeitlich begrenzter Zugriffs-Bearer, niemals das Administratortoken. Starten Sie memories daemon mit dieser Konfiguration. Inhaltsanfragen des Daemons werden mit dem TLS/HTTP-Client aus Core außerhalb der lokalen Schreibsperre an /v1/rpc dieses Centers gesendet. Nicht unterstützte gehostete Operationen werden sicher abgewiesen; sie fallen nicht auf lokalen Speicher zurück. Verwenden Sie den gebundenen Tresornamen (zum Beispiel default) und die von gehosteten RPCs zurückgegebenen kanonischen Asset-IDs. Lokaler Status/Center-Auflistung bleiben lokal. Init, Restore, lokale MCP-Ausstellung und lokale Registrierung bleiben verboten; eine alte lokale Datenbank ist nicht das Inhaltsbackend für diese Anbindung. Inhalte und Berechtigungen gehören zu den Berechtigungen/Mitgliedern des gehosteten Centers. Andere ausschließlich ticketbasierte Center können daneben bestehen.

Die konfigurierte Daemon-URL ist maßgeblich (keine URL-Überschreibung durch die Umgebung). Der Daemon-Bearer wird von authentifizierten Daemon-Clients gemeinsam genutzt; schützen Sie den IPC-Zugriff und jedes Daemon-Listener-/Relay-Token als Delegation der Befugnisse dieses Mitglieds. Lokale MCP-Fähigkeiten werden nicht mit dem Daemon-Bearer weitergeleitet; verwenden Sie stattdessen ein separat eingeschränktes gehostetes Mitglied mit einem direkten HTTP/MCP-Adapter. Es werden keine Center-Admin-MCP-Werkzeuge hinzugefügt.

Für direkte CLI-HTTP-Aufrufe wird die URL in folgender Reihenfolge ausgewählt: --center-url, dann MEMORIES_CENTER_URL, dann das konfigurierte SaaS-Center. Admin-Aufrufe erfordern MEMORIES_CENTER_ADMIN_TOKEN; Inhalts-RPCs erfordern MEMORIES_CENTER_TOKEN. Keines dieser Bearer-Token gehört in TOML. TLS-Einstellungen verwenden --ca-file / --insecure erneut; deaktivieren Sie die TLS-Prüfung nicht in der Produktion. Weiterleitungen werden nicht verfolgt. Der direkte Helfer benötigt keinen laufenden Daemon:

export MEMORIES_CENTER_URL="https://center.example.com"
export MEMORIES_CENTER_TOKEN="…"
# request.json contains an ordinary hosted Request, e.g. {"op":"list","vault":"default"}
memories center rpc --request request.json

CLI

# Admin: derive public key for config.toml
export MEMORIES_CENTER_SECRET="…"   # 32-byte URL-safe base64 or 64 hex
memories center public-key

# Admin: issue tickets (or use memories-center HTTP service)
memories center issue-bootstrap --center corp --device-name laptop
memories center issue-grant --center corp --vault VAULT_ID --minutes 15
memories center issue-grant --center corp --vault VAULT_ID --scope read --minutes 15
memories center issue-grant --center corp --vault VAULT_ID --scope write --minutes 15
memories center issue-grant --center corp --vault VAULT_ID --scope read_write --minutes 15
memories center issue-grant --center corp --vault VAULT_ID --scope 'read+write+delete' --minutes 15
memories center issue-grant --center corp --vault VAULT_ID --scope allow_all --minutes 15
# Legacy: --write alone ⇒ read_write (when --scope omitted)

# Endpoint (daemon already running with centers in config)
memories center list
memories center enroll --ticket "$BOOTSTRAP_TICKET"
memories sudo
memories center import-grant --ticket "$GRANT_TICKET"

Lokale MCP-Berechtigungen (ohne Center) akzeptieren dieselben Umfänge:

memories mcp grant VAULT_ID ./grant.token --scope read --minutes 15
memories mcp grant VAULT_ID ./grant.token --scope read_write_delete --minutes 15
# Legacy: --write ⇒ read_write

Center-HTTP-Dienst (memories-center)

export MEMORIES_CENTER_SECRET="…"
export MEMORIES_CENTER_ADMIN_TOKEN="…"
memories-center --listen http://127.0.0.1:9191 --center-id corp

Das Center stellt unverschlüsseltes HTTP über TCP bereit. --listen https://HOST:PORT wählt nur die Bindeadresse; es aktiviert kein natives TLS. Binden Sie das Center für eine öffentliche Bereitstellung an Loopback oder eine geschützte interne Adresse hinter einem TLS-Reverse-Proxy und konfigurieren Sie Clients mit der öffentlichen https://-URL des Proxys. Schützen Sie Administratortoken und Signiergeheimnis; stellen Sie den unverschlüsselten HTTP-Listener nicht direkt öffentlich bereit.

  • GET /health
  • GET /v1/public-key
  • POST /v1/tickets/bootstrap (Bearer-Administratortoken)
  • POST /v1/tickets/mcp-grant (Bearer-Administratortoken)
  • POST /v1/tickets/unlock (Bearer-Administratortoken; {"ttl":300}, 1–3600 Sekunden)

Berechtigungsinhalt (JSON):

{
  "vault": "…",
  "scope": "read_write",
  "minutes": 30,
  "ttl": 3600
}

scope akzeptiert dieselben Übertragungsnamen und Aliasse wie die CLI. Wird scope weggelassen, wird write: true auf read_write abgebildet, andernfalls ist der Standard read. Statische gehostete Berechtigungen können den Umfang weglassen (TOKEN oder TOKEN::VAULT), und die Mitgliedererstellung verwendet standardmäßig read, wenn der Umfang fehlt. Fordern Sie allow_all ausdrücklich an, statt sich auf den früheren großzügigen Standard zu verlassen.

Vollständiger gehosteter Tresor (SaaS)

Aktivieren Sie den gehosteten Tresor mit --data DIR (oder MEMORIES_CENTER_DATA). Stellen Sie ein nicht leeres MEMORIES_CENTER_VAULT_PASSWORD über die geschützte Umgebung/Geheimniseinspeisung Ihres Dienstmanagers bereit. Es gibt bewusst kein Passwort-Kommandozeilenflag. Das Passwort ist nur mit --data erforderlich; sein Verlust bedeutet den Verlust des Zugriffs auf den Store. Verwenden Sie ein starkes, unabhängig generiertes Passwort, kein Bearer-Token oder keinen Signierschlüssel.

# Inject MEMORIES_CENTER_SECRET, MEMORIES_CENTER_ADMIN_TOKEN,
# MEMORIES_CENTER_VAULT_PASSWORD and MEMORIES_CENTER_GRANTS securely first.
memories-center --listen http://127.0.0.1:9191 --center-id corp --data ./center-data

Stellen Sie bei Verwendung eines Checkouts den Optionen cargo run -p memories-center -- voran. Ohne --data bleibt der Prozess ein abwärtskompatibles, ausschließlich ticketbasiertes Center. Tickets und Registrierung funktionieren weiterhin in beiden Modi.

Der gehostete Modus verwendet memories_core::service::Service, Request, Content und den verschlüsselten SQLite-Store des Daemons wieder. Er kann Center + Daemon für gehostete Tresorinhalte ersetzen, einschließlich:

  • Vollständiger Erinnerungs-/Kartenfelder: Inhalte, Tags, Quellen, Aliasse, Notizen, Kategorien, Privat-Kennzeichnung, Links, erlaubte Hosts und Geheimnisreferenzen.
  • Brain-, Persona-, Workflow- und Workflow-Template-Karten; geschützte Account-, Env-, Token-, Login-, TOTP/HOTP- und otpauth-Profile.
  • Signierter Revisions-DAGs, Verlauf, Diffs, historischer Lesezugriffe und erneuter Anwendung; Kartenlinks und Graphen innerhalb desselben Tresors.
  • Persona-Welt-Snapshots, Rollover, Archivkarten, Dinge/Attribute, Chatunterhaltungen/Lesecursor, Automatisierungshooks, Erlaubnislisten und Auslöser.
  • Verschlüsselter Datei- und Anmeldedatenanhänge, Ersetzung geschützter Geheimnisse, ausdrücklicher Auslieferung von Anmeldedaten und OTP-Generierung.

Speicherung und Migration

DIR/
  store/
    memories.db       # Same encrypted Store format as the daemon
    memories.lock     # Exclusive process lock
  memories.json.bak   # Only if imported from the old notes library

SQLite kann außerdem seine normalen Transaktionsjournaldateien erstellen. Store-Speicherungen sind transaktional; Tresoridentität, signierte Revisionen und Audit-Zustand werden gemeinsam dauerhaft gespeichert. Ein Center-Prozess besitzt den Store jeweils exklusiv. Der Standardtresor und benannte Tresore, die von konfigurierten oder ausgestellten Berechtigungen verwendet werden, werden bei Bedarf erstellt. Berechtigungsbindungen verwenden intern kanonische Tresor-IDs und können andere Tresore weder auflisten noch auf sie zugreifen. Unix-Verzeichnisse sind nur für den Eigentümer zugänglich (0700); Store-Dateien und die Altsicherung ebenfalls (0600). Schützen Sie Verzeichnis und Dienstkonto auf jeder Plattform.

Wenn DIR/memories.json vorhanden ist, importiert der Start dessen gewöhnliche Notizen unter Beibehaltung von IDs und Tresornamen in einer einzigen atomaren Inhaltstransaktion und benennt die Eingabe anschließend in memories.json.bak um. Ungültige Datensätze lassen den Start fehlschlagen, ohne die Quelle zu verwerfen oder einen unvollständigen Notizstapel zu veröffentlichen. Ein erneuter Versuch nach einer unterbrochenen Umbenennung überspringt identische importierte Datensätze; widersprüchliche Datensätze oder eine bereits vorhandene Sicherung führen zur sicheren Abweisung zwecks Betreiberprüfung, statt Daten zu überschreiben. Die Altsicherung ist weiterhin Klartext: Entfernen Sie sie sicher oder verschlüsseln Sie sie unabhängig, nachdem Sie den Import geprüft und eine Sicherung eingerichtet haben. Neu geschriebene Inhalte werden niemals als JSON gespeichert.

Verschlüsselung und Bedrohungsmodell

Der Store wird beim Prozessstart mit dem vom Betreiber gehaltenen Passwort entsperrt (Argon2-Passwortumschließung und dieselbe authentifizierte Verschlüsselung wie beim lokalen Store). Bei jeder autorisierten Inhaltsoperation erneuert der gehostete Dispatcher die Serversitzung vor Prüfungen des Leerlaufablaufs; er sperrt nicht nach fünfzehn ruhigen Minuten automatisch. Herunterfahren und Admin-Sperren geben Store-Schlüssel und zwischengespeicherte Inhalte im Speicher frei. Admin-Sperren/-Entsperren erfolgt über separate Admin-HTTP-Routen, niemals über Inhalts-RPCs der Berechtigungen. Es gibt keine gehosteten sudo- oder Passwortänderungs-RPCs.

Dies ist serverseitige Verschlüsselung, keine Ende-zu-Ende-Clientverschlüsselung. Betreiber mit Kontrolle über Host/Prozess/Passwort können jeden gehosteten Tresor lesen, einschließlich privater Inhalte und Anmeldedaten. Jeder, der sowohl das Passwort als auch eine Festplattenkopie besitzt, kann den Store entschlüsseln. Hostspeicher, Absturzabbilder, Einsicht in die Umgebung, bösartige autorisierte Clients und kompromittierte TLS-Terminierung liegen außerhalb dieser Vertraulichkeitsgrenze. private kontrolliert weiterhin sichere Zusammenfassungen/Retrieval, stellt aber keine Barriere gegen eine gehostete Berechtigung dar, die zum Lesen dieses Tresors autorisiert ist.

Der Daemon verwendet dagegen ein Gerätepasswort und kann lokale, vom Betriebssystem versiegelte unbeaufsichtigte Schlüssel verwenden. Der gehostete Modus hat keine versiegelten Geräteschlüssel oder gerätespezifische Passwortoberfläche. Gerätetresorschlüssel werden nicht automatisch hochgeladen oder mit diesem gehosteten Store geteilt. Verwenden Sie den oben beschriebenen TLS-Reverse-Proxy; HTTP-Anfragen und die autorisierte Auslieferung von Geheimnissen liegen für Center und TLS-Terminierer im Klartext vor. Protokollieren Sie keine Bearer-Token, RPC-Inhalte, Anmeldedatenantworten oder Passwörter.

Fernsperren/-entsperren

Gehostete Routen erfordern den Admin-Bearer und existieren nur mit --data:

Route Verhalten
GET /v1/admin/status Gibt unlocked, gehosteten Modus, Mitgliederanzahl und restart_required zurück, ohne Geheimnisse
POST /v1/admin/lock Verwirft Store-Schlüssel/-Zustand, leert Caches und setzt Berechtigungen bis zum Entsperren aus
POST /v1/admin/unlock Akzeptiert {"password":"…"} und öffnet denselben vorhandenen Store mit dem Betreiberpasswort erneut

Im gesperrten Zustand geben Inhaltsrouten und die Ausstellung gehosteter Zugriffstoken 503 zurück; keine Berechtigung kann Klartext bereitstellen. Admin-Status, Auflisten/Entfernen von Mitgliedern und Ausstellung von Gerätetickets bleiben verfügbar. Mitgliedererstellung sowie Umfangs-/Tresoraktualisierung erfordern einen entsperrten Store. Falsche gehostete Passwörter geben 403 zurück; fehlgeschlagene Authentifizierung verwendet das exponentielle Backoff von Core (nachfolgende Versuche während des Backoffs geben 429 zurück). Erfolgreiches Entsperren stellt statischen/Mitgliedszugriff wieder her, nicht widerrufene ausgestellte Token. Bei bereits vor dem Sperren abgeschlossenen Anfragen kann der zurückgegebene Klartext nicht zurückgenommen werden. Der Start erfordert weiterhin MEMORIES_CENTER_VAULT_PASSWORD; Fernentsperren speichert das übergebene Passwort nicht dauerhaft und ändert die Startkonfiguration nicht.

export MEMORIES_CENTER_ADMIN_TOKEN="…"
memories center status --center-url https://center.example.com
memories center lock --center-url https://center.example.com
memories center unlock --center-url https://center.example.com  # password prompt

Geräteentsperren ist anders: POST /v1/tickets/unlock ist sowohl bei ausschließlich ticketbasierten als auch bei gehosteten Centern verfügbar. Der Administrator signiert ein kurzlebiges unlock-Ticket; der lokale Daemon prüft Art, Signatur, konfiguriertes Center und Ablauf und entsperrt dann mit dem lokal abgefragten Gerätepasswort des Betreibers. Es gewährt keine sudo/MCP-Rechteerhöhung. memories center unlock --ticket verwendet immer lokale, vom Betriebssystem authentifizierte IPC, nicht den ausgewählten Remote-Daemon oder die Center-HTTP-API. Es gibt keine automatische Gerätepasswortauslieferung, Hinterlegung oder keinen Push-Kanal.

# Admin: save the returned ticket securely; do not put it in logs.
memories center issue-unlock --center-url https://center.example.com --ttl 300
# On the device (daemon running with the same --home/config):
memories center unlock --ticket "…"  # local device password prompt

Entsperrtickets sind bis zum Ablauf wiederverwendbar und autorisieren das Entsperren auf Endpunkten, die diesem Center vertrauen, vorbehaltlich des jeweiligen Endpunktpassworts; sie sind weder einmalig verwendbar noch gerätegebunden. Bestehendes lokales Entsperren per Passwort bleibt auf ausschließlich ticketbasierten verwalteten Geräten verfügbar. SaaS-Anbindungen können kein Ticket verwenden, um einen parallelen lokalen Inhalts-Store zu registrieren oder zu entsperren.

Passwortverwahrung: Der gehostete Betreiber hält das Passwort des gehosteten Stores und sendet es nur zum gehosteten Entsperren an das vertrauenswürdige Center/den TLS-Terminierer. Gerätepasswörter und Tresorschlüssel bleiben im Ticketmodus auf dem Gerät/im lokalen Daemon. Ein kompromittiertes Center kann Entsperrtickets ausstellen, benötigt aber weiterhin ein Gerätepasswort, um dessen Chiffretext zu entsperren. Ein kompromittierter gehosteter Administrator kann den Store sperren und Mitglieder mit Klartextbefugnissen ausstellen, sobald er entsperrt ist. Gehostete Betreiber kontrollieren bereits den Prozess und können sämtlichen entsperrten Klartext lesen; die Trennung von Admin/Mitglied ist keine Verschlüsselung gegen den Betreiber.

Dauerhafte Mitglieder

Gehostete Mitglieder sind benannte, dauerhafte Bearer-Principals mit denselben fünf GrantScope-Stufen, keine Konten eines Identitätsanbieters. Eine optionale role ist reader, editor, admin oder owner; weggelassene Rollen behalten die bisherige Zuordnung von read, write/read_write, read_write_delete beziehungsweise allow_all bei. Eine ausdrückliche Rolle begrenzt den Mitgliedsumfang (Reader: read, Editor: read_write, Admin: read_write_delete, Owner: allow_all). Mitglieder-CRUD-Routen erfordern weiterhin den Betreiber-Admin-Bearer, nicht die Admin/Owner-Rolle eines Mitglieds:

Route Inhalt / Antwort
GET /v1/admin/members members-Array aus id, vault, scope, role, created und updated; keine Bearer-Token
POST /v1/admin/members {"id":"agent","vault":"default","scope":"read"}; Metadaten plus generiertes token, das nur in dieser Antwort angezeigt wird
PUT /v1/admin/members/{id} Optionaler Umfang, Tresor und/oder Rolle; derselbe Bearer, Antwort nur mit Metadaten
DELETE /v1/admin/members/{id} Entfernt das Mitglied und macht den Bearer sofort ungültig

IDs sind stabile Namen mit 1–64 Zeichen (ASCII-Buchstaben/Ziffern, -, _); center-admin ist für den Betreiber-Owner reserviert. Doppelte IDs geben 409 zurück. Token sind zufällig, eindeutig und von Admin-/statischen Token verschieden. Verwenden Sie für die Mitgliedererstellung ein geschütztes Terminal/ein geschütztes Ausgabeziel; die CLI gibt den zurückgegebenen Bearer absichtlich einmal aus. Erfassen Sie Erstellungsantworten niemals in Protokollen. Mitglieder authentifizieren sich über dieselbe Berechtigungstabelle auf /v1/memories und /v1/rpc; Umfangs-/Tresoränderungen gelten für nachfolgende Anfragen ohne Neustart. Anfragen, die vor einer zwischenzeitlichen Mitgliedschaftsänderung authentifiziert wurden, werden vor der Inhaltsverarbeitung abgewiesen. Entfernen/Neuanlegen eines Mitglieds ist das Verfahren zur Tokenrotation.

DIR/members.json ist eine atomar ersetzte, dauerhafte Datei, die nur dem Eigentümer zugänglich ist (0600 unter Unix), im ebenfalls nur dem Eigentümer zugänglichen gehosteten Verzeichnis. Sie enthält die Bearer-Token im Klartext, aber keine Passwörter, Schlüssel oder Tresorinhalte; schützen Sie sie wie Anmeldedaten, nehmen Sie sie in geschützte Sicherungen auf und committen Sie sie nicht. Beim Start werden Mitglieder neu geladen/validiert; bei beschädigten oder kollidierenden Bearern wird sicher abgewiesen. Eine fehlgeschlagene dauerhafte Mitgliedsspeicherung sperrt Inhalte und setzt restart_required: Fernentsperren gibt 503 zurück, bis der Betreiber das Dateisystem repariert und neu startet, um die dauerhafte Autorisierung neu zu laden. Dies verhindert, dass unsichere Persistenzergebnisse widerrufene Bearer wiederbeleben.

memories center member list --center-url https://center.example.com
memories center member add --center-url https://center.example.com --id agent --vault default --scope read
memories center member set --center-url https://center.example.com --id agent --scope read_write
memories center member remove --center-url https://center.example.com --id agent

Dies ist weiterhin ein einzelner Store mit einem vom Betreiber gehaltenen Schlüssel und logischer Berechtigungsbindung pro Tresor, keine harte Mandantentrennung, kein OIDC/SSO, keine Benutzerpasswörter, Refresh-Token, Kontingente oder Selbstbedienungswiederherstellung.

Berechtigungen und API

Statische Berechtigungen verwenden wiederholbares --grant TOKEN[:SCOPE[:VAULT]] und/oder kommasepariertes MEMORIES_CENTER_GRANTS; ein weggelassener Umfang bedeutet read, und ein weggelassener Tresor bedeutet default (TOKEN::VAULT wählt einen Tresor mit dem Standardumfang). Ihre Lebensdauer entspricht der Prozesslebensdauer. Admin-authentifiziertes POST /v1/tickets/mcp-grant gibt das unveränderte signierte Ticket plus ein gehostetes access_token zurück, das an seinen Tresor/Umfang gebunden ist. Dieses Zugriffstoken läuft nach minutes (1–60) ab und überlebt einen gehosteten Neustart. Das ttl des Tickets regelt separat die Gültigkeit des Ticketimports. Ausgestellte gehostete Berechtigungen werden atomar in DIR/grants.json gespeichert, nur für den Eigentümer zugänglich (0600): ausschließlich SHA-256-Bearer-Hashes und Autorisierungsmetadaten, niemals ausgestellte Token im Klartext. Bearer-Hashes werden in konstanter Zeit verglichen. Widerrufe bleiben bestehen, und das Entfernen von Mitgliedern wird nach dem Neustart weiterhin über wiederhergestellte Berechtigungsvorfahren fortgepflanzt. Abgelaufene Berechtigungen und ihre Nachfolger werden beim Laden, jede Minute und während Authentifizierung/Ausstellung entfernt. Behandeln Sie diese vom Eigentümer kontrollierte Autorisierungsdatei und ihre Sicherungen als sicherheitskritisch; ein Rollback dieser Datei oder des Stores kann alten Zustand wiederherstellen. Ein Persistenzfehler sperrt den Dienst und erfordert Reparatur/Neustart.

Das Sperren des gehosteten Stores verwirft seine Schlüssel und macht Berechtigungen unbrauchbar, ohne sie zu widerrufen; noch nicht abgelaufene ausgestellte Berechtigungen, statische Berechtigungen und dauerhafte Mitglieder funktionieren nach dem Entsperren wieder. Jedes dauerhafte Mitglied hat einen persistenten Generationszähler. Aussteller- und Empfängergenerationen werden bei Ausstellung eingefroren und niemals durch Authentifizierung erneuert; das öffentliche Feld generation ist die Empfängergeneration bei der Ausstellung. Eine Umfangs-/Rollen-/Tresoraktualisierung oder Entfernung erhöht nur die Generation dieses Mitglieds; Zähler entfernter Mitglieder bleiben erhalten, damit das Neuanlegen einer ID sie nicht zurücksetzt. Entfernen/Aktualisieren widerruft ausdrücklich Berechtigungen, die von oder an dieses Mitglied ausgestellt wurden, und transitiv alle Nachfolger; unabhängige Berechtigungen bleiben nutzbar, auch nach Neustart. Statische/dauerhafte Anmeldedaten werden beim ausdrücklichen Richtlinienübergang neu etabliert, nicht bei der Authentifizierung. Statische Principal- und dauerhafte Mitglieder-Eltern-IDs sind über Neustarts hinweg stabil, sodass wiederhergestellte Delegationsketten verbunden bleiben.

Der Admin-Bearer allein erhält 401 auf /v1/memories und /v1/rpc, auch beim Lesen. Er kann Tresorinhalte nicht direkt ändern. Administratoren können weiterhin separate Berechtigungen über die Ticket- oder Autorisierungs-API ausstellen; diese administrative Fähigkeit ist keine Vertraulichkeitsbarriere gegen den Administrator.

Autorisierungs-HTTP-API

Diese Routen existieren nur im gehosteten Modus. Sie authentifizieren entweder den Betreiber-Admin-Bearer (ein Owner über alle Tresore) oder den Bearer eines gehosteten Principals. Der Betreiber kontrolliert Serversperren/-entsperren/Mitglieder-CRUD; ein gehosteter Admin/Owner darf Autorisierung nur innerhalb von Bearer-Tresor und -Umfang verwalten. Keine Rechteerhöhung im Terminal ist erforderlich. Reader und Editor können weder ausstellen noch delegieren, auch wenn ihnen umfassenderer Inhaltszugriff gewährt wurde. Rollen-/Umfangs-/Tresor-/Ablaufverstöße geben 403 mit einem klaren Befugnisfehler zurück; Validierungsfehler im Handler geben 400 zurück, fehlende Objekte 404, wiederholte Entscheidungen 409 und abgelaufene/widerrufene Bearer oder solche mit veralteter Generation 401. Fehlerhaftes JSON oder JSON mit falschen Typen kann vom JSON-Extraktor von Axum mit 400 oder 422 abgewiesen werden.

Route Felder und Antwort
GET /v1/access/{vault} Admin/Owner; vault, principals, gruppiert unter owner, admin, editor, reader, aktive grants einschließlich Ablauf sowie pending_requests und approved_unclaimed_requests (id, requester, scope, Liste approvers oder "broadcast", created und expires in Unix-Sekunden)
POST /v1/grants Admin/Owner; vault, optionales scope (Standard read), duration_minutes (Standard 30, Alias minutes), grantee; Berechtigungsmetadaten plus einmaliges token
GET /v1/grants Optionales vault; Admin/Owner sehen alle ausgestellten Berechtigungen im Tresor, andere aktuelle Principals sehen nur ihre eigenen ausgestellten Berechtigungen; grants-Array, ohne statische/dauerhafte Anmeldedaten und abgelaufene/veraltete Berechtigungen
DELETE /v1/grants/{id} Aussteller oder Admin/Owner innerhalb des Tresors; widerruft ausgestellte Berechtigung und Nachfolger, gibt revoked und count zurück
POST /v1/requests Jedes Mitglied; vault, optionales scope (Standard read), reason, duration_minutes (Standard 30, Alias duration), approvers; Metadaten der ausstehenden Anfrage
GET /v1/requests Optionales vault; ausstehende Anfragen des Antragstellers oder eines berechtigten Genehmigers sowie genehmigte, noch nicht abgeholte Anfragen des Antragstellers; keine Token
POST /v1/requests/{id}/approve Berechtigter Admin/Owner; kein Inhalt; nur Metadaten der genehmigten, noch nicht abgeholten request und validierte Grenzen, keine Berechtigung und kein Token
POST /v1/requests/{id}/claim Nur der dauerhafte Mitglieds-Bearer des Antragstellers; kein Inhalt; request plus neu ausgestellte grant mit einmaligem token
POST /v1/requests/{id}/reject Berechtigter Admin/Owner; optionaler JSON-reason; request mit Status rejected
POST /v1/requests/{id}/cancel Nur Antragsteller; kein Inhalt; request mit Status cancelled
GET /v1/audit Admin/Owner; optionales vault, format=json|jsonl (Standard json); verifizierte entries/verified oder zeilenweise Export

Alle Ausstellungs-/Anfragedauern betragen 1–60 Minuten. Höchstens 10,000 Berechtigungen dürfen gleichzeitig aktiv sein (memories_core::service::MAX_ACTIVE_GRANTS); der lokale Daemon verwendet dieselbe Obergrenze. Aussteller dürfen weder ihre Rollenobergrenze oder ihren Bearer-Umfang überschreiten noch ihren Tresor verlassen oder den Ablauf ihrer Elternberechtigung verlängern. Empfänger sind standardmäßig das ausstellende Mitglied; ausdrücklich angegebene grantee-Namen müssen bestehende Principals des ausgewählten Tresors sein. Der reservierte Empfänger center-admin wird immer mit HTTP 403 abgewiesen; zuvor gespeicherte Berechtigungen mit diesem Subjekt sind ebenfalls unbrauchbar. Eine Betreiberausstellung ohne Empfänger (einschließlich gehosteter Ticketausstellung) erstellt einen anonymen Principal, dessen Subjekt seine Berechtigungs-ID ist, nicht center-admin. Kein Empfänger darf eine höhere Rolle als die effektive Rolle des Ausstellers haben, auch bei einer reinen Leseberechtigung.

Sowohl Center als auch Daemon definieren pub const MAX_DELEGATION_DEPTH: u32 = 2. Direkte Mitglieds-/Betreiberausstellung hat Tiefe 1; bei Verwendung einer Berechtigung erfolgt die Ausstellung mit parent.depth + 1, und Tiefe 3 gibt HTTP 403 zurück. Dauerhafte Mitgliedsanmeldedaten sind direkte Mitgliedsbefugnisse (interne Tiefe 0); von ihnen ausgestellte Berechtigungen haben Tiefe 1 ohne Berechtigungs-Elternteil. Persistierte alte Berechtigungen ohne depth werden anhand ihrer vollständigen Elternkette rekonstruiert, einschließlich konfigurierter statischer und dauerhafter Anmeldedaten. Fehlende/zyklische oder die Grenze überschreitende Abstammung ist unbrauchbar und wird beim Start entfernt.

Eine Berechtigungsbefugnis mit subject != issued_by ist ein benannter Berechtigungsaufrufer. Solche Aufrufer können keine Berechtigungsanfrage genehmigen, ablehnen, stornieren oder abholen, auch nicht ihre eigene (HTTP 403); sie sind keine berechtigten Genehmiger. Sie dürfen Anfragen erstellen, müssen aber ihre tatsächlichen Mitgliedsanmeldedaten für Berechtigungsabläufe verwenden. Delegierte Ausstellung bewahrt den tatsächlichen Aussteller, sodass ein benannter Bearer sich nicht in eine selbst ausgestellte Berechtigung umwandeln kann. Selbst ausgestellte Berechtigungen behalten ihre bestehenden Anfrageregeln, und das Abholen erfordert weiterhin den dauerhaften Mitglieds-Bearer des Antragstellers. Aufgeschobene alte Genehmigungen, die mit einer Berechtigung für einen benannten Empfänger erteilt wurden, können keine Abholung autorisieren; holen Sie eine neue Genehmigung von einer berechtigten Mitgliedsbefugnis ein.

Inkompatible Änderungen: Empfänger mit höherer Rolle und center-admin, Berechtigungsentscheidungen/Stornierungen/Abholungen durch benannte Empfänger sowie Delegation über mehr als zwei Berechtigungen werden abgewiesen. Vom Betreiber ausgestellte Subjekte sind jetzt anonym statt center-admin; von Mitgliedern ausgestellte Wurzeln führen die dauerhaften Mitgliedsanmeldedaten nicht mehr als Delegations-Elternteil auf. Stellen Sie eine geeignete Wurzel neu aus oder verwenden Sie Mitgliedsanmeldedaten, statt sich auf diese früheren Verhaltensweisen zu verlassen.

Berechtigungen zeichnen id (eine unabhängige undurchsichtige ID), subject, scope, vault, expiry in Unix-Sekunden, parent, issued_by, generation, depth und role auf. Statische Principal-IDs sind static:OPAQUE_ID. GET /v1/grants gibt nur ausgestellte zeitlich begrenzte Berechtigungen mit id, parent, issued_by, grantee, scope, vault, expiry in Unix-Sekunden, generation, depth und, sofern verfügbar, created in Unix-Sekunden zurück. Es gibt niemals ein Token oder einen Bearer-Hash zurück. grantee ist der Empfänger (subject in Ausstellungs-/Zugriffsantworten). Die Generation bleibt die Generation bei der Ausstellung. Diese Ansicht ausgestellter Berechtigungen unterscheidet sich von der unveränderten Principal-/Zugriffsansicht GET /v1/access/{vault}: Statische und dauerhafte Anmeldedaten erscheinen nur in letzterer und werden über Konfiguration/Mitglieder-CRUD entfernt, nicht über DELETE /v1/grants/{id}. Aussteller dürfen ihre eigenen Berechtigungen auflisten; allein der Empfang einer Berechtigung macht sie für einen Empfänger ohne Admin-Rolle nicht sichtbar. Gehostete Bearer sind auf ihren Tresor beschränkt; ein weggelassenes vault wählt diesen Tresor, während der Betreiber tresorübergreifend auflisten kann. memories center grant list [VAULT] gibt dieselbe Antwort ausgestellter Berechtigungen zurück.

Anfragen mit leeren/weggelassenen approvers werden über berechtigte Listen ausstehender Anfragen verbreitet; nicht leere Listen enthalten benannte Admin/Owner-Genehmiger-IDs (oder center-admin). Sowohl Genehmigung als auch Ablehnung sind durch Umfang, Tresor, Rolle und verbleibende Berechtigungslebensdauer des Genehmigers begrenzt. Der Antragsteller kann seine eigene Anfrage weder genehmigen noch ablehnen, auch nicht als Admin/Owner oder benannter Genehmiger; er darf sie weiterhin stornieren. Entscheidungen werden unter derselben Autorisierungssperre serialisiert und dürfen nur einmal erfolgen. Anfragezustände sind pending, approved, rejected oder cancelled. Die Genehmigung zeichnet genehmigte Berechtigungsparameter und die Umfangs-/Tresor-/Rollen-/Ablaufgrenzen des Genehmigers auf, stellt jedoch nichts aus und gibt kein Token zurück. Das anfragende Mitglied verwendet seine dauerhaften Mitgliedsanmeldedaten, um POST /v1/requests/{id}/claim oder memories center request claim ID aufzurufen. Genehmiger, andere Mitglieder und ausgestellte Berechtigungen für dasselbe Antragstellersubjekt werden abgewiesen. Abholungen sind serialisiert: Nur eine Abholung ist erfolgreich, und nachfolgende Versuche geben 409 zurück, auch nach einem Neustart. Die Generation der Berechtigung und ihre Erstellungs-/Ablaufuhr beginnen beim Abholen; ihr Ablauf wird durch den aufgezeichneten Ablauf der genehmigenden Befugnis begrenzt. Abgelaufene/widerrufene Elternberechtigungen und geänderte Aussteller-/Antragstellergenerationen verhindern Abholungen. Nur der Token-Hash wird mit Berechtigungsmetadaten gespeichert. request.claim protokolliert den Antragsteller als Akteur und die Berechtigungs-ID, niemals das Token. Geht die einmalige Antwort verloren, fordern Sie eine neue Genehmigung an. Eine genehmigte Inhaltsberechtigung ändert weder die Mitgliedsrolle noch die Delegationsbefugnis ihres Antragstellers.

Inkompatible Änderung: Genehmigungsantworten enthalten nicht mehr grant oder dessen Token; Clients müssen ausdrücklich mit dem Mitglieds-Bearer des Antragstellers abholen. Anfragelisten zeigen genehmigte, noch nicht abgeholte Metadaten, keine Token. Alte genehmigte Anfragen ohne aufgeschobene Genehmigungsgrenzen können nicht abgeholt werden; erstellen Sie stattdessen eine neue Anfrage.

Center-Audit- und Anfragedateien

DIR/requests.json wird atomar mit Modus 0600 ersetzt und speichert Anfragemetadaten und abgeschlossene Entscheidungen über Neustarts hinweg. DIR/audit.jsonl wird im Anhängemodus mit Modus 0600 geöffnet, nach jedem Eintrag per fsync synchronisiert und niemals vom Center neu geschrieben. Beide liegen unter dem gehosteten Verzeichnis mit Modus 0700. Begründungen sind Audit-Metadaten: Geben Sie darin keine Passwörter oder andere Geheimnisse an. Audit-Datensätze enthalten keine Bearer-Token, Passwörter, Schlüssel oder Tresorinhalte.

Audit-Einträge stellen sequence, timestamp, prev_hash, hash, action und optional issued_by / via_grant für durch Berechtigungen autorisierte Aktionen bereit. Ersteres ist der tatsächliche Aussteller, letzteres die Berechtigungs-ID des Aufrufers; actor bleibt das Berechtigungssubjekt, außer dass grant.issue den tatsächlichen Aussteller als Akteur und den Empfänger als Subjekt aufzeichnet. Die Felder sind standardmäßig nicht vorhanden und werden bei Fehlen weggelassen, sodass alte Audit-Protokolle ihre bestehenden Hashes behalten. Die signierten gehosteten Inhaltsaudits des gemeinsamen Stores zeichnen diese Felder ebenfalls auf. Die bestehenden Felder umfassen actor, subject, scope, vault, expiry, parent, reason, request_id und object. Das erste prev_hash ist null; spätere Werte verweisen auf den vorhergehenden Hash. SHA-256 umfasst das JSON-Tupel (sequence, timestamp, prev_hash, event_fields). verify_audit_chain(path) in crates/center/src/saas/audit.rs prüft Kontinuität, Hashes und vollständige JSONL-Zeilen. Der Start prüft die Datei und gleicht Anfrageentscheidungen und Abholungen damit ab, sodass ein Absturz nach dem Protokollieren einer Entscheidung oder Abholung, aber vor dem Ersetzen der Anfragemetadaten keine Wiederholung ermöglichen kann. Anhängen und Lesen prüfen die Kette gegen den aktuellen prozessinternen Kopf; Audit-Lesezugriffe prüfen die gesamte Kette, bevor ein Tresorfilter angewendet wird.

Aktionen sind device.authorize (Ausstellung eines Bootstrap-Tickets), grant.issue, grant.revoke, member.add, member.set, member.remove, session.lock, session.unlock, request.create, request.approve, request.claim, request.reject und request.cancel. Widerrufe durch Sperren und Mitgliederänderungen werden ebenfalls protokolliert. JSONL-Exporte verwenden Content-Type: application/x-ndjson; gefilterte Exporte behalten ursprüngliche Hashes/Sequenzen und sind keine unabhängigen vollständigen Ketten. Tresorgebundene Admin/Owner-Aufrufer sehen nur Einträge ihres Tresors; der Betreiber sieht auch globale Ereignisse und darf das vollständige Protokoll exportieren. Jeder Fehler beim Audit-Anhängen/bei der Anfragepersistierung sperrt den Dienst, setzt restart_required und deaktiviert Fernentsperren bis zu Reparatur und Neustart. Autorisierungsänderungen und Berechtigungsentscheidungen geben 503 zurück, während restart_required gesetzt ist; schreibgeschützte Betreiberprüfung bleibt verfügbar. Bewahren Sie diese Dateien in geschützten Sicherungen auf, nicht in der Versionsverwaltung.

Dies ist eine Kette ohne Schlüssel, keine Gerätesignatur oder externe Verankerung: Ein kompromittierter Betreiber kann sie neu schreiben/neu berechnen, Ereignisse auslassen oder alle Dateien gemeinsam zurückrollen. Das vollständige Abschneiden des Endes vor dem Start kann ohne einen extern bekannten Kopf nicht erkannt werden. Betrachten Sie die Kettenprüfung nicht als unabhängiges Sicherheitsaudit.

Gehosteter Inhaltsumfang und API

Gehostete Inhaltsumfänge gelten für die Operation, nicht nur für die HTTP-Methode. Routen zur Autorisierungsverwaltung prüfen zusätzlich die Rolle des Principals wie oben beschrieben; der Inhalts-scope allein gewährt niemals Hostadministration:

Umfang Gehostete Befugnis im gebundenen Tresor
read Sicheres Auflisten/Suchen/Graph; vollständige autorisierte Lesezugriffe, Dateilesen, Verlauf/Diff/Audit und ausdrückliches credential_copy
write Inhaltserstellung/-aktualisierung, geschützte/OTP-Registrierung, Dateien/Anmeldedaten, Welt-/Chat-/Automatisierungsschreibzugriffe; kein Lesen vorheriger Inhalte oder Löschen
read_write Beides; außerdem otp_code (erfordert Lesen + Schreiben, da HOTP den Zustand fortschreibt)
read_write_delete Beides plus Löschen von Assets, Dingen, Attributen und Automatisierungshooks
allow_all Alles oben Genannte innerhalb der ausschließlich für Inhalte vorgesehenen gehosteten Schnittstelle, keine Server-/Geräteadministration

Anders als Daemon-MCP liefert der gehostete Dispatcher operationslokale Rechteerhöhung erst nachdem die geschlossene Operationserlaubnisliste, Umfang und Tresorbindung erfolgreich geprüft wurden. Daemon-check_mcp und dessen lokale Rechteerhöhungseinschränkungen bleiben unverändert. Gehostete Agenten/MCP-Adapter können ihren eingeschränkten Bearer auf der vollständigen RPC-Inhaltsschnittstelle verwenden; keine lokale Terminal-Rechteerhöhung oder Daemon-Verbindung ist erforderlich. Tresorübergreifende Brain-/Archivreferenzen können über eine Berechtigung keine Inhalte eines anderen Tresors auflösen.

  • GET /v1/session → aktueller Tresor, Rolle, Umfang, Ablauf und Lese-/Schreib-/Löschfähigkeiten, ohne Bearer-Material. Reine Schreibtoken können ihre Sitzung einsehen; Betreiber-Administratortoken können dies nicht. Siehe mobiler gehosteter Modus.
  • GET /v1/memories → {"memories":[...]}. Gewöhnliche nicht private Notizdatensätze behalten id, vault, title, body; Karten-/Privat-/Datei-/Anmeldedatensätze verwenden sichere Zusammenfassungen, niemals Anmeldedateninhalte oder aufgelöste Geheimnisse.
  • GET /v1/memories/{id} → vollständige sichere Clientinhalte + id, vault. Anmeldedaten erfordern ausdrückliches credential_copy anstelle allgemeiner Lesezugriffe.
  • POST /v1/memories und PUT /v1/memories/{id} akzeptieren title/body plus vollständige Content-Metadaten. PUT bewahrt weggelassene Felder. Das Hinzufügen von Kartenmetadaten bei der Erstellung leitet kind: "card" ab, wenn keine Art angegeben wird. Strukturierte/geschützte Profilerstellung verwendet ihren speziellen RPC, kein allgemeines PUT. Ein reines Schreib-PUT gibt nur übermittelte Felder und Datensatzidentität zurück, keine bestehenden privaten Felder.
  • Optionales JSON-vault / ?vault=… muss dem Berechtigungsnamen oder der kanonischen ID entsprechen; bei Weglassen wird der Tresor der Berechtigung gewählt. DELETE /v1/memories/{id} erfordert Löschen.
  • POST /v1/rpc akzeptiert das Daemon-Request-JSON (op in snake_case), gibt dessen direktes JSON-Ergebnis zurück und prüft jede Operation unabhängig. Verwenden Sie kanonische Asset-/Revisions-IDs aus Antworten; vault akzeptiert den Namen oder die kanonische ID der Berechtigung. list ohne vault wählt nur den Tresor der Berechtigung. Fehler verwenden HTTP 401 (unbekanntes/Admin-/abgelaufenes Token), 403 (Umfang/Schnittstelle/Tresor), 404 (fehlend), 409 (Konflikt), 400 (ungültige Eingabe) oder 422 (fehlerhaftes Request-JSON/-Schema).

Beispiele (mit dem Berechtigungs-Bearer senden, nicht mit dem Admin-Bearer):

{"op":"brain_card","vault":"default","title":"Research","abstract":"Summary","links":[]}
{"op":"history","vault":"default","asset":"CANONICAL_ASSET_ID"}
{"op":"persona_world_get","vault":"default","asset":"PERSONA_ASSET_ID"}
{"op":"put","vault":"default","content":{"title":"attachment.bin","kind":"file","private":true,"body":"BASE64URL_BYTES"}}

Dateien/Anmeldedaten verwenden die bestehende URL-sichere Base64-Inhaltskonvention, keinen zweiten Blob-Store. Das Inhaltslimit von Core von 16 MiB gilt weiterhin; das HTTP-JSON-Inhaltslimit beträgt 24 MiB. protect_secret verwaltet Anmeldedatenreferenzen atomar. Allgemeine Lesezugriffe/Auflistungen/Diffs lösen niemals gespeicherte Anmeldedatenbytes auf; autorisiertes credential_copy ist der bewusst ausdrückliche Endpunkt zur Klartextauslieferung.

Gehostetes archive_history/archive_read adressiert signierte Revisionen des gebundenen aktiven Tresors (einschließlich historischer/als gelöscht markierter Revisionen), keine Daemon-Wiederherstellungsarchive. archive_audit adressiert das Audit dieses Tresors. Gehostetes reapply hängt eine signierte historische oder quarantänisierte Revision als neuen Kopf an, einschließlich strukturierter/geschützter Metadaten; das erneute Anwenden einer Löschmarkierung erfordert auch Löschen. Anders als das Erfinden geschützter Referenzen über allgemeines PUT stellt dies Referenzen wieder her, die bereits im signierten Verlauf des Tresors authentifiziert wurden. Es stellt verknüpfte gelöschte Anmeldedaten nicht automatisch wieder her; wenden Sie bei Bedarf deren Revision separat erneut an.

Beabsichtigte Unterschiede zum Daemon

  • POST /v1/bootstrap und /v1/restore geben immer 403 zurück: Dies bleibt eine vom Center verwaltete Bibliothek, keine Selbstbedienungs-Geräteregistrierung/-wiederherstellung.
  • Kein sudo, keine Geräteregistrierung innerhalb gehosteter Inhalte, Tresorrichtlinien-Mitgliedschaftsverwaltung, Inhalts-RPC zur Berechtigungsausstellung/-widerrufung, vollständige Store-Sicherungs-/Wiederherstellungs-RPCs, Remote-Sitzungen/-Proxys, Cloud-/Relay-Synchronisierung, unbeaufsichtigte Verwahrung, Ausführung oder Kryptojob-Ausführung. Solche Anfragen werden auch mit allow_all sicher abgewiesen.
  • Gehostetes Sperren/Entsperren/Status und dauerhafte Mitgliederverwaltung sind separate adminautorisierte HTTP-Routen, keine durch allow_all verliehenen Fähigkeiten.
  • Wiederherstellungsarchive und tresorübergreifende Inhaltsauflösung werden nicht offengelegt. Historische Lesezugriffe/erneute Anwendung der eigenen Revisionen des gehosteten Tresors werden unterstützt.
  • Semantische/RAG-Modellkonfiguration/-generierung und Modellinstallation sind keine gehosteten Endpunkte. Lexikalisches search und der synchrone retrieve-Pfad verwenden die Core-Retrieval-Richtlinie wieder (keine privaten Inhalte, Datei- oder Anmeldedateninhalte).
  • Automatisierung läuft auf ausdrückliche RPC-Aufrufe und bestehende inhaltsausgelöste Ereignisse hin; es gibt keinen Hintergrundscheduler. Ausgehende Webhooks verwenden die genaue URL-Erlaubnisliste von Core; behandeln Sie einen gehosteten Schreiber, der Webhooks konfigurieren kann, als zum ausgehenden Netzwerkzugriff autorisiert und setzen Sie Betreiber-Egress-Einschränkungen für nicht vertrauenswürdige Mandanten durch.
  • SaaS-konfigurierte Daemons und der schlanke CLI-Helfer verwenden gehostetes /v1/rpc; natives Mobile verwendet seinen separaten hosted_*-FFI-Pfad mit kleinerer Inhaltserlaubnisliste. Ausschließlich ticketbasierte lokale IPC bleibt intakt. Es gibt keinen JSON-RPC-MCP-Admin-Werkzeugserver.

Die Store-Persistenz verwendet weiterhin transaktionale Speicherungen des Gesamtzustands und serialisierte Dienstoperationen; dies ist weder unabhängige Mandantenschlüsselverschlüsselung noch eine Behauptung über produktive Mandantentrennung/Sicherheitszertifizierung.

Mobile / FFI

Die ausgelieferte Flutter-App wählt Standalone, Center oder SaaS in ihrer eigenen Oberfläche. Sie lädt weder die config.toml des Daemons noch konfiguriert sie einen ticketverwalteten lokalen Dienst. Ihre Wahl Center verbindet sich mit einem selbst gehosteten Server mit gehostetem Speicher, während SaaS eine Verbindung zu https://memories.ivjn.us herstellt. Beide verwenden die unten genannten gehosteten FFI-Operationen.

Der gemeinsame Dienst setzt ticketverwaltete Init/Restore- und Berechtigungseinschränkungen durch, wenn ein Aufrufer Center auf diesem Dienst konfiguriert. Dies ist von der Modusauswahl des Telefons getrennt. Mobile-FFI verweigert weiterhin Run/CryptoJob/lokale MCP-Berechtigungsverwaltung/Remote/Proxy und lokale Berechtigungs-/Berechtigungsanfrage-RPCs; die Auswahl eines gehosteten Modus erweitert diese lokale Schnittstelle nicht.

Verbleibende Arbeiten

Genehmigungen für Remote-Anweisungen und andere erhöhte Richtlinienschnittstellen können später vom Center signierte Genehmigungstickets akzeptieren. Bis dahin verwenden Center-verwaltete Endpunkte weiterhin lokales sudo für tresorbezogene Operationen mit erhöhten Rechten, außer MCP-Berechtigungsausstellung und Bootstrap. allow_all ist dafür reserviert, mit diesen Schnittstellen zu wachsen, ohne Umfänge umzubenennen.

Grenzen, Ablauf und Aufbewahrung von Berechtigungsanfragen

Gilt sowohl für den Daemon (Anfragen im verschlüsselten Store) als auch für Center (requests.json):

  • MAX_PENDING_PER_REQUESTER_PER_VAULT = 20 und MAX_PENDING_PER_VAULT = 200 zählen nur ausstehende Anfragen. Entschiedene, stornierte, abgelaufene und genehmigte, aber noch nicht abgeholte Anfragen zählen nicht zu diesen Grenzen. (Dies ersetzt die alte globale Obergrenze von 1000 Anfragen, die jede jemals gestellte Anfrage zählte.) Überschreiten Sie eine Grenze, gibt der Daemon einen Grenzfehler und Center HTTP 429 zurück.
  • PENDING_REQUEST_TTL = 7 days: Eine ausstehende Anfrage, die älter ist, wechselt in den Status expired. Dies wird als request.expire mit Akteur system protokolliert, und sie kann nicht mehr genehmigt werden. Eine genehmigte Umfangsanfrage, die nicht innerhalb von 7 Tagen nach Genehmigung abgeholt wurde, läuft auf dieselbe Weise ebenfalls ab und kann danach nicht mehr abgeholt werden.
  • REQUEST_RETENTION = 30 days: Abgelehnte, stornierte, abgelaufene oder abgeholte Anfragen werden nach dieser Zeit seit ihrem letzten Übergang gelöscht (Zeitstempel decided oder created für ältere Datensätze ohne diesen).
  • Ablauf und Bereinigung erfolgen verzögert: Der Daemon führt sie zu Beginn jeder Autorisierungsanfrage aus, und Center beim Erstellen, Auflisten, Entscheiden und Abholen von Anfragen. Beim Start werden sie nicht ausgeführt.
  • Der Abgleich beim Center-Start ignoriert Audit-Einträge für bereinigte Anfragen und akzeptiert request.expire-Einträge. Eine expired-Anfrage muss einen protokollierten Ablauf haben. Anfrage-IDs sind zufällige 128-Bit-Werte, die niemals wiederverwendet werden, sodass eine bereinigte Anfrage (einschließlich einer abgeholten) nicht mehr existiert und nicht abgeholt werden kann. Deshalb hält Center keine separate Menge von Löschmarkierungen vor.

Mobiler gehosteter Modus (Telefonclient)

Die Center- und SaaS-Modi der mobilen App verbinden sich direkt mit einem Center, das mit --data DIR läuft; das Telefon benötigt keinen Daemon-Eintrag mode = "saas". Siehe mobile Verwendung für erste Verbindung und Wechsel sowie Konfiguration für Profilmigration. Die FFI-API memories_call akzeptiert diese hosted_*-Operationen:

  • {"op":"hosted_connect","center_url":"https://…","bearer":"…","ca_file":null,"insecure":false} → {"session":N,"url":…,"server_readable":true}
  • {"op":"hosted_rpc","session":N,"request":{…}} verwendet die untenstehende Inhaltserlaubnisliste
  • {"op":"hosted_status","session":N} authentifiziert über GET /v1/session
  • {"op":"hosted_requests","session":N}, hosted_approve / hosted_reject (id), hosted_access (vault)
  • {"op":"hosted_disconnect","session":N}; memories_lock_all verwirft ebenfalls jede gehostete Sitzung

HostedClient::rpc in crates/core/src/center.rs erlaubt list, read, search, delete, type_list, type_show, type_create, type_update, type_delete, card_create, card_fields, card_field, credential_set, credential_show sowie put, wenn content.kind memory, card oder credential ist. Der Server wendet weiterhin Tresor, Rolle und Umfang des Mitglieds an. Diese FFI-Erlaubnisliste verspricht nicht, dass jede Operation eine Flutter-Ansicht hat: Gehostetes Wissen unterstützt Auflisten, Serversuche, Details, gewöhnliche Erinnerungs-/Kartenbearbeitung, Erstellung und bestätigtes Löschen. Strukturierte Profile, geschützte Karten, Typvorlagen und versiegelte Karten erfordern spezialisierte Editoren. Autorisierungsanfragen und Steuerelemente für gekoppelte Geräte bleiben verfügbar.

GET /v1/session gibt vault, vault_id, scope, role, expires_at (Unix-Sekunden oder null), can_read, can_write, can_delete und server_readable zurück. Es akzeptiert jedes aktive eingeschränkte Inhaltstoken, einschließlich reiner Schreibtoken, weist aber Betreiber-Administratortoken ab. Es gibt kein Bearer- oder Geheimnismaterial zurück. Jede Inhaltsanfrage prüft weiterhin die Autorisierung erneut; diese Antwort ist eine UI-Momentaufnahme, keine Berechtigung. Stellen Sie diesen Endpunkt vor dem App-Upgrade bereit: Ältere Server ohne ihn können eine neue App-Verbindung nicht validieren.

Die Suche verwendet den gemeinsamen Retrieval-Dienst und schließt private Inhalte, Anmeldedaten und Dateien aus. Die ungefilterte Wissensliste kann private Karten für einen autorisierten Leser enthalten. Fehlgeschlagene Speicherungen behalten den Entwurf; Löschen erfordert eine Bestätigung und entfernt das Element erst nach Servererfolg. Aktualisierungen verwenden den bestehenden Revisionsdienst ohne atomare Vorbedingung einer erwarteten Revision; gleichzeitige Bearbeitungen können die jeweils neuesten Felder gegenseitig ersetzen.

Der gehostete Modus ist für den Server lesbar: Der Store ist im Ruhezustand verschlüsselt, aber der Betreiber hält das Passwort und kann gehostete Inhalte lesen. Die App kennzeichnet ihn mit „Server kann lesen“. Rust hält den Bearer jedes aktiven Clients im Speicher, in Debug und Fehlern geschwärzt; Flutter speichert das URL-/Token-Paar jedes Modus dauerhaft im sicheren Plattformspeicher. Ein Wechsel beendet die aktive Sitzung, behält aber das Profil. Trennen entfernt den gespeicherten Bearer dieses Profils; es widerruft nicht das Servertoken. Der Wechsel in den Hintergrund verwirft gehostete Sitzungen und sichtbare Inhalte; beim Zurückkehren muss ausdrücklich neu verbunden werden.

E2E-Geheimnisse zwischen Geräten (gehostetes Center)

Gehostete Tresore sind für den Server lesbar. Koppeln Sie Geräte und liefern Sie versiegelte Umschläge (crypto::Envelope: X25519 + Signatur mit dem Ed25519-Schlüssel des Senders) für Geheimnisse, die das Center niemals sehen darf. Das Center speichert nur öffentliche Schlüssel und Chiffretext.

Kopplungsablauf

  1. CLI: memories device hosted init --backend <keychain|secret-service|dpapi|owner-file> erstellt die Geräteidentität (32-Byte-Seed in Betriebssystemverwahrung; X25519 + Ed25519 abgeleitet).
  2. CLI (Mitgliedstoken in MEMORIES_CENTER_TOKEN): memories device hosted pair --vault V → POST /v1/devices/pairings mit beiden öffentlichen Schlüsseln und einer Selbstsignatur. Das Center erstellt eine ausstehende PermissionRequest mit dem Gerätefingerabdruck und gibt {code, request_id, qr: {pairing_id, fingerprint, center}} zurück (center ist die --center-id des Centers). Kopplungen laufen nach 5 Minuten ab. Die CLI gibt einen Terminal-QR (stderr) von {"type":"memories-pair","v":1,"pairing_id","fingerprint","center","code"} aus — der Einmalcode ist enthalten, sodass Scannen genügt; stdout-JSON bleibt unverändert. Das erneute Koppeln eines bereits aktiven Schlüssels gibt 409 zurück; nach dem Widerruf kann derselbe Schlüssel erneut gekoppelt werden.
  3. Das Telefon (Administrator des Tresors) scannt den QR (oder gibt den Code ein) → GET /v1/devices/pairings/{code}. Das Telefon verweigert einen QR, der kein Memories-Kopplungs-QR ist, dessen center vom verbundenen Center abweicht oder dessen Fingerabdruck vom abgerufenen Gerät abweicht. Unbekannte, abgelaufene oder verwendete Codes geben alle 404 zurück. — einmalig verwendbar, ablaufend, 10 fehlgeschlagene Abfragen/Minute → 429. Zeigt den Gerätefingerabdruck.
  4. Das Telefon genehmigt mit POST /v1/requests/{id}/approve und dem Inhalt {"attestation": DeviceAttestation}, signiert mit dem Ed25519-Schlüssel des Telefons über Gerätefingerabdruck, beide Geräteschlüssel, Kopplungs-ID, Genehmiger, Umfang und Ablauf.
  5. CLI: memories device hosted claim --request-id ID (einmal). Das gerätebeschränkte Berechtigungstoken wird in Betriebssystemverwahrung gespeichert; das Center hält nur seinen Hash.
  6. Vergleichen Sie die SAS: Das Telefon zeigt sie vor der Genehmigung (gruppiert 123 456); nach der Genehmigung gibt memories device hosted sas --pairing-id P dieselben Ziffern in der CLI aus. Unterschiedliche Ziffern: Gerät widerrufen und erneut koppeln.

Mobile Berechtigungen: Android CAMERA (Kamerafunktion optional), iOS NSCameraUsageDescription. Wird der Kamerazugriff verweigert, erklärt das Telefon, wie er in den Systemeinstellungen aktiviert wird, und bietet manuelle Codeeingabe an. CLI und Telefon übersetzen Center-Statuswerte in handlungsorientierte Meldungen (404 abgelaufen/verwendet/anderes Center, 409 bereits erledigt oder bereits gekoppelt, 403 nicht erlaubt oder widerrufenes Gerät, 422 e2e-Inhalt verweigert, 429 ratenbegrenzt).

SAS = erste 6 Dezimalziffern von u64_be(SHA-256("memories/device-sas/v1\0" ‖ phone_ed25519_pub ‖ "\0" ‖ cli_ed25519_pub ‖ "\0" ‖ pairing_id)[0..8]) mod 10^6, mit führenden Nullen aufgefüllt. Das Telefon hat den CLI-Schlüssel aus dem Abruf; die CLI erfährt den Telefonschlüssel aus der Attestierung. Eine Abweichung bedeutet einen ausgetauschten Schlüssel: sofort widerrufen.

Regeln

  • Geräteberechtigungen sind an das Gerät (nicht widerrufen, attestiert) und die Generation des Mitglieds gebunden; Delegationstiefe ≤ 2. Geräte können weder Berechtigungen ausstellen noch Anfragen entscheiden.
  • Das Erhöhen der Mitgliedsgeneration oder Entfernen des Mitglieds macht das Gerät ungültig und löscht seine Umschläge.
  • PUT|GET|DELETE /v1/sealed/{vault}/{card}/{device}, GET /v1/sealed?device=: Umschläge nur für attestierte Geräte, adressiert an den X25519-Schlüssel des Geräts, von einem bekannten Signierer; Versionen müssen steigen. Das Audit zeichnet nur Fingerabdrücke auf.
  • Karten mit e2e: true verweigern Geheimnisinhalte im Klartext auf dem gehosteten Center.
  • /v1/access/{vault} listet Geräte auf. MCP: device_list, sealed_reveal (erfordert intent: "reveal_plaintext" und eine Begründung).

Bedrohungsmodell

Der Center-Betreiber kann versiegelte Geheimnisse nicht lesen, kann aber alte Umschläge zurückhalten oder erneut abspielen (Versionen sind pro Gerät monoton) und sieht Metadaten (wer, welche Karte, wann). Die Kopplung vertraut auf den SAS-Vergleich und den Telefonschlüssel des Genehmigers. Widerruf kann bereits an ein Gerät ausgelieferten Klartext nicht zurückholen: Rotieren Sie nach dem Widerruf das Geheimnis beim vorgelagerten Anbieter.

E2E-Härtung (P2)

  • Beständiges e2e-Flag. Sobald eine Karte e2e: true ist, werden Schreibzugriffe, die das Flag entfernen, abgewiesen (422). Nur eine Owner-Berechtigung (keine Geräteberechtigung) darf es löschen, und nur mit einem Schreibzugriff ohne Geheimnismaterial; spätere Schreibzugriffe folgen dann normalen Regeln.
  • OTP-Parameter. Ein versiegeltes OTP-Geheimnis kann ein reiner Base32-Seed (SHA1, 6 Ziffern, 30 s) oder eine vollständige otpauth://totp/...-URI sein; memories device hosted sealed-get --otp berücksichtigt algorithm (SHA1/SHA256/SHA512), digits (6/8) und period (30/60) aus der URI. device hosted pair gibt den Kopplungsinhalt auch als Terminal-QR-Code aus (stderr).
  • Nach Widerruf erneut versiegeln. Das Widerrufen (oder Ungültigmachen) eines Geräts löscht seine Umschläge und markiert jede betroffene Karte mit needs_rotation (angezeigt in GET /v1/sealed?device=, GET /v1/sealed/rotation?vault=, der Zugriffsliste und der Seite zum erneuten Versiegeln auf dem Telefon). Widerruf kann bereits ausgelieferten Klartext nicht zurückholen: Rotieren Sie das Geheimnis beim vorgelagerten Anbieter und verwenden Sie dann auf dem Telefon Für alle Geräte erneut versiegeln (hosted_reseal_all), das für jedes aktuell genehmigte Gerät mit einer neuen Version versiegelt und das Flag löscht. Widerrufene Geräte werden niemals einbezogen.
  • Telefonwiederherstellung. Das Center hält niemals die Telefonidentität. Bei der Erstellung zeigt das Telefon einen einmaligen Wiederherstellungscode (Base32 des 32-Byte-Seeds + 2-Byte-Prüfsumme, Vierergruppen) zum Aufschreiben; Aus Wiederherstellungscode wiederherstellen (hosted_phone_restore) stellt dieselbe Identität wieder her.
  • Identitätsrotation. Zu einem neuen Telefonschlüssel wechseln (hosted_identity_rotate) erstellt eine neue Identität und sendet POST /v1/devices/identity-rotations mit einem Datensatz, der sowohl vom alten als auch vom neuen Schlüssel signiert ist; nur ein Admin-Mitglied (kein Gerät) darf ihn senden, und dem alten Schlüssel muss bereits für ein Gerät vertraut werden. CLIs fixieren den ersten genehmigenden Telefonschlüssel (hosted-device-trust.json, Vertrauen bei Erstverwendung) und akzeptieren nur Umschlagsignierer, die von dieser Wurzel über verifizierte Rotationen erreichbar sind.
  • Hardwaregestützter Speicher. Der Telefon-Seed wird mit flutter_secure_storage mit den stärksten integrierten Optionen gespeichert: iOS/macOS-Keychain-Zugänglichkeit passcode (nur dieses Gerät, nicht synchronisiert, erfordert einen Gerätecode); durch Android Keystore umschlossener Speicher mit biometrischer oder Geräte-Anmeldedatenfreigabe und resetOnError: false. Grenzen: Der Seed wird zum Signieren/Versiegeln weiterhin in den App-Speicher exportiert (Secure Enclave / StrongBox können X25519/Ed25519 nicht nativ ausführen), daher schützt dies im Ruhezustand, nicht gegen eine kompromittierte laufende App.
  • Transparenzprotokoll. Das Center führt ein nur angehängtes, hashverkettetes Geräteprotokoll (device.pair, device.approve, identity.rotate, device.revoke) unter GET /v1/devices/log. Jeder Eintrag enthält die CLI-Kopplungsselbstsignatur, die Telefonattestierung oder den Rotationsdatensatz. memories device hosted log --verify prüft Kettenverknüpfung, jede Signatur und dass das Protokoll den zuletzt verifizierten Kopf erweitert (hosted-device-log.json); ein neu geschriebener Verlauf wird als Fehler gemeldet.