Capability Grants
Access to Waypoint is controlled entirely by Tailscale ACL capability grants under the name redo.com/cap/waypoint. There are no users, no roles, and no permissions stored in Waypoint itself — every authorization decision is read from the ACL on each connection.
{ "grants": [{ "src": ["group:backend"], "dst": ["tag:waypoint"], "cap": { "redo.com/cap/waypoint": [{ "limits": { /* optional per-user limits */ }, "backends": { /* per-listener grants */ } }] } }]}src and dst are standard Tailscale ACL fields. The capability payload is an array of objects; if multiple grants match, Waypoint merges the backends permissions across rules ✓ TestMergeRules_MultipleRulesMergePermissions internal/auth/auth_test.go:32 and takes the strictest values from limits. ✓ TestMergeLimits_MostRestrictiveWins internal/auth/auth_test.go:109
limits
Section titled “limits”| Field | Meaning |
|---|---|
max_conns | Concurrent connections per user |
max_conn_duration | Hard ceiling on a single connection’s lifetime |
max_bytes_per_conn | Byte budget per connection (e.g. "10GB") |
Missing fields fall back to [defaults.limits] from the server config. ✓ TestMergeLimits_FirstValueSetsBaseline internal/auth/auth_test.go:123 ✓ TestMergeLimits_ZeroDoesNotOverride internal/auth/auth_test.go:144 Bandwidth tiers stack across rules but deduplicate by period and pick the strictest byte budget per period. ✓ TestMergeLimits_BandwidthMostRestrictive internal/auth/auth_test.go:173 ✓ TestMergeLimits_BandwidthMultipleTiers_DedupByPeriod internal/auth/auth_test.go:212 See Provisioning & Defaults.
backends
Section titled “backends”Map keyed by listener name. Empty objects mean “allowed with no per-protocol detail” (the right shape for TCP listeners).
For Postgres:
{ "backends": { "pg-main": { "pg": { "databases": { "myapp": { "permissions": ["readwrite"], "schemas": ["public", "app"] }, "*": { "permissions": ["readonly"] } } } } }}The databases map keys are database names; * matches anything not listed explicitly. ✓ TestDatabasePermissions_WildcardMatch internal/auth/auth_test.go:333 When both an exact match and * are present, the exact match’s permissions are merged with the wildcard’s. ✓ TestDatabasePermissions_ExactAndWildcardMerge internal/auth/auth_test.go:354 Each entry has:
permissions— array of preset names (see below).schemas— schemas to apply the presets to. Defaults to["public"].sql— optional raw SQL templates. See Raw SQL.
Presets
Section titled “Presets”| Preset | Grants |
|---|---|
readonly | USAGE on schema; SELECT on all tables and sequences ✓ TestExpandPresets_Readonly internal/provision/presets_test.go:8 |
readwrite | Everything in readonly + INSERT, UPDATE, DELETE on tables, USAGE on sequences ✓ TestExpandPresets_Readwrite internal/provision/presets_test.go:28 |
admin | ALL PRIVILEGES on tables and sequences; USAGE + CREATE on schema ✓ TestExpandPresets_Admin internal/provision/presets_test.go:52 |
Preset names are case-insensitive ✓ TestExpandPresets_CaseInsensitive internal/provision/presets_test.go:126 , deduplicated ✓ TestExpandPresets_NoDuplicates internal/provision/presets_test.go:136 , and validated against the known set. ✓ TestExpandPresets_InvalidPreset internal/provision/presets_test.go:96
For MongoDB, presets map to MongoDB built-in roles (read, readWrite, dbAdmin). ✓ TestExpandMongoPresets_Readonly internal/provision/mongo_test.go:78 ✓ TestExpandMongoPresets_ReadWrite internal/provision/mongo_test.go:91 ✓ TestExpandMongoPresets_Admin internal/provision/mongo_test.go:101 See MongoDB for the static-user matching rules when provision.mode = "static".
Per-connection downgrade
Section titled “Per-connection downgrade”Postgres clients can downgrade their effective preset for one connection with ?waypoint_presets=readonly in the connection string. This cannot elevate beyond the grant; it only narrows. ✓ TestLimitDBPermissionsToPostgresPreset internal/proxy/preset_limit_test.go:83 See Postgres.