@tinycloud/share-sdk 1.2.0-beta.5 → 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/index.cjs.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/share-index.cjs.map +1 -1
- package/dist/share-index.js.map +1 -1
- package/dist/share-root.cjs +96 -0
- package/dist/share-root.cjs.map +1 -1
- package/dist/share-root.d.cts +74 -12
- package/dist/share-root.d.ts +74 -12
- package/dist/share-root.js +94 -0
- package/dist/share-root.js.map +1 -1
- package/package.json +1 -1
package/dist/share-root.cjs
CHANGED
|
@@ -42,6 +42,8 @@ __export(share_root_entry_exports, {
|
|
|
42
42
|
ownerRootCacaoCid: () => ownerRootCacaoCid,
|
|
43
43
|
perShareNetworkIdFor: () => perShareNetworkIdFor,
|
|
44
44
|
planShareControlBatches: () => planShareControlBatches,
|
|
45
|
+
publishRootBearerLink: () => publishRootBearerLink,
|
|
46
|
+
revokeRootBearerLink: () => revokeRootBearerLink,
|
|
45
47
|
revokeShareGrant: () => revokeShareGrant,
|
|
46
48
|
runShareControlBatch: () => runShareControlBatch,
|
|
47
49
|
signShareKeyDelegation: () => signShareKeyDelegation
|
|
@@ -6976,6 +6978,35 @@ var ShareRoot = class _ShareRoot {
|
|
|
6976
6978
|
covers(expiresAt, now = this.#now()) {
|
|
6977
6979
|
return this.#key !== void 0 && now < this.expiresAt.getTime() && expiresAt.getTime() <= this.expiresAt.getTime();
|
|
6978
6980
|
}
|
|
6981
|
+
/**
|
|
6982
|
+
* Sign a 60-second `POST /revoke` invocation, by the share key, for one
|
|
6983
|
+
* delegation this root issued (a bearer link). Zero approvals. The Node
|
|
6984
|
+
* authorizes it because the share key is that delegation's delegator. The
|
|
6985
|
+
* root itself is never revoked this way: only the owner does that.
|
|
6986
|
+
*/
|
|
6987
|
+
async signLinkRevocation(input) {
|
|
6988
|
+
const key = this.#activeKey();
|
|
6989
|
+
if (typeof input.delegationCid !== "string" || !/^b[a-z2-7]+$/.test(input.delegationCid)) throw new ShareRootError("invalid-request", "delegation CID is invalid");
|
|
6990
|
+
if (input.delegationCid === this.cid) throw new ShareRootError("invalid-request", "the share key does not revoke its own root; the owner does");
|
|
6991
|
+
try {
|
|
6992
|
+
ed25519PublicKeyFromDidKey(input.nodeDid);
|
|
6993
|
+
} catch {
|
|
6994
|
+
throw new ShareRootError("invalid-request", "node DID must be an Ed25519 did:key");
|
|
6995
|
+
}
|
|
6996
|
+
const now = seconds(this.#now());
|
|
6997
|
+
const revocation = await signCompactUcanAuthorization({
|
|
6998
|
+
issuerDid: key.did,
|
|
6999
|
+
audienceDid: input.nodeDid,
|
|
7000
|
+
attenuation: { [`urn:cid:${input.delegationCid}`]: { "tinycloud.delegation/revoke": [{}] } },
|
|
7001
|
+
facts: [{}],
|
|
7002
|
+
proofs: [],
|
|
7003
|
+
notBefore: now,
|
|
7004
|
+
expiresAt: now + 60,
|
|
7005
|
+
nonce: `urn:uuid:${crypto.randomUUID()}`,
|
|
7006
|
+
sign: (bytes2) => key.sign(bytes2)
|
|
7007
|
+
});
|
|
7008
|
+
return revocation.authorization;
|
|
7009
|
+
}
|
|
6979
7010
|
/**
|
|
6980
7011
|
* Sign a bearer link: `kv/get` on one exact key under the prefix, to the
|
|
6981
7012
|
* link's own key, with this root as its only proof. It never outlives the
|
|
@@ -7758,6 +7789,69 @@ async function runShareControlBatch(input) {
|
|
|
7758
7789
|
key.clear();
|
|
7759
7790
|
}
|
|
7760
7791
|
}
|
|
7792
|
+
|
|
7793
|
+
// src/share-root-link.ts
|
|
7794
|
+
var import_ed255196 = require("@noble/curves/ed25519");
|
|
7795
|
+
|
|
7796
|
+
// src/native.ts
|
|
7797
|
+
var NATIVE_SHARE_FRAGMENT_PARAMETER = "tc1";
|
|
7798
|
+
function canonicalViewerUrl(viewerOrigin) {
|
|
7799
|
+
const url = new URL(viewerOrigin);
|
|
7800
|
+
if (url.protocol !== "https:" || url.origin !== viewerOrigin || url.pathname !== "/" || url.search || url.hash) throw new TypeError("viewer origin must be a canonical HTTPS origin");
|
|
7801
|
+
url.pathname = "/viewer";
|
|
7802
|
+
return url;
|
|
7803
|
+
}
|
|
7804
|
+
|
|
7805
|
+
// src/share-root-link.ts
|
|
7806
|
+
async function publishRootBearerLink(input) {
|
|
7807
|
+
const fetchFn = input.fetch ?? ((url, init) => globalThis.fetch(url, init));
|
|
7808
|
+
const viewerUrl = canonicalViewerUrl(input.viewerOrigin);
|
|
7809
|
+
const secret = import_ed255196.ed25519.utils.randomPrivateKey();
|
|
7810
|
+
try {
|
|
7811
|
+
const publicKey = import_ed255196.ed25519.getPublicKey(secret);
|
|
7812
|
+
const linkDid = didKeyFromEd25519PublicKey(publicKey);
|
|
7813
|
+
const link = await input.root.signBearerLink({ linkDid, path: input.path, expiresAt: input.expiresAt });
|
|
7814
|
+
const response = await fetchFn(new URL("/delegate", input.root.nodeOrigin), { method: "POST", redirect: "error", headers: { Authorization: link.delegation.authorization } });
|
|
7815
|
+
if (!response.ok) throw new ShareRootError("node-refused", `the Node refused the link delegation: HTTP ${response.status} ${(await response.text()).slice(0, 120)}`, { rootCid: input.root.cid });
|
|
7816
|
+
const createdAt = /* @__PURE__ */ new Date();
|
|
7817
|
+
const shareData = {
|
|
7818
|
+
key: { kty: "OKP", crv: "Ed25519", x: toBase64Url(publicKey), d: toBase64Url(secret) },
|
|
7819
|
+
keyDid: `${linkDid}#${linkDid.slice("did:key:".length)}`,
|
|
7820
|
+
delegation: {
|
|
7821
|
+
cid: link.delegation.cid,
|
|
7822
|
+
delegateDID: linkDid,
|
|
7823
|
+
delegatorDID: input.root.keyDid,
|
|
7824
|
+
spaceId: input.root.spaceId,
|
|
7825
|
+
path: input.path,
|
|
7826
|
+
actions: ["tinycloud.kv/get"],
|
|
7827
|
+
expiry: link.expiresAt,
|
|
7828
|
+
isRevoked: false,
|
|
7829
|
+
allowSubDelegation: true,
|
|
7830
|
+
createdAt,
|
|
7831
|
+
parentCid: input.root.cid,
|
|
7832
|
+
authHeader: link.delegation.authorization
|
|
7833
|
+
},
|
|
7834
|
+
path: input.path,
|
|
7835
|
+
host: input.root.nodeOrigin,
|
|
7836
|
+
spaceId: input.root.spaceId,
|
|
7837
|
+
version: 1
|
|
7838
|
+
};
|
|
7839
|
+
const token = `tc1:${toBase64Url(new TextEncoder().encode(JSON.stringify(shareData)))}`;
|
|
7840
|
+
viewerUrl.hash = `${NATIVE_SHARE_FRAGMENT_PARAMETER}=${encodeURIComponent(token)}`;
|
|
7841
|
+
return { url: viewerUrl.toString(), delegationCid: link.delegation.cid, rootCid: input.root.cid, spaceId: input.root.spaceId, path: input.path, expiresAt: link.expiresAt };
|
|
7842
|
+
} finally {
|
|
7843
|
+
secret.fill(0);
|
|
7844
|
+
}
|
|
7845
|
+
}
|
|
7846
|
+
async function revokeRootBearerLink(input) {
|
|
7847
|
+
const fetchFn = input.fetch ?? ((url, init) => globalThis.fetch(url, init));
|
|
7848
|
+
const nodeDid = await nodeDidOf(input.root.nodeOrigin, fetchFn);
|
|
7849
|
+
const authorization = await input.root.signLinkRevocation({ delegationCid: input.delegationCid, nodeDid });
|
|
7850
|
+
const response = await fetchFn(new URL("/revoke", input.root.nodeOrigin), { method: "POST", redirect: "error", headers: { Authorization: authorization } });
|
|
7851
|
+
if (!response.ok) throw new ShareRootError("node-refused", `the Node refused the link revocation: HTTP ${response.status} ${(await response.text()).slice(0, 120)}`, { rootCid: input.root.cid });
|
|
7852
|
+
if (!await isRevokeReceiptFor(response, input.delegationCid)) throw new ShareRootError("invalid-request", "link revocation receipt does not confirm this delegation");
|
|
7853
|
+
return { revoked: true, cid: input.delegationCid };
|
|
7854
|
+
}
|
|
7761
7855
|
// Annotate the CommonJS export names for ESM import in node:
|
|
7762
7856
|
0 && (module.exports = {
|
|
7763
7857
|
AGENT_SHARE_ROOT_MAX_LIFETIME_MS,
|
|
@@ -7782,6 +7876,8 @@ async function runShareControlBatch(input) {
|
|
|
7782
7876
|
ownerRootCacaoCid,
|
|
7783
7877
|
perShareNetworkIdFor,
|
|
7784
7878
|
planShareControlBatches,
|
|
7879
|
+
publishRootBearerLink,
|
|
7880
|
+
revokeRootBearerLink,
|
|
7785
7881
|
revokeShareGrant,
|
|
7786
7882
|
runShareControlBatch,
|
|
7787
7883
|
signShareKeyDelegation
|