@haverstack/core 0.8.0 → 0.10.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.
Files changed (65) hide show
  1. package/README.md +30 -14
  2. package/dist/access.d.ts +20 -7
  3. package/dist/access.d.ts.map +1 -1
  4. package/dist/access.js +37 -16
  5. package/dist/access.js.map +1 -1
  6. package/dist/adapter-entry.d.ts +12 -0
  7. package/dist/adapter-entry.d.ts.map +1 -0
  8. package/dist/adapter-entry.js +11 -0
  9. package/dist/adapter-entry.js.map +1 -0
  10. package/dist/attachment-download.d.ts +75 -0
  11. package/dist/attachment-download.d.ts.map +1 -0
  12. package/dist/attachment-download.js +128 -0
  13. package/dist/attachment-download.js.map +1 -0
  14. package/dist/auth.d.ts +88 -0
  15. package/dist/auth.d.ts.map +1 -0
  16. package/dist/auth.js +145 -0
  17. package/dist/auth.js.map +1 -0
  18. package/dist/combine.d.ts.map +1 -1
  19. package/dist/combine.js +20 -3
  20. package/dist/combine.js.map +1 -1
  21. package/dist/did-entry.d.ts +12 -0
  22. package/dist/did-entry.d.ts.map +1 -0
  23. package/dist/did-entry.js +16 -0
  24. package/dist/did-entry.js.map +1 -0
  25. package/dist/did.d.ts +51 -0
  26. package/dist/did.d.ts.map +1 -0
  27. package/dist/did.js +153 -0
  28. package/dist/did.js.map +1 -0
  29. package/dist/id.d.ts +18 -6
  30. package/dist/id.d.ts.map +1 -1
  31. package/dist/id.js +39 -10
  32. package/dist/id.js.map +1 -1
  33. package/dist/index.d.ts +15 -10
  34. package/dist/index.d.ts.map +1 -1
  35. package/dist/index.js +14 -9
  36. package/dist/index.js.map +1 -1
  37. package/dist/merge.d.ts +11 -0
  38. package/dist/merge.d.ts.map +1 -0
  39. package/dist/merge.js +38 -0
  40. package/dist/merge.js.map +1 -0
  41. package/dist/schema.d.ts +31 -9
  42. package/dist/schema.d.ts.map +1 -1
  43. package/dist/schema.js +134 -11
  44. package/dist/schema.js.map +1 -1
  45. package/dist/stack.d.ts +850 -152
  46. package/dist/stack.d.ts.map +1 -1
  47. package/dist/stack.js +2017 -365
  48. package/dist/stack.js.map +1 -1
  49. package/dist/testing.d.ts +85 -23
  50. package/dist/testing.d.ts.map +1 -1
  51. package/dist/testing.js +261 -19
  52. package/dist/testing.js.map +1 -1
  53. package/dist/types.d.ts +281 -31
  54. package/dist/types.d.ts.map +1 -1
  55. package/dist/types.js +14 -0
  56. package/dist/types.js.map +1 -1
  57. package/dist/validate.d.ts +26 -0
  58. package/dist/validate.d.ts.map +1 -1
  59. package/dist/validate.js +51 -1
  60. package/dist/validate.js.map +1 -1
  61. package/dist/wire-entry.d.ts +17 -0
  62. package/dist/wire-entry.d.ts.map +1 -0
  63. package/dist/wire-entry.js +24 -0
  64. package/dist/wire-entry.js.map +1 -0
  65. package/package.json +13 -1
package/dist/index.d.ts CHANGED
@@ -3,19 +3,24 @@
3
3
  * -------------------------------------------------------
4
4
  * Core library for Haverstack — portable personal data stack.
5
5
  *
6
- * Exports the Stack class, all types, and utility functions.
6
+ * Exports the Stack class, the app/plugin-facing data types, and the
7
+ * general-purpose utilities every caller needs. Audience-specific surfaces
8
+ * live behind their own subpaths, which this root does not re-export:
9
+ * ./did — key generation, custody and signing (did:key)
10
+ * ./wire — the auth handshake and attachment-download policy shared
11
+ * by both sides of a client/server connection
12
+ * ./adapter — the interfaces a storage adapter implements
13
+ * ./testing — the in-memory MemoryAdapter for tests
7
14
  * Storage adapters are published as separate packages:
