Security posture
This page documents how Glassmkr handles authentication, encryption, backups, and the audit log. It is the customer-facing technical companion to glassmkr.com/security (which covers what the agent collects and where the data lives). If you are evaluating Glassmkr against a security checklist or filling in a vendor questionnaire, this page should have the specifics you need.
Glassmkr is operated by a small team. Security is taken seriously, but the company does not hold formal compliance certifications yet. The "What we don't have yet" section near the bottom is just as load-bearing as the rest of this page.
Authentication
Passwords
Customer passwords are hashed with bcrypt at 12 salt rounds before being stored. Login compares with bcrypt's built-in constant-time check. Plaintext passwords are never logged or written to the database.
Sessions
Dashboard sessions use a signed JWT in an httpOnly, secure, SameSite=Lax cookie named guardian_token, scoped to .glassmkr.com. The session lifetime is 7 days. JWTs are signed with a server-only secret; rotating the secret invalidates every session.
API keys
Programmatic access uses API keys with the format gmk_acct_live_<43-char-base62>_<4-char-checksum> (account keys) and gmk_cru_live_* (per-server collector keys). The 43-character body carries 256 bits of CSPRNG entropy. The 4-character suffix is a CRC32 checksum to defend against typos and to give the dashboard a deterministic last-4 to display.
Keys are never stored in plaintext. Dashboard stores HMAC-SHA256(server_pepper, key). The pepper is a server-only secret loaded from environment at startup; the database alone is not enough to dashboard a key. Verification is a constant-time HMAC comparison.
Scoped access
Account keys carry one of three scopes: read, write, or admin. The scope is checked on every request before the route handler runs. Collector keys are server-bound and can only ingest snapshots for the server they were minted for.
Re-authentication for sensitive actions
Creating or rotating an API key requires that the operator's password was verified in the last 5 minutes. If the window has expired, the dashboard surfaces a password prompt before the action proceeds; the original request is replayed automatically after the password is verified. This prevents a stolen session cookie from being escalated into a long-lived API key.
OAuth
Customer signup is via Google OAuth. The OAuth callback exchanges the code for an identity, creates the customer row if needed, and issues a session cookie. No third-party password is ever stored.
Encryption in transit
All public traffic to glassmkr.com, app.glassmkr.com, and the ingest endpoint is served over HTTPS. TLS termination happens at Cloudflare's edge with their default profile (TLS 1.2 minimum, modern cipher suites). Cloudflare also sets:
- HSTS:
max-age=15552000; includeSubDomains(180 days) - X-Content-Type-Options:
nosniff - X-Frame-Options:
DENY - Referrer-Policy:
strict-origin-when-cross-origin
Internal cross-host traffic between the application host and the backup/AI host runs over a WireGuard tunnel on a private 10.100.0.0/24 subnet. SSH used for backup operations is pinned to the WireGuard peer IPs in the recipient's authorized_keys.
Rate limiting
Three tiers of token-bucket rate limiting run in front of authenticated endpoints, backed by Redis with atomic Lua scripts:
| Tier | Capacity | Refill rate | Applies to |
|---|---|---|---|
| Per-IP | 100 tokens | 10 / second | Pre-auth requests, brute-force defense |
| Per-key | 1,000 tokens | 100 / second | Authenticated programmatic API |
| Per-account | 5,000 tokens | 500 / second | All requests for one customer |
If Redis is unreachable, the limiter fails open and logs the degradation. The reasoning is documented in the source: a temporary infrastructure problem should not lock customers out of monitoring during exactly the kind of incident where monitoring is most valuable. This trade-off is intentional, not accidental.
Audit log
Every authenticated API call writes a row to api_audit_log in PostgreSQL with the following fields:
- Who: customer_id, key_id (or null if a session), user_id (for session calls)
- When and where: timestamp, source IP, user agent, request id
- What: HTTP method, path, resource type, resource id, action verb (create / list / read / update / delete / rotate / auth_failed)
- Outcome: result, HTTP status code
- Context: per-route metadata as JSON (for example, the scopes on a created key, or the reason an action was denied)
The audit table is append-only at the database level. The agent role used by the application has no UPDATE or DELETE permission on it, enforced by a SQL migration. Plaintext secrets (passwords, raw key material) are never written.
Customers can read their own audit log at /settings/audit in the dashboard. The endpoint requires the admin scope on a programmatic key.
Encryption at rest
Backups
Two independent backup systems run, both encrypted:
- PostgreSQL via pgBackRest: AES-256-CBC with a shared passphrase. Daily differential backups Monday through Saturday at 02:00 UTC, weekly full on Sunday at 03:00 UTC. Retention: 4 full + 14 differential + 4 archive sets.
- ClickHouse via clickhouse-backup: per-blob encryption using age (an authenticated, modern public-key file encryption format), then SFTP'd over WireGuard to the backup host. Daily full snapshots at 04:00 UTC, zstd-compressed. Retention: 30 days.
Both passphrases and the age private key are stored in operator password managers (the canonical copy) with operational copies on the two hosts. Restoration is verified monthly: a scheduled cron job on the backup host pulls the latest PostgreSQL backup, decrypts it, restores into a scratch directory, runs pg_ctl start, then pg_ctl stop, and writes the result to a log. A red restore-verify fires a notification.
Disks
Database disks themselves are not full-disk encrypted. This is the honest gap: full-disk encryption on bare metal hosts with auto-unlock has its own trade-offs (the unlock key has to live somewhere the host can read on boot, which limits the meaningful protection). Encrypted backups defend against the more realistic threat models, namely stolen backup media and read-only leaks. Full disk encryption is on the eventual roadmap.
Data retention
| Data type | Retention |
|---|---|
| ClickHouse snapshots (metrics) | 90 days on Pro, 7 days on Free (TTL-enforced) |
| ClickHouse alert history | 365 days |
| ClickHouse analyses + notifications | 90 days |
| PostgreSQL customer + server metadata | Until the customer deletes the server or account (hard delete with cascade) |
| PostgreSQL audit log | Retained for the life of the customer; on delete, customer_id is nulled but rows remain so the audit trail is preserved |
| Account deletion | All associated server data is removed within 30 days |
Backups expire according to the schedules above. A customer-deleted server's snapshots will leave production within 90 days (TTL) and the most recent backups within 30 days.
Infrastructure
All Glassmkr infrastructure runs on dedicated, single-tenant servers in EU data centers. No public-cloud services (AWS, GCP, Azure) are used for data processing or storage.
- Application + database host (services-1): hosts Dashboard, PostgreSQL, ClickHouse, Redis, nginx. Public IP behind Cloudflare.
- Backup + AI host (gpu-1): hosts the encrypted backup repository and the self-hosted GPU for AI narration. No public-facing services. Reachable from services-1 over WireGuard only.
Operator access to both hosts is SSH-key-only with password authentication disabled. Backup-host SSH for the unprivileged pgbackrest and clickhouse-backup users is chrooted and pinned to the WireGuard source IP.
Source code and release integrity
The Crucible agent is open source (github.com/glassmkr/crucible, MIT). Every npm release is published with provenance attestation via npm Trusted Publishing, which cryptographically links the tarball to the exact GitHub commit and workflow run that built it. Customers who want to verify what they install run:
npm view @glassmkr/crucible@latest dist.attestations Release artefacts on GitHub are signed with the Glassmkr GPG key. Fingerprint and verification instructions are published at glassmkr.com/security.
Reporting security issues
Report vulnerabilities to [email protected]. We acknowledge within 48 hours and provide a timeline for resolution. There is no bug bounty program at the moment.
The same address is the contact for the GitHub secret-scanning partner program once that integration ships (see "Planned" below).
What we don't have yet
Read this section before deciding whether Glassmkr meets your security bar. The gaps are real, not marketing-speak omissions.
- No formal compliance certifications. Glassmkr does not hold SOC 2, ISO 27001, PCI DSS, HIPAA, or equivalent. These are on the roadmap but require significant investment.
- No completed third-party penetration test. An external pen test is scheduled, not done. Findings will be summarised here once that work is complete.
- No bug bounty program. Security@ is monitored and acknowledged within 48 hours; vulnerability reports are welcome and credited, but there is no monetary reward yet.
- No multi-factor authentication on customer accounts. Password plus 5-minute re-auth on key creation is the current step-up control. WebAuthn / TOTP is on the roadmap.
- No full-disk encryption on database hosts. Backups are encrypted; disks are not. See "Disks" above for the threat-model reasoning.
- No offsite backup replication yet. Backups currently live on a single host in the same data center as the application. Off-site replication to a second region is planned once customer count justifies the operational complexity.
Planned
The following are tracked and scoped, not yet shipped:
- GitHub secret-scanning partner program. When a leaked Glassmkr API key is detected in a public GitHub repo, GitHub notifies a partner endpoint, and Glassmkr will auto-revoke the key and notify the customer. The endpoint, signature verification, and revocation workflow are not yet built.
- WebAuthn / TOTP. Adds a second factor to dashboard sign-in and to step-up operations.
- Off-site backup replication. A second encrypted backup destination in a different region.
- Customer-visible session list and revocation. "Sign out of all other sessions" in the dashboard.
- External penetration test. Scheduled.
Customer-requested security work is welcome. If your evaluation requires a control that is not on this list, write to [email protected] and we will tell you honestly whether it's in scope and when.