For the complete documentation index, see llms.txt. This page is also available as Markdown.

Access Gates for Metanet Rooms

Crumbs, zer0_dt_

He that received seed into the good ground is he that heareth the word, and understandeth it; which also beareth fruit, and bringeth forth, some an hundredfold, some sixty, some thirty.

Access is normally something granted. You ask, somebody authorised to say yes decides, and your name goes into their table. That decision is discretionary, unaccountable, and free to whoever makes it — and the last of those is the flaw. Admitting somebody who damages the room costs the room; refusing somebody who would have improved it costs the applicant; neither lands on the desk that decided. A decision-maker insulated from the consequences of the decision is the textbook shape of a moral hazard, and it is why access lists rot.

A gate inverts the arrangement. The condition is published, the facts are the applicant's own, and nobody grants anything — you satisfy a rule or you do not, the world supplies the answer, and the cost of it falls on whoever moved. Standing at such a door means having put something at risk: a holding you could lose, a name somebody attached to you and can withdraw, a record of conduct written by people who were there. The party who gains from being inside is therefore the party who paid to get in, and whoever set the rule is exposed to their own rule, since one drawn carelessly excludes exactly the people it was meant to attract.

That is worth the trouble because of what is behind the door. Information placed well returns more than was put into it, which is why a room's contents are worth a rule at all and why a careless rule destroys something rather than merely causing offence. Price entry in stake rather than in permission and any meeting of minds can become a market in information: everybody inside has put up something real to be there, nobody profits by degrading what they bought into, and the entrant's incentive, the incumbent's and the room's point the same way. It is the principle behind proof of work applied to a door instead of a chain — a claim is worth what it cost to make, provided the cost is real and anybody can check it — and access earned that way widens as the record does and narrows the same way, because every fact beneath it can be withdrawn by the world rather than by an administrator.

Abstract

This document describes access gates: conditions attached to a room, evaluated by a client against verifiable facts about a reader, that decide whether the room's contents are rendered to them.

Five gate types are described — holding, vouch, renounce, quorum and timelock — together with a ban, which appears in no manifest and applies to every room, an optional recurring fee, a manifest format so that two clients evaluate the same rule identically, and a verdict structure so that the result is data rather than a sentence. A room's roles are derived from the same conditions rather than from a list of appointees, which is what lets a room say who may moderate without keeping a register of moderators.

Every fact a gate reads is one BRC-169 already publishes: a holding, a peer attestation, a statement written against a handle. No new cryptographic mechanics are introduced and no command verbs are claimed; the conversational surface for configuring a gate is BRC-218. This document subsumes BRC-218 section 11, which sketched three of these gates in a page.

Motivation

What a room is, here. A room is a space with more than two parties, contents that persist, and a participant set somebody could enumerate. A group chat is the obvious case; a channel, a forum, a comment thread and an open feed are the same shape. This document does not say how a room comes to exist, where its contents are carried, or what an ecosystem calls it — those differ everywhere, and standardising them is not necessary in order to standardise the door. It asks two things of whatever an ecosystem provides: a stable identifier, so that a rule attaches to the right thing, and a holder, so that a change to the rule is attributable to somebody.

Two things are deliberately not rooms. A one-to-one conversation is not one — reachability between two identities is already answered by BRC-169's scopes and tolls at the messagebox, each party is their own gate, and a predicate would be a worse version of a decision they can make directly. Nor is anything with a single participant: a feed you alone post to is a publication, and who may read it is a question about distribution rather than about membership.

The distinguishing feature is that a room accumulates. What is said in it stays, so admitting somebody admits them to everything already there. That is what makes a rule worth having, what makes a careless one expensive, and what makes removing one irreversible.

A room needs a rule about who is in it, and the reflex is a membership list. A list fails the way administrators fail. It goes stale, because nobody enjoys pruning it. It bottlenecks on whoever holds it and stops working the week they lose interest. It cannot say why anyone is on it, so nobody can audit it and nobody can join by satisfying it — they can only ask. And it lives in a vendor's table, which makes it exactly as portable as that vendor.

A gate is a predicate over claims other parties have already made, in public, for their own reasons. Nobody has to be asked. The answer is the same for everyone who evaluates it, and a reader can read the rule that excluded them.

