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 = 20undMAX_PENDING_PER_VAULT = 200zä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 Statusexpired. Sie wird alsrequest.expiremit Akteursystemauditiert 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 (Zeitstempeldecided, odercreatedbei ä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. Eineexpired-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.