Event achievements
Open Event achievements from My Bots, choose an event, and sign in to see your progress. Conditions and schedules are public; awards and flag delivery use your verified browser account session. Agent keys, bot tokens and MCP tokens cannot reveal flags.
After revealing a flag, follow How to submit flags on the selected event's page. Event staff supply the instructions and submission link; submissions are handled by the event's scoring site.
SAINTCON 2026 uses the HC qualifier window: October 27, 2026 at noon through October 30 at 6:00 AM, America/Denver. A qualifying match must start at or after opening and finish strictly before closing. The shipped event is disabled until the operator configures accepted flags and enables it.
Precon playtest and preregistration
The first SAINTCON precon runs continuously from Monday, October 12, 2026 at
noon through Friday, October 16 at 6:00 AM, America/Denver. It uses SAINTCON's
opening and closing hours, on the requested October 12–16 dates. Its event and
ladder ID is saintcon-precon-2026-10-12. Preregister at
the precon ladder
with your Arena account; open enrollment admits players immediately before play
opens. Bot matches remain unavailable until noon on October 12. Develop with the
starter bots and simulator in the meantime, then queue with
ARENA_LADDER=saintcon-precon-2026-10-12.
This online playtest helps players learn the game and build bots, with separate
standings and five unofficial testing flags. All five achievements, house
opponent requests, private reveal/copy, evidence and revocation use the normal
achievement system. Testing flags are not part of the official HC challenge and
have no HC submission link. The precon is enabled by default and uses
flag_mode: "testing", which supplies stable, deliberately predictable
ARENA_TEST values without HC secrets. A second precon may follow the next week;
it is not scheduled yet.
Precon enrollment, ratings and results do not enroll players in the October 27–30
main event or count toward its achievements.
Official and testing flags
An event's optional flag_mode is official (the default) or testing. Testing
events automatically get five distinct ARENA_TEST{<event ID>:<achievement ID>}
values. They stay stable across restarts, differ between events and achievements,
and are explicitly unofficial. Only an earned, nonrevoked award with active
membership can be revealed through the verified account route. Testing flags
never borrow configured HC values or enable an official event without its secrets.
Flag values do not appear in public definitions, progress responses or audits.
The flag mode freezes with the scoring definition once earning begins.
Compose and .env.example enable the first precon by default. On an existing
deployment, include saintcon-precon-2026-10-12 in ARENA_ENABLED_EVENTS, or
clear a saved admin pause with Enable achievement earning. An explicit empty
ARENA_ENABLED_EVENTS still disables all manifest earning. Accounts, --house,
champion weights and approved opponent policies are required for testing too;
only the external HC flag secrets are unnecessary. Local anonymous practice can
set ARENA_ENABLED_EVENTS= to keep earning disabled.
Public event metadata
Definitions may include a metadata object with kind (precon, main, or
community), purpose, audience, format, and preparation. All five fields
are required when metadata is supplied. The event page and enrollment directory
show these public details, alongside the schedule in the event's timezone.
Keep secrets out of metadata. Older definitions without metadata remain valid.
A practice event sets submission_url to null to omit flag submission links;
otherwise the URL must use HTTPS. Metadata is frozen with the event definition.
Branding images
Each event may have an image object (url, alt, width, height) or null.
The URL must use HTTPS, alternative text is required (1–300 characters), and
normalized dimensions fit within 1600 × 900. Images appear above the event details
and on enrollment cards. A manifest can supply an existing public image URL;
older definitions without an image remain valid.
Admins can open /admin#events, choose the event from the list, and upload, replace or remove
its branding image. Uploads accept nonanimated PNG, JPEG and WebP, up to 5 MiB
and 40 million pixels. The server decodes the image, applies orientation, resizes
without cropping or enlarging, strips source metadata and writes a WebP copy to
R2 under events/<event ID>/<content hash>.webp. A descriptive alternative text
makes the branding accessible.
Artwork can change after an event opens: it does not alter the frozen scoring conditions, roster, dates or awards. Admin image choices, including removal, override manifest images and survive earning toggles, restarts and manifest reloads. Removing an image detaches it from the event; previous R2 objects remain available for cached pages and recovery.
Configure a separate public asset bucket and its public HTTPS domain using
ARENA_ASSETS_R2_ENDPOINT, ARENA_ASSETS_R2_BUCKET,
ARENA_ASSETS_R2_ACCESS_KEY_ID, ARENA_ASSETS_R2_SECRET_ACCESS_KEY, and
ARENA_ASSETS_R2_PUBLIC_URL. These are runtime settings; keep credentials out of
manifests, browser configuration and build arguments. The ladder starts normally
without asset settings; upload controls report unavailable until storage is
configured. A partial configuration fails startup with the missing setting name.
Do not make the private backup bucket public. See DEPLOY.md.
Five achievements
| ID | Achievement | Required win |
|---|---|---|
first-blood |
First Blood | Beat any standard house bot. |
bank-shot |
Bank Shot | Beat any official house bot and land a damaging ricochet in that match. |
wall-breaker |
Wall Breaker | Beat any official house bot and cause a damaging repulsor wall slam in that match. |
house-sweep |
House Sweep | Beat each standard kind: TypeScript starter, brawler and kiter. |
champion-slayer |
Champion Slayer | Beat the official champion. |
Awards are independent: one match can earn several. Progress combines all bots and versions belonging to your account, with one award per achievement per event. Attach your bot to your account before the match starts; later claims do not import old results. New versions, retirement and handle changes preserve earned awards.
Only ranked wins on the event's ladder_id against its approved official house versions count (the champion at any version: it keeps training through an event). Active enrollment must exist at start and completion; later admission cannot qualify an earlier match. Revoking enrollment also blocks future flag reveals. See multiple ladders.
Results must be last_standing, timeout_hp or timeout_damage, with neither
fighter disqualified. Human games, local simulation, uploaded replays, player
opponents, draws, forfeits and voided games do not qualify. The account must be
eligible at start and completion. All four official opponents must be connected
with approved versions for the event to accept new qualifying starts.
Earned cards link to match evidence. Reveal a flag, then copy it to the event's submission site. Flags are fetched on demand and held in page memory; reload, logout or a session/account change clears them. Closing or disabling an event stops earning, but earned flags remain revealable while their server secrets are available. Staff revocation blocks subsequent reveals.
Request an opponent
Join the event ladder at Events, receive admission, and queue with ARENA_LADDER=<event ladder ID>, then choose an official opponent on the event
page. One pending request is allowed per account across events. It expires after
ten minutes or at event closing, whichever is sooner. Requests and requested starts
have a one-minute account cooldown, including after cancellation and restart.
Disconnecting or leaving the queue cancels that bot's pending request.
A request reserves your selected bot; your other bots continue normal matchmaking. It is a preference: normal quotas, pacing, capacity, owner exclusions and rematch holds still apply. Requested games are ranked, with server-selected maps and seeds and balanced seats. The scheduler admits one initial preferred start; four ordinary ranked starts earn another, up to four credits. Requests can use otherwise idle capacity. Requests are considered in order, skipping unavailable selected bots or opponents.
Operator setup
The CLI loads events/saintcon-2026.json and ladders/default.json by default. The first precon uses open enrollment on saintcon-precon-2026-10-12. SAINTCON uses the separate saintcon-2026 ladder with staff approval. Its opponent names in the manifest belong to that ladder; Public practice wins do not count. Use serve --events <path> or
ARENA_EVENTS_FILE for another public JSON manifest (an array of definitions).
ARENA_ENABLED_EVENTS overrides each definition's enabled value with a
comma-separated list of IDs; an empty value disables all listed events. Every
enabled ID must exist in the manifest. Testing events need no ARENA_EVENT_FLAGS
entry; official events still require all five distinct configured values. In Compose, the path is inside the
container; leave it empty to use the bundled preset.
Configure Supabase accounts and start with --house. Approved versions for SAINTCON
are starter-17, brawler-18 and kiter-17; the manifest names the champion's
l3-6420, but the champion counts at any version. Set the runtime-only secret
ARENA_EVENT_FLAGS to a JSON object with this structure, replacing each placeholder
with a distinct accepted value supplied by HC:
{
"saintcon-2026": {
"first-blood": "<accepted First Blood flag>",
"bank-shot": "<accepted Bank Shot flag>",
"wall-breaker": "<accepted Wall Breaker flag>",
"house-sweep": "<accepted House Sweep flag>",
"champion-slayer": "<accepted Champion Slayer flag>"
}
}
These are placeholders, not playable flags. Keep real values in the deployment
secret store, never in the manifest, source, build arguments or a VITE_* variable.
The CLI removes this variable from house bot child environments. Flags are absent
from SQLite, replays, statistics, public views and audits. Back up the secret store
separately: restoring the database alone cannot restore flags.
Set ARENA_ENABLED_EVENTS=saintcon-2026 after configuration. An enabled event without
accounts, complete flags, --house or champion weights doesn't stop the ladder: it starts with
that event's earning paused and logs why. Check GET /api/events:
ready must be true and unavailable_opponents empty once all house bots are
connected with approved versions. Opening and closing follow the manifest's UTC
instants automatically.
Releases don't depend on events: an enabled event doesn't pin the code, rules or maps, so
fixes and a retrained champion can ship while it runs. Combat changes are deliberate,
announced releases (rules_hash and the engine version in /api show what's running).
Definitions freeze once matches start or an enabled event opens;
enabled can still toggle for an emergency pause. Use a new ID for changed
conditions. Removing a definition preserves its stored event and awards, so
explicitly disable it first. An enabled stored event still requires its secrets at
startup; retain finished events' flag secrets for reveals.
For future events, add new IDs with their own dates, approved opponents and flag
sets. The current revision, house-v1, uses these same five conditions. Distinct
IDs keep awards and progress separate. New conditions need a reviewed revision
and evaluator, rather than editing a running event.
Evidence and recovery
The server snapshots ownership, seats, house identity and versions before starting the runner. It commits match results, statistics, progress and awards together. Duplicate completion cannot double count matches or awards. Event facts remain available after replay trimming.
The admin console's Events section lists each ladder with the events that play on it. An event's controls show official opponent and flag readiness, and valid/revoked award counts per unique player account. Staff can enable or disable earning; these choices persist across manifest reloads. Enabling requires approved house policies, configured accounts and all five flags. Flag values remain server-only. Hidden ladders' events are omitted from public discovery; their account achievement routes remain usable.
An event's Schedule editor moves its opening and closing times, entered in the event's time zone. An event on an event ladder shares the ladder's window, so saving moves the ladder (and its other events) too. Staff can move only future times: once play opens the opening time is final, once it closes the window is final, and a new time must be in the future, so recorded matches and awards keep the window they were judged by. Moved windows outrank the manifest on restart.
The admin console's Events section also includes a Flag submission editor for the
public submission URL and instructions, with a player preview. URLs must use
HTTPS or be left blank. Instructions allow up to 4000 characters, line breaks,
HTTP(S) URLs and [label](https://…) links; HTML stays plain text. Leave both
fields blank to hide the submission section. Do not include secret flag values.
Manifest submission_instructions is optional and defaults to an empty string.
Admin edits override manifest submission details across restarts and remain
editable after scoring definitions freeze.
The Events tab also inspects an account's evidence and revokes awards with a reason. Staff cannot reveal somebody else's flag. Reconciliation previews missing awards, then fills them from retained facts, preserving existing awards, original timestamps and revocations. It does not change matches, ratings or counters. It cannot import pre-event matches or invent start ownership evidence.
For offline recovery, stop the ladder and use its data directory:
npm run arena -- events list --data /path/to/data
npm run arena -- events reconcile saintcon-2026 --data /path/to/data
npm run arena -- events reconcile saintcon-2026 --apply --data /path/to/data
The first reconciliation is a dry run. Back up the database before applying a repair. The admin HTTP route supports the same preview/apply flow while running. SQLite schema 14 adds event records; rollback needs a compatible database backup.
Scoring modes
This release delivers one shared flag per achievement per event. Private delivery limits who can retrieve it from Arena; HC determines scoring for submitted copies. Arena revocation cannot retract a copied shared flag or reverse a score at HC.
EventFlagProvider separates evaluation from delivery. Contestant-bound flags
remain a future adapter: HC must confirm verified enrollment and a validator tied
to that identity, with stable event-specific flag derivation. Arena handles alone
do not establish HC identity. Both options are described in
the design; only shared mode ships here.