@xnetjs/data 0.0.2 → 0.0.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.
Files changed (137) hide show
  1. package/README.md +112 -0
  2. package/dist/account-BZHETMC4.js +12 -0
  3. package/dist/auth/index.d.ts +413 -0
  4. package/dist/auth/index.js +102 -0
  5. package/dist/budget-WR2Q4YH3.js +12 -0
  6. package/dist/canvas-HFMMVQLD.js +10 -0
  7. package/dist/channel-DXDYJ3ZH.js +12 -0
  8. package/dist/chat-message-QUUQGXEW.js +10 -0
  9. package/dist/chunk-2DSDH2ZH.js +52 -0
  10. package/dist/chunk-337E3ZOB.js +54 -0
  11. package/dist/chunk-37267RSF.js +41 -0
  12. package/dist/chunk-3JKW6TDE.js +66 -0
  13. package/dist/chunk-3RB2FMMO.js +148 -0
  14. package/dist/{chunk-BQBPA5HS.js → chunk-4U4KBCDN.js} +16 -2
  15. package/dist/chunk-4UQTURCD.js +722 -0
  16. package/dist/chunk-54Y7QRZN.js +109 -0
  17. package/dist/chunk-5FHJE7RC.js +46 -0
  18. package/dist/chunk-64AM6JPM.js +40 -0
  19. package/dist/chunk-6CN53PON.js +143 -0
  20. package/dist/chunk-6GB7PBCR.js +40 -0
  21. package/dist/chunk-6OPZJ7MG.js +78 -0
  22. package/dist/{chunk-IDMBCRUC.js → chunk-77UDLVQY.js} +1 -1
  23. package/dist/chunk-7GMJOAPF.js +52 -0
  24. package/dist/chunk-7PDRDSFH.js +69 -0
  25. package/dist/chunk-C5IRSEEZ.js +69 -0
  26. package/dist/chunk-CHZUSBSB.js +45 -0
  27. package/dist/chunk-DOZJXPQ6.js +232 -0
  28. package/dist/chunk-DTPSTMUD.js +105 -0
  29. package/dist/chunk-E6S557NC.js +402 -0
  30. package/dist/chunk-EIQX7INF.js +45 -0
  31. package/dist/chunk-ENTHVNOC.js +57 -0
  32. package/dist/chunk-EZA5UT4Y.js +5543 -0
  33. package/dist/chunk-GR3NDMBY.js +76 -0
  34. package/dist/chunk-GWYVY2K4.js +63 -0
  35. package/dist/chunk-IJ675GJR.js +42 -0
  36. package/dist/chunk-IP4BEVVD.js +57 -0
  37. package/dist/chunk-J4IVJA5M.js +102 -0
  38. package/dist/chunk-J6EDPPH4.js +84 -0
  39. package/dist/{chunk-SZC345Z2.js → chunk-JESSJ5CZ.js} +1015 -1110
  40. package/dist/chunk-JO6Y4E5V.js +73 -0
  41. package/dist/chunk-KPVBKKZS.js +47 -0
  42. package/dist/chunk-KTJLFJEQ.js +43 -0
  43. package/dist/chunk-L66WXPTW.js +32 -0
  44. package/dist/chunk-LGD72FVD.js +48 -0
  45. package/dist/chunk-O64EK5FK.js +887 -0
  46. package/dist/chunk-PMUQACPY.js +33 -0
  47. package/dist/chunk-PSUJEKVV.js +1722 -0
  48. package/dist/chunk-QVZXXJSP.js +6122 -0
  49. package/dist/chunk-QWFTRZQT.js +142 -0
  50. package/dist/chunk-RSSZXCLL.js +51 -0
  51. package/dist/chunk-S4B5OPZU.js +415 -0
  52. package/dist/{chunk-VYR5GPJP.js → chunk-SPFKSTPT.js} +9 -3
  53. package/dist/chunk-U6CBYDVZ.js +50 -0
  54. package/dist/chunk-UDUPQKRB.js +49 -0
  55. package/dist/chunk-V6HZ3LF3.js +380 -0
  56. package/dist/chunk-WMSCEBFH.js +64 -0
  57. package/dist/chunk-WUR3WWQM.js +65 -0
  58. package/dist/chunk-XHEA5UER.js +75 -0
  59. package/dist/chunk-XTUGZSYQ.js +75 -0
  60. package/dist/chunk-XWA3CJQ6.js +45 -0
  61. package/dist/chunk-YEQ6LLUY.js +49 -0
  62. package/dist/chunk-YWN27MLD.js +47 -0
  63. package/dist/chunk-YXZGYLKV.js +65 -0
  64. package/dist/chunk-ZICIXDEE.js +54 -0
  65. package/dist/chunk-ZMCO3O2Z.js +70 -0
  66. package/dist/clone-DpbVKLUu.d.ts +2205 -0
  67. package/dist/comment-Y2Y3QYYI.js +10 -0
  68. package/dist/crm-AAJXYIJY.js +68 -0
  69. package/dist/dashboard-3DC6B4BJ.js +10 -0
  70. package/dist/database/index.d.ts +882 -0
  71. package/dist/database/index.js +523 -0
  72. package/dist/database-DRGL5UYS.js +10 -0
  73. package/dist/database-field-F47FY3XX.js +10 -0
  74. package/dist/database-row-77OXW2NF.js +10 -0
  75. package/dist/database-select-option-6S3TTA7A.js +10 -0
  76. package/dist/database-view-YW7DQG5X.js +10 -0
  77. package/dist/experiment-TJOAL3OH.js +10 -0
  78. package/dist/external-item-D654PKLI.js +14 -0
  79. package/dist/external-reference-K5SUJIQN.js +8 -0
  80. package/dist/feed-L23XTNDI.js +12 -0
  81. package/dist/feed-item-GSO242J6.js +12 -0
  82. package/dist/folder-ONKSWHUT.js +21 -0
  83. package/dist/game-BF7DP5JU.js +50 -0
  84. package/dist/grant-NNKMWXPX.js +8 -0
  85. package/dist/grant-expiration-cleaner-DBiNTWbD.d.ts +249 -0
  86. package/dist/import-batch-JMESZ4VI.js +12 -0
  87. package/dist/inbox-state-AN6FPCIY.js +12 -0
  88. package/dist/index.d.ts +224 -4548
  89. package/dist/index.js +2206 -4754
  90. package/dist/map-AUV65YS3.js +10 -0
  91. package/dist/media-asset-4I5YPR4R.js +8 -0
  92. package/dist/memory-NV6EVJBE.js +12 -0
  93. package/dist/metric-X7W55DLC.js +10 -0
  94. package/dist/milestone-JJGOGK4R.js +12 -0
  95. package/dist/moderation-QSUVBCNS.js +30 -0
  96. package/dist/observation-UZSXXGBC.js +10 -0
  97. package/dist/page-NI7XODS6.js +10 -0
  98. package/dist/posting-FZOYVGH2.js +12 -0
  99. package/dist/profile-42A43GES.js +8 -0
  100. package/dist/project-G2CTLDXY.js +10 -0
  101. package/dist/query-ast-CWo6_30h.d.ts +226 -0
  102. package/dist/reaction-VAQBVDUD.js +10 -0
  103. package/dist/registry-CQoN_p8U.d.ts +99 -0
  104. package/dist/saved-view-AOQHGHNM.js +10 -0
  105. package/dist/schema/index.d.ts +6182 -0
  106. package/dist/schema/index.js +631 -0
  107. package/dist/schema-extension-5BUXRDPB.js +18 -0
  108. package/dist/space-PZ737CIS.js +42 -0
  109. package/dist/space-membership-N35NRX6F.js +14 -0
  110. package/dist/store/index.d.ts +391 -0
  111. package/dist/store/index.js +135 -0
  112. package/dist/store-CvgiydME.d.ts +338 -0
  113. package/dist/sync/awareness.d.ts +69 -0
  114. package/dist/sync/awareness.js +20 -0
  115. package/dist/system-Q5I6STDC.js +38 -0
  116. package/dist/tag-C677GKQW.js +16 -0
  117. package/dist/task-WQLMPN5U.js +16 -0
  118. package/dist/task-view-T5S32V4L.js +10 -0
  119. package/dist/transaction-U3ITRGJP.js +12 -0
  120. package/dist/transcription-F3T23LLO.js +12 -0
  121. package/dist/types-Def-5Nka.d.ts +1525 -0
  122. package/dist/updates.d.ts +44 -0
  123. package/dist/updates.js +16 -0
  124. package/dist/user-widget-4SJJFPG5.js +8 -0
  125. package/dist/view-types-DSde-uT_.d.ts +316 -0
  126. package/package.json +32 -9
  127. package/dist/canvas-HSIKIQFK.js +0 -7
  128. package/dist/chunk-2L5ZUGG5.js +0 -53
  129. package/dist/chunk-4MTS5KAQ.js +0 -22
  130. package/dist/chunk-GZHARFKC.js +0 -25
  131. package/dist/chunk-WKIKJTI2.js +0 -45
  132. package/dist/comment-277JD7DV.js +0 -7
  133. package/dist/database-W3KEHLI3.js +0 -7
  134. package/dist/database-row-3O2QSNZN.js +0 -7
  135. package/dist/grant-QVZ454YC.js +0 -7
  136. package/dist/page-O4WTOIEO.js +0 -7
  137. package/dist/task-SEKAYJH7.js +0 -7
