feat(v1.1.8): app_user_sessions table + repo with sliding TTL

App-user session storage (migration 0027) mirrors admin_sessions but
adds three things v1.1.8 needs:

  * app_id column + FK cascade — every v1.1+ table starts with app_id
    so cross-app isolation is bright at the SQL layer (lookup keys
    off the hash only, but defense-in-depth: a leaked row's session
    still scopes to its app on every read).
  * absolute_expires_at — hard cap on the sliding window (default 30d
    via PICLOUD_APP_USER_SESSION_ABSOLUTE_HOURS). Beyond this the
    user must re-login regardless of recent activity.
  * revoked_at — explicit revocation by token (logout) or per-user
    (admin revoke-sessions button, password reset). Lookups reject
    revoked rows immediately so revocation takes effect before the
    weekly GC sweep runs.

The repo's gc() uses FOR UPDATE SKIP LOCKED matching the dead-letter
and abandoned-executions sweep patterns; the GC wiring lands in a
later commit.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
MechaCat02
2026-06-05 23:17:24 +02:00
parent 97546e2eb2
commit 7a44cbf5a4
3 changed files with 242 additions and 0 deletions

View File

@@ -18,6 +18,7 @@ pub mod app_members_repo;
pub mod app_repo;
pub mod app_secrets_repo;
pub mod app_user_repo;
pub mod app_user_session_repo;
pub mod apps_api;
pub mod auth;
pub mod auth_api;
@@ -81,6 +82,10 @@ pub use app_user_repo::{
AppUserCredentials, AppUserRepository, AppUserRepositoryError, AppUserRow,
ListOpts as AppUserListOpts, ListPage as AppUserListPage, PostgresAppUserRepository,
};
pub use app_user_session_repo::{
AppUserSessionLookup, AppUserSessionRepository, AppUserSessionRepositoryError,
PostgresAppUserSessionRepository,
};
pub use admin_users_api::{admins_router, AdminsState};
pub use api::{admin_router, AdminState};
pub use api_key_repo::{