Memories / Dokumentation

Auf dieser Seite

Vault-Autorisierung

Dieses Dokument beschreibt den Autorisierungsdienst des lokalen Daemons und die HTTP-Autorisierungsschnittstelle des SaaS Center. Die folgenden lokalen RPC-Operationen stehen im gemeinsamen Core sowie in den Autorisierungswerkzeugen von CLI und MCP zur Verfügung. Die vorhandenen Befehle memories mcp grant, memories mcp revoke, der Import von Center-Tickets und die Vault-Audit-Befehle verwenden die aktualisierten Core-Prüfungen.

Rollen und Obergrenzen für Berechtigungsbereiche

Vault-Rolle Maximaler Grant-Berechtigungsbereich Darf ausstellen oder delegieren?
Reader read Nein
Editor read_write Nein
Admin read_write_delete Ja
Owner allow_all Ja

Ein ausgelassener Berechtigungsbereich bedeutet Lesen, nicht allow_all. Dies gilt für lokale Grants, die Ausstellung von Center-Tickets, statische gehostete Grants und die Erstellung von Mitgliedern. Explizites altes write: true wählt weiterhin read_write; write: false wählt read. write bleibt ein ausschließlich zum Schreiben berechtigender Bereich. allow_all erfordert eine explizite Auswahl und einen Owner als Aussteller, obwohl es derzeit dieselben Inhaltsoperationen für gewöhnliche Assets abdeckt wie read_write_delete.

Bei der Ausstellung werden sowohl die aktuelle Vault-Rolle des Ausstellers als auch bei einem Bearer-Aufrufer der Berechtigungsbereich des ausstellenden Grants geprüft. Ein Grant kann keinen anderen Vault autorisieren, keine der beiden Obergrenzen überschreiten und seinen übergeordneten Grant nicht überdauern. Die Laufzeiten betragen 1–60 Minuten. Anforderungen nach weitergehenden oder längeren Berechtigungen schlagen fehl, statt den angeforderten Bereich stillschweigend einzuschränken. Empfänger müssen bereits Mitglieder des ausgewählten Vaults sein. Ein Inhalts-Grant kann einem Mitglied zusätzlichen Inhaltszugriff gewähren, ändert aber seine Rolle nicht: Ein Editor oder Reader mit einem weitreichenden Grant kann weiterhin weder delegieren noch Anfragen genehmigen.

Grant-Datensätze enthalten id, vault, scope, issued_by (Mitglieds-ID), grantee, parent (ID des ausstellenden Grants oder null), depth und expiry in Unix-Sekunden. Eine Grant-ID ist eine zufällige opake Kennung, die unabhängig von ihrem Bearer-Token ist. Die Ausstellung gibt das Token einmal zurück; Zugriffs- und Grant-Auflistungen enthalten es niemals. Grant- und Anfrage-IDs sowie Principal-IDs sind opake, kanonische Kennungen; Vault-IDs für Clients behalten die normale Kurz-ID-Projektion bei.

Die lokale Grant-Ausstellung durch Admin/Owner erfordert einen entsperrten Vault, keine Rechteerhöhung im Terminal. Auch ein Widerruf benötigt keine Rechteerhöhung, ist aber nur dem Aussteller des Grants oder einem aktuellen Admin/Owner seines Vaults erlaubt. Ein Widerruf wirkt transitiv. Das Entfernen eines Ausstellers oder Empfängers oder das Herabsetzen der Rolle eines Ausstellers unter seinen ausgestellten Berechtigungsbereich macht betroffene Grants und ihre Nachfolger ungültig, sobald die Richtlinie übernommen wird. Dies schließt durch Synchronisierung importierte Richtlinienänderungen und Änderungen nach einem Neustart ein. Grants werden im verschlüsselten gerätelokalen Store nur mit dem SHA-256-Bearer-Hash und Autorisierungsmetadaten gespeichert; die Authentifizierung vergleicht Hashes in konstanter Zeit. Widerruf und Entfernung von Nachfolgern werden zusammen mit dem verschlüsselten Zustand übernommen. Das Sperren entfernt die Grants und Store-Schlüssel aus dem Arbeitsspeicher und macht alle Grants bis zum Entsperren unbrauchbar; nicht abgelaufene Grants werden nach dem Entsperren oder einem Daemon-Neustart wieder nutzbar. Der absolute Ablaufzeitpunkt wird gespeichert, und abgelaufene Grants und ihre Nachfolger werden beim Laden und bei Daemon-Ticks entfernt. Grants werden nicht durch Vault-Synchronisierung oder Wiederherstellungssicherungen exportiert.

