Skip to main content

AccessStateUtils

The verdict an AccessFeature produces, and the fold most features want.

Three outcomes, not two. disallowed(UNRESOLVED) means no answer came back yet -- a lookup still in flight, a service that failed, a realm that cannot resolve a fact at all -- and it is deliberately not the same as being denied. Each consumer decides what an unanswered question means for it: a storefront may offer on it, an enforcement gate must never open on it.

Types

AccessState

type AccessState = AccessAllowedState | AccessDisallowedState

AccessFactState

type AccessFactState = {[string]string}

Every declared fact and what it said, as an AccessFactContributionState.

Always present, never nil: a Lua table cannot hold a nil, so the old boolean? map silently lost exactly the facts that had not answered -- the ones a gate most needs to know about.

Properties

Reasons

AccessStateUtils.Reasons: {
UNRESOLVEDstring,
NOT_GRANTEDstring
}

The reasons this module produces on its own. A feature is free to return any other string; these are the two that fall out of the fact fold rather than out of game policy.

Functions

allowed

AccessStateUtils.allowed(grantedBy{string}?) → AccessAllowedState

Allowed, listing every fact that granted rather than the first one found. Callers surface grantedBy in debug output, so a state that was granted three ways says so.

disallowed

AccessStateUtils.disallowed(reasonstring) → AccessDisallowedState

unresolved

AccessStateUtils.unresolved() → AccessDisallowedState

isAllowed

AccessStateUtils.isAllowed(stateAccessState) → boolean

isUnresolved

AccessStateUtils.isUnresolved(stateAccessState) → boolean

Whether a state is specifically unresolved, for the callers that must not act on a non-answer.

key

AccessStateUtils.key(stateAccessState) → string

Two states are the same verdict when they deny for the same reason, or grant on the same facts.

fromFacts

AccessStateUtils.fromFacts(
factStateAccessFactState,
factNames{string}
) → AccessState

The fold most features want: any true fact allows, an unanswered fact leaves it unresolved, and only a complete set of false answers denies.

Order matters. A true fact wins even while another is still unresolved, because an answer that already grants cannot be changed by one that hasn't arrived -- waiting for it would keep an entitled player out for no reason.

fromAllFacts

AccessStateUtils.fromAllFacts(
factStateAccessFactState,
factNames{string}
) → AccessState

Granted only when every named fact allows, unresolved while any is unanswered, refused as soon as one denies.

The and-of that every flag-gated grant actually is -- isEarlyAccessTester and testerEarlyAccessEnabled -- so a feature can declare its shape rather than hand-write the fold.

fromNoFacts

AccessStateUtils.fromNoFacts(
factStateAccessFactState,
factNames{string}
) → AccessState

Granted when every named fact is definitely false, unresolved while any is unanswered.

The gate "does not own the game" needs this rather than a not: inverting the value turns unresolved into true, which is the difference between "we could not confirm" and "definitely does not own it" -- and on a purchase gate that difference is offering to sell something somebody already has.

anyAllowed

AccessStateUtils.anyAllowed(states{AccessState}) → AccessState

The first allowed verdict among these, else unresolved if any is, else the first refusal.

An or-fold over whole verdicts rather than over facts, which is what lets a composed feature keep both halves' reasoning instead of collapsing to a boolean on the way.

fromAnyFact

AccessStateUtils.fromAnyFact(factStateAccessFactState) → AccessState

The same fold over every fact present, for a feature whose fact list is not fixed when it is written. Safe now that states are always present -- it was not, when an unanswered fact vanished from the map.

