harperdb 4.6.6 → 4.7.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/LICENSE +0 -0
  2. package/README.md +1 -1
  3. package/bin/harperdb.js +89 -78
  4. package/bin/lite.js +85 -74
  5. package/components/requestRestart.d.ts +3 -0
  6. package/components/status/ComponentStatus.d.ts +61 -0
  7. package/components/status/ComponentStatusRegistry.d.ts +80 -0
  8. package/components/status/api.d.ts +104 -0
  9. package/components/status/crossThread.d.ts +62 -0
  10. package/components/status/errors.d.ts +68 -0
  11. package/components/status/index.d.ts +35 -0
  12. package/components/status/internal.d.ts +40 -0
  13. package/components/status/registry.d.ts +10 -0
  14. package/components/status/types.d.ts +75 -0
  15. package/json/systemSchema.json +68 -7
  16. package/launchServiceScripts/launchNatsIngestService.js +85 -74
  17. package/launchServiceScripts/launchNatsReplyService.js +85 -74
  18. package/launchServiceScripts/launchUpdateNodes4-0-0.js +85 -74
  19. package/npm-shrinkwrap.json +361 -71
  20. package/package.json +6 -6
  21. package/resources/RequestTarget.d.ts +1 -1
  22. package/resources/Resource.d.ts +3 -3
  23. package/resources/ResourceInterface.d.ts +33 -10
  24. package/resources/Resources.d.ts +1 -0
  25. package/resources/Table.d.ts +3 -3
  26. package/resources/analytics/hostnames.d.ts +3 -3
  27. package/resources/analytics/write.d.ts +2 -0
  28. package/resources/auditStore.d.ts +2 -0
  29. package/resources/databases.d.ts +3 -3
  30. package/resources/usageLicensing.d.ts +23 -0
  31. package/security/certificateVerification.d.ts +80 -0
  32. package/security/pkijs-ed25519-patch.d.ts +14 -0
  33. package/server/jobs/jobProcess.js +85 -74
  34. package/server/replication/knownNodes.d.ts +13 -1
  35. package/server/replication/replicationConnection.d.ts +2 -1
  36. package/server/status/index.d.ts +14 -5
  37. package/server/threads/threadServer.js +85 -74
  38. package/studio/build-local/asset-manifest.json +2 -2
  39. package/studio/build-local/index.html +1 -1
  40. package/studio/build-local/static/js/main.b93998e3.js +2 -0
  41. package/utility/hdbTerms.d.ts +8 -0
  42. package/utility/scripts/restartHdb.js +85 -74
  43. package/validation/usageLicensing.d.ts +34 -0
  44. package/studio/build-local/static/js/main.f9919fa0.js +0 -2
  45. /package/studio/build-local/static/js/{main.f9919fa0.js.LICENSE.txt → main.b93998e3.js.LICENSE.txt} +0 -0
@@ -1,8 +1,9 @@
1
1
  import { DatabaseTransaction } from './DatabaseTransaction.ts';
2
2
  import { OperationFunctionName } from '../server/serverHelpers/serverUtilities.ts';
