mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-02 09:20:22 +08:00
refactor: 大规模模块拆分与重组,新增 aether-admin crate
- 新建独立 aether-admin crate 承载 admin 相关共享契约与纯辅助函数 - 拆分 ai_pipeline 下 kiro/private_envelope/conversion/planner 等大文件为子模块目录 - 重组 admin handlers 各业务域(billing/oauth/provider/system/users 等)为目录结构,移除 shared.rs/builders.rs 等反模式 - 移除 ai_pipeline runtime adapters 旧实现(claude/openai/gemini/kiro/vertex/antigravity 等),改由 provider transport 统一承载 - 移除 control_facade/execution_facade/auth_snapshot_facade 等冗余 facade 层 - 拆分 query/billing 与 query/monitoring 模块、state/runtime/payments 与 security 模块 - 扩展架构测试覆盖 admin_billing/admin_model/admin_users 等新模块 - 删除 docs/architecture/refactor-execution-plan.md 已完成的执行计划文档
This commit is contained in:
148
apps/aether-gateway/src/tests/architecture/admin_billing.rs
Normal file
148
apps/aether-gateway/src/tests/architecture/admin_billing.rs
Normal file
@@ -0,0 +1,148 @@
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn admin_billing_wallets_boundaries_are_split() {
|
||||
let wallets_mod =
|
||||
read_workspace_file("apps/aether-gateway/src/handlers/admin/billing/wallets/mod.rs");
|
||||
for pattern in ["mod mutations;", "mod reads;", "mod routes;", "mod shared;"] {
|
||||
assert!(
|
||||
wallets_mod.contains(pattern),
|
||||
"handlers/admin/billing/wallets/mod.rs should register {pattern}"
|
||||
);
|
||||
}
|
||||
|
||||
let shared_mod =
|
||||
read_workspace_file("apps/aether-gateway/src/handlers/admin/billing/wallets/shared/mod.rs");
|
||||
for pattern in [
|
||||
"mod normalizers;",
|
||||
"mod payloads;",
|
||||
"mod requests;",
|
||||
"mod responses;",
|
||||
"mod support;",
|
||||
] {
|
||||
assert!(
|
||||
shared_mod.contains(pattern),
|
||||
"handlers/admin/billing/wallets/shared/mod.rs should register {pattern}"
|
||||
);
|
||||
}
|
||||
|
||||
let mutations_mod = read_workspace_file(
|
||||
"apps/aether-gateway/src/handlers/admin/billing/wallets/mutations/mod.rs",
|
||||
);
|
||||
for pattern in [
|
||||
"mod adjust;",
|
||||
"mod complete_refund;",
|
||||
"mod fail_refund;",
|
||||
"mod process_refund;",
|
||||
"mod recharge;",
|
||||
] {
|
||||
assert!(
|
||||
mutations_mod.contains(pattern),
|
||||
"handlers/admin/billing/wallets/mutations/mod.rs should register {pattern}"
|
||||
);
|
||||
}
|
||||
|
||||
let reads_mod =
|
||||
read_workspace_file("apps/aether-gateway/src/handlers/admin/billing/wallets/reads/mod.rs");
|
||||
for pattern in [
|
||||
"mod detail;",
|
||||
"mod ledger;",
|
||||
"mod list;",
|
||||
"mod refund_requests;",
|
||||
"mod refunds;",
|
||||
"mod transactions;",
|
||||
] {
|
||||
assert!(
|
||||
reads_mod.contains(pattern),
|
||||
"handlers/admin/billing/wallets/reads/mod.rs should register {pattern}"
|
||||
);
|
||||
}
|
||||
|
||||
for path in [
|
||||
"apps/aether-gateway/src/handlers/admin/billing/wallets/shared/core.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/billing/wallets/mutations/core.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/billing/wallets/reads.rs",
|
||||
] {
|
||||
assert!(
|
||||
!workspace_file_exists(path),
|
||||
"{path} should be removed after wallets boundaries are split"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn admin_billing_collectors_owner_is_split() {
|
||||
let collectors_mod =
|
||||
read_workspace_file("apps/aether-gateway/src/handlers/admin/billing/collectors/mod.rs");
|
||||
for pattern in ["mod reads;", "mod support;", "mod writes;"] {
|
||||
assert!(
|
||||
collectors_mod.contains(pattern),
|
||||
"handlers/admin/billing/collectors/mod.rs should register {pattern}"
|
||||
);
|
||||
}
|
||||
|
||||
for path in [
|
||||
"apps/aether-gateway/src/handlers/admin/billing/collectors/support.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/billing/collectors/reads.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/billing/collectors/writes.rs",
|
||||
] {
|
||||
assert!(
|
||||
workspace_file_exists(path),
|
||||
"{path} should exist after collectors owner split"
|
||||
);
|
||||
}
|
||||
|
||||
assert!(
|
||||
!workspace_file_exists("apps/aether-gateway/src/handlers/admin/billing/collectors.rs"),
|
||||
"handlers/admin/billing/collectors.rs should be removed after collectors owner split"
|
||||
);
|
||||
|
||||
let collectors_support =
|
||||
read_workspace_file("apps/aether-gateway/src/handlers/admin/billing/collectors/support.rs");
|
||||
assert!(
|
||||
!collectors_support.contains("pub(super) use super::super::{"),
|
||||
"handlers/admin/billing/collectors/support.rs should not keep wildcard bridge re-export from billing root"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn admin_billing_presets_owner_is_split() {
|
||||
let presets_mod =
|
||||
read_workspace_file("apps/aether-gateway/src/handlers/admin/billing/presets/mod.rs");
|
||||
for pattern in ["mod apply;", "mod support;"] {
|
||||
assert!(
|
||||
presets_mod.contains(pattern),
|
||||
"handlers/admin/billing/presets/mod.rs should register {pattern}"
|
||||
);
|
||||
}
|
||||
|
||||
for path in [
|
||||
"apps/aether-gateway/src/handlers/admin/billing/presets/support.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/billing/presets/apply.rs",
|
||||
] {
|
||||
assert!(
|
||||
workspace_file_exists(path),
|
||||
"{path} should exist after presets owner split"
|
||||
);
|
||||
}
|
||||
|
||||
assert!(
|
||||
!workspace_file_exists("apps/aether-gateway/src/handlers/admin/billing/presets.rs"),
|
||||
"handlers/admin/billing/presets.rs should be removed after presets owner split"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn admin_billing_wallets_support_uses_wrapped_request_context() {
|
||||
let wallets_support = read_workspace_file(
|
||||
"apps/aether-gateway/src/handlers/admin/billing/wallets/shared/support.rs",
|
||||
);
|
||||
assert!(
|
||||
wallets_support.contains("use crate::handlers::admin::request::AdminRequestContext;"),
|
||||
"handlers/admin/billing/wallets/shared/support.rs should consume wrapped AdminRequestContext"
|
||||
);
|
||||
assert!(
|
||||
!wallets_support.contains("GatewayPublicRequestContext"),
|
||||
"handlers/admin/billing/wallets/shared/support.rs should not keep raw GatewayPublicRequestContext seam"
|
||||
);
|
||||
}
|
||||
52
apps/aether-gateway/src/tests/architecture/admin_model.rs
Normal file
52
apps/aether-gateway/src/tests/architecture/admin_model.rs
Normal file
@@ -0,0 +1,52 @@
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn admin_model_global_owner_is_split() {
|
||||
let global_mod =
|
||||
read_workspace_file("apps/aether-gateway/src/handlers/admin/model/global/mod.rs");
|
||||
for pattern in ["mod helpers;", "mod payloads;", "mod providers;"] {
|
||||
assert!(
|
||||
global_mod.contains(pattern),
|
||||
"handlers/admin/model/global/mod.rs should register {pattern}"
|
||||
);
|
||||
}
|
||||
for path in [
|
||||
"apps/aether-gateway/src/handlers/admin/model/global/helpers.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/model/global/payloads.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/model/global/providers.rs",
|
||||
] {
|
||||
assert!(
|
||||
workspace_file_exists(path),
|
||||
"{path} should exist after model/global owner split"
|
||||
);
|
||||
}
|
||||
assert!(
|
||||
!workspace_file_exists("apps/aether-gateway/src/handlers/admin/model/global.rs"),
|
||||
"handlers/admin/model/global.rs should be removed after owner split"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn admin_model_root_exposes_single_route_seam() {
|
||||
let model_mod = read_workspace_file("apps/aether-gateway/src/handlers/admin/model/mod.rs");
|
||||
assert!(
|
||||
model_mod.contains("mod routes;"),
|
||||
"handlers/admin/model/mod.rs should register routes.rs as the model route seam"
|
||||
);
|
||||
assert!(
|
||||
model_mod.contains("pub(super) use self::routes::maybe_build_local_admin_model_response;"),
|
||||
"handlers/admin/model/mod.rs should expose maybe_build_local_admin_model_response"
|
||||
);
|
||||
|
||||
let model_routes =
|
||||
read_workspace_file("apps/aether-gateway/src/handlers/admin/model/routes.rs");
|
||||
for pattern in [
|
||||
"catalog_routes::maybe_build_local_admin_model_catalog_response(",
|
||||
"global_models::maybe_build_local_admin_global_models_response(",
|
||||
] {
|
||||
assert!(
|
||||
model_routes.contains(pattern),
|
||||
"handlers/admin/model/routes.rs should dispatch through {pattern}"
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -44,13 +44,7 @@ fn non_admin_handlers_do_not_depend_on_admin_stats_module() {
|
||||
let admin_observability_mod =
|
||||
read_workspace_file("apps/aether-gateway/src/handlers/admin/observability/mod.rs");
|
||||
for pattern in [
|
||||
"admin_stats_bad_request_response",
|
||||
"aggregate_usage_stats",
|
||||
"list_usage_for_optional_range",
|
||||
"parse_bounded_u32",
|
||||
"round_to",
|
||||
"AdminStatsTimeRange",
|
||||
"AdminStatsUsageFilter",
|
||||
"match_admin_monitoring_route",
|
||||
"AdminMonitoringRoute",
|
||||
"ADMIN_MONITORING_REDIS_REQUIRED_DETAIL",
|
||||
@@ -61,12 +55,25 @@ fn non_admin_handlers_do_not_depend_on_admin_stats_module() {
|
||||
"handlers/admin/observability/mod.rs should not re-export {pattern}"
|
||||
);
|
||||
}
|
||||
for pattern in [
|
||||
"admin_stats_bad_request_response",
|
||||
"list_usage_for_optional_range",
|
||||
"parse_bounded_u32",
|
||||
"round_to",
|
||||
"AdminStatsTimeRange",
|
||||
"AdminStatsUsageFilter",
|
||||
] {
|
||||
assert!(
|
||||
admin_observability_mod.contains(pattern),
|
||||
"handlers/admin/observability/mod.rs should expose admin stats facade helper {pattern}"
|
||||
);
|
||||
}
|
||||
|
||||
let shared_usage_stats =
|
||||
read_workspace_file("apps/aether-gateway/src/handlers/shared/usage_stats.rs");
|
||||
assert!(
|
||||
shared_usage_stats.contains("crate::handlers::admin::observability::stats::{"),
|
||||
"handlers/shared/usage_stats.rs should depend on observability::stats directly"
|
||||
shared_usage_stats.contains("crate::admin_api::{"),
|
||||
"handlers/shared/usage_stats.rs should depend on crate::admin_api facade directly"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -103,8 +110,8 @@ fn admin_monitoring_root_stays_thin() {
|
||||
"handlers/admin/observability/monitoring/mod.rs should register cache_mutations as a dedicated mutation boundary"
|
||||
);
|
||||
assert!(
|
||||
monitoring_mod.contains("mod responses;"),
|
||||
"handlers/admin/observability/monitoring/mod.rs should register responses as a dedicated response boundary"
|
||||
!monitoring_mod.contains("mod responses;"),
|
||||
"handlers/admin/observability/monitoring/mod.rs should not keep local monitoring responses after crate split"
|
||||
);
|
||||
assert!(
|
||||
!workspace_file_exists(
|
||||
@@ -112,6 +119,35 @@ fn admin_monitoring_root_stays_thin() {
|
||||
),
|
||||
"handlers/admin/observability/monitoring/common.rs should stay removed after boundary split"
|
||||
);
|
||||
assert!(
|
||||
!workspace_file_exists(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/monitoring/responses.rs",
|
||||
),
|
||||
"handlers/admin/observability/monitoring/responses.rs should stay removed after crate split"
|
||||
);
|
||||
|
||||
let monitoring_routes = read_workspace_file(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/monitoring/routes.rs",
|
||||
);
|
||||
for pattern in [
|
||||
"use aether_admin::observability::monitoring::{",
|
||||
"match_admin_monitoring_route",
|
||||
"AdminMonitoringRoute",
|
||||
] {
|
||||
assert!(
|
||||
monitoring_routes.contains(pattern),
|
||||
"handlers/admin/observability/monitoring/routes.rs should depend on crate-owned monitoring seam {pattern}"
|
||||
);
|
||||
}
|
||||
for pattern in [
|
||||
"pub(crate) enum AdminMonitoringRoute",
|
||||
"pub(crate) fn match_admin_monitoring_route(",
|
||||
] {
|
||||
assert!(
|
||||
!monitoring_routes.contains(pattern),
|
||||
"handlers/admin/observability/monitoring/routes.rs should not keep local monitoring route matcher {pattern}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -120,8 +156,6 @@ fn admin_stats_root_stays_thin() {
|
||||
read_workspace_file("apps/aether-gateway/src/handlers/admin/observability/stats/mod.rs");
|
||||
for pattern in [
|
||||
"use self::leaderboard::{",
|
||||
"use self::responses::{",
|
||||
"use self::timeseries::{",
|
||||
"enum AdminStatsComparisonType",
|
||||
"enum AdminStatsGranularity",
|
||||
"struct AdminStatsForecastPoint",
|
||||
@@ -130,6 +164,12 @@ fn admin_stats_root_stays_thin() {
|
||||
"struct AdminStatsTimeSeriesBucket",
|
||||
"impl AdminStatsTimeRange {",
|
||||
"pub(crate) fn round_to(",
|
||||
"mod helpers;",
|
||||
"mod responses;",
|
||||
"mod timeseries;",
|
||||
"pub(crate) use self::helpers::{round_to, AdminStatsTimeRange, AdminStatsUsageFilter};",
|
||||
"pub(crate) use self::responses::admin_stats_bad_request_response;",
|
||||
"pub(crate) use self::timeseries::aggregate_usage_stats;",
|
||||
] {
|
||||
assert!(
|
||||
!stats_mod.contains(pattern),
|
||||
@@ -137,70 +177,107 @@ fn admin_stats_root_stays_thin() {
|
||||
);
|
||||
}
|
||||
for pattern in [
|
||||
"mod helpers;",
|
||||
"pub(crate) use self::helpers::{round_to, AdminStatsTimeRange, AdminStatsUsageFilter};",
|
||||
"pub(crate) use self::range::{list_usage_for_optional_range, parse_bounded_u32};",
|
||||
"pub(crate) use self::responses::admin_stats_bad_request_response;",
|
||||
"pub(crate) use self::timeseries::aggregate_usage_stats;",
|
||||
"pub(crate) use aether_admin::observability::stats::{",
|
||||
"admin_stats_bad_request_response",
|
||||
"aggregate_usage_stats",
|
||||
"round_to",
|
||||
"AdminStatsTimeRange",
|
||||
"AdminStatsUsageFilter",
|
||||
] {
|
||||
assert!(
|
||||
stats_mod.contains(pattern),
|
||||
"handlers/admin/observability/stats/mod.rs should stay as a thin seam for {pattern}"
|
||||
);
|
||||
}
|
||||
assert!(
|
||||
stats_mod.contains("pub(crate) use self::range::{"),
|
||||
"handlers/admin/observability/stats/mod.rs should re-export the split range seam"
|
||||
);
|
||||
for pattern in [
|
||||
"list_usage_for_optional_range",
|
||||
"list_usage_for_range",
|
||||
"parse_bounded_u32",
|
||||
] {
|
||||
assert!(
|
||||
stats_mod.contains(pattern),
|
||||
"handlers/admin/observability/stats/mod.rs should keep range re-export {pattern}"
|
||||
);
|
||||
}
|
||||
|
||||
let analytics_routes = read_workspace_file(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/stats/analytics_routes.rs",
|
||||
);
|
||||
for pattern in [
|
||||
"use super::helpers::{",
|
||||
"use super::range::{",
|
||||
"use super::responses::{",
|
||||
"use super::timeseries::{",
|
||||
"use aether_admin::observability::stats::{",
|
||||
"AdminStatsComparisonType",
|
||||
"build_admin_stats_comparison_response",
|
||||
] {
|
||||
assert!(
|
||||
analytics_routes.contains(pattern),
|
||||
"stats/analytics_routes.rs should depend on split stats boundaries via {pattern}"
|
||||
"stats/analytics_routes.rs should depend on crate-owned stats helper {pattern}"
|
||||
);
|
||||
}
|
||||
assert!(
|
||||
!analytics_routes.contains("use super::helpers::{")
|
||||
&& !analytics_routes.contains("use super::responses::{")
|
||||
&& !analytics_routes.contains("use super::timeseries::{"),
|
||||
"stats/analytics_routes.rs should no longer depend on local stats pure bridges"
|
||||
);
|
||||
assert!(
|
||||
analytics_routes.contains("use super::range::{")
|
||||
|| analytics_routes.contains("use super::range::build_comparison_range;"),
|
||||
"stats/analytics_routes.rs should depend on the split stats range seam"
|
||||
);
|
||||
|
||||
let cost_routes = read_workspace_file(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/stats/cost_routes.rs",
|
||||
);
|
||||
for pattern in [
|
||||
"use super::helpers::{",
|
||||
"use super::range::{",
|
||||
"use super::responses::{",
|
||||
"use super::timeseries::{",
|
||||
"use aether_admin::observability::stats::{",
|
||||
"build_admin_stats_cost_forecast_response",
|
||||
] {
|
||||
assert!(
|
||||
cost_routes.contains(pattern),
|
||||
"stats/cost_routes.rs should depend on split stats boundaries via {pattern}"
|
||||
"stats/cost_routes.rs should depend on crate-owned stats helper {pattern}"
|
||||
);
|
||||
}
|
||||
assert!(
|
||||
!cost_routes.contains("use super::helpers::{")
|
||||
&& !cost_routes.contains("use super::responses::{")
|
||||
&& !cost_routes.contains("use super::timeseries::{"),
|
||||
"stats/cost_routes.rs should no longer depend on local stats pure bridges"
|
||||
);
|
||||
|
||||
let leaderboard_routes = read_workspace_file(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/stats/leaderboard_routes.rs",
|
||||
);
|
||||
for pattern in [
|
||||
"use super::helpers::{",
|
||||
"use super::leaderboard::{",
|
||||
"use super::range::{",
|
||||
"use super::responses::{",
|
||||
"use aether_admin::observability::stats::{",
|
||||
"admin_stats_leaderboard_empty_response",
|
||||
] {
|
||||
assert!(
|
||||
leaderboard_routes.contains(pattern),
|
||||
"stats/leaderboard_routes.rs should depend on split stats boundaries via {pattern}"
|
||||
"stats/leaderboard_routes.rs should depend on explicit local/crate owner {pattern}"
|
||||
);
|
||||
}
|
||||
assert!(
|
||||
!leaderboard_routes.contains("use super::helpers::{")
|
||||
&& !leaderboard_routes.contains("use super::responses::{"),
|
||||
"stats/leaderboard_routes.rs should no longer depend on local stats pure bridges"
|
||||
);
|
||||
|
||||
let provider_quota_routes = read_workspace_file(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/stats/provider_quota_routes.rs",
|
||||
);
|
||||
assert!(
|
||||
provider_quota_routes
|
||||
.contains("use super::responses::admin_stats_provider_quota_usage_empty_response;"),
|
||||
"stats/provider_quota_routes.rs should depend on responses boundary directly"
|
||||
provider_quota_routes.contains("use aether_admin::observability::stats::{")
|
||||
|| provider_quota_routes.contains(
|
||||
"use aether_admin::observability::stats::admin_stats_provider_quota_usage_empty_response;",
|
||||
),
|
||||
"stats/provider_quota_routes.rs should depend on crate-owned responses directly"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -226,23 +303,33 @@ fn admin_monitoring_cache_mutations_are_split_from_reads() {
|
||||
}
|
||||
|
||||
let monitoring_cache_mutations = read_workspace_file(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/monitoring/cache_mutations.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/observability/monitoring/cache_mutations/mod.rs",
|
||||
);
|
||||
for pattern in [
|
||||
"pub(super) async fn build_admin_monitoring_cache_users_delete_response(",
|
||||
"pub(super) async fn build_admin_monitoring_cache_affinity_delete_response(",
|
||||
"pub(super) async fn build_admin_monitoring_cache_flush_response(",
|
||||
"pub(super) async fn build_admin_monitoring_cache_provider_delete_response(",
|
||||
"pub(super) async fn build_admin_monitoring_model_mapping_delete_response(",
|
||||
"pub(super) async fn build_admin_monitoring_model_mapping_delete_model_response(",
|
||||
"pub(super) async fn build_admin_monitoring_model_mapping_delete_provider_response(",
|
||||
"pub(super) async fn build_admin_monitoring_redis_keys_delete_response(",
|
||||
"mod users;",
|
||||
"mod affinity;",
|
||||
"mod flush;",
|
||||
"mod provider;",
|
||||
"mod model_mapping;",
|
||||
"mod redis_keys;",
|
||||
"pub(super) use users::build_admin_monitoring_cache_users_delete_response;",
|
||||
"pub(super) use affinity::build_admin_monitoring_cache_affinity_delete_response;",
|
||||
"pub(super) use flush::build_admin_monitoring_cache_flush_response;",
|
||||
"pub(super) use provider::build_admin_monitoring_cache_provider_delete_response;",
|
||||
"pub(super) use model_mapping::{",
|
||||
"pub(super) use redis_keys::build_admin_monitoring_redis_keys_delete_response;",
|
||||
] {
|
||||
assert!(
|
||||
monitoring_cache_mutations.contains(pattern),
|
||||
"monitoring/cache_mutations.rs should own {pattern}"
|
||||
"monitoring/cache_mutations/mod.rs should own {pattern}"
|
||||
);
|
||||
}
|
||||
assert!(
|
||||
!workspace_file_exists(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/monitoring/cache_mutations.rs"
|
||||
),
|
||||
"monitoring/cache_mutations.rs should stay removed after directory split"
|
||||
);
|
||||
|
||||
let monitoring_routes = read_workspace_file(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/monitoring/routes.rs",
|
||||
@@ -297,6 +384,59 @@ fn admin_monitoring_cache_mutations_are_split_from_reads() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn admin_monitoring_route_payloads_prefer_crate_owned_builders() {
|
||||
for (path, pattern) in [
|
||||
(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/monitoring/activity.rs",
|
||||
"build_admin_monitoring_system_status_payload_response",
|
||||
),
|
||||
(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/monitoring/trace.rs",
|
||||
"build_admin_monitoring_trace_provider_stats_payload_response",
|
||||
),
|
||||
(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/monitoring/resilience/history.rs",
|
||||
"build_admin_monitoring_circuit_history_payload_response",
|
||||
),
|
||||
(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/monitoring/resilience/status.rs",
|
||||
"build_admin_monitoring_resilience_status_payload_response",
|
||||
),
|
||||
(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/monitoring/resilience/reset.rs",
|
||||
"build_admin_monitoring_reset_error_stats_payload_response",
|
||||
),
|
||||
(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/monitoring/cache_mutations/flush.rs",
|
||||
"build_admin_monitoring_cache_flush_success_response",
|
||||
),
|
||||
(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/monitoring/cache_mutations/provider.rs",
|
||||
"admin_monitoring_cache_provider_not_found_response",
|
||||
),
|
||||
(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/monitoring/cache_mutations/model_mapping.rs",
|
||||
"build_admin_monitoring_model_mapping_delete_success_response",
|
||||
),
|
||||
(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/monitoring/cache_mutations/redis_keys.rs",
|
||||
"build_admin_monitoring_redis_keys_delete_success_response",
|
||||
),
|
||||
] {
|
||||
let file = read_workspace_file(path);
|
||||
assert!(
|
||||
file.contains("use aether_admin::observability::monitoring::{")
|
||||
|| file.contains("use aether_admin::observability::monitoring::"),
|
||||
"{path} should depend on aether_admin::observability::monitoring"
|
||||
);
|
||||
assert!(
|
||||
file.contains(pattern),
|
||||
"{path} should route payload building through crate-owned helper {pattern}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn admin_usage_root_stays_thin() {
|
||||
let usage_mod =
|
||||
@@ -311,7 +451,6 @@ fn admin_usage_root_stays_thin() {
|
||||
"mod analytics;",
|
||||
"mod analytics_routes;",
|
||||
"mod detail_routes;",
|
||||
"mod helpers;",
|
||||
"mod replay;",
|
||||
"mod summary_routes;",
|
||||
"detail_routes::maybe_build_local_admin_usage_detail_response",
|
||||
@@ -324,47 +463,140 @@ fn admin_usage_root_stays_thin() {
|
||||
);
|
||||
}
|
||||
|
||||
let analytics_mod = read_workspace_file(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/usage/analytics/mod.rs",
|
||||
);
|
||||
for pattern in [
|
||||
"mod aggregations;",
|
||||
"mod cache_affinity;",
|
||||
"mod filters;",
|
||||
"pub(super) use aggregations::admin_usage_aggregation_by_user_json;",
|
||||
"pub(super) use cache_affinity::list_recent_completed_usage_for_cache_affinity;",
|
||||
"pub(super) use filters::admin_usage_provider_key_names;",
|
||||
] {
|
||||
assert!(
|
||||
analytics_mod.contains(pattern),
|
||||
"usage/analytics/mod.rs should keep explicit analytics owner seam {pattern}"
|
||||
);
|
||||
}
|
||||
for pattern in [
|
||||
"mod parse;",
|
||||
"admin_usage_aggregation_by_model_json",
|
||||
"admin_usage_parse_limit",
|
||||
"admin_usage_matches_search",
|
||||
] {
|
||||
assert!(
|
||||
!analytics_mod.contains(pattern),
|
||||
"usage/analytics/mod.rs should not keep pure crate forwarders {pattern}"
|
||||
);
|
||||
}
|
||||
assert!(
|
||||
!workspace_file_exists(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/usage/analytics.rs"
|
||||
),
|
||||
"usage/analytics.rs should be removed once analytics is directoryized"
|
||||
);
|
||||
|
||||
let analytics_routes = read_workspace_file(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/usage/analytics_routes.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/observability/usage/analytics_routes/mod.rs",
|
||||
);
|
||||
assert!(
|
||||
analytics_routes.contains("use super::analytics::{"),
|
||||
"usage/analytics_routes.rs should depend on analytics boundary directly"
|
||||
analytics_routes.contains("mod aggregation;"),
|
||||
"usage/analytics_routes/mod.rs should register aggregation owner"
|
||||
);
|
||||
assert!(
|
||||
analytics_routes.contains("use super::helpers::{"),
|
||||
"usage/analytics_routes.rs should depend on helpers boundary directly"
|
||||
analytics_routes.contains("mod cache_affinity_hit_analysis;"),
|
||||
"usage/analytics_routes/mod.rs should register cache_affinity_hit_analysis owner"
|
||||
);
|
||||
assert!(
|
||||
analytics_routes.contains("mod cache_affinity_interval_timeline;"),
|
||||
"usage/analytics_routes/mod.rs should register cache_affinity_interval_timeline owner"
|
||||
);
|
||||
assert!(
|
||||
analytics_routes.contains("mod cache_affinity_ttl_analysis;"),
|
||||
"usage/analytics_routes/mod.rs should register cache_affinity_ttl_analysis owner"
|
||||
);
|
||||
assert!(
|
||||
analytics_routes.contains("mod heatmap;"),
|
||||
"usage/analytics_routes/mod.rs should register heatmap owner"
|
||||
);
|
||||
assert!(
|
||||
analytics_routes.contains("aggregation::build_admin_usage_aggregation_stats_response"),
|
||||
"usage/analytics_routes/mod.rs should delegate aggregation handling to aggregation owner"
|
||||
);
|
||||
assert!(
|
||||
!workspace_file_exists(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/usage/analytics_routes.rs"
|
||||
),
|
||||
"usage/analytics_routes.rs should stay removed after directory split"
|
||||
);
|
||||
|
||||
let summary_routes = read_workspace_file(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/usage/summary_routes.rs",
|
||||
);
|
||||
assert!(
|
||||
summary_routes.contains("use super::analytics::{"),
|
||||
"usage/summary_routes.rs should depend on analytics boundary directly"
|
||||
summary_routes.contains("use super::analytics::admin_usage_provider_key_names;"),
|
||||
"usage/summary_routes.rs should keep only the local stateful analytics lookup"
|
||||
);
|
||||
assert!(
|
||||
summary_routes.contains("use super::helpers::{"),
|
||||
"usage/summary_routes.rs should depend on helpers boundary directly"
|
||||
summary_routes.contains("use aether_admin::observability::usage::{"),
|
||||
"usage/summary_routes.rs should depend on crate-owned usage helpers directly"
|
||||
);
|
||||
|
||||
let detail_routes = read_workspace_file(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/usage/detail_routes.rs",
|
||||
);
|
||||
assert!(
|
||||
detail_routes.contains("use super::analytics::{"),
|
||||
"usage/detail_routes.rs should depend on analytics boundary directly"
|
||||
detail_routes.contains("use super::analytics::admin_usage_provider_key_names;"),
|
||||
"usage/detail_routes.rs should keep only the local stateful analytics lookup"
|
||||
);
|
||||
assert!(
|
||||
detail_routes.contains("use super::helpers::{"),
|
||||
"usage/detail_routes.rs should depend on helpers boundary directly"
|
||||
detail_routes.contains("use aether_admin::observability::usage::{"),
|
||||
"usage/detail_routes.rs should depend on crate-owned usage helpers directly"
|
||||
);
|
||||
|
||||
let replay =
|
||||
read_workspace_file("apps/aether-gateway/src/handlers/admin/observability/usage/replay.rs");
|
||||
assert!(
|
||||
replay.contains("use super::helpers::{"),
|
||||
"usage/replay.rs should depend on helpers boundary directly"
|
||||
replay.contains("use aether_admin::observability::usage::{"),
|
||||
"usage/replay.rs should depend on crate-owned usage helpers directly"
|
||||
);
|
||||
|
||||
let analytics_aggregations = read_workspace_file(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/usage/analytics/aggregations.rs",
|
||||
);
|
||||
assert!(
|
||||
analytics_aggregations
|
||||
.contains("pub(in super::super) async fn admin_usage_aggregation_by_user_json("),
|
||||
"usage/analytics/aggregations.rs should keep only the local user aggregation owner"
|
||||
);
|
||||
let analytics_cache_affinity = read_workspace_file(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/usage/analytics/cache_affinity.rs",
|
||||
);
|
||||
assert!(
|
||||
analytics_cache_affinity.contains(
|
||||
"pub(in super::super) async fn list_recent_completed_usage_for_cache_affinity("
|
||||
),
|
||||
"usage/analytics/cache_affinity.rs should own cache-affinity analytics helpers"
|
||||
);
|
||||
let analytics_filters = read_workspace_file(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/usage/analytics/filters.rs",
|
||||
);
|
||||
assert!(
|
||||
analytics_filters.contains("pub(in super::super) async fn admin_usage_provider_key_names("),
|
||||
"usage/analytics/filters.rs should keep only the local provider key lookup"
|
||||
);
|
||||
assert!(
|
||||
!workspace_file_exists(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/usage/helpers.rs"
|
||||
),
|
||||
"usage/helpers.rs should stay removed after crate split"
|
||||
);
|
||||
assert!(
|
||||
!workspace_file_exists(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/usage/analytics/parse.rs"
|
||||
),
|
||||
"usage/analytics/parse.rs should stay removed after crate split"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -384,15 +616,41 @@ fn admin_monitoring_snapshots_stay_app_local() {
|
||||
}
|
||||
|
||||
let monitoring_resilience = read_workspace_file(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/monitoring/resilience.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/observability/monitoring/resilience/mod.rs",
|
||||
);
|
||||
assert!(
|
||||
monitoring_resilience.contains("AdminMonitoringResilienceSnapshot"),
|
||||
"monitoring/resilience.rs should keep resilience snapshot ownership locally"
|
||||
monitoring_resilience.contains("mod history;"),
|
||||
"monitoring/resilience/mod.rs should register history owner"
|
||||
);
|
||||
assert!(
|
||||
monitoring_resilience.contains("struct AdminMonitoringResilienceSnapshot"),
|
||||
"monitoring/resilience.rs should define AdminMonitoringResilienceSnapshot locally"
|
||||
monitoring_resilience.contains("mod snapshot;"),
|
||||
"monitoring/resilience/mod.rs should register snapshot owner"
|
||||
);
|
||||
assert!(
|
||||
monitoring_resilience.contains("mod status;"),
|
||||
"monitoring/resilience/mod.rs should register status owner"
|
||||
);
|
||||
assert!(
|
||||
monitoring_resilience.contains("mod reset;"),
|
||||
"monitoring/resilience/mod.rs should register reset owner"
|
||||
);
|
||||
assert!(
|
||||
!workspace_file_exists(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/monitoring/resilience.rs"
|
||||
),
|
||||
"monitoring/resilience.rs should stay removed after directory split"
|
||||
);
|
||||
|
||||
let resilience_snapshot = read_workspace_file(
|
||||
"apps/aether-gateway/src/handlers/admin/observability/monitoring/resilience/snapshot.rs",
|
||||
);
|
||||
assert!(
|
||||
resilience_snapshot.contains("AdminMonitoringResilienceSnapshot"),
|
||||
"monitoring/resilience/snapshot.rs should keep resilience snapshot ownership locally"
|
||||
);
|
||||
assert!(
|
||||
resilience_snapshot.contains("pub(super) struct AdminMonitoringResilienceSnapshot"),
|
||||
"monitoring/resilience/snapshot.rs should define AdminMonitoringResilienceSnapshot locally"
|
||||
);
|
||||
|
||||
let data_system = read_workspace_file("crates/aether-data/src/repository/system.rs");
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,229 @@
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn admin_external_usage_is_confined_to_admin_api() {
|
||||
let workspace_root = std::path::Path::new(env!("CARGO_MANIFEST_DIR"))
|
||||
.join("../..")
|
||||
.canonicalize()
|
||||
.expect("workspace root should resolve");
|
||||
let mut violations = Vec::new();
|
||||
|
||||
for file in collect_workspace_rust_files("apps/aether-gateway/src") {
|
||||
let relative = file
|
||||
.canonicalize()
|
||||
.expect("workspace file should canonicalize")
|
||||
.strip_prefix(&workspace_root)
|
||||
.expect("workspace file should be under workspace root")
|
||||
.to_string_lossy()
|
||||
.replace('\\', "/");
|
||||
if relative == "apps/aether-gateway/src/admin_api.rs"
|
||||
|| relative.starts_with("apps/aether-gateway/src/handlers/admin/")
|
||||
|| relative.starts_with("apps/aether-gateway/src/tests/")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
let source = std::fs::read_to_string(&file).expect("source file should be readable");
|
||||
if source.contains("crate::handlers::admin::")
|
||||
|| source.contains("use crate::handlers::admin::")
|
||||
{
|
||||
violations.push(relative);
|
||||
}
|
||||
}
|
||||
|
||||
assert!(
|
||||
violations.is_empty(),
|
||||
"gateway code outside admin_api.rs should not directly depend on handlers::admin internals:\n{}",
|
||||
violations.join("\n")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn admin_wrapped_state_owns_api_key_and_proxy_capabilities() {
|
||||
let admin_request =
|
||||
read_workspace_module_tree("apps/aether-gateway/src/handlers/admin/request/mod.rs");
|
||||
for pattern in [
|
||||
"pub(crate) fn has_auth_api_key_writer(&self) -> bool",
|
||||
"pub(crate) fn encryption_key(&self) -> Option<&str>",
|
||||
"pub(crate) fn encrypt_catalog_secret_with_fallbacks(&self, secret: &str) -> Option<String>",
|
||||
"pub(crate) fn decrypt_catalog_secret_with_fallbacks(",
|
||||
"pub(crate) async fn add_admin_security_blacklist(",
|
||||
"pub(crate) async fn list_auth_api_key_snapshots_by_ids(",
|
||||
"pub(crate) async fn list_auth_api_key_export_records_by_user_ids(",
|
||||
"pub(crate) async fn list_auth_api_key_export_standalone_records_page(",
|
||||
"pub(crate) async fn count_auth_api_key_export_standalone_records(",
|
||||
"pub(crate) async fn find_auth_api_key_export_standalone_record_by_id(",
|
||||
"pub(crate) async fn create_user_api_key(",
|
||||
"pub(crate) async fn create_standalone_api_key(",
|
||||
"pub(crate) async fn resolve_transport_proxy_snapshot_with_tunnel_affinity(",
|
||||
"pub(crate) async fn update_user_api_key_basic(",
|
||||
"pub(crate) async fn update_standalone_api_key_basic(",
|
||||
"pub(crate) async fn set_standalone_api_key_active(",
|
||||
"pub(crate) async fn set_user_api_key_locked(",
|
||||
"pub(crate) async fn set_user_api_key_allowed_providers(",
|
||||
"pub(crate) async fn summarize_usage_total_tokens_by_api_key_ids(",
|
||||
"pub(crate) async fn delete_user_api_key(",
|
||||
"pub(crate) async fn delete_standalone_api_key(",
|
||||
] {
|
||||
assert!(
|
||||
admin_request.contains(pattern),
|
||||
"handlers/admin/request/mod.rs should expose admin state capability {pattern}"
|
||||
);
|
||||
}
|
||||
|
||||
for path in [
|
||||
"apps/aether-gateway/src/handlers/admin/auth/api_keys/mutation_routes.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/auth/oauth_config.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/auth/ldap/builders.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/users/api_keys/responses/create.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/users/api_keys/responses/update.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/users/api_keys/responses/delete.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/users/api_keys/responses/toggle_lock.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/users/api_keys/responses/list.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/users/api_keys/responses/reveal.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/features/gemini_files/upload/stage.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/system/proxy_nodes.rs",
|
||||
] {
|
||||
let contents = read_workspace_file(path);
|
||||
assert!(
|
||||
!contents.contains("state.data.has_auth_api_key_writer()"),
|
||||
"{path} should use AdminAppState capability instead of raw state.data.has_auth_api_key_writer()"
|
||||
);
|
||||
assert!(
|
||||
!contents.contains("state.data.has_proxy_node_reader()"),
|
||||
"{path} should use AdminAppState capability instead of raw state.data.has_proxy_node_reader()"
|
||||
);
|
||||
assert!(
|
||||
!contents.contains(".data\n .list_auth_api_key_snapshots_by_ids(")
|
||||
&& !contents.contains(".data.list_auth_api_key_snapshots_by_ids("),
|
||||
"{path} should use AdminAppState snapshot capability instead of raw state.data.list_auth_api_key_snapshots_by_ids()"
|
||||
);
|
||||
assert!(
|
||||
!contents.contains("encrypt_catalog_secret_with_fallbacks(state.app(),"),
|
||||
"{path} should use AdminAppState encryption capability instead of raw state.app() encryption"
|
||||
);
|
||||
assert!(
|
||||
!contents.contains("decrypt_catalog_secret_with_fallbacks(state.app().encryption_key(),"),
|
||||
"{path} should use AdminAppState decryption capability instead of raw state.app().encryption_key()"
|
||||
);
|
||||
assert!(
|
||||
!contents.contains("resolve_transport_proxy_snapshot_with_tunnel_affinity(\n state.app(),")
|
||||
&& !contents.contains("resolve_transport_proxy_snapshot_with_tunnel_affinity(state.app(),"),
|
||||
"{path} should use AdminAppState proxy capability instead of raw state.app() transport proxy resolution"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn admin_wrapped_state_owns_billing_capabilities() {
|
||||
let admin_request =
|
||||
read_workspace_module_tree("apps/aether-gateway/src/handlers/admin/request/mod.rs");
|
||||
for pattern in [
|
||||
"pub(crate) fn has_postgres_pool(&self) -> bool",
|
||||
"pub(crate) async fn list_admin_billing_collectors(",
|
||||
"pub(crate) async fn read_admin_billing_collector(",
|
||||
"pub(crate) async fn create_admin_billing_collector(",
|
||||
"pub(crate) async fn update_admin_billing_collector(",
|
||||
"pub(crate) async fn apply_admin_billing_preset(",
|
||||
"pub(crate) async fn list_admin_billing_rules(",
|
||||
"pub(crate) async fn read_admin_billing_rule(",
|
||||
"pub(crate) async fn create_admin_billing_rule(",
|
||||
"pub(crate) async fn update_admin_billing_rule(",
|
||||
"pub(crate) async fn list_admin_wallets(",
|
||||
"pub(crate) async fn list_admin_wallet_ledger(",
|
||||
"pub(crate) async fn list_admin_wallet_refund_requests(",
|
||||
"pub(crate) async fn list_admin_wallet_transactions(",
|
||||
"pub(crate) async fn list_admin_wallet_refunds(",
|
||||
"pub(crate) async fn list_admin_payment_orders(",
|
||||
"pub(crate) async fn list_admin_payment_callbacks(",
|
||||
"pub(crate) async fn read_admin_payment_order(",
|
||||
"pub(crate) async fn admin_expire_payment_order(",
|
||||
"pub(crate) async fn admin_credit_payment_order(",
|
||||
"pub(crate) async fn admin_fail_payment_order(",
|
||||
"pub(crate) async fn admin_adjust_wallet_balance(",
|
||||
"pub(crate) async fn admin_create_manual_wallet_recharge(",
|
||||
"pub(crate) async fn admin_process_wallet_refund(",
|
||||
"pub(crate) async fn admin_complete_wallet_refund(",
|
||||
"pub(crate) async fn admin_fail_wallet_refund(",
|
||||
] {
|
||||
assert!(
|
||||
admin_request.contains(pattern),
|
||||
"handlers/admin/request/mod.rs should expose billing capability {pattern}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn admin_wrapped_state_owns_observability_capabilities() {
|
||||
let admin_request =
|
||||
read_workspace_module_tree("apps/aether-gateway/src/handlers/admin/request/mod.rs");
|
||||
for pattern in [
|
||||
"pub(crate) fn has_auth_api_key_data_reader(&self) -> bool",
|
||||
"pub(crate) fn has_user_data_reader(&self) -> bool",
|
||||
"pub(crate) async fn list_provider_catalog_providers(",
|
||||
"pub(crate) async fn list_admin_usage_for_range(",
|
||||
"pub(crate) async fn list_admin_usage_for_optional_range(",
|
||||
"pub(crate) async fn aggregate_finalized_request_candidate_timeline_by_endpoint_ids_since(",
|
||||
"pub(crate) async fn read_recent_request_candidates(",
|
||||
"pub(crate) fn provider_key_rpm_reset_at(",
|
||||
"pub(crate) async fn update_provider_catalog_key_health_state(",
|
||||
"pub(crate) async fn list_usage_audits(",
|
||||
"pub(crate) async fn list_users_by_ids(",
|
||||
] {
|
||||
assert!(
|
||||
admin_request.contains(pattern),
|
||||
"handlers/admin/request/mod.rs should expose observability capability {pattern}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn admin_wrapped_state_owns_provider_oauth_capabilities() {
|
||||
let admin_request =
|
||||
read_workspace_module_tree("apps/aether-gateway/src/handlers/admin/request/mod.rs");
|
||||
for pattern in [
|
||||
"pub(crate) fn cloned_app(&self) -> AppState",
|
||||
"pub(crate) async fn save_provider_oauth_state(",
|
||||
"pub(crate) async fn consume_provider_oauth_state(",
|
||||
"pub(crate) async fn exchange_admin_provider_oauth_code(",
|
||||
"pub(crate) async fn exchange_admin_provider_oauth_refresh_token(",
|
||||
"pub(crate) async fn save_provider_oauth_batch_task_payload(",
|
||||
"pub(crate) async fn read_provider_oauth_batch_task_payload(",
|
||||
"pub(crate) async fn save_provider_oauth_device_session(",
|
||||
"pub(crate) async fn read_provider_oauth_device_session(",
|
||||
"pub(crate) async fn register_admin_kiro_device_oidc_client(",
|
||||
"pub(crate) async fn start_admin_kiro_device_authorization(",
|
||||
"pub(crate) async fn poll_admin_kiro_device_token(",
|
||||
"pub(crate) async fn find_duplicate_provider_oauth_key(",
|
||||
"pub(crate) async fn create_provider_oauth_catalog_key(",
|
||||
"pub(crate) async fn update_existing_provider_oauth_catalog_key(",
|
||||
"pub(crate) async fn refresh_provider_oauth_account_state_after_update(",
|
||||
"pub(crate) async fn update_provider_catalog_key_oauth_credentials(",
|
||||
] {
|
||||
assert!(
|
||||
admin_request.contains(pattern),
|
||||
"handlers/admin/request/mod.rs should expose provider oauth capability {pattern}"
|
||||
);
|
||||
}
|
||||
|
||||
for path in [
|
||||
"apps/aether-gateway/src/handlers/admin/provider/oauth/dispatch/start.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/provider/oauth/dispatch/import.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/provider/oauth/dispatch/tasks.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/provider/oauth/dispatch/refresh/request.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/provider/oauth/dispatch/device/authorize.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/provider/oauth/dispatch/device/poll.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/provider/oauth/dispatch/complete/key.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/provider/oauth/dispatch/complete/provider.rs",
|
||||
] {
|
||||
let contents = read_workspace_file(path);
|
||||
assert!(
|
||||
!contents.contains("state.app()"),
|
||||
"{path} should use AdminAppState oauth capability instead of raw state.app()"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn admin_shared_does_not_own_provider_support() {
|
||||
let admin_shared = read_workspace_file("apps/aether-gateway/src/handlers/admin/shared/mod.rs");
|
||||
@@ -39,19 +263,46 @@ fn admin_shared_does_not_own_provider_support() {
|
||||
);
|
||||
}
|
||||
|
||||
let provider_paths =
|
||||
read_workspace_file("apps/aether-gateway/src/handlers/admin/provider/shared/paths.rs");
|
||||
assert!(
|
||||
!workspace_file_exists("apps/aether-gateway/src/handlers/admin/provider/shared/paths.rs"),
|
||||
"provider/shared/paths.rs should be replaced by split path-owner modules"
|
||||
);
|
||||
|
||||
let provider_paths_mod =
|
||||
read_workspace_file("apps/aether-gateway/src/handlers/admin/provider/shared/paths/mod.rs");
|
||||
for pattern in [
|
||||
"pub(crate) fn admin_provider_id_for_manage_path",
|
||||
"pub(crate) fn admin_provider_oauth_start_key_id",
|
||||
"pub(crate) fn admin_provider_ops_architecture_id_from_path",
|
||||
"pub(crate) use self::crud::{",
|
||||
"pub(crate) use self::oauth::{",
|
||||
"pub(crate) use self::ops::{",
|
||||
] {
|
||||
assert!(
|
||||
provider_paths.contains(pattern),
|
||||
"provider/shared/paths.rs should own {pattern}"
|
||||
provider_paths_mod.contains(pattern),
|
||||
"provider/shared/paths/mod.rs should re-export split path owners through {pattern}"
|
||||
);
|
||||
}
|
||||
|
||||
let provider_crud_paths =
|
||||
read_workspace_file("apps/aether-gateway/src/handlers/admin/provider/shared/paths/crud.rs");
|
||||
assert!(
|
||||
provider_crud_paths.contains("pub(crate) fn admin_provider_id_for_manage_path"),
|
||||
"provider/shared/paths/crud.rs should own admin_provider_id_for_manage_path"
|
||||
);
|
||||
|
||||
let provider_oauth_paths = read_workspace_file(
|
||||
"apps/aether-gateway/src/handlers/admin/provider/shared/paths/oauth.rs",
|
||||
);
|
||||
assert!(
|
||||
provider_oauth_paths.contains("pub(crate) fn admin_provider_oauth_start_key_id"),
|
||||
"provider/shared/paths/oauth.rs should own admin_provider_oauth_start_key_id"
|
||||
);
|
||||
|
||||
let provider_ops_paths =
|
||||
read_workspace_file("apps/aether-gateway/src/handlers/admin/provider/shared/paths/ops.rs");
|
||||
assert!(
|
||||
provider_ops_paths.contains("pub(crate) fn admin_provider_ops_architecture_id_from_path"),
|
||||
"provider/shared/paths/ops.rs should own admin_provider_ops_architecture_id_from_path"
|
||||
);
|
||||
|
||||
let provider_shared_mod =
|
||||
read_workspace_file("apps/aether-gateway/src/handlers/admin/provider/shared/mod.rs");
|
||||
for pattern in [
|
||||
@@ -264,22 +515,54 @@ fn admin_shared_does_not_own_system_core_routes_or_payloads() {
|
||||
#[test]
|
||||
fn admin_handlers_expose_real_subdomains_without_facade() {
|
||||
let admin_mod = read_workspace_file("apps/aether-gateway/src/handlers/admin/mod.rs");
|
||||
assert!(
|
||||
!admin_mod.contains("pub(crate) use self::"),
|
||||
"handlers/admin/mod.rs should stay as pure module wiring after facade removal"
|
||||
);
|
||||
|
||||
for pattern in [
|
||||
"mod announcements;",
|
||||
"pub(super) mod auth;",
|
||||
"pub(super) mod endpoint;",
|
||||
"pub(super) mod features;",
|
||||
"pub(super) mod observability;",
|
||||
"pub(super) mod provider;",
|
||||
"pub(super) mod request;",
|
||||
"pub(super) mod routes;",
|
||||
"mod system;",
|
||||
] {
|
||||
assert!(
|
||||
admin_mod.contains(pattern),
|
||||
"handlers/admin/mod.rs should expose admin subdomain module {pattern}"
|
||||
);
|
||||
}
|
||||
|
||||
for forbidden in [
|
||||
"pub(crate) mod announcements;",
|
||||
"pub(crate) mod auth;",
|
||||
"pub(crate) mod endpoint;",
|
||||
"pub(crate) mod features;",
|
||||
"pub(crate) mod observability;",
|
||||
"pub(crate) mod provider;",
|
||||
"pub(crate) mod system;",
|
||||
] {
|
||||
assert!(
|
||||
!admin_mod.contains(forbidden),
|
||||
"handlers/admin/mod.rs should keep non-api subdomains private for {forbidden}"
|
||||
);
|
||||
}
|
||||
|
||||
for pattern in [
|
||||
"pub(crate) use self::request::{",
|
||||
"AdminAppState",
|
||||
"AdminRequestContext",
|
||||
"AdminRouteRequest",
|
||||
"AdminRouteResponse",
|
||||
"AdminRouteResult",
|
||||
"pub(crate) use self::routes::maybe_build_local_admin_response;",
|
||||
"pub(crate) use self::provider::{",
|
||||
"maybe_build_local_admin_provider_oauth_response",
|
||||
"maybe_build_local_admin_providers_response",
|
||||
] {
|
||||
assert!(
|
||||
admin_mod.contains(pattern),
|
||||
"handlers/admin/mod.rs should expose admin subdomain module {pattern}"
|
||||
"handlers/admin/mod.rs should expose the crate-facing admin seam {pattern}"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -288,3 +571,525 @@ fn admin_handlers_expose_real_subdomains_without_facade() {
|
||||
"handlers/admin/facade.rs should be removed after direct subdomain exposure"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ai_pipeline_external_consumers_use_single_api_facade() {
|
||||
let ai_pipeline_mod = read_workspace_file("apps/aether-gateway/src/ai_pipeline/mod.rs");
|
||||
for pattern in [
|
||||
"mod adaptation;",
|
||||
"mod contracts;",
|
||||
"mod conversion;",
|
||||
"mod finalize;",
|
||||
"mod planner;",
|
||||
"pub(crate) mod transport;",
|
||||
"pub(crate) use self::finalize::internal::{",
|
||||
"pub(crate) use self::planner::{",
|
||||
"pub(crate) use crate::execution_runtime::{ConversionMode, ExecutionStrategy};",
|
||||
"pub(crate) async fn resolve_execution_runtime_auth_context(",
|
||||
"pub(crate) fn maybe_build_local_sync_finalize_response(",
|
||||
] {
|
||||
assert!(
|
||||
ai_pipeline_mod.contains(pattern),
|
||||
"ai_pipeline/mod.rs should expose only the crate-facing ai_pipeline seam for {pattern}"
|
||||
);
|
||||
}
|
||||
|
||||
for forbidden in [
|
||||
"pub(super) mod adaptation;",
|
||||
"pub(super) mod finalize;",
|
||||
"pub(super) mod planner;",
|
||||
"pub(crate) mod adaptation;",
|
||||
"pub(crate) mod contracts;",
|
||||
"pub(crate) mod conversion;",
|
||||
"pub(crate) mod finalize;",
|
||||
"pub(crate) mod planner;",
|
||||
"pub(super) mod api;",
|
||||
] {
|
||||
assert!(
|
||||
!ai_pipeline_mod.contains(forbidden),
|
||||
"ai_pipeline/mod.rs should not expose internal module {forbidden}"
|
||||
);
|
||||
}
|
||||
|
||||
for path in [
|
||||
"apps/aether-gateway/src/executor/orchestration.rs",
|
||||
"apps/aether-gateway/src/execution_runtime/sync/execution.rs",
|
||||
"apps/aether-gateway/src/execution_runtime/stream/execution.rs",
|
||||
"apps/aether-gateway/src/execution_runtime/submission.rs",
|
||||
"apps/aether-gateway/src/execution_runtime/tests.rs",
|
||||
"apps/aether-gateway/src/lib.rs",
|
||||
] {
|
||||
let contents = read_workspace_file(path);
|
||||
assert!(
|
||||
contents.contains("ai_pipeline_api"),
|
||||
"{path} should use the ai_pipeline_api facade"
|
||||
);
|
||||
for forbidden in [
|
||||
"crate::ai_pipeline::planner::",
|
||||
"crate::ai_pipeline::contracts::",
|
||||
"crate::ai_pipeline::adaptation::private_envelope",
|
||||
"crate::ai_pipeline::conversion::",
|
||||
] {
|
||||
assert!(
|
||||
!contents.contains(forbidden),
|
||||
"{path} should not bypass ai_pipeline_api through {forbidden}"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn crate_root_exposes_real_admin_and_ai_pipeline_facades() {
|
||||
let lib_rs = read_workspace_file("apps/aether-gateway/src/lib.rs");
|
||||
for pattern in ["mod admin_api;", "mod ai_pipeline_api;"] {
|
||||
assert!(
|
||||
lib_rs.contains(pattern),
|
||||
"lib.rs should register crate root facade module {pattern}"
|
||||
);
|
||||
}
|
||||
for forbidden in [
|
||||
"pub(crate) use self::handlers::admin_api;",
|
||||
"pub(crate) use self::ai_pipeline::api as ai_pipeline_api;",
|
||||
] {
|
||||
assert!(
|
||||
!lib_rs.contains(forbidden),
|
||||
"lib.rs should not keep alias-only facade wiring {forbidden}"
|
||||
);
|
||||
}
|
||||
|
||||
let admin_api = read_workspace_file("apps/aether-gateway/src/admin_api.rs");
|
||||
assert!(
|
||||
admin_api.contains("pub(crate) use crate::handlers::admin::{"),
|
||||
"admin_api.rs should own the crate root admin facade instead of re-exporting handlers/admin_api"
|
||||
);
|
||||
|
||||
let handlers_mod = read_workspace_file("apps/aether-gateway/src/handlers/mod.rs");
|
||||
assert!(
|
||||
handlers_mod.contains("pub(super) mod admin;"),
|
||||
"handlers/mod.rs should expose admin only to the crate root boundary"
|
||||
);
|
||||
assert!(
|
||||
!handlers_mod.contains("pub(super) mod admin_api;"),
|
||||
"handlers/mod.rs should not keep a separate handlers/admin_api facade module"
|
||||
);
|
||||
assert!(
|
||||
!handlers_mod.contains("pub(crate) use self::admin::api as admin_api;"),
|
||||
"handlers/mod.rs should not keep alias-only admin_api wiring after crate root facade extraction"
|
||||
);
|
||||
|
||||
let ai_pipeline_api = read_workspace_file("apps/aether-gateway/src/ai_pipeline_api.rs");
|
||||
assert!(
|
||||
ai_pipeline_api.contains("use crate::ai_pipeline::{is_json_request, GatewayControlDecision};"),
|
||||
"ai_pipeline_api.rs should depend on the crate-facing ai_pipeline seam instead of deep internal modules"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn gateway_ai_pipeline_api_facade_delegates_pure_ownership_to_pipeline_crate() {
|
||||
let gateway_api = read_workspace_file("apps/aether-gateway/src/ai_pipeline_api.rs");
|
||||
assert!(
|
||||
gateway_api.contains("pub(crate) use aether_ai_pipeline::api::{"),
|
||||
"crate root ai_pipeline_api.rs should re-export pure ownership through aether_ai_pipeline::api"
|
||||
);
|
||||
|
||||
let pipeline_crate_api = read_workspace_file("crates/aether-ai-pipeline/src/api.rs");
|
||||
for pattern in [
|
||||
"pub use crate::contracts::{",
|
||||
"pub use crate::conversion::{",
|
||||
"pub use crate::planner::common::{",
|
||||
"pub use crate::planner::route::{",
|
||||
] {
|
||||
assert!(
|
||||
pipeline_crate_api.contains(pattern),
|
||||
"aether-ai-pipeline/src/api.rs should expose crate facade seam {pattern}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn admin_proxy_uses_single_admin_routes_entrypoint() {
|
||||
let proxy_local = read_workspace_file("apps/aether-gateway/src/handlers/proxy/local.rs");
|
||||
assert!(
|
||||
proxy_local.contains("admin_api::maybe_build_local_admin_response("),
|
||||
"handlers/proxy/local.rs should delegate admin dispatch through crate root admin_api facade"
|
||||
);
|
||||
assert!(
|
||||
proxy_local.contains("admin_api::AdminRouteRequest::new("),
|
||||
"handlers/proxy/local.rs should construct AdminRouteRequest through crate root admin_api facade"
|
||||
);
|
||||
let admin_api = read_workspace_file("apps/aether-gateway/src/admin_api.rs");
|
||||
for pattern in [
|
||||
"pub(crate) use crate::handlers::admin::{",
|
||||
"AdminAppState",
|
||||
"AdminRequestContext",
|
||||
"AdminRouteRequest",
|
||||
"AdminRouteResponse",
|
||||
"AdminRouteResult",
|
||||
"maybe_build_local_admin_response",
|
||||
] {
|
||||
assert!(
|
||||
admin_api.contains(pattern),
|
||||
"admin_api.rs should own the public admin entry seam {pattern}"
|
||||
);
|
||||
}
|
||||
|
||||
for forbidden in [
|
||||
"auth as admin_auth",
|
||||
"billing as admin_billing",
|
||||
"endpoint as admin_endpoint",
|
||||
"features as admin_features",
|
||||
"model as admin_model",
|
||||
"observability as admin_observability",
|
||||
"provider as admin_provider",
|
||||
"system as admin_system",
|
||||
"users as admin_users",
|
||||
"public::maybe_build_local_admin_announcements_response(",
|
||||
"admin_auth::maybe_build_local_admin_auth_response(",
|
||||
"admin_observability::maybe_build_local_admin_observability_response(",
|
||||
"admin_features::maybe_build_local_admin_features_response(",
|
||||
"admin_users::maybe_build_local_admin_users_response(",
|
||||
"admin_provider::maybe_build_local_admin_provider_oauth_response(",
|
||||
"admin_provider::maybe_build_local_admin_provider_response(",
|
||||
"admin_system::maybe_build_local_admin_core_response(",
|
||||
"admin_system::maybe_build_local_admin_system_response(",
|
||||
"admin_billing::maybe_build_local_admin_billing_routes_response(",
|
||||
] {
|
||||
assert!(
|
||||
!proxy_local.contains(forbidden),
|
||||
"handlers/proxy/local.rs should not dispatch admin subdomains directly for {forbidden}"
|
||||
);
|
||||
}
|
||||
|
||||
let admin_routes = read_workspace_file("apps/aether-gateway/src/handlers/admin/routes.rs");
|
||||
for pattern in [
|
||||
"use super::{",
|
||||
"pub(crate) async fn maybe_build_local_admin_response(",
|
||||
"request::AdminRouteRequest<'_>",
|
||||
") -> request::AdminRouteResult {",
|
||||
"announcements::maybe_build_local_admin_announcements_response(",
|
||||
"auth::maybe_build_local_admin_auth_response(",
|
||||
"observability::maybe_build_local_admin_observability_response(",
|
||||
"features::maybe_build_local_admin_features_response(",
|
||||
"model::maybe_build_local_admin_model_response(",
|
||||
"provider::maybe_build_local_admin_provider_response(",
|
||||
"system::maybe_build_local_admin_system_response(",
|
||||
"billing::maybe_build_local_admin_billing_routes_response(",
|
||||
"users::maybe_build_local_admin_users_response(",
|
||||
"endpoint::maybe_build_local_admin_endpoints_response(",
|
||||
] {
|
||||
assert!(
|
||||
admin_routes.contains(pattern),
|
||||
"handlers/admin/routes.rs should own admin proxy dispatch seam {pattern}"
|
||||
);
|
||||
}
|
||||
|
||||
for forbidden in [
|
||||
"use super::super::public;",
|
||||
"public::maybe_build_local_admin_announcements_response(",
|
||||
"auth::maybe_build_local_admin_security_response(",
|
||||
"auth::maybe_build_local_admin_api_keys_response(",
|
||||
"auth::maybe_build_local_admin_ldap_response(",
|
||||
"observability::maybe_build_local_admin_stats_response(",
|
||||
"observability::maybe_build_local_admin_monitoring_response(",
|
||||
"observability::maybe_build_local_admin_usage_response(",
|
||||
"model::maybe_build_local_admin_global_models_response(",
|
||||
"model::maybe_build_local_admin_model_catalog_response(",
|
||||
"features::maybe_build_local_admin_video_tasks_response(",
|
||||
"features::maybe_build_local_admin_gemini_files_response(",
|
||||
"provider::maybe_build_local_admin_provider_oauth_response(",
|
||||
"provider::maybe_build_local_admin_provider_models_response(",
|
||||
"provider::maybe_build_local_admin_providers_response(",
|
||||
"provider::maybe_build_local_admin_provider_ops_response(",
|
||||
"provider::maybe_build_local_admin_provider_query_response(",
|
||||
"provider::maybe_build_local_admin_provider_strategy_response(",
|
||||
"billing::maybe_build_local_admin_billing_response(",
|
||||
"billing::maybe_build_local_admin_payments_response(",
|
||||
"billing::maybe_build_local_admin_wallets_response(",
|
||||
] {
|
||||
assert!(
|
||||
!admin_routes.contains(forbidden),
|
||||
"handlers/admin/routes.rs should not dispatch provider or billing internals directly for {forbidden}"
|
||||
);
|
||||
}
|
||||
|
||||
let admin_request =
|
||||
read_workspace_module_tree("apps/aether-gateway/src/handlers/admin/request/mod.rs");
|
||||
for pattern in [
|
||||
"pub(crate) struct AdminAppState<'a>",
|
||||
"pub(crate) fn new(app: &'a AppState) -> Self",
|
||||
"pub(crate) fn app(&self) -> &AppState",
|
||||
"pub(crate) fn has_provider_catalog_data_reader(&self) -> bool",
|
||||
"pub(crate) fn has_provider_catalog_data_writer(&self) -> bool",
|
||||
"pub(crate) fn has_request_candidate_data_reader(&self) -> bool",
|
||||
"pub(crate) fn has_management_token_reader(&self) -> bool",
|
||||
"pub(crate) fn has_management_token_writer(&self) -> bool",
|
||||
"pub(crate) fn has_global_model_data_reader(&self) -> bool",
|
||||
"pub(crate) fn has_usage_data_reader(&self) -> bool",
|
||||
"pub(crate) fn has_auth_module_writer(&self) -> bool",
|
||||
"pub(crate) async fn get_ldap_module_config(",
|
||||
"pub(crate) async fn upsert_ldap_module_config(",
|
||||
"pub(crate) async fn count_active_local_admin_users_with_valid_password(",
|
||||
"pub(crate) async fn list_oauth_provider_configs(",
|
||||
"pub(crate) async fn get_oauth_provider_config(",
|
||||
"pub(crate) async fn upsert_oauth_provider_config(",
|
||||
"pub(crate) async fn delete_oauth_provider_config(",
|
||||
"pub(crate) async fn get_management_token_with_user(",
|
||||
"pub(crate) async fn delete_management_token(",
|
||||
"pub(crate) async fn remove_admin_security_blacklist(",
|
||||
"pub(crate) async fn admin_security_blacklist_stats(",
|
||||
"pub(crate) async fn list_admin_security_blacklist(",
|
||||
"pub(crate) async fn add_admin_security_whitelist(",
|
||||
"pub(crate) async fn remove_admin_security_whitelist(",
|
||||
"pub(crate) async fn list_admin_security_whitelist(&self) -> Result<Vec<String>, GatewayError>",
|
||||
"pub(crate) fn mark_provider_key_rpm_reset(&self, key_id: &str, now_unix_secs: u64)",
|
||||
"pub(crate) async fn list_proxy_nodes(",
|
||||
"pub(crate) async fn find_proxy_node(",
|
||||
"pub(crate) async fn read_provider_catalog_endpoints_by_ids(",
|
||||
"pub(crate) async fn count_distinct_video_task_users(",
|
||||
"pub(crate) struct AdminRequestContext<'a>",
|
||||
"pub(crate) fn new(context: &'a GatewayPublicRequestContext) -> Self",
|
||||
"pub(crate) fn decision(&self) -> Option<&GatewayControlDecision>",
|
||||
"pub(crate) fn method(&self) -> &Method",
|
||||
"pub(crate) fn path(&self) -> &str",
|
||||
"pub(crate) fn query_string(&self) -> Option<&str>",
|
||||
"pub(crate) fn public(&self) -> &GatewayPublicRequestContext",
|
||||
"impl<'a> Deref for AdminRequestContext<'a>",
|
||||
"pub(crate) type AdminRouteResponse",
|
||||
"pub(crate) type AdminRouteResult",
|
||||
"pub(crate) struct AdminRouteRequest<'a>",
|
||||
"pub(crate) fn new(",
|
||||
"state: AdminAppState<'a>",
|
||||
"request_context: AdminRequestContext<'a>",
|
||||
"request_body: Option<&'a Bytes>",
|
||||
"pub(crate) fn state(self) -> AdminAppState<'a>",
|
||||
"pub(crate) fn request_context(self) -> AdminRequestContext<'a>",
|
||||
"pub(crate) fn request_body(self) -> Option<&'a Bytes>",
|
||||
] {
|
||||
assert!(
|
||||
admin_request.contains(pattern),
|
||||
"handlers/admin/request/mod.rs should own unified admin request injection field {pattern}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn admin_second_layer_route_seams_use_wrapped_request_types() {
|
||||
for file in [
|
||||
"apps/aether-gateway/src/handlers/admin/auth/security.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/auth/api_keys/mod.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/auth/ldap/mod.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/auth/ldap/routes.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/auth/oauth_routes.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/billing/mod.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/billing/collectors/mod.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/billing/payments/mod.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/billing/payments/routes.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/billing/presets/mod.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/billing/wallets/mod.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/billing/wallets/routes.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/endpoint/health.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/endpoint/rpm.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/features/video_tasks/mod.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/features/video_tasks/routes.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/features/gemini_files/mod.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/model/catalog_routes.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/model/global_models/routes/core/mod.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/observability/stats/mod.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/observability/stats/analytics_routes.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/observability/stats/cost_routes.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/observability/stats/leaderboard_routes.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/observability/stats/provider_quota_routes.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/observability/monitoring/mod.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/observability/usage/mod.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/provider/endpoint_keys.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/provider/endpoints_admin/mod.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/provider/models/mod.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/provider/ops/mod.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/provider/pool_admin/mod.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/provider/query/mod.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/provider/query/routes.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/provider/strategy/mod.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/provider/strategy/routes.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/provider/oauth/dispatch/mod.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/provider/oauth/dispatch/refresh.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/provider/oauth/dispatch/device/mod.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/provider/oauth/dispatch/complete/mod.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/system/core/mod.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/system/adaptive/mod.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/system/adaptive/routes.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/system/management_tokens.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/system/modules.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/system/proxy_nodes.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/users/routes.rs",
|
||||
] {
|
||||
let contents = read_workspace_file(file);
|
||||
assert!(
|
||||
contents.contains("state: &AdminAppState<'_>,"),
|
||||
"{file} should accept AdminAppState at the second-layer admin seam",
|
||||
);
|
||||
assert!(
|
||||
contents.contains("request_context: &AdminRequestContext<'_>,"),
|
||||
"{file} should accept AdminRequestContext at the second-layer admin seam",
|
||||
);
|
||||
assert!(
|
||||
!contents.contains("let state = state.app();"),
|
||||
"{file} should not expose raw AppState as a second-layer local variable",
|
||||
);
|
||||
assert!(
|
||||
!contents.contains("let app_state = state.app();"),
|
||||
"{file} should not expose raw AppState aliasing at the second-layer admin seam",
|
||||
);
|
||||
}
|
||||
|
||||
let admin_request =
|
||||
read_workspace_module_tree("apps/aether-gateway/src/handlers/admin/request/mod.rs");
|
||||
assert!(
|
||||
!admin_request.contains("impl<'a> Deref for AdminAppState<'a>"),
|
||||
"handlers/admin/request/mod.rs should not expose AdminAppState via implicit Deref<AppState>",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn admin_route_adjacent_owners_use_wrapped_state_types() {
|
||||
for file in [
|
||||
"apps/aether-gateway/src/handlers/admin/auth/ldap/builders.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/auth/api_keys/shared.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/auth/api_keys/mutation_routes.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/auth/api_keys/read_routes.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/auth/oauth_config.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/billing/collectors/reads.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/billing/collectors/writes.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/billing/payments/callbacks.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/billing/payments/orders.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/billing/presets/apply.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/billing/rules.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/billing/wallets/reads/detail.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/billing/wallets/reads/ledger.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/billing/wallets/reads/list.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/billing/wallets/reads/refund_requests.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/billing/wallets/reads/refunds.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/billing/wallets/reads/transactions.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/billing/wallets/mutations/adjust.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/billing/wallets/mutations/complete_refund.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/billing/wallets/mutations/fail_refund.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/billing/wallets/mutations/process_refund.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/billing/wallets/mutations/recharge.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/billing/wallets/shared/payloads.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/model/global/helpers.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/model/global/payloads.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/model/global/providers.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/model/write.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/users/lifecycle/support.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/provider/query/models.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/provider/strategy/builders.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/features/video_tasks/builders.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/observability/stats/leaderboard.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/provider/endpoints_admin/reads.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/provider/models/payloads.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/system/shared/configs.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/system/shared/settings.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/system/shared/modules.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/system/shared/export/providers.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/users/sessions.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/users/api_keys/responses/create.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/users/api_keys/responses/delete.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/users/api_keys/responses/list.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/users/api_keys/responses/reveal.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/users/api_keys/responses/toggle_lock.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/users/api_keys/responses/update.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/features/gemini_files/read_routes.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/features/gemini_files/upload/mod.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/features/gemini_files/upload/request.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/features/gemini_files/upload/support.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/model/global_models/routes/core/reads.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/model/global_models/routes/core/writes.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/provider/oauth/dispatch/start.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/provider/oauth/dispatch/import.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/provider/oauth/dispatch/tasks.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/provider/oauth/dispatch/refresh/request.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/provider/oauth/dispatch/device/authorize.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/provider/oauth/dispatch/device/poll.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/provider/oauth/dispatch/complete/key.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/provider/oauth/dispatch/complete/provider.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/provider/oauth/dispatch/batch/orchestration.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/provider/oauth/dispatch/batch/task.rs",
|
||||
] {
|
||||
let contents = read_workspace_file(file);
|
||||
assert!(
|
||||
contents.contains("state: &AdminAppState<'_>,"),
|
||||
"{file} should accept AdminAppState at the route-adjacent admin owner layer",
|
||||
);
|
||||
assert!(
|
||||
!contents.contains("state: &AppState,"),
|
||||
"{file} should not keep raw AppState in route-adjacent owner signatures",
|
||||
);
|
||||
}
|
||||
|
||||
for file in [
|
||||
"apps/aether-gateway/src/handlers/admin/provider/endpoints_admin/create.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/provider/endpoints_admin/update.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/provider/endpoints_admin/delete.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/provider/endpoints_admin/list.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/provider/endpoints_admin/detail.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/provider/endpoints_admin/defaults.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/provider/models/list.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/provider/models/detail.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/provider/models/create.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/provider/models/update.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/provider/models/delete.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/provider/models/batch.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/provider/models/available_source.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/provider/models/assign_global.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/provider/models/import.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/users/lifecycle/reads.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/users/lifecycle/create.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/users/lifecycle/update.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/users/lifecycle/delete.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/users/api_keys/responses/create.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/users/api_keys/responses/delete.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/users/api_keys/responses/list.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/users/api_keys/responses/reveal.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/users/api_keys/responses/toggle_lock.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/users/api_keys/responses/update.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/features/gemini_files/read_routes.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/features/gemini_files/upload/mod.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/features/gemini_files/upload/request.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/features/gemini_files/upload/support.rs",
|
||||
] {
|
||||
let contents = read_workspace_file(file);
|
||||
assert!(
|
||||
contents.contains("state: &AdminAppState<'_>,"),
|
||||
"{file} should accept AdminAppState at the route-owner layer",
|
||||
);
|
||||
assert!(
|
||||
contents.contains("request_context: &AdminRequestContext<'_>,")
|
||||
|| contents.contains("_state: &AdminAppState<'_>,"),
|
||||
"{file} should accept wrapped admin request/state types at the route-owner layer",
|
||||
);
|
||||
assert!(
|
||||
!contents.contains("state: &AppState,"),
|
||||
"{file} should not keep raw AppState in route-owner signatures",
|
||||
);
|
||||
assert!(
|
||||
!contents.contains("request_context: &GatewayPublicRequestContext,"),
|
||||
"{file} should not keep raw GatewayPublicRequestContext in route-owner signatures",
|
||||
);
|
||||
}
|
||||
|
||||
for file in [
|
||||
"apps/aether-gateway/src/handlers/admin/endpoint/health_builders/status.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/endpoint/health_builders/keys.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/provider/write/reveal.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/provider/write/keys/payload.rs",
|
||||
] {
|
||||
let contents = read_workspace_file(file);
|
||||
assert!(
|
||||
contents.contains("state: &AdminAppState<'_>,"),
|
||||
"{file} should accept AdminAppState at the wrapped helper-owner layer",
|
||||
);
|
||||
assert!(
|
||||
!contents.contains("state: &AppState,"),
|
||||
"{file} should not keep raw AppState in helper-owner signatures",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,23 +14,27 @@ fn admin_system_and_endpoint_roots_stay_thin() {
|
||||
);
|
||||
}
|
||||
for pattern in [
|
||||
"pub(crate) use self::adaptive::maybe_build_local_admin_adaptive_response;",
|
||||
"pub(crate) use self::core::maybe_build_local_admin_core_response;",
|
||||
"pub(crate) use self::management_tokens::maybe_build_local_admin_management_tokens_response;",
|
||||
"pub(crate) use self::modules::maybe_build_local_admin_modules_response;",
|
||||
"pub(crate) use self::proxy_nodes::maybe_build_local_admin_proxy_nodes_response;",
|
||||
"mod routes;",
|
||||
"pub(super) use self::routes::maybe_build_local_admin_system_response;",
|
||||
] {
|
||||
assert!(
|
||||
system_mod.contains(pattern),
|
||||
"handlers/admin/system/mod.rs should stay as a thin system subdomain router for {pattern}"
|
||||
);
|
||||
}
|
||||
assert!(
|
||||
system_mod.contains(
|
||||
"pub(crate) use crate::handlers::admin::provider::pool_admin::maybe_build_local_admin_pool_response;"
|
||||
),
|
||||
"handlers/admin/system/mod.rs should delegate pool admin seam directly to provider::pool_admin"
|
||||
);
|
||||
for forbidden in [
|
||||
"pub(crate) use self::adaptive::maybe_build_local_admin_adaptive_response;",
|
||||
"pub(crate) use self::core::maybe_build_local_admin_core_response;",
|
||||
"pub(crate) use self::management_tokens::maybe_build_local_admin_management_tokens_response;",
|
||||
"pub(crate) use self::modules::maybe_build_local_admin_modules_response;",
|
||||
"pub(crate) use self::proxy_nodes::maybe_build_local_admin_proxy_nodes_response;",
|
||||
"pub(crate) use crate::handlers::admin::provider::pool_admin::maybe_build_local_admin_pool_response;",
|
||||
] {
|
||||
assert!(
|
||||
!system_mod.contains(forbidden),
|
||||
"handlers/admin/system/mod.rs should not remain a public owner export hub for {forbidden}"
|
||||
);
|
||||
}
|
||||
|
||||
assert!(
|
||||
!workspace_file_exists("apps/aether-gateway/src/handlers/admin/system/pool/mod.rs"),
|
||||
@@ -39,6 +43,15 @@ fn admin_system_and_endpoint_roots_stay_thin() {
|
||||
|
||||
let endpoint_mod =
|
||||
read_workspace_file("apps/aether-gateway/src/handlers/admin/endpoint/mod.rs");
|
||||
for pattern in [
|
||||
"mod routes;",
|
||||
"pub(super) use self::routes::maybe_build_local_admin_endpoints_response;",
|
||||
] {
|
||||
assert!(
|
||||
endpoint_mod.contains(pattern),
|
||||
"handlers/admin/endpoint/mod.rs should stay as a thin endpoint router for {pattern}"
|
||||
);
|
||||
}
|
||||
for pattern in [
|
||||
"use self::extractors::{",
|
||||
"use self::health_builders::{",
|
||||
@@ -53,15 +66,15 @@ fn admin_system_and_endpoint_roots_stay_thin() {
|
||||
endpoint_mod.contains(
|
||||
"pub(crate) use self::health_builders::build_admin_endpoint_health_status_payload;"
|
||||
),
|
||||
"handlers/admin/endpoint/mod.rs should keep only the public health status payload seam"
|
||||
"handlers/admin/endpoint/mod.rs should keep only the crate-facing health status payload seam"
|
||||
);
|
||||
|
||||
let system_core_mod =
|
||||
read_workspace_file("apps/aether-gateway/src/handlers/admin/system/core/mod.rs");
|
||||
for pattern in [
|
||||
"maybe_build_local_admin_management_tokens_response",
|
||||
"super::management_tokens::maybe_build_local_admin_management_tokens_response",
|
||||
"maybe_build_local_admin_oauth_response",
|
||||
"maybe_build_local_admin_modules_response",
|
||||
"super::modules::maybe_build_local_admin_modules_response",
|
||||
"maybe_build_local_admin_model_catalog_response",
|
||||
] {
|
||||
assert!(
|
||||
@@ -69,6 +82,20 @@ fn admin_system_and_endpoint_roots_stay_thin() {
|
||||
"handlers/admin/system/core/mod.rs should call the real owner {pattern}"
|
||||
);
|
||||
}
|
||||
|
||||
let system_routes =
|
||||
read_workspace_file("apps/aether-gateway/src/handlers/admin/system/routes.rs");
|
||||
for pattern in [
|
||||
"core::maybe_build_local_admin_core_response(",
|
||||
"adaptive::maybe_build_local_admin_adaptive_response(",
|
||||
"pool_admin::maybe_build_local_admin_pool_response(",
|
||||
"proxy_nodes::maybe_build_local_admin_proxy_nodes_response(",
|
||||
] {
|
||||
assert!(
|
||||
system_routes.contains(pattern),
|
||||
"handlers/admin/system/routes.rs should dispatch through specific system owner {pattern}"
|
||||
);
|
||||
}
|
||||
for path in [
|
||||
"apps/aether-gateway/src/handlers/admin/system/core/management_tokens_routes.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/system/core/model_routes.rs",
|
||||
@@ -104,23 +131,22 @@ fn admin_system_and_endpoint_roots_stay_thin() {
|
||||
);
|
||||
}
|
||||
|
||||
let endpoint_routes =
|
||||
read_workspace_file("apps/aether-gateway/src/handlers/admin/endpoint/routes.rs");
|
||||
assert!(
|
||||
endpoint_mod.contains(
|
||||
endpoint_routes.contains(
|
||||
"endpoint_keys::maybe_build_local_admin_endpoints_keys_response"
|
||||
),
|
||||
"handlers/admin/endpoint/mod.rs should dispatch provider key management directly to provider::endpoint_keys"
|
||||
"handlers/admin/endpoint/routes.rs should dispatch provider key management directly to provider::endpoint_keys"
|
||||
);
|
||||
|
||||
assert!(
|
||||
endpoint_mod.contains(
|
||||
endpoint_routes.contains(
|
||||
"endpoints_admin::maybe_build_local_admin_endpoints_routes_response"
|
||||
),
|
||||
"handlers/admin/endpoint/mod.rs should dispatch provider endpoint CRUD directly to provider::endpoints_admin"
|
||||
"handlers/admin/endpoint/routes.rs should dispatch provider endpoint CRUD directly to provider::endpoints_admin"
|
||||
);
|
||||
for path in [
|
||||
"apps/aether-gateway/src/handlers/admin/endpoint/keys.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/endpoint/routes.rs",
|
||||
] {
|
||||
for path in ["apps/aether-gateway/src/handlers/admin/endpoint/keys.rs"] {
|
||||
assert!(
|
||||
!workspace_file_exists(path),
|
||||
"{path} should be deleted once endpoint root dispatches directly to provider-owned handlers"
|
||||
@@ -137,7 +163,7 @@ fn admin_model_root_owns_model_catalog_routes() {
|
||||
);
|
||||
assert!(
|
||||
model_mod.contains(
|
||||
"pub(crate) use self::catalog_routes::maybe_build_local_admin_model_catalog_response;"
|
||||
"pub(super) use self::catalog_routes::maybe_build_local_admin_model_catalog_response;"
|
||||
),
|
||||
"handlers/admin/model/mod.rs should expose model catalog route seam"
|
||||
);
|
||||
@@ -352,7 +378,7 @@ fn admin_system_owns_system_route_helpers() {
|
||||
read_workspace_file("apps/aether-gateway/src/handlers/admin/system/shared/mod.rs");
|
||||
for pattern in [
|
||||
"pub(crate) mod configs;",
|
||||
"pub(crate) mod email_templates;",
|
||||
"pub(crate) mod export;",
|
||||
"pub(crate) mod modules;",
|
||||
"pub(crate) mod paths;",
|
||||
"pub(crate) mod settings;",
|
||||
@@ -399,9 +425,6 @@ fn admin_system_owns_system_route_helpers() {
|
||||
let system_shared_configs =
|
||||
read_workspace_file("apps/aether-gateway/src/handlers/admin/system/shared/configs.rs");
|
||||
for pattern in [
|
||||
"pub(crate) async fn build_admin_system_config_export_payload",
|
||||
"pub(crate) fn serialize_admin_system_users_export_wallet",
|
||||
"pub(crate) async fn build_admin_system_users_export_payload",
|
||||
"pub(crate) fn build_admin_system_configs_payload",
|
||||
"pub(crate) async fn build_admin_system_config_detail_payload",
|
||||
"pub(crate) async fn apply_admin_system_config_update",
|
||||
@@ -413,19 +436,98 @@ fn admin_system_owns_system_route_helpers() {
|
||||
);
|
||||
}
|
||||
|
||||
let system_shared_email_templates = read_workspace_file(
|
||||
"apps/aether-gateway/src/handlers/admin/system/shared/email_templates.rs",
|
||||
);
|
||||
let request_system =
|
||||
read_workspace_module_tree("apps/aether-gateway/src/handlers/admin/request/system/mod.rs");
|
||||
for pattern in [
|
||||
"pub(crate) async fn build_admin_email_templates_payload",
|
||||
"pub(crate) async fn build_admin_email_template_payload",
|
||||
"pub(crate) async fn apply_admin_email_template_update",
|
||||
"pub(crate) async fn preview_admin_email_template",
|
||||
"pub(crate) async fn reset_admin_email_template",
|
||||
"pub(crate) async fn build_admin_system_config_export_payload",
|
||||
"pub(crate) async fn build_admin_system_users_export_payload",
|
||||
] {
|
||||
assert!(
|
||||
system_shared_email_templates.contains(pattern),
|
||||
"handlers/admin/system/shared/email_templates.rs should own {pattern}"
|
||||
request_system.contains(pattern),
|
||||
"handlers/admin/request/system/mod.rs should own {pattern}"
|
||||
);
|
||||
}
|
||||
for path in [
|
||||
"apps/aether-gateway/src/handlers/admin/system/shared/email_templates.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/system/shared/users_export.rs",
|
||||
] {
|
||||
assert!(
|
||||
!workspace_file_exists(path),
|
||||
"{path} should be deleted once request/system/mod.rs owns system email/export route wrappers"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn admin_system_shared_configs_split_export_owners() {
|
||||
let system_shared_mod =
|
||||
read_workspace_file("apps/aether-gateway/src/handlers/admin/system/shared/mod.rs");
|
||||
for pattern in ["pub(crate) mod configs;", "pub(crate) mod export;"] {
|
||||
assert!(
|
||||
system_shared_mod.contains(pattern),
|
||||
"handlers/admin/system/shared/mod.rs should register explicit system shared owner {pattern}"
|
||||
);
|
||||
}
|
||||
|
||||
let system_shared_configs =
|
||||
read_workspace_file("apps/aether-gateway/src/handlers/admin/system/shared/configs.rs");
|
||||
for forbidden in [
|
||||
"build_admin_system_config_export_payload(",
|
||||
"build_admin_system_users_export_payload(",
|
||||
"serialize_admin_system_users_export_wallet(",
|
||||
] {
|
||||
assert!(
|
||||
!system_shared_configs.contains(forbidden),
|
||||
"handlers/admin/system/shared/configs.rs should stay focused on config CRUD, not export owner {forbidden}"
|
||||
);
|
||||
}
|
||||
|
||||
assert!(
|
||||
!workspace_file_exists("apps/aether-gateway/src/handlers/admin/system/shared/export.rs"),
|
||||
"handlers/admin/system/shared/export.rs should be replaced by export/ directory owners"
|
||||
);
|
||||
|
||||
let system_shared_export =
|
||||
read_workspace_file("apps/aether-gateway/src/handlers/admin/system/shared/export/mod.rs");
|
||||
for pattern in [
|
||||
"pub(crate) use self::providers::build_admin_system_export_providers_payload;",
|
||||
"decrypt_admin_system_export_secret",
|
||||
"ADMIN_SYSTEM_CONFIG_EXPORT_VERSION",
|
||||
"ADMIN_SYSTEM_EXPORT_PAGE_LIMIT",
|
||||
] {
|
||||
assert!(
|
||||
system_shared_export.contains(pattern),
|
||||
"handlers/admin/system/shared/export/mod.rs should own {pattern}"
|
||||
);
|
||||
}
|
||||
let request_system =
|
||||
read_workspace_module_tree("apps/aether-gateway/src/handlers/admin/request/system/mod.rs");
|
||||
for pattern in [
|
||||
"pub(crate) async fn build_admin_system_config_export_payload(",
|
||||
"pub(crate) async fn build_admin_system_users_export_payload(",
|
||||
] {
|
||||
assert!(
|
||||
request_system.contains(pattern),
|
||||
"handlers/admin/request/system/mod.rs should own {pattern}"
|
||||
);
|
||||
}
|
||||
for path in [
|
||||
"apps/aether-gateway/src/handlers/admin/system/shared/export/support.rs",
|
||||
"apps/aether-gateway/src/handlers/admin/system/shared/export/providers.rs",
|
||||
] {
|
||||
assert!(
|
||||
workspace_file_exists(path),
|
||||
"{path} should exist once system export owner is split into specific modules"
|
||||
);
|
||||
}
|
||||
|
||||
assert!(
|
||||
!workspace_file_exists("apps/aether-gateway/src/handlers/admin/system/shared/users_export.rs"),
|
||||
"handlers/admin/system/shared/users_export.rs should be deleted once request/system/mod.rs owns users export wrapper"
|
||||
);
|
||||
}
|
||||
|
||||
58
apps/aether-gateway/src/tests/architecture/admin_users.rs
Normal file
58
apps/aether-gateway/src/tests/architecture/admin_users.rs
Normal file
@@ -0,0 +1,58 @@
|
||||
use super::{read_workspace_file, workspace_file_exists};
|
||||
|
||||
#[test]
|
||||
fn admin_users_lifecycle_mod_stays_thin() {
|
||||
let lifecycle_mod =
|
||||
read_workspace_file("apps/aether-gateway/src/handlers/admin/users/lifecycle/mod.rs");
|
||||
for pattern in [
|
||||
"mod create;",
|
||||
"mod delete;",
|
||||
"mod reads;",
|
||||
"mod support;",
|
||||
"mod update;",
|
||||
] {
|
||||
assert!(
|
||||
lifecycle_mod.contains(pattern),
|
||||
"users/lifecycle/mod.rs should keep explicit owner seam {pattern}"
|
||||
);
|
||||
}
|
||||
assert!(
|
||||
!workspace_file_exists("apps/aether-gateway/src/handlers/admin/users/lifecycle/core.rs"),
|
||||
"users/lifecycle/core.rs should be removed once lifecycle is split into explicit owners"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn admin_users_api_key_responses_mod_stays_wrapped() {
|
||||
let responses_mod = read_workspace_file(
|
||||
"apps/aether-gateway/src/handlers/admin/users/api_keys/responses/mod.rs",
|
||||
);
|
||||
for pattern in [
|
||||
"mod create;",
|
||||
"mod delete;",
|
||||
"mod list;",
|
||||
"mod reveal;",
|
||||
"mod toggle_lock;",
|
||||
"mod update;",
|
||||
"pub(in super::super::super) use create::build_admin_create_user_api_key_response;",
|
||||
"pub(in super::super::super) use update::build_admin_update_user_api_key_response;",
|
||||
] {
|
||||
assert!(
|
||||
responses_mod.contains(pattern),
|
||||
"users/api_keys/responses/mod.rs should keep wrapped response seam {pattern}"
|
||||
);
|
||||
}
|
||||
for forbidden in [
|
||||
"pub mod create;",
|
||||
"pub mod delete;",
|
||||
"pub mod list;",
|
||||
"pub mod reveal;",
|
||||
"pub mod toggle_lock;",
|
||||
"pub mod update;",
|
||||
] {
|
||||
assert!(
|
||||
!responses_mod.contains(forbidden),
|
||||
"users/api_keys/responses/mod.rs should not expose raw public response module seam {forbidden}"
|
||||
);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -115,6 +115,16 @@ pub(super) fn workspace_file_exists(root_relative_path: &str) -> bool {
|
||||
.exists()
|
||||
}
|
||||
|
||||
pub(super) fn collect_workspace_rust_files(root_relative_path: &str) -> Vec<PathBuf> {
|
||||
let root = Path::new(env!("CARGO_MANIFEST_DIR"))
|
||||
.join("../..")
|
||||
.join(root_relative_path);
|
||||
let mut files = Vec::new();
|
||||
collect_rust_files(&root, &mut files);
|
||||
files.sort();
|
||||
files
|
||||
}
|
||||
|
||||
pub(super) fn read_workspace_file(path: &str) -> String {
|
||||
let workspace_root = Path::new(env!("CARGO_MANIFEST_DIR"))
|
||||
.join("../..")
|
||||
@@ -123,10 +133,44 @@ pub(super) fn read_workspace_file(path: &str) -> String {
|
||||
fs::read_to_string(workspace_root.join(path)).expect("source file should be readable")
|
||||
}
|
||||
|
||||
pub(super) fn read_workspace_module_tree(path: &str) -> String {
|
||||
let workspace_root = Path::new(env!("CARGO_MANIFEST_DIR"))
|
||||
.join("../..")
|
||||
.canonicalize()
|
||||
.expect("workspace root should resolve");
|
||||
let root_path = workspace_root.join(path);
|
||||
let mut contents =
|
||||
vec![fs::read_to_string(&root_path).expect("source file should be readable")];
|
||||
|
||||
let module_dir = if root_path.file_name().and_then(|value| value.to_str()) == Some("mod.rs") {
|
||||
root_path
|
||||
.parent()
|
||||
.expect("mod.rs should have parent module directory")
|
||||
.to_path_buf()
|
||||
} else if root_path.extension().and_then(|value| value.to_str()) == Some("rs") {
|
||||
root_path.with_extension("")
|
||||
} else {
|
||||
root_path.clone()
|
||||
};
|
||||
if module_dir.is_dir() {
|
||||
let mut files = Vec::new();
|
||||
collect_rust_files(&module_dir, &mut files);
|
||||
files.sort();
|
||||
for file in files {
|
||||
contents.push(fs::read_to_string(file).expect("source file should be readable"));
|
||||
}
|
||||
}
|
||||
|
||||
contents.join("\n")
|
||||
}
|
||||
|
||||
mod admin_billing;
|
||||
mod admin_model;
|
||||
mod admin_observability;
|
||||
mod admin_provider;
|
||||
mod admin_shared;
|
||||
mod admin_system;
|
||||
mod admin_users;
|
||||
mod ai_pipeline;
|
||||
mod runtime_and_security;
|
||||
mod sql_and_data;
|
||||
|
||||
@@ -2,6 +2,87 @@ use std::path::{Path, PathBuf};
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn gateway_small_runtime_shims_stay_deleted() {
|
||||
for path in [
|
||||
"apps/aether-gateway/src/hooks/audit.rs",
|
||||
"apps/aether-gateway/src/hooks/shadow.rs",
|
||||
"apps/aether-gateway/src/auth/runtime.rs",
|
||||
"apps/aether-gateway/src/auth/trusted.rs",
|
||||
"apps/aether-gateway/src/usage/runtime.rs",
|
||||
"apps/aether-gateway/src/usage/config.rs",
|
||||
"apps/aether-gateway/src/usage/queue.rs",
|
||||
"apps/aether-gateway/src/usage/event.rs",
|
||||
"apps/aether-gateway/src/executor/diagnostics.rs",
|
||||
"apps/aether-gateway/src/executor/reports.rs",
|
||||
"apps/aether-gateway/src/executor/retries.rs",
|
||||
"apps/aether-gateway/src/query/billing/mod.rs",
|
||||
"apps/aether-gateway/src/query/monitoring/mod.rs",
|
||||
"apps/aether-gateway/src/state/runtime/security/mod.rs",
|
||||
"apps/aether-gateway/src/state/runtime/payments/mod.rs",
|
||||
] {
|
||||
assert!(
|
||||
!workspace_file_exists(path),
|
||||
"{path} should stay removed after M6 shim cleanup"
|
||||
);
|
||||
}
|
||||
|
||||
let hooks_mod = read_workspace_file("apps/aether-gateway/src/hooks/mod.rs");
|
||||
assert!(
|
||||
hooks_mod.contains("pub(crate) use crate::audit::record_shadow_result_non_blocking;"),
|
||||
"hooks/mod.rs should re-export shadow audit directly from crate::audit"
|
||||
);
|
||||
assert!(
|
||||
hooks_mod.contains("pub(crate) use crate::usage::http::{get_request_audit_bundle, get_request_usage_audit};"),
|
||||
"hooks/mod.rs should re-export request audit helpers directly from usage/http"
|
||||
);
|
||||
|
||||
let auth_mod = read_workspace_file("apps/aether-gateway/src/auth/mod.rs");
|
||||
for pattern in [
|
||||
"resolve_execution_runtime_auth_context",
|
||||
"should_buffer_request_for_local_auth",
|
||||
"GatewayControlAuthContext",
|
||||
"request_model_local_rejection",
|
||||
"trusted_auth_local_rejection",
|
||||
"GatewayLocalAuthRejection",
|
||||
] {
|
||||
assert!(
|
||||
auth_mod.contains(pattern),
|
||||
"auth/mod.rs should expose control-owned auth seam {pattern}"
|
||||
);
|
||||
}
|
||||
for forbidden in ["mod runtime;", "mod trusted;"] {
|
||||
assert!(
|
||||
!auth_mod.contains(forbidden),
|
||||
"auth/mod.rs should not keep local shim {forbidden}"
|
||||
);
|
||||
}
|
||||
|
||||
let usage_mod = read_workspace_file("apps/aether-gateway/src/usage/mod.rs");
|
||||
assert!(
|
||||
usage_mod.contains("pub(crate) use aether_usage_runtime::UsageRuntime;"),
|
||||
"usage/mod.rs should expose UsageRuntime directly from aether_usage_runtime"
|
||||
);
|
||||
assert!(
|
||||
!usage_mod.contains("mod runtime;"),
|
||||
"usage/mod.rs should not keep a local runtime shim"
|
||||
);
|
||||
for forbidden in ["mod config;", "mod queue;", "mod event;"] {
|
||||
assert!(
|
||||
!usage_mod.contains(forbidden),
|
||||
"usage/mod.rs should not keep deleted shim module {forbidden}"
|
||||
);
|
||||
}
|
||||
|
||||
let executor_mod = read_workspace_file("apps/aether-gateway/src/executor/mod.rs");
|
||||
for forbidden in ["mod diagnostics;", "mod reports;", "mod retries;"] {
|
||||
assert!(
|
||||
!executor_mod.contains(forbidden),
|
||||
"executor/mod.rs should not keep deleted shim module {forbidden}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn gateway_request_candidate_trace_type_is_owned_by_aether_data_contracts() {
|
||||
let gateway_candidates = read_workspace_file("apps/aether-gateway/src/data/candidates.rs");
|
||||
@@ -1241,3 +1322,40 @@ fn execution_runtime_video_finalize_paths_depend_on_shared_video_task_core() {
|
||||
"internal gateway finalize path should not own local finalize signature inference"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ai_pipeline_runtime_kiro_wrapper_is_facade_only() {
|
||||
for path in [
|
||||
"apps/aether-gateway/src/ai_pipeline/runtime/mod.rs",
|
||||
"apps/aether-gateway/src/ai_pipeline/runtime/provider_types.rs",
|
||||
"apps/aether-gateway/src/ai_pipeline/runtime/adapters/mod.rs",
|
||||
"apps/aether-gateway/src/ai_pipeline/runtime/adapters/antigravity/mod.rs",
|
||||
"apps/aether-gateway/src/ai_pipeline/runtime/adapters/claude/mod.rs",
|
||||
"apps/aether-gateway/src/ai_pipeline/runtime/adapters/claude_code/mod.rs",
|
||||
"apps/aether-gateway/src/ai_pipeline/runtime/adapters/gemini/mod.rs",
|
||||
"apps/aether-gateway/src/ai_pipeline/runtime/adapters/generic_oauth.rs",
|
||||
"apps/aether-gateway/src/ai_pipeline/runtime/adapters/kiro/mod.rs",
|
||||
"apps/aether-gateway/src/ai_pipeline/runtime/adapters/openai/mod.rs",
|
||||
"apps/aether-gateway/src/ai_pipeline/runtime/adapters/vertex/mod.rs",
|
||||
"apps/aether-gateway/src/ai_pipeline/runtime/adapters/kiro/auth.rs",
|
||||
"apps/aether-gateway/src/ai_pipeline/runtime/adapters/kiro/converter.rs",
|
||||
"apps/aether-gateway/src/ai_pipeline/runtime/adapters/kiro/credentials.rs",
|
||||
"apps/aether-gateway/src/ai_pipeline/runtime/adapters/kiro/headers.rs",
|
||||
"apps/aether-gateway/src/ai_pipeline/runtime/adapters/kiro/policy.rs",
|
||||
"apps/aether-gateway/src/ai_pipeline/runtime/adapters/kiro/refresh.rs",
|
||||
"apps/aether-gateway/src/ai_pipeline/runtime/adapters/kiro/request.rs",
|
||||
"apps/aether-gateway/src/ai_pipeline/runtime/adapters/kiro/url.rs",
|
||||
] {
|
||||
assert!(
|
||||
!workspace_file_exists(path),
|
||||
"{path} should be removed once gateway ai_pipeline runtime adapter ownership is flattened into adaptation/provider_transport facades"
|
||||
);
|
||||
}
|
||||
|
||||
let adaptation_mod =
|
||||
read_workspace_file("apps/aether-gateway/src/ai_pipeline/adaptation/mod.rs");
|
||||
assert!(
|
||||
adaptation_mod.contains("pub(crate) use kiro::KiroToClaudeCliStreamState;"),
|
||||
"adaptation/mod.rs should own KiroToClaudeCliStreamState export after runtime facade removal"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -200,11 +200,14 @@ fn gateway_auth_data_layer_does_not_keep_ldap_row_wrapper() {
|
||||
|
||||
#[test]
|
||||
fn gateway_provider_oauth_storage_types_are_owned_by_aether_data() {
|
||||
let provider_oauth_state =
|
||||
read_workspace_file("apps/aether-gateway/src/handlers/admin/provider/oauth/state.rs");
|
||||
let provider_oauth_storage = read_workspace_file(
|
||||
"apps/aether-gateway/src/handlers/admin/provider/oauth/state/storage.rs",
|
||||
);
|
||||
let request_provider_oauth =
|
||||
read_workspace_file("apps/aether-gateway/src/handlers/admin/request/provider/oauth.rs");
|
||||
assert!(
|
||||
provider_oauth_state.contains("aether_data::repository::provider_oauth"),
|
||||
"provider_oauth/state.rs should depend on aether-data provider oauth storage types"
|
||||
request_provider_oauth.contains("aether_data::repository::provider_oauth"),
|
||||
"request/provider/oauth.rs should depend on aether-data provider oauth storage types"
|
||||
);
|
||||
for pattern in [
|
||||
"pub(crate) struct StoredAdminProviderOAuthDeviceSession",
|
||||
@@ -217,17 +220,38 @@ fn gateway_provider_oauth_storage_types_are_owned_by_aether_data() {
|
||||
"format!(\"provider_oauth_state:{nonce}\")",
|
||||
] {
|
||||
assert!(
|
||||
!provider_oauth_state.contains(pattern),
|
||||
"provider_oauth/state.rs should not own local storage helper {pattern}"
|
||||
!provider_oauth_storage.contains(pattern),
|
||||
"provider_oauth/state/storage.rs should not own local storage helper {pattern}"
|
||||
);
|
||||
}
|
||||
for pattern in [
|
||||
"StoredAdminProviderOAuthDeviceSession",
|
||||
"StoredAdminProviderOAuthState",
|
||||
"provider_oauth_batch_task_storage_key",
|
||||
"build_provider_oauth_batch_task_status_payload",
|
||||
"PROVIDER_OAUTH_BATCH_TASK_TTL_SECS",
|
||||
] {
|
||||
assert!(
|
||||
request_provider_oauth.contains(pattern),
|
||||
"request/provider/oauth.rs should own aether-data provider oauth storage boundary {pattern}"
|
||||
);
|
||||
}
|
||||
|
||||
let dispatch_device = read_workspace_file(
|
||||
"apps/aether-gateway/src/handlers/admin/provider/oauth/dispatch/device.rs",
|
||||
assert!(
|
||||
!workspace_file_exists("apps/aether-gateway/src/handlers/admin/provider/oauth/state.rs"),
|
||||
"provider_oauth/state.rs should not exist after oauth storage helpers move under state/storage.rs"
|
||||
);
|
||||
|
||||
let dispatch_device_authorize = read_workspace_file(
|
||||
"apps/aether-gateway/src/handlers/admin/provider/oauth/dispatch/device/authorize.rs",
|
||||
);
|
||||
assert!(
|
||||
dispatch_device.contains("aether_data::repository::provider_oauth"),
|
||||
"provider_oauth/dispatch/device.rs should use shared provider oauth storage DTOs"
|
||||
dispatch_device_authorize.contains("aether_data::repository::provider_oauth"),
|
||||
"provider_oauth/dispatch/device/authorize.rs should use shared provider oauth storage DTOs"
|
||||
);
|
||||
assert!(
|
||||
!workspace_file_exists("apps/aether-gateway/src/handlers/admin/provider/oauth/dispatch/device.rs"),
|
||||
"provider_oauth/dispatch/device.rs should be removed once device flows move under dispatch/device/"
|
||||
);
|
||||
|
||||
let shared_provider_oauth =
|
||||
|
||||
@@ -2,8 +2,23 @@ use super::*;
|
||||
|
||||
#[test]
|
||||
fn usage_runtime_paths_depend_on_shared_crates_not_app_runtime_shims() {
|
||||
assert!(
|
||||
!workspace_file_exists("apps/aether-gateway/src/usage/runtime.rs"),
|
||||
"usage/runtime.rs should stay removed after collapsing the runtime shim into usage/mod.rs"
|
||||
);
|
||||
for path in [
|
||||
"apps/aether-gateway/src/usage/runtime.rs",
|
||||
"apps/aether-gateway/src/usage/config.rs",
|
||||
"apps/aether-gateway/src/usage/queue.rs",
|
||||
"apps/aether-gateway/src/usage/event.rs",
|
||||
] {
|
||||
assert!(
|
||||
!workspace_file_exists(path),
|
||||
"{path} should stay removed after collapsing usage shim modules into usage/mod.rs"
|
||||
);
|
||||
}
|
||||
|
||||
for path in [
|
||||
"apps/aether-gateway/src/usage/mod.rs",
|
||||
"apps/aether-gateway/src/usage/worker.rs",
|
||||
"apps/aether-gateway/src/async_task/runtime.rs",
|
||||
] {
|
||||
@@ -34,19 +49,47 @@ fn usage_runtime_paths_depend_on_shared_crates_not_app_runtime_shims() {
|
||||
);
|
||||
}
|
||||
|
||||
let usage_runtime = read_workspace_file("apps/aether-gateway/src/usage/runtime.rs");
|
||||
let usage_runtime = read_workspace_file("apps/aether-gateway/src/usage/mod.rs");
|
||||
assert!(
|
||||
!usage_runtime.contains("GatewayDataState"),
|
||||
"usage/runtime.rs should not own GatewayDataState integration impls anymore"
|
||||
"usage/mod.rs should not own GatewayDataState integration impls anymore"
|
||||
);
|
||||
assert!(
|
||||
!usage_runtime.contains("UsageBillingEventEnricher"),
|
||||
"usage/runtime.rs should not own UsageBillingEventEnricher impl anymore"
|
||||
"usage/mod.rs should not own UsageBillingEventEnricher impl anymore"
|
||||
);
|
||||
assert!(
|
||||
!usage_runtime.contains("UsageRuntimeAccess"),
|
||||
"usage/runtime.rs should not own UsageRuntimeAccess impl anymore"
|
||||
"usage/mod.rs should not own UsageRuntimeAccess impl anymore"
|
||||
);
|
||||
assert!(
|
||||
usage_runtime.contains("pub(crate) use aether_usage_runtime::UsageRuntime;"),
|
||||
"usage/mod.rs should expose UsageRuntime directly from aether_usage_runtime"
|
||||
);
|
||||
for pattern in [
|
||||
"UsageRuntimeConfig",
|
||||
"UsageQueue",
|
||||
"UsageEvent",
|
||||
"UsageEventData",
|
||||
"UsageEventType",
|
||||
"USAGE_EVENT_VERSION",
|
||||
"now_ms",
|
||||
] {
|
||||
assert!(
|
||||
usage_runtime.contains(pattern),
|
||||
"usage/mod.rs should expose usage runtime seam {pattern} directly"
|
||||
);
|
||||
}
|
||||
assert!(
|
||||
!usage_runtime.contains("mod runtime;"),
|
||||
"usage/mod.rs should not keep a local runtime shim module"
|
||||
);
|
||||
for forbidden in ["mod config;", "mod queue;", "mod event;"] {
|
||||
assert!(
|
||||
!usage_runtime.contains(forbidden),
|
||||
"usage/mod.rs should not keep deleted shim module {forbidden}"
|
||||
);
|
||||
}
|
||||
|
||||
let usage_worker = read_workspace_file("apps/aether-gateway/src/usage/worker.rs");
|
||||
let runtime_usage_worker = usage_worker
|
||||
|
||||
@@ -22,6 +22,9 @@ use super::super::{
|
||||
build_router_with_state, sample_endpoint, sample_key, sample_management_token,
|
||||
sample_oauth_provider_config, sample_provider, start_server, AppState,
|
||||
};
|
||||
use crate::admin_api::{
|
||||
maybe_build_local_admin_provider_oauth_response, AdminAppState, AdminRequestContext,
|
||||
};
|
||||
use crate::audit::AdminAuditEvent;
|
||||
use crate::constants::{
|
||||
GATEWAY_HEADER, TRUSTED_ADMIN_MANAGEMENT_TOKEN_ID_HEADER, TRUSTED_ADMIN_SESSION_ID_HEADER,
|
||||
@@ -29,7 +32,6 @@ use crate::constants::{
|
||||
};
|
||||
use crate::control::resolve_public_request_context;
|
||||
use crate::data::GatewayDataState;
|
||||
use crate::handlers::admin::provider::maybe_build_local_admin_provider_oauth_response;
|
||||
|
||||
fn trusted_admin_headers() -> HeaderMap {
|
||||
let mut headers = HeaderMap::new();
|
||||
@@ -70,10 +72,14 @@ async fn local_admin_provider_oauth_response(
|
||||
.await
|
||||
.expect("request context should resolve");
|
||||
let body_bytes = body.map(|value| Bytes::from(value.to_string()));
|
||||
maybe_build_local_admin_provider_oauth_response(state, &request_context, body_bytes.as_ref())
|
||||
.await
|
||||
.expect("local provider oauth response should build")
|
||||
.expect("provider oauth route should resolve locally")
|
||||
maybe_build_local_admin_provider_oauth_response(
|
||||
&AdminAppState::new(state),
|
||||
&AdminRequestContext::new(&request_context),
|
||||
body_bytes.as_ref(),
|
||||
)
|
||||
.await
|
||||
.expect("local provider oauth response should build")
|
||||
.expect("provider oauth route should resolve locally")
|
||||
}
|
||||
|
||||
fn sample_kiro_device_access_token(email: &str) -> String {
|
||||
@@ -2029,9 +2035,13 @@ async fn gateway_refreshes_admin_provider_oauth_key_locally_with_trusted_admin_p
|
||||
.as_bool()
|
||||
.expect("account_state_recheck_attempted should be bool");
|
||||
if account_state_recheck_attempted {
|
||||
assert_eq!(
|
||||
payload["account_state_recheck_error"],
|
||||
"wham/usage API 返回状态码 401"
|
||||
let account_state_recheck_error = payload["account_state_recheck_error"]
|
||||
.as_str()
|
||||
.expect("account_state_recheck_error should be string when attempted");
|
||||
assert!(
|
||||
account_state_recheck_error == "wham/usage API 返回状态码 401"
|
||||
|| account_state_recheck_error.starts_with("wham/usage 请求执行失败:"),
|
||||
"unexpected account_state_recheck_error: {account_state_recheck_error}"
|
||||
);
|
||||
} else {
|
||||
assert_eq!(
|
||||
@@ -2055,7 +2065,9 @@ async fn gateway_refreshes_admin_provider_oauth_key_locally_with_trusted_admin_p
|
||||
)
|
||||
.expect("refreshed api key should decrypt");
|
||||
assert_eq!(decrypted_api_key, "refreshed-codex-access-token");
|
||||
if account_state_recheck_attempted {
|
||||
if account_state_recheck_attempted
|
||||
&& payload["account_state_recheck_error"] == "wham/usage API 返回状态码 401"
|
||||
{
|
||||
assert!(stored_key.oauth_invalid_at_unix_secs.is_some());
|
||||
assert_eq!(
|
||||
stored_key.oauth_invalid_reason.as_deref(),
|
||||
|
||||
@@ -12,6 +12,7 @@ use serde_json::json;
|
||||
use super::super::{
|
||||
build_router_with_state, sample_endpoint, sample_key, sample_provider, start_server, AppState,
|
||||
};
|
||||
use crate::admin_api::{maybe_build_local_admin_pool_response, AdminAppState, AdminRequestContext};
|
||||
use crate::audit::AdminAuditEvent;
|
||||
use crate::constants::{
|
||||
GATEWAY_HEADER, TRUSTED_ADMIN_MANAGEMENT_TOKEN_ID_HEADER, TRUSTED_ADMIN_SESSION_ID_HEADER,
|
||||
@@ -19,7 +20,6 @@ use crate::constants::{
|
||||
};
|
||||
use crate::control::resolve_public_request_context;
|
||||
use crate::data::GatewayDataState;
|
||||
use crate::handlers::admin::system::maybe_build_local_admin_pool_response;
|
||||
|
||||
fn trusted_admin_headers() -> HeaderMap {
|
||||
let mut headers = HeaderMap::new();
|
||||
@@ -60,10 +60,14 @@ async fn local_admin_pool_response(
|
||||
.await
|
||||
.expect("request context should resolve");
|
||||
let body_bytes = body.map(|value| Bytes::from(value.to_string()));
|
||||
maybe_build_local_admin_pool_response(state, &request_context, body_bytes.as_ref())
|
||||
.await
|
||||
.expect("local pool response should build")
|
||||
.expect("pool route should resolve locally")
|
||||
maybe_build_local_admin_pool_response(
|
||||
&AdminAppState::new(state),
|
||||
&AdminRequestContext::new(&request_context),
|
||||
body_bytes.as_ref(),
|
||||
)
|
||||
.await
|
||||
.expect("local pool response should build")
|
||||
.expect("pool route should resolve locally")
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
||||
@@ -947,8 +947,8 @@ async fn gateway_verifies_admin_provider_ops_locally_for_anyrouter_proxy_mode()
|
||||
.and_then(serde_json::Value::as_str)
|
||||
.unwrap_or_default();
|
||||
assert!(
|
||||
message.starts_with("连接失败:"),
|
||||
"message should include connect error, got: {message}"
|
||||
message.starts_with("连接失败:") || message == "连接超时",
|
||||
"message should report local network verification failure, got: {message}"
|
||||
);
|
||||
assert_eq!(*upstream_hits.lock().expect("mutex should lock"), 0);
|
||||
|
||||
|
||||
@@ -27,6 +27,9 @@ use super::super::{
|
||||
sample_provider_model_stats, sample_provider_quota, sample_public_global_model_with_mappings,
|
||||
sample_request_candidate, start_server, AppState,
|
||||
};
|
||||
use crate::admin_api::{
|
||||
maybe_build_local_admin_providers_response, AdminAppState, AdminRequestContext,
|
||||
};
|
||||
use crate::audit::AdminAuditEvent;
|
||||
use crate::constants::{
|
||||
GATEWAY_HEADER, TRUSTED_ADMIN_MANAGEMENT_TOKEN_ID_HEADER, TRUSTED_ADMIN_SESSION_ID_HEADER,
|
||||
@@ -34,7 +37,6 @@ use crate::constants::{
|
||||
};
|
||||
use crate::control::resolve_public_request_context;
|
||||
use crate::data::GatewayDataState;
|
||||
use crate::handlers::admin::provider::maybe_build_local_admin_providers_response;
|
||||
|
||||
const ADMIN_PROVIDERS_DATA_UNAVAILABLE_DETAIL: &str = "Admin provider catalog data unavailable";
|
||||
|
||||
@@ -77,10 +79,14 @@ async fn local_admin_providers_response(
|
||||
.await
|
||||
.expect("request context should resolve");
|
||||
let body_bytes = body.map(|value| Bytes::from(value.to_string()));
|
||||
maybe_build_local_admin_providers_response(state, &request_context, body_bytes.as_ref())
|
||||
.await
|
||||
.expect("local providers response should build")
|
||||
.expect("providers route should resolve locally")
|
||||
maybe_build_local_admin_providers_response(
|
||||
&AdminAppState::new(state),
|
||||
&AdminRequestContext::new(&request_context),
|
||||
body_bytes.as_ref(),
|
||||
)
|
||||
.await
|
||||
.expect("local providers response should build")
|
||||
.expect("providers route should resolve locally")
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
||||
@@ -7,13 +7,15 @@ use http::{HeaderMap, HeaderValue, StatusCode};
|
||||
use serde_json::json;
|
||||
|
||||
use super::super::{build_router_with_state, start_server, AppState};
|
||||
use crate::admin_api::{
|
||||
maybe_build_local_admin_security_response, AdminAppState, AdminRequestContext,
|
||||
};
|
||||
use crate::audit::AdminAuditEvent;
|
||||
use crate::constants::{
|
||||
GATEWAY_HEADER, TRUSTED_ADMIN_MANAGEMENT_TOKEN_ID_HEADER, TRUSTED_ADMIN_SESSION_ID_HEADER,
|
||||
TRUSTED_ADMIN_USER_ID_HEADER, TRUSTED_ADMIN_USER_ROLE_HEADER,
|
||||
};
|
||||
use crate::control::resolve_public_request_context;
|
||||
use crate::handlers::admin::auth::maybe_build_local_admin_security_response;
|
||||
|
||||
async fn send_admin_security_request(
|
||||
gateway: Router,
|
||||
@@ -98,10 +100,14 @@ async fn local_admin_security_response(
|
||||
.await
|
||||
.expect("request context should resolve");
|
||||
let body_bytes = body.map(|value| Bytes::from(value.to_string()));
|
||||
maybe_build_local_admin_security_response(state, &request_context, body_bytes.as_ref())
|
||||
.await
|
||||
.expect("local security response should build")
|
||||
.expect("security route should resolve locally")
|
||||
maybe_build_local_admin_security_response(
|
||||
&AdminAppState::new(state),
|
||||
&AdminRequestContext::new(&request_context),
|
||||
body_bytes.as_ref(),
|
||||
)
|
||||
.await
|
||||
.expect("local security response should build")
|
||||
.expect("security route should resolve locally")
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
||||
@@ -14,6 +14,9 @@ use super::super::{
|
||||
build_router_with_state, issue_test_admin_access_token, sample_endpoint, sample_key,
|
||||
sample_provider, start_server, AppState,
|
||||
};
|
||||
use crate::admin_api::{
|
||||
maybe_build_local_admin_usage_response, AdminAppState, AdminRequestContext,
|
||||
};
|
||||
use crate::audit::AdminAuditEvent;
|
||||
use crate::constants::{
|
||||
GATEWAY_HEADER, TRUSTED_ADMIN_MANAGEMENT_TOKEN_ID_HEADER, TRUSTED_ADMIN_SESSION_ID_HEADER,
|
||||
@@ -21,7 +24,6 @@ use crate::constants::{
|
||||
};
|
||||
use crate::control::resolve_public_request_context;
|
||||
use crate::data::GatewayDataState;
|
||||
use crate::handlers::admin::observability::maybe_build_local_admin_usage_response;
|
||||
|
||||
const ADMIN_USAGE_DATA_UNAVAILABLE_DETAIL: &str = "Admin usage data unavailable";
|
||||
const DAY_1_UNIX_SECS: i64 = 1_711_000_000;
|
||||
@@ -74,10 +76,14 @@ async fn local_admin_usage_response(
|
||||
.await
|
||||
.expect("request context should resolve");
|
||||
let body_bytes = body.map(|value| Bytes::from(value.to_string()));
|
||||
maybe_build_local_admin_usage_response(state, &request_context, body_bytes.as_ref())
|
||||
.await
|
||||
.expect("local usage response should build")
|
||||
.expect("usage route should resolve locally")
|
||||
maybe_build_local_admin_usage_response(
|
||||
&AdminAppState::new(state),
|
||||
&AdminRequestContext::new(&request_context),
|
||||
body_bytes.as_ref(),
|
||||
)
|
||||
.await
|
||||
.expect("local usage response should build")
|
||||
.expect("usage route should resolve locally")
|
||||
}
|
||||
|
||||
async fn start_usage_upstream(
|
||||
|
||||
@@ -18,6 +18,9 @@ use super::super::{
|
||||
build_router_with_state, build_state_with_execution_runtime_override, sample_endpoint,
|
||||
sample_key, sample_provider, start_server, AppState,
|
||||
};
|
||||
use crate::admin_api::{
|
||||
maybe_build_local_admin_video_tasks_response, AdminAppState, AdminRequestContext,
|
||||
};
|
||||
use crate::audit::AdminAuditEvent;
|
||||
use crate::constants::{
|
||||
GATEWAY_HEADER, TRUSTED_ADMIN_MANAGEMENT_TOKEN_ID_HEADER, TRUSTED_ADMIN_SESSION_ID_HEADER,
|
||||
@@ -25,7 +28,6 @@ use crate::constants::{
|
||||
};
|
||||
use crate::control::resolve_public_request_context;
|
||||
use crate::data::GatewayDataState;
|
||||
use crate::handlers::admin::features::maybe_build_local_admin_video_tasks_response;
|
||||
|
||||
fn trusted_admin_headers() -> HeaderMap {
|
||||
let mut headers = HeaderMap::new();
|
||||
@@ -65,10 +67,13 @@ async fn local_admin_video_tasks_response(
|
||||
)
|
||||
.await
|
||||
.expect("request context should resolve");
|
||||
maybe_build_local_admin_video_tasks_response(state, &request_context)
|
||||
.await
|
||||
.expect("local video tasks response should build")
|
||||
.expect("video tasks route should resolve locally")
|
||||
maybe_build_local_admin_video_tasks_response(
|
||||
&AdminAppState::new(state),
|
||||
&AdminRequestContext::new(&request_context),
|
||||
)
|
||||
.await
|
||||
.expect("local video tasks response should build")
|
||||
.expect("video tasks route should resolve locally")
|
||||
}
|
||||
|
||||
fn sample_admin_video_task(
|
||||
|
||||
@@ -3871,7 +3871,8 @@ async fn gateway_handles_wallet_balance_locally_without_proxying_upstream() {
|
||||
|
||||
#[tokio::test]
|
||||
async fn gateway_handles_wallet_today_cost_locally_without_proxying_upstream() {
|
||||
let now = chrono::DateTime::<chrono::Utc>::from_naive_utc_and_offset(
|
||||
let now = Utc::now();
|
||||
let usage_now = chrono::DateTime::<chrono::Utc>::from_naive_utc_and_offset(
|
||||
Utc::now()
|
||||
.date_naive()
|
||||
.and_hms_opt(12, 0, 0)
|
||||
@@ -3900,7 +3901,7 @@ async fn gateway_handles_wallet_today_cost_locally_without_proxying_upstream() {
|
||||
"gpt-4.1",
|
||||
"OpenAI",
|
||||
"completed",
|
||||
now - chrono::Duration::minutes(30),
|
||||
usage_now - chrono::Duration::minutes(30),
|
||||
),
|
||||
sample_user_usage_audit(
|
||||
"usage-wallet-old-1",
|
||||
@@ -3909,7 +3910,7 @@ async fn gateway_handles_wallet_today_cost_locally_without_proxying_upstream() {
|
||||
"gpt-4.1",
|
||||
"OpenAI",
|
||||
"completed",
|
||||
now - chrono::Duration::days(1),
|
||||
usage_now - chrono::Duration::days(1),
|
||||
),
|
||||
]));
|
||||
let (gateway_url, upstream_hits, gateway_handle, upstream_handle) =
|
||||
|
||||
Reference in New Issue
Block a user