FlexGalaxy Resource Names (FRN)¶
An FRN identifies a resource inside the FlexGalaxy.AI authorization model. FRNs play the same role AWS ARNs play in IAM: policy statements name resources with FRNs, authorization requests carry a target resource FRN, and audit events can record the affected resource.
Format¶
frn:{account-id}:{service}:{resource-path}
Four colon-separated segments, never five:
Segment |
Description |
Example |
|---|---|---|
|
Literal prefix. Always exactly |
|
|
Owning account identifier, or |
|
|
Service namespace. |
|
|
Slash-delimited resource hierarchy. The resource type is part of this path. |
|
An FRN parser splits on : into exactly four parts. A value like frn:dotid:acc-029cea77800e:user:alice is invalid because it has five colon-separated parts. Put the resource kind inside {resource-path} instead: frn:acc-029cea77800e:iam:user/alice.
Service segment registry¶
{service} is reserved by an authoritative service team. Adding a new segment without registration here is forbidden — two services on the same segment collide on policy resource patterns and audit-event resource fields.
Segment |
Owner |
Notes |
|---|---|---|
|
DotID — IAM core |
Users, groups, policies, access keys |
|
DotID — Organization service |
Organizations, OUs, delegation |
|
DotID — Identity Center |
Permission sets, account assignments |
|
DotID — Audit service |
Audit events |
|
DotID — Keycloak proxy |
Realm + keycloak-mediated resources |
|
DotID — Generic resource example |
Example/documentation resource shape |
|
DotID — Profile service |
User profile data |
|
DotID — example IoT capability |
Reserved name for future devices capability |
|
DotID — example licensing capability |
Reserved name for future licensing capability |
|
DotID — examples / smoke tests |
Test fixtures only — not a real service |
To reserve a new segment, open a PR against this file with a justification for the segment (per-resource vs per-capability split, naming alignment with the IAM action namespace, etc.).
Examples¶
These examples match FRNs used by the PDP tests and service code:
frn:acc-029cea77800e:iam:user/alice
frn:acc-029cea77800e:iam:group/platform-admins
frn:acc-029cea77800e:iam:policy/pol-7d3b9f12
frn:acc-029cea77800e:iam:access-key/AKIA-9F3B-12C8
frn:acc-target:licensing:device/dev-001
frn:acc-target:audit:event/ev-001
frn:acc-target:org:ou/ou-001
frn:acc-target:idc:permissionset/ps-001
frn:acc-target:keycloak:realm/r-001
frn:acc-1:s3:bucket/reports/2026.csv
The account segment is the owning account, even when another account is making the request.
Policy patterns¶
Concrete resource FRNs should identify one resource. Policy statement resource patterns may use wildcards:
frn:*:iam:user/*
frn:acc-1:devices:device/*
frn:acc-1:s3:bucket/**
* matches one segment value or one resource-path part. ** is only meaningful inside the resource path, where it matches deeper slash-delimited paths.
Parsing FRNs in your service¶
Keep the same four-segment shape wherever you parse FRNs:
def parse_frn(s: str):
parts = s.split(":", 3)
if len(parts) != 4 or parts[0] != "frn":
raise ValueError(f"not a valid FRN: {s}")
_, account_id, service, resource_path = parts
return account_id, service, resource_path
public record Frn(String accountId, String service, String resourcePath) {
public static Frn parse(String s) {
String[] parts = s.split(":", 4);
if (parts.length != 4 || !"frn".equals(parts[0])) {
throw new IllegalArgumentException("not a valid FRN: " + s);
}
return new Frn(parts[1], parts[2], parts[3]);
}
}
Valid segment characters are intentionally conservative: account and service segments allow letters, digits, _, ., *, and -; the resource path also allows /.
Cross-account FRNs¶
When a policy in account A references a resource in account B, the FRN’s {account-id} is B, the owning account, not the caller. Cross-account access is denied by default. To enable it, the owning account must publish an explicit trust policy naming the calling account, and the calling identity must still pass its own account’s identity-side checks. Without a matching trust policy, PDP returns decision: DENY, reason: CROSS_ACCOUNT_NO_TRUST.
What FRNs are not¶
FRNs are identifiers, not URLs. They do not dereference over HTTP, and there is no GET frn:... endpoint.
To look up the resource behind a DotID FRN, call the owning service’s public API using the account-scoped route. For example:
GET /identity/v1/accounts/{accountId}/users/{userId}
GET /audit/v1/accounts/{accountId}/events
Other service namespaces use their own public APIs. Treat FRNs as opaque authorization identifiers you pass around, not as fetchable URLs.
Empty-account-id form (org-delegation exception)¶
The empty-{account-id} segment form
frn::{service}:{resource-path}
is RESERVED exclusively for resources whose lifecycle does not belong to any single account. The canonical first instance is the org-wide service-delegation pointer:
frn::example-service:org-delegation/{org-id}
This is the FRN the authorization service evaluates when a registered service needs to know which account holds delegated-administrator authority for that service in an organization.
Empty account-id is NEVER a wildcard¶
Wildcards are * only. A pattern with empty {account-id} matches ONLY a target with empty {account-id}; a pattern with * does NOT match a target with empty {account-id}. The matcher treats the empty account-id as its own distinct segment value.
Concretely:
Pattern |
Target |
Matches? |
|---|---|---|
|
|
TRUE — empty-to-empty |
|
|
FALSE — |
|
|
FALSE — explicit account-id does not match empty |
|
|
FALSE — empty pattern does not match populated target |
Parsing the empty account-id¶
When you parse this form, the {account-id} segment is the empty string "". If your code branches on whether an FRN has an owning account, treat an empty account-id as its own distinct case — not as a missing value and not as a wildcard.
When to use this form¶
Adding another instance of the empty-{account-id} form requires explicit justification (“which other resource has a lifecycle that does not belong to any single account?”); do not silently extend the convention to ad-hoc resources.