Storage

The storage mixin: the genro_storage.StorageManager the server owns, its mounts and its at-rest key material.

Storage capability: genro-storage as a mixin over the base server (§4, D6).

StorageMixin is a capability composed over BaseServer (class S(..., StorageMixin, BaseServer)). Unlike AuthMixin/SessionMixin it arms NO middleware — storage is survival infrastructure, not a request-chain concern (§4: PUBLIC = base + storage). Its cooperative __init__ peels storage= and storage_key= and forwards everything else down the D16 chain.

storage= shapes the genro_storage.StorageManager the server owns:

  • None → a manager with the single mount site:, the deployment directory (the process cwd);

  • a StorageManager instance → adopted as-is;

  • a list[dict] → genro-storage’s own mount configuration, handed to configure() verbatim ({"name": ..., "protocol": ..., ...}); an EMPTY list reads like None — a recipe that declared a storage section for its key material alone asked for the default layout, not for no storage.

storage_key= is the at-rest key material: comma-separated Fernet keys, each optionally <domain>: prefixed (the first key of a domain encrypts, all of them decrypt). It reaches configure(storage_key=...); key material that resolves empty is genro-storage’s own boot error, never a silent no-encryption fallback. Omitted, encryption stays dormant and any encrypted=True write raises at the write site.

Encryption is declared per WRITE, not per mount: the stores that hold credentials pass encrypted=True, everything else writes plain, and both share one directory tree — what lands on disk is self-describing (an envelope whose first line is #GNRE1:), so reads declare nothing.

genro-storage nodes are smartasync: under a running event loop they would hand back a coroutine instead of a value. This server’s storage API is SYNCHRONOUS by ratification (D22, core 1b) — the stores and the spool are plain sync objects and async dispatch paths wrap them — so the mixin pins the sync dispatch (set_sync()) for the context the server is built in, which every task it later spawns inherits.

A composition WITHOUT the mixin has NO storage attribute at all.

genro_asgi.storage_mixin.DEFAULT_SITE_MOUNT = {'name': 'site', 'protocol': 'local'}

ONE local mount named site.

The anchor is deliberately absent — it is the cwd read when the manager is built, which is boot. BaseConfiguration.storage_mounts writes the same mount as a recipe line, so this is the one place the two agree on.

Type:

The default layout, minus its anchor

class genro_asgi.storage_mixin.StorageMixin(**kwargs)[source]

Bases: object

Storage capability mixin, composed over the base server. Arms no middleware.

Constructor kwargs peeled here: storageNone (a manager with the single site: mount on the deployment directory), a StorageManager instance (adopted), or a list[dict] of genro-storage mount configs (empty reads like None); storage_key — the at-rest key material.

Parameters:

kwargs (Any)

property storage: StorageManager

The storage this server owns (mounts + at-rest encryption key material).