OverviewFilesCommitsIssuesDocsReleasesPeers

hyper-tps / scenes / test / gate_admin_facade_meta.gd

79 lines · gd ref:
extends SceneTree
## Gate: AdminFacade's per-property / per-method configuration is SETTABLE.
##
## From 2026-05-18 until today it was not. The facade composed meta keys like
## `admin_role:<prop>:write` and `admin_call_scope:<method>`, and
## Object::set_meta REJECTS any name failing is_valid_ascii_identifier()
## (core/object/object.cpp:1036) -- a colon is not one. `git log -L` dates that
## guard to 2022-03-23, so it held for all of Godot 4: nothing could ever set
## them, every lookup fell back to its default, and the whole configuration
## surface was decorative. Zero writers existed in this repo's history.
##
## Tests the RESOLVERS directly rather than driving a full facade scan: the
## change is two pure helpers plus one dictionary read, and _scan() needs a
## current_scene that a bare SceneTree script does not have. An earlier version
## of this gate DID drive the scan, indexed nothing, and reported three passes
## that were really "unknown path" -- a broken instrument reading as success.

var ok := true

func _p(c: bool, m: String) -> void:
	print(("ok   " if c else "FAIL: ") + m)
	if not c: ok = false


func _initialize() -> void:
	var facade: Object = load("res://autoloads/admin_facade.gd").new()
	var target := Node.new()

	target.set_meta("admin_roles", {
		"secret": {"read": "admin", "write": "admin"},
		"volume": {"read": "peer", "write": "peer"},
		"peek": {"call": "peer"},
		"everything": "mod",            # shorthand: one role for every verb
	})
	target.set_meta("admin_call_scopes", {"peek": "local"})
	target.set_meta("admin_exposed_props", {"volume": true})

	# 1. the metas are SETTABLE at all -- the entire defect
	_p(target.has_meta("admin_roles"), "admin_roles is settable")
	_p(target.has_meta("admin_call_scopes"), "admin_call_scopes is settable")
	target.set_meta("admin_role:secret:write", "admin")
	_p(not target.has_meta("admin_role:secret:write"),
			"the OLD colon form is still rejected by the engine")

	# 2. per-property roles resolve, and fall back where unset
	_p(facade._role_for(target, "volume", "write", "admin") == "peer",
			"volume write role -> peer (overrides the admin default)")
	_p(facade._role_for(target, "secret", "read", "peer") == "admin",
			"secret read role -> admin (overrides the peer default)")
	_p(facade._role_for(target, "unlisted", "write", "admin") == "admin",
			"unlisted prop falls back to the documented default")
	_p(facade._role_for(target, "everything", "call", "admin") == "mod",
			"string shorthand applies to every verb")

	# 3. per-method call scope
	var scopes: Dictionary = target.get_meta("admin_call_scopes", {})
	_p(String(scopes.get("peek", "")) == "local", "peek scope -> local")
	_p(String(scopes.get("bump", "authority")) == "authority",
			"unlisted method falls back to authority")

	# 4. explicit opt-in is no longer a trap. admin_exposed_only is settable (no
	#    colon) but gated on `admin_exposed:<prop>` which was not -- so enabling
	#    it exposed ZERO properties, silently.
	_p(facade._prop_opted_in(target, "volume"), "opted-in prop reads as explicit")
	_p(not facade._prop_opted_in(target, "secret"), "non-opted prop does not")
	target.set_meta("admin_exposed_props", ["volume"])
	_p(facade._prop_opted_in(target, "volume"), "array form works too")

	# 5. a skipped call must not read as success (it could clobber the real
	#    result: every peer dispatches and writes the same admin:result:<seq>,
	#    LWW-by-ts).
	var skipped := {"ok": false, "skipped": true, "error": "not authority"}
	_p(not bool(skipped.get("ok", false)) and bool(skipped.get("skipped", false)),
			"skipped shape is ok:false + skipped:true")

	target.free()
	print("GATE admin_facade_meta: %s" % ("PASS" if ok else "FAIL"))
	quit(0 if ok else 1)