Skip to content

Official Optional Module Acceptance Matrix ​

This document defines the acceptance matrix of the official optional modules. It is not an implementation plan nor a collection of examples; it is the module-level contract that follow-up coding must satisfy.

Goals:

  • prevent optional modules from polluting shield_core in reverse
  • freeze the module enable/disable boundaries
  • freeze the public surface, configuration ownership, and key failure semantics

examples/hello_world/ does not replace the tests in this document.

General Acceptance Items ​

IDScenarioOperationExpectation
OMOD-000-01no optional module enabledstart the minimal runtimethe core path works normally
OMOD-000-02an optional section exists in config but the module is unregistered or disabledbootstrapstartup fails; the error includes the module name and config path
OMOD-000-03an optional module fails to initializestart the runtimethe error is attributed to the corresponding module; core error semantics are not rewritten
OMOD-000-04an optional module is disabledcall the minimal APIshield.send/call/query, gateway, and plugin namespace data capabilities keep their existing semantics
OMOD-000-05public header / Lua API checkbuild/binding testsoptional modules leak no CAF or old-architecture API to users
OMOD-000-06an optional module explicitly enabled with invalid configbootstrapfail fast by default; only degrade scenarios declared in the module's documentation may continue starting and expose unhealthy

OMOD-CL shield_cluster ​

IDScenarioOperationExpectation
OMOD-CL-001cluster not enabledshield.query("local")still queries only the local registry
OMOD-CL-002cluster not enabledlocal shield.send/callsemantics identical to core
OMOD-CL-003duplicate NodeIdtwo nodes handshakethe new connection is rejected
OMOD-CL-004remote name resolutionshield.cluster.query(node, name)returns a remote ServiceHandle or a clear error
OMOD-CL-005remote handle sendshield.send(remote_handle, ...)reuses local envelope / timeout semantics
OMOD-CL-006remote handle call timeoutshield.call(remote_handle, ...)returns false, timeout
OMOD-CL-007node offlinea pending call existsreturns false, node_offline
OMOD-CL-008node recovers after offlinea route cache existsstale routes are cleaned and re-resolved
OMOD-CL-009cluster disabledremote discovery interfacereturns module_unavailable or an equally clear error; silent success is not allowed
OMOD-CL-010discovery switchstatic / redis / k8saffects only node discovery; local service registry rules unchanged
OMOD-CL-011remote connection fails but local config is validstart clustermay degrade to single node; local services keep running; cluster state is unhealthy

OMOD-GL shield_global ​

IDScenarioOperationExpectation
OMOD-GL-001global not enabledcall the global namespacereturns module_unavailable or a module-unavailable error
OMOD-GL-002cache/queue/leaderboard plugins enabled, global not enabledcall the corresponding plugin namespacestill fully usable
OMOD-GL-003distributed lockacquire/releasecompleted per the module contract; no underlying Redis handle exposed
OMOD-GL-004Redis unavailabledistributed lock / rank / queuereturns Redis-related errors; core semantics are not written back
OMOD-GL-005rank resetreset period reachedaffects only rank data; core scheduler semantics untouched
OMOD-GL-006queue persistenceservice restartqueues are restored or dropped per module configuration
OMOD-GL-007rate limiterover-quota requestsreturns a module-level rate-limit result; shield.call success/failure semantics unpolluted
OMOD-GL-008global config missingstart the moduleattributed to a module configuration error
OMOD-GL-009negative results like lock contention / empty queueacquire / popreturned as module contract results, never disguised as runtime transport errors

OMOD-PL shield_player ​

IDScenarioOperationExpectation
OMOD-PL-001player not enabledgateway callbackson_client_bound/on_disconnect/on_client_unbound still work independently
OMOD-PL-002player enabledlogin successon_auth -> on_login order is stable
OMOD-PL-003client business messagecompiled binding handler(ctx, client, request)only request / player state passed; no legacy msg_type entry
OMOD-PL-004cross-service collaborationgateway -> player_manageronly session_id/ClientRef tokens passed; no bare connection handles
OMOD-PL-005disconnect/reconnect successreconnect within the windowon_reconnect fires; PlayerSession restored
OMOD-PL-006reconnect window timeoutreconnect failson_logout(reason=timeout) fires
OMOD-PL-007offline message cacheplayer returns after being offlinemessages delivered and cleared per module policy
OMOD-PL-008multi-device policysecond loginbehavior matches the single/multi/kick_old configuration
OMOD-PL-009PlayerManager indexlogin/logoutuid/state indexes updated in sync
OMOD-PL-010module disabledordinary service method dispatchunaffected by player hooks
OMOD-PL-011auth rejectedon_auth returns rejectexpressed as a player contract result, never disguised as handler_error

