Bridge contract¶
Version: 0.2 · Last Updated: 2026-09-08 · Status: 🔴 DA REVISIONARE
The need. genropy-asgi is the first customer: it must run legacy GenroPy sites on this core WITHOUT the core learning GenroPy's logic. The bridge implements a contract; the core offers generalized mechanisms.
What the hosted site must provide and what it may consume: the WSGI
callable behind WsgiSeam; the site names its OWN connection while serving
(the spa_connection_id identity decision, 2026-08-22); what the bridge pins
(frozen tag v0.35.0) until migrated to this core. NO release of genro-asgi
from develop until this contract is honoured by a migrated bridge.
The site's own data plane — datachanges, dbevents, table subscriptions, the user view — is the bridge's since #59 (2026-09-04), attached through the seams the core names, composition never a subclass of the worker or the vertex:
SpaApplication.commander_class: the bridge's subclass ofSpaCommander.SpaCommander.commander_dispatcher.add_branches(...): the bridge's own operations under/commander/<name>/…, called by the worker up the lane.SpaWorker.worker_dispatcher.commander_orders.add_branches(...): the bridge's own orders to the worker, called by the vertex down the lane.SpaCommander.on_worker_presented(worker_handler): a process has just presented itself — where the bridge pushes what a newborn must know.SpaCommander.envelope_handler(property): the last layer of the envelope chain; the bridge returns its subclass ofCommanderEnvelopeHandlerand reads in its ownon_<op>, after the core's, what a worker event carries for it — the tables a newborn page subscribes, above all.SpaWorker.build_request_slot()/on_request_served(): what a request carries, and the tail of every served request.RegisterRegistry.page_row_class+subscribe_page_store/detach_page/new_store: the bridge's row fields, its capture, its store type.SpaCommander.new_global_store(): the vertex's data at birth — an emptydict[str, Any]. A consumer may fill it, never change its type; its values must be types the TYTX codec knows, because a grant carries them down the lane.
Interactions: spa-application (the cookie) · orchestration (the worker that hosts, the two dispatchers) · global-store (the operations).
The global store on the consumer's side¶
The core offers SpaWorker.global_store: get, set, delete and
for_update(key=None), on literal string keys with opaque values (see
040_global-store/design.md). It offers nothing path-shaped: there is no change
batch, no capturing store and no apply_global_store_changes.
genropy-asgi adapts the legacy dotted paths on the first segment: the first
segment is the dictionary key, the rest is resolved inside the legacy Bag stored
as that key's value, in the worker. A read of a subpath is one get plus a local
read; a write of a subpath is a keyed turn on the first segment, publishing the
complete Bag. with globalStore() is one whole-dictionary turn — for_update()
with no key. The core knows none of this.