8
15
  * @haverstack/adapter-sqlite
9
16
  */
10
- export { Stack, ScopedStack, StackValidationError, StackMigrationError, StackPermissionError, StackNotFoundError, StackConflictError, } from './stack.js';
11
- export type { StackClient, CreateRecordOptions, GetRecordOptions, DeleteRecordOptions, } from './stack.js';
12
- export { checkAccess } from './access.js';
13
- export type { AccessMode, RecordResolver } from './access.js';
14
- export type { RecordId, TypeId, FileId, AttachmentContent, StackRecord, RecordVersion, StackType, TypeSchema, FieldDef, ScalarFieldDef, ArrayFieldDef, ObjectFieldDef, ScalarFieldKind, Association, TagAssociation, AttachmentAssociation, RelationshipAssociation, Permission, StackQuery, RecordFilter, QuerySort, QueryResult, DateRange, Migration, MigrationFn, AdapterCapabilities, StackFeatures, StackRecordAdapter, StackBlobAdapter, StackAdapter, EntityContent, AppContent, GroupContent, GrantAction, GrantContent, ConfigContent, } from './types.js';
17
+ export { Stack, ScopedStack, StackError, StackValidationError, StackMigrationError, StackPermissionError, StackNotFoundError, StackConflictError, StackVersionConflictError, StackQueryError, StackSchemaDriftError, StackPayloadTooLargeError, StackTimeoutError, StackClosedError, } from './stack.js';
18
+ export type { StackErrorCode, StackClient, CreateRecordOptions, StackOptions, GetRecordOptions, DeleteRecordOptions, IfVersionOptions, CollectAttachmentGarbageOptions, CollectAttachmentGarbageResult, } from './stack.js';
19
+ export type { RecordId, TypeId, FileId, EntityId, AttachmentContent, StackRecord, RecordVersion, StackType, TypeSchema, FieldDef, ScalarFieldDef, ArrayFieldDef, ObjectFieldDef, ScalarFieldKind, Association, TagAssociation, AttachmentAssociation, RelationshipAssociation, Permission, StackQuery, RecordFilter, QuerySort, QueryResult, DateRange, Migration, MigrationFn, StackAdapter, StackFeatures, TokenSession, EntityContent, AppContent, GroupContent, GrantAction, GrantContent, ConfigContent, } from './types.js';
15
20
  export { SYSTEM_TYPES } from './types.js';
16
- export { combineAdapters } from './combine.js';
17
- export { generateId, crockford32Encode, crockford32Decode } from './id.js';
18
- export { hashSchema, isCompatible, parseTypeId, buildTypeId } from './schema.js';
19
- export { validateContent, isValid } from './validate.js';
21
+ export { generateId } from './id.js';
22
+ export { hashSchema, isCompatible } from './schema.js';
23
+ export type { SchemaDriftViolation } from './schema.js';
20
24
  export type { ValidationError } from './validate.js';