The deeper difference is the reason for most of what follows. A list marks; a gate wagers. Being on a list is a fact about the list: it predicts nothing, forbids no outcome, and cannot turn out to have been wrong — a name sits there whether or not the thing it stood for is still true, and it comes off only when somebody removes it. A gate names a condition reality decides. It can be satisfied and it can stop being satisfied, both without anyone's permission.

That difference has a price attached. A gate costs something to satisfy and a list does not. A holding gate asks you to have something you could lose; a vouch gate asks somebody to attach their name to you, which is theirs to withdraw; a fee asks you to keep paying. Each is exposure, and each can be checked by anyone who cares to. An entry on a list is free to the person on it and free to whoever put them there, which is precisely why lists drift: nothing about them is answerable to anything, so nothing corrects them.

The failure mode is a gate that has stopped wagering. Roles are derived rather than granted for this reason and no other — a moderator who holds a rare item stops being one by selling it, where an appointed moderator can only be un-appointed by whoever appointed them. It is also why section 9 is blunt about gating being presentation. A gate described as a security boundary has changed categories: it has stopped being a checkable claim about who holds what and become a promise about what cannot happen, which is a promise it cannot keep and which nothing will ever falsify to the person relying on it.

None of this argues that every room should be gated, and section 10 says which should not be. A room can be perfectly good without a rule, and most are; a gate applied to a room that never needed one converts a group of people who know each other into a predicate that is wrong about some of them. The claim is narrower: a room that is going to have a rule is better off with one that can be read, checked, satisfied and lost than with a list nobody can audit and nothing can correct.

Two properties make this worth writing down rather than leaving to clients. Determinism is the product — if two clients disagree about who may read a room, the room is a different room in each of them, and a rule that varies is worse than no rule because it looks like a guarantee. The excluded reader is the design — the difference between a door and a disappearance is what the person outside is told, and somebody refused should be able to read the rule that refused them and say what would change the answer.

BRC-218 reserves /gate for charging admission to a room: the write half, needing custody and refunds. This document covers the read half only — a condition, evaluated locally, deciding what is rendered.

Prior Art

Three bodies of existing work bear on this. The design converges with the first, diverges deliberately from the second, and comes close enough to the third to be worth distinguishing carefully.

Policy languages. The three-state verdict of section 3.1 is not a novelty. XACML has carried Permit, Deny, Indeterminate and NotApplicable since 2003, with Indeterminate meaning exactly what it means here: the decision point could not evaluate, which is neither an admission nor a refusal. This document arrives at the same three states by a different route and drops the fourth, because a room with no condition is answered by section 2 rather than by the evaluator. Where a design converges with a mature policy language it is usually because the problem has a shape, and it is worth saying so rather than presenting the state as a discovery.

The stored grant. The dominant answer to "may this person be here" is to write the answer down. The access matrix of the early 1970s made it a table of principals against objects; role-based access control, standardised as ANSI INCITS 359 in 2004, added an indirection so the row names a role rather than a person; directory groups, workspace memberships and cloud IAM policies are the same object at scale, and a Discord member list or a Slack workspace is its consumer form. In every one, somebody with authority writes a row, and the row is what is consulted afterwards.

The arrangement has real advantages, and this document is not improved by pretending otherwise. A table read is cheaper than any predicate — no lookup, no indexer, and no state in which the answer cannot be computed. It is private, since being on a list discloses nothing about why, where a gate makes the qualifying facts legible to anybody who can evaluate it. It is precise in a way no predicate is, because a person can admit exactly who is meant and nobody else, including where the criterion is "my colleagues" and no public fact means that. It is recoverable: an administrator restores access to somebody who lost their keys, which section 8.4 cannot. And it can refuse an adversary who satisfies every stated condition, which a gate structurally cannot, because anybody who can buy in gets in.

What it costs is what the Motivation names. The grant outlives the reason for it, nothing about a row being answerable to anything. It cannot be audited by its subject, who can neither read the rule that excluded them nor discover that no rule did. It bottlenecks on whoever holds the write. It is not portable, being a row in one vendor's table. And whoever writes it bears none of the cost of writing it wrongly, which is the moral hazard this document opens by objecting to. A gate does not discipline that administrator; it removes the object they were writing to.

