The disaster-recovery plan had one quiet assumption: somewhere, a copy of the software still existed.
Perhaps the source repository survived. Perhaps a container registry held an immutable image, a release server retained the binary, or another region still ran an identical replica. The database might need restoring and the traffic might need rerouting, but the executable truth of the service was expected to be waiting somewhere.
Remove that assumption and ordinary recovery changes character.
Imagine that the source, binary and deployable image have all disappeared from the relevant failure domain. The service’s state may survive in backups. Its interface contracts, signed policies and protocol traces may survive elsewhere. Operators may know what requests it accepted and which transitions it was forbidden to make. They have evidence of meaning, but no artefact to restart.
Can that surviving meaning be enough to regrow useful function?
That question became Anasemble, an open-source Rust disaster-recovery control plane. It reconstructs a narrowly bounded service component from independently retained semantic evidence, checks the candidate through a separate implementation, restores associated state and activates an immutable replacement only after operator approval.
The important part is not that Anasemble sometimes says yes. It is that uncertainty, inconsistency and unsupported infrastructure all produce an explicit no.
Backups preserve data, not necessarily behaviour
Backups are indispensable, but a database dump does not explain the program that made the database meaningful.
Consider a small stateful service. Its stored value might say locked, open or alarm. Without the program, that state does not tell us which inputs are valid, which transitions are allowed, which side effects must happen, or what must never happen. A protocol trace adds evidence, but a few observed requests do not define every possible behaviour. An interface schema describes shape, not intent.
Anasemble therefore does not treat any one surviving source as the lost component. It collects several kinds of evidence before disaster:
- signed service and transition contracts;
- positive, negative and metamorphic protocol obligations;
- traces retained outside the artefact’s failure domain;
- state snapshots with identity, length and integrity bindings;
- effect, resource and compatibility policies; and
- operator and evidence-store identities with rotation and revocation rules.
These fragments are not a clever substitute for source control. They are a second recovery path for a declared total-artefact-loss case. If a normal binary, image, replica or native backup satisfies the recovery objective, operators should use it.
The distinction matters because semantic evidence is incomplete by design. It should justify one bounded candidate or justify refusal. It should never be promoted into a claim that arbitrary software can be recovered from observation alone.
Reconstruction had to be finite
The tempting version of this idea is also the dangerous one: ask an unconstrained generator to write a replacement service, run a few tests and hope for the best.
Anasemble takes the opposite approach. Its reconstruction kernel searches a finite, typed grammar. The current candidate is an inspectable finite-state component, not a general-purpose HTTP server. Search time, candidate count, memory, execution fuel and output size are all bounded. Missing semantics do not become creative freedom.
The core path looks like this:
independent evidence
|
v
collect, authenticate and canonicalise
|
v
search a finite typed grammar
|
v
untrusted candidate
|
v
independent held-out checker
|
+---- disagreement or exhaustion ----> refusal
|
v
certificate bound to evidence and identity
Determinism is an operational property here. Given the same canonical inputs and budgets, the control plane must produce the same candidate, certificate or refusal. That makes a recovery replayable and gives investigators something stronger than a log saying that an opaque model once seemed confident.
The candidate also crosses a capability-empty WebAssembly boundary. Generated modules have no imports and execute under fuel, memory, table and instance limits. WebAssembly is not treated as a magic sandbox. The host, runtime and embedding policy remain trusted, and the project says so in its trusted-computing-base ledger. The point is to make ambient authority absent and resource use explicit.
The checker cannot share the candidate’s mistakes
Generating a plausible candidate is not the same as certifying it.
One of Anasemble’s central invariants is that the synthesiser and checker do not share an interpreter. A candidate crosses a private binary wire format and is evaluated by a separate implementation against held-out obligations. The checker binds its result to the exact candidate identity, evidence set, service manifest and resource policy.
That separation protects against a subtle failure mode. If generation and verification reuse the same parser or execution semantics, one bug can make a wrong program and then approve the same wrong program. Two calls to the same code are not independent assurance.
The checker exercises more than happy paths. Negative obligations describe actions that must be rejected. Metamorphic obligations describe relationships that must remain true when inputs change. Held-out traces constrain overfitting because they are unavailable to the synthesis step. A mutated candidate fails its identity binding even if it looks structurally similar.
There is still no universal proof hiding inside the certificate. It says that one exact candidate satisfied one exact evidence set under declared semantics and budgets. If the evidence is poisoned by correlated administrators, if the checker host is compromised, or if required behaviour lies outside the finite grammar, the guarantee does not expand to cover it.
This is why refusal remains a first-class result. A contradictory transition, a stale fragment, an exhausted search budget, a missing copy quorum or a checker disagreement ends the attempt before activation.
State made the research question real
The early reconstruction kernel could recover behaviour and issue a certificate. That proved the concept, but it did not recover a service.
A useful disaster-recovery system has to bring state back without destroying the last good copy. It has to cope with interruption, preserve rollback, avoid mixing identities and distinguish a prepared restore from an accepted recovery.
Anasemble now has bounded adapters for filesystem state, PostgreSQL, S3-compatible object storage and Redis Streams. Each adapter follows the same broad discipline:
- capture or retrieve a versioned snapshot before the disaster;
- verify service identity, integrity, length and revision before mutation;
- prepare a migration plan bound to the certified candidate;
- restore into a staged destination while retaining the prior state;
- issue a receipt for the exact restored result; and
- keep rollback material until the operator explicitly accepts the recovery.
The details differ because the backends are not interchangeable. PostgreSQL needs authenticated connections, consistent snapshots and quiesced writers. S3 restoration must bound both object bodies and listings. Redis Streams must preserve stream identity and entry ordering. The project does not pretend that these separate systems form one distributed transaction. A coordinated recovery can still encounter partial failure, so every stage retains enough evidence to reverse what it changed.
Remote transports were another boundary that could not remain implicit. PostgreSQL and Redis require authenticated TLS and DNS identity. Production S3-compatible endpoints require HTTPS. Connection, operation and body-size limits are enforced before remote state can exceed the recovery budget. Short-lived S3 credentials reduce the lifetime of authority carried into the operation.
The result is less elegant than a single restore() abstraction. It is also more honest.
Activation is a transaction with a human boundary
A certified binary and restored state are still not a live service.
Anasemble publishes the candidate as a plan-bound OCI artefact. The digest, candidate identity and activation plan travel together. Docker provides the supported single-host isolation path. Kubernetes provides the orchestrated path: an immutable Deployment is staged behind a zero-egress NetworkPolicy, a Lease serialises work for the service, health checks run in isolation, and one Service selector change switches traffic.
No traffic switch occurs merely because reconstruction completed. An operator signs approval for the exact plan and artefact binding. After activation, the prior workload and restored-state rollback material remain available until the operator chooses one of two outcomes:
- accept, which seals the recovery receipt and retires rollback resources; or
- roll back, which restores the prior workload and the previous PostgreSQL, object and stream state.
This lifecycle is deliberately restart-safe. Recovery jobs live in a bounded, file-backed operations store with atomic records, expiring execution leases, immutable results and hash-chained events. A runner releases the store lock while doing expensive reconstruction, then reacquires it to commit the result. Queue capacity, batches, attempts, record size and total job count are fixed rather than left to grow with an incident.
The operational consequence is important. Killing the command midway should not create a second, ambiguous recovery when it restarts. The same plan can be reconciled idempotently, while a conflicting plan is refused.
Support is an evidence claim
One of the most instructive parts of building Anasemble was discovering that implementation, testing and support are different facts.
A Kubernetes adapter can exist without every Kubernetes environment being safe to operate. A Linux binary can compile under emulation without proving a production host. An S3-compatible API can pass against MinIO without establishing the behaviour of every object-storage provider.
The compatibility contract therefore records three separate dimensions for every profile: whether the path is implemented, whether retained evidence exercises the exact combination, and whether maintainers support it.
The first release candidate supports deliberately narrow profiles. They include macOS arm64 local operation, exact Amazon Linux 2023 arm64 and x86_64 instances, RDS PostgreSQL 18.3, S3 and ElastiCache Redis 7.1 in eu-west-1, and an EKS 1.36 profile with a specific VPC CNI build and strict NetworkPolicy enforcement. Generic Linux, other Kubernetes providers and unqualified remote-state combinations remain experimental.
That narrowness is not a missing marketing pass. It is the consequence of making support follow retained destructive evidence.
The AWS qualification used short-lived, tagged resources to exercise native arm64 and x86_64 control planes, authenticated managed-state restore and rollback, and EKS network-policy enforcement. The resources were torn down after the drills. Locally, the authoritative CI path creates disposable PostgreSQL, MinIO, Redis, OCI registry and kind fixtures, deliberately deletes source state, reconstructs the component, restores all three state backends, activates through Kubernetes, then tests rollback and separate acceptance.
An emulated result is labelled emulated. A partially tested CNI boundary stays experimental. An unlisted combination is not inferred from independently supported rows.
Productising the refusal path
The distance from a research kernel to a usable recovery product was not filled by adding a dashboard.
It required installation into immutable prefixes, exact uninstallation, configuration migration, a disaster runbook, redacted support bundles, bounded scheduling, recovery metrics and a compatibility manifest that a tool can consume. It required a security policy, contribution and governance documents, dependency licence checks, pinned release actions and a public CI subset that is safe to run on forks.
It also required a visual language that could explain the system without disguising its limits. The Semantic Fit mark is made from three fragments around an open interface. It represents the central claim: separately retained pieces can fit well enough to recover a bounded function, but only when their semantics agree. The orange interruption in the mark preserves the possibility of refusal.
That design principle runs through the implementation. Anasemble does not report success when it merely found a candidate. It reports success only after collection, synthesis, independent certification, state restoration, isolated staging, signed approval and a recorded operator decision agree on the same identities.
Every hand-off is a place to stop.
What the first release proves, and what it does not
Anasemble v0.1.0-rc.1 is available as an Apache 2.0 Rust crate and as Linux arm64 and x86_64 release archives with checksums and provenance records. The public repository contains the architecture, compatibility contract, threat model, disaster runbook, destructive reference workflow and retained evidence behind its supported profiles.
The release demonstrates a production-shaped path from independently retained semantic evidence to an operator-controlled recovery for those exact profiles. It can reconstruct its finite-state service contract, certify an import-free WebAssembly candidate, restore several kinds of state, publish an immutable OCI artefact and switch or reverse a supported deployment.
It does not reconstruct arbitrary programs. It does not generate a live general-purpose HTTP server. It does not replace source control, native backups, replication, point-in-time recovery, object versioning or queue durability. Docker, Kubernetes, the host kernel, the OCI registry, configured identities and the independent checker remain part of the trusted base. External security review and independent reproduction are useful post-release assurance, not claims already earned by the repository.
Those limitations leave substantial work for future releases, but they do not make the current result trivial. Disaster recovery usually asks how to preserve an artefact. Anasemble asks a stranger question: how much separately preserved meaning is required before function can be recreated safely?
The answer is not “as much as possible”. It is a bounded contract, independent evidence, a separate checker, reversible state and an operator who still has the power to say no.
That is what survived when the artefact did not.
Anasemble is open source on GitHub. The most useful next step is to read the compatibility contract, run the integrated evaluation in disposable infrastructure and test whether the evidence boundaries deserve your trust.