#!/usr/bin/env python3.14# -*- coding: utf-8 -*-"""Per-user service entry point: `python -m euler_webshell.user`.Run by `euler-user@<slug>.service` as that collaborator's own uid — named for theslug itself (`u3c9a0f1e2b7d4a68`) — from the `/opt/euler` system venv, configured entirely bythe environment (`EULER_USER_SLUG`, `EULER_REPO_ROOT` → their `~/euler` clone).Three ways to get a listener, in order:1. **systemd socket activation** — the `euler-user@<slug>.socket` unit creates `/run/euler/user-<slug>.sock` and passes it as `fd 3` (`LISTEN_FDS`); the service is spawned on the first Caddy connection and reuses that socket.2. **dev TCP** — `EULER_USER_TCP=127.0.0.1:8084` (the harness path).3. **plain unix bind** — `EULER_USER_SOCKET` (an always-on run without a .socket unit).Serves until SIGTERM; cleanup reaps every PTY child:: EULER_USER_TCP=127.0.0.1:8084 EULER_USER_SLUG=me-abc123 \\ EULER_AUTH_SOCKET=/tmp/dev-auth.sock python -m euler_webshell.user"""from__future__importannotationsimportasyncioimportloggingimportosimportshutilimportsignalimportsocketfromaiohttpimportwebfromeuler_webshell.user.appimportbuild_appfromeuler_webshell.user.configimportUserConfiglog=logging.getLogger('euler-user')#: The first file descriptor systemd passes for socket activation (sd_listen_fds)._SD_LISTEN_FDS_START=3def_systemd_socket()->socket.socket|None:"""The listener systemd passed for socket activation, or None (not activated)."""ifint(os.environ.get('LISTEN_FDS','0')or'0')<1:returnNoneifint(os.environ.get('LISTEN_PID','0')or'0')!=os.getpid():returnNone# the fds were meant for a different processreturnsocket.socket(socket.AF_UNIX,socket.SOCK_STREAM,fileno=_SD_LISTEN_FDS_START)asyncdefserve()->None:config=UserConfig.from_env()runner=web.AppRunner(build_app(config),access_log=None)awaitrunner.setup()activated=_systemd_socket()ifactivatedisnotNone:# prod: socket-activatedsite:web.BaseSite=web.SockSite(runner,activated)awaitsite.start()log.info('listening on the systemd socket (user %s)',config.slugor'<unpinned>')elifconfig.tcp_bind:# dev: TCP listenerhost,_,port=config.tcp_bind.partition(':')site=web.TCPSite(runner,hostor'127.0.0.1',int(portor'8084'))awaitsite.start()log.info('listening on %s (tcp, dev)',config.tcp_bind)else:# always-on unix bindpath=config.socket_pathpath.parent.mkdir(parents=True,exist_ok=True)path.unlink(missing_ok=True)site=web.UnixSite(runner,str(path))awaitsite.start()os.chmod(path,0o660)try:shutil.chown(path,group=config.socket_group)except(LookupError,PermissionError,OSError)asexc:log.warning('could not set group %r on %s (%s) — dev run?',config.socket_group,path,exc)log.info('listening on %s (group %s)',path,config.socket_group)stop=asyncio.Event()loop=asyncio.get_running_loop()forsigin(signal.SIGTERM,signal.SIGINT):loop.add_signal_handler(sig,stop.set)log.info('per-user service up (user %s)',config.slugor'<unpinned dev>')awaitstop.wait()log.info('shutting down')awaitrunner.cleanup()# on_cleanup reaps every shelldefmain()->None:logging.basicConfig(level=logging.INFO,format='%(name)s: %(message)s')asyncio.run(serve())if__name__=='__main__':main()