@tinycloud/operations 0.5.0-beta.0 → 0.5.0-beta.2
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/coverage.json +9 -1
- package/dist/artifacts.d.cts +1 -1
- package/dist/artifacts.d.ts +1 -1
- package/dist/cli-runtime.cjs +788 -180
- 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 +786 -179
- package/dist/cli-runtime.js.map +1 -1
- package/dist/{contract-DfyrluLB.d.cts → contract-zRklonbR.d.cts} +6 -3
- package/dist/{contract-DfyrluLB.d.ts → contract-zRklonbR.d.ts} +6 -3
- package/dist/delegation-binding.cjs +7 -0
- package/dist/delegation-binding.cjs.map +1 -1
- package/dist/delegation-binding.d.cts +15 -3
- package/dist/delegation-binding.d.ts +15 -3
- package/dist/delegation-binding.js +6 -0
- package/dist/delegation-binding.js.map +1 -1
- package/dist/index.cjs +816 -181
- 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 +812 -178
- package/dist/index.js.map +1 -1
- package/dist/profile.cjs +5 -0
- package/dist/profile.cjs.map +1 -1
- package/dist/profile.d.cts +14 -2
- package/dist/profile.d.ts +14 -2
- package/dist/profile.js +4 -0
- package/dist/profile.js.map +1 -1
- package/dist/recovery.cjs +67 -0
- package/dist/recovery.cjs.map +1 -0
- package/dist/recovery.d.cts +38 -0
- package/dist/recovery.d.ts +38 -0
- package/dist/recovery.js +39 -0
- package/dist/recovery.js.map +1 -0
- package/dist/secret-request.cjs +271 -0
- package/dist/secret-request.cjs.map +1 -0
- package/dist/secret-request.d.cts +119 -0
- package/dist/secret-request.d.ts +119 -0
- package/dist/secret-request.js +222 -0
- package/dist/secret-request.js.map +1 -0
- package/generated/operations.json +1838 -89
- package/package.json +15 -5
package/dist/cli-runtime.cjs
CHANGED
|
@@ -300,6 +300,7 @@ var init_errors2 = __esm({
|
|
|
300
300
|
"PROFILE_NOT_FOUND",
|
|
301
301
|
"PROFILE_POSTURE_NOT_ALLOWED",
|
|
302
302
|
"PROFILE_OWNER_OPT_IN_REQUIRED",
|
|
303
|
+
"PROFILE_MIGRATION_REQUIRED",
|
|
303
304
|
"AUTH_REQUIRED",
|
|
304
305
|
"PERMISSION_DENIED",
|
|
305
306
|
"SESSION_NOT_FOUND",
|
|
@@ -5232,6 +5233,45 @@ var init_artifacts = __esm({
|
|
|
5232
5233
|
}
|
|
5233
5234
|
});
|
|
5234
5235
|
|
|
5236
|
+
// src/recovery.ts
|
|
5237
|
+
function signInRecovery(profile, posture) {
|
|
5238
|
+
if (!SAFE_PROFILE_TOKEN.test(profile)) return { action: "sign_in" };
|
|
5239
|
+
const template = posture === "local-owner-key" ? SIGN_IN_TEMPLATES.local : posture === "delegate-session" ? SIGN_IN_TEMPLATES.scoped : SIGN_IN_TEMPLATES.openkey;
|
|
5240
|
+
return { action: "sign_in", command: template(profile) };
|
|
5241
|
+
}
|
|
5242
|
+
function migrationRecovery(profile) {
|
|
5243
|
+
return SAFE_PROFILE_TOKEN.test(profile) ? { action: "complete_migration", command: migrationCommand(profile), operationId: MIGRATION_OPERATION_ID } : { action: "complete_migration", operationId: MIGRATION_OPERATION_ID };
|
|
5244
|
+
}
|
|
5245
|
+
function isSafeRecovery(value, action) {
|
|
5246
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
|
|
5247
|
+
const record = value;
|
|
5248
|
+
if (record.action !== action) return false;
|
|
5249
|
+
const keys = Object.keys(record);
|
|
5250
|
+
const allowed = action === "sign_in" ? ["action", "command"] : ["action", "command", "operationId"];
|
|
5251
|
+
if (!keys.every((key) => allowed.includes(key))) return false;
|
|
5252
|
+
if (action === "complete_migration" && record.operationId !== MIGRATION_OPERATION_ID) return false;
|
|
5253
|
+
if (!("command" in record)) return true;
|
|
5254
|
+
const command = record.command;
|
|
5255
|
+
if (typeof command !== "string") return false;
|
|
5256
|
+
const profile = /^tc --profile (\S+) /.exec(command)?.[1];
|
|
5257
|
+
if (profile === void 0 || !SAFE_PROFILE_TOKEN.test(profile)) return false;
|
|
5258
|
+
return action === "sign_in" ? Object.values(SIGN_IN_TEMPLATES).some((template) => template(profile) === command) : migrationCommand(profile) === command;
|
|
5259
|
+
}
|
|
5260
|
+
var SAFE_PROFILE_TOKEN, MIGRATION_OPERATION_ID, SIGN_IN_TEMPLATES, migrationCommand;
|
|
5261
|
+
var init_recovery = __esm({
|
|
5262
|
+
"src/recovery.ts"() {
|
|
5263
|
+
"use strict";
|
|
5264
|
+
SAFE_PROFILE_TOKEN = /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/;
|
|
5265
|
+
MIGRATION_OPERATION_ID = "tinycloud.auth.capabilities";
|
|
5266
|
+
SIGN_IN_TEMPLATES = {
|
|
5267
|
+
local: (profile) => `tc --profile ${profile} auth login --method local`,
|
|
5268
|
+
openkey: (profile) => `tc --profile ${profile} auth login --method openkey`,
|
|
5269
|
+
scoped: (profile) => `tc --profile ${profile} auth login --method openkey --paste --manifest <manifest.json>`
|
|
5270
|
+
};
|
|
5271
|
+
migrationCommand = (profile) => `tc --profile ${profile} auth caps`;
|
|
5272
|
+
}
|
|
5273
|
+
});
|
|
5274
|
+
|
|
5235
5275
|
// src/secrets.ts
|
|
5236
5276
|
function normalizeSecretsGetInput(input) {
|
|
5237
5277
|
const reference = resolveSecretReference(input);
|
|
@@ -5318,15 +5358,6 @@ function canonicalizeSpaceUri(space) {
|
|
|
5318
5358
|
}
|
|
5319
5359
|
return space;
|
|
5320
5360
|
}
|
|
5321
|
-
function buildSecretSetupUrl(reference) {
|
|
5322
|
-
const parameters = [
|
|
5323
|
-
["secret", reference.name],
|
|
5324
|
-
...reference.scope === void 0 ? [] : [["scope", reference.scope]],
|
|
5325
|
-
["space", reference.space]
|
|
5326
|
-
];
|
|
5327
|
-
const query = parameters.map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`).join("&");
|
|
5328
|
-
return `${SECRET_MANAGER_BASE_URL}/app?${query}`;
|
|
5329
|
-
}
|
|
5330
5361
|
function canonicalizeSecretScope(scope) {
|
|
5331
5362
|
if (scope === void 0 || scope === "") return void 0;
|
|
5332
5363
|
const trimmed = scope.trim();
|
|
@@ -5354,14 +5385,13 @@ function invalidSecretInput() {
|
|
|
5354
5385
|
operationError("INPUT_INVALID", "The secret reference is invalid.")
|
|
5355
5386
|
);
|
|
5356
5387
|
}
|
|
5357
|
-
var nodeSdk, DEFAULT_SECRETS_SPACE,
|
|
5388
|
+
var nodeSdk, DEFAULT_SECRETS_SPACE, SECRET_NAME_RE2, RESERVED_SECRET_SCOPES;
|
|
5358
5389
|
var init_secrets = __esm({
|
|
5359
5390
|
"src/secrets.ts"() {
|
|
5360
5391
|
"use strict";
|
|
5361
5392
|
nodeSdk = __toESM(require("@tinycloud/node-sdk"), 1);
|
|
5362
5393
|
init_errors2();
|
|
5363
5394
|
DEFAULT_SECRETS_SPACE = "secrets";
|
|
5364
|
-
SECRET_MANAGER_BASE_URL = "https://secrets.tinycloud.xyz";
|
|
5365
5395
|
SECRET_NAME_RE2 = /^[A-Z][A-Z0-9_]*$/;
|
|
5366
5396
|
RESERVED_SECRET_SCOPES = /* @__PURE__ */ new Set(["default", "global"]);
|
|
5367
5397
|
}
|
|
@@ -5516,7 +5546,10 @@ async function importRequestBoundDelegation(context, input) {
|
|
|
5516
5546
|
delegation,
|
|
5517
5547
|
{ host }
|
|
5518
5548
|
);
|
|
5519
|
-
} catch {
|
|
5549
|
+
} catch (error) {
|
|
5550
|
+
if (typeof error === "object" && error !== null && "reason" in error && error.reason === "expired") {
|
|
5551
|
+
return expiredDelegation();
|
|
5552
|
+
}
|
|
5520
5553
|
return operationFailure(
|
|
5521
5554
|
"DELEGATION_REJECTED",
|
|
5522
5555
|
"The delegation was rejected by the TinyCloud runtime."
|
|
@@ -5534,55 +5567,67 @@ async function importRequestBoundDelegation(context, input) {
|
|
|
5534
5567
|
);
|
|
5535
5568
|
}
|
|
5536
5569
|
try {
|
|
5537
|
-
return await
|
|
5538
|
-
context.summary.profile
|
|
5539
|
-
|
|
5540
|
-
|
|
5541
|
-
|
|
5542
|
-
|
|
5543
|
-
|
|
5544
|
-
return {
|
|
5545
|
-
|
|
5546
|
-
|
|
5570
|
+
return await withProfileLock(context.summary.profile, async () => {
|
|
5571
|
+
const previousRecords = await readAdditionalDelegations(context.summary.profile);
|
|
5572
|
+
const result = await updateProfileStore(
|
|
5573
|
+
context.summary.profile,
|
|
5574
|
+
"additional-delegations",
|
|
5575
|
+
async (records) => {
|
|
5576
|
+
const state = await importState(context, input.requestId);
|
|
5577
|
+
if (!state.ok) return { records, result: state.result };
|
|
5578
|
+
if (state.sessionDid !== sessionDid || normalizeHost(state.host) !== normalizeHost(host)) {
|
|
5579
|
+
return {
|
|
5580
|
+
records,
|
|
5581
|
+
result: audienceMismatch(state.sessionDid, sessionDid)
|
|
5582
|
+
};
|
|
5583
|
+
}
|
|
5584
|
+
if (state.request.profile !== context.summary.profile || !samePrincipal(state.request.sessionDid, sessionDid) || normalizeHost(state.request.host) !== normalizeHost(host) || JSON.stringify(canonicalizeOperationCapabilities(state.request.requested, resolveSpace2)) !== JSON.stringify(canonicalizeOperationCapabilities(request.requested, resolveSpace2))) {
|
|
5585
|
+
return {
|
|
5586
|
+
records,
|
|
5587
|
+
result: operationFailure(
|
|
5588
|
+
"DELEGATION_ARTIFACT_INVALID",
|
|
5589
|
+
"The delegation does not reference a current stored request."
|
|
5590
|
+
)
|
|
5591
|
+
};
|
|
5592
|
+
}
|
|
5593
|
+
const record = {
|
|
5594
|
+
delegation: activated.delegation,
|
|
5595
|
+
permissions: activated.effectivePermissions,
|
|
5596
|
+
authorityRequest: {
|
|
5597
|
+
requestId: request.requestId,
|
|
5598
|
+
requested: request.requested
|
|
5599
|
+
}
|
|
5547
5600
|
};
|
|
5548
|
-
|
|
5549
|
-
|
|
5601
|
+
const position = records.findIndex((entry) => delegationCid(entry) === activated.cid);
|
|
5602
|
+
const alreadyPresent = position !== -1;
|
|
5603
|
+
const others = records.filter((entry) => delegationCid(entry) !== activated.cid);
|
|
5550
5604
|
return {
|
|
5551
|
-
records,
|
|
5552
|
-
result:
|
|
5553
|
-
"
|
|
5554
|
-
|
|
5555
|
-
|
|
5605
|
+
records: alreadyPresent ? [...others.slice(0, position), record, ...others.slice(position)] : [...records, record],
|
|
5606
|
+
result: {
|
|
5607
|
+
status: "ok",
|
|
5608
|
+
output: {
|
|
5609
|
+
cid: activated.cid,
|
|
5610
|
+
effectivePermissions,
|
|
5611
|
+
expiry: activated.expiry.toISOString(),
|
|
5612
|
+
audience: activated.audience,
|
|
5613
|
+
host: activated.host,
|
|
5614
|
+
activated: true,
|
|
5615
|
+
alreadyPresent
|
|
5616
|
+
}
|
|
5617
|
+
}
|
|
5556
5618
|
};
|
|
5557
5619
|
}
|
|
5558
|
-
|
|
5559
|
-
|
|
5560
|
-
|
|
5561
|
-
|
|
5562
|
-
|
|
5563
|
-
|
|
5564
|
-
|
|
5565
|
-
|
|
5566
|
-
const position = records.findIndex((entry) => delegationCid(entry) === activated.cid);
|
|
5567
|
-
const alreadyPresent = position !== -1;
|
|
5568
|
-
const others = records.filter((entry) => delegationCid(entry) !== activated.cid);
|
|
5569
|
-
return {
|
|
5570
|
-
records: alreadyPresent ? [...others.slice(0, position), record, ...others.slice(position)] : [...records, record],
|
|
5571
|
-
result: {
|
|
5572
|
-
status: "ok",
|
|
5573
|
-
output: {
|
|
5574
|
-
cid: activated.cid,
|
|
5575
|
-
effectivePermissions,
|
|
5576
|
-
expiry: activated.expiry.toISOString(),
|
|
5577
|
-
audience: activated.audience,
|
|
5578
|
-
host: activated.host,
|
|
5579
|
-
activated: true,
|
|
5580
|
-
alreadyPresent
|
|
5581
|
-
}
|
|
5582
|
-
}
|
|
5583
|
-
};
|
|
5620
|
+
);
|
|
5621
|
+
if (activated.expiry.getTime() <= Date.now()) {
|
|
5622
|
+
await updateProfileStore(
|
|
5623
|
+
context.summary.profile,
|
|
5624
|
+
"additional-delegations",
|
|
5625
|
+
() => ({ records: previousRecords, result: void 0 })
|
|
5626
|
+
);
|
|
5627
|
+
return expiredDelegation();
|
|
5584
5628
|
}
|
|
5585
|
-
|
|
5629
|
+
return result;
|
|
5630
|
+
});
|
|
5586
5631
|
} catch {
|
|
5587
5632
|
return internalImportFailure();
|
|
5588
5633
|
}
|
|
@@ -5831,6 +5876,33 @@ var init_auth = __esm({
|
|
|
5831
5876
|
}
|
|
5832
5877
|
});
|
|
5833
5878
|
|
|
5879
|
+
// src/kv-failure.ts
|
|
5880
|
+
function kvRefusal(error) {
|
|
5881
|
+
const verdict = (0, import_sdk_services2.authorizationVerdictOf)(error);
|
|
5882
|
+
if (verdict === "unauthenticated") {
|
|
5883
|
+
return (0, import_sdk_services2.validatedCapabilityOf)(error) === void 0 ? "auth_required" : "permission_denied";
|
|
5884
|
+
}
|
|
5885
|
+
return verdict === "forbidden" ? "permission_denied" : void 0;
|
|
5886
|
+
}
|
|
5887
|
+
function authorizationFailure(error, action) {
|
|
5888
|
+
switch (kvRefusal(error)) {
|
|
5889
|
+
case "auth_required":
|
|
5890
|
+
return { status: "error", error: operationError("AUTH_REQUIRED", `Authentication is required to ${action}.`) };
|
|
5891
|
+
case "permission_denied":
|
|
5892
|
+
return { status: "error", error: operationError("PERMISSION_DENIED", `Permission is denied to ${action}.`) };
|
|
5893
|
+
case void 0:
|
|
5894
|
+
return void 0;
|
|
5895
|
+
}
|
|
5896
|
+
}
|
|
5897
|
+
var import_sdk_services2;
|
|
5898
|
+
var init_kv_failure = __esm({
|
|
5899
|
+
"src/kv-failure.ts"() {
|
|
5900
|
+
"use strict";
|
|
5901
|
+
import_sdk_services2 = require("@tinycloud/sdk-services");
|
|
5902
|
+
init_errors2();
|
|
5903
|
+
}
|
|
5904
|
+
});
|
|
5905
|
+
|
|
5834
5906
|
// src/operations/exploration.ts
|
|
5835
5907
|
async function planAccountRegistryRead(context, path) {
|
|
5836
5908
|
return [{
|
|
@@ -6198,19 +6270,6 @@ function caughtKvFailure(error, action) {
|
|
|
6198
6270
|
if (error instanceof OperationInvocationError) return { status: "error", error: error.operationError };
|
|
6199
6271
|
return authorizationFailure(error, action) ?? nodeFailure(action);
|
|
6200
6272
|
}
|
|
6201
|
-
function authorizationFailure(error, action) {
|
|
6202
|
-
const verdict = (0, import_sdk_services2.authorizationVerdictOf)(error);
|
|
6203
|
-
if (verdict === "unauthenticated") {
|
|
6204
|
-
if ((0, import_sdk_services2.validatedCapabilityOf)(error) !== void 0) {
|
|
6205
|
-
return { status: "error", error: operationError("PERMISSION_DENIED", `Permission is denied to ${action}.`) };
|
|
6206
|
-
}
|
|
6207
|
-
return { status: "error", error: operationError("AUTH_REQUIRED", `Authentication is required to ${action}.`) };
|
|
6208
|
-
}
|
|
6209
|
-
if (verdict === "forbidden") {
|
|
6210
|
-
return { status: "error", error: operationError("PERMISSION_DENIED", `Permission is denied to ${action}.`) };
|
|
6211
|
-
}
|
|
6212
|
-
return void 0;
|
|
6213
|
-
}
|
|
6214
6273
|
function accountRegistryOutput(output) {
|
|
6215
6274
|
if (Buffer.byteLength(JSON.stringify(output), "utf8") > MAX_ACCOUNT_REGISTRY_BYTES) {
|
|
6216
6275
|
return {
|
|
@@ -6259,11 +6318,11 @@ function nodeFailure(action) {
|
|
|
6259
6318
|
)
|
|
6260
6319
|
};
|
|
6261
6320
|
}
|
|
6262
|
-
var
|
|
6321
|
+
var import_zod4, MAX_KV_VALUE_BYTES, DEFAULT_KV_LIST_LIMIT, MAX_ACCOUNT_REGISTRY_RECORDS, MAX_ACCOUNT_REGISTRY_BYTES, EmptyInputSchema2, SpaceSchema, PrefixSchema, KeySchema, LimitSchema, StrongEtagSchema, ContentTypeSchema, JsonNumberSchema, JsonValueSchema, KvMetadataSchema, AccountSpaceSchema, AccountSpacesOutputSchema, AccountApplicationSchema, AccountApplicationsOutputSchema, KvListInputSchema, KvListOutputSchema, KvGetInputSchema, KvGetOutputSchema, KvPutContentSchema, KvPutCommonSchema, KvPutInputSchema, KvPutOutputSchema, KvHeadInputSchema, KvHeadOutputSchema, KvDeleteInputSchema, KvDeleteOutputSchema, AUTHENTICATED_POSTURES, EXPLORATION_EXPOSURE, ACCOUNT_SPACES_SENSITIVITY, ACCOUNT_APPLICATIONS_SENSITIVITY, KV_LIST_SENSITIVITY, KV_GET_SENSITIVITY, KV_PUT_SENSITIVITY, KV_KEY_SENSITIVITY, explorationOperationDefinitions;
|
|
6263
6322
|
var init_exploration = __esm({
|
|
6264
6323
|
"src/operations/exploration.ts"() {
|
|
6265
6324
|
"use strict";
|
|
6266
|
-
|
|
6325
|
+
init_kv_failure();
|
|
6267
6326
|
import_zod4 = require("zod");
|
|
6268
6327
|
init_errors2();
|
|
6269
6328
|
init_secrets();
|
|
@@ -6565,6 +6624,191 @@ var init_exploration = __esm({
|
|
|
6565
6624
|
}
|
|
6566
6625
|
});
|
|
6567
6626
|
|
|
6627
|
+
// src/secret-request.ts
|
|
6628
|
+
function canonicalSecretRequestOwner(did) {
|
|
6629
|
+
const match = typeof did === "string" ? OWNER_RE.exec(did) : null;
|
|
6630
|
+
if (match === null || !Number.isSafeInteger(Number(match[1]))) throw invalidOwner();
|
|
6631
|
+
const address = match[2];
|
|
6632
|
+
let checksummed;
|
|
6633
|
+
try {
|
|
6634
|
+
checksummed = nodeSdk3.canonicalizeAddress(address);
|
|
6635
|
+
} catch {
|
|
6636
|
+
throw invalidOwner();
|
|
6637
|
+
}
|
|
6638
|
+
if (/[A-F]/.test(address.slice(2)) && address !== checksummed) throw invalidOwner();
|
|
6639
|
+
return `did:pkh:eip155:${match[1]}:${checksummed}`;
|
|
6640
|
+
}
|
|
6641
|
+
function buildSecretRequestUrl(input) {
|
|
6642
|
+
const owner = canonicalSecretRequestOwner(input.owner);
|
|
6643
|
+
const names = validSecretNames(input.names);
|
|
6644
|
+
if (input.scope !== void 0) assertSecretRequestScope(input.scope);
|
|
6645
|
+
const requester = input.requester;
|
|
6646
|
+
if (requester !== void 0 && (typeof requester !== "string" || requester.length === 0 || requester.length > MAX_REQUESTER_LENGTH || CONTROL_OR_FORMAT.test(requester))) {
|
|
6647
|
+
throw new SecretRequestInputError("INVALID_REQUESTER", "The requester label must be 1-64 characters with no control or format characters.");
|
|
6648
|
+
}
|
|
6649
|
+
if (input.returnTo !== void 0 && !isAllowedReturnTo(input.returnTo)) {
|
|
6650
|
+
throw new SecretRequestInputError("INVALID_RETURN_TO", "The return address is not an allowed Secret Manager callback.");
|
|
6651
|
+
}
|
|
6652
|
+
if (input.state !== void 0 && !STATE_RE.test(input.state)) {
|
|
6653
|
+
throw new SecretRequestInputError("INVALID_STATE", "The state must be 1-128 characters of A-Z, a-z, 0-9, '.', '_', '~' or '-'.");
|
|
6654
|
+
}
|
|
6655
|
+
const parameters = [
|
|
6656
|
+
["owner", owner],
|
|
6657
|
+
...names.map((name) => ["name", name]),
|
|
6658
|
+
...input.scope === void 0 ? [] : [["scope", input.scope]],
|
|
6659
|
+
...input.requester === void 0 ? [] : [["requester", input.requester]],
|
|
6660
|
+
...input.returnTo === void 0 ? [] : [["return_to", input.returnTo]],
|
|
6661
|
+
...input.state === void 0 ? [] : [["state", input.state]],
|
|
6662
|
+
["v", "1"]
|
|
6663
|
+
];
|
|
6664
|
+
const url = `${SECRET_MANAGER_ORIGIN}/request?${parameters.map(([key, value]) => `${key}=${encodeURIComponent(value)}`).join("&")}`;
|
|
6665
|
+
if (url.length > SECRET_REQUEST_MAX_URL_LENGTH) {
|
|
6666
|
+
throw new SecretRequestInputError("REQUEST_LINK_TOO_LONG", `The request link is longer than ${SECRET_REQUEST_MAX_URL_LENGTH} characters.`);
|
|
6667
|
+
}
|
|
6668
|
+
return { url, owner, names, ...input.scope === void 0 ? {} : { scope: input.scope } };
|
|
6669
|
+
}
|
|
6670
|
+
function secretSetupFor(link2) {
|
|
6671
|
+
return {
|
|
6672
|
+
url: link2.url,
|
|
6673
|
+
names: [...link2.names],
|
|
6674
|
+
...link2.scope === void 0 ? {} : { scope: link2.scope },
|
|
6675
|
+
owner: link2.owner,
|
|
6676
|
+
action: "add_secret"
|
|
6677
|
+
};
|
|
6678
|
+
}
|
|
6679
|
+
function resolveSecretsOwner(profile, requestedOwner) {
|
|
6680
|
+
const resolved = profile.local ? ownerOrUndefined(profile.principalDid) : ownerOrUndefined(profile.ownerDid) ?? (profile.posture === "delegate-session" ? ownerOfSpace(profile.space) : void 0) ?? ownerOrUndefined(profile.principalDid);
|
|
6681
|
+
const requested = requestedOwner === void 0 ? void 0 : ownerOrUndefined(requestedOwner);
|
|
6682
|
+
if (resolved !== void 0) {
|
|
6683
|
+
if (requestedOwner !== void 0 && requested !== resolved) {
|
|
6684
|
+
return {
|
|
6685
|
+
ok: false,
|
|
6686
|
+
code: "OWNER_MISMATCH",
|
|
6687
|
+
message: "The requested owner is not the owner of this identity's secrets."
|
|
6688
|
+
};
|
|
6689
|
+
}
|
|
6690
|
+
return { ok: true, owner: resolved, local: profile.local };
|
|
6691
|
+
}
|
|
6692
|
+
if (requested !== void 0 && !profile.local) return { ok: true, owner: requested, local: false };
|
|
6693
|
+
return {
|
|
6694
|
+
ok: false,
|
|
6695
|
+
code: "OWNER_DID_UNKNOWN",
|
|
6696
|
+
message: "The owner of this identity's secrets is unknown. Pass the owner's did:pkh with --owner."
|
|
6697
|
+
};
|
|
6698
|
+
}
|
|
6699
|
+
function missingSecretRecovery(input) {
|
|
6700
|
+
if (input.local) {
|
|
6701
|
+
return { kind: "put_locally", hint: `Store it with: ${putCommands(input.names, input.scope)}` };
|
|
6702
|
+
}
|
|
6703
|
+
if (input.owner !== void 0) {
|
|
6704
|
+
try {
|
|
6705
|
+
return {
|
|
6706
|
+
kind: "add_secret",
|
|
6707
|
+
setup: secretSetupFor(buildSecretRequestUrl({
|
|
6708
|
+
owner: input.owner,
|
|
6709
|
+
names: input.names,
|
|
6710
|
+
...input.scope === void 0 ? {} : { scope: input.scope }
|
|
6711
|
+
}))
|
|
6712
|
+
};
|
|
6713
|
+
} catch {
|
|
6714
|
+
}
|
|
6715
|
+
}
|
|
6716
|
+
return {
|
|
6717
|
+
kind: "not_requestable",
|
|
6718
|
+
hint: `No Secret Manager request link can express this secret. The owner can store it with: ${putCommands(input.names, input.scope)}`
|
|
6719
|
+
};
|
|
6720
|
+
}
|
|
6721
|
+
function isValidSecretRequestScope(scope) {
|
|
6722
|
+
return scope.length <= MAX_SCOPE_LENGTH && SCOPE_RE.test(scope) && !RESERVED_SCOPES.includes(scope);
|
|
6723
|
+
}
|
|
6724
|
+
function isValidSecretName(name) {
|
|
6725
|
+
return name.length <= MAX_NAME_LENGTH && NAME_RE.test(name);
|
|
6726
|
+
}
|
|
6727
|
+
function validSecretNames(names) {
|
|
6728
|
+
for (const name of names) assertSecretName(name);
|
|
6729
|
+
const unique = dedupe(names);
|
|
6730
|
+
if (unique.length === 0) {
|
|
6731
|
+
throw new SecretRequestInputError("INVALID_SECRET_NAME", "At least one secret name is required.");
|
|
6732
|
+
}
|
|
6733
|
+
if (unique.length > SECRET_REQUEST_MAX_NAMES) {
|
|
6734
|
+
throw new SecretRequestInputError("TOO_MANY_SECRET_NAMES", `At most ${SECRET_REQUEST_MAX_NAMES} secret names can be requested at once.`);
|
|
6735
|
+
}
|
|
6736
|
+
return unique;
|
|
6737
|
+
}
|
|
6738
|
+
function assertSecretName(name) {
|
|
6739
|
+
if (typeof name !== "string" || !isValidSecretName(name)) {
|
|
6740
|
+
throw new SecretRequestInputError("INVALID_SECRET_NAME", "Secret names are 1-64 characters of A-Z, 0-9 and '_', starting with a letter.");
|
|
6741
|
+
}
|
|
6742
|
+
}
|
|
6743
|
+
function assertSecretRequestScope(scope) {
|
|
6744
|
+
if (typeof scope !== "string" || !isValidSecretRequestScope(scope)) {
|
|
6745
|
+
throw new SecretRequestInputError("INVALID_SECRET_SCOPE", "The scope must be a canonical scope of at most 64 characters, not default, global or scoped.");
|
|
6746
|
+
}
|
|
6747
|
+
}
|
|
6748
|
+
function isAllowedReturnTo(returnTo) {
|
|
6749
|
+
if (typeof returnTo !== "string" || returnTo.length > MAX_RETURN_TO_LENGTH) return false;
|
|
6750
|
+
let url;
|
|
6751
|
+
try {
|
|
6752
|
+
url = new URL(returnTo);
|
|
6753
|
+
} catch {
|
|
6754
|
+
return false;
|
|
6755
|
+
}
|
|
6756
|
+
if (url.username !== "" || url.password !== "") return false;
|
|
6757
|
+
return RETURN_TO_ORIGINS.includes(url.origin) || RETURN_TO_PREVIEW.test(url.origin);
|
|
6758
|
+
}
|
|
6759
|
+
function ownerOrUndefined(did) {
|
|
6760
|
+
if (did === void 0) return void 0;
|
|
6761
|
+
try {
|
|
6762
|
+
return canonicalSecretRequestOwner(did);
|
|
6763
|
+
} catch {
|
|
6764
|
+
return void 0;
|
|
6765
|
+
}
|
|
6766
|
+
}
|
|
6767
|
+
function ownerOfSpace(space) {
|
|
6768
|
+
const match = space === void 0 ? null : PKH_SPACE_RE.exec(space);
|
|
6769
|
+
if (match === null) return void 0;
|
|
6770
|
+
return ownerOrUndefined(`did:pkh:eip155:${match[1]}:${match[2].toLowerCase()}`);
|
|
6771
|
+
}
|
|
6772
|
+
function putCommands(names, scope) {
|
|
6773
|
+
return dedupe(names).map((name) => `tc secrets put ${name}${scope === void 0 ? "" : ` --scope ${scope}`} --stdin`).join("; ");
|
|
6774
|
+
}
|
|
6775
|
+
function dedupe(names) {
|
|
6776
|
+
return [...new Set(names)];
|
|
6777
|
+
}
|
|
6778
|
+
function invalidOwner() {
|
|
6779
|
+
return new SecretRequestInputError("INVALID_OWNER", "The owner must be a did:pkh:eip155 account with a valid EIP-55 address.");
|
|
6780
|
+
}
|
|
6781
|
+
var nodeSdk3, SECRET_MANAGER_ORIGIN, SECRET_REQUEST_MAX_NAMES, SECRET_REQUEST_MAX_URL_LENGTH, OWNER_RE, NAME_RE, MAX_NAME_LENGTH, SCOPE_RE, MAX_SCOPE_LENGTH, RESERVED_SCOPES, MAX_REQUESTER_LENGTH, CONTROL_OR_FORMAT, STATE_RE, MAX_RETURN_TO_LENGTH, RETURN_TO_ORIGINS, RETURN_TO_PREVIEW, PKH_SPACE_RE, SecretRequestInputError;
|
|
6782
|
+
var init_secret_request = __esm({
|
|
6783
|
+
"src/secret-request.ts"() {
|
|
6784
|
+
"use strict";
|
|
6785
|
+
nodeSdk3 = __toESM(require("@tinycloud/node-sdk"), 1);
|
|
6786
|
+
SECRET_MANAGER_ORIGIN = "https://secrets.tinycloud.xyz";
|
|
6787
|
+
SECRET_REQUEST_MAX_NAMES = 10;
|
|
6788
|
+
SECRET_REQUEST_MAX_URL_LENGTH = 8192;
|
|
6789
|
+
OWNER_RE = /^did:pkh:eip155:([1-9][0-9]*):(0x[0-9a-fA-F]{40})$/;
|
|
6790
|
+
NAME_RE = /^[A-Z][A-Z0-9_]*$/;
|
|
6791
|
+
MAX_NAME_LENGTH = 64;
|
|
6792
|
+
SCOPE_RE = /^[a-z0-9]+(-[a-z0-9]+)*$/;
|
|
6793
|
+
MAX_SCOPE_LENGTH = 64;
|
|
6794
|
+
RESERVED_SCOPES = ["default", "global", "scoped"];
|
|
6795
|
+
MAX_REQUESTER_LENGTH = 64;
|
|
6796
|
+
CONTROL_OR_FORMAT = /[\p{Cc}\p{Cf}]/u;
|
|
6797
|
+
STATE_RE = /^[A-Za-z0-9._~-]{1,128}$/;
|
|
6798
|
+
MAX_RETURN_TO_LENGTH = 2048;
|
|
6799
|
+
RETURN_TO_ORIGINS = ["https://feed.tinycloud.xyz"];
|
|
6800
|
+
RETURN_TO_PREVIEW = /^https:\/\/[a-z0-9-]+\.tinyfeed\.pages\.dev$/;
|
|
6801
|
+
PKH_SPACE_RE = /^tinycloud:pkh:eip155:([1-9][0-9]*):(0x[0-9a-fA-F]{40}):[^:]+$/;
|
|
6802
|
+
SecretRequestInputError = class extends Error {
|
|
6803
|
+
constructor(code, message) {
|
|
6804
|
+
super(message);
|
|
6805
|
+
this.name = "SecretRequestInputError";
|
|
6806
|
+
this.code = code;
|
|
6807
|
+
}
|
|
6808
|
+
};
|
|
6809
|
+
}
|
|
6810
|
+
});
|
|
6811
|
+
|
|
6568
6812
|
// src/operations/secrets-get.ts
|
|
6569
6813
|
async function planSecretGet(context, input) {
|
|
6570
6814
|
const reference = resolveSecretReferenceForOperation(
|
|
@@ -6631,27 +6875,14 @@ async function executeSecretGet(context, input) {
|
|
|
6631
6875
|
)
|
|
6632
6876
|
};
|
|
6633
6877
|
}
|
|
6634
|
-
return classifySecretRead(reference, result);
|
|
6878
|
+
return classifySecretRead(reference, result, context.runtime?.localOwner === true);
|
|
6635
6879
|
}
|
|
6636
|
-
function classifySecretRead(reference, result) {
|
|
6880
|
+
function classifySecretRead(reference, result, localOwner) {
|
|
6637
6881
|
switch (result.status) {
|
|
6638
6882
|
case "ok":
|
|
6639
6883
|
return { status: "ok", output: { value: result.value } };
|
|
6640
6884
|
case "not_found":
|
|
6641
|
-
return
|
|
6642
|
-
status: "setup_required",
|
|
6643
|
-
setup: {
|
|
6644
|
-
kind: "secret_manager",
|
|
6645
|
-
secret: {
|
|
6646
|
-
name: reference.name,
|
|
6647
|
-
...reference.scope === void 0 ? {} : { scope: reference.scope },
|
|
6648
|
-
space: reference.space
|
|
6649
|
-
},
|
|
6650
|
-
url: buildSecretSetupUrl(reference),
|
|
6651
|
-
message: "Enter this secret in Secret Manager, then retry the operation."
|
|
6652
|
-
},
|
|
6653
|
-
requiresCallerInput: true
|
|
6654
|
-
};
|
|
6885
|
+
return missingSecretOutcome(reference, localOwner);
|
|
6655
6886
|
case "permission_required":
|
|
6656
6887
|
return {
|
|
6657
6888
|
status: "authority_required",
|
|
@@ -6696,6 +6927,47 @@ function classifySecretRead(reference, result) {
|
|
|
6696
6927
|
error: operationError("SECRET_READ_FAILED", "The secret read failed.")
|
|
6697
6928
|
};
|
|
6698
6929
|
}
|
|
6930
|
+
function missingSecretOutcome(reference, localOwner) {
|
|
6931
|
+
const owner = ownerOfSpace(reference.space);
|
|
6932
|
+
const recovery = missingSecretRecovery({
|
|
6933
|
+
owner,
|
|
6934
|
+
local: localOwner,
|
|
6935
|
+
names: [reference.name],
|
|
6936
|
+
...reference.scope === void 0 ? {} : { scope: reference.scope }
|
|
6937
|
+
});
|
|
6938
|
+
if (recovery.kind === "add_secret") {
|
|
6939
|
+
const { setup } = recovery;
|
|
6940
|
+
return {
|
|
6941
|
+
status: "setup_required",
|
|
6942
|
+
setup: {
|
|
6943
|
+
kind: "secret_manager",
|
|
6944
|
+
action: setup.action,
|
|
6945
|
+
url: setup.url,
|
|
6946
|
+
names: setup.names,
|
|
6947
|
+
...setup.scope === void 0 ? {} : { scope: setup.scope },
|
|
6948
|
+
owner: setup.owner,
|
|
6949
|
+
secret: {
|
|
6950
|
+
name: reference.name,
|
|
6951
|
+
...reference.scope === void 0 ? {} : { scope: reference.scope },
|
|
6952
|
+
space: reference.space
|
|
6953
|
+
},
|
|
6954
|
+
message: "Ask the owner to add this secret in Secret Manager, then retry the operation."
|
|
6955
|
+
},
|
|
6956
|
+
requiresCallerInput: true
|
|
6957
|
+
};
|
|
6958
|
+
}
|
|
6959
|
+
return {
|
|
6960
|
+
status: "error",
|
|
6961
|
+
error: operationError("KV_NOT_FOUND", recovery.hint, {
|
|
6962
|
+
details: {
|
|
6963
|
+
names: [reference.name],
|
|
6964
|
+
...reference.scope === void 0 ? {} : { scope: reference.scope },
|
|
6965
|
+
...owner === void 0 ? {} : { owner },
|
|
6966
|
+
recoveryKind: recovery.kind
|
|
6967
|
+
}
|
|
6968
|
+
})
|
|
6969
|
+
};
|
|
6970
|
+
}
|
|
6699
6971
|
function resolveEncryptionNetworkId(node, space) {
|
|
6700
6972
|
const candidate = node;
|
|
6701
6973
|
let scoped;
|
|
@@ -6723,6 +6995,7 @@ var init_secrets_get = __esm({
|
|
|
6723
6995
|
"use strict";
|
|
6724
6996
|
import_zod5 = require("zod");
|
|
6725
6997
|
init_errors2();
|
|
6998
|
+
init_secret_request();
|
|
6726
6999
|
init_secrets();
|
|
6727
7000
|
SecretsGetInputSchema = import_zod5.z.object({
|
|
6728
7001
|
name: import_zod5.z.string(),
|
|
@@ -6774,6 +7047,194 @@ var init_secrets_get = __esm({
|
|
|
6774
7047
|
}
|
|
6775
7048
|
});
|
|
6776
7049
|
|
|
7050
|
+
// src/operations/secrets-status.ts
|
|
7051
|
+
async function executeSecretsStatus(context, input) {
|
|
7052
|
+
const runtime = context.runtime;
|
|
7053
|
+
const node = runtime?.node;
|
|
7054
|
+
if (runtime === void 0 || typeof node?.kvForSpace !== "function") {
|
|
7055
|
+
return {
|
|
7056
|
+
status: "error",
|
|
7057
|
+
error: operationError("NODE_ERROR", "The TinyCloud node could not check the secrets.", { retryable: true })
|
|
7058
|
+
};
|
|
7059
|
+
}
|
|
7060
|
+
const local = runtime.localOwner === true;
|
|
7061
|
+
const resolution = resolveSecretsOwner({
|
|
7062
|
+
local,
|
|
7063
|
+
posture: context.summary.posture,
|
|
7064
|
+
...context.summary.ownerDid === void 0 ? {} : { ownerDid: context.summary.ownerDid },
|
|
7065
|
+
...context.summary.principalDid === void 0 ? {} : { principalDid: context.summary.principalDid },
|
|
7066
|
+
...context.summary.space === void 0 ? {} : { space: context.summary.space }
|
|
7067
|
+
}, input.owner);
|
|
7068
|
+
if (!resolution.ok) {
|
|
7069
|
+
return {
|
|
7070
|
+
status: "error",
|
|
7071
|
+
error: operationError("INPUT_INVALID", resolution.message, { details: { reason: resolution.code } })
|
|
7072
|
+
};
|
|
7073
|
+
}
|
|
7074
|
+
const owner = resolution.owner;
|
|
7075
|
+
const skipped2 = runtime.skippedGrantReasons ?? [];
|
|
7076
|
+
const pkh = nodeSdk4.parsePkhDid(owner);
|
|
7077
|
+
const kv = node.kvForSpace(nodeSdk4.makePkhSpaceId(pkh.address, pkh.chainId, "secrets"));
|
|
7078
|
+
const outcomes = await Promise.all(input.names.map(async (name) => {
|
|
7079
|
+
const path = input.scope === void 0 ? `vault/secrets/${name}` : `vault/secrets/scoped/${input.scope}/${name}`;
|
|
7080
|
+
try {
|
|
7081
|
+
const result = await kv.get(path, { raw: true, prefix: "", timeout: PROBE_TIMEOUT_MS });
|
|
7082
|
+
if (result.ok) return "present";
|
|
7083
|
+
const error = result.error;
|
|
7084
|
+
if (typeof error === "object" && error !== null && "code" in error && error.code === "KV_NOT_FOUND") {
|
|
7085
|
+
return "pending";
|
|
7086
|
+
}
|
|
7087
|
+
const refusal = kvRefusal(error);
|
|
7088
|
+
if (refusal === "auth_required") return "auth_required";
|
|
7089
|
+
if (refusal === "permission_denied") return "denied";
|
|
7090
|
+
return "unreachable";
|
|
7091
|
+
} catch {
|
|
7092
|
+
return "unreachable";
|
|
7093
|
+
}
|
|
7094
|
+
}));
|
|
7095
|
+
const namesWith = (outcome) => input.names.filter((_, index) => outcomes[index] === outcome);
|
|
7096
|
+
const present = namesWith("present");
|
|
7097
|
+
const pending = namesWith("pending");
|
|
7098
|
+
const denied = namesWith("denied");
|
|
7099
|
+
if (present.length + pending.length < input.names.length) {
|
|
7100
|
+
if (outcomes.includes("auth_required") || skipped2.includes("activation_unauthenticated")) {
|
|
7101
|
+
return {
|
|
7102
|
+
status: "error",
|
|
7103
|
+
error: operationError(
|
|
7104
|
+
"AUTH_REQUIRED",
|
|
7105
|
+
"The node did not accept this profile's stored session. Sign in again, then retry.",
|
|
7106
|
+
{ retryable: false, details: { recovery: signInRecovery(context.summary.profile, context.summary.posture) } }
|
|
7107
|
+
)
|
|
7108
|
+
};
|
|
7109
|
+
}
|
|
7110
|
+
if (outcomes.includes("unreachable") || skipped2.includes("activation_unavailable")) {
|
|
7111
|
+
return {
|
|
7112
|
+
status: "error",
|
|
7113
|
+
error: operationError("NODE_UNREACHABLE", "The TinyCloud node could not be reached.", { retryable: true })
|
|
7114
|
+
};
|
|
7115
|
+
}
|
|
7116
|
+
}
|
|
7117
|
+
const recovery = pending.length === 0 ? void 0 : missingSecretRecovery({
|
|
7118
|
+
owner,
|
|
7119
|
+
local,
|
|
7120
|
+
names: pending,
|
|
7121
|
+
...input.scope === void 0 ? {} : { scope: input.scope }
|
|
7122
|
+
});
|
|
7123
|
+
return {
|
|
7124
|
+
status: "ok",
|
|
7125
|
+
output: {
|
|
7126
|
+
status: denied.length > 0 ? "consent_required" : pending.length > 0 ? "pending" : "ready",
|
|
7127
|
+
owner,
|
|
7128
|
+
names: [...input.names],
|
|
7129
|
+
...input.scope === void 0 ? {} : { scope: input.scope },
|
|
7130
|
+
present,
|
|
7131
|
+
pending,
|
|
7132
|
+
denied,
|
|
7133
|
+
...recovery === void 0 ? {} : recovery.kind === "add_secret" ? { setup: recovery.setup } : { hint: recovery.hint }
|
|
7134
|
+
}
|
|
7135
|
+
};
|
|
7136
|
+
}
|
|
7137
|
+
var import_zod6, nodeSdk4, PROBE_TIMEOUT_MS, SECRETS_STATUS_DEADLINE_MS, SecretsStatusInputSchema, SecretSetupSchema, SecretsStatusOutputSchema, SECRETS_STATUS_POSTURES, SECRETS_STATUS_EXPOSURE, SECRETS_STATUS_SENSITIVITY, secretsStatusOperationDefinition, secretsStatusOperationDefinitions;
|
|
7138
|
+
var init_secrets_status = __esm({
|
|
7139
|
+
"src/operations/secrets-status.ts"() {
|
|
7140
|
+
"use strict";
|
|
7141
|
+
import_zod6 = require("zod");
|
|
7142
|
+
nodeSdk4 = __toESM(require("@tinycloud/node-sdk"), 1);
|
|
7143
|
+
init_errors2();
|
|
7144
|
+
init_kv_failure();
|
|
7145
|
+
init_recovery();
|
|
7146
|
+
init_secret_request();
|
|
7147
|
+
init_secrets();
|
|
7148
|
+
PROBE_TIMEOUT_MS = 15e3;
|
|
7149
|
+
SECRETS_STATUS_DEADLINE_MS = 18e3;
|
|
7150
|
+
SecretsStatusInputSchema = import_zod6.z.object({
|
|
7151
|
+
names: import_zod6.z.array(import_zod6.z.string()),
|
|
7152
|
+
scope: import_zod6.z.string().optional(),
|
|
7153
|
+
owner: import_zod6.z.string().optional()
|
|
7154
|
+
}).strict().superRefine((input, context) => {
|
|
7155
|
+
try {
|
|
7156
|
+
validSecretNames(input.names);
|
|
7157
|
+
} catch {
|
|
7158
|
+
context.addIssue({ code: import_zod6.z.ZodIssueCode.custom, path: ["names"], message: "Invalid secret names." });
|
|
7159
|
+
}
|
|
7160
|
+
try {
|
|
7161
|
+
const scope = canonicalizeSecretScope(input.scope);
|
|
7162
|
+
if (scope !== void 0 && !isValidSecretRequestScope(scope)) throw new Error("invalid scope");
|
|
7163
|
+
} catch {
|
|
7164
|
+
context.addIssue({ code: import_zod6.z.ZodIssueCode.custom, path: ["scope"], message: "Invalid secret scope." });
|
|
7165
|
+
}
|
|
7166
|
+
if (input.owner !== void 0) {
|
|
7167
|
+
try {
|
|
7168
|
+
canonicalSecretRequestOwner(input.owner);
|
|
7169
|
+
} catch {
|
|
7170
|
+
context.addIssue({ code: import_zod6.z.ZodIssueCode.custom, path: ["owner"], message: "Invalid owner." });
|
|
7171
|
+
}
|
|
7172
|
+
}
|
|
7173
|
+
}).transform((input) => {
|
|
7174
|
+
const scope = canonicalizeSecretScope(input.scope);
|
|
7175
|
+
return {
|
|
7176
|
+
names: validSecretNames(input.names),
|
|
7177
|
+
...scope === void 0 ? {} : { scope },
|
|
7178
|
+
...input.owner === void 0 ? {} : { owner: canonicalSecretRequestOwner(input.owner) }
|
|
7179
|
+
};
|
|
7180
|
+
});
|
|
7181
|
+
SecretSetupSchema = import_zod6.z.object({
|
|
7182
|
+
url: import_zod6.z.string().url(),
|
|
7183
|
+
names: import_zod6.z.array(import_zod6.z.string()).min(1),
|
|
7184
|
+
scope: import_zod6.z.string().optional(),
|
|
7185
|
+
owner: import_zod6.z.string(),
|
|
7186
|
+
action: import_zod6.z.literal("add_secret")
|
|
7187
|
+
}).strict();
|
|
7188
|
+
SecretsStatusOutputSchema = import_zod6.z.object({
|
|
7189
|
+
status: import_zod6.z.enum(["ready", "pending", "consent_required"]),
|
|
7190
|
+
owner: import_zod6.z.string(),
|
|
7191
|
+
names: import_zod6.z.array(import_zod6.z.string()).min(1),
|
|
7192
|
+
scope: import_zod6.z.string().optional(),
|
|
7193
|
+
present: import_zod6.z.array(import_zod6.z.string()),
|
|
7194
|
+
pending: import_zod6.z.array(import_zod6.z.string()),
|
|
7195
|
+
denied: import_zod6.z.array(import_zod6.z.string()),
|
|
7196
|
+
setup: SecretSetupSchema.optional(),
|
|
7197
|
+
hint: import_zod6.z.string().optional()
|
|
7198
|
+
}).strict();
|
|
7199
|
+
SECRETS_STATUS_POSTURES = [
|
|
7200
|
+
"owner-openkey",
|
|
7201
|
+
"delegate-session",
|
|
7202
|
+
"local-owner-key"
|
|
7203
|
+
];
|
|
7204
|
+
SECRETS_STATUS_EXPOSURE = {
|
|
7205
|
+
cli: { status: "required" },
|
|
7206
|
+
mcp: { status: "required" },
|
|
7207
|
+
skill: { status: "required" },
|
|
7208
|
+
docs: { status: "required" }
|
|
7209
|
+
};
|
|
7210
|
+
SECRETS_STATUS_SENSITIVITY = {
|
|
7211
|
+
input: [],
|
|
7212
|
+
output: []
|
|
7213
|
+
};
|
|
7214
|
+
secretsStatusOperationDefinition = {
|
|
7215
|
+
id: "tinycloud.secrets.status",
|
|
7216
|
+
version: 1,
|
|
7217
|
+
title: "Check whether TinyCloud secrets exist",
|
|
7218
|
+
description: "Report, without reading any value, which named secrets exist in the owner's secrets space: ready, pending (with a Secret Manager request link), or consent_required for names this identity may not read. Each name needs tinycloud.kv/get; this operation never requests it. It never signs in: it uses only the profile's stored session, and writes no profile state.",
|
|
7219
|
+
input: SecretsStatusInputSchema,
|
|
7220
|
+
output: SecretsStatusOutputSchema,
|
|
7221
|
+
effects: ["read"],
|
|
7222
|
+
runtime: "restored",
|
|
7223
|
+
postures: SECRETS_STATUS_POSTURES,
|
|
7224
|
+
exposure: SECRETS_STATUS_EXPOSURE,
|
|
7225
|
+
sensitivity: SECRETS_STATUS_SENSITIVITY,
|
|
7226
|
+
deadlineMs: SECRETS_STATUS_DEADLINE_MS,
|
|
7227
|
+
// Never evaluated against the session: a missing grant is reported as
|
|
7228
|
+
// `consent_required`, never saved as an authority request.
|
|
7229
|
+
authority: async () => [],
|
|
7230
|
+
execute: executeSecretsStatus
|
|
7231
|
+
};
|
|
7232
|
+
secretsStatusOperationDefinitions = [
|
|
7233
|
+
secretsStatusOperationDefinition
|
|
7234
|
+
];
|
|
7235
|
+
}
|
|
7236
|
+
});
|
|
7237
|
+
|
|
6777
7238
|
// src/operations/sql.ts
|
|
6778
7239
|
async function planSqlRead(context, input) {
|
|
6779
7240
|
const space = resolveSqlSpace(context, input.space);
|
|
@@ -7086,15 +7547,15 @@ function isByte(value) {
|
|
|
7086
7547
|
function isRecord3(value) {
|
|
7087
7548
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
7088
7549
|
}
|
|
7089
|
-
var import_node_sql_parser,
|
|
7550
|
+
var import_node_sql_parser, import_zod7, DEFAULT_MAX_ROWS, MAX_MAX_ROWS, DEFAULT_MAX_BYTES, MAX_MAX_BYTES, SCHEMA_MAX_ROWS, SCHEMA_MAX_BYTES, MAX_PARAMETERS, MAX_SQL_LENGTH, SQL_WRITE_AUTHORITY_NOTICE, SCHEMA_QUERY, sqlParser, SpaceSchema2, DatabaseSchema, SafeNumberSchema, Base64Schema, SqlInputValueSchema, SqlParamsSchema, RequiredSqlParamsSchema, SqlOutputValueSchema, SqlTargetInputSchema, SqlQueryInputSchema, SqlExecuteInputSchema, SqlLimitsOutputSchema, SqlSchemaInspectOutputSchema, SqlQueryOutputSchema, SqlExecuteOutputSchema, AUTHENTICATED_POSTURES2, SQL_EXPOSURE, SQL_SCHEMA_SENSITIVITY, SQL_QUERY_SENSITIVITY, SQL_EXECUTE_SENSITIVITY, sqlOperationDefinitions;
|
|
7090
7551
|
var init_sql = __esm({
|
|
7091
7552
|
"src/operations/sql.ts"() {
|
|
7092
7553
|
"use strict";
|
|
7093
7554
|
import_node_sql_parser = __toESM(require("node-sql-parser"), 1);
|
|
7094
|
-
|
|
7555
|
+
import_zod7 = require("zod");
|
|
7095
7556
|
init_errors2();
|
|
7096
7557
|
init_secrets();
|
|
7097
|
-
|
|
7558
|
+
init_kv_failure();
|
|
7098
7559
|
DEFAULT_MAX_ROWS = 100;
|
|
7099
7560
|
MAX_MAX_ROWS = 1e3;
|
|
7100
7561
|
DEFAULT_MAX_BYTES = 1024 * 1024;
|
|
@@ -7110,29 +7571,29 @@ WHERE type IN ('table', 'view', 'index', 'trigger')
|
|
|
7110
7571
|
AND name NOT LIKE 'sqlite_%'
|
|
7111
7572
|
ORDER BY type, name`;
|
|
7112
7573
|
sqlParser = new import_node_sql_parser.default.Parser();
|
|
7113
|
-
SpaceSchema2 =
|
|
7574
|
+
SpaceSchema2 = import_zod7.z.string().min(1).refine(
|
|
7114
7575
|
(space) => (/^[A-Za-z0-9_-]+$/.test(space) || space.startsWith("tinycloud:")) && !space.includes("*"),
|
|
7115
7576
|
"Invalid TinyCloud space."
|
|
7116
7577
|
);
|
|
7117
|
-
DatabaseSchema =
|
|
7578
|
+
DatabaseSchema = import_zod7.z.string().min(1).max(256).refine(
|
|
7118
7579
|
(database) => database !== "/" && !database.endsWith("/") && !database.includes("*") && !/[\u0000-\u001f\u007f]/.test(database),
|
|
7119
7580
|
"Invalid SQLite database name."
|
|
7120
7581
|
);
|
|
7121
|
-
SafeNumberSchema =
|
|
7582
|
+
SafeNumberSchema = import_zod7.z.number().finite().refine(
|
|
7122
7583
|
(value) => !Number.isInteger(value) || Number.isSafeInteger(value),
|
|
7123
7584
|
"SQLite integer parameters must be JavaScript safe integers."
|
|
7124
7585
|
);
|
|
7125
|
-
Base64Schema =
|
|
7586
|
+
Base64Schema = import_zod7.z.string().max(Math.ceil(MAX_MAX_BYTES / 3) * 4).refine(
|
|
7126
7587
|
isCanonicalBase642,
|
|
7127
7588
|
"Invalid base64 BLOB value."
|
|
7128
7589
|
);
|
|
7129
|
-
SqlInputValueSchema =
|
|
7130
|
-
|
|
7590
|
+
SqlInputValueSchema = import_zod7.z.union([
|
|
7591
|
+
import_zod7.z.null(),
|
|
7131
7592
|
SafeNumberSchema,
|
|
7132
|
-
|
|
7133
|
-
|
|
7593
|
+
import_zod7.z.string().max(MAX_MAX_BYTES),
|
|
7594
|
+
import_zod7.z.object({ type: import_zod7.z.literal("blob"), base64: Base64Schema }).strict()
|
|
7134
7595
|
]);
|
|
7135
|
-
SqlParamsSchema =
|
|
7596
|
+
SqlParamsSchema = import_zod7.z.array(SqlInputValueSchema).max(MAX_PARAMETERS).superRefine(
|
|
7136
7597
|
(params, context) => {
|
|
7137
7598
|
const totalBytes = params.reduce(
|
|
7138
7599
|
(total, value) => total + sqlInputValueBytes(value),
|
|
@@ -7140,13 +7601,13 @@ ORDER BY type, name`;
|
|
|
7140
7601
|
);
|
|
7141
7602
|
if (totalBytes > MAX_MAX_BYTES) {
|
|
7142
7603
|
context.addIssue({
|
|
7143
|
-
code:
|
|
7604
|
+
code: import_zod7.z.ZodIssueCode.custom,
|
|
7144
7605
|
message: "SQLite query parameters exceed the 4 MiB input limit."
|
|
7145
7606
|
});
|
|
7146
7607
|
}
|
|
7147
7608
|
}
|
|
7148
7609
|
);
|
|
7149
|
-
RequiredSqlParamsSchema =
|
|
7610
|
+
RequiredSqlParamsSchema = import_zod7.z.array(SqlInputValueSchema).min(1).max(MAX_PARAMETERS).superRefine(
|
|
7150
7611
|
(params, context) => {
|
|
7151
7612
|
const totalBytes = params.reduce(
|
|
7152
7613
|
(total, value) => total + sqlInputValueBytes(value),
|
|
@@ -7154,88 +7615,88 @@ ORDER BY type, name`;
|
|
|
7154
7615
|
);
|
|
7155
7616
|
if (totalBytes > MAX_MAX_BYTES) {
|
|
7156
7617
|
context.addIssue({
|
|
7157
|
-
code:
|
|
7618
|
+
code: import_zod7.z.ZodIssueCode.custom,
|
|
7158
7619
|
message: "SQLite query parameters exceed the 4 MiB input limit."
|
|
7159
7620
|
});
|
|
7160
7621
|
}
|
|
7161
7622
|
}
|
|
7162
7623
|
);
|
|
7163
|
-
SqlOutputValueSchema =
|
|
7164
|
-
|
|
7624
|
+
SqlOutputValueSchema = import_zod7.z.union([
|
|
7625
|
+
import_zod7.z.null(),
|
|
7165
7626
|
SafeNumberSchema,
|
|
7166
|
-
|
|
7167
|
-
|
|
7168
|
-
type:
|
|
7169
|
-
base64:
|
|
7170
|
-
byteLength:
|
|
7627
|
+
import_zod7.z.string(),
|
|
7628
|
+
import_zod7.z.object({
|
|
7629
|
+
type: import_zod7.z.literal("blob"),
|
|
7630
|
+
base64: import_zod7.z.string(),
|
|
7631
|
+
byteLength: import_zod7.z.number().int().nonnegative()
|
|
7171
7632
|
}).strict()
|
|
7172
7633
|
]);
|
|
7173
|
-
SqlTargetInputSchema =
|
|
7634
|
+
SqlTargetInputSchema = import_zod7.z.object({
|
|
7174
7635
|
space: SpaceSchema2,
|
|
7175
7636
|
database: DatabaseSchema
|
|
7176
7637
|
}).strict();
|
|
7177
|
-
SqlQueryInputSchema =
|
|
7638
|
+
SqlQueryInputSchema = import_zod7.z.object({
|
|
7178
7639
|
space: SpaceSchema2,
|
|
7179
7640
|
database: DatabaseSchema,
|
|
7180
|
-
sql:
|
|
7641
|
+
sql: import_zod7.z.string().min(1).max(MAX_SQL_LENGTH).superRefine((sql, context) => {
|
|
7181
7642
|
if (!isSingleReadQuery(sql)) {
|
|
7182
7643
|
context.addIssue({
|
|
7183
|
-
code:
|
|
7644
|
+
code: import_zod7.z.ZodIssueCode.custom,
|
|
7184
7645
|
message: "SQL must parse as exactly one SQLite SELECT statement."
|
|
7185
7646
|
});
|
|
7186
7647
|
}
|
|
7187
7648
|
}),
|
|
7188
7649
|
params: SqlParamsSchema.optional(),
|
|
7189
|
-
maxRows:
|
|
7190
|
-
maxBytes:
|
|
7650
|
+
maxRows: import_zod7.z.number().int().positive().max(MAX_MAX_ROWS).optional(),
|
|
7651
|
+
maxBytes: import_zod7.z.number().int().positive().max(MAX_MAX_BYTES).optional()
|
|
7191
7652
|
}).strict();
|
|
7192
|
-
SqlExecuteInputSchema =
|
|
7653
|
+
SqlExecuteInputSchema = import_zod7.z.object({
|
|
7193
7654
|
space: SpaceSchema2,
|
|
7194
7655
|
database: DatabaseSchema,
|
|
7195
|
-
sql:
|
|
7656
|
+
sql: import_zod7.z.string().min(1).max(MAX_SQL_LENGTH),
|
|
7196
7657
|
params: RequiredSqlParamsSchema,
|
|
7197
|
-
acknowledgeDatabaseWideAuthority:
|
|
7658
|
+
acknowledgeDatabaseWideAuthority: import_zod7.z.literal(true).describe(SQL_WRITE_AUTHORITY_NOTICE)
|
|
7198
7659
|
}).strict().superRefine((input, context) => {
|
|
7199
7660
|
if (parseSingleDmlStatement(input.sql, input.params.length) === void 0) {
|
|
7200
7661
|
context.addIssue({
|
|
7201
|
-
code:
|
|
7662
|
+
code: import_zod7.z.ZodIssueCode.custom,
|
|
7202
7663
|
path: ["sql"],
|
|
7203
7664
|
message: "SQL must parse as exactly one parameterized INSERT, UPDATE, or DELETE with one value per positional placeholder."
|
|
7204
7665
|
});
|
|
7205
7666
|
}
|
|
7206
7667
|
});
|
|
7207
|
-
SqlLimitsOutputSchema =
|
|
7208
|
-
maxRows:
|
|
7209
|
-
maxBytes:
|
|
7210
|
-
enforcement:
|
|
7668
|
+
SqlLimitsOutputSchema = import_zod7.z.object({
|
|
7669
|
+
maxRows: import_zod7.z.number().int().positive(),
|
|
7670
|
+
maxBytes: import_zod7.z.number().int().positive(),
|
|
7671
|
+
enforcement: import_zod7.z.literal("node-requested-client-verified")
|
|
7211
7672
|
}).strict();
|
|
7212
|
-
SqlSchemaInspectOutputSchema =
|
|
7213
|
-
space:
|
|
7214
|
-
database:
|
|
7215
|
-
objects:
|
|
7216
|
-
type:
|
|
7217
|
-
name:
|
|
7218
|
-
tableName:
|
|
7219
|
-
sql:
|
|
7673
|
+
SqlSchemaInspectOutputSchema = import_zod7.z.object({
|
|
7674
|
+
space: import_zod7.z.string().min(1),
|
|
7675
|
+
database: import_zod7.z.string().min(1),
|
|
7676
|
+
objects: import_zod7.z.array(import_zod7.z.object({
|
|
7677
|
+
type: import_zod7.z.enum(["table", "view", "index", "trigger"]),
|
|
7678
|
+
name: import_zod7.z.string().min(1),
|
|
7679
|
+
tableName: import_zod7.z.string().min(1),
|
|
7680
|
+
sql: import_zod7.z.string().optional()
|
|
7220
7681
|
}).strict()),
|
|
7221
|
-
count:
|
|
7682
|
+
count: import_zod7.z.number().int().nonnegative(),
|
|
7222
7683
|
limits: SqlLimitsOutputSchema
|
|
7223
7684
|
}).strict();
|
|
7224
|
-
SqlQueryOutputSchema =
|
|
7225
|
-
space:
|
|
7226
|
-
database:
|
|
7227
|
-
columns:
|
|
7228
|
-
rows:
|
|
7229
|
-
rowCount:
|
|
7685
|
+
SqlQueryOutputSchema = import_zod7.z.object({
|
|
7686
|
+
space: import_zod7.z.string().min(1),
|
|
7687
|
+
database: import_zod7.z.string().min(1),
|
|
7688
|
+
columns: import_zod7.z.array(import_zod7.z.string()),
|
|
7689
|
+
rows: import_zod7.z.array(import_zod7.z.array(SqlOutputValueSchema)),
|
|
7690
|
+
rowCount: import_zod7.z.number().int().nonnegative(),
|
|
7230
7691
|
limits: SqlLimitsOutputSchema
|
|
7231
7692
|
}).strict();
|
|
7232
|
-
SqlExecuteOutputSchema =
|
|
7233
|
-
space:
|
|
7234
|
-
database:
|
|
7235
|
-
statementType:
|
|
7236
|
-
changes:
|
|
7237
|
-
lastInsertRowId:
|
|
7238
|
-
authorityNotice:
|
|
7693
|
+
SqlExecuteOutputSchema = import_zod7.z.object({
|
|
7694
|
+
space: import_zod7.z.string().min(1),
|
|
7695
|
+
database: import_zod7.z.string().min(1),
|
|
7696
|
+
statementType: import_zod7.z.enum(["insert", "update", "delete"]),
|
|
7697
|
+
changes: import_zod7.z.number().int().nonnegative(),
|
|
7698
|
+
lastInsertRowId: import_zod7.z.number().int().nullable(),
|
|
7699
|
+
authorityNotice: import_zod7.z.literal(SQL_WRITE_AUTHORITY_NOTICE)
|
|
7239
7700
|
}).strict();
|
|
7240
7701
|
AUTHENTICATED_POSTURES2 = [
|
|
7241
7702
|
"owner-openkey",
|
|
@@ -7335,6 +7796,8 @@ var init_contract = __esm({
|
|
|
7335
7796
|
"resources_mismatch",
|
|
7336
7797
|
"unsupported",
|
|
7337
7798
|
"activation_rejected",
|
|
7799
|
+
"activation_unavailable",
|
|
7800
|
+
"activation_unauthenticated",
|
|
7338
7801
|
"invalid"
|
|
7339
7802
|
];
|
|
7340
7803
|
DELEGATION_CID_PATTERN = "^bafkr4i[a-z2-7]{52}$";
|
|
@@ -7437,6 +7900,9 @@ function skipped(reason) {
|
|
|
7437
7900
|
}
|
|
7438
7901
|
async function replayProfileDelegations(profile, node, options) {
|
|
7439
7902
|
await prepareStoredDelegationReplay(profile, node, { host: options.host, migrate: options.migrate });
|
|
7903
|
+
return replayStoredDelegationRecords(profile, node, options);
|
|
7904
|
+
}
|
|
7905
|
+
async function replayStoredDelegationRecords(profile, node, options) {
|
|
7440
7906
|
const installed = [];
|
|
7441
7907
|
const warnings = [];
|
|
7442
7908
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -7477,7 +7943,7 @@ function storedDelegationForAnotherKey(entry, node) {
|
|
|
7477
7943
|
const audience = verifiedCompactAudience(node, delegation);
|
|
7478
7944
|
if (audience === void 0) return false;
|
|
7479
7945
|
try {
|
|
7480
|
-
return
|
|
7946
|
+
return nodeSdk5.principalDidEquals(delegation.delegateDID, audience) && !nodeSdk5.principalDidEquals(audience, node.sessionDid);
|
|
7481
7947
|
} catch {
|
|
7482
7948
|
return false;
|
|
7483
7949
|
}
|
|
@@ -7511,7 +7977,7 @@ async function assess(node, entry, options, mode) {
|
|
|
7511
7977
|
let outsideRequest = false;
|
|
7512
7978
|
let effectivePermissions;
|
|
7513
7979
|
try {
|
|
7514
|
-
const installed = await
|
|
7980
|
+
const installed = await nodeSdk5.activateValidatedRuntimeDelegation(node, toActivate, {
|
|
7515
7981
|
host: options.host,
|
|
7516
7982
|
authorize: (effective) => {
|
|
7517
7983
|
verifyCompactProof(toActivate);
|
|
@@ -7543,7 +8009,7 @@ function verifyCompactProof(delegation) {
|
|
|
7543
8009
|
try {
|
|
7544
8010
|
parseSignedCompactUcanAttenuation(withoutBearer(authorization), delegation.cid);
|
|
7545
8011
|
} catch {
|
|
7546
|
-
throw new
|
|
8012
|
+
throw new nodeSdk5.RuntimeDelegationRejectedError("proof_invalid", "The compact delegation proof is invalid.");
|
|
7547
8013
|
}
|
|
7548
8014
|
}
|
|
7549
8015
|
function rejectionReason(error) {
|
|
@@ -7560,7 +8026,7 @@ async function bindingMigrationRecorded(profile) {
|
|
|
7560
8026
|
async function signedCapabilities(node, delegation, host) {
|
|
7561
8027
|
let signed;
|
|
7562
8028
|
try {
|
|
7563
|
-
await
|
|
8029
|
+
await nodeSdk5.activateValidatedRuntimeDelegation(node, delegation, {
|
|
7564
8030
|
// The transport host is not signed authority; check it at replay instead.
|
|
7565
8031
|
host: delegation.host ?? host,
|
|
7566
8032
|
authorize: (effective) => {
|
|
@@ -7595,13 +8061,13 @@ function recordKey(entry) {
|
|
|
7595
8061
|
function isRecord4(value) {
|
|
7596
8062
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
7597
8063
|
}
|
|
7598
|
-
var import_node_path2,
|
|
8064
|
+
var import_node_path2, nodeSdk5, REQUEST_ID_PREFIX, BINDING_NOTES, MIGRATION_LOCK_TIMEOUT_MS, NOT_REPLAYED, DELEGATION_CID;
|
|
7599
8065
|
var init_delegation_binding = __esm({
|
|
7600
8066
|
"src/delegation-binding.ts"() {
|
|
7601
8067
|
"use strict";
|
|
7602
8068
|
import_node_path2 = require("path");
|
|
7603
8069
|
init_operations_bundle();
|
|
7604
|
-
|
|
8070
|
+
nodeSdk5 = __toESM(require("@tinycloud/node-sdk"), 1);
|
|
7605
8071
|
init_artifacts();
|
|
7606
8072
|
init_authority();
|
|
7607
8073
|
init_contract();
|
|
@@ -7742,35 +8208,35 @@ function profileNotFound(profile) {
|
|
|
7742
8208
|
function isRecord5(value) {
|
|
7743
8209
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
7744
8210
|
}
|
|
7745
|
-
var
|
|
8211
|
+
var import_zod8, StatusInputSchema, StatusOutputSchema, STATUS_POSTURES, STATUS_EXPOSURE, STATUS_SENSITIVITY, statusOperationDefinitions;
|
|
7746
8212
|
var init_status = __esm({
|
|
7747
8213
|
"src/operations/status.ts"() {
|
|
7748
8214
|
"use strict";
|
|
7749
|
-
|
|
8215
|
+
import_zod8 = require("zod");
|
|
7750
8216
|
init_delegation_binding();
|
|
7751
8217
|
init_errors2();
|
|
7752
8218
|
init_state();
|
|
7753
|
-
StatusInputSchema =
|
|
7754
|
-
StatusOutputSchema =
|
|
7755
|
-
profile:
|
|
7756
|
-
host:
|
|
7757
|
-
posture:
|
|
8219
|
+
StatusInputSchema = import_zod8.z.object({}).strict();
|
|
8220
|
+
StatusOutputSchema = import_zod8.z.object({
|
|
8221
|
+
profile: import_zod8.z.string().min(1),
|
|
8222
|
+
host: import_zod8.z.string().min(1),
|
|
8223
|
+
posture: import_zod8.z.enum([
|
|
7758
8224
|
"owner-openkey",
|
|
7759
8225
|
"delegate-session",
|
|
7760
8226
|
"local-owner-key",
|
|
7761
8227
|
"unauthenticated"
|
|
7762
8228
|
]),
|
|
7763
|
-
operatorType:
|
|
7764
|
-
principalDid:
|
|
7765
|
-
sessionDid:
|
|
7766
|
-
ownerDid:
|
|
7767
|
-
space:
|
|
7768
|
-
session:
|
|
7769
|
-
present:
|
|
7770
|
-
expired:
|
|
7771
|
-
expiresAt:
|
|
8229
|
+
operatorType: import_zod8.z.enum(["human", "agent"]).optional(),
|
|
8230
|
+
principalDid: import_zod8.z.string().min(1).optional(),
|
|
8231
|
+
sessionDid: import_zod8.z.string().min(1).optional(),
|
|
8232
|
+
ownerDid: import_zod8.z.string().min(1).optional(),
|
|
8233
|
+
space: import_zod8.z.string().min(1).optional(),
|
|
8234
|
+
session: import_zod8.z.object({
|
|
8235
|
+
present: import_zod8.z.boolean(),
|
|
8236
|
+
expired: import_zod8.z.boolean().nullable(),
|
|
8237
|
+
expiresAt: import_zod8.z.string().datetime({ offset: true }).nullable()
|
|
7772
8238
|
}).strict(),
|
|
7773
|
-
liveAdditionalDelegationCount:
|
|
8239
|
+
liveAdditionalDelegationCount: import_zod8.z.number().int().nonnegative().describe(
|
|
7774
8240
|
"Stored, unexpired compact-UCAN or signed-login delegations with a valid request binding. Each still requires local proof validation and node activation before it grants authority."
|
|
7775
8241
|
)
|
|
7776
8242
|
}).strict();
|
|
@@ -7814,7 +8280,8 @@ function registeredOperationDefinitions() {
|
|
|
7814
8280
|
...authOperationDefinitions,
|
|
7815
8281
|
...explorationOperationDefinitions,
|
|
7816
8282
|
...sqlOperationDefinitions,
|
|
7817
|
-
...secretsGetOperationDefinitions
|
|
8283
|
+
...secretsGetOperationDefinitions,
|
|
8284
|
+
...secretsStatusOperationDefinitions
|
|
7818
8285
|
]);
|
|
7819
8286
|
return operationDefinitions;
|
|
7820
8287
|
}
|
|
@@ -7846,6 +8313,7 @@ var init_registry = __esm({
|
|
|
7846
8313
|
init_auth();
|
|
7847
8314
|
init_exploration();
|
|
7848
8315
|
init_secrets_get();
|
|
8316
|
+
init_secrets_status();
|
|
7849
8317
|
init_sql();
|
|
7850
8318
|
init_status();
|
|
7851
8319
|
}
|
|
@@ -7898,6 +8366,9 @@ function resolvePosture(profile) {
|
|
|
7898
8366
|
if (profile.authMethod === "local") return "local-owner-key";
|
|
7899
8367
|
return "owner-openkey";
|
|
7900
8368
|
}
|
|
8369
|
+
function isLocalOwnerProfile(profile) {
|
|
8370
|
+
return resolvePosture(profile) === "local-owner-key" || profile.authMethod === "local" || typeof profile.privateKey === "string";
|
|
8371
|
+
}
|
|
7901
8372
|
function profileNotFound2(profile) {
|
|
7902
8373
|
return {
|
|
7903
8374
|
ok: false,
|
|
@@ -7982,11 +8453,14 @@ async function createInvocationRuntime(target, requirement = "authenticated") {
|
|
|
7982
8453
|
if (requirement === "inspection") {
|
|
7983
8454
|
return { ok: true, context: { summary } };
|
|
7984
8455
|
}
|
|
8456
|
+
if (requirement === "restored") {
|
|
8457
|
+
return createRestoredRuntime(target, resolved);
|
|
8458
|
+
}
|
|
7985
8459
|
const profileName = summary.profile;
|
|
7986
8460
|
try {
|
|
7987
8461
|
const {
|
|
7988
8462
|
TinyCloudNode: TinyCloudNodeConstructor
|
|
7989
|
-
} =
|
|
8463
|
+
} = nodeSdk6;
|
|
7990
8464
|
const explicitPrivateKeyOverride = typeof target.privateKey === "string";
|
|
7991
8465
|
const [session, key] = explicitPrivateKeyOverride ? [null, null] : await Promise.all([
|
|
7992
8466
|
readSession(profileName),
|
|
@@ -8064,7 +8538,9 @@ async function createInvocationRuntime(target, requirement = "authenticated") {
|
|
|
8064
8538
|
const runtime = {
|
|
8065
8539
|
node,
|
|
8066
8540
|
granted: canonicalizeCapabilities(livePermissions),
|
|
8067
|
-
...warnings.length === 0 ? {} : { warnings }
|
|
8541
|
+
...warnings.length === 0 ? {} : { warnings },
|
|
8542
|
+
localOwner: explicitPrivateKeyOverride || isLocalOwnerProfile(profile),
|
|
8543
|
+
skippedGrantReasons: warnings.map((warning) => warning.reason)
|
|
8068
8544
|
};
|
|
8069
8545
|
return {
|
|
8070
8546
|
ok: true,
|
|
@@ -8088,11 +8564,112 @@ async function createInvocationRuntime(target, requirement = "authenticated") {
|
|
|
8088
8564
|
));
|
|
8089
8565
|
}
|
|
8090
8566
|
}
|
|
8567
|
+
async function createRestoredRuntime(target, resolved) {
|
|
8568
|
+
const summary = resolved.context;
|
|
8569
|
+
const profileName = summary.profile;
|
|
8570
|
+
const profile = resolved.profile;
|
|
8571
|
+
if (typeof target.privateKey === "string") {
|
|
8572
|
+
return failed(summary, operationError(
|
|
8573
|
+
"AUTH_REQUIRED",
|
|
8574
|
+
"This operation never signs in; an explicit private key has no stored session.",
|
|
8575
|
+
{ details: { reason: "explicit_key" } }
|
|
8576
|
+
));
|
|
8577
|
+
}
|
|
8578
|
+
try {
|
|
8579
|
+
const actualPosture = resolvePosture(profile);
|
|
8580
|
+
const selectedPosture = profile.authMethod === "local" ? "local-owner-key" : summary.posture;
|
|
8581
|
+
if (actualPosture !== summary.posture || selectedPosture !== summary.posture) {
|
|
8582
|
+
return failed(
|
|
8583
|
+
{ ...summary, posture: actualPosture !== summary.posture ? actualPosture : selectedPosture },
|
|
8584
|
+
operationError(
|
|
8585
|
+
"PROFILE_POSTURE_NOT_ALLOWED",
|
|
8586
|
+
"The selected profile changed posture during runtime resolution."
|
|
8587
|
+
)
|
|
8588
|
+
);
|
|
8589
|
+
}
|
|
8590
|
+
const [session, key] = await Promise.all([
|
|
8591
|
+
readSession(profileName),
|
|
8592
|
+
readJson(`${profilePath(profileName)}/key.json`)
|
|
8593
|
+
]);
|
|
8594
|
+
const activeSession = session === null ? void 0 : normalizeSession(session, key);
|
|
8595
|
+
if (activeSession === void 0) {
|
|
8596
|
+
return failed(summary, operationError(
|
|
8597
|
+
"SESSION_NOT_FOUND",
|
|
8598
|
+
"The selected profile does not have an active session. This operation never signs in.",
|
|
8599
|
+
{ details: { recovery: signInRecovery(profileName, summary.posture) } }
|
|
8600
|
+
));
|
|
8601
|
+
}
|
|
8602
|
+
if (!await bindingMigrationRecorded(profileName)) {
|
|
8603
|
+
const records = await readAdditionalDelegations(profileName);
|
|
8604
|
+
if (records.some(
|
|
8605
|
+
(entry) => storedDelegationKind(entry) === "compact" && !("authorityRequest" in entry)
|
|
8606
|
+
)) {
|
|
8607
|
+
return failed(summary, operationError(
|
|
8608
|
+
"PROFILE_MIGRATION_REQUIRED",
|
|
8609
|
+
`Profile "${profileName}" has a one-time stored-grant upgrade to finish. Run one authenticated command on it (tc --profile <profile> auth caps), then retry.`,
|
|
8610
|
+
{ retryable: false, details: { recovery: migrationRecovery(profileName) } }
|
|
8611
|
+
));
|
|
8612
|
+
}
|
|
8613
|
+
}
|
|
8614
|
+
const { TinyCloudNode: TinyCloudNodeConstructor } = nodeSdk6;
|
|
8615
|
+
const node = new TinyCloudNodeConstructor({
|
|
8616
|
+
host: summary.host,
|
|
8617
|
+
...typeof profile.privateKey === "string" ? { privateKey: profile.privateKey } : {}
|
|
8618
|
+
});
|
|
8619
|
+
try {
|
|
8620
|
+
await node.restoreSession(activeSession);
|
|
8621
|
+
} catch (error) {
|
|
8622
|
+
if (isRecord7(error) && error.code === "AUTH_EXPIRED") {
|
|
8623
|
+
return failed(summary, operationError(
|
|
8624
|
+
"AUTH_REQUIRED",
|
|
8625
|
+
"The stored session has expired or is no longer valid. Sign in again.",
|
|
8626
|
+
{ retryable: false, details: { recovery: signInRecovery(profileName, summary.posture) } }
|
|
8627
|
+
));
|
|
8628
|
+
}
|
|
8629
|
+
throw error;
|
|
8630
|
+
}
|
|
8631
|
+
const activeSessionDid = normalizeDid(node.sessionDid);
|
|
8632
|
+
const livePrincipalDid = normalizeDid(node.did);
|
|
8633
|
+
const livePermissions = [...node.getVerifiedSessionCapabilities()];
|
|
8634
|
+
const replay = await replayStoredDelegationRecords(
|
|
8635
|
+
profileName,
|
|
8636
|
+
node,
|
|
8637
|
+
{ host: summary.host, resolveSpace: operationSpaceResolver(node, summary.space) }
|
|
8638
|
+
);
|
|
8639
|
+
for (const installed of replay.installed) {
|
|
8640
|
+
livePermissions.push(...installed.effectivePermissions);
|
|
8641
|
+
}
|
|
8642
|
+
const runtime = {
|
|
8643
|
+
node,
|
|
8644
|
+
granted: canonicalizeCapabilities(livePermissions),
|
|
8645
|
+
...replay.warnings.length === 0 ? {} : { warnings: replay.warnings },
|
|
8646
|
+
localOwner: isLocalOwnerProfile(profile),
|
|
8647
|
+
skippedGrantReasons: replay.warnings.map((warning) => warning.reason)
|
|
8648
|
+
};
|
|
8649
|
+
return {
|
|
8650
|
+
ok: true,
|
|
8651
|
+
context: {
|
|
8652
|
+
summary: {
|
|
8653
|
+
...summary,
|
|
8654
|
+
...livePrincipalDid === void 0 ? {} : { principalDid: livePrincipalDid },
|
|
8655
|
+
...activeSessionDid === void 0 ? {} : { sessionDid: activeSessionDid }
|
|
8656
|
+
},
|
|
8657
|
+
runtime
|
|
8658
|
+
}
|
|
8659
|
+
};
|
|
8660
|
+
} catch {
|
|
8661
|
+
return failed(summary, operationError(
|
|
8662
|
+
"NODE_ERROR",
|
|
8663
|
+
"The selected profile runtime could not be initialized.",
|
|
8664
|
+
{ retryable: true }
|
|
8665
|
+
));
|
|
8666
|
+
}
|
|
8667
|
+
}
|
|
8091
8668
|
function spaceForAuthenticatedPrincipal(principal2) {
|
|
8092
8669
|
if (principal2 === void 0) return void 0;
|
|
8093
8670
|
try {
|
|
8094
|
-
const pkh =
|
|
8095
|
-
return pkh === null ? void 0 :
|
|
8671
|
+
const pkh = nodeSdk6.parsePkhDid(principal2);
|
|
8672
|
+
return pkh === null ? void 0 : nodeSdk6.makePkhSpaceId(pkh.address, pkh.chainId, "secrets");
|
|
8096
8673
|
} catch {
|
|
8097
8674
|
return void 0;
|
|
8098
8675
|
}
|
|
@@ -8136,14 +8713,15 @@ function unresolvedSummary(target) {
|
|
|
8136
8713
|
posture: "unauthenticated"
|
|
8137
8714
|
};
|
|
8138
8715
|
}
|
|
8139
|
-
var
|
|
8716
|
+
var nodeSdk6;
|
|
8140
8717
|
var init_runtime = __esm({
|
|
8141
8718
|
"src/runtime.ts"() {
|
|
8142
8719
|
"use strict";
|
|
8143
|
-
|
|
8720
|
+
nodeSdk6 = __toESM(require("@tinycloud/node-sdk"), 1);
|
|
8144
8721
|
init_authority();
|
|
8145
8722
|
init_errors2();
|
|
8146
8723
|
init_profile();
|
|
8724
|
+
init_recovery();
|
|
8147
8725
|
init_secrets();
|
|
8148
8726
|
init_state();
|
|
8149
8727
|
init_delegation_binding();
|
|
@@ -8166,6 +8744,9 @@ init_errors2();
|
|
|
8166
8744
|
init_authority();
|
|
8167
8745
|
init_artifacts();
|
|
8168
8746
|
|
|
8747
|
+
// src/redaction.ts
|
|
8748
|
+
init_recovery();
|
|
8749
|
+
|
|
8169
8750
|
// src/safe-values.ts
|
|
8170
8751
|
function safeOriginHost(value) {
|
|
8171
8752
|
if (typeof value !== "string" || value.length === 0) return void 0;
|
|
@@ -8242,7 +8823,25 @@ function redactOperationError(_definition, error) {
|
|
|
8242
8823
|
}
|
|
8243
8824
|
var SAFE_ERROR_DETAIL_POLICIES = {
|
|
8244
8825
|
INPUT_INVALID: {
|
|
8245
|
-
issues: (value) => Array.isArray(value) ? safeIssueCodes(value) : void 0
|
|
8826
|
+
issues: (value) => Array.isArray(value) ? safeIssueCodes(value) : void 0,
|
|
8827
|
+
reason: (value) => value === "OWNER_MISMATCH" || value === "OWNER_DID_UNKNOWN" ? value : void 0
|
|
8828
|
+
},
|
|
8829
|
+
AUTH_REQUIRED: {
|
|
8830
|
+
recovery: (value) => isSafeRecovery(value, "sign_in") ? { ...value } : void 0,
|
|
8831
|
+
reason: (value) => value === "explicit_key" ? value : void 0
|
|
8832
|
+
},
|
|
8833
|
+
SESSION_NOT_FOUND: {
|
|
8834
|
+
recovery: (value) => isSafeRecovery(value, "sign_in") ? { ...value } : void 0
|
|
8835
|
+
},
|
|
8836
|
+
PROFILE_MIGRATION_REQUIRED: {
|
|
8837
|
+
recovery: (value) => isSafeRecovery(value, "complete_migration") ? { ...value } : void 0
|
|
8838
|
+
},
|
|
8839
|
+
// `secrets.get` not found for an identity no request link serves.
|
|
8840
|
+
KV_NOT_FOUND: {
|
|
8841
|
+
recoveryKind: (value) => value === "put_locally" || value === "not_requestable" ? value : void 0,
|
|
8842
|
+
names: (value) => Array.isArray(value) && value.length >= 1 && value.length <= 10 && value.every((name) => typeof name === "string" && name.length <= 256 && /^[A-Z][A-Z0-9_]*$/.test(name)) ? [...value] : void 0,
|
|
8843
|
+
scope: (value) => typeof value === "string" && value.length <= 256 && /^[a-z0-9]+(-[a-z0-9]+)*$/.test(value) ? value : void 0,
|
|
8844
|
+
owner: (value) => typeof value === "string" && /^did:pkh:eip155:[1-9][0-9]*:0x[0-9a-fA-F]{40}$/.test(value) ? value : void 0
|
|
8246
8845
|
},
|
|
8247
8846
|
OPERATION_VERSION_UNSUPPORTED: {
|
|
8248
8847
|
supportedVersions: (value) => Array.isArray(value) && value.every((item) => Number.isInteger(item)) ? value : void 0
|
|
@@ -8526,7 +9125,7 @@ async function prepareInvocation(operationId, operationVersion, invocationTarget
|
|
|
8526
9125
|
)
|
|
8527
9126
|
) };
|
|
8528
9127
|
}
|
|
8529
|
-
if (target.privateKey === void 0 && definition.runtime
|
|
9128
|
+
if (target.privateKey === void 0 && requiresRuntime(definition.runtime) && isOwnerPosture(inspectionResolution.context.summary.posture) && target.allowOwnerProfile !== true) {
|
|
8530
9129
|
return { status: "error", result: errorResult(
|
|
8531
9130
|
operation,
|
|
8532
9131
|
inspectionResolution.context.summary,
|
|
@@ -8536,15 +9135,15 @@ async function prepareInvocation(operationId, operationVersion, invocationTarget
|
|
|
8536
9135
|
)
|
|
8537
9136
|
) };
|
|
8538
9137
|
}
|
|
8539
|
-
const runtimeResolution = definition.runtime === "inspection" ? inspectionResolution : await resolveRuntime(target,
|
|
9138
|
+
const runtimeResolution = definition.runtime === "inspection" ? inspectionResolution : await resolveRuntime(target, definition.runtime);
|
|
8540
9139
|
if (!runtimeResolution.ok) {
|
|
8541
9140
|
return { status: "error", result: errorResult(
|
|
8542
9141
|
operation,
|
|
8543
9142
|
runtimeResolution.context,
|
|
8544
|
-
runtimeResolution.error
|
|
9143
|
+
redactOperationError(definition, runtimeResolution.error)
|
|
8545
9144
|
) };
|
|
8546
9145
|
}
|
|
8547
|
-
if (definition.runtime
|
|
9146
|
+
if (requiresRuntime(definition.runtime)) {
|
|
8548
9147
|
const actualPosture = runtimeResolution.context.summary.posture;
|
|
8549
9148
|
if (!definition.postures.includes(actualPosture)) {
|
|
8550
9149
|
return { status: "error", result: errorResult(
|
|
@@ -9030,6 +9629,15 @@ function internalOperationErrorResult(prepared) {
|
|
|
9030
9629
|
function isOwnerPosture(posture) {
|
|
9031
9630
|
return posture === "owner-openkey" || posture === "local-owner-key";
|
|
9032
9631
|
}
|
|
9632
|
+
function requiresRuntime(requirement) {
|
|
9633
|
+
switch (requirement) {
|
|
9634
|
+
case "authenticated":
|
|
9635
|
+
case "restored":
|
|
9636
|
+
return true;
|
|
9637
|
+
case "inspection":
|
|
9638
|
+
return false;
|
|
9639
|
+
}
|
|
9640
|
+
}
|
|
9033
9641
|
function zodIssueDetails(error) {
|
|
9034
9642
|
return {
|
|
9035
9643
|
// The canonical error channel carries only schema-owned issue codes.
|