Delegated agent identity and message verification. hallpass.org
Hallpass answers one question for any verifier:
Did this exact message come from an agent that is currently delegated by this user?
- A person creates a username account at hallpass.org
- They add public attestations (domain DNS, X post, GitHub gist, Bluesky handle)
- An agent registers a public key and proves possession
- The person delegates to that agent
- The agent signs messages with its own key
- Anyone can verify the username, delegation chain, and message signature together
The verification result is message-specific, not just profile-level.
| Package | Language | Path |
|---|---|---|
@hallpass/sdk |
TypeScript | packages/sdk-typescript |
@hallpass/cli |
TypeScript | packages/cli |
hallpass-sdk |
Python | packages/sdk-python |
hallpass_sdk |
Elixir | packages/sdk-elixir |
# 1. Log in (or register at hallpass.org first)
npx @hallpass/cli auth login
# 2. Register an agent under your profile
npx @hallpass/cli agent register my-agent
# 3. Sign a message as the delegated agent
npx @hallpass/cli message sign --username alice --body "Invoice #1234 approved"
# 4. Anyone can verify it
npx @hallpass/cli message verify bundle.jsonimport {
createClient,
createMessageProofBundle,
loadAgentKeyMaterial,
verifyMessageBundle,
} from '@hallpass/sdk';
const client = createClient({ baseUrl: 'https://hallpass.org/api/v1' });
const keyMaterial = await loadAgentKeyMaterial();
// Sign a message as a delegated agent
const bundle = createMessageProofBundle({
principalUsername: 'alice',
body: 'Invoice #1234 approved',
authorLabel: 'Billing Agent',
keyMaterial,
});
// Anyone can verify: identity, delegation chain, and signature
const { data } = await verifyMessageBundle({ client, body: bundle });
console.log(data.overall_decision); // "verified"from hallpass_sdk import HallpassClient, generate_agent_key_material, create_message_proof_bundle
key_material = generate_agent_key_material()
bundle = create_message_proof_bundle(
principal_username="alice",
body="Invoice #1234 approved",
author_label="Billing Agent",
key_material=key_material,
)
client = HallpassClient()
result = client.verify_message(bundle)Hallpass is a Phoenix (Elixir) application with a React frontend.
- Elixir 1.17+ / OTP 27+
- PostgreSQL 15+
- Node.js 22+ / pnpm
# Install dependencies
mix deps.get
cd assets && pnpm install && cd ..
# Create and migrate the database
mix ecto.setup
# Start the server
mix phx.serverThe app will be available at http://localhost:4000.
| Variable | Required | Description |
|---|---|---|
DATABASE_URL |
prod | PostgreSQL connection string |
SECRET_KEY_BASE |
prod | Phoenix secret (generate with mix phx.gen.secret) |
KEY_ENCRYPTION_KEY |
prod | 32-byte base64 key for encrypting service-managed private keys |
PHX_HOST |
prod | Public hostname (e.g. hallpass.org) |
GCS_BUCKET |
optional | GCP Cloud Storage bucket for avatar uploads |
GCS_SERVICE_ACCOUNT_JSON |
optional | GCP service account JSON key |
GITHUB_TOKEN |
optional | GitHub API token for higher rate limits on gist verification |
fly launch --copy-config
fly secrets set SECRET_KEY_BASE="$(mix phx.gen.secret)"
fly secrets set KEY_ENCRYPTION_KEY="$(elixir -e ':crypto.strong_rand_bytes(32) |> Base.encode64() |> IO.puts()')"
fly secrets set DATABASE_URL="postgres://..."
fly deployThe full OpenAPI 3.1 spec is at openapi/openapi.yaml. Public endpoints:
POST /api/v1/verifications— verify a signed message bundleGET /api/v1/profiles/:username— public profile with attestationsPOST /api/v1/messages— submit a signed message for hosted verificationGET /api/v1/messages/:id/verification— hosted verification result
Browser / CLI / SDK
│
▼ HTTPS
┌──────────────┐
│ Hallpass │ Phoenix + Bandit
│ (Elixir) │ React frontend (Vite)
└──────┬───────┘
▼ SSL
┌──────────────┐
│ PostgreSQL │ Neon / self-hosted
└──────────────┘
- Key modes: service-managed (server holds encrypted private key) or self-managed (server holds only public key)
- Encryption: service-managed private keys are AES-256-GCM encrypted at rest via
cloak_ecto - Auth: password (Argon2id), passkeys (WebAuthn/FIDO2), key-based challenge-response
- Attestations: domain DNS TXT, X/Twitter post, GitHub gist, Bluesky handle resolution
- Rate limiting: per-IP on auth endpoints via Hammer
See SECURITY.md for the threat model, key custodianship details, and vulnerability reporting.
Apache 2.0 — see LICENSE.