@@ -0,0 +1,49 @@
1
+ import {
2
+ spaceCascadeAuthorization
3
+ } from "./chunk-6OPZJ7MG.js";
4
+ import {
5
+ checkbox,
6
+ defineSchema,
7
+ json,
8
+ number,
9
+ relation,
10
+ text
11
+ } from "./chunk-O64EK5FK.js";
12
+
13
+ // src/schema/schemas/database-field.ts
14
+ var DatabaseFieldSchema = defineSchema({
15
+ name: "DatabaseField",
16
+ namespace: "xnet://xnet.fyi/",
17
+ properties: {
18
+ /** Parent database */
19
+ database: relation({
20
+ target: "xnet://xnet.fyi/Database@2.0.0",
21
+ required: true
22
+ }),
23
+ /** Display name */
24
+ name: text({ required: true, maxLength: 200 }),
25
+ /** Field type (FieldType union, enforced in field-operations) */
26
+ type: text({ required: true, maxLength: 50 }),
27
+ /**
28
+ * Type-specific configuration (FieldConfig).
29
+ * Note: select/multiSelect options are NOT stored here — they are
30
+ * separate DatabaseSelectOption nodes so concurrent option creation
31
+ * merges cleanly.
32
+ */
33
+ config: json({}),
34
+ /** Fractional index for default column ordering */
35
+ sortKey: text({ required: true }),
36
+ /** Default column width in pixels (table views) */
37
+ width: number({ min: 40, integer: true }),
38
+ /** Whether this is the title field (exactly one per database) */
39
+ isTitle: checkbox({}),
40
+ /** Hidden by default (views can override) */
41
+ hidden: checkbox({})
42
+ },
43
+ // Inherits access from its home Space (exploration 0181/0192).
44
+ authorization: spaceCascadeAuthorization("database")
45
+ });
46
+
47
+ export {
48
+ DatabaseFieldSchema
49
+ };
@@ -0,0 +1,380 @@
1
+ import {
2
+ checkbox,
3
+ defineSchema,
4
+ number,
5
+ person,
6
+ select,
7
+ text
8
+ } from "./chunk-O64EK5FK.js";
9
+
10
+ // src/schema/schemas/system.ts
11
+ import { base64ToBytes, hashHex, verify } from "@xnetjs/crypto";
12
+ import { parseDID } from "@xnetjs/identity";
13
+ var SCHEMA_STATUS_OPTIONS = [
14
+ { id: "draft", name: "Draft", color: "gray" },
15
+ { id: "published", name: "Published", color: "green" },
16
+ { id: "deprecated", name: "Deprecated", color: "yellow" },
17
+ { id: "revoked", name: "Revoked", color: "red" }
18
+ ];
19
+ var COMPATIBILITY_MODE_OPTIONS = [
20
+ { id: "compatible", name: "Compatible", color: "green" },
21
+ { id: "requires-lens", name: "Requires Lens", color: "yellow" },
22
+ { id: "breaking", name: "Breaking", color: "red" }
23
+ ];
24
+ var POLICY_STATUS_OPTIONS = [
25
+ { id: "active", name: "Active", color: "green" },
26
+ { id: "superseded", name: "Superseded", color: "yellow" },
27
+ { id: "revoked", name: "Revoked", color: "red" }
28
+ ];
29
+ var PRESENCE_VISIBILITY_OPTIONS = [
30
+ { id: "private", name: "Private", color: "gray" },
31
+ { id: "trusted-app", name: "Trusted App", color: "blue" },
32
+ { id: "public-metadata", name: "Public Metadata", color: "green" }
33
+ ];
34
+ var PRESENCE_COUNT_BUCKET_OPTIONS = [
35
+ { id: "0", name: "0", color: "gray" },
36
+ { id: "1", name: "1", color: "gray" },
37
+ { id: "2-5", name: "2-5", color: "blue" },
38
+ { id: "6-20", name: "6-20", color: "blue" },
39
+ { id: "21-100", name: "21-100", color: "green" },
40
+ { id: "100+", name: "100+", color: "green" }
41
+ ];
42
+ var SCHEMA_IRI_PATTERN = /^xnet:\/\/[^/]+\/.+/;
43
+ var SEMVER_PATTERN = /^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?$/;
44
+ var CONTENT_HASH_PATTERN = /^cid:blake3:[0-9a-f]{64}$/;
45
+ var SYSTEM_NAMESPACE_KINDS = ["schema", "compat", "policy", "presence", "authz"];
46
+ var SchemaDefinitionSchema = defineSchema({
47
+ name: "SchemaDefinition",
48
+ namespace: "xnet://xnet.fyi/",
49
+ properties: {
50
+ schemaIri: text({ required: true, pattern: SCHEMA_IRI_PATTERN }),
51
+ version: text({ required: true, pattern: SEMVER_PATTERN }),
52
+ authority: text({ required: true }),
53
+ definitionBytes: text({ required: true, minLength: 2 }),
54
+ contentHash: text({ required: true, pattern: CONTENT_HASH_PATTERN }),
55
+ publishedAt: number({ required: true, integer: true, min: 0 }),
56
+ status: select({ options: SCHEMA_STATUS_OPTIONS, required: true, default: "draft" }),
57
+ signature: text({ required: true, minLength: 80 }),
58
+ signingKeyId: text({ required: true }),
59
+ policyDefaults: text({}),
60
+ authorityProof: text({})
61
+ }
62
+ });
63
+ var SchemaCompatibilitySchema = defineSchema({
64
+ name: "SchemaCompatibility",
65
+ namespace: "xnet://xnet.fyi/",
66
+ properties: {
67
+ fromSchema: text({ required: true, pattern: SCHEMA_IRI_PATTERN }),
68
+ toSchema: text({ required: true, pattern: SCHEMA_IRI_PATTERN }),
69
+ mode: select({ options: COMPATIBILITY_MODE_OPTIONS, required: true }),
70
+ lossless: checkbox({ default: false }),
71
+ lensRef: text({}),
72
+ validatedAt: number({ required: true, integer: true, min: 0 }),
73
+ validatedBy: person({})
74
+ }
75
+ });
76
+ var SyncPolicySchema = defineSchema({
77
+ name: "SyncPolicy",
78
+ namespace: "xnet://xnet.fyi/",
79
+ properties: {
80
+ subjectDid: person({ required: true }),
81
+ matchRules: text({ required: true, minLength: 2 }),
82
+ destinations: text({ required: true, minLength: 2 }),
83
+ priority: number({ required: true, integer: true, min: 0 }),
84
+ revision: number({ required: true, integer: true, min: 1 }),
85
+ effectiveFrom: number({ required: true, integer: true, min: 0 }),
86
+ expiresAt: number({ integer: true, min: 0 }),
87
+ status: select({ options: POLICY_STATUS_OPTIONS, required: true, default: "active" })
88
+ }
89
+ });
90
+ var PresenceSummarySchema = defineSchema({
91
+ name: "PresenceSummary",
92
+ namespace: "xnet://xnet.fyi/",
93
+ properties: {
94
+ subjectDid: person({ required: true }),
95
+ schemaIri: text({ required: true, pattern: SCHEMA_IRI_PATTERN }),
96
+ namespace: text({ required: true }),
97
+ countBucket: select({ options: PRESENCE_COUNT_BUCKET_OPTIONS, required: true }),
98
+ visibility: select({ options: PRESENCE_VISIBILITY_OPTIONS, required: true }),
99
+ lastUpdatedAt: number({ required: true, integer: true, min: 0 }),
100
+ sourcePolicy: text({}),
101
+ noise: text({})
102
+ }
103
+ });
104
+ var SYSTEM_SCHEMA_IRIS = {
105
+ SchemaDefinition: SchemaDefinitionSchema.schema["@id"],
106
+ SchemaCompatibility: SchemaCompatibilitySchema.schema["@id"],
107
+ SyncPolicy: SyncPolicySchema.schema["@id"],
108
+ PresenceSummary: PresenceSummarySchema.schema["@id"]
109
+ };
110
+ var SYSTEM_SCHEMA_BASE_IRIS = {
111
+ SchemaDefinition: "xnet://xnet.fyi/SchemaDefinition",
112
+ SchemaCompatibility: "xnet://xnet.fyi/SchemaCompatibility",
113
+ SyncPolicy: "xnet://xnet.fyi/SyncPolicy",
114
+ PresenceSummary: "xnet://xnet.fyi/PresenceSummary",
115
+ Grant: "xnet://xnet.fyi/Grant"
116
+ };
117
+ function isSystemSchemaIri(schemaIri) {
118
+ return Object.values(SYSTEM_SCHEMA_IRIS).some((iri) => schemaIri === iri) || Object.values(SYSTEM_SCHEMA_BASE_IRIS).some((iri) => schemaIri === iri);
119
+ }
120
+ function buildSystemNamespace(subjectDid, kind) {
121
+ return `xnet://${subjectDid}/sys/${kind}/`;
122
+ }
123
+ function buildSystemNodeId(subjectDid, kind, localId) {
124
+ return `${buildSystemNamespace(subjectDid, kind)}${localId.replace(/^\/+/, "")}`;
125
+ }
126
+ function parseSystemNamespaceResource(resource) {
127
+ const kinds = SYSTEM_NAMESPACE_KINDS.join("|");
128
+ const match = new RegExp(`^xnet://(did:key:[^/]+)/sys/(${kinds})(?:/(.*))?$`).exec(resource);
129
+ if (!match) {
130
+ return null;
131
+ }
132
+ const [, subjectDid, kind, localId = ""] = match;
133
+ return {
134
+ subjectDid,
135
+ kind,
136
+ namespace: buildSystemNamespace(subjectDid, kind),
137
+ localId
138
+ };
139
+ }
140
+ function isSystemNamespaceResource(resource) {
141
+ return parseSystemNamespaceResource(resource) !== null;
142
+ }
143
+ function resolveSchemaAuthority(options) {
144
+ const authority = extractSchemaIriAuthority(options.schemaIri);
145
+ const declaredAuthority = options.authority ?? authority ?? "";
146
+ const errors = [];
147
+ if (!authority) {
148
+ errors.push({
149
+ path: "schemaIri",
150
+ message: "schemaIri must use xnet://<authority>/<name> format",
151
+ value: options.schemaIri
152
+ });
153
+ return { valid: false, errors, kind: "invalid", authority: declaredAuthority };
154
+ }
155
+ if (declaredAuthority !== authority) {
156
+ errors.push({
157
+ path: "authority",
158
+ message: "authority must match schema IRI authority",
159
+ value: declaredAuthority
160
+ });
161
+ }
162
+ if (authority.startsWith("did:key:")) {
163
+ if (options.publisherDid && options.publisherDid !== authority) {
164
+ errors.push({
165
+ path: "publisherDid",
166
+ message: "DID authority schemas must be published by the authority DID",
167
+ value: options.publisherDid
168
+ });
169
+ }
170
+ return { valid: errors.length === 0, errors, kind: "did", authority };
171
+ }
172
+ if (!options.allowDomainAuthority) {
173
+ errors.push({
174
+ path: "schemaIri",
175
+ message: "domain authority schemas require explicit domain linkage policy",
176
+ value: options.schemaIri
177
+ });
178
+ }
179
+ if (options.allowDomainAuthority && !options.domainLinkageProof) {
180
+ errors.push({
181
+ path: "domainLinkageProof",
182
+ message: "domain authority schemas require a domain linkage proof"
183
+ });
184
+ }
185
+ return { valid: errors.length === 0, errors, kind: "domain", authority };
186
+ }
187
+ function computeSchemaDefinitionContentHash(definitionBytes) {
188
+ return `cid:blake3:${hashHex(new TextEncoder().encode(definitionBytes))}`;
189
+ }
190
+ function createSchemaDefinitionSigningPayload(input) {
191
+ return new TextEncoder().encode(canonicalJson(input));
192
+ }
193
+ function validateSchemaDefinitionNode(node, options = {}) {
194
+ const flattened = flattenNodeProperties(node);
195
+ const schemaResult = SchemaDefinitionSchema.validate(flattened);
196
+ const errors = [...schemaResult.errors];
197
+ const schemaIri = asString(flattened.schemaIri);
198
+ const version = asString(flattened.version);
199
+ const authority = asString(flattened.authority);
200
+ const definitionBytes = asString(flattened.definitionBytes);
201
+ const contentHash = asString(flattened.contentHash);
202
+ const signature = asString(flattened.signature);
203
+ const publishedAt = asNumber(flattened.publishedAt);
204
+ const status = asSchemaDefinitionStatus(flattened.status);
205
+ const authorityProof = asString(flattened.authorityProof);
206
+ if (schemaIri && authority) {
207
+ const authorityResult = resolveSchemaAuthority({
208
+ schemaIri,
209
+ authority,
210
+ publisherDid: options.publisherDid ?? asDid(flattened.createdBy),
211
+ allowDomainAuthority: options.allowDomainAuthority,
212
+ domainLinkageProof: options.domainLinkageProof ?? authorityProof ?? void 0
213
+ });
214
+ errors.push(...authorityResult.errors);
215
+ }
216
+ if (definitionBytes && contentHash) {
217
+ const expectedHash = computeSchemaDefinitionContentHash(definitionBytes);
218
+ if (contentHash !== expectedHash) {
219
+ errors.push({
220
+ path: "contentHash",
221
+ message: "contentHash must match definitionBytes",
222
+ value: contentHash
223
+ });
224
+ }
225
+ const parsedDefinition = parseSchemaJson(definitionBytes);
226
+ if (!parsedDefinition) {
227
+ errors.push({
228
+ path: "definitionBytes",
229
+ message: "definitionBytes must contain a valid JSON schema definition"
230
+ });
231
+ } else {
232
+ if (parsedDefinition["@id"] !== schemaIri) {
233
+ errors.push({
234
+ path: "definitionBytes.@id",
235
+ message: "embedded schema @id must match schemaIri",
236
+ value: parsedDefinition["@id"]
237
+ });
238
+ }
239
+ if (parsedDefinition.version !== version) {
240
+ errors.push({
241
+ path: "definitionBytes.version",
242
+ message: "embedded schema version must match version",
243
+ value: parsedDefinition.version
244
+ });
245
+ }
246
+ }
247
+ }
248
+ if (schemaIri && version && authority && contentHash && publishedAt !== null && status && signature) {
249
+ const signatureResult = validateSchemaDefinitionSignature({
250
+ signature,
251
+ authority,
252
+ authorityPublicKey: options.authorityPublicKey,
253
+ payload: createSchemaDefinitionSigningPayload({
254
+ schemaIri,
255
+ version,
256
+ authority,
257
+ contentHash,
258
+ publishedAt,
259
+ status
260
+ })
261
+ });
262
+ errors.push(...signatureResult.errors);
263
+ }
264
+ return { valid: errors.length === 0, errors };
265
+ }
266
+ function validateSchemaDefinitionSignature(input) {
267
+ const errors = [];
268
+ let signatureBytes;
269
+ try {
270
+ signatureBytes = base64ToBytes(input.signature);
271
+ } catch {
272
+ return {
273
+ valid: false,
274
+ errors: [{ path: "signature", message: "signature must be base64 encoded" }]
275
+ };
276
+ }
277
+ if (signatureBytes.length !== 64) {
278
+ errors.push({
279
+ path: "signature",
280
+ message: "signature must be an Ed25519 signature"
281
+ });
282
+ }
283
+ const publicKey = input.authorityPublicKey ?? getAuthorityPublicKey(input.authority);
284
+ if (publicKey && !verify(input.payload, signatureBytes, publicKey)) {
285
+ errors.push({
286
+ path: "signature",
287
+ message: "signature must verify against schema authority"
288
+ });
289
+ }
290
+ return { valid: errors.length === 0, errors };
291
+ }
292
+ function getAuthorityPublicKey(authority) {
293
+ if (!authority.startsWith("did:key:")) {
294
+ return null;
295
+ }
296
+ try {
297
+ return parseDID(authority);
298
+ } catch {
299
+ return null;
300
+ }
301
+ }
302
+ function extractSchemaIriAuthority(schemaIri) {
303
+ const match = /^xnet:\/\/([^/]+)\/.+/.exec(schemaIri);
304
+ return match?.[1] ?? null;
305
+ }
306
+ function flattenNodeProperties(node) {
307
+ if (!isRecord(node)) {
308
+ return {};
309
+ }
310
+ if (isRecord(node.properties)) {
311
+ return {
312
+ id: node.id,
313
+ schemaId: node.schemaId,
314
+ createdAt: node.createdAt,
315
+ createdBy: node.createdBy,
316
+ ...node.properties
317
+ };
318
+ }
319
+ return node;
320
+ }
321
+ function parseSchemaJson(definitionBytes) {
322
+ try {
323
+ const parsed = JSON.parse(definitionBytes);
324
+ if (!isRecord(parsed)) return null;
325
+ if (typeof parsed["@id"] !== "string") return null;
326
+ if (typeof parsed.version !== "string") return null;
327
+ if (!Array.isArray(parsed.properties)) return null;
328
+ return parsed;
329
+ } catch {
330
+ return null;
331
+ }
332
+ }
333
+ function canonicalJson(value) {
334
+ return JSON.stringify(sortKeys(value));
335
+ }
336
+ function sortKeys(value) {
337
+ if (value === null || typeof value !== "object") {
338
+ return value;
339
+ }
340
+ if (Array.isArray(value)) {
341
+ return value.map(sortKeys);
342
+ }
343
+ return Object.fromEntries(
344
+ Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key, entry]) => [key, sortKeys(entry)])
345
+ );
346
+ }
347
+ function isRecord(value) {
348
+ return Boolean(value && typeof value === "object");
349
+ }
350
+ function asString(value) {
351
+ return typeof value === "string" && value.length > 0 ? value : null;
352
+ }
353
+ function asNumber(value) {
354
+ return typeof value === "number" && Number.isFinite(value) ? value : null;
355
+ }
356
+ function asDid(value) {
357
+ return typeof value === "string" && value.startsWith("did:key:") ? value : void 0;
358
+ }
359
+ function asSchemaDefinitionStatus(value) {
360
+ return SCHEMA_STATUS_OPTIONS.some((option) => option.id === value) ? value : null;
361
+ }
362
+
363
+ export {
364
+ SYSTEM_NAMESPACE_KINDS,
365
+ SchemaDefinitionSchema,
366
+ SchemaCompatibilitySchema,
367
+ SyncPolicySchema,
368
+ PresenceSummarySchema,
369
+ SYSTEM_SCHEMA_IRIS,
370
+ SYSTEM_SCHEMA_BASE_IRIS,
371
+ isSystemSchemaIri,
372
+ buildSystemNamespace,
373
+ buildSystemNodeId,
374
+ parseSystemNamespaceResource,
375
+ isSystemNamespaceResource,
376
+ resolveSchemaAuthority,
377
+ computeSchemaDefinitionContentHash,
378
+ createSchemaDefinitionSigningPayload,
379
+ validateSchemaDefinitionNode
380
+ };
@@ -0,0 +1,64 @@
1
+ import {
2
+ spaceCascadeAuthorization
3
+ } from "./chunk-6OPZJ7MG.js";
4
+ import {
5
+ date,
6
+ defineSchema,
7
+ person,
8
+ relation,
9
+ select,
10
+ text
11
+ } from "./chunk-O64EK5FK.js";
12
+
13
+ // src/schema/schemas/project.ts
14
+ var ProjectSchema = defineSchema({
15
+ name: "Project",
16
+ namespace: "xnet://xnet.fyi/",
17
+ properties: {
18
+ /** Project name */
19
+ name: text({ required: true, maxLength: 200 }),
20
+ /** Emoji or icon URL */
21
+ icon: text({ maxLength: 500 }),
22
+ /** Project lifecycle status */
23
+ status: select({
24
+ options: [
25
+ { id: "planned", name: "Planned", color: "gray" },
26
+ { id: "in-progress", name: "In Progress", color: "blue" },
27
+ { id: "paused", name: "Paused", color: "yellow" },
28
+ { id: "completed", name: "Completed", color: "green" },
29
+ { id: "cancelled", name: "Cancelled", color: "red" }
30
+ ],
31
+ default: "planned"
32
+ }),
33
+ /** Project lead */
34
+ lead: person({}),
35
+ /** Target completion date */
36
+ targetDate: date({}),
37
+ /** Canonical home; empty = Unfiled (exploration 0169) */
38
+ folder: relation({ target: "xnet://xnet.fyi/Folder@1.0.0" }),
39
+ /** Order among folder siblings — fractional index */
40
+ sortKey: text({ maxLength: 500 }),
41
+ /** Workspace-wide labels, referenced by id (exploration 0169) */
42
+ tags: relation({ target: "xnet://xnet.fyi/Tag@1.0.0", multiple: true }),
43
+ /** Canonical SECURITY home; empty = personal/private (exploration 0179) */
44
+ space: relation({ target: "xnet://xnet.fyi/Space@1.0.0" }),
45
+ /** Per-node visibility; `inherit` defers to the Space (exploration 0179) */
46
+ visibility: select({
47
+ options: [
48
+ { id: "inherit", name: "Inherit", color: "gray" },
49
+ { id: "private", name: "Private", color: "gray" },
50
+ { id: "unlisted", name: "Unlisted", color: "yellow" },
51
+ { id: "public", name: "Public", color: "green" }
52
+ ],
53
+ default: "inherit"
54
+ })
55
+ },
56
+ document: "yjs",
57
+ // Collaborative project brief
58
+ // Inherits access from its home Space (exploration 0181).
59
+ authorization: spaceCascadeAuthorization()
60
+ });
61
+
62
+ export {
63
+ ProjectSchema
64
+ };
@@ -0,0 +1,65 @@
1
+ import {
2
+ spaceCascadeAuthorization
3
+ } from "./chunk-6OPZJ7MG.js";
4
+ import {
5
+ defineSchema,
6
+ json,
7
+ number,
8
+ relation,
9
+ text
10
+ } from "./chunk-O64EK5FK.js";
11
+
12
+ // src/schema/schemas/schema-extension.ts
13
+ var SCHEMA_EXTENSION_SCHEMA_IRI = "xnet://xnet.fyi/SchemaExtension@1.0.0";
14
+ var EXTENSION_FIELD_SCHEMA_IRI = "xnet://xnet.fyi/ExtensionField@1.0.0";
15
+ var SchemaExtensionSchema = defineSchema({
16
+ name: "SchemaExtension",
17
+ namespace: "xnet://xnet.fyi/",
18
+ properties: {
19
+ /** Versioned IRI of the schema being extended, e.g. 'xnet://xnet.fyi/Contact@1.0.0' */
20
+ targetSchema: text({ required: true, maxLength: 300 }),
21
+ /**
22
+ * Namespace authority that owns these fields — a Space id, a DID, or a
23
+ * domain. Becomes the `<authority>` segment of every `ext:` key, so two
24
+ * tenants extending the same schema never collide.
25
+ */
26
+ authority: text({ required: true, maxLength: 200 }),
27
+ /** Human-readable label for the extension set (e.g. "Acme CRM fields") */
28
+ label: text({ maxLength: 200 }),
29
+ /** Optional owning Space — drives the authorization cascade for this overlay */
30
+ space: relation({ target: "xnet://xnet.fyi/Space@1.0.0" })
31
+ },
32
+ authorization: spaceCascadeAuthorization()
33
+ });
34
+ var ExtensionFieldSchema = defineSchema({
35
+ name: "ExtensionField",
36
+ namespace: "xnet://xnet.fyi/",
37
+ properties: {
38
+ /** Parent SchemaExtension */
39
+ extension: relation({ target: SCHEMA_EXTENSION_SCHEMA_IRI, required: true }),
40
+ /** Field token — the `<field>` segment of the `ext:<authority>/<field>` key */
41
+ name: text({ required: true, maxLength: 200 }),
42
+ /** Field type (FieldType union, enforced in field-operations) */
43
+ type: text({ required: true, maxLength: 50 }),
44
+ /** Type-specific configuration (FieldConfig) */
45
+ config: json({}),
46
+ /** Fractional index for ordering among a schema's extension fields */
47
+ sortKey: text({ required: true }),
48
+ /** Default column width in pixels (table views) */
49
+ width: number({ min: 40, integer: true }),
50
+ /** Optional owning Space — mirrors the parent extension's cascade */
51
+ space: relation({ target: "xnet://xnet.fyi/Space@1.0.0" })
52
+ },
53
+ authorization: spaceCascadeAuthorization()
54
+ });
55
+ function schemaExtensionId(authority, targetSchema) {
56
+ return `schemaext:${authority}:${targetSchema}`;
57
+ }
58
+
59
+ export {
60
+ SCHEMA_EXTENSION_SCHEMA_IRI,
61
+ EXTENSION_FIELD_SCHEMA_IRI,
62
+ SchemaExtensionSchema,
63
+ ExtensionFieldSchema,
64
+ schemaExtensionId
65
+ };
@@ -0,0 +1,75 @@
1
+ // src/updates.ts
2
+ import { sign, verify, hashHex } from "@xnetjs/crypto";
3
+ import * as Y from "yjs";
4
+ function signUpdate(options) {
5
+ const { update, authorDID, signingKey, parentHash, vectorClock } = options;
6
+ const updateHash = hashHex(update);
7
+ const timestamp = Date.now();
8
+ const signaturePayload = new TextEncoder().encode(
9
+ JSON.stringify({ updateHash, parentHash, authorDID, timestamp })
10
+ );
11
+ const signature = sign(signaturePayload, signingKey);
12
+ return {
13
+ update,
14
+ parentHash,
15
+ updateHash,
16
+ authorDID,
17
+ signature,
18
+ timestamp,
19
+ vectorClock
20
+ };
21
+ }
22
+ function verifyUpdate(update, getPublicKey) {
23
+ const publicKey = getPublicKey(update.authorDID);
24
+ if (!publicKey) return false;
25
+ const actualHash = hashHex(update.update);
26
+ if (actualHash !== update.updateHash) return false;
27
+ const signaturePayload = new TextEncoder().encode(
28
+ JSON.stringify({
29
+ updateHash: update.updateHash,
30
+ parentHash: update.parentHash,
31
+ authorDID: update.authorDID,
32
+ timestamp: update.timestamp
33
+ })
34
+ );
35
+ return verify(signaturePayload, update.signature, publicKey);
36
+ }
37
+ function applySignedUpdate(doc, update) {
38
+ Y.applyUpdate(doc, update.update);
39
+ }
40
+ function captureUpdate(doc, authorDID, signingKey, parentHash, vectorClock, callback) {
41
+ let capturedUpdate = null;
42
+ const handler = (update) => {
43
+ capturedUpdate = update;
44
+ };
45
+ doc.on("update", handler);
46
+ callback();
47
+ doc.off("update", handler);
48
+ if (!capturedUpdate) return null;
49
+ return signUpdate({
50
+ doc,
51
+ update: capturedUpdate,
52
+ authorDID,
53
+ signingKey,
54
+ parentHash,
55
+ vectorClock
56
+ });
57
+ }
58
+ function mergeDocuments(target, sources) {
59
+ for (const source of sources) {
60
+ const state = Y.encodeStateAsUpdate(source);
61
+ Y.applyUpdate(target, state);
62
+ }
63
+ }
64
+ function getMissingUpdates(doc, remoteStateVector) {
65
+ return Y.encodeStateAsUpdate(doc, remoteStateVector);
66
+ }
67
+
68
+ export {
69
+ signUpdate,
70
+ verifyUpdate,
71
+ applySignedUpdate,
72
+ captureUpdate,
73
+ mergeDocuments,
74
+ getMissingUpdates
75
+ };