@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.
- package/README.md +112 -0
- package/dist/account-MWNCH4GJ.js +12 -0
- package/dist/account-ledger-R2GAFJL6.js +38 -0
- package/dist/auth/index.d.ts +420 -0
- package/dist/auth/index.js +102 -0
- package/dist/budget-NN7P35XP.js +12 -0
- package/dist/canvas-6WYBNH53.js +10 -0
- package/dist/channel-AT3LQF4A.js +12 -0
- package/dist/chat-message-DSVO72B3.js +10 -0
- package/dist/chunk-2ZNJWIQG.js +84 -0
- package/dist/chunk-3J3HILXO.js +46 -0
- package/dist/chunk-3RUDVTMH.js +5543 -0
- package/dist/chunk-4EYKGTSQ.js +49 -0
- package/dist/chunk-53F4PRNC.js +32 -0
- package/dist/chunk-5EXHNXPL.js +48 -0
- package/dist/{chunk-BQBPA5HS.js → chunk-5HC5NO57.js} +16 -2
- package/dist/chunk-6KLGA6IR.js +47 -0
- package/dist/chunk-6OMG4I7M.js +41 -0
- package/dist/chunk-7PDRDSFH.js +69 -0
- package/dist/chunk-BQLQSWKZ.js +232 -0
- package/dist/chunk-BY5O6LNC.js +380 -0
- package/dist/chunk-DCTRX6II.js +40 -0
- package/dist/{chunk-VYR5GPJP.js → chunk-DWEXKD6E.js} +9 -3
- package/dist/chunk-EBNMV2VO.js +896 -0
- package/dist/chunk-FVEACSKE.js +102 -0
- package/dist/chunk-GU6THOAB.js +45 -0
- package/dist/chunk-H4GA4BBK.js +75 -0
- package/dist/chunk-IJ44LR7N.js +76 -0
- package/dist/chunk-J4ANIXIV.js +402 -0
- package/dist/chunk-JDFNMFOZ.js +45 -0
- package/dist/chunk-K7DOZWWT.js +1811 -0
- package/dist/chunk-KQAT4XBL.js +49 -0
- package/dist/chunk-KQUALW4O.js +183 -0
- package/dist/chunk-LYSWLCOI.js +47 -0
- package/dist/chunk-MBTUO3ZL.js +65 -0
- package/dist/chunk-NI4FHG2K.js +52 -0
- package/dist/chunk-OCMSAKWV.js +78 -0
- package/dist/chunk-OGJCRNGE.js +57 -0
- package/dist/chunk-OPPHF3TF.js +143 -0
- package/dist/{chunk-IDMBCRUC.js → chunk-OSAWNZVM.js} +1 -1
- package/dist/chunk-PMUQACPY.js +33 -0
- package/dist/chunk-PNESGUH5.js +63 -0
- package/dist/chunk-Q3IEGH4B.js +51 -0
- package/dist/chunk-QJW5LDP4.js +52 -0
- package/dist/chunk-QWFTRZQT.js +142 -0
- package/dist/{chunk-SZC345Z2.js → chunk-RL64OJJ5.js} +1025 -1110
- package/dist/chunk-S5RP5RKY.js +416 -0
- package/dist/chunk-S6U6TCMN.js +722 -0
- package/dist/chunk-SVNGSZZA.js +69 -0
- package/dist/chunk-T5AZAOG5.js +54 -0
- package/dist/chunk-TCTZW4A6.js +42 -0
- package/dist/chunk-U64CW73O.js +109 -0
- package/dist/chunk-UDWKWTAX.js +6526 -0
- package/dist/chunk-UQM3G5A2.js +148 -0
- package/dist/chunk-VQ7JHB67.js +57 -0
- package/dist/chunk-W7EBL7ZU.js +73 -0
- package/dist/chunk-WEPK7SZF.js +65 -0
- package/dist/chunk-XHEA5UER.js +75 -0
- package/dist/chunk-XMSKJ5PV.js +66 -0
- package/dist/chunk-XROI44ZP.js +64 -0
- package/dist/chunk-Y3S5SRVM.js +45 -0
- package/dist/chunk-YEFKQYKA.js +43 -0
- package/dist/chunk-YSUIXD2Y.js +105 -0
- package/dist/chunk-ZCOFZY5M.js +70 -0
- package/dist/chunk-ZLU4Y3O2.js +50 -0
- package/dist/chunk-ZPZ7XDA6.js +54 -0
- package/dist/chunk-ZZ6TWKGS.js +40 -0
- package/dist/clone-C0Jhk2UN.d.ts +2205 -0
- package/dist/comment-QSWYAQVS.js +10 -0
- package/dist/crm-L5RYAAF3.js +68 -0
- package/dist/dashboard-JMKTTRA7.js +10 -0
- package/dist/database/index.d.ts +882 -0
- package/dist/database/index.js +523 -0
- package/dist/database-GIXSPZJW.js +10 -0
- package/dist/database-field-3EPAMZUR.js +10 -0
- package/dist/database-row-6Q6TRVE4.js +10 -0
- package/dist/database-select-option-BBBJFLLH.js +10 -0
- package/dist/database-view-5PLSOBI2.js +10 -0
- package/dist/experiment-DOVOZ34Y.js +10 -0
- package/dist/external-item-P2E5X7BZ.js +14 -0
- package/dist/external-reference-7BSFF6SA.js +8 -0
- package/dist/feed-2IXHHP6O.js +12 -0
- package/dist/feed-item-DPE6LN7I.js +12 -0
- package/dist/folder-6KM3KYD5.js +21 -0
- package/dist/game-5AK5XWBR.js +50 -0
- package/dist/grant-WTQSNT5A.js +8 -0
- package/dist/grant-expiration-cleaner-CY6BcmlR.d.ts +249 -0
- package/dist/import-batch-IXBJLQPJ.js +12 -0
- package/dist/inbox-state-E5NSVOGP.js +12 -0
- package/dist/index.d.ts +224 -4548
- package/dist/index.js +2252 -4754
- package/dist/map-RG5Y3CPC.js +10 -0
- package/dist/media-asset-QTCGLIZA.js +8 -0
- package/dist/memory-PNRTMBZO.js +12 -0
- package/dist/metric-65SVOX5C.js +10 -0
- package/dist/milestone-XEO6ZGDG.js +12 -0
- package/dist/moderation-FFHETMRB.js +30 -0
- package/dist/observation-2Y3QKUXM.js +10 -0
- package/dist/page-2V27JGKJ.js +10 -0
- package/dist/posting-GBOSZCMZ.js +12 -0
- package/dist/profile-BLLDWIDK.js +8 -0
- package/dist/project-CQL5LN26.js +10 -0
- package/dist/query-ast-C3m6kZYv.d.ts +226 -0
- package/dist/reaction-T2DTJBBV.js +10 -0
- package/dist/registry-DunPv__d.d.ts +99 -0
- package/dist/saved-view-4R2DBCL3.js +10 -0
- package/dist/schema/index.d.ts +6489 -0
- package/dist/schema/index.js +677 -0
- package/dist/schema-extension-LNRF2YRD.js +18 -0
- package/dist/space-IJU24PBH.js +42 -0
- package/dist/space-membership-DEUMM7NV.js +14 -0
- package/dist/store/index.d.ts +518 -0
- package/dist/store/index.js +135 -0
- package/dist/store-DtIDjk7c.d.ts +355 -0
- package/dist/sync/awareness.d.ts +69 -0
- package/dist/sync/awareness.js +20 -0
- package/dist/system-ILHCZOVO.js +38 -0
- package/dist/tag-SKCHM3U5.js +16 -0
- package/dist/task-7AOBP7WC.js +16 -0
- package/dist/task-view-NUGKELJP.js +10 -0
- package/dist/transaction-ZDSEGDIR.js +12 -0
- package/dist/transcription-PSCLDAGX.js +12 -0
- package/dist/types-S-BJAKyK.d.ts +1576 -0
- package/dist/updates.d.ts +44 -0
- package/dist/updates.js +16 -0
- package/dist/user-widget-RLY2N46A.js +8 -0
- package/dist/view-types-DSde-uT_.d.ts +316 -0
- package/package.json +32 -9
- package/dist/canvas-HSIKIQFK.js +0 -7
- package/dist/chunk-2L5ZUGG5.js +0 -53
- package/dist/chunk-4MTS5KAQ.js +0 -22
- package/dist/chunk-GZHARFKC.js +0 -25
- package/dist/chunk-WKIKJTI2.js +0 -45
- package/dist/comment-277JD7DV.js +0 -7
- package/dist/database-W3KEHLI3.js +0 -7
- package/dist/database-row-3O2QSNZN.js +0 -7
- package/dist/grant-QVZ454YC.js +0 -7
- package/dist/page-O4WTOIEO.js +0 -7
- package/dist/task-SEKAYJH7.js +0 -7
|
@@ -0,0 +1,380 @@
|
|
|
1
|
+
import {
|
|
2
|
+
checkbox,
|
|
3
|
+
defineSchema,
|
|
4
|
+
number,
|
|
5
|
+
person,
|
|
6
|
+
select,
|
|
7
|
+
text
|
|
8
|
+
} from "./chunk-EBNMV2VO.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,40 @@
|
|
|
1
|
+
import {
|
|
2
|
+
created,
|
|
3
|
+
createdBy,
|
|
4
|
+
defineSchema,
|
|
5
|
+
person,
|
|
6
|
+
text
|
|
7
|
+
} from "./chunk-EBNMV2VO.js";
|
|
8
|
+
|
|
9
|
+
// src/schema/schemas/profile.ts
|
|
10
|
+
var ProfileSchema = defineSchema({
|
|
11
|
+
name: "Profile",
|
|
12
|
+
namespace: "xnet://xnet.fyi/",
|
|
13
|
+
properties: {
|
|
14
|
+
/** The DID this profile describes (should match createdBy) */
|
|
15
|
+
did: person({ required: true }),
|
|
16
|
+
/** Human-readable display name */
|
|
17
|
+
displayName: text({ required: true, maxLength: 120 }),
|
|
18
|
+
/**
|
|
19
|
+
* Optional @handle — a short, workspace-unique slug for typing mentions
|
|
20
|
+
* (exploration 0172). The stable identity is always the DID; the handle is
|
|
21
|
+
* a resolver input at compose time and a display option at read time, so a
|
|
22
|
+
* rename never breaks an existing mention. Global uniqueness is out of
|
|
23
|
+
* scope — the DID remains the source of truth.
|
|
24
|
+
*/
|
|
25
|
+
handle: text({ maxLength: 32 }),
|
|
26
|
+
/** Avatar URL or blob reference */
|
|
27
|
+
avatar: text({ maxLength: 500 }),
|
|
28
|
+
/** Short status emoji (e.g. 🔴, 🌴) */
|
|
29
|
+
statusEmoji: text({ maxLength: 32 }),
|
|
30
|
+
/** Free-form status message */
|
|
31
|
+
statusMessage: text({ maxLength: 200 }),
|
|
32
|
+
createdAt: created(),
|
|
33
|
+
createdBy: createdBy()
|
|
34
|
+
},
|
|
35
|
+
document: void 0
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
export {
|
|
39
|
+
ProfileSchema
|
|
40
|
+
};
|
|
@@ -1,20 +1,24 @@
|
|
|
1
|
+
import {
|
|
2
|
+
spaceCascadeAuthorization
|
|
3
|
+
} from "./chunk-OCMSAKWV.js";
|
|
1
4
|
import {
|
|
2
5
|
defineSchema,
|
|
3
6
|
relation,
|
|
4
7
|
text
|
|
5
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-EBNMV2VO.js";
|
|
6
9
|
|
|
7
10
|
// src/schema/schemas/database-row.ts
|
|
8
11
|
var DatabaseRowSchema = defineSchema({
|
|
9
12
|
name: "DatabaseRow",
|
|
10
13
|
namespace: "xnet://xnet.fyi/",
|
|
14
|
+
version: "2.0.0",
|
|
11
15
|
properties: {
|
|
12
16
|
/**
|
|
13
17
|
* Reference to the parent database.
|
|
14
18
|
* This is a typed relation that only accepts Database node IDs.
|
|
15
19
|
*/
|
|
16
20
|
database: relation({
|
|
17
|
-
target: "xnet://xnet.fyi/Database@
|
|
21
|
+
target: "xnet://xnet.fyi/Database@2.0.0",
|
|
18
22
|
required: true
|
|
19
23
|
}),
|
|
20
24
|
/**
|
|
@@ -31,7 +35,9 @@ var DatabaseRowSchema = defineSchema({
|
|
|
31
35
|
* Only created when the row has rich text columns.
|
|
32
36
|
* Each rich text column gets its own Y.XmlFragment in the doc.
|
|
33
37
|
*/
|
|
34
|
-
document: "yjs"
|
|
38
|
+
document: "yjs",
|
|
39
|
+
// Inherits access from its home Space (exploration 0181/0192).
|
|
40
|
+
authorization: spaceCascadeAuthorization("database")
|
|
35
41
|
});
|
|
36
42
|
|
|
37
43
|
export {
|