3
- import { RequestTarget } from './RequestTarget';
3
+ import { RequestTarget } from './RequestTarget.ts';
4
+ import { Entry } from './RecordEncoder.ts';
4
5
  export interface ResourceInterface<Key = any, Record = any> {
5
- get?(id: Id): Promise<UpdatableRecord<Record>>;
6
+ get?(id: Id): Promise<Record>;
6
7
  get?(query: RequestTargetOrId): Promise<AsyncIterable<Record>>;
7
8
  put?(target: RequestTargetOrId, record: any): void;
8
9
  post?(target: RequestTargetOrId, record: any): void;
@@ -21,25 +22,25 @@ export interface User {
21
22
  username: string;
22
23
  }
23
24
  export interface Context {
24
- /** The user making the request */
25
+ /** The user making the request */
25
26
  user?: User;
26
- /** The database transaction object */
27
+ /** The database transaction object */
27
28
  transaction?: DatabaseTransaction;
28
- /** If the operation that will be performed with this context should check user authorization */
29
+ /** If the operation that will be performed with this context should check user authorization */
29
30
  authorize?: number;
30
- /** The last modification time of any data that has been accessed with this context */
31
+ /** The last modification time of any data that has been accessed with this context */
31
32
  lastModified?: number;
32
33
  /** The time at which a saved record should expire */
33
34
  expiresAt?: number;
34
- /** Indicates that caching should not be applied */
35
+ /** Indicates that caching should not be applied */
35
36
  noCache?: boolean;
36
- /** Indicates that values from the source data should be stored as a cached value */
37
+ /** Indicates that values from the source data should be stored as a cached value */
37
38
  noCacheStore?: boolean;
38
39
  /** Only return values from the table, and don't use data from the source */
39
40
  onlyIfCached?: boolean;
40
41
  /** Allows data from a caching table to be used if there is an error retrieving data from the source */
41
42
  staleIfError?: boolean;
42
- /** Indicates any cached data must be revalidated */
43
+ /** Indicates any cached data must be revalidated */
43
44
  mustRevalidate?: boolean;
44
45
  /** An array of nodes to replicate to */
45
46
  replicateTo?: string[];
@@ -52,6 +53,28 @@ export interface Context {
52
53
  resourceCache?: Map<Id, any>;
53
54
  _freezeRecords?: boolean;
54
55
  }
56
+ export interface SourceContext<TRequestContext = Context> {
57
+ /** The original request context passed from the caching layer */
58
+ requestContext: TRequestContext;
59
+ /** The existing record, from the existing entry (if any) */
60
+ replacingRecord?: any;
61
+ /** The existing database entry (if any) */
62
+ replacingEntry?: Entry;
63
+ /** The version/timestamp of the existing record */
64
+ replacingVersion?: number;
65
+ /** Indicates that values from the source data should NOT be stored as a cached value */
66
+ noCacheStore?: boolean;
67
+ /** Reference to the source Resource instance */
68
+ source?: ResourceInterface;
69
+ /** Shared resource cache from parent context for visibility of modifications */
70
+ resourceCache?: Map<Id, any>;
71
+ /** Database transaction for the context */
72
+ transaction?: DatabaseTransaction;
73
+ /** The time at which the cached entry should expire (ms since epoch) */
74
+ expiresAt?: number;
75
+ /** The last modification time of any data accessed with this context */
76
+ lastModified?: number;
77
+ }
55
78
  export type Operator = 'and' | 'or';
56
79
  type SearchType = 'equals' | 'contains' | 'starts_with' | 'ends_with' | 'greater_than' | 'greater_than_equal' | 'less_than' | 'less_than_equal' | 'between';
57
80
  export interface DirectCondition {
@@ -94,7 +117,7 @@ export interface SubscriptionRequest {
94
117
  export type Query = RequestTarget;
95
118
  export type RequestTargetOrId = RequestTarget | Id;
96
119
  export type Id = number | string | (number | string | null)[] | null;
97
- type UpdatableRecord<T> = T;
120
+ export type UpdatableRecord<T> = T;
98
121
  interface Subscription {
99
122
  }
100
123
  export {};
@@ -12,6 +12,7 @@ interface ResourceEntry {
12
12
  export declare class Resources extends Map<string, ResourceEntry> {
13
13
  isWorker: boolean;
14
14
  loginPath?: (request: any) => string;
15
+ allTypes: Map<any, any>;
15
16
  set(path: any, resource: any, exportTypes?: {
16
17
  [key: string]: boolean;
17
18
  }, force?: boolean): void;
@@ -203,7 +203,7 @@ export declare function makeTable(options: any): {
203
203
  get isCollection(): boolean;
204
204
  connect(incomingMessages: import("./IterableEventQueue.js").IterableEventQueue, query?: {}): AsyncIterable<any>;
205
205
  getId(): Id;
206
- getContext(): Context;
206
+ getContext(): Context | import("./ResourceInterface.ts").SourceContext;
207
207
  };
208
208
  name: any;
209
209
  primaryStore: any;
@@ -412,7 +412,7 @@ export declare function makeTable(options: any): {
412
412
  get isCollection(): boolean;
413
413
  connect(incomingMessages: import("./IterableEventQueue.js").IterableEventQueue, query?: {}): AsyncIterable<any>;
414
414
  getId(): Id;
415
- getContext(): Context;
415
+ getContext(): Context | import("./ResourceInterface.ts").SourceContext;
416
416
  }> | {
417
417
  #record: any;
418
418
  #changes: any;
@@ -574,7 +574,7 @@ export declare function makeTable(options: any): {
574
574
  get isCollection(): boolean;
575
575
  connect(incomingMessages: import("./IterableEventQueue.js").IterableEventQueue, query?: {}): AsyncIterable<any>;
576
576
  getId(): Id;
577
- getContext(): Context;
577
+ getContext(): Context | import("./ResourceInterface.ts").SourceContext;
578
578
  };
579
579
  _updateResource(resource: any, entry: any): void;
580
580
  getNewId(): any;
@@ -110,7 +110,7 @@ export declare function getAnalyticsHostnameTable(): {
110
110
  get isCollection(): boolean;
111
111
  connect(incomingMessages: import("../IterableEventQueue.js").IterableEventQueue, query?: {}): AsyncIterable<any>;
112
112
  getId(): import("../ResourceInterface.js").Id;
113
- getContext(): import("../ResourceInterface.js").Context;
113
+ getContext(): import("../ResourceInterface.js").Context | import("../ResourceInterface.js").SourceContext;
114
114
  };
115
115
  name: any;
116
116
  primaryStore: any;
@@ -250,7 +250,7 @@ export declare function getAnalyticsHostnameTable(): {
250
250
  get isCollection(): boolean;
251
251
  connect(incomingMessages: import("../IterableEventQueue.js").IterableEventQueue, query?: {}): AsyncIterable<any>;
252
252
  getId(): import("../ResourceInterface.js").Id;
253
- getContext(): import("../ResourceInterface.js").Context;
253
+ getContext(): import("../ResourceInterface.js").Context | import("../ResourceInterface.js").SourceContext;
254
254
  }> | {
255
255
  #record: any;
256
256
  #changes: any;
@@ -361,7 +361,7 @@ export declare function getAnalyticsHostnameTable(): {
361
361
  get isCollection(): boolean;
362
362
  connect(incomingMessages: import("../IterableEventQueue.js").IterableEventQueue, query?: {}): AsyncIterable<any>;
363
363
  getId(): import("../ResourceInterface.js").Id;
364
- getContext(): import("../ResourceInterface.js").Context;
364
+ getContext(): import("../ResourceInterface.js").Context | import("../ResourceInterface.js").SourceContext;
365
365
  };
366
366
  _updateResource(resource: any, entry: any): void;
367
367
  getNewId(): any;
@@ -23,6 +23,7 @@ export declare function setAnalyticsEnabled(enabled: boolean): void;
23
23
  */
24
24
  export declare function recordAction(value: Value, metric: string, path?: string, method?: string, type?: string): void;
25
25
  export declare function recordActionBinary(value: any, metric: any, path?: any, method?: any, type?: any): void;
26
+ export declare const analyticsDelay = 1000;
26
27
  export declare function addAnalyticsListener(callback: any): void;
27
28
  export declare function recordHostname(): Promise<void>;
28
29
  export interface Metric {
@@ -47,6 +48,7 @@ export declare function calculateCPUUtilization(resourceUsage: ResourceUsage, pe
47
48
  * new values for this time period.
48
49
  */
49
50
  export declare function diffResourceUsage(lastResourceUsage: ResourceUsage, resourceUsage: ResourceUsage): ResourceUsage;
51
+ export declare function onAnalyticsAggregate(callback: any): void;
50
52
  export {};
51
53
  /**
52
54
  * This section contains a possible/experimental approach to bucketing values as they come instead of pushing all into an array and sorting.
@@ -53,6 +53,7 @@ export declare function readAuditEntry(buffer: Uint8Array, start?: number, end?:
53
53
  previousLocalTime: any;
54
54
  readonly user: import("ordered-binary").Key;
55
55
  readonly encoded: Uint8Array<ArrayBufferLike>;
56
+ readonly size: number;
56
57
  getValue(store: any, fullRecord?: any, auditTime?: any): any;
57
58
  getBinaryValue(): Uint8Array<ArrayBufferLike>;
58
59
  extendedType: any;
@@ -70,6 +71,7 @@ export declare function readAuditEntry(buffer: Uint8Array, start?: number, end?:
70
71
  previousLocalTime?: undefined;
71
72
  readonly user?: undefined;
72
73
  readonly encoded?: undefined;
74
+ readonly size?: undefined;
73
75
  getValue?: undefined;
74
76
  getBinaryValue?: undefined;
75
77
  extendedType?: undefined;
@@ -187,7 +187,7 @@ export declare function table(tableDefinition: TableDefinition): {
187
187
  get isCollection(): boolean;
188
188
  connect(incomingMessages: import("./IterableEventQueue.js").IterableEventQueue, query?: {}): AsyncIterable<any>;
189
189
  getId(): import("./ResourceInterface.js").Id;
190
- getContext(): import("./ResourceInterface.js").Context;
190
+ getContext(): import("./ResourceInterface.js").Context | import("./ResourceInterface.js").SourceContext;
191
191
  };
192
192
  name: any;
193
193
  primaryStore: any;
@@ -327,7 +327,7 @@ export declare function table(tableDefinition: TableDefinition): {
327
327
  get isCollection(): boolean;
328
328
  connect(incomingMessages: import("./IterableEventQueue.js").IterableEventQueue, query?: {}): AsyncIterable<any>;
329
329
  getId(): import("./ResourceInterface.js").Id;
330
- getContext(): import("./ResourceInterface.js").Context;
330
+ getContext(): import("./ResourceInterface.js").Context | import("./ResourceInterface.js").SourceContext;
331
331
  }> | {
332
332
  #record: any;
333
333
  #changes: any;
@@ -438,7 +438,7 @@ export declare function table(tableDefinition: TableDefinition): {
438
438
  get isCollection(): boolean;
439
439
  connect(incomingMessages: import("./IterableEventQueue.js").IterableEventQueue, query?: {}): AsyncIterable<any>;
440
440
  getId(): import("./ResourceInterface.js").Id;
441
- getContext(): import("./ResourceInterface.js").Context;
441
+ getContext(): import("./ResourceInterface.js").Context | import("./ResourceInterface.js").SourceContext;
442
442
  };
443
443
  _updateResource(resource: any, entry: any): void;
444
444
  getNewId(): any;
@@ -0,0 +1,23 @@
1
+ import { ValidatedLicense } from '../validation/usageLicensing.ts';
2
+ interface InstallLicenseRequest {
3
+ operation: 'install_usage_license';
4
+ license: string;
5
+ }
6
+ export declare function installUsageLicenseOp(req: InstallLicenseRequest): Promise<string>;
7
+ interface UsageLicense extends ValidatedLicense {
8
+ usedReads: number;
9
+ usedReadBytes: number;
10
+ usedWrites: number;
11
+ usedWriteBytes: number;
12
+ usedRealTimeMessages: number;
13
+ usedRealTimeBytes: number;
14
+ usedCpuTime: number;
15
+ }
16
+ interface UsageLicenseRecord extends UsageLicense {
17
+ addTo: (field: string, value: number) => void;
18
+ }
19
+ interface GetUsageLicensesReq {
20
+ operation: 'get_usage_licenses';
21
+ }
22
+ export declare function getUsageLicensesOp(req: GetUsageLicensesReq): AsyncIterable<UsageLicenseRecord>;
23
+ export {};
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Certificate verification for mTLS authentication
3
+ *
4
+ * This module provides certificate revocation checking for client certificates
5
+ * in mutual TLS (mTLS) connections. Currently supports OCSP (Online Certificate
6
+ * Status Protocol) with the ability to add CRL (Certificate Revocation List) support.
7
+ * Uses a system table, hdb_certificate_cache, for a certificate verification
8
+ * status cache.
9
+ *
10
+ * Default configuration:
11
+ * - Enabled by default when mTLS is configured
12
+ * - Timeout: 5 seconds
13
+ * - Cache TTL: 1 hour
14
+ * - Failure mode: fail-open (allows connections if verification fails)
15
+ */
16
+ import './pkijs-ed25519-patch.ts';
17
+ interface CertificateVerificationResult {
18
+ valid: boolean;
19
+ status: string;
20
+ cached?: boolean;
21
+ error?: string;
22
+ method?: 'ocsp' | 'crl' | 'disabled';
23
+ }
24
+ interface PeerCertificate {
25
+ subject?: {
26
+ CN?: string;
27
+ [key: string]: any;
28
+ };
29
+ raw?: Buffer;
30
+ issuerCertificate?: PeerCertificate;
31
+ }
32
+ interface CertificateVerificationConfig {
33
+ timeout?: number;
34
+ cacheTtl?: number;
35
+ failureMode?: 'fail-open' | 'fail-closed';
36
+ }
37
+ interface CertificateChainEntry {
38
+ cert: Buffer;
39
+ issuer?: Buffer;
40
+ }
41
+ /**
42
+ * Determine if certificate verification should be performed based on configuration
43
+ * @param mtlsConfig - The mTLS configuration (can be boolean or object)
44
+ * @returns Configuration object or false if verification is disabled
45
+ */
46
+ export declare function getCertificateVerificationConfig(mtlsConfig: boolean | Record<string, any> | null | undefined): false | CertificateVerificationConfig;
47
+ /**
48
+ * Verify certificate revocation status
49
+ * @param peerCertificate - Peer certificate object from TLS connection
50
+ * @param mtlsConfig - The mTLS configuration from the request
51
+ * @returns Promise resolving to verification result
52
+ */
53
+ export declare function verifyCertificate(peerCertificate: PeerCertificate, mtlsConfig?: boolean | Record<string, any> | null): Promise<CertificateVerificationResult>;
54
+ /**
55
+ * Verify OCSP status of a client certificate
56
+ * @param certPem - Client certificate in PEM format or Buffer
57
+ * @param issuerPem - Issuer (CA) certificate in PEM format or Buffer
58
+ * @returns Promise resolving to verification result
59
+ */
60
+ export declare function verifyOCSP(certPem: Buffer | string, issuerPem: Buffer | string, config?: CertificateVerificationConfig): Promise<CertificateVerificationResult>;
61
+ /**
62
+ * Set TTL configuration for the certificate cache
63
+ * @param ttlConfig - Configuration for cache expiration and eviction
64
+ */
65
+ export declare function setCertificateCacheTTL(ttlConfig: {
66
+ expiration: number;
67
+ eviction?: number;
68
+ scanInterval?: number;
69
+ }): void;
70
+ /**
71
+ * Convert a buffer to PEM format
72
+ */
73
+ export declare function bufferToPem(buffer: Buffer, type: string): string;
74
+ /**
75
+ * Extract certificate chain from peer certificate object
76
+ * @param peerCertificate - Peer certificate object from TLS connection
77
+ * @returns Certificate chain
78
+ */
79
+ export declare function extractCertificateChain(peerCertificate: PeerCertificate): CertificateChainEntry[];
80
+ export {};
@@ -0,0 +1,14 @@
1
+ /**
2
+ * PKI.js Ed25519/Ed448 Support Patch
3
+ *
4
+ * This module patches PKI.js to add complete Ed25519/Ed448 support for certificate
5
+ * and OCSP response verification. While PKI.js has some Ed25519/Ed448 support,
6
+ * it currently lacks:
7
+ * - getHashAlgorithm() support for Ed25519/Ed448 OIDs
8
+ * - getAlgorithmByOID() recognition of Ed25519/Ed448
9
+ * - Certificate verification using Ed25519/Ed448 signatures
10
+ * - OCSP response signature verification with Ed25519/Ed448
11
+ *
12
+ * This patch must be loaded before any module that uses PKI.js (including easy-ocsp).
13
+ */
14
+ export declare function applyEd25519Patch(): void;