Skip to main content
Tokenization operating system

Real-world assets, issued and serviced like institutional instruments.

Structure an asset, publish a compliance policy, run the book, issue to a register, release proceeds through a double-entry ledger, and service the instrument for its whole life — in one system, inside one transaction boundary.

67 asset classes across 8 groups · permissioned token standards · maker-checker on every irreversible action

The platform, from asset to registerFour stages stacked vertically — asset, compliance policy, offering book and register — enclosed by a single transaction boundary and resting on a double-entry ledger.One transaction boundaryAssetStructured, documented, valuedCompliance policyIn force, versioned, replayableOffering bookDerived, never a cached totalRegisterHolders of record, rebuildableDouble-entry ledgerBoth sides of every movement, in minor unitsRefused at COMMIT if the debits and credits disagree — by the database, not by a check.
67Asset classes modelledEach with its own template, token standard and readiness requirements.
3Independent isolation layersSchema, client and database row-level security, failing independently.
2×Invariants enforced twiceOnce in the application, once by the database, with two failure modes.
1,103Automated testsIncluding a Solidity suite executing against a real EVM.
The problem

Most tokenization fails after the token is issued.

Issuance is the easy part. What breaks is everything afterwards: a register that disagrees with the cap table, a distribution that does not sum, a compliance decision nobody can reconstruct, and money that cannot be matched to the subscription it paid for.

Registers that driftA spreadsheet, a transfer agent's book and a chain explorer, reconciled quarterly by somebody who is not sure which is right.
Servicing done by handDistributions computed in a spreadsheet leave the issuer a few minor units out every cycle, and the difference is money belonging to nobody.
Compliance you cannot replayAsked why an investor was admitted two years ago, most platforms can show today's rules rather than the ones that actually applied.
Money that arrives unattachedA credit with no usable reference sits in a suspense account nobody is chasing, or worse, is guessed onto the wrong subscription.
How it works

One path, from a structured asset to a serviced instrument.

Each step refuses to proceed on facts the next step depends on. That is the design: an offering cannot open without a policy in force, and units cannot be issued against an allocation that has not settled.

  1. Structure the assetChoose from 67 asset classes, record the legal vehicle, appoint the parties and assemble the data room. Readiness is derived from what has actually been recorded, not from a checklist somebody ticks.
  2. Publish a compliance policyEligibility is a rule set over a closed vocabulary of investor attributes, reviewable as data and never evaluated as code. A workspace with no published policy admits nobody.
  3. Open the offeringSubscriptions are checked against the terms first and the policy second, and only then is a payment reference issued — telling somebody ineligible where to send funds manufactures a refund obligation out of nothing.
  4. Allocate and issueAn oversubscribed book is accepted and scaled back deterministically, rounded down to whole units with the residual returned. Units reach the register before the issuer is paid for them.
  5. Service for the instrument’s lifeDistributions to holders of record, corporate actions that rewrite the register under a previewed plan, and redemptions that burn units and recognise the payable in one transaction.
How the platform is arrangedFour stages — asset, compliance, offering and register — connected left to right, all enclosed by a single transaction boundary that rests on a double-entry ledger.AssetStructured and documentedCompliancePolicy in forceOfferingA book that is derivedRegisterHolders of recordOne transaction boundaryA movement and the entries behind it commit together, or neither doesDouble-entry ledgerEvery movement, both sides, in minor unitsBalanced at COMMIT
The same four stages, arranged as the system arranges them. What distinguishes this from the diagram every platform in this category draws is the bracket: the four sit inside one transaction boundary, on one ledger, so a register that disagrees with the cash is not a state the software can reach.
The mechanisms

Three drawings that describe how it actually behaves.

Not an architecture poster. Each of these is a mechanism you can find in the product, and the last one shows what is missing as plainly as what is there.

One gate, evaluated identically on both sides

Before any unit moves, canTransfer evaluates the sender, the recipient, the instrument and the amount together. The function that answers it is the same one that mirrors the Solidity compliance module check for check — so an off-chain gate and an on-chain gate cannot drift apart, because there is only one.

A refusal is a state to act on rather than a message that vanishes. Lockups expire and freezes are lifted, so a refused transfer stays re-checkable.

The transfer gateA transfer request passes through eight compliance checks. Any single failure refuses the transfer; the same gate is evaluated off-chain and on-chain.Senderholds unitscanTransfer( )Sender holds the unitsNeither party frozenLockup expiredRecipient eligible under policyJurisdiction permittedInvestor type permittedHolding limit not breachedSanctions screening clearRecipientunits move, or none doOne implementation. The Solidity module and the register evaluate the same rules.
Eight checks, evaluated as one decision. An absent fact never satisfies a rule — not knowing whether verification is valid is refused, not permitted.
The payment railMoney is matched to a subscription by its reference and no other attribute, then screened and settled. Provider adapters for card and crypto rails are not built, and are drawn as an absent component.ReferencechecksummedFunds arrivebank or custodyReconcilereference or nothingScreenAMLSettlesecond authoriserSuspense (2900)unidentified, and visibleNo reference matchProvider adaptersCard, local rail, stablecoinNot built — the registry ships empty
Money is matched to a subscription by its reference and by nothing else. An unmatched credit posts to suspense where it stays visible, rather than being applied to the nearest plausible payment.

