Setups
Overview
From v0.3.x onward, OpenCore follows a zero-config by default philosophy.
This means:
- You can start a server with
init({ mode: 'CORE' })and everything works. - Core systems (commands, players, net events, identity, sessions) are auto-configured.
- Reasonable default implementations are installed internally.
The Setup API exists for advanced customization, not as a requirement.
You only need it if you want to replace or extend core behavior.
What is a Setup?
A setup is a set of explicit registrations into the global DI container before init() runs.
Internally, OpenCore uses a global dependency container (GLOBAL_CONTAINER).
Setup helpers allow you to register your own implementations for critical contracts.
Typical use cases:
- Custom authentication / permissions
- Custom persistence (database, cache, API)
- Security hardening
- Centralized error handling
Available setup functions
Principal Provider
import { setPrincipalProvider } from '@open-core/framework/server'
setPrincipalProvider(MyPrincipalProvider)
Registers a custom implementation of:
PrincipalProviderContract
What it controls:
- Player identity
- Roles, permissions, claims
- Authorization logic used by
@Guard
Default behavior if not set:
- A default principal provider is installed automatically
- Guards follow a deny-by-default model
- Suitable for development and simple servers
Use a custom provider if you need:
- Database-backed roles
- External auth (API, Discord, OAuth, etc.)
- Advanced permission models
Security Handler
setSecurityHandler(MySecurityHandler)
Registers:
SecurityHandlerContract
What it controls:
- How security rules are evaluated
- How guards, states, and permissions are enforced
Default behavior if not set:
- Built-in security handler is used
- Guards, throttles, and state checks work out of the box
You usually only replace this for deep framework integrations.
Player Persistence Provider
setPersistenceProvider(MyPlayerPersistence)
Registers:
PlayerPersistenceContract
What it controls:
- How player data is stored and restored
- Session persistence and recovery
Default behavior if not set:
- In-memory persistence
- Data is lost on restart
- Session recovery still works for hot-reload scenarios
Use a custom provider if you want:
- Database persistence (SQL / NoSQL)
- Redis-backed sessions
- External player state storage
Net Event Security Observer
setNetEventSecurityObserver(MyNetEventObserver)
Registers:
NetEventSecurityObserverContract
What it controls:
- Observes and validates incoming network events
- Can log, block, rate-limit, or audit events
Default behavior if not set:
- A safe internal observer is used
- Basic validation and security checks are applied
Useful for:
- Anti-cheat
- Network auditing
- Advanced telemetry
Command Error Observer
setCommandErrorObserver(MyCommandErrorObserver)
Registers:
CommandErrorObserverContract
What it controls:
- How command errors are handled and reported
- Logging, player feedback, telemetry
Default behavior if not set:
- Errors are logged
- Players receive usage-based error messages automatically
Useful if you want:
- Custom error messages
- Centralized logging
- External monitoring
When setups are required
Most setups are optional.
The only case where setup is mandatory:
Principal Provider in CORE / STANDALONE
If:
principalfeature is enabled (default)- Mode is
COREorSTANDALONE - And no provider is registered
Then:
- OpenCore will fail fast during bootstrap
- A clear fatal error is logged
This is intentional to prevent insecure deployments.
Execution order (important)
Setups must be executed before calling init().
Correct pattern:
import {
init,
setPersistenceProvider,
setPrincipalProvider,
} from '@open-core/framework/server'
setPrincipalProvider(MyPrincipalProvider)
setPersistenceProvider(MyPersistence)
await init({
mode: 'CORE',
})
Incorrect pattern (too late):
await init({ mode: 'CORE' })
setPrincipalProvider(MyPrincipalProvider) // ❌ ignored
How setups integrate with bootstrap
During bootstrap, OpenCore:
- Registers platform adapters (FiveM / Node)
- Registers core services
- Loads framework controllers
- Registers system processors
- Checks required providers
- Scans decorators and binds runtime behavior
- Emits
core:ready
Setup functions affect steps 3–6.
If a setup is missing:
- Defaults are applied
- Or a fatal error is thrown if the contract is mandatory
core:ready and setups
The core:ready event is emitted after:
- All setups are resolved
- Controllers are loaded
- System processors are registered
This guarantees that:
- Resources waiting for CORE can safely start
- All contracts and providers are available
You should not perform setup logic inside core:ready.
Summary
- Setup is optional, not mandatory
- Defaults exist for everything except critical security contracts
- Use setups only when you need custom behavior
- Always configure setups before
init() core:readyis automatic and reliable
This keeps OpenCore:
- Safe by default
- Flexible when needed
- Predictable in production