Bound authority at every interface.
Trestle separates administrative control, application identity, service automation, storage and outbound delivery. Security claims are tied to implemented controls and retained abuse tests.
Trust boundaries
| Actor | Credential | Authority |
|---|---|---|
| Administrator | Server-side cookie session + CSRF token | Dashboard and administrative APIs |
| Application user | Short-lived access token; rotating refresh token | Collection operations allowed by rules |
| Service account | Scoped bearer secret | Machine scopes plus collection rules |
| Personal token | Scoped bearer secret | Administrator-owned automation |
| Webhook receiver | HMAC signing secret | Verify deliveries from one target |
| AWS Lambda | Process-configured AWS credentials | Asynchronous invocation of validated ARNs |
Passwords and sessions
Passwords use Argon2id with per-password salts. Administrator setup closes atomically after the first account. Login is rate limited; browser mutations require the session cookie, matching CSRF token and valid origin. Application refresh tokens rotate once, cannot act as access tokens and lose authority when their server-side session is revoked.
Collection authorization
List, view, create, update and delete are independent operations. Application users and service identities must pass the collection rule; services must also possess the exact read or write scope. Individual denials return the same 404 as an absent record.
{
"list": "actor.id == record.owner",
"view": "actor.id == record.owner",
"create": "actor.id == input.owner",
"update": "actor.id == record.owner",
"delete": "false"
}The rule language is deliberately small. See Rule language for the expressions actually implemented.
CP23.6 abuse evidence
A composed matrix attacked cross-owner list/view/update/delete, forged ownership, refresh/access token confusion, service read/write scope confusion and cookie-versus-bearer mutation handling. It found and repaired an individual row-rule bypass; ten repaired repetitions and race-enabled security packages passed. See Battle tested for the exact boundary.
Queries, files and egress
Filters parse into a bounded typed AST and compile to parameterized SQL. Generated storage keys, staged writes and symlink refusal keep client filenames out of paths. Webhooks require HTTPS, reject private/link-local destinations and redirects, re-resolve DNS, bound responses and sign each delivery. Secrets are copy-once; hashes or encrypted values persist according to lookup requirements.
Deployment and reporting
Trestle binds loopback by default. Only configured proxy CIDRs can supply forwarded scheme and client identity. TLS, firewalling, owner-only configuration/data directories, provider-managed S3 recovery and host patching remain operator responsibilities.
Email security@trestle.dev with the affected version, reproduction and impact after removing secrets and personal data. Before stable release, only the newest release line receives security fixes.