# @helyx/sdk

Deployment-neutral contracts for official Helyx modules.

## Requirements

- Node.js 24–26
- npm 11 or newer

The SDK defines module lifecycle, service access, interactions, modals, Components V2 messages, events, logging and dashboard actions. Modal contracts support text fields and Discord-native string, user, role, mentionable and channel selectors. `defineModule` preserves the typed module definition without coupling feature packages to the hosted bot.

Interaction contexts expose Discord's `interactionCreatedAt` when the runtime
provides it. Immediate-response and immediate-modal flows must base their whole
response budget on that timestamp, including platform authorization, instead
of starting a new deadline inside the module handler.

## Shard-neutral contract

The additive Channel audit types describe bounded role assumptions, safe findings,
coverage and a narrow explicitly requested configuration projection. Optional
`ChannelAuditControl` / Discord inspection methods allow older implementations to
report unsupported. These are read operations; they do not expose module mutation
helpers or guarantee individual member access. Verification remains hosted-only.

`helyx.application-urls` is a deployment-local, read-only service. Its
`dashboardBaseUrl` identifies the configured dashboard origin; optional
`dashboardInstallationId` is read from the current Cloud Connect identity when
a self-hosted runtime is paired, including through the worker's Cloud proxy.
Read this value when constructing a link, not once at module startup, so pairing,
rotation or disconnect can update the context. Hosted and unpaired runtimes
omit it. The service performs no writes and does not bypass dashboard access
checks; modules must URL-encode installation and guild identifiers.

Modules consume deployment-neutral services and remain unaware of shard IDs, worker routing and process topology. They must not import Redis, Discord.js, shard managers, process IPC, application-private code or hosted deployment infrastructure.

- A module runtime may be instantiated once per shard worker. Lifecycle hooks must be repeatable and must not create an uncoordinated global side effect.
- Worker-local Discord state is valid only for guilds owned by that worker. Discord guild operations are routed to the owning worker through SDK services.
- Cross-guild state, whole-bot statistics, shared rate limits, sessions, uniqueness controls and globally owned jobs use core-provided durable, distributed or aggregation contracts.
- SDK service documentation must state whether a contract is worker-local, guild-owner-routed or deployment-wide, including its ownership, consistency, idempotency, retry and expiry semantics where relevant.
- Worker caches are bounded optimizations rather than sources of truth. Event and task contracts require bounded concurrency and backpressure.
- Module tests mock SDK contracts and cover concurrent workers, retries, duplicate delivery, restart and stale ownership when those failure modes apply.

Core may expose the optional `ModuleRecordService.findManyForRecovery` boundary
to a module lifecycle. It reads only records attributed to the current worker's
Discord servers, uses a server-prefixed deterministic cursor and keeps every
page bounded. Modules must use an immutable declared record order and retain a
separate total startup limit. This boundary is not an ordinary unfiltered query,
does not reveal shard identity, and is unavailable when core has no validated
worker ownership.

## Durable scheduled work

`helyx.scheduled-tasks` is deployment-wide and backed by the selected database
adapter. Modules
declare versioned one-shot or coalesced task handlers and submit only bounded
ID payloads. Delivery is at least once, so handlers must make business-state
changes idempotent and render external state from authoritative records.
One-shot schedules and coalesced signals may be attached to
`replaceOwnedSet` so the domain write and required delayed or refresh work
commit together. Expected-state updates may attach a required audit and
bounded record-retention descriptors; core resolves and persists them in the
same transaction. The core retention executor remains available after module
disablement or removal and never exposes table names or SQL to modules.

The record service also supports allowlisted server-side text search, bounded
single-field prefix lookup and exact distinct counts. Search and prefix fields
must be declared readable strings; distinct fields must be declared readable
and groupable. Modules never receive SQL or a database connection.

`aggregateCounts` returns grouped counts, total rows and one distinct total
from a single database snapshot so retention or privacy work cannot produce a
torn public result.

