Structs Permissions

Permissions are identity and authority in Structs. Every object (player, guild, reactor, provider, substation, struct) has a 25-bit permission bitmask per grantee, and addresses can be attached to a player so multiple keys act on its behalf. This is the foundation of delegation — running a focused worker agent that can mine but not spend, or a watcher that can read but not act. Granted breadth is the risk: a wide grant to an adversarial key is unrecoverable.

Conventions (TX_FLAGS, -- rule, one-tx-at-a-time) are in conventions.md. Every transaction here is Tier 1 or Tier 2 — default to interactive, and prefer minimum-necessary bits.

When to use it

Decisions

Grant the minimum, not PermAll. Compose exactly the bits a task needs (they OR together). PermAll (33554431) yields total control and there is no undo if the holder turns. Reserve it for keys you fully control.

Object grant vs address grant vs guild-rank grant:

Address registration is an attack surface. address-register attaches a new signing key using attacker-suppliable proof material — if you register a key you don’t control, you’ve hired your attacker. Verify proof provenance; see awareness/agent-security.

Your primary address cannot be narrowed. Any permission-set-on-address / permission-revoke-on-address that would leave the player’s primary address below PermAll is rejected (primary_full_access_required). Scope delegates on secondary addresses; the primary stays the full-authority recovery key.

Vault spends ride on the signing key’s token bits. PermTokenTransfer / PermTokenInfuse / PermTokenMigrate / PermTokenDefuse on the key are what let it spend the player vault (and, with an object grant, a guild vault). A delegate without PermTokenTransfer cannot vault-send, buy ranks, open agreements, or mint.

The 25-bit permission model

Permission Value Description
PermPlay 1 Basic play access
PermAdmin 2 Manage permissions on the object (and set member ranks, on the signing key)
PermUpdate 4 Update object settings (also self-service UGC name/pfp)
PermDelete 8 Delete object
PermTokenTransfer 16 Transfer tokens; spend the vault (vault-send, agreements, rank purchase, mint collateral)
PermTokenInfuse 32 Infuse tokens into reactors/generators
PermTokenMigrate 64 Migrate stake between reactors (also needed for a guild join that migrates stake)
PermTokenDefuse 128 Defuse (withdraw) tokens
PermSourceAllocation 256 Create/update/delete allocations and providers from the object
PermGuildMembership 512 Manage guild membership (also required on the key for invite/request bypass joins and proxy-joining a registered address)
PermSubstationConnection 1024 Connect to substations
PermAllocationConnection 2048 Connect allocations to substations
PermGuildTokenBurn 4096 Burn & confiscate guild tokens
PermGuildTokenMint 8192 Mint guild tokens
PermGuildEndpointUpdate 16384 Update guild endpoint
PermGuildJoinConstraintsUpdate 32768 Update join infusion minimum / bypass settings
PermGuildSubstationUpdate 65536 Update guild entry substation
PermProviderWithdraw 131072 Withdraw provider balance
PermProviderOpen 262144 Open agreements on a provider
PermReactorGuildCreate 524288 Reserved reactor bit; guild-create no longer checks it
PermHashBuild 1048576 Submit build proof-of-work
PermHashMine 2097152 Submit mine proof-of-work
PermHashRefine 4194304 Submit refine proof-of-work
PermHashRaid 8388608 Submit raid proof-of-work
PermGuildUGCUpdate 16777216 Moderate name/pfp on guild-owned objects
PermAll 33554431 All permissions

Composites: PermAssetsAll = 16+32+64+128 = 240; PermHashAll = 15728640; PermGuildAll = admin/update/delete + membership + the three guild-settings bits + mint/burn + ProviderOpen + UGC + PermAssetsAll + PermSourceAllocation + PermAllocationConnection (a guild-admin grant therefore also conveys spending of the guild vault and allocation control — grant it knowingly). Canonical page: knowledge/mechanics/permissions.

Delegation recipes (multi-agent play)

Compose the bits for a worker key, then grant them on the relevant object/address. Different keys transact in parallel (one-tx-at-a-time is per account), so delegates multiply your throughput.

Verify every grant after applying it (permission-by-object), and revoke promptly when a delegate’s job ends.

