@plasius/asset-sources 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/dist/index.js ADDED
@@ -0,0 +1,376 @@
1
+ // src/contracts.ts
2
+ var FEATURE_FLAGS = Object.freeze({
3
+ parent: "asset.pipeline.unified-ai-assets.enabled",
4
+ externalHarvest: "asset.pipeline.external-model-harvest.enabled",
5
+ polyHaven: "asset.pipeline.provider.polyhaven.enabled",
6
+ kenney: "asset.pipeline.provider.kenney.enabled",
7
+ smithsonian: "asset.pipeline.provider.smithsonian.enabled",
8
+ nasa: "asset.pipeline.provider.nasa.enabled",
9
+ sketchfab: "asset.pipeline.provider.sketchfab.enabled"
10
+ });
11
+ var CAPABILITIES = Object.freeze({
12
+ sourceManage: "asset.source.manage",
13
+ catalogReview: "asset.catalog.review",
14
+ catalogRequest: "asset.catalog.request"
15
+ });
16
+
17
+ // src/validation.ts
18
+ var OPAQUE_ID = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/u;
19
+ var SAFE_CURSOR = /^[A-Za-z0-9._:-]{1,256}$/u;
20
+ var SHA256 = /^[a-f0-9]{64}$/u;
21
+ var SOURCE_PAGE = /^https:\/\/[A-Za-z0-9.-]+(?:\/[^\s<>]*)?$/u;
22
+ var URL_LIKE = /(?:https?:\/\/|ftp:\/\/|file:\/\/|data:|javascript:|\\\\|\/\/)/iu;
23
+ var MARKUP = /<\/?[A-Za-z][^>]*>/gu;
24
+ var SourceValidationError = class extends Error {
25
+ code;
26
+ constructor(code) {
27
+ super(code);
28
+ this.name = "SourceValidationError";
29
+ this.code = code;
30
+ }
31
+ };
32
+ var SourceUnavailableError = class extends Error {
33
+ constructor() {
34
+ super("source-unavailable");
35
+ this.name = "SourceUnavailableError";
36
+ }
37
+ };
38
+ var ProviderDisabledError = class extends Error {
39
+ constructor() {
40
+ super("provider-disabled");
41
+ this.name = "ProviderDisabledError";
42
+ }
43
+ };
44
+ function deepFreeze(value, seen = /* @__PURE__ */ new WeakSet()) {
45
+ if (value === null || typeof value !== "object") return value;
46
+ if (seen.has(value)) return value;
47
+ seen.add(value);
48
+ for (const child of Object.values(value)) deepFreeze(child, seen);
49
+ return Object.freeze(value);
50
+ }
51
+ function validateProviderId(value) {
52
+ return validateOpaque(value, "invalid-provider-id");
53
+ }
54
+ function validateAssetIdentifier(value) {
55
+ if (typeof value === "string" && URL_LIKE.test(value)) {
56
+ throw new SourceValidationError("unsafe-asset-id");
57
+ }
58
+ const identifier = validateOpaque(value, "invalid-asset-id");
59
+ return identifier;
60
+ }
61
+ function validateRevision(value) {
62
+ if (!Number.isSafeInteger(value) || value < 0) {
63
+ throw new SourceValidationError("invalid-revision");
64
+ }
65
+ return value;
66
+ }
67
+ function validateIdempotencyKey(value) {
68
+ return validateOpaque(value, "invalid-idempotency-key");
69
+ }
70
+ function validateQuery(value) {
71
+ if (typeof value !== "string") throw new SourceValidationError("invalid-query");
72
+ const query = value.normalize("NFKC").trim();
73
+ if (query.length === 0 || query.length > 256 || containsControl(query)) {
74
+ throw new SourceValidationError("invalid-query");
75
+ }
76
+ return sanitizeUntrustedText(query, 256);
77
+ }
78
+ function validateCursor(value) {
79
+ if (value === void 0) return void 0;
80
+ if (typeof value !== "string" || !SAFE_CURSOR.test(value)) {
81
+ throw new SourceValidationError("invalid-cursor");
82
+ }
83
+ return value;
84
+ }
85
+ function validateLimit(value) {
86
+ if (value === void 0) return 20;
87
+ if (!Number.isSafeInteger(value) || value < 1 || value > 100) {
88
+ throw new SourceValidationError("invalid-limit");
89
+ }
90
+ return value;
91
+ }
92
+ function sanitizeUntrustedText(value, maxLength) {
93
+ if (typeof value !== "string" || value.length > maxLength || containsControl(value)) {
94
+ throw new SourceValidationError("invalid-provider-text");
95
+ }
96
+ return value.normalize("NFKC").replace(MARKUP, "[redacted-markup]").replace(URL_LIKE, "[redacted-url]").slice(0, maxLength);
97
+ }
98
+ function validateSourcePage(value) {
99
+ if (typeof value !== "string" || value.length > 512 || !SOURCE_PAGE.test(value)) {
100
+ throw new SourceValidationError("invalid-source-page");
101
+ }
102
+ return value;
103
+ }
104
+ function validateChecksum(value) {
105
+ if (typeof value !== "string" || !SHA256.test(value)) {
106
+ throw new SourceValidationError("invalid-checksum");
107
+ }
108
+ return value;
109
+ }
110
+ function validateDescriptor(descriptor2) {
111
+ validateProviderId(descriptor2.providerId);
112
+ sanitizeUntrustedText(descriptor2.displayName, 80);
113
+ if (descriptor2.parentFeatureFlag !== FEATURE_FLAGS.parent) {
114
+ throw new SourceValidationError("invalid-parent-feature-flag");
115
+ }
116
+ if (!descriptor2.featureFlag.startsWith("asset.pipeline.provider.")) {
117
+ throw new SourceValidationError("invalid-provider-feature-flag");
118
+ }
119
+ if (!descriptor2.requiredCapabilities.includes(CAPABILITIES.sourceManage)) {
120
+ throw new SourceValidationError("missing-source-capability");
121
+ }
122
+ if (descriptor2.sourceReview !== "approved" || descriptor2.enabled !== false) {
123
+ throw new SourceValidationError("descriptor-must-be-disabled-until-approved");
124
+ }
125
+ if (descriptor2.rightsPolicy === "not-approved") {
126
+ throw new SourceValidationError("descriptor-rights-not-approved");
127
+ }
128
+ if (descriptor2.supportedFormats.length === 0) {
129
+ throw new SourceValidationError("missing-format-matrix");
130
+ }
131
+ return deepFreeze({
132
+ ...descriptor2,
133
+ requiredCapabilities: [...descriptor2.requiredCapabilities],
134
+ operationalGates: [...descriptor2.operationalGates],
135
+ supportedFormats: [...descriptor2.supportedFormats]
136
+ });
137
+ }
138
+ function assertRightsApproved(rights) {
139
+ validateRevision(rights.evidenceRevision);
140
+ if (rights.state !== "approved" || rights.policy !== "commercial-redistribution" && rights.policy !== "commercial-with-attribution") {
141
+ throw new SourceValidationError("rights-evidence-not-approved");
142
+ }
143
+ }
144
+ function normalizeCandidate(candidate, expectedProviderId) {
145
+ if (candidate.providerId !== expectedProviderId) {
146
+ throw new SourceValidationError("provider-mismatch");
147
+ }
148
+ const rightsApproved = candidate.rights.state === "approved" && (candidate.rights.policy === "commercial-redistribution" || candidate.rights.policy === "commercial-with-attribution");
149
+ return deepFreeze({
150
+ ...candidate,
151
+ title: sanitizeUntrustedText(candidate.title, 256),
152
+ description: sanitizeUntrustedText(candidate.description, 4096),
153
+ sourcePage: validateSourcePage(candidate.sourcePage),
154
+ revision: validateRevision(candidate.revision),
155
+ rights: {
156
+ ...candidate.rights,
157
+ evidenceRevision: validateRevision(candidate.rights.evidenceRevision)
158
+ },
159
+ supportedFormats: [...candidate.supportedFormats],
160
+ disposition: rightsApproved ? candidate.disposition : "quarantined"
161
+ });
162
+ }
163
+ function normalizeMetadata(metadata, expectedProviderId) {
164
+ const candidate = normalizeCandidate(metadata, expectedProviderId);
165
+ return deepFreeze({
166
+ ...candidate,
167
+ ...metadata.creator === void 0 ? {} : { creator: sanitizeUntrustedText(metadata.creator, 256) },
168
+ ...metadata.attributionText === void 0 ? {} : { attributionText: sanitizeUntrustedText(metadata.attributionText, 512) }
169
+ });
170
+ }
171
+ function validateOpaque(value, code) {
172
+ if (typeof value !== "string" || !OPAQUE_ID.test(value) || containsControl(value)) {
173
+ throw new SourceValidationError(code);
174
+ }
175
+ return value;
176
+ }
177
+ function containsControl(value) {
178
+ return [...value].some((character) => {
179
+ const codePoint = character.codePointAt(0) ?? 0;
180
+ return codePoint <= 31 || codePoint === 127;
181
+ });
182
+ }
183
+
184
+ // src/registry.ts
185
+ var DEFAULT_PROVIDER_DESCRIPTORS = deepFreeze([
186
+ descriptor("polyhaven", "Poly Haven", FEATURE_FLAGS.polyHaven, ["glb", "gltf", "blend"]),
187
+ descriptor("kenney", "Kenney", FEATURE_FLAGS.kenney, ["glb", "gltf", "fbx"]),
188
+ descriptor("smithsonian", "Smithsonian Open Access", FEATURE_FLAGS.smithsonian, ["glb", "gltf", "obj"]),
189
+ descriptor("nasa", "NASA", FEATURE_FLAGS.nasa, ["glb", "gltf", "obj", "fbx"]),
190
+ descriptor("sketchfab", "Sketchfab", FEATURE_FLAGS.sketchfab, ["glb", "gltf", "fbx"])
191
+ ]);
192
+ function createProviderRegistry(descriptors = DEFAULT_PROVIDER_DESCRIPTORS) {
193
+ const validated = descriptors.map(validateDescriptor);
194
+ const byId = /* @__PURE__ */ new Map();
195
+ for (const item of validated) {
196
+ if (byId.has(item.providerId)) throw new SourceValidationError("duplicate-provider-id");
197
+ byId.set(item.providerId, item);
198
+ }
199
+ const list = Object.freeze([...byId.values()]);
200
+ return Object.freeze({
201
+ get(providerId) {
202
+ validateProviderId(providerId);
203
+ const descriptor2 = byId.get(providerId);
204
+ if (!descriptor2) throw new SourceValidationError("unknown-provider-id");
205
+ return descriptor2;
206
+ },
207
+ list() {
208
+ return list;
209
+ }
210
+ });
211
+ }
212
+ function descriptor(providerId, displayName, featureFlag, supportedFormats) {
213
+ return {
214
+ providerId,
215
+ displayName,
216
+ enabled: false,
217
+ featureFlag,
218
+ parentFeatureFlag: FEATURE_FLAGS.parent,
219
+ requiredCapabilities: [CAPABILITIES.sourceManage, CAPABILITIES.catalogReview, CAPABILITIES.catalogRequest],
220
+ operationalGates: ["parent-flag", "provider-flag", "source-review", "rights-evidence", "private-staging"],
221
+ sourceReview: "approved",
222
+ rightsPolicy: "commercial-with-attribution",
223
+ supportedFormats
224
+ };
225
+ }
226
+
227
+ // src/connector.ts
228
+ function createProviderConnector(descriptor2, dependencies) {
229
+ const assertEnabled = () => {
230
+ if (!descriptor2.enabled) throw new ProviderDisabledError();
231
+ };
232
+ return Object.freeze({
233
+ descriptor: descriptor2,
234
+ async search(request) {
235
+ assertEnabled();
236
+ const providerId = validateProviderId(request.providerId);
237
+ if (providerId !== descriptor2.providerId) throw new SourceValidationError("provider-mismatch");
238
+ const query = validateQuery(request.query);
239
+ const limit = validateLimit(request.limit);
240
+ const cursor = validateCursor(request.cursor);
241
+ const credential = await dependencies.credentials.getCredential({ providerId, operation: "search" });
242
+ const payload = await dependencies.transport.execute(
243
+ { providerId, operation: "search", query, limit, cursor },
244
+ credential
245
+ );
246
+ return deepFreeze(dependencies.normalizer.normalizeSearch(payload).map((candidate) => normalizeCandidate(candidate, descriptor2.providerId)));
247
+ },
248
+ async resolveMetadata(request) {
249
+ assertEnabled();
250
+ const providerId = validateProviderId(request.providerId);
251
+ const assetId = validateAssetIdentifier(request.assetId);
252
+ if (providerId !== descriptor2.providerId) throw new SourceValidationError("provider-mismatch");
253
+ const credential = await dependencies.credentials.getCredential({ providerId, operation: "resolveMetadata" });
254
+ const payload = await dependencies.transport.execute({ providerId, operation: "resolveMetadata", assetId }, credential);
255
+ return normalizeMetadata(dependencies.normalizer.normalizeMetadata(payload), descriptor2.providerId);
256
+ },
257
+ async requestDownload(request) {
258
+ assertEnabled();
259
+ const providerId = validateProviderId(request.providerId);
260
+ const assetId = validateAssetIdentifier(request.assetId);
261
+ const idempotencyKey = validateIdempotencyKey(request.idempotencyKey);
262
+ const expectedRevision = request.expectedRevision === void 0 ? void 0 : validateRevision(request.expectedRevision);
263
+ if (providerId !== descriptor2.providerId) throw new SourceValidationError("provider-mismatch");
264
+ const existing = await dependencies.checkpoints.get(idempotencyKey);
265
+ if (existing) return deepFreeze({ ...existing.receipt });
266
+ const receipt = await dependencies.acquisition.requestDownload({ providerId, assetId, idempotencyKey, expectedRevision });
267
+ if (receipt.status === "accepted") await dependencies.checkpoints.put(deepFreeze({ idempotencyKey, receipt: { ...receipt } }));
268
+ return deepFreeze({ ...receipt });
269
+ },
270
+ async download(request) {
271
+ assertEnabled();
272
+ const providerId = validateProviderId(request.providerId);
273
+ const assetId = validateAssetIdentifier(request.assetId);
274
+ const acquisitionId = validateIdempotencyKey(request.acquisitionId);
275
+ if (providerId !== descriptor2.providerId) throw new SourceValidationError("provider-mismatch");
276
+ const content = await dependencies.acquisition.download({ providerId, assetId, acquisitionId });
277
+ if (content.acquisitionId !== acquisitionId) throw new SourceValidationError("acquisition-mismatch");
278
+ return deepFreeze({ ...await dependencies.staging.stage(content) });
279
+ }
280
+ });
281
+ }
282
+
283
+ // src/fake.ts
284
+ function createMemoryCheckpoints() {
285
+ const values = /* @__PURE__ */ new Map();
286
+ return {
287
+ async get(key) {
288
+ return values.get(key) ?? null;
289
+ },
290
+ async put(value) {
291
+ values.set(value.idempotencyKey, value);
292
+ }
293
+ };
294
+ }
295
+ function createFakeDependencies(providerId, fixture) {
296
+ const normalizedProviderId = validateProviderId(providerId);
297
+ const candidate = deepFreeze({ ...fixture.candidate });
298
+ const credentials = {
299
+ async getCredential() {
300
+ return { kind: "none", value: "" };
301
+ }
302
+ };
303
+ const transport = {
304
+ async execute(request) {
305
+ if (request.providerId !== normalizedProviderId) throw new SourceUnavailableError();
306
+ return request.operation === "search" ? [candidate] : candidate;
307
+ }
308
+ };
309
+ const normalizer = {
310
+ normalizeSearch(payload) {
311
+ if (!Array.isArray(payload)) throw new SourceUnavailableError();
312
+ return payload;
313
+ },
314
+ normalizeMetadata(payload) {
315
+ if (!payload || typeof payload !== "object") throw new SourceUnavailableError();
316
+ return { ...candidate, ...fixture.metadata ?? {}, ...payload };
317
+ }
318
+ };
319
+ const acquisition = {
320
+ async requestDownload(request) {
321
+ return { acquisitionId: request.idempotencyKey, providerId: request.providerId, assetId: request.assetId, revision: candidate.revision, status: "accepted" };
322
+ },
323
+ async download(request) {
324
+ if (request.providerId !== normalizedProviderId || request.assetId !== candidate.assetId) throw new SourceUnavailableError();
325
+ return { acquisitionId: request.acquisitionId, mediaType: "model/gltf-binary", byteLength: 128, checksumSha256: "a".repeat(64) };
326
+ }
327
+ };
328
+ const staging = {
329
+ async stage(content) {
330
+ return { stagingId: `stage:${content.acquisitionId}`, mediaType: content.mediaType, byteLength: content.byteLength, checksumSha256: content.checksumSha256, expiresAt: "2030-01-01T00:00:00.000Z" };
331
+ }
332
+ };
333
+ return { credentials, transport, normalizer, acquisition, staging, checkpoints: createMemoryCheckpoints() };
334
+ }
335
+ function fixtureCandidate(providerId, assetId) {
336
+ return deepFreeze({
337
+ providerId: validateProviderId(providerId),
338
+ assetId: validateAssetIdentifier(assetId),
339
+ title: "Fixture asset",
340
+ description: "Bounded fixture metadata",
341
+ sourcePage: "https://example.test/assets/fixture",
342
+ rights: { state: "approved", policy: "commercial-with-attribution", evidenceRevision: validateRevision(1), attributionRequired: true },
343
+ supportedFormats: ["glb"],
344
+ revision: validateRevision(1),
345
+ disposition: "eligible"
346
+ });
347
+ }
348
+ export {
349
+ CAPABILITIES,
350
+ DEFAULT_PROVIDER_DESCRIPTORS,
351
+ FEATURE_FLAGS,
352
+ ProviderDisabledError,
353
+ SourceUnavailableError,
354
+ SourceValidationError,
355
+ assertRightsApproved,
356
+ createFakeDependencies,
357
+ createMemoryCheckpoints,
358
+ createProviderConnector,
359
+ createProviderRegistry,
360
+ deepFreeze,
361
+ fixtureCandidate,
362
+ normalizeCandidate,
363
+ normalizeMetadata,
364
+ sanitizeUntrustedText,
365
+ validateAssetIdentifier,
366
+ validateChecksum,
367
+ validateCursor,
368
+ validateDescriptor,
369
+ validateIdempotencyKey,
370
+ validateLimit,
371
+ validateProviderId,
372
+ validateQuery,
373
+ validateRevision,
374
+ validateSourcePage
375
+ };
376
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/contracts.ts","../src/validation.ts","../src/registry.ts","../src/connector.ts","../src/fake.ts"],"sourcesContent":["export const FEATURE_FLAGS = Object.freeze({\n parent: \"asset.pipeline.unified-ai-assets.enabled\",\n externalHarvest: \"asset.pipeline.external-model-harvest.enabled\",\n polyHaven: \"asset.pipeline.provider.polyhaven.enabled\",\n kenney: \"asset.pipeline.provider.kenney.enabled\",\n smithsonian: \"asset.pipeline.provider.smithsonian.enabled\",\n nasa: \"asset.pipeline.provider.nasa.enabled\",\n sketchfab: \"asset.pipeline.provider.sketchfab.enabled\",\n} as const);\n\nexport const CAPABILITIES = Object.freeze({\n sourceManage: \"asset.source.manage\",\n catalogReview: \"asset.catalog.review\",\n catalogRequest: \"asset.catalog.request\",\n} as const);\n\nexport type ProviderId = string & { readonly __providerId: unique symbol };\nexport type AssetIdentifier = string & {\n readonly __assetIdentifier: unique symbol;\n};\nexport type Revision = number & { readonly __revision: unique symbol };\n\nexport type ProviderOperation =\n | \"search\"\n | \"resolveMetadata\"\n | \"requestDownload\"\n | \"download\";\n\nexport type SupportedFormat =\n | \"glb\"\n | \"gltf\"\n | \"fbx\"\n | \"obj\"\n | \"blend\"\n | \"zip\"\n | \"unknown\";\n\nexport type SourceReviewState = \"pending\" | \"approved\" | \"rejected\";\nexport type RightsEvidenceState = \"approved\" | \"unknown\" | \"changed\";\nexport type RightsPolicyState =\n | \"commercial-redistribution\"\n | \"commercial-with-attribution\"\n | \"not-approved\";\n\nexport interface ProviderSourceDescriptor {\n readonly providerId: ProviderId;\n readonly displayName: string;\n readonly enabled: boolean;\n readonly featureFlag: string;\n readonly parentFeatureFlag: typeof FEATURE_FLAGS.parent;\n readonly requiredCapabilities: readonly string[];\n readonly operationalGates: readonly string[];\n readonly sourceReview: SourceReviewState;\n readonly rightsPolicy: RightsPolicyState;\n readonly supportedFormats: readonly SupportedFormat[];\n}\n\nexport interface SearchRequest {\n readonly providerId: ProviderId;\n readonly query: string;\n readonly limit?: number;\n readonly cursor?: string;\n}\n\nexport interface ResolveMetadataRequest {\n readonly providerId: ProviderId;\n readonly assetId: AssetIdentifier;\n}\n\nexport interface RequestDownloadRequest {\n readonly providerId: ProviderId;\n readonly assetId: AssetIdentifier;\n readonly idempotencyKey: string;\n readonly expectedRevision?: Revision;\n}\n\nexport interface DownloadRequest {\n readonly providerId: ProviderId;\n readonly assetId: AssetIdentifier;\n readonly acquisitionId: string;\n}\n\nexport interface RightsEvidence {\n readonly state: RightsEvidenceState;\n readonly policy: RightsPolicyState;\n readonly evidenceRevision: Revision;\n readonly attributionRequired: boolean;\n}\n\nexport interface ProviderAssetCandidate {\n readonly providerId: ProviderId;\n readonly assetId: AssetIdentifier;\n readonly title: string;\n readonly description: string;\n readonly sourcePage: string;\n readonly rights: RightsEvidence;\n readonly supportedFormats: readonly SupportedFormat[];\n readonly revision: Revision;\n readonly disposition: \"eligible\" | \"quarantined\";\n}\n\nexport interface ProviderAssetMetadata extends ProviderAssetCandidate {\n readonly creator?: string;\n readonly attributionText?: string;\n}\n\nexport interface CredentialRequest {\n readonly providerId: ProviderId;\n readonly operation: ProviderOperation;\n}\n\nexport interface ProviderCredential {\n readonly kind: \"oauth\" | \"api-key\" | \"none\";\n readonly value: string;\n}\n\nexport interface CredentialProvider {\n getCredential(request: CredentialRequest): Promise<ProviderCredential | null>;\n}\n\nexport interface ProviderTransportRequest {\n readonly providerId: ProviderId;\n readonly operation: \"search\" | \"resolveMetadata\";\n readonly assetId?: AssetIdentifier;\n readonly query?: string;\n readonly limit?: number;\n readonly cursor?: string;\n}\n\nexport interface ProviderTransport {\n execute(\n request: ProviderTransportRequest,\n credential: ProviderCredential | null,\n ): Promise<unknown>;\n}\n\nexport interface ProviderPayloadNormalizer {\n normalizeSearch(payload: unknown): readonly ProviderAssetCandidate[];\n normalizeMetadata(payload: unknown): ProviderAssetMetadata;\n}\n\nexport interface AcquisitionRequest {\n readonly providerId: ProviderId;\n readonly assetId: AssetIdentifier;\n readonly idempotencyKey: string;\n readonly expectedRevision?: Revision;\n}\n\nexport interface AcquisitionReceipt {\n readonly acquisitionId: string;\n readonly providerId: ProviderId;\n readonly assetId: AssetIdentifier;\n readonly revision: Revision;\n readonly status: \"accepted\" | \"unavailable\" | \"quarantined\";\n}\n\nexport interface AcquiredContent {\n readonly acquisitionId: string;\n readonly mediaType: string;\n readonly byteLength: number;\n readonly checksumSha256: string;\n}\n\nexport interface AcquisitionPort {\n requestDownload(request: AcquisitionRequest): Promise<AcquisitionReceipt>;\n download(request: DownloadRequest): Promise<AcquiredContent>;\n}\n\nexport interface PrivateStagingRef {\n readonly stagingId: string;\n readonly mediaType: string;\n readonly byteLength: number;\n readonly checksumSha256: string;\n readonly expiresAt: string;\n}\n\nexport interface PrivateStagingPort {\n stage(content: AcquiredContent): Promise<PrivateStagingRef>;\n}\n\nexport interface Checkpoint {\n readonly idempotencyKey: string;\n readonly receipt: AcquisitionReceipt;\n}\n\nexport interface CheckpointPort {\n get(idempotencyKey: string): Promise<Checkpoint | null>;\n put(checkpoint: Checkpoint): Promise<void>;\n}\n\nexport interface ProviderConnector {\n readonly descriptor: ProviderSourceDescriptor;\n search(request: SearchRequest): Promise<readonly ProviderAssetCandidate[]>;\n resolveMetadata(request: ResolveMetadataRequest): Promise<ProviderAssetMetadata>;\n requestDownload(request: RequestDownloadRequest): Promise<AcquisitionReceipt>;\n download(request: DownloadRequest): Promise<PrivateStagingRef>;\n}\n\nexport interface ProviderRegistry {\n get(providerId: ProviderId): ProviderSourceDescriptor;\n list(): readonly ProviderSourceDescriptor[];\n}\n","import {\n type AssetIdentifier,\n type ProviderId,\n type Revision,\n type RightsEvidence,\n type ProviderSourceDescriptor,\n type ProviderAssetCandidate,\n type ProviderAssetMetadata,\n FEATURE_FLAGS,\n CAPABILITIES,\n} from \"./contracts.js\";\n\nconst OPAQUE_ID = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/u;\nconst SAFE_CURSOR = /^[A-Za-z0-9._:-]{1,256}$/u;\nconst SHA256 = /^[a-f0-9]{64}$/u;\nconst SOURCE_PAGE = /^https:\\/\\/[A-Za-z0-9.-]+(?:\\/[^\\s<>]*)?$/u;\nconst URL_LIKE = /(?:https?:\\/\\/|ftp:\\/\\/|file:\\/\\/|data:|javascript:|\\\\\\\\|\\/\\/)/iu;\nconst MARKUP = /<\\/?[A-Za-z][^>]*>/gu;\n\nexport class SourceValidationError extends Error {\n readonly code: string;\n\n constructor(code: string) {\n super(code);\n this.name = \"SourceValidationError\";\n this.code = code;\n }\n}\n\nexport class SourceUnavailableError extends Error {\n constructor() {\n super(\"source-unavailable\");\n this.name = \"SourceUnavailableError\";\n }\n}\n\nexport class ProviderDisabledError extends Error {\n constructor() {\n super(\"provider-disabled\");\n this.name = \"ProviderDisabledError\";\n }\n}\n\nexport function deepFreeze<T>(value: T, seen = new WeakSet<object>()): T {\n if (value === null || typeof value !== \"object\") return value;\n if (seen.has(value)) return value;\n seen.add(value);\n for (const child of Object.values(value)) deepFreeze(child, seen);\n return Object.freeze(value);\n}\n\nexport function validateProviderId(value: unknown): ProviderId {\n return validateOpaque(value, \"invalid-provider-id\") as ProviderId;\n}\n\nexport function validateAssetIdentifier(value: unknown): AssetIdentifier {\n if (typeof value === \"string\" && URL_LIKE.test(value)) {\n throw new SourceValidationError(\"unsafe-asset-id\");\n }\n const identifier = validateOpaque(value, \"invalid-asset-id\");\n return identifier as AssetIdentifier;\n}\n\nexport function validateRevision(value: unknown): Revision {\n if (!Number.isSafeInteger(value) || (value as number) < 0) {\n throw new SourceValidationError(\"invalid-revision\");\n }\n return value as Revision;\n}\n\nexport function validateIdempotencyKey(value: unknown): string {\n return validateOpaque(value, \"invalid-idempotency-key\");\n}\n\nexport function validateQuery(value: unknown): string {\n if (typeof value !== \"string\") throw new SourceValidationError(\"invalid-query\");\n const query = value.normalize(\"NFKC\").trim();\n if (query.length === 0 || query.length > 256 || containsControl(query)) {\n throw new SourceValidationError(\"invalid-query\");\n }\n return sanitizeUntrustedText(query, 256);\n}\n\nexport function validateCursor(value: unknown): string | undefined {\n if (value === undefined) return undefined;\n if (typeof value !== \"string\" || !SAFE_CURSOR.test(value)) {\n throw new SourceValidationError(\"invalid-cursor\");\n }\n return value;\n}\n\nexport function validateLimit(value: unknown): number {\n if (value === undefined) return 20;\n if (!Number.isSafeInteger(value) || (value as number) < 1 || (value as number) > 100) {\n throw new SourceValidationError(\"invalid-limit\");\n }\n return value as number;\n}\n\nexport function sanitizeUntrustedText(value: unknown, maxLength: number): string {\n if (typeof value !== \"string\" || value.length > maxLength || containsControl(value)) {\n throw new SourceValidationError(\"invalid-provider-text\");\n }\n return value\n .normalize(\"NFKC\")\n .replace(MARKUP, \"[redacted-markup]\")\n .replace(URL_LIKE, \"[redacted-url]\")\n .slice(0, maxLength);\n}\n\nexport function validateSourcePage(value: unknown): string {\n if (typeof value !== \"string\" || value.length > 512 || !SOURCE_PAGE.test(value)) {\n throw new SourceValidationError(\"invalid-source-page\");\n }\n return value;\n}\n\nexport function validateChecksum(value: unknown): string {\n if (typeof value !== \"string\" || !SHA256.test(value)) {\n throw new SourceValidationError(\"invalid-checksum\");\n }\n return value;\n}\n\nexport function validateDescriptor(\n descriptor: ProviderSourceDescriptor,\n): ProviderSourceDescriptor {\n validateProviderId(descriptor.providerId);\n sanitizeUntrustedText(descriptor.displayName, 80);\n if (descriptor.parentFeatureFlag !== FEATURE_FLAGS.parent) {\n throw new SourceValidationError(\"invalid-parent-feature-flag\");\n }\n if (!descriptor.featureFlag.startsWith(\"asset.pipeline.provider.\")) {\n throw new SourceValidationError(\"invalid-provider-feature-flag\");\n }\n if (!descriptor.requiredCapabilities.includes(CAPABILITIES.sourceManage)) {\n throw new SourceValidationError(\"missing-source-capability\");\n }\n if (descriptor.sourceReview !== \"approved\" || descriptor.enabled !== false) {\n throw new SourceValidationError(\"descriptor-must-be-disabled-until-approved\");\n }\n if (descriptor.rightsPolicy === \"not-approved\") {\n throw new SourceValidationError(\"descriptor-rights-not-approved\");\n }\n if (descriptor.supportedFormats.length === 0) {\n throw new SourceValidationError(\"missing-format-matrix\");\n }\n return deepFreeze({\n ...descriptor,\n requiredCapabilities: [...descriptor.requiredCapabilities],\n operationalGates: [...descriptor.operationalGates],\n supportedFormats: [...descriptor.supportedFormats],\n });\n}\n\nexport function assertRightsApproved(rights: RightsEvidence): void {\n validateRevision(rights.evidenceRevision);\n if (\n rights.state !== \"approved\" ||\n (rights.policy !== \"commercial-redistribution\" &&\n rights.policy !== \"commercial-with-attribution\")\n ) {\n throw new SourceValidationError(\"rights-evidence-not-approved\");\n }\n}\n\nexport function normalizeCandidate(\n candidate: ProviderAssetCandidate,\n expectedProviderId: ProviderId,\n): ProviderAssetCandidate {\n if (candidate.providerId !== expectedProviderId) {\n throw new SourceValidationError(\"provider-mismatch\");\n }\n const rightsApproved =\n candidate.rights.state === \"approved\" &&\n (candidate.rights.policy === \"commercial-redistribution\" ||\n candidate.rights.policy === \"commercial-with-attribution\");\n return deepFreeze({\n ...candidate,\n title: sanitizeUntrustedText(candidate.title, 256),\n description: sanitizeUntrustedText(candidate.description, 4096),\n sourcePage: validateSourcePage(candidate.sourcePage),\n revision: validateRevision(candidate.revision),\n rights: {\n ...candidate.rights,\n evidenceRevision: validateRevision(candidate.rights.evidenceRevision),\n },\n supportedFormats: [...candidate.supportedFormats],\n disposition: rightsApproved ? candidate.disposition : \"quarantined\",\n });\n}\n\nexport function normalizeMetadata(\n metadata: ProviderAssetMetadata,\n expectedProviderId: ProviderId,\n): ProviderAssetMetadata {\n const candidate = normalizeCandidate(metadata, expectedProviderId);\n return deepFreeze({\n ...candidate,\n ...(metadata.creator === undefined\n ? {}\n : { creator: sanitizeUntrustedText(metadata.creator, 256) }),\n ...(metadata.attributionText === undefined\n ? {}\n : { attributionText: sanitizeUntrustedText(metadata.attributionText, 512) }),\n });\n}\n\nfunction validateOpaque(value: unknown, code: string): string {\n if (typeof value !== \"string\" || !OPAQUE_ID.test(value) || containsControl(value)) {\n throw new SourceValidationError(code);\n }\n return value;\n}\n\nfunction containsControl(value: string): boolean {\n return [...value].some((character) => {\n const codePoint = character.codePointAt(0) ?? 0;\n return codePoint <= 0x1f || codePoint === 0x7f;\n });\n}\n","import {\n CAPABILITIES,\n FEATURE_FLAGS,\n type ProviderId,\n type ProviderRegistry,\n type ProviderSourceDescriptor,\n} from \"./contracts.js\";\nimport { deepFreeze, validateDescriptor, validateProviderId, SourceValidationError } from \"./validation.js\";\n\nexport const DEFAULT_PROVIDER_DESCRIPTORS: readonly ProviderSourceDescriptor[] = deepFreeze([\n descriptor(\"polyhaven\", \"Poly Haven\", FEATURE_FLAGS.polyHaven, [\"glb\", \"gltf\", \"blend\"]),\n descriptor(\"kenney\", \"Kenney\", FEATURE_FLAGS.kenney, [\"glb\", \"gltf\", \"fbx\"]),\n descriptor(\"smithsonian\", \"Smithsonian Open Access\", FEATURE_FLAGS.smithsonian, [\"glb\", \"gltf\", \"obj\"]),\n descriptor(\"nasa\", \"NASA\", FEATURE_FLAGS.nasa, [\"glb\", \"gltf\", \"obj\", \"fbx\"]),\n descriptor(\"sketchfab\", \"Sketchfab\", FEATURE_FLAGS.sketchfab, [\"glb\", \"gltf\", \"fbx\"]),\n]);\n\nexport function createProviderRegistry(\n descriptors: readonly ProviderSourceDescriptor[] = DEFAULT_PROVIDER_DESCRIPTORS,\n): ProviderRegistry {\n const validated = descriptors.map(validateDescriptor);\n const byId = new Map<ProviderId, ProviderSourceDescriptor>();\n for (const item of validated) {\n if (byId.has(item.providerId)) throw new SourceValidationError(\"duplicate-provider-id\");\n byId.set(item.providerId, item);\n }\n const list = Object.freeze([...byId.values()]);\n return Object.freeze({\n get(providerId: ProviderId): ProviderSourceDescriptor {\n validateProviderId(providerId);\n const descriptor = byId.get(providerId);\n if (!descriptor) throw new SourceValidationError(\"unknown-provider-id\");\n return descriptor;\n },\n list(): readonly ProviderSourceDescriptor[] {\n return list;\n },\n });\n}\n\nfunction descriptor(\n providerId: string,\n displayName: string,\n featureFlag: string,\n supportedFormats: readonly (\"glb\" | \"gltf\" | \"fbx\" | \"obj\" | \"blend\")[],\n): ProviderSourceDescriptor {\n return {\n providerId: providerId as ProviderId,\n displayName,\n enabled: false,\n featureFlag,\n parentFeatureFlag: FEATURE_FLAGS.parent,\n requiredCapabilities: [CAPABILITIES.sourceManage, CAPABILITIES.catalogReview, CAPABILITIES.catalogRequest],\n operationalGates: [\"parent-flag\", \"provider-flag\", \"source-review\", \"rights-evidence\", \"private-staging\"],\n sourceReview: \"approved\",\n rightsPolicy: \"commercial-with-attribution\",\n supportedFormats,\n };\n}\n","import {\n type AcquisitionPort,\n type CheckpointPort,\n type CredentialProvider,\n type DownloadRequest,\n type ProviderAssetCandidate,\n type ProviderAssetMetadata,\n type ProviderConnector,\n type ProviderPayloadNormalizer,\n type ProviderSourceDescriptor,\n type ProviderTransport,\n type PrivateStagingPort,\n type RequestDownloadRequest,\n type ResolveMetadataRequest,\n type SearchRequest,\n type AcquisitionReceipt,\n type PrivateStagingRef,\n} from \"./contracts.js\";\nimport {\n deepFreeze,\n ProviderDisabledError,\n SourceValidationError,\n validateAssetIdentifier,\n validateCursor,\n validateIdempotencyKey,\n validateLimit,\n normalizeCandidate,\n normalizeMetadata,\n validateProviderId,\n validateQuery,\n validateRevision,\n} from \"./validation.js\";\n\nexport interface ProviderConnectorDependencies {\n readonly credentials: CredentialProvider;\n readonly transport: ProviderTransport;\n readonly normalizer: ProviderPayloadNormalizer;\n readonly acquisition: AcquisitionPort;\n readonly staging: PrivateStagingPort;\n readonly checkpoints: CheckpointPort;\n}\n\nexport function createProviderConnector(\n descriptor: ProviderSourceDescriptor,\n dependencies: ProviderConnectorDependencies,\n): ProviderConnector {\n const assertEnabled = (): void => {\n if (!descriptor.enabled) throw new ProviderDisabledError();\n };\n\n return Object.freeze({\n descriptor,\n async search(request: SearchRequest): Promise<readonly ProviderAssetCandidate[]> {\n assertEnabled();\n const providerId = validateProviderId(request.providerId);\n if (providerId !== descriptor.providerId) throw new SourceValidationError(\"provider-mismatch\");\n const query = validateQuery(request.query);\n const limit = validateLimit(request.limit);\n const cursor = validateCursor(request.cursor);\n const credential = await dependencies.credentials.getCredential({ providerId, operation: \"search\" });\n const payload = await dependencies.transport.execute(\n { providerId, operation: \"search\", query, limit, cursor },\n credential,\n );\n return deepFreeze(dependencies.normalizer.normalizeSearch(payload).map(candidate => normalizeCandidate(candidate, descriptor.providerId)));\n },\n async resolveMetadata(request: ResolveMetadataRequest): Promise<ProviderAssetMetadata> {\n assertEnabled();\n const providerId = validateProviderId(request.providerId);\n const assetId = validateAssetIdentifier(request.assetId);\n if (providerId !== descriptor.providerId) throw new SourceValidationError(\"provider-mismatch\");\n const credential = await dependencies.credentials.getCredential({ providerId, operation: \"resolveMetadata\" });\n const payload = await dependencies.transport.execute({ providerId, operation: \"resolveMetadata\", assetId }, credential);\n return normalizeMetadata(dependencies.normalizer.normalizeMetadata(payload), descriptor.providerId);\n },\n async requestDownload(request: RequestDownloadRequest): Promise<AcquisitionReceipt> {\n assertEnabled();\n const providerId = validateProviderId(request.providerId);\n const assetId = validateAssetIdentifier(request.assetId);\n const idempotencyKey = validateIdempotencyKey(request.idempotencyKey);\n const expectedRevision = request.expectedRevision === undefined ? undefined : validateRevision(request.expectedRevision);\n if (providerId !== descriptor.providerId) throw new SourceValidationError(\"provider-mismatch\");\n const existing = await dependencies.checkpoints.get(idempotencyKey);\n if (existing) return deepFreeze({ ...existing.receipt });\n const receipt = await dependencies.acquisition.requestDownload({ providerId, assetId, idempotencyKey, expectedRevision });\n if (receipt.status === \"accepted\") await dependencies.checkpoints.put(deepFreeze({ idempotencyKey, receipt: { ...receipt } }));\n return deepFreeze({ ...receipt });\n },\n async download(request: DownloadRequest): Promise<PrivateStagingRef> {\n assertEnabled();\n const providerId = validateProviderId(request.providerId);\n const assetId = validateAssetIdentifier(request.assetId);\n const acquisitionId = validateIdempotencyKey(request.acquisitionId);\n if (providerId !== descriptor.providerId) throw new SourceValidationError(\"provider-mismatch\");\n const content = await dependencies.acquisition.download({ providerId, assetId, acquisitionId });\n if (content.acquisitionId !== acquisitionId) throw new SourceValidationError(\"acquisition-mismatch\");\n return deepFreeze({ ...(await dependencies.staging.stage(content)) });\n },\n });\n}\n","import {\n type AcquisitionPort,\n type AcquisitionReceipt,\n type AssetIdentifier,\n type Checkpoint,\n type CheckpointPort,\n type CredentialProvider,\n type ProviderAssetCandidate,\n type ProviderAssetMetadata,\n type ProviderCredential,\n type ProviderId,\n type ProviderPayloadNormalizer,\n type ProviderTransport,\n type PrivateStagingPort,\n type PrivateStagingRef,\n} from \"./contracts.js\";\nimport { deepFreeze, SourceUnavailableError, validateAssetIdentifier, validateProviderId, validateRevision } from \"./validation.js\";\n\nexport interface FakeConnectorFixture {\n readonly candidate: ProviderAssetCandidate;\n readonly metadata?: Partial<ProviderAssetMetadata>;\n}\n\nexport function createMemoryCheckpoints(): CheckpointPort {\n const values = new Map<string, Checkpoint>();\n return {\n async get(key) { return values.get(key) ?? null; },\n async put(value) { values.set(value.idempotencyKey, value); },\n };\n}\n\nexport function createFakeDependencies(\n providerId: ProviderId,\n fixture: FakeConnectorFixture,\n): {\n credentials: CredentialProvider;\n transport: ProviderTransport;\n normalizer: ProviderPayloadNormalizer;\n acquisition: AcquisitionPort;\n staging: PrivateStagingPort;\n checkpoints: CheckpointPort;\n} {\n const normalizedProviderId = validateProviderId(providerId);\n const candidate = deepFreeze({ ...fixture.candidate });\n const credentials: CredentialProvider = {\n async getCredential(): Promise<ProviderCredential | null> { return { kind: \"none\", value: \"\" }; },\n };\n const transport: ProviderTransport = {\n async execute(request) {\n if (request.providerId !== normalizedProviderId) throw new SourceUnavailableError();\n return request.operation === \"search\" ? [candidate] : candidate;\n },\n };\n const normalizer: ProviderPayloadNormalizer = {\n normalizeSearch(payload): readonly ProviderAssetCandidate[] {\n if (!Array.isArray(payload)) throw new SourceUnavailableError();\n return payload as ProviderAssetCandidate[];\n },\n normalizeMetadata(payload): ProviderAssetMetadata {\n if (!payload || typeof payload !== \"object\") throw new SourceUnavailableError();\n return { ...candidate, ...(fixture.metadata ?? {}), ...(payload as Partial<ProviderAssetMetadata>) };\n },\n };\n const acquisition: AcquisitionPort = {\n async requestDownload(request): Promise<AcquisitionReceipt> {\n return { acquisitionId: request.idempotencyKey, providerId: request.providerId, assetId: request.assetId, revision: candidate.revision, status: \"accepted\" };\n },\n async download(request) {\n if (request.providerId !== normalizedProviderId || request.assetId !== candidate.assetId) throw new SourceUnavailableError();\n return { acquisitionId: request.acquisitionId, mediaType: \"model/gltf-binary\", byteLength: 128, checksumSha256: \"a\".repeat(64) };\n },\n };\n const staging: PrivateStagingPort = {\n async stage(content): Promise<PrivateStagingRef> {\n return { stagingId: `stage:${content.acquisitionId}`, mediaType: content.mediaType, byteLength: content.byteLength, checksumSha256: content.checksumSha256, expiresAt: \"2030-01-01T00:00:00.000Z\" };\n },\n };\n return { credentials, transport, normalizer, acquisition, staging, checkpoints: createMemoryCheckpoints() };\n}\n\nexport function fixtureCandidate(providerId: string, assetId: string): ProviderAssetCandidate {\n return deepFreeze({\n providerId: validateProviderId(providerId),\n assetId: validateAssetIdentifier(assetId),\n title: \"Fixture asset\",\n description: \"Bounded fixture metadata\",\n sourcePage: \"https://example.test/assets/fixture\",\n rights: { state: \"approved\", policy: \"commercial-with-attribution\", evidenceRevision: validateRevision(1), attributionRequired: true },\n supportedFormats: [\"glb\"],\n revision: validateRevision(1),\n disposition: \"eligible\",\n });\n}\n"],"mappings":"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","names":["descriptor","descriptor","descriptor"]}
package/package.json ADDED
@@ -0,0 +1,99 @@
1
+ {
2
+ "name": "@plasius/asset-sources",
3
+ "version": "0.1.0",
4
+ "description": "Fail-closed provider source connector contracts and disabled registry for the Plasius asset pipeline",
5
+ "type": "module",
6
+ "sideEffects": false,
7
+ "main": "./dist/index.cjs",
8
+ "module": "./dist/index.js",
9
+ "types": "./dist/index.d.ts",
10
+ "files": ["dist", "THIRD_PARTY_NOTICES.md"],
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/index.d.ts",
14
+ "import": "./dist/index.js",
15
+ "require": "./dist/index.cjs"
16
+ },
17
+ "./package.json": "./package.json"
18
+ },
19
+ "scripts": {
20
+ "build": "tsup",
21
+ "test": "vitest run",
22
+ "test:watch": "vitest",
23
+ "typecheck": "tsc --noEmit",
24
+ "audit:eslint": "eslint . --max-warnings=0",
25
+ "audit:deps": "npm ls --all --omit=optional --omit=peer",
26
+ "audit:npm": "npm audit --audit-level=high --omit=dev",
27
+ "audit:test": "vitest run --coverage",
28
+ "lint": "eslint . --max-warnings=0",
29
+ "prepare": "npm run build",
30
+ "clean": "rimraf dist",
31
+ "test:coverage": "vitest run --coverage",
32
+ "pack:check": "node scripts/verify-public-package.cjs",
33
+ "privacy:check": "node scripts/verify-public-artifacts.cjs --package-dir .",
34
+ "prepublishOnly": "npm run build && npm run pack:check"
35
+ },
36
+ "keywords": [
37
+ "asset-pipeline",
38
+ "provider-connectors",
39
+ "asset-sources",
40
+ "runtime-validation",
41
+ "typescript",
42
+ "typesafe",
43
+ "runtime-validation",
44
+ "type-safety",
45
+ "plasius",
46
+ "provider-registry",
47
+ "source-acquisition",
48
+ "agnostic",
49
+ "oss",
50
+ "frontend",
51
+ "backend",
52
+ "portable",
53
+ "scalability",
54
+ "monorepo-friendly"
55
+ ],
56
+ "author": "Plasius LTD <development@plasius.co.uk>",
57
+ "license": "Apache-2.0",
58
+ "repository": {
59
+ "type": "git",
60
+ "url": "git+https://github.com/Plasius-LTD/asset-sources.git"
61
+ },
62
+ "bugs": {
63
+ "url": "https://github.com/Plasius-LTD/asset-sources/issues"
64
+ },
65
+ "homepage": "https://github.com/Plasius-LTD/asset-sources#readme",
66
+ "devDependencies": {
67
+ "@eslint/js": "^10.0.1",
68
+ "@types/node": "^26.1.1",
69
+ "@typescript-eslint/eslint-plugin": "^8.64.0",
70
+ "@typescript-eslint/parser": "^8.64.0",
71
+ "@vitest/coverage-v8": "^4.1.10",
72
+ "eslint": "^10.7.0",
73
+ "globals": "^17.7.0",
74
+ "tsup": "^8.5.1",
75
+ "typescript": "^6.0.3",
76
+ "vitest": "^4.1.10"
77
+ },
78
+ "publishConfig": {
79
+ "access": "public"
80
+ },
81
+ "funding": [
82
+ {
83
+ "type": "patreon",
84
+ "url": "https://www.patreon.com/c/plasiusltd/membership"
85
+ },
86
+ {
87
+ "type": "github",
88
+ "url": "https://github.com/sponsors/Plasius-LTD"
89
+ }
90
+ ],
91
+ "overrides": {
92
+ "brace-expansion": "^5.0.8",
93
+ "esbuild": "^0.28.1",
94
+ "minimatch": "^10.2.1"
95
+ },
96
+ "engines": {
97
+ "node": ">=24"
98
+ }
99
+ }