Mitgliedschaftsänderungen und Gerätegenehmigungen behalten ihre bisherigen Prüfungen auf Rechteerhöhung zusätzlich zur neuen Admin/Owner-Anforderung bei. Das Erstellen einer Einladung erfordert nun eine Admin/Owner-Mitgliedschaft in mindestens einem lokalen Vault. Aufrufer ohne Vaults und Aufrufer mit ausschließlich Editor/Reader-Mitgliedschaften werden sicher abgewiesen. Admins können Admin-Mitgliedschaften verwalten, aber keinen Owner hinzufügen, entfernen oder ändern. Eigentümerwechsel verwenden die signierte Eigentumsübertragung und bewahren genau einen Owner.

Berechtigungsanfragen

Benannte Empfänger und Delegationstiefe

Sowohl der Daemon als auch das gehostete Center lehnen die Ausstellung an einen Empfänger ab, dessen Rolle höher als die effektive Rolle des Ausstellers ist, selbst wenn der angeforderte Inhaltsbereich nur read ist. Center lehnt außerdem den reservierten Empfänger center-admin ab, einschließlich früher gespeicherter Grants mit diesem Subjekt.

Ein Grant-Aufrufer verwendet Grant-Berechtigungen mit einem Subjekt, das von seinem tatsächlichen Aussteller abweicht (subject != issued_by). Solche Aufrufer dürfen Anfragen erstellen, können aber keine Berechtigungsanfrage genehmigen, ablehnen, abbrechen oder einlösen, auch nicht ihre eigene. Der Daemon gibt Unauthorized zurück; Center gibt HTTP 403 zurück. Diese Aufrufer sind keine zulässigen Genehmiger. Für selbst ausgestellte Grants gelten weiterhin die bisherigen Anfrageregeln; das Einlösen im Center erfordert weiterhin die dauerhafte Mitglieds-Zugangsinformation des Antragstellers. Dauerhafte Center-Mitglieds-Bearer stellen Mitgliedsberechtigungen dar, keine delegierten Grant-Berechtigungen.

Der Daemon behält seine exakte Bindung an die Zugangsinformation des Antragstellers bei: Eine mit einem Bearer für einen benannten Empfänger erstellte Anfrage kann später nicht mit einer anderen Mitglieds-Zugangsinformation eingelöst werden. Erstellen Sie eine solche Anfrage erneut mit der Mitglieds- oder selbst ausgestellten Zugangsinformation, die sie einlösen wird. Center bindet das Einlösen stattdessen an den dauerhaften Mitglieds-Bearer des Antragstellers.

Beide Implementierungen definieren pub const MAX_DELEGATION_DEPTH: u32 = 2. Direkt von einem Mitglied ausgestellte Grants haben Tiefe 1. Eine Ausstellung unter Verwendung von Grant-Berechtigungen, einschließlich des übergeordneten Grants einer aufgeschobenen Genehmigung zum Einlösezeitpunkt, hat die Tiefe parent.depth + 1; Tiefe 3 wird abgelehnt. depth wird gespeichert und in Grant-Zusammenfassungen, Ausstellungsantworten, Zugriffsansichten und Listen ausgestellter Grants enthalten. Alte Datensätze ohne depth werden aus ihrer übergeordneten Kette rekonstruiert (ein Grant ohne übergeordneten Grant hat Tiefe 1). Fehlende, zyklische oder überlange Grant-Abstammung wird sicher abgewiesen und beim Laden entfernt. Die internen dauerhaften Mitglieds-Zugangsinformationen des Centers haben Tiefe 0 und sind keine delegierten Grants.

Delegierte Ausstellung bewahrt den tatsächlichen Aussteller über die übergeordnete Kette, statt einen benannten Empfänger zu einem selbst ausstellenden Principal zu machen. Vorhandene alte Ketten werden ebenfalls geprüft, wenn der tatsächliche Aussteller des Aufrufers ermittelt wird.

Aufgeschobene alte Genehmigungen, die mit einem Grant für einen benannten Empfänger aufgezeichnet wurden, werden beim Einlösen ebenfalls sicher abgewiesen; holen Sie eine neue Genehmigung von zulässigen Mitgliedsberechtigungen ein.

Inkompatible Änderungen: Empfänger mit höherer Rolle und center-admin-Empfänger können keine Grants mehr erhalten; Bearer für benannte Empfänger können nicht mehr an Berechtigungsentscheidungen, Abbruch oder Einlösen teilnehmen; Ketten mit mehr als zwei Grants sind nicht mehr nutzbar. Verwenden Sie für Berechtigungsentscheidungen und das Einlösen eine Mitglieds-Zugangsinformation und stellen Sie einen neuen Root-Grant aus, wenn eine weitere Delegation die Grenze überschreiten würde.

