@tinycloud/operations 0.4.0-beta.11 → 0.4.0-beta.13
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 -1
- package/dist/artifacts.cjs.map +1 -1
- package/dist/artifacts.d.cts +1 -1
- package/dist/artifacts.d.ts +1 -1
- package/dist/artifacts.js +10 -1
- package/dist/artifacts.js.map +1 -1
- package/dist/cli-runtime.cjs +121 -20
- package/dist/cli-runtime.cjs.map +1 -1
- package/dist/cli-runtime.d.cts +1 -1
- package/dist/cli-runtime.d.ts +1 -1
- package/dist/cli-runtime.js +121 -19
- package/dist/cli-runtime.js.map +1 -1
- package/dist/{contract-eWtDSMeI.d.cts → contract-BRwWJpPs.d.cts} +23 -1
- package/dist/{contract-eWtDSMeI.d.ts → contract-BRwWJpPs.d.ts} +23 -1
- package/dist/delegation-binding.cjs +70 -13
- package/dist/delegation-binding.cjs.map +1 -1
- package/dist/delegation-binding.d.cts +43 -13
- package/dist/delegation-binding.d.ts +43 -13
- package/dist/delegation-binding.js +69 -13
- package/dist/delegation-binding.js.map +1 -1
- package/dist/index.cjs +119 -21
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +119 -20
- package/dist/index.js.map +1 -1
- package/dist/profile.d.cts +1 -1
- package/dist/profile.d.ts +1 -1
- package/generated/operations.json +2628 -4
- package/package.json +4 -4
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { I as InvocationTarget, a as OperationResult } from './contract-
|
|
1
|
+
import { I as InvocationTarget, a as OperationResult } from './contract-BRwWJpPs.cjs';
|
|
2
2
|
|
|
3
3
|
/** The sole projection-facing execution API. */
|
|
4
4
|
declare function invokeOperation(operationId: string, operationVersion: number, invocationTarget: InvocationTarget, unknownInput: unknown): Promise<OperationResult<unknown>>;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { I as InvocationTarget, a as OperationResult } from './contract-
|
|
1
|
+
import { I as InvocationTarget, a as OperationResult } from './contract-BRwWJpPs.js';
|
|
2
2
|
|
|
3
3
|
/** The sole projection-facing execution API. */
|
|
4
4
|
declare function invokeOperation(operationId: string, operationVersion: number, invocationTarget: InvocationTarget, unknownInput: unknown): Promise<OperationResult<unknown>>;
|
package/dist/index.js
CHANGED
|
@@ -355,8 +355,13 @@ function canonicalizeRecapCaveats(caveats) {
|
|
|
355
355
|
}
|
|
356
356
|
return `[${branches.join(",")}]`;
|
|
357
357
|
}
|
|
358
|
+
function isExplicitOnlyAction(action) {
|
|
359
|
+
return Object.prototype.hasOwnProperty.call(EXPLICIT_ONLY_ACTIONS, action);
|
|
360
|
+
}
|
|
358
361
|
function actionContains(grantedAction, requestedAction) {
|
|
359
|
-
if (grantedAction ===
|
|
362
|
+
if (grantedAction === requestedAction) return true;
|
|
363
|
+
if (isExplicitOnlyAction(requestedAction)) return false;
|
|
364
|
+
if (grantedAction === "*") return true;
|
|
360
365
|
if (!grantedAction.endsWith("/*")) return false;
|
|
361
366
|
const service = grantedAction.slice(0, -2);
|
|
362
367
|
return requestedAction === service || requestedAction.startsWith(`${service}/`);
|
|
@@ -381,10 +386,15 @@ function cloneEntry(entry) {
|
|
|
381
386
|
...entry.expiry !== void 0 ? { expiry: entry.expiry } : {}
|
|
382
387
|
};
|
|
383
388
|
}
|
|
389
|
+
var EXPLICIT_ONLY_ACTIONS;
|
|
384
390
|
var init_capabilities = __esm({
|
|
385
391
|
"../sdk-core/src/capabilities.ts"() {
|
|
386
392
|
"use strict";
|
|
387
393
|
init_manifest();
|
|
394
|
+
EXPLICIT_ONLY_ACTIONS = {
|
|
395
|
+
"tinycloud.kv/sync": true,
|
|
396
|
+
"tinycloud.kv/retain": true
|
|
397
|
+
};
|
|
388
398
|
}
|
|
389
399
|
});
|
|
390
400
|
|
|
@@ -3626,6 +3636,32 @@ ORDER BY type, name`;
|
|
|
3626
3636
|
}
|
|
3627
3637
|
});
|
|
3628
3638
|
|
|
3639
|
+
// src/contract.ts
|
|
3640
|
+
var STORED_GRANT_SKIP_REASONS, DELEGATION_CID_PATTERN;
|
|
3641
|
+
var init_contract = __esm({
|
|
3642
|
+
"src/contract.ts"() {
|
|
3643
|
+
"use strict";
|
|
3644
|
+
STORED_GRANT_SKIP_REASONS = [
|
|
3645
|
+
"malformed",
|
|
3646
|
+
"unbound",
|
|
3647
|
+
"outside_request",
|
|
3648
|
+
"host_mismatch",
|
|
3649
|
+
"expired",
|
|
3650
|
+
"cid_mismatch",
|
|
3651
|
+
"authority_invalid",
|
|
3652
|
+
"proof_missing",
|
|
3653
|
+
"proof_invalid",
|
|
3654
|
+
"owner_mismatch",
|
|
3655
|
+
"audience_mismatch",
|
|
3656
|
+
"resources_mismatch",
|
|
3657
|
+
"unsupported",
|
|
3658
|
+
"activation_rejected",
|
|
3659
|
+
"invalid"
|
|
3660
|
+
];
|
|
3661
|
+
DELEGATION_CID_PATTERN = "^bafkr4i[a-z2-7]{52}$";
|
|
3662
|
+
}
|
|
3663
|
+
});
|
|
3664
|
+
|
|
3629
3665
|
// src/delegation-binding.ts
|
|
3630
3666
|
import { join as join2 } from "path";
|
|
3631
3667
|
import * as nodeSdk3 from "@tinycloud/node-sdk";
|
|
@@ -3651,12 +3687,12 @@ function replayLimit(entry, migrated) {
|
|
|
3651
3687
|
if (binding.success) return binding.data.requested;
|
|
3652
3688
|
return !migrated && kind === "compact" && !("authorityRequest" in entry) ? "signed" : void 0;
|
|
3653
3689
|
}
|
|
3654
|
-
function
|
|
3690
|
+
function bindToRequest(record, requested, source, recordedAt = (/* @__PURE__ */ new Date()).toISOString()) {
|
|
3655
3691
|
return {
|
|
3656
3692
|
...record,
|
|
3657
3693
|
authorityRequest: DelegationRequestBindingSchema.parse({
|
|
3658
3694
|
requestId: `${REQUEST_ID_PREFIX[source]}:${record.delegation.cid}`,
|
|
3659
|
-
requested: structuredClone(
|
|
3695
|
+
requested: structuredClone(requested)
|
|
3660
3696
|
}),
|
|
3661
3697
|
authorityRequestAudit: { source, recordedAt, note: BINDING_NOTES[source] }
|
|
3662
3698
|
};
|
|
@@ -3712,23 +3748,40 @@ async function migratedRecord(node, entry, host, recordedAt) {
|
|
|
3712
3748
|
const signed = await signedCapabilities(node, delegation, host);
|
|
3713
3749
|
if (signed === void 0) return void 0;
|
|
3714
3750
|
try {
|
|
3715
|
-
return
|
|
3751
|
+
return bindToRequest({ ...entry, delegation: { ...entry.delegation, cid: delegation.cid } }, signed, "migration", recordedAt);
|
|
3716
3752
|
} catch {
|
|
3717
3753
|
return void 0;
|
|
3718
3754
|
}
|
|
3719
3755
|
}
|
|
3756
|
+
function skipped(reason) {
|
|
3757
|
+
return { status: "skipped", reason };
|
|
3758
|
+
}
|
|
3720
3759
|
async function replayStoredDelegation(node, entry, options) {
|
|
3760
|
+
const kind = storedDelegationKind(entry);
|
|
3721
3761
|
const delegation = normalizeStoredDelegation(entry);
|
|
3722
|
-
if (
|
|
3762
|
+
if (kind === "refused" || delegation === void 0) return skipped("malformed");
|
|
3763
|
+
if (delegation.expiry.getTime() <= Date.now()) return NOT_REPLAYED;
|
|
3764
|
+
if (kind === "other") return skipped("proof_missing");
|
|
3723
3765
|
const limit = replayLimit(entry, options.migrated);
|
|
3724
|
-
if (limit === void 0) return
|
|
3725
|
-
|
|
3766
|
+
if (limit === void 0) return skipped("unbound");
|
|
3767
|
+
let outsideRequest = false;
|
|
3768
|
+
const authorize = limit === "signed" ? () => true : (effective) => {
|
|
3769
|
+
outsideRequest = !delegationWithinRequest(limit, effective, options.resolveSpace);
|
|
3770
|
+
return !outsideRequest;
|
|
3771
|
+
};
|
|
3726
3772
|
try {
|
|
3727
|
-
return
|
|
3728
|
-
|
|
3729
|
-
|
|
3773
|
+
return {
|
|
3774
|
+
status: "installed",
|
|
3775
|
+
delegation: await nodeSdk3.activateValidatedRuntimeDelegation(node, delegation, { host: options.host, authorize })
|
|
3776
|
+
};
|
|
3777
|
+
} catch (error) {
|
|
3778
|
+
return skipped(outsideRequest ? "outside_request" : rejectionReason(error));
|
|
3730
3779
|
}
|
|
3731
3780
|
}
|
|
3781
|
+
function rejectionReason(error) {
|
|
3782
|
+
const reason = isRecord4(error) ? error.reason : void 0;
|
|
3783
|
+
return typeof reason === "string" && STORED_GRANT_SKIP_REASONS.includes(reason) ? reason : "invalid";
|
|
3784
|
+
}
|
|
3732
3785
|
async function bindingMigrationRecorded(profile) {
|
|
3733
3786
|
try {
|
|
3734
3787
|
return await readJson(bindingMigrationPath(profile)) !== null;
|
|
@@ -3773,23 +3826,27 @@ function recordKey(entry) {
|
|
|
3773
3826
|
function isRecord4(value) {
|
|
3774
3827
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3775
3828
|
}
|
|
3776
|
-
var REQUEST_ID_PREFIX, BINDING_NOTES, MIGRATION_LOCK_TIMEOUT_MS;
|
|
3829
|
+
var REQUEST_ID_PREFIX, BINDING_NOTES, MIGRATION_LOCK_TIMEOUT_MS, NOT_REPLAYED;
|
|
3777
3830
|
var init_delegation_binding = __esm({
|
|
3778
3831
|
"src/delegation-binding.ts"() {
|
|
3779
3832
|
"use strict";
|
|
3780
3833
|
init_artifacts();
|
|
3781
3834
|
init_authority();
|
|
3835
|
+
init_contract();
|
|
3782
3836
|
init_state();
|
|
3783
3837
|
init_secrets();
|
|
3784
3838
|
REQUEST_ID_PREFIX = {
|
|
3785
3839
|
migration: "migrated",
|
|
3786
|
-
"unbound-import": "unbound-import"
|
|
3840
|
+
"unbound-import": "unbound-import",
|
|
3841
|
+
"cli-grant": "cli-grant"
|
|
3787
3842
|
};
|
|
3788
3843
|
BINDING_NOTES = {
|
|
3789
3844
|
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.",
|
|
3790
|
-
"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."
|
|
3845
|
+
"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.",
|
|
3846
|
+
"cli-grant": "Granted to this CLI by `tc auth request --grant` or a permission escalation, and checked against the request it answered. Bound to exactly its own signed capabilities, so replay refuses any delegation in this record that exceeds them."
|
|
3791
3847
|
};
|
|
3792
3848
|
MIGRATION_LOCK_TIMEOUT_MS = 250;
|
|
3849
|
+
NOT_REPLAYED = { status: "not-replayed" };
|
|
3793
3850
|
}
|
|
3794
3851
|
});
|
|
3795
3852
|
|
|
@@ -4202,7 +4259,18 @@ async function createInvocationRuntime(target, requirement = "authenticated") {
|
|
|
4202
4259
|
));
|
|
4203
4260
|
}
|
|
4204
4261
|
} else {
|
|
4205
|
-
|
|
4262
|
+
try {
|
|
4263
|
+
await node.restoreSession(activeSession);
|
|
4264
|
+
} catch (error) {
|
|
4265
|
+
if (isRecord7(error) && error.code === "AUTH_EXPIRED") {
|
|
4266
|
+
return failed(summary, operationError(
|
|
4267
|
+
"AUTH_REQUIRED",
|
|
4268
|
+
"The stored session has expired or is no longer valid. Sign in again.",
|
|
4269
|
+
{ retryable: false }
|
|
4270
|
+
));
|
|
4271
|
+
}
|
|
4272
|
+
throw error;
|
|
4273
|
+
}
|
|
4206
4274
|
}
|
|
4207
4275
|
const activeSessionDid = normalizeDid(node.sessionDid);
|
|
4208
4276
|
const livePrincipalDid = normalizeDid(node.did);
|
|
@@ -4210,6 +4278,7 @@ async function createInvocationRuntime(target, requirement = "authenticated") {
|
|
|
4210
4278
|
const livePermissions = [...node.getVerifiedSessionCapabilities()];
|
|
4211
4279
|
const resolveSpace2 = operationSpaceResolver(node, authenticatedSpace ?? summary.space);
|
|
4212
4280
|
const seenCids = /* @__PURE__ */ new Set();
|
|
4281
|
+
const warnings = [];
|
|
4213
4282
|
if (!explicitPrivateKeyOverride) {
|
|
4214
4283
|
const activator = node;
|
|
4215
4284
|
const migrated = await prepareStoredDelegationReplay(profileName, activator, {
|
|
@@ -4219,20 +4288,25 @@ async function createInvocationRuntime(target, requirement = "authenticated") {
|
|
|
4219
4288
|
migrate: activeSession !== void 0
|
|
4220
4289
|
});
|
|
4221
4290
|
for (const entry of await readAdditionalDelegations(profileName)) {
|
|
4222
|
-
const
|
|
4291
|
+
const replay = await replayStoredDelegation(activator, entry, {
|
|
4223
4292
|
host: summary.host,
|
|
4224
4293
|
migrated,
|
|
4225
4294
|
resolveSpace: resolveSpace2
|
|
4226
4295
|
});
|
|
4227
|
-
if (
|
|
4228
|
-
seenCids.
|
|
4229
|
-
|
|
4296
|
+
if (replay.status === "installed") {
|
|
4297
|
+
if (!seenCids.has(replay.delegation.cid)) {
|
|
4298
|
+
seenCids.add(replay.delegation.cid);
|
|
4299
|
+
livePermissions.push(...replay.delegation.effectivePermissions);
|
|
4300
|
+
}
|
|
4301
|
+
} else if (replay.status === "skipped") {
|
|
4302
|
+
warnings.push(skippedGrantWarning(node, entry, replay.reason));
|
|
4230
4303
|
}
|
|
4231
4304
|
}
|
|
4232
4305
|
}
|
|
4233
4306
|
const runtime = {
|
|
4234
4307
|
node,
|
|
4235
|
-
granted: canonicalizeCapabilities(livePermissions)
|
|
4308
|
+
granted: canonicalizeCapabilities(livePermissions),
|
|
4309
|
+
...warnings.length === 0 ? {} : { warnings }
|
|
4236
4310
|
};
|
|
4237
4311
|
return {
|
|
4238
4312
|
ok: true,
|
|
@@ -4256,6 +4330,24 @@ async function createInvocationRuntime(target, requirement = "authenticated") {
|
|
|
4256
4330
|
));
|
|
4257
4331
|
}
|
|
4258
4332
|
}
|
|
4333
|
+
function skippedGrantWarning(node, entry, reason) {
|
|
4334
|
+
const grantCid = verifiedStoredCid(node, entry);
|
|
4335
|
+
return { code: "STORED_GRANT_SKIPPED", reason, ...grantCid === void 0 ? {} : { grantCid } };
|
|
4336
|
+
}
|
|
4337
|
+
function verifiedStoredCid(node, entry) {
|
|
4338
|
+
const delegation = isRecord7(entry) && isRecord7(entry.delegation) ? entry.delegation : void 0;
|
|
4339
|
+
const header = isRecord7(delegation?.delegationHeader) ? delegation.delegationHeader : void 0;
|
|
4340
|
+
const cid = delegation?.cid;
|
|
4341
|
+
const computeDelegationCid = isRecord7(node) ? node.computeDelegationCid : void 0;
|
|
4342
|
+
if (typeof cid !== "string" || typeof header?.Authorization !== "string" || typeof computeDelegationCid !== "function") {
|
|
4343
|
+
return void 0;
|
|
4344
|
+
}
|
|
4345
|
+
try {
|
|
4346
|
+
return computeDelegationCid.call(node, header.Authorization) === cid && DELEGATION_CID.test(cid) ? cid : void 0;
|
|
4347
|
+
} catch {
|
|
4348
|
+
return void 0;
|
|
4349
|
+
}
|
|
4350
|
+
}
|
|
4259
4351
|
function spaceForAuthenticatedPrincipal(principal2) {
|
|
4260
4352
|
if (principal2 === void 0) return void 0;
|
|
4261
4353
|
try {
|
|
@@ -4304,15 +4396,18 @@ function unresolvedSummary(target) {
|
|
|
4304
4396
|
posture: "unauthenticated"
|
|
4305
4397
|
};
|
|
4306
4398
|
}
|
|
4399
|
+
var DELEGATION_CID;
|
|
4307
4400
|
var init_runtime = __esm({
|
|
4308
4401
|
"src/runtime.ts"() {
|
|
4309
4402
|
"use strict";
|
|
4403
|
+
init_contract();
|
|
4310
4404
|
init_authority();
|
|
4311
4405
|
init_errors();
|
|
4312
4406
|
init_profile();
|
|
4313
4407
|
init_secrets();
|
|
4314
4408
|
init_state();
|
|
4315
4409
|
init_delegation_binding();
|
|
4410
|
+
DELEGATION_CID = new RegExp(DELEGATION_CID_PATTERN);
|
|
4316
4411
|
}
|
|
4317
4412
|
});
|
|
4318
4413
|
|
|
@@ -4692,9 +4787,13 @@ async function invokeOperation(operationId, operationVersion, invocationTarget,
|
|
|
4692
4787
|
unknownInput
|
|
4693
4788
|
);
|
|
4694
4789
|
if (isPreparedError(prepared)) return prepared.result;
|
|
4695
|
-
return executePreparedInvocation(prepared);
|
|
4790
|
+
return withRuntimeWarnings(await executePreparedInvocation(prepared), prepared);
|
|
4696
4791
|
});
|
|
4697
4792
|
}
|
|
4793
|
+
function withRuntimeWarnings(result, prepared) {
|
|
4794
|
+
const warnings = prepared.runtimeResolution.context.runtime?.warnings;
|
|
4795
|
+
return warnings === void 0 || warnings.length === 0 ? result : { ...result, warnings: [...warnings] };
|
|
4796
|
+
}
|
|
4698
4797
|
function isPreparedError(prepared) {
|
|
4699
4798
|
return "status" in prepared;
|
|
4700
4799
|
}
|