Skip to main content

Custom Service Provisioning

A custom service uses the standard customer-service and user-service request contract. This gives custom rules the customer or user identity, service metadata, effective service properties, access levels, and—when configured—service package properties.

Event names

Replace <ServiceName> with the internal service name, not its display label.

Event$Customer Service$<ServiceName>$After Provision
Event$Customer Service$<ServiceName>$After Deprovision
Event$User Service$<ServiceName>$After Provision
Event$User Service$<ServiceName>$After Deprovision

The full PreProvision, Provision, PostProvision, PreDeprovision, Deprovision, and PostDeprovision lifecycle is available, with Before, Main, and After rule sets for each phase.

Customer-service request

A customer-service request begins with the base customer properties—from CustomerID through the audit values—and adds:

PropertyShapeDescription
ServicePropertiesHashtableEffective properties for this customer-service instance.
ServiceIDIntegerCustomer-service database identifier.
ServiceNameStringInternal service name used in event paths.
ServiceLabelStringCustomer-facing service label.
ServiceAdminUsersString arrayService administrator accounts.
ServiceObjectIDIntegerProvisioning object identifier for the customer service.
CorrelationIDStringCorrelation value for related service requests.
ServiceAccessLevelsString arrayUser plans assigned to the customer service.
ServicePackageHashtableDefault customer package properties; present only when customer package creation is enabled and a package exists.
ServiceInstanceStringInstance name; present only for a multi-instance service.

CustomerRoles is also added to customer-service provision and deprovision requests. The core-customer-only values such as CustomerProperties, CustomerLevel, and ProxyServiceProperties are not automatically copied to every service request. Proxy service requests add additional Proxy-specific customer values.

User-service request

A user-service request includes the base customer and user properties—through SystemDomain in the user table—then adds:

PropertyShapeDescription
UserServiceObjectIDIntegerProvisioning object identifier for this user-service assignment.
ServicePropertiesHashtableMerged customer-service, user-service, enabled user-plan, and provider-added properties.
ServiceIDIntegerCustomer-service database identifier.
ServiceNameStringInternal service name.
ServiceLabelStringCustomer-facing service label.
ServiceAccessLevelsString arrayEnabled access-level names for the user.
ServicePackageHashtableDefault customer package properties when customer package creation is enabled and a package exists.
ServiceInstanceStringSanitised service instance name for a multi-instance service.
isCopyProcessBooleanPresent and True when the request was generated by a copy process.

The core-user-only values such as top-level UserProperties, SpecificProperties, UserServices, and UserConnectors are not automatically copied to every user-service request. A service can add equivalent values inside ServiceProperties; the MSOL service does this for UserProperties.

The service implementation can add more ServiceProperties. For a user service, CORE builds that hashtable in this order:

  1. customer-service properties;
  2. user-service properties;
  3. properties from enabled user access levels;
  4. values added by the service's customer and user provider classes.

On deprovision, CORE uses access levels that were originally enabled and adds the internal package-deprovision flag. If a customer-service removal caused the user-service removal, the service can also receive isCustomerServiceDeprovision.

Access custom service properties

Assume a custom service defines an ExternalSystemUrl customer-service property and a ProfileCode user-plan property. Both are available through ServiceProperties:

{ServiceProperties}("ExternalSystemUrl")
{ServiceProperties}("ProfileCode")

Example condition:

Not String.IsNullOrEmpty({ServiceProperties}("ExternalSystemUrl")) AndAlso
Not String.IsNullOrEmpty({ServiceProperties}("ProfileCode"))

Choose unique property names. When two sources define the same key, the merged value depends on the merge order and the service implementation.

Access service package properties

Customer package template properties are exposed separately through ServicePackage:

{ServicePackage}("ExternalSku")

Example Powershell Execute script parameter:

& 'C:\AtriaScripts\Set-ExternalPlan.ps1' `
-CustomerId {CustomerID} `
-PlanCode '{ServicePackage}("ExternalSku")'

Add a condition because ServicePackage is optional:

Not {ServicePackage} Is Nothing AndAlso
Not String.IsNullOrEmpty({ServicePackage}("ExternalSku"))
Package selection

ServicePackage contains the default customer package selected for the service. It is not a list of every package and it is not populated for services that do not enable customer package creation.

A practical custom service pattern

For an external SaaS service:

  1. Put tenant creation in Event$Customer Service$<ServiceName>$After Provision.
  2. Store any external tenant reference using an Atria-supported persistence mechanism; a property created only by a rule lasts for the current request path.
  3. Put user assignment in Event$User Service$<ServiceName>$After Provision.
  4. Put user removal before tenant removal in the matching deprovision events.
  5. Make every create/update action safe to repeat because provision events can represent both initial provision and later changes.
  6. Confirm the live property set with a journalled request before enabling the rule in production.

See Rule values and PowerShell actions for substitution and result-property behaviour.