Jedes aktuelle Mitglied darf eine Anfrage für seinen eigenen Zugriff in einem Vault einreichen:

{
  "op": "request_create",
  "vault": "VAULT",
  "target": {"type": "scope", "scope": "read_write"},
  "reason": "Update the shared project notes",
  "duration_minutes": 15,
  "approvers": []
}

target ist entweder {"type":"scope","scope":"..."} (der Bereich ist standardmäßig read) oder {"type":"role","role":"editor"}. Begründung, Laufzeit und Genehmiger sind optional. Eine bereichsbezogene Genehmigung gilt standardmäßig 30 Minuten, wenn die Laufzeit ausgelassen wird. Rollenänderungen sind dauerhaft: Eine Laufzeit in einer Rollenanfrage wird abgelehnt, und zeitlich begrenzte Grant-Aufrufer können keine dauerhafte Rollenänderung genehmigen. Das Genehmigen einer Rollenanfrage erfordert dieselbe an den Aufrufer gebundene Rechteerhöhung wie direkte Änderungen von Mitgliedsrollen. Ein Owner, der eine Anfrage für die Owner-Rolle genehmigt, führt eine signierte Eigentumsübertragung aus.

Eine leere Genehmigerliste verteilt die Anfrage an alle aktuellen Admin/Owner- Mitglieder dieses Vaults. Andernfalls dürfen nur die aufgeführten Mitglieds-IDs entscheiden; jede aufgeführte ID muss bei der Erstellung ein Admin/Owner-Mitglied sein, und die Zulässigkeit wird bei der Entscheidung erneut geprüft. Reader und Editor dürfen nicht als Genehmiger aufgeführt werden. Der Antragsteller kann seine eigene Anfrage nicht genehmigen oder ablehnen, auch nicht als Admin/Owner oder benannter Genehmiger; er darf sie weiterhin abbrechen. Eine Bereichs- oder Rollengenehmigung muss innerhalb der Rolle und des Bearer-Bereichs des Genehmigers liegen, und der bereichsbezogene Ablaufzeitpunkt muss in den des übergeordneten Grants passen. Eine Genehmigung außerhalb dieser Grenzen lässt die Anfrage ausstehend.

Anfragen haben genau einen Übergang von pending zu approved, rejected oder cancelled. Nur der Antragsteller kann eine ausstehende Anfrage abbrechen. Eine Bereichsgenehmigung zeichnet Grant-Parameter auf, ohne einen Bearer zu erzeugen. Der Antragsteller verwendet request_claim einmal, um das Token zu erzeugen und zu erhalten; request_list gibt nur Metadaten zurück. Erstellung/Generation und Grant-Laufzeit beginnen beim Einlösen, begrenzt durch den aufgezeichneten Ablaufzeitpunkt des übergeordneten Grants. Genehmigungs- und Einlösestatus überstehen Sperren/Neustarts, aber widerrufene oder abgelaufene Genehmigungsberechtigungen können kein Einlösen autorisieren. Kein Klartext-Token wird im Anfragezustand oder im gespeicherten Store-Zustand aufbewahrt. Eingelöste Grants überstehen Sperren/Neustarts als Hashes und Metadaten. Anfragen und Tokens werden nicht bei der Vault-Synchronisierung exportiert.

request_list gibt die Anfragen des Aufrufers (einschließlich entschiedener) sowie ausstehende Anfragen zurück, über die er entscheiden darf. Andere Mitglieder können eine gerichtete Anfrage nicht einsehen. Ein Vault unterstützt höchstens 1,000 gespeicherte Anfragen; Begründungen sind auf 4,096 Bytes begrenzt. Sowohl im lokalen Daemon als auch in einem gehosteten Center dürfen höchstens 10,000 Grants gleichzeitig aktiv sein.

Grenzen für ausstehende Anfragen: Ein Antragsteller darf höchstens 20 ausstehende Anfragen pro Vault haben, ein Vault höchstens 200 ausstehende Anfragen; eine Erstellung über der Grenze schlägt mit einem Limitfehler fehl (HTTP 429 in einem gehosteten Center). Ausstehende und genehmigte, aber nicht eingelöste Anfragen laufen nach 7 Tagen ab (auditiert als request.expire, Akteur system); entschiedene Anfragen werden 30 Tage nach ihrem letzten Übergang entfernt.

RPC-Operationen und Schnittstellen