Procedure

  1. Inspect — permission-by-object [object-id], permission-by-player [player-id], address-all-by-player [player-id]. These are paginated (default 100, max 1000, total always 0) — walk next_key on busy objects.
  2. Grant / revoke / set on object — permission-grant-on-object -- [object-id] [player-id] [bits] (additive; the target player must exist, and you need PermAdmin on the object plus the bits you are granting); permission-revoke-on-object -- ...; permission-set-on-object -- ... (replaces the set — confirm you aren’t dropping a bit you need).
  3. Address-level — permission-grant-on-address|revoke-on-address|set-on-address -- [address] [bits]. The primary address cannot be set below PermAll.
  4. Guild rank — permission-guild-rank-set -- [object-id] [guild-id] [permission] [rank] / permission-guild-rank-revoke -- [object-id] [guild-id] [permission]. Rank-register PermAdmin grants no authority of its own — rank-setting still needs PermAdmin on the signing key. Kicked members keep their direct object grants; revoke those separately.
  5. Address management — register a key: address-register -- [player-id] [address] [proof-pubkey] [proof-signature] [permissions] (Tier 2, verify proof). The new key signs the exact string CHAIN<chain-id>|REGISTERADDRESSPLAYER<player-id>ADDRESS<address>NONCE<n>, where n is the per-address nonce served as proofNonce by structsd query structs address [address] (0 for a never-registered address). A successful registration burns that nonce, so a captured proof cannot be replayed — including after an address-revoke, which does not reset it. Revoke: address-revoke -- [address] (don’t orphan your own --from; revoke leaves Cosmos stake and drops game capacity on that address); change primary: player-update-primary-address -- [new-address] (requires PermAll on the signing address — a limited delegate cannot rotate primary). Strict address moves refuse while a redelegation is in flight. Distinguish two patterns: address-register (or a webapp activation code) adds another signing key to one existing player (shared identity, planet, inventory); deriving fresh addresses from one mnemonic at m/44'/118'/0'/0/N and running a separate guild signup for each creates fully independent players (separate identities) recoverable from a single seed — see team-operations — Keys and accounts.

Webapp device workflow

A webapp session or bearer token authenticates API access; it does not grant chain permission. Use the device API contract for activation: keep the issued activation_id with the short code, persist the new key before sending consent, and obtain the current native proofNonce. Sign the chain-bound registration message above with that new key. An authorized existing key submits MsgAddressRegister; pending SQL permission selection alone grants nothing. Confirm committed success and matching native/indexed ownership before using the new device.

Confirmed-device permission edits use MsgPermissionSetOnAddress. The legacy SQL endpoint returns 410 chain_transaction_required. Preserve unexposed mask bits; check the signer’s ceiling over removed and added bits. Revocation requires the signing key’s Delete bit. The existing Log Out control without that bit clears this browser’s key/session only; it does not revoke the on-chain address.

Retain an uncertain transaction’s signed identity across reloads and device changes. Do not generate another key, proof or replacement transaction to resolve uncertainty. Public registration status contains chain/indexed identity; private IP/browser metadata and pending consent belong to the authenticated player.

Commands reference

Action Command
Grant / revoke / set on object structsd tx structs permission-grant-on-object \| permission-revoke-on-object \| permission-set-on-object TX_FLAGS -- [object-id] [player-id] [bits]
Grant / revoke / set on address structsd tx structs permission-grant-on-address \| ...-revoke-on-address \| ...-set-on-address TX_FLAGS -- [address] [bits]
Guild rank set / revoke structsd tx structs permission-guild-rank-set \| permission-guild-rank-revoke TX_FLAGS -- [object-id] [guild-id] [permission] [rank]
Address register / revoke structsd tx structs address-register \| address-revoke TX_FLAGS -- ...
Update primary address structsd tx structs player-update-primary-address TX_FLAGS -- [new-address] (signer must hold PermAll)
Query permission / address (incl. proofNonce) structsd query structs permission-by-object \| permission-by-player \| address \| address-all-by-player [id]

TX_FLAGS per conventions.md. Requires structsd on PATH and a signing key.

Verification

Errors

See also