Security model · CP23.6

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

ActorCredentialAuthority
AdministratorServer-side cookie session + CSRF tokenDashboard and administrative APIs
Application userShort-lived access token; rotating refresh tokenCollection operations allowed by rules
Service accountScoped bearer secretMachine scopes plus collection rules
Personal tokenScoped bearer secretAdministrator-owned automation
Webhook receiverHMAC signing secretVerify deliveries from one target
AWS LambdaProcess-configured AWS credentialsAsynchronous 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.

Report vulnerabilities privately

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.