Die JSON-op-Namen des Daemons sind:

Operation Felder Berechtigung
access_list vault Admin/Owner
grant_list vault Admin/Owner sehen alle; andere aktuelle Mitglieder sehen nur von ihnen ausgestellte Grants
grant_issue vault, minutes, optional scope, grantee Admin/Owner
grant_revoke vault, id Aussteller oder Admin/Owner
request_create vault, target, optional reason, duration_minutes, approvers Jedes Mitglied
request_list vault Eigene oder zulässige ausstehende Anfragen
request_approve vault, id Zulässiger Admin/Owner
request_claim vault, id Ursprüngliche Antragsteller-Zugangsinformation der genehmigten Bereichsanfrage; nur einmal
request_reject vault, id, optional reason Zulässiger Admin/Owner
request_cancel vault, id Antragsteller der ausstehenden Anfrage
audit vault, verify_only Admin/Owner

Die alten Operationen mcp_grant und mcp_revoke werden weiterhin unterstützt. Bearer-Aufrufer dürfen diese Autorisierungs-RPCs nur für den Vault ihres Grants verwenden; dies erlaubt MCP weder, eine Rechteerhöhung im Terminal zu übernehmen, noch auf gespeicherte Zugangsdaten zuzugreifen. Die mobile FFI lehnt Grant-Verwaltung und die neuen Berechtigungsanfrage-Operationen weiterhin ab; Änderungen an der nativen ABI sind nicht erforderlich.

access_list gibt principals, gruppiert unter owner, admin, editor und reader, sowie aktive grants, devices (autorisierte, nicht widerrufene Geräte aus der Vault-Richtlinie: device, besitzendes member, name; die Richtlinie zeichnet keine Erstellungszeit auf), pending_requests und approved_unclaimed_requests zurück (jeweils mit id, requester, target als Bereich/Rolle, approvers-Liste oder "broadcast", created und expires in Unix-Sekunden). Die Sichtbarkeit bleibt auf Admin/Owner beschränkt. grant_list gibt {"vault":"VAULT","grants":[...]} ohne Principal-Gruppen zurück. Jeder ausgestellte Grant enthält id, parent (null für einen Root-Grant), issued_by, grantee, scope, vault, expiry in Unix-Sekunden, generation, depth und, sofern verfügbar, created in Unix-Sekunden. Die lokale Generation ist die bei der Ausstellung übernommene Zustandsgeneration, nicht die aktuelle Generation bei der Auflistung. Abgelaufene/widerrufene Grants sind ausgeschlossen. Admin/Owner können alle Grants im Vault auflisten; andere aktuelle Mitglieder dürfen nur ihre eigenen ausgestellten Grants auflisten, nicht lediglich empfangene Grants. Bearer-Aufrufer bleiben an den Vault ihres Grants gebunden. Weder Token noch Bearer-Hash oder Asset-Inhalt erscheinen in einer der Antworten. Daemon-RPC, MCP grant_list und memories grant list VAULT teilen diese Dienstantwort.

Die CLI-Wrapper sind mit diesen exakten Befehlen implementiert (IDs sind opak):

memories access list VAULT
memories grant issue VAULT --minutes N [--scope S] [--grantee ID]
memories grant list VAULT
memories grant revoke VAULT ID
memories request create VAULT [--scope S | --role R] [--reason T] [--duration M] [--approver ID]...
memories request list VAULT
memories request approve VAULT ID
memories request claim VAULT ID
memories request reject VAULT ID [--reason T]
memories request cancel VAULT ID
memories audit list VAULT [--verify-only]

Die alte Syntax memories audit VAULT [--verify] wird weiterhin unterstützt. Der Bereich ist standardmäßig read; lokale Bereichsanfragen ohne Laufzeit behalten den 30-Minuten-Standard für Genehmigungen des Daemons bei. Rollenanfragen dürfen keine Laufzeit enthalten. Die Ausgabe ist JSON im normalen CLI-Umschlag.

Die Entsprechungen im gehosteten Center verwenden die HTTP-Autorisierungsrouten:

memories center access VAULT
memories center grant issue VAULT --minutes N [--scope S] [--grantee ID]
memories center grant list [VAULT]
memories center grant revoke ID
memories center request create VAULT [--scope S] [--reason T] [--duration M] [--approver ID]...
memories center request list [VAULT]
memories center request approve ID
memories center request claim ID
memories center request reject ID [--reason T]
memories center request cancel ID
memories center audit [--vault V] [--format json|jsonl]