25
+ export { applyMergePatch } from './merge.js';
21
26
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EACL,KAAK,EACL,WAAW,EACX,oBAAoB,EACpB,mBAAmB,EACnB,oBAAoB,EACpB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,WAAW,EACX,mBAAmB,EACnB,gBAAgB,EAChB,mBAAmB,GACpB,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,YAAY,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAG9D,YAAY,EACV,QAAQ,EACR,MAAM,EACN,MAAM,EACN,iBAAiB,EACjB,WAAW,EACX,aAAa,EACb,SAAS,EACT,UAAU,EACV,QAAQ,EACR,cAAc,EACd,aAAa,EACb,cAAc,EACd,eAAe,EACf,WAAW,EACX,cAAc,EACd,qBAAqB,EACrB,uBAAuB,EACvB,UAAU,EACV,UAAU,EACV,YAAY,EACZ,SAAS,EACT,WAAW,EACX,SAAS,EACT,SAAS,EACT,WAAW,EACX,mBAAmB,EACnB,aAAa,EACb,kBAAkB,EAClB,gBAAgB,EAChB,YAAY,EACZ,aAAa,EACb,UAAU,EACV,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,aAAa,GACd,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAG1C,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAG/C,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAC3E,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACjF,OAAO,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACzD,YAAY,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,EACL,KAAK,EACL,WAAW,EACX,UAAU,EACV,oBAAoB,EACpB,mBAAmB,EACnB,oBAAoB,EACpB,kBAAkB,EAClB,kBAAkB,EAClB,yBAAyB,EACzB,eAAe,EACf,qBAAqB,EACrB,yBAAyB,EACzB,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,cAAc,EACd,WAAW,EACX,mBAAmB,EACnB,YAAY,EACZ,gBAAgB,EAChB,mBAAmB,EACnB,gBAAgB,EAChB,+BAA+B,EAC/B,8BAA8B,GAC/B,MAAM,YAAY,CAAC;AAGpB,YAAY,EACV,QAAQ,EACR,MAAM,EACN,MAAM,EACN,QAAQ,EACR,iBAAiB,EACjB,WAAW,EACX,aAAa,EACb,SAAS,EACT,UAAU,EACV,QAAQ,EACR,cAAc,EACd,aAAa,EACb,cAAc,EACd,eAAe,EACf,WAAW,EACX,cAAc,EACd,qBAAqB,EACrB,uBAAuB,EACvB,UAAU,EACV,UAAU,EACV,YAAY,EACZ,SAAS,EACT,WAAW,EACX,SAAS,EACT,SAAS,EACT,WAAW,EACX,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,aAAa,EACb,UAAU,EACV,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,aAAa,GACd,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAM1C,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACvD,YAAY,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACxD,YAAY,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC"}
package/dist/index.js CHANGED
@@ -3,19 +3,24 @@
3
3
  * -------------------------------------------------------
4
4
  * Core library for Haverstack — portable personal data stack.
5
5
  *
6
- * Exports the Stack class, all types, and utility functions.
6
+ * Exports the Stack class, the app/plugin-facing data types, and the
7
+ * general-purpose utilities every caller needs. Audience-specific surfaces
8
+ * live behind their own subpaths, which this root does not re-export:
9
+ * ./did — key generation, custody and signing (did:key)
10
+ * ./wire — the auth handshake and attachment-download policy shared
11
+ * by both sides of a client/server connection
12
+ * ./adapter — the interfaces a storage adapter implements
13
+ * ./testing — the in-memory MemoryAdapter for tests
7
14
  * Storage adapters are published as separate packages:
8
15
  * @haverstack/adapter-sqlite
9
16
  */
10
17
  // Core class and client interface
11
- export { Stack, ScopedStack, StackValidationError, StackMigrationError, StackPermissionError, StackNotFoundError, StackConflictError, } from './stack.js';
12
- // Permissions
13
- export { checkAccess } from './access.js';
18
+ export { Stack, ScopedStack, StackError, StackValidationError, StackMigrationError, StackPermissionError, StackNotFoundError, StackConflictError, StackVersionConflictError, StackQueryError, StackSchemaDriftError, StackPayloadTooLargeError, StackTimeoutError, StackClosedError, } from './stack.js';
14
19
  export { SYSTEM_TYPES } from './types.js';
15
- // Adapter composition
16
- export { combineAdapters } from './combine.js';
17
20
  // Utilities
