Files
neural-hunt/V4.2.6_CUSTOMER_ENGAGEMENT_ADMIN.md
jbergner 74d6b2f7d2
release-tag / release-image (push) Failing after 2m11s
RC-10
2026-08-11 22:08:00 +02:00

4.0 KiB

V4.2.6 — Customer Engagement + Admin Controls

Credit rewards

Two optional reward values are managed persistently by the private Customer-Service admin UI:

  • Signup bonus: credited atomically when a new Customer account is created.
  • Positive-tip bonus: credited when a Hosted Worker submits a signed, lottery-selected/evaluated guess that improves that worker's own best score for the task.

The defaults are intentionally 0, so an update does not change the existing economy until the operator enables it:

CS_NEW_CUSTOMER_CREDITS=0
CS_POSITIVE_TIP_CREDITS=0

These environment values seed SQLite only the first time the setting exists. Afterwards the live values are controlled from Customer Admin and survive restarts.

A positive-tip reward is not granted for every submitted guess and not for a guess that loses the task lottery before evaluation. Ordinary browser/CLI identities also do not receive Customer-Service credits. The Game server creates the reward event only when the submitting identity has an active Hosted Worker delegation.

To avoid losing rewards during a Customer-Service restart/outage, the Game DB contains a durable hosted_credit_events outbox. The server retries delivery to the private Customer Service endpoint. Both the outbox event ID and Customer-Service ledger reference are idempotent, so retries cannot double-credit the customer.

For Docker/Compose the Game server therefore needs:

CUSTOMER_SERVICE_INTERNAL_URL=http://customer-service:8092

For a direct local go run setup use http://127.0.0.1:8092 instead.

Customer dashboard

When PayPal is disabled or not fully configured, Credits kaufen is not rendered as an available purchase area and package requests are skipped. The credit history is intentionally compact: entries are grouped by UTC day and booking reason, while the raw immutable-style credit_ledger remains unchanged in SQLite for audit/idempotency.

Private Customer Admin

The private :8091 Customer Admin now supports:

  • block / unblock a Customer account;
  • stop one Worker or all Workers of a Customer;
  • disable/enable new Customer logins globally;
  • disable/enable new registrations independently;
  • configure registration Proof-of-Work difficulty (0..24 bits);
  • optionally require a one-shot registration invite;
  • create time-limited one-shot invite codes;
  • configure signup and positive-tip credit rewards.

Blocking an account invalidates all Customer sessions immediately and revokes/stops its Worker leases. Docker stop is attempted immediately. Even if that Docker operation fails, the Worker cannot renew its lease and its existing lease-failure shutdown path terminates it.

The global login kill switch intentionally blocks new logins; it does not mass-log-out already authenticated customers. Use individual account blocking when an existing session must be invalidated. Registration has a separate switch.

Anti-bot / account farming

Open registration can require a stateless, username-bound SHA-256 Proof-of-Work. The challenge is HMAC-authenticated by Customer Service, short lived and cannot be moved to another username. This adds a measurable cost to bulk account creation, especially when signup credits are enabled.

Proof-of-Work is friction, not proof that one account equals one human. For controlled launches or valuable signup credits, enable invite required as the stronger control. Each nhinvite_... code is one-shot, has an expiry and is stored only as a hash. Continue to rate-limit /api/register/challenge, /api/register and /api/login at Traefik/Caddy as an independent layer.

Suggested starting point for an open beta:

CS_CUSTOMER_LOGIN_ENABLED=true
CS_CUSTOMER_REGISTRATION_ENABLED=true
CS_REGISTRATION_POW_BITS=16
CS_REGISTRATION_INVITE_REQUIRED=false
CS_NEW_CUSTOMER_CREDITS=0
CS_POSITIVE_TIP_CREDITS=0

If signup credits become meaningful, increase PoW gradually and/or switch to invite-only registration before raising the free balance.