Diese Befehle akzeptieren --center-url und verwenden andernfalls MEMORIES_CENTER_URL oder das konfigurierte SaaS Center. Sie verwenden MEMORIES_CENTER_TOKEN, wenn gesetzt, andernfalls MEMORIES_CENTER_ADMIN_TOKEN; bei Berechtigungsfehlern wird kein erneuter Versuch mit einem anderen Bearer unternommen. Gehostete Anfragen unterstützen Bereiche, keine lokalen Rollenänderungen. Der Bereich ist standardmäßig read, die Anfragelaufzeit 30 Minuten. Der JSONL-Audit-Export gibt einen JSON-Eintrag pro Zeile ohne CLI-Umschlag aus; andere Ausgaben verwenden den JSON-Umschlag.

Die MCP-Werkzeuge des Daemons sind access_list, grant_issue, grant_list, grant_revoke, request_create, request_list, request_approve, request_claim, request_reject, request_cancel und audit_list. Ihre Argumente folgen den obigen RPC-Feldern (minutes für die Grant-Ausstellung, target und duration_minutes für die Anfrageerstellung sowie verify_only für Audits). Ein ausgelassener Grant-Bereich oder ein ausgelassenes Anfrageziel ist standardmäßig read. Jeder Aufruf verwendet die vorhandene MCP-Capability, niemals eine Rechteerhöhung im Terminal oder einen Bearer des gehosteten Centers.

Das SaaS Center implementiert GET /v1/access/{vault}, POST/GET /v1/grants, DELETE /v1/grants/{id}, POST/GET /v1/requests, POST /v1/requests/{id}/approve|claim|reject|cancel und das nur für Admin/Owner verfügbare GET /v1/audit. Diese Routen erfordern den gehosteten Modus (--data). Siehe center.md für die exakten HTTP-Bodys, Abfrageparameter, Antworten und gespeicherten Dateien.

SaaS-Center-Autorisierung

Gehostete Mitglieder haben eine optionale explizite role (reader, editor, admin, owner), unabhängig von ihrem Inhaltsbereich scope. Wenn role ausgelassen wird, werden vorhandene Bereichsstufen auf Reader (read), Editor (write/read_write), Admin (read_write_delete) oder Owner (allow_all) abgebildet. Der Betreiber-Bearer handelt als center-admin-Owner über alle gehosteten Vaults hinweg. Statische Bearer-Principals verwenden static:OPAQUE_ID-IDs und dieselbe Zuordnung von Bereichen zu Rollen. Mitglieds-IDs dürfen den reservierten Namen center-admin nicht verwenden. Ein Inhaltsbereich erhebt einen Reader/Editor-Empfänger nicht in eine administrative Rolle.

POST /v1/grants setzt scope standardmäßig auf read und duration_minutes auf 30; minutes ist ein Alias für die Laufzeit. Die Ausstellung erfordert die Rolle Admin/Owner mit denselben Rollen-, Bereichs-, Vault- und Ablaufgrenzen wie bei der lokalen Ausstellung. Antworten verwenden subject für den Empfänger und enthalten parent, issued_by, expiry, generation und depth. Grant-Tokens erscheinen nur in Ausstellungs-/Einlöseantworten, niemals in Genehmigungen, Auflistungen oder im Audit. Für Mitgliedsaufrufer ist der Empfänger standardmäßig der Aussteller; ein explizites grantee muss einen vorhandenen Principal im ausgewählten Vault bezeichnen. Eine Betreiberausstellung ohne grantee erstellt einen anonymen Grant-Principal, der durch seine Grant-ID identifiziert wird, niemals ein center-admin-Subjekt. Dies gilt auch für die Ausstellung gehosteter Tickets.

Jedes gehostete Mitglied hat einen gespeicherten Generationszähler. Erzeugte Grants frieren sowohl die Aussteller- als auch die Empfängergeneration bei der Ausstellung ein; die Authentifizierung aktualisiert sie niemals. Das Ändern des Bereichs, der Rolle oder des Vaults eines Mitglieds oder sein Entfernen erhöht nur die Generation dieses Mitglieds. Zähler entfernter Mitglieder bleiben bestehen, sodass das erneute Erstellen einer ID ihre Generation nicht zurücksetzt. Entfernen oder Aktualisieren widerruft Grants, die von diesem Mitglied oder an dieses Mitglied ausgestellt wurden, und alle Nachfolger mit Audit-Aufzeichnungen, während unbeteiligte Grants weiter funktionieren. Das öffentliche Feld generation ist die Empfängergeneration bei der Ausstellung. Statische und Betreiber-Principals haben eine feste Generation. Dauerhafte Mitglieds-Zugangsinformationen werden nur beim expliziten Richtlinienübergang neu hergestellt, nicht durch die Authentifizierung.

