@xnetjs/data 0.0.2 → 0.1.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 (139) hide show
  1. package/README.md +112 -0
  2. package/dist/account-MWNCH4GJ.js +12 -0
  3. package/dist/account-ledger-R2GAFJL6.js +38 -0
  4. package/dist/auth/index.d.ts +420 -0
  5. package/dist/auth/index.js +102 -0
  6. package/dist/budget-NN7P35XP.js +12 -0
  7. package/dist/canvas-6WYBNH53.js +10 -0
  8. package/dist/channel-AT3LQF4A.js +12 -0
  9. package/dist/chat-message-DSVO72B3.js +10 -0
  10. package/dist/chunk-2ZNJWIQG.js +84 -0
  11. package/dist/chunk-3J3HILXO.js +46 -0
  12. package/dist/chunk-3RUDVTMH.js +5543 -0
  13. package/dist/chunk-4EYKGTSQ.js +49 -0
  14. package/dist/chunk-53F4PRNC.js +32 -0
  15. package/dist/chunk-5EXHNXPL.js +48 -0
  16. package/dist/{chunk-BQBPA5HS.js → chunk-5HC5NO57.js} +16 -2
  17. package/dist/chunk-6KLGA6IR.js +47 -0
  18. package/dist/chunk-6OMG4I7M.js +41 -0
  19. package/dist/chunk-7PDRDSFH.js +69 -0
  20. package/dist/chunk-BQLQSWKZ.js +232 -0
  21. package/dist/chunk-BY5O6LNC.js +380 -0
  22. package/dist/chunk-DCTRX6II.js +40 -0
  23. package/dist/{chunk-VYR5GPJP.js → chunk-DWEXKD6E.js} +9 -3
  24. package/dist/chunk-EBNMV2VO.js +896 -0
  25. package/dist/chunk-FVEACSKE.js +102 -0
  26. package/dist/chunk-GU6THOAB.js +45 -0
  27. package/dist/chunk-H4GA4BBK.js +75 -0
  28. package/dist/chunk-IJ44LR7N.js +76 -0
  29. package/dist/chunk-J4ANIXIV.js +402 -0
  30. package/dist/chunk-JDFNMFOZ.js +45 -0
  31. package/dist/chunk-K7DOZWWT.js +1811 -0
  32. package/dist/chunk-KQAT4XBL.js +49 -0
  33. package/dist/chunk-KQUALW4O.js +183 -0
  34. package/dist/chunk-LYSWLCOI.js +47 -0
  35. package/dist/chunk-MBTUO3ZL.js +65 -0
  36. package/dist/chunk-NI4FHG2K.js +52 -0
  37. package/dist/chunk-OCMSAKWV.js +78 -0
  38. package/dist/chunk-OGJCRNGE.js +57 -0
  39. package/dist/chunk-OPPHF3TF.js +143 -0
  40. package/dist/{chunk-IDMBCRUC.js → chunk-OSAWNZVM.js} +1 -1
  41. package/dist/chunk-PMUQACPY.js +33 -0
  42. package/dist/chunk-PNESGUH5.js +63 -0
  43. package/dist/chunk-Q3IEGH4B.js +51 -0
  44. package/dist/chunk-QJW5LDP4.js +52 -0
  45. package/dist/chunk-QWFTRZQT.js +142 -0
  46. package/dist/{chunk-SZC345Z2.js → chunk-RL64OJJ5.js} +1025 -1110
  47. package/dist/chunk-S5RP5RKY.js +416 -0
  48. package/dist/chunk-S6U6TCMN.js +722 -0
  49. package/dist/chunk-SVNGSZZA.js +69 -0
  50. package/dist/chunk-T5AZAOG5.js +54 -0
  51. package/dist/chunk-TCTZW4A6.js +42 -0
  52. package/dist/chunk-U64CW73O.js +109 -0
  53. package/dist/chunk-UDWKWTAX.js +6526 -0
  54. package/dist/chunk-UQM3G5A2.js +148 -0
  55. package/dist/chunk-VQ7JHB67.js +57 -0
  56. package/dist/chunk-W7EBL7ZU.js +73 -0
  57. package/dist/chunk-WEPK7SZF.js +65 -0
  58. package/dist/chunk-XHEA5UER.js +75 -0
  59. package/dist/chunk-XMSKJ5PV.js +66 -0
  60. package/dist/chunk-XROI44ZP.js +64 -0
  61. package/dist/chunk-Y3S5SRVM.js +45 -0
  62. package/dist/chunk-YEFKQYKA.js +43 -0
  63. package/dist/chunk-YSUIXD2Y.js +105 -0
  64. package/dist/chunk-ZCOFZY5M.js +70 -0
  65. package/dist/chunk-ZLU4Y3O2.js +50 -0
  66. package/dist/chunk-ZPZ7XDA6.js +54 -0
  67. package/dist/chunk-ZZ6TWKGS.js +40 -0
  68. package/dist/clone-C0Jhk2UN.d.ts +2205 -0
  69. package/dist/comment-QSWYAQVS.js +10 -0
  70. package/dist/crm-L5RYAAF3.js +68 -0
  71. package/dist/dashboard-JMKTTRA7.js +10 -0
  72. package/dist/database/index.d.ts +882 -0
  73. package/dist/database/index.js +523 -0
  74. package/dist/database-GIXSPZJW.js +10 -0
  75. package/dist/database-field-3EPAMZUR.js +10 -0
  76. package/dist/database-row-6Q6TRVE4.js +10 -0
  77. package/dist/database-select-option-BBBJFLLH.js +10 -0
  78. package/dist/database-view-5PLSOBI2.js +10 -0
  79. package/dist/experiment-DOVOZ34Y.js +10 -0
  80. package/dist/external-item-P2E5X7BZ.js +14 -0
  81. package/dist/external-reference-7BSFF6SA.js +8 -0
  82. package/dist/feed-2IXHHP6O.js +12 -0
  83. package/dist/feed-item-DPE6LN7I.js +12 -0
  84. package/dist/folder-6KM3KYD5.js +21 -0
  85. package/dist/game-5AK5XWBR.js +50 -0
  86. package/dist/grant-WTQSNT5A.js +8 -0
  87. package/dist/grant-expiration-cleaner-CY6BcmlR.d.ts +249 -0
  88. package/dist/import-batch-IXBJLQPJ.js +12 -0
  89. package/dist/inbox-state-E5NSVOGP.js +12 -0
  90. package/dist/index.d.ts +224 -4548
  91. package/dist/index.js +2252 -4754
  92. package/dist/map-RG5Y3CPC.js +10 -0
  93. package/dist/media-asset-QTCGLIZA.js +8 -0
  94. package/dist/memory-PNRTMBZO.js +12 -0
  95. package/dist/metric-65SVOX5C.js +10 -0
  96. package/dist/milestone-XEO6ZGDG.js +12 -0
  97. package/dist/moderation-FFHETMRB.js +30 -0
  98. package/dist/observation-2Y3QKUXM.js +10 -0
  99. package/dist/page-2V27JGKJ.js +10 -0
  100. package/dist/posting-GBOSZCMZ.js +12 -0
  101. package/dist/profile-BLLDWIDK.js +8 -0
  102. package/dist/project-CQL5LN26.js +10 -0
  103. package/dist/query-ast-C3m6kZYv.d.ts +226 -0
  104. package/dist/reaction-T2DTJBBV.js +10 -0
  105. package/dist/registry-DunPv__d.d.ts +99 -0
  106. package/dist/saved-view-4R2DBCL3.js +10 -0
  107. package/dist/schema/index.d.ts +6489 -0
  108. package/dist/schema/index.js +677 -0
  109. package/dist/schema-extension-LNRF2YRD.js +18 -0
  110. package/dist/space-IJU24PBH.js +42 -0
  111. package/dist/space-membership-DEUMM7NV.js +14 -0
  112. package/dist/store/index.d.ts +518 -0
  113. package/dist/store/index.js +135 -0
  114. package/dist/store-DtIDjk7c.d.ts +355 -0
  115. package/dist/sync/awareness.d.ts +69 -0
  116. package/dist/sync/awareness.js +20 -0
  117. package/dist/system-ILHCZOVO.js +38 -0
  118. package/dist/tag-SKCHM3U5.js +16 -0
  119. package/dist/task-7AOBP7WC.js +16 -0
  120. package/dist/task-view-NUGKELJP.js +10 -0
  121. package/dist/transaction-ZDSEGDIR.js +12 -0
  122. package/dist/transcription-PSCLDAGX.js +12 -0
  123. package/dist/types-S-BJAKyK.d.ts +1576 -0
  124. package/dist/updates.d.ts +44 -0
  125. package/dist/updates.js +16 -0
  126. package/dist/user-widget-RLY2N46A.js +8 -0
  127. package/dist/view-types-DSde-uT_.d.ts +316 -0
  128. package/package.json +32 -9
  129. package/dist/canvas-HSIKIQFK.js +0 -7
  130. package/dist/chunk-2L5ZUGG5.js +0 -53
  131. package/dist/chunk-4MTS5KAQ.js +0 -22
  132. package/dist/chunk-GZHARFKC.js +0 -25
  133. package/dist/chunk-WKIKJTI2.js +0 -45
  134. package/dist/comment-277JD7DV.js +0 -7
  135. package/dist/database-W3KEHLI3.js +0 -7
  136. package/dist/database-row-3O2QSNZN.js +0 -7
  137. package/dist/grant-QVZ454YC.js +0 -7
  138. package/dist/page-O4WTOIEO.js +0 -7
  139. package/dist/task-SEKAYJH7.js +0 -7
