MEMEROOT · COMPOSABLE SUBSTRATE · ARCHITECTURAL REFERENCE
Eight blocks, one spine.
A composable XML substrate for Memeroot. Eight fundamental block kinds — data, schema, script, process, type, view, identity, address — each in its own XML namespace, with zero crossover between kinds. Each block projects to the universal TABLE_SPECIFICATIONS spine shape via its own XSL stylesheet. The spine is computed, never stored — emerging from federation across the source blocks.
Direct lineage to the production MBI_SCRIPT_AS_TABLE_SPEC_V Oracle view (twenty-five years deployed across enterprise data systems). This document carries that pattern out of SQL into pure XML/XSL so the same self-describing combinatorial properties apply across any substrate — file systems, object stores, regulated archives, federated networks.
Section 01Thesis · zero crossover
The architectural claim is sharp. Every fundamental model of the system lives in its own XML namespace, with its own XSL stylesheet for projection. Data does not contain script. Script does not contain process. Process does not contain identity. The boundary is enforced by namespace; the projection across boundaries happens through the spine, never through inclusion.
Conventional data architecture mixes the concerns. A SQL stored procedure interleaves data references, control flow, type assumptions, security context, and orchestration logic. The artifact that results is unaddressable at any granularity finer than the whole procedure. Changing one concern requires touching all of them. The composable substrate inverts this point-for-point: each concern lives in its own block; blocks compose via projection through the spine; addressing is granular to the value.
The discipline is the same as the principle of separation of concerns in software engineering, but pushed to the substrate level. It is not a recommendation; it is the structural property that makes the rest of the substrate work. With crossover, the spine becomes ambiguous; without crossover, the spine is a clean projection.
What "no crossover" means concretely
- A
data-block carries values (v owner="..." name="..." attribute="..." type="..." value="...") — but no parsing rules, no triggers, no validation functions, no embedded scripts
- A
schema-block carries structural metadata (column definitions, indexes, constraints) — but no actual values
- A
script-block carries parametrized templates — but no actual data, no signing, no orchestration sequence
- A
process-block carries dispatch order with references to scripts by address — but no script bodies, no inline data
- A
type-block carries datatype definitions — but no instances, no schemas
- A
view-block carries projection rules referencing other blocks by id — but no source content
- An
identity-block carries public keys and roles — but no signatures (those live on signed artifacts)
- An
address-block carries content-hash → location bindings — but no content (content is pointed at, never carried)
The cardinality of crossover violations should be exactly zero. The XSL projection layer is the only legitimate way one block can influence another. Even composition is mediated: the composition document references blocks by import; the compiler applies each block's own XSL; the spine emerges; no block sees any other block's internal structure.
Section 02The eight block kinds
Eight kinds is enough to span the addressable space of an enterprise data substrate. Each kind has a fixed namespace URI, a single concern, a documented set of permitted elements, and a corresponding XSL projector. New kinds may be added; existing kinds are immutable — once published, a kind's namespace is fixed forever (existing consumers continue to verify).
Block · data
Pure values
memeroot://block/data/v1
Actual content. Observations. Rows from source systems. File contents. Sensor readings. Every value addressed by owner.name.attribute.type.
Block · schema
Structural metadata
memeroot://block/schema/v1
The shape of addressable spaces. Column definitions, indexes, constraints. Directly in spine row shape — identity projection.
Block · script
Templates
memeroot://block/script/v1
Parametrized executable templates. MBI_SCRIPT-shaped: sequence, loop, condition, indent, token contract. Resolved at dispatch.
Block · process
Orchestration
memeroot://block/process/v1
Dispatch sequences. Steps reference scripts by content-hash address. MPP-friendly: independent steps run in parallel. Queue channels.
Block · type
Datatype definitions
memeroot://block/type/v1
Formats, encodings, validations. Pure definitions referenced by schemas. Regex, enum, range, format, encoding.
Block · view
Projections
memeroot://block/view/v1
Views-on-views. The recursive layer. References other blocks by id; emits projected rows in any target shape (typically spine).
Block · identity
Public keys
memeroot://block/identity/v1
ECDSA P-256 public keys. Fingerprint + role + validity window. Private keys never appear; they live in keychain/HSM.
Block · address
Content addresses
memeroot://block/address/v1
sha256 → location bindings. Hash is the identity; location is a mutable pointer. Object store / lake integration lookup.
Each kind's XML schema is minimal and stable. Compliance to a block's shape is checkable by namespace plus element name. The substrate's validator is small because the rules are few: each kind has its own namespace, its own permitted elements, and its own projector. There is no central registry of cross-references because there are no cross-references.
Section 03The spine · universal absorber
The spine is TABLE_SPECIFICATIONS. It is the universal absorbing and projecting layer. Any block kind projects to it; from spine rows, any block kind can be partially reconstructed (the parts that survive the projection). The spine is itself a view, not a table. It is computed by UNION across the per-kind projections — federated, never stored.
The canonical row shape
Mirroring the production MBI_SCRIPT_AS_TABLE_SPEC_V SQL view exactly, the spine row carries thirty-some columns spanning source identity, target binding, process hints, view projection, origin, and kind-specific extensions:
-- source identity: where the content originated
source-owner -- e.g. OPS_DW, OWNER_MBI, IDENTITY, ADDRESS
source-name -- entity name
source-attribute -- attribute / column / parameter / step name
source-datatype -- declared type
-- target binding: where the projection lands
target-owner target-name target-prefix
target-attribute target-function target-id
index-type target-null target-datatype
target-default
-- process hints: how this row participates in resolution
aggregate filter-flag condition join-condition
-- view projection
view-owner view-filter view-prefix
-- origin: which block kind contributed this row
spec-source -- data | schema | script | process | type | view | identity | address
-- extensions: kind-specific carry-through fields
ext-category ext-object-type ext-script-name
ext-sequence ext-is-loop ext-loop-delimiter
ext-indent-level ext-condition-token
Why this shape
The shape is wide enough to carry every block kind's essential content (the wide columns), but narrow enough to be queried efficiently as columns (every consumer can pick what it needs). The shape is not a compromise; it is the universal combinator for the addressable space. Every block kind has a faithful projection into it. Every projection from it back to a block kind preserves what was projectable.
The information that doesn't survive a roundtrip — block-internal formatting, parent-child element nesting, attribute ordering — is also the information that shouldn't matter for the substrate's purposes. The substrate cares about addressable values; presentational structure lives in the render XSLs, not in the spine.
Lineage
This shape is directly imported from twenty-five years of production deployment as TABLE_SPECIFICATIONS in the MBI generative data architecture framework. The production deployments include Aviva, Marsh, ABN AMRO, Sanofi, Smith & Nephew, SEB, Cembra, Greene King. The Smith & Nephew engagement alone replaced 1,389 FTE-days of manual data work. The shape is not invented; it is observed-to-work at industrial scale.
Section 04Per-kind projection · XSL pattern
Each block kind has its own XSL stylesheet that projects it into spine rows. The stylesheets are pure transformations: they read input XML (in the block's namespace) and emit output XML (in the spine namespace). No side effects, no shared state, no cross-block references. Each stylesheet can run in isolation against its block — MPP-friendly by construction.
The eight projectors
| Stylesheet | Input namespace | Output |
xsl/as-table-spec-data.xsl | memeroot://block/data/v1 | 1 spine row per <v> element |
xsl/as-table-spec-schema.xsl | memeroot://block/schema/v1 | 1 spine row per <spec> element · identity projection |
xsl/as-table-spec-script.xsl | memeroot://block/script/v1 | 1 HC row per script line + 1 row per contract param |
xsl/as-table-spec-process.xsl | memeroot://block/process/v1 | 1 spine row per dispatch step |
xsl/as-table-spec-type.xsl | memeroot://block/type/v1 | 1 spine row per type definition |
xsl/as-table-spec-view.xsl | memeroot://block/view/v1 | 1 row per input, 1 per select-attribute, 1 per where-clause |
xsl/as-table-spec-identity.xsl | memeroot://block/identity/v1 | 1 spine row per identity declaration |
xsl/as-table-spec-address.xsl | memeroot://block/address/v1 | 1 spine row per (hash, location) pair |
The pattern of one projector
The schema projector is the simplest — it's the identity transform, because schema blocks are already in spine shape:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:sch="memeroot://block/schema/v1"
xmlns:s="memeroot://spine/v1">
<xsl:template match="/">
<s:spine-rows from-block="schema">
<xsl:apply-templates select="sch:schema-block/sch:specifications/sch:spec"/>
</s:spine-rows>
</xsl:template>
<xsl:template match="sch:spec">
<s:row spec-source="schema">
<xsl:copy-of select="@*"/>
</s:row>
</xsl:template>
</xsl:stylesheet>
The script projector is the most substantive — it mirrors the production MBI_SCRIPT_AS_TABLE_SPEC_V view's HC-row-plus-structure-row pattern. Each line of the script template becomes a row whose target-function carries the line text and whose filter-flag distinguishes loop lines (L) from single lines (S). The contract parameters become additional rows with filter-flag='p'. All in the same spine table, queryable through the same SQL surface.
Section 05Composition & compilation
A composition document lists the blocks that participate in a unit. The compiler reads the composition, applies each block's projector independently (parallelisable), assembles the projected rows, and emits the unified spine plus a rendered surface. The unit is the deliverable — typically a zip carrying the source blocks, the XSL stylesheets, the compiled spine, and the rendered HTML.
Composition shape
<composition id="COMPOSITION-CUSTOMER-CHURN-2026Q2">
<imports>
<import kind="data" id="DATA-ACCT-SAMPLE-001" path="../blocks/data-example.xml"/>
<import kind="schema" id="SCHEMA-CUSTOMER-001" path="../blocks/schema-example.xml"/>
<import kind="script" id="SCRIPT-CREATE-TRANS-VIEW" path="../blocks/script-example.xml"/>
<!-- ... five more imports ... -->
</imports>
<emit>
<target name="spine" format="xml" xsl="../spine/table-specifications.xsl"/>
<target name="surface" format="html" xsl="render-composition.xsl"/>
<target name="archive" format="zip"/>
</emit>
</composition>
Compilation
The compiler is pure Node.js (no runtime dependencies beyond jsdom for DOM parsing). It iterates the imports, projects each block via the appropriate XSL, assembles the rows, emits the unified spine. Compilation of the example composition produces:
$ node composition/compile.js
compiling COMPOSITION-CUSTOMER-CHURN-2026Q2
8 imported blocks · projecting each in parallel-ready isolation
✓ data:DATA-ACCT-SAMPLE-001 · 8 spine rows · hash 8b3e7b3cc85f…
✓ schema:SCHEMA-CUSTOMER-001 · 4 spine rows · hash 2613f704330d…
✓ script:SCRIPT-CREATE-TRANS-VIEW · 9 spine rows · hash 38ed3edd3945…
✓ process:PROCESS-DAILY-FEATURE-LOAD · 4 spine rows · hash ae89cdafea97…
✓ type:TYPE-CANONICAL-001 · 5 spine rows · hash 54b6118c822e…
✓ view:VIEW-CUSTOMER-CHURNED-001 · 6 spine rows · hash 3da81cb1ee92…
✓ identity:IDENTITY-FOUNDER-001 · 2 spine rows · hash 07fe33e82dec…
✓ address:ADDRESS-CATALOG-ENTRIES-001 · 5 spine rows · hash 3bdbcdb8eac2…
spine: 43 rows from 8 blocks
Forty-three rows across eight blocks — a complete addressable space for the customer-churn-2026Q2 unit, queryable through the spine, every value content-hashed, every block independently signable.
Section 06Self-describing recursion
The substrate is self-describing. The schema block describes the spine shape; the spine projects the schema block via the schema projector; the spine is a view, computed from blocks that include the schema block describing the spine. The recursion is operationally fine because the spine is computed, not stored. Every invocation recomputes from sources; there is no eager-evaluation fixed-point problem.
The recursion in pictures
SOURCE BLOCKS (independent, no crossover)
data schema script process
│ │ │ │
│ │ │ │
type view identity address
│ │ │ │
│ ▼ │ │
│ [view-block can reference any of the others]
│ │ │ │
▼ ▼ ▼ ▼
Per-kind XSL projection
(8 independent transformations)
│
▼
TABLE_SPECIFICATIONS spine
(computed view, not stored)
│
▼
Downstream consumers
render · execute · audit · sign · bundle · query · MPP dispatch
The recursion in practice
When a view-block declares its inputs as references to other blocks (<input kind="schema" id-ref="..."/>), it does not embed those blocks. The composition compiler resolves the references at compile time by looking them up in the imports list. The view's projection becomes additional spine rows; the schema block independently contributes its own spine rows; the spine carries both, distinguishable by origin-block.
The recursion stays bounded because blocks never embed blocks. A view can reference twenty other blocks, but it never carries any of them inline. The recursion-depth of the substrate is the depth of the composition's import graph, which is shallow by construction.
The connection to the production view
The Oracle production view MBI_SCRIPT_AS_TABLE_SPEC_V demonstrates this recursion in SQL form. The view's second half describes itself — each of its own columns is emitted as a row in TABLE_SPECIFICATIONS format. The same view describes other tables (via the first half, the HC rows) and itself (via the second half, the structure rows). Queryable as WHERE target_name = 'MBI_SCRIPT' returns the view's own schema; queryable as WHERE target_name = 'CUSTOMER' returns the customer schema; same query interface, recursively self-aware.
The XML/XSL substrate does the same thing through namespaces. A schema-block can describe the spine's columns. The spine projects the schema-block. The result includes rows describing the spine's columns. The recursion closes.
Section 07MPP & independent processes
Because blocks have zero crossover and each projector is a pure transformation, every block's projection is an independent process. They can run in parallel on different cores, different machines, different physical sites. This is not a parallelisability-friendly architecture; it is a parallelisability-mandatory architecture — there is no shared state to bottleneck against.
The MPP dispatch pattern
A composition with 1,000 blocks compiles via 1,000 independent processes. The compiler dispatches each projection as a bounded session per the principles in MEMEROOT-REF-2026-001: typed input contract (the block's XML), typed output channel (the spine-rows stream), no ambient authority, no persistent script surface (the projector XSL is loaded at dispatch, executed once, disposed). The aggregator collects spine-rows streams; the final spine emerges from the union.
The aggregator's work is trivial — concatenate row streams, sort if needed, emit. The expensive work is the per-block projection; that's where the parallelism lives. For the customer-churn-2026Q2 example, the eight projections take milliseconds total even sequentially; at scale (thousands of blocks per composition), the parallel dispatch becomes the only feasible path.
Dispatch primitives by environment
| Environment | Dispatch primitive | Concurrency model |
| Oracle 26ai | DBMS_PARALLEL_EXECUTE | In-database parallel sessions, ROWID-chunked |
| Node.js | Promise.all with workers | Worker threads, message-passing |
| Bash / Make | make -j N | POSIX process fan-out, file-based outputs |
| Kubernetes | Job parallelism | Pod-per-block, parallelism declared in spec |
| Federated | HTTP fan-out + sign-on-receipt | Each publisher signs their projection independently |
The substrate doesn't pick a dispatch primitive; it provides the structural property that makes any dispatch primitive applicable. Blocks compose because they're independent. Federation across publishers is the limiting case of MPP across cores.
Section 08The deliverable · zip structure
The composable substrate ships as a single zip. Inside: the eight block examples, the sixteen XSL stylesheets (eight render + eight projector), the spine definition, the composition document, the compiler, the compiled output, and this architectural reference document. Everything is text; everything is portable; nothing requires a runtime beyond Node and a browser.
Zip contents
memeroot-composable-substrate/
├── README.md
├── reference.html # this document
├── blocks/
│ ├── data-example.xml
│ ├── schema-example.xml
│ ├── script-example.xml
│ ├── process-example.xml
│ ├── type-example.xml
│ ├── view-example.xml
│ ├── identity-example.xml
│ └── address-example.xml
├── xsl/
│ ├── as-table-spec-data.xsl
│ ├── as-table-spec-schema.xsl
│ ├── as-table-spec-script.xsl
│ ├── as-table-spec-process.xsl
│ ├── as-table-spec-type.xsl
│ ├── as-table-spec-view.xsl
│ ├── as-table-spec-identity.xsl
│ └── as-table-spec-address.xsl
├── spine/
│ ├── table-specifications.xsl # universal absorbing stylesheet
│ └── projection-shape.xml # canonical row shape declaration
└── composition/
├── composition.xml # the unit definition
├── compile.js # the dispatcher
└── compiled-unit.spine.xml # output: 43 spine rows from 8 blocks
Use cases
- Domain modelling: define new block kinds following the same pattern; ship as additional namespace + projector; consumers ingest and the spine widens
- Federated catalogs: each publisher ships their own block set; the curator's composition imports across publishers; the curator's compile produces a spine that's federated by construction
- Audit packets: a regulatory submission is a composition: control blocks (schema-shaped) + evidence blocks (data-shaped) + sign-off blocks (identity-shaped) + provenance blocks (address-shaped); the spine renders the auditor's view
- Translation layers: a script block holds the template, a process block holds the orchestration, a type block holds the validations; the spine generates the actual SQL DDL/DML on demand, never persisting the generated artifact
- Substrate migration: blocks signed today verify in 2050; the namespace URIs are stable forever; the XSL stylesheets are pure text; nothing in the substrate depends on any particular vendor's continued existence
What this is
This document is itself an artifact of the substrate. The blocks-and-spine pattern it describes is the pattern by which it could be authored, signed, and shipped within the substrate it defines. The recursion closes here too. The work of the next quarters is to ship the production materialisations: the canvas features that render block kinds, the Claude Code skills that author them, the catalog entries that publish them, the cross-publisher federation that demonstrates the trust topology. The architecture is settled; the materialisation is the work.