DB-TAB
ZAYAZ Domain Strategy (MDX)
Overview
This document defines the domain architecture for the ZAYAZ ecosystem. Domains are treated as infrastructure primitives, not just branding assets. Each domain maps to:
- Environment (prod, dev, sandbox)
- Trust level (public, regulated, internal)
- System layer (core, AI, partner, education)
Owned Domains (Authoritative Inventory)
zayaz.io
zayaz.dev
zayaz.cloud
zayaz.ai
ecoworld.ai
eco-number.com
eco-number.org
e-c-o.com
viroway.com
sustainability-act.org
Domain Role Classification
| Domain | Role | Layer | Trust Level |
|---|---|---|---|
| zayaz.io | Core platform | Production | High (regulated) |
| zayaz.dev | Dev + sandbox | Development | Internal |
| zayaz.cloud | White-label infra | Partner | Medium–High |
| zayaz.ai | AI positioning | AI layer | Medium |
| ecoworld.ai | Education + public ESG | Ecosystem | Public |
| eco-number.com | Public ESG lookup | Trust layer | Public |
| eco-number.org | NGO/regulatory mirror | Trust layer | Public/Institutional |
| e-c-o.com | Brand/media/SEO | Ecosystem | Public |
| viroway.com | Corporate | Corporate | Public |
| sustainability-act.org | Policy/legislation | Governance | Public/Institutional |
Core Principles
1. Environment Isolation
Each environment must be strictly separated at the domain level.
- Production must never share domains with development
- Sandbox must be explicitly identifiable
2. Trust Zoning
| Zone | Description | Examples |
|---|---|---|
| Public | Open access, low trust barrier | eco-number.com |
| Regulated | Client-facing, compliance-critical | app.zayaz.io |
| Internal | Restricted, experimental | *.zayaz.dev |
3. Functional Mapping
Each domain must have a single clear responsibility.
Domain Layers
1. Core Platform (Production)
zayaz.io
app.zayaz.io
api.zayaz.io
Purpose:
- ESG reporting (CSRD/ESRS)
- Client dashboards
- Core APIs
2. Development & Sandbox
zayaz.dev
api.zayaz.dev
sandbox.zayaz.dev
lab.zayaz.dev
agents.zayaz.dev
Purpose:
- Safe experimentation
- Partner testing
- AI agent development (ZAAM/ZARA)
3. Public Trust Layer
eco-number.com
eco-number.org
Purpose:
- Public ESG lookup
- Supplier transparency
- NGO / regulator access
4. Education & Ecosystem
ecoworld.ai
academy.zayaz.io
e-c-o.com
Purpose:
- ESG education
- Academy modules
- Thought leadership
5. Partner & White-Label Layer
zayaz.cloud
partners.zayaz.cloud
Pattern:
<client>.zayaz.cloud
Redirecting host:
- public client-facing redirect host:
<client>.zayaz.cloud/<Primary Code>
- runtime/API target:
- region-specific app endpoint, for example:
https://api.eu-central-1.zayaz.io/...https://api.ap-northeast-3.zayaz.io/...
- region-specific app endpoint, for example:
Purpose:
- zayaz.cloud is the branded client entry layer
- zayaz.io is the application/service layer
- routing use client metadata to decide region/tenant target
- we avoid overloading www.zayaz.io
6. AI Layer
zayaz.ai
ai.zayaz.io
zara.zayaz.ai
7. Corporate Layer
viroway.com
Purpose:
- Corporate identity
- Investor relations
- Legal entity
8. Governance / Policy Layer (Strategic)
sustainability-act.org
Purpose:
- Legislative proposals
- ESG policy frameworks
- NGO / institutional engagement
Environment Architecture
Production
app.zayaz.io
api.zayaz.io
ai.zayaz.io
Development
api.zayaz.dev
sandbox.zayaz.dev
agents.zayaz.dev
Internal
internal.zayaz.io
admin.zayaz.io
AI Governance Domains
ai.zayaz.dev # model testing
ai.zayaz.io # production AI
audit.zayaz.io # audit dashboards
Developer Ecosystem
zayaz.dev/docs
zayaz.dev/playground
zayaz.dev/sandbox
DNS & Routing Strategy (Cloudflare-Centric)
Stack
- Cloudflare DNS (authoritative)
- Cloudflare Workers (edge routing)
- Cloudflare KV / D1 (config + redirect mapping)
- API Gateway (internal service mesh)
Example Routing Table
| Domain | Target |
|---|---|
| api.zayaz.io | API Gateway (prod cluster) |
| api.zayaz.dev | Dev cluster |
| sandbox.zayaz.dev | Sandbox compute cluster |
| app.zayaz.io | Frontend (prod) |
| ecoworld.ai | Public frontend |
Security Model
- HTTPS enforced globally (.dev already HSTS)
- Separate auth providers per environment
- Zero trust between dev and prod
- Strict CORS policies per domain
Anti-Patterns (Avoid)
❌ Mixing environments:
dev.zayaz.io + zayaz.dev
❌ Multi-purpose domains
❌ Inconsistent naming
Roadmap
Phase 1 (Current)
- zayaz.io
- zayaz.dev
- zayaz.cloud
- zayaz.ai
- ecoworld.ai
- eco-number.com
- eco-number.org
- e-c-o.com
- viroway.com
- sustainability-act.org
Phase 2
- Developer portal expansion
- Partner provisioning via zayaz.cloud
- AI productization via zayaz.ai
Phase 3
- Policy platform scaling (splt-act)
- Global ESG identity federation
Infrastructure Specification
Objective
Define a deployable, environment-isolated, Cloudflare-centric infrastructure model for the ZAYAZ ecosystem, including DNS, routing, edge services, API segmentation, security boundaries, and white-label provisioning.
1. Infrastructure Design Principles
1.1 Production and Development Must Be Physically and Logically Separated
Separation must exist at all layers:
- DNS zones and subdomains
- authentication audiences
- API gateways
- databases and storage
- secrets
- telemetry streams
- deployment pipelines
Development systems must never share production credentials, production data stores, or production event pipelines.
1.2 Edge-First Routing
Cloudflare should act as the front-door control plane for:
- DNS
- TLS termination
- WAF
- bot protection
- redirect services
- edge routing
- worker-based request shaping
1.3 Service-Oriented Internal Architecture
All major platform capabilities should sit behind explicit service boundaries.
Examples:
- identity service
- API gateway
- reporting service
- FOGE service
- SSSR service
- AI orchestration service
- MICE execution service
- public trust lookup service
- partner provisioning service
1.4 Domain Responsibility Must Mirror System Responsibility
Each domain or subdomain must correspond to a clear runtime role:
- user interface
- API endpoint
- documentation portal
- sandbox runtime
- public lookup
- partner tenant ingress
2. Target Platform Topology
2.1 Internet-Facing Domain Map
viroway.com → Corporate site
zayaz.io → Main product entry
app.zayaz.io → Main authenticated SaaS UI
api.zayaz.io → Production public API gateway
admin.zayaz.io → Restricted admin UI
partners.zayaz.io → Partner onboarding and control plane
academy.zayaz.io → Academy entry / redirect or app
ai.zayaz.io → Production AI service ingress
audit.zayaz.io → Audit / trust / lineage dashboards
zayaz.dev → Developer portal root
api.zayaz.dev → Development API gateway
sandbox.zayaz.dev → Sandbox runtime for partners and internal QA
agents.zayaz.dev → Agent-mode testing UI / API
lab.zayaz.dev → Experimental engines and prototypes
docs.zayaz.dev → Developer docs
playground.zayaz.dev → API playground / token-safe testing
zayaz.cloud → White-label landing / partner infra anchor
<tenant>.zayaz.cloud → White-label tenant ingress
zayaz.ai → AI product positioning / marketing / future AI surface
zara.zayaz.ai → AI-first interface (future)
ecoworld.ai → Public-facing ESG ecosystem / Academy / thought leadership
eco-number.com → Primary public company lookup portal
eco-number.org → Institutional / NGO / mirrored trust portal
e-c-o.com → Editorial / public education / SEO layer
sustainability-act.org → Policy / legislation proposal hub
3. Zone Strategy
3.1 Recommended DNS Zones
Each of the following should be maintained as a separately governed DNS zone:
zayaz.iozayaz.devzayaz.cloudzayaz.aiecoworld.aieco-number.comeco-number.orge-c-o.comviroway.comsustainability-act.org
3.2 Zone Governance Rules
Each zone should have:
- dedicated ownership metadata
- change logging
- least-privilege DNS access
- registrar lock where available
- DNSSEC enabled where supported
- Cloudflare-proxied records by default unless there is a specific reason not to proxy
3.3 Naming Conventions
Use a stable naming convention across all platform domains:
app= primary end-user applicationapi= API gatewayadmin= restricted operator interfacedocs= documentationsandbox= safe partner / test environmentaudit= auditability surfacespartners= partner control planeai= production AI ingressagents= agent-specific testing/runtimelab= experimental surfaces
4. Cloudflare Control Plane
4.1 Cloudflare Services to Use
Recommended baseline:
- DNS
- Universal or Advanced SSL
- WAF managed rules
- Rate limiting
- Zero Trust access policies
- Workers
- KV for lightweight configuration/redirects
- D1 for small operational control-plane tables if needed
- R2 for static file/object delivery if appropriate
- Tunnel for selected internal admin origins if needed
- Turnstile for abuse-sensitive forms
- Logpush for security and request logging
4.2 Edge Routing Model
Cloudflare Workers should be used for:
- canonical redirects
- hostname-based routing
- lightweight auth pre-checks
- feature flag routing at the edge
- request normalization
- short-link and academy redirects
- public lookup caching and shaping
Workers should not become the primary business logic layer for heavy ESG computation. That logic belongs in core services behind the gateway.
5. Environment Model
5.1 Production Environment
Production serves regulated, client-facing, business-critical workloads.
Primary endpoints:
app.zayaz.io
api.zayaz.io
ai.zayaz.io
audit.zayaz.io
partners.zayaz.io
Production rules:
- production-only identity provider audiences
- production-only secrets store
- production-only databases
- production-only message buses
- production-only telemetry projects
- strong WAF and rate-limiting policies
- human-reviewed deployment approvals for critical services
5.2 Development Environment
Development exists for engineering integration, agent iteration, and QA.
Primary endpoints:
api.zayaz.dev
sandbox.zayaz.dev
agents.zayaz.dev
lab.zayaz.dev
docs.zayaz.dev
playground.zayaz.dev
Development rules:
- no production data by default
- synthetic or masked data only
- ephemeral preview deployments allowed
- broader observability and debugging enabled
- lower trust tier than production
5.3 Sandbox Environment
Sandbox is a separately governed surface for:
- partner API testing
- verifier integration testing
- white-label validation
- SDK experimentation
- demo environments with safe data
Recommended endpoint:
sandbox.zayaz.dev
Sandbox rules:
- isolated tenant namespace
- isolated credentials and tokens
- documented API limits
- seeded sample organizations and reports
- easy environment reset and replay
5.4 Internal / Restricted Operations
Restricted operator endpoints:
admin.zayaz.io
internal.zayaz.io
ops.viroway.com
These should sit behind Cloudflare Zero Trust or equivalent identity-aware access controls.
6. Application and Service Segmentation
6.1 Frontend Surfaces
| Surface | Domain | Purpose |
|---|---|---|
| Product marketing | zayaz.io | Product entry, narrative, conversion |
| Main app | app.zayaz.io | Authenticated client UI |
| Admin console | admin.zayaz.io | Restricted platform administration |
| Partner control plane | partners.zayaz.io | White-label setup, keys, billing, domains |
| Developer docs | docs.zayaz.dev | API docs, SDK docs, schemas |
| Playground | playground.zayaz.dev | Safe testing interface |
| Public lookup | eco-number.com | Public ESG lookup |
| Institutional mirror | eco-number.org | NGO/regulatory oriented lookup |
| Academy | academy.zayaz.io / ecoworld.ai | Education and learning journeys |
6.2 Gateway Layer
Two gateway tiers are recommended:
Production Gateway
api.zayaz.io
Purpose:
- enforce auth
- route to service mesh / internal services
- validate versioned API contracts
- apply quotas and rate limits
- centralize audit and telemetry
Development / Sandbox Gateway
api.zayaz.dev
sandbox.zayaz.dev
Purpose:
- non-production API traffic
- partner testing
- experimental contract rollout
- pre-release schema verification
6.3 Core Internal Service Domains (Logical)
These do not need public DNS but should exist as formal service boundaries:
- Identity Service
- Tenant Service
- Billing Service
- SSSR Service
- ZAR / artifact registry service
- FOGE Service
- Reporting Service
- XBRL Export Service
- MICE Execution Service
- Validation / Trust Service
- AI Orchestration Service (ZAAM/ZADIF/ZARA runtime)
- Audit / Lineage Service
- Public Lookup Service
- Notification Service
- Partner Provisioning Service
7. Network and Request Flow
7.1 Canonical Request Flow for SaaS App
User
↓
Cloudflare DNS
↓
Cloudflare Edge (TLS, WAF, bot filtering, rate limits)
↓
app.zayaz.io frontend
↓
api.zayaz.io gateway
↓
internal service mesh / service router
↓
service-specific backends and data stores
7.2 Canonical Request Flow for Public Lookup
User / NGO / Stakeholder
↓
eco-number.com
↓
Cloudflare Edge + Worker cache logic
↓
Public Lookup Service
↓
read-optimized public trust dataset
7.3 Canonical Request Flow for Partner Sandbox
Partner Developer
↓
sandbox.zayaz.dev
↓
Cloudflare Edge
↓
Sandbox Gateway
↓
Sandbox tenant services + synthetic/sample data
8. Identity and Access Architecture
8.1 Identity Separation
Identity must be environment-scoped.
Minimum split:
- production audience / issuer for
*.zayaz.io - development audience / issuer for
*.zayaz.dev - partner-scoped identities for white-label operations
- internal operator identities for
admin.zayaz.ioand restricted surfaces
8.2 Access Tiers
| Access Tier | Examples | Controls |
|---|---|---|
| Public | eco-number.com, ecoworld.ai | no login or light auth |
| Client Authenticated | app.zayaz.io | SSO / MFA / RBAC |
| Partner Authenticated | partners.zayaz.io, zayaz.cloud control plane | SSO / MFA / scoped keys |
| Operator Restricted | admin.zayaz.io | Zero Trust + MFA + device checks |
| Machine-to-Machine | api.zayaz.io | signed tokens, mTLS or equivalent where needed |
8.3 RBAC / ABAC Principles
Use role-based access control enriched by attribute-based rules for:
- tenant
- verifier role
- regulator/NGO role
- jurisdiction
- framework scope
- data sensitivity level
- audit access rights
9. White-Label Infrastructure Model
9.1 Primary White-Label Pattern
Use zayaz.cloud as the infrastructure anchor.
Pattern:
<tenant>.zayaz.cloud
Examples:
partnera.zayaz.cloud
verifierhub.zayaz.cloud
clientdemo.zayaz.cloud
9.2 White-Label Provisioning Workflow
- Create tenant record in Tenant Service
- Allocate tenant slug
- Provision DNS record under
zayaz.cloud - Issue TLS automatically via Cloudflare
- Attach tenant branding config
- Attach tenant auth config / SSO metadata
- Bind tenant to API scopes and storage namespaces
- Emit audit event for provisioning
9.3 Custom Domain Support (Future)
Allow enterprise partners to bring their own domain later, for example:
esg.partnername.com
Model:
- partner verifies domain ownership
- CNAME or delegated setup
- tenant mapping added to control plane
- edge routing maps custom hostname to correct tenant
9.4 Control Plane Endpoint
Recommended partner control plane:
partners.zayaz.io
Functions:
- manage tenants
- create API keys
- configure webhooks
- upload branding assets
- configure custom domains
- view audit history
- manage sandbox access
10. AI and Agent Runtime Architecture
10.1 Domain Separation for AI
Production AI ingress:
ai.zayaz.io
Development/testing AI ingress:
ai.zayaz.dev
agents.zayaz.dev
Future AI-facing public product surface:
zara.zayaz.ai
10.2 Runtime Segmentation
Separate:
- prompt orchestration
- model adapters
- trust scoring
- agent routing
- audit logging
- retrieval / policy retrieval
- sandboxed experiments
10.3 Governance-Critical Rule
No experimental agent or model runtime under *.zayaz.dev may call production compliance-critical execution paths without an explicit brokered approval layer.
10.4 Audit Surfaces
Recommended:
audit.zayaz.io
Scope:
- lineage views
- trust score trails
- AI-origin tagging visibility
- model version references
- validation decision history
11. Data and Storage Segmentation
11.1 Storage Categories
Separate storage by purpose:
- operational relational data
- analytics / warehouse data
- document / artifact storage
- audit log storage
- public trust dataset
- sandbox sample data
- AI evaluation datasets
11.2 Environment Rules
Production and development must not share:
- primary databases
- object storage buckets
- signing keys
- queue namespaces
- analytics workspaces unless explicitly partitioned
11.3 Public Dataset Strategy
For eco-number.com and eco-number.org, expose a deliberately curated, read-optimized public dataset rather than querying regulated production application tables directly.
12. Observability and Logging
12.1 Core Observability Streams
Maintain separate observability channels for:
- edge request logs
- application logs
- audit logs
- security logs
- AI runtime traces
- partner provisioning logs
- schema and routing change logs
12.2 Environment Isolation
Use separate telemetry projects or namespaces for:
- production
- development
- sandbox
- internal operations
12.3 Minimum Dashboards
Required dashboards:
- edge traffic and attack patterns
- API latency and error rates
- tenant health
- agent / AI trust events
- public lookup performance
- partner provisioning status
- audit event throughput
13. Security Controls
13.1 Baseline Controls
- TLS everywhere
- HSTS on all eligible domains
- WAF managed rules enabled
- rate limiting on public APIs
- bot mitigation on public forms and lookup endpoints
- secret rotation policy
- MFA for operators and partners
- Zero Trust access for admin surfaces
- signed webhooks with replay protection
13.2 Sensitive Surfaces
Highest protections should apply to:
admin.zayaz.ioapi.zayaz.iopartners.zayaz.ioaudit.zayaz.io- white-label provisioning paths
13.3 CORS Strategy
Never use permissive wildcard CORS for regulated APIs.
Maintain explicit allowlists per environment and per product surface.
14. DNS Record Blueprint
14.1 Example High-Level Record Plan
zayaz.io
- apex → marketing / landing frontend
app→ authenticated SaaS frontendapi→ production gatewayadmin→ restricted admin frontendpartners→ partner control planeacademy→ academy service / redirect workerai→ production AI ingressaudit→ audit dashboards
zayaz.dev
- apex → developer portal
api→ dev gatewaysandbox→ sandbox runtimeagents→ agent runtime / UIlab→ experimental appsdocs→ docs siteplayground→ playground UIai→ model test ingress
zayaz.cloud
- apex → white-label info / partner landing
- wildcard
*→ tenant ingress routing
eco-number.com
- apex → public lookup frontend
api(optional) → public lookup API
ecoworld.ai
- apex → public ecosystem site
academy(optional if not usingacademy.zayaz.io) → learning experience
15. Deployment and Release Model
15.1 Recommended Deployment Stages
- local development
- preview / ephemeral branch environment
- shared development (
*.zayaz.dev) - sandbox certification environment
- production (
*.zayaz.io)
15.2 Critical Release Rules
Production releases affecting:
- reporting
- public trust data
- AI governance
- partner provisioning
- auth
should require structured approval, automated tests, and audit logging.
15.3 Infrastructure as Code
All DNS, Workers, routing rules, WAF rules, and tenant provisioning workflows should be managed via Infrastructure as Code.
Preferred categories:
- Terraform or Pulumi for cloud and DNS resources
- Wrangler-managed Worker deployments
- version-controlled environment manifests
16. Recommended Phase Plan
Phase A — Core Production and Dev Separation
Implement first:
zayaz.io
app.zayaz.io
api.zayaz.io
admin.zayaz.io
zayaz.dev
api.zayaz.dev
sandbox.zayaz.dev
docs.zayaz.dev
Phase B — Public Trust and Education Layer
Implement:
eco-number.com
eco-number.org
ecoworld.ai
academy.zayaz.io
Phase C — White-Label Control Plane
Implement:
partners.zayaz.io
zayaz.cloud
*.zayaz.cloud
Phase D — AI and Audit Surfaces
Implement:
ai.zayaz.io
audit.zayaz.io
agents.zayaz.dev
ai.zayaz.dev
zara.zayaz.ai
Phase E — Policy and Governance Outreach
Implement:
sustainability-act.org
as a separate policy narrative platform, not as part of the regulated app stack.
17. Decisions to Lock Early
The following decisions should be locked early to prevent future architectural drift:
zayaz.iois the regulated product rootzayaz.devis the only non-production engineering rootzayaz.cloudis the white-label tenant namespaceeco-number.comis the primary public trust portalecoworld.aiis the public education and ecosystem brandviroway.comremains the corporate/legal layersustainability-act.orgremains policy/governance, not product runtime
18. Tenant Routing & Resolution Architecture
All tenant-facing domains under zayaz.cloud are resolved dynamically using a hostname → tenant mapping layer implemented at the edge.
18.1. DNS Layer (Cloudflare)
*.zayaz.cloud → tenant-edge-router (Cloudflare Worker)
- Wildcard DNS routes all tenants to a shared ingress
- No per-tenant DNS record required for standard onboarding
- Custom domains (future) may override this behavior
18.2. Edge Routing (Cloudflare Worker)
The Worker performs:
- Extract hostname → acme.zayaz.cloud
- Lookup in KV:
key = "acme.zayaz.cloud"
- Retrieve tenant configuration
- Attach tenant context to request
- Route to appropriate origin (origin_target)
18.3. KV Payload Structure
{
"client_id": "eco-173-123-456-789",
"tenant_slug": "acme",
"hostname": "acme.zayaz.cloud",
"status": "active",
"origin_target": "app_prod",
"css_sssr_ref": "sssr:asset.client-profiles.css.css @ eco-173-123-456-789",
"logo_sssr_ref": "sssr:asset.client-profiles.main-logo.gif @ eco-173-123-456-789",
"auth_profile_id": "auth_acme_v1"
}
18.4. Key Design Principles
- KV stores references, not assets or URLs
- All branding is resolved via SSSR
- Hostname determines tenant before authentication
- Tenant resolution must be:
- deterministic
- low-latency
- globally available
19. Branding Resolution via SSSR
Tenant branding is not stored in KV as raw values.
Instead, KV stores SSSR references, which are resolved at runtime.
19.1. CSS Resolution
"css_sssr_ref": "sssr:asset.client-profiles.css.css @ eco-173-123-456-789"
Runtime flow:
- Worker passes css_sssr_ref to frontend
- Frontend (or resolver API) resolves SSSR reference
- CSS file is loaded dynamically
19.2. Logo Resolution
{
"logo_sssr_ref": "sssr:asset.client-profiles.main-logo.gif @ eco-173-123-456-789"
}
Resolved via:
sssr → asset registry → path_template → CDN URL
19.3. Benefits
- No hardcoded branding values
- Full auditability via SSSR
- Easy rebranding (change asset, not references)
- CDN/provider independence
- Supports:
- theming
- localization
- versioning
20. Tenant Onboarding Flow (Automated)
Tenant onboarding must be fully automatable and exportable.
20.1. Input (Control Plane)
New tenant created in AWS:
client_id = eco-173-123-456-789
tenant_slug = acme
hostname = acme.zayaz.cloud
20.2. KV Record Generation
Generated automatically:
{
"client_id": "eco-173-123-456-789",
"hostname": "acme.zayaz.cloud",
"status": "active",
"origin_target": "app_prod",
"primary_region": "eu-north-1",
"data_residency_zone": "eu",
"css_sssr_ref": "sssr:asset.client-profiles.css.css @ eco-173-123-456-789",
"logo_sssr_ref": "sssr:asset.client-profiles.main-logo.gif @ eco-173-123-456-789",
"auth_profile_id": "auth_acme_v1"
}
20.3. DNS Import Strategy (CSV Export)
Tenant DNS entries can be exported as:
type,name,content,ttl,proxied
CNAME,acme.zayaz.cloud,tenant-edge-router.zayaz.io,300,true
This enables:
- batch onboarding
- migration between environments
- external provisioning systems
20.4. KV Sync Strategy
KV must be updated:
- immediately on tenant creation
- on branding changes
- on status changes (suspension, activation)
Source of truth:
AWS DB → Event → KV update
21. Authentication & Tenant Context
Tenant resolution occurs before authentication.
21.1. Flow
acme.zayaz.cloud
↓
Tenant resolved via KV
↓
Auth system loads tenant-specific config
↓
User authenticates
↓
Session bound to client_id
21.2. Auth Profile Mapping
{
"auth_profile_id": "auth_acme_v1"
}
Used to determine:
- SSO provider
- login method
- identity domain
- token configuration
21.3. Key Principle
Authentication must always be tenant-aware from the first request.
22. Environment Separation
Each environment must have strict domain isolation.
22.1. Production
zayaz.cloud
zayaz.io
ecoworld.ai
eco-number.com
22.2. Development
*.zayaz.dev
Used for:
- feature branches
- sandbox tenants
- test environments
22.3. Rules
- No production data on
.dev - No shared cookies between
.devand.cloud - Separate auth systems per environment
23. Future Extensions
The architecture supports:
23.1. Custom Domains
app.acme.com → acme.zayaz.cloud
Handled via:
- Cloudflare custom hostname mapping
- same KV lookup logic
23.2. Multi-Scope Branding
Future extension of SSSR:
sssr:asset.client-profiles.css.css @ eco-... + region_id
23.3. Multi-Region Routing
acme.zayaz.cloud → EU cluster / US cluster
Based on:
- latency
- compliance (GDPR, data residency)
23.4. Tenant-Level CDN Overrides
tenant-specific asset routing via SSSR override_rules
24. Governance & Audit
All tenant configuration changes must be:
- logged in ALTD
- versioned
- traceable to user/system
- reversible
24.1. KV Changes
Every KV write must include:
timestampactor(system/user)diffclient_id
24.2. Branding Changes
Changing:
css_sssr_ref
logo_sssr_ref
must:
- create audit record
- preserve historical reference
- support rollback
25. Final Architectural Principle
The hostname is the entry point. The tenant is the context. The SSSR is the source of truth.
ZAYAZ must never rely on:
- hardcoded URLs
- implicit tenant context
- duplicated branding logic
All runtime behavior must be derived from:
- hostname
- KV routing layer
- SSSR registry
- control-plane configuration
Final Principle
Domain architecture = system architecture.
Every domain and subdomain must have a defensible purpose, a clear trust tier, an explicit routing policy, and a governed lifecycle.
ZAYAZ should operate as a global ESG infrastructure layer with production-grade separation between public trust, regulated application runtime, AI surfaces, and partner ecosystems.
APPENDIX A - Tenant Edge Router Spec
Cloudflare Worker Implementation
A.1. Purpose
The tenant-edge-router Worker is the runtime ingress for:
*.zayaz.cloud- future custom hostnames
- optional tenant-aware login pre-routing
It resolves the incoming hostname to a tenant config, attaches tenant context, enforces status rules, and forwards the request to the correct origin.
Cloudflare recommends wildcard routing to a dispatch Worker for SaaS hostname routing, including subdomains and custom hostnames, and supports KV-backed dynamic mappings. 
A.2. Responsibilities
The Worker must:
- read the incoming Host header
- normalize the hostname
- resolve tenant config from KV
- reject unknown / suspended tenants
- map
origin_targetto an upstream origin - attach tenant context headers
- preserve request path/query
- avoid embedding branding values directly
- return deterministic error pages for inactive tenants
- emit telemetry for routing outcomes
The Worker must not:
- be the source of truth for tenant data
- store large branding payloads
- execute heavy ESG logic
- depend on a live AWS lookup on every request
A.3. Inputs
A.3.1 Incoming request
Example:
GET /login HTTP/1.1
Host: acme.zayaz.cloud
A.3.2 KV key
acme.zayaz.cloud
A.3.3 KV payload
{
"client_id": "eco-173-123-456-789",
"hostname": "acme.zayaz.cloud",
"status": "active",
"origin_target": "app_prod",
"primary_region": "eu-north-1",
"data_residency_zone": "eu",
"css_sssr_ref": "sssr:asset.client-profiles.css.css @ eco-173-123-456-789",
"logo_sssr_ref": "sssr:asset.client-profiles.main-logo.gif @ eco-173-123-456-789",
"auth_profile_id": "auth_acme_v1"
}
Cloudflare Workers KV supports JSON reads directly through the Worker binding. 
A.4. Origin target model
origin_target is a ZAYAZ-defined routing alias.
A.4.1 Allowed values
Examples:
app_prodapp_maintenancesandbox_defaultpartner_dedicated_acme
A.4.2 Origin map
Configured in Worker environment or config module:
/**
* Supported regions
*/
type Region = "eu-north-1" | "eu-central-1" | "us-east-1";
/**
* Supported origin targets
*/
type OriginTarget = "app_prod" | "app_maintenance" | "sandbox_default";
/**
* Region → base URL mapping
*/
const REGION_MAP: Record<Region, string> = {
"eu-north-1": "https://eu-north-1.app.zayaz.io",
"eu-central-1": "https://eu-central-1.app.zayaz.io",
"us-east-1": "https://us-east-1.app.zayaz.io",
};
/**
* Resolve origin URL based on target and region
*/
export function resolveOrigin(
originTarget: OriginTarget,
region: Region
): string {
switch (originTarget) {
case "app_prod": {
const url = REGION_MAP[region];
if (!url) {
throw new Error(`Unsupported region: ${region}`);
}
return url;
}
case "app_maintenance":
return "https://maintenance.zayaz.io";
case "sandbox_default":
return "https://sandbox.zayaz.dev";
default:
// Exhaustiveness check (TypeScript safety)
const _exhaustive: never = originTarget;
throw new Error(`Invalid origin_target: ${_exhaustive}`);
}
}
/**
* Example usage
*/
const example = resolveOrigin("app_prod", "eu-north-1");
console.log(example);
A.4.3 Rule
If origin_target is unknown, return 502 Bad Gateway and emit a routing error event.
A.5. Worker resolution flow
A.5.1 Happy path
Request
↓
Extract Host
↓
Normalize hostname
↓
KV lookup by hostname
↓
Validate tenant status
↓
Resolve origin_target → upstream URL
↓
Clone request to upstream
↓
Attach tenant headers
↓
fetch(upstreamRequest)
↓
Return response
A.5.2 Pseudocode
/**
* Stand-alone Cloudflare Worker: policy-driven edge routing layer
*/
type TenantStatus = "active" | "inactive" | "suspended" | "maintenance";
type OriginTarget =
| "app_prod"
| "app_maintenance"
| "sandbox_default";
type Region =
| "eu-north-1"
| "eu-central-1"
| "us-east-1";
interface Tenant {
client_id: string;
tenant_slug: string;
hostname: string;
auth_profile_id: string;
css_sssr_ref: string;
logo_sssr_ref: string;
origin_target: OriginTarget;
status: TenantStatus;
primary_region?: Region;
fallback_region?: Region;
}
interface RoutingPolicy {
force_maintenance?: boolean;
allow_fallback_region?: boolean;
default_region?: Region;
}
interface KVNamespaceLike {
get(
key: string,
options?: { type?: "json"; cacheTtl?: number }
): Promise<unknown>;
}
interface Env {
TENANT_ROUTING: KVNamespaceLike;
ROUTING_POLICY?: KVNamespaceLike;
}
const REGION_MAP: Record<Region, string> = {
"eu-north-1": "https://eu-north-1.app.zayaz.io",
"eu-central-1": "https://eu-central-1.app.zayaz.io",
"us-east-1": "https://us-east-1.app.zayaz.io"
};
const STATIC_ORIGINS: Record<Exclude<OriginTarget, "app_prod">, string> = {
app_maintenance: "https://maintenance.zayaz.io",
sandbox_default: "https://sandbox.zayaz.dev"
};
function jsonResponse(body: unknown, status: number): Response {
return new Response(JSON.stringify(body, null, 2), {
status,
headers: {
"content-type": "application/json; charset=utf-8"
}
});
}
function notFoundTenant(hostname: string): Response {
return jsonResponse(
{
ok: false,
error: "tenant_not_found",
hostname
},
404
);
}
function tenantUnavailable(tenant: Tenant): Response {
return jsonResponse(
{
ok: false,
error: "tenant_unavailable",
tenant_slug: tenant.tenant_slug,
status: tenant.status
},
503
);
}
function badOriginTarget(target: string): Response {
return jsonResponse(
{
ok: false,
error: "invalid_origin_target",
origin_target: target
},
502
);
}
function badRegion(region?: string): Response {
return jsonResponse(
{
ok: false,
error: "invalid_region",
region: region ?? null
},
502
);
}
function resolveOrigin(
tenant: Tenant,
policy: RoutingPolicy = {}
): string {
if (policy.force_maintenance || tenant.status === "maintenance") {
return STATIC_ORIGINS.app_maintenance;
}
switch (tenant.origin_target) {
case "app_maintenance":
return STATIC_ORIGINS.app_maintenance;
case "sandbox_default":
return STATIC_ORIGINS.sandbox_default;
case "app_prod": {
const primaryRegion = tenant.primary_region ?? policy.default_region;
if (primaryRegion && REGION_MAP[primaryRegion]) {
return REGION_MAP[primaryRegion];
}
if (
policy.allow_fallback_region &&
tenant.fallback_region &&
REGION_MAP[tenant.fallback_region]
) {
return REGION_MAP[tenant.fallback_region];
}
throw new Error(`No valid region available for tenant "${tenant.tenant_slug}"`);
}
default: {
const exhaustiveCheck: never = tenant.origin_target;
throw new Error(`Unsupported origin target: ${exhaustiveCheck}`);
}
}
}
function buildUpstreamUrl(request: Request, originBase: string): URL {
const upstreamUrl = new URL(request.url);
const origin = new URL(originBase);
upstreamUrl.protocol = origin.protocol;
upstreamUrl.host = origin.host;
return upstreamUrl;
}
function enrichHeaders(headers: Headers, tenant: Tenant, originResolved: string): Headers {
const out = new Headers(headers);
out.set("x-zayaz-client-id", tenant.client_id);
out.set("x-zayaz-tenant-slug", tenant.tenant_slug);
out.set("x-zayaz-hostname", tenant.hostname);
out.set("x-zayaz-auth-profile-id", tenant.auth_profile_id);
out.set("x-zayaz-css-sssr-ref", tenant.css_sssr_ref);
out.set("x-zayaz-logo-sssr-ref", tenant.logo_sssr_ref);
out.set("x-zayaz-origin-target", tenant.origin_target);
out.set("x-zayaz-origin-resolved", originResolved);
out.set("x-zayaz-primary-region", tenant.primary_region ?? "");
out.set("x-zayaz-fallback-region", tenant.fallback_region ?? "");
return out;
}
async function loadRoutingPolicy(env: Env): Promise<RoutingPolicy> {
if (!env.ROUTING_POLICY) {
return {
allow_fallback_region: true,
default_region: "eu-north-1"
};
}
const policy = await env.ROUTING_POLICY.get("global", {
type: "json",
cacheTtl: 60
});
return (policy as RoutingPolicy) ?? {
allow_fallback_region: true,
default_region: "eu-north-1"
};
}
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const url = new URL(request.url);
const hostname = url.hostname.toLowerCase();
const tenant = (await env.TENANT_ROUTING.get(hostname, {
type: "json",
cacheTtl: 60
})) as Tenant | null;
if (!tenant) {
return notFoundTenant(hostname);
}
if (tenant.status === "inactive" || tenant.status === "suspended") {
return tenantUnavailable(tenant);
}
const policy = await loadRoutingPolicy(env);
let originBase: string;
try {
originBase = resolveOrigin(tenant, policy);
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
if (message.includes("region")) {
return badRegion(tenant.primary_region);
}
return badOriginTarget(tenant.origin_target);
}
const upstreamUrl = buildUpstreamUrl(request, originBase);
const upstreamReq = new Request(upstreamUrl.toString(), request);
const routedHeaders = enrichHeaders(
upstreamReq.headers,
tenant,
originBase
);
const routedReq = new Request(upstreamReq, {
headers: routedHeaders
});
const response = await fetch(routedReq);
const outHeaders = new Headers(response.headers);
outHeaders.set("x-zayaz-tenant-routed", "true");
outHeaders.set("x-zayaz-origin-resolved", originBase);
return new Response(response.body, {
status: response.status,
statusText: response.statusText,
headers: outHeaders
});
}
};
The RoutingPolicy can later be extended with fields such as:
force_maintenance?: boolean;
allow_fallback_region?: boolean;
default_region?: Region;
allowed_regions?: Region[];
required_compliance_profile?: string;
origin_failover_mode?: "strict" | "fallback";
This keeps tenant routing facts separate from environment-level routing policy.
- The tenant record defines tenant-specific routing inputs such as
primary_region,fallback_region,origin_target, andstatus. - The routing policy defines global or environment-level rules that influence how those inputs are interpreted.
Over time, resolveOrigin() can evolve into the core decision engine for:
- maintenance overrides
- region restrictions
- failover behavior
- compliance-aware routing
- sovereign/data-residency enforcement
Split this further into:
- tenant-registry.ts
- routing-policy.ts
- origin-resolver.ts
- request-context.ts
- worker.ts
A.6. Status handling
A.6.1 active
Route normally.
A.6.2 provisioning
Return branded provisioning page or controlled 503.
A.6.3 suspended
Return branded suspension page or restricted login block.
A.6.4 maintenance
Route to app_maintenance.
A.6.5 retired
Return 410 Gone.
Recommended enum:
active
provisioning
maintenance
suspended
retired
error
A.7. Branding behavior
The Worker does not resolve branding URLs itself unless you deliberately choose to.
It forwards:
css_sssr_reflogo_sssr_ref
to the app layer.
Then the app or a resolver API resolves those SSSR references into concrete URLs.
This keeps the Worker:
- fast
- deterministic
- free of asset-resolution complexity
A.8. Authentication behavior
Tenant resolution happens before login.
A.8.1 Flow
acme.zayaz.cloud
↓
Worker resolves tenant
↓
Worker forwards auth_profile_id + client_id
↓
App/login service uses tenant-specific auth rules
↓
Session created for client_id
A.8.2 Rule
No generic login should be shown without tenant context if the request came from a tenant hostname.
A.9. KV update model
KV should be updated by event-driven sync from the AWS control plane:
- tenant created
- hostname changed
- status changed
- branding refs changed
- auth profile changed
- origin target changed
KV is well-suited for globally replicated routing/config data and read-heavy patterns. 
A.9.1 Recommended model
AWS DB
↓
Control-plane event
↓
KV update API / sync worker
↓
tenant-edge-router reads KV
A.9.2 Safety net
Run a reconciliation job periodically:
AWS DB ↔ KV ↔ actual routing outcomes
A.10. Cloudflare configuration
A.10.1 Route
Use wildcard routing to the Worker.
Cloudflare documents wildcard routing to a dispatch Worker for hostname-based SaaS routing. 
A.10.2 KV binding
Bind a namespace such as:
name = "zayaz-edge-router"
main = "src/index.ts"
compatibility_date = "2026-03-19"
# Enable node compatibility if you use node-style APIs
compatibility_flags = ["nodejs_compat"]
# Default route (production)
routes = [
{ pattern = "*.zayaz.io/*", zone_name = "zayaz.io" }
]
########################################
# KV NAMESPACES (PRODUCTION)
########################################
[[kv_namespaces]]
binding = "TENANT_ROUTING"
id = "prod-tenant-routing-kv-id"
[[kv_namespaces]]
binding = "ROUTING_POLICY"
id = "prod-routing-policy-kv-id"
########################################
# ENV: DEVELOPMENT
########################################
[env.dev]
name = "zayaz-edge-router-dev"
routes = [
{ pattern = "*.dev.zayaz.io/*", zone_name = "zayaz.io" }
]
[[env.dev.kv_namespaces]]
binding = "TENANT_ROUTING"
id = "dev-tenant-routing-kv-id"
preview_id = "dev-tenant-routing-preview-id"
[[env.dev.kv_namespaces]]
binding = "ROUTING_POLICY"
id = "dev-routing-policy-kv-id"
preview_id = "dev-routing-policy-preview-id"
[env.dev.vars]
ENVIRONMENT = "development"
DEFAULT_REGION = "eu-north-1"
ALLOW_FALLBACK = true
########################################
# ENV: STAGING
########################################
[env.staging]
name = "zayaz-edge-router-staging"
routes = [
{ pattern = "*.staging.zayaz.io/*", zone_name = "zayaz.io" }
]
[[env.staging.kv_namespaces]]
binding = "TENANT_ROUTING"
id = "staging-tenant-routing-kv-id"
[[env.staging.kv_namespaces]]
binding = "ROUTING_POLICY"
id = "staging-routing-policy-kv-id"
[env.staging.vars]
ENVIRONMENT = "staging"
DEFAULT_REGION = "eu-central-1"
ALLOW_FALLBACK = true
########################################
# ENV: PRODUCTION (explicit override)
########################################
[env.production]
name = "zayaz-edge-router-prod"
routes = [
{ pattern = "*.zayaz.io/*", zone_name = "zayaz.io" }
]
[[env.production.kv_namespaces]]
binding = "TENANT_ROUTING"
id = "prod-tenant-routing-kv-id"
[[env.production.kv_namespaces]]
binding = "ROUTING_POLICY"
id = "prod-routing-policy-kv-id"
[env.production.vars]
ENVIRONMENT = "production"
DEFAULT_REGION = "eu-north-1"
ALLOW_FALLBACK = true
########################################
# OPTIONAL: R2 (future asset / SSSR storage)
########################################
# [[r2_buckets]]
# binding = "SSSR_ASSETS"
# bucket_name = "zayaz-sssr-assets"
########################################
# OPTIONAL: Durable Objects (future control plane)
########################################
# [[durable_objects.bindings]]
# name = "ROUTING_ENGINE"
# class_name = "RoutingEngine"
########################################
# OPTIONAL: LOGGING / OBSERVABILITY
########################################
[observability]
enabled = true
KV bindings are configured in Wrangler and accessed directly from Worker code. 
A.10.3 Optional custom domains
Future custom hostnames can be routed through the same dispatch logic. Cloudflare supports hostname routing and custom domains for Workers. 
A.11. Request headers to upstream
Recommended forwarded headers:
x-zayaz-client-idx-zayaz-tenant-slugx-zayaz-hostnamex-zayaz-auth-profile-idx-zayaz-css-sssr-refx-zayaz-logo-sssr-ref
Optional:
x-zayaz-origin-targetx-zayaz-routing-versionx-zayaz-tenant-status
Do not trust these headers from public clients; only trust them when injected by the Worker.
A.12. Error handling
A.12.1 Unknown hostname
Response:
404 Not Found- internal reason:
tenant_not_found
A.12.2 Invalid origin target
Response:
502 Bad Gateway- internal reason:
invalid_origin_target
A.12.3 Suspended tenant
Response:
423 Lockedor branded 403/503 depending on UX choice
A.12.4 KV transient failure
Preferred behavior:
- attempt fallback control-plane API lookup
- if resolved, optionally self-heal KV
- otherwise return controlled 503
A.13. Observability
Emit structured events for:
tenant_route_successtenant_route_not_foundtenant_route_suspendedtenant_route_invalid_origintenant_route_kv_misstenant_route_fallback_api_successtenant_route_fallback_api_failure
Minimum event payload:
{
"hostname": "acme.zayaz.cloud",
"client_id": "eco-173-123-456-789",
"tenant_slug": "acme",
"origin_target": "app_prod",
"status": "active",
"outcome": "success",
"timestamp": "2026-03-20T12:00:00Z"
}
A.14. Security rules
- do not expose raw AWS control-plane endpoints to the public path
- never trust client-supplied tenant headers
- only accept proxied traffic through Cloudflare
- restrict fallback control-plane API with service auth
- keep Worker logic minimal and deterministic
- avoid embedding secrets in KV values
A.15. Future extensions
The same model supports:
- custom domains
- region-aware routing
- dedicated tenant origins
- maintenance bypass logic
- per-tenant feature flags
- SSSR-driven theme families beyond CSS/logo
A.16. Final rule
The Worker resolves the hostname. KV provides the routing snapshot. The control plane provides the truth. SSSR provides the branding references.