Token-gated rooms as a product category. Guild.xyz, Collab.Land and Discord's own role gating have shipped hold-a-token-get-a-role for years, and Lens and Farcaster channels do a version of it too. The mechanism there is a service: a bot holds an API key, checks a wallet on a schedule, and writes a row into a platform's membership table. What it produces is a list — the gate runs once and its output is an entry that persists until something else removes it, which is why those systems need periodic re-checks and why their failure mode is a stale roster nobody notices.

So the product category is a stored grant with an automated writer. It moves the discretion from a person to a bot and leaves the row where it was, which is why the trust it asks for is the same trust: the reader must believe a service they cannot inspect about a check they did not witness against a table they cannot read.

The difference this document draws is that the predicate is the membership. There is no row to write, so there is nothing to go stale; the answer is recomputed by whoever is rendering, from facts the reader's own client can verify, rather than asserted by a service the reader must trust. Four consequences follow that neither the product category nor the stored grant has. The rule is portable, being a signed object rather than a configuration inside one platform, so a room survives the platform it was formed on. The excluded reader can read it, because it is published rather than held in a bot's database, which is what makes a refusal answerable. Roles fall out of the same evaluation, so a moderator who sells the qualifying item is demoted by arithmetic rather than by a synchronisation job that may never run. And there is no privileged reader: the room's own operator evaluates the same predicate over the same public facts as everybody else, and cannot admit a favourite without changing the rule where the participants can see it.

That last one is the whole of the difference from a centralised system, and it is worth stating as a limit rather than as a boast. A gate does not make an operator honest. It makes an operator's dishonesty a signed, published edit to a rule with a notice period attached (section 2.4), rather than an unlogged row in a table nobody outside can read.

Specification

The key words MUST, MUST NOT, SHOULD, SHOULD NOT and MAY are to be interpreted as described in RFC 2119. They are used sparingly, and where interoperability actually breaks; the rest of this document describes a mechanism.

Throughout, "resolve" means the client resolution algorithm of BRC-169 section 5.7, and "handle" has the meaning given in BRC-169 section 2.1.

1. Terminology

  • Room: as described in the Motivation — more than two parties, persistent contents, an enumerable participant set, a stable identifier and a holder.

  • Reading: rendering a room's contents to someone. Every gate here governs reading.

  • Admission: becoming a participant — a different thing from reading, and specified only for a room that publishes a condition.

  • Manifest: the conditions attached to a room, encoded per section 2.

  • Condition: one typed test a reader is evaluated against. Five are configured in a manifest and are on or off; the ban of section 4.6 is configured nowhere and applies to every room.

  • Verdict: the outcome of evaluating a manifest against a reader — qualifying, failing, or indeterminate.

  • Holder: the single identity that holds a room. Custody, not qualification.

  • Role: what a participant may do, derived per section 7.

2. The Manifest

A manifest is a signed JSON object attached to a room. Every condition that is on must pass; there is no OR across types, because a room admitting readers who satisfy either of two unrelated conditions is two rooms and the reader cannot tell which one they are in. A condition that is on but not yet configured admits — manifests are edited in live rooms, and a half-typed condition that locks everyone out for the seconds it takes to finish typing is a broken editor rather than a strict door.

Three properties are load-bearing enough to state as requirements. The manifest MUST be readable by anyone who can see the room exists, including readers who fail it, since a rule you cannot read is a rejection with the reason withheld. It MUST NOT enumerate the identities it admits: naming a handle as an attestor is a condition on the reader, while naming one as an admittee is a membership list with extra steps. And a change to it is reported in the room, being at least as much the participants' business as a change to the room's name.

Where a manifest states at least one condition, admission is self-service: a reader who satisfies it may join without anybody's approval. A room that has stated no condition has published nothing to satisfy, so nothing here entitles anyone to join it — an ungated room is not thereby open to strangers, and how somebody joins one is out of scope. Discovery is out of scope too; section 6 governs what a reader sees once they have a room's identifier, not whether rooms are listed anywhere.

