Documentation
Security
Key handling, tenancy isolation, and what AssetForge deliberately cannot do.
Keys
- AssetForge never holds a private key and never broadcasts a transaction on your behalf.
- API key secrets are never stored. What is stored is an HMAC under API_KEY_HASH_SECRET, compared in constant time.
- A key secret is shown exactly once, at creation. A lost key is rotated, not recovered.
- No secret is ever rendered in the interface, returned by the API, or written to the audit log.
- Anything prefixed NEXT_PUBLIC_ is compiled into the browser bundle and is therefore public.
Tenancy
Every tenant-owned row carries an organizationId, and the repository layer exposes no unscoped accessor for tenant data. The only way to read another organization’s rows is to pass its id, which the session layer never yields.
Uniqueness constraints that users influence — slugs, symbols, key names — are scoped to the organization, so one tenant cannot squat another’s namespace or probe for the existence of their records.
Request handling
- Rate limiting runs before authentication, so a flood of invalid keys is also bounded.
- Every input is parsed with Zod at the boundary before it reaches domain logic.
- Errors are mapped to a stable code and a written message. A raw exception or stack trace is never returned.
- Webhook endpoints must be HTTPS.
- Every material action is written to the audit log with actor, timestamp, before and after state, and transaction hash.
The default rate limiter is in-memory: it does not survive a restart and does not coordinate across instances. Point REDIS_URL at a shared store before running more than one instance.