core PK: id 11 required 2 unique

Description

Rotating refresh tokens issued by the Authentication Module to maintain persistent sessions for users across both the Meander Mobile App and Admin Web Portal. Each token belongs to a rotation family; consuming a token invalidates it and issues a replacement. Reuse of a revoked token triggers full family revocation to mitigate token theft.

16
Attributes
6
Indexes
7
Validation Rules
11
CRUD Operations

Data Structure

Name Type Description Constraints
id uuid Primary key, unique per issued token
PKrequiredunique
user_id uuid Foreign key to the user who owns this token
required
session_id uuid Foreign key to the session this token belongs to
required
token_hash string SHA-256 hash of the raw refresh token. Never stored in plaintext. Used for lookup on token presentation.
requiredunique
family_id uuid Groups all tokens in a single rotation chain. If any revoked token in a family is reused, the entire family is immediately revoked (token theft detection).
required
rotation_count integer Number of times this specific family has been rotated. Monotonically increasing; used to enforce expected rotation sequence.
required
is_revoked boolean Whether this token has been invalidated. Set true on rotation (token consumed), logout, admin revocation, or security event.
required
revoked_at datetime UTC timestamp when token was revoked. Null if still active.
-
revoked_reason enum Reason the token was revoked. Used for audit and security analysis.
-
expires_at datetime UTC timestamp when this token expires regardless of revocation state. Tokens past this timestamp are unconditionally rejected.
required
issued_at datetime UTC timestamp when the token was issued.
required
ip_address string Client IP address at token issuance. Stored for audit and anomaly detection. IPv4 or IPv6.
-
user_agent string HTTP User-Agent header at issuance. Used for session display in Session Management UI and for anomaly detection.
-
device_fingerprint string Optional opaque device identifier from the mobile client (platform + model hash). Enables per-device session revocation from the Session Management UI.
-
created_at datetime Record creation timestamp (same as issued_at; kept for consistency with ORM conventions).
required
updated_at datetime Last modification timestamp. Updated on revocation.
required

Database Indexes

idx_refresh_tokens_token_hash
btree unique

Columns: token_hash

idx_refresh_tokens_user_id
btree

Columns: user_id

idx_refresh_tokens_session_id
btree

Columns: session_id

idx_refresh_tokens_family_id
btree

Columns: family_id

idx_refresh_tokens_user_active
btree

Columns: user_id, is_revoked

idx_refresh_tokens_expires_at
btree

Columns: expires_at

Validation Rules

token_hash_format error

Validation failed

expires_at_future error

Validation failed

user_id_references_active_user error

Validation failed

session_id_references_active_session error

Validation failed

revoked_fields_consistency error

Validation failed

rotation_count_monotonic error

Validation failed

ip_address_format warning

Validation failed

Business Rules

rotating_token_on_use
on_update

When a valid refresh token is presented, it must be immediately revoked (revoked_reason='rotation') and a new token issued in the same family with rotation_count incremented. The old token becomes unusable the instant the new one is issued.

Enforced by: Auth Service
reuse_detection_family_revocation
always

If a token that is already revoked (is_revoked=true) is presented, all tokens in the same family_id are immediately revoked with revoked_reason='security_event'. This assumes token theft — an attacker replayed a stolen token after the legitimate client already rotated it.

expiry_hard_reject
always

Tokens past expires_at are rejected unconditionally, even if is_revoked=false. No grace period.

admin_revocation_cascades_to_family
on_delete

When an admin revokes a session from Session Management UI, all refresh tokens belonging to that session_id are marked is_revoked=true with revoked_reason='admin_revoke'. This ensures the user is fully signed out across all clients holding that session's tokens.

user_logout_revokes_token
on_update

On explicit logout, the current refresh token is revoked (revoked_reason='logout'). The entire family may also be revoked if the logout is a 'sign out all devices' operation.

token_plaintext_never_stored
on_create

The raw token value must never be persisted. Only the SHA-256 hash is stored in token_hash. The raw value is returned to the client once at issuance and never retrievable from the database.

Enforced by: Auth Service
mobile_secure_store_only
always

The Flutter client must store the raw refresh token exclusively in the platform secure store (Keychain on iOS, Keystore on Android) via secure-token-store. It must never be written to Drift/SQLCipher local DB, shared preferences, or any other non-secure storage.

expired_token_cleanup
always

Tokens past expires_at AND older than 30 days may be hard-deleted by a scheduled cleanup job. Active and recently-revoked tokens within the 30-day window are retained for audit trail.

Enforced by: Auth Service

Storage Configuration

Storage Type
primary_table
Location
main_db
Partitioning
by_date
Retention
delete_after_30days