Proxy Shared User Drafts

This commit is contained in:
Alexey
2026-09-14 20:19:48 +03:00
parent b37f1ebdeb
commit 0ac236955a
59 changed files with 1485 additions and 401 deletions
+16 -12
View File
@@ -89,11 +89,6 @@ impl WebProcessRuntime {
.record_rejection(WebRejectionReason::ConfigDisabled);
return Err(ManagerError::Closed);
}
if !generation.proxy_shared.is_user_enabled(&profile.user) {
self.telemetry
.record_rejection(WebRejectionReason::UserDisabled);
return Err(ManagerError::Closed);
}
let _operator_admission = self.try_operator_admission()?;
let now = Instant::now();
let mut state = self.state.lock();
@@ -146,12 +141,25 @@ impl WebProcessRuntime {
.record_rejection(WebRejectionReason::BootstrapCapacity);
return Err(ManagerError::Limit);
};
let Some(mut user_publication) = generation
.proxy_shared
.claim_authenticated_user(&profile.user, profile.credential_id)
else {
self.telemetry
.record_rejection(WebRejectionReason::UserDisabled);
return Err(ManagerError::Closed);
};
let Some(user_registration) = user_publication.take_registration() else {
return Err(ManagerError::Closed);
};
let trace_session_id = self.trace.next_session_id();
let bridge_diagnostics_enabled = config.web.debug.bridge_diagnostics_enabled();
let (user_agent, user_agent_id) = bounded_user_agent(user_agent);
let issued_profile = Arc::clone(&profile);
state.bootstraps.insert(
hash,
Bootstrap {
user_registration,
expires_at: now + Duration::from_secs(config.web.timeouts.bootstrap_lifetime_secs),
issued_at: now,
issuance_ip: client_ip,
@@ -186,11 +194,7 @@ impl WebProcessRuntime {
},
);
*state.bootstraps_per_ip.entry(client_ip).or_insert(0) += 1;
let profile = state
.bootstraps
.get(&hash)
.map(|entry| Arc::clone(&entry.profile))
.ok_or(ManagerError::Closed)?;
user_publication.commit();
drop(state);
if recovery {
self.telemetry
@@ -202,7 +206,7 @@ impl WebProcessRuntime {
Some(client_ip),
crate::web::trace::TraceIdentity::from_optional_profile(
Some(trace_session_id),
&profile,
&issued_profile,
),
crate::web::trace::TraceLifecycleEvent::BridgeIssued,
None,
@@ -216,7 +220,7 @@ impl WebProcessRuntime {
self.trace.record_profile_lifecycle(
client_ip,
Some(trace_session_id),
&profile,
&issued_profile,
crate::web::trace::TraceLifecycleEvent::BridgeIssued,
None,
None,
+4 -1
View File
@@ -30,14 +30,17 @@ pub(crate) struct WebShutdownDrain {
}
impl WebProcessRuntime {
/// Applies learning policy before publishing one new runtime generation.
/// Applies issuance and learning policy before publishing one new generation.
pub(crate) fn activate_generation(
&self,
generation: Arc<RuntimeGeneration>,
) -> Arc<RuntimeGeneration> {
let config = generation.config();
let (replaced, detached) = {
// Manager state precedes learning in the request-path lock order.
let mut state = self.state.lock();
let mut learning = self.learning.lock();
state.apply_issuance_policy(generation.id, config.web.enabled);
let outcome = learning.apply_policy(
Instant::now(),
generation.id,
+15 -1
View File
@@ -69,7 +69,10 @@ impl WebProcessRuntime {
let Some(entry) = state.bootstraps.get(&bootstrap_hash) else {
return Err(ManagerError::Authentication);
};
if entry.profile.host != host || now > entry.expires_at {
if entry.profile.host != host
|| now > entry.expires_at
|| entry.user_registration.is_cancelled()
{
return Err(ManagerError::Authentication);
}
if entry.used {
@@ -301,6 +304,15 @@ impl WebProcessRuntime {
return Err(ManagerError::Protocol);
};
let _operator_admission = self.try_operator_admission()?;
let Some(mut user_publication) = generation
.proxy_shared
.claim_authenticated_user(&profile.user, profile.credential_id)
else {
return Err(ManagerError::Closed);
};
let Some(user_registration) = user_publication.take_registration() else {
return Err(ManagerError::Closed);
};
if !admit_initial(self, &mut state, now, client_ip, profile_key, &profile) {
return Err(ManagerError::Limit);
}
@@ -338,6 +350,7 @@ impl WebProcessRuntime {
recovery,
self.limits.clone(),
issued_timeouts.clone(),
Some(user_registration),
);
state.sessions.insert(session_hash, Arc::clone(&session));
*state.sessions_per_ip.entry(client_ip).or_insert(0) += 1;
@@ -402,6 +415,7 @@ impl WebProcessRuntime {
user_agent_id,
},
);
user_publication.commit();
drop(state);
self.telemetry
.record_carrier_selection(carrier, learning_disposition);
@@ -43,14 +43,24 @@ impl WebProcessRuntime {
if !valid
|| state.closed
|| !state.issuance_enabled
|| !generation
.proxy_shared
.is_user_enabled(&replacement.profile.user)
{
drop(state);
self.cancel_replacement(bootstrap_hash, &replacement.old_session);
return Err(ManagerError::Closed);
}
let Some(mut user_publication) = generation.proxy_shared.claim_authenticated_user(
&replacement.profile.user,
replacement.profile.credential_id,
) else {
drop(state);
self.cancel_replacement(bootstrap_hash, &replacement.old_session);
return Err(ManagerError::Closed);
};
let Some(user_registration) = user_publication.take_registration() else {
drop(state);
self.cancel_replacement(bootstrap_hash, &replacement.old_session);
return Err(ManagerError::Closed);
};
let Some((session_token, session_hash)) = new_unique_token(&generation, &state) else {
self.record_limit_hit();
self.telemetry
@@ -86,6 +96,7 @@ impl WebProcessRuntime {
replacement.recovery,
self.limits.clone(),
replacement.old_session.timeouts().clone(),
Some(user_registration),
);
let Some(supersede) = replacement.old_session.prepare_carrier_supersede() else {
drop(state);
@@ -146,6 +157,7 @@ impl WebProcessRuntime {
index.bootstrap_hash = bootstrap_hash;
index.attempt = replacement.attempt;
}
user_publication.commit();
let identity = session.trace_identity();
let old_identity = replacement.old_session.trace_identity();
drop(state);
+4
View File
@@ -10,6 +10,7 @@ use zeroize::Zeroizing;
use super::{CarrierRequest, ProfileKey, TOKEN_BYTES, TokenHash};
use crate::config::{WebCarrier, WebRuntimeConfig, WebRuntimeProfile, WebTimeoutsConfig};
use crate::maestro::generation::RuntimeGeneration;
use crate::proxy::user_admission::UserSessionRegistration;
use crate::web::session::WebSession;
use crate::web::telemetry::WebCarrierSelectionDisposition;
@@ -34,6 +35,8 @@ impl CarrierChainPhase {
/// One issued bootstrap and optional idempotent session-creation replay state.
pub(super) struct Bootstrap {
/// User authority ownership retained for the credential lifetime.
pub(super) user_registration: UserSessionRegistration,
/// Credential and replay-state expiry deadline.
pub(super) expires_at: Instant,
/// Stable ordering point used for bounded eviction.
@@ -273,6 +276,7 @@ pub(super) fn matching_profile(
profile.host == expected.host
&& profile.public_addr == expected.public_addr
&& profile.user == expected.user
&& profile.credential_id == expected.credential_id
&& profile.secret_mode == expected.secret_mode
&& profile.carrier == expected.carrier
&& profile.carrier_negotiation_enabled == expected.carrier_negotiation_enabled