Show raw api
{
    "functions": [
        {
            "name": "allowed",
            "desc": "Allowed, listing every fact that granted rather than the first one found. Callers surface `grantedBy`\nin debug output, so a state that was granted three ways says so.",
            "params": [
                {
                    "name": "grantedBy",
                    "desc": "",
                    "lua_type": "{ string }?"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "AccessAllowedState"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 66,
                "path": "src/access/src/Shared/AccessStateUtils.lua"
            }
        },
        {
            "name": "disallowed",
            "desc": "",
            "params": [
                {
                    "name": "reason",
                    "desc": "",
                    "lua_type": "string"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "AccessDisallowedState"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 74,
                "path": "src/access/src/Shared/AccessStateUtils.lua"
            }
        },
        {
            "name": "unresolved",
            "desc": "",
            "params": [],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "AccessDisallowedState"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 83,
                "path": "src/access/src/Shared/AccessStateUtils.lua"
            }
        },
        {
            "name": "isAllowed",
            "desc": "",
            "params": [
                {
                    "name": "state",
                    "desc": "",
                    "lua_type": "AccessState"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "boolean"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 91,
                "path": "src/access/src/Shared/AccessStateUtils.lua"
            }
        },
        {
            "name": "isUnresolved",
            "desc": "Whether a state is specifically unresolved, for the callers that must not act on a non-answer.",
            "params": [
                {
                    "name": "state",
                    "desc": "",
                    "lua_type": "AccessState"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "boolean"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 101,
                "path": "src/access/src/Shared/AccessStateUtils.lua"
            }
        },
        {
            "name": "key",
            "desc": "Two states are the same verdict when they deny for the same reason, or grant on the same facts.",
            "params": [
                {
                    "name": "state",
                    "desc": "",
                    "lua_type": "AccessState"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "string"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 111,
                "path": "src/access/src/Shared/AccessStateUtils.lua"
            }
        },
        {
            "name": "fromFacts",
            "desc": "The fold most features want: any true fact allows, an unanswered fact leaves it unresolved, and only a\ncomplete set of false answers denies.\n\nOrder matters. A true fact wins even while another is still unresolved, because an answer that already\ngrants cannot be changed by one that hasn't arrived -- waiting for it would keep an entitled player out\nfor no reason.",
            "params": [
                {
                    "name": "factState",
                    "desc": "",
                    "lua_type": "AccessFactState"
                },
                {
                    "name": "factNames",
                    "desc": "",
                    "lua_type": "{ string }"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "AccessState"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 131,
                "path": "src/access/src/Shared/AccessStateUtils.lua"
            }
        },
        {
            "name": "fromAllFacts",
            "desc": "Granted only when **every** named fact allows, unresolved while any is unanswered, refused as soon as\none denies.\n\nThe and-of that every flag-gated grant actually is -- `isEarlyAccessTester` *and*\n`testerEarlyAccessEnabled` -- so a feature can declare its shape rather than hand-write the fold.",
            "params": [
                {
                    "name": "factState",
                    "desc": "",
                    "lua_type": "AccessFactState"
                },
                {
                    "name": "factNames",
                    "desc": "",
                    "lua_type": "{ string }"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "AccessState"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 166,
                "path": "src/access/src/Shared/AccessStateUtils.lua"
            }
        },
        {
            "name": "fromNoFacts",
            "desc": "Granted when every named fact is definitely **false**, unresolved while any is unanswered.\n\nThe gate \"does not own the game\" needs this rather than a `not`: inverting the value turns unresolved\ninto true, which is the difference between \"we could not confirm\" and \"definitely does not own it\" --\nand on a purchase gate that difference is offering to sell something somebody already has.",
            "params": [
                {
                    "name": "factState",
                    "desc": "",
                    "lua_type": "AccessFactState"
                },
                {
                    "name": "factNames",
                    "desc": "",
                    "lua_type": "{ string }"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "AccessState"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 198,
                "path": "src/access/src/Shared/AccessStateUtils.lua"
            }
        },
        {
            "name": "anyAllowed",
            "desc": "The first allowed verdict among these, else unresolved if any is, else the first refusal.\n\nAn or-fold over whole verdicts rather than over facts, which is what lets a composed feature keep both\nhalves' reasoning instead of collapsing to a boolean on the way.",
            "params": [
                {
                    "name": "states",
                    "desc": "",
                    "lua_type": "{ AccessState }"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "AccessState"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 217,
                "path": "src/access/src/Shared/AccessStateUtils.lua"
            }
        },
        {
            "name": "fromAnyFact",
            "desc": "The same fold over every fact present, for a feature whose fact list is not fixed when it is written.\nSafe now that states are always present -- it was not, when an unanswered fact vanished from the map.",
            "params": [
                {
                    "name": "factState",
                    "desc": "",
                    "lua_type": "AccessFactState"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "AccessState"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 251,
                "path": "src/access/src/Shared/AccessStateUtils.lua"
            }
        }
    ],
    "properties": [
        {
            "name": "Reasons",
            "desc": "The reasons this module produces on its own. A feature is free to return any other string; these are\nthe two that fall out of the fact fold rather than out of game policy.",
            "lua_type": "{ UNRESOLVED: string, NOT_GRANTED: string }",
            "source": {
                "line": 27,
                "path": "src/access/src/Shared/AccessStateUtils.lua"
            }
        }
    ],
    "types": [
        {
            "name": "AccessState",
            "desc": "",
            "lua_type": "AccessAllowedState | AccessDisallowedState",
            "source": {
                "line": 46,
                "path": "src/access/src/Shared/AccessStateUtils.lua"
            }
        },
        {
            "name": "AccessFactState",
            "desc": "Every declared fact and what it said, as an [AccessFactContributionState].\n\nAlways present, never nil: a Lua table cannot hold a nil, so the old `boolean?` map silently lost\nexactly the facts that had not answered -- the ones a gate most needs to know about.",
            "lua_type": "{ [string]: string }",
            "source": {
                "line": 57,
                "path": "src/access/src/Shared/AccessStateUtils.lua"
            }
        }
    ],
    "name": "AccessStateUtils",
    "desc": "The verdict an [AccessFeature] produces, and the fold most features want.\n\nThree outcomes, not two. `disallowed(UNRESOLVED)` means no answer came back yet -- a lookup still in\nflight, a service that failed, a realm that cannot resolve a fact at all -- and it is deliberately not\nthe same as being denied. Each consumer decides what an unanswered question means for it: a storefront\nmay offer on it, an enforcement gate must never open on it.",
    "source": {
        "line": 12,
        "path": "src/access/src/Shared/AccessStateUtils.lua"
    }
}