@tinycloud/share-sdk 1.2.0-beta.4 → 1.2.0-beta.6
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/{addressed-publish-BDaGyQA9.d.ts → addressed-publish-BnSBJ-MX.d.ts} +3 -1
- package/dist/{addressed-publish-DVvTlGog.d.cts → addressed-publish-DtcLNG2m.d.cts} +3 -1
- package/dist/artifact.cjs +88 -13
- package/dist/artifact.cjs.map +1 -1
- package/dist/artifact.d.cts +28 -8
- package/dist/artifact.d.ts +28 -8
- package/dist/artifact.js +84 -14
- package/dist/artifact.js.map +1 -1
- package/dist/index.cjs +128 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +90 -4
- package/dist/index.d.ts +90 -4
- package/dist/index.js +123 -4
- package/dist/index.js.map +1 -1
- package/dist/share-index.cjs +21 -1
- package/dist/share-index.cjs.map +1 -1
- package/dist/share-index.js +21 -1
- package/dist/share-index.js.map +1 -1
- package/dist/share-root.cjs +119 -1
- package/dist/share-root.cjs.map +1 -1
- package/dist/share-root.d.cts +75 -13
- package/dist/share-root.d.ts +75 -13
- package/dist/share-root.js +117 -1
- package/dist/share-root.js.map +1 -1
- package/package.json +2 -2
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ShareEnvelopeV2, UnifiedPolicyCapability, ShareAction, UnifiedContentSource, PolicyCredentialRequirementV1 } from '@tinycloud/share-envelope';
|
|
1
|
+
import { ShareEnvelopeV2, UnifiedPolicyCapability, ShareAction, UnifiedContentSource, PolicyCredentialRequirementV1, ArtifactPin } from '@tinycloud/share-envelope';
|
|
2
2
|
import { p as SharePublishTarget, P as PublishedShare, o as SharePublishOptions, d as OwnerShareAction, j as PublishedShareDeliveryMaterial } from './owner-policy-BqzRlkb6.js';
|
|
3
3
|
|
|
4
4
|
/** The only interactive boundary exposed by the headless SDK. */
|
|
@@ -206,6 +206,8 @@ interface AddressedSharePublishOptions {
|
|
|
206
206
|
readonly mediaType: string;
|
|
207
207
|
readonly byteLength: number;
|
|
208
208
|
readonly artifact?: "html";
|
|
209
|
+
/** TC-1428: pins the share to one write-once artifact version; signed with the envelope. Required when the content source is under `artifacts/`. */
|
|
210
|
+
readonly artifactPin?: ArtifactPin;
|
|
209
211
|
readonly deliveryEmail?: string;
|
|
210
212
|
readonly expiresAt: Date;
|
|
211
213
|
/** Sender-history material required by Node's Policy/v3 delivery authorization. */
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ShareEnvelopeV2, UnifiedPolicyCapability, ShareAction, UnifiedContentSource, PolicyCredentialRequirementV1 } from '@tinycloud/share-envelope';
|
|
1
|
+
import { ShareEnvelopeV2, UnifiedPolicyCapability, ShareAction, UnifiedContentSource, PolicyCredentialRequirementV1, ArtifactPin } from '@tinycloud/share-envelope';
|
|
2
2
|
import { p as SharePublishTarget, P as PublishedShare, o as SharePublishOptions, d as OwnerShareAction, j as PublishedShareDeliveryMaterial } from './owner-policy-BqzRlkb6.cjs';
|
|
3
3
|
|
|
4
4
|
/** The only interactive boundary exposed by the headless SDK. */
|
|
@@ -206,6 +206,8 @@ interface AddressedSharePublishOptions {
|
|
|
206
206
|
readonly mediaType: string;
|
|
207
207
|
readonly byteLength: number;
|
|
208
208
|
readonly artifact?: "html";
|
|
209
|
+
/** TC-1428: pins the share to one write-once artifact version; signed with the envelope. Required when the content source is under `artifacts/`. */
|
|
210
|
+
readonly artifactPin?: ArtifactPin;
|
|
209
211
|
readonly deliveryEmail?: string;
|
|
210
212
|
readonly expiresAt: Date;
|
|
211
213
|
/** Sender-history material required by Node's Policy/v3 delivery authorization. */
|
package/dist/artifact.cjs
CHANGED
|
@@ -29,16 +29,18 @@ __export(artifact_exports, {
|
|
|
29
29
|
artifactVersionResource: () => artifactVersionResource,
|
|
30
30
|
artifactVersionsPrefix: () => artifactVersionsPrefix,
|
|
31
31
|
assertArtifactId: () => assertArtifactId,
|
|
32
|
+
buildArtifactPin: () => buildArtifactPin,
|
|
32
33
|
listArtifactVersions: () => listArtifactVersions,
|
|
33
34
|
manifestBytes: () => manifestBytes,
|
|
34
35
|
newArtifactId: () => newArtifactId,
|
|
35
36
|
parseArtifactManifest: () => parseArtifactManifest,
|
|
36
37
|
parseArtifactVersionPath: () => parseArtifactVersionPath,
|
|
37
38
|
publishArtifactVersion: () => publishArtifactVersion,
|
|
38
|
-
sha256Hex: () => sha256Hex
|
|
39
|
+
sha256Hex: () => sha256Hex,
|
|
40
|
+
verifyArtifactFileBytes: () => verifyArtifactFileBytes,
|
|
41
|
+
verifyArtifactManifestBytes: () => verifyArtifactManifestBytes
|
|
39
42
|
});
|
|
40
43
|
module.exports = __toCommonJS(artifact_exports);
|
|
41
|
-
var import_sha2562 = require("@noble/hashes/sha256");
|
|
42
44
|
|
|
43
45
|
// ../share-envelope/dist/index.js
|
|
44
46
|
var import_sha2 = require("@noble/hashes/sha2");
|
|
@@ -5322,6 +5324,20 @@ var v3TargetSchema = external_exports.object({
|
|
|
5322
5324
|
nodeAudience: external_exports.string().min(1),
|
|
5323
5325
|
spaceId: external_exports.string().refine(isCanonicalPathSegment, { message: "expected a canonical space id" })
|
|
5324
5326
|
}).strict();
|
|
5327
|
+
var ARTIFACT_ID_PATTERN = /^[a-z0-9][a-z0-9_-]{2,62}$/;
|
|
5328
|
+
var artifactPinSchema = external_exports.object({
|
|
5329
|
+
v: external_exports.literal(1),
|
|
5330
|
+
artifactId: external_exports.string().regex(ARTIFACT_ID_PATTERN),
|
|
5331
|
+
version: external_exports.number().int().min(1).max(Number.MAX_SAFE_INTEGER),
|
|
5332
|
+
/** SHA-256 (lowercase hex) of the exact `manifest.json` bytes. The manifest itself stays an owner-side record. */
|
|
5333
|
+
manifestSha256: external_exports.string().regex(/^[0-9a-f]{64}$/),
|
|
5334
|
+
/** An addressed share reads one exact file, so exactly one entry: the stored bytes (ciphertext) it will fetch. */
|
|
5335
|
+
files: external_exports.array(external_exports.object({
|
|
5336
|
+
path: external_exports.string().min(1).max(255),
|
|
5337
|
+
sha256: external_exports.string().regex(/^[0-9a-f]{64}$/),
|
|
5338
|
+
bytes: external_exports.number().int().nonnegative()
|
|
5339
|
+
}).strict()).length(1)
|
|
5340
|
+
}).strict();
|
|
5325
5341
|
var unsignedShareEnvelopeV3BaseSchema = external_exports.object({
|
|
5326
5342
|
version: external_exports.literal(3),
|
|
5327
5343
|
shareId: external_exports.string().min(1),
|
|
@@ -5341,7 +5357,13 @@ var unsignedShareEnvelopeV3BaseSchema = external_exports.object({
|
|
|
5341
5357
|
expiry: external_exports.string().datetime({ offset: true }),
|
|
5342
5358
|
display: displaySchema,
|
|
5343
5359
|
encrypted: external_exports.literal(true),
|
|
5344
|
-
metadata: contentMetadataSchema
|
|
5360
|
+
metadata: contentMetadataSchema,
|
|
5361
|
+
/**
|
|
5362
|
+
* TC-1428: an owner-signed statement that this share reads one write-once artifact version. Additive: absent on
|
|
5363
|
+
* every other share, and covered by the envelope signature because the signature spans the whole unsigned object.
|
|
5364
|
+
* The shape is checked here; its binding to the content source is `verifyArtifactShare` in share-sdk.
|
|
5365
|
+
*/
|
|
5366
|
+
artifactPin: artifactPinSchema.optional()
|
|
5345
5367
|
}).strict();
|
|
5346
5368
|
function validateV3Invariants(value, ctx) {
|
|
5347
5369
|
const actions = [...value.actions];
|
|
@@ -5440,6 +5462,17 @@ function canonicalize(value) {
|
|
|
5440
5462
|
}
|
|
5441
5463
|
var MAX_INLINE_BYTES = 256 * 1024;
|
|
5442
5464
|
|
|
5465
|
+
// src/artifact.ts
|
|
5466
|
+
var import_sha2562 = require("@noble/hashes/sha256");
|
|
5467
|
+
|
|
5468
|
+
// src/artifact-core.ts
|
|
5469
|
+
var ARTIFACT_ROOT = "artifacts";
|
|
5470
|
+
function parseArtifactVersionPath(path) {
|
|
5471
|
+
const match = /^artifacts\/([a-z0-9][a-z0-9_-]{2,62})\/versions\/([1-9][0-9]{0,14})\/([^/]+)$/.exec(path);
|
|
5472
|
+
if (match === null) return void 0;
|
|
5473
|
+
return { artifactId: match[1], version: Number(match[2]), file: match[3] };
|
|
5474
|
+
}
|
|
5475
|
+
|
|
5443
5476
|
// src/filename-policy.ts
|
|
5444
5477
|
var UNSAFE_FILENAME_CODE_POINT = /[\p{Cc}\p{Cf}\p{Cs}\u2028\u2029]/u;
|
|
5445
5478
|
function hasUnsafeFilenameCodePoint(value) {
|
|
@@ -5453,8 +5486,21 @@ function canonicalShareFilename(value) {
|
|
|
5453
5486
|
return canonical;
|
|
5454
5487
|
}
|
|
5455
5488
|
|
|
5489
|
+
// src/artifact-pin.ts
|
|
5490
|
+
var ArtifactPinError = class extends Error {
|
|
5491
|
+
code;
|
|
5492
|
+
/** The code is the message: stable, short, and what callers and tests match on. */
|
|
5493
|
+
constructor(code2) {
|
|
5494
|
+
super(code2);
|
|
5495
|
+
this.name = "ArtifactPinError";
|
|
5496
|
+
this.code = code2;
|
|
5497
|
+
}
|
|
5498
|
+
};
|
|
5499
|
+
|
|
5456
5500
|
// src/artifact.ts
|
|
5457
|
-
|
|
5501
|
+
function sha256Hex(bytes) {
|
|
5502
|
+
return Array.from((0, import_sha2562.sha256)(bytes), (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
5503
|
+
}
|
|
5458
5504
|
var ARTIFACT_MANIFEST_NAME = "manifest.json";
|
|
5459
5505
|
var ARTIFACT_MANIFEST_VERSION = 1;
|
|
5460
5506
|
var ARTIFACT_MAX_PUBLISH_ATTEMPTS = 16;
|
|
@@ -5468,9 +5514,6 @@ var ArtifactError = class extends Error {
|
|
|
5468
5514
|
this.code = code2;
|
|
5469
5515
|
}
|
|
5470
5516
|
};
|
|
5471
|
-
function sha256Hex(bytes) {
|
|
5472
|
-
return Array.from((0, import_sha2562.sha256)(bytes), (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
5473
|
-
}
|
|
5474
5517
|
function newArtifactId(random = (length2) => crypto.getRandomValues(new Uint8Array(length2))) {
|
|
5475
5518
|
return `art_${Array.from(random(8), (byte) => byte.toString(16).padStart(2, "0")).join("")}`;
|
|
5476
5519
|
}
|
|
@@ -5493,11 +5536,6 @@ function artifactVersionResource(artifactId, version) {
|
|
|
5493
5536
|
function artifactVersionFilePath(artifactId, version, filename) {
|
|
5494
5537
|
return `${artifactVersionResource(artifactId, version)}/${filename}`;
|
|
5495
5538
|
}
|
|
5496
|
-
function parseArtifactVersionPath(path) {
|
|
5497
|
-
const match = /^artifacts\/([a-z0-9][a-z0-9_-]{2,62})\/versions\/([1-9][0-9]{0,14})\/([^/]+)$/.exec(path);
|
|
5498
|
-
if (match === null) return void 0;
|
|
5499
|
-
return { artifactId: match[1], version: Number(match[2]), file: match[3] };
|
|
5500
|
-
}
|
|
5501
5539
|
function manifestBytes(manifest) {
|
|
5502
5540
|
return new TextEncoder().encode(canonicalize(manifest));
|
|
5503
5541
|
}
|
|
@@ -5643,6 +5681,40 @@ async function publishArtifactVersion(store, input) {
|
|
|
5643
5681
|
}
|
|
5644
5682
|
throw new ArtifactError("conflict", "could not claim an artifact version number after repeated races; retry");
|
|
5645
5683
|
}
|
|
5684
|
+
function buildArtifactPin(version, filename) {
|
|
5685
|
+
const entry = version.manifest.files.find((candidate) => candidate.path === filename);
|
|
5686
|
+
if (entry === void 0) throw new ArtifactError("invalid-argument", "artifact manifest does not list that file");
|
|
5687
|
+
return {
|
|
5688
|
+
v: 1,
|
|
5689
|
+
artifactId: version.artifactId,
|
|
5690
|
+
version: version.version,
|
|
5691
|
+
manifestSha256: version.manifestSha256,
|
|
5692
|
+
files: [{ path: entry.path, sha256: entry.sha256, bytes: entry.bytes }]
|
|
5693
|
+
};
|
|
5694
|
+
}
|
|
5695
|
+
function verifyArtifactManifestBytes(pin, manifestBytes2) {
|
|
5696
|
+
if (sha256Hex(manifestBytes2) !== pin.manifestSha256) {
|
|
5697
|
+
throw new ArtifactPinError("manifest-mismatch");
|
|
5698
|
+
}
|
|
5699
|
+
let manifest;
|
|
5700
|
+
try {
|
|
5701
|
+
manifest = parseArtifactManifest(manifestBytes2);
|
|
5702
|
+
} catch {
|
|
5703
|
+
throw new ArtifactPinError("manifest-mismatch");
|
|
5704
|
+
}
|
|
5705
|
+
const file = pin.files[0];
|
|
5706
|
+
const listed = manifest.files.find((candidate) => candidate.path === file.path);
|
|
5707
|
+
if (listed === void 0 || listed.sha256 !== file.sha256 || listed.bytes !== file.bytes) {
|
|
5708
|
+
throw new ArtifactPinError("manifest-mismatch");
|
|
5709
|
+
}
|
|
5710
|
+
return manifest;
|
|
5711
|
+
}
|
|
5712
|
+
function verifyArtifactFileBytes(pin, storedBytes) {
|
|
5713
|
+
const file = pin.files[0];
|
|
5714
|
+
if (storedBytes.byteLength !== file.bytes || sha256Hex(storedBytes) !== file.sha256) {
|
|
5715
|
+
throw new ArtifactPinError("file-digest-mismatch");
|
|
5716
|
+
}
|
|
5717
|
+
}
|
|
5646
5718
|
// Annotate the CommonJS export names for ESM import in node:
|
|
5647
5719
|
0 && (module.exports = {
|
|
5648
5720
|
ARTIFACT_MANIFEST_NAME,
|
|
@@ -5654,12 +5726,15 @@ async function publishArtifactVersion(store, input) {
|
|
|
5654
5726
|
artifactVersionResource,
|
|
5655
5727
|
artifactVersionsPrefix,
|
|
5656
5728
|
assertArtifactId,
|
|
5729
|
+
buildArtifactPin,
|
|
5657
5730
|
listArtifactVersions,
|
|
5658
5731
|
manifestBytes,
|
|
5659
5732
|
newArtifactId,
|
|
5660
5733
|
parseArtifactManifest,
|
|
5661
5734
|
parseArtifactVersionPath,
|
|
5662
5735
|
publishArtifactVersion,
|
|
5663
|
-
sha256Hex
|
|
5736
|
+
sha256Hex,
|
|
5737
|
+
verifyArtifactFileBytes,
|
|
5738
|
+
verifyArtifactManifestBytes
|
|
5664
5739
|
});
|
|
5665
5740
|
//# sourceMappingURL=artifact.cjs.map
|