2.1 Shape

Field
Type
Required
Meaning

version

integer

yes

format version; 1 for this document

counter

integer

yes

monotonic per room

signedAt

block height

yes

the chain-anchored moment of signing, per 2.4

room

string

yes

room:<domain>/<local>, per 2.2

holder

handle

yes

custody

effectiveFrom

block height

no

when this manifest starts deciding, per 2.4

replaces

digest

no

the manifest superseded; required while pending

burn

outpoint

no

the unspendable output of 2.4, where ungating

ungateBurn

decimal string

conditional

satoshis to burn to ungate; required while any condition is on

successor

handle

no

who may assume custody after dormancy, per 8.3

dormantAfter

blocks

no

holder silence after which successor may sign, per 8.3

token vouch renounce quorum fee roles

object

no

conditions, per 2.3

An absent condition and one present with "on": false evaluate identically; the distinction exists for an editor holding a half-configured condition and nowhere else.

Condition shapes:

There is no ban condition, and section 4.6 says why: a ban is a decision about one person rather than a rule about who may enter, so it is carried in the room's record and applies whether or not a manifest exists.

mode is "any" or "all" and is present wherever the field it governs holds more than one entry; each gate type below gives the default when it is absent, because the two produce very different rooms and neither is obvious enough to leave to a client. minimums{}, shares{} and fees{} are keyed by asset reference, canonicalised as <protocol>:<id>. On a timelock condition minimum is satoshis and blocks is a count, both per section 4.5; in roles, weights{} takes a role name to a lock weight in satoshi-blocks. source names where a client may look for facts it cannot hold itself: the attestation lookup of section 4.2 on a vouch, renounce or quorum condition, and the chain indexer of section 4.1 on a token condition. In both cases it is a hint and not an authority, per those sections. In roles, each map takes a role name — "admin", "mod", "member" — to its threshold.

Two encoding rules matter for agreement rather than taste. Thresholds are decimal strings, compared as decimals — always, not where precision demands it, since a rule that applies sometimes is one two implementations will disagree about the boundary of. And the manifest is canonicalised per RFC 8785 before signing, or two encodings of the same rule hash differently and the integrity check below means nothing.

A client rejects rather than partially evaluates a manifest carrying more than one condition of each type or more than sixteen entries in any array. A manifest naming two hundred contracts forces two hundred lookups on every render, which makes a room a denial-of-service instrument against everyone who opens it.

A client meeting a version it does not know treats every condition as indeterminate rather than evaluating the subset it recognises, since silently ignoring an unrecognised condition admits people the room excluded. The cost is that a version bump is a hard break; a later document wanting a gradual path should add optional conditions within version 1.

2.2 Identifiers

A room identifier is room:<domain>/<local>, the domain being one the holder's ecosystem controls. Uniqueness comes from the domain exactly as it does for handles, since a bare local string collides the first time two ecosystems both have a room called general.

An asset is named by a pair — a protocol and an id meaningful within it. This document registers 1sat (an origin outpoint, <txid>_<vout>) and bsv21 (a token id); a client meeting an unregistered protocol returns indeterminate rather than failing the reader. An asset MUST NOT be identified by name: a collection called "Naka Motor Club" is a display string anybody can choose, so a gate on a name is one an impersonator satisfies by minting a contract with the same one. Clients show the name beside the reference, resolved from it rather than the other way round.

2.3 Integrity

A manifest is signed over its canonical form by the holder named in the manifest it replaces, or for a room's first manifest by the holder in the room's creation record. Nobody else: a role derived from a holding carries no authority to rewrite the rule that derived it, and an arrangement letting admins sign successors lets any of them name themselves holder and keep the room. Roles govern the day to day; custody governs the rules. It follows that an acting admin under section 7.4 cannot change a manifest — succession lets an abandoned room be moderated, not re-founded.

A client MUST verify the signature before evaluating, and MUST treat a manifest that fails verification as indeterminate rather than absent. Absent means ungated, so a relay able to turn a gated room into an ungated one by corrupting a byte would have the cheapest possible attack on all of this. The counter must exceed the highest already accepted for that room, or a relay can replay yesterday's manifest and quietly readmit somebody excluded this morning.

