Onboarding an SME client with its own instance

This page is the SME path. An SME client gets its own Memex instance, running in its own subscription inside the shared MeshWeaver Customers tenant. Systemorph builds it and operates it. The client signs in to its portal and asks for nothing else. An enterprise client, one with a directory of its own, follows Onboarding.md instead.

The fleet statement behind both paths is Systemorph/Memex docs/client-tenancy.md. Where this page and that one disagree, that page wins.

Three rules first

  1. We host none of the client's data. The Postgres server and its databases, the backups, the file shares behind the content, attachments, users and data claims, and the Key Vault all live in the client's subscription. None of it goes on a Systemorph resource: not memexaks-pg, not the Systemorph vault, not memexaks-cluster or its node resource group. The pearl trial on the Systemorph cluster predates this rule and is not a model.
  2. Everything is steered from memex.systemorph.com. The client's estate is changed only by a Hosting/InstanceAction there, approved in the mesh. memex dispatches the client config repository's aks-ops.yml through the systemorph-com App. There is no client control instance, no operator Job and no human access to the cluster.
  3. The client has no access to Azure. It gets no role on the subscription and no role in the tenant. Its users sign in to their own portal, and that is the whole surface.

The tenancy model

SME client (this page) Enterprise client (Onboarding.md)
Directory the shared MeshWeaver Customers tenant, 93c60c29-6a77-4832-ab81-3400fce42b59 a tenant of its own
Subscription its own, in the shared tenant, on Systemorph's billing profile its own, in its tenant
Who has access to the subscription and the tenant Systemorph only; the shared tenant's Global Administrators are Roland Bürgi and Robert Salzmann Systemorph while building; the client may get admin rights
Who operates it Systemorph, from memex.systemorph.com the same
Hand-over none by default the client can take the tenant over
First client Pearl Technology: subscription Pearl Technology Memex, not created yet (two alias attempts on 2026-09-15 produced no subscription; see step 1) PartnerRe

What Systemorph runs, in order

Every step is Systemorph's. Steps 1 and 2 are done by a person with rights on the billing account and the shared tenant. After that, the lanes and memex.systemorph.com do the work.

1. The subscription, in the shared tenant

The Azure portal only creates a subscription in the tenant you are signed in to. So the subscription comes from the billing side through the alias API, homed in the shared tenant.

First, know what happened on Pearl's run of 2026-09-15:

So confirm the billing account lists the new subscription before you accept it. If it does not, stop: another alias only adds another empty one. Ask for the associated-billing-tenant route or a Microsoft support case instead. Read the policy first anyway:

az rest --method get --url "https://management.azure.com/providers/Microsoft.Subscription/policies/default?api-version=2021-10-01"

Then create the subscription, signed in to the billing tenant. The owner must be an object id in the shared tenant:

az rest --method put \
  --url "https://management.azure.com/providers/Microsoft.Subscription/aliases/<alias>?api-version=2021-10-01" \
  --body '{"properties":{"displayName":"<Client> Memex","workload":"Production",
    "billingScope":"/providers/Microsoft.Billing/billingAccounts/<account>/billingProfiles/<profile>/invoiceSections/<section>",
    "additionalProperties":{"subscriptionTenantId":"93c60c29-6a77-4832-ab81-3400fce42b59","subscriptionOwnerId":"<owner object id in the shared tenant>"}}}'

Accept ownership, signed in to the shared tenant (az login --tenant 93c60c29-6a77-4832-ab81-3400fce42b59):

az rest --method post \
  --url "https://management.azure.com/providers/Microsoft.Subscription/subscriptions/<subscription id>/acceptOwnership?api-version=2021-10-01" \
  --body '{"properties":{"displayName":"<Client> Memex"}}'
az rest --method get \
  --url "https://management.azure.com/providers/Microsoft.Subscription/subscriptions/<subscription id>/acceptOwnershipStatus?api-version=2021-10-01"

The status reaches Completed and the subscription reads Enabled. Do not try to move an existing subscription into the tenant: policy writes answered 200 and changed nothing, and changeTenantRequest answered 403 or 404.

Then register the resource providers and request quota, exactly as in Onboarding.md Part A.

2. The estate, from the lanes

The client's config repository carries the lanes, shaped like Systemorph/PartnerRe.Memex. Whether each SME client gets its own repository or all share one is still open.

  1. infra/bootstrap-oidc.sh <subscription id>, signed in to the shared tenant, creates three things:
    • the CI app, federated to main and the infra environment only;
    • the infra, aks-ops and aks-ops-prod environments, each deployable from main only;
    • the three repository secrets Infra deploy reads.
  2. Infra deploy, dispatched as systemorph-com[bot], what-if first and then deploy. It creates the whole estate in the client's subscription:
    • the private cluster;
    • Postgres with its own backups;
    • the Azure Files account behind the claims;
    • the Key Vault;
    • the portal identity;
    • hosting-operator, federated to aks-ops and aks-ops-prod and to nothing else.
  3. The in-VNet runner set for the operations lane, registered to the Systemorph organisation for this repository only.

The lane's prerequisites and what must never exist are in Onboarding.mdOperations lane prerequisites.

3. The record, in memex

The instance is a Hosting/Deployment record in memex.systemorph.com's Deployments space. It has:

Where the file is authored is still open: the config repository, synced into memex, or memex itself.

4. The sign-in app, invitation-only

Register the portal's sign-in app in the shared tenant, multi-tenant, so the client's users sign in with their own work accounts. Set Features__Onboarding__InvitationOnly: "true" on the record. Invitation-only is what keeps the portal closed, not the app's audience. The client secret goes into the client's vault, by name on the record, never as a value.

5. The instance key and the vault objects

Register the instance at the plugin registry. The mwi_ key is returned once and stored in the client's vault. The master key and the connection string are minted into the same vault by the lane. The objects and their names are those in Onboarding.md §7 and §8.

6. Provision, approved in the mesh

Create a Provision action on memex.systemorph.com for the record, dry run first. After the approval, memex dispatches the client repository's aks-ops.yml. Its mutate lane creates the namespace, the claims on the client's file shares, the database on the client's server, the portal, the ingress and the certificate.

7. Invite, then verify

Invite the users the client named, and make the named administrators portal administrators. Run Onboarding.md §12, then add one more check. Every claim must be bound to a share in the client's subscription, and the database must be on the client's server.

What the client is asked for

What the client never gets

Not built yet

These gaps are shared with the enterprise path. Until they close, a client estate cannot be provisioned from memex end to end:

Reconnecting…
The connection to the server was interrupted. Trying to restore it…
Trying again…
The connection could not be restored. Reloading the page…
The server was updated. Reloading the page to pick up the latest version.