Role-Based Access Control (RBAC)
- Works today: JWT
rolesclaim is extracted and stored on the connection principal. - Works today: Basic per-connection, per-map
read/writebooleans are enforced byWriteValidator. - Works today: Default-allow —
MapPermissions::default()is{ read: true, write: true }andrequire_authdefaults tofalse. All maps are accessible without authentication by default. - To enable deny-by-default: Configure
SecurityConfigwithrequire_auth: trueanddefault_permissions: MapPermissions { read: false, write: false }. - Planned (TODO-171): Role-based policy evaluation, map pattern matching (
users:*), and field-level security (allowedFields) are not yet implemented.
TopGun provides a flexible security model based on Permission Policies. You can define fine-grained access control rules for your data maps, controlling who can read (READ), write (PUT), or delete (REMOVE) data based on user roles.
Development-Friendly Defaults
TopGun Server allows all access by default (read: true, write: true, require_auth: false). To enable deny-by-default, configure SecurityConfig with require_auth: true and default_permissions: { read: false, write: false }.
Core Concepts
Principal
Represents the authenticated user. Contains the sub claim from the JWT (RFC 7519 user identifier) and a list of roles (e.g., ‘USER’, ‘ADMIN’).
Permission Policy
A rule that grants specific actions (READ, PUT, REMOVE) on a set of maps to a specific role.
What Works Today
The following RBAC capabilities are implemented and enforced in the current server:
- JWT role extraction: The server reads the
rolesarray from the JWT payload and stores it on the connection’s principal object. Roles are available for use in permission checks. - Per-connection map permissions: Each connection can be granted
read: trueorwrite: true(or both) on specific maps. These booleans are the primary access control mechanism today. - Default-allow:
MapPermissions::default()is{ read: true, write: true }andrequire_authdefaults tofalse. All maps are accessible without authentication unless you explicitly configure otherwise. To enable deny-by-default, setrequire_auth: trueanddefault_permissions: MapPermissions { read: false, write: false }inSecurityConfig. Per-connectionmap_permissionscan then grant access to specific maps. WriteValidatorenforcement: All write operations pass throughWriteValidator, which checks map-level permissions before allowing the CRDT merge.
Configuration (Planned — TODO-171)
Map name pattern matching (e.g., users:*) and role-based policy evaluation are not yet implemented. The configuration example below shows the planned design.
RBAC policies will be configured on the Rust server via security settings and environment variables.
# PLANNED — map pattern matching (users:*, public:*, etc.) is not yet implemented.
# Role-based policy evaluation against map name patterns is planned (TODO-171).
#
# Planned policy structure (future):
# ANON -> public:* -> READ only
# USER -> users:{userId}:* -> ALL (read, write, delete)
# ADMIN -> * -> ALL
#
# What works today: basic per-connection read/write booleans applied by WriteValidator.
# Roles are extracted from the JWT "roles" claim and stored on the connection principal.
#
# Start the server (development):
PORT=8765 \
DATABASE_URL=postgres://user:pass@localhost/myapp \
JWT_SECRET=your-secret-key \
cargo run --bin test-server
#
# Note: a standalone topgun-server production binary is planned but does not yet exist.
# For the full RBAC configuration API (when implemented), see: /docs/reference/server Field-Level Security (Planned — TODO-171)
allowedFields field-level security is not yet implemented. The example below shows the planned API.
You will be able to restrict which fields are returned to the client using allowedFields.
This is useful for hiding sensitive data like password hashes or internal metadata.
{
role: 'USER',
mapNamePattern: 'users:*',
actions: ['READ'],
// Only allow reading public profile fields
allowedFields: ['username', 'displayName', 'avatarUrl']
}