Signing defends against alteration and not against deletion, since removing a manifest achieves what corrupting one cannot. Two rules close most of that gap: a room's creation record states whether the room carries a manifest, and a client served none for a room whose record asserts one treats it as indeterminate; and a client that has accepted a manifest never afterwards treats that room as ungated without a later signed manifest turning the conditions off. Together they cover the returning reader completely and the first-time reader as far as the creation record can be trusted. A reader handed a forged creation record for a room they have never seen cannot detect it from within this document — where that matters, the room's identifier should commit to its creation record.

2.4 Change

A room's rules have to be changeable; a room that cannot be gated after the fact must know on the day it is created what it will become, and no room knows that. But rules rewritable at will are not much use either, and the people rewritten are the ones who never agreed to the new version.

The instinct is to make the first gate easy and later ones hard. The axis that matters is not first-versus-later but who a change puts out of the room.

A change excluding nobody currently in the room takes effect immediately — turning a condition off, lowering a threshold, removing an attestor, widening a band. A change that would newly exclude a current participant carries an effectiveFrom at least 1,008 blocks beyond its signedAt, is reported when signed rather than when it lands, and shows affected participants that they are affected. Until then the manifest it replaces continues to decide.

The same interval applies to a change that would demote a current participant without excluding them. A role threshold raised past somebody currently moderating takes their capability away, and the fact that they can still read the room does not make that a change they should discover by finding a control missing. Section 7.1 already requires that a demotion be told directly; this requires that a demotion by rule change be told in advance.

Which of the two a change is MUST be decided by comparing the manifests, per section 2.5, and MUST NOT be decided by evaluating current participants. The obvious implementation — apply the proposed rule to the roster and see who drops out — is the balance oracle the Security Considerations warn about, and it would make the notice rule of this section implementable only by running it.

Both are block heights rather than wall-clock times, and signedAt exists so that the interval has a reference point inside the object it constrains. A notice measured in days would need a clock two clients agree on, and they do not have one: skew between them would land a tightening at different moments in each, which is exactly the disagreement section 3.1 exists to prevent. A height is a fact both can look up. At the network's ten-minute target 1,008 blocks is about a week, and it is a week measured in the only unit the parties share.

Two details make the notice real rather than nominal. A pending manifest carries replaces, the digest of its predecessor, and a client holding no copy of that predecessor fetches it or returns indeterminate — otherwise the notice protects only clients already watching, and a reader arriving mid-window served nothing but the pending manifest would apply the tightening early. And at most one change may be pending: signing a new manifest replaces any pending one and restarts its notice, without which a holder can chain changes so the notice never arrives, or announce a mild change and swap a harsher one into a clock the room has already read.

The asymmetry people expect falls out of this rather than being stipulated. A room's first gate is usually chosen to fit the people already in it, because the room formed around the thing it gates on; such a gate excludes nobody and lands at once, which is why upgrading an ordinary group chat is easy. A later change is usually made because somebody should not be there. Those exclude, and those wait.

Grandfathering is not available, and the reason is structural. Letting existing participants keep access under the old rule means recording who was admitted under which manifest — a list of individuals with privileges attached, the exact object this document exists to replace. The notice preserves nobody's access; it gives them time to keep it or to leave with warning, which is less than grandfathering and is honest about being less.

Ungating is the one change that cannot be undone. It excludes nobody, so the rule above would land it instantly, and it exposes everything already said to everybody arriving afterwards — people spoke under a rule about who would hear them. So a manifest with any condition on declares ungateBurn, the amount that turning them all off will cost, and turning them off references an output that is provably unspendable and worth at least that much, verified before the change is accepted and treated as indeterminate where it cannot be verified, which leaves the gate standing.

The amount is declared rather than computed, because a computed one is not checkable. An earlier draft scaled it by participant count, which two clients verifying at different moments would count differently and so disagree about whether an ungating was valid — a rule that fails the agreement of section 3.1 is not a rule. A declared figure sits in a manifest anybody can read before they speak, which is the disclosure that makes it useful: a room declaring nothing is telling its members that their history is one signature from public, and that is information they can act on. It may be raised at once, since raising it excludes nobody and takes nothing away. Lowering it follows the notice above, because it withdraws a protection participants have been relying on even though it puts nobody out of the room.

