Offline Mode
Offline mode provides full cryptographic attestation without requiring an API key. Perfect for development, testing, and air-gapped environments.
Quick Start
from glacis import Glacis
# No API key neededglacis = Glacis(mode="offline")
receipt = glacis.attest( service_id="local-dev", operation_type="inference", input={"prompt": "What is 2+2?"}, output={"response": "4"},)
print(f"Receipt ID: {receipt.attestation_id}") # oatt_xxx (offline attestation)print(f"Witness status: {receipt.witness_status}") # "UNVERIFIED"print(f"Signature: {receipt.signature[:32]}...") # Ed25519 signatureHow It Works
In offline mode, the SDK:
- Generates a local Ed25519 keypair (or uses your provided seed)
- Hashes payloads using SHA-256 with RFC 8785 canonical JSON
- Signs receipts locally with the Ed25519 private key
- Stores receipts in a local SQLite database at
~/.glacis/receipts.db
Offline vs Online
| Feature | Offline | Online |
|---|---|---|
| API key required | No | Yes |
| Signing | Local Ed25519 | Glacis witness network |
| Merkle proofs | No | Yes |
| Transparency log | No | Yes |
| Verification URL | No | Yes |
| Witness status | "UNVERIFIED" | "VERIFIED" |
Providing Your Own Seed
For reproducible testing, provide a fixed signing seed:
import osfrom glacis import Glacis
# Provide a custom signing seedseed = os.urandom(32)glacis = Glacis(mode="offline", signing_seed=seed)
# Or derive from a passphrase (for testing only!)import hashlibseed = hashlib.sha256(b"my-test-seed").digest()glacis = Glacis(mode="offline", signing_seed=seed)Local Storage
Offline receipts are stored in SQLite:
# Default location~/.glacis/receipts.db
# Query stored receiptsglacis = Glacis(mode="offline")receipts = glacis.list_receipts(limit=10)for r in receipts: print(f"{r.attestation_id}: {r.timestamp}")Verifying Offline Receipts
glacis = Glacis(mode="offline")
# Create a receiptreceipt = glacis.attest( service_id="test", operation_type="inference", input={"prompt": "test"}, output={"response": "result"},)
# Verify the signatureresult = glacis.verify(receipt)print(f"Signature valid: {result.signature_valid}") # Trueprint(f"Overall valid: {result.valid}") # TrueCLI Verification
Verify offline receipts from the command line:
# Save receipt to filepython -c "from glacis import Glacisimport json
glacis = Glacis(mode='offline')receipt = glacis.attest( service_id='test', operation_type='test', input={'test': True}, output={'ok': True})print(json.dumps(receipt.model_dump(), indent=2))" > receipt.json
# Verifypython -m glacis verify receipt.jsonOutput:
Receipt: oatt_abc123...Type: Offline
Status: VALID Signature: PASSWhen to Use Offline Mode
| Scenario | Recommendation |
|---|---|
| Local development | Offline mode |
| CI/CD testing | Offline mode |
| Air-gapped environments | Offline mode |
| Internal audits only | Offline mode (acceptable) |
| External audits | Online mode (recommended) |
| Customer due diligence | Online mode (required) |
| Published research | Online mode (recommended) |
Upgrading to Online Mode
When you need third-party verifiability:
# Before: offlineglacis = Glacis(mode="offline")
# After: onlineglacis = Glacis(api_key="glsk_live_...")That’s it. The API is identical—only the witness status changes.