[Unit] Description=Curriculum Project Hub (Feishu agent + cph) After=network-online.target postgresql.service Wants=network-online.target [Service] Type=simple User=__SERVICE_USER__ WorkingDirectory=__HUB_DIR__ EnvironmentFile=__ENV_FILE__ # Run prisma migrations before each start, then launch the Hub. ExecStartPre=__NODE_BIN__ __HUB_DIR__/node_modules/prisma/build/index.js migrate deploy --schema __HUB_DIR__/prisma/schema.prisma ExecStart=__NODE_BIN__ __HUB_DIR__/dist/server.js Restart=on-failure RestartSec=5 # Graceful shutdown: lark ws close + in-flight runs. KillSignal=SIGTERM TimeoutStopSec=30 # ADR-0018: the agent sandbox (bubblewrap) must be available on the host — # failIfUnavailable makes the Hub refuse to run unsandboxed. Install bwrap. AssertPathExists=/usr/bin/bwrap # Hardening: no new privileges. ProtectSystem/ProtectHome are NOT set here — # they would break cph's render-cache extraction (~/.cache/cph/) and the # bwrap user-namespace setup. The OS-level sandbox (ADR-0018) is the hard # boundary; systemd hardening is kept minimal to avoid interfering with it. NoNewPrivileges=true [Install] WantedBy=multi-user.target