@raidiant/notifai 12.0.0-beta.8 → 12.0.1
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/CHANGELOG.md +37 -11
- package/bin/notifai.mjs +67 -19
- package/data/install.ps1 +142 -11
- package/data/release.json +1 -1
- package/inventory.json +1 -1
- package/npm-adapter-files.json +14 -14
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -8,23 +8,49 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
8
8
|
This project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html)
|
|
9
9
|
and [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/).
|
|
10
10
|
|
|
11
|
-
## [12.0.
|
|
11
|
+
## [12.0.1](https://github.com/Raidiant-io/notifai/compare/v12.0.0...v12.0.1) (2026-10-12)
|
|
12
12
|
|
|
13
|
-
### Breaking changes
|
|
14
13
|
|
|
15
|
-
|
|
14
|
+
### Bug Fixes
|
|
15
|
+
|
|
16
|
+
* **cli:** update compatible native installations without draining agents ([#292](https://github.com/Raidiant-io/notifai/issues/292)) ([689b10e](https://github.com/Raidiant-io/notifai/commit/689b10ee8af9af9e92ecb31eb0ce5eedf0ac7243))
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
### Dependencies
|
|
20
|
+
|
|
21
|
+
* The following workspace dependencies were updated
|
|
22
|
+
* dependencies
|
|
23
|
+
* @raidiant/notifai-protocol bumped from 8.3.0 to 8.3.1
|
|
24
|
+
|
|
25
|
+
## [12.0.0](https://github.com/Raidiant-io/notifai/compare/v11.8.0...v12.0.0) (2026-10-12)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
### ⚠ BREAKING CHANGES
|
|
29
|
+
|
|
30
|
+
* **cli:** unify native and npm installation
|
|
31
|
+
|
|
32
|
+
### Features
|
|
33
|
+
|
|
34
|
+
* **cli:** link a Claude Code picker by its questions, not a copied marker ([#278](https://github.com/Raidiant-io/notifai/issues/278)) ([449a4eb](https://github.com/Raidiant-io/notifai/commit/449a4ebe9de2284b808531675ee9f44f9f6978f1))
|
|
35
|
+
* **cli:** share one sign-in per machine with desktop apps ([#282](https://github.com/Raidiant-io/notifai/issues/282)) ([32863ba](https://github.com/Raidiant-io/notifai/commit/32863ba132261f706726664fd4796134a4d38eb6))
|
|
36
|
+
* **cli:** unify native and npm installation ([2ea7ef7](https://github.com/Raidiant-io/notifai/commit/2ea7ef735b75deee1deda7e08672ad0c757d0d0c))
|
|
37
|
+
* **protocol:** add desktop platforms, the stream provider and the changes feed ([#281](https://github.com/Raidiant-io/notifai/issues/281)) ([4b2bf51](https://github.com/Raidiant-io/notifai/commit/4b2bf51ecf5c120e5fa12141736f0df649f9fea5))
|
|
38
|
+
* **sounds:** add a bundled Update tone ([#289](https://github.com/Raidiant-io/notifai/issues/289)) ([31a7e5d](https://github.com/Raidiant-io/notifai/commit/31a7e5d103b318d7b8b10d1d29bd8c7964172dfe))
|
|
16
39
|
|
|
17
|
-
### Improvements
|
|
18
40
|
|
|
19
|
-
|
|
41
|
+
### Bug Fixes
|
|
20
42
|
|
|
21
|
-
*
|
|
43
|
+
* **auth:** preserve Linux credential authority across sessions ([#285](https://github.com/Raidiant-io/notifai/issues/285)) ([ce1ec66](https://github.com/Raidiant-io/notifai/commit/ce1ec66ea6f6078132b474a5b708107438d9017c))
|
|
44
|
+
* **cli:** link grouped Claude questions across registrations ([#288](https://github.com/Raidiant-io/notifai/issues/288)) ([b2e1bc4](https://github.com/Raidiant-io/notifai/commit/b2e1bc46d68c25dbf7a79bc67f88898d66ec720b))
|
|
45
|
+
* **cli:** preserve activity verification through long Codex turns ([#276](https://github.com/Raidiant-io/notifai/issues/276)) ([151ba68](https://github.com/Raidiant-io/notifai/commit/151ba687effee47ccef65f3800502ea896cd76dc))
|
|
46
|
+
* **cli:** stop reporting an acknowledgement as still required after recording it ([#277](https://github.com/Raidiant-io/notifai/issues/277)) ([0c4b363](https://github.com/Raidiant-io/notifai/commit/0c4b36358c9ff0616732043611aeebdcfd6cf4dd))
|
|
22
47
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
*
|
|
27
|
-
*
|
|
48
|
+
|
|
49
|
+
### Dependencies
|
|
50
|
+
|
|
51
|
+
* The following workspace dependencies were updated
|
|
52
|
+
* dependencies
|
|
53
|
+
* @raidiant/notifai-protocol bumped from 8.2.2 to 8.3.0
|
|
28
54
|
|
|
29
55
|
## [11.8.0](https://github.com/Raidiant-io/notifai/compare/v11.7.1...v11.8.0) (2026-10-08)
|
|
30
56
|
|
package/bin/notifai.mjs
CHANGED
|
@@ -7031,7 +7031,7 @@ var init_zip_reader = __esm({
|
|
|
7031
7031
|
});
|
|
7032
7032
|
|
|
7033
7033
|
// apps/cli/npm/main.mjs
|
|
7034
|
-
import { readFileSync as readFileSync5, lstatSync as
|
|
7034
|
+
import { readFileSync as readFileSync5, lstatSync as lstatSync6 } from "node:fs";
|
|
7035
7035
|
import path7 from "node:path";
|
|
7036
7036
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
7037
7037
|
|
|
@@ -7053,6 +7053,33 @@ function isPrerelease(value) {
|
|
|
7053
7053
|
return SEMVER.exec(value)?.[4] !== void 0;
|
|
7054
7054
|
}
|
|
7055
7055
|
|
|
7056
|
+
// apps/cli/src/local-continuity.ts
|
|
7057
|
+
var LOCAL_CONTINUITY = "notifai-session-state-v2";
|
|
7058
|
+
var HISTORICAL_LOCAL_CONTINUITY = "notifai-session-state-v1";
|
|
7059
|
+
var LOCAL_CONTINUITY_CAPABILITIES = Object.freeze({
|
|
7060
|
+
contract: LOCAL_CONTINUITY,
|
|
7061
|
+
compatible: Object.freeze({ [HISTORICAL_LOCAL_CONTINUITY]: Object.freeze([
|
|
7062
|
+
"bun-darwin-arm64",
|
|
7063
|
+
"bun-darwin-x64",
|
|
7064
|
+
"bun-windows-arm64",
|
|
7065
|
+
"bun-windows-x64"
|
|
7066
|
+
]) })
|
|
7067
|
+
});
|
|
7068
|
+
function localContinuity(value) {
|
|
7069
|
+
const item = value;
|
|
7070
|
+
if (!item || typeof item.contract !== "string" || !/^[a-z0-9][a-z0-9-]{0,63}$/.test(item.contract)) throw new Error("Invalid local continuity contract");
|
|
7071
|
+
if (item.compatible === void 0) return { contract: item.contract };
|
|
7072
|
+
if (item.compatible === null || typeof item.compatible !== "object" || Array.isArray(item.compatible) || Object.keys(item.compatible).length > 8) throw new Error("Invalid local continuity compatibility");
|
|
7073
|
+
const compatible = /* @__PURE__ */ Object.create(null);
|
|
7074
|
+
for (const [contract, targets] of Object.entries(item.compatible)) {
|
|
7075
|
+
if (!/^[a-z0-9][a-z0-9-]{0,63}$/.test(contract) || contract === item.contract || !Array.isArray(targets) || targets.length === 0 || targets.length > 6 || new Set(targets).size !== targets.length || targets.some((target) => typeof target !== "string" || !/^bun-(darwin|linux|windows)-(arm64|x64)$/.test(target))) {
|
|
7076
|
+
throw new Error("Invalid local continuity compatibility");
|
|
7077
|
+
}
|
|
7078
|
+
compatible[contract] = Object.freeze([...targets]);
|
|
7079
|
+
}
|
|
7080
|
+
return { contract: item.contract, compatible: Object.freeze(compatible) };
|
|
7081
|
+
}
|
|
7082
|
+
|
|
7056
7083
|
// apps/cli/src/release-distribution.ts
|
|
7057
7084
|
var RELEASE_TARGETS = [
|
|
7058
7085
|
"bun-darwin-arm64",
|
|
@@ -7111,11 +7138,19 @@ var Distribution = class {
|
|
|
7111
7138
|
const publicKey = createPublicKey(key);
|
|
7112
7139
|
if (publicKey.asymmetricKeyType !== "ed25519" || signature.length !== 64 || !verify(null, releaseSigningMessage(kind, payload), publicKey, signature)) throw new Error("Invalid release signature");
|
|
7113
7140
|
const value = JSON.parse(payload.toString("utf8"));
|
|
7114
|
-
if (!record(value) || value["schema"] !== 1
|
|
7141
|
+
if (!record(value) || value["schema"] !== 1 && !(kind === "inventory" && value["schema"] === 2)) {
|
|
7142
|
+
throw new Error("Unsupported release record schema");
|
|
7143
|
+
}
|
|
7115
7144
|
return value;
|
|
7116
7145
|
}
|
|
7117
7146
|
verifyInventory(bytes) {
|
|
7118
7147
|
const value = this.verifyRecord("inventory", bytes);
|
|
7148
|
+
if (value["schema"] === 2) {
|
|
7149
|
+
const continuity = localContinuity(value["local_continuity"]);
|
|
7150
|
+
value["local_continuity"] = Object.freeze(continuity);
|
|
7151
|
+
} else if (value["local_continuity"] !== void 0) {
|
|
7152
|
+
throw new Error("Historical inventory cannot declare an enforcing continuity contract");
|
|
7153
|
+
}
|
|
7119
7154
|
if (!version(value["version"]) || typeof value["source_revision"] !== "string" || !/^[a-f0-9]{40}$/.test(value["source_revision"]) || !positive(value["store_schema"]) || !positive(value["launcher_schema"]) || !Array.isArray(value["artifacts"]) || value["artifacts"].length === 0 || value["artifacts"].length > RELEASE_TARGETS.length) {
|
|
7120
7155
|
throw new Error("Malformed release inventory");
|
|
7121
7156
|
}
|
|
@@ -7260,6 +7295,20 @@ var NPM_ADAPTER_MANIFEST = "npm-adapter-files.json";
|
|
|
7260
7295
|
var NPM_ADAPTER_INVENTORY = "inventory.json";
|
|
7261
7296
|
var NPM_ADAPTER_MAX_METADATA = 256 * 1024;
|
|
7262
7297
|
var NPM_ADAPTER_MAX_BYTES = 16 * 1024 * 1024;
|
|
7298
|
+
function assertNpmAdapterPackage(value, manifest) {
|
|
7299
|
+
const pkg = value;
|
|
7300
|
+
const bin = pkg?.["bin"];
|
|
7301
|
+
if (!pkg || pkg["name"] !== manifest.package || pkg["version"] !== manifest.adapter_version || !bin || typeof bin !== "object" || Array.isArray(bin) || Object.keys(bin).length !== 1 || bin["notifai"] !== NPM_ADAPTER_BIN || [
|
|
7302
|
+
"scripts",
|
|
7303
|
+
"dependencies",
|
|
7304
|
+
"optionalDependencies",
|
|
7305
|
+
"peerDependencies",
|
|
7306
|
+
"bundleDependencies",
|
|
7307
|
+
"bundledDependencies",
|
|
7308
|
+
"directories",
|
|
7309
|
+
"man"
|
|
7310
|
+
].some((key) => Object.hasOwn(pkg, key))) throw new Error("Invalid published npm adapter package contract");
|
|
7311
|
+
}
|
|
7263
7312
|
function npmAdapterInventoryUrl(version2) {
|
|
7264
7313
|
if (version2.length > 100 || !isSemVer(version2)) throw new Error("Invalid npm adapter version");
|
|
7265
7314
|
return `https://github.com/Raidiant-io/notifai/releases/download/v${version2}/inventory.json`;
|
|
@@ -7353,8 +7402,7 @@ function verifyNpmAdapterArtifact(directory, distribution, checkAccess = npmAdap
|
|
|
7353
7402
|
}
|
|
7354
7403
|
if (expected.size) throw new Error("Npm adapter payload is incomplete");
|
|
7355
7404
|
const executable = path.join(directory, NPM_ADAPTER_BIN);
|
|
7356
|
-
|
|
7357
|
-
if (pkg.name !== manifest.package || pkg.version !== manifest.adapter_version || pkg.bin?.notifai !== NPM_ADAPTER_BIN || pkg.scripts !== void 0 || pkg.dependencies !== void 0) throw new Error("Invalid published npm adapter package contract");
|
|
7405
|
+
assertNpmAdapterPackage(JSON.parse(metadata("package.json")), manifest);
|
|
7358
7406
|
return { directory, executable, manifest, inventory, signedInventory };
|
|
7359
7407
|
}
|
|
7360
7408
|
|
|
@@ -10711,12 +10759,12 @@ function assertCurrentUserOwns(file, owner) {
|
|
|
10711
10759
|
var MAX_EXPANDED = 768 * 1024 * 1024;
|
|
10712
10760
|
var MAX_FILE = 512 * 1024 * 1024;
|
|
10713
10761
|
var MAX_ENTRIES = 130;
|
|
10714
|
-
async function tarEntries(bytes, consume) {
|
|
10762
|
+
async function tarEntries(bytes, consume, maxExpanded = MAX_EXPANDED) {
|
|
10715
10763
|
const reader = (0, import_tar_stream.extract)();
|
|
10716
10764
|
let expanded = 0;
|
|
10717
10765
|
const limit = new Transform({ transform(chunk, _encoding, done) {
|
|
10718
10766
|
expanded += chunk.length;
|
|
10719
|
-
done(expanded >
|
|
10767
|
+
done(expanded > maxExpanded ? new Error("Archive expanded size exceeds its limit") : null, chunk);
|
|
10720
10768
|
} });
|
|
10721
10769
|
const pumping = pipeline(
|
|
10722
10770
|
Readable.from([bytes]),
|
|
@@ -10888,11 +10936,11 @@ async function acquireNative(release, { distribution, platform, capture = false,
|
|
|
10888
10936
|
}
|
|
10889
10937
|
|
|
10890
10938
|
// apps/cli/src/npm-adapter-route.ts
|
|
10891
|
-
import { lstatSync as
|
|
10939
|
+
import { lstatSync as lstatSync4, readFileSync as readFileSync3, realpathSync as realpathSync2 } from "node:fs";
|
|
10892
10940
|
import path5 from "node:path";
|
|
10893
10941
|
|
|
10894
10942
|
// apps/cli/src/local-path.ts
|
|
10895
|
-
import { realpathSync } from "node:fs";
|
|
10943
|
+
import { lstatSync as lstatSync3, readlinkSync, realpathSync } from "node:fs";
|
|
10896
10944
|
import path4 from "node:path";
|
|
10897
10945
|
function canonicalPath(file) {
|
|
10898
10946
|
const absolute = path4.resolve(file);
|
|
@@ -11007,7 +11055,7 @@ function inspectNpmAdapterRoute(command, proof, options = {}) {
|
|
|
11007
11055
|
const platform = options.platform ?? process.platform, access = options.checkAccess ?? npmAdapterPosixAccess;
|
|
11008
11056
|
try {
|
|
11009
11057
|
const candidate = path5.resolve(command), root = path5.resolve(proof.directory);
|
|
11010
|
-
if (sameLocalPath(candidate, proof.executable, platform) && !
|
|
11058
|
+
if (sameLocalPath(candidate, proof.executable, platform) && !lstatSync4(candidate).isSymbolicLink()) {
|
|
11011
11059
|
access([{ file: candidate, directory: false }]);
|
|
11012
11060
|
return { kind: "direct", command: candidate, directory: path5.dirname(candidate), global_prefix: null, temporary_bin: null };
|
|
11013
11061
|
}
|
|
@@ -11020,7 +11068,7 @@ function inspectNpmAdapterRoute(command, proof, options = {}) {
|
|
|
11020
11068
|
for (const start of [root, route.directory]) {
|
|
11021
11069
|
let current = start;
|
|
11022
11070
|
for (let depth = 0; depth < 16; depth++) {
|
|
11023
|
-
const stat2 =
|
|
11071
|
+
const stat2 = lstatSync4(current);
|
|
11024
11072
|
if (!stat2.isDirectory() || stat2.isSymbolicLink()) return null;
|
|
11025
11073
|
directories.add(current);
|
|
11026
11074
|
if (sameLocalPath(current, stop, platform)) break;
|
|
@@ -11029,7 +11077,7 @@ function inspectNpmAdapterRoute(command, proof, options = {}) {
|
|
|
11029
11077
|
current = parent;
|
|
11030
11078
|
}
|
|
11031
11079
|
}
|
|
11032
|
-
const stat =
|
|
11080
|
+
const stat = lstatSync4(candidate);
|
|
11033
11081
|
if (platform !== "win32") {
|
|
11034
11082
|
if (!stat.isSymbolicLink() || !process.getuid || stat.uid !== process.getuid() || !sameLocalPath(realpathSync2(candidate), proof.executable, platform)) return null;
|
|
11035
11083
|
} else {
|
|
@@ -11191,7 +11239,7 @@ async function runNpmAdapter(args, { locator, platform, distribution, verify: ve
|
|
|
11191
11239
|
import assert3 from "node:assert/strict";
|
|
11192
11240
|
import { execFileSync, spawn, spawnSync } from "node:child_process";
|
|
11193
11241
|
import { randomUUID } from "node:crypto";
|
|
11194
|
-
import { lstatSync as
|
|
11242
|
+
import { lstatSync as lstatSync5, mkdtempSync as mkdtempSync2, readFileSync as readFileSync4, readdirSync as readdirSync2 } from "node:fs";
|
|
11195
11243
|
import os from "node:os";
|
|
11196
11244
|
import path6 from "node:path";
|
|
11197
11245
|
import { fileURLToPath } from "node:url";
|
|
@@ -11239,13 +11287,13 @@ function windowsPackageAccess(paths, execute = execFileSync) {
|
|
|
11239
11287
|
function ownedPosixCommand(home, uid = process.getuid()) {
|
|
11240
11288
|
const command = path6.join(home, ".notifai/bin/notifai");
|
|
11241
11289
|
try {
|
|
11242
|
-
|
|
11290
|
+
lstatSync5(command);
|
|
11243
11291
|
} catch (error) {
|
|
11244
11292
|
if (error.code === "ENOENT") return null;
|
|
11245
11293
|
throw error;
|
|
11246
11294
|
}
|
|
11247
11295
|
for (const file of [home, path6.join(home, ".notifai"), path6.dirname(command), command]) {
|
|
11248
|
-
const stat =
|
|
11296
|
+
const stat = lstatSync5(file);
|
|
11249
11297
|
assert3.ok(
|
|
11250
11298
|
!stat.isSymbolicLink() && stat.uid === uid && (stat.mode & 18) === 0 && (file === command ? stat.isFile() && (stat.mode & 64) !== 0 : stat.isDirectory()),
|
|
11251
11299
|
"Existing installation is not privately owned; inspect it before repair"
|
|
@@ -11258,7 +11306,7 @@ function assertAcquisitionReady(home, checkAccess, checkHomeAccess = checkAccess
|
|
|
11258
11306
|
for (const directory of [home, root]) {
|
|
11259
11307
|
let stat;
|
|
11260
11308
|
try {
|
|
11261
|
-
stat =
|
|
11309
|
+
stat = lstatSync5(directory);
|
|
11262
11310
|
} catch (error) {
|
|
11263
11311
|
if (directory === root && error.code === "ENOENT") return;
|
|
11264
11312
|
throw error;
|
|
@@ -11269,7 +11317,7 @@ function assertAcquisitionReady(home, checkAccess, checkHomeAccess = checkAccess
|
|
|
11269
11317
|
}
|
|
11270
11318
|
for (const name of ["uninstall.json", "transaction.json", "install.json", "active.json"]) {
|
|
11271
11319
|
try {
|
|
11272
|
-
|
|
11320
|
+
lstatSync5(path6.join(root, name));
|
|
11273
11321
|
} catch (error) {
|
|
11274
11322
|
if (error.code === "ENOENT") continue;
|
|
11275
11323
|
throw error;
|
|
@@ -11280,7 +11328,7 @@ function assertAcquisitionReady(home, checkAccess, checkHomeAccess = checkAccess
|
|
|
11280
11328
|
const directory = path6.join(root, name);
|
|
11281
11329
|
let stat;
|
|
11282
11330
|
try {
|
|
11283
|
-
stat =
|
|
11331
|
+
stat = lstatSync5(directory);
|
|
11284
11332
|
} catch (error) {
|
|
11285
11333
|
if (error.code === "ENOENT") continue;
|
|
11286
11334
|
throw error;
|
|
@@ -11355,7 +11403,7 @@ function nativePlatform() {
|
|
|
11355
11403
|
checkAccess(paths) {
|
|
11356
11404
|
if (!windows) {
|
|
11357
11405
|
for (const { file } of paths) {
|
|
11358
|
-
const stat =
|
|
11406
|
+
const stat = lstatSync5(file);
|
|
11359
11407
|
assert3.ok(stat.uid === process.getuid() && (stat.mode & 18) === 0, "Npm adapter path is not owned by this User");
|
|
11360
11408
|
}
|
|
11361
11409
|
return;
|
|
@@ -11403,7 +11451,7 @@ function nativePlatform() {
|
|
|
11403
11451
|
try {
|
|
11404
11452
|
const root = path7.resolve(path7.dirname(fileURLToPath2(import.meta.url)), "..");
|
|
11405
11453
|
const file = path7.join(root, "data/release.json");
|
|
11406
|
-
const stat =
|
|
11454
|
+
const stat = lstatSync6(file);
|
|
11407
11455
|
if (!stat.isFile() || stat.isSymbolicLink() || stat.size > 1024) throw new Error("Invalid npm adapter release locator");
|
|
11408
11456
|
const locator = JSON.parse(readFileSync5(file, "utf8"));
|
|
11409
11457
|
const platform = nativePlatform(), distribution = new Distribution(RELEASE_PUBLIC_KEYS);
|
package/data/install.ps1
CHANGED
|
@@ -9,7 +9,8 @@ param(
|
|
|
9
9
|
[switch]$Json,
|
|
10
10
|
[switch]$NoInit,
|
|
11
11
|
[switch]$NoPath,
|
|
12
|
-
[switch]$MigrateNpm
|
|
12
|
+
[switch]$MigrateNpm,
|
|
13
|
+
[switch]$Upgrade
|
|
13
14
|
)
|
|
14
15
|
Set-StrictMode -Version Latest
|
|
15
16
|
$ErrorActionPreference = 'Stop'
|
|
@@ -147,9 +148,38 @@ function Expand-NotifaiArchive([string]$Archive, [string]$Destination) {
|
|
|
147
148
|
}
|
|
148
149
|
} finally { $zip.Dispose() }
|
|
149
150
|
}
|
|
151
|
+
function Add-NotifaiBootstrapType([string]$Source) {
|
|
152
|
+
if ($PSVersionTable.PSEdition -ne 'Desktop') { Add-Type -TypeDefinition $Source -ErrorAction Stop; return }
|
|
153
|
+
# Framework CodeDom passes csc an ANSI environment block. Keep its temporary
|
|
154
|
+
# paths relative even when the User's profile/TEMP contains non-ANSI text.
|
|
155
|
+
# Only this synchronous compiler invocation changes process-local cwd/env.
|
|
156
|
+
$scratch = [IO.Path]::Combine([IO.Path]::GetTempPath(), 'notifai-compiler-' + [Guid]::NewGuid().ToString('N'))
|
|
157
|
+
New-NotifaiPrivateDirectory $scratch
|
|
158
|
+
$previousDirectory = [Environment]::CurrentDirectory
|
|
159
|
+
$previousTemp = $env:TEMP
|
|
160
|
+
$previousTmp = $env:TMP
|
|
161
|
+
$parameters = [CodeDom.Compiler.CompilerParameters]::new()
|
|
162
|
+
$parameters.GenerateInMemory = $true
|
|
163
|
+
[void]$parameters.ReferencedAssemblies.Add([ComponentModel.Win32Exception].Assembly.Location)
|
|
164
|
+
$parameters.TempFiles = [CodeDom.Compiler.TempFileCollection]::new('.', $false)
|
|
165
|
+
try {
|
|
166
|
+
[Environment]::CurrentDirectory = $scratch
|
|
167
|
+
$env:TEMP = '.'
|
|
168
|
+
$env:TMP = '.'
|
|
169
|
+
Add-Type -TypeDefinition $Source -CompilerParameters $parameters -ErrorAction Stop
|
|
170
|
+
} finally {
|
|
171
|
+
try { $parameters.TempFiles.Dispose() }
|
|
172
|
+
finally {
|
|
173
|
+
[Environment]::CurrentDirectory = $previousDirectory
|
|
174
|
+
$env:TEMP = $previousTemp
|
|
175
|
+
$env:TMP = $previousTmp
|
|
176
|
+
[IO.Directory]::Delete($scratch, $true)
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
150
180
|
function Get-NotifaiWindowsTarget {
|
|
151
181
|
if (-not ('NotifaiBootstrap.Native' -as [type])) {
|
|
152
|
-
Add-
|
|
182
|
+
Add-NotifaiBootstrapType @'
|
|
153
183
|
using System;
|
|
154
184
|
using System.Runtime.InteropServices;
|
|
155
185
|
namespace NotifaiBootstrap {
|
|
@@ -215,15 +245,113 @@ function Get-NotifaiAccountHome {
|
|
|
215
245
|
}
|
|
216
246
|
return $accountHome
|
|
217
247
|
}
|
|
248
|
+
# Read the descriptor and physical location through one non-following handle.
|
|
249
|
+
# Package capabilities restrict a User's access; they do not replace it.
|
|
250
|
+
# Only the registered package owning this current-User npm location is admitted.
|
|
251
|
+
function Get-NotifaiPathSecurity([string]$File, [bool]$Package) {
|
|
252
|
+
if (-not ('NotifaiBootstrap.PathSecurity' -as [type])) {
|
|
253
|
+
Add-NotifaiBootstrapType @'
|
|
254
|
+
using System;
|
|
255
|
+
using System.IO;
|
|
256
|
+
using System.Text;
|
|
257
|
+
using System.ComponentModel;
|
|
258
|
+
using System.Runtime.InteropServices;
|
|
259
|
+
using System.Security.AccessControl;
|
|
260
|
+
using System.Security.Principal;
|
|
261
|
+
using Microsoft.Win32.SafeHandles;
|
|
262
|
+
namespace NotifaiBootstrap {
|
|
263
|
+
public sealed class PathSecurity {
|
|
264
|
+
public RawSecurityDescriptor Descriptor;
|
|
265
|
+
public uint Attributes;
|
|
266
|
+
public string Capability;
|
|
267
|
+
[DllImport("kernel32.dll", CharSet=CharSet.Unicode, SetLastError=true)]
|
|
268
|
+
static extern SafeFileHandle CreateFile(string name, uint access, uint share, IntPtr security, uint disposition, uint flags, IntPtr template);
|
|
269
|
+
[DllImport("kernel32.dll", CharSet=CharSet.Unicode, SetLastError=true)]
|
|
270
|
+
static extern uint GetFinalPathNameByHandle(SafeFileHandle file, StringBuilder path, uint length, uint flags);
|
|
271
|
+
[DllImport("kernel32.dll", SetLastError=true)]
|
|
272
|
+
static extern bool GetFileInformationByHandleEx(SafeFileHandle file, int kind, out TagInfo info, uint size);
|
|
273
|
+
[DllImport("kernel32.dll")]
|
|
274
|
+
static extern uint GetFileType(SafeFileHandle file);
|
|
275
|
+
[StructLayout(LayoutKind.Sequential)] struct TagInfo { public uint Attributes; public uint Tag; }
|
|
276
|
+
[DllImport("advapi32.dll")]
|
|
277
|
+
static extern uint GetSecurityInfo(SafeFileHandle file, int kind, uint information, out IntPtr owner, out IntPtr group, out IntPtr dacl, out IntPtr sacl, out IntPtr descriptor);
|
|
278
|
+
[DllImport("advapi32.dll")]
|
|
279
|
+
static extern uint GetSecurityDescriptorLength(IntPtr descriptor);
|
|
280
|
+
[DllImport("kernel32.dll")]
|
|
281
|
+
static extern IntPtr LocalFree(IntPtr memory);
|
|
282
|
+
[DllImport("advapi32.dll")]
|
|
283
|
+
static extern IntPtr FreeSid(IntPtr sid);
|
|
284
|
+
[DllImport("userenv.dll", CharSet=CharSet.Unicode)]
|
|
285
|
+
static extern int DeriveAppContainerSidFromAppContainerName(string name, out IntPtr sid);
|
|
286
|
+
[DllImport("kernel32.dll", CharSet=CharSet.Unicode)]
|
|
287
|
+
static extern int GetPackagesByPackageFamily(string family, ref uint count, IntPtr names, ref uint size, IntPtr buffer);
|
|
288
|
+
static SafeFileHandle Open(string file, uint access) {
|
|
289
|
+
var handle = CreateFile(file, access, 7, IntPtr.Zero, 3, 0x02200000, IntPtr.Zero);
|
|
290
|
+
if (handle.IsInvalid) { handle.Dispose(); throw new Win32Exception(); }
|
|
291
|
+
return handle;
|
|
292
|
+
}
|
|
293
|
+
static string Physical(SafeFileHandle handle) {
|
|
294
|
+
var path = new StringBuilder(32768);
|
|
295
|
+
uint length = GetFinalPathNameByHandle(handle, path, 32768, 0);
|
|
296
|
+
if (length == 0 || length >= 32768) throw new Win32Exception();
|
|
297
|
+
return path.ToString();
|
|
298
|
+
}
|
|
299
|
+
static string PackageCapability(string physical) {
|
|
300
|
+
string home = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
|
|
301
|
+
string prefix;
|
|
302
|
+
using (var handle = Open(home, 0x80)) { prefix = Physical(handle).TrimEnd('\\') + @"\AppData\Local\Packages\"; }
|
|
303
|
+
if (!physical.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)) return null;
|
|
304
|
+
string relative = physical.Substring(prefix.Length);
|
|
305
|
+
int end = relative.IndexOf('\\');
|
|
306
|
+
if (end <= 0 || end > 255) return null;
|
|
307
|
+
string family = relative.Substring(0, end), tail = relative.Substring(end);
|
|
308
|
+
const string npm = @"\LocalCache\Roaming\npm";
|
|
309
|
+
if (!tail.Equals(npm, StringComparison.OrdinalIgnoreCase) && !tail.StartsWith(npm + @"\", StringComparison.OrdinalIgnoreCase)) return null;
|
|
310
|
+
uint count = 0, size = 0;
|
|
311
|
+
if (GetPackagesByPackageFamily(family, ref count, IntPtr.Zero, ref size, IntPtr.Zero) != 122 || count == 0 || size == 0) return null;
|
|
312
|
+
IntPtr pointer;
|
|
313
|
+
if (DeriveAppContainerSidFromAppContainerName(family, out pointer) != 0) return null;
|
|
314
|
+
try {
|
|
315
|
+
var sid = new SecurityIdentifier(pointer);
|
|
316
|
+
byte[] bytes = new byte[sid.BinaryLength]; sid.GetBinaryForm(bytes, 0);
|
|
317
|
+
if (bytes.Length != 40 || bytes[1] != 8 || BitConverter.ToUInt32(bytes, 8) != 2) return null;
|
|
318
|
+
bytes[8] = 3;
|
|
319
|
+
return new SecurityIdentifier(bytes, 0).Value;
|
|
320
|
+
} finally { FreeSid(pointer); }
|
|
321
|
+
}
|
|
322
|
+
public static PathSecurity Read(string file, bool package) {
|
|
323
|
+
using (var handle = Open(file, 0x20080)) {
|
|
324
|
+
TagInfo info;
|
|
325
|
+
if (GetFileType(handle) != 1 || !GetFileInformationByHandleEx(handle, 9, out info, 8) || (info.Attributes & 0x400) != 0) throw new IOException("Existing path is linked or not a disk object");
|
|
326
|
+
IntPtr owner, group, dacl, sacl, descriptor;
|
|
327
|
+
uint error = GetSecurityInfo(handle, 1, 5, out owner, out group, out dacl, out sacl, out descriptor);
|
|
328
|
+
if (error != 0) throw new Win32Exception((int)error);
|
|
329
|
+
try {
|
|
330
|
+
uint length = GetSecurityDescriptorLength(descriptor);
|
|
331
|
+
if (length == 0 || length > 1024 * 1024) throw new IOException("Invalid path security descriptor");
|
|
332
|
+
byte[] bytes = new byte[length]; Marshal.Copy(descriptor, bytes, 0, bytes.Length);
|
|
333
|
+
return new PathSecurity { Descriptor = new RawSecurityDescriptor(bytes, 0), Attributes = info.Attributes,
|
|
334
|
+
Capability = package ? PackageCapability(Physical(handle)) : null };
|
|
335
|
+
} finally { LocalFree(descriptor); }
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
'@
|
|
341
|
+
}
|
|
342
|
+
return [NotifaiBootstrap.PathSecurity]::Read($File, $Package)
|
|
343
|
+
}
|
|
218
344
|
# Read-only inspection of an existing path. npm can inherit a token's default
|
|
219
345
|
# owner. The OS-confirmed profile can belong to Windows itself; this exception
|
|
220
346
|
# must never admit a system-owned npm package or managed installation path.
|
|
221
347
|
function Assert-NotifaiPathAccess([string]$File, [switch]$AllowDefaultOwner, [switch]$RequireProtected, [switch]$AccountHome) {
|
|
222
348
|
$identity = [Security.Principal.WindowsIdentity]::GetCurrent()
|
|
223
349
|
$user = $identity.User.Value
|
|
224
|
-
$
|
|
225
|
-
$
|
|
226
|
-
$
|
|
350
|
+
$security = Get-NotifaiPathSecurity $File $AllowDefaultOwner
|
|
351
|
+
$attributes = [IO.FileAttributes]$security.Attributes
|
|
352
|
+
$acl = $security.Descriptor
|
|
353
|
+
if ($null -eq $acl.Owner -or $null -eq $acl.DiscretionaryAcl) { throw 'Existing path has no owner or discretionary access control' }
|
|
354
|
+
$owner = $acl.Owner.Value
|
|
227
355
|
$defaultOwner = $AllowDefaultOwner -and $identity.Owner.Value -eq 'S-1-5-32-544' -and $owner -eq $identity.Owner.Value
|
|
228
356
|
$profileOwner = $false
|
|
229
357
|
if ($AccountHome) {
|
|
@@ -234,12 +362,13 @@ function Assert-NotifaiPathAccess([string]$File, [switch]$AllowDefaultOwner, [sw
|
|
|
234
362
|
}
|
|
235
363
|
if (($attributes -band [IO.FileAttributes]::ReparsePoint) -ne 0 -or
|
|
236
364
|
($owner -ne $user -and -not $defaultOwner -and -not $profileOwner) -or
|
|
237
|
-
($RequireProtected -and
|
|
365
|
+
($RequireProtected -and ($acl.ControlFlags -band [Security.AccessControl.ControlFlags]::DiscretionaryAclProtected) -eq 0)) { throw 'Existing path is not privately owned; inspect it before repair' }
|
|
238
366
|
$writes = [int64][Security.AccessControl.FileSystemRights]'Write, Delete, DeleteSubdirectoriesAndFiles, ChangePermissions, TakeOwnership' -bor 0x50000000
|
|
239
|
-
foreach ($rule in $acl.
|
|
240
|
-
if ($rule.
|
|
241
|
-
|
|
242
|
-
|
|
367
|
+
foreach ($rule in $acl.DiscretionaryAcl) {
|
|
368
|
+
if ($rule.AceType -eq [Security.AccessControl.AceType]::AccessDenied) { continue }
|
|
369
|
+
if ($rule.AceType -ne [Security.AccessControl.AceType]::AccessAllowed) { throw 'Existing path has unsupported access rules' }
|
|
370
|
+
if (([int64]$rule.AccessMask -band $writes) -ne 0 -and
|
|
371
|
+
$rule.SecurityIdentifier.Value -notin @($user, 'S-1-5-18', 'S-1-5-32-544', $security.Capability)) { throw 'Existing path permits another writer; inspect it before repair' }
|
|
243
372
|
}
|
|
244
373
|
}
|
|
245
374
|
function Get-NotifaiInstalledCommand {
|
|
@@ -264,13 +393,15 @@ function Get-NotifaiInstallArguments {
|
|
|
264
393
|
if ($NoInit) { $nativeArgs += '--no-init' }
|
|
265
394
|
if ($NoPath) { $nativeArgs += '--no-path' }
|
|
266
395
|
if ($MigrateNpm) { $nativeArgs += '--migrate-npm' }
|
|
396
|
+
if ($Upgrade) { $nativeArgs += '--upgrade' }
|
|
267
397
|
return $nativeArgs
|
|
268
398
|
}
|
|
269
399
|
function Invoke-NotifaiBootstrap {
|
|
270
400
|
$selectedChannel = if ($Channel) { $Channel } else { 'stable' }
|
|
271
401
|
if ($Version -and -not (Test-NotifaiVersion $Version)) { throw 'Version must be an exact semantic version' }
|
|
402
|
+
if ($Upgrade -and (-not $Version -or -not $Channel -or -not $NoInit -or -not $NoPath)) { throw 'Upgrade requires exact version, channel, no-init and no-path' }
|
|
272
403
|
$existing = Get-NotifaiInstalledCommand
|
|
273
|
-
if ($existing) {
|
|
404
|
+
if ($existing -and -not $Upgrade) {
|
|
274
405
|
Invoke-NotifaiCandidate $existing (Get-NotifaiInstallArguments)
|
|
275
406
|
return
|
|
276
407
|
}
|
package/data/release.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":"12.0.
|
|
1
|
+
{"version":"12.0.1","source_revision":"94729846f336fd6610123864096cb950889d969e"}
|
package/inventory.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"key_id":"notifai-release-2026-10","payload":"eyJzY2hlbWEiOjEsInZlcnNpb24iOiIxMi4wLjAtYmV0YS44Iiwic291cmNlX3JldmlzaW9uIjoiYzVhODU1MjAwYTNhYzg1ODJlYTFhYTBmNWQxMzcwNDBmZWZkYjQ5ZSIsInN0b3JlX3NjaGVtYSI6MSwibGF1bmNoZXJfc2NoZW1hIjoxLCJhcnRpZmFjdHMiOlt7InRhcmdldCI6ImJ1bi1kYXJ3aW4tYXJtNjQiLCJmaWxlbmFtZSI6Im5vdGlmYWktMTIuMC4wLWJldGEuOC1kYXJ3aW4tYXJtNjQudGFyLmd6IiwiYnl0ZXMiOjI3NzY0NDA1LCJzaGEyNTYiOiIxYTczYWFmZGEyMjdjNTIxODAwZjJhN2RlZDM5M2MwYzBhODhkNjkyYTM2NTE4NDY2MzIyZjAxNTM1YmY0MWEzIiwicnVudGltZV9zaGEyNTYiOiI3YzVhOTNkZmJmMTFiZjMzNjZiZjgwYWM1ZjkyZTk4ZDBhNTY4OGFhODk1ODFiOTBjOTY5NDIzYjI5ZDI3NmFlIiwibGF1bmNoZXJfc2hhMjU2IjoiZGVjMmMzMmU1MTFmOWNlYzdlOGQ2OGFjM2Q4M2Q0ZDUzNGY1ODQ0Mjg2OTVkMzA3NjMyNTQ0M2YyMWVlMjEyNiIsIm1hdGVyaWFscyI6W3sicGF0aCI6IkJVTi1MSUNFTlNFLm1kIiwiYnl0ZXMiOjU2MTMsInNoYTI1NiI6ImI5Y2FmNTI3Mjg2OTFiNDA1N2UzNzEyMzJjMjIxYTEzMjg4MzE5OGJlMmYzZDJkZGY5MmM5MDQwNGM5ODRiMWEifSx7InBhdGgiOiJDT1JSRVNQT05ESU5HLVNPVVJDRVMuanNvbiIsImJ5dGVzIjoyMDIwLCJzaGEyNTYiOiJmYTRjMzQ0ODAxMTU0ODcyZDYxNzllZTJlZjQ5OTIzZGM5Zjg5MDllZjAxZTUzYjg2ZThmNTdjNjI1ODIzMjc0In0seyJwYXRoIjoiTElDRU5TRS50eHQiLCJieXRlcyI6MTEzNDYsInNoYTI1NiI6Ijk0NGMxM2ZmMGZlNzk1ZTI5MWZkMWM0OTQ3M2Y5OGQ0ZmRmMWY3NDYzOGUwMWY4ODI3NjljZDRjYWU3OGI3M2QifSx7InBhdGgiOiJOT1RJQ0UtUFJPVkVOQU5DRS5qc29uIiwiYnl0ZXMiOjQ1MDI2NCwic2hhMjU2IjoiNTM0ZGQ1OWZkNGMxNWRkMTM4MmU4MjdmMGI4NWMxOWY3YzY5OGUyMzVmOTI5OWVhYTIwMmRiNTQwMDgzNDI4OCJ9LHsicGF0aCI6Ik5PVElDRS50eHQiLCJieXRlcyI6NjI2LCJzaGEyNTYiOiIxZGZiZjQ0OThkYzAyNmIyMDU5YzBiMGI1ZWI1ZmExZDgyYWUzMzRlNThmZjExZTdjMjk3MzMzMjdmMjVjNGViIn0seyJwYXRoIjoiUkVCVUlMRElORy5tZCIsImJ5dGVzIjozODQyLCJzaGEyNTYiOiJjZTYwNWI1ZmRiMDMxOTMzOWY5ZjgzZjJmZTdjY2NiYzdlNTcyNmZkZjQ5NGRhNmUyODQzM2JlZjgyOWViMGJlIn0seyJwYXRoIjoiU09VUkNFLU5PVElDRVMudHh0IiwiYnl0ZXMiOjkwMTc3NzEsInNoYTI1NiI6Ijg5OTc2YmVjYzI1NjU0MGU2ZDJlODA3YjQ3YTRlMDVlODg5OTgyYzA2MjJmYzA0NDEzYTdiZjdlNzdhNzdlMzcifSx7InBhdGgiOiJUSElSRC1QQVJUWS1OT1RJQ0VTLnR4dCIsImJ5dGVzIjoyNDkxNDk2LCJzaGEyNTYiOiIxMTY0NDdlZmY3Nzg5MzUxMTc5N2VmNDc2MDExZGVjODAwMjI0ZjkxZTMzNDJlM2Q2NTcwNzA4NzEyYjRiNzcyIn0seyJwYXRoIjoibGljZW5zZXMvbnBtLWNtZC1zaGltLnR4dCIsImJ5dGVzIjo4MTMsInNoYTI1NiI6ImFmZmZkZjEyMDgxMTIyNzQ5YzRiNzFjNWIxYzExYmM2NTlkNzkyNDJkMTllMThmNWU4ZGJhYjA0YTQ1ZTM2YmIifSx7InBhdGgiOiJucG0tYWRhcHRlci1maWxlcy5qc29uIiwiYnl0ZXMiOjE1MjEsInNoYTI1NiI6IjEyNTE2N2FiYjk3MTA0Zjc4NmYyNTUwMTAxZWI3MjdkM2ZlMDQyMGZmMjQ2YTJmYjM5ZTNjMzdlMzIzZjgyYjMifV19LHsidGFyZ2V0IjoiYnVuLWRhcndpbi14NjQiLCJmaWxlbmFtZSI6Im5vdGlmYWktMTIuMC4wLWJldGEuOC1kYXJ3aW4teDY0LnRhci5neiIsImJ5dGVzIjozMDAwMTM4MCwic2hhMjU2IjoiODA2MTVmZGY4YTcyYTdiMTc0MjI4OWI3ODljNTI3NmFjZDliMTQ0N2FlNWQxODdlNzQ2MDU1YzYyYzdjNDI1OCIsInJ1bnRpbWVfc2hhMjU2IjoiOGVlMmU0YzUxZWJmZWExMDUzZDU4YzUyODU0NWIwODRkNWYzZjExNTQwYmVkYzNiNDFlMzhmNWFmMzgzNWRlNCIsImxhdW5jaGVyX3NoYTI1NiI6IjE2Y2RhNTNjYmIxMDA3ODkzMDA2ZDE2YzI4N2U3Mzc1NzRkYWQ5ZWU5OTcwNjIxNWNmZWFhOTg0YjE2ZjMyYWIiLCJtYXRlcmlhbHMiOlt7InBhdGgiOiJCVU4tTElDRU5TRS5tZCIsImJ5dGVzIjo1NjEzLCJzaGEyNTYiOiJiOWNhZjUyNzI4NjkxYjQwNTdlMzcxMjMyYzIyMWExMzI4ODMxOThiZTJmM2QyZGRmOTJjOTA0MDRjOTg0YjFhIn0seyJwYXRoIjoiQ09SUkVTUE9ORElORy1TT1VSQ0VTLmpzb24iLCJieXRlcyI6MjAyMCwic2hhMjU2IjoiZmE0YzM0NDgwMTE1NDg3MmQ2MTc5ZWUyZWY0OTkyM2RjOWY4OTA5ZWYwMWU1M2I4NmU4ZjU3YzYyNTgyMzI3NCJ9LHsicGF0aCI6IkxJQ0VOU0UudHh0IiwiYnl0ZXMiOjExMzQ2LCJzaGEyNTYiOiI5NDRjMTNmZjBmZTc5NWUyOTFmZDFjNDk0NzNmOThkNGZkZjFmNzQ2MzhlMDFmODgyNzY5Y2Q0Y2FlNzhiNzNkIn0seyJwYXRoIjoiTk9USUNFLVBST1ZFTkFOQ0UuanNvbiIsImJ5dGVzIjo0NTAyNjQsInNoYTI1NiI6IjUzNGRkNTlmZDRjMTVkZDEzODJlODI3ZjBiODVjMTlmN2M2OThlMjM1ZjkyOTllYWEyMDJkYjU0MDA4MzQyODgifSx7InBhdGgiOiJOT1RJQ0UudHh0IiwiYnl0ZXMiOjYyNiwic2hhMjU2IjoiMWRmYmY0NDk4ZGMwMjZiMjA1OWMwYjBiNWViNWZhMWQ4MmFlMzM0ZTU4ZmYxMWU3YzI5NzMzMzI3ZjI1YzRlYiJ9LHsicGF0aCI6IlJFQlVJTERJTkcubWQiLCJieXRlcyI6Mzg0Miwic2hhMjU2IjoiY2U2MDViNWZkYjAzMTkzMzlmOWY4M2YyZmU3Y2NjYmM3ZTU3MjZmZGY0OTRkYTZlMjg0MzNiZWY4MjllYjBiZSJ9LHsicGF0aCI6IlNPVVJDRS1OT1RJQ0VTLnR4dCIsImJ5dGVzIjo5MDE3NzcxLCJzaGEyNTYiOiI4OTk3NmJlY2MyNTY1NDBlNmQyZTgwN2I0N2E0ZTA1ZTg4OTk4MmMwNjIyZmMwNDQxM2E3YmY3ZTc3YTc3ZTM3In0seyJwYXRoIjoiVEhJUkQtUEFSVFktTk9USUNFUy50eHQiLCJieXRlcyI6MjQ5MTQ5Niwic2hhMjU2IjoiMTE2NDQ3ZWZmNzc4OTM1MTE3OTdlZjQ3NjAxMWRlYzgwMDIyNGY5MWUzMzQyZTNkNjU3MDcwODcxMmI0Yjc3MiJ9LHsicGF0aCI6ImxpY2Vuc2VzL25wbS1jbWQtc2hpbS50eHQiLCJieXRlcyI6ODEzLCJzaGEyNTYiOiJhZmZmZGYxMjA4MTEyMjc0OWM0YjcxYzViMWMxMWJjNjU5ZDc5MjQyZDE5ZTE4ZjVlOGRiYWIwNGE0NWUzNmJiIn0seyJwYXRoIjoibnBtLWFkYXB0ZXItZmlsZXMuanNvbiIsImJ5dGVzIjoxNTIxLCJzaGEyNTYiOiIxMjUxNjdhYmI5NzEwNGY3ODZmMjU1MDEwMWViNzI3ZDNmZTA0MjBmZjI0NmEyZmIzOWUzYzM3ZTMyM2Y4MmIzIn1dfSx7InRhcmdldCI6ImJ1bi1saW51eC1hcm02NCIsImZpbGVuYW1lIjoibm90aWZhaS0xMi4wLjAtYmV0YS44LWxpbnV4LWFybTY0LnRhci5neiIsImJ5dGVzIjozOTMxMjAyNiwic2hhMjU2IjoiZDFmYjdjYTEzYTRjZjQ3ZmU2ZTI2MGExZjZmYWQxMzg2OWY4NjhiYWE2YWY1NzBiZDNlMGU3ODE5MDczNWIxYSIsInJ1bnRpbWVfc2hhMjU2IjoiM2IxM2Y3OTM5MmEyNTFmNjliMmVkMTdmNmY5ZTY4YWY2YmJmZTcxNmQxOTNjY2RhYjg4YWY2M2YxOGZiNDRhYyIsImxhdW5jaGVyX3NoYTI1NiI6ImMxOWUzMzJjODIxYjcxMjhjYjI1ZjYxZTRhYjdlMGIzYzYzMzQ1ZjA0ZTJhYjVhYjk1ZDQ1MWE0YTZmYmRjNDUiLCJtYXRlcmlhbHMiOlt7InBhdGgiOiJCVU4tTElDRU5TRS5tZCIsImJ5dGVzIjo1NjEzLCJzaGEyNTYiOiJiOWNhZjUyNzI4NjkxYjQwNTdlMzcxMjMyYzIyMWExMzI4ODMxOThiZTJmM2QyZGRmOTJjOTA0MDRjOTg0YjFhIn0seyJwYXRoIjoiQ09SUkVTUE9ORElORy1TT1VSQ0VTLmpzb24iLCJieXRlcyI6MjAyMCwic2hhMjU2IjoiZmE0YzM0NDgwMTE1NDg3MmQ2MTc5ZWUyZWY0OTkyM2RjOWY4OTA5ZWYwMWU1M2I4NmU4ZjU3YzYyNTgyMzI3NCJ9LHsicGF0aCI6IkxJQ0VOU0UudHh0IiwiYnl0ZXMiOjExMzQ2LCJzaGEyNTYiOiI5NDRjMTNmZjBmZTc5NWUyOTFmZDFjNDk0NzNmOThkNGZkZjFmNzQ2MzhlMDFmODgyNzY5Y2Q0Y2FlNzhiNzNkIn0seyJwYXRoIjoiTk9USUNFLVBST1ZFTkFOQ0UuanNvbiIsImJ5dGVzIjo0NTAyNjQsInNoYTI1NiI6IjUzNGRkNTlmZDRjMTVkZDEzODJlODI3ZjBiODVjMTlmN2M2OThlMjM1ZjkyOTllYWEyMDJkYjU0MDA4MzQyODgifSx7InBhdGgiOiJOT1RJQ0UudHh0IiwiYnl0ZXMiOjYyNiwic2hhMjU2IjoiMWRmYmY0NDk4ZGMwMjZiMjA1OWMwYjBiNWViNWZhMWQ4MmFlMzM0ZTU4ZmYxMWU3YzI5NzMzMzI3ZjI1YzRlYiJ9LHsicGF0aCI6IlJFQlVJTERJTkcubWQiLCJieXRlcyI6Mzg0Miwic2hhMjU2IjoiY2U2MDViNWZkYjAzMTkzMzlmOWY4M2YyZmU3Y2NjYmM3ZTU3MjZmZGY0OTRkYTZlMjg0MzNiZWY4MjllYjBiZSJ9LHsicGF0aCI6IlNPVVJDRS1OT1RJQ0VTLnR4dCIsImJ5dGVzIjo5MDE3NzcxLCJzaGEyNTYiOiI4OTk3NmJlY2MyNTY1NDBlNmQyZTgwN2I0N2E0ZTA1ZTg4OTk4MmMwNjIyZmMwNDQxM2E3YmY3ZTc3YTc3ZTM3In0seyJwYXRoIjoiVEhJUkQtUEFSVFktTk9USUNFUy50eHQiLCJieXRlcyI6MjQ5MTQ5Niwic2hhMjU2IjoiMTE2NDQ3ZWZmNzc4OTM1MTE3OTdlZjQ3NjAxMWRlYzgwMDIyNGY5MWUzMzQyZTNkNjU3MDcwODcxMmI0Yjc3MiJ9LHsicGF0aCI6ImxpY2Vuc2VzL25wbS1jbWQtc2hpbS50eHQiLCJieXRlcyI6ODEzLCJzaGEyNTYiOiJhZmZmZGYxMjA4MTEyMjc0OWM0YjcxYzViMWMxMWJjNjU5ZDc5MjQyZDE5ZTE4ZjVlOGRiYWIwNGE0NWUzNmJiIn0seyJwYXRoIjoibnBtLWFkYXB0ZXItZmlsZXMuanNvbiIsImJ5dGVzIjoxNTIxLCJzaGEyNTYiOiIxMjUxNjdhYmI5NzEwNGY3ODZmMjU1MDEwMWViNzI3ZDNmZTA0MjBmZjI0NmEyZmIzOWUzYzM3ZTMyM2Y4MmIzIn1dfSx7InRhcmdldCI6ImJ1bi1saW51eC14NjQiLCJmaWxlbmFtZSI6Im5vdGlmYWktMTIuMC4wLWJldGEuOC1saW51eC14NjQudGFyLmd6IiwiYnl0ZXMiOjM4ODc1NDc4LCJzaGEyNTYiOiJmYjUzY2ViY2I3YmFiNjVlYWE1MzI4ZThiODVjYWJkNDhlMjU1NGQwODIwZmM2Nzg5YzQ5YzBiZDg3YzE2ZDNjIiwicnVudGltZV9zaGEyNTYiOiI5ZGY0NTAyZDNiYzE1YTYwNmRmZWVkYWUyMzliYzA1MjZkYTk3NzdlZDY3MGMwNzdkZjcxZTkxNGU4YzNkNjMzIiwibGF1bmNoZXJfc2hhMjU2IjoiYmRmOGQ0N2RmODU4MWFjZTI5YjU3OTA0NTdjYmM2YzI2ZDEyYjNjYjE0YzBkZGFiMzM3OWE3Mjc1ZDllYTRiMSIsIm1hdGVyaWFscyI6W3sicGF0aCI6IkJVTi1MSUNFTlNFLm1kIiwiYnl0ZXMiOjU2MTMsInNoYTI1NiI6ImI5Y2FmNTI3Mjg2OTFiNDA1N2UzNzEyMzJjMjIxYTEzMjg4MzE5OGJlMmYzZDJkZGY5MmM5MDQwNGM5ODRiMWEifSx7InBhdGgiOiJDT1JSRVNQT05ESU5HLVNPVVJDRVMuanNvbiIsImJ5dGVzIjoyMDIwLCJzaGEyNTYiOiJmYTRjMzQ0ODAxMTU0ODcyZDYxNzllZTJlZjQ5OTIzZGM5Zjg5MDllZjAxZTUzYjg2ZThmNTdjNjI1ODIzMjc0In0seyJwYXRoIjoiTElDRU5TRS50eHQiLCJieXRlcyI6MTEzNDYsInNoYTI1NiI6Ijk0NGMxM2ZmMGZlNzk1ZTI5MWZkMWM0OTQ3M2Y5OGQ0ZmRmMWY3NDYzOGUwMWY4ODI3NjljZDRjYWU3OGI3M2QifSx7InBhdGgiOiJOT1RJQ0UtUFJPVkVOQU5DRS5qc29uIiwiYnl0ZXMiOjQ1MDI2NCwic2hhMjU2IjoiNTM0ZGQ1OWZkNGMxNWRkMTM4MmU4MjdmMGI4NWMxOWY3YzY5OGUyMzVmOTI5OWVhYTIwMmRiNTQwMDgzNDI4OCJ9LHsicGF0aCI6Ik5PVElDRS50eHQiLCJieXRlcyI6NjI2LCJzaGEyNTYiOiIxZGZiZjQ0OThkYzAyNmIyMDU5YzBiMGI1ZWI1ZmExZDgyYWUzMzRlNThmZjExZTdjMjk3MzMzMjdmMjVjNGViIn0seyJwYXRoIjoiUkVCVUlMRElORy5tZCIsImJ5dGVzIjozODQyLCJzaGEyNTYiOiJjZTYwNWI1ZmRiMDMxOTMzOWY5ZjgzZjJmZTdjY2NiYzdlNTcyNmZkZjQ5NGRhNmUyODQzM2JlZjgyOWViMGJlIn0seyJwYXRoIjoiU09VUkNFLU5PVElDRVMudHh0IiwiYnl0ZXMiOjkwMTc3NzEsInNoYTI1NiI6Ijg5OTc2YmVjYzI1NjU0MGU2ZDJlODA3YjQ3YTRlMDVlODg5OTgyYzA2MjJmYzA0NDEzYTdiZjdlNzdhNzdlMzcifSx7InBhdGgiOiJUSElSRC1QQVJUWS1OT1RJQ0VTLnR4dCIsImJ5dGVzIjoyNDkxNDk2LCJzaGEyNTYiOiIxMTY0NDdlZmY3Nzg5MzUxMTc5N2VmNDc2MDExZGVjODAwMjI0ZjkxZTMzNDJlM2Q2NTcwNzA4NzEyYjRiNzcyIn0seyJwYXRoIjoibGljZW5zZXMvbnBtLWNtZC1zaGltLnR4dCIsImJ5dGVzIjo4MTMsInNoYTI1NiI6ImFmZmZkZjEyMDgxMTIyNzQ5YzRiNzFjNWIxYzExYmM2NTlkNzkyNDJkMTllMThmNWU4ZGJhYjA0YTQ1ZTM2YmIifSx7InBhdGgiOiJucG0tYWRhcHRlci1maWxlcy5qc29uIiwiYnl0ZXMiOjE1MjEsInNoYTI1NiI6IjEyNTE2N2FiYjk3MTA0Zjc4NmYyNTUwMTAxZWI3MjdkM2ZlMDQyMGZmMjQ2YTJmYjM5ZTNjMzdlMzIzZjgyYjMifV19LHsidGFyZ2V0IjoiYnVuLXdpbmRvd3MtYXJtNjQiLCJmaWxlbmFtZSI6Im5vdGlmYWktMTIuMC4wLWJldGEuOC13aW5kb3dzLWFybTY0LnppcCIsImJ5dGVzIjozODcwNjI0MSwic2hhMjU2IjoiNWI3MDVmMmYxZGQwNmQzYTc1NTU2ZWQ4MTE3Mjc5MjhjNDk0YzU0ZWE4MjU4NjRlMTMwNGQwMGMyZWU4MDRlNSIsInJ1bnRpbWVfc2hhMjU2IjoiYmFiODdhOTBiMDIxNzg4ODJlMjI0NmFhNDE2ZmI4OTFhZjBjMjFhMzhiN2ZhNTJkNzBhZmM4NDI0ZjcyNmIyYiIsImxhdW5jaGVyX3NoYTI1NiI6IjNmMTZkOThkZDAwZmNkYWNlNWY3MmM1YjkzMzEwNTVjMWNlMzQ4OWQ2NzVmYzcyZTc1ODZiMmI1M2UyYTBlNDUiLCJtYXRlcmlhbHMiOlt7InBhdGgiOiJCVU4tTElDRU5TRS5tZCIsImJ5dGVzIjo1NjEzLCJzaGEyNTYiOiJiOWNhZjUyNzI4NjkxYjQwNTdlMzcxMjMyYzIyMWExMzI4ODMxOThiZTJmM2QyZGRmOTJjOTA0MDRjOTg0YjFhIn0seyJwYXRoIjoiQ09SUkVTUE9ORElORy1TT1VSQ0VTLmpzb24iLCJieXRlcyI6MjAyMCwic2hhMjU2IjoiZmE0YzM0NDgwMTE1NDg3MmQ2MTc5ZWUyZWY0OTkyM2RjOWY4OTA5ZWYwMWU1M2I4NmU4ZjU3YzYyNTgyMzI3NCJ9LHsicGF0aCI6IkxJQ0VOU0UudHh0IiwiYnl0ZXMiOjExMzQ2LCJzaGEyNTYiOiI5NDRjMTNmZjBmZTc5NWUyOTFmZDFjNDk0NzNmOThkNGZkZjFmNzQ2MzhlMDFmODgyNzY5Y2Q0Y2FlNzhiNzNkIn0seyJwYXRoIjoiTk9USUNFLVBST1ZFTkFOQ0UuanNvbiIsImJ5dGVzIjo0NTAyNjQsInNoYTI1NiI6IjUzNGRkNTlmZDRjMTVkZDEzODJlODI3ZjBiODVjMTlmN2M2OThlMjM1ZjkyOTllYWEyMDJkYjU0MDA4MzQyODgifSx7InBhdGgiOiJOT1RJQ0UudHh0IiwiYnl0ZXMiOjYyNiwic2hhMjU2IjoiMWRmYmY0NDk4ZGMwMjZiMjA1OWMwYjBiNWViNWZhMWQ4MmFlMzM0ZTU4ZmYxMWU3YzI5NzMzMzI3ZjI1YzRlYiJ9LHsicGF0aCI6IlJFQlVJTERJTkcubWQiLCJieXRlcyI6Mzg0Miwic2hhMjU2IjoiY2U2MDViNWZkYjAzMTkzMzlmOWY4M2YyZmU3Y2NjYmM3ZTU3MjZmZGY0OTRkYTZlMjg0MzNiZWY4MjllYjBiZSJ9LHsicGF0aCI6IlNPVVJDRS1OT1RJQ0VTLnR4dCIsImJ5dGVzIjo5MDE3NzcxLCJzaGEyNTYiOiI4OTk3NmJlY2MyNTY1NDBlNmQyZTgwN2I0N2E0ZTA1ZTg4OTk4MmMwNjIyZmMwNDQxM2E3YmY3ZTc3YTc3ZTM3In0seyJwYXRoIjoiVEhJUkQtUEFSVFktTk9USUNFUy50eHQiLCJieXRlcyI6MjQ5MTQ5Niwic2hhMjU2IjoiMTE2NDQ3ZWZmNzc4OTM1MTE3OTdlZjQ3NjAxMWRlYzgwMDIyNGY5MWUzMzQyZTNkNjU3MDcwODcxMmI0Yjc3MiJ9LHsicGF0aCI6ImxpY2Vuc2VzL25wbS1jbWQtc2hpbS50eHQiLCJieXRlcyI6ODEzLCJzaGEyNTYiOiJhZmZmZGYxMjA4MTEyMjc0OWM0YjcxYzViMWMxMWJjNjU5ZDc5MjQyZDE5ZTE4ZjVlOGRiYWIwNGE0NWUzNmJiIn0seyJwYXRoIjoibnBtLWFkYXB0ZXItZmlsZXMuanNvbiIsImJ5dGVzIjoxNTIxLCJzaGEyNTYiOiIxMjUxNjdhYmI5NzEwNGY3ODZmMjU1MDEwMWViNzI3ZDNmZTA0MjBmZjI0NmEyZmIzOWUzYzM3ZTMyM2Y4MmIzIn1dfSx7InRhcmdldCI6ImJ1bi13aW5kb3dzLXg2NCIsImZpbGVuYW1lIjoibm90aWZhaS0xMi4wLjAtYmV0YS44LXdpbmRvd3MteDY0LnppcCIsImJ5dGVzIjo0MTg1MjAyOSwic2hhMjU2IjoiMjlhYTQ3ZmM4ZjRmNmVhNTQ1YmZjZjllNTI5NDQ3OTE4YTU4ZTk2NjZhZWY4ODEwZDZjY2ExMzhmYzFkZDNlZCIsInJ1bnRpbWVfc2hhMjU2IjoiNmFjMTAxZGY2YTczNmZjNzExYzg4ODk5YzhlNDBiZDMyZGMzZWM2YzBiM2Q0MmZjMjhjOTFhZDVhMTgyN2UyYiIsImxhdW5jaGVyX3NoYTI1NiI6IjcxYzlmMDlkYTZmMDgzMzUzMWE3ZDhkNmNjY2YwNDI3OTcxOTQzMTQ2ZTQ3NDlkYzJkZGNkMGJiODhlYjgwMGYiLCJtYXRlcmlhbHMiOlt7InBhdGgiOiJCVU4tTElDRU5TRS5tZCIsImJ5dGVzIjo1NjEzLCJzaGEyNTYiOiJiOWNhZjUyNzI4NjkxYjQwNTdlMzcxMjMyYzIyMWExMzI4ODMxOThiZTJmM2QyZGRmOTJjOTA0MDRjOTg0YjFhIn0seyJwYXRoIjoiQ09SUkVTUE9ORElORy1TT1VSQ0VTLmpzb24iLCJieXRlcyI6MjAyMCwic2hhMjU2IjoiZmE0YzM0NDgwMTE1NDg3MmQ2MTc5ZWUyZWY0OTkyM2RjOWY4OTA5ZWYwMWU1M2I4NmU4ZjU3YzYyNTgyMzI3NCJ9LHsicGF0aCI6IkxJQ0VOU0UudHh0IiwiYnl0ZXMiOjExMzQ2LCJzaGEyNTYiOiI5NDRjMTNmZjBmZTc5NWUyOTFmZDFjNDk0NzNmOThkNGZkZjFmNzQ2MzhlMDFmODgyNzY5Y2Q0Y2FlNzhiNzNkIn0seyJwYXRoIjoiTk9USUNFLVBST1ZFTkFOQ0UuanNvbiIsImJ5dGVzIjo0NTAyNjQsInNoYTI1NiI6IjUzNGRkNTlmZDRjMTVkZDEzODJlODI3ZjBiODVjMTlmN2M2OThlMjM1ZjkyOTllYWEyMDJkYjU0MDA4MzQyODgifSx7InBhdGgiOiJOT1RJQ0UudHh0IiwiYnl0ZXMiOjYyNiwic2hhMjU2IjoiMWRmYmY0NDk4ZGMwMjZiMjA1OWMwYjBiNWViNWZhMWQ4MmFlMzM0ZTU4ZmYxMWU3YzI5NzMzMzI3ZjI1YzRlYiJ9LHsicGF0aCI6IlJFQlVJTERJTkcubWQiLCJieXRlcyI6Mzg0Miwic2hhMjU2IjoiY2U2MDViNWZkYjAzMTkzMzlmOWY4M2YyZmU3Y2NjYmM3ZTU3MjZmZGY0OTRkYTZlMjg0MzNiZWY4MjllYjBiZSJ9LHsicGF0aCI6IlNPVVJDRS1OT1RJQ0VTLnR4dCIsImJ5dGVzIjo5MDE3NzcxLCJzaGEyNTYiOiI4OTk3NmJlY2MyNTY1NDBlNmQyZTgwN2I0N2E0ZTA1ZTg4OTk4MmMwNjIyZmMwNDQxM2E3YmY3ZTc3YTc3ZTM3In0seyJwYXRoIjoiVEhJUkQtUEFSVFktTk9USUNFUy50eHQiLCJieXRlcyI6MjQ5MTQ5Niwic2hhMjU2IjoiMTE2NDQ3ZWZmNzc4OTM1MTE3OTdlZjQ3NjAxMWRlYzgwMDIyNGY5MWUzMzQyZTNkNjU3MDcwODcxMmI0Yjc3MiJ9LHsicGF0aCI6ImxpY2Vuc2VzL25wbS1jbWQtc2hpbS50eHQiLCJieXRlcyI6ODEzLCJzaGEyNTYiOiJhZmZmZGYxMjA4MTEyMjc0OWM0YjcxYzViMWMxMWJjNjU5ZDc5MjQyZDE5ZTE4ZjVlOGRiYWIwNGE0NWUzNmJiIn0seyJwYXRoIjoibnBtLWFkYXB0ZXItZmlsZXMuanNvbiIsImJ5dGVzIjoxNTIxLCJzaGEyNTYiOiIxMjUxNjdhYmI5NzEwNGY3ODZmMjU1MDEwMWViNzI3ZDNmZTA0MjBmZjI0NmEyZmIzOWUzYzM3ZTMyM2Y4MmIzIn1dfV19","signature":"z0JPO9k27DHv9z11T1CzmRRLjyH7FNLem10hm/MmtMApfo9QgJ2x575rNyOUHf7guNeani7gKT21EHqqe0vEAg=="}
|
|
1
|
+
{"key_id":"notifai-release-2026-10","payload":"eyJzY2hlbWEiOjIsInZlcnNpb24iOiIxMi4wLjEiLCJzb3VyY2VfcmV2aXNpb24iOiI5NDcyOTg0NmYzMzZmZDY2MTAxMjM4NjQwOTZjYjk1MDg4OWQ5NjllIiwibG9jYWxfY29udGludWl0eSI6eyJjb250cmFjdCI6Im5vdGlmYWktc2Vzc2lvbi1zdGF0ZS12MiIsImNvbXBhdGlibGUiOnsibm90aWZhaS1zZXNzaW9uLXN0YXRlLXYxIjpbImJ1bi1kYXJ3aW4tYXJtNjQiLCJidW4tZGFyd2luLXg2NCIsImJ1bi13aW5kb3dzLWFybTY0IiwiYnVuLXdpbmRvd3MteDY0Il19fSwic3RvcmVfc2NoZW1hIjoyLCJsYXVuY2hlcl9zY2hlbWEiOjEsImFydGlmYWN0cyI6W3sidGFyZ2V0IjoiYnVuLWRhcndpbi1hcm02NCIsImZpbGVuYW1lIjoibm90aWZhaS0xMi4wLjEtZGFyd2luLWFybTY0LnRhci5neiIsImJ5dGVzIjoyNzgzNTAxMywic2hhMjU2IjoiNjM3NzY0MDQ4MTdmMDc1M2E1NTRlNzg4NzNiM2E0Mzk1Y2I2YjdkMTc5Zjg4Y2ZmNDExNzQ2MjM2NWQyYTc3ZiIsInJ1bnRpbWVfc2hhMjU2IjoiYzcwYzUyNzA5ZjllYWRiODBjYTM1MTQ0MThmNmMyMDBjYjcyOGUzMjAxYTJhNTI5ODc5YzBhMjE3MzRmOWY3YSIsImxhdW5jaGVyX3NoYTI1NiI6ImI5MTk1MGFmYzA4YjU5ZWJjMmI2MDM2ZjY4N2Y0YjQzYTZmZjk5YjMzNjg4OGY0OGZhYzY0ZWI2MDg5MGEyOTMiLCJtYXRlcmlhbHMiOlt7InBhdGgiOiJCVU4tTElDRU5TRS5tZCIsImJ5dGVzIjo1NjEzLCJzaGEyNTYiOiJiOWNhZjUyNzI4NjkxYjQwNTdlMzcxMjMyYzIyMWExMzI4ODMxOThiZTJmM2QyZGRmOTJjOTA0MDRjOTg0YjFhIn0seyJwYXRoIjoiQ09SUkVTUE9ORElORy1TT1VSQ0VTLmpzb24iLCJieXRlcyI6MjAyMCwic2hhMjU2IjoiZmE0YzM0NDgwMTE1NDg3MmQ2MTc5ZWUyZWY0OTkyM2RjOWY4OTA5ZWYwMWU1M2I4NmU4ZjU3YzYyNTgyMzI3NCJ9LHsicGF0aCI6IkxJQ0VOU0UudHh0IiwiYnl0ZXMiOjExMzQ2LCJzaGEyNTYiOiI5NDRjMTNmZjBmZTc5NWUyOTFmZDFjNDk0NzNmOThkNGZkZjFmNzQ2MzhlMDFmODgyNzY5Y2Q0Y2FlNzhiNzNkIn0seyJwYXRoIjoiTk9USUNFLVBST1ZFTkFOQ0UuanNvbiIsImJ5dGVzIjo0NTAyNjQsInNoYTI1NiI6IjUzNGRkNTlmZDRjMTVkZDEzODJlODI3ZjBiODVjMTlmN2M2OThlMjM1ZjkyOTllYWEyMDJkYjU0MDA4MzQyODgifSx7InBhdGgiOiJOT1RJQ0UudHh0IiwiYnl0ZXMiOjYyNiwic2hhMjU2IjoiMWRmYmY0NDk4ZGMwMjZiMjA1OWMwYjBiNWViNWZhMWQ4MmFlMzM0ZTU4ZmYxMWU3YzI5NzMzMzI3ZjI1YzRlYiJ9LHsicGF0aCI6IlJFQlVJTERJTkcubWQiLCJieXRlcyI6Mzg0Miwic2hhMjU2IjoiY2U2MDViNWZkYjAzMTkzMzlmOWY4M2YyZmU3Y2NjYmM3ZTU3MjZmZGY0OTRkYTZlMjg0MzNiZWY4MjllYjBiZSJ9LHsicGF0aCI6IlNPVVJDRS1OT1RJQ0VTLnR4dCIsImJ5dGVzIjo5MDE3NzcxLCJzaGEyNTYiOiI4OTk3NmJlY2MyNTY1NDBlNmQyZTgwN2I0N2E0ZTA1ZTg4OTk4MmMwNjIyZmMwNDQxM2E3YmY3ZTc3YTc3ZTM3In0seyJwYXRoIjoiVEhJUkQtUEFSVFktTk9USUNFUy50eHQiLCJieXRlcyI6MjQ5MTQ5Niwic2hhMjU2IjoiMTE2NDQ3ZWZmNzc4OTM1MTE3OTdlZjQ3NjAxMWRlYzgwMDIyNGY5MWUzMzQyZTNkNjU3MDcwODcxMmI0Yjc3MiJ9LHsicGF0aCI6ImxpY2Vuc2VzL25wbS1jbWQtc2hpbS50eHQiLCJieXRlcyI6ODEzLCJzaGEyNTYiOiJhZmZmZGYxMjA4MTEyMjc0OWM0YjcxYzViMWMxMWJjNjU5ZDc5MjQyZDE5ZTE4ZjVlOGRiYWIwNGE0NWUzNmJiIn0seyJwYXRoIjoibnBtLWFkYXB0ZXItZmlsZXMuanNvbiIsImJ5dGVzIjoxNTAwLCJzaGEyNTYiOiI0Yjg5OTcwYWMwZTFlNmZkN2E0OGVhNjliZmYxMzJhMDI1NWQ5YmNlYWMyM2RhOWM4OTE4M2I5MzEzM2YzOTBlIn1dfSx7InRhcmdldCI6ImJ1bi1kYXJ3aW4teDY0IiwiZmlsZW5hbWUiOiJub3RpZmFpLTEyLjAuMS1kYXJ3aW4teDY0LnRhci5neiIsImJ5dGVzIjozMDA3NDE0Miwic2hhMjU2IjoiZGY2NjdkYTc3MWE0ZDQ2OGRmODg2NmM1Zjg3OGVmNzEyMjg4ZTYwMjZiYzg0YTQyMDU2ZTI2NDdlYTk4NDRjOCIsInJ1bnRpbWVfc2hhMjU2IjoiNzIwYjkxNDIyOTY5YWIxYzY3MjliMDVhYTY3Y2I1NTMwMGUxYmQwNDZlNTkyMWNiNjNhNTg1Njc1ZWZmNTYyZiIsImxhdW5jaGVyX3NoYTI1NiI6IjhiODBhNmYxYmMzY2I2MTBjMzIzZTQyZjdiZGZkODc1YWIyYmU5M2YyZTQzODFhNDQ0Y2M0MDViMTUzN2M3MjEiLCJtYXRlcmlhbHMiOlt7InBhdGgiOiJCVU4tTElDRU5TRS5tZCIsImJ5dGVzIjo1NjEzLCJzaGEyNTYiOiJiOWNhZjUyNzI4NjkxYjQwNTdlMzcxMjMyYzIyMWExMzI4ODMxOThiZTJmM2QyZGRmOTJjOTA0MDRjOTg0YjFhIn0seyJwYXRoIjoiQ09SUkVTUE9ORElORy1TT1VSQ0VTLmpzb24iLCJieXRlcyI6MjAyMCwic2hhMjU2IjoiZmE0YzM0NDgwMTE1NDg3MmQ2MTc5ZWUyZWY0OTkyM2RjOWY4OTA5ZWYwMWU1M2I4NmU4ZjU3YzYyNTgyMzI3NCJ9LHsicGF0aCI6IkxJQ0VOU0UudHh0IiwiYnl0ZXMiOjExMzQ2LCJzaGEyNTYiOiI5NDRjMTNmZjBmZTc5NWUyOTFmZDFjNDk0NzNmOThkNGZkZjFmNzQ2MzhlMDFmODgyNzY5Y2Q0Y2FlNzhiNzNkIn0seyJwYXRoIjoiTk9USUNFLVBST1ZFTkFOQ0UuanNvbiIsImJ5dGVzIjo0NTAyNjQsInNoYTI1NiI6IjUzNGRkNTlmZDRjMTVkZDEzODJlODI3ZjBiODVjMTlmN2M2OThlMjM1ZjkyOTllYWEyMDJkYjU0MDA4MzQyODgifSx7InBhdGgiOiJOT1RJQ0UudHh0IiwiYnl0ZXMiOjYyNiwic2hhMjU2IjoiMWRmYmY0NDk4ZGMwMjZiMjA1OWMwYjBiNWViNWZhMWQ4MmFlMzM0ZTU4ZmYxMWU3YzI5NzMzMzI3ZjI1YzRlYiJ9LHsicGF0aCI6IlJFQlVJTERJTkcubWQiLCJieXRlcyI6Mzg0Miwic2hhMjU2IjoiY2U2MDViNWZkYjAzMTkzMzlmOWY4M2YyZmU3Y2NjYmM3ZTU3MjZmZGY0OTRkYTZlMjg0MzNiZWY4MjllYjBiZSJ9LHsicGF0aCI6IlNPVVJDRS1OT1RJQ0VTLnR4dCIsImJ5dGVzIjo5MDE3NzcxLCJzaGEyNTYiOiI4OTk3NmJlY2MyNTY1NDBlNmQyZTgwN2I0N2E0ZTA1ZTg4OTk4MmMwNjIyZmMwNDQxM2E3YmY3ZTc3YTc3ZTM3In0seyJwYXRoIjoiVEhJUkQtUEFSVFktTk9USUNFUy50eHQiLCJieXRlcyI6MjQ5MTQ5Niwic2hhMjU2IjoiMTE2NDQ3ZWZmNzc4OTM1MTE3OTdlZjQ3NjAxMWRlYzgwMDIyNGY5MWUzMzQyZTNkNjU3MDcwODcxMmI0Yjc3MiJ9LHsicGF0aCI6ImxpY2Vuc2VzL25wbS1jbWQtc2hpbS50eHQiLCJieXRlcyI6ODEzLCJzaGEyNTYiOiJhZmZmZGYxMjA4MTEyMjc0OWM0YjcxYzViMWMxMWJjNjU5ZDc5MjQyZDE5ZTE4ZjVlOGRiYWIwNGE0NWUzNmJiIn0seyJwYXRoIjoibnBtLWFkYXB0ZXItZmlsZXMuanNvbiIsImJ5dGVzIjoxNTAwLCJzaGEyNTYiOiI0Yjg5OTcwYWMwZTFlNmZkN2E0OGVhNjliZmYxMzJhMDI1NWQ5YmNlYWMyM2RhOWM4OTE4M2I5MzEzM2YzOTBlIn1dfSx7InRhcmdldCI6ImJ1bi1saW51eC1hcm02NCIsImZpbGVuYW1lIjoibm90aWZhaS0xMi4wLjEtbGludXgtYXJtNjQudGFyLmd6IiwiYnl0ZXMiOjM5Mzc5NTU0LCJzaGEyNTYiOiI0ZTc5NWI4OWM2OTgwODI0Mjg5NDVlN2MyNzViYTgxZDBlN2E3NjkwMjZmMzYzZjkyYzM2YzE2ODMwMWYxMDBkIiwicnVudGltZV9zaGEyNTYiOiIwNjcyOTFlNzQ5YzdlMTBjNGQ4MmFjZjhkZjEzOWU4YTNkMzM3NmZjMmIwZGU4N2JkMTA2NzJhODUzOTkwYzhmIiwibGF1bmNoZXJfc2hhMjU2IjoiZjgwZmRiZjMzZmJhYTM5MDNjNTQ1MjZmMTk1NmM2MTlmMmY0NzAxZjk4NzE5MGM1YmEyYjRkNTc0YjQzMTBhNCIsIm1hdGVyaWFscyI6W3sicGF0aCI6IkJVTi1MSUNFTlNFLm1kIiwiYnl0ZXMiOjU2MTMsInNoYTI1NiI6ImI5Y2FmNTI3Mjg2OTFiNDA1N2UzNzEyMzJjMjIxYTEzMjg4MzE5OGJlMmYzZDJkZGY5MmM5MDQwNGM5ODRiMWEifSx7InBhdGgiOiJDT1JSRVNQT05ESU5HLVNPVVJDRVMuanNvbiIsImJ5dGVzIjoyMDIwLCJzaGEyNTYiOiJmYTRjMzQ0ODAxMTU0ODcyZDYxNzllZTJlZjQ5OTIzZGM5Zjg5MDllZjAxZTUzYjg2ZThmNTdjNjI1ODIzMjc0In0seyJwYXRoIjoiTElDRU5TRS50eHQiLCJieXRlcyI6MTEzNDYsInNoYTI1NiI6Ijk0NGMxM2ZmMGZlNzk1ZTI5MWZkMWM0OTQ3M2Y5OGQ0ZmRmMWY3NDYzOGUwMWY4ODI3NjljZDRjYWU3OGI3M2QifSx7InBhdGgiOiJOT1RJQ0UtUFJPVkVOQU5DRS5qc29uIiwiYnl0ZXMiOjQ1MDI2NCwic2hhMjU2IjoiNTM0ZGQ1OWZkNGMxNWRkMTM4MmU4MjdmMGI4NWMxOWY3YzY5OGUyMzVmOTI5OWVhYTIwMmRiNTQwMDgzNDI4OCJ9LHsicGF0aCI6Ik5PVElDRS50eHQiLCJieXRlcyI6NjI2LCJzaGEyNTYiOiIxZGZiZjQ0OThkYzAyNmIyMDU5YzBiMGI1ZWI1ZmExZDgyYWUzMzRlNThmZjExZTdjMjk3MzMzMjdmMjVjNGViIn0seyJwYXRoIjoiUkVCVUlMRElORy5tZCIsImJ5dGVzIjozODQyLCJzaGEyNTYiOiJjZTYwNWI1ZmRiMDMxOTMzOWY5ZjgzZjJmZTdjY2NiYzdlNTcyNmZkZjQ5NGRhNmUyODQzM2JlZjgyOWViMGJlIn0seyJwYXRoIjoiU09VUkNFLU5PVElDRVMudHh0IiwiYnl0ZXMiOjkwMTc3NzEsInNoYTI1NiI6Ijg5OTc2YmVjYzI1NjU0MGU2ZDJlODA3YjQ3YTRlMDVlODg5OTgyYzA2MjJmYzA0NDEzYTdiZjdlNzdhNzdlMzcifSx7InBhdGgiOiJUSElSRC1QQVJUWS1OT1RJQ0VTLnR4dCIsImJ5dGVzIjoyNDkxNDk2LCJzaGEyNTYiOiIxMTY0NDdlZmY3Nzg5MzUxMTc5N2VmNDc2MDExZGVjODAwMjI0ZjkxZTMzNDJlM2Q2NTcwNzA4NzEyYjRiNzcyIn0seyJwYXRoIjoibGljZW5zZXMvbnBtLWNtZC1zaGltLnR4dCIsImJ5dGVzIjo4MTMsInNoYTI1NiI6ImFmZmZkZjEyMDgxMTIyNzQ5YzRiNzFjNWIxYzExYmM2NTlkNzkyNDJkMTllMThmNWU4ZGJhYjA0YTQ1ZTM2YmIifSx7InBhdGgiOiJucG0tYWRhcHRlci1maWxlcy5qc29uIiwiYnl0ZXMiOjE1MDAsInNoYTI1NiI6IjRiODk5NzBhYzBlMWU2ZmQ3YTQ4ZWE2OWJmZjEzMmEwMjU1ZDliY2VhYzIzZGE5Yzg5MTgzYjkzMTMzZjM5MGUifV19LHsidGFyZ2V0IjoiYnVuLWxpbnV4LXg2NCIsImZpbGVuYW1lIjoibm90aWZhaS0xMi4wLjEtbGludXgteDY0LnRhci5neiIsImJ5dGVzIjozODk0NDM0NSwic2hhMjU2IjoiMjIzMDMxMzU5MGU3MjZlZGRlNjk2NmI5NmI0NTYzNTJkODk2NmYwNDMzOWU4ZjcwZWE1ZWUxMWIzYjM1YWYxNSIsInJ1bnRpbWVfc2hhMjU2IjoiMzk4NGU4YTNkNDJjOTM2YzY0NDY1NjQxMGZiYjRiMGRiMDdkMWU5NzY0ZWE0MGFiM2Q4OGFmYjZlMDc5NjI3YiIsImxhdW5jaGVyX3NoYTI1NiI6IjhiMWYwOTNlNDRjNmZkMzk4NDFlMzliZGU5N2IyNzE1MDQ4ZDM5NjNiNzA0ZjYyZjJhYmViNTkwMmM3ZmJiZTciLCJtYXRlcmlhbHMiOlt7InBhdGgiOiJCVU4tTElDRU5TRS5tZCIsImJ5dGVzIjo1NjEzLCJzaGEyNTYiOiJiOWNhZjUyNzI4NjkxYjQwNTdlMzcxMjMyYzIyMWExMzI4ODMxOThiZTJmM2QyZGRmOTJjOTA0MDRjOTg0YjFhIn0seyJwYXRoIjoiQ09SUkVTUE9ORElORy1TT1VSQ0VTLmpzb24iLCJieXRlcyI6MjAyMCwic2hhMjU2IjoiZmE0YzM0NDgwMTE1NDg3MmQ2MTc5ZWUyZWY0OTkyM2RjOWY4OTA5ZWYwMWU1M2I4NmU4ZjU3YzYyNTgyMzI3NCJ9LHsicGF0aCI6IkxJQ0VOU0UudHh0IiwiYnl0ZXMiOjExMzQ2LCJzaGEyNTYiOiI5NDRjMTNmZjBmZTc5NWUyOTFmZDFjNDk0NzNmOThkNGZkZjFmNzQ2MzhlMDFmODgyNzY5Y2Q0Y2FlNzhiNzNkIn0seyJwYXRoIjoiTk9USUNFLVBST1ZFTkFOQ0UuanNvbiIsImJ5dGVzIjo0NTAyNjQsInNoYTI1NiI6IjUzNGRkNTlmZDRjMTVkZDEzODJlODI3ZjBiODVjMTlmN2M2OThlMjM1ZjkyOTllYWEyMDJkYjU0MDA4MzQyODgifSx7InBhdGgiOiJOT1RJQ0UudHh0IiwiYnl0ZXMiOjYyNiwic2hhMjU2IjoiMWRmYmY0NDk4ZGMwMjZiMjA1OWMwYjBiNWViNWZhMWQ4MmFlMzM0ZTU4ZmYxMWU3YzI5NzMzMzI3ZjI1YzRlYiJ9LHsicGF0aCI6IlJFQlVJTERJTkcubWQiLCJieXRlcyI6Mzg0Miwic2hhMjU2IjoiY2U2MDViNWZkYjAzMTkzMzlmOWY4M2YyZmU3Y2NjYmM3ZTU3MjZmZGY0OTRkYTZlMjg0MzNiZWY4MjllYjBiZSJ9LHsicGF0aCI6IlNPVVJDRS1OT1RJQ0VTLnR4dCIsImJ5dGVzIjo5MDE3NzcxLCJzaGEyNTYiOiI4OTk3NmJlY2MyNTY1NDBlNmQyZTgwN2I0N2E0ZTA1ZTg4OTk4MmMwNjIyZmMwNDQxM2E3YmY3ZTc3YTc3ZTM3In0seyJwYXRoIjoiVEhJUkQtUEFSVFktTk9USUNFUy50eHQiLCJieXRlcyI6MjQ5MTQ5Niwic2hhMjU2IjoiMTE2NDQ3ZWZmNzc4OTM1MTE3OTdlZjQ3NjAxMWRlYzgwMDIyNGY5MWUzMzQyZTNkNjU3MDcwODcxMmI0Yjc3MiJ9LHsicGF0aCI6ImxpY2Vuc2VzL25wbS1jbWQtc2hpbS50eHQiLCJieXRlcyI6ODEzLCJzaGEyNTYiOiJhZmZmZGYxMjA4MTEyMjc0OWM0YjcxYzViMWMxMWJjNjU5ZDc5MjQyZDE5ZTE4ZjVlOGRiYWIwNGE0NWUzNmJiIn0seyJwYXRoIjoibnBtLWFkYXB0ZXItZmlsZXMuanNvbiIsImJ5dGVzIjoxNTAwLCJzaGEyNTYiOiI0Yjg5OTcwYWMwZTFlNmZkN2E0OGVhNjliZmYxMzJhMDI1NWQ5YmNlYWMyM2RhOWM4OTE4M2I5MzEzM2YzOTBlIn1dfSx7InRhcmdldCI6ImJ1bi13aW5kb3dzLWFybTY0IiwiZmlsZW5hbWUiOiJub3RpZmFpLTEyLjAuMS13aW5kb3dzLWFybTY0LnppcCIsImJ5dGVzIjozODc3NjU3Mywic2hhMjU2IjoiNzNkM2YyNDMwYzY5OTJmN2E3MzhhZTY0MzgyYjRhMTVkMTBiZThhZThkZWFhOGYxN2I4MWFmNWU5MDFjMzViNCIsInJ1bnRpbWVfc2hhMjU2IjoiNThiOTQ5MmYxM2FjY2FhZTRiZDgwYmRkN2Y2N2Q2MGNjY2UyNjllYjg0ZGY3ZTYxM2U3OWZmOGE1MGE1NWJiYSIsImxhdW5jaGVyX3NoYTI1NiI6Ijc5MTYxZjM1OGZiNzRjY2ZlZDhlZGQzNzcxNDYxY2IyMDFmZmI2N2U3YzEyNTcyNDc5ZmZjOGQ2Y2U3YWQ4Y2YiLCJtYXRlcmlhbHMiOlt7InBhdGgiOiJCVU4tTElDRU5TRS5tZCIsImJ5dGVzIjo1NjEzLCJzaGEyNTYiOiJiOWNhZjUyNzI4NjkxYjQwNTdlMzcxMjMyYzIyMWExMzI4ODMxOThiZTJmM2QyZGRmOTJjOTA0MDRjOTg0YjFhIn0seyJwYXRoIjoiQ09SUkVTUE9ORElORy1TT1VSQ0VTLmpzb24iLCJieXRlcyI6MjAyMCwic2hhMjU2IjoiZmE0YzM0NDgwMTE1NDg3MmQ2MTc5ZWUyZWY0OTkyM2RjOWY4OTA5ZWYwMWU1M2I4NmU4ZjU3YzYyNTgyMzI3NCJ9LHsicGF0aCI6IkxJQ0VOU0UudHh0IiwiYnl0ZXMiOjExMzQ2LCJzaGEyNTYiOiI5NDRjMTNmZjBmZTc5NWUyOTFmZDFjNDk0NzNmOThkNGZkZjFmNzQ2MzhlMDFmODgyNzY5Y2Q0Y2FlNzhiNzNkIn0seyJwYXRoIjoiTk9USUNFLVBST1ZFTkFOQ0UuanNvbiIsImJ5dGVzIjo0NTAyNjQsInNoYTI1NiI6IjUzNGRkNTlmZDRjMTVkZDEzODJlODI3ZjBiODVjMTlmN2M2OThlMjM1ZjkyOTllYWEyMDJkYjU0MDA4MzQyODgifSx7InBhdGgiOiJOT1RJQ0UudHh0IiwiYnl0ZXMiOjYyNiwic2hhMjU2IjoiMWRmYmY0NDk4ZGMwMjZiMjA1OWMwYjBiNWViNWZhMWQ4MmFlMzM0ZTU4ZmYxMWU3YzI5NzMzMzI3ZjI1YzRlYiJ9LHsicGF0aCI6IlJFQlVJTERJTkcubWQiLCJieXRlcyI6Mzg0Miwic2hhMjU2IjoiY2U2MDViNWZkYjAzMTkzMzlmOWY4M2YyZmU3Y2NjYmM3ZTU3MjZmZGY0OTRkYTZlMjg0MzNiZWY4MjllYjBiZSJ9LHsicGF0aCI6IlNPVVJDRS1OT1RJQ0VTLnR4dCIsImJ5dGVzIjo5MDE3NzcxLCJzaGEyNTYiOiI4OTk3NmJlY2MyNTY1NDBlNmQyZTgwN2I0N2E0ZTA1ZTg4OTk4MmMwNjIyZmMwNDQxM2E3YmY3ZTc3YTc3ZTM3In0seyJwYXRoIjoiVEhJUkQtUEFSVFktTk9USUNFUy50eHQiLCJieXRlcyI6MjQ5MTQ5Niwic2hhMjU2IjoiMTE2NDQ3ZWZmNzc4OTM1MTE3OTdlZjQ3NjAxMWRlYzgwMDIyNGY5MWUzMzQyZTNkNjU3MDcwODcxMmI0Yjc3MiJ9LHsicGF0aCI6ImxpY2Vuc2VzL25wbS1jbWQtc2hpbS50eHQiLCJieXRlcyI6ODEzLCJzaGEyNTYiOiJhZmZmZGYxMjA4MTEyMjc0OWM0YjcxYzViMWMxMWJjNjU5ZDc5MjQyZDE5ZTE4ZjVlOGRiYWIwNGE0NWUzNmJiIn0seyJwYXRoIjoibnBtLWFkYXB0ZXItZmlsZXMuanNvbiIsImJ5dGVzIjoxNTAwLCJzaGEyNTYiOiI0Yjg5OTcwYWMwZTFlNmZkN2E0OGVhNjliZmYxMzJhMDI1NWQ5YmNlYWMyM2RhOWM4OTE4M2I5MzEzM2YzOTBlIn1dfSx7InRhcmdldCI6ImJ1bi13aW5kb3dzLXg2NCIsImZpbGVuYW1lIjoibm90aWZhaS0xMi4wLjEtd2luZG93cy14NjQuemlwIiwiYnl0ZXMiOjQxOTIyODAwLCJzaGEyNTYiOiJjNDNmZmFjMzg5ODEwYWU4YTJhYzNlYzcxZWY3YjgxNTU4MGYxNTg1YmM5MGIyYmYzYTdkMzQwMjMwYTM2ZTUyIiwicnVudGltZV9zaGEyNTYiOiJlNDE3Y2RiMzk5MjVhOWY4ZWU3ODA1NjdlMDMyYWFkYTI2NGJlZTcwZjQ0YzQ4MGQzMDBkYzZiNDZmOTYyYjlhIiwibGF1bmNoZXJfc2hhMjU2IjoiZTUyMmM3MTJiZWJlYmJiYmI5NzVhMjdkOTMxMDViMTk2YmNhNmVkYTgzOGIwNDgyMmU3ZDYxOGMyYjFmZmQxZCIsIm1hdGVyaWFscyI6W3sicGF0aCI6IkJVTi1MSUNFTlNFLm1kIiwiYnl0ZXMiOjU2MTMsInNoYTI1NiI6ImI5Y2FmNTI3Mjg2OTFiNDA1N2UzNzEyMzJjMjIxYTEzMjg4MzE5OGJlMmYzZDJkZGY5MmM5MDQwNGM5ODRiMWEifSx7InBhdGgiOiJDT1JSRVNQT05ESU5HLVNPVVJDRVMuanNvbiIsImJ5dGVzIjoyMDIwLCJzaGEyNTYiOiJmYTRjMzQ0ODAxMTU0ODcyZDYxNzllZTJlZjQ5OTIzZGM5Zjg5MDllZjAxZTUzYjg2ZThmNTdjNjI1ODIzMjc0In0seyJwYXRoIjoiTElDRU5TRS50eHQiLCJieXRlcyI6MTEzNDYsInNoYTI1NiI6Ijk0NGMxM2ZmMGZlNzk1ZTI5MWZkMWM0OTQ3M2Y5OGQ0ZmRmMWY3NDYzOGUwMWY4ODI3NjljZDRjYWU3OGI3M2QifSx7InBhdGgiOiJOT1RJQ0UtUFJPVkVOQU5DRS5qc29uIiwiYnl0ZXMiOjQ1MDI2NCwic2hhMjU2IjoiNTM0ZGQ1OWZkNGMxNWRkMTM4MmU4MjdmMGI4NWMxOWY3YzY5OGUyMzVmOTI5OWVhYTIwMmRiNTQwMDgzNDI4OCJ9LHsicGF0aCI6Ik5PVElDRS50eHQiLCJieXRlcyI6NjI2LCJzaGEyNTYiOiIxZGZiZjQ0OThkYzAyNmIyMDU5YzBiMGI1ZWI1ZmExZDgyYWUzMzRlNThmZjExZTdjMjk3MzMzMjdmMjVjNGViIn0seyJwYXRoIjoiUkVCVUlMRElORy5tZCIsImJ5dGVzIjozODQyLCJzaGEyNTYiOiJjZTYwNWI1ZmRiMDMxOTMzOWY5ZjgzZjJmZTdjY2NiYzdlNTcyNmZkZjQ5NGRhNmUyODQzM2JlZjgyOWViMGJlIn0seyJwYXRoIjoiU09VUkNFLU5PVElDRVMudHh0IiwiYnl0ZXMiOjkwMTc3NzEsInNoYTI1NiI6Ijg5OTc2YmVjYzI1NjU0MGU2ZDJlODA3YjQ3YTRlMDVlODg5OTgyYzA2MjJmYzA0NDEzYTdiZjdlNzdhNzdlMzcifSx7InBhdGgiOiJUSElSRC1QQVJUWS1OT1RJQ0VTLnR4dCIsImJ5dGVzIjoyNDkxNDk2LCJzaGEyNTYiOiIxMTY0NDdlZmY3Nzg5MzUxMTc5N2VmNDc2MDExZGVjODAwMjI0ZjkxZTMzNDJlM2Q2NTcwNzA4NzEyYjRiNzcyIn0seyJwYXRoIjoibGljZW5zZXMvbnBtLWNtZC1zaGltLnR4dCIsImJ5dGVzIjo4MTMsInNoYTI1NiI6ImFmZmZkZjEyMDgxMTIyNzQ5YzRiNzFjNWIxYzExYmM2NTlkNzkyNDJkMTllMThmNWU4ZGJhYjA0YTQ1ZTM2YmIifSx7InBhdGgiOiJucG0tYWRhcHRlci1maWxlcy5qc29uIiwiYnl0ZXMiOjE1MDAsInNoYTI1NiI6IjRiODk5NzBhYzBlMWU2ZmQ3YTQ4ZWE2OWJmZjEzMmEwMjU1ZDliY2VhYzIzZGE5Yzg5MTgzYjkzMTMzZjM5MGUifV19XX0=","signature":"UX9Ah/FIY0ZFjm3D7h/VWyTMt2goOLNBvO53ZXn4gt0x1aVNHWMYHDnfxA79OVKOyxIIVcU8Jbf5K0tXMcqZAQ=="}
|
package/npm-adapter-files.json
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schema": 1,
|
|
3
3
|
"package": "@raidiant/notifai",
|
|
4
|
-
"adapter_version": "12.0.
|
|
4
|
+
"adapter_version": "12.0.1",
|
|
5
5
|
"native": {
|
|
6
|
-
"version": "12.0.
|
|
7
|
-
"source_revision": "
|
|
8
|
-
"inventory_url": "https://github.com/Raidiant-io/notifai/releases/download/v12.0.
|
|
6
|
+
"version": "12.0.1",
|
|
7
|
+
"source_revision": "94729846f336fd6610123864096cb950889d969e",
|
|
8
|
+
"inventory_url": "https://github.com/Raidiant-io/notifai/releases/download/v12.0.1/inventory.json"
|
|
9
9
|
},
|
|
10
10
|
"files": [
|
|
11
11
|
{
|
|
12
12
|
"path": "CHANGELOG.md",
|
|
13
|
-
"bytes":
|
|
14
|
-
"sha256": "
|
|
13
|
+
"bytes": 62768,
|
|
14
|
+
"sha256": "0140730d6d4b8573357c811e8348432e2ff146e1dfb0a4a2d4d26a828bc307b8"
|
|
15
15
|
},
|
|
16
16
|
{
|
|
17
17
|
"path": "LICENSE",
|
|
@@ -30,23 +30,23 @@
|
|
|
30
30
|
},
|
|
31
31
|
{
|
|
32
32
|
"path": "bin/notifai.mjs",
|
|
33
|
-
"bytes":
|
|
34
|
-
"sha256": "
|
|
33
|
+
"bytes": 522895,
|
|
34
|
+
"sha256": "b549cdbfd09c49fbe9ebc826b9be40467f2f27084f613392a22bfb418dd4e72c"
|
|
35
35
|
},
|
|
36
36
|
{
|
|
37
37
|
"path": "data/install.ps1",
|
|
38
|
-
"bytes":
|
|
39
|
-
"sha256": "
|
|
38
|
+
"bytes": 26228,
|
|
39
|
+
"sha256": "e111259532c11e1e822356d34b0b30059db17b59e6b69ce3af74e491ee3cbc5a"
|
|
40
40
|
},
|
|
41
41
|
{
|
|
42
42
|
"path": "data/release.json",
|
|
43
|
-
"bytes":
|
|
44
|
-
"sha256": "
|
|
43
|
+
"bytes": 82,
|
|
44
|
+
"sha256": "d5ce790eab8ebe8fb75e3172e3f478f83037d1a3c155249c145c9bc330b90e80"
|
|
45
45
|
},
|
|
46
46
|
{
|
|
47
47
|
"path": "package.json",
|
|
48
|
-
"bytes":
|
|
49
|
-
"sha256": "
|
|
48
|
+
"bytes": 807,
|
|
49
|
+
"sha256": "4f1268413a0e47d1cb4fc26694483801e0d119fbb244b9434e09f10eb0fc2a25"
|
|
50
50
|
}
|
|
51
51
|
]
|
|
52
52
|
}
|