feat!: drop the backend-side elevation windows; password and passkey sessions share capabilities, passkeys guard what nodes verify; the trust page lists added and removed passkeys [CI]

This commit is contained in:
justme committed 2026-10-08 04:57:28 +08:00
1 parent f704c66dd9
commit 4106f831dc
34 files changed
+191 -1364

No files matched your search

@@ -60,9 +60,6 @@ public static class PrincipalResolver
/// </summary>
public sealed record CapabilityRequirement(string? Capability);
/// <summary>端点自己验 passkey 签名(见 <see cref="EndpointConventions.ElevationExempt"/>)。</summary>
public sealed record ElevationExemptMarker;
/// <summary>管理层守卫:按端点声明的能力授权;Cookie 会话的非 GET 请求必须带 <c>X-CSRF-Token</c>。</summary>
public static class CapabilityGuard
{
@@ -92,12 +89,6 @@ public static class CapabilityGuard
}
}
// 信任类的操作(加节点、吊销、改凭证):登录用户还要有这一种的提权窗口;API key 自己带着能力,不经过这里
if (requirement.Capability is { } trusted && Elevation.For(trusted) is { } elevation && http.GetEndpoint()?.Metadata.GetMetadata<ElevationExemptMarker>() is null && ElevationGate.Require(http, elevation, consume: true) is { } needed)
{
return needed;
}
if (principal.Kind != PrincipalKind.Anonymous && !HttpMethods.IsGet(http.Request.Method) && !HttpMethods.IsHead(http.Request.Method) && !HttpMethods.IsOptions(http.Request.Method))
{
// 写操作都记审计:响应发完之后才知道结果,所以放在 OnCompleted 里
@@ -120,24 +111,6 @@ public static class CapabilityGuard
}
}
/// <summary>提权检查:登录用户(含用 return_session 拿到的 Bearer 会话)要有对应种类的有效窗口,API key 不需要。</summary>
public static class ElevationGate
{
/// <summary>没问题返回 null;否则 403 <c>elevation_required</c>,detail 是缺的窗口种类,前端据此触碰 passkey 后重试。</summary>
public static IResult? Require(HttpContext http, ElevationClass elevation, bool consume)
{
Principal principal = http.GetPrincipal();
if (principal.UserId is null)
{
return null;
}
return principal.SessionId is { } session && http.RequestServices.GetRequiredService<ElevationService>().Check(session, elevation, consume)
? null
: Problems.Create(http, MoShiroErrors.ElevationRequired, Elevation.IdOf(elevation));
}
}
/// <summary>展示层守卫:站点公开时匿名可读;私有时需要登录或只读令牌。</summary>
public static class PublicGuard
{