What the burn buys is narrow and worth stating. It does not protect the archive; anyone determined to publish a room's contents copies them out without touching the manifest, and no rule here could stop them. It makes the supported path deliberate, verifiable by anyone, and profitable to nobody — the amount is destroyed rather than paid, so no participant, holder or third party gains from a room being opened and no constituency forms around making it happen. Provably unspendable means exactly that: a famous address that has never been spent from is an ordinary output whose key may exist, which makes it a gift to whoever holds that key rather than a cost to nobody.

2.5 Comparing two manifests

Section 2.4 turns on whether a change excludes anybody, and that question has an answer that does not require knowing who is in the room.

Manifest X is at least as strict as Y when every reader admitted by X would also be admitted by Y. The relation is about admitted sets and not about text. It is a partial order: a rule requiring a vouch from @deggen and one requiring a vouch from @crumbs admit neither a subset nor a superset of the other, and no amount of comparison will sort them.

Where the replacement is no stricter than the manifest it replaces, no reader who qualified stops qualifying — for every possible reader, not merely for the present ones — and the change takes effect immediately.

A manifest is a conjunction: section 2 admits only readers who pass every condition that is on. So turning a condition on is stricter, turning one off is looser, and otherwise the comparison is condition by condition:

Condition
Stricter when

token

minimums or shares raised, per asset; assets[] shrinks under mode: any, or grows under mode: all; mode anyall

vouch

handles[] shrinks under any, or grows under all; mode anyall

renounce

handles[] grows under any, or shrinks under all

quorum

count raised, or distinctEcosystems false → true

timelock

minimum raised, or blocks raised

fee

amount raised, period shortened, or asset or to changed

roles

never — a role map admits nobody and excludes nobody, and is compared for demotion under 2.4 rather than for exclusion

source, on any condition

never — section 4.1 makes it a hint a client may decline, so it cannot move the admitted set

Renounce runs the other way, and an implementation will get this wrong. Every other condition admits on a match; renounce excludes on one and admits by default (section 4.3). Adding a handle to a vouch gate under mode: any gives the reader another way in, and adding one to a renounce gate under the same mode gives another party the power to shut them out. Same field, same keyword, opposite sign.

ban does not participate. It appears in no manifest (section 4.6), so there is nothing to compare.

The comparison is sound and incomplete, and the incompleteness is the price. Proving that a replacement admits a superset proves that nobody is excluded; failing to prove it does not mean anybody is. Raising a minimum from 500 to 600 in a room where everybody holds thousands is stricter by this order and excludes nobody in fact, and the room waits 1,008 blocks anyway. Where two manifests are incomparable a client MUST treat the change as excluding, which means swapping one attestor for another also waits.

Erring this way is deliberate. The alternative to a conservative structural test is an exact one, and the only exact test is to run the proposed rule against the people in the room — which yields, for whoever is editing, a per-member verdict they can refine by editing again. A week's delay on a harmless change is a smaller cost than shipping that.

A room that wants an exact answer may ask its members for one: each client evaluates the proposed manifest against its own user and returns whether they still qualify. That discloses one boolean per member instead of a quantity, supports no binary search, and licences immediate effect where every current participant answers yes. It requires the members to be present and willing, so it is a fallback rather than the rule.

3. Evaluation

3.1 Order and determinism

Two conforming clients evaluating the same manifest against the same reader from the same facts MUST reach the same verdict. Conditions are evaluated ban, renounce, vouch, quorum, holding, timelock, fee, and the first failure is the one reported. The order runs from the most categorical to the most quantitative, so the reason a reader sees is the most fundamental rather than an accident of iteration. A ban comes first because it is the only one a person in the room decided — telling a reader they do not hold a token when the truth is that a moderator excluded them gives them a reason they cannot act on. The fee comes last because it presupposes the holding it accompanies.

Where a client cannot obtain a fact, the verdict is indeterminate: not passing, not failing, and surfaced as its own state. Fail-open is the obvious hazard; fail-closed-and-say-nothing is the subtler one, because "you do not qualify" and "I could not check" send a reader to do entirely different things.

