feat(v1.1.8): F3 realtime auth_mode = 'session' (migration 0033)
Migration 0033 widens topics.auth_mode CHECK to include 'session'
alongside 'public' and 'token'.
TopicAuthMode enum gains a Session variant (as_str + from_db
extended uniformly).
RealtimeAuthorityImpl now takes Arc<dyn UsersService> as a third
constructor arg. The Session branch of authorize_subscribe
delegates to UsersService::verify_session_for_realtime(app_id,
token):
* Returns Some(user) → allow. The service bumps the sliding TTL
on success.
* Returns None → Unauthorized.
* Defense-in-depth: even though verify_session_for_realtime
already enforces cross-app isolation, the branch re-checks
user.app_id == app_id.
Tests added (4 new cases): valid session token allows; missing
token is Unauthorized; wrong token is Unauthorized; cross-app
session token is Unauthorized. All 12 realtime_authority tests
pass.
Dashboard: TopicAuthMode TypeScript union widened to include
'session'; the topic create + edit forms gain a third radio option
labeled "session — requires a per-app user session minted by
users::login (v1.1.8)".
picloud binary: construction order reshuffled so users is built
before realtime_authority. app_secrets_repo is now .clone()'d into
the pubsub realtime wiring so the original Arc can be re-used by
realtime_authority.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -201,11 +201,6 @@ pub async fn build_app(
|
||||
// column. Operators upgrading from v1.1.6 or earlier MUST apply
|
||||
// v1.1.7 first; the 0032 migration's guard refuses to run
|
||||
// otherwise.
|
||||
let realtime_authority: Arc<dyn RealtimeAuthority> = Arc::new(RealtimeAuthorityImpl::new(
|
||||
topic_repo.clone(),
|
||||
app_secrets_repo.clone(),
|
||||
));
|
||||
|
||||
// v1.1.5 durable pub/sub, extended in v1.1.6 with the realtime
|
||||
// broadcast + subscriber-token mint. Publishes fan out to matching
|
||||
// pubsub triggers at publish time (one outbox row each, delivered by
|
||||
@@ -216,7 +211,7 @@ pub async fn build_app(
|
||||
PubsubServiceImpl::new(pubsub_repo, authz.clone()).with_realtime(
|
||||
broadcaster.clone(),
|
||||
topic_repo.clone(),
|
||||
app_secrets_repo,
|
||||
app_secrets_repo.clone(),
|
||||
SubscriberTokenConfig::from_env(),
|
||||
),
|
||||
);
|
||||
@@ -261,6 +256,14 @@ pub async fn build_app(
|
||||
events.clone(),
|
||||
UsersServiceConfig::from_env(),
|
||||
));
|
||||
// v1.1.8 F3: build the realtime authority now that UsersService
|
||||
// is constructed; the Session arm of authorize_subscribe calls
|
||||
// users.verify_session_for_realtime.
|
||||
let realtime_authority: Arc<dyn RealtimeAuthority> = Arc::new(RealtimeAuthorityImpl::new(
|
||||
topic_repo.clone(),
|
||||
app_secrets_repo.clone(),
|
||||
users.clone(),
|
||||
));
|
||||
let services = Services::new(
|
||||
kv,
|
||||
docs,
|
||||
|
||||
Reference in New Issue
Block a user