Repository navigation
[Design Discussion] Architectural First Principles for Resource Modeling in B2B Context #3310
Replies: 2 comments
Update: where this design landedThe two layers, confirmedThe split proposed in the original post held up. What changed is that the second layer is not a separate copy of the resource. It is a set of limits that travel with the share. flowchart LR
CC["Core configuration<br/>owning OU only"] --> P["Sharing policy<br/>who it reaches, on what terms"]
P --> OR["Overlay rules<br/>what the receiver may change"]
OR --> CV["Receiver's own values<br/>chosen inside those limits"]
There is only ever one instance of the resource. The resource receiving OU (via sharing policy) never gets a duplicate, it gets permission to override some templated values, and some options to be picked as values if required. Words we settled onThe terminology question from the original post, resolved:
One OU has at most one policy per resource. How a share travelsThe ways to say who a share reaches
Two rules shape that list:
Sharing inside one treeThis is the everyday case, and it needs no settings turned on. An OU shares with a child, or with a child and its branch, or with its whole branch at once. Because each step down is a decision made at that step, a company keeps control of who inside it holds what. Blanket policiesThree rows in the table reach a whole family rather than named OUs: "everything under me", "every root", and "everything". We call those blanket, and they behave differently in two ways. NOTE: "every root", and "everything" policies can be define for a resource only from the declarative form, any ou can't set these policies to a created resource via API as this decision should be known by the deployment managing admins First, they can only be narrowed later. You may carve OUs out of one, but you cannot widen it and you cannot turn it into a different kind of share. A blanket policy already reaches everything in its family, so there is nothing to expand toward, and narrowing is the only edit that means anything. Second, and this applies to "everything" alone, it sits behind the specific shares rather than on top of them. Where a specific share already reached an OU, that specific share sets the terms. A broad safety net can never loosen a share somebody deliberately made tight. Carving an OU out takes its whole branch with it. flowchart TD
D["OU making the decision"]
D --> C1["Child 1"]
D --> C2["Child 2, carved out"]
C1 --> G1["Under child 1"]
C2 --> G2["Under child 2"]
classDef reached fill:#d9ead3,stroke:#38761d,color:#000
classDef cut fill:#f4cccc,stroke:#a61c00,color:#000
class C1,G1 reached
class C2,G2 cut
Sharing "everything under me", with child 2 carved out. Child 2 and everything under it stays hidden. Crossing into another tree, and the setting that controls itThe only way out of your own tree is to land on another tree's root. That is deliberate. It means a company's root always decides what enters the company. Whether you may do it at all depends on who is asking:
Landing on a root reaches that root and nothing under it. So a share into another tree is always two decisions, never one. flowchart LR
subgraph A["Company A"]
OW["Owning OU"]
end
subgraph B["Company B"]
RB["Root of B"]
B1["OU inside B"]
B2["Another OU inside B"]
end
OW -->|"1. owner shares to the root of B"| RB
RB -->|"2. B chooses who inside B sees it"| B1
RB -.->|"stays hidden until B chooses"| B2
Company B stays in charge of its own tree. Nobody outside it can reach inside it. Deciding whether an OU can see a resourceWe do not match a policy against an OU. We walk down the OU's branch, and every step has to hold. flowchart TD
S{"Is this OU the owner?"} -->|yes| V["Visible"]
S -->|no| T["Start at the top of its branch"]
T --> C{"Does some policy reach this step?"}
C -->|no| H["Hidden.<br/>Everything below it is hidden too"]
C -->|yes| N{"Is this the OU we asked about?"}
N -->|no| D["Move one step down"]
D --> C
N -->|yes| V
The useful consequence: removing one share cleanly removes everything that depended on it. There are no orphaned grants left behind. Do restrictions cascade through levels? Yes, and they only tightenThis was the fourth question in the original post. The answer is yes, with two supporting rules: eg: limiting allowed scopes throughout the tree flowchart TD
O["Owner allows: read, write, delete"] --> M["Middle OU receives: read, write"]
M --> L["Lower OU receives: read"]
M -.->|"refused, not trimmed"| X["Cannot pass on delete.<br/>It never held it"]
Combining rather than picking matters more than it looks. It means withdrawing a narrow share can never accidentally widen somebody who then falls back on a broader one. Can core config permission be delegated? NoThe third question from the original post. Core configuration stays with the owning OU. What can be handed over is the right to change a specific field, and that right always sits inside limits the owner set. So an OU can be given room to move without ever being given the structural properties of the resource. Open points:
|
Sharing Policy Definition: Existing Model vs Proposed ModelThe following change is proposed to make sharing policies easier to read and to simplify building the organization access UIs.
Status
How to read the examples
NOTE: The given overlayRules are just samples, but not final ones. Summary
Scope mapping
Cases1. Only the owner (not shared)No other organization unit can use the application.
2. All child units, with exceptions and common termsEvery unit under the owner, now and later, except
3. Selected child units, each with its own reach and terms
4. Selected top units of other trees, each with its own termsThe top units
5. Child units and other trees togetherAll child units except
6. The top unit of every tree, with exceptions and common termsEvery tree's top unit, now and later, except
7. Every organization unit, with exceptions and common termsEvery unit in every tree, at any depth, now and later, except
8. A granted unit passing access on (reshare)
|

Uh oh!
There was an error while loading. Please reload this page.
Related Feature Issue
#2645
Problem Summary
As Thunder ID expands its organization management usecases (#2719), managing resource configuration across hierarchical Organizational Units (OUs) introduces a critical tension between rigid centralized control and decentralized customization. We need a unified architectural framework that decouples asset ownership from runtime access rules. This proposal establishes first principles to handle multi-OU resource behavior without creating split-brain state mutations or overly complex resource duplication across OUs.
High-Level Approach
Instance Creation API and Core Config Management API: Invoked by the Resource Creator to initialize core configurations, establish default template boundaries, manage the core configurations and resource deprovisioning.
Resource Template Customization API: Invoked by Resource Accessing OUs to safely hydrate permitted localized configuration parameters.
Architecture Overview
Structural Breakdown of a Resource
Every resource blueprint defined by Thunder ID developers consists of two distinct functional zones:
The Actor-Configuration Lifecycle Matrix
Multi-OU Runtime Context Resolution
During runtime invocation (e.g., login or an active API call), the engine resolves five specific environmental contexts:
Security Considerations
Impacted Areas
Alternatives Considered
Alternative 1: Completely Flat Resource Replication
Questions for Community Input
validations:
All reactions