Security Architecture · Interactive

How SiliconProof
keeps devices trustworthy

Every device gets a hardware-anchored cryptographic identity. The key that signs those identities lives inside a tamper-proof chip that nothing — not a server, not an attacker, not us — can ever extract.

FIPS 140-2 L3HSM root of trust
1Google account, isolated
0copies of the CA key on disk
~$2.50/mo for the crown jewel
The whole picture

The system, end to end

Click any block to see what it is, what it holds, and — deliberately — what it can't hold. Animated lines are live trust & data flows.

Trust flows in coral · data flows in goldTap a node →
🔐 HSM Device CA Google Cloud HSM · the key EC P-256 · non-extractable 🛰️ Issuance box vault-cell-hel1 · Hetzner FI asks HSM to sign · holds no key 🌐 gate1 customer API · brokers cannot sign anything 📡 mTLS brokers Mosquitto · CN = identity 📟 Devices key in ATECC608B chip CSR out · private key stays 🗄️ Data stores Postgres (RLS) · ClickHouse per-tenant isolation ☁️ R2 backups Parquet · verified

Root of trust start here

Pick any block on the map. Each one tells you what it does — and the design's whole point is what each box is not allowed to hold.

  • Coral lines = trust (signing / identity)
  • Gold lines = telemetry & backups
  • The CA private key lives in exactly one place, and it never moves
↑ interactive — click the blocks
Layer 1 — the crown jewel

The key nothing can steal

A Certificate Authority signs every device's identity. Whoever holds the CA's private key can impersonate your entire fleet. So we put it where no one can hold it.

🔐

Hardware Security Module

The CA private key is generated inside a FIPS 140-2 Level 3 chip and can never be exported. Root a server, and the key is still untouchable — you can only ask the chip to sign.

WhereGoogle Cloud HSM
CurveEC P-256
Projectsiliconproof-security
Accountkalanitechco
🛰️

Isolated signing box

A separate Hetzner box (Finland) runs the issuance service. It has the CA's public cert and a Google permission-slip to request signatures — but never the key. Firewalled so only gate1 can reach it.

Hostvault-cell-hel1
Toolingstep-kms-plugin
Reachable bygate1 IP only
🚫

Least privilege

Exactly one service account can use the key, with exactly one permission (signerVerifier). Your internet-facing customer box (gate1) can't sign at all.

Signers1 SA
gate1 can sign?no
Key copies0
Layer 2 — device lifecycle

From bare silicon to trusted device

Identity is minted at the factory — before any customer exists. Ownership is assigned later, at deployment. The device's private key never leaves its secure element.

🏭

1 · Factory provision

An engineer registers a serial and issues its cert (no organization yet). The device generates its own keypair in an ATECC608B secure element and only sends out a CSR — the private key never leaves the chip.

UIprovision.siliconproof.io
Gatebasic-auth + super-admin
Key flowCSR (key stays on device)
🎫

2 · Claim (at sale)

The device ships with a QR claim token. At deployment, an org admin scans it — that assigns the device to their organisation and creates its record. Ownership is a database pointer, not baked into the device.

Org in cert?never
Transfer orgSQL update, no re-flash
📡

3 · Connect (mTLS)

The device connects to the broker with its cert. The broker verifies the signature against the CA and uses the cert's Common Name as the device's identity — the CN is the serial.

Transportmutual TLS
Identitycert CN = serial
Topic scopeper-serial ACL
Watch it happen

How a certificate gets signed

Step through the exact path a signing request takes — and notice the private key never travels.

🧑‍🔧 🛰️issuance 🔐HSM 📟 engineer vault-cell-hel1 Google Cloud HSM device
Ready. Press play to send a CSR through the chain.
Layer 3 — isolation

One platform, walled-off tenants

Telemetry and state are split by store and fenced by the database itself — not just by app code.

🧱

Row-Level Security

Postgres enforces tenant isolation at the row level under a non-superuser role with FORCE RLS. A missed filter in app code still can't leak another tenant's rows — the database refuses.

Runtime roleNOSUPERUSER
Policyorg_id = current tenant
📊

Two right-sized stores

State (devices, orgs, assessments) in Postgres; high-volume telemetry in ClickHouse. Each query is org-scoped before any limit is applied.

StatePostgreSQL
TelemetryClickHouse
🔏

Two kinds of TLS

Public web traffic uses free auto-renewing Let's Encrypt certs (via Caddy). Machine & device identity uses the private HSM CA. The right tool for each job.

