Access Control Layers¶
The FlexGalaxy.AI platform uses three distinct layers of access control. Each layer answers a different question and is managed by a different persona.
Request arrives
│
▼
┌──────────────────────────────────────────┐
│ Layer 1: Role (User-level) │
│ "What is this user's job?" │
│ Managed by: Account admin (AdminCenter) │
│ Stored in: identity provider (per-user roles) │
│ Example: admin, operator, viewer │
└──────────────┬───────────────────────────┘
│ User has required role?
▼
┌──────────────────────────────────────────┐
│ Layer 2: SCP (Account-level policy) │
│ "What is this account allowed to call?" │
│ Managed by: Platform admin (SuperCrew) │
│ Stored in: DotID authorization service │
│ Example: deny thinghub:Thing:Enroll │
└──────────────┬───────────────────────────┘
│ SCP permits the action?
▼
┌──────────────────────────────────────────┐
│ Layer 3: Capability (Account-level) │
│ "What is this account qualified to do?" │
│ Managed by: Platform admin (SuperCrew) │
│ Stored in: DotID authorization service │
│ Example: enroll_things, approve_licenses│
└──────────────┬───────────────────────────┘
│ Account has capability?
▼
Execute
Layer 1: Role¶
Question: What is this user's job within this account?
Roles are user-level permissions managed by the account admin in AdminCenter. They determine what a specific person can do within their account's resources.
Role |
Can do |
Cannot do |
|---|---|---|
|
Manage users, groups, policies, settings |
N/A (full access within account) |
|
Enroll devices, join devices via access_code, manage assignments, create scopes |
Manage users, change account settings |
|
View devices, telemetry, reports |
Modify anything |
Roles are stored in the identity provider as realm roles or client roles. They are evaluated by each service before any authorization check.
Managed in: AdminCenter (tenant-facing)
Visible in: AdminCenter
Layer 2: Service Control Policy (SCP)¶
Question: What API actions is this account permitted to call?
SCPs are account-level policy boundaries — deny-based guardrails that restrict what actions an account can invoke, regardless of user roles or capabilities. They are the ceiling.
{
"Version": "2024-01-01",
"Statement": [
{
"Effect": "Deny",
"Action": [
"thinghub:Thing:Enroll",
"thinghub:Thing:BulkEnroll"
],
"Resource": "*"
}
]
}
SCPs use the same policy document format as IAM policies (see 策略文档格式). They are evaluated at step 6 of the authorization evaluation algorithm (see 授权模型).
Key properties:
Deny-based — SCPs define what is not allowed. If an SCP denies an action, it is blocked regardless of any other permission.
Account-scoped — each SCP applies to a specific account.
Inherited — in organizations, SCPs can be attached at the OU level and inherited by child accounts (future).
Cannot grant access — SCPs only restrict. An SCP that allows
thinghub:*does not grant access; it merely does not deny it.
Managed in: SuperCrew (platform admin)
Visible in: AdminCenter (read-only), SuperCrew (full management)
Layer 3: Capability¶
Question: What is this account qualified to do?
Capabilities are account-level business qualifications — grant-based feature entitlements that represent verified trust. They are not action permissions; they are business prerequisites that certain operations check.
Capability |
What it qualifies |
Who typically has it |
|---|---|---|
|
Register new devices in ThingHub |
Verified device manufacturers |
|
Approve/issue licenses in TrustMint |
Manufacturers, white-label partners |
|
Publish products to Bazaar marketplace |
Verified manufacturers |
|
Create and manage OTA rollouts in OTAForge |
Manufacturers, authorized service partners |
Key properties:
Grant-based — capabilities must be explicitly granted. Accounts start with no capabilities.
Account-scoped — capabilities belong to the account, not individual users. All users in the account benefit from the account's capabilities.
Multiple — an account can have any combination of capabilities. They are not mutually exclusive.
Verified — granting a capability implies the platform has verified the account's qualification (e.g., confirming they are a legitimate manufacturer).
Not action permissions — capabilities don't say "you can call this API." They say "you are qualified to perform this business function." The API permission is handled by roles and SCPs.
Stored as a set of strings on the account in DotID authorization service:
Account
├── id: acc-xxx
├── name: "BROIT Robotics"
└── capabilities: ["enroll_things", "approve_licenses", "publish_marketplace"]
Managed in: SuperCrew (platform admin grants/revokes)
Visible in: AdminCenter (read-only — account admin can see what capabilities their account has)
How the Three Layers Interact¶
Example: User "alice" in account "BROIT" calls POST /api/v1/things (enroll)
Layer 1 — Role:
Does alice have the "operator" or "admin" role?
YES → proceed
NO → 403 Forbidden ("insufficient role")
Layer 2 — SCP:
Does BROIT's SCP allow "thinghub:Thing:Enroll"?
YES (no deny) → proceed
NO (explicit deny) → 403 Forbidden ("action denied by policy")
Layer 3 — Capability:
Does BROIT have the "enroll_things" capability?
YES → proceed
NO → 403 Forbidden ("account not qualified — contact platform support")
All three passed → 201 Created
Role |
SCP |
Capability |
Result |
Reason |
|---|---|---|---|---|
✗ |
— |
— |
403 |
User lacks required role |
✓ |
Deny |
— |
403 |
Action denied by SCP |
✓ |
Allow |
✗ |
403 |
Account not qualified (no capability) |
✓ |
Allow |
✓ |
✓ Execute |
All layers passed |
Comparison¶
Aspect |
Role |
SCP |
Capability |
|
|---|---|---|---|---|
Question |
What is your job? |
What are you allowed to call? |
What are you qualified to do? |
|
Scope |
User |
Account |
Account |
|
Type |
Permission |
Guardrail (deny-based) |
Entitlement (grant-based) |
|
Managed by |
Account admin |
Platform admin |
Platform admin |
|
Managed in |
AdminCenter |
SuperCrew |
SuperCrew |
|
Visible in |
AdminCenter |
AdminCenter (read-only) |
AdminCenter (read-only) |
|
Analogous to |
AWS IAM Role |
AWS SCP |
AWS service enablement |
|
Default |
No roles (no access) |
No SCPs (everything allowed) |
No capabilities (nothing qualified) |
Service-Specific Capability Checks¶
Each service checks for the capability relevant to the operation:
Service |
Operation |
Required Capability |
Without Capability |
|---|---|---|---|
ThingHub |
|
|
403 — "Join by Code instead" |
ThingHub |
|
(none) |
Any account can join |
TrustMint |
Approve license |
|
403 |
Bazaar |
Publish product |
|
403 |
OTAForge |
Create / edit target filter |
|
403 |
OTAForge |
Preview matched targets |
|
403 |
OTAForge |
Create rollout |
|
403 |
OTAForge |
View rollout status (own devices) |
(none) |
Any assigned account can see rollout status |
Note: POST /things/join requires no capability — any account with a valid access_code can join. Viewing rollout status also requires no capability. Capabilities gate creation and management, not read access.
UI Visibility¶
SuperCrew (platform admin):
Account: BROIT Robotics (acc-xxx)
Service Control Policies
┌──────────────────────────────────────────┐
│ [DefaultAllow] No restrictions │
│ [+ Attach SCP] │
└──────────────────────────────────────────┘
Capabilities
┌──────────────────────────────────┬─────────┐
│ enroll_things │ [Revoke] │
│ approve_licenses │ [Revoke] │
│ publish_marketplace │ [Revoke] │
│ manage_ota_rollouts │ [Revoke] │
│ │ │
│ [+ Grant Capability] │ │
└──────────────────────────────────┴─────────┘
AdminCenter (tenant admin, read-only):
Account Settings → Access & Capabilities
Service Control Policies (read-only)
┌──────────────────────────────────────────┐
│ No restrictions applied to this account. │
└──────────────────────────────────────────┘
Capabilities (read-only)
┌──────────────────────────────────┬──────────┐
│ Enroll Things │ ● Active │
│ Approve Licenses │ ● Active │
│ Publish to Marketplace │ ● Active │
│ Manage OTA Rollouts │ ○ — │
└──────────────────────────────────┴──────────┘
To request additional capabilities, contact platform support.