@tinycloud/operations 0.5.0-beta.1 → 0.5.0-beta.3
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 +10 -1
- package/dist/artifacts.d.cts +1 -1
- package/dist/artifacts.d.ts +1 -1
- package/dist/cli-runtime.cjs +728 -135
- 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 +726 -134
- 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 +756 -136
- 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 +752 -133
- 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/index.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
|
}
|
|
@@ -5846,6 +5876,33 @@ var init_auth = __esm({
|
|
|
5846
5876
|
}
|
|
5847
5877
|
});
|
|
5848
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
|
+
|
|
5849
5906
|
// src/operations/exploration.ts
|
|
5850
5907
|
async function planAccountRegistryRead(context, path) {
|
|
5851
5908
|
return [{
|
|
@@ -6213,19 +6270,6 @@ function caughtKvFailure(error, action) {
|
|
|
6213
6270
|
if (error instanceof OperationInvocationError) return { status: "error", error: error.operationError };
|
|
6214
6271
|
return authorizationFailure(error, action) ?? nodeFailure(action);
|
|
6215
6272
|
}
|
|
6216
|
-
function authorizationFailure(error, action) {
|
|
6217
|
-
const verdict = (0, import_sdk_services2.authorizationVerdictOf)(error);
|
|
6218
|
-
if (verdict === "unauthenticated") {
|
|
6219
|
-
if ((0, import_sdk_services2.validatedCapabilityOf)(error) !== void 0) {
|
|
6220
|
-
return { status: "error", error: operationError("PERMISSION_DENIED", `Permission is denied to ${action}.`) };
|
|
6221
|
-
}
|
|
6222
|
-
return { status: "error", error: operationError("AUTH_REQUIRED", `Authentication is required to ${action}.`) };
|
|
6223
|
-
}
|
|
6224
|
-
if (verdict === "forbidden") {
|
|
6225
|
-
return { status: "error", error: operationError("PERMISSION_DENIED", `Permission is denied to ${action}.`) };
|
|
6226
|
-
}
|
|
6227
|
-
return void 0;
|
|
6228
|
-
}
|
|
6229
6273
|
function accountRegistryOutput(output) {
|
|
6230
6274
|
if (Buffer.byteLength(JSON.stringify(output), "utf8") > MAX_ACCOUNT_REGISTRY_BYTES) {
|
|
6231
6275
|
return {
|
|
@@ -6274,11 +6318,11 @@ function nodeFailure(action) {
|
|
|
6274
6318
|
)
|
|
6275
6319
|
};
|
|
6276
6320
|
}
|
|
6277
|
-
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;
|
|
6278
6322
|
var init_exploration = __esm({
|
|
6279
6323
|
"src/operations/exploration.ts"() {
|
|
6280
6324
|
"use strict";
|
|
6281
|
-
|
|
6325
|
+
init_kv_failure();
|
|
6282
6326
|
import_zod4 = require("zod");
|
|
6283
6327
|
init_errors2();
|
|
6284
6328
|
init_secrets();
|
|
@@ -6580,6 +6624,191 @@ var init_exploration = __esm({
|
|
|
6580
6624
|
}
|
|
6581
6625
|
});
|
|
6582
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
|
+
|
|
6583
6812
|
// src/operations/secrets-get.ts
|
|
6584
6813
|
async function planSecretGet(context, input) {
|
|
6585
6814
|
const reference = resolveSecretReferenceForOperation(
|
|
@@ -6646,27 +6875,14 @@ async function executeSecretGet(context, input) {
|
|
|
6646
6875
|
)
|
|
6647
6876
|
};
|
|
6648
6877
|
}
|
|
6649
|
-
return classifySecretRead(reference, result);
|
|
6878
|
+
return classifySecretRead(reference, result, context.runtime?.localOwner === true);
|
|
6650
6879
|
}
|
|
6651
|
-
function classifySecretRead(reference, result) {
|
|
6880
|
+
function classifySecretRead(reference, result, localOwner) {
|
|
6652
6881
|
switch (result.status) {
|
|
6653
6882
|
case "ok":
|
|
6654
6883
|
return { status: "ok", output: { value: result.value } };
|
|
6655
6884
|
case "not_found":
|
|
6656
|
-
return
|
|
6657
|
-
status: "setup_required",
|
|
6658
|
-
setup: {
|
|
6659
|
-
kind: "secret_manager",
|
|
6660
|
-
secret: {
|
|
6661
|
-
name: reference.name,
|
|
6662
|
-
...reference.scope === void 0 ? {} : { scope: reference.scope },
|
|
6663
|
-
space: reference.space
|
|
6664
|
-
},
|
|
6665
|
-
url: buildSecretSetupUrl(reference),
|
|
6666
|
-
message: "Enter this secret in Secret Manager, then retry the operation."
|
|
6667
|
-
},
|
|
6668
|
-
requiresCallerInput: true
|
|
6669
|
-
};
|
|
6885
|
+
return missingSecretOutcome(reference, localOwner);
|
|
6670
6886
|
case "permission_required":
|
|
6671
6887
|
return {
|
|
6672
6888
|
status: "authority_required",
|
|
@@ -6711,6 +6927,47 @@ function classifySecretRead(reference, result) {
|
|
|
6711
6927
|
error: operationError("SECRET_READ_FAILED", "The secret read failed.")
|
|
6712
6928
|
};
|
|
6713
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
|
+
}
|
|
6714
6971
|
function resolveEncryptionNetworkId(node, space) {
|
|
6715
6972
|
const candidate = node;
|
|
6716
6973
|
let scoped;
|
|
@@ -6738,6 +6995,7 @@ var init_secrets_get = __esm({
|
|
|
6738
6995
|
"use strict";
|
|
6739
6996
|
import_zod5 = require("zod");
|
|
6740
6997
|
init_errors2();
|
|
6998
|
+
init_secret_request();
|
|
6741
6999
|
init_secrets();
|
|
6742
7000
|
SecretsGetInputSchema = import_zod5.z.object({
|
|
6743
7001
|
name: import_zod5.z.string(),
|
|
@@ -6789,6 +7047,194 @@ var init_secrets_get = __esm({
|
|
|
6789
7047
|
}
|
|
6790
7048
|
});
|
|
6791
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
|
+
|
|
6792
7238
|
// src/operations/sql.ts
|
|
6793
7239
|
async function planSqlRead(context, input) {
|
|
6794
7240
|
const space = resolveSqlSpace(context, input.space);
|
|
@@ -7101,15 +7547,15 @@ function isByte(value) {
|
|
|
7101
7547
|
function isRecord3(value) {
|
|
7102
7548
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
7103
7549
|
}
|
|
7104
|
-
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;
|
|
7105
7551
|
var init_sql = __esm({
|
|
7106
7552
|
"src/operations/sql.ts"() {
|
|
7107
7553
|
"use strict";
|
|
7108
7554
|
import_node_sql_parser = __toESM(require("node-sql-parser"), 1);
|
|
7109
|
-
|
|
7555
|
+
import_zod7 = require("zod");
|
|
7110
7556
|
init_errors2();
|
|
7111
7557
|
init_secrets();
|
|
7112
|
-
|
|
7558
|
+
init_kv_failure();
|
|
7113
7559
|
DEFAULT_MAX_ROWS = 100;
|
|
7114
7560
|
MAX_MAX_ROWS = 1e3;
|
|
7115
7561
|
DEFAULT_MAX_BYTES = 1024 * 1024;
|
|
@@ -7125,29 +7571,29 @@ WHERE type IN ('table', 'view', 'index', 'trigger')
|
|
|
7125
7571
|
AND name NOT LIKE 'sqlite_%'
|
|
7126
7572
|
ORDER BY type, name`;
|
|
7127
7573
|
sqlParser = new import_node_sql_parser.default.Parser();
|
|
7128
|
-
SpaceSchema2 =
|
|
7574
|
+
SpaceSchema2 = import_zod7.z.string().min(1).refine(
|
|
7129
7575
|
(space) => (/^[A-Za-z0-9_-]+$/.test(space) || space.startsWith("tinycloud:")) && !space.includes("*"),
|
|
7130
7576
|
"Invalid TinyCloud space."
|
|
7131
7577
|
);
|
|
7132
|
-
DatabaseSchema =
|
|
7578
|
+
DatabaseSchema = import_zod7.z.string().min(1).max(256).refine(
|
|
7133
7579
|
(database) => database !== "/" && !database.endsWith("/") && !database.includes("*") && !/[\u0000-\u001f\u007f]/.test(database),
|
|
7134
7580
|
"Invalid SQLite database name."
|
|
7135
7581
|
);
|
|
7136
|
-
SafeNumberSchema =
|
|
7582
|
+
SafeNumberSchema = import_zod7.z.number().finite().refine(
|
|
7137
7583
|
(value) => !Number.isInteger(value) || Number.isSafeInteger(value),
|
|
7138
7584
|
"SQLite integer parameters must be JavaScript safe integers."
|
|
7139
7585
|
);
|
|
7140
|
-
Base64Schema =
|
|
7586
|
+
Base64Schema = import_zod7.z.string().max(Math.ceil(MAX_MAX_BYTES / 3) * 4).refine(
|
|
7141
7587
|
isCanonicalBase642,
|
|
7142
7588
|
"Invalid base64 BLOB value."
|
|
7143
7589
|
);
|
|
7144
|
-
SqlInputValueSchema =
|
|
7145
|
-
|
|
7590
|
+
SqlInputValueSchema = import_zod7.z.union([
|
|
7591
|
+
import_zod7.z.null(),
|
|
7146
7592
|
SafeNumberSchema,
|
|
7147
|
-
|
|
7148
|
-
|
|
7593
|
+
import_zod7.z.string().max(MAX_MAX_BYTES),
|
|
7594
|
+
import_zod7.z.object({ type: import_zod7.z.literal("blob"), base64: Base64Schema }).strict()
|
|
7149
7595
|
]);
|
|
7150
|
-
SqlParamsSchema =
|
|
7596
|
+
SqlParamsSchema = import_zod7.z.array(SqlInputValueSchema).max(MAX_PARAMETERS).superRefine(
|
|
7151
7597
|
(params, context) => {
|
|
7152
7598
|
const totalBytes = params.reduce(
|
|
7153
7599
|
(total, value) => total + sqlInputValueBytes(value),
|
|
@@ -7155,13 +7601,13 @@ ORDER BY type, name`;
|
|
|
7155
7601
|
);
|
|
7156
7602
|
if (totalBytes > MAX_MAX_BYTES) {
|
|
7157
7603
|
context.addIssue({
|
|
7158
|
-
code:
|
|
7604
|
+
code: import_zod7.z.ZodIssueCode.custom,
|
|
7159
7605
|
message: "SQLite query parameters exceed the 4 MiB input limit."
|
|
7160
7606
|
});
|
|
7161
7607
|
}
|
|
7162
7608
|
}
|
|
7163
7609
|
);
|
|
7164
|
-
RequiredSqlParamsSchema =
|
|
7610
|
+
RequiredSqlParamsSchema = import_zod7.z.array(SqlInputValueSchema).min(1).max(MAX_PARAMETERS).superRefine(
|
|
7165
7611
|
(params, context) => {
|
|
7166
7612
|
const totalBytes = params.reduce(
|
|
7167
7613
|
(total, value) => total + sqlInputValueBytes(value),
|
|
@@ -7169,88 +7615,88 @@ ORDER BY type, name`;
|
|
|
7169
7615
|
);
|
|
7170
7616
|
if (totalBytes > MAX_MAX_BYTES) {
|
|
7171
7617
|
context.addIssue({
|
|
7172
|
-
code:
|
|
7618
|
+
code: import_zod7.z.ZodIssueCode.custom,
|
|
7173
7619
|
message: "SQLite query parameters exceed the 4 MiB input limit."
|
|
7174
7620
|
});
|
|
7175
7621
|
}
|
|
7176
7622
|
}
|
|
7177
7623
|
);
|
|
7178
|
-
SqlOutputValueSchema =
|
|
7179
|
-
|
|
7624
|
+
SqlOutputValueSchema = import_zod7.z.union([
|
|
7625
|
+
import_zod7.z.null(),
|
|
7180
7626
|
SafeNumberSchema,
|
|
7181
|
-
|
|
7182
|
-
|
|
7183
|
-
type:
|
|
7184
|
-
base64:
|
|
7185
|
-
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()
|
|
7186
7632
|
}).strict()
|
|
7187
7633
|
]);
|
|
7188
|
-
SqlTargetInputSchema =
|
|
7634
|
+
SqlTargetInputSchema = import_zod7.z.object({
|
|
7189
7635
|
space: SpaceSchema2,
|
|
7190
7636
|
database: DatabaseSchema
|
|
7191
7637
|
}).strict();
|
|
7192
|
-
SqlQueryInputSchema =
|
|
7638
|
+
SqlQueryInputSchema = import_zod7.z.object({
|
|
7193
7639
|
space: SpaceSchema2,
|
|
7194
7640
|
database: DatabaseSchema,
|
|
7195
|
-
sql:
|
|
7641
|
+
sql: import_zod7.z.string().min(1).max(MAX_SQL_LENGTH).superRefine((sql, context) => {
|
|
7196
7642
|
if (!isSingleReadQuery(sql)) {
|
|
7197
7643
|
context.addIssue({
|
|
7198
|
-
code:
|
|
7644
|
+
code: import_zod7.z.ZodIssueCode.custom,
|
|
7199
7645
|
message: "SQL must parse as exactly one SQLite SELECT statement."
|
|
7200
7646
|
});
|
|
7201
7647
|
}
|
|
7202
7648
|
}),
|
|
7203
7649
|
params: SqlParamsSchema.optional(),
|
|
7204
|
-
maxRows:
|
|
7205
|
-
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()
|
|
7206
7652
|
}).strict();
|
|
7207
|
-
SqlExecuteInputSchema =
|
|
7653
|
+
SqlExecuteInputSchema = import_zod7.z.object({
|
|
7208
7654
|
space: SpaceSchema2,
|
|
7209
7655
|
database: DatabaseSchema,
|
|
7210
|
-
sql:
|
|
7656
|
+
sql: import_zod7.z.string().min(1).max(MAX_SQL_LENGTH),
|
|
7211
7657
|
params: RequiredSqlParamsSchema,
|
|
7212
|
-
acknowledgeDatabaseWideAuthority:
|
|
7658
|
+
acknowledgeDatabaseWideAuthority: import_zod7.z.literal(true).describe(SQL_WRITE_AUTHORITY_NOTICE)
|
|
7213
7659
|
}).strict().superRefine((input, context) => {
|
|
7214
7660
|
if (parseSingleDmlStatement(input.sql, input.params.length) === void 0) {
|
|
7215
7661
|
context.addIssue({
|
|
7216
|
-
code:
|
|
7662
|
+
code: import_zod7.z.ZodIssueCode.custom,
|
|
7217
7663
|
path: ["sql"],
|
|
7218
7664
|
message: "SQL must parse as exactly one parameterized INSERT, UPDATE, or DELETE with one value per positional placeholder."
|
|
7219
7665
|
});
|
|
7220
7666
|
}
|
|
7221
7667
|
});
|
|
7222
|
-
SqlLimitsOutputSchema =
|
|
7223
|
-
maxRows:
|
|
7224
|
-
maxBytes:
|
|
7225
|
-
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")
|
|
7226
7672
|
}).strict();
|
|
7227
|
-
SqlSchemaInspectOutputSchema =
|
|
7228
|
-
space:
|
|
7229
|
-
database:
|
|
7230
|
-
objects:
|
|
7231
|
-
type:
|
|
7232
|
-
name:
|
|
7233
|
-
tableName:
|
|
7234
|
-
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()
|
|
7235
7681
|
}).strict()),
|
|
7236
|
-
count:
|
|
7682
|
+
count: import_zod7.z.number().int().nonnegative(),
|
|
7237
7683
|
limits: SqlLimitsOutputSchema
|
|
7238
7684
|
}).strict();
|
|
7239
|
-
SqlQueryOutputSchema =
|
|
7240
|
-
space:
|
|
7241
|
-
database:
|
|
7242
|
-
columns:
|
|
7243
|
-
rows:
|
|
7244
|
-
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(),
|
|
7245
7691
|
limits: SqlLimitsOutputSchema
|
|
7246
7692
|
}).strict();
|
|
7247
|
-
SqlExecuteOutputSchema =
|
|
7248
|
-
space:
|
|
7249
|
-
database:
|
|
7250
|
-
statementType:
|
|
7251
|
-
changes:
|
|
7252
|
-
lastInsertRowId:
|
|
7253
|
-
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)
|
|
7254
7700
|
}).strict();
|
|
7255
7701
|
AUTHENTICATED_POSTURES2 = [
|
|
7256
7702
|
"owner-openkey",
|
|
@@ -7350,6 +7796,8 @@ var init_contract = __esm({
|
|
|
7350
7796
|
"resources_mismatch",
|
|
7351
7797
|
"unsupported",
|
|
7352
7798
|
"activation_rejected",
|
|
7799
|
+
"activation_unavailable",
|
|
7800
|
+
"activation_unauthenticated",
|
|
7353
7801
|
"invalid"
|
|
7354
7802
|
];
|
|
7355
7803
|
DELEGATION_CID_PATTERN = "^bafkr4i[a-z2-7]{52}$";
|
|
@@ -7452,6 +7900,9 @@ function skipped(reason) {
|
|
|
7452
7900
|
}
|
|
7453
7901
|
async function replayProfileDelegations(profile, node, options) {
|
|
7454
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) {
|
|
7455
7906
|
const installed = [];
|
|
7456
7907
|
const warnings = [];
|
|
7457
7908
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -7492,7 +7943,7 @@ function storedDelegationForAnotherKey(entry, node) {
|
|
|
7492
7943
|
const audience = verifiedCompactAudience(node, delegation);
|
|
7493
7944
|
if (audience === void 0) return false;
|
|
7494
7945
|
try {
|
|
7495
|
-
return
|
|
7946
|
+
return nodeSdk5.principalDidEquals(delegation.delegateDID, audience) && !nodeSdk5.principalDidEquals(audience, node.sessionDid);
|
|
7496
7947
|
} catch {
|
|
7497
7948
|
return false;
|
|
7498
7949
|
}
|
|
@@ -7526,7 +7977,7 @@ async function assess(node, entry, options, mode) {
|
|
|
7526
7977
|
let outsideRequest = false;
|
|
7527
7978
|
let effectivePermissions;
|
|
7528
7979
|
try {
|
|
7529
|
-
const installed = await
|
|
7980
|
+
const installed = await nodeSdk5.activateValidatedRuntimeDelegation(node, toActivate, {
|
|
7530
7981
|
host: options.host,
|
|
7531
7982
|
authorize: (effective) => {
|
|
7532
7983
|
verifyCompactProof(toActivate);
|
|
@@ -7558,7 +8009,7 @@ function verifyCompactProof(delegation) {
|
|
|
7558
8009
|
try {
|
|
7559
8010
|
parseSignedCompactUcanAttenuation(withoutBearer(authorization), delegation.cid);
|
|
7560
8011
|
} catch {
|
|
7561
|
-
throw new
|
|
8012
|
+
throw new nodeSdk5.RuntimeDelegationRejectedError("proof_invalid", "The compact delegation proof is invalid.");
|
|
7562
8013
|
}
|
|
7563
8014
|
}
|
|
7564
8015
|
function rejectionReason(error) {
|
|
@@ -7575,7 +8026,7 @@ async function bindingMigrationRecorded(profile) {
|
|
|
7575
8026
|
async function signedCapabilities(node, delegation, host) {
|
|
7576
8027
|
let signed;
|
|
7577
8028
|
try {
|
|
7578
|
-
await
|
|
8029
|
+
await nodeSdk5.activateValidatedRuntimeDelegation(node, delegation, {
|
|
7579
8030
|
// The transport host is not signed authority; check it at replay instead.
|
|
7580
8031
|
host: delegation.host ?? host,
|
|
7581
8032
|
authorize: (effective) => {
|
|
@@ -7610,13 +8061,13 @@ function recordKey(entry) {
|
|
|
7610
8061
|
function isRecord4(value) {
|
|
7611
8062
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
7612
8063
|
}
|
|
7613
|
-
var import_node_path2,
|
|
8064
|
+
var import_node_path2, nodeSdk5, REQUEST_ID_PREFIX, BINDING_NOTES, MIGRATION_LOCK_TIMEOUT_MS, NOT_REPLAYED, DELEGATION_CID;
|
|
7614
8065
|
var init_delegation_binding = __esm({
|
|
7615
8066
|
"src/delegation-binding.ts"() {
|
|
7616
8067
|
"use strict";
|
|
7617
8068
|
import_node_path2 = require("path");
|
|
7618
8069
|
init_operations_bundle();
|
|
7619
|
-
|
|
8070
|
+
nodeSdk5 = __toESM(require("@tinycloud/node-sdk"), 1);
|
|
7620
8071
|
init_artifacts();
|
|
7621
8072
|
init_authority();
|
|
7622
8073
|
init_contract();
|
|
@@ -7757,35 +8208,35 @@ function profileNotFound(profile) {
|
|
|
7757
8208
|
function isRecord5(value) {
|
|
7758
8209
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
7759
8210
|
}
|
|
7760
|
-
var
|
|
8211
|
+
var import_zod8, StatusInputSchema, StatusOutputSchema, STATUS_POSTURES, STATUS_EXPOSURE, STATUS_SENSITIVITY, statusOperationDefinitions;
|
|
7761
8212
|
var init_status = __esm({
|
|
7762
8213
|
"src/operations/status.ts"() {
|
|
7763
8214
|
"use strict";
|
|
7764
|
-
|
|
8215
|
+
import_zod8 = require("zod");
|
|
7765
8216
|
init_delegation_binding();
|
|
7766
8217
|
init_errors2();
|
|
7767
8218
|
init_state();
|
|
7768
|
-
StatusInputSchema =
|
|
7769
|
-
StatusOutputSchema =
|
|
7770
|
-
profile:
|
|
7771
|
-
host:
|
|
7772
|
-
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([
|
|
7773
8224
|
"owner-openkey",
|
|
7774
8225
|
"delegate-session",
|
|
7775
8226
|
"local-owner-key",
|
|
7776
8227
|
"unauthenticated"
|
|
7777
8228
|
]),
|
|
7778
|
-
operatorType:
|
|
7779
|
-
principalDid:
|
|
7780
|
-
sessionDid:
|
|
7781
|
-
ownerDid:
|
|
7782
|
-
space:
|
|
7783
|
-
session:
|
|
7784
|
-
present:
|
|
7785
|
-
expired:
|
|
7786
|
-
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()
|
|
7787
8238
|
}).strict(),
|
|
7788
|
-
liveAdditionalDelegationCount:
|
|
8239
|
+
liveAdditionalDelegationCount: import_zod8.z.number().int().nonnegative().describe(
|
|
7789
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."
|
|
7790
8241
|
)
|
|
7791
8242
|
}).strict();
|
|
@@ -7829,7 +8280,8 @@ function registeredOperationDefinitions() {
|
|
|
7829
8280
|
...authOperationDefinitions,
|
|
7830
8281
|
...explorationOperationDefinitions,
|
|
7831
8282
|
...sqlOperationDefinitions,
|
|
7832
|
-
...secretsGetOperationDefinitions
|
|
8283
|
+
...secretsGetOperationDefinitions,
|
|
8284
|
+
...secretsStatusOperationDefinitions
|
|
7833
8285
|
]);
|
|
7834
8286
|
return operationDefinitions;
|
|
7835
8287
|
}
|
|
@@ -7861,6 +8313,7 @@ var init_registry = __esm({
|
|
|
7861
8313
|
init_auth();
|
|
7862
8314
|
init_exploration();
|
|
7863
8315
|
init_secrets_get();
|
|
8316
|
+
init_secrets_status();
|
|
7864
8317
|
init_sql();
|
|
7865
8318
|
init_status();
|
|
7866
8319
|
}
|
|
@@ -7913,6 +8366,9 @@ function resolvePosture(profile) {
|
|
|
7913
8366
|
if (profile.authMethod === "local") return "local-owner-key";
|
|
7914
8367
|
return "owner-openkey";
|
|
7915
8368
|
}
|
|
8369
|
+
function isLocalOwnerProfile(profile) {
|
|
8370
|
+
return resolvePosture(profile) === "local-owner-key" || profile.authMethod === "local" || typeof profile.privateKey === "string";
|
|
8371
|
+
}
|
|
7916
8372
|
function profileNotFound2(profile) {
|
|
7917
8373
|
return {
|
|
7918
8374
|
ok: false,
|
|
@@ -7997,11 +8453,14 @@ async function createInvocationRuntime(target, requirement = "authenticated") {
|
|
|
7997
8453
|
if (requirement === "inspection") {
|
|
7998
8454
|
return { ok: true, context: { summary } };
|
|
7999
8455
|
}
|
|
8456
|
+
if (requirement === "restored") {
|
|
8457
|
+
return createRestoredRuntime(target, resolved);
|
|
8458
|
+
}
|
|
8000
8459
|
const profileName = summary.profile;
|
|
8001
8460
|
try {
|
|
8002
8461
|
const {
|
|
8003
8462
|
TinyCloudNode: TinyCloudNodeConstructor
|
|
8004
|
-
} =
|
|
8463
|
+
} = nodeSdk6;
|
|
8005
8464
|
const explicitPrivateKeyOverride = typeof target.privateKey === "string";
|
|
8006
8465
|
const [session, key] = explicitPrivateKeyOverride ? [null, null] : await Promise.all([
|
|
8007
8466
|
readSession(profileName),
|
|
@@ -8079,7 +8538,9 @@ async function createInvocationRuntime(target, requirement = "authenticated") {
|
|
|
8079
8538
|
const runtime = {
|
|
8080
8539
|
node,
|
|
8081
8540
|
granted: canonicalizeCapabilities(livePermissions),
|
|
8082
|
-
...warnings.length === 0 ? {} : { warnings }
|
|
8541
|
+
...warnings.length === 0 ? {} : { warnings },
|
|
8542
|
+
localOwner: explicitPrivateKeyOverride || isLocalOwnerProfile(profile),
|
|
8543
|
+
skippedGrantReasons: warnings.map((warning) => warning.reason)
|
|
8083
8544
|
};
|
|
8084
8545
|
return {
|
|
8085
8546
|
ok: true,
|
|
@@ -8103,11 +8564,112 @@ async function createInvocationRuntime(target, requirement = "authenticated") {
|
|
|
8103
8564
|
));
|
|
8104
8565
|
}
|
|
8105
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
|
+
}
|
|
8106
8668
|
function spaceForAuthenticatedPrincipal(principal2) {
|
|
8107
8669
|
if (principal2 === void 0) return void 0;
|
|
8108
8670
|
try {
|
|
8109
|
-
const pkh =
|
|
8110
|
-
return pkh === null ? void 0 :
|
|
8671
|
+
const pkh = nodeSdk6.parsePkhDid(principal2);
|
|
8672
|
+
return pkh === null ? void 0 : nodeSdk6.makePkhSpaceId(pkh.address, pkh.chainId, "secrets");
|
|
8111
8673
|
} catch {
|
|
8112
8674
|
return void 0;
|
|
8113
8675
|
}
|
|
@@ -8151,14 +8713,15 @@ function unresolvedSummary(target) {
|
|
|
8151
8713
|
posture: "unauthenticated"
|
|
8152
8714
|
};
|
|
8153
8715
|
}
|
|
8154
|
-
var
|
|
8716
|
+
var nodeSdk6;
|
|
8155
8717
|
var init_runtime = __esm({
|
|
8156
8718
|
"src/runtime.ts"() {
|
|
8157
8719
|
"use strict";
|
|
8158
|
-
|
|
8720
|
+
nodeSdk6 = __toESM(require("@tinycloud/node-sdk"), 1);
|
|
8159
8721
|
init_authority();
|
|
8160
8722
|
init_errors2();
|
|
8161
8723
|
init_profile();
|
|
8724
|
+
init_recovery();
|
|
8162
8725
|
init_secrets();
|
|
8163
8726
|
init_state();
|
|
8164
8727
|
init_delegation_binding();
|
|
@@ -8181,6 +8744,9 @@ init_errors2();
|
|
|
8181
8744
|
init_authority();
|
|
8182
8745
|
init_artifacts();
|
|
8183
8746
|
|
|
8747
|
+
// src/redaction.ts
|
|
8748
|
+
init_recovery();
|
|
8749
|
+
|
|
8184
8750
|
// src/safe-values.ts
|
|
8185
8751
|
function safeOriginHost(value) {
|
|
8186
8752
|
if (typeof value !== "string" || value.length === 0) return void 0;
|
|
@@ -8257,7 +8823,25 @@ function redactOperationError(_definition, error) {
|
|
|
8257
8823
|
}
|
|
8258
8824
|
var SAFE_ERROR_DETAIL_POLICIES = {
|
|
8259
8825
|
INPUT_INVALID: {
|
|
8260
|
-
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
|
|
8261
8845
|
},
|
|
8262
8846
|
OPERATION_VERSION_UNSUPPORTED: {
|
|
8263
8847
|
supportedVersions: (value) => Array.isArray(value) && value.every((item) => Number.isInteger(item)) ? value : void 0
|
|
@@ -8339,7 +8923,7 @@ async function invokeOperation(operationId, operationVersion, invocationTarget,
|
|
|
8339
8923
|
operationError("INPUT_INVALID", "The invocation target is invalid.")
|
|
8340
8924
|
);
|
|
8341
8925
|
}
|
|
8342
|
-
|
|
8926
|
+
const run = withTinyCloudStateRoot(target.stateRoot, async () => {
|
|
8343
8927
|
const prepared = await prepareInvocation(
|
|
8344
8928
|
operationId,
|
|
8345
8929
|
operationVersion,
|
|
@@ -8349,6 +8933,33 @@ async function invokeOperation(operationId, operationVersion, invocationTarget,
|
|
|
8349
8933
|
if (isPreparedError(prepared)) return prepared.result;
|
|
8350
8934
|
return withRuntimeWarnings(await executePreparedInvocation(prepared), prepared);
|
|
8351
8935
|
});
|
|
8936
|
+
const { lookupOperation: lookupOperation2 } = await Promise.resolve().then(() => (init_registry(), registry_exports));
|
|
8937
|
+
const lookup = lookupOperation2(operationId, operationVersion);
|
|
8938
|
+
const deadlineMs = lookup.status === "found" ? lookup.definition.deadlineMs : void 0;
|
|
8939
|
+
if (deadlineMs === void 0) return run;
|
|
8940
|
+
return withResponseDeadline(run, deadlineMs, () => errorResult(
|
|
8941
|
+
{ operationId, operationVersion },
|
|
8942
|
+
unresolvedContextSummary(target),
|
|
8943
|
+
operationError(
|
|
8944
|
+
"NODE_UNREACHABLE",
|
|
8945
|
+
`The operation did not finish within ${deadlineMs / 1e3} s.`,
|
|
8946
|
+
{ retryable: true }
|
|
8947
|
+
)
|
|
8948
|
+
));
|
|
8949
|
+
}
|
|
8950
|
+
async function withResponseDeadline(run, deadlineMs, expired) {
|
|
8951
|
+
run.catch(() => {
|
|
8952
|
+
});
|
|
8953
|
+
let timer;
|
|
8954
|
+
const deadline = new Promise((resolve2) => {
|
|
8955
|
+
timer = setTimeout(() => resolve2(expired()), deadlineMs);
|
|
8956
|
+
timer.unref();
|
|
8957
|
+
});
|
|
8958
|
+
try {
|
|
8959
|
+
return await Promise.race([run, deadline]);
|
|
8960
|
+
} finally {
|
|
8961
|
+
clearTimeout(timer);
|
|
8962
|
+
}
|
|
8352
8963
|
}
|
|
8353
8964
|
function withRuntimeWarnings(result, prepared) {
|
|
8354
8965
|
const warnings = prepared.runtimeResolution.context.runtime?.warnings;
|
|
@@ -8423,7 +9034,7 @@ async function prepareInvocation(operationId, operationVersion, invocationTarget
|
|
|
8423
9034
|
)
|
|
8424
9035
|
) };
|
|
8425
9036
|
}
|
|
8426
|
-
if (target.privateKey === void 0 && definition.runtime
|
|
9037
|
+
if (target.privateKey === void 0 && requiresRuntime(definition.runtime) && isOwnerPosture(inspectionResolution.context.summary.posture) && target.allowOwnerProfile !== true) {
|
|
8427
9038
|
return { status: "error", result: errorResult(
|
|
8428
9039
|
operation,
|
|
8429
9040
|
inspectionResolution.context.summary,
|
|
@@ -8433,15 +9044,15 @@ async function prepareInvocation(operationId, operationVersion, invocationTarget
|
|
|
8433
9044
|
)
|
|
8434
9045
|
) };
|
|
8435
9046
|
}
|
|
8436
|
-
const runtimeResolution = definition.runtime === "inspection" ? inspectionResolution : await resolveRuntime(target,
|
|
9047
|
+
const runtimeResolution = definition.runtime === "inspection" ? inspectionResolution : await resolveRuntime(target, definition.runtime);
|
|
8437
9048
|
if (!runtimeResolution.ok) {
|
|
8438
9049
|
return { status: "error", result: errorResult(
|
|
8439
9050
|
operation,
|
|
8440
9051
|
runtimeResolution.context,
|
|
8441
|
-
runtimeResolution.error
|
|
9052
|
+
redactOperationError(definition, runtimeResolution.error)
|
|
8442
9053
|
) };
|
|
8443
9054
|
}
|
|
8444
|
-
if (definition.runtime
|
|
9055
|
+
if (requiresRuntime(definition.runtime)) {
|
|
8445
9056
|
const actualPosture = runtimeResolution.context.summary.posture;
|
|
8446
9057
|
if (!definition.postures.includes(actualPosture)) {
|
|
8447
9058
|
return { status: "error", result: errorResult(
|
|
@@ -8828,6 +9439,15 @@ function exactCapabilities2(value) {
|
|
|
8828
9439
|
function isOwnerPosture(posture) {
|
|
8829
9440
|
return posture === "owner-openkey" || posture === "local-owner-key";
|
|
8830
9441
|
}
|
|
9442
|
+
function requiresRuntime(requirement) {
|
|
9443
|
+
switch (requirement) {
|
|
9444
|
+
case "authenticated":
|
|
9445
|
+
case "restored":
|
|
9446
|
+
return true;
|
|
9447
|
+
case "inspection":
|
|
9448
|
+
return false;
|
|
9449
|
+
}
|
|
9450
|
+
}
|
|
8831
9451
|
function zodIssueDetails(error) {
|
|
8832
9452
|
return {
|
|
8833
9453
|
// The canonical error channel carries only schema-owned issue codes.
|