@hasna/recordings 0.3.2 → 0.3.8
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/README.md +38 -34
- package/bun.lock +96 -36
- package/dist/__tests__/helpers/source-assertions.d.ts +6 -4
- package/dist/__tests__/helpers/source-assertions.d.ts.map +1 -1
- package/dist/cli/index.js +182 -93
- package/dist/cli/macos-shortcut.d.ts +2 -2
- package/dist/db/pg-migrations.d.ts +1 -1
- package/dist/http/client.d.ts +0 -10
- package/dist/http/client.d.ts.map +1 -1
- package/dist/index.js +162 -73
- package/dist/lib/capture-probe.d.ts +3 -3
- package/dist/lib/capture-probe.d.ts.map +1 -1
- package/dist/lib/macos-bundle.d.ts +1 -1
- package/dist/lib/release-install-policy.d.ts +21 -0
- package/dist/lib/release-install-policy.d.ts.map +1 -1
- package/dist/mcp/index.js +144 -59
- package/dist/sdk/index.d.ts +2 -2
- package/dist/sdk/index.js +7 -3
- package/dist/sdk/v1.generated.d.ts.map +1 -1
- package/dist/server/cloud-config.d.ts +4 -19
- package/dist/server/cloud-config.d.ts.map +1 -1
- package/dist/server/cloud.d.ts +1 -1
- package/dist/server/cloud.d.ts.map +1 -1
- package/dist/server/index.js +168 -110
- package/dist/server/serve.d.ts.map +1 -1
- package/dist/storage.d.ts +1 -1
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +144 -60
- 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 +4 -3
- package/packaging/macos/build_release_pkg.sh +10 -4
- package/packaging/macos/managed_bootstrap.sh +4 -4
- package/packaging/macos/scripts/postinstall +2 -2
- package/packaging/macos/scripts/preinstall +2 -0
- package/scripts/generate-sdk.ts +17 -16
- package/scripts/install_macos_app.sh +22 -22
- package/scripts/macos_artifact.ts +48 -39
- package/scripts/migrate.ts +2 -2
- package/scripts/release-suite-gate.ts +181 -0
- package/scripts/set-version.ts +5 -5
- package/scripts/smoke_macos_app.sh +21 -21
- package/scripts/vacuity-manifests/version-sites.tsv +8 -4
- package/src/native/Recordings/RecordingsLib/Info.plist +3 -3
- package/src/native/Recordings/RecordingsTests/CLIRunnerTests.swift +2 -2
- package/src/native/Recordings/RecordingsTests/RecordingStartGateTests.swift +1 -1
- package/src/native/Recordings/Updater/BootstrapPreflight/BootstrapPreflightMain.swift +1 -1
- package/src/native/Recordings/Updater/Broker/ApplicationNamespace.swift +2 -2
- package/src/native/Recordings/Updater/Broker/BrokerMain.swift +1 -1
- package/src/native/Recordings/Updater/Broker/CanonicalTreeCopy.swift +1 -1
- package/src/native/Recordings/Updater/Broker/InstallJournal.swift +1 -1
- package/src/native/Recordings/Updater/BrokerTests/ActivationRecoveryPolicyTests.swift +2 -2
- package/src/native/Recordings/Updater/Protocol/UpdateProtocol.swift +1 -1
- package/src/native/Recordings/Updater/VerifierLauncher/RecordingsVerifierLauncher.c +2 -2
- package/src/native/Recordings/build.sh +14 -20
- package/dist/lib/retired-deployment-modes.d.ts +0 -24
- package/dist/lib/retired-deployment-modes.d.ts.map +0 -1
package/dist/storage.js
CHANGED
|
@@ -1019,9 +1019,118 @@ function setAgentFocus(idOrName, projectId, db) {
|
|
|
1019
1019
|
d.query("UPDATE agents SET active_project_id = ?, last_seen_at = ? WHERE id = ?").run(resolvedProjectId, new Date().toISOString(), agent.id);
|
|
1020
1020
|
return getAgent(agent.id, d);
|
|
1021
1021
|
}
|
|
1022
|
+
// package.json
|
|
1023
|
+
var package_default = {
|
|
1024
|
+
name: "@hasna/recordings",
|
|
1025
|
+
version: "0.3.8",
|
|
1026
|
+
type: "module",
|
|
1027
|
+
description: "Speech-to-text recording tool with MCP and CLI \u2014 records, transcribes, and optionally enhances text using AI",
|
|
1028
|
+
repository: {
|
|
1029
|
+
type: "git",
|
|
1030
|
+
url: "git+https://github.com/hasna/apps"
|
|
1031
|
+
},
|
|
1032
|
+
main: "dist/index.js",
|
|
1033
|
+
types: "dist/index.d.ts",
|
|
1034
|
+
bin: {
|
|
1035
|
+
recordings: "dist/cli/index.js",
|
|
1036
|
+
"recordings-mcp": "dist/mcp/index.js",
|
|
1037
|
+
"recordings-serve": "dist/server/index.js"
|
|
1038
|
+
},
|
|
1039
|
+
exports: {
|
|
1040
|
+
".": {
|
|
1041
|
+
import: "./dist/index.js",
|
|
1042
|
+
types: "./dist/index.d.ts"
|
|
1043
|
+
},
|
|
1044
|
+
"./storage": {
|
|
1045
|
+
import: "./dist/storage.js",
|
|
1046
|
+
types: "./dist/storage.d.ts"
|
|
1047
|
+
},
|
|
1048
|
+
"./sdk": {
|
|
1049
|
+
import: "./dist/sdk/index.js",
|
|
1050
|
+
types: "./dist/sdk/index.d.ts"
|
|
1051
|
+
}
|
|
1052
|
+
},
|
|
1053
|
+
engines: {
|
|
1054
|
+
bun: ">=1.0.0"
|
|
1055
|
+
},
|
|
1056
|
+
scripts: {
|
|
1057
|
+
clean: "rm -rf dist",
|
|
1058
|
+
build: "bun run clean && bun run build:cli && bun run build:mcp && bun run build:serve && bun run build:lib && tsc --emitDeclarationOnly --outDir dist",
|
|
1059
|
+
"build:cli": "bun build src/cli/index.ts --target=bun --outfile=dist/cli/index.js --external=commander --external=chalk --external=openai",
|
|
1060
|
+
"build:mcp": "bun build src/mcp/index.ts --target=bun --outfile=dist/mcp/index.js --external=@modelcontextprotocol/sdk --external=openai",
|
|
1061
|
+
"build:serve": "bun build src/server/index.ts --target=bun --outfile=dist/server/index.js --external=@modelcontextprotocol/sdk --external=@hasna/contracts --external=openai --external=pg",
|
|
1062
|
+
"build:lib": "bun build src/index.ts src/storage.ts src/sdk/index.ts --target=bun --outdir=dist --external=openai",
|
|
1063
|
+
"build:native-fs-guard": "/bin/bash scripts/build_native_fs_guard.sh",
|
|
1064
|
+
"generate:sdk": "bun run scripts/generate-sdk.ts",
|
|
1065
|
+
migrate: "bun run scripts/migrate.ts",
|
|
1066
|
+
typecheck: "tsc --noEmit",
|
|
1067
|
+
"typecheck:tcc-contract": "tsc --noEmit -p tsconfig.tcc-contract.json",
|
|
1068
|
+
test: "bun test",
|
|
1069
|
+
"verify:ci-suite": "bun scripts/ci-linux-suite.ts --check",
|
|
1070
|
+
"verify:ci-suite:run": "bun scripts/ci-linux-suite.ts --verify-run",
|
|
1071
|
+
"verify:ci-native": "bun scripts/ci-native-build.ts",
|
|
1072
|
+
"test:gated": 'bun scripts/ci-linux-suite.ts --check && RECORDINGS_TEST_TIMEOUT_MS="${RECORDINGS_TEST_TIMEOUT_MS:-120000}" bun test --timeout "$RECORDINGS_TEST_TIMEOUT_MS" $(bun scripts/ci-linux-suite.ts --gated)',
|
|
1073
|
+
"test:vacuity-battery": 'bun scripts/vacuity-manifest-gen.ts > "${TMPDIR:-/tmp}/vacuity-corrupt-sites.tsv" && bun scripts/vacuity-mutation-battery.ts "${TMPDIR:-/tmp}/vacuity-corrupt-sites.tsv"',
|
|
1074
|
+
"test:vacuity-battery:source": "bun scripts/vacuity-mutation-battery.ts scripts/vacuity-manifests/source-side.tsv",
|
|
1075
|
+
"test:vacuity-battery:chain": "bun scripts/vacuity-mutation-battery.ts scripts/vacuity-manifests/install-chain.tsv",
|
|
1076
|
+
"test:vacuity-battery:vars": "bun scripts/vacuity-mutation-battery.ts scripts/vacuity-manifests/variable-operands.tsv",
|
|
1077
|
+
"test:vacuity-battery:reorder": "bun scripts/vacuity-mutation-battery.ts scripts/vacuity-manifests/reorder.tsv",
|
|
1078
|
+
"test:coverage": "bun test --coverage",
|
|
1079
|
+
"dev:cli": "bun run src/cli/index.ts",
|
|
1080
|
+
"desktop:snapshot": "bun run src/cli/index.ts app snapshot",
|
|
1081
|
+
"dev:mcp": "bun run src/mcp/index.ts",
|
|
1082
|
+
"verify:release": "bun run scripts/release-guard.ts",
|
|
1083
|
+
"scan:artifact": "bun run scripts/scan-artifact.ts",
|
|
1084
|
+
"version:set": "bun run scripts/set-version.ts",
|
|
1085
|
+
"version:check": "bun run scripts/set-version.ts --check",
|
|
1086
|
+
prepack: "bun run prepack:platform-gate && bun run version:check && bun run build && bun run verify:release && bun run scan:artifact",
|
|
1087
|
+
"prepack:platform-gate": `bash -c 'if [ "$(uname -s)" = Darwin ]; then bun run build:native-fs-guard; else echo "WARN: native fs-guard build skipped on $(uname -s) \u2014 dry-run/CI pack; publish recordings from macOS"; fi'`,
|
|
1088
|
+
prepublishOnly: "bun run typecheck && bun run release-suite-gate",
|
|
1089
|
+
"release-suite-gate": "bun run scripts/release-suite-gate.ts",
|
|
1090
|
+
"typecheck:shortcut-contract": "tsc --noEmit -p tsconfig.test.json"
|
|
1091
|
+
},
|
|
1092
|
+
files: [
|
|
1093
|
+
"dist/",
|
|
1094
|
+
"scripts/",
|
|
1095
|
+
"Dockerfile.package",
|
|
1096
|
+
"bun.lock",
|
|
1097
|
+
"src/native/Recordings/App/",
|
|
1098
|
+
"src/native/Recordings/RecordingsLib/",
|
|
1099
|
+
"src/native/Recordings/RecordingsTests/",
|
|
1100
|
+
"src/native/Recordings/Updater/",
|
|
1101
|
+
"src/native/Recordings/Package.swift",
|
|
1102
|
+
"src/native/Recordings/Package.resolved",
|
|
1103
|
+
"src/native/Recordings/build.sh",
|
|
1104
|
+
"packaging/macos/",
|
|
1105
|
+
"README.md",
|
|
1106
|
+
"LICENSE"
|
|
1107
|
+
],
|
|
1108
|
+
dependencies: {
|
|
1109
|
+
"@hasna/contracts": "0.13.3",
|
|
1110
|
+
"@hasna/events": "0.1.11",
|
|
1111
|
+
"@modelcontextprotocol/sdk": "^1.12.1",
|
|
1112
|
+
chalk: "^5.4.1",
|
|
1113
|
+
commander: "^13.1.0",
|
|
1114
|
+
openai: "^5.1.0",
|
|
1115
|
+
pg: "^8.13.3",
|
|
1116
|
+
zod: "^3.24.2"
|
|
1117
|
+
},
|
|
1118
|
+
devDependencies: {
|
|
1119
|
+
"@types/bun": "^1.2.5",
|
|
1120
|
+
"@types/pg": "^8.11.11",
|
|
1121
|
+
"node-api-headers": "1.9.0",
|
|
1122
|
+
typescript: "^5.8.2"
|
|
1123
|
+
},
|
|
1124
|
+
publishConfig: {
|
|
1125
|
+
registry: "https://registry.npmjs.org",
|
|
1126
|
+
access: "public"
|
|
1127
|
+
},
|
|
1128
|
+
license: "Apache-2.0",
|
|
1129
|
+
author: "Hasna <andrei@hasna.com>"
|
|
1130
|
+
};
|
|
1022
1131
|
|
|
1023
1132
|
// src/version.ts
|
|
1024
|
-
var VERSION =
|
|
1133
|
+
var VERSION = package_default.version;
|
|
1025
1134
|
|
|
1026
1135
|
// src/db/feedback.ts
|
|
1027
1136
|
function saveFeedback(input) {
|
|
@@ -1029,58 +1138,26 @@ function saveFeedback(input) {
|
|
|
1029
1138
|
db.query("INSERT INTO feedback (message, email, category, version) VALUES (?, ?, ?, ?)").run(input.message, input.email ?? null, input.category ?? "general", input.version ?? VERSION);
|
|
1030
1139
|
}
|
|
1031
1140
|
|
|
1032
|
-
// src/lib/retired-deployment-modes.ts
|
|
1033
|
-
var RETIRED_DEPLOYMENT_MODES = [
|
|
1034
|
-
"local",
|
|
1035
|
-
"self_hosted",
|
|
1036
|
-
"cloud",
|
|
1037
|
-
"remote",
|
|
1038
|
-
"hybrid"
|
|
1039
|
-
];
|
|
1040
|
-
function normalizeModeToken(value) {
|
|
1041
|
-
return value.trim().toLowerCase().replace(/-/g, "_");
|
|
1042
|
-
}
|
|
1043
|
-
function asRetiredDeploymentMode(value) {
|
|
1044
|
-
const token = normalizeModeToken(value);
|
|
1045
|
-
return RETIRED_DEPLOYMENT_MODES.includes(token) ? token : null;
|
|
1046
|
-
}
|
|
1047
|
-
function retiredDeploymentModeError(rawValue, sourceEnvKey, replacement) {
|
|
1048
|
-
const mode = asRetiredDeploymentMode(rawValue);
|
|
1049
|
-
const value = mode === "local" ? replacement.onBox : replacement.offBox;
|
|
1050
|
-
return new Error(`${sourceEnvKey}=${rawValue} names a deployment mode, and deployment modes are removed: ` + `${RETIRED_DEPLOYMENT_MODES.join(" | ")} no longer select anything. ` + `Set ${replacement.envKey}=${value} instead ` + `(${replacement.envKey} takes ${replacement.onBox} or ${replacement.offBox}).`);
|
|
1051
|
-
}
|
|
1052
|
-
|
|
1053
1141
|
// src/http/client.ts
|
|
1054
|
-
var SERVER_BACKEND_VALUES = ["sqlite", "postgresql", "postgres"];
|
|
1055
1142
|
function envToken(name) {
|
|
1056
1143
|
return name.toUpperCase().replace(/-/g, "_");
|
|
1057
1144
|
}
|
|
1058
|
-
function
|
|
1059
|
-
|
|
1145
|
+
function envKeys(name) {
|
|
1146
|
+
const token = envToken(name);
|
|
1147
|
+
return {
|
|
1148
|
+
storeKeys: [`HASNA_${token}_CLIENT_STORE`, `${token}_CLIENT_STORE`],
|
|
1149
|
+
apiUrlKeys: [`HASNA_${token}_API_URL`],
|
|
1150
|
+
apiKeyKeys: [`HASNA_${token}_API_KEY`]
|
|
1151
|
+
};
|
|
1060
1152
|
}
|
|
1061
|
-
function normalizeClientStore(value
|
|
1062
|
-
const normalized =
|
|
1153
|
+
function normalizeClientStore(value) {
|
|
1154
|
+
const normalized = value.trim().toLowerCase();
|
|
1063
1155
|
if (normalized === "sqlite")
|
|
1064
1156
|
return "sqlite";
|
|
1065
1157
|
if (normalized === "http" || normalized === "https")
|
|
1066
1158
|
return "http";
|
|
1067
|
-
if (asRetiredDeploymentMode(value)) {
|
|
1068
|
-
throw retiredDeploymentModeError(value, sourceEnvKey, clientStoreReplacement(replacementEnvKey));
|
|
1069
|
-
}
|
|
1070
1159
|
throw new Error(`Unknown client store: ${value}. Use sqlite or http.`);
|
|
1071
1160
|
}
|
|
1072
|
-
function defaultApiBaseUrl(name) {
|
|
1073
|
-
return `http://localhost:8874`;
|
|
1074
|
-
}
|
|
1075
|
-
function envKeys(name) {
|
|
1076
|
-
const token = envToken(name);
|
|
1077
|
-
return {
|
|
1078
|
-
storeKeys: [`HASNA_${token}_CLIENT_STORE`, `${token}_CLIENT_STORE`],
|
|
1079
|
-
retiredModeKeys: [`HASNA_${token}_STORAGE_MODE`, `HASNA_${token}_MODE`, `${token}_STORAGE_MODE`, `${token}_MODE`],
|
|
1080
|
-
apiUrlKeys: [`HASNA_${token}_API_URL`, `${token}_API_URL`],
|
|
1081
|
-
apiKeyKeys: [`HASNA_${token}_API_KEY`, `${token}_API_KEY`]
|
|
1082
|
-
};
|
|
1083
|
-
}
|
|
1084
1161
|
function firstEnv(env, keys) {
|
|
1085
1162
|
for (const key of keys) {
|
|
1086
1163
|
const value = env[key]?.trim();
|
|
@@ -1089,20 +1166,6 @@ function firstEnv(env, keys) {
|
|
|
1089
1166
|
}
|
|
1090
1167
|
return null;
|
|
1091
1168
|
}
|
|
1092
|
-
function assertNoRetiredMode(env, keys) {
|
|
1093
|
-
for (const key of keys.retiredModeKeys) {
|
|
1094
|
-
const value = env[key]?.trim();
|
|
1095
|
-
if (!value)
|
|
1096
|
-
continue;
|
|
1097
|
-
const normalized = normalizeModeToken(value);
|
|
1098
|
-
if (SERVER_BACKEND_VALUES.includes(normalized))
|
|
1099
|
-
continue;
|
|
1100
|
-
if (asRetiredDeploymentMode(value)) {
|
|
1101
|
-
throw retiredDeploymentModeError(value, key, clientStoreReplacement(keys.storeKeys[0]));
|
|
1102
|
-
}
|
|
1103
|
-
throw new Error(`${key}=${value} is not a client store. ${key} no longer selects one; ` + `set ${keys.storeKeys[0]}=sqlite or ${keys.storeKeys[0]}=http instead.`);
|
|
1104
|
-
}
|
|
1105
|
-
}
|
|
1106
1169
|
function toV1BaseUrl(apiUrl) {
|
|
1107
1170
|
const url = new URL(apiUrl);
|
|
1108
1171
|
if (url.protocol !== "http:" && url.protocol !== "https:") {
|
|
@@ -1118,22 +1181,44 @@ function toV1BaseUrl(apiUrl) {
|
|
|
1118
1181
|
}
|
|
1119
1182
|
function resolveTransport(name, env = process.env) {
|
|
1120
1183
|
const keys = envKeys(name);
|
|
1121
|
-
assertNoRetiredMode(env, keys);
|
|
1122
1184
|
const storeHit = firstEnv(env, keys.storeKeys);
|
|
1123
1185
|
const urlHit = firstEnv(env, keys.apiUrlKeys);
|
|
1124
1186
|
const keyHit = firstEnv(env, keys.apiKeyKeys);
|
|
1125
1187
|
let requested = "sqlite";
|
|
1126
1188
|
let modeSource = "default";
|
|
1127
1189
|
if (storeHit) {
|
|
1128
|
-
requested = normalizeClientStore(storeHit.value
|
|
1190
|
+
requested = normalizeClientStore(storeHit.value);
|
|
1129
1191
|
modeSource = storeHit.key;
|
|
1130
1192
|
} else if (urlHit && keyHit) {
|
|
1131
1193
|
requested = "http";
|
|
1132
1194
|
modeSource = "auto:api-url+api-key";
|
|
1195
|
+
} else if (urlHit || keyHit) {
|
|
1196
|
+
const missing = urlHit ? keys.apiKeyKeys[0] : keys.apiUrlKeys[0];
|
|
1197
|
+
const present = urlHit ? keys.apiUrlKeys[0] : keys.apiKeyKeys[0];
|
|
1198
|
+
return {
|
|
1199
|
+
transport: "sqlite",
|
|
1200
|
+
requested,
|
|
1201
|
+
modeSource,
|
|
1202
|
+
baseUrl: null,
|
|
1203
|
+
apiKeyPresent: Boolean(keyHit),
|
|
1204
|
+
misconfigured: true,
|
|
1205
|
+
warning: `${present} is set but ${missing} is not: the hosted API is only ` + `selected when BOTH are present. Set ${missing}, or unset ${present} to ` + `use the on-box store.`
|
|
1206
|
+
};
|
|
1133
1207
|
}
|
|
1134
1208
|
if (requested === "sqlite") {
|
|
1135
1209
|
return { transport: "sqlite", requested, modeSource, baseUrl: null, apiKeyPresent: Boolean(keyHit), misconfigured: false, warning: null };
|
|
1136
1210
|
}
|
|
1211
|
+
if (!urlHit) {
|
|
1212
|
+
return {
|
|
1213
|
+
transport: "sqlite",
|
|
1214
|
+
requested,
|
|
1215
|
+
modeSource,
|
|
1216
|
+
baseUrl: null,
|
|
1217
|
+
apiKeyPresent: Boolean(keyHit),
|
|
1218
|
+
misconfigured: true,
|
|
1219
|
+
warning: `${modeSource}=http but no API URL is set (${keys.apiUrlKeys[0]}). Refusing to route to the API.`
|
|
1220
|
+
};
|
|
1221
|
+
}
|
|
1137
1222
|
if (!keyHit) {
|
|
1138
1223
|
return {
|
|
1139
1224
|
transport: "sqlite",
|
|
@@ -1145,7 +1230,7 @@ function resolveTransport(name, env = process.env) {
|
|
|
1145
1230
|
warning: `${modeSource}=http but no API key is set (${keys.apiKeyKeys[0]}). Refusing to route to the API.`
|
|
1146
1231
|
};
|
|
1147
1232
|
}
|
|
1148
|
-
const rawUrl = urlHit
|
|
1233
|
+
const rawUrl = urlHit.value;
|
|
1149
1234
|
let baseUrl;
|
|
1150
1235
|
try {
|
|
1151
1236
|
baseUrl = toV1BaseUrl(rawUrl);
|
|
@@ -1617,7 +1702,6 @@ export {
|
|
|
1617
1702
|
resolveTransport,
|
|
1618
1703
|
resolveStorageClient,
|
|
1619
1704
|
getStore,
|
|
1620
|
-
defaultApiBaseUrl,
|
|
1621
1705
|
createStorageClient,
|
|
1622
1706
|
createHttpTransport,
|
|
1623
1707
|
__resetStore,
|
package/dist/store.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EACV,SAAS,EACT,oBAAoB,EACpB,eAAe,EACf,KAAK,EACL,OAAO,EACR,MAAM,kBAAkB,CAAC;AAI1B,OAAO,EAAqC,KAAK,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAMzF,eAAO,MAAM,GAAG,eAAe,CAAC;AAEhC,YAAY,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEtD,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED,MAAM,WAAW,KAAK;IACpB,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAC;IACjC,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAGhC,eAAe,CAAC,KAAK,EAAE,oBAAoB,EAAE,cAAc,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IAC1F,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC;IACpD,cAAc,CAAC,MAAM,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;IAC/D,eAAe,CAAC,CAAC,MAAM,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5D,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;IAChF,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC9C,iBAAiB,IAAI,OAAO,CAAC,cAAc,CAAC,CAAC;IAG7C,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;IACjF,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC;IAClD,UAAU,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;IAC/B,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC;IACxD,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC;IAGjF,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACpF,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;IACtD,YAAY,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IAGnC,YAAY,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACnD;AAwPD,wBAAsB,oBAAoB,CACxC,KAAK,EAAE,KAAK,EACZ,MAAM,CAAC,EAAE,eAAe,GACvB,OAAO,CAAC,MAAM,CAAC,CA0BjB;AAID;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,GAAG,GAAE,MAAM,CAAC,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAe,GAAG,KAAK,CAMzG;AAED,2CAA2C;AAC3C,wBAAgB,YAAY,IAAI,IAAI,CAEnC"}
|
package/dist/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const VERSION
|
|
1
|
+
export declare const VERSION: string;
|
|
2
2
|
//# sourceMappingURL=version.d.ts.map
|
package/dist/version.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,OAAO,QAAsB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hasna/recordings",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.8",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Speech-to-text recording tool with MCP and CLI — records, transcribes, and optionally enhances text using AI",
|
|
6
6
|
"repository": {
|
|
@@ -63,7 +63,8 @@
|
|
|
63
63
|
"version:check": "bun run scripts/set-version.ts --check",
|
|
64
64
|
"prepack": "bun run prepack:platform-gate && bun run version:check && bun run build && bun run verify:release && bun run scan:artifact",
|
|
65
65
|
"prepack:platform-gate": "bash -c 'if [ \"$(uname -s)\" = Darwin ]; then bun run build:native-fs-guard; else echo \"WARN: native fs-guard build skipped on $(uname -s) — dry-run/CI pack; publish recordings from macOS\"; fi'",
|
|
66
|
-
"prepublishOnly": "bun run typecheck && bun run
|
|
66
|
+
"prepublishOnly": "bun run typecheck && bun run release-suite-gate",
|
|
67
|
+
"release-suite-gate": "bun run scripts/release-suite-gate.ts",
|
|
67
68
|
"typecheck:shortcut-contract": "tsc --noEmit -p tsconfig.test.json"
|
|
68
69
|
},
|
|
69
70
|
"files": [
|
|
@@ -83,7 +84,7 @@
|
|
|
83
84
|
"LICENSE"
|
|
84
85
|
],
|
|
85
86
|
"dependencies": {
|
|
86
|
-
"@hasna/contracts": "0.
|
|
87
|
+
"@hasna/contracts": "0.13.3",
|
|
87
88
|
"@hasna/events": "0.1.11",
|
|
88
89
|
"@modelcontextprotocol/sdk": "^1.12.1",
|
|
89
90
|
"chalk": "^5.4.1",
|
|
@@ -222,8 +222,14 @@ done
|
|
|
222
222
|
case "$VERSION" in
|
|
223
223
|
''|*[!0-9A-Za-z._+-]*) echo "Package version is missing or invalid." >&2; exit 2 ;;
|
|
224
224
|
esac
|
|
225
|
-
|
|
226
|
-
|
|
225
|
+
# The artifact basename is derived from the canonical bundle identity, never hardcoded:
|
|
226
|
+
# build.sh emits ${APP_BASENAME}-${VERSION}-macos-${RELEASE_SUBTYPE} with APP_BASENAME
|
|
227
|
+
# taken from the bundle name (currently HasnaRecordings.app). The legacy
|
|
228
|
+
# Recordings-* form was dropped with the bundle rename and must not be re-required.
|
|
229
|
+
[ -n "$APP" ] && [ -d "$APP" ] || { echo "Package app bundle path is missing or invalid." >&2; exit 2; }
|
|
230
|
+
expected_basename="$(/usr/bin/basename "$APP" .app)-${VERSION}-macos-initial-bootstrap"
|
|
231
|
+
[ "$ARTIFACT_BASENAME" = "$expected_basename" ] || {
|
|
232
|
+
echo "Initial-bootstrap package artifact basename is missing or mode-incompatible (expected ${expected_basename})." >&2
|
|
227
233
|
exit 2
|
|
228
234
|
}
|
|
229
235
|
[[ "$SOURCE_SHA" =~ ^[0-9a-f]{40}$ ]] || { echo "Package source SHA must be an exact commit." >&2; exit 2; }
|
|
@@ -527,7 +533,7 @@ PACKAGE_BOOTSTRAP_ID="$(/usr/bin/uuidgen | /usr/bin/tr '[:upper:]' '[:lower:]')"
|
|
|
527
533
|
"$SCRIPTS"
|
|
528
534
|
require_no_extended_acl "$PACKAGE_STAGE_DIR"
|
|
529
535
|
|
|
530
|
-
/usr/bin/ditto "$APP" "$ROOT/Applications/
|
|
536
|
+
/usr/bin/ditto "$APP" "$ROOT/Applications/HasnaRecordings.app"
|
|
531
537
|
/bin/cp "$BROKER" "$ROOT/Library/PrivilegedHelperTools/com.hasna.recordings.updater"
|
|
532
538
|
/bin/cp "$VERIFIER" "$ROOT/Library/PrivilegedHelperTools/com.hasna.recordings.artifact-verifier"
|
|
533
539
|
/bin/cp "$PUBLIC_KEY" "$ROOT/Library/Application Support/Hasna/Recordings/Trust/envelope-keys/${KEY_EPOCH}.raw"
|
|
@@ -576,7 +582,7 @@ require_tree_without_extended_acl "$SCRIPTS"
|
|
|
576
582
|
"$ROOT/Library/LaunchDaemons/com.hasna.recordings.updater.plist"
|
|
577
583
|
/usr/bin/plutil -lint "$ROOT/Library/LaunchDaemons/com.hasna.recordings.updater.plist" >/dev/null
|
|
578
584
|
|
|
579
|
-
STAGED_APP="$ROOT/Applications/
|
|
585
|
+
STAGED_APP="$ROOT/Applications/HasnaRecordings.app"
|
|
580
586
|
STAGED_BROKER="$ROOT/Library/PrivilegedHelperTools/com.hasna.recordings.updater"
|
|
581
587
|
STAGED_CLIENT="$STAGED_APP/Contents/Helpers/recordings-update-client"
|
|
582
588
|
STAGED_VERIFIER="$ROOT/Library/PrivilegedHelperTools/com.hasna.recordings.artifact-verifier"
|
|
@@ -173,7 +173,7 @@ validate_target_ancestry() {
|
|
|
173
173
|
|
|
174
174
|
validate_target_ancestry
|
|
175
175
|
|
|
176
|
-
CLIENT="/Applications/
|
|
176
|
+
CLIENT="/Applications/HasnaRecordings.app/Contents/Helpers/recordings-update-client"
|
|
177
177
|
STATE="/var/db/com.hasna.recordings.updater/release-state.json"
|
|
178
178
|
AUTHORIZATION_ROOT="/private/var/db/com.hasna.recordings.bootstrap-authorization"
|
|
179
179
|
AUTHORIZATION_JOURNAL="${AUTHORIZATION_ROOT}/journal"
|
|
@@ -182,7 +182,7 @@ COHORT_PATHS=(
|
|
|
182
182
|
"/Library/PrivilegedHelperTools/com.hasna.recordings.updater"
|
|
183
183
|
"/Library/PrivilegedHelperTools/com.hasna.recordings.artifact-verifier"
|
|
184
184
|
"/Library/LaunchDaemons/com.hasna.recordings.updater.plist"
|
|
185
|
-
"/Applications/
|
|
185
|
+
"/Applications/HasnaRecordings.app"
|
|
186
186
|
"$CLIENT"
|
|
187
187
|
"/Library/Application Support/Hasna/Recordings/Trust"
|
|
188
188
|
"/Library/Application Support/Hasna/Recordings/Bootstrap"
|
|
@@ -304,7 +304,7 @@ PAYLOAD="$EXPANDED/Payload"
|
|
|
304
304
|
PREFLIGHT="$EXPANDED/Scripts/recordings-bootstrap-preflight"
|
|
305
305
|
EXPANDED_PREINSTALL="$EXPANDED/Scripts/preinstall"
|
|
306
306
|
EXPANDED_POSTINSTALL="$EXPANDED/Scripts/postinstall"
|
|
307
|
-
PAYLOAD_CLIENT="$PAYLOAD/Applications/
|
|
307
|
+
PAYLOAD_CLIENT="$PAYLOAD/Applications/HasnaRecordings.app/Contents/Helpers/recordings-update-client"
|
|
308
308
|
[ -d "$PAYLOAD" ] && [ ! -L "$PAYLOAD" ] && \
|
|
309
309
|
[ -x "$PREFLIGHT" ] && [ ! -L "$PREFLIGHT" ] && \
|
|
310
310
|
[ -x "$EXPANDED_PREINSTALL" ] && [ ! -L "$EXPANDED_PREINSTALL" ] && \
|
|
@@ -512,7 +512,7 @@ cohort_expected_mode() {
|
|
|
512
512
|
"/Library/PrivilegedHelperTools/com.hasna.recordings.updater"|\
|
|
513
513
|
"/Library/PrivilegedHelperTools/com.hasna.recordings.artifact-verifier") printf '555\n' ;;
|
|
514
514
|
"/Library/LaunchDaemons/com.hasna.recordings.updater.plist") printf '444\n' ;;
|
|
515
|
-
"/Applications/
|
|
515
|
+
"/Applications/HasnaRecordings.app"|"$CLIENT") printf '755\n' ;;
|
|
516
516
|
"/Library/Application Support/Hasna/Recordings/Trust") printf '700-or-755\n' ;;
|
|
517
517
|
"/Library/Application Support/Hasna/Recordings/Bootstrap"|\
|
|
518
518
|
"/Library/Application Support/Hasna/Recordings/Updates"|\
|
|
@@ -11,9 +11,9 @@ PACKAGE_BOOTSTRAP_ID="__RECORDINGS_PACKAGE_BOOTSTRAP_ID__"
|
|
|
11
11
|
AUTHORIZATION_ROOT="/private/var/db/com.hasna.recordings.bootstrap-authorization"
|
|
12
12
|
AUTHORIZATION_JOURNAL="${AUTHORIZATION_ROOT}/journal"
|
|
13
13
|
BROKER="/Library/PrivilegedHelperTools/com.hasna.recordings.updater"
|
|
14
|
-
CLIENT="/Applications/
|
|
14
|
+
CLIENT="/Applications/HasnaRecordings.app/Contents/Helpers/recordings-update-client"
|
|
15
15
|
VERIFIER="/Library/PrivilegedHelperTools/com.hasna.recordings.artifact-verifier"
|
|
16
|
-
APP="/Applications/
|
|
16
|
+
APP="/Applications/HasnaRecordings.app"
|
|
17
17
|
STATE_ROOT="/Library/Application Support/Hasna/Recordings/Updates"
|
|
18
18
|
TRUST_ROOT="/Library/Application Support/Hasna/Recordings/Trust"
|
|
19
19
|
BOOTSTRAP_ROOT="/Library/Application Support/Hasna/Recordings/Bootstrap"
|
|
@@ -248,6 +248,8 @@ COHORT_PATHS=(
|
|
|
248
248
|
"/Library/PrivilegedHelperTools/com.hasna.recordings.updater:555"
|
|
249
249
|
"/Library/PrivilegedHelperTools/com.hasna.recordings.artifact-verifier:555"
|
|
250
250
|
"/Library/LaunchDaemons/com.hasna.recordings.updater.plist:444"
|
|
251
|
+
"/Applications/HasnaRecordings.app:755"
|
|
252
|
+
"/Applications/HasnaRecordings.app/Contents/Helpers/recordings-update-client:755"
|
|
251
253
|
"/Applications/Recordings.app:755"
|
|
252
254
|
"/Applications/Recordings.app/Contents/Helpers/recordings-update-client:755"
|
|
253
255
|
"/Library/Application Support/Hasna/Recordings/Trust:700-or-755"
|
package/scripts/generate-sdk.ts
CHANGED
|
@@ -20,23 +20,24 @@ const { code, operations, warnings } = generateSdkFromOpenApi(spec as never, {
|
|
|
20
20
|
apiKeyHeader: "x-api-key",
|
|
21
21
|
});
|
|
22
22
|
|
|
23
|
-
// @hasna/contracts 0.
|
|
24
|
-
//
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
23
|
+
// @hasna/contracts 0.13.1 emits array-aware query serialization natively —
|
|
24
|
+
// per-item append, null/undefined items skipped — which is exactly OpenAPI's
|
|
25
|
+
// form+explode semantics the 0.8.4-era transform used to add by hand. Assert
|
|
26
|
+
// the measured 0.13.1 shape so a future serializer change fails generation
|
|
27
|
+
// loudly instead of silently altering request semantics.
|
|
28
|
+
const arrayQuerySerialization =
|
|
29
|
+
" if (value === undefined || value === null) continue;\n" +
|
|
30
|
+
" if (Array.isArray(value)) {\n" +
|
|
31
|
+
" for (const item of value) {\n" +
|
|
32
|
+
" if (item !== undefined && item !== null) url.searchParams.append(key, String(item));\n" +
|
|
33
|
+
" }\n" +
|
|
34
|
+
" } else {\n" +
|
|
35
|
+
" url.searchParams.set(key, String(value));\n" +
|
|
36
|
+
" }";
|
|
37
|
+
if (!code.includes(arrayQuerySerialization)) {
|
|
38
|
+
throw new Error("Generated SDK query serializer changed; update the serializer shape assertion");
|
|
29
39
|
}
|
|
30
|
-
const compatibleCode = code
|
|
31
|
-
scalarQuerySerialization,
|
|
32
|
-
[
|
|
33
|
-
" if (Array.isArray(value)) {",
|
|
34
|
-
" for (const item of value) url.searchParams.append(key, String(item));",
|
|
35
|
-
" } else if (value !== undefined && value !== null) {",
|
|
36
|
-
" url.searchParams.set(key, String(value));",
|
|
37
|
-
" }",
|
|
38
|
-
].join("\n"),
|
|
39
|
-
);
|
|
40
|
+
const compatibleCode = code;
|
|
40
41
|
|
|
41
42
|
const header =
|
|
42
43
|
"// AUTO-GENERATED by scripts/generate-sdk.ts from src/server/openapi.ts — DO NOT EDIT BY HAND.\n" +
|
|
@@ -126,18 +126,18 @@ require_absolute_canonical_owned_home() {
|
|
|
126
126
|
local canonical
|
|
127
127
|
case "$candidate" in
|
|
128
128
|
/*) ;;
|
|
129
|
-
*) echo "
|
|
129
|
+
*) echo "HasnaRecordings.app installation requires HOME to be an absolute canonical path." >&2; exit 1 ;;
|
|
130
130
|
esac
|
|
131
131
|
[ -d "$candidate" ] && [ ! -L "$candidate" ] || {
|
|
132
|
-
echo "
|
|
132
|
+
echo "HasnaRecordings.app installation requires HOME to be an absolute canonical path to a non-symlink directory." >&2
|
|
133
133
|
exit 1
|
|
134
134
|
}
|
|
135
135
|
canonical="$(cd "$candidate" 2>/dev/null && builtin pwd -P)" || {
|
|
136
|
-
echo "
|
|
136
|
+
echo "HasnaRecordings.app installation could not resolve HOME canonically." >&2
|
|
137
137
|
exit 1
|
|
138
138
|
}
|
|
139
139
|
[ "$candidate" = "$canonical" ] || {
|
|
140
|
-
echo "
|
|
140
|
+
echo "HasnaRecordings.app installation requires HOME to be an absolute canonical path." >&2
|
|
141
141
|
exit 1
|
|
142
142
|
}
|
|
143
143
|
[ "$("$STAT_EXECUTABLE" -f '%u' "$candidate")" = "$("$ID_EXECUTABLE" -u)" ] || {
|
|
@@ -352,7 +352,7 @@ require_absolute_executable "BUN_EXECUTABLE" "$BUN_EXECUTABLE"
|
|
|
352
352
|
require_absolute_canonical_owned_home
|
|
353
353
|
|
|
354
354
|
if [ "$("$UNAME_EXECUTABLE" -s)" != "Darwin" ]; then
|
|
355
|
-
echo "
|
|
355
|
+
echo "HasnaRecordings.app installation is only supported on macOS." >&2
|
|
356
356
|
exit 1
|
|
357
357
|
fi
|
|
358
358
|
|
|
@@ -546,7 +546,7 @@ fi
|
|
|
546
546
|
"$BUN_EXECUTABLE" "$ARTIFACT_TOOL" native-fs-guard-check
|
|
547
547
|
DATA_DIR="${HOME}/.hasna/recordings"
|
|
548
548
|
DATA_PARENT="$("$DIRNAME_EXECUTABLE" "$DATA_DIR")"
|
|
549
|
-
MANIFEST_BUNDLE_NAME="
|
|
549
|
+
MANIFEST_BUNDLE_NAME="HasnaRecordings.app"
|
|
550
550
|
APP_DEST="${HOME}/Applications/${MANIFEST_BUNDLE_NAME}"
|
|
551
551
|
APP_PARENT="$("$DIRNAME_EXECUTABLE" "$APP_DEST")"
|
|
552
552
|
ROLLBACK_DIR="${DATA_DIR}/rollbacks"
|
|
@@ -794,7 +794,7 @@ acquire_install_lock() {
|
|
|
794
794
|
if kill -0 "$owner_pid" 2>/dev/null; then
|
|
795
795
|
actual_start="$("$PS_EXECUTABLE" -o lstart= -p "$owner_pid" 2>/dev/null | "$TR_EXECUTABLE" -s ' ' | "$SED_EXECUTABLE" 's/^ //;s/ $//' || true)"
|
|
796
796
|
if [ -z "$owner_start" ] || [ -z "$actual_start" ] || [ "$owner_start" = "$actual_start" ]; then
|
|
797
|
-
echo "Another
|
|
797
|
+
echo "Another HasnaRecordings.app installer owns the active install lock." >&2
|
|
798
798
|
exit 1
|
|
799
799
|
fi
|
|
800
800
|
fi
|
|
@@ -807,17 +807,17 @@ acquire_install_lock() {
|
|
|
807
807
|
now="$("$DATE_EXECUTABLE" +%s)"
|
|
808
808
|
lock_age=$((now - $("$STAT_EXECUTABLE" -f '%m' "$LOCK_DIR")))
|
|
809
809
|
if [ "$lock_age" -lt "$stale_seconds" ]; then
|
|
810
|
-
echo "
|
|
810
|
+
echo "HasnaRecordings.app install lock is incomplete and too recent to reclaim safely." >&2
|
|
811
811
|
exit 1
|
|
812
812
|
fi
|
|
813
813
|
fi
|
|
814
814
|
stale_claim="${LOCK_DIR}.stale.$$"
|
|
815
815
|
if ! "$MV_EXECUTABLE" "$LOCK_DIR" "$stale_claim" 2>/dev/null; then
|
|
816
|
-
echo "
|
|
816
|
+
echo "HasnaRecordings.app install lock changed during stale-owner recovery." >&2
|
|
817
817
|
exit 1
|
|
818
818
|
fi
|
|
819
819
|
"$RM_EXECUTABLE" -rf "$stale_claim"
|
|
820
|
-
"$MKDIR_EXECUTABLE" -m 700 "$LOCK_DIR" || { echo "Could not acquire
|
|
820
|
+
"$MKDIR_EXECUTABLE" -m 700 "$LOCK_DIR" || { echo "Could not acquire HasnaRecordings.app install lock." >&2; exit 1; }
|
|
821
821
|
fi
|
|
822
822
|
LOCK_OWNED=1
|
|
823
823
|
local start
|
|
@@ -1263,13 +1263,13 @@ stop_uncommitted_candidate() {
|
|
|
1263
1263
|
done <<< "$remaining"
|
|
1264
1264
|
"$SLEEP_EXECUTABLE" 0.1
|
|
1265
1265
|
[ -z "$(pids_for_exact_executable "$expected")" ] || {
|
|
1266
|
-
echo "Uncommitted
|
|
1266
|
+
echo "Uncommitted HasnaRecordings.app process could not be stopped before recovery." >&2
|
|
1267
1267
|
return 1
|
|
1268
1268
|
}
|
|
1269
1269
|
}
|
|
1270
1270
|
|
|
1271
1271
|
if [ -f "$JOURNAL_PATH" ]; then
|
|
1272
|
-
echo "Recovering incomplete
|
|
1272
|
+
echo "Recovering incomplete HasnaRecordings.app installation transaction." >&2
|
|
1273
1273
|
if ! RECOVER_WAS_RUNNING="$("$BUN_EXECUTABLE" "$ARTIFACT_TOOL" journal-get --journal "$JOURNAL_PATH" --field was_running)" || \
|
|
1274
1274
|
! RECOVER_PHASE="$("$BUN_EXECUTABLE" "$ARTIFACT_TOOL" journal-get --journal "$JOURNAL_PATH" --field phase)" || \
|
|
1275
1275
|
! RECOVER_RUNNING_APP_PATHS_JSON="$("$BUN_EXECUTABLE" "$ARTIFACT_TOOL" journal-get --journal "$JOURNAL_PATH" --field prior_running_app_paths)"; then
|
|
@@ -1376,7 +1376,7 @@ if ! "$BUN_EXECUTABLE" -e '
|
|
|
1376
1376
|
if ((actual[i] ?? 0) < (minimum[i] ?? 0)) process.exit(1);
|
|
1377
1377
|
}
|
|
1378
1378
|
' "$CURRENT_MACOS" "$MINIMUM_MACOS"; then
|
|
1379
|
-
echo "
|
|
1379
|
+
echo "HasnaRecordings.app requires macOS ${MINIMUM_MACOS} or later; target is ${CURRENT_MACOS}." >&2
|
|
1380
1380
|
exit 1
|
|
1381
1381
|
fi
|
|
1382
1382
|
TARGET_ARCH="$("$UNAME_EXECUTABLE" -m)"
|
|
@@ -1386,7 +1386,7 @@ MANIFEST_ARCHITECTURES="$("$BUN_EXECUTABLE" "$ARTIFACT_TOOL" manifest-get \
|
|
|
1386
1386
|
--field architectures)"
|
|
1387
1387
|
case " ${MANIFEST_ARCHITECTURES} " in
|
|
1388
1388
|
*" ${TARGET_ARCH} "*) ;;
|
|
1389
|
-
*) echo "
|
|
1389
|
+
*) echo "HasnaRecordings.app artifact does not support target architecture ${TARGET_ARCH}." >&2; exit 1 ;;
|
|
1390
1390
|
esac
|
|
1391
1391
|
|
|
1392
1392
|
verify_secure_parent "$APP_PARENT"
|
|
@@ -1412,7 +1412,7 @@ add_unique_app() {
|
|
|
1412
1412
|
local existing
|
|
1413
1413
|
if [ -e "$candidate" ] || [ -L "$candidate" ]; then
|
|
1414
1414
|
[ -d "$candidate" ] && [ ! -L "$candidate" ] || {
|
|
1415
|
-
echo "
|
|
1415
|
+
echo "HasnaRecordings.app path is not a secure directory: ${candidate}" >&2
|
|
1416
1416
|
exit 1
|
|
1417
1417
|
}
|
|
1418
1418
|
fi
|
|
@@ -1524,7 +1524,7 @@ stop_old_processes() {
|
|
|
1524
1524
|
"$SLEEP_EXECUTABLE" 0.1
|
|
1525
1525
|
done
|
|
1526
1526
|
if [ "$remaining" -ne 0 ]; then
|
|
1527
|
-
echo "Existing
|
|
1527
|
+
echo "Existing HasnaRecordings.app process did not stop before replacement." >&2
|
|
1528
1528
|
exit 1
|
|
1529
1529
|
fi
|
|
1530
1530
|
}
|
|
@@ -1545,7 +1545,7 @@ quiesce_old_processes() {
|
|
|
1545
1545
|
fi
|
|
1546
1546
|
"$SLEEP_EXECUTABLE" 0.1
|
|
1547
1547
|
done
|
|
1548
|
-
echo "Existing
|
|
1548
|
+
echo "Existing HasnaRecordings.app processes did not remain quiescent before replacement." >&2
|
|
1549
1549
|
exit 1
|
|
1550
1550
|
}
|
|
1551
1551
|
|
|
@@ -1727,7 +1727,7 @@ for existing_app in ${DISCOVERED_APPS[@]+"${DISCOVERED_APPS[@]}"}; do
|
|
|
1727
1727
|
MANAGEABLE_APPS+=("$existing_app")
|
|
1728
1728
|
;;
|
|
1729
1729
|
*)
|
|
1730
|
-
echo "Duplicate
|
|
1730
|
+
echo "Duplicate HasnaRecordings.app at ${existing_app} is outside the transactional user install paths; archive or remove it before installing." >&2
|
|
1731
1731
|
exit 1
|
|
1732
1732
|
;;
|
|
1733
1733
|
esac
|
|
@@ -1954,7 +1954,7 @@ for ((refresh_attempt = 1; refresh_attempt <= 5; refresh_attempt++)); do
|
|
|
1954
1954
|
fi
|
|
1955
1955
|
done
|
|
1956
1956
|
[ "$STOPPED_REFRESH_STABLE" -eq 1 ] || {
|
|
1957
|
-
echo "Existing
|
|
1957
|
+
echo "Existing HasnaRecordings.app writers did not remain quiescent around the stopped-state refresh." >&2
|
|
1958
1958
|
exit 1
|
|
1959
1959
|
}
|
|
1960
1960
|
|
|
@@ -2004,7 +2004,7 @@ for ((move_index = 0; move_index < MOVED_ORIGINAL_COUNT; move_index++)); do
|
|
|
2004
2004
|
existing_app="${MOVED_ORIGINALS[$move_index]}"
|
|
2005
2005
|
moved_path="${MOVED_PATHS[$move_index]}"
|
|
2006
2006
|
[ "$("$BUN_EXECUTABLE" "$ARTIFACT_TOOL" tree-digest --path "$existing_app")" = "${MOVED_DIGESTS[$move_index]}" ] || {
|
|
2007
|
-
echo "Installed
|
|
2007
|
+
echo "Installed HasnaRecordings.app changed after transactional backup planning." >&2
|
|
2008
2008
|
exit 1
|
|
2009
2009
|
}
|
|
2010
2010
|
RECORDINGS_TEST_INSTALLER_PID="$$" \
|
|
@@ -2117,7 +2117,7 @@ if [ "$LAUNCH_APP" -eq 1 ] || [ "$was_running" -eq 1 ]; then
|
|
|
2117
2117
|
fi
|
|
2118
2118
|
|
|
2119
2119
|
if [ "$ARTIFACT_POLICY" = "local_only" ]; then
|
|
2120
|
-
echo "Installed local-only
|
|
2120
|
+
echo "Installed local-only HasnaRecordings.app for ${APPROVED_TARGET}; this artifact is ad-hoc signed and non-notarized."
|
|
2121
2121
|
if [ "$identity_migration" -eq 1 ]; then
|
|
2122
2122
|
# Not a maybe: the designated requirement did change, under an explicit approval.
|
|
2123
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."
|
|
@@ -2127,5 +2127,5 @@ if [ "$ARTIFACT_POLICY" = "local_only" ]; then
|
|
|
2127
2127
|
elif [ "$identity_migration" -eq 1 ]; then
|
|
2128
2128
|
echo "Installed a new signing identity; macOS will require one-time permission approval for this migration."
|
|
2129
2129
|
else
|
|
2130
|
-
echo "Installed verified
|
|
2130
|
+
echo "Installed verified HasnaRecordings.app release artifact: ${APP_DEST}"
|
|
2131
2131
|
fi
|