feat(import): resolve references and schema composition

This commit is contained in:
2026-08-29 08:54:26 +03:00
parent 6c2a3712d8
commit 55209a9bbc
46 changed files with 4848 additions and 437 deletions
+65 -2
View File
@@ -4,6 +4,7 @@ use std::sync::Arc;
use base64::{Engine as _, engine::general_purpose::URL_SAFE_NO_PAD};
use crank_artifacts::ArtifactStore;
use crank_config::ExternalReferenceSettings;
use crank_core::{
AuditActor, AuditEvent, AuditEventId, AuditSink, AuditTarget, AuditTargetKind, AuthProfile,
CapabilityProfile, CommunityCapabilityProfile, CorrelationContext, EditionCapabilities,
@@ -19,7 +20,8 @@ use crank_registry::{
UsageBucket,
};
use crank_runtime::{
OutboundHttpPolicy, ResolvedAuth, RuntimeError, RuntimeExecutor, SecretCrypto,
ExternalReferenceFetcher, OutboundHttpPolicy, ResolvedAuth, RuntimeError, RuntimeExecutor,
SecretCrypto,
};
use crank_schema::{Schema, SchemaKind};
use crank_trace::{DbOperation, ErrorCategory, Stage, StageOutcome, observe_db_query};
@@ -68,6 +70,9 @@ pub struct AdminService {
audit_sink: Arc<dyn AuditSink>,
capability_profile: Arc<dyn CapabilityProfile>,
outbound_http_policy: OutboundHttpPolicy,
external_reference_fetcher: ExternalReferenceFetcher,
external_reference_normalization: crank_import::rest::NormalizationConfig,
external_reference_materialization_timeout: std::time::Duration,
public_base_url: String,
}
@@ -83,6 +88,9 @@ pub struct AdminServiceBuilder {
audit_sink: Option<Arc<dyn AuditSink>>,
capability_profile: Option<Arc<dyn CapabilityProfile>>,
outbound_http_policy: OutboundHttpPolicy,
external_reference_fetcher: ExternalReferenceFetcher,
external_reference_normalization: crank_import::rest::NormalizationConfig,
external_reference_settings: ExternalReferenceSettings,
public_base_url: String,
}
@@ -220,6 +228,22 @@ impl AdminServiceBuilder {
secret_crypto: SecretCrypto,
runtime: RuntimeExecutor,
) -> Self {
let outbound_http_policy = OutboundHttpPolicy::default();
let external_reference_settings = ExternalReferenceSettings {
allowed_url_prefixes: Vec::new(),
max_depth: 8,
max_documents: 32,
max_fetch_bytes: 256 * 1024,
fetch_timeout_ms: 5_000,
max_expanded_nodes: 10_000,
};
let external_reference_fetcher = ExternalReferenceFetcher::try_new(
outbound_http_policy.clone(),
external_reference_settings.allowed_url_prefixes.clone(),
external_reference_settings.max_fetch_bytes,
std::time::Duration::from_millis(external_reference_settings.fetch_timeout_ms),
)
.expect("static external reference defaults are valid");
Self {
registry,
storage_root,
@@ -231,7 +255,10 @@ impl AdminServiceBuilder {
policy_engine: None,
audit_sink: None,
capability_profile: None,
outbound_http_policy: OutboundHttpPolicy::default(),
outbound_http_policy,
external_reference_fetcher,
external_reference_normalization: Default::default(),
external_reference_settings,
public_base_url: "http://localhost:3000".to_owned(),
}
}
@@ -242,10 +269,41 @@ impl AdminServiceBuilder {
}
pub fn with_outbound_http_policy(mut self, policy: OutboundHttpPolicy) -> Self {
self.external_reference_fetcher = ExternalReferenceFetcher::try_new(
policy.clone(),
self.external_reference_settings
.allowed_url_prefixes
.clone(),
self.external_reference_settings.max_fetch_bytes,
std::time::Duration::from_millis(self.external_reference_settings.fetch_timeout_ms),
)
.expect("validated external reference settings remain valid");
self.outbound_http_policy = policy;
self
}
pub fn with_external_reference_import(
mut self,
settings: &ExternalReferenceSettings,
) -> Result<Self, crank_runtime::ExternalReferenceFetchError> {
self.external_reference_fetcher = ExternalReferenceFetcher::try_new(
self.outbound_http_policy.clone(),
settings.allowed_url_prefixes.clone(),
settings.max_fetch_bytes,
std::time::Duration::from_millis(settings.fetch_timeout_ms),
)?;
self.external_reference_normalization.max_reference_depth = settings.max_depth;
self.external_reference_normalization
.max_reference_documents = settings.max_documents;
self.external_reference_normalization
.max_external_document_bytes = settings.max_fetch_bytes;
self.external_reference_normalization.max_expanded_nodes = settings.max_expanded_nodes;
self.external_reference_normalization
.external_references_enabled = !settings.allowed_url_prefixes.is_empty();
self.external_reference_settings = settings.clone();
Ok(self)
}
/// Reuses the process-wide immutable artifact authority for OpenAPI
/// ingress and reconciliation. Tests may omit this and use their private
/// storage root instead.
@@ -299,6 +357,11 @@ impl AdminServiceBuilder {
.capability_profile
.unwrap_or_else(|| Arc::new(CommunityCapabilityProfile)),
outbound_http_policy: self.outbound_http_policy,
external_reference_fetcher: self.external_reference_fetcher,
external_reference_normalization: self.external_reference_normalization,
external_reference_materialization_timeout: std::time::Duration::from_millis(
self.external_reference_settings.fetch_timeout_ms,
),
public_base_url: self.public_base_url,
}
}