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 route_headers_json(&self) -> String
pub fn route_headers_json(&self) -> String
The ROUTE_HEADERS Worker binding for this domain (R746) — the route
table’s path + headers pairs, in manifest order, with routes that
declare no headers dropped. "[]" when nothing declares any.
Order is load-bearing and must survive serialization: the front door
applies the FIRST matching rule, so /app/* above /* is what gives
the app its isolation headers and leaves the marketing site alone.
That is why this is a Vec of pairs and not a map keyed by path.
Infallible by design — Self::validate_route_headers has already run
at Self::load, so by the time a reconciler calls this the table is
known to be one both front doors can apply.
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.
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