One always-on Node server that hosts the published web site of every store
with the web capability, each on its own subdomain:
https://{sid}.inbs.dev— the store's PROD site,https://demo-{sid}.inbs.dev— the store's DEMO site,- plus any custom domains bound DNS-first via a
_drop.{domain}TXT record (drop-site={env}.{sid}.{site_key}— see docs/DOMAINS.md).
Internally it is a host router over a fleet of per-store "mini servers":
each mounted store gets its own WebSite (from drop-core-server) with its
own per-store access token, DataRepository cache, render/deps caches and
hook feed, held in an LRU — the same isolation examples/instore has as a
standalone process, multiplexed into one Node process and picked per request
by the Host header.
Architecture#
Host header ──▶ TenantDirectory.parseHost (pure syntax: subdomain = sid,
│ demo- prefix = env, reserved
▼ labels rejected)
lookup(env, sid) ──────────────▶ POST {core}/system/tenant/resolve
│ (master token, that env's API;
▼ negative-cached misses)
TenantMount {token, hookKey}
│
▼
WebPreviewServer (per env) ────▶ WebSite (per store, LRU)
siteOptions injection: reads: 'public'
accessToken = store token headerStore = sidTenantDirectory—host → {env, sid} → credentials. Resolution is a master-token call to/system/tenant/resolve; unknown hosts negative- cache (60 s), a periodic sweep (10 min) re-resolves mounted entries, and credential drift (reroll) evicts the store'sWebSiteviaonChange(a serving 5xx also triggers a throttled background re-resolve, so a rerolled token self-heals on the next request instead of waiting for the sweep). The sweep at scale (plans/hosting/tenant-sweep-and-exposure.md): one pass at a time, ever — a guarded, self-rescheduling timer chain (the next pass is duestartedAt + recheckMs, orendedAt + 30 safter a pass that overran, loggedTENANT SWEEP OVERRUN {durationMs, mounts}); the warm boot is pass 0 and the first sweep is scheduled from its END; a pass snapshots the mount keys and resolves them on a bounded pool (TENANT_SWEEP_CONCURRENCY, default 8, clamped 1–32 — a key invalidated mid-pass is skipped), then re-checks the custom-domain TXTs on a pool of 16; every/system/tenant/*call has a timeout (TENANT_CORE_TIMEOUT_MS, default 10 s — a timeout is a transport error: the old mount stays, never a 404), which also bounds a visitor's first request. The same value bounds every store site's core READS (WebSiteOptions.coreTimeoutMs— the render, meta and data reads; checkout, cart, forms,/fnand provider calls stay untimed, plans/tenthousand W9 E-D7). One set of mount rules (applyPayload: 404 → drop, transport / 5xx → keep, token change →onChange) serves the single resolve, the sweep and warm boot alike. Each pass leaves{pass, startedAt, durationMs, mounts, resolved, dropped, failed, skipped, overran, hosts, unbound}as the last sweep, shown on/-/statusonly. Off-zone hosts (kind: 'external') bind DNS-first:_drop.{host}TXT →drop-site={env}.{sid}.{site_key}→ resolve → the TXT's key must match the store'ssite_key(mutual intent: the TXT proves domain-owner intent, the unguessable key proves store-owner intent). No server-side domain registry; DNS is soft state — transport failures never unbind, only two consecutive sweeps that positively confirm a missing/mismatched record do. The first bound domain becomes the store's canonicalsiteBaseUrl.TenantServer— the http handler. Store hosts dispatch into that env'sWebPreviewServerengine (the full route table: pages,/ref/, slugs, robots/sitemaps,/assets/**,/store/{sid}/css|js/**,POST /form/:locale/:form— andGETon the same path, which issues the form guard's fields ({fields}, no-store) for the page's submit script to fetch at load —POST /content/:locale,POST /variant/:locale,POST /cart/:locale+POST /checkout/:locale(+/checkout/:locale/payment) — the storefront cart/checkout proxies riding each store's own{public, process}serving token —GET|POST|PUT|DELETE /m/{moduleId}/**, an installed module's storefront leg forwarded toPOST /api/public/moduleover the same serving token, the module's answer re-emitted — andGET|POST|PUT|DELETE|OPTIONS /fn/{serviceId}/**, the store's services, run in this machine's sandbox (see "Store services" below); a cacheableGETanswer of either sits in the store'sedgedisk slot;mandfnare reserved first segments, never slugs). Store hosts are served non-indexable:{sid}.inbs.dev/demo-{sid}.inbs.devanswer a constantDisallow: /robots.txt, 404 the sitemaps and carryx-robots-tag: noindexon every response, whatever the store'ssetup/web.robotssays — search indexing is a custom-domain feature, and once a domain is bound the subdomain serves the very same pages. Custom domains (kind: 'external') are indexable per the store's own config, except on the Demo env, which is a copy of the prod store and is never indexable.GET|HEAD /healthz— liveness only, on every host (Fly's checker probes without the canonical Host): exactly{"ok":true}(HEAD: no body). No uptime, build, mounts or env names — nothing public says what runs here (plans/hosting/tenant-sweep-and-exposure.mdX-D1).- Any unhandled error answers
500 {"error":"internal"}(the message and stack go to the log only — X-D4).
The canonical host (
tenant.inbs.dev) carries the cross-store surfaces. Every ops route authenticates first (authenticateOps: theaccess-tokenheader against the configured env masters, constant-time) —401before any body is read — and acts only on the env whose master matched (X-D3):GET /-/status[?list=1]— the ops status, scoped to that env:{ok, uptimeMs, build, env, mounts, domains, sites, sweep, sweeping, nextSweepMs, services: {mode, sandbox, reports}}— counts only;?list=1adds that env'ssids(a Demo master never sees a PROD sid). No CORS (no browser caller). On any other host it is an ordinary store path (404).buildis the build stamp — the short sha the running server was built from, whether that tree had uncommitted changes, and the build's ms epoch (src/build_info.ts, read once at startup): fromTENANT_BUILD_COMMIT/TENANT_BUILD_DIRTY/TENANT_BUILD_AT(the Docker image bakes them from the deploy line's build args), else from therelease.jsona vshosting release carries at its root;commit: ''when neither is there.tools/deploysreads it here with the env master.services.sandbox= the machine's executor counters (slots,busy,queued,restarts,busyRefusals,calls),services.reports= this env's report batcher.POST /-/mount {env, sid}— master-token-authenticated poke to mount / refresh a store immediately (the admin calls it after provisioning).envmust be the authenticated env (else403) andsida store id (SID_PATTERN, else400 invalid_sid) — checked before any lookup or cache wipe;wipeStoreCachesadditionally refuses any path that does not resolve strictly inside{dir}/{env}/{sid}(services plan H1). A rebuild keeps the store's disk slots.POST /-/mount {env, sid, flush: true}additionally calls the site'sWebSite.flushAll()and wipes the store's disk slots under{dir}/{env}/{sid}/— the lever that ends any staleness after a lost push (the console's Refresh site caches).POST /-/mount {env, domain[, remove]}— custom-domain connect: forces the_dropTXT validation and, on success, either registers the domain's Fly certificate (FlyCerts, needsFLY_API_TOKEN+FLY_APP_NAME) or, withTENANT_CERTS=probe, checks TLS managed by an external reverse proxy.removealways unbinds; only Fly mode also deletes a certificate.GET /-/domain?domain=…reports cert status for the admin chips. Both answer CORS (the master token is the gate; direct-dev admin calls them from the browser).POST /hook/{env}/{sid}— the MULTI-EVENT hook ingress (what the managedallentries call): forwarded to the matched site'sreceiveEventHook, which dispatches onx-drop-event(data / files / templates / elements / setup / slug / services; unknown kinds no-op-accept). Only the canonical host takes hooks — a customer-domain host answers 405. Signature-verified with the store's hook key;x-drop-updatedordering guard applies.POST /hook/{env}/{sid}/data+POST /hook/{env}/{sid}/files[/**]— the legacy per-event ingress, forwarded toreceiveHook/receiveFilesHook. Kept alive indefinitely — serves every not-yet-migrated managed entry and is the rollback path.
Token model — the two master tokens (one per env) are held only by the directory and used exclusively against
/system/tenant/*. Every render, data read, form push and checkout call runs on the store's own{public: true, process: true}token (noteCORE - Autogenerated), resolved from thesystem/{sid}custody in admin-eur3 by the backend.Provisioning is automatic for new stores — the backend's
storeSetuptrigger provisions on store-doc creation (modules/tenant/tenant_model.ts), and/system/store/deletedeprovisions./system/tenant/provisionand the admin card's "Enable web hosting" remain the manual/repair path for pre-existing stores.Publish gate — stays in
WebSite: an unpublished store's host answers 404 regardless of mount state.Platform pages — what a visitor sees when NO store page can render, all from
drop-core-server'splatform_pages.ts(one design — theinmake-websitetokens + logo, dark by default, light underprefers-color-scheme, English or Czech perAccept-Language, no external request so the page renders when the store / core / DNS is what failed):unbound(404 — an unknown or reserved subdomain, the apex, an unprovisioned store,TENANT_CUSTOM_DOMAINS_ONLYrefusing a subdomain),dns(404 — a custom domain that reaches this server without a valid_dropTXT: the page names the host, says where the record is (the Hosting card — never the record itself, it carries the site key) and the directory's verdict —no_txt/dns_error/env_off/store_unknown/key_mismatch,TenantDirectory.hostFailure(host); the same verdict rides asdetailon/-/mount's 404), anderror(the catch-all 500, for a request whoseAcceptnames HTML — anything else keeps the{"error":"internal"}JSON). The store-level built-in 404 (a mounted store with no customnotFounddoc) is the same module'snot_foundpage, served byWebPreviewServer. All go outno-store+x-robots-tag: noindex, nofollow.