I'm trying to design a new microservice architecture that will eventually replace our current two monolithic APIs (we develop a desktop payroll software that uses our API to send payroll documents to employees or have them sign contracts, and more features and front-ends to come).

There is a lot of complexity regarding users relationships and I'd like to future-proof my design as much as possible.

*Please excuse me if I'm not clear enough, I'm not a native English speaker and there are a lot of fine details :)*

TL;DR
=====

I will give many details below in case you're interested, but here is a summary: 

* I have **many types of actors** who are tied with **chained, business logic relationships** (ex: `Organization > Company > Employee`).
* Most of (maybe all in the future) these actors are candidates for being linked to a web user account. And a user account should be able to act like multiple actors (ex: an account `X` could act as a `Company A`, an `Employee from Company A` and an `Employee from Company B`).

And I hesitate between at least 2 solutions:

1) Creating a microservice per actor type
-----------------------------------------

* This could make sense because each actor have its own business logic (properties, actions).
* But I'm afraid it will generate a lot of inter-services requests for basic actions (ex: `DocumentService` must check if the user account has rights to send `Documents` to an `Employee`, and this permission is defined as a `Company` business logic...).
* Moreover, each microservice should be aware of others business logic, which greatly defeats the microservice philosophy in my opinion.

![Option 1](https://www.plantuml.com/plantuml/img/dLH1JiCm4Bpx5Vv03rnxG8N20GcfXuepCiwI6ZbsP6zI5TI_uxPU7ASEBVYKxDWp4yzk5Xw5mwxHZA523NpLehA6t_0vNndW7bol9F0M71SIhUEuQu4nOolWTnrkrd735-DXsRSFaCYN3Yemg8IEzSDwLLLw5bBQpk2ni6Tx8ZnLYvmHAn2cyylEest0bKr5y6-MxfNMojH5nYVJsrGy8vHHSCIuShKmwbCSxhb8Eznm5VSlzjVs7RV2mOkVk9NXXYanEp1K5Zoiy0xUFqCFUXoBRLfXTkLKJjZ_fPFCOzDgkmCewX0uUQ4d7vSq7gpi6fXeKGAlre1eQXoQget0pfM_P2a2YvhkZCiYW_6SELLlS7PBuyKOpTciibiJ01gR18JYi4KpODXE6H1ppcgKIN14iqcgcK12oMsSF9QDofd-6KecgEb8RM24a52bEETSEX08dlqqKGu74fyVZHdD-V7tEZgOm91pEBW0KuK_y3S0)

2) Creating a generic UserManagement service
--------------------------------------------

* This could also make sense because I feel "actors and users relationships" could be seen as a business logic in itself, and all these actors are tightly coupled.
* My main fear with this option is that this service could become bigger and bigger as we bring features to the web. But then again I could create new microservices for these features and keep using my UserManagementService as a sort of RBAC provider.