package/README.md CHANGED
@@ -2,6 +2,12 @@
2
2
 
3
3
  Schema system, NodeStore, and Yjs CRDT engine for xNet. This is the central data package -- it defines how structured data and rich text documents are created, stored, and synced.
4
4
 
5
+ > **Status:** Mixed
6
+ > Stable entrypoints: `@xnetjs/data/schema`, `@xnetjs/data/store`, `@xnetjs/data/updates`, `@xnetjs/data/awareness`
7
+ > Experimental entrypoints: `@xnetjs/data/database`, `@xnetjs/data/auth`
8
+
9
+ The root `@xnetjs/data` barrel remains supported for compatibility, but new code should prefer the narrower entrypoints above. See [`docs/reference/api-lifecycle-matrix.md`](../../docs/reference/api-lifecycle-matrix.md) for the current matrix.
10
+
5
11
  ## Installation
6
12
 
7
13
  ```bash
@@ -18,6 +24,7 @@ pnpm add @xnetjs/data
18
24
  - **Blob service** -- File upload/download with content addressing
19
25
  - **Storage adapters** -- SQLite and in-memory NodeStore adapters
20
26
  - **Temp ID mapping** -- Optimistic creates with server-assigned IDs
27
+ - **Query AST** -- Validated relation, aggregate, query-set, and saved-view descriptors
21
28
 
22
29
  ## Usage
23
30
 
@@ -95,6 +102,54 @@ const tasks = await store.list(TaskSchema)
95
102
  await store.remove(task.id)
96
103
  ```
