asobi_extension_reserved (asobi v0.84.0)
View SourceThe names core keeps for itself.
asobi_extensions:validate/1 refuses an owns/0 claim on anything in here,
so an extension cannot shadow a core table, a core Lua namespace, a core error
domain or a core job queue.
Every list is derived from the live core source rather than restated, so it cannot drift:
lua from
asobi_lua_surface:reserved_namespaces/0, the one place thegame.*vocabulary is written down.tables from every core
kura_schemamodule'stable/0, found the same way asobi finds an extension's schemas.queues from every core
shigoto_workermodule'squeue/0.rpc from the domains of
asobi_error:core_codes/0, the Lua namespaces, andcore_wire_prefixes/0. An RPC prefix and an error domain are the same token by construction ({"code": "quests.name_taken"}), so an extension owning thestorageprefix would mint codes inside core's closed code set.core_wire_prefixes/0adds the wire frame families a code domain and a Lua namespace between them miss -session,presenceandmodule- so an extension can neither mint asession.*code nor emit asession.connectedevent underasobi_extensions:emit/4.core_codes/0rather thancodes/0on purpose:codes/0includes the codes the installed extensions declare, and reserving those would tell an extension it may not claim the namespace it just claimed.http from the route tables of every co-mounted application - the same list Nova compiles,
[nova, asobi | nova_apps]- so/health,/readyand/live(served bynova_resiliencein both shipped configs) are as unclaimable as core's own paths. asobi's table comes fromasobi_router:core_routes/0, the groups without the extension mounts, because this runs insideasobi_extensions:resolve/0and reading the full table there would re-enter the resolver before its term exists; every other app's comes from its<app>_router:routes/1. A path any co-mounted app serves can never be re-served, or shadowed under a binding, by an extension.
On top of the derived set, route_prefixes/0 names the privileged plane
roots (/api/v1/ops, /api/v1/auth, /api/v1/iap, /api/v1/rpc, /console,
/ws): no extension route may sit anywhere under them, whatever it would
resolve to. This is a policy list, not a derivation - which sub-paths of a
plane are sensitive is a judgment the route table cannot express.
core_capabilities/0 answers the mirror-image question owns/0 does not:
not "what may an extension never claim" but "what may an extension depend on".
A subsystem name here can be named in requires/0 yet never in owns/0 - you
may call into economy, never claim its namespace - so the two roles sit in
one module because both are the authority on core's own subsystem names.
Deriving from modules costs one code:ensure_loaded/1 sweep over core's
module list. asobi_extensions only asks for it when at least one extension
is installed, so a node with none pays nothing.
schema_tables/1 and worker_queues/1 are the two derivation rules
themselves, exported over an arbitrary module list. asobi_extensions runs
them over an extension's modules to derive that extension's table and queue
claims, so core's names and an extension's names are found by the same rule
rather than by two that can disagree.
Summary
Functions
The core subsystem names an extension may name in requires/0.
The core wire frame-family prefixes with no error domain and no Lua namespace.
The namespace kinds an extension may claim in owns/0.
Core's reserved token set, per namespace kind.
The privileged plane roots. No extension route may sit anywhere under one -
mounting an open webhook handler inside the operator, auth, purchase,
extension-rpc, console or socket plane is refused whatever the path would
resolve to. /api/v1/rpc is the core rpc dispatcher's own HTTP route
(asobi_rpc_controller), reserved so an extension cannot shadow the frozen
POST /api/v1/rpc/<method> surface through its routes/0.
Every table declared by a kura_schema module in this list.
Every queue declared by a shigoto_worker module in this list.
Types
Functions
-spec core_capabilities() -> [asobi_extension:name(), ...].
The core subsystem names an extension may name in requires/0.
A documented constant, not a derivation, and deliberately so. The names an
extension depends on are the extraction-unit names - the one each subsystem
carries out of core as its own package, so asobi_leaderboards's
info().name is leaderboards - and no single core artefact spells that set:
the game.* Lua namespaces are singular and partial (leaderboard, no
world or tournaments at all) and the error-code domains mix machinery in.
So the set is written here, one atom per subsystem, tied to its src/
directory and its extraction wave. It has two groups: the extraction-unit
names, each of which becomes an extension of exactly that name; and the
kernel-permanent runtime subsystems an extension may call into but that never
leave core (matches, world, votes, presence, timers). Only the first
group moves.
The resolution set asobi_extensions validates a requires/0 against is the
union of this set and the installed extensions' own names, and that union is
why the set stays correct across an extraction: when a subsystem leaves core
its atom is deleted here and reappears as the extracted package's
info().name, so a requires on it moves from the core side of the union to
the extension side with the same answer - satisfied, because the bundle
installs the package. Sub-parts are named by the unit that extracts, never
separately: use economy for inventory, chat for dm, matches for the
matchmaker or match-scoped zones, world for world zones and terrain.
-spec core_wire_prefixes() -> [asobi_extension:token(), ...].
The core wire frame-family prefixes with no error domain and no Lua namespace.
error_domains/0 and lua/0 between them cover most core wire frame families -
match.*, world.*, chat.*, matchmaker.* and the rest all have an error
code or a game.* namespace under the same prefix. Three do not:
session(session.connected,session.heartbeat),presence(presence.updated),module(module.message,module.error,module.event, the frames an extension pushes - the last throughasobi_extensions:emit/4).
An RPC prefix, an error-code domain and an event domain are one token by
construction, so without reserving these an extension could own session in
owns/0 and mint a session.* code or emit a session.connected event,
colliding with a core frame family. This constant is a documented list rather
than a derivation precisely because no core artefact names these prefixes -
they exist only as wire type literals in asobi_ws_handler. Folded into the
reserved rpc union, so the gap closes for error codes and the module.event
event seam alike.
-spec kinds() -> [kind(), ...].
The namespace kinds an extension may claim in owns/0.
-spec namespaces() -> #{kind() := [asobi_extension:token()]}.
Core's reserved token set, per namespace kind.
-spec route_prefixes() -> [asobi_extension:token(), ...].
The privileged plane roots. No extension route may sit anywhere under one -
mounting an open webhook handler inside the operator, auth, purchase,
extension-rpc, console or socket plane is refused whatever the path would
resolve to. /api/v1/rpc is the core rpc dispatcher's own HTTP route
(asobi_rpc_controller), reserved so an extension cannot shadow the frozen
POST /api/v1/rpc/<method> surface through its routes/0.
-spec schema_tables([module()]) -> [asobi_extension:token()].
Every table declared by a kura_schema module in this list.
-spec worker_queues([module()]) -> [asobi_extension:token()].
Every queue declared by a shigoto_worker module in this list.