![Option 2](https://www.plantuml.com/plantuml/img/dLHDRyCW3BtpA_W3lUpOmzJkup1fKmxLpXCZNif4J0LEgsxgVv_RmW9jibRZ5FpYzspyO1P8UUfQAmGPiY2h5Hc7yaPEPOKW6q3mHilN0Fv5eMgW1IJ9kxNH80Iw6kIye-NY697VGl9oxv-WITvxgFbtesoCxzURgVjlfRNha0w1dTX5mb9ja7f-J1pWPPAyX2wGQy5VLq2UMVb6eVbIX_COoTQH_Hg-XVkWZVAmRswCpsMQmvpxnNi8uHdMO8SwTkrAuVR_4YNTOxkoRWimUWH7kKiZlJFM6cm6P_c4QzS7_pxadl71wMxK7Wcykcg8RPw8B4o3YZeFm_vMp6B6tN5P9BiX4s-Q9KrkaxM5I1wVr6w332Glzm07SviMGEwt0eW6AM9fobnHkZ19jH3eqLHj79uehikP_XcQYaXkJMfP8GdXQ1hdL6eFYY28NrkMC9E4CZNEQ2eFBzr9OW_od3bn1bZpO_W3)

What sounds more like a future-proof, best practice to you?

Do you have any advice or thoughts?

More details
============

Currently, these are the different types of actors in our system:

![Types of actors](https://www.plantuml.com/plantuml/img/XP0n3i8m34LtdyBAte6L0HLLh30W3f0M0q59NCMkgd9w44f4Cp6-hwVlBxUYDkaKF80wzOJxGJa99l9M7KTvk540k7_IeDXDeXme5JwbkutkzJLBTkQRpZRHHNvUns6qSIbu2AFdXGYW5ABP66oQ7PgZgLgto7CKM4ULkxxspyqhifQfCigmh41ByVhvpHi0)

Please note these edge (but nonetheless common) cases:

1. A `Customer` could be an accounting firm and manage payrolls for multiple `Companies`.
2. A `Customer` could be managing its `Company` alone, so all these actors could be one single person. And the Customer could be one of their own `Employees` as well.
3. `Employees`, being artists for the most part, often work for several `Companies` (which could be managed by different `Organizations`).

This is basically how our software works (locally, without APIs):

1. `Customer` pays for their licence.
2. `Customer` provides licence key to create an `Organization` (can create multiple ones).
3. `Customer` creates `SoftwareUsers` inside this `Organization`, with different access levels (which determines which companies/employees one can read/write).
4. `SoftwareUsers` can create `Companies` inside this `Organization` to manage their payroll.
5. `SoftwareUsers` can create `Employees` attached to a single `Company`.
6. `SoftwareUsers` can generate payslips for `Employees`.

Then, these are the web-based features that are implemented by our current APIs:

1. `SoftwareUser` can invite an `Employee` to create their web account (on behalf of their attached `Company`).
2. `SoftwareUser` can send PDF `Documents` to an `Employee`'s account (on behalf of their attached `Company`).
3. `SoftwareUser` can create a `Campain` to have an `Employee` sign a contract online (on behalf of their attached `Company`).

As for future features, there will be:

1. `Customer` can pay for their licence online and view some data (remaining payroll volume, consumed phone support time, etc...).
2. `Companies` (who are not using the software if the `Customer` is an accountant firm) can view `Employees` related to them, signed `Campains` and `Documents` generated on their behalf.
3. `SoftwareUsers` who don't have access to the desktop software can enter data to populate payslips (this "feature" is expected to grow in the next years as we will progressively bring all the software's features to the web).

Finally, this system needs to be flexible, considering the following use cases:

* `Companies` could be transferred to other `Organizations` (ex: a company could ask its accountant to provide its data if they wanted to manage their payroll itself).
* The same principle applies to each actor type.
* `Account` creation invitations (with `Documents` attached) could be sent to wrong email addresses, so we must be able to transfer an `Employee` to a different account.

These are the reason I was planning this for relationships and authentication:

* For relationships, each actor will only know its parent ID and its linked `Account(s)` ID(s): this will enable to easily switch owners (a required feature).
* For authentication, I'm planning to use JWTs with only the `Account` ID as payload.

UPDATE
======

I took your comments into consideration and talked with some teammates, here is a new option:

3) With a PermissionService
---------------------------

* `Accounts` are not linked to "actors" anymore. Instead, they are linked to multiple `Permissions` that each specifies **who** has access to **which resource**, and possibly additional **claims** (ex: `accessLevel` for a `Permission` on an `Organization`).
* This gives the possibility to provide either "account tokens" (with only the account ID), or "permission tokens" (with also the target ID and claims), depending on whether we enable SSO or need restricted service accounts.
* As for the `ActorService` (not sure if the name fits well), its purpose is to hold the business logic regarding "actors relationships" as well as their properties (some of which were added on the diagram to illustrate their business value).

![Option 3](https://www.plantuml.com/plantuml/img/ZLKzRzim4DtvAxXvgRrqyr34JJ8KA1gZBj3HOAIBSWK_1FBam4tpttkoAP6qhSGS3FCTUVVuxaCtWPIdpcWX24c3V6W9dPMVvLB-HdgMIgx16mo1qGtu7LOWX7Kro5L7pn6HhqBoSez_e29vww46IwXqnFkrnJhzLrNbEaiZe5s3TjorByUZR-9j27KyVp5Qj4s4gfmbLT6zKQYZq_utTx21m-EkvKfeW4KpxOXq0VogWNWciJuJhYIUpDU6tdAk6iYe7BQ_zYqivQpg0Za3VYR_oHcOLhizGBzPB1P93gtGXALybUoRt_qTTg0_zKUYCBdcv7n9l4Xo33UfUmtPnl39YWiYvQ5V63W8xY03rXuCTYPooGC--4PP_Ale7S463KQ4CyDHVtJcCOAbprjdMcNtK-vS5d94hJA9S42VvSDPZHRkW5NsXqkJWUzZVYOVSYGs0a_e0nMHjJe1pYhzAEXF8EPusb1VKJFLvc9TVhCxby2FDLQcAD9Q4QpL_YpadQiw0nDDF1YlrMCx57Zg1Uw2SME05FDG9nGss5X5dOVBOujxMk5qRNr8uJ1AeLvHLXwD7O43ZsmspkTVXk4bXY4sr_14ZCUPbF3QlLZ6qynWLqC7zexoxYWjCPsYw9_U48jV34tGOqDTYW8TihEKbGTERn1Z_PPc9XdAgr7KvL6Saul9o3hnnHkmDN-A_WC0)

I'm still not 100% sure about this design, so every comment is welcome.