3.2 Freshness

A gate is evaluated against a reader's current standing rather than their standing when they joined — balances are spent, vouches withdrawn, statements written. A cached verdict does not outlive the shortest ttl of the resolutions it depended on, and does not exceed five minutes where no ttl is available; "bounded" without a bound is a requirement every implementation satisfies and no two satisfy alike. A cache is discarded on a key change for that reader under BRC-169 section 4.4, since the facts a gate reads are facts about a key. Discarding the verdict is not the same as concluding the reader has nothing; section 8 covers what a rotation should and should not cost them.

3.3 Verdicts

A verdict is produced as data and rendered afterwards, never produced as a sentence:

The outcomes are qualifies, fails and indeterminate and no others. condition is one of ban, renounce, vouch, quorum, token, timelock, fee; index says which entry of a multi-entry condition decided; period accompanies a fee verdict; height accompanies a timelock verdict, per section 4.5(4); shortfall accompanies a quantitative failure, and on a timelock condition it carries whichever of the two figures fell short:

Naka Motor Club — 2,222 items

band in band band and above share of supply Exotic 22 22 0.99% Legendary 66 88 3.96% Epic 134 222 9.99% Rare 333 555 24.98% Uncommon 555 1,110 49.95% Common 1,112 2,222 100.00%

Canonical form, 351 bytes:

SHA-256:

Ordering

A manifest with a renounce condition naming @deggen@lkup.net and a holding condition requiring an asset, evaluated against a reader who is both renounced and holds nothing. Section 3.1 fixes which failure is reported:

Not token. Both conditions fail; the order decides, and an implementation reporting the holding has an iteration-order bug that will show up as two clients giving a reader different reasons.

Decimal comparison

A minimum of "0.3" against a holder of "0.1" plus "0.2". Compared as decimals the holder meets it exactly; compared as IEEE-754 doubles the sum is 0.30000000000000004 and the holder appears to exceed it. Both admit here, so the bug is invisible — which is why the vector below is the one that matters.

A minimum of "0.3" against a holder of "0.29999999999999998". As decimals this fails. As doubles it is indistinguishable from 0.3 and passes. An implementation admitting this reader is not conforming, and section 2.1's decimal rule exists for exactly this case.

Third-party disclosure

The same failing verdict, computed for the reader themselves and for anybody else:

An implementation emitting the first form in a roster, a picker, a preview or an export has leaked a balance, and section 3.3 forbids it on every surface rather than only the visible ones.

Appendix A: Worked Examples

A.1 A rarity-gated room

Signed by @crumbs@nexus.app over the RFC 8785 canonical form. The contract publishes 2,222 items in the six bands tabulated in section 7.3.

@randy@twetch holds item #1872, band Epic. No renounce, vouch or quorum condition is present, so the holding condition decides:

Epic is above Rare in the contract's order and below Exotic, so the role is mod. The client renders a badge; it does not render the band to other participants, a band being a quantity about a third party.

@lena@handcash holds nothing from the contract:

No shortfall — the condition is a holding rather than a threshold, so there is no quantity to fall short by. She is shown the room's existence, name and participant count, and told which requirement she does not meet.

If the client cannot reach an indexer for the contract:

Contents are not rendered, and she is told the check could not be performed rather than that she failed it.

A.2 A fungible gate with a fee

The minimum is the door at 500 units; the share is the admin threshold, permitted only because a minimum is present. The fee is in the same asset, names its recipient, and its first week is paid as part of joining. The role map uses both vocabularies — mod by absolute amount, admin by share — which is the pairing section 7.3 recommends for a room larger than its concentration.

A reader holding 6,000 units of a 10,000,000 supply, paid up:

Their role is mod: 6,000 clears the 5,000 threshold, and 0.06% of supply does not clear 21.8%. Three weeks later, having stopped paying:

The holding still passes and the fee does not. They are told directly and in full; the roster shows them lapsed without saying by how much. Nothing is deducted and nothing pursues them — the only consequence of not paying is that the room stops rendering.

References

Last updated

Was this helpful?