@tinycloud/share-sdk 1.2.0-beta.3 → 1.2.0-beta.5
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-BnSBJ-MX.d.ts +242 -0
- package/dist/addressed-publish-DtcLNG2m.d.cts +242 -0
- 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/history-CUWDK0lE.d.cts +180 -0
- package/dist/history-CyT6x8h4.d.ts +180 -0
- package/dist/index.cjs +128 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +93 -154
- package/dist/index.d.ts +93 -154
- package/dist/index.js +123 -4
- package/dist/index.js.map +1 -1
- package/dist/owner-policy-BqzRlkb6.d.cts +297 -0
- package/dist/owner-policy-BqzRlkb6.d.ts +297 -0
- package/dist/share-index.cjs +8714 -0
- package/dist/share-index.cjs.map +1 -0
- package/dist/share-index.d.cts +1063 -0
- package/dist/share-index.d.ts +1063 -0
- package/dist/share-index.js +8642 -0
- package/dist/share-index.js.map +1 -0
- package/dist/share-root.cjs +23 -1
- package/dist/share-root.cjs.map +1 -1
- package/dist/share-root.d.cts +2 -1
- package/dist/share-root.d.ts +2 -1
- package/dist/share-root.js +23 -1
- package/dist/share-root.js.map +1 -1
- package/package.json +8 -2
- package/dist/addressed-publish-CsUS7-SI.d.cts +0 -535
- package/dist/addressed-publish-CsUS7-SI.d.ts +0 -535
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
import { ShareEnvelopeV2, UnifiedPolicyCapability, ShareAction, UnifiedContentSource, PolicyCredentialRequirementV1, ArtifactPin } from '@tinycloud/share-envelope';
|
|
2
|
+
import { p as SharePublishTarget, P as PublishedShare, o as SharePublishOptions, d as OwnerShareAction, j as PublishedShareDeliveryMaterial } from './owner-policy-BqzRlkb6.js';
|
|
3
|
+
|
|
4
|
+
/** The only interactive boundary exposed by the headless SDK. */
|
|
5
|
+
type ShareAuthorizationMethod = "openkey-device" | "email-claim" | "email-otp";
|
|
6
|
+
interface ShareAuthorizationRequired {
|
|
7
|
+
readonly state: "authorization-required";
|
|
8
|
+
readonly method: ShareAuthorizationMethod;
|
|
9
|
+
/** A browser-safe continuation location. It must never contain a claim secret. */
|
|
10
|
+
readonly continueUrl?: string;
|
|
11
|
+
/** An opaque, short-lived, nonce-bound handle. It is not a bearer credential. */
|
|
12
|
+
readonly resumeToken?: string;
|
|
13
|
+
}
|
|
14
|
+
interface ShareAuthorizationDenied {
|
|
15
|
+
readonly state: "denied";
|
|
16
|
+
readonly reason: "rejected" | "expired" | "revoked" | "unsupported";
|
|
17
|
+
}
|
|
18
|
+
interface ShareAuthorizationReady<T> {
|
|
19
|
+
readonly state: "ready";
|
|
20
|
+
readonly value: T;
|
|
21
|
+
}
|
|
22
|
+
type ShareAuthorizationResult<T> = ShareAuthorizationReady<T> | ShareAuthorizationRequired | ShareAuthorizationDenied;
|
|
23
|
+
interface ShareAuthorizationAdapter<T> {
|
|
24
|
+
begin(input: {
|
|
25
|
+
readonly envelope: ShareEnvelopeV2;
|
|
26
|
+
readonly method: ShareAuthorizationMethod;
|
|
27
|
+
}): Promise<ShareAuthorizationResult<T>>;
|
|
28
|
+
resume(input: {
|
|
29
|
+
readonly envelope: ShareEnvelopeV2;
|
|
30
|
+
readonly method: ShareAuthorizationMethod;
|
|
31
|
+
readonly resumeToken: string;
|
|
32
|
+
readonly proof?: unknown;
|
|
33
|
+
}): Promise<ShareAuthorizationResult<T>>;
|
|
34
|
+
/** Verify the detached node proof against a pinned authority trust bundle. */
|
|
35
|
+
readonly verifyResult?: (input: {
|
|
36
|
+
readonly envelope: ShareEnvelopeV2;
|
|
37
|
+
readonly value: T;
|
|
38
|
+
readonly proof: unknown;
|
|
39
|
+
}) => Promise<boolean>;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* A node-authorized addressed read. Returning plaintext alone is not an
|
|
43
|
+
* authorization result: the caller must also return the signed response
|
|
44
|
+
* binding and digest that the node produced for that exact share.
|
|
45
|
+
*/
|
|
46
|
+
interface ShareAuthorizedContent {
|
|
47
|
+
readonly bytes: Uint8Array;
|
|
48
|
+
readonly bodyDigest: string;
|
|
49
|
+
readonly contentSourceDigest: string;
|
|
50
|
+
readonly binding: {
|
|
51
|
+
readonly shareId: string;
|
|
52
|
+
readonly delegationCid: string;
|
|
53
|
+
readonly authorityMaterialHandle: string;
|
|
54
|
+
readonly authorityMaterialDigest: string;
|
|
55
|
+
readonly resource: {
|
|
56
|
+
readonly kind: "exact" | "prefix";
|
|
57
|
+
readonly path: string;
|
|
58
|
+
};
|
|
59
|
+
readonly action?: string;
|
|
60
|
+
};
|
|
61
|
+
/** A detached node proof; self-reported bytes and digests are not authorization. */
|
|
62
|
+
readonly proof: unknown;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Start or continue a target authorization without ever guessing a device,
|
|
66
|
+
* claim, or delegation secret. Adapters own their protocol and are expected
|
|
67
|
+
* to bind their resume token to a server challenge and expiry.
|
|
68
|
+
*/
|
|
69
|
+
declare function authorizeShare<T>(input: {
|
|
70
|
+
readonly envelope: ShareEnvelopeV2;
|
|
71
|
+
readonly method: ShareAuthorizationMethod;
|
|
72
|
+
readonly adapter: ShareAuthorizationAdapter<T>;
|
|
73
|
+
readonly resumeToken?: string;
|
|
74
|
+
readonly proof?: unknown;
|
|
75
|
+
}): Promise<ShareAuthorizationResult<T>>;
|
|
76
|
+
declare function authorizationMethodForTarget(target: {
|
|
77
|
+
readonly kind: string;
|
|
78
|
+
}): ShareAuthorizationMethod | undefined;
|
|
79
|
+
|
|
80
|
+
type ShareTarget = SharePublishTarget;
|
|
81
|
+
interface TargetPublishInput {
|
|
82
|
+
readonly source: Uint8Array;
|
|
83
|
+
readonly filename: string;
|
|
84
|
+
readonly mediaType?: string;
|
|
85
|
+
/** Additional files for a prefix resource; source remains the first file for compatibility. */
|
|
86
|
+
readonly files?: readonly {
|
|
87
|
+
readonly bytes: Uint8Array;
|
|
88
|
+
readonly filename: string;
|
|
89
|
+
readonly mediaType?: string;
|
|
90
|
+
}[];
|
|
91
|
+
readonly target: ShareTarget;
|
|
92
|
+
readonly expiresAt: Date;
|
|
93
|
+
readonly expiryWasExplicit?: boolean;
|
|
94
|
+
readonly origin: string;
|
|
95
|
+
readonly resourceKind?: "exact" | "prefix";
|
|
96
|
+
readonly actions?: readonly ("read" | "list" | "edit")[];
|
|
97
|
+
readonly notify?: boolean;
|
|
98
|
+
/** Publish as the next write-once version of this artifact and pin the share to it (TC-1428). */
|
|
99
|
+
readonly artifact?: {
|
|
100
|
+
readonly id: string;
|
|
101
|
+
readonly note?: string;
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
type TargetPublishOutcome = PublishedShare | ShareAuthorizationRequired;
|
|
105
|
+
interface TargetPublishAdapter {
|
|
106
|
+
publish(input: TargetPublishInput): Promise<TargetPublishOutcome>;
|
|
107
|
+
}
|
|
108
|
+
declare function normalizeShareTarget(target: ShareTarget): ShareTarget;
|
|
109
|
+
declare function targetAuthorizationMethod(target: ShareTarget): ShareAuthorizationMethod | undefined;
|
|
110
|
+
/** Route every share through the authenticated TinyCloud authority adapter. */
|
|
111
|
+
declare function publishTargetShare(input: SharePublishOptions & {
|
|
112
|
+
readonly target: ShareTarget;
|
|
113
|
+
readonly notify?: boolean;
|
|
114
|
+
readonly targetAdapter?: TargetPublishAdapter;
|
|
115
|
+
readonly files?: readonly {
|
|
116
|
+
readonly bytes: Uint8Array;
|
|
117
|
+
readonly filename: string;
|
|
118
|
+
readonly mediaType?: string;
|
|
119
|
+
}[];
|
|
120
|
+
readonly resourceKind?: "exact" | "prefix";
|
|
121
|
+
readonly actions?: readonly ("read" | "list" | "edit")[];
|
|
122
|
+
}): Promise<TargetPublishOutcome>;
|
|
123
|
+
|
|
124
|
+
interface AddressedOwnerRootInput {
|
|
125
|
+
readonly ownerDid: string;
|
|
126
|
+
readonly role: "policy-authority" | "policy-enforcement";
|
|
127
|
+
readonly audienceDid: string;
|
|
128
|
+
readonly policyId: string;
|
|
129
|
+
readonly policyDigestHex: string;
|
|
130
|
+
readonly policyCid: string;
|
|
131
|
+
readonly contentSourceDigestHex: string;
|
|
132
|
+
readonly capabilityCeilingHashHex: string;
|
|
133
|
+
readonly nativeProjectionHashHex: string;
|
|
134
|
+
readonly notBefore: Date;
|
|
135
|
+
readonly expiresAt: Date;
|
|
136
|
+
readonly nodeAudience: string;
|
|
137
|
+
readonly capabilities: readonly UnifiedPolicyCapability[];
|
|
138
|
+
}
|
|
139
|
+
interface AddressedOwnerRootReceipt {
|
|
140
|
+
readonly cid: string;
|
|
141
|
+
readonly delegationHeader: {
|
|
142
|
+
readonly Authorization: string;
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
interface AddressedPolicyRegistrationInput {
|
|
146
|
+
readonly policyCid: string;
|
|
147
|
+
readonly policy: Readonly<Record<string, unknown>>;
|
|
148
|
+
readonly policyRoot: {
|
|
149
|
+
readonly cid: string;
|
|
150
|
+
readonly authorization: string;
|
|
151
|
+
};
|
|
152
|
+
readonly enforcementRoot: {
|
|
153
|
+
readonly cid: string;
|
|
154
|
+
readonly authorization: string;
|
|
155
|
+
};
|
|
156
|
+
readonly contentSourceDigestHex: string;
|
|
157
|
+
readonly nativeProjectionHashHex: string;
|
|
158
|
+
readonly rootExpiresAt: string;
|
|
159
|
+
readonly enforcerDid: string;
|
|
160
|
+
readonly expectedNodeAudience: string;
|
|
161
|
+
}
|
|
162
|
+
interface AddressedPolicyRegistrationReceipt {
|
|
163
|
+
readonly policyCid: string;
|
|
164
|
+
readonly policyRootCid: string;
|
|
165
|
+
readonly enforcementRootCid: string;
|
|
166
|
+
readonly attestedEnforcerBinding: {
|
|
167
|
+
readonly schema: "xyz.tinycloud.policy/attested-enforcer/v2";
|
|
168
|
+
readonly enforcerDid: string;
|
|
169
|
+
readonly nodeAudience: string;
|
|
170
|
+
readonly attestationBindingDigestHex: string;
|
|
171
|
+
readonly issuedAt: string;
|
|
172
|
+
readonly expiresAt: string;
|
|
173
|
+
readonly signature: {
|
|
174
|
+
readonly suite: "Ed25519";
|
|
175
|
+
readonly signerDid: string;
|
|
176
|
+
readonly value: string;
|
|
177
|
+
};
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
/** App-neutral owner authority. Node SDK owns all Policy/v3 transport. */
|
|
181
|
+
interface AddressedPublishAuthority {
|
|
182
|
+
readonly ownerDid: string;
|
|
183
|
+
createOwnerRoot(input: AddressedOwnerRootInput): Promise<AddressedOwnerRootReceipt>;
|
|
184
|
+
sign(bytes: Uint8Array): Promise<Uint8Array>;
|
|
185
|
+
registerPolicy(input: AddressedPolicyRegistrationInput): Promise<AddressedPolicyRegistrationReceipt>;
|
|
186
|
+
}
|
|
187
|
+
interface AddressedSharePublishOptions {
|
|
188
|
+
readonly shareId: string;
|
|
189
|
+
readonly shareOrigin: string;
|
|
190
|
+
readonly nodeOrigin: string;
|
|
191
|
+
readonly nodeAudience: string;
|
|
192
|
+
readonly enforcerDid: string;
|
|
193
|
+
readonly spaceId: string;
|
|
194
|
+
readonly target: Exclude<ShareTarget, {
|
|
195
|
+
readonly kind: "bearer";
|
|
196
|
+
}>;
|
|
197
|
+
readonly resource: {
|
|
198
|
+
readonly kind: "exact" | "prefix";
|
|
199
|
+
readonly path: string;
|
|
200
|
+
};
|
|
201
|
+
readonly actions: readonly ShareAction[];
|
|
202
|
+
readonly policyActions: readonly OwnerShareAction[];
|
|
203
|
+
readonly contentSource: UnifiedContentSource;
|
|
204
|
+
readonly credentialRequirement?: PolicyCredentialRequirementV1;
|
|
205
|
+
readonly filename: string;
|
|
206
|
+
readonly mediaType: string;
|
|
207
|
+
readonly byteLength: number;
|
|
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;
|
|
211
|
+
readonly deliveryEmail?: string;
|
|
212
|
+
readonly expiresAt: Date;
|
|
213
|
+
/** Sender-history material required by Node's Policy/v3 delivery authorization. */
|
|
214
|
+
readonly onDeliveryMaterial?: (input: PublishedShareDeliveryMaterial) => void;
|
|
215
|
+
readonly authority: AddressedPublishAuthority;
|
|
216
|
+
}
|
|
217
|
+
type MailboxTarget = Extract<ShareTarget, {
|
|
218
|
+
readonly kind: "email" | "emailDomain";
|
|
219
|
+
}>;
|
|
220
|
+
/** The Policy/v2 credential commitment a share addressed to `target` must carry. */
|
|
221
|
+
declare function addressedCredentialRequirement(target: MailboxTarget): PolicyCredentialRequirementV1;
|
|
222
|
+
/** Facts every addressed-share check needs, available before any side effect. */
|
|
223
|
+
type AddressedShareRequest = Pick<AddressedSharePublishOptions, "target" | "actions" | "policyActions" | "filename" | "deliveryEmail">;
|
|
224
|
+
interface PreparedAddressedShare {
|
|
225
|
+
/** The canonical target the envelope's recipient matcher will carry. */
|
|
226
|
+
readonly target: Exclude<ShareTarget, {
|
|
227
|
+
readonly kind: "bearer";
|
|
228
|
+
}>;
|
|
229
|
+
/** Present for mailbox targets: the Policy/v2 commitment to pass to `publishAddressedShare`. */
|
|
230
|
+
readonly credentialRequirement?: PolicyCredentialRequirementV1;
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Runs every argument and target check of `publishAddressedShare` that does
|
|
234
|
+
* not depend on stored content, and derives the credential commitment. It has
|
|
235
|
+
* no side effects, so senders call it before uploading content or publishing
|
|
236
|
+
* a location record; a refused share then leaves nothing behind.
|
|
237
|
+
*/
|
|
238
|
+
declare function prepareAddressedShare(request: AddressedShareRequest): PreparedAddressedShare;
|
|
239
|
+
/** Canonical application-neutral Policy/v3 addressed publisher shared by browser and CLI. */
|
|
240
|
+
declare function publishAddressedShare(input: AddressedSharePublishOptions): Promise<PublishedShare>;
|
|
241
|
+
|
|
242
|
+
export { type AddressedOwnerRootInput as A, type PreparedAddressedShare as P, type ShareAuthorizationMethod as S, type TargetPublishOutcome as T, type ShareAuthorizedContent as a, type ShareAuthorizationAdapter as b, type TargetPublishInput as c, type ShareAuthorizationResult as d, type ShareTarget as e, type AddressedOwnerRootReceipt as f, type AddressedPolicyRegistrationInput as g, type AddressedPolicyRegistrationReceipt as h, type AddressedPublishAuthority as i, type AddressedSharePublishOptions as j, type AddressedShareRequest as k, type ShareAuthorizationDenied as l, type ShareAuthorizationReady as m, type ShareAuthorizationRequired as n, type TargetPublishAdapter as o, addressedCredentialRequirement as p, authorizationMethodForTarget as q, authorizeShare as r, normalizeShareTarget as s, prepareAddressedShare as t, publishAddressedShare as u, publishTargetShare as v, targetAuthorizationMethod as w };
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
import { ShareEnvelopeV2, UnifiedPolicyCapability, ShareAction, UnifiedContentSource, PolicyCredentialRequirementV1, ArtifactPin } from '@tinycloud/share-envelope';
|
|
2
|
+
import { p as SharePublishTarget, P as PublishedShare, o as SharePublishOptions, d as OwnerShareAction, j as PublishedShareDeliveryMaterial } from './owner-policy-BqzRlkb6.cjs';
|
|
3
|
+
|
|
4
|
+
/** The only interactive boundary exposed by the headless SDK. */
|
|
5
|
+
type ShareAuthorizationMethod = "openkey-device" | "email-claim" | "email-otp";
|
|
6
|
+
interface ShareAuthorizationRequired {
|
|
7
|
+
readonly state: "authorization-required";
|
|
8
|
+
readonly method: ShareAuthorizationMethod;
|
|
9
|
+
/** A browser-safe continuation location. It must never contain a claim secret. */
|
|
10
|
+
readonly continueUrl?: string;
|
|
11
|
+
/** An opaque, short-lived, nonce-bound handle. It is not a bearer credential. */
|
|
12
|
+
readonly resumeToken?: string;
|
|
13
|
+
}
|
|
14
|
+
interface ShareAuthorizationDenied {
|
|
15
|
+
readonly state: "denied";
|
|
16
|
+
readonly reason: "rejected" | "expired" | "revoked" | "unsupported";
|
|
17
|
+
}
|
|
18
|
+
interface ShareAuthorizationReady<T> {
|
|
19
|
+
readonly state: "ready";
|
|
20
|
+
readonly value: T;
|
|
21
|
+
}
|
|
22
|
+
type ShareAuthorizationResult<T> = ShareAuthorizationReady<T> | ShareAuthorizationRequired | ShareAuthorizationDenied;
|
|
23
|
+
interface ShareAuthorizationAdapter<T> {
|
|
24
|
+
begin(input: {
|
|
25
|
+
readonly envelope: ShareEnvelopeV2;
|
|
26
|
+
readonly method: ShareAuthorizationMethod;
|
|
27
|
+
}): Promise<ShareAuthorizationResult<T>>;
|
|
28
|
+
resume(input: {
|
|
29
|
+
readonly envelope: ShareEnvelopeV2;
|
|
30
|
+
readonly method: ShareAuthorizationMethod;
|
|
31
|
+
readonly resumeToken: string;
|
|
32
|
+
readonly proof?: unknown;
|
|
33
|
+
}): Promise<ShareAuthorizationResult<T>>;
|
|
34
|
+
/** Verify the detached node proof against a pinned authority trust bundle. */
|
|
35
|
+
readonly verifyResult?: (input: {
|
|
36
|
+
readonly envelope: ShareEnvelopeV2;
|
|
37
|
+
readonly value: T;
|
|
38
|
+
readonly proof: unknown;
|
|
39
|
+
}) => Promise<boolean>;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* A node-authorized addressed read. Returning plaintext alone is not an
|
|
43
|
+
* authorization result: the caller must also return the signed response
|
|
44
|
+
* binding and digest that the node produced for that exact share.
|
|
45
|
+
*/
|
|
46
|
+
interface ShareAuthorizedContent {
|
|
47
|
+
readonly bytes: Uint8Array;
|
|
48
|
+
readonly bodyDigest: string;
|
|
49
|
+
readonly contentSourceDigest: string;
|
|
50
|
+
readonly binding: {
|
|
51
|
+
readonly shareId: string;
|
|
52
|
+
readonly delegationCid: string;
|
|
53
|
+
readonly authorityMaterialHandle: string;
|
|
54
|
+
readonly authorityMaterialDigest: string;
|
|
55
|
+
readonly resource: {
|
|
56
|
+
readonly kind: "exact" | "prefix";
|
|
57
|
+
readonly path: string;
|
|
58
|
+
};
|
|
59
|
+
readonly action?: string;
|
|
60
|
+
};
|
|
61
|
+
/** A detached node proof; self-reported bytes and digests are not authorization. */
|
|
62
|
+
readonly proof: unknown;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Start or continue a target authorization without ever guessing a device,
|
|
66
|
+
* claim, or delegation secret. Adapters own their protocol and are expected
|
|
67
|
+
* to bind their resume token to a server challenge and expiry.
|
|
68
|
+
*/
|
|
69
|
+
declare function authorizeShare<T>(input: {
|
|
70
|
+
readonly envelope: ShareEnvelopeV2;
|
|
71
|
+
readonly method: ShareAuthorizationMethod;
|
|
72
|
+
readonly adapter: ShareAuthorizationAdapter<T>;
|
|
73
|
+
readonly resumeToken?: string;
|
|
74
|
+
readonly proof?: unknown;
|
|
75
|
+
}): Promise<ShareAuthorizationResult<T>>;
|
|
76
|
+
declare function authorizationMethodForTarget(target: {
|
|
77
|
+
readonly kind: string;
|
|
78
|
+
}): ShareAuthorizationMethod | undefined;
|
|
79
|
+
|
|
80
|
+
type ShareTarget = SharePublishTarget;
|
|
81
|
+
interface TargetPublishInput {
|
|
82
|
+
readonly source: Uint8Array;
|
|
83
|
+
readonly filename: string;
|
|
84
|
+
readonly mediaType?: string;
|
|
85
|
+
/** Additional files for a prefix resource; source remains the first file for compatibility. */
|
|
86
|
+
readonly files?: readonly {
|
|
87
|
+
readonly bytes: Uint8Array;
|
|
88
|
+
readonly filename: string;
|
|
89
|
+
readonly mediaType?: string;
|
|
90
|
+
}[];
|
|
91
|
+
readonly target: ShareTarget;
|
|
92
|
+
readonly expiresAt: Date;
|
|
93
|
+
readonly expiryWasExplicit?: boolean;
|
|
94
|
+
readonly origin: string;
|
|
95
|
+
readonly resourceKind?: "exact" | "prefix";
|
|
96
|
+
readonly actions?: readonly ("read" | "list" | "edit")[];
|
|
97
|
+
readonly notify?: boolean;
|
|
98
|
+
/** Publish as the next write-once version of this artifact and pin the share to it (TC-1428). */
|
|
99
|
+
readonly artifact?: {
|
|
100
|
+
readonly id: string;
|
|
101
|
+
readonly note?: string;
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
type TargetPublishOutcome = PublishedShare | ShareAuthorizationRequired;
|
|
105
|
+
interface TargetPublishAdapter {
|
|
106
|
+
publish(input: TargetPublishInput): Promise<TargetPublishOutcome>;
|
|
107
|
+
}
|
|
108
|
+
declare function normalizeShareTarget(target: ShareTarget): ShareTarget;
|
|
109
|
+
declare function targetAuthorizationMethod(target: ShareTarget): ShareAuthorizationMethod | undefined;
|
|
110
|
+
/** Route every share through the authenticated TinyCloud authority adapter. */
|
|
111
|
+
declare function publishTargetShare(input: SharePublishOptions & {
|
|
112
|
+
readonly target: ShareTarget;
|
|
113
|
+
readonly notify?: boolean;
|
|
114
|
+
readonly targetAdapter?: TargetPublishAdapter;
|
|
115
|
+
readonly files?: readonly {
|
|
116
|
+
readonly bytes: Uint8Array;
|
|
117
|
+
readonly filename: string;
|
|
118
|
+
readonly mediaType?: string;
|
|
119
|
+
}[];
|
|
120
|
+
readonly resourceKind?: "exact" | "prefix";
|
|
121
|
+
readonly actions?: readonly ("read" | "list" | "edit")[];
|
|
122
|
+
}): Promise<TargetPublishOutcome>;
|
|
123
|
+
|
|
124
|
+
interface AddressedOwnerRootInput {
|
|
125
|
+
readonly ownerDid: string;
|
|
126
|
+
readonly role: "policy-authority" | "policy-enforcement";
|
|
127
|
+
readonly audienceDid: string;
|
|
128
|
+
readonly policyId: string;
|
|
129
|
+
readonly policyDigestHex: string;
|
|
130
|
+
readonly policyCid: string;
|
|
131
|
+
readonly contentSourceDigestHex: string;
|
|
132
|
+
readonly capabilityCeilingHashHex: string;
|
|
133
|
+
readonly nativeProjectionHashHex: string;
|
|
134
|
+
readonly notBefore: Date;
|
|
135
|
+
readonly expiresAt: Date;
|
|
136
|
+
readonly nodeAudience: string;
|
|
137
|
+
readonly capabilities: readonly UnifiedPolicyCapability[];
|
|
138
|
+
}
|
|
139
|
+
interface AddressedOwnerRootReceipt {
|
|
140
|
+
readonly cid: string;
|
|
141
|
+
readonly delegationHeader: {
|
|
142
|
+
readonly Authorization: string;
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
interface AddressedPolicyRegistrationInput {
|
|
146
|
+
readonly policyCid: string;
|
|
147
|
+
readonly policy: Readonly<Record<string, unknown>>;
|
|
148
|
+
readonly policyRoot: {
|
|
149
|
+
readonly cid: string;
|
|
150
|
+
readonly authorization: string;
|
|
151
|
+
};
|
|
152
|
+
readonly enforcementRoot: {
|
|
153
|
+
readonly cid: string;
|
|
154
|
+
readonly authorization: string;
|
|
155
|
+
};
|
|
156
|
+
readonly contentSourceDigestHex: string;
|
|
157
|
+
readonly nativeProjectionHashHex: string;
|
|
158
|
+
readonly rootExpiresAt: string;
|
|
159
|
+
readonly enforcerDid: string;
|
|
160
|
+
readonly expectedNodeAudience: string;
|
|
161
|
+
}
|
|
162
|
+
interface AddressedPolicyRegistrationReceipt {
|
|
163
|
+
readonly policyCid: string;
|
|
164
|
+
readonly policyRootCid: string;
|
|
165
|
+
readonly enforcementRootCid: string;
|
|
166
|
+
readonly attestedEnforcerBinding: {
|
|
167
|
+
readonly schema: "xyz.tinycloud.policy/attested-enforcer/v2";
|
|
168
|
+
readonly enforcerDid: string;
|
|
169
|
+
readonly nodeAudience: string;
|
|
170
|
+
readonly attestationBindingDigestHex: string;
|
|
171
|
+
readonly issuedAt: string;
|
|
172
|
+
readonly expiresAt: string;
|
|
173
|
+
readonly signature: {
|
|
174
|
+
readonly suite: "Ed25519";
|
|
175
|
+
readonly signerDid: string;
|
|
176
|
+
readonly value: string;
|
|
177
|
+
};
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
/** App-neutral owner authority. Node SDK owns all Policy/v3 transport. */
|
|
181
|
+
interface AddressedPublishAuthority {
|
|
182
|
+
readonly ownerDid: string;
|
|
183
|
+
createOwnerRoot(input: AddressedOwnerRootInput): Promise<AddressedOwnerRootReceipt>;
|
|
184
|
+
sign(bytes: Uint8Array): Promise<Uint8Array>;
|
|
185
|
+
registerPolicy(input: AddressedPolicyRegistrationInput): Promise<AddressedPolicyRegistrationReceipt>;
|
|
186
|
+
}
|
|
187
|
+
interface AddressedSharePublishOptions {
|
|
188
|
+
readonly shareId: string;
|
|
189
|
+
readonly shareOrigin: string;
|
|
190
|
+
readonly nodeOrigin: string;
|
|
191
|
+
readonly nodeAudience: string;
|
|
192
|
+
readonly enforcerDid: string;
|
|
193
|
+
readonly spaceId: string;
|
|
194
|
+
readonly target: Exclude<ShareTarget, {
|
|
195
|
+
readonly kind: "bearer";
|
|
196
|
+
}>;
|
|
197
|
+
readonly resource: {
|
|
198
|
+
readonly kind: "exact" | "prefix";
|
|
199
|
+
readonly path: string;
|
|
200
|
+
};
|
|
201
|
+
readonly actions: readonly ShareAction[];
|
|
202
|
+
readonly policyActions: readonly OwnerShareAction[];
|
|
203
|
+
readonly contentSource: UnifiedContentSource;
|
|
204
|
+
readonly credentialRequirement?: PolicyCredentialRequirementV1;
|
|
205
|
+
readonly filename: string;
|
|
206
|
+
readonly mediaType: string;
|
|
207
|
+
readonly byteLength: number;
|
|
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;
|
|
211
|
+
readonly deliveryEmail?: string;
|
|
212
|
+
readonly expiresAt: Date;
|
|
213
|
+
/** Sender-history material required by Node's Policy/v3 delivery authorization. */
|
|
214
|
+
readonly onDeliveryMaterial?: (input: PublishedShareDeliveryMaterial) => void;
|
|
215
|
+
readonly authority: AddressedPublishAuthority;
|
|
216
|
+
}
|
|
217
|
+
type MailboxTarget = Extract<ShareTarget, {
|
|
218
|
+
readonly kind: "email" | "emailDomain";
|
|
219
|
+
}>;
|
|
220
|
+
/** The Policy/v2 credential commitment a share addressed to `target` must carry. */
|
|
221
|
+
declare function addressedCredentialRequirement(target: MailboxTarget): PolicyCredentialRequirementV1;
|
|
222
|
+
/** Facts every addressed-share check needs, available before any side effect. */
|
|
223
|
+
type AddressedShareRequest = Pick<AddressedSharePublishOptions, "target" | "actions" | "policyActions" | "filename" | "deliveryEmail">;
|
|
224
|
+
interface PreparedAddressedShare {
|
|
225
|
+
/** The canonical target the envelope's recipient matcher will carry. */
|
|
226
|
+
readonly target: Exclude<ShareTarget, {
|
|
227
|
+
readonly kind: "bearer";
|
|
228
|
+
}>;
|
|
229
|
+
/** Present for mailbox targets: the Policy/v2 commitment to pass to `publishAddressedShare`. */
|
|
230
|
+
readonly credentialRequirement?: PolicyCredentialRequirementV1;
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Runs every argument and target check of `publishAddressedShare` that does
|
|
234
|
+
* not depend on stored content, and derives the credential commitment. It has
|
|
235
|
+
* no side effects, so senders call it before uploading content or publishing
|
|
236
|
+
* a location record; a refused share then leaves nothing behind.
|
|
237
|
+
*/
|
|
238
|
+
declare function prepareAddressedShare(request: AddressedShareRequest): PreparedAddressedShare;
|
|
239
|
+
/** Canonical application-neutral Policy/v3 addressed publisher shared by browser and CLI. */
|
|
240
|
+
declare function publishAddressedShare(input: AddressedSharePublishOptions): Promise<PublishedShare>;
|
|
241
|
+
|
|
242
|
+
export { type AddressedOwnerRootInput as A, type PreparedAddressedShare as P, type ShareAuthorizationMethod as S, type TargetPublishOutcome as T, type ShareAuthorizedContent as a, type ShareAuthorizationAdapter as b, type TargetPublishInput as c, type ShareAuthorizationResult as d, type ShareTarget as e, type AddressedOwnerRootReceipt as f, type AddressedPolicyRegistrationInput as g, type AddressedPolicyRegistrationReceipt as h, type AddressedPublishAuthority as i, type AddressedSharePublishOptions as j, type AddressedShareRequest as k, type ShareAuthorizationDenied as l, type ShareAuthorizationReady as m, type ShareAuthorizationRequired as n, type TargetPublishAdapter as o, addressedCredentialRequirement as p, authorizationMethodForTarget as q, authorizeShare as r, normalizeShareTarget as s, prepareAddressedShare as t, publishAddressedShare as u, publishTargetShare as v, targetAuthorizationMethod as w };
|
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
|