Skip to content

Guild officer rank

One guild-owned officer threshold per verified club:<id> guild. Issue contract: #405.

Guild Info, Guild Supplies, and the one-time Loot Helper admin grant read this policy. They do not keep a second live rank setting.

Contract

Concern Owner
Stored threshold, bootstrap, and commit SF.GuildOfficer (Policy)
Gossip record Gossip provider sf.guildofficer.policy
Native rank and guild identity Guild Gossip GetGuildIdentity / GetGuildMember / GetGuildRanks
Settings selector Guild Settings → Main / Alt Assignments, top of the page
  • Positions are 1-based. Guild Master is rank 1. A member is an officer when rankOrder <= threshold.
  • The default is rank 3, capped to the last existing native rank. A shorter rank list caps checks and display. It does not rewrite the stored value and it does not widen who qualifies.
  • An empty local cache is unknown, not "never configured". Editing stays disabled until a valid record is stored or a verified Guild Master bootstraps or recovers it. Bootstrap does not overwrite a valid policy.
  • Any verified member can view the effective policy. An officer may change it. Authority is rechecked when the change is committed and when a remote record is admitted.
  • A self-restricting edit is authorized against the previous threshold. After it lands, that officer loses further edit rights.
  • Same-revision concurrent edits keep the lower (more restrictive) threshold. A later revision replaces it, including a deliberate widen by someone who still qualifies. A lower revision is stale.
  • When this client already has a valid policy, a remote sender must meet that known threshold. The predecessor claimed in the incoming record does not grant authority. Same-revision edits are still checked against the shared predecessor.
  • A client with no stored policy authorizes the transport sender against the approved default officer cap (min(3, rankCount)). That lets an eligible officer relay a GM-created bootstrap after the GM logs off, and it rejects a non-officer who only claims a more permissive predecessor. Local bootstrap and recovery still require a verified Guild Master. Ordinary Gossip fields cannot prove original authorship, so an eligible-by-default officer can still install any valid first-record content.
  • Remote revisions must stay below the terminal revision and within a bounded catch-up gap of the known local revision. A stored terminal or map-key/body guild mismatch is unusable so a verified Guild Master can recover. Confirmations bind the complete policy fingerprint, not only revN.
  • Verified Guild Master recovery writes baseThreshold = 0 with a newer revN. Established peers accept that authenticated recovery from the Guild Master so a corrupt local entry can converge again. Non-GM forgery of a bootstrap/recovery record is rejected. Offline or relay peers that never observe the recovery keep their prior policy until reconnect; that is an accepted v1 limitation, not a consensus log.
  • When the officer policy becomes available, Guild Gossip reopens unresolved pull obligations for Guild Info and Guild Supplies so records previously rejected with policy_unknown can retry without waiting for the unresolved TTL.
  • The policy is independent of Guild Supplies datasets, Loot Helper profiles, and Guild Info relationship cleanup.

Disconnected clients may briefly use an older threshold. That limitation is accepted. This is not a consensus log.

Storage

SpectrumFederationDB.guildOfficer = {
  schemaVersion = 1,
  localWriter = { nonce = "<24 hex>", nextSeq = 1 },
  guilds = {
    ["club:<id>"] = {
      schemaVersion = 1,
      guildKey = "club:<id>",
      threshold = 3,
      baseThreshold = 0, -- 0 = bootstrap/recovery; otherwise the previous stored threshold
      revN = 1,
      revW = "<24 hex>",
      at = 0,
    },
  },
}

Gossip publishes one current record, go-p:current, kind guild-officer-policy. Incoming envelopes must use that canonical id and a fingerprint that matches the normalized policy body. A changed fingerprint bumps the Guild Gossip index and the next index pass inserts that current record. A guild switch clears the previous guild's row. There is no per-frame roster poll and no operation history.

Consumers

  • Guild Info. Assign, move, unassign, Change Main, and history cleanup use the shared threshold for local commits and authenticated remote mutations. Cleanup does not replace the threshold.
  • Guild Supplies. Configuration, initialization, campaigns, and maintenance use the shared threshold. permission.editorRankPosition stays on existing records so historical validation and replica ancestry still work. It does not decide who can edit. Settings shows a historical permission repair control only when that stored permission record is actually corrupt. An unknown officer policy does not show it, and ordinary configured or unconfigured use does not show an editor-rank selector.
  • Loot Helper. Adding a new character to an existing profile may grant profile admin once, through the existing admin log, when that character's native guild rank meets the policy. Profile creation, import, hydration, snapshot replay, and remote rebuilds do not grant. Unknown or ambiguous verification adds a regular member. Later demotion, threshold changes, and manual admin removal do not scan or regrant.