pub struct DomainConfig {
pub schema_version: u32,
pub name: String,
pub domain: String,
pub front_door: FrontDoor,
pub cdn_bucket: String,
pub worker_bundle_path: Option<String>,
pub routes: Vec<DomainRoute>,
}Expand description
A routing manifest for one domain, from .yah/domains/<name>.toml.
The domain manifest is the only place that knows about path routing:
services declare static/backend components by opaque ID, and this
manifest binds those components to URL paths on a public-facing
domain. Generated Worker bundles consume this. See
.yah/docs/working/W118-yah-domain-tiers.md (R347).
Fields§
§schema_version: u32§name: StringStable identifier for this domain (file stem of the manifest).
Example: "yah-dev" for the yah.dev zone.
domain: StringThe fully-qualified domain this manifest routes for. Example:
"yah.dev", "app.yah.dev".
front_door: FrontDoorWhich front door serves this domain (R594-F12). Required — a
default here would silently re-create the defect the field exists to
close. Cross-checked against routes / worker_bundle_path by
DomainConfig::validate_front_door at load time.
cdn_bucket: StringPublic CDN bucket name. Static-mode route components publish into this bucket. Owned by the domain, not by any single service.
worker_bundle_path: Option<String>Optional path (relative to workspace root) where the generated
Worker bundle lands. None while the bundle generator (R347-F4)
is still being wired up.
routes: Vec<DomainRoute>Implementations§
Source§impl DomainConfig
impl DomainConfig
Sourcepub fn load(path: &Path) -> Result<Self>
pub fn load(path: &Path) -> Result<Self>
Parse a single .yah/domains/<name>.toml, rejecting a manifest whose
declared front door contradicts its route table
(Self::validate_front_door).
Sourcepub fn validate_front_door(&self) -> Result<()>
pub fn validate_front_door(&self) -> Result<()>
R594-F12 — the front door must agree with the rest of the manifest.
bucket-directis an R2 custom domain: a Worker route table would never be consulted, so declaring one means the author expected Worker behaviour (clean URLs, SPA fallback, branded errors) from a surface that cannot provide it. Rejected rather than silently ignored. Same forworker_bundle_path— nothing would deploy it.worker/passwaywith an empty route table is a silent 404 machine: the front door exists, has nothing to serve, and every request falls through to the catch-all.
Called from Self::load, so both CloudConfig::load and
CloudConfig::load_from_config_dir enforce it.
Sourcepub fn validate_route_headers(&self) -> Result<()>
pub fn validate_route_headers(&self) -> Result<()>
R749-T5 — everything Self::route_headers_json emits must be
applicable, checked here where the table is PRODUCED.
That method serializes a typed struct, so the table’s JSON shape is
sound by construction. Its contents are not: a route’s headers map is
a free-form name -> value read verbatim out of hand-written TOML, so
"Cross Origin Opener Policy" (spaces instead of hyphens) or a value
carrying a newline ships a structurally-valid table that neither front
door can apply — and they fail differently, neither naming the
manifest line responsible:
- passway —
mesofact::route_headers::RouteHeaderTable::parserefuses the start, so the origin is simply down. - worker —
validateRouteHeaderTableaccepts it (it checks shape, not header validity) andapplyRouteHeadersthen throws inside the exportedfetch, which is a 500 on every request, not the serve-without-the-headers degradation that code intends.
So the strictness lives at the producer: a table that cannot be applied
fails yah cloud apply at manifest load, naming domain, route and
header. This is deliberately not a second parser — the check is
HeaderName/HeaderValue’s own, the very constructors the passway door
runs on the far side, and route matching semantics stay defined once,
at the doors. Only routes that contribute to the table are checked, so
the invariant is exactly “route_headers_json’s output parses”.
Called from Self::load, alongside Self::validate_front_door.
Sourcepub fn serves_service(&self, service: &str) -> bool
pub fn serves_service(&self, service: &str) -> bool
Whether this domain’s route table binds any component of service.
Source§impl DomainConfig
impl DomainConfig
Sourcepub fn route_table(&self, placement: &dyn RoutePlacement) -> Result<RouteTable>
pub fn route_table(&self, placement: &dyn RoutePlacement) -> Result<RouteTable>
Compile this domain’s declared routes into one resolved table.
Manifest order is preserved because it is the matching order — see the
module doc. Fails, naming the route, when placement cannot resolve an
origin: the alternative is an entry silently missing from the table,
which serves that path from whichever shorter entry matches instead of
failing.
Sourcepub fn route_headers_json(&self) -> String
pub fn route_headers_json(&self) -> String
The ROUTE_HEADERS / MESOFACT_ROUTE_HEADERS wire value (R746) — the
header column of Self::route_table, which is the only column those
two bindings carry until R898-F2/F3 widen them.
Needs no RoutePlacement, which is why it is here and not on
RouteTable alone: the reconcilers that set those bindings run before
anything is placed. Both spellings share [headers_json], so the
projection cannot drift from the table it projects.
Sourcepub fn route_for_path(&self, path: &str) -> Option<&DomainRoute>
pub fn route_for_path(&self, path: &str) -> Option<&DomainRoute>
The declared route that governs path — the same walk
RouteTable::match_path makes, over the routes instead of over the
compiled entries.
Placement-free, and here for exactly the reason
Self::route_headers_json is: a consumer that runs BEFORE anything is
placed cannot compile a table to ask. crate::inner_door::plan is that
consumer, and for it the dependency is not merely inconvenient but
circular — CdnPlacement::backend_origin resolves a route’s origin
out of InnerDoorPlan::resolve_addresses’ output, which is derived from
the very plan that would be asking (R898-F1’s handoff states that keying).
One rule, two walks, pinned by
the_declared_walk_and_the_compiled_walk_pick_the_same_route — the same
arrangement [headers_json] already has, and for the same reason.
Trait Implementations§
Source§impl Clone for DomainConfig
impl Clone for DomainConfig
Source§fn clone(&self) -> DomainConfig
fn clone(&self) -> DomainConfig
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for DomainConfig
impl Debug for DomainConfig
Source§impl<'de> Deserialize<'de> for DomainConfig
impl<'de> Deserialize<'de> for DomainConfig
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Auto Trait Implementations§
impl Freeze for DomainConfig
impl RefUnwindSafe for DomainConfig
impl Send for DomainConfig
impl Sync for DomainConfig
impl Unpin for DomainConfig
impl UnsafeUnpin for DomainConfig
impl UnwindSafe for DomainConfig
Blanket Implementations§
impl<T> Allocation for T
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can
then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be
further downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be
downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further
downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.Source§impl<T> DowncastSend for T
impl<T> DowncastSend for T
Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
impl<T> ErasedDestructor for Twhere
T: 'static,
impl<T> Fruit for T
impl<A, B, T> HttpServerConnExec<A, B> for Twhere
B: Body,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more