@highstate/backend 0.9.37 → 0.11.3
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/highstate.manifest.json +5 -5
- package/dist/index.js +44 -15
- package/dist/index.js.map +1 -1
- package/package.json +18 -22
- package/src/database/local/backend.ts +20 -9
- package/src/database/local/keyring.test.ts +89 -0
- package/src/database/local/keyring.ts +52 -2
- package/src/terminal/run.sh.ts +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"sourceHashes": {
|
|
3
|
-
"./dist/index.js":
|
|
4
|
-
"./dist/shared/index.js":
|
|
5
|
-
"./dist/library/worker/main.js":
|
|
6
|
-
"./dist/library/package-resolution-worker.js":
|
|
7
|
-
"./dist/database/local/prisma.config.js":
|
|
3
|
+
"./dist/index.js": 4290144902,
|
|
4
|
+
"./dist/shared/index.js": 1121681166,
|
|
5
|
+
"./dist/library/worker/main.js": 875302514,
|
|
6
|
+
"./dist/library/package-resolution-worker.js": 1596195914,
|
|
7
|
+
"./dist/database/local/prisma.config.js": 4014074705
|
|
8
8
|
}
|
|
9
9
|
}
|
package/dist/index.js
CHANGED
|
@@ -5,7 +5,7 @@ import { randomBytes, createHash } from 'node:crypto';
|
|
|
5
5
|
import { createId } from '@paralleldrive/cuid2';
|
|
6
6
|
import { hubModelSchema, instanceModelSchema, parseInstanceId, isUnitModel, HighstateConfigKey, unitArtifactSchema, unitArtifactId, unitWorkerSchema, unitTriggerSchema, unitPageSchema, unitTerminalSchema, instanceStatusFieldSchema, getInstanceId } from '@highstate/contract';
|
|
7
7
|
import { omit, isNonNullish, groupBy, mapValues, unique, join as join$1, omitBy } from 'remeda';
|
|
8
|
-
import
|
|
8
|
+
import z4, { z } from 'zod';
|
|
9
9
|
import * as os from 'node:os';
|
|
10
10
|
import { tmpdir, hostname } from 'node:os';
|
|
11
11
|
import { PrismaLibSQL } from '@prisma/adapter-libsql';
|
|
@@ -18,8 +18,8 @@ import { PrismaClientKnownRequestError } from '@prisma/client/runtime/client';
|
|
|
18
18
|
import { execa } from 'execa';
|
|
19
19
|
import { resolve } from 'import-meta-resolve';
|
|
20
20
|
import { detectPackageManager, runScript, addDependency, ensureDependencyInstalled } from 'nypm';
|
|
21
|
+
import { readFile, mkdir, writeFile, access, unlink, readdir, rm, mkdtemp } from 'node:fs/promises';
|
|
21
22
|
import { findCredentialsAsync, AsyncEntry } from '@napi-rs/keyring';
|
|
22
|
-
import { mkdir, readFile, writeFile, access, unlink, readdir, rm, mkdtemp } from 'node:fs/promises';
|
|
23
23
|
import { stringify, parse } from 'yaml';
|
|
24
24
|
import { LRUCache } from 'lru-cache';
|
|
25
25
|
import { ulid } from 'ulid';
|
|
@@ -726,11 +726,33 @@ async function ensureWellKnownEntitiesCreated(database) {
|
|
|
726
726
|
}
|
|
727
727
|
var serviceName = "io.highstate.backend";
|
|
728
728
|
var accountName = "identity";
|
|
729
|
-
|
|
729
|
+
var backendIdentityConfig = z.object({
|
|
730
|
+
HIGHSTATE_BACKEND_DATABASE_IDENTITY: z.string().optional(),
|
|
731
|
+
HIGHSTATE_BACKEND_DATABASE_IDENTITY_PATH: z.string().optional()
|
|
732
|
+
});
|
|
733
|
+
async function getOrCreateBackendIdentity(config4, logger) {
|
|
734
|
+
if (config4.HIGHSTATE_BACKEND_DATABASE_IDENTITY) {
|
|
735
|
+
logger.info("using backend identity from HIGHSTATE_BACKEND_DATABASE_IDENTITY");
|
|
736
|
+
return config4.HIGHSTATE_BACKEND_DATABASE_IDENTITY;
|
|
737
|
+
}
|
|
738
|
+
if (config4.HIGHSTATE_BACKEND_DATABASE_IDENTITY_PATH) {
|
|
739
|
+
try {
|
|
740
|
+
const identity = await readFile(config4.HIGHSTATE_BACKEND_DATABASE_IDENTITY_PATH, "utf-8");
|
|
741
|
+
logger.info(
|
|
742
|
+
`using backend identity from path specified in HIGHSTATE_BACKEND_DATABASE_IDENTITY_PATH`
|
|
743
|
+
);
|
|
744
|
+
return identity.trim();
|
|
745
|
+
} catch (error) {
|
|
746
|
+
throw new Error(
|
|
747
|
+
`Failed to read backend identity from "${config4.HIGHSTATE_BACKEND_DATABASE_IDENTITY_PATH}"`,
|
|
748
|
+
{ cause: error }
|
|
749
|
+
);
|
|
750
|
+
}
|
|
751
|
+
}
|
|
730
752
|
const credentials = await findCredentialsAsync(serviceName);
|
|
731
753
|
const entry = credentials.find((entry2) => entry2.account === accountName);
|
|
732
754
|
if (entry) {
|
|
733
|
-
logger.
|
|
755
|
+
logger.info("using backend identity from OS keyring");
|
|
734
756
|
return entry.password;
|
|
735
757
|
}
|
|
736
758
|
const newIdentity = await generateIdentity();
|
|
@@ -772,12 +794,14 @@ async function writeMetaFile(databasePath, meta) {
|
|
|
772
794
|
var localBackendDatabaseConfig = z.object({
|
|
773
795
|
...codebaseConfig.shape,
|
|
774
796
|
HIGHSTATE_BACKEND_DATABASE_LOCAL_PATH: z.string().optional(),
|
|
797
|
+
...backendIdentityConfig.shape,
|
|
775
798
|
HIGHSTATE_ENCRYPTION_ENABLED: z.stringbool().default(true)
|
|
776
799
|
});
|
|
777
800
|
var LocalBackendDatabaseBackend = class {
|
|
778
|
-
constructor(database, databasePath, logger, isEncryptionEnabled) {
|
|
801
|
+
constructor(database, databasePath, config4, logger, isEncryptionEnabled) {
|
|
779
802
|
this.database = database;
|
|
780
803
|
this.databasePath = databasePath;
|
|
804
|
+
this.config = config4;
|
|
781
805
|
this.logger = logger;
|
|
782
806
|
this.isEncryptionEnabled = isEncryptionEnabled;
|
|
783
807
|
}
|
|
@@ -798,7 +822,7 @@ var LocalBackendDatabaseBackend = class {
|
|
|
798
822
|
);
|
|
799
823
|
return;
|
|
800
824
|
}
|
|
801
|
-
const identity = await getOrCreateBackendIdentity(this.logger);
|
|
825
|
+
const identity = await getOrCreateBackendIdentity(this.config, this.logger);
|
|
802
826
|
const decrypter = new Decrypter();
|
|
803
827
|
decrypter.addIdentity(identity);
|
|
804
828
|
const plaintextMasterKey = await decrypter.decrypt(armor.decode(meta.masterKey), "text");
|
|
@@ -815,8 +839,8 @@ var LocalBackendDatabaseBackend = class {
|
|
|
815
839
|
});
|
|
816
840
|
}
|
|
817
841
|
};
|
|
818
|
-
async function createMasterKey(logger) {
|
|
819
|
-
const identity = await getOrCreateBackendIdentity(logger);
|
|
842
|
+
async function createMasterKey(config4, logger) {
|
|
843
|
+
const identity = await getOrCreateBackendIdentity(config4, logger);
|
|
820
844
|
const masterKey = randomBytes(32).toString("hex");
|
|
821
845
|
const encrypter = new Encrypter();
|
|
822
846
|
const recipient = await identityToRecipient(identity);
|
|
@@ -825,11 +849,11 @@ async function createMasterKey(logger) {
|
|
|
825
849
|
const armoredMasterKey = armor.encode(encryptedMasterKey);
|
|
826
850
|
return { armoredMasterKey, masterKey, recipient };
|
|
827
851
|
}
|
|
828
|
-
async function ensureDatabaseInitialized(databasePath, encryptionEnabled, logger) {
|
|
852
|
+
async function ensureDatabaseInitialized(databasePath, encryptionEnabled, config4, logger) {
|
|
829
853
|
const meta = await readMetaFile(databasePath);
|
|
830
854
|
if (!meta) {
|
|
831
855
|
logger.info("creating new database");
|
|
832
|
-
const masterKey2 = encryptionEnabled ? await createMasterKey(logger) : void 0;
|
|
856
|
+
const masterKey2 = encryptionEnabled ? await createMasterKey(config4, logger) : void 0;
|
|
833
857
|
const metaFile = {
|
|
834
858
|
version: backendDatabaseVersion,
|
|
835
859
|
masterKey: masterKey2?.armoredMasterKey
|
|
@@ -860,12 +884,11 @@ async function ensureDatabaseInitialized(databasePath, encryptionEnabled, logger
|
|
|
860
884
|
`Database meta file at "${databasePath}/backend.meta.yaml" does not contain a master key.`
|
|
861
885
|
);
|
|
862
886
|
}
|
|
863
|
-
const identity = await getOrCreateBackendIdentity(logger);
|
|
887
|
+
const identity = await getOrCreateBackendIdentity(config4, logger);
|
|
864
888
|
const decrypter = new Decrypter();
|
|
865
889
|
decrypter.addIdentity(identity);
|
|
866
890
|
const encryptedMasterKey = armor.decode(meta.masterKey);
|
|
867
891
|
const masterKey = await decrypter.decrypt(encryptedMasterKey, "text");
|
|
868
|
-
logger.info("loaded backend master key using OS keyring");
|
|
869
892
|
return {
|
|
870
893
|
shouldMigrate: meta.version < backendDatabaseVersion,
|
|
871
894
|
masterKey,
|
|
@@ -879,7 +902,12 @@ async function createLocalBackendDatabaseBackend(config4, logger) {
|
|
|
879
902
|
}
|
|
880
903
|
let databasePath = config4.HIGHSTATE_BACKEND_DATABASE_LOCAL_PATH;
|
|
881
904
|
databasePath ??= await getCodebaseHighstatePath(config4, logger);
|
|
882
|
-
const { shouldMigrate, masterKey, metaFile, created, initialRecipient } = await ensureDatabaseInitialized(
|
|
905
|
+
const { shouldMigrate, masterKey, metaFile, created, initialRecipient } = await ensureDatabaseInitialized(
|
|
906
|
+
databasePath,
|
|
907
|
+
config4.HIGHSTATE_ENCRYPTION_ENABLED,
|
|
908
|
+
config4,
|
|
909
|
+
logger
|
|
910
|
+
);
|
|
883
911
|
const databaseUrl = `file:${databasePath}/backend.db`;
|
|
884
912
|
if (shouldMigrate) {
|
|
885
913
|
await migrateDatabase(databaseUrl, "backend/sqlite", masterKey, logger);
|
|
@@ -900,6 +928,7 @@ async function createLocalBackendDatabaseBackend(config4, logger) {
|
|
|
900
928
|
return new LocalBackendDatabaseBackend(
|
|
901
929
|
database,
|
|
902
930
|
databasePath,
|
|
931
|
+
config4,
|
|
903
932
|
backendLogger,
|
|
904
933
|
config4.HIGHSTATE_ENCRYPTION_ENABLED
|
|
905
934
|
);
|
|
@@ -1139,8 +1168,8 @@ var LocalProjectDatabaseBackend = class _LocalProjectDatabaseBackend {
|
|
|
1139
1168
|
return new _LocalProjectDatabaseBackend(highstatePath);
|
|
1140
1169
|
}
|
|
1141
1170
|
};
|
|
1142
|
-
var databaseManagerConfig =
|
|
1143
|
-
HIGHSTATE_ENCRYPTION_ENABLED:
|
|
1171
|
+
var databaseManagerConfig = z4.object({
|
|
1172
|
+
HIGHSTATE_ENCRYPTION_ENABLED: z4.stringbool().default(true)
|
|
1144
1173
|
});
|
|
1145
1174
|
var DatabaseManagerImpl = class {
|
|
1146
1175
|
constructor(backendBackend, projectUnlockBackend, projectDatabaseBackend, config4, logger) {
|