97
104
 
105
+ ### Batch Writes
106
+
107
+ Use `NodeStore.batchWrite()` for high-volume deterministic imports, restores, migrations, and other
108
+ bulk workflows that already know stable node IDs. The store still signs one change per draft and
109
+ preserves LWW semantics, but storage adapters can apply materialized nodes, changes, Lamport state,
110
+ and touched secondary indexes in one owned batch.
111
+
112
+ ```mermaid
113
+ sequenceDiagram
114
+ participant Caller as "Importer / migration"
115
+ participant Store as "NodeStore.batchWrite()"
116
+ participant Storage as "NodeStorageAdapter.applyNodeBatch()"
117
+ participant SQLite as "SQLite transaction"
118
+
119
+ Caller->>Store: deterministic drafts + policy
120
+ Store->>Storage: batch preflight
121
+ Store->>Store: sign changes + materialize nodes
122
+ Store->>Storage: apply materialized nodes and changes
123
+ Storage->>SQLite: write nodes, properties, changes, touched indexes
124
+ Store-->>Caller: counters, timings, affected schemas
125
+ ```
126
+
127
+ ```typescript
128
+ const result = await store.batchWrite({
129
+ kind: 'deterministic-import',
130
+ drafts: [
131
+ {
132
+ id: 'social:content:example',
133
+ schemaId: 'xnet://xnet.fyi/social/Content',
134
+ properties: { title: 'Example post', platform: 'youtube' }
135
+ }
136
+ ],
137
+ policy: {
138
+ indexMode: 'touched',
139
+ notificationMode: 'batch',
140
+ syncMode: 'defer'
141
+ }
142
+ })
143
+
144
+ console.log(result.created, result.updated, result.timings.applyMs, result.storage)
145
+ ```
146
+
147
+ `indexMode: 'touched'` is the import default. It avoids whole-schema rebuilds by reindexing only the
148
+ nodes changed by the batch. `notificationMode: 'batch'` coalesces live reload work. Deferred sync is
149
+ an advisory hint for runtimes that can coalesce outbound replication.
150
+ `importDeterministicNodes()` remains available for existing callers and returns the same storage
151
+ counters and phase timings while preserving its detailed `changes` array.
152
+
98
153
  ### Yjs Documents
99
154
 
100
155
  ```typescript
@@ -120,6 +175,62 @@ applySignedUpdate(docB, signed)
120
175
  mergeDocuments(docA, docB)
121
176
  ```
122
177
 
178
+ ### Canonical Query AST
179
+
180
+ `useQuery()` remains the stable React read API. Advanced relation includes, aggregate reads, dashboards, and saved views are represented in `@xnetjs/data` as a canonical AST before they become public hook shortcuts.
181
+
182
+ ```mermaid
183
+ flowchart LR
184
+ Helpers["queryOperators(), from(), count()"]
185
+ AST["QueryAST"]
186
+ Validate["validateQueryAST()"]
187
+ Plan["planQueryASTAggregates()"]
188
+ Indexes["getQueryASTRelationIndexRequirements()"]
189
+ Saved["SavedViewDescriptor / SavedViewSchema"]
190
+
191
+ Helpers --> AST
192
+ AST --> Validate
193
+ Validate --> Plan
194
+ Validate --> Indexes
195
+ AST --> Saved
196
+ ```
197
+
198
+ ```typescript
199
+ import {
200
+ PageSchema,
201
+ TaskSchema,
202
+ count,
203
+ countDistinct,
204
+ defineNodeQueryAST,
205
+ defineSavedViewDescriptor,
206
+ from,
207
+ queryOperators,
208
+ validateSavedViewDescriptor
209
+ } from '@xnetjs/data'
210
+
211
+ const task = queryOperators<(typeof TaskSchema)['_properties']>()
212
+
213
+ const query = defineNodeQueryAST(PageSchema, {
214
+ include: {
215
+ tasks: from(TaskSchema, 'page', {
216
+ where: task.neq('status', 'done'),
217
+ page: { first: 25, count: 'exact' },
218
+ aggregates: [count(), countDistinct('assignee', 'assigneeCount')]
219
+ })
220
+ }
221
+ })
222
+
223
+ const saved = defineSavedViewDescriptor({
224
+ title: 'Open task dashboard',
225
+ scope: 'workspace',
226
+ query
227
+ })
228
+
229
+ const validation = validateSavedViewDescriptor(saved)
230
+ ```
231
+
232
+ The AST helpers only construct and validate descriptors. Execution of relation expansion, aggregate pushdown, and future `useFind()` pattern queries should go through planner gates before becoming stable public APIs.
233
+
123
234
  ## Architecture