A reference, or an exception for a person

Matching on amount and date “when it is obvious” is how one investor’s subscription money gets credited to another and discovered months later, once tokens have been issued against it. Under- and overpayments are exceptions, never part-applied.

The dashed box is deliberate. No card, local-rail or stablecoin provider adapter is connected in this build, and every surface that offers one says so with the reason.

Isolation that fails three separate ways

A tenant’s data is separated in the schema, in the query client and by the database’s own row-level security. Each layer is sufficient alone, which is the only reason to run three: a defect in one is contained by the others.

The database layer is not theoretical. With no tenant context the application role reads zero rows, and a cross-tenant insert is refused by Postgres — both verified running against the deployed database rather than asserted here.

Three independent isolation layersTenant isolation is enforced in the schema, in the query client and in the database's row-level security. Each is sufficient on its own and each fails differently.SchemaEvery owned row carries its tenantA query that forgets the column does not compileClientQueries are rewritten, not trustedtenantDb(context) is the only read pathDatabaseRow-level security, verified runningThe app role cannot read across tenants at allA defect in one layer is contained by the other two — which is the only reason to have three.
The application connects as a role without row-level-security bypass. Connecting as the database owner would leave every isolation policy silently doing nothing.
Why it holds together

A status and the entries behind it cannot disagree.

Every movement that touches money posts to a double-entry ledger in the same database transaction as the state change that caused it. If the posting fails, the status change rolls back with it.

Investor money is a liabilityFrom the moment it arrives until an allocation settles, it belongs to the investor — not to the platform and not to the issuer. The balance sheet says so.
Balances are derived, never storedA stored balance is a second source of truth that will eventually disagree with the first, and when it does nobody can tell which is wrong.
Corrections are reversalsLedger entries and audit events are append-only, enforced by revoked grants and database triggers rather than by convention.
Two authorisers, bound to the figuresSettlement, issuance, distributions and role changes each need a second signature, and the approval binds to a hash of exactly what was approved.
The audit chainEach audit event stores a hash of its predecessor, so removing or altering one breaks every hash after it.seq 1prevHashseq 2prevHashseq 3prevHashseq 4prevHashAppend-only in the database as well as the application: the app role holds no UPDATE or DELETE on this table.Verified running — a DELETE is refused by Postgres, not merely by code.
Each audit event stores a hash of its predecessor. Altering one breaks every hash after it — and the application's database role holds no UPDATE or DELETE on the table, so the chain cannot be quietly rewritten either.
Status

Integrations and rails.

§57 of our own specification forbids a mocked capability that looks finished. This table is asked of the running process rather than written down, so it stops saying a provider is missing the moment one is connected.

Object storageConnected

The data room stores documents with a content hash verified on every read, so what an investor reads is provably what was filed.

Payment providerNot connected

Subscriptions can be recorded and reconciled against a bank statement, but no payment is initiated from here.

Identity verification providerNot connected

Verification cases can be opened, decided and evidenced by a person; nothing is checked automatically against an external register.

Blockchain signerNot connected

A deployment plan is produced with preflight checks and an approval gate, and the broadcast step reports that it cannot sign rather than appearing to succeed.

Notification deliveryNot connected

In-app notifications are written to this system’s own database. Email, SMS and webhook have a port and no adapter, and say so per channel.

Model providerNot connected

Assistants report unavailable with the reason rather than degrading into keyword matching presented as intelligence.

Assurance still outstanding

These are launch gates in our own specification and none of them has been satisfied. They are listed because their absence is not visible from any screen.

  • An external smart-contract audit
  • A penetration test
  • A disaster-recovery rehearsal against a real restore
  • A load test at the volumes the SLOs assume
  • An independent accessibility audit
A port with no adapter behind itThe platform side is built and the interface is defined. The provider side is an empty dashed outline: no adapter ships in this build, so the call has nowhere to go.PlatformbuiltportProvidernot registeredThe surface reports this, with the reason.It does not fall back to somethingthat looks like it worked.
The shape of every unconnected row: an interface that exists and an adapter that does not. The surface reports it with the reason rather than degrading into something that looks like it worked.

See it against your own asset.

The fastest way to judge infrastructure is to structure something real in it. Bring an instrument you are actually considering and we will walk it through end to end.