@tinycloud/operations 0.3.4-beta.6 → 0.4.0-beta.7
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/artifacts.cjs +10 -2
- package/dist/artifacts.cjs.map +1 -1
- package/dist/artifacts.d.cts +115 -58
- package/dist/artifacts.d.ts +115 -58
- package/dist/artifacts.js +9 -2
- package/dist/artifacts.js.map +1 -1
- package/dist/authority-ofwbEqmj.d.cts +30 -0
- package/dist/authority-ofwbEqmj.d.ts +30 -0
- package/dist/cli-runtime.cjs +249 -71
- package/dist/cli-runtime.cjs.map +1 -1
- package/dist/cli-runtime.js +240 -67
- package/dist/cli-runtime.js.map +1 -1
- package/dist/delegation-binding.cjs +7598 -0
- package/dist/delegation-binding.cjs.map +1 -0
- package/dist/delegation-binding.d.cts +130 -0
- package/dist/delegation-binding.d.ts +130 -0
- package/dist/delegation-binding.js +7588 -0
- package/dist/delegation-binding.js.map +1 -0
- package/dist/index.cjs +246 -68
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +240 -67
- package/dist/index.js.map +1 -1
- package/dist/profile.cjs +7 -2
- package/dist/profile.cjs.map +1 -1
- package/dist/profile.js +7 -2
- package/dist/profile.js.map +1 -1
- package/dist/state.cjs +7 -2
- package/dist/state.cjs.map +1 -1
- package/dist/state.js +7 -2
- package/dist/state.js.map +1 -1
- package/generated/operations.json +8 -4
- package/package.json +8 -3
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { PermissionEntry } from '@tinycloud/sdk-core';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* A capability in the canonical form persisted in a v1 request artifact.
|
|
5
|
+
*
|
|
6
|
+
* The SDK remains the semantic authority for containment. This module only
|
|
7
|
+
* establishes deterministic exact identity for persistence and display.
|
|
8
|
+
*/
|
|
9
|
+
type CanonicalPermissionEntry = Readonly<PermissionEntry>;
|
|
10
|
+
interface AuthorityEvaluation {
|
|
11
|
+
readonly satisfied: boolean;
|
|
12
|
+
readonly missing: readonly CanonicalPermissionEntry[];
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Operation-owned space resolution. The SDK's general capability evaluator
|
|
16
|
+
* intentionally preserves its historical short/full-space compatibility; the
|
|
17
|
+
* operation kernel supplies this narrower resolver when a space identifies a
|
|
18
|
+
* remote owner's resource.
|
|
19
|
+
*/
|
|
20
|
+
type OperationSpaceResolver = (space: string) => string;
|
|
21
|
+
/**
|
|
22
|
+
* Evaluates required authority with the SDK's public subset primitive.
|
|
23
|
+
*
|
|
24
|
+
* In particular, this intentionally does not implement matching rules or
|
|
25
|
+
* manufacture wildcards. A wildcard can cover a requirement only when it was
|
|
26
|
+
* already present in the supplied granted authority and the SDK says so.
|
|
27
|
+
*/
|
|
28
|
+
declare function evaluateAuthority(granted: readonly PermissionEntry[], required: readonly PermissionEntry[]): AuthorityEvaluation;
|
|
29
|
+
|
|
30
|
+
export { type OperationSpaceResolver as O, evaluateAuthority as e };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { PermissionEntry } from '@tinycloud/sdk-core';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* A capability in the canonical form persisted in a v1 request artifact.
|
|
5
|
+
*
|
|
6
|
+
* The SDK remains the semantic authority for containment. This module only
|
|
7
|
+
* establishes deterministic exact identity for persistence and display.
|
|
8
|
+
*/
|
|
9
|
+
type CanonicalPermissionEntry = Readonly<PermissionEntry>;
|
|
10
|
+
interface AuthorityEvaluation {
|
|
11
|
+
readonly satisfied: boolean;
|
|
12
|
+
readonly missing: readonly CanonicalPermissionEntry[];
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Operation-owned space resolution. The SDK's general capability evaluator
|
|
16
|
+
* intentionally preserves its historical short/full-space compatibility; the
|
|
17
|
+
* operation kernel supplies this narrower resolver when a space identifies a
|
|
18
|
+
* remote owner's resource.
|
|
19
|
+
*/
|
|
20
|
+
type OperationSpaceResolver = (space: string) => string;
|
|
21
|
+
/**
|
|
22
|
+
* Evaluates required authority with the SDK's public subset primitive.
|
|
23
|
+
*
|
|
24
|
+
* In particular, this intentionally does not implement matching rules or
|
|
25
|
+
* manufacture wildcards. A wildcard can cover a requirement only when it was
|
|
26
|
+
* already present in the supplied granted authority and the SDK says so.
|
|
27
|
+
*/
|
|
28
|
+
declare function evaluateAuthority(granted: readonly PermissionEntry[], required: readonly PermissionEntry[]): AuthorityEvaluation;
|
|
29
|
+
|
|
30
|
+
export { type OperationSpaceResolver as O, evaluateAuthority as e };
|
package/dist/cli-runtime.cjs
CHANGED
|
@@ -6967,6 +6967,9 @@ function evaluateOperationAuthority(granted, required, resolveSpace2) {
|
|
|
6967
6967
|
missing: canonicalizeCapabilities(missing)
|
|
6968
6968
|
};
|
|
6969
6969
|
}
|
|
6970
|
+
function delegationWithinRequest(requested, effective, resolveSpace2) {
|
|
6971
|
+
return requested.length > 0 && evaluateOperationAuthority(requested, canonicalizeCapabilities(effective), resolveSpace2).satisfied;
|
|
6972
|
+
}
|
|
6970
6973
|
function isExactCapabilityMemberSubset(hinted, planned, resolveSpace2) {
|
|
6971
6974
|
const canonicalHinted = canonicalizeOperationCapabilities(hinted, resolveSpace2);
|
|
6972
6975
|
const canonicalPlanned = canonicalizeOperationCapabilities(planned, resolveSpace2);
|
|
@@ -7079,6 +7082,11 @@ var init_authority = __esm({
|
|
|
7079
7082
|
});
|
|
7080
7083
|
|
|
7081
7084
|
// src/state.ts
|
|
7085
|
+
function processWideContext(key) {
|
|
7086
|
+
var _a;
|
|
7087
|
+
const registry = globalThis;
|
|
7088
|
+
return registry[_a = Symbol.for(key)] ?? (registry[_a] = new import_node_async_hooks.AsyncLocalStorage());
|
|
7089
|
+
}
|
|
7082
7090
|
function tinycloudHomePath() {
|
|
7083
7091
|
const home = invocationStateRoot.getStore() ?? process.env.TC_HOME ?? process.env.HOME ?? process.env.USERPROFILE ?? (0, import_node_os.homedir)();
|
|
7084
7092
|
return (0, import_node_path.join)(home, ".tinycloud");
|
|
@@ -7418,8 +7426,8 @@ var init_state = __esm({
|
|
|
7418
7426
|
TEST_LOCK_CLAIMED_BARRIER_DIR = "TC_TEST_PROFILE_LOCK_CLAIMED_BARRIER_DIR";
|
|
7419
7427
|
TEST_LOCK_FENCED_BARRIER_DIR = "TC_TEST_PROFILE_LOCK_FENCED_BARRIER_DIR";
|
|
7420
7428
|
TEST_LOCK_VERIFIED_BARRIER_DIR = "TC_TEST_PROFILE_LOCK_VERIFIED_BARRIER_DIR";
|
|
7421
|
-
invocationStateRoot =
|
|
7422
|
-
heldProfileLocks =
|
|
7429
|
+
invocationStateRoot = processWideContext("tinycloud.operations.invocationStateRoot.v1");
|
|
7430
|
+
heldProfileLocks = processWideContext("tinycloud.operations.heldProfileLocks.v1");
|
|
7423
7431
|
ProfileLockTimeoutError = class extends Error {
|
|
7424
7432
|
constructor(profile, timeoutMs) {
|
|
7425
7433
|
super(`Timed out waiting for the profile lock for "${profile}" after ${timeoutMs}ms.`);
|
|
@@ -7634,7 +7642,7 @@ function evaluateArtifactAuthority(granted, required, resolveSpace2) {
|
|
|
7634
7642
|
function defaultRequestId(now) {
|
|
7635
7643
|
return `req_${now.getTime().toString(36)}_${(0, import_node_crypto2.randomUUID)().replace(/-/g, "")}`;
|
|
7636
7644
|
}
|
|
7637
|
-
var import_node_crypto2, import_zod2, THIRTY_DAYS_MS, PermissionEntrySchema, CommandSchema, LegacyPermissionRequestArtifactSchema, PortableDelegationSchema, PermissionRequestArtifactSchema, DelegationImportArtifactSchema;
|
|
7645
|
+
var import_node_crypto2, import_zod2, THIRTY_DAYS_MS, PermissionEntrySchema, CommandSchema, LegacyPermissionRequestArtifactSchema, PortableDelegationSchema, PermissionRequestArtifactSchema, DelegationImportArtifactSchema, DelegationRequestBindingSchema;
|
|
7638
7646
|
var init_artifacts = __esm({
|
|
7639
7647
|
"src/artifacts.ts"() {
|
|
7640
7648
|
"use strict";
|
|
@@ -7709,6 +7717,7 @@ var init_artifacts = __esm({
|
|
|
7709
7717
|
expiry: import_zod2.z.string().datetime({ offset: true }).optional(),
|
|
7710
7718
|
prompted: import_zod2.z.boolean().optional()
|
|
7711
7719
|
}).strict();
|
|
7720
|
+
DelegationRequestBindingSchema = PermissionRequestArtifactSchema.pick({ requestId: true, requested: true }).strict();
|
|
7712
7721
|
}
|
|
7713
7722
|
});
|
|
7714
7723
|
|
|
@@ -7768,18 +7777,18 @@ function resolveOperationSpace(space, node, ownerSpace) {
|
|
|
7768
7777
|
if (resolved !== void 0) return canonicalizeSpaceUri(resolved);
|
|
7769
7778
|
}
|
|
7770
7779
|
const did = typeof candidate.did === "string" ? candidate.did : void 0;
|
|
7771
|
-
const pkh = did === void 0 ? null :
|
|
7780
|
+
const pkh = did === void 0 ? null : nodeSdk.parsePkhDid(did);
|
|
7772
7781
|
if (pkh === null) {
|
|
7773
7782
|
throw invalidSecretInput();
|
|
7774
7783
|
}
|
|
7775
|
-
return
|
|
7784
|
+
return nodeSdk.makePkhSpaceId(pkh.address, pkh.chainId, space);
|
|
7776
7785
|
}
|
|
7777
7786
|
function ownedSpaceForName(ownerSpace, name) {
|
|
7778
|
-
const parsed =
|
|
7787
|
+
const parsed = nodeSdk.parseSpaceUri(ownerSpace);
|
|
7779
7788
|
if (parsed === null) return void 0;
|
|
7780
7789
|
try {
|
|
7781
|
-
const pkh =
|
|
7782
|
-
return pkh === null ? void 0 :
|
|
7790
|
+
const pkh = nodeSdk.parsePkhDid(parsed.owner);
|
|
7791
|
+
return pkh === null ? void 0 : nodeSdk.makePkhSpaceId(pkh.address, pkh.chainId, name);
|
|
7783
7792
|
} catch {
|
|
7784
7793
|
return void 0;
|
|
7785
7794
|
}
|
|
@@ -7794,7 +7803,7 @@ function canonicalizeSpaceUri(space) {
|
|
|
7794
7803
|
/^tinycloud:pkh:eip155:(\d+):(0x[0-9a-fA-F]{40}):([^:]+)$/
|
|
7795
7804
|
);
|
|
7796
7805
|
if (pkh !== null) {
|
|
7797
|
-
return `tinycloud:pkh:eip155:${pkh[1]}:${
|
|
7806
|
+
return `tinycloud:pkh:eip155:${pkh[1]}:${nodeSdk.canonicalizeAddress(pkh[2]).toLowerCase()}:${pkh[3]}`;
|
|
7798
7807
|
}
|
|
7799
7808
|
return space;
|
|
7800
7809
|
}
|
|
@@ -7834,11 +7843,11 @@ function invalidSecretInput() {
|
|
|
7834
7843
|
operationError("INPUT_INVALID", "The secret reference is invalid.")
|
|
7835
7844
|
);
|
|
7836
7845
|
}
|
|
7837
|
-
var
|
|
7846
|
+
var nodeSdk, DEFAULT_SECRETS_SPACE, SECRET_MANAGER_BASE_URL, SECRET_NAME_RE2, RESERVED_SECRET_SCOPES;
|
|
7838
7847
|
var init_secrets = __esm({
|
|
7839
7848
|
"src/secrets.ts"() {
|
|
7840
7849
|
"use strict";
|
|
7841
|
-
|
|
7850
|
+
nodeSdk = __toESM(require("@tinycloud/node-sdk"), 1);
|
|
7842
7851
|
init_errors();
|
|
7843
7852
|
DEFAULT_SECRETS_SPACE = "secrets";
|
|
7844
7853
|
SECRET_MANAGER_BASE_URL = "https://secrets.tinycloud.xyz";
|
|
@@ -7991,7 +8000,7 @@ async function importRequestBoundDelegation(context, input) {
|
|
|
7991
8000
|
};
|
|
7992
8001
|
let activated;
|
|
7993
8002
|
try {
|
|
7994
|
-
activated = await
|
|
8003
|
+
activated = await nodeSdk2.activateValidatedRuntimeDelegation(
|
|
7995
8004
|
context.runtime.node,
|
|
7996
8005
|
delegation,
|
|
7997
8006
|
{ host }
|
|
@@ -8007,11 +8016,7 @@ async function importRequestBoundDelegation(context, input) {
|
|
|
8007
8016
|
context.runtime.node,
|
|
8008
8017
|
context.summary.space
|
|
8009
8018
|
);
|
|
8010
|
-
if (request.requested
|
|
8011
|
-
request.requested,
|
|
8012
|
-
effectivePermissions,
|
|
8013
|
-
resolveSpace2
|
|
8014
|
-
).satisfied) {
|
|
8019
|
+
if (!delegationWithinRequest(request.requested, effectivePermissions, resolveSpace2)) {
|
|
8015
8020
|
return operationFailure(
|
|
8016
8021
|
"DELEGATION_REJECTED",
|
|
8017
8022
|
"The delegation exceeds the stored authority request."
|
|
@@ -8039,12 +8044,19 @@ async function importRequestBoundDelegation(context, input) {
|
|
|
8039
8044
|
)
|
|
8040
8045
|
};
|
|
8041
8046
|
}
|
|
8042
|
-
const
|
|
8047
|
+
const record = {
|
|
8048
|
+
delegation: activated.delegation,
|
|
8049
|
+
permissions: activated.effectivePermissions,
|
|
8050
|
+
authorityRequest: {
|
|
8051
|
+
requestId: request.requestId,
|
|
8052
|
+
requested: request.requested
|
|
8053
|
+
}
|
|
8054
|
+
};
|
|
8055
|
+
const position = records.findIndex((entry) => delegationCid(entry) === activated.cid);
|
|
8056
|
+
const alreadyPresent = position !== -1;
|
|
8057
|
+
const others = records.filter((entry) => delegationCid(entry) !== activated.cid);
|
|
8043
8058
|
return {
|
|
8044
|
-
records: alreadyPresent ?
|
|
8045
|
-
delegation: activated.delegation,
|
|
8046
|
-
permissions: activated.effectivePermissions
|
|
8047
|
-
}],
|
|
8059
|
+
records: alreadyPresent ? [...others.slice(0, position), record, ...others.slice(position)] : [...records, record],
|
|
8048
8060
|
result: {
|
|
8049
8061
|
status: "ok",
|
|
8050
8062
|
output: {
|
|
@@ -8173,11 +8185,11 @@ function internalImportFailure() {
|
|
|
8173
8185
|
function operationFailure(code, message, details) {
|
|
8174
8186
|
return { status: "error", error: operationError(code, message, { ...details === void 0 ? {} : { details } }) };
|
|
8175
8187
|
}
|
|
8176
|
-
var
|
|
8188
|
+
var nodeSdk2, import_zod3, EmptyInputSchema, CapabilitiesOutputSchema, AuthRequestInputSchema, PermissionRequestOutputSchema, AuthRequestOutputSchema, AuthImportOutputSchema, AUTH_POSTURES, AUTH_EXPOSURE, AUTH_CAPABILITIES_SENSITIVITY, AUTH_REQUEST_SENSITIVITY, AUTH_IMPORT_SENSITIVITY, authOperationDefinitions;
|
|
8177
8189
|
var init_auth = __esm({
|
|
8178
8190
|
"src/operations/auth.ts"() {
|
|
8179
8191
|
"use strict";
|
|
8180
|
-
|
|
8192
|
+
nodeSdk2 = __toESM(require("@tinycloud/node-sdk"), 1);
|
|
8181
8193
|
import_zod3 = require("zod");
|
|
8182
8194
|
init_authority();
|
|
8183
8195
|
init_artifacts();
|
|
@@ -9774,6 +9786,173 @@ ORDER BY type, name`;
|
|
|
9774
9786
|
}
|
|
9775
9787
|
});
|
|
9776
9788
|
|
|
9789
|
+
// src/delegation-binding.ts
|
|
9790
|
+
function bindingMigrationPath(profile) {
|
|
9791
|
+
return (0, import_node_path2.join)(profilePath(profile), "delegation-binding-migration.json");
|
|
9792
|
+
}
|
|
9793
|
+
function storedDelegationKind(entry) {
|
|
9794
|
+
if (!isRecord4(entry)) return "refused";
|
|
9795
|
+
const delegation = entry.delegation;
|
|
9796
|
+
if (!isRecord4(delegation)) return "refused";
|
|
9797
|
+
const header = delegation.delegationHeader;
|
|
9798
|
+
if (!isRecord4(header) || Object.keys(header).length !== 1 || !Object.prototype.hasOwnProperty.call(header, "Authorization") || typeof header.Authorization !== "string") {
|
|
9799
|
+
return "refused";
|
|
9800
|
+
}
|
|
9801
|
+
if ("siweProof" in delegation) return "signed-login";
|
|
9802
|
+
if (header.Authorization.includes(".")) return "compact";
|
|
9803
|
+
return "authorityRequest" in entry ? "refused" : "other";
|
|
9804
|
+
}
|
|
9805
|
+
function replayLimit(entry, migrated) {
|
|
9806
|
+
const kind = storedDelegationKind(entry);
|
|
9807
|
+
if (!isRecord4(entry) || kind !== "compact" && kind !== "signed-login") return void 0;
|
|
9808
|
+
const binding = DelegationRequestBindingSchema.safeParse(entry.authorityRequest);
|
|
9809
|
+
if (binding.success) return binding.data.requested;
|
|
9810
|
+
return !migrated && kind === "compact" && !("authorityRequest" in entry) ? "signed" : void 0;
|
|
9811
|
+
}
|
|
9812
|
+
function bindToSignedCapabilities(record, signed, source, recordedAt = (/* @__PURE__ */ new Date()).toISOString()) {
|
|
9813
|
+
return {
|
|
9814
|
+
...record,
|
|
9815
|
+
authorityRequest: DelegationRequestBindingSchema.parse({
|
|
9816
|
+
requestId: `${REQUEST_ID_PREFIX[source]}:${record.delegation.cid}`,
|
|
9817
|
+
requested: structuredClone(signed)
|
|
9818
|
+
}),
|
|
9819
|
+
authorityRequestAudit: { source, recordedAt, note: BINDING_NOTES[source] }
|
|
9820
|
+
};
|
|
9821
|
+
}
|
|
9822
|
+
async function prepareStoredDelegationReplay(profile, node, options) {
|
|
9823
|
+
if (await bindingMigrationRecorded(profile)) return true;
|
|
9824
|
+
if (!options.migrate || !await holdsPersistedSession(profile, node)) return false;
|
|
9825
|
+
try {
|
|
9826
|
+
return await withProfileLock(profile, async () => {
|
|
9827
|
+
if (await bindingMigrationRecorded(profile)) return true;
|
|
9828
|
+
if (!await holdsPersistedSession(profile, node)) return false;
|
|
9829
|
+
const recordedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
9830
|
+
const bound = /* @__PURE__ */ new Map();
|
|
9831
|
+
const unbound = [];
|
|
9832
|
+
for (const entry of await readAdditionalDelegations(profile)) {
|
|
9833
|
+
if (!isRecord4(entry) || "authorityRequest" in entry || storedDelegationKind(entry) !== "compact") continue;
|
|
9834
|
+
const migrated = await migratedRecord(node, entry, options.host, recordedAt);
|
|
9835
|
+
if (migrated === void 0) unbound.push(String(storedCid(entry)));
|
|
9836
|
+
else bound.set(recordKey(entry), migrated);
|
|
9837
|
+
}
|
|
9838
|
+
if (bound.size > 0) {
|
|
9839
|
+
await updateProfileStore(profile, "additional-delegations", (records) => ({
|
|
9840
|
+
records: records.map((entry) => {
|
|
9841
|
+
const key = !isRecord4(entry) || "authorityRequest" in entry ? void 0 : recordKey(entry);
|
|
9842
|
+
return (key === void 0 ? void 0 : bound.get(key)) ?? entry;
|
|
9843
|
+
}),
|
|
9844
|
+
result: void 0
|
|
9845
|
+
}));
|
|
9846
|
+
}
|
|
9847
|
+
await writeJsonAtomic(bindingMigrationPath(profile), {
|
|
9848
|
+
formatVersion: 1,
|
|
9849
|
+
migratedAt: recordedAt,
|
|
9850
|
+
bound: [...bound.values()].map(storedCid),
|
|
9851
|
+
unbound
|
|
9852
|
+
});
|
|
9853
|
+
return true;
|
|
9854
|
+
}, { timeoutMs: MIGRATION_LOCK_TIMEOUT_MS });
|
|
9855
|
+
} catch {
|
|
9856
|
+
return false;
|
|
9857
|
+
}
|
|
9858
|
+
}
|
|
9859
|
+
async function holdsPersistedSession(profile, node) {
|
|
9860
|
+
try {
|
|
9861
|
+
const persisted = await readSession(profile);
|
|
9862
|
+
return typeof persisted?.verificationMethod === "string" && typeof node.sessionDid === "string" && persisted.verificationMethod.split("#", 1)[0] === node.sessionDid.split("#", 1)[0];
|
|
9863
|
+
} catch {
|
|
9864
|
+
return false;
|
|
9865
|
+
}
|
|
9866
|
+
}
|
|
9867
|
+
async function migratedRecord(node, entry, host, recordedAt) {
|
|
9868
|
+
const delegation = normalizeStoredDelegation(entry);
|
|
9869
|
+
if (delegation === void 0) return void 0;
|
|
9870
|
+
const signed = await signedCapabilities(node, delegation, host);
|
|
9871
|
+
if (signed === void 0) return void 0;
|
|
9872
|
+
try {
|
|
9873
|
+
return bindToSignedCapabilities({ ...entry, delegation: { ...entry.delegation, cid: delegation.cid } }, signed, "migration", recordedAt);
|
|
9874
|
+
} catch {
|
|
9875
|
+
return void 0;
|
|
9876
|
+
}
|
|
9877
|
+
}
|
|
9878
|
+
async function replayStoredDelegation(node, entry, options) {
|
|
9879
|
+
const delegation = normalizeStoredDelegation(entry);
|
|
9880
|
+
if (delegation === void 0 || delegation.expiry.getTime() <= Date.now()) return void 0;
|
|
9881
|
+
const limit = replayLimit(entry, options.migrated);
|
|
9882
|
+
if (limit === void 0) return void 0;
|
|
9883
|
+
const authorize = limit === "signed" ? () => true : (effective) => delegationWithinRequest(limit, effective, options.resolveSpace);
|
|
9884
|
+
try {
|
|
9885
|
+
return await nodeSdk3.activateValidatedRuntimeDelegation(node, delegation, { host: options.host, authorize });
|
|
9886
|
+
} catch {
|
|
9887
|
+
return void 0;
|
|
9888
|
+
}
|
|
9889
|
+
}
|
|
9890
|
+
async function bindingMigrationRecorded(profile) {
|
|
9891
|
+
try {
|
|
9892
|
+
return await readJson(bindingMigrationPath(profile)) !== null;
|
|
9893
|
+
} catch {
|
|
9894
|
+
return true;
|
|
9895
|
+
}
|
|
9896
|
+
}
|
|
9897
|
+
async function signedCapabilities(node, delegation, host) {
|
|
9898
|
+
let signed;
|
|
9899
|
+
try {
|
|
9900
|
+
await nodeSdk3.activateValidatedRuntimeDelegation(node, delegation, {
|
|
9901
|
+
// The transport host is not signed authority; check it at replay instead.
|
|
9902
|
+
host: delegation.host ?? host,
|
|
9903
|
+
authorize: (effective) => {
|
|
9904
|
+
signed = effective;
|
|
9905
|
+
return false;
|
|
9906
|
+
}
|
|
9907
|
+
});
|
|
9908
|
+
} catch {
|
|
9909
|
+
}
|
|
9910
|
+
return signed;
|
|
9911
|
+
}
|
|
9912
|
+
function normalizeStoredDelegation(entry) {
|
|
9913
|
+
if (!isRecord4(entry)) return void 0;
|
|
9914
|
+
const raw = entry.delegation;
|
|
9915
|
+
if (!isRecord4(raw) || !isRecord4(raw.delegationHeader)) return void 0;
|
|
9916
|
+
const expiry = raw.expiry instanceof Date ? raw.expiry : typeof raw.expiry === "string" ? new Date(raw.expiry) : void 0;
|
|
9917
|
+
if (expiry === void 0 || Number.isNaN(expiry.getTime()) || typeof raw.cid !== "string" || typeof raw.spaceId !== "string" || typeof raw.path !== "string" || !Array.isArray(raw.actions) || !raw.actions.every((action) => typeof action === "string") || typeof raw.delegateDID !== "string" || typeof raw.ownerAddress !== "string" || typeof raw.chainId !== "number" || typeof raw.delegationHeader.Authorization !== "string") {
|
|
9918
|
+
return void 0;
|
|
9919
|
+
}
|
|
9920
|
+
return { ...raw, expiry };
|
|
9921
|
+
}
|
|
9922
|
+
function storedCid(entry) {
|
|
9923
|
+
const cid = isRecord4(entry) && isRecord4(entry.delegation) ? entry.delegation.cid : void 0;
|
|
9924
|
+
return typeof cid === "string" ? cid : void 0;
|
|
9925
|
+
}
|
|
9926
|
+
function recordKey(entry) {
|
|
9927
|
+
const delegation = entry.delegation;
|
|
9928
|
+
if (!isRecord4(delegation) || !isRecord4(delegation.delegationHeader)) return void 0;
|
|
9929
|
+
return JSON.stringify([delegation.cid, delegation.delegationHeader.Authorization]);
|
|
9930
|
+
}
|
|
9931
|
+
function isRecord4(value) {
|
|
9932
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
9933
|
+
}
|
|
9934
|
+
var import_node_path2, nodeSdk3, REQUEST_ID_PREFIX, BINDING_NOTES, MIGRATION_LOCK_TIMEOUT_MS;
|
|
9935
|
+
var init_delegation_binding = __esm({
|
|
9936
|
+
"src/delegation-binding.ts"() {
|
|
9937
|
+
"use strict";
|
|
9938
|
+
import_node_path2 = require("path");
|
|
9939
|
+
nodeSdk3 = __toESM(require("@tinycloud/node-sdk"), 1);
|
|
9940
|
+
init_artifacts();
|
|
9941
|
+
init_authority();
|
|
9942
|
+
init_state();
|
|
9943
|
+
init_secrets();
|
|
9944
|
+
REQUEST_ID_PREFIX = {
|
|
9945
|
+
migration: "migrated",
|
|
9946
|
+
"unbound-import": "unbound-import"
|
|
9947
|
+
};
|
|
9948
|
+
BINDING_NOTES = {
|
|
9949
|
+
migration: "Stored without a request binding before bindings were required. Bound at migration to exactly its own signed capabilities, so replay refuses any delegation in this record that exceeds them.",
|
|
9950
|
+
"unbound-import": "Imported by `tc auth import` without a stored request. Bound to exactly its own signed capabilities, so replay refuses any delegation in this record that exceeds them."
|
|
9951
|
+
};
|
|
9952
|
+
MIGRATION_LOCK_TIMEOUT_MS = 250;
|
|
9953
|
+
}
|
|
9954
|
+
});
|
|
9955
|
+
|
|
9777
9956
|
// src/operations/status.ts
|
|
9778
9957
|
function createStatusDefinition(params) {
|
|
9779
9958
|
return {
|
|
@@ -9829,7 +10008,7 @@ async function inspectPinnedProfileStatus(context, _input) {
|
|
|
9829
10008
|
async function pinnedProfileExists(profile) {
|
|
9830
10009
|
try {
|
|
9831
10010
|
const storedProfile = await readProfile(profile);
|
|
9832
|
-
return
|
|
10011
|
+
return isRecord5(storedProfile);
|
|
9833
10012
|
} catch {
|
|
9834
10013
|
return false;
|
|
9835
10014
|
}
|
|
@@ -9840,16 +10019,18 @@ async function countLiveAdditionalDelegations(profile) {
|
|
|
9840
10019
|
if (rawDelegations === null) return 0;
|
|
9841
10020
|
if (!Array.isArray(rawDelegations)) throw new TypeError("Invalid additional delegation store.");
|
|
9842
10021
|
const now = Date.now();
|
|
10022
|
+
const migrated = await bindingMigrationRecorded(profile);
|
|
9843
10023
|
let count = 0;
|
|
9844
10024
|
for (const entry of rawDelegations) {
|
|
10025
|
+
if (storedDelegationKind(entry) === "refused") continue;
|
|
9845
10026
|
const expiry = storedDelegationExpiry(entry);
|
|
9846
|
-
if (expiry.getTime() > now) count += 1;
|
|
10027
|
+
if (expiry.getTime() > now && replayLimit(entry, migrated) !== void 0) count += 1;
|
|
9847
10028
|
}
|
|
9848
10029
|
return count;
|
|
9849
10030
|
}
|
|
9850
10031
|
function summarizeSession(session) {
|
|
9851
10032
|
if (session === null) return { present: false, expired: null, expiresAt: null };
|
|
9852
|
-
if (!
|
|
10033
|
+
if (!isRecord5(session)) throw new TypeError("Invalid session store.");
|
|
9853
10034
|
const expiry = extractSessionExpiry(session);
|
|
9854
10035
|
if (expiry === null) return { present: true, expired: null, expiresAt: null };
|
|
9855
10036
|
return {
|
|
@@ -9859,7 +10040,7 @@ function summarizeSession(session) {
|
|
|
9859
10040
|
};
|
|
9860
10041
|
}
|
|
9861
10042
|
function storedDelegationExpiry(entry) {
|
|
9862
|
-
if (!
|
|
10043
|
+
if (!isRecord5(entry) || !isRecord5(entry.delegation) || !("expiry" in entry.delegation)) {
|
|
9863
10044
|
throw new TypeError("Invalid stored delegation.");
|
|
9864
10045
|
}
|
|
9865
10046
|
return parseExpiry(entry.delegation.expiry);
|
|
@@ -9888,7 +10069,7 @@ function profileNotFound(profile) {
|
|
|
9888
10069
|
)
|
|
9889
10070
|
};
|
|
9890
10071
|
}
|
|
9891
|
-
function
|
|
10072
|
+
function isRecord5(value) {
|
|
9892
10073
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
9893
10074
|
}
|
|
9894
10075
|
var import_zod7, StatusInputSchema, StatusOutputSchema, STATUS_POSTURES, STATUS_EXPOSURE, STATUS_SENSITIVITY, statusOperationDefinitions;
|
|
@@ -9896,6 +10077,7 @@ var init_status = __esm({
|
|
|
9896
10077
|
"src/operations/status.ts"() {
|
|
9897
10078
|
"use strict";
|
|
9898
10079
|
import_zod7 = require("zod");
|
|
10080
|
+
init_delegation_binding();
|
|
9899
10081
|
init_errors();
|
|
9900
10082
|
init_state();
|
|
9901
10083
|
StatusInputSchema = import_zod7.z.object({}).strict();
|
|
@@ -9918,7 +10100,9 @@ var init_status = __esm({
|
|
|
9918
10100
|
expired: import_zod7.z.boolean().nullable(),
|
|
9919
10101
|
expiresAt: import_zod7.z.string().datetime({ offset: true }).nullable()
|
|
9920
10102
|
}).strict(),
|
|
9921
|
-
liveAdditionalDelegationCount: import_zod7.z.number().int().nonnegative()
|
|
10103
|
+
liveAdditionalDelegationCount: import_zod7.z.number().int().nonnegative().describe(
|
|
10104
|
+
"Stored, unexpired delegations the replay rule accepts: compact-UCAN or signed-login records with a request binding, and unbound compact-UCAN records before the profile's one-time binding migration. Each is still validated, and checked against its binding, when a runtime installs it."
|
|
10105
|
+
)
|
|
9922
10106
|
}).strict();
|
|
9923
10107
|
STATUS_POSTURES = [
|
|
9924
10108
|
"owner-openkey",
|
|
@@ -10072,9 +10256,9 @@ function isOperatorType(value) {
|
|
|
10072
10256
|
return value === "human" || value === "agent";
|
|
10073
10257
|
}
|
|
10074
10258
|
function isStoredProfile(value) {
|
|
10075
|
-
return
|
|
10259
|
+
return isRecord6(value) && isNonEmptyString(value.name) && isNonEmptyString(value.host) && typeof value.chainId === "number" && Number.isFinite(value.chainId) && isNonEmptyString(value.spaceName) && isNonEmptyString(value.did) && isNonEmptyString(value.createdAt) && isOptionalNonEmptyString(value.sessionDid) && isOptionalNonEmptyString(value.ownerDid) && isOptionalNonEmptyString(value.spaceId) && isOptionalPosture(value.posture) && isOptionalOperatorType(value.operatorType) && isOptionalAuthMethod(value.authMethod) && isOptionalNonEmptyString(value.defaultSpace) && isOptionalNonEmptyString(value.privateKey) && isOptionalNonEmptyString(value.address) && isOptionalNonEmptyString(value.openkeyHost);
|
|
10076
10260
|
}
|
|
10077
|
-
function
|
|
10261
|
+
function isRecord6(value) {
|
|
10078
10262
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
10079
10263
|
}
|
|
10080
10264
|
function isNonEmptyString(value) {
|
|
@@ -10131,14 +10315,12 @@ async function createInvocationRuntime(target, requirement = "authenticated") {
|
|
|
10131
10315
|
const profileName = summary.profile;
|
|
10132
10316
|
try {
|
|
10133
10317
|
const {
|
|
10134
|
-
activateValidatedRuntimeDelegation: activateValidatedRuntimeDelegation2,
|
|
10135
10318
|
TinyCloudNode: TinyCloudNodeConstructor
|
|
10136
|
-
} =
|
|
10319
|
+
} = nodeSdk4;
|
|
10137
10320
|
const explicitPrivateKeyOverride = typeof target.privateKey === "string";
|
|
10138
|
-
const [session, key
|
|
10321
|
+
const [session, key] = explicitPrivateKeyOverride ? [null, null] : await Promise.all([
|
|
10139
10322
|
readSession(profileName),
|
|
10140
|
-
readJson(`${profilePath(profileName)}/key.json`)
|
|
10141
|
-
readAdditionalDelegations(profileName)
|
|
10323
|
+
readJson(`${profilePath(profileName)}/key.json`)
|
|
10142
10324
|
]);
|
|
10143
10325
|
const profile = resolved.profile;
|
|
10144
10326
|
const actualPosture = resolvePosture(profile);
|
|
@@ -10185,19 +10367,26 @@ async function createInvocationRuntime(target, requirement = "authenticated") {
|
|
|
10185
10367
|
const livePrincipalDid = normalizeDid(node.did);
|
|
10186
10368
|
const authenticatedSpace = explicitPrivateKeyOverride ? spaceForAuthenticatedPrincipal(livePrincipalDid) : void 0;
|
|
10187
10369
|
const livePermissions = [...node.getVerifiedSessionCapabilities()];
|
|
10370
|
+
const resolveSpace2 = operationSpaceResolver(node, authenticatedSpace ?? summary.space);
|
|
10188
10371
|
const seenCids = /* @__PURE__ */ new Set();
|
|
10189
|
-
|
|
10190
|
-
const
|
|
10191
|
-
|
|
10192
|
-
|
|
10193
|
-
|
|
10194
|
-
|
|
10372
|
+
if (!explicitPrivateKeyOverride) {
|
|
10373
|
+
const activator = node;
|
|
10374
|
+
const migrated = await prepareStoredDelegationReplay(profileName, activator, {
|
|
10375
|
+
host: summary.host,
|
|
10376
|
+
// Only the profile's own restored session; a local sign-in without
|
|
10377
|
+
// one uses a fresh session key the stored records do not address.
|
|
10378
|
+
migrate: activeSession !== void 0
|
|
10379
|
+
});
|
|
10380
|
+
for (const entry of await readAdditionalDelegations(profileName)) {
|
|
10381
|
+
const activated = await replayStoredDelegation(activator, entry, {
|
|
10382
|
+
host: summary.host,
|
|
10383
|
+
migrated,
|
|
10384
|
+
resolveSpace: resolveSpace2
|
|
10195
10385
|
});
|
|
10196
|
-
if (!seenCids.has(activated.cid)) {
|
|
10386
|
+
if (activated !== void 0 && !seenCids.has(activated.cid)) {
|
|
10197
10387
|
seenCids.add(activated.cid);
|
|
10198
10388
|
livePermissions.push(...activated.effectivePermissions);
|
|
10199
10389
|
}
|
|
10200
|
-
} catch {
|
|
10201
10390
|
}
|
|
10202
10391
|
}
|
|
10203
10392
|
const runtime = {
|
|
@@ -10229,8 +10418,8 @@ async function createInvocationRuntime(target, requirement = "authenticated") {
|
|
|
10229
10418
|
function spaceForAuthenticatedPrincipal(principal2) {
|
|
10230
10419
|
if (principal2 === void 0) return void 0;
|
|
10231
10420
|
try {
|
|
10232
|
-
const pkh =
|
|
10233
|
-
return pkh === null ? void 0 :
|
|
10421
|
+
const pkh = nodeSdk4.parsePkhDid(principal2);
|
|
10422
|
+
return pkh === null ? void 0 : nodeSdk4.makePkhSpaceId(pkh.address, pkh.chainId, "secrets");
|
|
10234
10423
|
} catch {
|
|
10235
10424
|
return void 0;
|
|
10236
10425
|
}
|
|
@@ -10238,7 +10427,7 @@ function spaceForAuthenticatedPrincipal(principal2) {
|
|
|
10238
10427
|
function normalizeSession(session, key) {
|
|
10239
10428
|
const header = session.delegationHeader;
|
|
10240
10429
|
const jwk = hasPrivateParameter(session.jwk) ? session.jwk : key;
|
|
10241
|
-
if (!
|
|
10430
|
+
if (!isRecord7(header) || typeof header.Authorization !== "string" || typeof session.delegationCid !== "string" || typeof session.spaceId !== "string" || !hasPrivateParameter(jwk) || typeof session.verificationMethod !== "string") {
|
|
10242
10431
|
return void 0;
|
|
10243
10432
|
}
|
|
10244
10433
|
return {
|
|
@@ -10254,27 +10443,14 @@ function normalizeSession(session, key) {
|
|
|
10254
10443
|
...Array.isArray(session.tinycloudHosts) && session.tinycloudHosts.every((host) => typeof host === "string") ? { tinycloudHosts: session.tinycloudHosts } : {}
|
|
10255
10444
|
};
|
|
10256
10445
|
}
|
|
10257
|
-
function normalizeStoredDelegation(entry) {
|
|
10258
|
-
const raw = entry.delegation;
|
|
10259
|
-
if (!isRecord6(raw) || !isRecord6(raw.delegationHeader)) return void 0;
|
|
10260
|
-
const expiry = parseExpiry2(raw.expiry);
|
|
10261
|
-
if (expiry === void 0 || typeof raw.cid !== "string" || typeof raw.spaceId !== "string" || typeof raw.path !== "string" || !Array.isArray(raw.actions) || !raw.actions.every((action) => typeof action === "string") || typeof raw.delegateDID !== "string" || typeof raw.ownerAddress !== "string" || typeof raw.chainId !== "number" || typeof raw.delegationHeader.Authorization !== "string") {
|
|
10262
|
-
return void 0;
|
|
10263
|
-
}
|
|
10264
|
-
return { ...raw, expiry };
|
|
10265
|
-
}
|
|
10266
|
-
function parseExpiry2(value) {
|
|
10267
|
-
const expiry = value instanceof Date ? value : typeof value === "string" ? new Date(value) : void 0;
|
|
10268
|
-
return expiry !== void 0 && !Number.isNaN(expiry.getTime()) ? expiry : void 0;
|
|
10269
|
-
}
|
|
10270
10446
|
function hasPrivateParameter(value) {
|
|
10271
|
-
return
|
|
10447
|
+
return isRecord7(value) && typeof value.d === "string" && value.d.length > 0;
|
|
10272
10448
|
}
|
|
10273
10449
|
function normalizeDid(value) {
|
|
10274
10450
|
if (typeof value !== "string" || value.length === 0) return void 0;
|
|
10275
10451
|
return value.split("#", 1)[0];
|
|
10276
10452
|
}
|
|
10277
|
-
function
|
|
10453
|
+
function isRecord7(value) {
|
|
10278
10454
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
10279
10455
|
}
|
|
10280
10456
|
function failed(context, error) {
|
|
@@ -10287,15 +10463,17 @@ function unresolvedSummary(target) {
|
|
|
10287
10463
|
posture: "unauthenticated"
|
|
10288
10464
|
};
|
|
10289
10465
|
}
|
|
10290
|
-
var
|
|
10466
|
+
var nodeSdk4;
|
|
10291
10467
|
var init_runtime = __esm({
|
|
10292
10468
|
"src/runtime.ts"() {
|
|
10293
10469
|
"use strict";
|
|
10294
|
-
|
|
10470
|
+
nodeSdk4 = __toESM(require("@tinycloud/node-sdk"), 1);
|
|
10295
10471
|
init_authority();
|
|
10296
10472
|
init_errors();
|
|
10297
10473
|
init_profile();
|
|
10474
|
+
init_secrets();
|
|
10298
10475
|
init_state();
|
|
10476
|
+
init_delegation_binding();
|
|
10299
10477
|
}
|
|
10300
10478
|
});
|
|
10301
10479
|
|
|
@@ -10308,8 +10486,8 @@ module.exports = __toCommonJS(cli_runtime_exports);
|
|
|
10308
10486
|
|
|
10309
10487
|
// src/invoke.ts
|
|
10310
10488
|
var import_node_crypto3 = require("crypto");
|
|
10311
|
-
var
|
|
10312
|
-
var
|
|
10489
|
+
var import_node_path3 = require("path");
|
|
10490
|
+
var import_node_sdk = require("@tinycloud/node-sdk");
|
|
10313
10491
|
|
|
10314
10492
|
// ../sdk-core/src/policy/errors.ts
|
|
10315
10493
|
var SignedObjectProfileError = class extends Error {
|
|
@@ -11129,7 +11307,7 @@ function normalizeInvocationTarget(target) {
|
|
|
11129
11307
|
const stateRoot = candidate.stateRoot;
|
|
11130
11308
|
const allowOwnerProfile = candidate.allowOwnerProfile;
|
|
11131
11309
|
const privateKey = candidate.privateKey;
|
|
11132
|
-
if (profile !== void 0 && typeof profile !== "string" || host !== void 0 && typeof host !== "string" || stateRoot !== void 0 && (typeof stateRoot !== "string" || !(0,
|
|
11310
|
+
if (profile !== void 0 && typeof profile !== "string" || host !== void 0 && typeof host !== "string" || stateRoot !== void 0 && (typeof stateRoot !== "string" || !(0, import_node_path3.isAbsolute)(stateRoot)) || allowOwnerProfile !== void 0 && typeof allowOwnerProfile !== "boolean" || privateKey !== void 0 && typeof privateKey !== "string") {
|
|
11133
11311
|
return void 0;
|
|
11134
11312
|
}
|
|
11135
11313
|
return {
|
|
@@ -11269,11 +11447,11 @@ function requirementsBelongToAuthenticatedOwner(requirements, authenticatedSpace
|
|
|
11269
11447
|
}
|
|
11270
11448
|
function canonicalPkhOwner(space) {
|
|
11271
11449
|
if (typeof space !== "string") return void 0;
|
|
11272
|
-
const parsedSpace = (0,
|
|
11450
|
+
const parsedSpace = (0, import_node_sdk.parseSpaceUri)(space);
|
|
11273
11451
|
if (parsedSpace === null) return void 0;
|
|
11274
11452
|
try {
|
|
11275
|
-
const pkh = (0,
|
|
11276
|
-
return pkh === null ? void 0 : (0,
|
|
11453
|
+
const pkh = (0, import_node_sdk.parsePkhDid)(parsedSpace.owner);
|
|
11454
|
+
return pkh === null ? void 0 : (0, import_node_sdk.parseSpaceUri)((0, import_node_sdk.makePkhSpaceId)(pkh.address, pkh.chainId, parsedSpace.name))?.owner;
|
|
11277
11455
|
} catch {
|
|
11278
11456
|
return void 0;
|
|
11279
11457
|
}
|