extends RefCounted ## Venue-correct access artifacts (override_access, no free recognition on guests). const Rules := preload("res://src/core/rules.gd") const AccessLoadout := preload("res://src/core/access_loadout.gd") const AccessVerifier := preload("res://src/core/access_verifier.gd") const ScenarioFactory := preload("res://src/content/scenario_factory.gd") const NpcProfile := preload("res://src/core/npc_profile.gd") var verifier := AccessVerifier.new() func _guest() -> NpcProfile: var p := NpcProfile.new() p.id = "authorized_guest" p.display_name = "Authorized Guest" p.npc_type = Rules.NpcType.AUTHORIZED_GUEST return p func _staff() -> NpcProfile: var p := NpcProfile.new() p.id = "authorized_staff" p.display_name = "Staff Member" p.npc_type = Rules.NpcType.AUTHORIZED_STAFF return p func _kinds(artifacts: Array) -> Array: var out: Array = [] for a in artifacts: out.append(a.kind) return out func test_joke_guest_valid_needs_screen_then_grants() -> bool: var policy = ScenarioFactory.joke_shop().access_policy var arts: Array = AccessLoadout.build(_guest(), policy, {"has_id": true, "has_ticket": true}) var has_rec := false for art in arts: if art.kind == Rules.AccessKind.RECOGNITION: has_rec = true var a := TestUtils.check(not has_rec, "no free recognition") var before := verifier.verify(arts, policy, false) var after := verifier.verify(arts, policy, true) var b := TestUtils.check_eq(before["granted"], false, "unscreened valid guest denied") var c := TestUtils.check_eq(after["granted"], true, "screened valid guest granted") return a and b and c func test_joke_guest_no_id_denied_even_when_screened() -> bool: var policy = ScenarioFactory.joke_shop().access_policy var arts: Array = AccessLoadout.build(_guest(), policy, {"has_id": false, "has_ticket": true}) var result := verifier.verify(arts, policy, true) return TestUtils.check_eq(result["granted"], false, "no-id guest denied") func test_joke_guest_expired_id_denied() -> bool: var policy = ScenarioFactory.joke_shop().access_policy var arts: Array = AccessLoadout.build(_guest(), policy, { "has_id": true, "has_ticket": true, "id_status": Rules.ArtifactStatus.EXPIRED, }) var result := verifier.verify(arts, policy, true) return TestUtils.check_eq(result["granted"], false, "expired id denied") func test_joke_event_payload_matches_factory() -> bool: var shop = ScenarioFactory.joke_shop() var found_expired := false var found_no_id := false for event in shop.event_pool: var ov: Dictionary = event.get("override_access", {}) if event.get("id", "") == "guest_expired_id": found_expired = int(ov.get("id_status", -1)) == Rules.ArtifactStatus.EXPIRED if event.get("id", "") == "guest_no_id": found_no_id = ov.get("has_id", true) == false var a := TestUtils.check(found_expired, "guest_expired_id carries expired status") var b := TestUtils.check(found_no_id, "guest_no_id has has_id false") return a and b func test_joke_staff_recognized_without_override() -> bool: var policy = ScenarioFactory.joke_shop().access_policy var arts: Array = AccessLoadout.build(_staff(), policy, {}) var has_rec := false for a in arts: if a.kind == Rules.AccessKind.RECOGNITION and a.status == Rules.ArtifactStatus.VALID: has_rec = true var screened := verifier.verify(arts, policy, true) return TestUtils.check(has_rec, "staff are recognized") and TestUtils.check_eq(screened["granted"], true, "recognized staff enter after screen") func test_building_guest_uses_wristband_not_recognition() -> bool: var policy = ScenarioFactory.hollywood_building().access_policy var arts: Array = AccessLoadout.build(_guest(), policy, {}) var has_rec := false var has_band := false for a in arts: if a.kind == Rules.AccessKind.RECOGNITION: has_rec = true if a.kind == Rules.AccessKind.WRISTBAND and a.status == Rules.ArtifactStatus.VALID: has_band = true var result := verifier.verify(arts, policy) var a := TestUtils.check(not has_rec, "building guest is not auto-recognized") var b := TestUtils.check(has_band, "building guest presents a wristband") var c := TestUtils.check_eq(result["granted"], true, "valid wristband grants") return a and b and c func test_studio_ticket_grants_without_recognition() -> bool: var policy = ScenarioFactory.tv_studio().access_policy var arts: Array = AccessLoadout.build(_guest(), policy, {"has_ticket": true}) var has_rec := false for a in arts: if a.kind == Rules.AccessKind.RECOGNITION: has_rec = true var result := verifier.verify(arts, policy) return TestUtils.check(not has_rec, "audience ticket is not recognition") and TestUtils.check_eq(result["granted"], true, "ticket grants at studio") func test_studio_counterfeit_denied() -> bool: var policy = ScenarioFactory.tv_studio().access_policy var arts: Array = AccessLoadout.build(_guest(), policy, { "wristband_status": Rules.ArtifactStatus.COUNTERFEIT, "credential_status": Rules.ArtifactStatus.COUNTERFEIT, }) var result := verifier.verify(arts, policy) return TestUtils.check_eq(result["granted"], false, "counterfeit studio artifacts deny") func test_carried_items_override_and_roll() -> bool: var forced: Array = AccessLoadout.roll_carried_items(1, {"carried_items": ["weapon"]}) var a := TestUtils.check_eq(forced, ["weapon"], "override items win") var rolled: Array = AccessLoadout.roll_carried_items(42, {}) var b := TestUtils.check(rolled is Array, "roll returns an array") var again: Array = AccessLoadout.roll_carried_items(42, {}) var c := TestUtils.check_eq(rolled, again, "same seed same pocket") return a and b and c func test_joke_shop_sidewalk_exists() -> bool: var shop = ScenarioFactory.joke_shop() var studio = ScenarioFactory.tv_studio() var a := TestUtils.check(shop.locations.has("sidewalk"), "joke shop sidewalk") var b := TestUtils.check(studio.locations.has("sidewalk"), "studio sidewalk") var c := TestUtils.check_eq(shop.waypoint_for_intent("film").z, shop.locations["sidewalk"].z, "film walks to sidewalk") return a and b and c