NetStack

Security model

The server is the authority

Clients can only call Functions by name and read the state they are allowed to see. They cannot write properties directly. Put every rule that matters, such as ownership checks, costs and cooldowns, inside Functions.

Never trust arguments

args comes straight from the client. Validate types and ranges in every Function, and check ownership against properties rather than against anything the client claims.

Private by default

Player properties are only sent to their owner. Room properties go to the room. Sensitive data such as currency or hidden inventory belongs in player properties.

Player identity

NetStack uses the player ID your game provides when joining. It does not verify who the player is. If players could benefit from impersonating each other, authenticate them in your own backend and only hand out the IDs they are entitled to.

Why Functions sit in the middle

Every action a player takes goes through a Function that you wrote, on the server, before any state changes or any other player hears about it. That makes cheating a matter of fooling your own rules instead of editing a client. In relay-style networking, clients exchange messages directly and you add a trusted server yourself if you want one. With NetStack the trusted server is the default.

Function isolation

Your Functions run in an isolated JavaScript sandbox with no access to the network, filesystem, environment or other projects. Each call has strict time, memory and size limits, and its writes are applied only if it succeeds. One project's Function cannot read or change another project's data.

Keys

API keys are stored as hashes and shown once. Rotate a key if it may have leaked, and do not embed it in downloadable client builds. See API keys and teams.

Audit log

Changes to Functions, properties, keys and team membership are recorded with who made them and when.