Parent-and-owned-set writes can declare bounded quota guards. Core serializes
matching quota scopes through adapter-owned locks, checks the
authoritative count and inserts the parent in the same transaction. Modules do
not own counters or lock keys.

Guarded owned-set writes also support a 100,000-row relationship quota,
required-row locks, module-enabled fencing and up to 20 bounded child rows.
These constraints let high-volume entry and winner relationships serialize
with lifecycle, disablement and Privacy deletion without exposing locks or SQL
to modules. Expected-state updates may atomically attach replacement one-shot
or coalesced work.

## Secure outcome selection

`helyx.secure-random` is deployment-wide and uses operating-system
cryptographic entropy. Bounded integers use rejection sampling. Weighted
selection starts with an opaque, operating-system-random operation reference.
Core combines a server-held 32-byte key with that reference and framed context
to derive separate scoring and checkpoint-integrity keys. Candidate scores and
tie-breakers are deterministic only to Core; the reference exposed to a module
cannot predict outcomes or forge a checkpoint. Selection remains streamed
through a versioned reservoir and returns only selected candidate IDs plus an
audit-safe algorithm version, operation reference and digest.

Long-running handlers may call `checkpoint()` and persist the returned bounded,
JSON-serialisable value. Supplying that checkpoint to
`createWeightedSelection` resumes the same operation across fixed database-page
budgets without storing raw entropy or raw selection scores. Core validates the
algorithm, context digest, winner count, canonical cursor, counts, totals,
integrity digest and reservoir before resuming. A checkpoint holds at most the
requested reservoir of 20 candidate IDs and weights. Candidates supplied after
resume must continue in canonical, strictly increasing ID order.

The receipt field `entropyDigest` is retained for compatibility; for weighted
selection version 3 it contains the final candidate hash-chain audit digest.
Production entropy and scoring primitives are not injectable through the SDK
contract; deterministic platform construction exists only for tests.
The server-held key must remain stable while checkpointed draws are in
progress. Rotating it invalidates their checkpoints, so deployments must drain
or complete those draws before rotation.

Exact member snapshots are guild-owner-routed through
`helyx.discord-resources`. A bounded lookup returns current membership, bot
state, role IDs and `joinedAt` without storing a Discord profile. Modules must
fail closed when an eligibility snapshot cannot be obtained.

Hosted OAuth contracts use a closed provider and purpose registry, a hard
three-slot account bound and a versioned consumer/connection/request context.
Modules receive connection identities and eligibility results only; provider
tokens, client secrets and credential-vault access are never part of the SDK
service boundary. Creator Connections is hosted-only.

## Moderation and Auto Moderation boundaries

Feature access is resolved through `helyx.feature-access`; modules do not call a
billing system. Hosted and Self-Hosted runtimes may use different policy sources,
but return the same closed decision set.

Member, member-authored-message, native Discord Auto Moderation and private
violation-thread mutations are guild-owner-routed services with immutable
operation keys, typed outcomes and revalidation callbacks.
`helyx.discord-owned-messages` remains restricted to messages authored by Helyx.
Atomic moderation-case creation allocates a per-guild case number; its automatic
form also selects the repeat-offender step and persists the claim, pending case
and first attempt without exposing SQL or a transaction callback.

Cross-module automated actions use only the allowlisted
`helyx.moderation-actions` version 2 provider. Auto Moderation resolves the
current policy through its separate closed contribution; callers cannot select
an offence ordinal or action. Enhanced scanning uses the closed
`helyx.automod-enhanced-config/v1`, `helyx.automod-enhanced-result/v1` and
single-delivery `helyx.automod-enhanced-evidence/v1` contracts. Adapter selection
is deployment-neutral: Hosted may select Ecko while Self-Hosted selects the
embedded adapter. Detection results never contain message content or matched
fragments; transient evidence is delivered only through a core-owned adapter.

## Publication status

Published as a public scoped package under the Helyx Source Available Licence.
Read the packaged `LICENSE` before installing, using, modifying, or distributing
the software.