124
235
 
125
236
  ```mermaid
@@ -206,6 +317,7 @@ All telemetry respects user consent settings and privacy buckets (no exact value
206
317
  | `schema/node.ts` | FlatNode type (flattened properties) |
207
318
  | `schema/registry.ts` | Schema registry |
208
319
  | `store/store.ts` | NodeStore engine |
320
+ | `store/query-ast.ts` | Canonical query AST and planner gates |
209
321
  | `store/sqlite-adapter.ts` | SQLite NodeStore adapter (recommended) |
210
322
  | `store/memory-adapter.ts` | In-memory NodeStore adapter |
211
323
  | `store/tempids.ts` | Temp ID mapping for optimistic creates |
@@ -0,0 +1,12 @@
1
+ import {
2
+ ACCOUNT_SCHEMA_IRI,
3
+ AccountSchema
4
+ } from "./chunk-XMSKJ5PV.js";
5
+ import "./chunk-OCMSAKWV.js";
6
+ import "./chunk-T5AZAOG5.js";
7
+ import "./chunk-EBNMV2VO.js";
8
+ import "./chunk-RL64OJJ5.js";
9
+ export {
10
+ ACCOUNT_SCHEMA_IRI,
11
+ AccountSchema
12
+ };
@@ -0,0 +1,38 @@
1
+ import {
2
+ ACCOUNT_RECORD_SCHEMA_IRI,
3
+ AccountRecordSchema,
4
+ DEVICE_RECORD_SCHEMA_IRI,
5
+ DeviceRecordSchema,
6
+ RECOVERY_RECORD_SCHEMA_IRI,
7
+ REVOCATION_RECORD_SCHEMA_IRI,
8
+ RecoveryRecordSchema,
9
+ RevocationRecordSchema,
10
+ accountRecordId,
11
+ deviceRecipientExpander,
12
+ deviceRecordId,
13
+ isDeviceAuthorized,
14
+ recoveryRecordId,
15
+ resolveActiveDevices,
16
+ revocationRecordId,
17
+ revokedSubjects
18
+ } from "./chunk-KQUALW4O.js";
19
+ import "./chunk-EBNMV2VO.js";
20
+ import "./chunk-RL64OJJ5.js";
21
+ export {
22
+ ACCOUNT_RECORD_SCHEMA_IRI,
23
+ AccountRecordSchema,
24
+ DEVICE_RECORD_SCHEMA_IRI,
25
+ DeviceRecordSchema,
26
+ RECOVERY_RECORD_SCHEMA_IRI,
27
+ REVOCATION_RECORD_SCHEMA_IRI,
28
+ RecoveryRecordSchema,
29
+ RevocationRecordSchema,
30
+ accountRecordId,
31
+ deviceRecipientExpander,
32
+ deviceRecordId,
33
+ isDeviceAuthorized,
34
+ recoveryRecordId,
35
+ resolveActiveDevices,
36
+ revocationRecordId,
37
+ revokedSubjects
38
+ };
@@ -0,0 +1,420 @@
1
+ import { AllowExpr, DenyExpr, AuthExpression, AndExpr, OrExpr, NotExpr, PublicExpr, AuthenticatedExpr, CreatorRoleResolver, PropertyRoleResolver, RelationRoleResolver, MembershipRoleResolver, AuthorizationDefinition, SerializedAuthorization, SerializedAuthExpression, DID } from '@xnetjs/core';
2
+ export { AUTH_ACTIONS, AllowExpr, AndExpr, AuthAction, AuthCheckInput, AuthDecision, AuthDenyReason, AuthExpression, AuthTrace, AuthTraceStep, AuthenticatedExpr, AuthorizationDefinition, CreatorRoleResolver, DenyExpr, MembershipRoleResolver, NotExpr, OrExpr, PolicyEvaluator, PropertyRoleResolver, PublicExpr, RelationRoleResolver, RoleRefExpr, RoleResolver, SerializedAuthExpression, SerializedAuthorization, SerializedRoleResolver } from '@xnetjs/core';
3
+ import { E as PropertyDefinition, a as Schema, h as NodeState, S as SchemaIRI } from '../types-S-BJAKyK.js';
4
+ export { aX as DEFAULT_OFFLINE_POLICY, aV as GRANT_SCHEMA_IRI, b1 as Grant, w as GrantIndex, b6 as GrantIndexOptions, b5 as GrantIndexStore, b0 as GrantInput, b4 as GrantNode, aU as GrantRateLimiter, b9 as GrantRateLimiterOptions, O as OfflineAuthPolicy, b8 as RevocationConfig, b7 as RevocationConsistency, aT as StoreAuth, e as StoreAuthAPI, b2 as StoreAuthError, b3 as StoreAuthErrorCode, a$ as StoreAuthKeyManager, aZ as StoreAuthOptions, a_ as StoreAuthStore, aW as isGrantActive, aY as mergeOfflinePolicy } from '../types-S-BJAKyK.js';
5
+ export { A as ActionPermission, m as AuthDecisionEvent, b as DecisionCache, g as DecisionCacheOptions, D as DefaultPolicyEvaluator, j as DefaultPolicyEvaluatorOptions, a as DefaultRoleResolver, i as DefaultRoleResolverOptions, k as DefinedSchemaLike, G as GrantExpirationCleaner, o as GrantExpirationCleanerOptions, n as GrantExpirationStore, H as HubPolicy, N as NodeStoreReader, P as PermissionMatrix, l as RevalidationEvent, R as RoleSummary, S as SchemaRegistryReader, c as buildPermissionMatrix, f as createPolicyEvaluator, d as describeRoleResolver, e as evaluateExpression, h as hubActionsForSpaceRole, s as schemaToHubPolicy } from '../grant-expiration-cleaner-CY6BcmlR.js';
6
+ import { PublicKeyResolver } from '@xnetjs/crypto';
7
+ import '@xnetjs/sqlite';
8
+ import '@xnetjs/sync';
9
+ import '../registry-DunPv__d.js';
10
+
11
+ /**
12
+ * Authorization expression builders for schema definitions.
13
+ *
14
+ * These functions create typed AST nodes for authorization rules.
15
+ *
16
+ * @example
17
+ * ```typescript
18
+ * import { allow, deny, and, or, not, role, PUBLIC, AUTHENTICATED } from '@xnetjs/data/auth'
19
+ *
20
+ * const TaskSchema = defineSchema({
21
+ * // ...
22
+ * authorization: {
23
+ * roles: {
24
+ * owner: role.creator(),
25
+ * editor: role.property('editors'),
26
+ * admin: role.relation('project', 'admin')
27
+ * },
28
+ * actions: {
29
+ * read: allow('editor', 'admin', 'owner'),
30
+ * write: allow('editor', 'admin', 'owner'),
31
+ * delete: allow('admin', 'owner'),
32
+ * share: allow('admin', 'owner')
33
+ * }
34
+ * }
35
+ * })
36
+ * ```
37
+ */
38
+
39
+ /**
40
+ * Allow access if the subject has any of the specified roles.
41
+ *
42
+ * @example
43
+ * ```typescript
44
+ * read: allow('viewer', 'editor', 'admin', 'owner')
45
+ * ```
46
+ */
47
+ declare function allow(...roles: string[]): AllowExpr;
48
+ /**
49
+ * Deny access if the subject has any of the specified roles.
50
+ * Deny ALWAYS takes precedence over allow.
51
+ *
52
+ * @example
53
+ * ```typescript
54
+ * read: and(allow('member'), deny('banned'))
55
+ * ```
56
+ */
57
+ declare function deny(...roles: string[]): DenyExpr;
58
+ /**
59
+ * Logical AND - all sub-expressions must be true.
60
+ *
61
+ * @example
62
+ * ```typescript
63
+ * write: and(allow('editor'), deny('readonly'))
64
+ * ```
65
+ */
66
+ declare function and(...exprs: AuthExpression[]): AndExpr;
67
+ /**
68
+ * Logical OR - any sub-expression must be true.
69
+ *
70
+ * @example
71
+ * ```typescript
72
+ * read: or(allow('owner'), PUBLIC)
73
+ * ```
74
+ */
75
+ declare function or(...exprs: AuthExpression[]): OrExpr;
76
+ /**
77
+ * Logical NOT - negate the sub-expression.
78
+ *
79
+ * @example
80
+ * ```typescript
81
+ * write: and(AUTHENTICATED, not(allow('banned')))
82
+ * ```
83
+ */
84
+ declare function not(expr: AuthExpression): NotExpr;
85
+ /**
86
+ * Public access - always allows access.
87
+ * Use for read-only public content.
88
+ *
89
+ * @example
90
+ * ```typescript
91
+ * read: PUBLIC
92
+ * ```
93
+ */
94
+ declare const PUBLIC: PublicExpr;
95
+ /**
96
+ * Authenticated access - allows any authenticated user.
97
+ * Use for open-but-not-anonymous content.
98
+ *
99
+ * @example
100
+ * ```typescript
101
+ * read: AUTHENTICATED
102
+ * write: AUTHENTICATED
103
+ * ```
104
+ */
105
+ declare const AUTHENTICATED: AuthenticatedExpr;
106
+ /**
107
+ * Role resolver builders.
108
+ *
109
+ * @example
110
+ * ```typescript
111
+ * roles: {
112
+ * owner: role.creator(),
113
+ * assignee: role.property('assignee'),
114
+ * admin: role.relation('project', 'admin')
115
+ * }
116
+ * ```
117
+ */
118
+ declare const role: {
119
+ /**
120
+ * Role held by the node's creator.
121
+ * The DID in `createdBy` holds this role.
122
+ */
123
+ creator(): CreatorRoleResolver;
124
+ /**
125
+ * Role determined by a person property on the node.
126
+ * The DID(s) in that property hold this role.
127
+ *
128
+ * @param propertyName - Name of the person/person[] property
129
+ */
130
+ property(propertyName: string): PropertyRoleResolver;
131
+ /**
132
+ * Role inherited from a related node.
133
+ * Users who hold `targetRole` on the related node hold this role.
134
+ *
135
+ * @param relationName - Name of the relation property
136
+ * @param targetRole - Role to check on the related node
137
+ */
138
+ relation(relationName: string, targetRole: string): RelationRoleResolver;
139
+ /**
140
+ * Role determined by membership edges that reference THIS node.
141
+ *
142
+ * Unlike `relation` (which follows a forward relation) this is a reverse-edge
143
+ * lookup: the subject holds the role when a `config.edgeSchema` edge points at
144
+ * this node (or, when `parentProp` is set, any ancestor) with the subject as
145
+ * `memberProp` and a `roleProp` rank `>= minRole`. This is how Space
146
+ * membership cascades down a nested container tree.
147
+ *
148
+ * @example
149
+ * ```typescript
150
+ * spaceMember: role.members({
151
+ * edgeSchema: SPACE_MEMBERSHIP_SCHEMA_IRI, containerProp: 'space',
152
+ * memberProp: 'member', roleProp: 'role', minRole: 'member',
153
+ * roleOrder: SPACE_ROLES, parentProp: 'parent'
154
+ * })
155
+ * ```
156
+ */
157
+ members(config: {
158
+ edgeSchema: string;
159
+ containerProp: string;
160
+ memberProp: string;
161
+ roleProp: string;
162
+ minRole: string;
163
+ roleOrder: readonly string[];
164
+ parentProp?: string;
165
+ }): MembershipRoleResolver;
166
+ };
167
+ /**
168
+ * Alias for role.relation() for use in authorization expressions.
169
+ * @deprecated Use role.relation() instead
170
+ */
171
+ declare const relation: (relationName: string, targetRole: string) => RelationRoleResolver;
172
+
173
+ /**
174
+ * Authorization schema validation.
175
+ *
176
+ * Validates that authorization blocks are well-formed:
177
+ * - Role references in actions exist in the roles definition
178
+ * - Property-based roles reference existing person properties
179
+ * - Expression depth limits are enforced
180
+ */
181
+
182
+ /**
183
+ * Result of authorization schema validation.
184
+ */
185
+ interface AuthValidationResult {
186
+ valid: boolean;
187
+ errors: AuthValidationError[];
188
+ }
189
+ /**
190
+ * A single validation error.
191
+ */
192
+ interface AuthValidationError {
193
+ /** Error code for programmatic handling */
194
+ code: AuthSchemaErrorCode;
195
+ /** Human-readable error message */
196
+ message: string;
197
+ /** JSON path to the error location */
198
+ path: string;
199
+ }
200
+ /**
201
+ * Error codes for authorization schema validation.
202
+ */
203
+ type AuthSchemaErrorCode = 'AUTH_SCHEMA_INVALID_ROLE_REF' | 'AUTH_SCHEMA_INVALID_ACTION_REF' | 'AUTH_SCHEMA_INVALID_RELATION_PATH' | 'AUTH_SCHEMA_ROLE_CYCLE' | 'AUTH_SCHEMA_EXPR_LIMIT_EXCEEDED' | 'AUTH_SCHEMA_UNSAFE_PUBLIC_MUTATION' | 'AUTH_SCHEMA_INVALID_FIELD_REF' | 'AUTH_SCHEMA_INVALID_PUBLIC_PROP';
204
+ /**
205
+ * Roles that are always available without definition.
206
+ */
207
+ declare const BUILTIN_ROLES: readonly ["owner"];
208
+ /**
209
+ * Extract all role references from an authorization expression.
210
+ */
211
+ declare function extractRoleRefs(expr: AuthExpression): string[];
212
+ /**
213
+ * Count the number of nodes in an expression tree.
214
+ */
215
+ declare function countExpressionNodes(expr: AuthExpression): number;
216
+ /**
217
+ * Check if an expression allows public access.
218
+ */
219
+ declare function hasPublicAccess(expr: AuthExpression): boolean;
220
+ /**
221
+ * Maximum allowed nodes in an expression tree.
222
+ */
223
+ declare const MAX_EXPRESSION_NODES = 50;
224
+ /**
225
+ * Validate an authorization definition against property definitions.
226
+ *
227
+ * Checks:
228
+ * 1. All role references in action expressions exist in roles
229
+ * 2. Property-based roles reference existing person properties
230
+ * 3. Relation-based roles reference existing relation properties
231
+ * 4. publicProps reference existing properties
232
+ * 5. Expression depth limits are enforced
233
+ * 6. Write/delete/share actions don't use PUBLIC (unsafe)
234
+ */
235
+ declare function validateAuthorization(auth: AuthorizationDefinition, properties: Record<string, PropertyDefinition>): AuthValidationResult;
236
+
237
+ /**
238
+ * Serialization and deserialization of authorization definitions.
239
+ *
240
+ * Authorization blocks in schemas need to be serialized to JSON for storage
241
+ * and deserialized back to typed objects for evaluation.
242
+ */
243
+
244
+ /**
245
+ * Serialize an AuthExpression to its JSON-serializable form.
246
+ */
247
+ declare function serializeAuthExpression(expr: AuthExpression): SerializedAuthExpression;
248
+ /**
249
+ * Deserialize a SerializedAuthExpression back to its typed form.
250
+ */
251
+ declare function deserializeAuthExpression(serialized: SerializedAuthExpression): AuthExpression;
252
+ /**
253
+ * Serialize an AuthorizationDefinition to its JSON-serializable form.
254
+ */
255
+ declare function serializeAuthorization(auth: AuthorizationDefinition): SerializedAuthorization;
256
+ /**
257
+ * Deserialize a SerializedAuthorization back to its typed form.
258
+ */
259
+ declare function deserializeAuthorization(serialized: SerializedAuthorization): AuthorizationDefinition;
260
+
261
+ /**
262
+ * Authorization presets - common authorization patterns as reusable factories.
263
+ *
264
+ * @example
265
+ * ```typescript
266
+ * import { presets } from '@xnetjs/data/auth'
267
+ *
268
+ * const NoteSchema = defineSchema({
269
+ * name: 'Note',
270
+ * namespace: 'xnet://myapp/',
271
+ * properties: { ... },
272
+ * authorization: presets.private()
273
+ * })
274
+ *
275
+ * const PublicArticleSchema = defineSchema({
276
+ * name: 'Article',
277
+ * namespace: 'xnet://myapp/',
278
+ * properties: { ... },
279
+ * authorization: presets.publicRead()
280
+ * })
281
+ * ```
282
+ */
283
+
284
+ /**
285
+ * Authorization presets for common patterns.
286
+ */
287
+ declare const presets: {
288
+ /**
289
+ * Private - only the creator can access.
290
+ *
291
+ * Use for personal notes, private documents, etc.
292
+ */
293
+ private: () => AuthorizationDefinition;
294
+ /**
295
+ * Public read - anyone can read, only creator can write.
296
+ *
297
+ * Use for published content, blog posts, etc.
298
+ */
299
+ publicRead: () => AuthorizationDefinition;
300
+ /**
301
+ * Collaborative - roles inherited from a parent relation.
302
+ *
303
+ * Use for items within a workspace/project that inherits permissions.
304
+ *
305
+ * @param parentRelation - Name of the relation property to the parent node
306
+ */
307
+ collaborative: (parentRelation: string) => AuthorizationDefinition;
308
+ /**
309
+ * Open - any authenticated user can read/write, only creator can delete.
310
+ *
311
+ * Use for wiki-style collaborative content.
312
+ */
313
+ open: () => AuthorizationDefinition;
314
+ /**
315
+ * Team-based - permissions based on a team/editors property.
316
+ *
317
+ * @param editorsProperty - Name of the person[] property containing editors
318
+ */
319
+ team: (editorsProperty: string) => AuthorizationDefinition;
320
+ };
321
+
322
+ /**
323
+ * Authorization mode helpers for schema compatibility.
324
+ */
325
+
326
+ type AuthMode = 'legacy' | 'compat' | 'enforce';
327
+ /**
328
+ * Determine authorization mode for a schema.
329
+ */
330
+ declare function getAuthMode(schema: Schema): AuthMode;
331
+ /**
332
+ * Warn developers when a schema has no authorization block.
333
+ */
334
+ declare function warnLegacySchema(schema: Schema): void;
335
+
336
+ declare const PUBLIC_CONTENT_KEY: Uint8Array<ArrayBuffer>;
337
+ declare const PUBLIC_RECIPIENT = "PUBLIC";
338
+ type Recipient = DID | typeof PUBLIC_RECIPIENT;
339
+ interface GrantRecordLike {
340
+ id: string;
341
+ properties: Record<string, unknown>;
342
+ }
343
+ interface GrantIndexReader {
344
+ findGrantsForResource(resourceId: string): GrantRecordLike[];
345
+ }
346
+ interface RecipientDependencies {
347
+ getNode: (nodeId: string) => Promise<NodeState | null>;
348
+ getSchema?: (schemaId: SchemaIRI) => Promise<Schema | undefined>;
349
+ /** Lists all nodes of a schema — required to expand membership-edge roles. */
350
+ listNodes?: (schemaId: string) => Promise<NodeState[]>;
351
+ grantIndex?: GrantIndexReader;
352
+ maxDepth?: number;
353
+ /**
354
+ * Account/device re-wrap (exploration 0243, P2.3). When set, each DID recipient is
355
+ * expanded to every active device of the account it belongs to, so a user's content
356
+ * is decryptable on all their devices. Build it with `deviceRecipientExpander` from
357
+ * the ledger records. Omitted → recipients are exactly the resolved DIDs (no change).
358
+ */
359
+ expandDeviceRecipients?: (did: DID) => readonly string[];
360
+ }
361
+ declare function computeRecipients(schema: Schema, node: NodeState, dependencies: RecipientDependencies): Promise<Recipient[]>;
362
+ declare function hasRecipientsChanged(previous: Recipient[], next: Recipient[]): boolean;
363
+ declare function canTransitionToPublic(readExpr: AuthExpression | undefined): boolean;
364
+
365
+ interface AuthMigrationDependencies extends RecipientDependencies {
366
+ encryptExistingNode: (node: NodeState, schema: Schema) => Promise<void>;
367
+ rotateContentKeyForNode: (nodeId: string, recipients: Recipient[]) => Promise<void>;
368
+ }
369
+ declare function handleAuthMigration(oldSchema: Schema, newSchema: Schema, node: NodeState, dependencies: AuthMigrationDependencies): Promise<void>;
370
+
371
+ interface EncryptionLayer {
372
+ encryptAndStoreNode(node: NodeState, recipientKeys: Map<DID, Uint8Array>): Promise<void>;
373
+ }
374
+ interface MigrationOptions {
375
+ batchSize?: number;
376
+ onProgress?: (done: number, total: number) => void;
377
+ }
378
+ interface MigrationError {
379
+ nodeId: string;
380
+ error: string;
381
+ }
382
+ interface MigrationResult {
383
+ total: number;
384
+ migrated: number;
385
+ failed: number;
386
+ errors: MigrationError[];
387
+ }
388
+ interface AuthMigratorStore {
389
+ get(nodeId: string): Promise<NodeState | null>;
390
+ list(options?: {
391
+ schemaId?: string;
392
+ includeDeleted?: boolean;
393
+ }): Promise<NodeState[]>;
394
+ }
395
+ interface AuthMigratorSchemaRegistry {
396
+ get(schemaId: SchemaIRI): Promise<{
397
+ schema: Schema;
398
+ } | undefined>;
399
+ }
400
+ declare class AuthMigrator {
401
+ private readonly store;
402
+ private readonly schemaRegistry;
403
+ private readonly publicKeyResolver;
404
+ private readonly grantIndex;
405
+ private readonly encryptionLayer;
406
+ constructor(store: AuthMigratorStore, schemaRegistry: AuthMigratorSchemaRegistry, publicKeyResolver: PublicKeyResolver, grantIndex: GrantIndexReader, encryptionLayer: EncryptionLayer);
407
+ migrateSchema(schemaIri: SchemaIRI, options?: MigrationOptions): Promise<MigrationResult>;
408
+ private resolveSchema;
409
+ }
410
+
411
+ interface AuthFeatureFlags {
412
+ enforceLocal: boolean;
413
+ enforceRemote: boolean;
414
+ enforceHub: boolean;
415
+ enforceEncryption: boolean;
416
+ logDecisions: boolean;
417
+ }
418
+ declare const AUTH_FEATURE_FLAGS: AuthFeatureFlags;
419
+
420
+ export { AUTHENTICATED, AUTH_FEATURE_FLAGS, type AuthFeatureFlags, type AuthMigrationDependencies, AuthMigrator, type AuthMigratorSchemaRegistry, type AuthMigratorStore, type AuthMode, type AuthSchemaErrorCode, type AuthValidationError, type AuthValidationResult, BUILTIN_ROLES, type EncryptionLayer, type GrantIndexReader, type GrantRecordLike, MAX_EXPRESSION_NODES, type MigrationError, type MigrationOptions, type MigrationResult, PUBLIC, PUBLIC_CONTENT_KEY, PUBLIC_RECIPIENT, type Recipient, type RecipientDependencies, allow, and, canTransitionToPublic, computeRecipients, countExpressionNodes, deny, deserializeAuthExpression, deserializeAuthorization, extractRoleRefs, getAuthMode, handleAuthMigration, hasPublicAccess, hasRecipientsChanged, not, or, presets, relation, role, serializeAuthExpression, serializeAuthorization, validateAuthorization, warnLegacySchema };