Web TLSLet's Encrypt
Device mTLSHSM CA
Layer 4 — keep it safe & recoverable

Every secret, and where it lives

The platform runs on a lot of secrets — database passwords, broker certificates, signing keys, API keys. Here is the full set, grouped by how it's held. Two custody models: hardware/PKI (keys that live in silicon or as issued certs) and application secrets (env values on the box, mirrored to Google Secret Manager).

🔒 
Names & custody only — no secret values appear here. Actual values live only inside the systems they protect (the HSM, the box's mode-600 env files, Google Secret Manager). This page — and every doc — is metadata-only, per the key-management rule.

🔑 Cryptographic identity — hardware & PKI (never in an env file)

SecretProtectsCustodyRotation
Device CA private keysigns every device's identityGoogle Cloud HSM — non-extractable, FIPS L3never moves
step-ca-signer SA keypermission to ask the HSM to signvault-cell-hel1 — file, gate1-firewalledon demand
Mosquitto server cert + keybroker's TLS identity to devicesdocker volume on gate1 (mode 600)re-issue from CA
fastify↔broker bridge certplatform's mTLS client identitydocker volume on gate1re-issue from CA
Device / ESP32 mTLS certseach device's identity on the wiresecure element (key never leaves chip)per-device re-issue
Public web TLS certshttps for aq / provision / vape …Let's Encrypt via Caddy (auto)auto ≈ 60 days

⚙️ Application secrets — .env.gate1* (mode 600 on the box) → mirrored to Google Secret Manager

SecretProtectsCustodyRotation
CLICKHOUSE_DEFAULT_PASSWORDClickHouse default/admin user.env + Secret Manager backupenv edit + CH recreate
CLICKHOUSE_INGEST_PASSWORDtelemetry ingestion path (DDL-off).env + Secret Manager backupenv edit + CH recreate
CLICKHOUSE_SRE_PASSWORDClickHouse operator/admin queries.env + Secret Manager backupenv edit + CH recreate
DATABASE_URL (Postgres pw)state DB, under a non-super RLS role.env + Secret Manager backupenv edit + restart
BETTER_AUTH_SECRETsigns user auth sessions.env + Secret Manager backupenv edit + restart
JWT_SECRETsigns API tokens.env + Secret Manager backupenv edit + restart
R2_ACCESS_KEY / R2_SECRET_KEYbackup storage (Cloudflare R2).env + Secret Manager backupCloudflare dashboard
KAIOT_CLAIM_SECRETHMAC on device-claim / QR tokens.env + Secret Manager backupenv edit + restart
BOOTSTRAP_SECRETfirst-boot provisioning handshake.env + Secret Manager backupenv edit + restart
VAPID public / private keysigns web-push notifications.env + Secret Manager backupregenerate keypair
Gemini API keyAI / assistant features.env + Secret Manager backupprovider rotate
🗝️

Backup, not exposure

Env secrets are mirrored to Google Secret Manager only when they change (a hash-compare sync — values are never printed to logs or the terminal). Nothing secret ever lands in git.

Backups18 in Secret Mgr
In git?never
💾

Backups that are proven

State backs up nightly to R2. Real-device telemetry is archived to R2 as Parquet and read back and row-count-verified — a backup that's confirmed restorable, not just "the job ran."

StoreCloudflare R2
Egress$0
Verifyread-back match
🧭

One account, consolidated

All security infra lives in a single Google account you control. The old personal/recovery accounts and their obsolete secrets (incl. the retired OpenBao stack) were deleted — smaller surface, clearer ownership.

Accounts1
Old projectsdeleted
Regulation — EU Cyber Resilience Act

Where we stand on CRA

CRA is a whole-product regime. Strong identity is necessary but not sufficient — here's an honest scorecard.

Hardware-anchored device identity

HSM CA, per-device mTLS, CSR flow — private keys never leave the device.

No default credentials

Every device gets a unique cert; humans use real auth + RBAC.

Confidentiality & integrity in transit

mTLS everywhere for devices; TLS for web.

Secrets in an HSM / manager

FIPS-L3 root, no plaintext keys on disk or in git.

Logging & tenant isolation

Audit trail + RLS in place; monitoring still maturing.

Signed OTA updates + secure boot

The biggest gap. Designed (ADR-035 neighbours); a firmware project on the roadmap.

SBOM · disclosure policy · incident reporting

Process & paperwork — cheap, not yet done. Reporting duties bite ~Sept 2026.

Conformity assessment + CE marking

Full obligations apply ~Dec 2027 — real runway.