@attest-it/core 0.7.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-T3NLSO5B.js → chunk-FGYLU2HL.js} +38 -8
- package/dist/chunk-FGYLU2HL.js.map +1 -0
- package/dist/core-alpha.d.ts +58 -18
- package/dist/core-beta.d.ts +58 -18
- package/dist/core-public.d.ts +58 -18
- package/dist/core-unstripped.d.ts +58 -18
- package/dist/crypto-SSL7OBY2.js +3 -0
- package/dist/{crypto-VT6YNHUE.js.map → crypto-SSL7OBY2.js.map} +1 -1
- package/dist/index.cjs +85 -53
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +58 -18
- package/dist/index.d.ts +58 -18
- package/dist/index.js +76 -74
- package/dist/index.js.map +1 -1
- package/package.json +3 -1
- package/dist/chunk-T3NLSO5B.js.map +0 -1
- package/dist/crypto-VT6YNHUE.js +0 -3
package/dist/index.cjs
CHANGED
|
@@ -63,7 +63,7 @@ __export(crypto_exports, {
|
|
|
63
63
|
verify: () => verify
|
|
64
64
|
});
|
|
65
65
|
async function runOpenSSL(args, stdin) {
|
|
66
|
-
return new Promise((
|
|
66
|
+
return new Promise((resolve5, reject) => {
|
|
67
67
|
const child = child_process.spawn("openssl", args, {
|
|
68
68
|
stdio: ["pipe", "pipe", "pipe"]
|
|
69
69
|
});
|
|
@@ -79,12 +79,15 @@ async function runOpenSSL(args, stdin) {
|
|
|
79
79
|
reject(new Error(`Failed to spawn OpenSSL: ${err.message}`));
|
|
80
80
|
});
|
|
81
81
|
child.on("close", (code) => {
|
|
82
|
-
|
|
82
|
+
resolve5({
|
|
83
83
|
exitCode: code ?? 1,
|
|
84
84
|
stdout: Buffer.concat(stdoutChunks),
|
|
85
85
|
stderr
|
|
86
86
|
});
|
|
87
87
|
});
|
|
88
|
+
if (stdin) {
|
|
89
|
+
child.stdin.write(stdin);
|
|
90
|
+
}
|
|
88
91
|
child.stdin.end();
|
|
89
92
|
});
|
|
90
93
|
}
|
|
@@ -157,7 +160,8 @@ async function generateKeyPair(options = {}) {
|
|
|
157
160
|
const {
|
|
158
161
|
privatePath = getDefaultPrivateKeyPath(),
|
|
159
162
|
publicPath = getDefaultPublicKeyPath(),
|
|
160
|
-
force = false
|
|
163
|
+
force = false,
|
|
164
|
+
passphrase
|
|
161
165
|
} = options;
|
|
162
166
|
const privateExists = await fileExists(privatePath);
|
|
163
167
|
const publicExists = await fileExists(publicPath);
|
|
@@ -181,12 +185,25 @@ async function generateKeyPair(options = {}) {
|
|
|
181
185
|
"-out",
|
|
182
186
|
privatePath
|
|
183
187
|
];
|
|
184
|
-
|
|
188
|
+
if (passphrase) {
|
|
189
|
+
genArgs.push("-aes256", "-pass", "stdin");
|
|
190
|
+
}
|
|
191
|
+
const genResult = await runOpenSSL(
|
|
192
|
+
genArgs,
|
|
193
|
+
passphrase ? Buffer.from(passphrase + "\n") : void 0
|
|
194
|
+
);
|
|
185
195
|
if (genResult.exitCode !== 0) {
|
|
186
196
|
throw new Error(`Failed to generate private key: ${genResult.stderr}`);
|
|
187
197
|
}
|
|
188
198
|
await setKeyPermissions(privatePath);
|
|
189
|
-
const
|
|
199
|
+
const pubArgs = ["pkey", "-in", privatePath, "-pubout", "-out", publicPath];
|
|
200
|
+
if (passphrase) {
|
|
201
|
+
pubArgs.push("-passin", "stdin");
|
|
202
|
+
}
|
|
203
|
+
const pubResult = await runOpenSSL(
|
|
204
|
+
pubArgs,
|
|
205
|
+
passphrase ? Buffer.from(passphrase + "\n") : void 0
|
|
206
|
+
);
|
|
190
207
|
if (pubResult.exitCode !== 0) {
|
|
191
208
|
throw new Error(`Failed to extract public key: ${pubResult.stderr}`);
|
|
192
209
|
}
|
|
@@ -201,7 +218,7 @@ async function generateKeyPair(options = {}) {
|
|
|
201
218
|
}
|
|
202
219
|
async function sign(options) {
|
|
203
220
|
await ensureOpenSSLAvailable();
|
|
204
|
-
const { privateKeyPath, keyProvider, keyRef, data } = options;
|
|
221
|
+
const { privateKeyPath, keyProvider, keyRef, data, passphrase } = options;
|
|
205
222
|
let effectiveKeyPath;
|
|
206
223
|
let cleanup;
|
|
207
224
|
if (keyProvider && keyRef) {
|
|
@@ -226,9 +243,22 @@ async function sign(options) {
|
|
|
226
243
|
const sigFile = path2__namespace.join(tmpDir, "sig.bin");
|
|
227
244
|
try {
|
|
228
245
|
await fs8__namespace.writeFile(dataFile, processBuffer);
|
|
229
|
-
const signArgs = ["dgst", "-sha256"
|
|
230
|
-
|
|
246
|
+
const signArgs = ["dgst", "-sha256"];
|
|
247
|
+
if (passphrase) {
|
|
248
|
+
signArgs.push("-passin", "stdin");
|
|
249
|
+
}
|
|
250
|
+
signArgs.push("-sign", effectiveKeyPath, "-out", sigFile, dataFile);
|
|
251
|
+
const result = await runOpenSSL(
|
|
252
|
+
signArgs,
|
|
253
|
+
passphrase ? Buffer.from(passphrase + "\n") : void 0
|
|
254
|
+
);
|
|
231
255
|
if (result.exitCode !== 0) {
|
|
256
|
+
const stderr = result.stderr.toLowerCase();
|
|
257
|
+
if (stderr.includes("bad decrypt") || stderr.includes("bad password") || stderr.includes("unable to load key") || stderr.includes("wrong password")) {
|
|
258
|
+
throw new Error(
|
|
259
|
+
"Failed to decrypt private key. Please check that the passphrase is correct."
|
|
260
|
+
);
|
|
261
|
+
}
|
|
232
262
|
throw new Error(`Failed to sign data: ${result.stderr}`);
|
|
233
263
|
}
|
|
234
264
|
const sigBuffer = await fs8__namespace.readFile(sigFile);
|
|
@@ -305,7 +335,8 @@ var teamMemberSchema = zod.z.object({
|
|
|
305
335
|
name: zod.z.string().min(1, "Team member name cannot be empty"),
|
|
306
336
|
email: zod.z.string().email().optional(),
|
|
307
337
|
github: zod.z.string().min(1).optional(),
|
|
308
|
-
publicKey: zod.z.string().min(1, "Public key is required")
|
|
338
|
+
publicKey: zod.z.string().min(1, "Public key is required"),
|
|
339
|
+
publicKeyAlgorithm: zod.z.enum(["ed25519"]).optional()
|
|
309
340
|
}).strict();
|
|
310
341
|
var fingerprintConfigSchema = zod.z.object({
|
|
311
342
|
paths: zod.z.array(zod.z.string().min(1, "Path cannot be empty")).min(1, "At least one path is required"),
|
|
@@ -335,6 +366,7 @@ var settingsSchema = zod.z.object({
|
|
|
335
366
|
maxAgeDays: zod.z.number().int().positive().default(30),
|
|
336
367
|
publicKeyPath: zod.z.string().default(".attest-it/pubkey.pem"),
|
|
337
368
|
attestationsPath: zod.z.string().default(".attest-it/attestations.json"),
|
|
369
|
+
sealsPath: zod.z.string().default(".attest-it/seals.json"),
|
|
338
370
|
defaultCommand: zod.z.string().optional(),
|
|
339
371
|
keyProvider: keyProviderSchema.optional()
|
|
340
372
|
// Note: algorithm field was removed - RSA is the only supported algorithm
|
|
@@ -488,7 +520,8 @@ function toAttestItConfig(config) {
|
|
|
488
520
|
settings: {
|
|
489
521
|
maxAgeDays: config.settings.maxAgeDays,
|
|
490
522
|
publicKeyPath: config.settings.publicKeyPath,
|
|
491
|
-
attestationsPath: config.settings.attestationsPath
|
|
523
|
+
attestationsPath: config.settings.attestationsPath,
|
|
524
|
+
sealsPath: config.settings.sealsPath
|
|
492
525
|
},
|
|
493
526
|
suites: {}
|
|
494
527
|
};
|
|
@@ -534,7 +567,8 @@ var teamMemberSchema2 = zod.z.object({
|
|
|
534
567
|
name: zod.z.string().min(1, "Team member name cannot be empty"),
|
|
535
568
|
email: zod.z.string().email().optional(),
|
|
536
569
|
github: zod.z.string().min(1).optional(),
|
|
537
|
-
publicKey: zod.z.string().min(1, "Public key is required")
|
|
570
|
+
publicKey: zod.z.string().min(1, "Public key is required"),
|
|
571
|
+
publicKeyAlgorithm: zod.z.literal("ed25519").optional()
|
|
538
572
|
}).strict();
|
|
539
573
|
var fingerprintConfigSchema2 = zod.z.object({
|
|
540
574
|
paths: zod.z.array(zod.z.string().min(1, "Path cannot be empty")).min(1, "At least one path is required"),
|
|
@@ -575,7 +609,8 @@ var keyProviderSchema2 = zod.z.object({
|
|
|
575
609
|
var policySettingsSchema = zod.z.object({
|
|
576
610
|
maxAgeDays: zod.z.number().int().positive().default(30),
|
|
577
611
|
publicKeyPath: zod.z.string().default(".attest-it/pubkey.pem"),
|
|
578
|
-
attestationsPath: zod.z.string().default(".attest-it/attestations.json")
|
|
612
|
+
attestationsPath: zod.z.string().default(".attest-it/attestations.json"),
|
|
613
|
+
sealsPath: zod.z.string().default(".attest-it/seals.json")
|
|
579
614
|
}).strict();
|
|
580
615
|
var policySchema = zod.z.object({
|
|
581
616
|
version: zod.z.literal(1),
|
|
@@ -752,7 +787,8 @@ function mergeConfigs(policy, operational) {
|
|
|
752
787
|
// Security settings from policy (these are trust-critical)
|
|
753
788
|
maxAgeDays: policy.settings.maxAgeDays,
|
|
754
789
|
publicKeyPath: policy.settings.publicKeyPath,
|
|
755
|
-
attestationsPath: policy.settings.attestationsPath
|
|
790
|
+
attestationsPath: policy.settings.attestationsPath,
|
|
791
|
+
sealsPath: policy.settings.sealsPath
|
|
756
792
|
};
|
|
757
793
|
if (operational.settings.defaultCommand !== void 0) {
|
|
758
794
|
settings.defaultCommand = operational.settings.defaultCommand;
|
|
@@ -847,7 +883,7 @@ function computeFinalFingerprint(fileHashes) {
|
|
|
847
883
|
}
|
|
848
884
|
async function hashFileAsync(realPath, normalizedPath, stats) {
|
|
849
885
|
if (stats.size > LARGE_FILE_THRESHOLD) {
|
|
850
|
-
return new Promise((
|
|
886
|
+
return new Promise((resolve5, reject) => {
|
|
851
887
|
const hash2 = crypto3__namespace.createHash("sha256");
|
|
852
888
|
hash2.update(normalizedPath);
|
|
853
889
|
hash2.update(":");
|
|
@@ -856,7 +892,7 @@ async function hashFileAsync(realPath, normalizedPath, stats) {
|
|
|
856
892
|
hash2.update(chunk);
|
|
857
893
|
});
|
|
858
894
|
stream.on("end", () => {
|
|
859
|
-
|
|
895
|
+
resolve5(hash2.digest());
|
|
860
896
|
});
|
|
861
897
|
stream.on("error", reject);
|
|
862
898
|
});
|
|
@@ -1470,16 +1506,23 @@ var FilesystemKeyProvider = class {
|
|
|
1470
1506
|
* @param options - Key generation options
|
|
1471
1507
|
*/
|
|
1472
1508
|
async generateKeyPair(options) {
|
|
1473
|
-
const { publicKeyPath, force = false } = options;
|
|
1474
|
-
const
|
|
1509
|
+
const { publicKeyPath, force = false, passphrase } = options;
|
|
1510
|
+
const cryptoOptions = {
|
|
1475
1511
|
privatePath: this.privateKeyPath,
|
|
1476
1512
|
publicPath: publicKeyPath,
|
|
1477
1513
|
force
|
|
1478
|
-
}
|
|
1514
|
+
};
|
|
1515
|
+
if (passphrase !== void 0) {
|
|
1516
|
+
cryptoOptions.passphrase = passphrase;
|
|
1517
|
+
}
|
|
1518
|
+
const result = await generateKeyPair(cryptoOptions);
|
|
1519
|
+
const encrypted = passphrase !== void 0 && passphrase.length > 0;
|
|
1520
|
+
const encryptionStatus = encrypted ? " (passphrase-encrypted)" : "";
|
|
1479
1521
|
return {
|
|
1480
1522
|
privateKeyRef: result.privatePath,
|
|
1481
1523
|
publicKeyPath: result.publicPath,
|
|
1482
|
-
storageDescription: `Filesystem: ${result.privatePath}
|
|
1524
|
+
storageDescription: `Filesystem: ${result.privatePath}${encryptionStatus}`,
|
|
1525
|
+
encrypted
|
|
1483
1526
|
};
|
|
1484
1527
|
}
|
|
1485
1528
|
/**
|
|
@@ -1718,7 +1761,7 @@ var OnePasswordKeyProvider = class _OnePasswordKeyProvider {
|
|
|
1718
1761
|
}
|
|
1719
1762
|
};
|
|
1720
1763
|
async function execCommand(command, args) {
|
|
1721
|
-
return new Promise((
|
|
1764
|
+
return new Promise((resolve5, reject) => {
|
|
1722
1765
|
const proc = child_process.spawn(command, args, { stdio: ["ignore", "pipe", "pipe"] });
|
|
1723
1766
|
let stdout = "";
|
|
1724
1767
|
let stderr = "";
|
|
@@ -1730,7 +1773,7 @@ async function execCommand(command, args) {
|
|
|
1730
1773
|
});
|
|
1731
1774
|
proc.on("close", (code) => {
|
|
1732
1775
|
if (code === 0) {
|
|
1733
|
-
|
|
1776
|
+
resolve5(stdout.trim());
|
|
1734
1777
|
} else {
|
|
1735
1778
|
reject(new Error(`Command failed with exit code ${String(code)}: ${stderr}`));
|
|
1736
1779
|
}
|
|
@@ -1932,7 +1975,7 @@ var MacOSKeychainKeyProvider = class _MacOSKeychainKeyProvider {
|
|
|
1932
1975
|
}
|
|
1933
1976
|
};
|
|
1934
1977
|
async function execCommand2(command, args) {
|
|
1935
|
-
return new Promise((
|
|
1978
|
+
return new Promise((resolve5, reject) => {
|
|
1936
1979
|
const proc = child_process.spawn(command, args, { stdio: ["ignore", "pipe", "pipe"] });
|
|
1937
1980
|
let stdout = "";
|
|
1938
1981
|
let stderr = "";
|
|
@@ -1944,7 +1987,7 @@ async function execCommand2(command, args) {
|
|
|
1944
1987
|
});
|
|
1945
1988
|
proc.on("close", (code) => {
|
|
1946
1989
|
if (code === 0) {
|
|
1947
|
-
|
|
1990
|
+
resolve5(stdout.trim());
|
|
1948
1991
|
} else {
|
|
1949
1992
|
reject(new Error(`Command failed with exit code ${String(code)}: ${stderr}`));
|
|
1950
1993
|
}
|
|
@@ -2105,16 +2148,19 @@ function loadLocalConfigSync(configPath) {
|
|
|
2105
2148
|
throw error;
|
|
2106
2149
|
}
|
|
2107
2150
|
}
|
|
2151
|
+
var IDENTITY_SCHEMA_HEADER = "# yaml-language-server: $schema=https://raw.githubusercontent.com/mike-north/attest-it/main/schemas/v1/identity.schema.json\n";
|
|
2108
2152
|
async function saveLocalConfig(config, configPath) {
|
|
2109
2153
|
const resolvedPath = configPath ?? getLocalConfigPath();
|
|
2110
|
-
const
|
|
2154
|
+
const yamlContent = yaml.stringify(config);
|
|
2155
|
+
const content = IDENTITY_SCHEMA_HEADER + yamlContent;
|
|
2111
2156
|
const dir = path2.dirname(resolvedPath);
|
|
2112
2157
|
await fs8.mkdir(dir, { recursive: true });
|
|
2113
2158
|
await fs8.writeFile(resolvedPath, content, "utf8");
|
|
2114
2159
|
}
|
|
2115
2160
|
function saveLocalConfigSync(config, configPath) {
|
|
2116
2161
|
const resolvedPath = configPath ?? getLocalConfigPath();
|
|
2117
|
-
const
|
|
2162
|
+
const yamlContent = yaml.stringify(config);
|
|
2163
|
+
const content = IDENTITY_SCHEMA_HEADER + yamlContent;
|
|
2118
2164
|
const dir = path2.dirname(resolvedPath);
|
|
2119
2165
|
fs.mkdirSync(dir, { recursive: true });
|
|
2120
2166
|
fs.writeFileSync(resolvedPath, content, "utf8");
|
|
@@ -2145,13 +2191,6 @@ async function savePublicKey(slug, publicKey, projectRoot = process.cwd()) {
|
|
|
2145
2191
|
const homePath = path2.join(homeDir, `${slug}.pem`);
|
|
2146
2192
|
await fs8.writeFile(homePath, publicKey, "utf8");
|
|
2147
2193
|
result.homePath = homePath;
|
|
2148
|
-
if (hasProjectConfig(projectRoot)) {
|
|
2149
|
-
const projectDir = getProjectPublicKeysDir(projectRoot);
|
|
2150
|
-
await fs8.mkdir(projectDir, { recursive: true });
|
|
2151
|
-
const projectPath = path2.join(projectDir, `${slug}.pem`);
|
|
2152
|
-
await fs8.writeFile(projectPath, publicKey, "utf8");
|
|
2153
|
-
result.projectPath = projectPath;
|
|
2154
|
-
}
|
|
2155
2194
|
return result;
|
|
2156
2195
|
}
|
|
2157
2196
|
function savePublicKeySync(slug, publicKey, projectRoot = process.cwd()) {
|
|
@@ -2163,13 +2202,6 @@ function savePublicKeySync(slug, publicKey, projectRoot = process.cwd()) {
|
|
|
2163
2202
|
const homePath = path2.join(homeDir, `${slug}.pem`);
|
|
2164
2203
|
fs.writeFileSync(homePath, publicKey, "utf8");
|
|
2165
2204
|
result.homePath = homePath;
|
|
2166
|
-
if (hasProjectConfig(projectRoot)) {
|
|
2167
|
-
const projectDir = getProjectPublicKeysDir(projectRoot);
|
|
2168
|
-
fs.mkdirSync(projectDir, { recursive: true });
|
|
2169
|
-
const projectPath = path2.join(projectDir, `${slug}.pem`);
|
|
2170
|
-
fs.writeFileSync(projectPath, publicKey, "utf8");
|
|
2171
|
-
result.projectPath = projectPath;
|
|
2172
|
-
}
|
|
2173
2205
|
return result;
|
|
2174
2206
|
}
|
|
2175
2207
|
|
|
@@ -2609,7 +2641,7 @@ var YubiKeyProvider = class _YubiKeyProvider {
|
|
|
2609
2641
|
}
|
|
2610
2642
|
};
|
|
2611
2643
|
async function execCommand3(command, args) {
|
|
2612
|
-
return new Promise((
|
|
2644
|
+
return new Promise((resolve5, reject) => {
|
|
2613
2645
|
const proc = child_process.spawn(command, args, { stdio: ["ignore", "pipe", "pipe"] });
|
|
2614
2646
|
let stdout = "";
|
|
2615
2647
|
let stderr = "";
|
|
@@ -2621,7 +2653,7 @@ async function execCommand3(command, args) {
|
|
|
2621
2653
|
});
|
|
2622
2654
|
proc.on("close", (code) => {
|
|
2623
2655
|
if (code === 0) {
|
|
2624
|
-
|
|
2656
|
+
resolve5(stdout.trim());
|
|
2625
2657
|
} else {
|
|
2626
2658
|
reject(new Error(`Command failed with exit code ${String(code)}: ${stderr}`));
|
|
2627
2659
|
}
|
|
@@ -2924,8 +2956,8 @@ ${issues}`);
|
|
|
2924
2956
|
}
|
|
2925
2957
|
return result.data;
|
|
2926
2958
|
}
|
|
2927
|
-
async function readSeals(dir) {
|
|
2928
|
-
const sealsPath = path2__namespace.join(dir, ".attest-it", "seals.json");
|
|
2959
|
+
async function readSeals(dir, sealsPathOverride) {
|
|
2960
|
+
const sealsPath = sealsPathOverride ? path2__namespace.resolve(dir, sealsPathOverride) : path2__namespace.join(dir, ".attest-it", "seals.json");
|
|
2929
2961
|
try {
|
|
2930
2962
|
const content = await fs__namespace.promises.readFile(sealsPath, "utf8");
|
|
2931
2963
|
return parseSealsContent(content);
|
|
@@ -2941,8 +2973,8 @@ async function readSeals(dir) {
|
|
|
2941
2973
|
);
|
|
2942
2974
|
}
|
|
2943
2975
|
}
|
|
2944
|
-
function readSealsSync(dir) {
|
|
2945
|
-
const sealsPath = path2__namespace.join(dir, ".attest-it", "seals.json");
|
|
2976
|
+
function readSealsSync(dir, sealsPathOverride) {
|
|
2977
|
+
const sealsPath = sealsPathOverride ? path2__namespace.resolve(dir, sealsPathOverride) : path2__namespace.join(dir, ".attest-it", "seals.json");
|
|
2946
2978
|
try {
|
|
2947
2979
|
const content = fs__namespace.readFileSync(sealsPath, "utf8");
|
|
2948
2980
|
return parseSealsContent(content);
|
|
@@ -2958,11 +2990,11 @@ function readSealsSync(dir) {
|
|
|
2958
2990
|
);
|
|
2959
2991
|
}
|
|
2960
2992
|
}
|
|
2961
|
-
async function writeSeals(dir, sealsFile) {
|
|
2962
|
-
const
|
|
2963
|
-
const
|
|
2993
|
+
async function writeSeals(dir, sealsFile, sealsPathOverride) {
|
|
2994
|
+
const sealsPath = sealsPathOverride ? path2__namespace.resolve(dir, sealsPathOverride) : path2__namespace.join(dir, ".attest-it", "seals.json");
|
|
2995
|
+
const sealsDir = path2__namespace.dirname(sealsPath);
|
|
2964
2996
|
try {
|
|
2965
|
-
await fs__namespace.promises.mkdir(
|
|
2997
|
+
await fs__namespace.promises.mkdir(sealsDir, { recursive: true });
|
|
2966
2998
|
const content = JSON.stringify(sealsFile, null, 2) + "\n";
|
|
2967
2999
|
await fs__namespace.promises.writeFile(sealsPath, content, "utf8");
|
|
2968
3000
|
} catch (error) {
|
|
@@ -2971,11 +3003,11 @@ async function writeSeals(dir, sealsFile) {
|
|
|
2971
3003
|
);
|
|
2972
3004
|
}
|
|
2973
3005
|
}
|
|
2974
|
-
function writeSealsSync(dir, sealsFile) {
|
|
2975
|
-
const
|
|
2976
|
-
const
|
|
3006
|
+
function writeSealsSync(dir, sealsFile, sealsPathOverride) {
|
|
3007
|
+
const sealsPath = sealsPathOverride ? path2__namespace.resolve(dir, sealsPathOverride) : path2__namespace.join(dir, ".attest-it", "seals.json");
|
|
3008
|
+
const sealsDir = path2__namespace.dirname(sealsPath);
|
|
2977
3009
|
try {
|
|
2978
|
-
fs__namespace.mkdirSync(
|
|
3010
|
+
fs__namespace.mkdirSync(sealsDir, { recursive: true });
|
|
2979
3011
|
const content = JSON.stringify(sealsFile, null, 2) + "\n";
|
|
2980
3012
|
fs__namespace.writeFileSync(sealsPath, content, "utf8");
|
|
2981
3013
|
} catch (error) {
|