OMOD-SV shield_server ​

IDScenarioOperationExpectation
OMOD-SV-001server module not enabledstart the runtimebootstrap / core do not depend on server_manager; shield.server.* returns module_unavailable
OMOD-SV-002server enabledinit completestate automatically enters running (mark_ready); uptime/started_at count from that point
OMOD-SV-003maintenance switchserver:set_state("maintenance")transition succeeds and watchers are notified; the admission gate is implemented at the business layer; existing services keep running
OMOD-SV-004shutdown requestserver:shutdown(ms)immediately enters shutdown and notifies watchers; after ms the stop request takes the same path as SIGINT; the drain budget still belongs to bootstrap
OMOD-SV-005state watcherserver:watch(fn) registeredstate changes deliver fn(ctx, new_state) on the watcher's actor thread
OMOD-SV-006config missing/invalidstart the modulemissing uses defaults; invalid (empty name / info over 64 chars) fails fast, attributed to a server_manager configuration error
OMOD-SV-007illegal state transitionrunning -> starting etc.returns invalid_state_transition; no runtime crash, state unchanged
OMOD-SV-008server module uncompiledcall any shield.server.* entryreturns nil + {code="module_unavailable"}, retryable=false
OMOD-SV-009duplicate watch / unknown unwatchthe same service watches again; unwatch of an unregistered idduplicate watch returns the same id; unknown unwatch succeeds silently
OMOD-SV-010shutdown illegal argumentshutdown(-1) / shutdown(1.5) / shutdown("x")returns invalid_argument; no state migration, no stop triggered
OMOD-SV-011services keep running under maintenanceset maintenance then send/callservice messaging, gateway, and plugin namespace semantics unchanged
OMOD-SV-012a watcher service exitsmigrate statestale watchers are unregistered automatically; other watchers and the state machine unaffected
OMOD-SV-013invalid config fails faststart with an over-long server_manager.info.namebootstrap initialization fails; the error is located at the server_manager config path
OMOD-SV-014read-only observation exposureroot.server / GET /ops/statusprints {state, uptime_seconds, version, node_id, started_at_ms, name, info, watchers}; when uncompiled, root.server prints a clear notice and the response has no server block

OMOD-SV Test Mapping ​

  • OMOD-SV-001 → tests/lua_api/test_lua_api_server.cpp stub branch + the shield_config_server_requires_module negative CLI case
  • OMOD-SV-002/007 → tests/server/test_server_manager.cpp ServerTransitions/ServerLifecycle/ServerSetState
  • OMOD-SV-003/011 → ServerSetState + tests/lua_api/test_lua_api_server.cpp (messaging semantics unchanged after transition)
  • OMOD-SV-004/010 → ServerShutdownScheduling + the Shutdown suite (immediate / duplicate / illegal argument)
  • OMOD-SV-005/009/012 → ServerWatch + the Watch suite (idempotency / auto-unregister / unwatch)
  • OMOD-SV-006/013 → ServerConfigParsing + InitializeFailsOnInvalidServerConfig
  • OMOD-SV-008 → stub-branch assertions across all entries
  • OMOD-SV-014 → console/ops suite assertions on root.server and the /ops/status server block

OMOD-OPS shield_ops ​

IDScenarioOperationExpectation
OMOD-OP-001ops not enabledaccess /ops/*no endpoints exposed
OMOD-OP-002ops enabledGET /ops/statusread-only display of the runtime snapshot
OMOD-OP-003sensitive fields/ops/config / diagnosticstokens, passwords, and keys are redacted
OMOD-OP-004profile/console default offstart with a production confighigh-risk entries are not opened automatically
OMOD-OP-005auth missingaccess controlled endpointsrequests are rejected
OMOD-OP-006internal module failuremetrics/exporter errorscore operation and the business message path unaffected
OMOD-OP-007service details/ops/services/:nameexposes no CAF actor handle or full business payload
OMOD-OP-008management plane errorsillegal profile/control requestserrors stay on the HTTP/admin plane; they do not flow back as business Lua runtime errors
OMOD-OP-009ops management port binding failsstart opsfail fast, so users aren't misled into thinking the observation entry is enabled

Relationship to Existing Topic Documents ​

  • Architecture and ownership: see the Official Optional Module Contracts
  • cluster details: see Cluster Runtime Semantics
  • global details: see Global Capabilities Runtime Semantics
  • player details: see Player Lifecycle Runtime Semantics
  • server details: see Server State Runtime Semantics
  • ops details: see Ops Runtime Semantics

Apache License 2.0