feat(serverless): add basic sandbox isolation and flexible driver options (#17176)

## Overview
- Add a DISABLED serverless driver to explicitly turn off execution
- Clarify self-hosting docs with driver options and recommended usage
- Keep integration coverage for serverless function execution (default +
external package example)

## Notes
- Local driver remains the default for development usage; Lambda or
Disabled recommended for production deployments
- No functional changes to Lambda execution

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Introduces flexible serverless execution modes and safer local
execution.
> 
> - **New driver:** `DISABLED` serverless driver with wiring in
`serverless.interface`, factory, module provider, and GraphQL exception
mapping; new exception code `SERVERLESS_FUNCTION_DISABLED`.
> - **Local driver hardening:** Strip `NODE_OPTIONS` when spawning child
processes; cleanup promise signature; better log capture.
> - **Dependency build reliability:** Use `execFile` with bundled Yarn
(`.yarn/releases/yarn-4.9.2.cjs`), strip `NODE_OPTIONS`, improved error
messages, and parallel cleanup excluding `node_modules`.
> - **Docs:** Add serverless section detailing `SERVERLESS_TYPE` options
(LOCAL, LAMBDA, DISABLED), security notice, and recommended configs.
> - **Config/env:** Default
`IS_WORKSPACE_CREATION_LIMITED_TO_SERVER_ADMINS` set to `true`
(examples/tests default `false`); sample envs updated.
> - **Tests:** Add integration tests and GraphQL helpers for creating,
updating, publishing, executing, and deleting serverless functions,
including external package usage and error paths.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
1a2958cc19cff1b0108c51b83095bbf95e75d931. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
This commit is contained in:
Félix Malfait
2026-01-16 15:54:44 +01:00
committed by GitHub
parent 9620961f16
commit 6a709d9c50
21 changed files with 677 additions and 22 deletions
@@ -14,6 +14,7 @@ export enum ServerlessFunctionExceptionCode {
SERVERLESS_FUNCTION_EXECUTION_LIMIT_REACHED = 'SERVERLESS_FUNCTION_EXECUTION_LIMIT_REACHED',
SERVERLESS_FUNCTION_CREATE_FAILED = 'SERVERLESS_FUNCTION_CREATE_FAILED',
SERVERLESS_FUNCTION_EXECUTION_TIMEOUT = 'SERVERLESS_FUNCTION_EXECUTION_TIMEOUT',
SERVERLESS_FUNCTION_DISABLED = 'SERVERLESS_FUNCTION_DISABLED',
}
const getServerlessFunctionExceptionUserFriendlyMessage = (
@@ -38,6 +39,8 @@ const getServerlessFunctionExceptionUserFriendlyMessage = (
return msg`Failed to create function.`;
case ServerlessFunctionExceptionCode.SERVERLESS_FUNCTION_EXECUTION_TIMEOUT:
return msg`Function execution timed out.`;
case ServerlessFunctionExceptionCode.SERVERLESS_FUNCTION_DISABLED:
return msg`Serverless function execution is disabled.`;
default:
assertUnreachable(code);
}
@@ -29,6 +29,8 @@ export const serverlessFunctionGraphQLApiExceptionHandler = (error: any) => {
case ServerlessFunctionExceptionCode.SERVERLESS_FUNCTION_CODE_UNCHANGED:
case ServerlessFunctionExceptionCode.SERVERLESS_FUNCTION_CREATE_FAILED:
throw error;
case ServerlessFunctionExceptionCode.SERVERLESS_FUNCTION_DISABLED:
throw new ForbiddenError(error);
default: {
return assertUnreachable(error.code);
}