@ai-development-environment/control-agent 0.0.33 → 0.0.35

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.
Files changed (2) hide show
  1. package/dist/control-agent.js +847 -123
  2. package/package.json +1 -1
@@ -842,6 +842,18 @@ var AgentGraphQLClient = class {
842
842
  );
843
843
  return data.claimAgentJob;
844
844
  }
845
+ async claimSigningSecretTransfer(transferId) {
846
+ const data = await this.request(
847
+ `mutation ClaimSigningSecretTransfer($transferId: ID!) {
848
+ claimSigningSecretTransfer(transferId: $transferId) {
849
+ p12Base64
850
+ passphrase
851
+ }
852
+ }`,
853
+ { transferId }
854
+ );
855
+ return data.claimSigningSecretTransfer;
856
+ }
845
857
  appendLog(jobId, log) {
846
858
  return this.request(
847
859
  `mutation AppendLog($jobId: ID!, $logs: [AgentJobLogInput!]!) {
@@ -2596,6 +2608,53 @@ function parseScript(value, index) {
2596
2608
  position
2597
2609
  };
2598
2610
  }
2611
+ function httpUrl(value, name) {
2612
+ const text2 = stringValue6(value, name);
2613
+ let url;
2614
+ try {
2615
+ url = new URL(text2);
2616
+ } catch {
2617
+ throw new Error(`${name} must be a valid HTTP(S) URL`);
2618
+ }
2619
+ if (url.protocol !== "http:" && url.protocol !== "https:") {
2620
+ throw new Error(`${name} must be a valid HTTP(S) URL`);
2621
+ }
2622
+ return url.toString().replace(/\/$/, "");
2623
+ }
2624
+ function parseBuildTelemetrySettings(value) {
2625
+ if (value === void 0 || value === null) return void 0;
2626
+ const input = objectValue6(value, "build job payload.telemetry");
2627
+ return {
2628
+ localBaseUrl: httpUrl(
2629
+ input.localBaseUrl,
2630
+ "build job payload.telemetry.localBaseUrl"
2631
+ ),
2632
+ remoteBaseUrl: httpUrl(
2633
+ input.remoteBaseUrl,
2634
+ "build job payload.telemetry.remoteBaseUrl"
2635
+ ),
2636
+ selectedBaseUrl: httpUrl(
2637
+ input.selectedBaseUrl,
2638
+ "build job payload.telemetry.selectedBaseUrl"
2639
+ ),
2640
+ consoleLogsUrl: httpUrl(
2641
+ input.consoleLogsUrl,
2642
+ "build job payload.telemetry.consoleLogsUrl"
2643
+ ),
2644
+ analyticsEventsUrl: httpUrl(
2645
+ input.analyticsEventsUrl,
2646
+ "build job payload.telemetry.analyticsEventsUrl"
2647
+ ),
2648
+ consoleCollectionEnabled: booleanValue2(
2649
+ input.consoleCollectionEnabled,
2650
+ "build job payload.telemetry.consoleCollectionEnabled"
2651
+ ),
2652
+ analyticsCollectionEnabled: booleanValue2(
2653
+ input.analyticsCollectionEnabled,
2654
+ "build job payload.telemetry.analyticsCollectionEnabled"
2655
+ )
2656
+ };
2657
+ }
2599
2658
  function parseBuildSourceDiscoverPayload(value) {
2600
2659
  return worktreeIdentity(objectValue6(value, "source discovery payload"));
2601
2660
  }
@@ -2604,7 +2663,11 @@ function parseBuildSourceParsePayload(value) {
2604
2663
  return {
2605
2664
  ...worktreeIdentity(input),
2606
2665
  source: parseBuildSource(input.source),
2607
- scheme: nullableString4(input.scheme, "source parse payload.scheme")
2666
+ scheme: nullableString4(input.scheme, "source parse payload.scheme"),
2667
+ configuration: nullableString4(
2668
+ input.configuration,
2669
+ "source parse payload.configuration"
2670
+ )
2608
2671
  };
2609
2672
  }
2610
2673
  function parseBuildDestinationsPayload(value) {
@@ -2679,6 +2742,7 @@ function parseBuildJobPayload(value) {
2679
2742
  destination,
2680
2743
  advancedSettings,
2681
2744
  scripts,
2745
+ telemetry: parseBuildTelemetrySettings(input.telemetry),
2682
2746
  worktreeCoverage: input.worktreeCoverage === void 0 ? false : booleanValue2(
2683
2747
  input.worktreeCoverage,
2684
2748
  "build job payload.worktreeCoverage"
@@ -2822,6 +2886,23 @@ function parseBuildExportSettings(value) {
2822
2886
  testFlightInternalTestingOnly: booleanValue2(
2823
2887
  input.testFlightInternalTestingOnly,
2824
2888
  "export settings.testFlightInternalTestingOnly"
2889
+ ),
2890
+ stripSwiftSymbols: input.stripSwiftSymbols === void 0 ? true : booleanValue2(
2891
+ input.stripSwiftSymbols,
2892
+ "export settings.stripSwiftSymbols"
2893
+ ),
2894
+ thinning: nullableString4(
2895
+ input.thinning ?? null,
2896
+ "export settings.thinning"
2897
+ ),
2898
+ iCloudContainerEnvironment: input.iCloudContainerEnvironment === null || input.iCloudContainerEnvironment === void 0 ? null : enumValue3(
2899
+ input.iCloudContainerEnvironment,
2900
+ ["Development", "Production"],
2901
+ "export settings.iCloudContainerEnvironment"
2902
+ ),
2903
+ distributionBundleIdentifier: nullableString4(
2904
+ input.distributionBundleIdentifier ?? null,
2905
+ "export settings.distributionBundleIdentifier"
2825
2906
  )
2826
2907
  };
2827
2908
  }
@@ -2866,6 +2947,81 @@ function parseBuildSigningInspectPayload(value) {
2866
2947
  };
2867
2948
  }
2868
2949
 
2950
+ // ../agent-contract/src/signing-assets.ts
2951
+ var SIGNING_ASSETS_SCAN_JOB_KIND = "ios.signing.assets.scan";
2952
+ var SIGNING_PROFILE_READ_JOB_KIND = "ios.signing.profile.read";
2953
+ var SIGNING_PROFILE_INSTALL_JOB_KIND = "ios.signing.profile.install";
2954
+ var SIGNING_PROFILE_DELETE_JOB_KIND = "ios.signing.profile.delete";
2955
+ var SIGNING_IDENTITY_IMPORT_JOB_KIND = "ios.signing.identity.import";
2956
+ var SIGNING_IDENTITY_DELETE_JOB_KIND = "ios.signing.identity.delete";
2957
+ var SIGNING_ASSET_JOB_KINDS = [
2958
+ SIGNING_ASSETS_SCAN_JOB_KIND,
2959
+ SIGNING_PROFILE_READ_JOB_KIND,
2960
+ SIGNING_PROFILE_INSTALL_JOB_KIND,
2961
+ SIGNING_PROFILE_DELETE_JOB_KIND,
2962
+ SIGNING_IDENTITY_IMPORT_JOB_KIND,
2963
+ SIGNING_IDENTITY_DELETE_JOB_KIND
2964
+ ];
2965
+ function objectValue7(value, name) {
2966
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
2967
+ throw new Error(`${name} must be an object`);
2968
+ }
2969
+ return value;
2970
+ }
2971
+ function stringValue7(value, name) {
2972
+ if (typeof value !== "string" || !value.trim() || value.includes("\0")) {
2973
+ throw new Error(`${name} must be a non-empty string`);
2974
+ }
2975
+ return value;
2976
+ }
2977
+ function exactKeys2(value, allowed, name) {
2978
+ const unexpected = Object.keys(value).find((key) => !allowed.includes(key));
2979
+ if (unexpected) throw new Error(`Unexpected ${name} field: ${unexpected}`);
2980
+ }
2981
+ function signingScanPayload(value) {
2982
+ const input = objectValue7(value, "signing scan payload");
2983
+ exactKeys2(input, [], "signing scan payload");
2984
+ return {};
2985
+ }
2986
+ function signingProfileKeyPayload(value) {
2987
+ const input = objectValue7(value, "signing profile payload");
2988
+ exactKeys2(input, ["uuid"], "signing profile payload");
2989
+ return { uuid: stringValue7(input.uuid, "signing profile payload.uuid") };
2990
+ }
2991
+ function signingProfileInstallPayload(value) {
2992
+ const input = objectValue7(value, "signing profile install payload");
2993
+ exactKeys2(input, ["contentBase64"], "signing profile install payload");
2994
+ const contentBase64 = stringValue7(
2995
+ input.contentBase64,
2996
+ "signing profile install payload.contentBase64"
2997
+ );
2998
+ if (contentBase64.length > 2 * 1024 * 1024) {
2999
+ throw new Error("Provisioning profile payload is too large");
3000
+ }
3001
+ return { contentBase64 };
3002
+ }
3003
+ function signingIdentityImportPayload(value) {
3004
+ const input = objectValue7(value, "signing identity import payload");
3005
+ exactKeys2(input, ["transferId", "sha256"], "signing identity import payload");
3006
+ const sha256 = stringValue7(input.sha256, "signing identity import sha256");
3007
+ if (!/^[A-Fa-f0-9]{64}$/.test(sha256)) {
3008
+ throw new Error("Signing identity import SHA-256 is invalid");
3009
+ }
3010
+ return {
3011
+ transferId: stringValue7(input.transferId, "signing identity transfer ID"),
3012
+ sha256: sha256.toUpperCase()
3013
+ };
3014
+ }
3015
+ function signingIdentityDeletePayload(value) {
3016
+ const input = objectValue7(value, "signing identity delete payload");
3017
+ exactKeys2(input, ["sha1"], "signing identity delete payload");
3018
+ const sha1 = stringValue7(input.sha1, "signing identity SHA-1");
3019
+ if (!/^[A-Fa-f0-9]{40}$/.test(sha1)) {
3020
+ throw new Error("Signing identity SHA-1 is invalid");
3021
+ }
3022
+ return { sha1: sha1.toUpperCase() };
3023
+ }
3024
+
2869
3025
  // src/inventory.ts
2870
3026
  var AGENT_VERSION = "0.1.0";
2871
3027
  var AGENT_CAPABILITIES = [
@@ -2876,7 +3032,8 @@ var AGENT_CAPABILITIES = [
2876
3032
  CODEBASE_RECONCILE_EVENT_CAPABILITY,
2877
3033
  ...WORKTREE_JOB_KINDS,
2878
3034
  ...SKILL_JOB_KINDS,
2879
- ...IOS_BUILD_JOB_KINDS
3035
+ ...IOS_BUILD_JOB_KINDS,
3036
+ ...SIGNING_ASSET_JOB_KINDS
2880
3037
  ];
2881
3038
  function collectInventory() {
2882
3039
  const disk = statfsSync("/", { bigint: true });
@@ -3006,9 +3163,17 @@ function runCloudflared(payload, timeoutMs, signal, onLog) {
3006
3163
  }
3007
3164
 
3008
3165
  // src/handlers/signing.ts
3009
- import { createHash as createHash2 } from "node:crypto";
3010
- import { readdir, stat as stat2 } from "node:fs/promises";
3011
- import { homedir as homedir2 } from "node:os";
3166
+ import { createHash as createHash2, randomUUID, X509Certificate } from "node:crypto";
3167
+ import {
3168
+ mkdir as mkdir2,
3169
+ mkdtemp,
3170
+ readFile as readFile2,
3171
+ readdir,
3172
+ rm,
3173
+ stat as stat2,
3174
+ writeFile as writeFile2
3175
+ } from "node:fs/promises";
3176
+ import { homedir as homedir2, tmpdir } from "node:os";
3012
3177
  import { basename, join as join2, relative, sep } from "node:path";
3013
3178
 
3014
3179
  // ../agent-contract/src/plist.ts
@@ -3246,7 +3411,7 @@ function text(value) {
3246
3411
  function stringList(value) {
3247
3412
  return Array.isArray(value) ? value.filter((v) => typeof v === "string") : [];
3248
3413
  }
3249
- async function decodeProfile(path, timeoutMs, signal) {
3414
+ async function decodeProfile(path, timeoutMs, signal, strict = false) {
3250
3415
  try {
3251
3416
  const result = await captureCommand({
3252
3417
  command: "/usr/bin/security",
@@ -3254,16 +3419,29 @@ async function decodeProfile(path, timeoutMs, signal) {
3254
3419
  timeoutMs: Math.min(timeoutMs, 1e4),
3255
3420
  signal
3256
3421
  });
3422
+ if (strict) assertCommandSucceeded(result, `Reading profile ${path}`);
3257
3423
  if (result.exitCode !== 0 || !result.stdout.trim()) return null;
3258
3424
  const parsed = parsePlist(result.stdout);
3259
3425
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
3426
+ if (strict) throw new Error(`Profile ${path} did not contain a plist`);
3260
3427
  return null;
3261
3428
  }
3262
3429
  return parsed;
3263
- } catch {
3430
+ } catch (error) {
3431
+ if (strict) throw error;
3264
3432
  return null;
3265
3433
  }
3266
3434
  }
3435
+ function assertCommandSucceeded(result, action) {
3436
+ if (result.cancelled) throw new Error(`${action} was cancelled`);
3437
+ if (result.timedOut) throw new Error(`${action} timed out`);
3438
+ if (result.exitCode !== 0) {
3439
+ const detail = result.stderr.trim();
3440
+ throw new Error(
3441
+ `${action} failed${detail ? `: ${detail}` : ` with exit code ${String(result.exitCode)}`}`
3442
+ );
3443
+ }
3444
+ }
3267
3445
  function toProfile(uuid, raw, now) {
3268
3446
  const name = text(raw.Name);
3269
3447
  if (!name) return null;
@@ -3333,6 +3511,66 @@ async function readProfiles(timeoutMs, signal) {
3333
3511
  (left, right) => left.name.localeCompare(right.name)
3334
3512
  );
3335
3513
  }
3514
+ async function decodedProfiles(timeoutMs, signal, strict = false) {
3515
+ const profiles = [];
3516
+ if (strict) signal.throwIfAborted();
3517
+ for (const directory of PROFILE_DIRECTORIES) {
3518
+ let entries;
3519
+ try {
3520
+ entries = await readdir(directory);
3521
+ } catch (error) {
3522
+ if (strict && error.code !== "ENOENT") {
3523
+ throw error;
3524
+ }
3525
+ continue;
3526
+ }
3527
+ for (const entry of entries) {
3528
+ if (!PROFILE_EXTENSIONS.some((suffix) => entry.endsWith(suffix))) {
3529
+ continue;
3530
+ }
3531
+ signal.throwIfAborted();
3532
+ const path = join2(directory, entry);
3533
+ const raw = await decodeProfile(path, timeoutMs, signal, strict);
3534
+ if (!raw) continue;
3535
+ let content;
3536
+ try {
3537
+ content = await readFile2(path);
3538
+ } catch (error) {
3539
+ if (strict) throw error;
3540
+ continue;
3541
+ }
3542
+ profiles.push({
3543
+ path,
3544
+ content,
3545
+ raw,
3546
+ uuid: text(raw.UUID) ?? basename(entry).replace(/\.[^.]+$/, "")
3547
+ });
3548
+ }
3549
+ }
3550
+ return profiles;
3551
+ }
3552
+ function profileAsset(decoded, now) {
3553
+ const profile = toProfile(decoded.uuid, decoded.raw, now);
3554
+ if (!profile) return null;
3555
+ const createdAt = text(decoded.raw.CreationDate);
3556
+ return {
3557
+ uuid: profile.uuid,
3558
+ contentHash: createHash2("sha256").update(decoded.content).digest("hex").toUpperCase(),
3559
+ name: profile.name,
3560
+ profileType: profile.type,
3561
+ bundleId: profile.bundleId,
3562
+ teamId: profile.teamId,
3563
+ teamName: profile.teamName,
3564
+ platforms: profile.platforms,
3565
+ deviceCount: stringList(decoded.raw.ProvisionedDevices).length,
3566
+ deviceUdids: stringList(decoded.raw.ProvisionedDevices),
3567
+ certificateSha1s: profile.certificateSha1s,
3568
+ createdAt,
3569
+ expiresAt: profile.expiresAt,
3570
+ expired: profile.expired,
3571
+ xcodeManaged: profile.xcodeManaged
3572
+ };
3573
+ }
3336
3574
  function dedupeProfiles(profiles) {
3337
3575
  const best = /* @__PURE__ */ new Map();
3338
3576
  for (const profile of profiles) {
@@ -3353,7 +3591,7 @@ function dedupeProfiles(profiles) {
3353
3591
  return [...best.values()];
3354
3592
  }
3355
3593
  var IDENTITY_PATTERN = /^\s*\d+\)\s+([0-9A-F]{40})\s+"(.+)"\s*$/i;
3356
- async function readIdentities(timeoutMs, signal) {
3594
+ async function readIdentities(timeoutMs, signal, strict = false) {
3357
3595
  try {
3358
3596
  const result = await captureCommand({
3359
3597
  command: "/usr/bin/security",
@@ -3361,6 +3599,7 @@ async function readIdentities(timeoutMs, signal) {
3361
3599
  timeoutMs: Math.min(timeoutMs, 1e4),
3362
3600
  signal
3363
3601
  });
3602
+ if (strict) assertCommandSucceeded(result, "Reading signing identities");
3364
3603
  if (result.exitCode !== 0) return [];
3365
3604
  const identities = /* @__PURE__ */ new Map();
3366
3605
  for (const line of result.stdout.split("\n")) {
@@ -3371,10 +3610,80 @@ async function readIdentities(timeoutMs, signal) {
3371
3610
  identities.set(sha1, { sha1, name, teamId: team?.[1] ?? null });
3372
3611
  }
3373
3612
  return [...identities.values()];
3374
- } catch {
3613
+ } catch (error) {
3614
+ if (strict) throw error;
3375
3615
  return [];
3376
3616
  }
3377
3617
  }
3618
+ function commonName(certificate) {
3619
+ return certificate.subject.split(/\n|,\s*/).find((part) => part.startsWith("CN="))?.slice(3) ?? certificate.subject;
3620
+ }
3621
+ function certificateType(name) {
3622
+ const known = [
3623
+ "Apple Development",
3624
+ "Apple Distribution",
3625
+ "iPhone Developer",
3626
+ "iPhone Distribution",
3627
+ "iOS Developer",
3628
+ "iOS Distribution",
3629
+ "Mac Developer",
3630
+ "Mac App Distribution",
3631
+ "Developer ID Application",
3632
+ "Developer ID Installer"
3633
+ ];
3634
+ return known.find((prefix) => name.startsWith(prefix)) ?? null;
3635
+ }
3636
+ function pemCertificates(value) {
3637
+ return value.match(
3638
+ /-----BEGIN CERTIFICATE-----[\s\S]+?-----END CERTIFICATE-----/g
3639
+ ) ?? [];
3640
+ }
3641
+ async function readCertificates(timeoutMs, signal, strict = false) {
3642
+ const [certificateResult, identities] = await Promise.all([
3643
+ captureCommand({
3644
+ command: "/usr/bin/security",
3645
+ args: ["find-certificate", "-a", "-p"],
3646
+ timeoutMs: Math.min(timeoutMs, 2e4),
3647
+ signal
3648
+ }),
3649
+ readIdentities(timeoutMs, signal, strict)
3650
+ ]);
3651
+ if (strict) {
3652
+ assertCommandSucceeded(certificateResult, "Reading signing certificates");
3653
+ }
3654
+ if (certificateResult.exitCode !== 0) return [];
3655
+ const identityHashes = new Set(
3656
+ identities.map((identity) => identity.sha1.toUpperCase())
3657
+ );
3658
+ const assets = /* @__PURE__ */ new Map();
3659
+ for (const pem of pemCertificates(certificateResult.stdout)) {
3660
+ try {
3661
+ const certificate = new X509Certificate(pem);
3662
+ const name = commonName(certificate);
3663
+ const type = certificateType(name);
3664
+ if (!type) continue;
3665
+ const sha1 = certificate.fingerprint.replaceAll(":", "").toUpperCase();
3666
+ const expiresAt = new Date(certificate.validTo);
3667
+ const team = /\(([A-Z0-9]{10})\)\s*$/.exec(name);
3668
+ assets.set(sha1, {
3669
+ sha1,
3670
+ sha256: certificate.fingerprint256.replaceAll(":", "").toUpperCase(),
3671
+ name,
3672
+ teamId: team?.[1] ?? null,
3673
+ certificateType: type,
3674
+ notBefore: new Date(certificate.validFrom).toISOString(),
3675
+ expiresAt: expiresAt.toISOString(),
3676
+ expired: expiresAt.getTime() < Date.now(),
3677
+ hasPrivateKey: identityHashes.has(sha1)
3678
+ });
3679
+ } catch {
3680
+ continue;
3681
+ }
3682
+ }
3683
+ return [...assets.values()].sort(
3684
+ (left, right) => left.name.localeCompare(right.name)
3685
+ );
3686
+ }
3378
3687
  async function readArchiveBundles(archivePath, timeoutMs, signal) {
3379
3688
  const products = join2(archivePath, "Products");
3380
3689
  const bundles = [];
@@ -3495,6 +3804,139 @@ var inspectIosSigning = async (payload, timeoutMs, signal) => {
3495
3804
  ...inspection
3496
3805
  };
3497
3806
  };
3807
+ var successfulProcess = {
3808
+ exitCode: 0,
3809
+ signal: null,
3810
+ timedOut: false,
3811
+ cancelled: false
3812
+ };
3813
+ var scanSigningAssets = async (payload, timeoutMs, signal) => {
3814
+ signingScanPayload(payload);
3815
+ const [decoded, certificates] = await Promise.all([
3816
+ decodedProfiles(timeoutMs, signal, true),
3817
+ readCertificates(timeoutMs, signal, true)
3818
+ ]);
3819
+ const byUuid = /* @__PURE__ */ new Map();
3820
+ for (const profile of decoded) {
3821
+ const asset = profileAsset(profile, Date.now());
3822
+ if (!asset) continue;
3823
+ const existing = byUuid.get(asset.uuid);
3824
+ if (!existing || (asset.expiresAt ?? "") > (existing.expiresAt ?? "")) {
3825
+ byUuid.set(asset.uuid, asset);
3826
+ }
3827
+ }
3828
+ return {
3829
+ ...successfulProcess,
3830
+ profiles: [...byUuid.values()].sort(
3831
+ (left, right) => left.name.localeCompare(right.name)
3832
+ ),
3833
+ certificates,
3834
+ warnings: []
3835
+ };
3836
+ };
3837
+ async function findDecodedProfile(uuid, timeoutMs, signal) {
3838
+ const profile = (await decodedProfiles(timeoutMs, signal)).find(
3839
+ (entry) => entry.uuid === uuid
3840
+ );
3841
+ if (!profile) throw new Error("Provisioning profile is no longer installed");
3842
+ return profile;
3843
+ }
3844
+ var readSigningProfile = async (payload, timeoutMs, signal) => {
3845
+ const { uuid } = signingProfileKeyPayload(payload);
3846
+ const profile = await findDecodedProfile(uuid, timeoutMs, signal);
3847
+ return {
3848
+ ...successfulProcess,
3849
+ uuid,
3850
+ contentBase64: profile.content.toString("base64"),
3851
+ sha256: createHash2("sha256").update(profile.content).digest("hex").toUpperCase()
3852
+ };
3853
+ };
3854
+ var installSigningProfile = async (payload, timeoutMs, signal) => {
3855
+ const { contentBase64 } = signingProfileInstallPayload(payload);
3856
+ const content = Buffer.from(contentBase64, "base64");
3857
+ if (!content.length) throw new Error("Provisioning profile is empty");
3858
+ const temporaryRoot = await mkdtemp(join2(tmpdir(), "ade-profile-"));
3859
+ const temporaryPath = join2(temporaryRoot, `${randomUUID()}.mobileprovision`);
3860
+ try {
3861
+ await writeFile2(temporaryPath, content, { mode: 384 });
3862
+ const raw = await decodeProfile(temporaryPath, timeoutMs, signal);
3863
+ if (!raw) throw new Error("Provisioning profile is invalid or unsigned");
3864
+ const uuid = text(raw.UUID);
3865
+ if (!uuid) throw new Error("Provisioning profile UUID is missing");
3866
+ const directory = PROFILE_DIRECTORIES[0];
3867
+ await mkdir2(directory, { recursive: true, mode: 448 });
3868
+ const destination = join2(directory, `${uuid}.mobileprovision`);
3869
+ await writeFile2(destination, content, { mode: 384 });
3870
+ return { ...successfulProcess, uuid };
3871
+ } finally {
3872
+ await rm(temporaryRoot, { recursive: true, force: true });
3873
+ }
3874
+ };
3875
+ var deleteSigningProfile = async (payload, timeoutMs, signal) => {
3876
+ const { uuid } = signingProfileKeyPayload(payload);
3877
+ const matches = (await decodedProfiles(timeoutMs, signal)).filter(
3878
+ (entry) => entry.uuid === uuid
3879
+ );
3880
+ for (const profile of matches) {
3881
+ signal.throwIfAborted();
3882
+ await rm(profile.path, { force: false });
3883
+ }
3884
+ return { ...successfulProcess, uuid, deleted: matches.length };
3885
+ };
3886
+ var importSigningIdentity = async (payload, timeoutMs, signal, _onLog, context) => {
3887
+ const input = signingIdentityImportPayload(payload);
3888
+ if (!context?.claimSigningSecretTransfer) {
3889
+ throw new Error("This agent cannot claim signing secret transfers");
3890
+ }
3891
+ const secret = await context.claimSigningSecretTransfer(input.transferId);
3892
+ const p12 = Buffer.from(secret.p12Base64, "base64");
3893
+ const hash = createHash2("sha256").update(p12).digest("hex").toUpperCase();
3894
+ if (hash !== input.sha256)
3895
+ throw new Error("Signing identity transfer changed");
3896
+ const temporaryRoot = await mkdtemp(join2(tmpdir(), "ade-identity-"));
3897
+ const path = join2(temporaryRoot, "identity.p12");
3898
+ try {
3899
+ await writeFile2(path, p12, { mode: 384 });
3900
+ const result = await captureCommand({
3901
+ command: "/usr/bin/security",
3902
+ args: [
3903
+ "import",
3904
+ path,
3905
+ "-P",
3906
+ secret.passphrase,
3907
+ "-T",
3908
+ "/usr/bin/codesign",
3909
+ "-T",
3910
+ "/usr/bin/security"
3911
+ ],
3912
+ timeoutMs: Math.min(timeoutMs, 6e4),
3913
+ signal
3914
+ });
3915
+ if (result.exitCode !== 0) {
3916
+ throw new Error(
3917
+ result.stderr.trim() || "Could not import signing identity"
3918
+ );
3919
+ }
3920
+ return { ...successfulProcess, sha256: input.sha256 };
3921
+ } finally {
3922
+ await rm(temporaryRoot, { recursive: true, force: true });
3923
+ }
3924
+ };
3925
+ var deleteSigningIdentity = async (payload, timeoutMs, signal) => {
3926
+ const { sha1 } = signingIdentityDeletePayload(payload);
3927
+ const result = await captureCommand({
3928
+ command: "/usr/bin/security",
3929
+ args: ["delete-identity", "-Z", sha1],
3930
+ timeoutMs: Math.min(timeoutMs, 3e4),
3931
+ signal
3932
+ });
3933
+ if (result.exitCode !== 0) {
3934
+ throw new Error(
3935
+ result.stderr.trim() || "Could not delete signing identity"
3936
+ );
3937
+ }
3938
+ return { ...successfulProcess, sha1 };
3939
+ };
3498
3940
 
3499
3941
  // src/handlers/ccusage.ts
3500
3942
  import { Buffer as Buffer2 } from "node:buffer";
@@ -3551,10 +3993,10 @@ async function runCcusage(payload, timeoutMs, signal, onLog) {
3551
3993
  }
3552
3994
 
3553
3995
  // src/handlers/build-data.ts
3554
- import { lstat, opendir, readdir as readdir2, realpath, rm } from "node:fs/promises";
3996
+ import { lstat, opendir, readdir as readdir2, realpath, rm as rm2 } from "node:fs/promises";
3555
3997
  import { homedir as homedir3 } from "node:os";
3556
3998
  import { basename as basename2, dirname as dirname2, isAbsolute, join as join3, resolve } from "node:path";
3557
- var successfulProcess = {
3999
+ var successfulProcess2 = {
3558
4000
  exitCode: 0,
3559
4001
  signal: null,
3560
4002
  timedOut: false,
@@ -3647,6 +4089,43 @@ async function scanRoot(configuredRoot, timeoutMs, signal) {
3647
4089
  entries.sort((first, second) => first.name.localeCompare(second.name));
3648
4090
  return { entries, warning: null };
3649
4091
  }
4092
+ async function scanDeviceSupport(signal) {
4093
+ const configuredRoot = join3(
4094
+ process.env.ADE_IOS_DEVICE_SUPPORT_DIRECTORY ?? homedir3(),
4095
+ ...process.env.ADE_IOS_DEVICE_SUPPORT_DIRECTORY ? [] : ["Library", "Developer", "Xcode", "iOS DeviceSupport"]
4096
+ );
4097
+ signal.throwIfAborted();
4098
+ let rootPath2;
4099
+ try {
4100
+ rootPath2 = await realpath(configuredRoot);
4101
+ } catch (error) {
4102
+ if (error.code === "ENOENT") {
4103
+ return { entries: [], warning: null };
4104
+ }
4105
+ return {
4106
+ entries: [],
4107
+ warning: `${configuredRoot}: ${errorMessage(error)}`
4108
+ };
4109
+ }
4110
+ try {
4111
+ const children = await readdir2(rootPath2, { withFileTypes: true });
4112
+ return {
4113
+ entries: children.filter((child) => child.isDirectory() && !child.isSymbolicLink()).map((child) => ({
4114
+ path: join3(rootPath2, child.name),
4115
+ rootPath: rootPath2,
4116
+ name: child.name,
4117
+ kind: "DEVICE_SUPPORT",
4118
+ workspacePath: null
4119
+ })).sort((first, second) => first.name.localeCompare(second.name)),
4120
+ warning: null
4121
+ };
4122
+ } catch (error) {
4123
+ return {
4124
+ entries: [],
4125
+ warning: `${rootPath2}: ${errorMessage(error)}`
4126
+ };
4127
+ }
4128
+ }
3650
4129
  var scanBuildData = async (rawPayload, timeoutMs, signal) => {
3651
4130
  const payload = buildDataScanPayload(rawPayload);
3652
4131
  const roots = await configuredRoots(payload);
@@ -3666,7 +4145,10 @@ var scanBuildData = async (rawPayload, timeoutMs, signal) => {
3666
4145
  entries.push(...result.entries);
3667
4146
  if (result.warning) warnings.push(result.warning);
3668
4147
  }
3669
- return { ...successfulProcess, entries, warnings };
4148
+ const deviceSupport = await scanDeviceSupport(signal);
4149
+ entries.push(...deviceSupport.entries);
4150
+ if (deviceSupport.warning) warnings.push(deviceSupport.warning);
4151
+ return { ...successfulProcess2, entries, warnings };
3670
4152
  };
3671
4153
  function assertDirectChild(rootPath2, path) {
3672
4154
  if (!isAbsolute(rootPath2) || !isAbsolute(path)) {
@@ -3724,7 +4206,7 @@ var sizeBuildData = async (rawPayload, _timeoutMs, signal) => {
3724
4206
  });
3725
4207
  }
3726
4208
  }
3727
- return { ...successfulProcess, sizes };
4209
+ return { ...successfulProcess2, sizes };
3728
4210
  };
3729
4211
  var deleteBuildData = async (rawPayload, _timeoutMs, signal) => {
3730
4212
  const payload = buildDataTargetsPayload(rawPayload);
@@ -3741,7 +4223,7 @@ var deleteBuildData = async (rawPayload, _timeoutMs, signal) => {
3741
4223
  if (!stats.isDirectory() || stats.isSymbolicLink()) {
3742
4224
  throw new Error("Build Data target is not a directory");
3743
4225
  }
3744
- await rm(target2.path, { recursive: true, force: false, maxRetries: 3 });
4226
+ await rm2(target2.path, { recursive: true, force: false, maxRetries: 3 });
3745
4227
  deleted.push({ path: target2.path, deleted: true, error: null });
3746
4228
  } catch (error) {
3747
4229
  signal.throwIfAborted();
@@ -3752,14 +4234,14 @@ var deleteBuildData = async (rawPayload, _timeoutMs, signal) => {
3752
4234
  });
3753
4235
  }
3754
4236
  }
3755
- return { ...successfulProcess, deleted };
4237
+ return { ...successfulProcess2, deleted };
3756
4238
  };
3757
4239
 
3758
4240
  // src/handlers/codebases.ts
3759
4241
  import { readdir as readdir3, realpath as realpath2, stat as stat3 } from "node:fs/promises";
3760
4242
  import { homedir as homedir4 } from "node:os";
3761
4243
  import { dirname as dirname3, join as join4, resolve as resolve2 } from "node:path";
3762
- var successfulProcess2 = {
4244
+ var successfulProcess3 = {
3763
4245
  exitCode: 0,
3764
4246
  signal: null,
3765
4247
  timedOut: false,
@@ -3850,7 +4332,7 @@ async function inspectCodebaseProcess(selectedFolder, timeoutMs, signal, expecte
3850
4332
  throw new Error("Folder is not a directory");
3851
4333
  } catch (error) {
3852
4334
  return {
3853
- ...successfulProcess2,
4335
+ ...successfulProcess3,
3854
4336
  snapshot: {
3855
4337
  ...base,
3856
4338
  availability: "MISSING",
@@ -3867,7 +4349,7 @@ async function inspectCodebaseProcess(selectedFolder, timeoutMs, signal, expecte
3867
4349
  );
3868
4350
  if (rootResult.exitCode !== 0) {
3869
4351
  return {
3870
- ...successfulProcess2,
4352
+ ...successfulProcess3,
3871
4353
  snapshot: {
3872
4354
  ...base,
3873
4355
  folder: selected,
@@ -3887,7 +4369,7 @@ async function inspectCodebaseProcess(selectedFolder, timeoutMs, signal, expecte
3887
4369
  );
3888
4370
  if (bare.stdout.trim() === "true") {
3889
4371
  return {
3890
- ...successfulProcess2,
4372
+ ...successfulProcess3,
3891
4373
  snapshot: {
3892
4374
  ...base,
3893
4375
  folder,
@@ -3919,7 +4401,7 @@ async function inspectCodebaseProcess(selectedFolder, timeoutMs, signal, expecte
3919
4401
  ]);
3920
4402
  if (originResult.exitCode !== 0) {
3921
4403
  return {
3922
- ...successfulProcess2,
4404
+ ...successfulProcess3,
3923
4405
  snapshot: {
3924
4406
  ...base,
3925
4407
  folder,
@@ -3966,7 +4448,7 @@ async function inspectCodebaseProcess(selectedFolder, timeoutMs, signal, expecte
3966
4448
  const syncState = !branch ? "DETACHED" : !upstream ? "NO_UPSTREAM" : ahead === null || behind === null ? "UNKNOWN" : ahead > 0 && behind > 0 ? "DIVERGED" : ahead > 0 ? "AHEAD" : behind > 0 ? "BEHIND" : "IN_SYNC";
3967
4449
  const mismatch = expectedOrigin !== void 0 && origin2.canonicalOrigin !== expectedOrigin;
3968
4450
  return {
3969
- ...successfulProcess2,
4451
+ ...successfulProcess3,
3970
4452
  snapshot: {
3971
4453
  folder,
3972
4454
  observedOrigin: origin2.sanitizedOrigin,
@@ -3988,7 +4470,7 @@ async function inspectCodebaseProcess(selectedFolder, timeoutMs, signal, expecte
3988
4470
  } catch (error) {
3989
4471
  if (error instanceof InterruptedGitInspection) return error.result;
3990
4472
  return {
3991
- ...successfulProcess2,
4473
+ ...successfulProcess3,
3992
4474
  snapshot: {
3993
4475
  ...base,
3994
4476
  folder: selected,
@@ -4049,7 +4531,7 @@ var browseCodebaseDirectories = async (payload) => {
4049
4531
  entries: entries.slice(0, 1e3),
4050
4532
  truncated: entries.length > 1e3
4051
4533
  };
4052
- return { ...successfulProcess2, listing };
4534
+ return { ...successfulProcess3, listing };
4053
4535
  };
4054
4536
  var inspectCodebaseFolder = async (payload, timeoutMs, signal) => {
4055
4537
  const input = codebaseJobPayload(payload);
@@ -4135,7 +4617,7 @@ var fetchCodebase = async (payload, timeoutMs, signal) => {
4135
4617
  if (!("snapshot" in beforeResult)) return beforeResult;
4136
4618
  const before = beforeResult.snapshot;
4137
4619
  if (before.availability !== "AVAILABLE") {
4138
- return { ...successfulProcess2, exitCode: 1, snapshot: before };
4620
+ return { ...successfulProcess3, exitCode: 1, snapshot: before };
4139
4621
  }
4140
4622
  let result;
4141
4623
  try {
@@ -4331,7 +4813,7 @@ var inspectCodebaseGit = async (payload, timeoutMs, signal) => {
4331
4813
  );
4332
4814
  if (input.action === "STATE") {
4333
4815
  return {
4334
- ...successfulProcess2,
4816
+ ...successfulProcess3,
4335
4817
  state: await inspectCodebaseGitState(folder, timeoutMs, signal)
4336
4818
  };
4337
4819
  }
@@ -4356,7 +4838,7 @@ var inspectCodebaseGit = async (payload, timeoutMs, signal) => {
4356
4838
  );
4357
4839
  const patch = truncateUtf8(result.stdout, MAX_CODEBASE_STASH_PATCH_BYTES);
4358
4840
  return {
4359
- ...successfulProcess2,
4841
+ ...successfulProcess3,
4360
4842
  diff: {
4361
4843
  oid: input.stashOid,
4362
4844
  patch: patch.value,
@@ -4575,7 +5057,7 @@ var operateCodebaseGit = async (payload, timeoutMs, signal) => {
4575
5057
  }
4576
5058
  }
4577
5059
  return {
4578
- ...successfulProcess2,
5060
+ ...successfulProcess3,
4579
5061
  snapshot: await inspectCodebase(
4580
5062
  folder,
4581
5063
  Math.min(timeoutMs, 3e4),
@@ -4592,25 +5074,25 @@ var operateCodebaseGit = async (payload, timeoutMs, signal) => {
4592
5074
 
4593
5075
  // src/handlers/skills.ts
4594
5076
  import { execFile } from "node:child_process";
4595
- import { randomUUID } from "node:crypto";
5077
+ import { randomUUID as randomUUID2 } from "node:crypto";
4596
5078
  import {
4597
5079
  access,
4598
5080
  chmod as chmod2,
4599
5081
  lstat as lstat2,
4600
- mkdir as mkdir2,
4601
- readFile as readFile2,
5082
+ mkdir as mkdir3,
5083
+ readFile as readFile3,
4602
5084
  realpath as realpath3,
4603
5085
  readdir as readdir4,
4604
5086
  rename as rename2,
4605
- rm as rm2,
5087
+ rm as rm3,
4606
5088
  stat as stat4,
4607
- writeFile as writeFile2
5089
+ writeFile as writeFile3
4608
5090
  } from "node:fs/promises";
4609
5091
  import { homedir as homedir5 } from "node:os";
4610
5092
  import { dirname as dirname4, isAbsolute as isAbsolute2, join as join5, relative as relative2, resolve as resolve3, sep as sep2 } from "node:path";
4611
5093
  import { promisify } from "node:util";
4612
5094
  var executeFile = promisify(execFile);
4613
- var successfulProcess3 = {
5095
+ var successfulProcess4 = {
4614
5096
  exitCode: 0,
4615
5097
  signal: null,
4616
5098
  timedOut: false,
@@ -4719,7 +5201,7 @@ async function listPackageFiles(skillDirectory) {
4719
5201
  throw new Error("Skill exceeds the package size limit");
4720
5202
  files.push({
4721
5203
  path: relative2(skillDirectory, path).split(sep2).join("/"),
4722
- contentsBase64: (await readFile2(path)).toString("base64"),
5204
+ contentsBase64: (await readFile3(path)).toString("base64"),
4723
5205
  executable: (metadata.mode & 73) !== 0
4724
5206
  });
4725
5207
  }
@@ -4841,7 +5323,7 @@ var scanSkills = async (payload) => {
4841
5323
  )
4842
5324
  )).flat();
4843
5325
  return {
4844
- ...successfulProcess3,
5326
+ ...successfulProcess4,
4845
5327
  configuredTools: observations,
4846
5328
  installations,
4847
5329
  warnings: warnings.slice(0, 500)
@@ -4866,7 +5348,7 @@ var readSkills = async (payload) => {
4866
5348
  package: await readPackage(join5(root, request.skillName))
4867
5349
  });
4868
5350
  }
4869
- return { ...successfulProcess3, packages };
5351
+ return { ...successfulProcess4, packages };
4870
5352
  };
4871
5353
  async function gitExcludePath(folder) {
4872
5354
  const result = await executeFile("git", [
@@ -4881,10 +5363,10 @@ async function gitExcludePath(folder) {
4881
5363
  }
4882
5364
  async function updateManagedExclude(folder, relativeSkillPath, present) {
4883
5365
  const excludePath = await gitExcludePath(folder);
4884
- await mkdir2(dirname4(excludePath), { recursive: true });
5366
+ await mkdir3(dirname4(excludePath), { recursive: true });
4885
5367
  let existing = "";
4886
5368
  try {
4887
- existing = await readFile2(excludePath, "utf8");
5369
+ existing = await readFile3(excludePath, "utf8");
4888
5370
  } catch {
4889
5371
  }
4890
5372
  const start = existing.indexOf(MANAGED_EXCLUDE_START);
@@ -4904,7 +5386,7 @@ async function updateManagedExclude(folder, relativeSkillPath, present) {
4904
5386
  const block = managed.size ? `${MANAGED_EXCLUDE_START}
4905
5387
  ${[...managed].sort().join("\n")}
4906
5388
  ${MANAGED_EXCLUDE_END}` : "";
4907
- await writeFile2(
5389
+ await writeFile3(
4908
5390
  excludePath,
4909
5391
  `${[before, block, after].filter(Boolean).join("\n\n")}
4910
5392
  `,
@@ -4927,17 +5409,17 @@ async function writePackage(location, skillPackage) {
4927
5409
  const root = rootPath(location);
4928
5410
  const destination = join5(root, skillPackage.name);
4929
5411
  await assertUntracked(location, destination);
4930
- await mkdir2(root, { recursive: true });
4931
- const temporary = join5(root, `.${skillPackage.name}.${randomUUID()}.tmp`);
4932
- const backup = join5(root, `.${skillPackage.name}.${randomUUID()}.bak`);
4933
- await mkdir2(temporary, { recursive: true });
5412
+ await mkdir3(root, { recursive: true });
5413
+ const temporary = join5(root, `.${skillPackage.name}.${randomUUID2()}.tmp`);
5414
+ const backup = join5(root, `.${skillPackage.name}.${randomUUID2()}.bak`);
5415
+ await mkdir3(temporary, { recursive: true });
4934
5416
  try {
4935
5417
  for (const file of skillPackage.files) {
4936
5418
  const path = resolve3(temporary, ...file.path.split("/"));
4937
5419
  if (!path.startsWith(`${temporary}${sep2}`))
4938
5420
  throw new Error("Skill file escaped temporary directory");
4939
- await mkdir2(dirname4(path), { recursive: true });
4940
- await writeFile2(path, Buffer.from(file.contentsBase64, "base64"));
5421
+ await mkdir3(dirname4(path), { recursive: true });
5422
+ await writeFile3(path, Buffer.from(file.contentsBase64, "base64"));
4941
5423
  await chmod2(path, file.executable ? 493 : 420);
4942
5424
  }
4943
5425
  let hadDestination = false;
@@ -4950,14 +5432,14 @@ async function writePackage(location, skillPackage) {
4950
5432
  }
4951
5433
  try {
4952
5434
  await rename2(temporary, destination);
4953
- if (hadDestination) await rm2(backup, { recursive: true, force: true });
5435
+ if (hadDestination) await rm3(backup, { recursive: true, force: true });
4954
5436
  } catch (error) {
4955
5437
  if (hadDestination) await rename2(backup, destination);
4956
5438
  throw error;
4957
5439
  }
4958
5440
  } finally {
4959
- await rm2(temporary, { recursive: true, force: true });
4960
- await rm2(backup, { recursive: true, force: true });
5441
+ await rm3(temporary, { recursive: true, force: true });
5442
+ await rm3(backup, { recursive: true, force: true });
4961
5443
  }
4962
5444
  return destination;
4963
5445
  }
@@ -4977,7 +5459,7 @@ var applySkills = async (payload) => {
4977
5459
  packageHash: operation.package.packageHash
4978
5460
  });
4979
5461
  } else {
4980
- await rm2(destination, { recursive: true, force: true });
5462
+ await rm3(destination, { recursive: true, force: true });
4981
5463
  results.push({
4982
5464
  kind: operation.kind,
4983
5465
  path: destination,
@@ -4992,13 +5474,13 @@ var applySkills = async (payload) => {
4992
5474
  );
4993
5475
  }
4994
5476
  }
4995
- return { ...successfulProcess3, results };
5477
+ return { ...successfulProcess4, results };
4996
5478
  };
4997
5479
 
4998
5480
  // src/handlers/worktrees.ts
4999
5481
  import { createWriteStream, watch } from "node:fs";
5000
- import { mkdtemp, open, readFile as readFile3, realpath as realpath4, rm as rm3, stat as stat5 } from "node:fs/promises";
5001
- import { tmpdir } from "node:os";
5482
+ import { mkdtemp as mkdtemp2, open, readFile as readFile4, realpath as realpath4, rm as rm4, stat as stat5 } from "node:fs/promises";
5483
+ import { tmpdir as tmpdir2 } from "node:os";
5002
5484
  import { basename as basename3, dirname as dirname5, join as join6, relative as relative4 } from "node:path";
5003
5485
  import { spawn as spawn4 } from "node:child_process";
5004
5486
 
@@ -5194,7 +5676,7 @@ async function worktreeCodeStateHash(folder, timeoutMs, signal) {
5194
5676
  }
5195
5677
 
5196
5678
  // src/handlers/worktrees.ts
5197
- var successfulProcess4 = {
5679
+ var successfulProcess5 = {
5198
5680
  exitCode: 0,
5199
5681
  signal: null,
5200
5682
  timedOut: false,
@@ -5638,7 +6120,7 @@ async function untrackedLines(folder, path) {
5638
6120
  try {
5639
6121
  const file = await stat5(`${folder}/${path}`);
5640
6122
  if (!file.isFile() || file.size > 1024 * 1024) return null;
5641
- const contents = await readFile3(`${folder}/${path}`);
6123
+ const contents = await readFile4(`${folder}/${path}`);
5642
6124
  if (contents.includes(0)) return null;
5643
6125
  const text2 = contents.toString("utf8");
5644
6126
  return text2 ? text2.split("\n").length - (text2.endsWith("\n") ? 1 : 0) : 0;
@@ -6089,7 +6571,7 @@ var inspectWorktreeDiff = async (payload, timeoutMs, signal) => {
6089
6571
  const input = worktreeDiffPayload(payload);
6090
6572
  const folder = await validateWorktree(input, timeoutMs, signal);
6091
6573
  return {
6092
- ...successfulProcess4,
6574
+ ...successfulProcess5,
6093
6575
  diff: await inspectRequestedDiff(input, folder, timeoutMs, signal)
6094
6576
  };
6095
6577
  };
@@ -6191,7 +6673,7 @@ var downloadWorktreeDiffAsset = async (payload, timeoutMs, signal, _onLog, conte
6191
6673
  if (!/^\d+$/.test(size) || Number(size) > 20 * 1024 * 1024) {
6192
6674
  throw new Error("Diff image exceeds the 20 MiB limit");
6193
6675
  }
6194
- temporaryDirectory = await mkdtemp(join6(tmpdir(), "ade-diff-image-"));
6676
+ temporaryDirectory = await mkdtemp2(join6(tmpdir2(), "ade-diff-image-"));
6195
6677
  uploadPath = join6(temporaryDirectory, basename3(input.path));
6196
6678
  await writeGitObject(
6197
6679
  folder,
@@ -6211,10 +6693,10 @@ var downloadWorktreeDiffAsset = async (payload, timeoutMs, signal, _onLog, conte
6211
6693
  filename: basename3(input.path),
6212
6694
  contentType: imageContentType(input.path)
6213
6695
  });
6214
- return successfulProcess4;
6696
+ return successfulProcess5;
6215
6697
  } finally {
6216
6698
  if (temporaryDirectory) {
6217
- await rm3(temporaryDirectory, { recursive: true, force: true });
6699
+ await rm4(temporaryDirectory, { recursive: true, force: true });
6218
6700
  }
6219
6701
  }
6220
6702
  };
@@ -6226,11 +6708,11 @@ var watchWorktree = async (payload, timeoutMs, signal, _onLog, context) => {
6226
6708
  closeWorktreeWatch(current);
6227
6709
  activeWorktreeWatches.delete(input.gitDirectory);
6228
6710
  }
6229
- return successfulProcess4;
6711
+ return successfulProcess5;
6230
6712
  }
6231
6713
  if (!context) throw new Error("Worktree activity reporting is unavailable");
6232
6714
  const folder = await validateWorktree(input, timeoutMs, signal);
6233
- if (current?.watchId === input.watchId) return successfulProcess4;
6715
+ if (current?.watchId === input.watchId) return successfulProcess5;
6234
6716
  if (current) {
6235
6717
  closeWorktreeWatch(current);
6236
6718
  activeWorktreeWatches.delete(input.gitDirectory);
@@ -6272,14 +6754,14 @@ var watchWorktree = async (payload, timeoutMs, signal, _onLog, context) => {
6272
6754
  activeWorktreeWatches.delete(input.gitDirectory);
6273
6755
  throw error;
6274
6756
  }
6275
- return successfulProcess4;
6757
+ return successfulProcess5;
6276
6758
  };
6277
6759
  var inspectWorktree = async (payload, timeoutMs, signal) => {
6278
6760
  const input = worktreeJobPayload(payload);
6279
6761
  const folder = await validateWorktree(input, timeoutMs, signal);
6280
6762
  if (!input.baseBranch) throw new Error("A base branch is required");
6281
6763
  return {
6282
- ...successfulProcess4,
6764
+ ...successfulProcess5,
6283
6765
  detail: await inspectWorktreeDetail(
6284
6766
  folder,
6285
6767
  input.baseBranch,
@@ -6510,7 +6992,7 @@ var branchWorktree = async (payload, timeoutMs, signal) => {
6510
6992
  throw new Error(worktree.error || "Could not inspect the updated worktree");
6511
6993
  }
6512
6994
  return {
6513
- ...successfulProcess4,
6995
+ ...successfulProcess5,
6514
6996
  worktree,
6515
6997
  branch,
6516
6998
  baseBranch: input.baseBranch,
@@ -6565,7 +7047,7 @@ var pushMovedWorktree = async (payload, timeoutMs, signal) => {
6565
7047
  throw new Error("The source branch changed while it was being pushed");
6566
7048
  }
6567
7049
  return {
6568
- ...successfulProcess4,
7050
+ ...successfulProcess5,
6569
7051
  moveId: input.moveId,
6570
7052
  branch,
6571
7053
  headSha: pushedHeadSha
@@ -6765,7 +7247,7 @@ var checkoutMovedWorktree = async (payload, timeoutMs, signal) => {
6765
7247
  if (switched.exitCode !== 0) {
6766
7248
  if (!input.stashOnFailure && hasChanges(targetChanges)) {
6767
7249
  return {
6768
- ...successfulProcess4,
7250
+ ...successfulProcess5,
6769
7251
  moveId: input.moveId,
6770
7252
  outcome: "NEEDS_STASH",
6771
7253
  message: cleanError2(
@@ -6810,7 +7292,7 @@ var checkoutMovedWorktree = async (payload, timeoutMs, signal) => {
6810
7292
  );
6811
7293
  }
6812
7294
  return {
6813
- ...successfulProcess4,
7295
+ ...successfulProcess5,
6814
7296
  moveId: input.moveId,
6815
7297
  outcome: "CHECKED_OUT",
6816
7298
  worktree,
@@ -6908,7 +7390,7 @@ var deleteWorktree = async (payload, timeoutMs, signal) => {
6908
7390
  );
6909
7391
  }
6910
7392
  return {
6911
- ...successfulProcess4,
7393
+ ...successfulProcess5,
6912
7394
  moveId: input.moveId,
6913
7395
  deleted: true,
6914
7396
  branch,
@@ -7002,7 +7484,7 @@ var operateWorktree = async (payload, timeoutMs, signal) => {
7002
7484
  break;
7003
7485
  }
7004
7486
  return {
7005
- ...successfulProcess4,
7487
+ ...successfulProcess5,
7006
7488
  worktree: await inspectWorktreeItem(
7007
7489
  folder,
7008
7490
  folder,
@@ -7015,22 +7497,22 @@ var operateWorktree = async (payload, timeoutMs, signal) => {
7015
7497
  };
7016
7498
 
7017
7499
  // src/handlers/builds.ts
7018
- import { createHash as createHash4, randomUUID as randomUUID2 } from "node:crypto";
7500
+ import { createHash as createHash4, randomUUID as randomUUID3 } from "node:crypto";
7019
7501
  import {
7020
7502
  cp,
7021
- mkdir as mkdir3,
7022
- mkdtemp as mkdtemp2,
7503
+ mkdir as mkdir4,
7504
+ mkdtemp as mkdtemp3,
7023
7505
  open as open2,
7024
7506
  readdir as readdir5,
7025
- readFile as readFile4,
7507
+ readFile as readFile5,
7026
7508
  realpath as realpath5,
7027
7509
  rename as rename3,
7028
- rm as rm4,
7510
+ rm as rm5,
7029
7511
  stat as stat6,
7030
- writeFile as writeFile3
7512
+ writeFile as writeFile4
7031
7513
  } from "node:fs/promises";
7032
7514
  import { createReadStream as createReadStream3, createWriteStream as createWriteStream2 } from "node:fs";
7033
- import { tmpdir as tmpdir2 } from "node:os";
7515
+ import { tmpdir as tmpdir3 } from "node:os";
7034
7516
  import { pipeline } from "node:stream/promises";
7035
7517
  import {
7036
7518
  basename as basename4,
@@ -7042,7 +7524,7 @@ import {
7042
7524
  sep as sep4
7043
7525
  } from "node:path";
7044
7526
  import { spawn as spawn5 } from "node:child_process";
7045
- var successfulProcess5 = {
7527
+ var successfulProcess6 = {
7046
7528
  exitCode: 0,
7047
7529
  signal: null,
7048
7530
  timedOut: false,
@@ -7235,7 +7717,7 @@ async function workspaceProjectPaths(workspacePath2, folder) {
7235
7717
  const contentsPath = join7(workspacePath2, "contents.xcworkspacedata");
7236
7718
  let contents;
7237
7719
  try {
7238
- contents = await readFile4(contentsPath, "utf8");
7720
+ contents = await readFile5(contentsPath, "utf8");
7239
7721
  } catch {
7240
7722
  return [];
7241
7723
  }
@@ -7336,11 +7818,211 @@ async function testPlans(source, absolutePath, folder, scheme, timeoutMs, signal
7336
7818
  }
7337
7819
  return [];
7338
7820
  }
7821
+ function buildSetting(settings, key) {
7822
+ const value = settings[key];
7823
+ return typeof value === "string" && value.trim() ? value.trim() : null;
7824
+ }
7825
+ function signingPlatform(settings) {
7826
+ const platform = buildSetting(settings, "PLATFORM_NAME");
7827
+ if (platform === "iphoneos") return "iOS";
7828
+ if (platform === "watchos") return "watchOS";
7829
+ if (platform === "appletvos") return "tvOS";
7830
+ if (platform === "xros") return "visionOS";
7831
+ if (platform === "macosx") return "macOS";
7832
+ return platform;
7833
+ }
7834
+ function requiresProvisioningProfile(productType) {
7835
+ return typeof productType === "string" && (productType.includes("application") || productType.includes("app-extension") || productType.includes("watchkit"));
7836
+ }
7837
+ function pbxObject(objects, id) {
7838
+ if (typeof id !== "string") return null;
7839
+ const value = objects[id];
7840
+ return value && typeof value === "object" && !Array.isArray(value) ? value : null;
7841
+ }
7842
+ function dependentSigningTargetNamesFromPbxProject(value, rootTargetNames) {
7843
+ if (!value || typeof value !== "object" || Array.isArray(value)) return [];
7844
+ const rawObjects = value.objects;
7845
+ if (!rawObjects || typeof rawObjects !== "object" || Array.isArray(rawObjects))
7846
+ return [];
7847
+ const objects = rawObjects;
7848
+ const roots = new Set(rootTargetNames);
7849
+ const targetEntries = Object.entries(objects).filter(([, target2]) => {
7850
+ if (!target2 || typeof target2 !== "object" || Array.isArray(target2)) {
7851
+ return false;
7852
+ }
7853
+ const record = target2;
7854
+ return (record.isa === "PBXNativeTarget" || record.isa === "PBXAggregateTarget") && typeof record.name === "string";
7855
+ });
7856
+ const queue = targetEntries.filter(
7857
+ ([, target2]) => roots.has(target2.name)
7858
+ ).map(([id]) => id);
7859
+ const visited = new Set(queue);
7860
+ const signingTargets = [];
7861
+ while (queue.length) {
7862
+ const target2 = pbxObject(objects, queue.shift());
7863
+ if (!target2 || !Array.isArray(target2.dependencies)) continue;
7864
+ for (const dependencyId of target2.dependencies) {
7865
+ const dependency = pbxObject(objects, dependencyId);
7866
+ const dependentTargetId = dependency?.target;
7867
+ if (typeof dependentTargetId !== "string") continue;
7868
+ const dependentTarget = pbxObject(objects, dependentTargetId);
7869
+ if (!dependentTarget) continue;
7870
+ if (!visited.has(dependentTargetId)) {
7871
+ visited.add(dependentTargetId);
7872
+ queue.push(dependentTargetId);
7873
+ }
7874
+ const name = dependentTarget.name;
7875
+ if (typeof name === "string" && !roots.has(name) && requiresProvisioningProfile(dependentTarget.productType)) {
7876
+ signingTargets.push(name);
7877
+ }
7878
+ }
7879
+ }
7880
+ return uniqueSorted(signingTargets);
7881
+ }
7882
+ function signingRequirementsFromBuildSettings(value) {
7883
+ if (!Array.isArray(value)) return [];
7884
+ const requirements = /* @__PURE__ */ new Map();
7885
+ for (const entry of value) {
7886
+ if (!entry || typeof entry !== "object" || Array.isArray(entry)) continue;
7887
+ const record = entry;
7888
+ const rawSettings = record.buildSettings;
7889
+ if (!rawSettings || typeof rawSettings !== "object" || Array.isArray(rawSettings)) {
7890
+ continue;
7891
+ }
7892
+ const settings = rawSettings;
7893
+ const bundleId = buildSetting(settings, "PRODUCT_BUNDLE_IDENTIFIER");
7894
+ if (!bundleId || buildSetting(settings, "CODE_SIGNING_ALLOWED") === "NO") {
7895
+ continue;
7896
+ }
7897
+ const productType = buildSetting(settings, "PRODUCT_TYPE") ?? "";
7898
+ if (productType && !requiresProvisioningProfile(productType)) {
7899
+ continue;
7900
+ }
7901
+ const target2 = typeof record.target === "string" && record.target.trim() || bundleId;
7902
+ const requirement = {
7903
+ bundleId,
7904
+ name: buildSetting(settings, "PRODUCT_NAME") ?? buildSetting(settings, "FULL_PRODUCT_NAME") ?? target2,
7905
+ target: target2,
7906
+ platform: signingPlatform(settings),
7907
+ teamId: buildSetting(settings, "DEVELOPMENT_TEAM"),
7908
+ provisioningProfileSpecifier: buildSetting(settings, "PROVISIONING_PROFILE_SPECIFIER") ?? buildSetting(settings, "PROVISIONING_PROFILE")
7909
+ };
7910
+ const existing = requirements.get(bundleId);
7911
+ if (!existing || !existing.provisioningProfileSpecifier && requirement.provisioningProfileSpecifier) {
7912
+ requirements.set(bundleId, requirement);
7913
+ }
7914
+ }
7915
+ return [...requirements.values()].sort(
7916
+ (left, right) => left.name.localeCompare(right.name)
7917
+ );
7918
+ }
7919
+ function mergeSigningRequirements(requirements) {
7920
+ const merged = /* @__PURE__ */ new Map();
7921
+ for (const requirement of requirements) {
7922
+ const existing = merged.get(requirement.bundleId);
7923
+ if (!existing || !existing.provisioningProfileSpecifier && requirement.provisioningProfileSpecifier) {
7924
+ merged.set(requirement.bundleId, requirement);
7925
+ }
7926
+ }
7927
+ return [...merged.values()].sort(
7928
+ (left, right) => left.name.localeCompare(right.name)
7929
+ );
7930
+ }
7931
+ async function dependentSigningRequirements(source, absolutePath, folder, rootTargetNames, configuration, timeoutMs, signal) {
7932
+ const projects = source.kind === "PROJECT" ? [absolutePath] : source.kind === "WORKSPACE" ? await workspaceProjectPaths(absolutePath, folder) : [];
7933
+ const targets = [];
7934
+ for (const project of projects.slice(0, 50)) {
7935
+ const converted = await command2(
7936
+ "plutil",
7937
+ ["-convert", "json", "-o", "-", join7(project, "project.pbxproj")],
7938
+ Math.min(timeoutMs, 15e3),
7939
+ signal,
7940
+ folder
7941
+ );
7942
+ if (converted.exitCode !== 0) continue;
7943
+ const names = dependentSigningTargetNamesFromPbxProject(
7944
+ parseJson(converted.stdout, "Xcode project graph"),
7945
+ rootTargetNames
7946
+ );
7947
+ targets.push(...names.map((name) => ({ project, name })));
7948
+ }
7949
+ const requirements = [];
7950
+ for (const target2 of targets.slice(0, 50)) {
7951
+ const result = await command2(
7952
+ "xcrun",
7953
+ [
7954
+ "xcodebuild",
7955
+ "-project",
7956
+ target2.project,
7957
+ "-target",
7958
+ target2.name,
7959
+ "-configuration",
7960
+ configuration,
7961
+ "-showBuildSettings",
7962
+ "-json"
7963
+ ],
7964
+ Math.min(timeoutMs, 6e4),
7965
+ signal,
7966
+ folder
7967
+ );
7968
+ if (result.exitCode !== 0) continue;
7969
+ try {
7970
+ requirements.push(
7971
+ ...signingRequirementsFromBuildSettings(JSON.parse(result.stdout))
7972
+ );
7973
+ } catch {
7974
+ }
7975
+ }
7976
+ return requirements;
7977
+ }
7978
+ async function inspectSigningRequirements(source, absolutePath, folder, scheme, configuration, timeoutMs, signal) {
7979
+ if (!scheme || !configuration) return [];
7980
+ const result = requireSuccess3(
7981
+ await command2(
7982
+ "xcrun",
7983
+ [
7984
+ "xcodebuild",
7985
+ ...sourceArguments(source, absolutePath),
7986
+ "-scheme",
7987
+ scheme,
7988
+ "-configuration",
7989
+ configuration,
7990
+ "-destination",
7991
+ "generic/platform=iOS",
7992
+ "-showBuildSettings",
7993
+ "-json"
7994
+ ],
7995
+ Math.min(timeoutMs, 6e4),
7996
+ signal,
7997
+ folder
7998
+ ),
7999
+ "Could not inspect signing requirements"
8000
+ );
8001
+ try {
8002
+ const direct = signingRequirementsFromBuildSettings(
8003
+ JSON.parse(result.stdout)
8004
+ );
8005
+ const dependent = await dependentSigningRequirements(
8006
+ source,
8007
+ absolutePath,
8008
+ folder,
8009
+ direct.map((requirement) => requirement.target),
8010
+ configuration,
8011
+ timeoutMs,
8012
+ signal
8013
+ );
8014
+ return mergeSigningRequirements([...direct, ...dependent]);
8015
+ } catch (error) {
8016
+ throw new Error(
8017
+ `Could not parse Xcode signing requirements: ${cleanError3(error)}`
8018
+ );
8019
+ }
8020
+ }
7339
8021
  var discoverBuildSources = async (payload, timeoutMs, signal) => {
7340
8022
  const input = parseBuildSourceDiscoverPayload(payload);
7341
8023
  const folder = await validateWorktree2(input, timeoutMs, signal);
7342
8024
  return {
7343
- ...successfulProcess5,
8025
+ ...successfulProcess6,
7344
8026
  sources: await discoverSourcesInFolder(folder)
7345
8027
  };
7346
8028
  };
@@ -7354,11 +8036,8 @@ var parseBuildSourceMetadata = async (payload, timeoutMs, signal) => {
7354
8036
  ]);
7355
8037
  const metadata = metadataFromList(list);
7356
8038
  const configurations = input.source.kind === "PACKAGE" ? ["Debug", "Release"] : input.source.kind === "WORKSPACE" && metadata.configurations.length === 0 ? await workspaceConfigurations(absolutePath, folder, timeoutMs, signal) : metadata.configurations;
7357
- return {
7358
- ...successfulProcess5,
7359
- schemes: uniqueSorted(metadata.schemes),
7360
- configurations: uniqueSorted(configurations),
7361
- testPlans: await testPlans(
8039
+ const [plans, signingRequirements] = await Promise.all([
8040
+ testPlans(
7362
8041
  input.source,
7363
8042
  absolutePath,
7364
8043
  folder,
@@ -7366,6 +8045,22 @@ var parseBuildSourceMetadata = async (payload, timeoutMs, signal) => {
7366
8045
  timeoutMs,
7367
8046
  signal
7368
8047
  ),
8048
+ inspectSigningRequirements(
8049
+ input.source,
8050
+ absolutePath,
8051
+ folder,
8052
+ input.scheme,
8053
+ input.configuration,
8054
+ timeoutMs,
8055
+ signal
8056
+ )
8057
+ ]);
8058
+ return {
8059
+ ...successfulProcess6,
8060
+ schemes: uniqueSorted(metadata.schemes),
8061
+ configurations: uniqueSorted(configurations),
8062
+ testPlans: plans,
8063
+ signingRequirements,
7369
8064
  xcodeVersion: version.exitCode === 0 ? version.stdout.trim().replace(/\n+/g, " \xB7 ") : null,
7370
8065
  headSha: input.headSha
7371
8066
  };
@@ -7476,7 +8171,7 @@ function genericBuildDestinations(action) {
7476
8171
  ];
7477
8172
  }
7478
8173
  async function listPhysicalDevices(timeoutMs, signal) {
7479
- const directory = await mkdtemp2(join7(tmpdir2(), "ade-devices-"));
8174
+ const directory = await mkdtemp3(join7(tmpdir3(), "ade-devices-"));
7480
8175
  const output = join7(directory, "devices.json");
7481
8176
  try {
7482
8177
  const result = await command2(
@@ -7495,9 +8190,9 @@ async function listPhysicalDevices(timeoutMs, signal) {
7495
8190
  signal
7496
8191
  );
7497
8192
  if (result.exitCode !== 0) return [];
7498
- return physicalDestinations(JSON.parse(await readFile4(output, "utf8")));
8193
+ return physicalDestinations(JSON.parse(await readFile5(output, "utf8")));
7499
8194
  } finally {
7500
- await rm4(directory, { recursive: true, force: true });
8195
+ await rm5(directory, { recursive: true, force: true });
7501
8196
  }
7502
8197
  }
7503
8198
  var inspectBuildDestinations = async (payload, timeoutMs, signal) => {
@@ -7532,7 +8227,7 @@ var inspectBuildDestinations = async (payload, timeoutMs, signal) => {
7532
8227
  listPhysicalDevices(timeoutMs, signal)
7533
8228
  ]);
7534
8229
  return {
7535
- ...successfulProcess5,
8230
+ ...successfulProcess6,
7536
8231
  destinations: [
7537
8232
  ...genericBuildDestinations(input.action),
7538
8233
  ...simulators.exitCode === 0 ? simulatorDestinations(JSON.parse(simulators.stdout)) : [],
@@ -7553,12 +8248,12 @@ var inspectBuildRunDestinations = async (payload, timeoutMs, signal) => {
7553
8248
  );
7554
8249
  requireSuccess3(simulators, "Could not inspect available simulators");
7555
8250
  return {
7556
- ...successfulProcess5,
8251
+ ...successfulProcess6,
7557
8252
  destinations: simulatorDestinations(JSON.parse(simulators.stdout))
7558
8253
  };
7559
8254
  }
7560
8255
  return {
7561
- ...successfulProcess5,
8256
+ ...successfulProcess6,
7562
8257
  destinations: await listPhysicalDevices(timeoutMs, signal)
7563
8258
  };
7564
8259
  };
@@ -7977,16 +8672,16 @@ async function runHook(options) {
7977
8672
  const log = join7(directory, `${prefix}.log`);
7978
8673
  const started = Date.now();
7979
8674
  try {
7980
- await mkdir3(directory, { recursive: true, mode: 448 });
7981
- await writeFile3(file, `${options.source}
8675
+ await mkdir4(directory, { recursive: true, mode: 448 });
8676
+ await writeFile4(file, `${options.source}
7982
8677
  `, { mode: 384 });
7983
- await writeFile3(
8678
+ await writeFile4(
7984
8679
  options.contextPath,
7985
8680
  `${JSON.stringify(options.hookContext, null, 2)}
7986
8681
  `,
7987
8682
  { mode: 384 }
7988
8683
  );
7989
- await writeFile3(
8684
+ await writeFile4(
7990
8685
  runner,
7991
8686
  `import { readFile } from "node:fs/promises";
7992
8687
  const hookModule = await import(${JSON.stringify(`./${basename4(file)}`)});
@@ -8008,7 +8703,20 @@ if (typeof hookModule.default === "function") {
8008
8703
  BUILD_ID: options.input.buildId,
8009
8704
  BUILD_PHASE: options.phase,
8010
8705
  BUILD_CONTEXT_PATH: options.contextPath,
8011
- BUILD_ARTIFACT_DIRECTORY: options.input.artifactDirectory
8706
+ BUILD_ARTIFACT_DIRECTORY: options.input.artifactDirectory,
8707
+ ...options.input.telemetry ? {
8708
+ TELEMETRY_LOCAL_BASE_URL: options.input.telemetry.localBaseUrl,
8709
+ TELEMETRY_REMOTE_BASE_URL: options.input.telemetry.remoteBaseUrl,
8710
+ TELEMETRY_BASE_URL: options.input.telemetry.selectedBaseUrl,
8711
+ CONSOLE_LOGS_URL: options.input.telemetry.consoleLogsUrl,
8712
+ ANALYTICS_EVENTS_URL: options.input.telemetry.analyticsEventsUrl,
8713
+ CONSOLE_LOG_COLLECTION_ENABLED: String(
8714
+ options.input.telemetry.consoleCollectionEnabled
8715
+ ),
8716
+ ANALYTICS_EVENT_COLLECTION_ENABLED: String(
8717
+ options.input.telemetry.analyticsCollectionEnabled
8718
+ )
8719
+ } : {}
8012
8720
  }),
8013
8721
  timeoutMs: options.script.timeoutSeconds * 1e3,
8014
8722
  signal: options.signal,
@@ -8251,7 +8959,7 @@ async function writeJsonReport(input, kind, timeoutMs, signal) {
8251
8959
  const resultBundle = join7(input.artifactDirectory, "result.xcresult");
8252
8960
  const filename = kind === "TEST_RESULTS" ? "test-results.json" : "code-coverage.json";
8253
8961
  const destination = join7(input.artifactDirectory, filename);
8254
- const temporary = `${destination}.tmp-${randomUUID2()}`;
8962
+ const temporary = `${destination}.tmp-${randomUUID3()}`;
8255
8963
  try {
8256
8964
  if (!await pathExists(resultBundle)) {
8257
8965
  throw new Error("The build result bundle is unavailable");
@@ -8278,7 +8986,7 @@ async function writeJsonReport(input, kind, timeoutMs, signal) {
8278
8986
  ),
8279
8987
  `Could not generate ${filename}`
8280
8988
  );
8281
- const serialized = await readFile4(temporary, "utf8");
8989
+ const serialized = await readFile5(temporary, "utf8");
8282
8990
  const parsed = JSON.parse(serialized);
8283
8991
  const normalized = kind === "TEST_RESULTS" ? normalizeTestResults(parsed) : normalizeCoverage(parsed);
8284
8992
  await rename3(temporary, destination);
@@ -8294,7 +9002,7 @@ async function writeJsonReport(input, kind, timeoutMs, signal) {
8294
9002
  error: null
8295
9003
  };
8296
9004
  } catch (error) {
8297
- await rm4(temporary, { force: true });
9005
+ await rm5(temporary, { force: true });
8298
9006
  return {
8299
9007
  kind,
8300
9008
  status: "FAILED",
@@ -8385,7 +9093,7 @@ async function snapshotCoverageChanges(input, folder, timeoutMs, signal) {
8385
9093
  const types = changeTypesFromStatus(status2.stdout);
8386
9094
  for (const path of untracked.stdout.split("\0").filter(Boolean)) {
8387
9095
  try {
8388
- const contents = await readFile4(join7(folder, path));
9096
+ const contents = await readFile5(join7(folder, path));
8389
9097
  if (contents.includes(0)) continue;
8390
9098
  const lineCount = contents.length ? contents.toString("utf8").split("\n").length - (contents.toString("utf8").endsWith("\n") ? 1 : 0) : 0;
8391
9099
  lines.set(
@@ -8421,7 +9129,7 @@ async function addChangedCoverage(report, changes, input, folder, timeoutMs, sig
8421
9129
  if (coveragePath && change.lines.length) {
8422
9130
  const temporary2 = join7(
8423
9131
  input.artifactDirectory,
8424
- `.changed-coverage-${randomUUID2()}.json`
9132
+ `.changed-coverage-${randomUUID3()}.json`
8425
9133
  );
8426
9134
  try {
8427
9135
  const result = await commandToFile(
@@ -8443,7 +9151,7 @@ async function addChangedCoverage(report, changes, input, folder, timeoutMs, sig
8443
9151
  );
8444
9152
  if (result.exitCode === 0 && !result.cancelled && !result.timedOut) {
8445
9153
  const parsed = jsonObject(
8446
- JSON.parse(await readFile4(temporary2, "utf8"))
9154
+ JSON.parse(await readFile5(temporary2, "utf8"))
8447
9155
  );
8448
9156
  const lineData = parsed?.[coveragePath];
8449
9157
  if (Array.isArray(lineData)) {
@@ -8460,7 +9168,7 @@ async function addChangedCoverage(report, changes, input, folder, timeoutMs, sig
8460
9168
  }
8461
9169
  }
8462
9170
  } finally {
8463
- await rm4(temporary2, { force: true });
9171
+ await rm5(temporary2, { force: true });
8464
9172
  }
8465
9173
  }
8466
9174
  changedCoveredLines += covered;
@@ -8481,8 +9189,8 @@ async function addChangedCoverage(report, changes, input, folder, timeoutMs, sig
8481
9189
  };
8482
9190
  const data = { ...report.data, changedFiles };
8483
9191
  const destination = join7(input.artifactDirectory, "worktree-coverage.json");
8484
- const temporary = `${destination}.tmp-${randomUUID2()}`;
8485
- await writeFile3(temporary, JSON.stringify({ summary, data }, null, 2), {
9192
+ const temporary = `${destination}.tmp-${randomUUID3()}`;
9193
+ await writeFile4(temporary, JSON.stringify({ summary, data }, null, 2), {
8486
9194
  mode: 384
8487
9195
  });
8488
9196
  await rename3(temporary, destination);
@@ -8598,8 +9306,8 @@ async function captureArtifacts(input, folder, signal, includeProducts = true) {
8598
9306
  if (source && await pathExists(source)) {
8599
9307
  const productDirectory = join7(input.artifactDirectory, "products");
8600
9308
  const destination = join7(productDirectory, basename4(source));
8601
- await mkdir3(productDirectory, { recursive: true, mode: 448 });
8602
- await rm4(destination, { recursive: true, force: true });
9309
+ await mkdir4(productDirectory, { recursive: true, mode: 448 });
9310
+ await rm5(destination, { recursive: true, force: true });
8603
9311
  await cp(source, destination, {
8604
9312
  recursive: true,
8605
9313
  preserveTimestamps: true
@@ -8664,7 +9372,7 @@ var runIosBuild = async (payload, timeoutMs, signal, onLog, context) => {
8664
9372
  Math.min(timeoutMs, 6e4),
8665
9373
  signal
8666
9374
  );
8667
- await mkdir3(input.artifactDirectory, { recursive: true, mode: 448 });
9375
+ await mkdir4(input.artifactDirectory, { recursive: true, mode: 448 });
8668
9376
  const rawLog = join7(input.artifactDirectory, "build.log");
8669
9377
  const logger = new BuildLogger(input.buildId, context, rawLog, process.env);
8670
9378
  try {
@@ -8683,7 +9391,8 @@ var runIosBuild = async (payload, timeoutMs, signal, onLog, context) => {
8683
9391
  },
8684
9392
  source: input.source,
8685
9393
  scheme: input.scheme,
8686
- configuration: input.configuration
9394
+ configuration: input.configuration,
9395
+ telemetry: input.telemetry ?? null
8687
9396
  };
8688
9397
  let buildResult = null;
8689
9398
  let coverageChanges = [];
@@ -8905,7 +9614,7 @@ var generateIosBuildReport = async (payload, timeoutMs, signal, onLog) => {
8905
9614
  if (!isAbsolute4(input.artifactDirectory) || basename4(input.artifactDirectory) !== input.buildId) {
8906
9615
  throw new Error("Build artifact directory is invalid");
8907
9616
  }
8908
- if (signal.aborted) return { ...successfulProcess5, cancelled: true };
9617
+ if (signal.aborted) return { ...successfulProcess6, cancelled: true };
8909
9618
  const report = await writeJsonReport(
8910
9619
  input,
8911
9620
  input.reportKind,
@@ -8919,22 +9628,22 @@ var generateIosBuildReport = async (payload, timeoutMs, signal, onLog) => {
8919
9628
  createdAt: (/* @__PURE__ */ new Date()).toISOString()
8920
9629
  });
8921
9630
  return {
8922
- ...successfulProcess5,
9631
+ ...successfulProcess6,
8923
9632
  report,
8924
9633
  artifacts: report.artifact ? [report.artifact] : []
8925
9634
  };
8926
9635
  };
8927
9636
  var deleteIosBuild = async (payload, _timeoutMs, signal, onLog) => {
8928
9637
  const input = parseBuildDeletePayload(payload);
8929
- if (signal.aborted) return { ...successfulProcess5, cancelled: true };
8930
- await rm4(input.artifactDirectory, { recursive: true, force: true });
9638
+ if (signal.aborted) return { ...successfulProcess6, cancelled: true };
9639
+ await rm5(input.artifactDirectory, { recursive: true, force: true });
8931
9640
  await onLog({
8932
9641
  sequence: 0,
8933
9642
  stream: "SYSTEM",
8934
9643
  message: `Deleted build folder ${input.artifactDirectory}`,
8935
9644
  createdAt: (/* @__PURE__ */ new Date()).toISOString()
8936
9645
  });
8937
- return successfulProcess5;
9646
+ return successfulProcess6;
8938
9647
  };
8939
9648
  var downloadIosBuildArtifact = async (payload, timeoutMs, signal, onLog, context) => {
8940
9649
  const input = parseBuildArtifactDownloadPayload(payload);
@@ -8957,8 +9666,8 @@ var downloadIosBuildArtifact = async (payload, timeoutMs, signal, onLog, context
8957
9666
  try {
8958
9667
  if (information.isDirectory()) {
8959
9668
  temporaryArchive = join7(
8960
- tmpdir2(),
8961
- `ade-build-artifact-${randomUUID2()}.tar.gz`
9669
+ tmpdir3(),
9670
+ `ade-build-artifact-${randomUUID3()}.tar.gz`
8962
9671
  );
8963
9672
  requireSuccess3(
8964
9673
  await command2(
@@ -8987,10 +9696,10 @@ var downloadIosBuildArtifact = async (payload, timeoutMs, signal, onLog, context
8987
9696
  filename,
8988
9697
  contentType
8989
9698
  });
8990
- return successfulProcess5;
9699
+ return successfulProcess6;
8991
9700
  } finally {
8992
9701
  if (temporaryArchive) {
8993
- await rm4(temporaryArchive, { force: true });
9702
+ await rm5(temporaryArchive, { force: true });
8994
9703
  }
8995
9704
  }
8996
9705
  };
@@ -9027,7 +9736,7 @@ var deployIosBuild = async (payload, timeoutMs, signal, _onLog, context) => {
9027
9736
  throw new Error("Runnable app artifact is missing");
9028
9737
  }
9029
9738
  const deploymentsDirectory = join7(input.artifactDirectory, "deployments");
9030
- await mkdir3(deploymentsDirectory, { recursive: true, mode: 448 });
9739
+ await mkdir4(deploymentsDirectory, { recursive: true, mode: 448 });
9031
9740
  const logger = new BuildLogger(
9032
9741
  input.buildId,
9033
9742
  context,
@@ -9042,7 +9751,7 @@ var deployIosBuild = async (payload, timeoutMs, signal, _onLog, context) => {
9042
9751
  "deployments",
9043
9752
  deployment.id
9044
9753
  );
9045
- await mkdir3(directory, { recursive: true, mode: 448 });
9754
+ await mkdir4(directory, { recursive: true, mode: 448 });
9046
9755
  const logPath = join7(directory, "deployment.log");
9047
9756
  const started = Date.now();
9048
9757
  let failure = null;
@@ -9226,8 +9935,16 @@ function exportPlist(settings) {
9226
9935
  signingStyle: settings.signingStyle.toLowerCase(),
9227
9936
  uploadSymbols: settings.uploadSymbols,
9228
9937
  manageAppVersionAndBuildNumber: settings.manageAppVersionAndBuildNumber,
9229
- testFlightInternalTestingOnly: settings.testFlightInternalTestingOnly
9938
+ testFlightInternalTestingOnly: settings.testFlightInternalTestingOnly,
9939
+ stripSwiftSymbols: settings.stripSwiftSymbols
9230
9940
  };
9941
+ if (settings.thinning) values.thinning = settings.thinning;
9942
+ if (settings.iCloudContainerEnvironment) {
9943
+ values.iCloudContainerEnvironment = settings.iCloudContainerEnvironment;
9944
+ }
9945
+ if (settings.distributionBundleIdentifier) {
9946
+ values.distributionBundleIdentifier = settings.distributionBundleIdentifier;
9947
+ }
9231
9948
  if (settings.teamId) values.teamID = settings.teamId;
9232
9949
  if (settings.signingCertificate)
9233
9950
  values.signingCertificate = settings.signingCertificate;
@@ -9255,10 +9972,10 @@ var exportIosArchive = async (payload, timeoutMs, signal, _onLog, context) => {
9255
9972
  "exports",
9256
9973
  input.exportId
9257
9974
  );
9258
- await mkdir3(exportDirectory, { recursive: true, mode: 448 });
9975
+ await mkdir4(exportDirectory, { recursive: true, mode: 448 });
9259
9976
  const plistPath = join7(exportDirectory, "ExportOptions.plist");
9260
9977
  const logPath = join7(exportDirectory, "export.log");
9261
- await writeFile3(plistPath, exportPlist(input.settings), { mode: 384 });
9978
+ await writeFile4(plistPath, exportPlist(input.settings), { mode: 384 });
9262
9979
  const logger = new BuildLogger(input.buildId, context, logPath, process.env);
9263
9980
  try {
9264
9981
  const result = await runLoggedCommand({
@@ -9350,7 +10067,13 @@ var handlers = {
9350
10067
  [IOS_EXPORT_JOB_KIND]: exportIosArchive,
9351
10068
  [IOS_TEST_RESULTS_JOB_KIND]: generateIosBuildReport,
9352
10069
  [IOS_COVERAGE_REPORT_JOB_KIND]: generateIosBuildReport,
9353
- [IOS_SIGNING_INSPECT_JOB_KIND]: inspectIosSigning
10070
+ [IOS_SIGNING_INSPECT_JOB_KIND]: inspectIosSigning,
10071
+ [SIGNING_ASSETS_SCAN_JOB_KIND]: scanSigningAssets,
10072
+ [SIGNING_PROFILE_READ_JOB_KIND]: readSigningProfile,
10073
+ [SIGNING_PROFILE_INSTALL_JOB_KIND]: installSigningProfile,
10074
+ [SIGNING_PROFILE_DELETE_JOB_KIND]: deleteSigningProfile,
10075
+ [SIGNING_IDENTITY_IMPORT_JOB_KIND]: importSigningIdentity,
10076
+ [SIGNING_IDENTITY_DELETE_JOB_KIND]: deleteSigningIdentity
9354
10077
  };
9355
10078
 
9356
10079
  // src/repository-coordinator.ts
@@ -9429,7 +10152,8 @@ var JobExecutor = class {
9429
10152
  reportWorktreeActivity: (input) => this.client.reportWorktreeActivity(input),
9430
10153
  reportBuildProgress: (input) => this.client.reportBuildProgress(input),
9431
10154
  appendBuildLogs: (buildId, events) => this.client.appendBuildLogs(buildId, events),
9432
- uploadBuildArtifact: (input) => this.client.uploadBuildArtifact(input)
10155
+ uploadBuildArtifact: (input) => this.client.uploadBuildArtifact(input),
10156
+ claimSigningSecretTransfer: (transferId) => this.client.claimSigningSecretTransfer(transferId)
9433
10157
  }
9434
10158
  );
9435
10159
  const codebaseId = claimed.payload && typeof claimed.payload === "object" && !Array.isArray(claimed.payload) && typeof claimed.payload.codebaseId === "string" ? String(claimed.payload.codebaseId) : null;