@decocms/sandbox-controller 0.16.2 → 0.16.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -3730,6 +3730,15 @@ interface FreestyleSandboxProviderOptions {
3730
3730
  image?: string;
3731
3731
  /** The org-fs sidecar image. Default: the chart's `orgFs.image`. */
3732
3732
  orgFsSidecarImage?: string;
3733
+ /**
3734
+ * What the daemon signs the bot's commits with, as the sandbox-env chart's
3735
+ * `commitSigning` does for pods. Unset leaves commits unsigned. The key goes
3736
+ * into the base snapshot, so code in any of these sandboxes can read it.
3737
+ */
3738
+ commitSigning?: {
3739
+ email: string;
3740
+ privateKey: string;
3741
+ };
3733
3742
  /** Pause a VM after this long without network activity. Default 5 min. */
3734
3743
  idleTimeoutSeconds?: number;
3735
3744
  /**
@@ -3760,6 +3769,7 @@ declare class FreestyleSandboxProvider implements SandboxProvider {
3760
3769
  private readonly image;
3761
3770
  private readonly sidecarImage;
3762
3771
  private readonly allowUserNamespaces;
3772
+ private readonly commitSigning;
3763
3773
  private readonly idleTimeoutSeconds;
3764
3774
  private readonly idlePauseMs;
3765
3775
  private readonly autoDeleteSeconds;
package/dist/index.js CHANGED
@@ -6804,7 +6804,7 @@ var Freestyle = class {
6804
6804
  // ../sandbox/package.json
6805
6805
  var package_default = {
6806
6806
  name: "@decocms/sandbox",
6807
- version: "1.96.2",
6807
+ version: "1.96.3",
6808
6808
  private: true,
6809
6809
  type: "module",
6810
6810
  description: "Sandbox runtime for isolated Studio tool execution",
@@ -6888,6 +6888,8 @@ var DEFAULT_SIDECAR_IMAGE = "ghcr.io/decocms/studio/orgfs-sidecar:0.2.0";
6888
6888
  var HOST_ORG_DIR = "/srv/sandbox/org";
6889
6889
  var HOST_CTL_DIR = "/srv/sandbox/orgfs-ctl";
6890
6890
  var CTL_DIR = "/run/orgfs";
6891
+ var HOST_SIGNING_KEY = "/srv/sandbox/git-signing-key";
6892
+ var SIGNING_KEY_FILE = "/run/git-signing/key";
6891
6893
  var HOST_SETUP = [
6892
6894
  `mkdir -p ${HOST_ORG_DIR} ${HOST_CTL_DIR}`,
6893
6895
  `grep -q ' ${HOST_ORG_DIR} ' /etc/fstab || printf '%s\\n' '${HOST_ORG_DIR} ${HOST_ORG_DIR} none bind,rshared 0 0' 'tmpfs ${HOST_CTL_DIR} tmpfs uid=1000,gid=1000,mode=0755,size=1m 0 0' >> /etc/fstab`,
@@ -6924,6 +6926,7 @@ var FreestyleSandboxProvider = class {
6924
6926
  image;
6925
6927
  sidecarImage;
6926
6928
  allowUserNamespaces;
6929
+ commitSigning;
6927
6930
  idleTimeoutSeconds;
6928
6931
  idlePauseMs;
6929
6932
  autoDeleteSeconds;
@@ -6965,6 +6968,7 @@ var FreestyleSandboxProvider = class {
6965
6968
  this.image = opts.image ?? `ghcr.io/decocms/studio/studio-sandbox-go:${package_default.version}`;
6966
6969
  this.sidecarImage = opts.orgFsSidecarImage ?? DEFAULT_SIDECAR_IMAGE;
6967
6970
  this.allowUserNamespaces = opts.allowUserNamespaces ?? false;
6971
+ this.commitSigning = opts.commitSigning;
6968
6972
  this.idleTimeoutSeconds = opts.idleTimeoutSeconds ?? 5 * 60;
6969
6973
  this.idlePauseMs = opts.idlePauseMs ?? 10 * 6e4;
6970
6974
  this.autoDeleteSeconds = opts.autoDeleteSeconds ?? 24 * 60 * 60;
@@ -7031,9 +7035,13 @@ var FreestyleSandboxProvider = class {
7031
7035
  baseSnapshot() {
7032
7036
  const { image, sidecarImage } = this;
7033
7037
  const namespaceMode = this.allowUserNamespaces ? "\nuser-namespaces" : "";
7038
+ const signing = this.commitSigning ? `
7039
+ signing
7040
+ ${this.commitSigning.email}
7041
+ ${this.commitSigning.privateKey}` : "";
7034
7042
  const slug = `studio-sandbox-${createHash3("sha256").update(`${image}
7035
7043
  ${sidecarImage}
7036
- running${namespaceMode}`).digest("hex").slice(0, 16)}`;
7044
+ running${namespaceMode}${signing}`).digest("hex").slice(0, 16)}`;
7037
7045
  if (this.knownSnapshots.has(slug)) return Promise.resolve(slug);
7038
7046
  return this.snapshotInflight.run(slug, async () => {
7039
7047
  if (await this.snapshotExists(slug)) {
@@ -7086,9 +7094,21 @@ running${namespaceMode}`).digest("hex").slice(0, 16)}`;
7086
7094
  APP_ROOT: WORKDIR,
7087
7095
  PROXY_PORT: String(DAEMON_PORT),
7088
7096
  ORGFS_SIDECAR_CONFIG_PATH: `${CTL_DIR}/config.json`,
7089
- ORGFS_SIDECAR_STATUS_PATH: `${CTL_DIR}/status.json`
7097
+ ORGFS_SIDECAR_STATUS_PATH: `${CTL_DIR}/status.json`,
7098
+ ...this.commitSigning && {
7099
+ GIT_SIGNING_KEY_FILE: SIGNING_KEY_FILE,
7100
+ GIT_SIGNING_KEY_EMAIL: this.commitSigning.email
7101
+ }
7090
7102
  };
7091
7103
  const envFlags = Object.keys(env).map((k) => `-e ${shellQuote(k)}`).join(" ");
7104
+ if (this.commitSigning) {
7105
+ await this.run(
7106
+ vm,
7107
+ `printf '%s' "$GIT_SIGNING_KEY" | sudo sh -c 'umask 377 && cat > ${HOST_SIGNING_KEY} && chown 1000:1000 ${HOST_SIGNING_KEY}'`,
7108
+ { env: { GIT_SIGNING_KEY: this.commitSigning.privateKey } }
7109
+ );
7110
+ }
7111
+ const signingKeyMount = this.commitSigning ? ` -v ${HOST_SIGNING_KEY}:${SIGNING_KEY_FILE}:ro` : "";
7092
7112
  await this.run(
7093
7113
  vm,
7094
7114
  `sudo sh -c ${shellQuote(HOST_SETUP)} && docker run -d --name ${SIDECAR} --restart=always --privileged --device /dev/fuse -e APP_ROOT=${WORKDIR} -e ORGFS_FEED_IDLE_MS=60000 -v ${HOST_ORG_DIR}:${WORKDIR}/org:rshared -v ${HOST_CTL_DIR}:${CTL_DIR} ${shellQuote(this.sidecarImage)}`,
@@ -7097,7 +7117,7 @@ running${namespaceMode}`).digest("hex").slice(0, 16)}`;
7097
7117
  await this.run(
7098
7118
  vm,
7099
7119
  // Codex's read-only sandbox uses bubblewrap inside this per-user VM.
7100
- `docker run -d --name ${CONTAINER} --restart=always${this.allowUserNamespaces ? " --security-opt seccomp=unconfined --security-opt apparmor=unconfined" : ""} -p ${DAEMON_PORT}:${DAEMON_PORT} -v ${HOST_ORG_DIR}:${WORKDIR}/org:rslave -v ${HOST_CTL_DIR}:${CTL_DIR} ${envFlags} ${shellQuote(this.image)}`,
7120
+ `docker run -d --name ${CONTAINER} --restart=always${this.allowUserNamespaces ? " --security-opt seccomp=unconfined --security-opt apparmor=unconfined" : ""} -p ${DAEMON_PORT}:${DAEMON_PORT} -v ${HOST_ORG_DIR}:${WORKDIR}/org:rslave -v ${HOST_CTL_DIR}:${CTL_DIR}${signingKeyMount} ${envFlags} ${shellQuote(this.image)}`,
7101
7121
  { env, timeoutMs: IMAGE_PULL_TIMEOUT_MS }
7102
7122
  );
7103
7123
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@decocms/sandbox-controller",
3
- "version": "0.16.2",
3
+ "version": "0.16.3",
4
4
  "description": "Runs Studio agent sandboxes on Kubernetes, and serves them to a remote Studio.",
5
5
  "repository": {
6
6
  "type": "git",