@hasna/recordings 0.2.14 → 0.3.2
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/Dockerfile.package +4 -5
- package/README.md +113 -8
- package/bun.lock +2 -2
- package/dist/__tests__/helpers/installer-guard-execution.d.ts +22 -0
- package/dist/__tests__/helpers/installer-guard-execution.d.ts.map +1 -0
- package/dist/__tests__/helpers/installer-preflight.d.ts +22 -0
- package/dist/__tests__/helpers/installer-preflight.d.ts.map +1 -0
- package/dist/__tests__/helpers/native-fs-guard.d.ts.map +1 -1
- package/dist/__tests__/helpers/source-assertions.d.ts +169 -0
- package/dist/__tests__/helpers/source-assertions.d.ts.map +1 -0
- package/dist/__tests__/preload.d.ts +1 -4
- package/dist/__tests__/preload.d.ts.map +1 -1
- package/dist/cli/desktop-snapshot.d.ts +20 -0
- package/dist/cli/desktop-snapshot.d.ts.map +1 -0
- package/dist/cli/index.js +2094 -280
- package/dist/cli/macos-permissions.d.ts +72 -0
- package/dist/cli/macos-permissions.d.ts.map +1 -1
- package/dist/cli/macos-shortcut.d.ts +139 -0
- package/dist/cli/macos-shortcut.d.ts.map +1 -0
- package/dist/cli/trigger-probe.d.ts +172 -0
- package/dist/cli/trigger-probe.d.ts.map +1 -0
- package/dist/db/database.d.ts +9 -0
- package/dist/db/database.d.ts.map +1 -1
- package/dist/http/client.d.ts +19 -7
- package/dist/http/client.d.ts.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +635 -50
- package/dist/lib/capture-probe.d.ts +216 -0
- package/dist/lib/capture-probe.d.ts.map +1 -0
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/macos-bundle.d.ts +50 -0
- package/dist/lib/macos-bundle.d.ts.map +1 -0
- package/dist/lib/persistence-probe.d.ts +208 -0
- package/dist/lib/persistence-probe.d.ts.map +1 -0
- package/dist/lib/recorder.d.ts.map +1 -1
- package/dist/lib/retired-deployment-modes.d.ts +24 -0
- package/dist/lib/retired-deployment-modes.d.ts.map +1 -0
- package/dist/lib/transcriber.d.ts +60 -0
- package/dist/lib/transcriber.d.ts.map +1 -1
- package/dist/mcp/index.js +141 -57
- package/dist/server/cloud-config.d.ts +25 -3
- package/dist/server/cloud-config.d.ts.map +1 -1
- package/dist/server/cloud-readiness.d.ts.map +1 -1
- package/dist/server/cloud.d.ts +8 -7
- package/dist/server/cloud.d.ts.map +1 -1
- package/dist/server/index.js +188 -80
- package/dist/server/migrate-command.d.ts.map +1 -1
- package/dist/server/serve.d.ts.map +1 -1
- package/dist/storage.d.ts +2 -2
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +109 -50
- package/dist/store.d.ts +1 -1
- package/dist/store.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.d.ts.map +1 -1
- package/package.json +25 -6
- package/scripts/ci-linux-suite.ts +403 -0
- package/scripts/ci-native-build.ts +402 -0
- package/scripts/enforce_identity_migration.sh +110 -0
- package/scripts/generate-sdk.ts +1 -1
- package/scripts/install_macos_app.sh +192 -31
- package/scripts/macos_artifact.ts +323 -43
- package/scripts/native/realtime-settle-probe/README.md +39 -0
- package/scripts/native/realtime-settle-probe/main.swift +135 -0
- package/scripts/policy/local-only-approved-targets.txt +21 -0
- package/scripts/read_local_only_targets.sh +203 -0
- package/scripts/scan-artifact.ts +40 -0
- package/scripts/set-version.ts +145 -0
- package/scripts/smoke_macos_app.sh +62 -16
- package/scripts/vacuity-manifest-gen.ts +96 -0
- package/scripts/vacuity-manifests/enhancement-screen-mirror.tsv +44 -0
- package/scripts/vacuity-manifests/install-chain.tsv +13 -0
- package/scripts/vacuity-manifests/must-survive-controls.tsv +10 -0
- package/scripts/vacuity-manifests/reorder.tsv +4 -0
- package/scripts/vacuity-manifests/source-side.tsv +15 -0
- package/scripts/vacuity-manifests/variable-operands.tsv +16 -0
- package/scripts/vacuity-manifests/version-sites.tsv +61 -0
- package/scripts/vacuity-mutation-battery.ts +266 -0
- package/src/native/Recordings/App/MenuBarStatusView.swift +23 -11
- package/src/native/Recordings/App/RecordingsApp.swift +37 -1
- package/src/native/Recordings/App/RuntimeSmoke.swift +5 -1
- package/src/native/Recordings/App/SidebarView.swift +1 -1
- package/src/native/Recordings/Package.swift +24 -5
- package/src/native/Recordings/RecordingsLib/EnhancementScreen.swift +91 -0
- package/src/native/Recordings/RecordingsLib/FnKeyMonitor.swift +27 -4
- package/src/native/Recordings/RecordingsLib/Info.plist +2 -2
- package/src/native/Recordings/RecordingsLib/MenuBarPresentation.swift +56 -3
- package/src/native/Recordings/RecordingsLib/NativePCMRecorder.swift +13 -0
- package/src/native/Recordings/RecordingsLib/PasteDeliveryVerification.swift +460 -0
- package/src/native/Recordings/RecordingsLib/PermissionRequestLaunchPlan.swift +21 -1
- package/src/native/Recordings/RecordingsLib/RealtimeTranscriptionClient.swift +41 -7
- package/src/native/Recordings/RecordingsLib/RecordingAttemptAlert.swift +36 -0
- package/src/native/Recordings/RecordingsLib/RecordingEngine.swift +1071 -75
- package/src/native/Recordings/RecordingsLib/SettingsView.swift +47 -3
- package/src/native/Recordings/RecordingsLib/VoiceShortcuts.swift +11 -6
- package/src/native/Recordings/RecordingsTests/BarOnlyLaunchPlanTests.swift +99 -0
- package/src/native/Recordings/RecordingsTests/CLIRunnerTests.swift +3 -3
- package/src/native/Recordings/RecordingsTests/EnhancementScreenTests.swift +191 -0
- package/src/native/Recordings/RecordingsTests/MenuBarPresentationTests.swift +144 -4
- package/src/native/Recordings/RecordingsTests/PasteDeliveryVerificationTests.swift +463 -0
- package/src/native/Recordings/RecordingsTests/PasteTargetTests.swift +33 -20
- package/src/native/Recordings/RecordingsTests/ProjectStoreTests.swift +1 -1
- package/src/native/Recordings/RecordingsTests/RealtimeSettleBenchmark.swift +200 -0
- package/src/native/Recordings/RecordingsTests/RealtimeSettleBudgetTests.swift +80 -0
- package/src/native/Recordings/RecordingsTests/RealtimeTranscriptionTests.swift +22 -4
- package/src/native/Recordings/RecordingsTests/RecordingEngineDeliveryTests.swift +12 -6
- package/src/native/Recordings/RecordingsTests/RecordingEngineHomeIsolationTests.swift +67 -0
- package/src/native/Recordings/RecordingsTests/RecordingStartGateTests.swift +12 -3
- package/src/native/Recordings/RecordingsTests/RecordingStartTimingTests.swift +207 -11
- package/src/native/Recordings/RecordingsTests/SpeechIntentTests.swift +17 -6
- package/src/native/Recordings/RecordingsTests/TestHomeDirectory.swift +23 -0
- package/src/native/Recordings/Updater/Broker/ApplicationProcessQuiescence.swift +7 -1
- package/src/native/Recordings/Updater/Broker/AtomicActivation.swift +10 -10
- package/src/native/Recordings/Updater/Broker/BrokerMain.swift +5 -1
- package/src/native/Recordings/Updater/Broker/HostOSProductVersion.swift +1 -0
- package/src/native/Recordings/Updater/Broker/PeerIdentity.swift +59 -3
- package/src/native/Recordings/Updater/Protocol/UpdateProtocol.swift +21 -2
- package/src/native/Recordings/Updater/ProtocolTests/ExpectationIntegrityTests.swift +60 -0
- package/src/native/Recordings/Updater/ProtocolTests/UpdateXPCInterfaceTests.swift +113 -0
- package/src/native/Recordings/Updater/VerifierLauncher/RecordingsVerifierLauncher.c +106 -5
- package/src/native/Recordings/build.sh +226 -20
- package/scripts/native/prebuilds/darwin-universal/recordings_fs_guard.node +0 -0
|
@@ -146,6 +146,66 @@ require_absolute_canonical_owned_home() {
|
|
|
146
146
|
}
|
|
147
147
|
}
|
|
148
148
|
|
|
149
|
+
# Every accepted argument, because until now there was no usage output at all and an
|
|
150
|
+
# unrecognized argument printed only "Unknown argument". That mattered most for
|
|
151
|
+
# --allow-adhoc-identity-migration: the identity-migration gate refuses a local-only
|
|
152
|
+
# reinstall by default, and an operator repairing a station had no way to discover the
|
|
153
|
+
# approval flag except by reading the refusal on stderr or the script itself.
|
|
154
|
+
print_usage() {
|
|
155
|
+
cat <<'USAGE'
|
|
156
|
+
Usage: install_macos_app.sh --artifact <zip> --manifest <json> [options]
|
|
157
|
+
|
|
158
|
+
Installs a Recordings macOS app artifact transactionally. Normally invoked through
|
|
159
|
+
`recordings app install`, which forwards these arguments.
|
|
160
|
+
|
|
161
|
+
Artifact and version:
|
|
162
|
+
--artifact <path> Finalized artifact archive to install
|
|
163
|
+
--manifest <path> Artifact manifest describing it
|
|
164
|
+
--manifest-sha256 <sha256> Authenticated digest of the manifest
|
|
165
|
+
--expected-source-sha <sha> Approved 40-character source commit
|
|
166
|
+
--expected-version <version> Version the artifact must declare
|
|
167
|
+
--expected-team-id <team-id> Required Apple Developer team identifier
|
|
168
|
+
|
|
169
|
+
Target selection:
|
|
170
|
+
--expected-hostname <name> Require this live short hostname before mutating
|
|
171
|
+
--variant <full|bar> Artifact variant the operator intends to install;
|
|
172
|
+
the manifest variant is verified against this at
|
|
173
|
+
install time (default: full)
|
|
174
|
+
--artifact-policy <release|local-only>
|
|
175
|
+
Trust policy to evaluate the artifact under
|
|
176
|
+
--approved-target <name> Approved target for a local-only artifact
|
|
177
|
+
--approved-target-identity-kind <kind>
|
|
178
|
+
hardware_uuid_sha256 or tailscale_node_id_sha256
|
|
179
|
+
--approved-target-identity-sha256 <sha256>
|
|
180
|
+
Authenticated digest of the target identity
|
|
181
|
+
|
|
182
|
+
Identity migration. Replacing an installed app with one signed by a different identity
|
|
183
|
+
voids the Microphone and Accessibility grants the installed app holds; macOS keys those
|
|
184
|
+
grants to code identity, and they cannot be restored by the installer. Both approvals are
|
|
185
|
+
one-shot and deliberately distinct: approving a release signer rotation is not approving
|
|
186
|
+
an ad-hoc replacement of a certificate-rooted install.
|
|
187
|
+
--allow-signing-identity-migration Approve one reviewed release signer change
|
|
188
|
+
--expected-old-identity-sha256 <sha256>
|
|
189
|
+
Exact installed identity approved for migration
|
|
190
|
+
--expected-new-identity-sha256 <sha256>
|
|
191
|
+
Exact candidate identity approved for migration
|
|
192
|
+
--allow-adhoc-identity-migration Approve replacing an installed app with an ad-hoc
|
|
193
|
+
signed local-only build. Required for essentially
|
|
194
|
+
every local-only reinstall, including a repair
|
|
195
|
+
install of the same version, because each ad-hoc
|
|
196
|
+
rebuild produces a new CDHash and is therefore a
|
|
197
|
+
real identity migration. Accepts that Microphone
|
|
198
|
+
and Accessibility must be granted again afterwards.
|
|
199
|
+
--acknowledge-local-signing-and-permissions
|
|
200
|
+
Acknowledge local-only ad-hoc signing up front
|
|
201
|
+
|
|
202
|
+
Launch and help:
|
|
203
|
+
--launch Launch the app after installing
|
|
204
|
+
--launch-timeout <seconds> Seconds to wait for the launch to settle
|
|
205
|
+
--help, -h Print this message and exit 0
|
|
206
|
+
USAGE
|
|
207
|
+
}
|
|
208
|
+
|
|
149
209
|
ARTIFACT_PATH=""
|
|
150
210
|
MANIFEST_PATH=""
|
|
151
211
|
EXPECTED_TEAM_ID="${RECORDINGS_EXPECTED_TEAM_IDENTIFIER:-}"
|
|
@@ -157,11 +217,13 @@ EXPECTED_NEW_IDENTITY_SHA256=""
|
|
|
157
217
|
EXPECTED_HOSTNAME=""
|
|
158
218
|
EXPECTED_HOSTNAME_SET=0
|
|
159
219
|
ARTIFACT_POLICY="release"
|
|
220
|
+
INSTALL_VARIANT="full"
|
|
160
221
|
APPROVED_TARGET="fleet"
|
|
161
222
|
APPROVED_TARGET_IDENTITY_KIND=""
|
|
162
223
|
APPROVED_TARGET_IDENTITY_SHA256="none"
|
|
163
224
|
ACKNOWLEDGE_LOCAL_SIGNING_AND_PERMISSIONS=0
|
|
164
225
|
ALLOW_IDENTITY_MIGRATION=0
|
|
226
|
+
ALLOW_ADHOC_IDENTITY_MIGRATION=0
|
|
165
227
|
LAUNCH_APP=0
|
|
166
228
|
LAUNCH_TIMEOUT_SECONDS="${RECORDINGS_LAUNCH_TIMEOUT_SECONDS:-10}"
|
|
167
229
|
|
|
@@ -196,6 +258,16 @@ while [ "$#" -gt 0 ]; do
|
|
|
196
258
|
EXPECTED_HOSTNAME_SET=1
|
|
197
259
|
shift 2
|
|
198
260
|
;;
|
|
261
|
+
--variant)
|
|
262
|
+
case "${2:-}" in
|
|
263
|
+
full|bar) INSTALL_VARIANT="${2}" ;;
|
|
264
|
+
*)
|
|
265
|
+
echo "Install variant must be full or bar." >&2
|
|
266
|
+
exit 2
|
|
267
|
+
;;
|
|
268
|
+
esac
|
|
269
|
+
shift 2
|
|
270
|
+
;;
|
|
199
271
|
--artifact-policy)
|
|
200
272
|
case "${2:-}" in
|
|
201
273
|
release) ARTIFACT_POLICY="release" ;;
|
|
@@ -232,6 +304,12 @@ while [ "$#" -gt 0 ]; do
|
|
|
232
304
|
ALLOW_IDENTITY_MIGRATION=1
|
|
233
305
|
shift
|
|
234
306
|
;;
|
|
307
|
+
# Distinct from --allow-signing-identity-migration: approving a release signer
|
|
308
|
+
# rotation is not approving an ad-hoc replacement of a certificate-rooted install.
|
|
309
|
+
--allow-adhoc-identity-migration)
|
|
310
|
+
ALLOW_ADHOC_IDENTITY_MIGRATION=1
|
|
311
|
+
shift
|
|
312
|
+
;;
|
|
235
313
|
--launch)
|
|
236
314
|
LAUNCH_APP=1
|
|
237
315
|
shift
|
|
@@ -240,8 +318,13 @@ while [ "$#" -gt 0 ]; do
|
|
|
240
318
|
LAUNCH_TIMEOUT_SECONDS="${2:-}"
|
|
241
319
|
shift 2
|
|
242
320
|
;;
|
|
321
|
+
--help | -h)
|
|
322
|
+
print_usage
|
|
323
|
+
exit 0
|
|
324
|
+
;;
|
|
243
325
|
*)
|
|
244
326
|
echo "Unknown argument: $1" >&2
|
|
327
|
+
echo "Run with --help for the accepted arguments." >&2
|
|
245
328
|
exit 2
|
|
246
329
|
;;
|
|
247
330
|
esac
|
|
@@ -310,6 +393,19 @@ PACKAGE_ROOT="$(cd "$("$DIRNAME_EXECUTABLE" "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
|
310
393
|
ARTIFACT_TOOL="${PACKAGE_ROOT}/scripts/macos_artifact.ts"
|
|
311
394
|
RUNTIME_SMOKE="${PACKAGE_ROOT}/scripts/smoke_macos_app.sh"
|
|
312
395
|
TAILSCALE_RESOLVER="${PACKAGE_ROOT}/scripts/resolve_tailscale_cli.sh"
|
|
396
|
+
# Sourced here, before either policy branch, so a missing or unusable guard denies every
|
|
397
|
+
# install rather than only the ones that happen to reach it.
|
|
398
|
+
IDENTITY_MIGRATION_GUARD="${PACKAGE_ROOT}/scripts/enforce_identity_migration.sh"
|
|
399
|
+
[ -f "$IDENTITY_MIGRATION_GUARD" ] && [ ! -L "$IDENTITY_MIGRATION_GUARD" ] || {
|
|
400
|
+
echo "Packaged identity-migration guard is missing." >&2
|
|
401
|
+
exit 2
|
|
402
|
+
}
|
|
403
|
+
# shellcheck source=/dev/null
|
|
404
|
+
. "$IDENTITY_MIGRATION_GUARD"
|
|
405
|
+
declare -F recordings_enforce_identity_migration >/dev/null || {
|
|
406
|
+
echo "Packaged identity-migration guard does not define its enforcement function." >&2
|
|
407
|
+
exit 2
|
|
408
|
+
}
|
|
313
409
|
if [ "$ARTIFACT_POLICY" = "release" ]; then
|
|
314
410
|
if [ -z "$EXPECTED_TEAM_ID" ]; then
|
|
315
411
|
echo "Release install requires --expected-team-id or RECORDINGS_EXPECTED_TEAM_IDENTIFIER." >&2
|
|
@@ -331,13 +427,36 @@ if [ "$ARTIFACT_POLICY" = "release" ]; then
|
|
|
331
427
|
echo "Local-only acknowledgment cannot be supplied for a release artifact." >&2
|
|
332
428
|
exit 2
|
|
333
429
|
fi
|
|
430
|
+
if [ "$ALLOW_ADHOC_IDENTITY_MIGRATION" -eq 1 ]; then
|
|
431
|
+
echo "Ad-hoc identity-migration approval is not valid for a release artifact; use --allow-signing-identity-migration with the exact old/new identity digests." >&2
|
|
432
|
+
exit 2
|
|
433
|
+
fi
|
|
334
434
|
else
|
|
335
|
-
|
|
336
|
-
|
|
435
|
+
# A local-station artifact may be Developer ID signed under a pinned team, because ad-hoc
|
|
436
|
+
# signing cannot hold a macOS TCC grant: TCC keys Accessibility to bundle id plus signing
|
|
437
|
+
# identity, and an ad-hoc CDHash changes on every rebuild, which is what silently killed the
|
|
438
|
+
# Fn/Globe hold-to-talk CGEventTap. A supplied team must therefore be a real Apple team, and
|
|
439
|
+
# it is matched against the manifest below exactly as a release team is.
|
|
440
|
+
if [ -n "$EXPECTED_TEAM_ID" ] && ! [[ "$EXPECTED_TEAM_ID" =~ ^[A-Z0-9]{10}$ ]]; then
|
|
441
|
+
echo "Local-only --expected-team-id must be a 10-character Developer ID team identifier." >&2
|
|
337
442
|
exit 2
|
|
338
443
|
fi
|
|
339
|
-
|
|
340
|
-
|
|
444
|
+
# The approved local-only targets are policy data shared with the artifact tool
|
|
445
|
+
# and the builder, parsed by one sourced reader so all three agree.
|
|
446
|
+
LOCAL_TARGET_POLICY="${PACKAGE_ROOT}/scripts/policy/local-only-approved-targets.txt"
|
|
447
|
+
LOCAL_TARGET_READER="${PACKAGE_ROOT}/scripts/read_local_only_targets.sh"
|
|
448
|
+
[ -f "$LOCAL_TARGET_READER" ] && [ ! -L "$LOCAL_TARGET_READER" ] || {
|
|
449
|
+
echo "Packaged local-only approved target reader is missing." >&2
|
|
450
|
+
exit 2
|
|
451
|
+
}
|
|
452
|
+
# shellcheck source=/dev/null
|
|
453
|
+
. "$LOCAL_TARGET_READER"
|
|
454
|
+
APPROVED_TARGET_MATCHED=0
|
|
455
|
+
APPROVED_TARGET_LIST=""
|
|
456
|
+
read_local_only_targets \
|
|
457
|
+
"$LOCAL_TARGET_POLICY" APPROVED_TARGET_LIST APPROVED_TARGET_MATCHED "$APPROVED_TARGET" || exit 2
|
|
458
|
+
if [ "$APPROVED_TARGET_MATCHED" -ne 1 ]; then
|
|
459
|
+
echo "Local-only install requires an approved --approved-target (${APPROVED_TARGET_LIST})." >&2
|
|
341
460
|
exit 2
|
|
342
461
|
fi
|
|
343
462
|
if ! [[ "$APPROVED_TARGET_IDENTITY_SHA256" =~ ^[a-f0-9]{64}$ ]]; then
|
|
@@ -386,12 +505,16 @@ else
|
|
|
386
505
|
exit 1
|
|
387
506
|
fi
|
|
388
507
|
if [ "$ALLOW_IDENTITY_MIGRATION" -eq 1 ] || [ -n "$EXPECTED_OLD_IDENTITY_SHA256" ] || [ -n "$EXPECTED_NEW_IDENTITY_SHA256" ]; then
|
|
389
|
-
echo "Release identity-migration flags are not valid for local-only artifacts." >&2
|
|
508
|
+
echo "Release identity-migration flags are not valid for local-only artifacts; an ad-hoc replacement is approved with --allow-adhoc-identity-migration." >&2
|
|
390
509
|
exit 2
|
|
391
510
|
fi
|
|
392
|
-
EXPECTED_TEAM_ID
|
|
511
|
+
if [ -z "$EXPECTED_TEAM_ID" ]; then
|
|
512
|
+
EXPECTED_TEAM_ID="ADHOC"
|
|
513
|
+
fi
|
|
393
514
|
echo "WARNING: installing a non-notarized local-only artifact approved only for ${APPROVED_TARGET}." >&2
|
|
394
|
-
|
|
515
|
+
if [ "$EXPECTED_TEAM_ID" = "ADHOC" ]; then
|
|
516
|
+
echo "WARNING: code identity can change; Microphone or Accessibility may require manual reauthorization." >&2
|
|
517
|
+
fi
|
|
395
518
|
fi
|
|
396
519
|
if [ "$ARTIFACT_POLICY" = "release" ] && [ "$ALLOW_IDENTITY_MIGRATION" -eq 1 ] && \
|
|
397
520
|
{ [ -z "$EXPECTED_OLD_IDENTITY_SHA256" ] || [ -z "$EXPECTED_NEW_IDENTITY_SHA256" ]; }; then
|
|
@@ -423,7 +546,8 @@ fi
|
|
|
423
546
|
"$BUN_EXECUTABLE" "$ARTIFACT_TOOL" native-fs-guard-check
|
|
424
547
|
DATA_DIR="${HOME}/.hasna/recordings"
|
|
425
548
|
DATA_PARENT="$("$DIRNAME_EXECUTABLE" "$DATA_DIR")"
|
|
426
|
-
|
|
549
|
+
MANIFEST_BUNDLE_NAME="Recordings.app"
|
|
550
|
+
APP_DEST="${HOME}/Applications/${MANIFEST_BUNDLE_NAME}"
|
|
427
551
|
APP_PARENT="$("$DIRNAME_EXECUTABLE" "$APP_DEST")"
|
|
428
552
|
ROLLBACK_DIR="${DATA_DIR}/rollbacks"
|
|
429
553
|
JOURNAL_PATH="${APP_PARENT}/.Recordings-install-transaction.json"
|
|
@@ -1214,6 +1338,7 @@ MANIFEST_SNAPSHOT="${WORK_DIR}/$("$BASENAME_EXECUTABLE" "$MANIFEST_PATH")"
|
|
|
1214
1338
|
--source-sha "$EXPECTED_SOURCE_SHA" \
|
|
1215
1339
|
--version "$EXPECTED_VERSION" \
|
|
1216
1340
|
--artifact-policy "$ARTIFACT_POLICY" \
|
|
1341
|
+
--variant "$INSTALL_VARIANT" \
|
|
1217
1342
|
--approved-target "$APPROVED_TARGET" \
|
|
1218
1343
|
--approved-target-identity-kind "$APPROVED_TARGET_IDENTITY_KIND" \
|
|
1219
1344
|
--approved-target-identity-sha256 "$APPROVED_TARGET_IDENTITY_SHA256"
|
|
@@ -1221,6 +1346,22 @@ MANIFEST_BUILDER_IDENTITY_KIND="$("$BUN_EXECUTABLE" "$ARTIFACT_TOOL" manifest-ge
|
|
|
1221
1346
|
--manifest "$MANIFEST_SNAPSHOT" \
|
|
1222
1347
|
--manifest-sha256 "$EXPECTED_MANIFEST_SHA256" \
|
|
1223
1348
|
--field builder_identity_kind)"
|
|
1349
|
+
AUTHENTICATED_BUNDLE_NAME="$("$BUN_EXECUTABLE" "$ARTIFACT_TOOL" manifest-get \
|
|
1350
|
+
--manifest "$MANIFEST_SNAPSHOT" \
|
|
1351
|
+
--manifest-sha256 "$EXPECTED_MANIFEST_SHA256" \
|
|
1352
|
+
--field bundle_name)"
|
|
1353
|
+
case "$AUTHENTICATED_BUNDLE_NAME" in
|
|
1354
|
+
*.app) ;;
|
|
1355
|
+
*)
|
|
1356
|
+
echo "Authenticated artifact manifest carries an invalid bundle name: ${AUTHENTICATED_BUNDLE_NAME}." >&2
|
|
1357
|
+
exit 1
|
|
1358
|
+
;;
|
|
1359
|
+
esac
|
|
1360
|
+
if [ "$AUTHENTICATED_BUNDLE_NAME" != "$MANIFEST_BUNDLE_NAME" ]; then
|
|
1361
|
+
MANIFEST_BUNDLE_NAME="$AUTHENTICATED_BUNDLE_NAME"
|
|
1362
|
+
APP_DEST="${HOME}/Applications/${MANIFEST_BUNDLE_NAME}"
|
|
1363
|
+
APP_PARENT="$("$DIRNAME_EXECUTABLE" "$APP_DEST")"
|
|
1364
|
+
fi
|
|
1224
1365
|
|
|
1225
1366
|
CURRENT_MACOS="$("$SW_VERS_EXECUTABLE" -productVersion)"
|
|
1226
1367
|
MINIMUM_MACOS="$("$BUN_EXECUTABLE" "$ARTIFACT_TOOL" manifest-get \
|
|
@@ -1252,7 +1393,7 @@ verify_secure_parent "$APP_PARENT"
|
|
|
1252
1393
|
verify_existing_state_root
|
|
1253
1394
|
|
|
1254
1395
|
STAGING_DIR="$("$MKTEMP_EXECUTABLE" -d "${APP_PARENT}/.Recordings-install.XXXXXX")"
|
|
1255
|
-
STAGED_APP="${STAGING_DIR}
|
|
1396
|
+
STAGED_APP="${STAGING_DIR}/${MANIFEST_BUNDLE_NAME}"
|
|
1256
1397
|
"$BUN_EXECUTABLE" "$ARTIFACT_TOOL" verify-archive \
|
|
1257
1398
|
--archive "$ARTIFACT_SNAPSHOT" \
|
|
1258
1399
|
--manifest "$MANIFEST_SNAPSHOT" \
|
|
@@ -1261,6 +1402,7 @@ STAGED_APP="${STAGING_DIR}/Recordings.app"
|
|
|
1261
1402
|
--source-sha "$EXPECTED_SOURCE_SHA" \
|
|
1262
1403
|
--version "$EXPECTED_VERSION" \
|
|
1263
1404
|
--artifact-policy "$ARTIFACT_POLICY" \
|
|
1405
|
+
--variant "$INSTALL_VARIANT" \
|
|
1264
1406
|
--approved-target "$APPROVED_TARGET" \
|
|
1265
1407
|
--approved-target-identity-kind "$APPROVED_TARGET_IDENTITY_KIND" \
|
|
1266
1408
|
--approved-target-identity-sha256 "$APPROVED_TARGET_IDENTITY_SHA256"
|
|
@@ -1538,10 +1680,11 @@ write_journal() {
|
|
|
1538
1680
|
--source-sha "$EXPECTED_SOURCE_SHA" \
|
|
1539
1681
|
--version "$EXPECTED_VERSION" \
|
|
1540
1682
|
--artifact-policy "$ARTIFACT_POLICY" \
|
|
1683
|
+
--variant "$INSTALL_VARIANT" \
|
|
1541
1684
|
--approved-target "$APPROVED_TARGET" \
|
|
1542
1685
|
--approved-target-identity-kind "$APPROVED_TARGET_IDENTITY_KIND" \
|
|
1543
1686
|
--approved-target-identity-sha256 "$APPROVED_TARGET_IDENTITY_SHA256"
|
|
1544
|
-
CANDIDATE_APP="$UNPACK_DIR
|
|
1687
|
+
CANDIDATE_APP="$UNPACK_DIR/${MANIFEST_BUNDLE_NAME}"
|
|
1545
1688
|
|
|
1546
1689
|
"$BUN_EXECUTABLE" "$ARTIFACT_TOOL" verify-app \
|
|
1547
1690
|
--app "$CANDIDATE_APP" \
|
|
@@ -1549,6 +1692,7 @@ CANDIDATE_APP="$UNPACK_DIR/Recordings.app"
|
|
|
1549
1692
|
--manifest-sha256 "$EXPECTED_MANIFEST_SHA256" \
|
|
1550
1693
|
--team-id "$EXPECTED_TEAM_ID" \
|
|
1551
1694
|
--artifact-policy "$ARTIFACT_POLICY" \
|
|
1695
|
+
--variant "$INSTALL_VARIANT" \
|
|
1552
1696
|
--approved-target "$APPROVED_TARGET" \
|
|
1553
1697
|
--approved-target-identity-kind "$APPROVED_TARGET_IDENTITY_KIND" \
|
|
1554
1698
|
--approved-target-identity-sha256 "$APPROVED_TARGET_IDENTITY_SHA256"
|
|
@@ -1562,10 +1706,12 @@ fi
|
|
|
1562
1706
|
DISCOVERED_APPS=()
|
|
1563
1707
|
add_unique_app "$APP_DEST"
|
|
1564
1708
|
add_unique_app "${DATA_DIR}/Recordings.app"
|
|
1565
|
-
|
|
1709
|
+
add_unique_app "${DATA_DIR}/HasnaRecordings.app"
|
|
1710
|
+
for candidate in "${HOME}"/Applications/Recordings.app.* "${HOME}"/Applications/HasnaRecordings.app.*; do
|
|
1566
1711
|
add_unique_app "$candidate"
|
|
1567
1712
|
done
|
|
1568
1713
|
add_unique_app "/Applications/Recordings.app"
|
|
1714
|
+
add_unique_app "/Applications/HasnaRecordings.app"
|
|
1569
1715
|
if [ -x "$MDFIND_EXECUTABLE" ]; then
|
|
1570
1716
|
while IFS= read -r candidate; do
|
|
1571
1717
|
[ -n "$candidate" ] || continue
|
|
@@ -1576,7 +1722,7 @@ fi
|
|
|
1576
1722
|
MANAGEABLE_APPS=()
|
|
1577
1723
|
for existing_app in ${DISCOVERED_APPS[@]+"${DISCOVERED_APPS[@]}"}; do
|
|
1578
1724
|
case "$existing_app" in
|
|
1579
|
-
"$APP_DEST"|"${DATA_DIR}/Recordings.app"|"${HOME}/Applications/Recordings.app."*)
|
|
1725
|
+
"$APP_DEST"|"${DATA_DIR}/Recordings.app"|"${DATA_DIR}/HasnaRecordings.app"|"${HOME}/Applications/Recordings.app."*|"${HOME}/Applications/HasnaRecordings.app."*)
|
|
1580
1726
|
echo "Duplicate disposition: archive transactionally, remove after activation: ${existing_app}"
|
|
1581
1727
|
MANAGEABLE_APPS+=("$existing_app")
|
|
1582
1728
|
;;
|
|
@@ -1621,7 +1767,10 @@ if [ "$ARTIFACT_POLICY" = "release" ] && [ -z "$candidate_requirement" ]; then
|
|
|
1621
1767
|
exit 1
|
|
1622
1768
|
fi
|
|
1623
1769
|
identity_migration=0
|
|
1624
|
-
|
|
1770
|
+
# Pass the SAME pinned team already given to verify-archive and verify-app. Without it the
|
|
1771
|
+
# digest verifies the candidate against the ad-hoc shape, which rejects a correctly
|
|
1772
|
+
# Developer-ID-signed local-station bundle and, under `set -euo pipefail`, aborts the install.
|
|
1773
|
+
candidate_identity_sha256="$("$BUN_EXECUTABLE" "$ARTIFACT_TOOL" requirement-digest --app "$CANDIDATE_APP" --artifact-policy "$ARTIFACT_POLICY" --expected-team-id "$EXPECTED_TEAM_ID")"
|
|
1625
1774
|
candidate_tree_sha256="$("$BUN_EXECUTABLE" "$ARTIFACT_TOOL" tree-digest --path "$CANDIDATE_APP")"
|
|
1626
1775
|
[ "$candidate_identity_sha256" = "$("$BUN_EXECUTABLE" "$ARTIFACT_TOOL" manifest-get \
|
|
1627
1776
|
--manifest "$MANIFEST_SNAPSHOT" \
|
|
@@ -1655,21 +1804,18 @@ for existing_app in ${MANAGEABLE_APPS[@]+"${MANAGEABLE_APPS[@]}"}; do
|
|
|
1655
1804
|
identity_migration=1
|
|
1656
1805
|
fi
|
|
1657
1806
|
done
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
echo "Identity migration approval was supplied but no identity migration is required." >&2
|
|
1671
|
-
exit 1
|
|
1672
|
-
fi
|
|
1807
|
+
# Enforced for every artifact policy. A local-only artifact is ad-hoc signed, so this is
|
|
1808
|
+
# the point at which an install would void the installed app's Microphone and
|
|
1809
|
+
# Accessibility grants; the printed warning further down is not a gate.
|
|
1810
|
+
recordings_enforce_identity_migration \
|
|
1811
|
+
"$ARTIFACT_POLICY" \
|
|
1812
|
+
"$identity_migration" \
|
|
1813
|
+
"$ALLOW_IDENTITY_MIGRATION" \
|
|
1814
|
+
"$ALLOW_ADHOC_IDENTITY_MIGRATION" \
|
|
1815
|
+
"$previous_identity_sha256" \
|
|
1816
|
+
"$candidate_identity_sha256" \
|
|
1817
|
+
"$EXPECTED_OLD_IDENTITY_SHA256" \
|
|
1818
|
+
"$EXPECTED_NEW_IDENTITY_SHA256" || exit 1
|
|
1673
1819
|
|
|
1674
1820
|
TRANSACTION_DIR="$("$MKTEMP_EXECUTABLE" -d "${APP_PARENT}/.Recordings-transaction.XXXXXX")"
|
|
1675
1821
|
TRANSACTION_NONCE="$("$BUN_EXECUTABLE" -e 'import { randomUUID } from "node:crypto"; process.stdout.write(randomUUID())')"
|
|
@@ -1738,6 +1884,7 @@ done
|
|
|
1738
1884
|
--manifest-sha256 "$EXPECTED_MANIFEST_SHA256" \
|
|
1739
1885
|
--team-id "$EXPECTED_TEAM_ID" \
|
|
1740
1886
|
--artifact-policy "$ARTIFACT_POLICY" \
|
|
1887
|
+
--variant "$INSTALL_VARIANT" \
|
|
1741
1888
|
--approved-target "$APPROVED_TARGET" \
|
|
1742
1889
|
--approved-target-identity-kind "$APPROVED_TARGET_IDENTITY_KIND" \
|
|
1743
1890
|
--approved-target-identity-sha256 "$APPROVED_TARGET_IDENTITY_SHA256"
|
|
@@ -1903,6 +2050,7 @@ write_journal candidate-installed
|
|
|
1903
2050
|
--manifest-sha256 "$EXPECTED_MANIFEST_SHA256" \
|
|
1904
2051
|
--team-id "$EXPECTED_TEAM_ID" \
|
|
1905
2052
|
--artifact-policy "$ARTIFACT_POLICY" \
|
|
2053
|
+
--variant "$INSTALL_VARIANT" \
|
|
1906
2054
|
--approved-target "$APPROVED_TARGET" \
|
|
1907
2055
|
--approved-target-identity-kind "$APPROVED_TARGET_IDENTITY_KIND" \
|
|
1908
2056
|
--approved-target-identity-sha256 "$APPROVED_TARGET_IDENTITY_SHA256"
|
|
@@ -1918,11 +2066,12 @@ fi
|
|
|
1918
2066
|
--manifest-sha256 "$EXPECTED_MANIFEST_SHA256" \
|
|
1919
2067
|
--team-id "$EXPECTED_TEAM_ID" \
|
|
1920
2068
|
--artifact-policy "$ARTIFACT_POLICY" \
|
|
2069
|
+
--variant "$INSTALL_VARIANT" \
|
|
1921
2070
|
--approved-target "$APPROVED_TARGET" \
|
|
1922
2071
|
--approved-target-identity-kind "$APPROVED_TARGET_IDENTITY_KIND" \
|
|
1923
2072
|
--approved-target-identity-sha256 "$APPROVED_TARGET_IDENTITY_SHA256"
|
|
1924
2073
|
SMOKE_TOOL_PATH="/usr/bin:/bin:/usr/sbin:/sbin:$("$DIRNAME_EXECUTABLE" "$BUN_EXECUTABLE")"
|
|
1925
|
-
PATH="$SMOKE_TOOL_PATH" "$RUNTIME_SMOKE" "$APP_DEST" "$BUN_EXECUTABLE"
|
|
2074
|
+
PATH="$SMOKE_TOOL_PATH" "$RUNTIME_SMOKE" "$APP_DEST" "$BUN_EXECUTABLE" --variant "$INSTALL_VARIANT"
|
|
1926
2075
|
write_journal activated
|
|
1927
2076
|
|
|
1928
2077
|
write_journal committed
|
|
@@ -1934,7 +2083,14 @@ STOPPED_RUNNING_APP=0
|
|
|
1934
2083
|
if [ "$LAUNCH_APP" -eq 1 ] || [ "$was_running" -eq 1 ]; then
|
|
1935
2084
|
EXPECTED_EXECUTABLE="$APP_DEST/Contents/MacOS/Recordings"
|
|
1936
2085
|
RUNNING_EXECUTABLES+=("$EXPECTED_EXECUTABLE")
|
|
1937
|
-
"$
|
|
2086
|
+
if [ "$INSTALL_VARIANT" = "bar" ]; then
|
|
2087
|
+
# Bar installs relaunch with an explicit --bar-only so the launch record is
|
|
2088
|
+
# self-describing; the compile-time RECORDINGS_BAR_ONLY default makes the bar
|
|
2089
|
+
# windowless even without the argument.
|
|
2090
|
+
"$OPEN_EXECUTABLE" -n "$APP_DEST" --args --bar-only
|
|
2091
|
+
else
|
|
2092
|
+
"$OPEN_EXECUTABLE" -n "$APP_DEST"
|
|
2093
|
+
fi
|
|
1938
2094
|
attempts=$((LAUNCH_TIMEOUT_SECONDS * 10))
|
|
1939
2095
|
launched_pid=""
|
|
1940
2096
|
launched_start_identity=""
|
|
@@ -1962,7 +2118,12 @@ fi
|
|
|
1962
2118
|
|
|
1963
2119
|
if [ "$ARTIFACT_POLICY" = "local_only" ]; then
|
|
1964
2120
|
echo "Installed local-only Recordings.app for ${APPROVED_TARGET}; this artifact is ad-hoc signed and non-notarized."
|
|
1965
|
-
|
|
2121
|
+
if [ "$identity_migration" -eq 1 ]; then
|
|
2122
|
+
# Not a maybe: the designated requirement did change, under an explicit approval.
|
|
2123
|
+
echo "Code identity changed under --allow-adhoc-identity-migration; the Microphone and Accessibility grants held by the replaced app no longer apply and must be reauthorized."
|
|
2124
|
+
else
|
|
2125
|
+
echo "Microphone or Accessibility may require manual reauthorization if this code identity differs from the last authorized one."
|
|
2126
|
+
fi
|
|
1966
2127
|
elif [ "$identity_migration" -eq 1 ]; then
|
|
1967
2128
|
echo "Installed a new signing identity; macOS will require one-time permission approval for this migration."
|
|
1968
2129
|
else
|