Gehostete erzeugte Grants überstehen Neustarts in der nur für den Eigentümer zugänglichen Datei DIR/grants.json, die ausschließlich SHA-256-Bearer-Hashes, eingefrorene Generationen, Ablauf-/übergeordnete Metadaten und Widerrufe enthält. Der Hash-Vergleich erfolgt in konstanter Zeit. Abgelaufene Grants und ihre Nachfolger werden beim Laden, regelmäßig und während der Authentifizierung/Ausstellung entfernt. Sperren entfernt Store-Schlüssel und setzt Grants aus, ohne sie zu widerrufen; nicht abgelaufene Grants und statische/dauerhafte Zugangsinformationen werden nach dem Entsperren wieder nutzbar. Persistenzfehler sperren den Dienst und erfordern eine Reparatur/einen Neustart durch den Betreiber, statt eine Wiederbelebung zu riskieren.

POST /v1/requests akzeptiert vault, optional scope, reason, duration_minutes (Alias duration) und approvers. Leere/ausgelassene approvers verteilen die Anfrage über die Listen ausstehender Anfragen zulässiger Admin/Owner; angegebene IDs richten die Anfrage gezielt. GET /v1/requests gibt ausstehende Anfragen zurück, die dem Aufrufer gehören oder in seinen Genehmigungsbereich fallen, sowie genehmigte, nicht eingelöste Anfragen des Antragstellers, optional nach vault gefiltert. Genehmigung und Ablehnung erfordern beide die Rollen-, Bereichs-, Vault- und Ablaufberechtigung des ausgewählten Genehmigers. Der Antragsteller kann seine eigene Anfrage nicht genehmigen oder ablehnen, auch nicht als Admin/Owner oder benannter Genehmiger; nur der Antragsteller darf abbrechen. Eine Entscheidung wird serialisiert und gespeichert; Wiederholungen geben 409 zurück. Die Genehmigung gibt nur request-Metadaten mit status: approved, claimed: false und validierten Bereichs-/Laufzeit-/Ausstellergrenzen zurück; sie erzeugt keinen Grant und gibt kein Token zurück. Anschließend ruft der Antragsteller POST /v1/requests/{id}/claim mit seinem dauerhaften Mitglieds-Bearer auf und erhält request sowie eine einmalige grant-Antwort. Genehmiger, andere Mitglieder und andere Grants für dasselbe Subjekt können mit diesen Zugangsinformationen nicht einlösen. Ein zweites Einlösen gibt 409 zurück. Generation, Erstellungszeit und Laufzeit beginnen beim Einlösen, wobei der Ablaufzeitpunkt durch den aufgezeichneten Ablaufzeitpunkt der Genehmigungsberechtigung begrenzt wird. Widerrufene/abgelaufene genehmigende Zugangsinformationen oder geänderte Mitgliedsgenerationen können nicht zum Einlösen verwendet werden.

Der Daemon verwendet denselben Ablauf mit aufgeschobener Erzeugung für Bereichsanfragen: request_approve speichert Genehmigungsgrenzen und request_claim gibt Grant-Metadaten sowie token einmal zurück. Lokale OS-authentifizierte Aufrufer müssen weiterhin das anfragende Mitglied sein; MCP muss exakt die Capability vorlegen, die die Anfrage erstellt hat, keinen anderen Grant für dasselbe Subjekt. Listen geben niemals Tokens zurück. Rollengenehmigungen bleiben unmittelbare Richtlinienänderungen und haben keinen einlösbaren Grant. Verschlüsselter Store-Zustand und DIR/requests.json enthalten nur Anfragemetadaten; Grants speichern nur Bearer-Hashes. Beim Start werden Center-Entscheidungen und Einlösungen mit dem verifizierten Audit abgeglichen, sodass unterbrochene Metadatenspeicherungen keine Entscheidung oder eingelöste Anfrage wieder öffnen können. Wenn eine erfolgreiche Einlöseantwort verloren geht, kann das Token nicht erneut abgerufen werden; fordern Sie stattdessen eine neue Genehmigung an.

Audit-Format und Verifizierung

Lokale Audit-Einträge behalten vault, previous, sequence, timestamp, action, object, result, Signaturzertifikat und Signatur bei. Neue optionale Felder auf oberster Ebene sind actor, subject (Empfänger), scope, expiry, parent, reason, issued_by, via_grant und request_id. Actor identifiziert das handelnde Mitglied; der Signierer identifiziert das Daemon-Gerät, das das Ereignis aufzeichnet. Eine delegierte Aktion kann daher unterschiedliche Akteure und signierende Benutzer haben. Audit-Einträge enthalten kein Passwort, keine gespeicherte Zugangsinformation und kein Bearer-Token.

