Eine Seite für Coding-Agents, CI-Bots und andere Automatisierung. Kein Login nötig.
https://tresorix.app/agent-handout
Kein Konto. Kein Passwort. Nur ein Tresor.
Tresorix ist ein Zero-Knowledge-Passwort-Tresor: Einträge werden auf dem Gerät des Nutzers verschlüsselt. Der Server speichert nur Ciphertext — nie Klartext-Passwörter, nie die 24-Wörter-Recovery-Phrase.
Wenn du im Auftrag des Nutzers auf gespeicherte Zugangsdaten zugreifen sollst (Deploy, SSH, API-Tests, Skripte). Es gibt keine mitgelieferte CLI beim Kunden — du implementierst den Zugriff selbst oder nutzt ein vom Kunden bereitgestelltes Hilfsskript.
wrap_key einmalig in den OS-Keyring legen (Anleitung in der UI nach Key-Anlage)..keyfile herunterladen (nur Metadaten in v3, ohne Token in der Datei).tresor_id, key_id, gewünschte entry_id oder Eintragstitel.Der Agent liest nur. Niemals cmdkey, secret-tool store oder Keyring schreiben.
tresorixt{tresor_id}:{key_id} (UUID aus UI/Keyfile)TOKEN~WRAP — Tilde trennt API-Token (cNpm_…) und wrap_key (Base64)Python (Paket keyring):
import keyring
raw = keyring.get_password("tresorix", "t13:KEY_ID_UUID")
api_token, wrap_key = raw.split("~", 1)
Linux: secret-tool lookup service tresorix username t13:KEY_ID
macOS: security find-generic-password -s tresorix -a t13:KEY_ID -w
Ältere Keys können Legacy-Targets (checkn-vault/agent-api-token:…) nutzen — der Mensch sagt, welches Schema gilt.
Basis = https://tresorix.app
1. Umschlag
GET {instance_url}/api/v1/agent/wrap
Authorization: Bearer {api_token}
Antwort: wrap_blob. Bei Widerruf, Pause oder Ablauf: Fehler — stoppen.
2. MEK lokal — mit wrap_key und wrap_blob den Tresor-MEK entschlüsseln (AES-GCM-Umschlag).
3. Einträge
GET {instance_url}/api/v1/entries?limit=50
GET https://tresorix.app/api/v1/entries/{entry_id}
payload_enc mit MEK lokal entschlüsseln → Felder wie secret, username, url.
Der API-Key allein reicht nicht für Klartext — dafür brauchst du wrap_key + gültigen wrap_blob.
Vollständiger Leseablauf: Keyring → API → lokal entschlüsseln → Daten im Skript nutzen. Abhängigkeiten: pip install cryptography keyring
#!/usr/bin/env python3
"""Tresorix — Eintrag lesen (Keyring + API).
Secrets nur im Skript verwenden — nie in Chat, Logs oder Commits."""
from __future__ import annotations
import base64
import json
import urllib.request
import keyring
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
BASE_URL = "https://tresorix.app"
TRESOR_ID = 13 # vom Menschen
KEY_ID = "00000000-0000-0000-0000-000000000000" # Agent-Key-UUID
ENTRY_ID = 94 # gewünschter Eintrag
def keyring_creds(tresor_id: int, key_id: str) -> tuple[str, bytes]:
account = f"t{tresor_id}:{key_id}"
raw = keyring.get_password("tresorix", account)
if not raw or "~" not in raw:
raise RuntimeError("Keyring fehlt oder falsches Format (TOKEN~WRAP)")
token, wrap_key_b64 = raw.split("~", 1)
return token, base64.b64decode(wrap_key_b64)
def api_get(path: str, token: str, retries: int = 8) -> dict:
import time
import urllib.error
url = f"{BASE_URL.rstrip('/')}{path}"
headers = {"Authorization": f"Bearer {token}", "Accept": "application/json"}
for attempt in range(retries + 1):
req = urllib.request.Request(url, headers=headers)
try:
with urllib.request.urlopen(req, timeout=45) as resp:
return json.loads(resp.read().decode())
except urllib.error.HTTPError as exc:
if exc.code != 429 or attempt >= retries:
raise
raw = exc.read().decode()
try:
body = json.loads(raw)
wait = int(body.get("retry_after", 2))
except (ValueError, json.JSONDecodeError, TypeError):
wait = 2
time.sleep(max(wait, 2))
def aes_gcm_decrypt(key: bytes, blob: bytes) -> bytes:
return AESGCM(key).decrypt(blob[:12], blob[12:], None)
def load_entry(entry_id: int) -> dict[str, str]:
token, wrap_key = keyring_creds(TRESOR_ID, KEY_ID)
wrap_blob_b64 = api_get("/api/v1/agent/wrap", token)["wrap_blob"]
mek = aes_gcm_decrypt(wrap_key, base64.b64decode(wrap_blob_b64))
entry = api_get(f"/api/v1/entries/{entry_id}", token)["entry"]
plain = aes_gcm_decrypt(mek, base64.b64decode(entry["payload_enc"]))
payload = json.loads(plain.decode())
return {
"title": str(payload.get("title") or ""),
"username": str(payload.get("username") or ""),
"secret": str(payload.get("secret") or ""),
"url": str(payload.get("url") or ""),
"notes": str(payload.get("notes") or ""),
}
if __name__ == "__main__":
data = load_entry(ENTRY_ID)
# Nur lokal weiterverwenden — Secret nicht ausgeben:
print(data["title"], data["username"], "***")
Das Ergebnis-Dict (load_entry) kannst du im Skript an andere Funktionen übergeben — z. B. SSH, HTTP-Client, Deploy. Nicht in Agent-Chats oder Tickets posten.
wrap_key, MEK oder Klartext in Chat, Wiki, Issues, Logs, Commits oder .env.cNpm_ff56…, Secret ***).rate_limited): Feld retry_after (Sekunden) bzw. Header Retry-After abwarten — mindestens so lange warten, dann erneut (z. B. max. 8×). Nicht sofort wiederholen.Markieren oder „Gesamttext kopieren“ — dann in den Agent einfügen.