Phase 1 (plugin side) of docs/ADMIN_CONTROLS.md: a staff write plane so the website can moderate the live shard. - BridgeAdmin.cs: inbound admin.kick, admin.ban (timed + indefinite), admin.unban, admin.broadcast. Each requires an `actor`, refuses targets at or above AdminAccessFloor (default CoOwner — Owner-only shield), replies admin.ok/admin.error with the reqId echoed, and emits an admin.audit (origin=web) broadcast. Attribution is web:<actor> in the console log and the ban BanDealer tag. Kicking enumerates NetState.Instances so a character-select session is caught too. - BridgeConfig/Bridge.cfg: AdminWriteEnabled (default OFF — opt-in), AdminAccessFloor, broadcast/reason length caps, ban duration clamp. - tools/stub_sidecar_admin.ps1: live smoke-test harness; *.log gitignored. Verified: compiles clean against ServUO (0 err/warn); live run on the seeded shard confirms all four verbs, the audit stream, timed-ban fields, and the Owner-floor refusal, with no exceptions. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0114TpmrNW4wNXsHq5CR72jQ
54 lines
2.3 KiB
INI
54 lines
2.3 KiB
INI
|
|
# uo-link bridge settings.
|
|
#
|
|
# Key scope is the filename: Bridge.cfg + StatSweepSeconds => "Bridge.StatSweepSeconds".
|
|
# Read in Configure(), which runs before World.Load.
|
|
|
|
# Loopback only. The socket being local is the trust boundary for inbound commands;
|
|
# if the sidecar ever moves off-host, add a shared secret first.
|
|
Host=127.0.0.1
|
|
Port=7788
|
|
|
|
# Outbound queue cap. On overflow the plugin drops oldest and counts the drops,
|
|
# because a stalled sidecar must never OOM the shard.
|
|
QueueCap=10000
|
|
|
|
# Sweep intervals, seconds. Measured on a 150-character shard: a vitals sweep costs
|
|
# 0.0015 ms/char, so 1000 online players is ~1.5 ms per sweep. See docs/PLAN.md §1.
|
|
StatSweepSeconds=30
|
|
DecaySweepSeconds=60
|
|
EconomySweepSeconds=300
|
|
|
|
# Shown to a player when they run [link. The website page where they enter the code.
|
|
LinkUrl=https://yoursite/link
|
|
|
|
# Town-crier news pushed from the website. Caps are defense in depth on top of the
|
|
# loopback trust boundary: a buggy or compromised sidecar still cannot flood the criers.
|
|
TownCrierMaxLines=6
|
|
TownCrierMaxLineLength=200
|
|
TownCrierMaxActive=20
|
|
TownCrierMaxDurationSec=86400
|
|
|
|
# Admin write plane (staff moderation from the website). OFF by default: the whole
|
|
# feature is opt-in per shard. When enabled, inbound admin.* commands (kick/ban/unban/
|
|
# broadcast) are honored. Authorization is enforced on the website; the shard trusts the
|
|
# loopback socket and applies a hard floor below.
|
|
AdminWriteEnabled=false
|
|
|
|
# The one shard-side safety floor. An admin.* command refuses any target whose AccessLevel
|
|
# is at or above this, so even a compromised sidecar can never touch the Owner. Values are
|
|
# AccessLevel names (Player, VIP, Counselor, Decorator, Spawner, GameMaster, Seer,
|
|
# Administrator, Developer, CoOwner, Owner). Default CoOwner => only Owner/CoOwners shielded.
|
|
AdminAccessFloor=CoOwner
|
|
|
|
# Defense-in-depth caps on admin.* payloads (mirroring the town-crier caps).
|
|
AdminBroadcastMaxLength=300
|
|
AdminReasonMaxLength=400
|
|
# Clamp on a timed ban's duration, seconds. A ban with no/zero duration is indefinite.
|
|
AdminBanMaxDurationSec=31536000
|
|
|
|
# The test scaffolding in tools/scaffolding/ reads its own flags from this file
|
|
# (SeedOnStart, CensusOnStart, ProbeOnStart). They are absent here on purpose:
|
|
# Config.Get returns the default of false when a key is missing, so a deployed
|
|
# server never runs the scaffolding even if its .cs files are present.
|