Purpose: AI-readable reference for the Structs permission system. Covers address permissions, object permissions, guild rank permissions, and the message handler permission reference.
The permission system controls what actions players and their addresses can perform on game objects. It operates at three layers:
All three layers are checked during PermissionCheck, the central authorization gate for every state-changing transaction.
Permissions are bitwise flags stored as uint64 values. There are 25 individual permission bits (bits 0–24):
| Bit | Value | Name | Description |
|---|---|---|---|
| 0 | 1 | PermPlay |
All struct, fleet, and planetary actions |
| 1 | 2 | PermAdmin |
Owner-level administrative access |
| 2 | 4 | PermUpdate |
Update object properties (also self-service UGC name/pfp) |
| 3 | 8 | PermDelete |
Delete objects |
| 4 | 16 | PermTokenTransfer |
Transfer tokens |
| 5 | 32 | PermTokenInfuse |
Infuse tokens into reactors |
| 6 | 64 | PermTokenMigrate |
Migrate tokens between validators |
| 7 | 128 | PermTokenDefuse |
Defuse tokens from reactors |
| 8 | 256 | PermSourceAllocation |
Create, update, delete allocations |
| 9 | 512 | PermGuildMembership |
Manage guild membership |
| 10 | 1024 | PermSubstationConnection |
Connect to substations |
| 11 | 2048 | PermAllocationConnection |
Connect allocations |
| 12 | 4096 | PermGuildTokenBurn |
Burn and confiscate guild tokens |
| 13 | 8192 | PermGuildTokenMint |
Mint guild tokens |
| 14 | 16384 | PermGuildEndpointUpdate |
Update guild endpoint URL |
| 15 | 32768 | PermGuildJoinConstraintsUpdate |
Update join infusion minimum and bypass settings |
| 16 | 65536 | PermGuildSubstationUpdate |
Update guild entry substation |
| 17 | 131072 | PermProviderWithdraw |
Withdraw provider balance |
| 18 | 262144 | PermProviderOpen |
Manage agreement restrictions |
| 19 | 524288 | PermReactorGuildCreate |
Reserved reactor bit (part of PermReactorAll); guild-create no longer checks it — founding is a paid transaction |
| 20 | 1048576 | PermHashBuild |
Submit struct build proof-of-work |
| 21 | 2097152 | PermHashMine |
Submit ore mining proof-of-work |
| 22 | 4194304 | PermHashRefine |
Submit ore refinery proof-of-work |
| 23 | 8388608 | PermHashRaid |
Submit planet raid proof-of-work |
| 24 | 16777216 | PermGuildUGCUpdate |
Moderate name/pfp on guild-owned objects (members, substations, planets) |
Multiple flags can be combined with bitwise OR. The system defines several useful composites:
| Name | Value | Flags Included |
|---|---|---|
Permissionless |
0 | No permissions |
PermAssetsAll |
240 | TokenTransfer, TokenInfuse, TokenMigrate, TokenDefuse |
PermHashAll |
15728640 | HashBuild, HashMine, HashRefine, HashRaid |
PermAgreementAll |
14 | Admin, Update, Delete |
PermProviderAll |
393230 | Admin, Update, Delete, ProviderWithdraw, ProviderOpen |
PermGuildAll |
17169406 | Admin, Update, Delete, GuildMembership, GuildEndpointUpdate, GuildJoinConstraintsUpdate, GuildSubstationUpdate, GuildTokenBurn, GuildTokenMint, ProviderOpen, GuildUGCUpdate, PermAssetsAll (TokenTransfer/Infuse/Migrate/Defuse), SourceAllocation, AllocationConnection — a guild-admin grant therefore also conveys spending the guild vault and allocation control |
PermSubstationAll |
1294 | Admin, Update, Delete, SubstationConnection, SourceAllocation |
PermReactorAll |
524558 | Admin, Update, Delete, SourceAllocation, ReactorGuildCreate |
PermAllocationAll |
2062 | Admin, Update, Delete, AllocationConnection |
PermAll |
33554431 | All 25 bits set (2^25 - 1) |
PermPlayerAll |
33554431 | Same as PermAll |
Each permission entry is keyed by a permission ID string stored under the Permission/value/ KV prefix.
Object permissions use the format:
{objectId}@{playerId}
For example, 4-1@1-2 means “player 1-2’s permissions on guild 4-1”.
Address permissions use the format:
{objectTypeNumber}-{address}@0
For example, 8-cosmos1abc...@0 represents the permissions for address cosmos1abc.... The @0 suffix distinguishes address permission keys from object permission keys.
The stored value is a single uint64 representing the bitwise OR of all granted permission flags. For example, if a player has PermUpdate | PermDelete on an object, the stored value is 12.
PermissionAdd): current | newFlags – adds flags without removing existing onesPermissionRemove): current &^ revokedFlags – removes only the specified flagsSetPermissions): Replaces the entire value – overwrites all flags to exactly the provided valueClearPermissions): Deletes the permission entry entirely (equivalent to setting to 0)PermissionCheck(object, activePlayer, requiredPermission) evaluates access in the following order, returning success on the first match:
Permissionless (0) always denies.{objectId}@{playerId} permission record. Uses HasAll semantics: all requested bits must be present.(objectId, guildId) pair. All requested permission bits must have a rank record, and the player’s guild rank must be numerically <= the most restrictive (lowest) rank across those bits.If none of the above grant access, the request is denied with a permission error.
Administration is the exception to step 7. PermissionAdministrationCheck — used by rank assignment, entry-rank changes, permission grants/sets/revokes and ownership transfer — accepts ownership or a direct PermAdmin grant, but a PermAdmin bit held only through a rank register confers nothing. Stored rank entries containing bit 2 may remain but are inert; owners grant direct PermAdmin to officers who should administer. Operational rank bits (membership, endpoint, mint, …) remain effective, subject to the signing key’s own ceiling at step 4.
Vaults inherit the key’s token bits. Spending an owner’s vault (vault-send, player-send from a vault address, reactor-infuse, struct-generator-infuse, agreement-open, rank purchase, guild-bank-*) runs PermissionCheck on the vault owner for the relevant PermToken* bit, so a secondary address scoped without PermTokenTransfer cannot drain it. See energy.md — vaults.
UGCPermissionCheck)Name and profile-picture updates on player, planet, and substation objects use a dedicated permission helper that allows EITHER self-service or guild moderation:
PermUpdate (4) on the target object via the standard PermissionCheck flow above. Owners pass automatically (ownership grants every permission), and explicit object-level grants of PermUpdate also pass. This is the self-service path.PermGuildUGCUpdate (16777216) on the owner’s guild object via PermissionCheck. This is the guild moderation path – it lets a guild member with that permission bit (granted directly or via a guild rank register entry on the guild) rewrite the name/pfp of any object owned by a guild-mate.MsgGuildUpdateName and MsgGuildUpdatePfp do NOT use UGCPermissionCheck. They fall back to the standard PermissionCheck(guild, player, PermUpdate) – so renaming a guild itself requires PermUpdate (4) on that guild, granted to the owner by ownership and reachable by other members only via an explicit grant or a rank-register entry that includes bit 2.
When the actor of a UGC update is not the target object’s owner, the chain emits a ugc_moderated event so guilds can audit moderator activity. See knowledge/mechanics/ugc-moderation.md for the full philosophy and validation rules.
Objects are identified by a string in the format {typeNumber}-{sequenceId}. The type number determines what kind of entity the object is:
| Type Number | Object Type |
|---|---|
| 0 | Guild |
| 1 | Player |
| 2 | Planet |
| 3 | Reactor |
| 4 | Substation |
| 5 | Struct |
| 6 | Allocation |
| 7 | Infusion |
| 8 | Address |
| 9 | Fleet |
| 10 | Provider |
| 11 | Agreement |
The guild rank permission system allows guild administrators to grant permissions on objects based on a player’s rank within the guild, rather than granting permissions to individual players. This enables scalable access control: instead of explicitly permissioning every guild member, an admin sets a rank threshold for a permission on an object, and any guild member at or above that rank automatically receives the permission.
Rank is a numeric value stored on each player’s profile (Player.GuildRank). Lower numbers represent higher privilege:
1 is the most powerful (guild creator default)101 is the default assigned on join0 means “no rank assigned”Guild administrators set player ranks via player-update-guild-rank.
Guild rank permissions are stored as a packed rank register per (objectId, guildId) pair. Each register is a fixed-size array of 24 uint64 slots (192 bytes total), where slot i holds the worst-allowed rank (highest numeric rank that still grants access) for permission bit i. A slot value of 0 means no guild rank permission is set for that bit.
KV Store key: Permission/guildRank/{objectId}/{guildId} -> 192-byte register
Example register state (after setting PermUpdate | PermGuildEndpointUpdate at rank 3):
| Slot | Permission | Rank Value |
|---|---|---|
| 0 | PermPlay | 0 (unset) |
| 1 | PermAdmin | 0 (unset) |
| 2 | PermUpdate | 3 |
| … | … | 0 (unset) |
| 14 | PermGuildEndpointUpdate | 3 |
| … | … | 0 (unset) |
Each bit stores its rank independently. A subsequent call to set PermUpdate at rank 5 only changes slot 2 – slot 14 remains at 3.
When a combined bitmask is passed to Set or Revoke, the system decomposes it into individual bits and operates on each slot independently:
permission=16388, rank=3: Writes rank 3 into slot 2 (PermUpdate) and slot 14 (PermGuildEndpointUpdate). All other slots untouched.permission=16384: Zeros slot 14 only. Slot 2 untouched.permission=16388: Zeros both slot 2 and slot 14 atomically.When a player attempts an action requiring a permission, and the check reaches the guild rank layer:
(objectId, playerGuildId)<= that minimum rank, access is grantedExample: If PermUpdate is set at rank 5 and PermDelete is set at rank 3, a check for PermUpdate | PermDelete requires the player’s rank to be <= 3 (the more restrictive threshold).
These manage per-player permission flags on specific objects. The caller must already have the permission flags they are granting/revoking/setting.
permission-grant-on-objectAdds permission flags to a player’s existing permissions on an object (bitwise OR).
structsd tx structs permission-grant-on-object {objectId} {playerId} {permissions} --from {signer} --gas auto -y
| Parameter | Type | Description |
|---|---|---|
objectId |
string | The target object (e.g., 4-1 for a guild) |
playerId |
string | The player receiving the permissions (e.g., 1-2) |
permissions |
uint64 | Permission bitmask to add |
Behavior: stored = stored | permissions. Existing flags are preserved; new flags are added.
permission-revoke-on-objectRemoves permission flags from a player’s permissions on an object (bitwise AND NOT).
structsd tx structs permission-revoke-on-object {objectId} {playerId} {permissions} --from {signer} --gas auto -y
Behavior: stored = stored &^ permissions. Only the specified flags are removed.
permission-set-on-objectReplaces a player’s permission value on an object entirely.
structsd tx structs permission-set-on-object {objectId} {playerId} {permissions} --from {signer} --gas auto -y
Behavior: stored = permissions. This overwrites the entire value. Use with care – any flags not included in the new value will be lost.
These manage what permissions an address is allowed to exercise. A player may have multiple addresses; each can be independently restricted — except the primary: any set or revoke that would leave the player’s primary address below PermAll is rejected with primary_full_access_required. The primary is the full-authority recovery key; scope delegates on secondary addresses.
permission-grant-on-addressstructsd tx structs permission-grant-on-address {address} {permissions} --from {signer} --gas auto -y
permission-revoke-on-addressstructsd tx structs permission-revoke-on-address {address} {permissions} --from {signer} --gas auto -y
permission-set-on-addressstructsd tx structs permission-set-on-address {address} {permissions} --from {signer} --gas auto -y
permission-guild-rank-setSets guild rank permissions on an object. Combined bitmasks are decomposed into individual bits before storage.
structsd tx structs permission-guild-rank-set {objectId} {guildId} {permission} {rank} --from {signer} --gas auto -y
| Parameter | Type | Description |
|---|---|---|
objectId |
string | The object to set permissions on (guild, substation, etc.) |
guildId |
string | The guild whose members will receive the permission |
permission |
uint64 | Permission bitmask (single or combined flags) |
rank |
uint64 | Worst-allowed rank (must be >= 1; lower = more privileged) |
The caller must already have the specified permission on the object.
permission-guild-rank-revokeRevokes guild rank permissions from an object. Only the specified bits are zeroed.
structsd tx structs permission-guild-rank-revoke {objectId} {guildId} {permission} --from {signer} --gas auto -y
player-update-guild-rankSets a player’s guild rank. Authorized by PermissionAdministrationCheck on the guild: the caller’s signing address must carry PermAdmin (2), and the calling player must be the guild owner or hold a direct PermAdmin grant on the guild. A rank register never qualifies — holding a good rank (bought or assigned) confers configured access, not the authority to hand out free ranks. The target must already be a member of the named guild (not_member otherwise); --guild-id may be omitted by a member caller, and is required for an owner who is not a member.
structsd tx structs player-update-guild-rank --from {signer} --gas auto -y -- {playerId} {guildRank}
permissionReturns the permission record for a specific permission ID.
structsd query structs permission {permissionId}
Response:
{
"permissionRecord": {
"permissionId": "4-1@1-2",
"value": "12"
}
}
The value field is the uint64 bitmask. Decompose with bitwise AND (e.g., value & 4 != 0 means PermUpdate is granted).
permission-by-objectReturns all permission records for a given object. Paginated over a scoped index: default 100 rows, --limit clamped to 1000, pagination.total always 0 — walk next_key.
structsd query structs permission-by-object {objectId}
permission-by-playerReturns all permission records for a given player. Paginated over a scoped index (same limits as above).
structsd query structs permission-by-player {playerId}
permission-allReturns all permission records. Paginated (default 100, max 1000, total always 0).
structsd query structs permission-all
guild-rank-permission-by-objectReturns all guild rank permission records for a given object across all guilds. Paginated over a scoped index (default 100, max 1000, total always 0).
structsd query structs guild-rank-permission-by-object {objectId}
guild-rank-permission-by-object-and-guildReturns guild rank permission records for a specific (objectId, guildId) pair. Returns at most 24 records. No pagination needed.
structsd query structs guild-rank-permission-by-object-and-guild {objectId} {guildId}
Response format (both guild rank queries):
{
"guild_rank_permission_records": [
{
"objectId": "6-1",
"guildId": "0-1",
"permissions": "4",
"rank": "3"
},
{
"objectId": "6-1",
"guildId": "0-1",
"permissions": "16384",
"rank": "3"
}
]
}
Each record represents a single permission bit. Combined bitmasks are always decomposed in query responses.
Emitted every time a permission value changes:
{
"permissionRecord": {
"permissionId": "4-1@1-2",
"value": 12
}
}
Events are emitted for every write, even if the value didn’t change.
Emitted for each guild rank permission bit that changes:
{
"guildRankPermissionRecord": {
"objectId": "6-1",
"guildId": "0-1",
"permissions": 4,
"rank": 3
}
}
When a player is created (via a native staking delegate from a fresh funded key, or guild join-proxy), their primary address is automatically granted PermPlayerAll (all 25 bits, value 33554431) on the address permission record, and that address can never be set below PermAll afterwards (primary_full_access_required). The primary address can exercise any permission the player holds. Rotating primary (player-update-primary-address) also requires PermAll on the signing address — a limited delegate cannot point the purse at a new key.
When an object is created, the creating player is typically set as the owner. Owners implicitly pass all permission checks on their objects without needing explicit permission records.
Object owners can delegate specific capabilities to other players:
# Guild owner grants Player 2 membership management and token minting
structsd tx structs permission-grant-on-object --from owner --gas auto -y -- $GUILD_ID $PLAYER_2_ID 8704
# 8704 = PermGuildMembership (512) | PermGuildTokenMint (8192)
A player can register secondary addresses and restrict each one:
# Grant a secondary address only play and hash permissions
structsd tx structs permission-set-on-address cosmos1secondary... 15728641 --from primary --gas auto -y
# 15728641 = PermPlay (1) | PermHashAll (15728640)
That limited key cannot call player-update-primary-address. Infusion playerId follows the current owner of the infusion’s address. Strict address moves (address-register, primary rotation) refuse while a redelegation is in flight. address-revoke leaves Cosmos stake in place and drops the game capacity credited to that address.
When an object is deleted, all permission records for that object (both direct {objectId}@{playerId} records and guild rank registers) are cleared, as bounded work: at most PermissionCleanupBudget (256) records per block, with the remainder queued (permissionCleanupQueue in genesis) and finished in following blocks. Revocation events are emitted for each cleared entry. A permission record that drops to zero is removed rather than stored as zero bytes, and grants/sets/revokes on objects reject a target player that does not exist.
# Admin sets: guild members rank 3 or better can update endpoint and manage membership
structsd tx structs permission-guild-rank-set --from admin --gas auto -y -- $GUILD_ID $GUILD_ID 16896 3
# 16896 = PermGuildMembership (512) | PermGuildEndpointUpdate (16384)
# Promote player to rank 2 (officer)
structsd tx structs player-update-guild-rank --from admin --gas auto -y -- $PLAYER_ID 2
# Player can now update the guild endpoint (rank 2 <= 3)
structsd tx structs guild-update-endpoint --from officer --gas auto -y -- $GUILD_ID "new.endpoint"
# Demote player to rank 5 (grunt)
structsd tx structs player-update-guild-rank --from admin --gas auto -y -- $PLAYER_ID 5
# Player can no longer update the endpoint (rank 5 > 3) -- transaction fails
# Rank 3+ can connect allocations
structsd tx structs permission-guild-rank-set --from admin --gas auto -y -- $SUB_ID $GUILD_ID 2048 3
# Rank 5+ can connect to the substation
structsd tx structs permission-guild-rank-set --from admin --gas auto -y -- $SUB_ID $GUILD_ID 1024 5
# Query shows 2 records with independent ranks
structsd query structs guild-rank-permission-by-object-and-guild $SUB_ID $GUILD_ID
# Set combined PermUpdate | PermDelete at rank 3
structsd tx structs permission-guild-rank-set --from admin --gas auto -y -- $GUILD_ID $GUILD_ID 12 3
# Revoke only PermUpdate (4), PermDelete (8) stays
structsd tx structs permission-guild-rank-revoke --from admin --gas auto -y -- $GUILD_ID $GUILD_ID 4
# Grant guild members rank 5+ the ability to open agreements on a provider
structsd tx structs permission-guild-rank-set --from admin --gas auto -y -- $PROVIDER_ID $GUILD_ID 262144 5
# 262144 = PermProviderOpen
Every msg_server_* handler that performs a permission check is listed below.
| Message | Object Checked | Permission Flag(s) |
|---|---|---|
PermissionGrantOnObject |
Target object (msg.ObjectId) |
Permission(msg.Permissions) (caller-specified) |
PermissionRevokeOnObject |
Target object (msg.ObjectId) |
Permission(msg.Permissions) (caller-specified) |
PermissionSetOnObject |
Target object (msg.ObjectId) |
Permission(msg.Permissions) (caller-specified) |
PermissionGrantOnAddress |
Target player (owner of msg.Address) |
Permission(msg.Permissions) (caller-specified) |
PermissionRevokeOnAddress |
Target player (owner of msg.Address) |
Permission(msg.Permissions) (caller-specified) |
PermissionSetOnAddress |
Target player (owner of msg.Address) |
Permission(msg.Permissions) (caller-specified) |
PermissionGuildRankSet |
Target object (msg.ObjectId) |
Permission(msg.Permission) (caller-specified) |
PermissionGuildRankRevoke |
Target object (msg.ObjectId) |
Permission(msg.Permission) (caller-specified) |
For all permission transactions, the caller must already possess the permission flags they are granting, revoking, or setting.
| Message | Object Checked | Permission Flag(s) | |
|---|---|---|---|
PlayerUpdatePrimaryAddress |
Target player | PermAll (33554431) |
CanUpdatePrimaryAddressBy — limited delegates cannot rotate primary |
PlayerSend |
Target player | PermTokenTransfer (16) |
|
PlayerUpdateGuildRank |
Guild | PermAdmin (2) — ownership or direct grant only; no rank fallback |
|
PlayerUpdateName |
Target player (UGC) | PermUpdate (4) on player OR PermGuildUGCUpdate (16777216) on the player’s guild |
|
PlayerUpdatePfp |
Target player (UGC) | PermUpdate (4) on player OR PermGuildUGCUpdate (16777216) on the player’s guild |
| Message | Object Checked | Permission Flag(s) |
|---|---|---|
GuildUpdateName |
Guild | PermUpdate (4) on the guild |
GuildUpdatePfp |
Guild | PermUpdate (4) on the guild |
PlanetUpdateName |
Planet (UGC) | PermUpdate (4) on planet OR PermGuildUGCUpdate (16777216) on the planet owner’s guild |
SubstationUpdateName |
Substation (UGC) | PermUpdate (4) on substation OR PermGuildUGCUpdate (16777216) on the substation owner’s guild |
SubstationUpdatePfp |
Substation (UGC) | PermUpdate (4) on substation OR PermGuildUGCUpdate (16777216) on the substation owner’s guild |
| Message | Object Checked | Permission Flag(s) |
|---|---|---|
AddressRegister |
Target player | Permission(msg.Permissions) (caller-specified) |
AddressRevoke |
Target player | PermDelete (8) |
| Message | Object Checked | Permission Flag(s) |
|---|---|---|
ReactorInfuse |
Funding owner (signing player’s vault by default; the registered key named by --delegator-address; or the guild named by --owner-id) |
PermTokenInfuse (32) |
ReactorDefuse |
Same funding owner | PermTokenDefuse (128) |
ReactorBeginMigration |
Same funding owner | PermTokenMigrate (64) |
ReactorCancelDefusion |
Same funding owner | PermTokenInfuse (32) |
VaultSend |
Sending owner (player or guild vault) | PermTokenTransfer (16) |
| Message | Object Checked | Permission Flag(s) | Notes |
|---|---|---|---|
GuildCreate |
Founder (self) | PermPlay (1) + PermTokenTransfer (16) |
Pays 2,000,000 ualpha from the founder’s vault; reactor’s validator must exist and not be jailed; PermSubstationConnection (1024) on the entry substation if specified; legacy proof fields rejected |
GuildUpdateRankPurchase |
Guild | PermAdmin (2) |
Direct grant or ownership; configures rank sales |
GuildRankPurchase |
Calling player | PermGuildMembership (512) + PermTokenTransfer (16) |
Pays guild token from player vault to guild vault |
GuildMembershipJoinByRankPurchase |
Calling player | PermGuildMembership (512) + PermTokenTransfer (16) |
Paid admission; migrates to entry substation |
GuildUpdateEndpoint |
Guild | PermGuildEndpointUpdate (16384) |
|
GuildUpdateEntrySubstationId |
Guild | PermGuildSubstationUpdate (65536) |
Also checks PermSubstationConnection (1024) on target substation |
GuildUpdateEntryRank |
Guild | PermUpdate (4) |
New entry rank must be >= caller’s own rank |
GuildUpdateJoinInfusionMinimum |
Guild | PermGuildJoinConstraintsUpdate (32768) |
|
GuildUpdateJoinInfusionMinimumBypassByRequest |
Guild | PermGuildJoinConstraintsUpdate (32768) |
Unknown enum values denied |
GuildUpdateJoinInfusionMinimumBypassByInvite |
Guild | PermGuildJoinConstraintsUpdate (32768) |
Unknown enum values denied |
GuildUpdateOwnerId |
Guild | PermAdmin (2) |
Clears the outgoing owner’s entire direct permission row on the guild |
GuildBankMint |
Guild | PermGuildTokenMint (8192) |
Plus PermTokenTransfer on the guild vault (collateral leaves the guild vault; tokens arrive there) |
GuildBankConfiscateAndBurn |
Guild | PermGuildTokenBurn (4096) |
|
GuildBankRedeem |
Calling player | PermTokenTransfer (16) |
Self-check |
GuildBankConvert |
Calling player | PermTokenTransfer (16) |
Open-market ualpha → token |
GuildBankConvertToken |
Calling player | PermTokenTransfer (16) |
Atomic token → token |
Permission checks are conditional based on guild join settings (GuildJoinBypassLevel).
| Message | Object Checked | Permission Flag(s) | Notes |
|---|---|---|---|
GuildMembershipInvite |
Guild | PermGuildMembership (512) |
Only when bypass level = permissioned. When member, requires guild membership only. When closed, always denied. |
GuildMembershipInviteApprove |
Target player | PermGuildMembership (512) |
Caller must be the invited player; requires a pending application |
GuildMembershipInviteDeny |
Target player | PermGuildMembership (512) |
Caller must be the invited player |
GuildMembershipInviteRevoke |
Guild | PermGuildMembership (512) |
Conditional on bypass level |
GuildMembershipRequest |
Target player | PermGuildMembership (512) |
Guild must allow requests |
GuildMembershipRequestApprove |
Guild | PermGuildMembership (512) |
Conditional on bypass level; requires a pending application |
GuildMembershipRequestDeny |
Guild | PermGuildMembership (512) |
Same conditions as approve |
GuildMembershipRequestRevoke |
Target player | PermGuildMembership (512) |
Caller must be the requesting player |
GuildMembershipJoin |
Target player | PermGuildMembership (512) |
Direct join (pre-approved). Additionally PermTokenMigrate (64) when an infusion’s reactor lies outside the destination guild and its stake must be redelegated |
GuildMembershipJoinProxy |
Guild | PermGuildMembership (512) |
Also checks PermSubstationConnection (1024) if substation override. If the joined address is already registered to a player, that address must itself hold PermGuildMembership; onboarding a brand-new address stays permissionless |
GuildMembershipKick |
Guild | PermGuildMembership (512) |
Cannot kick the guild owner. Removes rank authority but preserves the player’s direct grants (including on the guild itself) — revoke them explicitly |
| Message | Object Checked | Permission Flag(s) | Notes |
|---|---|---|---|
StructBuildInitiate |
Owner (player) | PermPlay (1) |
|
StructBuildCancel |
Owner (player) | PermPlay (1) |
|
StructBuildComplete |
Owner (player) | PermHashBuild (1048576) |
Only this single bit; ante also checks PermHashBuild on the signing address |
StructActivate |
Owner (player) | PermPlay (1) |
|
StructDeactivate |
Owner (player) | PermPlay (1) |
No player-online requirement; costs no charge |
StructDeactivateBatch |
Owner (player) | PermPlay (1) |
Checked per struct; up to 65 per tx |
StructTrash |
Owner (player) | PermPlay (1) |
Costs buildCharge (1); a registered charge message; destroys a built struct |
StructStealthActivate |
Owner (player) | PermPlay (1) |
|
StructStealthDeactivate |
Owner (player) | PermPlay (1) |
|
StructMove |
Owner (player) | PermPlay (1) |
|
StructAttack |
Owner (player) | PermPlay (1) |
|
StructDefenseSet |
Owner (player) | PermPlay (1) |
|
StructDefenseClear |
Owner (player) | PermPlay (1) |
|
StructOreMinerComplete |
Owner (player) | PermHashMine (2097152) |
Only this single bit |
StructOreRefineryComplete |
Owner (player) | PermHashRefine (4194304) |
Only this single bit |
StructGeneratorInfuse |
Calling player | PermTokenInfuse (32) |
Self-check |
CanBePlayedBy checks PermPlay on the struct’s owner (player object), not the struct itself. Each proof-of-work completion checks its own single hash bit on the owner (player): CanBuildHashedBy → PermHashBuild, CanMineHashedBy → PermHashMine, CanRefineHashedBy → PermHashRefine, CanRaidHashedBy → PermHashRaid. None of them requires all four bits. The ante handler independently requires the same single bit on the signing address. See hashing.md for the full proof-of-work mechanism.
| Message | Object Checked | Permission Flag(s) |
|---|---|---|
FleetMove |
Fleet owner (player) | PermPlay (1) |
PlanetExplore |
Player | PermPlay (1) |
PlanetRaidComplete |
Fleet owner (player) | PermHashRaid (8388608) |
| Message | Object Checked | Permission Flag(s) | Notes |
|---|---|---|---|
SubstationCreate |
Allocation | PermAllocationConnection (2048) |
|
SubstationDelete |
Substation | PermDelete (8) |
Also checks PermSubstationConnection (1024) on migration target if specified |
SubstationPlayerConnect |
Substation + Player | PermSubstationConnection (1024) on both |
Both checks must pass |
SubstationPlayerDisconnect |
Player OR Substation | PermSubstationConnection (1024) |
Either check sufficient |
SubstationPlayerMigrate |
Substation + Player | PermSubstationConnection (1024) on both |
Both required; the player-side check runs for every player in the list |
SubstationAllocationConnect |
Allocation | PermAllocationConnection (2048) |
|
SubstationAllocationDisconnect |
Allocation OR Destination | PermAllocationConnection (2048) |
Either sufficient |
| Message | Object Checked | Permission Flag(s) | Notes |
|---|---|---|---|
AllocationCreate |
Source object (player/reactor) | PermSourceAllocation (256) |
Only players and reactors are valid sources |
AllocationUpdate |
Source object | PermSourceAllocation (256) |
|
AllocationDelete |
Source, then allocation | PermSourceAllocation (256) OR PermDelete (8) |
Fallback: if source check fails, checks direct delete |
AllocationTransfer |
Allocation | PermAdmin (2) |
| Message | Object Checked | Permission Flag(s) |
|---|---|---|
ProviderCreate |
Substation | PermSourceAllocation (256) |
ProviderDelete |
Provider | PermDelete (8) |
ProviderUpdateCapacityMinimum |
Provider | PermUpdate (4) |
ProviderUpdateCapacityMaximum |
Provider | PermUpdate (4) |
ProviderUpdateDurationMinimum |
Provider | PermUpdate (4) |
ProviderUpdateDurationMaximum |
Provider | PermUpdate (4) |
ProviderUpdateAccessPolicy |
Provider | PermUpdate (4) |
ProviderWithdrawBalance |
Provider | PermProviderWithdraw (131072) |
| Message | Object Checked | Permission Flag(s) | Notes |
|---|---|---|---|
AgreementOpen |
Provider | PermProviderOpen (262144) |
Only for guildMarket policy. openMarket requires valid player only. closedMarket always denied. Also PermTokenTransfer (16) on the paying owner (self, or the guild named by --owner-id) — collateral leaves that owner’s vault |
AgreementClose |
Agreement | PermUpdate (4) |
|
AgreementCapacityIncrease |
Agreement | PermUpdate (4) |
|
AgreementDurationIncrease |
Agreement | PermUpdate (4) |
Some handlers check permissions on multiple objects. All checks must pass unless noted as fallback.
| Message | Check 1 | Check 2 | Relationship |
|---|---|---|---|
GuildCreate |
PermPlay + PermTokenTransfer on founder |
PermSubstationConnection on entry substation |
Both required (substation only if specified) |
ProviderCreate |
PermSourceAllocation on substation |
PermSourceAllocation on the guild named by --owner-id |
Both required (guild only if specified) |
GuildUpdateEntrySubstationId |
PermGuildSubstationUpdate on guild |
PermSubstationConnection on target substation |
Both required |
SubstationPlayerConnect |
PermSubstationConnection on substation |
PermSubstationConnection on player |
Both required |
SubstationPlayerDisconnect |
PermSubstationConnection on player |
PermSubstationConnection on substation |
Either sufficient |
SubstationPlayerMigrate |
PermSubstationConnection on destination |
PermSubstationConnection on player |
Both required (checked once per player in the list) |
SubstationDelete |
PermDelete on substation |
PermSubstationConnection on migration substation |
Both required (migration only) |
AllocationDelete |
PermSourceAllocation on source |
PermDelete on allocation |
Either sufficient |
SubstationAllocationDisconnect |
PermAllocationConnection on allocation |
PermAllocationConnection on destination |
Either sufficient |
GuildMembershipJoinProxy |
PermGuildMembership on guild |
PermSubstationConnection on substation |
Both required (substation only if specified) |
| Permission | Value | Used By |
|---|---|---|
PermPlay |
1 | StructBuildInitiate, StructBuildCancel, StructActivate, StructDeactivate, StructDeactivateBatch, StructTrash, StructStealthActivate, StructStealthDeactivate, StructMove, StructAttack, StructDefenseSet, StructDefenseClear, FleetMove, PlanetExplore |
PermAdmin |
2 | GuildUpdateOwnerId, PlayerUpdateGuildRank (on the signing address), GuildUpdateRankPurchase, AllocationTransfer, Permission transactions — always a direct grant or ownership, never via rank register |
PermUpdate |
4 | GuildUpdateEntryRank, ProviderUpdate, AgreementClose, AgreementCapacity/Duration, GuildUpdateName, GuildUpdatePfp; self-service path of PlayerUpdateName/Pfp, PlanetUpdateName, SubstationUpdateName/Pfp |
PermDelete |
8 | AddressRevoke, ProviderDelete, SubstationDelete, AllocationDelete (fallback) |
PermTokenTransfer |
16 | PlayerSend, VaultSend, GuildCreate, AgreementOpen (payer), GuildBankRedeem/Convert/ConvertToken, GuildBankMint (guild vault), GuildRankPurchase, GuildMembershipJoinByRankPurchase |
PermTokenInfuse |
32 | ReactorInfuse, ReactorCancelDefusion, StructGeneratorInfuse |
PermTokenMigrate |
64 | ReactorBeginMigration, GuildMembershipJoin (when stake must migrate) |
PermTokenDefuse |
128 | ReactorDefuse |
PermSourceAllocation |
256 | AllocationCreate, AllocationUpdate, AllocationDelete (primary), ProviderCreate |
PermGuildMembership |
512 | All GuildMembership* transactions, GuildMembershipKick |
PermSubstationConnection |
1024 | SubstationPlayerConnect/Disconnect/Migrate, GuildCreate (entry substation), GuildUpdateEntrySubstationId, GuildMembershipJoinProxy, SubstationDelete (migration) |
PermAllocationConnection |
2048 | SubstationCreate, SubstationAllocationConnect/Disconnect |
PermGuildTokenBurn |
4096 | GuildBankConfiscateAndBurn |
PermGuildTokenMint |
8192 | GuildBankMint |
PermGuildEndpointUpdate |
16384 | GuildUpdateEndpoint |
PermGuildJoinConstraintsUpdate |
32768 | GuildUpdateJoinInfusionMinimum, GuildUpdateJoinInfusionMinimumBypassBy* |
PermGuildSubstationUpdate |
65536 | GuildUpdateEntrySubstationId |
PermProviderWithdraw |
131072 | ProviderWithdrawBalance |
PermProviderOpen |
262144 | AgreementOpen (guildMarket only) |
PermReactorGuildCreate |
524288 | No handler; reserved (part of PermReactorAll) |
PermHashBuild |
1048576 | StructBuildComplete; part of PermHashAll |
PermHashMine |
2097152 | StructOreMinerComplete; part of PermHashAll |
PermHashRefine |
4194304 | StructOreRefineryComplete; part of PermHashAll |
PermHashRaid |
8388608 | PlanetRaidComplete; part of PermHashAll |
PermHashAll (composite) |
15728640 | Composite convenience flag granting all four hash bits; no single message requires all four |
PermGuildUGCUpdate |
16777216 | Guild moderation path of PlayerUpdateName/Pfp, PlanetUpdateName, SubstationUpdateName/Pfp (checked on the target object owner’s guild) |
schemas/entities.md – Entity permission propertiesschemas/actions.md – Transaction definitionsapi/queries/permission.md – Permission query API