Foundations
Superposition & collapse
The uncertainty principle said to keep the where open. This is what keeping it open buys you: a domain can hold many possible contexts at once, and commit to one only at the last possible instant, when a real event arrives.
#Adapters superpose
The principle
Choosing a runtime is usually a build-time, irreversible commitment. But if the domain names no runtime, there is nothing stopping several runtimes from coexisting around it. The choice can be a value carried until execution, not a fork taken during design.
In Stone.js
Stack as many adapters as you like on one Application. Each is a latent context. Working on Node while a Lambda and an edge worker sit in the same manifest is not a special mode; it is the default, because adapters do not exclude one another.
import { StoneApp } from '@stone-js/core'
import { Routing } from '@stone-js/router'
import { NodeHttp } from '@stone-js/node-http-adapter'
import { Fetch } from '@stone-js/fetch-adapter'
import { AwsLambdaHttp } from '@stone-js/aws-lambda-http-adapter'
// Three contexts, superposed on one domain. None is chosen here.
@NodeHttp()
@Fetch()
@AwsLambdaHttp()
@Routing()
@StoneApp({ name: 'tasks' })
export class Application {}import { defineStoneApp } from '@stone-js/core'
import { routerBlueprint } from '@stone-js/router'
import { nodeHttpAdapterBlueprint } from '@stone-js/node-http-adapter'
import { fetchAdapterBlueprint } from '@stone-js/fetch-adapter'
import { awsLambdaHttpAdapterBlueprint } from '@stone-js/aws-lambda-http-adapter'
export const App = defineStoneApp(
{ name: 'tasks' },
[routerBlueprint, nodeHttpAdapterBlueprint, fetchAdapterBlueprint, awsLambdaHttpAdapterBlueprint]
)#Runtime is the collapse
The selection does not happen when you write the code, nor when you build. It happens when a concrete cause reaches a concrete adapter: an HTTP request hits the Node adapter, an invocation reaches the Lambda adapter, a fetch arrives at the edge. That adapter, and only it, collapses the domain into a running application for that one event.
The adapters are the possibilities. The cause that arrives is the measurement. The response is the collapse.
#One artifact, two collapses
Take the manifest above, Node and Lambda stacked, and build it once. The same artifact collapses differently depending only on where it runs:
- Locally: run it and Stone.js resolves the Node adapter at run time; requests collapse onto Node.
- On Lambda: deploy that exact artifact and, at run time there, Stone.js resolves the Lambda adapter; invocations collapse onto Lambda.
Nothing chose between them at build, and deployment only decided where the artifact lives. The collapse is a runtime act, performed freshly wherever the app happens to run.
#Why decoherence lives at the edge
The collapse is confined to the integration dimension, the adapter. Everything inward, the kernel and your domain, only ever sees the result: one normalised intention. The messy business of turning a raw platform cause into a clean intention never propagates into your logic, which is why the same logic survives every collapse.