Skip to content

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 needed
glacis = 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 signature

How It Works

In offline mode, the SDK:

  1. Generates a local Ed25519 keypair (or uses your provided seed)
  2. Hashes payloads using SHA-256 with RFC 8785 canonical JSON
  3. Signs receipts locally with the Ed25519 private key
  4. Stores receipts in a local SQLite database at ~/.glacis/receipts.db

Offline vs Online

FeatureOfflineOnline
API key requiredNoYes
SigningLocal Ed25519Glacis witness network
Merkle proofsNoYes
Transparency logNoYes
Verification URLNoYes
Witness status"UNVERIFIED""VERIFIED"

Providing Your Own Seed

For reproducible testing, provide a fixed signing seed:

import os
from glacis import Glacis
# Provide a custom signing seed
seed = os.urandom(32)
glacis = Glacis(mode="offline", signing_seed=seed)
# Or derive from a passphrase (for testing only!)
import hashlib
seed = 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 receipts
glacis = 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 receipt
receipt = glacis.attest(
service_id="test",
operation_type="inference",
input={"prompt": "test"},
output={"response": "result"},
)
# Verify the signature
result = glacis.verify(receipt)
print(f"Signature valid: {result.signature_valid}") # True
print(f"Overall valid: {result.valid}") # True

CLI Verification

Verify offline receipts from the command line:

Terminal window
# Save receipt to file
python -c "
from glacis import Glacis
import 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
# Verify
python -m glacis verify receipt.json

Output:

Receipt: oatt_abc123...
Type: Offline
Status: VALID
Signature: PASS

When to Use Offline Mode

ScenarioRecommendation
Local developmentOffline mode
CI/CD testingOffline mode
Air-gapped environmentsOffline mode
Internal audits onlyOffline mode (acceptable)
External auditsOnline mode (recommended)
Customer due diligenceOnline mode (required)
Published researchOnline mode (recommended)

Upgrading to Online Mode

When you need third-party verifiability:

# Before: offline
glacis = Glacis(mode="offline")
# After: online
glacis = Glacis(api_key="glsk_live_...")

That’s it. The API is identical—only the witness status changes.