docs(modules): module-rust supports Carbon too, ships a Pterodactyl egg, and the rigs move to the panel #253

Merged
whitlocktech merged 4 commits from docs/rust-carbon-and-pterodactyl into main 2026-09-16 02:54:25 +00:00

4 Commits

Author SHA1 Message Date
22159ec78f docs(modules): the Carbon rig, R19 proven, and one refuted claim
rust-carbon (id 18, 87fb1f67) is built on the same egg with FRAMEWORK=carbon,
a clean install rather than a converted one. Install 122s, boot 543s.

R19 is proven. The byte-identical RunicGateway.cs that runs on the Oxide rig,
with no conditional compilation in it at all, loaded on Carbon 2.0.259.0 and
behaved identically - same startup line, same no-stall retry against an absent
sidecar. That contract now holds on three platforms from one source file:
Windows/Mono, Linux/Oxide, Linux/Carbon.

R18's amendment is confirmed the best way it could have been. The plugin's own
config, written by the same Oxide-compat API on both rigs, landed at
oxide/config/RunicGateway.json on one and carbon/configs/RunicGateway.json on
the other. Had the R18 editor used a literal path it would not have found its
own plugin's config on half of all installs, and no test would have caught it.

One claim is REFUTED, and it was wrong about Oxide as well as Carbon. CARBON.md
said Oxide stores permissions as JSON and Carbon as Protobuf or SQLite. Both
rigs say otherwise: both store Protobuf, under IDENTICAL filenames
(oxide.users.data, oxide.groups.data), differing only in directory - Carbon
writes its own data into files named after Oxide. This strengthens R2's
API-only rule rather than weakening it: a file reader would have worked on both
rigs today and broken silently for the one operator who ran c.migrate_perms_sql.

Two things nobody had thought to claim, found by looking. Carbon auto-creates a
third default group, moderator, which R2's full-set push must tolerate or
report drift for ever. And c.plugins exposes per-plugin hook telemetry that is
most of section 6's fired-hook mechanism, free, and only on Carbon.

Also: a wrong console command is indistinguishable from success at the API.
Pterodactyl's command endpoint returns 204 either way and Carbon prints nothing
for an unknown command, so oxide.plugins on Carbon looks exactly like it
worked. Anything driving the console must read a log to know.

CARBON.md gains a scorecard (section 10) and drops its unproven banner.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016wDDVXWMDz82WqE1i969r4
2026-09-15 21:51:11 -05:00
069e715b1b docs(modules): the Pterodactyl rig as built, R22, and a correction
Section 14 records R21's first rig, made with the application key and driven
with the client key. Both work; neither can do the other's job, and there is
no egg-write endpoint at all, so a published egg is a JSON file a human
imports.

The tier-2 loop was run rather than described: phase 1's real RunicGateway.cs
pushed from the working tree, oxide.reload through the client API, the edit
observed in Oxide's own log, source restored. About ten seconds end to end.
Three things worked that were not certain to - files/write creates missing
parents, a plugin placed before Oxide exists survives Oxide arriving, and the
plugin compiles and loads on Linux, which no previous phase had established.

Two findings that change decisions. The image installs the framework on EVERY
boot, Carbon from the rolling production_build tag and Oxide from
releases/latest, so a restart is a framework upgrade and neither is pinnable
through the egg. And R20's "wrapper launches the sidecar then RustDedicated"
does not survive Carbon: the entrypoint prepends LD_PRELOAD to the whole
startup string, so the preload would land on the sidecar and the server would
start cleanly, report nothing, and be silently unmodded.

R22 (org lead): the sidecar's configuration moves into the egg's variables.
Nearly free - rust-link already reads all five keys from the environment with
env-over-file-over-defaults precedence - but the game bind must not be
operator-editable, the web bind must derive from an allocation, and the db
path must not be able to agree with REMOVE_FILES.

Also corrects an earlier claim in this branch. The client key listing zero
servers and includes returning empty were both CORRECT; the servers were
being deleted between reads. A differential diagnosis across two API calls
assumes the state did not move between them.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016wDDVXWMDz82WqE1i969r4
2026-09-15 21:30:06 -05:00
a29cdf0fae docs(modules): record the Pterodactyl client key and its empty-server-list problem
The token file now carries both keys. The client key authenticates as the
admin owner and then lists zero servers, on every listing type and for both
the short identifier and the full UUID, so tier 2 of R21's deployment loop is
not usable yet. Reinstall and SFTP are unaffected.

Records the diagnosis rather than only the symptom, including one trap worth
not repeating: includes are independently broken on this panel, so
servers?include=user returns an empty list where the same route without the
include returns six. Nothing built on an include is evidence about ownership.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016wDDVXWMDz82WqE1i969r4
2026-09-15 21:08:15 -05:00
5890da633f docs(modules): module-rust supports Carbon too, and ships a Pterodactyl egg
Three new decisions of record, and a new reference for the second modding
framework.

R19 - the bridge plugin is framework-agnostic from now, not ported later.
Carbon is not a fork of Oxide but a separate loader shipping an Oxide
compatibility layer, so one .cs in the Oxide.Plugins namespace serves both,
with #if CARBON only where the APIs genuinely differ. Three existing
decisions take an amendment and none is reversed: R18's config walk roots at
Interface.Oxide.ConfigDirectory rather than a literal oxide/config (Carbon
uses carbon/configs AND lets an operator relocate every directory from the
command line); R2's permission store is Protobuf or SQLite on Carbon, which
permanently closes the file-reading shortcut it never planned to take, while
the PermissionExists pre-check survives because Carbon's bool return is the
one thing we cannot read portably; R4's doctor asks which framework rather
than whether Oxide, and gets a weaker "current enough" claim because Carbon
ships rolling release tags.

R20 - a Pterodactyl egg is a third supported deployment path beside the
installer and the hand install, derived from the community "Rust Autowipe"
egg, which already carries a FRAMEWORK variable offering vanilla/carbon/oxide.
The sidecar runs inside the game's container, which is what lets D2 stand
unchanged: a container's 127.0.0.1 is genuinely private, so the game link
stays loopback and stays unauthenticated. Lands in phase 18 beside the
installer.

R21 - both rigs move to the Pterodactyl panel, because Oxide and Carbon
cannot coexist in one install and so a single server cannot prove R19. Also
retires the wipe-day maintenance that dominated section 4, and makes the rig
Linux where every prior finding came from Windows and Mono.

New: modules/rust/CARBON.md, the difference list - file layout, the
permission store, the c. commands, 30 Carbon-only hooks, and 13 uMod names
Carbon's catalogue omits (at least two of which look like renames). Sourced
from Carbon's own published metadata and source at main, and labelled
throughout as not yet proven on a live Carbon server.

One outstanding request, recorded in section 3: the panel token on disk is an
application key and Pterodactyl puts files, power and console on the client
API, so iteration needs a ptlc_ key only the account holder can mint.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016wDDVXWMDz82WqE1i969r4
2026-09-15 20:59:23 -05:00