Mit Grant-Berechtigungen erstellte Einträge enthalten issued_by (den tatsächlichen Aussteller) und via_grant (die Grant-ID des Aufrufers); actor bleibt das Grant-Subjekt. Die Ausnahme für Ausstellungsereignisse (mcp.grant / Center grant.issue) zeichnet den tatsächlichen Aussteller als actor und den Empfänger als subject auf, auch bei delegierter Ausstellung. Beide optionalen Felder verwenden serde-Standardwerte und werden bei Abwesenheit ausgelassen, wodurch Serialisierung und Verifizierung älterer signierter Audits und Center-JSONL-Protokolle erhalten bleiben. Gehostete Inhaltsaudits tragen dieselbe Zuordnung im gemeinsamen Store.

Audits sind pro Gerät signierte Hash-Ketten. previous verweist auf den SHA-256-Hash des vorherigen serialisierten signierten Eintrags, und die Audit-Map verwendet diese Hashes als Schlüssel. Vault::verify validiert Signaturen, Hashes, Sequenzkontinuität und die bestehenden Invarianten des Vault-Verlaufs. Alte Datensätze lassen alle neuen Felder aus und behalten ihre exakten alten Signaturbytes und Hashes bei. Neue Felder verwenden serde-Standardwerte und werden bei Abwesenheit ausgelassen; ausgefüllte Details werden durch die Signatur abgedeckt.

Zu den Ereignissen gehören device.authorize, mcp.grant, mcp.grant.center, mcp.revoke, session.lock, session.unlock und request.create|request.approve|request.claim|request.reject|request.cancel neben bestehenden Mitgliedschafts- und Geräteereignissen. Explizite Sperren geben Audit-Persistenzfehler weiter, löschen aber dennoch den entsperrten Zustand. Lebenszyklus-/Inaktivitätssperren versuchen ein Audit und löschen den Zustand immer, selbst wenn die Speicherung fehlschlägt; sie dürfen Geheimnisse nicht entsperrt lassen, um einen Audit-Datensatz zu bewahren. Fehler im gesperrten Zustand können kein Audit signieren.

Das SaaS Center hat eine separate nur anhängbare SHA-256-Kette in DIR/audit.jsonl mit Modus 0600, nicht das lokale signierte Audit-Format. GET /v1/audit erfordert Admin/Owner, akzeptiert vault und format=json|jsonl und verifiziert die vollständige Kette vor dem Filtern/Exportieren. An einen Vault gebundene Administratoren können die Ereignisse eines anderen Vaults nicht lesen; der Betreiber kann auch globale Sperr-/Entsperr-/Registrierungsereignisse sehen. Einträge enthalten sequence, timestamp, prev_hash, hash, action, actor, subject, scope, vault, expiry, parent, reason, request_id und object; optionale Details sind null. Der Hash deckt das serialisierte Tupel (sequence, timestamp, prev_hash, event_fields) ab; prev_hash ist für den ersten Eintrag null und danach der Hash des vorherigen Eintrags.

verify_audit_chain(path) in crates/center/src/saas/audit.rs prüft Hashes, Sequenzkontinuität, vorherige Hashes und vollständige JSONL-Zeilen. Beim Start wird die vorhandene Datei verifiziert; Anhängen/Lesen vergleichen außerdem ihren Kopf mit dem bekannten Kopf des laufenden Prozesses. Ereignisse umfassen device.authorize, grant.issue, grant.revoke, member.add|member.set|member.remove, session.lock|session.unlock und request.create|request.approve|request.claim|request.reject|request.cancel. Einlöseereignisse zeichnen den Antragsteller als Akteur und die erzeugte Grant-ID als Objekt auf, niemals das Token. Fehler beim Anhängen von Audits oder beim Speichern von Anfragen/Mitgliedern sperren den gehosteten Dienst, setzen restart_required und blockieren das Entsperren aus der Ferne, bis ein Betreiber ihn repariert und neu startet. Autorisierungsänderungen und Berechtigungsentscheidungen werden ebenfalls angehalten, solange restart_required gesetzt ist; schreibgeschützte Einsicht durch den Betreiber bleibt verfügbar. Diese Ketten ohne Schlüssel sind kein Schutz gegen einen Betreiber, der das gesamte Protokoll neu schreibt oder alle Dateien zurücksetzt; stärkere Zusicherungen benötigen externe Verankerungen des Kettenkopfs.