18
- export { generateId, crockford32Encode, crockford32Decode } from './id.js';
19
- export { hashSchema, isCompatible, parseTypeId, buildTypeId } from './schema.js';
20
- export { validateContent, isValid } from './validate.js';
21
+ // No in-repo caller: client-minted IDs are the default per spec, and an app
22
+ // needing the ID before the write round-trips has to mint one itself.
23
+ export { generateId } from './id.js';
24
+ export { hashSchema, isCompatible } from './schema.js';
25
+ export { applyMergePatch } from './merge.js';
21
26
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,kCAAkC;AAClC,OAAO,EACL,KAAK,EACL,WAAW,EACX,oBAAoB,EACpB,mBAAmB,EACnB,oBAAoB,EACpB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,YAAY,CAAC;AAQpB,cAAc;AACd,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AA2C1C,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,sBAAsB;AACtB,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE/C,YAAY;AACZ,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAC3E,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACjF,OAAO,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,kCAAkC;AAClC,OAAO,EACL,KAAK,EACL,WAAW,EACX,UAAU,EACV,oBAAoB,EACpB,mBAAmB,EACnB,oBAAoB,EACpB,kBAAkB,EAClB,kBAAkB,EAClB,yBAAyB,EACzB,eAAe,EACf,qBAAqB,EACrB,yBAAyB,EACzB,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,YAAY,CAAC;AAoDpB,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,YAAY;AAEZ,4EAA4E;AAC5E,sEAAsE;AACtE,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAGvD,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Stack — RFC 7396 JSON Merge Patch
3
+ * -------------------------------------------------------
4
+ * Shallow merge-patch semantics for record content: a field set to `null`
5
+ * removes it, any other value replaces it, and omitted fields are retained.
6
+ * Shared by Stack.update() (for client-side validation) and every
7
+ * StackRecordAdapter's patchContent() implementation, so a patch produces
8
+ * the same merged content everywhere it's applied.
9
+ */
10
+ export declare function applyMergePatch(content: Record<string, unknown>, patch: Record<string, unknown | null>): Record<string, unknown>;
11
+ //# sourceMappingURL=merge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merge.d.ts","sourceRoot":"","sources":["../src/merge.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAAC,GACpC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CA0BzB"}
package/dist/merge.js ADDED
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Stack — RFC 7396 JSON Merge Patch
3
+ * -------------------------------------------------------
4
+ * Shallow merge-patch semantics for record content: a field set to `null`
5
+ * removes it, any other value replaces it, and omitted fields are retained.
6
+ * Shared by Stack.update() (for client-side validation) and every
7
+ * StackRecordAdapter's patchContent() implementation, so a patch produces
8
+ * the same merged content everywhere it's applied.
9
+ */
10
+ export function applyMergePatch(content, patch) {
11
+ const merged = { ...content };
12
+ for (const [key, value] of Object.entries(patch)) {
13
+ if (value === null) {
14
+ delete merged[key];
15
+ }
16
+ else {
17
+ // defineProperty, not `merged[key] = value`: assignment goes through
18
+ // [[Set]], so a patch key of `__proto__` would invoke the prototype
19
+ // setter and reassign the object's prototype instead of setting a
20
+ // field — silently losing the write. defineProperty creates an own
21
+ // data property for any key, which is also what JSON.parse does when
22
+ // the same key is read back, so both write paths agree. The spread
23
+ // above is already safe (it copies data properties directly).
24
+ //
25
+ // Stack.create()/update() reject the reserved keys outright (see
26
+ // validateReservedKeys); this is the backstop for adapters that call
27
+ // this directly, and for the day someone deepens the merge.
28
+ Object.defineProperty(merged, key, {
29
+ value,
30
+ writable: true,
31
+ enumerable: true,
32
+ configurable: true,
33
+ });
34
+ }
35
+ }
36
+ return merged;
37
+ }
38
+ //# sourceMappingURL=merge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merge.js","sourceRoot":"","sources":["../src/merge.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,UAAU,eAAe,CAC7B,OAAgC,EAChC,KAAqC;IAErC,MAAM,MAAM,GAA4B,EAAE,GAAG,OAAO,EAAE,CAAC;IACvD,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACjD,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YACnB,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC;QACrB,CAAC;aAAM,CAAC;YACN,qEAAqE;YACrE,oEAAoE;YACpE,kEAAkE;YAClE,mEAAmE;YACnE,qEAAqE;YACrE,mEAAmE;YACnE,8DAA8D;YAC9D,EAAE;YACF,iEAAiE;YACjE,qEAAqE;YACrE,4DAA4D;YAC5D,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,GAAG,EAAE;gBACjC,KAAK;gBACL,QAAQ,EAAE,IAAI;gBACd,UAAU,EAAE,IAAI;gBAChB,YAAY,EAAE,IAAI;aACnB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
package/dist/schema.d.ts CHANGED
@@ -16,17 +16,25 @@ import type { TypeSchema } from './types.js';
16
16
  */
17
17
  export declare const hashSchema: (schema: TypeSchema) => Promise<string>;
18
18
  /**
19
- * Check whether a candidate schema satisfies a required schema.
20
- *
21
- * A candidate is compatible if it contains all *required* fields from
22
- * the required schema with matching kinds. Optional fields in the
23
- * required schema are ignored. Array and object fields are matched
24
- * shallowly — only the top-level kind is checked.
25
- *
26
- * Apps that need precise type matching should compare typeIds directly.
27
- * isCompatible() is for duck-typed consumption across types.
19
+ * Check whether a candidate schema is read-compatible with a required
20
+ * schema — licensing duck-typed *consumption* of records, not writing
21
+ * them. Every required field must be declared required at a
22
+ * read-compatible kind; array/object fields recurse. See
23
+ * docs/spec/data-model.md § Type compatibility.
28
24
  */
