@soulcraft/brainy 5.3.3 → 5.3.4

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/brainy.js CHANGED
@@ -2031,9 +2031,11 @@ export class Brainy {
2031
2031
  // Get current state statistics
2032
2032
  const entityCount = await this.getNounCount();
2033
2033
  const relationshipCount = await this.getVerbCount();
2034
+ // v5.3.4: Import NULL_HASH constant
2035
+ const { NULL_HASH } = await import('./storage/cow/constants.js');
2034
2036
  // Build commit object using builder pattern
2035
2037
  const builder = CommitBuilder.create(blobStorage)
2036
- .tree('0000000000000000000000000000000000000000000000000000000000000000') // Empty tree hash for now
2038
+ .tree(NULL_HASH) // Empty tree hash (sentinel value)
2037
2039
  .message(options?.message || 'Snapshot commit')
2038
2040
  .author(options?.author || 'unknown')
2039
2041
  .timestamp(Date.now())
@@ -222,7 +222,9 @@ export class BaseStorage extends BaseStorageAdapter {
222
222
  const mainRef = await this.refManager.getRef('main');
223
223
  if (!mainRef) {
224
224
  // Create initial commit with empty tree
225
- const emptyTreeHash = '0000000000000000000000000000000000000000000000000000000000000000';
225
+ // v5.3.4: Use NULL_HASH constant instead of hardcoded string
226
+ const { NULL_HASH } = await import('./cow/constants.js');
227
+ const emptyTreeHash = NULL_HASH;
226
228
  // Import CommitBuilder
227
229
  const { CommitBuilder } = await import('./cow/CommitObject.js');
228
230
  // Create initial commit object
@@ -14,6 +14,7 @@
14
14
  * @module storage/cow/BlobStorage
15
15
  */
16
16
  import { createHash } from 'crypto';
17
+ import { NULL_HASH, isNullHash } from './constants.js';
17
18
  /**
18
19
  * State-of-the-art content-addressable blob storage
19
20
  *
@@ -162,6 +163,15 @@ export class BlobStorage {
162
163
  * @returns Blob data
163
164
  */
164
165
  async read(hash, options = {}) {
166
+ // v5.3.4 fix: Guard against NULL hash (sentinel value)
167
+ // NULL_HASH ('0000...0000') is used as a sentinel for "no parent" or "empty tree"
168
+ // It should NEVER be read as actual blob data
169
+ if (isNullHash(hash)) {
170
+ throw new Error(`Cannot read NULL hash (${NULL_HASH}): ` +
171
+ `This is a sentinel value indicating "no parent commit" or "empty tree". ` +
172
+ `If you're seeing this error from CommitObject.walk(), there's a bug in commit traversal logic. ` +
173
+ `If you're seeing this from TreeObject operations, there's a bug in tree handling.`);
174
+ }
165
175
  // Check cache first
166
176
  if (!options.skipCache) {
167
177
  const cached = this.getFromCache(hash);
@@ -15,6 +15,7 @@
15
15
  * @module storage/cow/CommitObject
16
16
  */
17
17
  import { BlobStorage } from './BlobStorage.js';
18
+ import { isNullHash } from './constants.js';
18
19
  /**
19
20
  * CommitBuilder: Fluent API for building commit objects
20
21
  *
@@ -269,7 +270,10 @@ export class CommitObject {
269
270
  static async *walk(blobStorage, startHash, options) {
270
271
  let currentHash = startHash;
271
272
  let depth = 0;
272
- while (currentHash) {
273
+ // v5.3.4 fix: Guard against NULL hash (sentinel for "no parent")
274
+ // The initial commit has parent = null or NULL_HASH ('0000...0000')
275
+ // We must stop walking when we reach it, not try to read it
276
+ while (currentHash && !isNullHash(currentHash)) {
273
277
  // Check max depth
274
278
  if (options?.maxDepth && depth >= options.maxDepth) {
275
279
  break;
@@ -291,7 +295,7 @@ export class CommitObject {
291
295
  if (options?.stopAt && currentHash === options.stopAt) {
292
296
  break;
293
297
  }
294
- // Move to parent
298
+ // Move to parent (can be null or NULL_HASH for initial commit)
295
299
  currentHash = commit.parent;
296
300
  depth++;
297
301
  }
@@ -0,0 +1,48 @@
1
+ /**
2
+ * COW Storage Constants
3
+ *
4
+ * Sentinel values and utilities for Copy-On-Write storage system.
5
+ *
6
+ * @module storage/cow/constants
7
+ */
8
+ /**
9
+ * NULL_HASH - Sentinel value for "no parent commit" or "empty tree"
10
+ *
11
+ * In Git-like COW systems, we need a way to represent:
12
+ * - Initial commit (has no parent)
13
+ * - Empty tree (contains no files)
14
+ *
15
+ * We use a 64-character zero hash as a sentinel value.
16
+ * This should NEVER be used as an actual content hash.
17
+ *
18
+ * @constant
19
+ * @example
20
+ * ```typescript
21
+ * const builder = CommitBuilder.create(storage)
22
+ * .tree(NULL_HASH) // Empty tree
23
+ * .parent(null) // No parent (use null, not NULL_HASH)
24
+ * .build()
25
+ * ```
26
+ */
27
+ export declare const NULL_HASH = "0000000000000000000000000000000000000000000000000000000000000000";
28
+ /**
29
+ * Check if a hash is the NULL sentinel value
30
+ *
31
+ * @param hash - Hash to check (can be string or null)
32
+ * @returns true if hash is null or NULL_HASH
33
+ *
34
+ * @example
35
+ * ```typescript
36
+ * if (isNullHash(commit.parent)) {
37
+ * console.log('This is the initial commit')
38
+ * }
39
+ * ```
40
+ */
41
+ export declare function isNullHash(hash: string | null | undefined): boolean;
42
+ /**
43
+ * Check if a hash is valid (non-null, non-empty, proper format)
44
+ *
45
+ * @param hash - Hash to check
46
+ * @returns true if hash is a valid SHA-256 hash
47
+ */
48
+ export declare function isValidHash(hash: string | null | undefined): boolean;
@@ -0,0 +1,57 @@
1
+ /**
2
+ * COW Storage Constants
3
+ *
4
+ * Sentinel values and utilities for Copy-On-Write storage system.
5
+ *
6
+ * @module storage/cow/constants
7
+ */
8
+ /**
9
+ * NULL_HASH - Sentinel value for "no parent commit" or "empty tree"
10
+ *
11
+ * In Git-like COW systems, we need a way to represent:
12
+ * - Initial commit (has no parent)
13
+ * - Empty tree (contains no files)
14
+ *
15
+ * We use a 64-character zero hash as a sentinel value.
16
+ * This should NEVER be used as an actual content hash.
17
+ *
18
+ * @constant
19
+ * @example
20
+ * ```typescript
21
+ * const builder = CommitBuilder.create(storage)
22
+ * .tree(NULL_HASH) // Empty tree
23
+ * .parent(null) // No parent (use null, not NULL_HASH)
24
+ * .build()
25
+ * ```
26
+ */
27
+ export const NULL_HASH = '0000000000000000000000000000000000000000000000000000000000000000';
28
+ /**
29
+ * Check if a hash is the NULL sentinel value
30
+ *
31
+ * @param hash - Hash to check (can be string or null)
32
+ * @returns true if hash is null or NULL_HASH
33
+ *
34
+ * @example
35
+ * ```typescript
36
+ * if (isNullHash(commit.parent)) {
37
+ * console.log('This is the initial commit')
38
+ * }
39
+ * ```
40
+ */
41
+ export function isNullHash(hash) {
42
+ return hash === null || hash === undefined || hash === NULL_HASH;
43
+ }
44
+ /**
45
+ * Check if a hash is valid (non-null, non-empty, proper format)
46
+ *
47
+ * @param hash - Hash to check
48
+ * @returns true if hash is a valid SHA-256 hash
49
+ */
50
+ export function isValidHash(hash) {
51
+ if (isNullHash(hash)) {
52
+ return false;
53
+ }
54
+ // SHA-256 hash must be exactly 64 hexadecimal characters
55
+ return typeof hash === 'string' && /^[a-f0-9]{64}$/.test(hash);
56
+ }
57
+ //# sourceMappingURL=constants.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@soulcraft/brainy",
3
- "version": "5.3.3",
3
+ "version": "5.3.4",
4
4
  "description": "Universal Knowledge Protocol™ - World's first Triple Intelligence database unifying vector, graph, and document search in one API. 31 nouns × 40 verbs for infinite expressiveness.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",