Bedrohungsmodell und Verhaltensänderungen

  • Lokale OS-authentifizierte Aufrufer handeln als Mitglied des entsperrten Geräts. Bösartige Prozesse desselben Benutzers bleiben innerhalb der bestehenden Vertrauensgrenze des Endpunkts.
  • Capability-Bearer sind Geheimnisse; jeder, der einen besitzt, kann seine begrenzten Berechtigungen bis zum Widerruf, Sperren oder Ablauf verwenden. Ein Bearer kann seinen eigenen Bereich nicht erweitern, seinen Vault nicht verlassen, den Ablaufzeitpunkt nicht verlängern und die Delegationsrolle seines Subjekts nicht umgehen.
  • Ein Widerruf löscht zuvor kopierten Klartext oder Schlüssel nicht und kann offline befindliche Peers nicht sofort erreichen. Richtlinien- und Grant-Ungültigkeit wirkt auf dem Daemon, der die aktualisierte Richtlinie übernommen hat.
  • Hash-Ketten erkennen Änderungen gegenüber bekanntem Zustand, nicht das vollständige Zurücksetzen der Datenbank oder von einem kompromittierten Gerät ausgelassene Ereignisse. Externe Verankerungen und ein unabhängiges Sicherheitsaudit bleiben für stärkere Zusicherungen erforderlich.
  • Inkompatible Änderungen: Ausstellung ohne Bereich ist schreibgeschützt; Editor/Reader können keine Grants oder Einladungen erzeugen; Audit-Zugriff erfordert Admin/Owner statt Rechteerhöhung; Mitgliedsänderungen machen delegierte Grants ungültig. Neue Admin/Owner-Grant-Ausstellung und Widerruf durch Aussteller/Admin erfordern keine Rechteerhöhung mehr. Einladungserstellung ohne Vault wird abgelehnt, statt einen Aufrufer stillschweigend als Administrator zu behandeln.
  • Inkompatible Änderung: Genehmigung erzeugt oder liefert keinen Bearer mehr, und Anfragelisten liefern keinen genehmigten Bearer mehr. Antragsteller müssen ausdrücklich einmal einlösen. Zuvor genehmigte Anfragen ohne aufgezeichnete Grenzen einer aufgeschobenen Genehmigung können nicht eingelöst werden; erstellen Sie eine neue Anfrage. Bestehende separat ausgestellte Grants unterliegen weiterhin ihren normalen Ablauf-/Widerrufsregeln.

Siehe SECURITY.md für Grenzen und center.md für die separaten Vertrauensgrenzen des nur für Tickets verwendeten sowie des mit Betreiberschlüsseln gesicherten gehosteten Centers.

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, abgebrochene, abgelaufene und genehmigte, aber nicht eingelöste Anfragen zählen nicht zu diesen Grenzen. (Dies ersetzt die alte globale Grenze von 1000 Anfragen, die jede jemals erstellte Anfrage zählte.) Bei Überschreiten einer Grenze gibt der Daemon einen Limitfehler und Center HTTP 429 zurück.
  • PENDING_REQUEST_TTL = 7 days: Eine ausstehende Anfrage, die älter ist, wechselt in den Status expired. Sie wird als request.expire mit Akteur system auditiert und kann nicht mehr genehmigt werden. Eine genehmigte Bereichsanfrage, die nicht innerhalb von 7 Tagen nach der Genehmigung eingelöst wurde, läuft auf dieselbe Weise ab und kann danach nicht mehr eingelöst werden.
  • REQUEST_RETENTION = 30 days: Abgelehnte, abgebrochene, abgelaufene oder eingelöste Anfragen werden diese Zeit nach ihrem letzten Übergang gelöscht (Zeitstempel decided, oder created bei älteren Datensätzen ohne diesen).
  • Ablauf und Bereinigung erfolgen bei Bedarf: Der Daemon führt sie zu Beginn jeder Autorisierungsanfrage aus, Center beim Erstellen, Auflisten, Entscheiden und Einlösen von Anfragen. Beim Start führt sie nichts aus.
  • Der Abgleich beim Center-Start ignoriert Audit-Einträge für bereinigte Anfragen und akzeptiert request.expire-Einträge. Eine expired-Anfrage muss einen auditierten Ablauf haben. Anfrage-IDs sind zufällige 128-Bit-Werte, die niemals wiederverwendet werden; eine bereinigte Anfrage (einschließlich einer eingelösten) existiert daher nicht mehr und kann nicht eingelöst werden. Deshalb führt Center keine separate Tombstone-Menge.