29
25
  export declare const isCompatible: (candidateSchema: TypeSchema, requiredSchema: TypeSchema) => boolean;
26
+ export type SchemaDriftViolation = {
27
+ /** Field path where the drift was detected, e.g. "title" or "author.name". Empty string means array-item context. */
28
+ path: string;
29
+ message: string;
30
+ };
31
+ /**
32
+ * Check whether `candidate` is a legal in-place evolution of `stored`:
33
+ * every existing field unchanged (recursively) and every added field
34
+ * optional. Returns the list of violations; empty means legal. See
35
+ * docs/spec/data-model.md § Schema drift detection.
36
+ */
37
+ export declare const diffSchemas: (stored: TypeSchema, candidate: TypeSchema) => SchemaDriftViolation[];
30
38
  /**
31
39
  * Parse a versioned TypeId into its base and version components.
32
40
  * e.g. "com.example.myapp/note@2" → { baseId: "com.example.myapp/note", version: 2 }
@@ -41,4 +49,18 @@ export declare const parseTypeId: (typeId: string) => {
41
49
  * e.g. ("com.example.myapp/note", 2) → "com.example.myapp/note@2"
42
50
  */
43
51
  export declare const buildTypeId: (baseId: string, version: number) => string;
52
+ /**
53
+ * Extract the base (family) ID from a TypeId, tolerating an already-bare
54
+ * baseId (no "@n" suffix) as a no-op. Used to compare across versions —
55
+ * e.g. a grant on "comment@1" and a record at "comment@2" share a baseId.
56
+ */
57
+ export declare const baseIdOf: (typeId: string) => string;
58
+ /**
59
+ * True if typeId is well-formed as either a bare baseId (no version
60
+ * suffix) or a versioned TypeId ("baseId@version") — the shape
61
+ * GrantContent.typeId accepts, the same tolerance baseIdOf() applies.
62
+ * Not used by defineType(), which requires a version and needs the parsed
63
+ * {baseId, version} itself — it calls parseTypeId() directly instead.
64
+ */
65
+ export declare const isWellFormedTypeId: (typeId: string) => boolean;
44
66
  //# sourceMappingURL=schema.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAY,MAAM,YAAY,CAAC;AA8CvD;;;;GAIG;AACH,eAAO,MAAM,UAAU,GAAU,QAAQ,UAAU,KAAG,OAAO,CAAC,MAAM,CAMnE,CAAC;AAMF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,YAAY,GAAI,iBAAiB,UAAU,EAAE,gBAAgB,UAAU,KAAG,OAMtF,CAAC;AAMF;;;;GAIG;AACH,eAAO,MAAM,WAAW,GAAI,QAAQ,MAAM,KAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,IAIlF,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,WAAW,GAAI,QAAQ,MAAM,EAAE,SAAS,MAAM,KAAG,MAAgC,CAAC"}
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,UAAU,EAA6B,MAAM,YAAY,CAAC;AA8CxE;;;;GAIG;AACH,eAAO,MAAM,UAAU,GAAU,QAAQ,UAAU,KAAG,OAAO,CAAC,MAAM,CAMnE,CAAC;AA8DF;;;;;;GAMG;AACH,eAAO,MAAM,YAAY,GAAI,iBAAiB,UAAU,EAAE,gBAAgB,UAAU,KAAG,OAC9B,CAAC;AAU1D,MAAM,MAAM,oBAAoB,GAAG;IACjC,qHAAqH;IACrH,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAyEF;;;;;GAKG;AACH,eAAO,MAAM,WAAW,GAAI,QAAQ,UAAU,EAAE,WAAW,UAAU,KAAG,oBAAoB,EAI3F,CAAC;AAMF;;;;GAIG;AACH,eAAO,MAAM,WAAW,GAAI,QAAQ,MAAM,KAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,IAIlF,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,WAAW,GAAI,QAAQ,MAAM,EAAE,SAAS,MAAM,KAAG,MAAgC,CAAC;AAE/F;;;;GAIG;AACH,eAAO,MAAM,QAAQ,GAAI,QAAQ,MAAM,KAAG,MAA+C,CAAC;AAE1F;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,GAAI,QAAQ,MAAM,KAAG,OAGnD,CAAC"}
package/dist/schema.js CHANGED
@@ -60,24 +60,129 @@ export const hashSchema = async (schema) => {
60
60
  // Type compatibility
61
61
  // -------------------------------------------------------
62
62
  /**
63
- * Check whether a candidate schema satisfies a required schema.
64
- *
65
- * A candidate is compatible if it contains all *required* fields from
66
- * the required schema with matching kinds. Optional fields in the
67
- * required schema are ignored. Array and object fields are matched
68
- * shallowly — only the top-level kind is checked.
69
- *
70
- * Apps that need precise type matching should compare typeIds directly.
71
- * isCompatible() is for duck-typed consumption across types.
63
+ * Kinds acceptable in a candidate field, per required kind. `string` and
64
+ * `text` are mutually acceptable for reading; everything else requires an
65
+ * exact match. See docs/spec/data-model.md § Type compatibility.
72
66
  */
73
- export const isCompatible = (candidateSchema, requiredSchema) => {
67
+ const READ_COMPATIBLE = {
68
+ string: ['string', 'text'],
69
+ text: ['text', 'string'],
70
+ number: ['number'],
71
+ boolean: ['boolean'],
72
+ date: ['date'],
73
+ 'record-ref': ['record-ref'],
74
+ 'file-ref': ['file-ref'],
75
+ };
76
+ // Candidate schemas can come from another app's Type definition (the
77
+ // untrusted side of duck-typed consumption), so recursion into array
78
+ // items / object properties is depth-bounded — matches MAX_VALIDATION_DEPTH
79
+ // in validate.ts. Past the limit we can't verify compatibility, so we
80
+ // fail closed (treat as incompatible) rather than risk a stack overflow.
81
+ const MAX_COMPATIBILITY_DEPTH = 32;
82
+ /**
83
+ * Check whether a candidate field satisfies a required field, recursing
84
+ * into array items and object properties.
85
+ */
86
+ const isFieldCompatible = (candidate, required, depth) => {
87
+ if (depth > MAX_COMPATIBILITY_DEPTH)
88
+ return false;
89
+ if (required.kind === 'array') {
90
+ return (candidate.kind === 'array' && isFieldCompatible(candidate.items, required.items, depth + 1));
91
+ }
92
+ if (required.kind === 'object') {
93
+ return (candidate.kind === 'object' &&
94
+ isCompatibleAtDepth(candidate.properties, required.properties, depth + 1));
95
+ }
96
+ if (candidate.kind === 'array' || candidate.kind === 'object')
97
+ return false;
98
+ return READ_COMPATIBLE[required.kind].includes(candidate.kind);
99
+ };
100
+ const isCompatibleAtDepth = (candidateSchema, requiredSchema, depth) => {
101
+ if (depth > MAX_COMPATIBILITY_DEPTH)
102
+ return false;
74
103
  return Object.entries(requiredSchema).every(([key, def]) => {
75
104
  if (!def.required)
76
105
  return true;
77
106
  const field = candidateSchema[key];
78
- return field !== undefined && field.kind === def.kind;
107
+ return field !== undefined && field.required === true && isFieldCompatible(field, def, depth);
79
108
  });
80
109
  };
110
+ /**
111
+ * Check whether a candidate schema is read-compatible with a required
112
+ * schema — licensing duck-typed *consumption* of records, not writing
113
+ * them. Every required field must be declared required at a
114
+ * read-compatible kind; array/object fields recurse. See
115
+ * docs/spec/data-model.md § Type compatibility.
116
+ */
117
+ export const isCompatible = (candidateSchema, requiredSchema) => isCompatibleAtDepth(candidateSchema, requiredSchema, 0);
118
+ // Same rationale and bound as MAX_COMPATIBILITY_DEPTH: a pathological or
119
+ // circular schema shouldn't be walked forever. Past the limit we can't
120
+ // verify the change is additive, so we fail closed — report it as drift
121
+ // rather than silently accept.
122
+ const MAX_DIFF_DEPTH = 32;
123
+ const diffField = (path, stored, candidate, depth, violations) => {
124
+ if (depth > MAX_DIFF_DEPTH) {
125
+ violations.push({ path, message: 'exceeds max nesting depth; cannot verify additive change' });
126
+ return;
127
+ }
128
+ if (stored.kind !== candidate.kind) {
129
+ violations.push({
130
+ path,
131
+ message: `kind changed from "${stored.kind}" to "${candidate.kind}"`,
132
+ });
133
+ return; // kinds differ — nested comparison (properties/items) is meaningless
134
+ }
135
+ if (!!stored.required !== !!candidate.required) {
136
+ violations.push({
137
+ path,
138
+ message: `required changed from ${!!stored.required} to ${!!candidate.required}`,
139
+ });
140
+ }
141
+ if (stored.kind === 'array' && candidate.kind === 'array') {
142
+ diffField(`${path}[]`, stored.items, candidate.items, depth + 1, violations);
143
+ }
144
+ if (stored.kind === 'object' && candidate.kind === 'object') {
145
+ diffFields(path, stored.properties, candidate.properties, depth + 1, violations);
146
+ }
147
+ };
148
+ const diffFields = (prefix, stored, candidate, depth, violations) => {
149
+ if (depth > MAX_DIFF_DEPTH) {
150
+ violations.push({
151
+ path: prefix,
152
+ message: 'exceeds max nesting depth; cannot verify additive change',
153
+ });
154
+ return;
155
+ }
156
+ for (const [key, storedDef] of Object.entries(stored)) {
157
+ const path = prefix ? `${prefix}.${key}` : key;
158
+ const candidateDef = candidate[key];
159
+ if (!candidateDef) {
160
+ violations.push({ path, message: 'field removed' });
161
+ continue;
162
+ }
163
+ diffField(path, storedDef, candidateDef, depth, violations);
164
+ }
165
+ for (const [key, candidateDef] of Object.entries(candidate)) {
166
+ if (key in stored)
167
+ continue; // already compared above
168
+ if (candidateDef.required) {
169
+ const path = prefix ? `${prefix}.${key}` : key;
170
+ violations.push({ path, message: 'new field is required; new fields must be optional' });
171
+ }
172
+ // A new optional field is exactly what additive evolution allows — no violation.
173
+ }
174
+ };
175
+ /**
176
+ * Check whether `candidate` is a legal in-place evolution of `stored`:
177
+ * every existing field unchanged (recursively) and every added field
178
+ * optional. Returns the list of violations; empty means legal. See
179
+ * docs/spec/data-model.md § Schema drift detection.
180
+ */
181
+ export const diffSchemas = (stored, candidate) => {
182
+ const violations = [];
183
+ diffFields('', stored, candidate, 0, violations);
184
+ return violations;
185
+ };
81
186
  // -------------------------------------------------------
82
187
  // Type ID parsing
83
188
  // -------------------------------------------------------
@@ -97,4 +202,22 @@ export const parseTypeId = (typeId) => {
97
202
  * e.g. ("com.example.myapp/note", 2) → "com.example.myapp/note@2"
98
203
  */
99
204
  export const buildTypeId = (baseId, version) => `${baseId}@${version}`;
205
+ /**
206
+ * Extract the base (family) ID from a TypeId, tolerating an already-bare
207
+ * baseId (no "@n" suffix) as a no-op. Used to compare across versions —
208
+ * e.g. a grant on "comment@1" and a record at "comment@2" share a baseId.
209
+ */
210
+ export const baseIdOf = (typeId) => parseTypeId(typeId)?.baseId ?? typeId;
211
+ /**
212
+ * True if typeId is well-formed as either a bare baseId (no version
213
+ * suffix) or a versioned TypeId ("baseId@version") — the shape
214
+ * GrantContent.typeId accepts, the same tolerance baseIdOf() applies.
215
+ * Not used by defineType(), which requires a version and needs the parsed
216
+ * {baseId, version} itself — it calls parseTypeId() directly instead.
217
+ */
218
+ export const isWellFormedTypeId = (typeId) => {
219
+ if (typeof typeId !== 'string' || typeId.trim().length === 0)
220
+ return false;
221
+ return !typeId.includes('@') || parseTypeId(typeId) !== null;
222
+ };
100
223
  //# sourceMappingURL=schema.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"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"}