Skip to content

feat(socket): admin socket settings (switch, mode, token TTL, origins) with signed config for the socket server - #314

Merged
roncodes merged 3 commits into
release/v1.6.71from
feature/socket-admin-settings
Oct 15, 2026
Merged

roncodes merged 3 commits into
release/v1.6.71from
feature/socket-admin-settings

Conversation

@roncodes

Copy link
Copy Markdown
Member

What

System administrators can manage the socket server from the console (Configure → Socket) instead of only through environment variables.

Settings (one settings row each; missing or null = fall back to the environment, which is today's behaviour):

key type env fallback
system.socket.enabled bool SOCKETCLUSTER_AUTH_ENABLED
system.socket.mode off | log | enforce SOCKETCLUSTER_AUTH_MODE (null = the socket server's own default)
system.socket.token_ttl int 60..3600 SOCKETCLUSTER_TOKEN_TTL
system.socket.origins SocketCluster origins string SOCKETCLUSTER_OPTIONS.origins
system.socket.publisher_origin URL origin SOCKETCLUSTER_ORIGIN

system.socket.updated_at is written on every save and served as updated_at by the config endpoint.

Resolver: Fleetbase\Support\SocketCluster\SocketSettings::effective() returns {enabled, mode, token_ttl, origins, publisher_origin, key_configured, sources: {field: 'setting'|'env'}}. Stored values are cached for 60 s under socket_settings:stored, and the cache is cleared on save. If the settings table can't be reached (e.g. during install) it falls back to the environment without an error. SocketToken::enabled(), the default token TTL and the websocket publisher's Origin header now use the effective settings.

Endpoints

  • GET int/v1/settings/socket (system admin, AdminRequest) returns {settings: <effective>, status: <socket /stats or null>, status_error: <string|null>}. Status comes from the socket server's GET /stats, signed with the publish key, with a 2 s timeout. On failure, status is null and status_error gives a short reason.
  • POST int/v1/settings/socket (system admin) takes any subset of {enabled, mode, token_ttl, origins, publisher_origin}, where null clears a value. The values are validated. enabled: true is refused with 422 {code: "key_missing"} while no valid key is configured. Each save is recorded in the activity log (settings / socket_settings_updated). The response has the same shape as GET.
  • GET int/v1/socket/config is for the socket server only. It is signed with the authorize key (VerifySocketSignature:key-only) and has no session. It returns {enabled, mode, origins, updated_at} and also answers while the API's own switch is off, which is how the server learns the switch was turned on.

Why

Before this, changing the switch, mode, TTL or origins meant editing the environment on the API and the socket server and restarting both. Now the socket server polls the config endpoint and applies changes at runtime.

The key stays env-only

SOCKETCLUSTER_AUTH_KEY is never stored, returned or settable through the API. Responses report only key_configured: bool, and the tests check that no response contains the key or any derived key.

Test plan

Verified by CI (unit suite with the 100% coverage gate, php-cs-fixer, date drift). New tests cover:

  • env fallback vs stored setting, and source reporting
  • the cache being busted on save
  • enabled: true refused without a key
  • validation errors
  • the admin guard
  • stats success, failure and timeout
  • the signed config endpoint (good, stale and bad signatures, working while the switch is off)
  • SocketToken::enabled, TTL and publisher Origin following the effective settings
  • no key in any response

Related: #313 (release), console + socket server PR to follow in fleetbase/fleetbase (release/v0.7.70, fleetbase/fleetbase#721)

… server

System administrators can now manage the socket server from the console
instead of only through the environment:

- system.socket.enabled / mode / token_ttl / origins / publisher_origin
  settings; a missing or cleared one falls back to the environment
  (SOCKETCLUSTER_AUTH_ENABLED, _AUTH_MODE, _TOKEN_TTL, _OPTIONS.origins,
  _ORIGIN), which is the behaviour before this change.
- SocketSettings resolves the effective values and their sources; the
  stored values are cached for 60 seconds and the cache is cleared on save.
  An unreachable settings table reads as nothing stored.
- SocketToken::enabled(), the default token TTL and the websocket
  publisher's Origin header follow the effective settings.
- GET/POST int/v1/settings/socket (AdminRequest): effective settings plus
  the socket server's signed /stats (2 s timeout, short reason on failure).
  Switching on without SOCKETCLUSTER_AUTH_KEY is refused with 422
  key_missing; saves are recorded in the activity log.
- GET int/v1/socket/config, signed with the authorize key and answered
  while the switch is off, so the socket server can apply the switch, mode
  and origins at runtime.

The auth key stays environment-only and is never stored or returned; only
key_configured is reported.
@codecov

codecov Bot commented Oct 15, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (f4693d4) to head (249e0fa).

Additional details and impacted files
@@                 Coverage Diff                  @@
##             release/v1.6.71      #314    +/-   ##
====================================================
  Coverage             100.00%   100.00%            
- Complexity              8885      8931    +46     
====================================================
  Files                    472       473     +1     
  Lines                  27934     28065   +131     
====================================================
+ Hits                   27934     28065   +131     
Flag Coverage Δ
backend 100.00% <100.00%> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@roncodes
roncodes merged commit b0932ed into release/v1.6.71 Oct 15, 2026
5 checks passed
@roncodes
roncodes deleted the feature/socket-admin-settings branch October 15, 2026 08:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant