@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/cli-runtime.js
CHANGED
|
@@ -298,6 +298,7 @@ var init_errors2 = __esm({
|
|
|
298
298
|
"PROFILE_NOT_FOUND",
|
|
299
299
|
"PROFILE_POSTURE_NOT_ALLOWED",
|
|
300
300
|
"PROFILE_OWNER_OPT_IN_REQUIRED",
|
|
301
|
+
"PROFILE_MIGRATION_REQUIRED",
|
|
301
302
|
"AUTH_REQUIRED",
|
|
302
303
|
"PERMISSION_DENIED",
|
|
303
304
|
"SESSION_NOT_FOUND",
|
|
@@ -5243,6 +5244,45 @@ var init_artifacts = __esm({
|
|
|
5243
5244
|
}
|
|
5244
5245
|
});
|
|
5245
5246
|
|
|
5247
|
+
// src/recovery.ts
|
|
5248
|
+
function signInRecovery(profile, posture) {
|
|
5249
|
+
if (!SAFE_PROFILE_TOKEN.test(profile)) return { action: "sign_in" };
|
|
5250
|
+
const template = posture === "local-owner-key" ? SIGN_IN_TEMPLATES.local : posture === "delegate-session" ? SIGN_IN_TEMPLATES.scoped : SIGN_IN_TEMPLATES.openkey;
|
|
5251
|
+
return { action: "sign_in", command: template(profile) };
|
|
5252
|
+
}
|
|
5253
|
+
function migrationRecovery(profile) {
|
|
5254
|
+
return SAFE_PROFILE_TOKEN.test(profile) ? { action: "complete_migration", command: migrationCommand(profile), operationId: MIGRATION_OPERATION_ID } : { action: "complete_migration", operationId: MIGRATION_OPERATION_ID };
|
|
5255
|
+
}
|
|
5256
|
+
function isSafeRecovery(value, action) {
|
|
5257
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
|
|
5258
|
+
const record = value;
|
|
5259
|
+
if (record.action !== action) return false;
|
|
5260
|
+
const keys = Object.keys(record);
|
|
5261
|
+
const allowed = action === "sign_in" ? ["action", "command"] : ["action", "command", "operationId"];
|
|
5262
|
+
if (!keys.every((key) => allowed.includes(key))) return false;
|
|
5263
|
+
if (action === "complete_migration" && record.operationId !== MIGRATION_OPERATION_ID) return false;
|
|
5264
|
+
if (!("command" in record)) return true;
|
|
5265
|
+
const command = record.command;
|
|
5266
|
+
if (typeof command !== "string") return false;
|
|
5267
|
+
const profile = /^tc --profile (\S+) /.exec(command)?.[1];
|
|
5268
|
+
if (profile === void 0 || !SAFE_PROFILE_TOKEN.test(profile)) return false;
|
|
5269
|
+
return action === "sign_in" ? Object.values(SIGN_IN_TEMPLATES).some((template) => template(profile) === command) : migrationCommand(profile) === command;
|
|
5270
|
+
}
|
|
5271
|
+
var SAFE_PROFILE_TOKEN, MIGRATION_OPERATION_ID, SIGN_IN_TEMPLATES, migrationCommand;
|
|
5272
|
+
var init_recovery = __esm({
|
|
5273
|
+
"src/recovery.ts"() {
|
|
5274
|
+
"use strict";
|
|
5275
|
+
SAFE_PROFILE_TOKEN = /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/;
|
|
5276
|
+
MIGRATION_OPERATION_ID = "tinycloud.auth.capabilities";
|
|
5277
|
+
SIGN_IN_TEMPLATES = {
|
|
5278
|
+
local: (profile) => `tc --profile ${profile} auth login --method local`,
|
|
5279
|
+
openkey: (profile) => `tc --profile ${profile} auth login --method openkey`,
|
|
5280
|
+
scoped: (profile) => `tc --profile ${profile} auth login --method openkey --paste --manifest <manifest.json>`
|
|
5281
|
+
};
|
|
5282
|
+
migrationCommand = (profile) => `tc --profile ${profile} auth caps`;
|
|
5283
|
+
}
|
|
5284
|
+
});
|
|
5285
|
+
|
|
5246
5286
|
// src/secrets.ts
|
|
5247
5287
|
import * as nodeSdk from "@tinycloud/node-sdk";
|
|
5248
5288
|
function normalizeSecretsGetInput(input) {
|
|
@@ -5330,15 +5370,6 @@ function canonicalizeSpaceUri(space) {
|
|
|
5330
5370
|
}
|
|
5331
5371
|
return space;
|
|
5332
5372
|
}
|
|
5333
|
-
function buildSecretSetupUrl(reference) {
|
|
5334
|
-
const parameters = [
|
|
5335
|
-
["secret", reference.name],
|
|
5336
|
-
...reference.scope === void 0 ? [] : [["scope", reference.scope]],
|
|
5337
|
-
["space", reference.space]
|
|
5338
|
-
];
|
|
5339
|
-
const query = parameters.map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`).join("&");
|
|
5340
|
-
return `${SECRET_MANAGER_BASE_URL}/app?${query}`;
|
|
5341
|
-
}
|
|
5342
5373
|
function canonicalizeSecretScope(scope) {
|
|
5343
5374
|
if (scope === void 0 || scope === "") return void 0;
|
|
5344
5375
|
const trimmed = scope.trim();
|
|
@@ -5366,13 +5397,12 @@ function invalidSecretInput() {
|
|
|
5366
5397
|
operationError("INPUT_INVALID", "The secret reference is invalid.")
|
|
5367
5398
|
);
|
|
5368
5399
|
}
|
|
5369
|
-
var DEFAULT_SECRETS_SPACE,
|
|
5400
|
+
var DEFAULT_SECRETS_SPACE, SECRET_NAME_RE2, RESERVED_SECRET_SCOPES;
|
|
5370
5401
|
var init_secrets = __esm({
|
|
5371
5402
|
"src/secrets.ts"() {
|
|
5372
5403
|
"use strict";
|
|
5373
5404
|
init_errors2();
|
|
5374
5405
|
DEFAULT_SECRETS_SPACE = "secrets";
|
|
5375
|
-
SECRET_MANAGER_BASE_URL = "https://secrets.tinycloud.xyz";
|
|
5376
5406
|
SECRET_NAME_RE2 = /^[A-Z][A-Z0-9_]*$/;
|
|
5377
5407
|
RESERVED_SECRET_SCOPES = /* @__PURE__ */ new Set(["default", "global"]);
|
|
5378
5408
|
}
|
|
@@ -5857,8 +5887,33 @@ var init_auth = __esm({
|
|
|
5857
5887
|
}
|
|
5858
5888
|
});
|
|
5859
5889
|
|
|
5860
|
-
// src/
|
|
5890
|
+
// src/kv-failure.ts
|
|
5861
5891
|
import { authorizationVerdictOf, validatedCapabilityOf } from "@tinycloud/sdk-services";
|
|
5892
|
+
function kvRefusal(error) {
|
|
5893
|
+
const verdict = authorizationVerdictOf(error);
|
|
5894
|
+
if (verdict === "unauthenticated") {
|
|
5895
|
+
return validatedCapabilityOf(error) === void 0 ? "auth_required" : "permission_denied";
|
|
5896
|
+
}
|
|
5897
|
+
return verdict === "forbidden" ? "permission_denied" : void 0;
|
|
5898
|
+
}
|
|
5899
|
+
function authorizationFailure(error, action) {
|
|
5900
|
+
switch (kvRefusal(error)) {
|
|
5901
|
+
case "auth_required":
|
|
5902
|
+
return { status: "error", error: operationError("AUTH_REQUIRED", `Authentication is required to ${action}.`) };
|
|
5903
|
+
case "permission_denied":
|
|
5904
|
+
return { status: "error", error: operationError("PERMISSION_DENIED", `Permission is denied to ${action}.`) };
|
|
5905
|
+
case void 0:
|
|
5906
|
+
return void 0;
|
|
5907
|
+
}
|
|
5908
|
+
}
|
|
5909
|
+
var init_kv_failure = __esm({
|
|
5910
|
+
"src/kv-failure.ts"() {
|
|
5911
|
+
"use strict";
|
|
5912
|
+
init_errors2();
|
|
5913
|
+
}
|
|
5914
|
+
});
|
|
5915
|
+
|
|
5916
|
+
// src/operations/exploration.ts
|
|
5862
5917
|
import { z as z4 } from "zod";
|
|
5863
5918
|
async function planAccountRegistryRead(context, path) {
|
|
5864
5919
|
return [{
|
|
@@ -6226,19 +6281,6 @@ function caughtKvFailure(error, action) {
|
|
|
6226
6281
|
if (error instanceof OperationInvocationError) return { status: "error", error: error.operationError };
|
|
6227
6282
|
return authorizationFailure(error, action) ?? nodeFailure(action);
|
|
6228
6283
|
}
|
|
6229
|
-
function authorizationFailure(error, action) {
|
|
6230
|
-
const verdict = authorizationVerdictOf(error);
|
|
6231
|
-
if (verdict === "unauthenticated") {
|
|
6232
|
-
if (validatedCapabilityOf(error) !== void 0) {
|
|
6233
|
-
return { status: "error", error: operationError("PERMISSION_DENIED", `Permission is denied to ${action}.`) };
|
|
6234
|
-
}
|
|
6235
|
-
return { status: "error", error: operationError("AUTH_REQUIRED", `Authentication is required to ${action}.`) };
|
|
6236
|
-
}
|
|
6237
|
-
if (verdict === "forbidden") {
|
|
6238
|
-
return { status: "error", error: operationError("PERMISSION_DENIED", `Permission is denied to ${action}.`) };
|
|
6239
|
-
}
|
|
6240
|
-
return void 0;
|
|
6241
|
-
}
|
|
6242
6284
|
function accountRegistryOutput(output) {
|
|
6243
6285
|
if (Buffer.byteLength(JSON.stringify(output), "utf8") > MAX_ACCOUNT_REGISTRY_BYTES) {
|
|
6244
6286
|
return {
|
|
@@ -6291,6 +6333,7 @@ var MAX_KV_VALUE_BYTES, DEFAULT_KV_LIST_LIMIT, MAX_ACCOUNT_REGISTRY_RECORDS, MAX
|
|
|
6291
6333
|
var init_exploration = __esm({
|
|
6292
6334
|
"src/operations/exploration.ts"() {
|
|
6293
6335
|
"use strict";
|
|
6336
|
+
init_kv_failure();
|
|
6294
6337
|
init_errors2();
|
|
6295
6338
|
init_secrets();
|
|
6296
6339
|
MAX_KV_VALUE_BYTES = 1024 * 1024;
|
|
@@ -6591,6 +6634,191 @@ var init_exploration = __esm({
|
|
|
6591
6634
|
}
|
|
6592
6635
|
});
|
|
6593
6636
|
|
|
6637
|
+
// src/secret-request.ts
|
|
6638
|
+
import * as nodeSdk3 from "@tinycloud/node-sdk";
|
|
6639
|
+
function canonicalSecretRequestOwner(did) {
|
|
6640
|
+
const match = typeof did === "string" ? OWNER_RE.exec(did) : null;
|
|
6641
|
+
if (match === null || !Number.isSafeInteger(Number(match[1]))) throw invalidOwner();
|
|
6642
|
+
const address = match[2];
|
|
6643
|
+
let checksummed;
|
|
6644
|
+
try {
|
|
6645
|
+
checksummed = nodeSdk3.canonicalizeAddress(address);
|
|
6646
|
+
} catch {
|
|
6647
|
+
throw invalidOwner();
|
|
6648
|
+
}
|
|
6649
|
+
if (/[A-F]/.test(address.slice(2)) && address !== checksummed) throw invalidOwner();
|
|
6650
|
+
return `did:pkh:eip155:${match[1]}:${checksummed}`;
|
|
6651
|
+
}
|
|
6652
|
+
function buildSecretRequestUrl(input) {
|
|
6653
|
+
const owner = canonicalSecretRequestOwner(input.owner);
|
|
6654
|
+
const names = validSecretNames(input.names);
|
|
6655
|
+
if (input.scope !== void 0) assertSecretRequestScope(input.scope);
|
|
6656
|
+
const requester = input.requester;
|
|
6657
|
+
if (requester !== void 0 && (typeof requester !== "string" || requester.length === 0 || requester.length > MAX_REQUESTER_LENGTH || CONTROL_OR_FORMAT.test(requester))) {
|
|
6658
|
+
throw new SecretRequestInputError("INVALID_REQUESTER", "The requester label must be 1-64 characters with no control or format characters.");
|
|
6659
|
+
}
|
|
6660
|
+
if (input.returnTo !== void 0 && !isAllowedReturnTo(input.returnTo)) {
|
|
6661
|
+
throw new SecretRequestInputError("INVALID_RETURN_TO", "The return address is not an allowed Secret Manager callback.");
|
|
6662
|
+
}
|
|
6663
|
+
if (input.state !== void 0 && !STATE_RE.test(input.state)) {
|
|
6664
|
+
throw new SecretRequestInputError("INVALID_STATE", "The state must be 1-128 characters of A-Z, a-z, 0-9, '.', '_', '~' or '-'.");
|
|
6665
|
+
}
|
|
6666
|
+
const parameters = [
|
|
6667
|
+
["owner", owner],
|
|
6668
|
+
...names.map((name) => ["name", name]),
|
|
6669
|
+
...input.scope === void 0 ? [] : [["scope", input.scope]],
|
|
6670
|
+
...input.requester === void 0 ? [] : [["requester", input.requester]],
|
|
6671
|
+
...input.returnTo === void 0 ? [] : [["return_to", input.returnTo]],
|
|
6672
|
+
...input.state === void 0 ? [] : [["state", input.state]],
|
|
6673
|
+
["v", "1"]
|
|
6674
|
+
];
|
|
6675
|
+
const url = `${SECRET_MANAGER_ORIGIN}/request?${parameters.map(([key, value]) => `${key}=${encodeURIComponent(value)}`).join("&")}`;
|
|
6676
|
+
if (url.length > SECRET_REQUEST_MAX_URL_LENGTH) {
|
|
6677
|
+
throw new SecretRequestInputError("REQUEST_LINK_TOO_LONG", `The request link is longer than ${SECRET_REQUEST_MAX_URL_LENGTH} characters.`);
|
|
6678
|
+
}
|
|
6679
|
+
return { url, owner, names, ...input.scope === void 0 ? {} : { scope: input.scope } };
|
|
6680
|
+
}
|
|
6681
|
+
function secretSetupFor(link2) {
|
|
6682
|
+
return {
|
|
6683
|
+
url: link2.url,
|
|
6684
|
+
names: [...link2.names],
|
|
6685
|
+
...link2.scope === void 0 ? {} : { scope: link2.scope },
|
|
6686
|
+
owner: link2.owner,
|
|
6687
|
+
action: "add_secret"
|
|
6688
|
+
};
|
|
6689
|
+
}
|
|
6690
|
+
function resolveSecretsOwner(profile, requestedOwner) {
|
|
6691
|
+
const resolved = profile.local ? ownerOrUndefined(profile.principalDid) : ownerOrUndefined(profile.ownerDid) ?? (profile.posture === "delegate-session" ? ownerOfSpace(profile.space) : void 0) ?? ownerOrUndefined(profile.principalDid);
|
|
6692
|
+
const requested = requestedOwner === void 0 ? void 0 : ownerOrUndefined(requestedOwner);
|
|
6693
|
+
if (resolved !== void 0) {
|
|
6694
|
+
if (requestedOwner !== void 0 && requested !== resolved) {
|
|
6695
|
+
return {
|
|
6696
|
+
ok: false,
|
|
6697
|
+
code: "OWNER_MISMATCH",
|
|
6698
|
+
message: "The requested owner is not the owner of this identity's secrets."
|
|
6699
|
+
};
|
|
6700
|
+
}
|
|
6701
|
+
return { ok: true, owner: resolved, local: profile.local };
|
|
6702
|
+
}
|
|
6703
|
+
if (requested !== void 0 && !profile.local) return { ok: true, owner: requested, local: false };
|
|
6704
|
+
return {
|
|
6705
|
+
ok: false,
|
|
6706
|
+
code: "OWNER_DID_UNKNOWN",
|
|
6707
|
+
message: "The owner of this identity's secrets is unknown. Pass the owner's did:pkh with --owner."
|
|
6708
|
+
};
|
|
6709
|
+
}
|
|
6710
|
+
function missingSecretRecovery(input) {
|
|
6711
|
+
if (input.local) {
|
|
6712
|
+
return { kind: "put_locally", hint: `Store it with: ${putCommands(input.names, input.scope)}` };
|
|
6713
|
+
}
|
|
6714
|
+
if (input.owner !== void 0) {
|
|
6715
|
+
try {
|
|
6716
|
+
return {
|
|
6717
|
+
kind: "add_secret",
|
|
6718
|
+
setup: secretSetupFor(buildSecretRequestUrl({
|
|
6719
|
+
owner: input.owner,
|
|
6720
|
+
names: input.names,
|
|
6721
|
+
...input.scope === void 0 ? {} : { scope: input.scope }
|
|
6722
|
+
}))
|
|
6723
|
+
};
|
|
6724
|
+
} catch {
|
|
6725
|
+
}
|
|
6726
|
+
}
|
|
6727
|
+
return {
|
|
6728
|
+
kind: "not_requestable",
|
|
6729
|
+
hint: `No Secret Manager request link can express this secret. The owner can store it with: ${putCommands(input.names, input.scope)}`
|
|
6730
|
+
};
|
|
6731
|
+
}
|
|
6732
|
+
function isValidSecretRequestScope(scope) {
|
|
6733
|
+
return scope.length <= MAX_SCOPE_LENGTH && SCOPE_RE.test(scope) && !RESERVED_SCOPES.includes(scope);
|
|
6734
|
+
}
|
|
6735
|
+
function isValidSecretName(name) {
|
|
6736
|
+
return name.length <= MAX_NAME_LENGTH && NAME_RE.test(name);
|
|
6737
|
+
}
|
|
6738
|
+
function validSecretNames(names) {
|
|
6739
|
+
for (const name of names) assertSecretName(name);
|
|
6740
|
+
const unique = dedupe(names);
|
|
6741
|
+
if (unique.length === 0) {
|
|
6742
|
+
throw new SecretRequestInputError("INVALID_SECRET_NAME", "At least one secret name is required.");
|
|
6743
|
+
}
|
|
6744
|
+
if (unique.length > SECRET_REQUEST_MAX_NAMES) {
|
|
6745
|
+
throw new SecretRequestInputError("TOO_MANY_SECRET_NAMES", `At most ${SECRET_REQUEST_MAX_NAMES} secret names can be requested at once.`);
|
|
6746
|
+
}
|
|
6747
|
+
return unique;
|
|
6748
|
+
}
|
|
6749
|
+
function assertSecretName(name) {
|
|
6750
|
+
if (typeof name !== "string" || !isValidSecretName(name)) {
|
|
6751
|
+
throw new SecretRequestInputError("INVALID_SECRET_NAME", "Secret names are 1-64 characters of A-Z, 0-9 and '_', starting with a letter.");
|
|
6752
|
+
}
|
|
6753
|
+
}
|
|
6754
|
+
function assertSecretRequestScope(scope) {
|
|
6755
|
+
if (typeof scope !== "string" || !isValidSecretRequestScope(scope)) {
|
|
6756
|
+
throw new SecretRequestInputError("INVALID_SECRET_SCOPE", "The scope must be a canonical scope of at most 64 characters, not default, global or scoped.");
|
|
6757
|
+
}
|
|
6758
|
+
}
|
|
6759
|
+
function isAllowedReturnTo(returnTo) {
|
|
6760
|
+
if (typeof returnTo !== "string" || returnTo.length > MAX_RETURN_TO_LENGTH) return false;
|
|
6761
|
+
let url;
|
|
6762
|
+
try {
|
|
6763
|
+
url = new URL(returnTo);
|
|
6764
|
+
} catch {
|
|
6765
|
+
return false;
|
|
6766
|
+
}
|
|
6767
|
+
if (url.username !== "" || url.password !== "") return false;
|
|
6768
|
+
return RETURN_TO_ORIGINS.includes(url.origin) || RETURN_TO_PREVIEW.test(url.origin);
|
|
6769
|
+
}
|
|
6770
|
+
function ownerOrUndefined(did) {
|
|
6771
|
+
if (did === void 0) return void 0;
|
|
6772
|
+
try {
|
|
6773
|
+
return canonicalSecretRequestOwner(did);
|
|
6774
|
+
} catch {
|
|
6775
|
+
return void 0;
|
|
6776
|
+
}
|
|
6777
|
+
}
|
|
6778
|
+
function ownerOfSpace(space) {
|
|
6779
|
+
const match = space === void 0 ? null : PKH_SPACE_RE.exec(space);
|
|
6780
|
+
if (match === null) return void 0;
|
|
6781
|
+
return ownerOrUndefined(`did:pkh:eip155:${match[1]}:${match[2].toLowerCase()}`);
|
|
6782
|
+
}
|
|
6783
|
+
function putCommands(names, scope) {
|
|
6784
|
+
return dedupe(names).map((name) => `tc secrets put ${name}${scope === void 0 ? "" : ` --scope ${scope}`} --stdin`).join("; ");
|
|
6785
|
+
}
|
|
6786
|
+
function dedupe(names) {
|
|
6787
|
+
return [...new Set(names)];
|
|
6788
|
+
}
|
|
6789
|
+
function invalidOwner() {
|
|
6790
|
+
return new SecretRequestInputError("INVALID_OWNER", "The owner must be a did:pkh:eip155 account with a valid EIP-55 address.");
|
|
6791
|
+
}
|
|
6792
|
+
var 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;
|
|
6793
|
+
var init_secret_request = __esm({
|
|
6794
|
+
"src/secret-request.ts"() {
|
|
6795
|
+
"use strict";
|
|
6796
|
+
SECRET_MANAGER_ORIGIN = "https://secrets.tinycloud.xyz";
|
|
6797
|
+
SECRET_REQUEST_MAX_NAMES = 10;
|
|
6798
|
+
SECRET_REQUEST_MAX_URL_LENGTH = 8192;
|
|
6799
|
+
OWNER_RE = /^did:pkh:eip155:([1-9][0-9]*):(0x[0-9a-fA-F]{40})$/;
|
|
6800
|
+
NAME_RE = /^[A-Z][A-Z0-9_]*$/;
|
|
6801
|
+
MAX_NAME_LENGTH = 64;
|
|
6802
|
+
SCOPE_RE = /^[a-z0-9]+(-[a-z0-9]+)*$/;
|
|
6803
|
+
MAX_SCOPE_LENGTH = 64;
|
|
6804
|
+
RESERVED_SCOPES = ["default", "global", "scoped"];
|
|
6805
|
+
MAX_REQUESTER_LENGTH = 64;
|
|
6806
|
+
CONTROL_OR_FORMAT = /[\p{Cc}\p{Cf}]/u;
|
|
6807
|
+
STATE_RE = /^[A-Za-z0-9._~-]{1,128}$/;
|
|
6808
|
+
MAX_RETURN_TO_LENGTH = 2048;
|
|
6809
|
+
RETURN_TO_ORIGINS = ["https://feed.tinycloud.xyz"];
|
|
6810
|
+
RETURN_TO_PREVIEW = /^https:\/\/[a-z0-9-]+\.tinyfeed\.pages\.dev$/;
|
|
6811
|
+
PKH_SPACE_RE = /^tinycloud:pkh:eip155:([1-9][0-9]*):(0x[0-9a-fA-F]{40}):[^:]+$/;
|
|
6812
|
+
SecretRequestInputError = class extends Error {
|
|
6813
|
+
constructor(code, message) {
|
|
6814
|
+
super(message);
|
|
6815
|
+
this.name = "SecretRequestInputError";
|
|
6816
|
+
this.code = code;
|
|
6817
|
+
}
|
|
6818
|
+
};
|
|
6819
|
+
}
|
|
6820
|
+
});
|
|
6821
|
+
|
|
6594
6822
|
// src/operations/secrets-get.ts
|
|
6595
6823
|
import { z as z5 } from "zod";
|
|
6596
6824
|
async function planSecretGet(context, input) {
|
|
@@ -6658,27 +6886,14 @@ async function executeSecretGet(context, input) {
|
|
|
6658
6886
|
)
|
|
6659
6887
|
};
|
|
6660
6888
|
}
|
|
6661
|
-
return classifySecretRead(reference, result);
|
|
6889
|
+
return classifySecretRead(reference, result, context.runtime?.localOwner === true);
|
|
6662
6890
|
}
|
|
6663
|
-
function classifySecretRead(reference, result) {
|
|
6891
|
+
function classifySecretRead(reference, result, localOwner) {
|
|
6664
6892
|
switch (result.status) {
|
|
6665
6893
|
case "ok":
|
|
6666
6894
|
return { status: "ok", output: { value: result.value } };
|
|
6667
6895
|
case "not_found":
|
|
6668
|
-
return
|
|
6669
|
-
status: "setup_required",
|
|
6670
|
-
setup: {
|
|
6671
|
-
kind: "secret_manager",
|
|
6672
|
-
secret: {
|
|
6673
|
-
name: reference.name,
|
|
6674
|
-
...reference.scope === void 0 ? {} : { scope: reference.scope },
|
|
6675
|
-
space: reference.space
|
|
6676
|
-
},
|
|
6677
|
-
url: buildSecretSetupUrl(reference),
|
|
6678
|
-
message: "Enter this secret in Secret Manager, then retry the operation."
|
|
6679
|
-
},
|
|
6680
|
-
requiresCallerInput: true
|
|
6681
|
-
};
|
|
6896
|
+
return missingSecretOutcome(reference, localOwner);
|
|
6682
6897
|
case "permission_required":
|
|
6683
6898
|
return {
|
|
6684
6899
|
status: "authority_required",
|
|
@@ -6723,6 +6938,47 @@ function classifySecretRead(reference, result) {
|
|
|
6723
6938
|
error: operationError("SECRET_READ_FAILED", "The secret read failed.")
|
|
6724
6939
|
};
|
|
6725
6940
|
}
|
|
6941
|
+
function missingSecretOutcome(reference, localOwner) {
|
|
6942
|
+
const owner = ownerOfSpace(reference.space);
|
|
6943
|
+
const recovery = missingSecretRecovery({
|
|
6944
|
+
owner,
|
|
6945
|
+
local: localOwner,
|
|
6946
|
+
names: [reference.name],
|
|
6947
|
+
...reference.scope === void 0 ? {} : { scope: reference.scope }
|
|
6948
|
+
});
|
|
6949
|
+
if (recovery.kind === "add_secret") {
|
|
6950
|
+
const { setup } = recovery;
|
|
6951
|
+
return {
|
|
6952
|
+
status: "setup_required",
|
|
6953
|
+
setup: {
|
|
6954
|
+
kind: "secret_manager",
|
|
6955
|
+
action: setup.action,
|
|
6956
|
+
url: setup.url,
|
|
6957
|
+
names: setup.names,
|
|
6958
|
+
...setup.scope === void 0 ? {} : { scope: setup.scope },
|
|
6959
|
+
owner: setup.owner,
|
|
6960
|
+
secret: {
|
|
6961
|
+
name: reference.name,
|
|
6962
|
+
...reference.scope === void 0 ? {} : { scope: reference.scope },
|
|
6963
|
+
space: reference.space
|
|
6964
|
+
},
|
|
6965
|
+
message: "Ask the owner to add this secret in Secret Manager, then retry the operation."
|
|
6966
|
+
},
|
|
6967
|
+
requiresCallerInput: true
|
|
6968
|
+
};
|
|
6969
|
+
}
|
|
6970
|
+
return {
|
|
6971
|
+
status: "error",
|
|
6972
|
+
error: operationError("KV_NOT_FOUND", recovery.hint, {
|
|
6973
|
+
details: {
|
|
6974
|
+
names: [reference.name],
|
|
6975
|
+
...reference.scope === void 0 ? {} : { scope: reference.scope },
|
|
6976
|
+
...owner === void 0 ? {} : { owner },
|
|
6977
|
+
recoveryKind: recovery.kind
|
|
6978
|
+
}
|
|
6979
|
+
})
|
|
6980
|
+
};
|
|
6981
|
+
}
|
|
6726
6982
|
function resolveEncryptionNetworkId(node, space) {
|
|
6727
6983
|
const candidate = node;
|
|
6728
6984
|
let scoped;
|
|
@@ -6749,6 +7005,7 @@ var init_secrets_get = __esm({
|
|
|
6749
7005
|
"src/operations/secrets-get.ts"() {
|
|
6750
7006
|
"use strict";
|
|
6751
7007
|
init_errors2();
|
|
7008
|
+
init_secret_request();
|
|
6752
7009
|
init_secrets();
|
|
6753
7010
|
SecretsGetInputSchema = z5.object({
|
|
6754
7011
|
name: z5.string(),
|
|
@@ -6800,9 +7057,197 @@ var init_secrets_get = __esm({
|
|
|
6800
7057
|
}
|
|
6801
7058
|
});
|
|
6802
7059
|
|
|
7060
|
+
// src/operations/secrets-status.ts
|
|
7061
|
+
import { z as z6 } from "zod";
|
|
7062
|
+
import * as nodeSdk4 from "@tinycloud/node-sdk";
|
|
7063
|
+
async function executeSecretsStatus(context, input) {
|
|
7064
|
+
const runtime = context.runtime;
|
|
7065
|
+
const node = runtime?.node;
|
|
7066
|
+
if (runtime === void 0 || typeof node?.kvForSpace !== "function") {
|
|
7067
|
+
return {
|
|
7068
|
+
status: "error",
|
|
7069
|
+
error: operationError("NODE_ERROR", "The TinyCloud node could not check the secrets.", { retryable: true })
|
|
7070
|
+
};
|
|
7071
|
+
}
|
|
7072
|
+
const local = runtime.localOwner === true;
|
|
7073
|
+
const resolution = resolveSecretsOwner({
|
|
7074
|
+
local,
|
|
7075
|
+
posture: context.summary.posture,
|
|
7076
|
+
...context.summary.ownerDid === void 0 ? {} : { ownerDid: context.summary.ownerDid },
|
|
7077
|
+
...context.summary.principalDid === void 0 ? {} : { principalDid: context.summary.principalDid },
|
|
7078
|
+
...context.summary.space === void 0 ? {} : { space: context.summary.space }
|
|
7079
|
+
}, input.owner);
|
|
7080
|
+
if (!resolution.ok) {
|
|
7081
|
+
return {
|
|
7082
|
+
status: "error",
|
|
7083
|
+
error: operationError("INPUT_INVALID", resolution.message, { details: { reason: resolution.code } })
|
|
7084
|
+
};
|
|
7085
|
+
}
|
|
7086
|
+
const owner = resolution.owner;
|
|
7087
|
+
const skipped2 = runtime.skippedGrantReasons ?? [];
|
|
7088
|
+
const pkh = nodeSdk4.parsePkhDid(owner);
|
|
7089
|
+
const kv = node.kvForSpace(nodeSdk4.makePkhSpaceId(pkh.address, pkh.chainId, "secrets"));
|
|
7090
|
+
const outcomes = await Promise.all(input.names.map(async (name) => {
|
|
7091
|
+
const path = input.scope === void 0 ? `vault/secrets/${name}` : `vault/secrets/scoped/${input.scope}/${name}`;
|
|
7092
|
+
try {
|
|
7093
|
+
const result = await kv.get(path, { raw: true, prefix: "", timeout: PROBE_TIMEOUT_MS });
|
|
7094
|
+
if (result.ok) return "present";
|
|
7095
|
+
const error = result.error;
|
|
7096
|
+
if (typeof error === "object" && error !== null && "code" in error && error.code === "KV_NOT_FOUND") {
|
|
7097
|
+
return "pending";
|
|
7098
|
+
}
|
|
7099
|
+
const refusal = kvRefusal(error);
|
|
7100
|
+
if (refusal === "auth_required") return "auth_required";
|
|
7101
|
+
if (refusal === "permission_denied") return "denied";
|
|
7102
|
+
return "unreachable";
|
|
7103
|
+
} catch {
|
|
7104
|
+
return "unreachable";
|
|
7105
|
+
}
|
|
7106
|
+
}));
|
|
7107
|
+
const namesWith = (outcome) => input.names.filter((_, index) => outcomes[index] === outcome);
|
|
7108
|
+
const present = namesWith("present");
|
|
7109
|
+
const pending = namesWith("pending");
|
|
7110
|
+
const denied = namesWith("denied");
|
|
7111
|
+
if (present.length + pending.length < input.names.length) {
|
|
7112
|
+
if (outcomes.includes("auth_required") || skipped2.includes("activation_unauthenticated")) {
|
|
7113
|
+
return {
|
|
7114
|
+
status: "error",
|
|
7115
|
+
error: operationError(
|
|
7116
|
+
"AUTH_REQUIRED",
|
|
7117
|
+
"The node did not accept this profile's stored session. Sign in again, then retry.",
|
|
7118
|
+
{ retryable: false, details: { recovery: signInRecovery(context.summary.profile, context.summary.posture) } }
|
|
7119
|
+
)
|
|
7120
|
+
};
|
|
7121
|
+
}
|
|
7122
|
+
if (outcomes.includes("unreachable") || skipped2.includes("activation_unavailable")) {
|
|
7123
|
+
return {
|
|
7124
|
+
status: "error",
|
|
7125
|
+
error: operationError("NODE_UNREACHABLE", "The TinyCloud node could not be reached.", { retryable: true })
|
|
7126
|
+
};
|
|
7127
|
+
}
|
|
7128
|
+
}
|
|
7129
|
+
const recovery = pending.length === 0 ? void 0 : missingSecretRecovery({
|
|
7130
|
+
owner,
|
|
7131
|
+
local,
|
|
7132
|
+
names: pending,
|
|
7133
|
+
...input.scope === void 0 ? {} : { scope: input.scope }
|
|
7134
|
+
});
|
|
7135
|
+
return {
|
|
7136
|
+
status: "ok",
|
|
7137
|
+
output: {
|
|
7138
|
+
status: denied.length > 0 ? "consent_required" : pending.length > 0 ? "pending" : "ready",
|
|
7139
|
+
owner,
|
|
7140
|
+
names: [...input.names],
|
|
7141
|
+
...input.scope === void 0 ? {} : { scope: input.scope },
|
|
7142
|
+
present,
|
|
7143
|
+
pending,
|
|
7144
|
+
denied,
|
|
7145
|
+
...recovery === void 0 ? {} : recovery.kind === "add_secret" ? { setup: recovery.setup } : { hint: recovery.hint }
|
|
7146
|
+
}
|
|
7147
|
+
};
|
|
7148
|
+
}
|
|
7149
|
+
var PROBE_TIMEOUT_MS, SECRETS_STATUS_DEADLINE_MS, SecretsStatusInputSchema, SecretSetupSchema, SecretsStatusOutputSchema, SECRETS_STATUS_POSTURES, SECRETS_STATUS_EXPOSURE, SECRETS_STATUS_SENSITIVITY, secretsStatusOperationDefinition, secretsStatusOperationDefinitions;
|
|
7150
|
+
var init_secrets_status = __esm({
|
|
7151
|
+
"src/operations/secrets-status.ts"() {
|
|
7152
|
+
"use strict";
|
|
7153
|
+
init_errors2();
|
|
7154
|
+
init_kv_failure();
|
|
7155
|
+
init_recovery();
|
|
7156
|
+
init_secret_request();
|
|
7157
|
+
init_secrets();
|
|
7158
|
+
PROBE_TIMEOUT_MS = 15e3;
|
|
7159
|
+
SECRETS_STATUS_DEADLINE_MS = 18e3;
|
|
7160
|
+
SecretsStatusInputSchema = z6.object({
|
|
7161
|
+
names: z6.array(z6.string()),
|
|
7162
|
+
scope: z6.string().optional(),
|
|
7163
|
+
owner: z6.string().optional()
|
|
7164
|
+
}).strict().superRefine((input, context) => {
|
|
7165
|
+
try {
|
|
7166
|
+
validSecretNames(input.names);
|
|
7167
|
+
} catch {
|
|
7168
|
+
context.addIssue({ code: z6.ZodIssueCode.custom, path: ["names"], message: "Invalid secret names." });
|
|
7169
|
+
}
|
|
7170
|
+
try {
|
|
7171
|
+
const scope = canonicalizeSecretScope(input.scope);
|
|
7172
|
+
if (scope !== void 0 && !isValidSecretRequestScope(scope)) throw new Error("invalid scope");
|
|
7173
|
+
} catch {
|
|
7174
|
+
context.addIssue({ code: z6.ZodIssueCode.custom, path: ["scope"], message: "Invalid secret scope." });
|
|
7175
|
+
}
|
|
7176
|
+
if (input.owner !== void 0) {
|
|
7177
|
+
try {
|
|
7178
|
+
canonicalSecretRequestOwner(input.owner);
|
|
7179
|
+
} catch {
|
|
7180
|
+
context.addIssue({ code: z6.ZodIssueCode.custom, path: ["owner"], message: "Invalid owner." });
|
|
7181
|
+
}
|
|
7182
|
+
}
|
|
7183
|
+
}).transform((input) => {
|
|
7184
|
+
const scope = canonicalizeSecretScope(input.scope);
|
|
7185
|
+
return {
|
|
7186
|
+
names: validSecretNames(input.names),
|
|
7187
|
+
...scope === void 0 ? {} : { scope },
|
|
7188
|
+
...input.owner === void 0 ? {} : { owner: canonicalSecretRequestOwner(input.owner) }
|
|
7189
|
+
};
|
|
7190
|
+
});
|
|
7191
|
+
SecretSetupSchema = z6.object({
|
|
7192
|
+
url: z6.string().url(),
|
|
7193
|
+
names: z6.array(z6.string()).min(1),
|
|
7194
|
+
scope: z6.string().optional(),
|
|
7195
|
+
owner: z6.string(),
|
|
7196
|
+
action: z6.literal("add_secret")
|
|
7197
|
+
}).strict();
|
|
7198
|
+
SecretsStatusOutputSchema = z6.object({
|
|
7199
|
+
status: z6.enum(["ready", "pending", "consent_required"]),
|
|
7200
|
+
owner: z6.string(),
|
|
7201
|
+
names: z6.array(z6.string()).min(1),
|
|
7202
|
+
scope: z6.string().optional(),
|
|
7203
|
+
present: z6.array(z6.string()),
|
|
7204
|
+
pending: z6.array(z6.string()),
|
|
7205
|
+
denied: z6.array(z6.string()),
|
|
7206
|
+
setup: SecretSetupSchema.optional(),
|
|
7207
|
+
hint: z6.string().optional()
|
|
7208
|
+
}).strict();
|
|
7209
|
+
SECRETS_STATUS_POSTURES = [
|
|
7210
|
+
"owner-openkey",
|
|
7211
|
+
"delegate-session",
|
|
7212
|
+
"local-owner-key"
|
|
7213
|
+
];
|
|
7214
|
+
SECRETS_STATUS_EXPOSURE = {
|
|
7215
|
+
cli: { status: "required" },
|
|
7216
|
+
mcp: { status: "required" },
|
|
7217
|
+
skill: { status: "required" },
|
|
7218
|
+
docs: { status: "required" }
|
|
7219
|
+
};
|
|
7220
|
+
SECRETS_STATUS_SENSITIVITY = {
|
|
7221
|
+
input: [],
|
|
7222
|
+
output: []
|
|
7223
|
+
};
|
|
7224
|
+
secretsStatusOperationDefinition = {
|
|
7225
|
+
id: "tinycloud.secrets.status",
|
|
7226
|
+
version: 1,
|
|
7227
|
+
title: "Check whether TinyCloud secrets exist",
|
|
7228
|
+
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.",
|
|
7229
|
+
input: SecretsStatusInputSchema,
|
|
7230
|
+
output: SecretsStatusOutputSchema,
|
|
7231
|
+
effects: ["read"],
|
|
7232
|
+
runtime: "restored",
|
|
7233
|
+
postures: SECRETS_STATUS_POSTURES,
|
|
7234
|
+
exposure: SECRETS_STATUS_EXPOSURE,
|
|
7235
|
+
sensitivity: SECRETS_STATUS_SENSITIVITY,
|
|
7236
|
+
deadlineMs: SECRETS_STATUS_DEADLINE_MS,
|
|
7237
|
+
// Never evaluated against the session: a missing grant is reported as
|
|
7238
|
+
// `consent_required`, never saved as an authority request.
|
|
7239
|
+
authority: async () => [],
|
|
7240
|
+
execute: executeSecretsStatus
|
|
7241
|
+
};
|
|
7242
|
+
secretsStatusOperationDefinitions = [
|
|
7243
|
+
secretsStatusOperationDefinition
|
|
7244
|
+
];
|
|
7245
|
+
}
|
|
7246
|
+
});
|
|
7247
|
+
|
|
6803
7248
|
// src/operations/sql.ts
|
|
6804
7249
|
import nodeSqlParser from "node-sql-parser";
|
|
6805
|
-
import { z as
|
|
7250
|
+
import { z as z7 } from "zod";
|
|
6806
7251
|
async function planSqlRead(context, input) {
|
|
6807
7252
|
const space = resolveSqlSpace(context, input.space);
|
|
6808
7253
|
return [{
|
|
@@ -7120,7 +7565,7 @@ var init_sql = __esm({
|
|
|
7120
7565
|
"use strict";
|
|
7121
7566
|
init_errors2();
|
|
7122
7567
|
init_secrets();
|
|
7123
|
-
|
|
7568
|
+
init_kv_failure();
|
|
7124
7569
|
DEFAULT_MAX_ROWS = 100;
|
|
7125
7570
|
MAX_MAX_ROWS = 1e3;
|
|
7126
7571
|
DEFAULT_MAX_BYTES = 1024 * 1024;
|
|
@@ -7136,29 +7581,29 @@ WHERE type IN ('table', 'view', 'index', 'trigger')
|
|
|
7136
7581
|
AND name NOT LIKE 'sqlite_%'
|
|
7137
7582
|
ORDER BY type, name`;
|
|
7138
7583
|
sqlParser = new nodeSqlParser.Parser();
|
|
7139
|
-
SpaceSchema2 =
|
|
7584
|
+
SpaceSchema2 = z7.string().min(1).refine(
|
|
7140
7585
|
(space) => (/^[A-Za-z0-9_-]+$/.test(space) || space.startsWith("tinycloud:")) && !space.includes("*"),
|
|
7141
7586
|
"Invalid TinyCloud space."
|
|
7142
7587
|
);
|
|
7143
|
-
DatabaseSchema =
|
|
7588
|
+
DatabaseSchema = z7.string().min(1).max(256).refine(
|
|
7144
7589
|
(database) => database !== "/" && !database.endsWith("/") && !database.includes("*") && !/[\u0000-\u001f\u007f]/.test(database),
|
|
7145
7590
|
"Invalid SQLite database name."
|
|
7146
7591
|
);
|
|
7147
|
-
SafeNumberSchema =
|
|
7592
|
+
SafeNumberSchema = z7.number().finite().refine(
|
|
7148
7593
|
(value) => !Number.isInteger(value) || Number.isSafeInteger(value),
|
|
7149
7594
|
"SQLite integer parameters must be JavaScript safe integers."
|
|
7150
7595
|
);
|
|
7151
|
-
Base64Schema =
|
|
7596
|
+
Base64Schema = z7.string().max(Math.ceil(MAX_MAX_BYTES / 3) * 4).refine(
|
|
7152
7597
|
isCanonicalBase642,
|
|
7153
7598
|
"Invalid base64 BLOB value."
|
|
7154
7599
|
);
|
|
7155
|
-
SqlInputValueSchema =
|
|
7156
|
-
|
|
7600
|
+
SqlInputValueSchema = z7.union([
|
|
7601
|
+
z7.null(),
|
|
7157
7602
|
SafeNumberSchema,
|
|
7158
|
-
|
|
7159
|
-
|
|
7603
|
+
z7.string().max(MAX_MAX_BYTES),
|
|
7604
|
+
z7.object({ type: z7.literal("blob"), base64: Base64Schema }).strict()
|
|
7160
7605
|
]);
|
|
7161
|
-
SqlParamsSchema =
|
|
7606
|
+
SqlParamsSchema = z7.array(SqlInputValueSchema).max(MAX_PARAMETERS).superRefine(
|
|
7162
7607
|
(params, context) => {
|
|
7163
7608
|
const totalBytes = params.reduce(
|
|
7164
7609
|
(total, value) => total + sqlInputValueBytes(value),
|
|
@@ -7166,13 +7611,13 @@ ORDER BY type, name`;
|
|
|
7166
7611
|
);
|
|
7167
7612
|
if (totalBytes > MAX_MAX_BYTES) {
|
|
7168
7613
|
context.addIssue({
|
|
7169
|
-
code:
|
|
7614
|
+
code: z7.ZodIssueCode.custom,
|
|
7170
7615
|
message: "SQLite query parameters exceed the 4 MiB input limit."
|
|
7171
7616
|
});
|
|
7172
7617
|
}
|
|
7173
7618
|
}
|
|
7174
7619
|
);
|
|
7175
|
-
RequiredSqlParamsSchema =
|
|
7620
|
+
RequiredSqlParamsSchema = z7.array(SqlInputValueSchema).min(1).max(MAX_PARAMETERS).superRefine(
|
|
7176
7621
|
(params, context) => {
|
|
7177
7622
|
const totalBytes = params.reduce(
|
|
7178
7623
|
(total, value) => total + sqlInputValueBytes(value),
|
|
@@ -7180,88 +7625,88 @@ ORDER BY type, name`;
|
|
|
7180
7625
|
);
|
|
7181
7626
|
if (totalBytes > MAX_MAX_BYTES) {
|
|
7182
7627
|
context.addIssue({
|
|
7183
|
-
code:
|
|
7628
|
+
code: z7.ZodIssueCode.custom,
|
|
7184
7629
|
message: "SQLite query parameters exceed the 4 MiB input limit."
|
|
7185
7630
|
});
|
|
7186
7631
|
}
|
|
7187
7632
|
}
|
|
7188
7633
|
);
|
|
7189
|
-
SqlOutputValueSchema =
|
|
7190
|
-
|
|
7634
|
+
SqlOutputValueSchema = z7.union([
|
|
7635
|
+
z7.null(),
|
|
7191
7636
|
SafeNumberSchema,
|
|
7192
|
-
|
|
7193
|
-
|
|
7194
|
-
type:
|
|
7195
|
-
base64:
|
|
7196
|
-
byteLength:
|
|
7637
|
+
z7.string(),
|
|
7638
|
+
z7.object({
|
|
7639
|
+
type: z7.literal("blob"),
|
|
7640
|
+
base64: z7.string(),
|
|
7641
|
+
byteLength: z7.number().int().nonnegative()
|
|
7197
7642
|
}).strict()
|
|
7198
7643
|
]);
|
|
7199
|
-
SqlTargetInputSchema =
|
|
7644
|
+
SqlTargetInputSchema = z7.object({
|
|
7200
7645
|
space: SpaceSchema2,
|
|
7201
7646
|
database: DatabaseSchema
|
|
7202
7647
|
}).strict();
|
|
7203
|
-
SqlQueryInputSchema =
|
|
7648
|
+
SqlQueryInputSchema = z7.object({
|
|
7204
7649
|
space: SpaceSchema2,
|
|
7205
7650
|
database: DatabaseSchema,
|
|
7206
|
-
sql:
|
|
7651
|
+
sql: z7.string().min(1).max(MAX_SQL_LENGTH).superRefine((sql, context) => {
|
|
7207
7652
|
if (!isSingleReadQuery(sql)) {
|
|
7208
7653
|
context.addIssue({
|
|
7209
|
-
code:
|
|
7654
|
+
code: z7.ZodIssueCode.custom,
|
|
7210
7655
|
message: "SQL must parse as exactly one SQLite SELECT statement."
|
|
7211
7656
|
});
|
|
7212
7657
|
}
|
|
7213
7658
|
}),
|
|
7214
7659
|
params: SqlParamsSchema.optional(),
|
|
7215
|
-
maxRows:
|
|
7216
|
-
maxBytes:
|
|
7660
|
+
maxRows: z7.number().int().positive().max(MAX_MAX_ROWS).optional(),
|
|
7661
|
+
maxBytes: z7.number().int().positive().max(MAX_MAX_BYTES).optional()
|
|
7217
7662
|
}).strict();
|
|
7218
|
-
SqlExecuteInputSchema =
|
|
7663
|
+
SqlExecuteInputSchema = z7.object({
|
|
7219
7664
|
space: SpaceSchema2,
|
|
7220
7665
|
database: DatabaseSchema,
|
|
7221
|
-
sql:
|
|
7666
|
+
sql: z7.string().min(1).max(MAX_SQL_LENGTH),
|
|
7222
7667
|
params: RequiredSqlParamsSchema,
|
|
7223
|
-
acknowledgeDatabaseWideAuthority:
|
|
7668
|
+
acknowledgeDatabaseWideAuthority: z7.literal(true).describe(SQL_WRITE_AUTHORITY_NOTICE)
|
|
7224
7669
|
}).strict().superRefine((input, context) => {
|
|
7225
7670
|
if (parseSingleDmlStatement(input.sql, input.params.length) === void 0) {
|
|
7226
7671
|
context.addIssue({
|
|
7227
|
-
code:
|
|
7672
|
+
code: z7.ZodIssueCode.custom,
|
|
7228
7673
|
path: ["sql"],
|
|
7229
7674
|
message: "SQL must parse as exactly one parameterized INSERT, UPDATE, or DELETE with one value per positional placeholder."
|
|
7230
7675
|
});
|
|
7231
7676
|
}
|
|
7232
7677
|
});
|
|
7233
|
-
SqlLimitsOutputSchema =
|
|
7234
|
-
maxRows:
|
|
7235
|
-
maxBytes:
|
|
7236
|
-
enforcement:
|
|
7678
|
+
SqlLimitsOutputSchema = z7.object({
|
|
7679
|
+
maxRows: z7.number().int().positive(),
|
|
7680
|
+
maxBytes: z7.number().int().positive(),
|
|
7681
|
+
enforcement: z7.literal("node-requested-client-verified")
|
|
7237
7682
|
}).strict();
|
|
7238
|
-
SqlSchemaInspectOutputSchema =
|
|
7239
|
-
space:
|
|
7240
|
-
database:
|
|
7241
|
-
objects:
|
|
7242
|
-
type:
|
|
7243
|
-
name:
|
|
7244
|
-
tableName:
|
|
7245
|
-
sql:
|
|
7683
|
+
SqlSchemaInspectOutputSchema = z7.object({
|
|
7684
|
+
space: z7.string().min(1),
|
|
7685
|
+
database: z7.string().min(1),
|
|
7686
|
+
objects: z7.array(z7.object({
|
|
7687
|
+
type: z7.enum(["table", "view", "index", "trigger"]),
|
|
7688
|
+
name: z7.string().min(1),
|
|
7689
|
+
tableName: z7.string().min(1),
|
|
7690
|
+
sql: z7.string().optional()
|
|
7246
7691
|
}).strict()),
|
|
7247
|
-
count:
|
|
7692
|
+
count: z7.number().int().nonnegative(),
|
|
7248
7693
|
limits: SqlLimitsOutputSchema
|
|
7249
7694
|
}).strict();
|
|
7250
|
-
SqlQueryOutputSchema =
|
|
7251
|
-
space:
|
|
7252
|
-
database:
|
|
7253
|
-
columns:
|
|
7254
|
-
rows:
|
|
7255
|
-
rowCount:
|
|
7695
|
+
SqlQueryOutputSchema = z7.object({
|
|
7696
|
+
space: z7.string().min(1),
|
|
7697
|
+
database: z7.string().min(1),
|
|
7698
|
+
columns: z7.array(z7.string()),
|
|
7699
|
+
rows: z7.array(z7.array(SqlOutputValueSchema)),
|
|
7700
|
+
rowCount: z7.number().int().nonnegative(),
|
|
7256
7701
|
limits: SqlLimitsOutputSchema
|
|
7257
7702
|
}).strict();
|
|
7258
|
-
SqlExecuteOutputSchema =
|
|
7259
|
-
space:
|
|
7260
|
-
database:
|
|
7261
|
-
statementType:
|
|
7262
|
-
changes:
|
|
7263
|
-
lastInsertRowId:
|
|
7264
|
-
authorityNotice:
|
|
7703
|
+
SqlExecuteOutputSchema = z7.object({
|
|
7704
|
+
space: z7.string().min(1),
|
|
7705
|
+
database: z7.string().min(1),
|
|
7706
|
+
statementType: z7.enum(["insert", "update", "delete"]),
|
|
7707
|
+
changes: z7.number().int().nonnegative(),
|
|
7708
|
+
lastInsertRowId: z7.number().int().nullable(),
|
|
7709
|
+
authorityNotice: z7.literal(SQL_WRITE_AUTHORITY_NOTICE)
|
|
7265
7710
|
}).strict();
|
|
7266
7711
|
AUTHENTICATED_POSTURES2 = [
|
|
7267
7712
|
"owner-openkey",
|
|
@@ -7361,6 +7806,8 @@ var init_contract = __esm({
|
|
|
7361
7806
|
"resources_mismatch",
|
|
7362
7807
|
"unsupported",
|
|
7363
7808
|
"activation_rejected",
|
|
7809
|
+
"activation_unavailable",
|
|
7810
|
+
"activation_unauthenticated",
|
|
7364
7811
|
"invalid"
|
|
7365
7812
|
];
|
|
7366
7813
|
DELEGATION_CID_PATTERN = "^bafkr4i[a-z2-7]{52}$";
|
|
@@ -7369,7 +7816,7 @@ var init_contract = __esm({
|
|
|
7369
7816
|
|
|
7370
7817
|
// src/delegation-binding.ts
|
|
7371
7818
|
import { join as join2 } from "path";
|
|
7372
|
-
import * as
|
|
7819
|
+
import * as nodeSdk5 from "@tinycloud/node-sdk";
|
|
7373
7820
|
function bindingMigrationPath(profile) {
|
|
7374
7821
|
return join2(profilePath(profile), "delegation-binding-migration.json");
|
|
7375
7822
|
}
|
|
@@ -7465,6 +7912,9 @@ function skipped(reason) {
|
|
|
7465
7912
|
}
|
|
7466
7913
|
async function replayProfileDelegations(profile, node, options) {
|
|
7467
7914
|
await prepareStoredDelegationReplay(profile, node, { host: options.host, migrate: options.migrate });
|
|
7915
|
+
return replayStoredDelegationRecords(profile, node, options);
|
|
7916
|
+
}
|
|
7917
|
+
async function replayStoredDelegationRecords(profile, node, options) {
|
|
7468
7918
|
const installed = [];
|
|
7469
7919
|
const warnings = [];
|
|
7470
7920
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -7505,7 +7955,7 @@ function storedDelegationForAnotherKey(entry, node) {
|
|
|
7505
7955
|
const audience = verifiedCompactAudience(node, delegation);
|
|
7506
7956
|
if (audience === void 0) return false;
|
|
7507
7957
|
try {
|
|
7508
|
-
return
|
|
7958
|
+
return nodeSdk5.principalDidEquals(delegation.delegateDID, audience) && !nodeSdk5.principalDidEquals(audience, node.sessionDid);
|
|
7509
7959
|
} catch {
|
|
7510
7960
|
return false;
|
|
7511
7961
|
}
|
|
@@ -7539,7 +7989,7 @@ async function assess(node, entry, options, mode) {
|
|
|
7539
7989
|
let outsideRequest = false;
|
|
7540
7990
|
let effectivePermissions;
|
|
7541
7991
|
try {
|
|
7542
|
-
const installed = await
|
|
7992
|
+
const installed = await nodeSdk5.activateValidatedRuntimeDelegation(node, toActivate, {
|
|
7543
7993
|
host: options.host,
|
|
7544
7994
|
authorize: (effective) => {
|
|
7545
7995
|
verifyCompactProof(toActivate);
|
|
@@ -7571,7 +8021,7 @@ function verifyCompactProof(delegation) {
|
|
|
7571
8021
|
try {
|
|
7572
8022
|
parseSignedCompactUcanAttenuation(withoutBearer(authorization), delegation.cid);
|
|
7573
8023
|
} catch {
|
|
7574
|
-
throw new
|
|
8024
|
+
throw new nodeSdk5.RuntimeDelegationRejectedError("proof_invalid", "The compact delegation proof is invalid.");
|
|
7575
8025
|
}
|
|
7576
8026
|
}
|
|
7577
8027
|
function rejectionReason(error) {
|
|
@@ -7588,7 +8038,7 @@ async function bindingMigrationRecorded(profile) {
|
|
|
7588
8038
|
async function signedCapabilities(node, delegation, host) {
|
|
7589
8039
|
let signed;
|
|
7590
8040
|
try {
|
|
7591
|
-
await
|
|
8041
|
+
await nodeSdk5.activateValidatedRuntimeDelegation(node, delegation, {
|
|
7592
8042
|
// The transport host is not signed authority; check it at replay instead.
|
|
7593
8043
|
host: delegation.host ?? host,
|
|
7594
8044
|
authorize: (effective) => {
|
|
@@ -7651,7 +8101,7 @@ var init_delegation_binding = __esm({
|
|
|
7651
8101
|
});
|
|
7652
8102
|
|
|
7653
8103
|
// src/operations/status.ts
|
|
7654
|
-
import { z as
|
|
8104
|
+
import { z as z8 } from "zod";
|
|
7655
8105
|
function createStatusDefinition(params) {
|
|
7656
8106
|
return {
|
|
7657
8107
|
id: params.id,
|
|
@@ -7776,27 +8226,27 @@ var init_status = __esm({
|
|
|
7776
8226
|
init_delegation_binding();
|
|
7777
8227
|
init_errors2();
|
|
7778
8228
|
init_state();
|
|
7779
|
-
StatusInputSchema =
|
|
7780
|
-
StatusOutputSchema =
|
|
7781
|
-
profile:
|
|
7782
|
-
host:
|
|
7783
|
-
posture:
|
|
8229
|
+
StatusInputSchema = z8.object({}).strict();
|
|
8230
|
+
StatusOutputSchema = z8.object({
|
|
8231
|
+
profile: z8.string().min(1),
|
|
8232
|
+
host: z8.string().min(1),
|
|
8233
|
+
posture: z8.enum([
|
|
7784
8234
|
"owner-openkey",
|
|
7785
8235
|
"delegate-session",
|
|
7786
8236
|
"local-owner-key",
|
|
7787
8237
|
"unauthenticated"
|
|
7788
8238
|
]),
|
|
7789
|
-
operatorType:
|
|
7790
|
-
principalDid:
|
|
7791
|
-
sessionDid:
|
|
7792
|
-
ownerDid:
|
|
7793
|
-
space:
|
|
7794
|
-
session:
|
|
7795
|
-
present:
|
|
7796
|
-
expired:
|
|
7797
|
-
expiresAt:
|
|
8239
|
+
operatorType: z8.enum(["human", "agent"]).optional(),
|
|
8240
|
+
principalDid: z8.string().min(1).optional(),
|
|
8241
|
+
sessionDid: z8.string().min(1).optional(),
|
|
8242
|
+
ownerDid: z8.string().min(1).optional(),
|
|
8243
|
+
space: z8.string().min(1).optional(),
|
|
8244
|
+
session: z8.object({
|
|
8245
|
+
present: z8.boolean(),
|
|
8246
|
+
expired: z8.boolean().nullable(),
|
|
8247
|
+
expiresAt: z8.string().datetime({ offset: true }).nullable()
|
|
7798
8248
|
}).strict(),
|
|
7799
|
-
liveAdditionalDelegationCount:
|
|
8249
|
+
liveAdditionalDelegationCount: z8.number().int().nonnegative().describe(
|
|
7800
8250
|
"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."
|
|
7801
8251
|
)
|
|
7802
8252
|
}).strict();
|
|
@@ -7840,7 +8290,8 @@ function registeredOperationDefinitions() {
|
|
|
7840
8290
|
...authOperationDefinitions,
|
|
7841
8291
|
...explorationOperationDefinitions,
|
|
7842
8292
|
...sqlOperationDefinitions,
|
|
7843
|
-
...secretsGetOperationDefinitions
|
|
8293
|
+
...secretsGetOperationDefinitions,
|
|
8294
|
+
...secretsStatusOperationDefinitions
|
|
7844
8295
|
]);
|
|
7845
8296
|
return operationDefinitions;
|
|
7846
8297
|
}
|
|
@@ -7872,6 +8323,7 @@ var init_registry = __esm({
|
|
|
7872
8323
|
init_auth();
|
|
7873
8324
|
init_exploration();
|
|
7874
8325
|
init_secrets_get();
|
|
8326
|
+
init_secrets_status();
|
|
7875
8327
|
init_sql();
|
|
7876
8328
|
init_status();
|
|
7877
8329
|
}
|
|
@@ -7924,6 +8376,9 @@ function resolvePosture(profile) {
|
|
|
7924
8376
|
if (profile.authMethod === "local") return "local-owner-key";
|
|
7925
8377
|
return "owner-openkey";
|
|
7926
8378
|
}
|
|
8379
|
+
function isLocalOwnerProfile(profile) {
|
|
8380
|
+
return resolvePosture(profile) === "local-owner-key" || profile.authMethod === "local" || typeof profile.privateKey === "string";
|
|
8381
|
+
}
|
|
7927
8382
|
function profileNotFound2(profile) {
|
|
7928
8383
|
return {
|
|
7929
8384
|
ok: false,
|
|
@@ -7995,7 +8450,7 @@ var runtime_exports = {};
|
|
|
7995
8450
|
__export(runtime_exports, {
|
|
7996
8451
|
createInvocationRuntime: () => createInvocationRuntime
|
|
7997
8452
|
});
|
|
7998
|
-
import * as
|
|
8453
|
+
import * as nodeSdk6 from "@tinycloud/node-sdk";
|
|
7999
8454
|
async function createInvocationRuntime(target, requirement = "authenticated") {
|
|
8000
8455
|
const resolved = await resolveInvocationProfile(target);
|
|
8001
8456
|
if (!resolved.ok) {
|
|
@@ -8009,11 +8464,14 @@ async function createInvocationRuntime(target, requirement = "authenticated") {
|
|
|
8009
8464
|
if (requirement === "inspection") {
|
|
8010
8465
|
return { ok: true, context: { summary } };
|
|
8011
8466
|
}
|
|
8467
|
+
if (requirement === "restored") {
|
|
8468
|
+
return createRestoredRuntime(target, resolved);
|
|
8469
|
+
}
|
|
8012
8470
|
const profileName = summary.profile;
|
|
8013
8471
|
try {
|
|
8014
8472
|
const {
|
|
8015
8473
|
TinyCloudNode: TinyCloudNodeConstructor
|
|
8016
|
-
} =
|
|
8474
|
+
} = nodeSdk6;
|
|
8017
8475
|
const explicitPrivateKeyOverride = typeof target.privateKey === "string";
|
|
8018
8476
|
const [session, key] = explicitPrivateKeyOverride ? [null, null] : await Promise.all([
|
|
8019
8477
|
readSession(profileName),
|
|
@@ -8091,7 +8549,9 @@ async function createInvocationRuntime(target, requirement = "authenticated") {
|
|
|
8091
8549
|
const runtime = {
|
|
8092
8550
|
node,
|
|
8093
8551
|
granted: canonicalizeCapabilities(livePermissions),
|
|
8094
|
-
...warnings.length === 0 ? {} : { warnings }
|
|
8552
|
+
...warnings.length === 0 ? {} : { warnings },
|
|
8553
|
+
localOwner: explicitPrivateKeyOverride || isLocalOwnerProfile(profile),
|
|
8554
|
+
skippedGrantReasons: warnings.map((warning) => warning.reason)
|
|
8095
8555
|
};
|
|
8096
8556
|
return {
|
|
8097
8557
|
ok: true,
|
|
@@ -8115,11 +8575,112 @@ async function createInvocationRuntime(target, requirement = "authenticated") {
|
|
|
8115
8575
|
));
|
|
8116
8576
|
}
|
|
8117
8577
|
}
|
|
8578
|
+
async function createRestoredRuntime(target, resolved) {
|
|
8579
|
+
const summary = resolved.context;
|
|
8580
|
+
const profileName = summary.profile;
|
|
8581
|
+
const profile = resolved.profile;
|
|
8582
|
+
if (typeof target.privateKey === "string") {
|
|
8583
|
+
return failed(summary, operationError(
|
|
8584
|
+
"AUTH_REQUIRED",
|
|
8585
|
+
"This operation never signs in; an explicit private key has no stored session.",
|
|
8586
|
+
{ details: { reason: "explicit_key" } }
|
|
8587
|
+
));
|
|
8588
|
+
}
|
|
8589
|
+
try {
|
|
8590
|
+
const actualPosture = resolvePosture(profile);
|
|
8591
|
+
const selectedPosture = profile.authMethod === "local" ? "local-owner-key" : summary.posture;
|
|
8592
|
+
if (actualPosture !== summary.posture || selectedPosture !== summary.posture) {
|
|
8593
|
+
return failed(
|
|
8594
|
+
{ ...summary, posture: actualPosture !== summary.posture ? actualPosture : selectedPosture },
|
|
8595
|
+
operationError(
|
|
8596
|
+
"PROFILE_POSTURE_NOT_ALLOWED",
|
|
8597
|
+
"The selected profile changed posture during runtime resolution."
|
|
8598
|
+
)
|
|
8599
|
+
);
|
|
8600
|
+
}
|
|
8601
|
+
const [session, key] = await Promise.all([
|
|
8602
|
+
readSession(profileName),
|
|
8603
|
+
readJson(`${profilePath(profileName)}/key.json`)
|
|
8604
|
+
]);
|
|
8605
|
+
const activeSession = session === null ? void 0 : normalizeSession(session, key);
|
|
8606
|
+
if (activeSession === void 0) {
|
|
8607
|
+
return failed(summary, operationError(
|
|
8608
|
+
"SESSION_NOT_FOUND",
|
|
8609
|
+
"The selected profile does not have an active session. This operation never signs in.",
|
|
8610
|
+
{ details: { recovery: signInRecovery(profileName, summary.posture) } }
|
|
8611
|
+
));
|
|
8612
|
+
}
|
|
8613
|
+
if (!await bindingMigrationRecorded(profileName)) {
|
|
8614
|
+
const records = await readAdditionalDelegations(profileName);
|
|
8615
|
+
if (records.some(
|
|
8616
|
+
(entry) => storedDelegationKind(entry) === "compact" && !("authorityRequest" in entry)
|
|
8617
|
+
)) {
|
|
8618
|
+
return failed(summary, operationError(
|
|
8619
|
+
"PROFILE_MIGRATION_REQUIRED",
|
|
8620
|
+
`Profile "${profileName}" has a one-time stored-grant upgrade to finish. Run one authenticated command on it (tc --profile <profile> auth caps), then retry.`,
|
|
8621
|
+
{ retryable: false, details: { recovery: migrationRecovery(profileName) } }
|
|
8622
|
+
));
|
|
8623
|
+
}
|
|
8624
|
+
}
|
|
8625
|
+
const { TinyCloudNode: TinyCloudNodeConstructor } = nodeSdk6;
|
|
8626
|
+
const node = new TinyCloudNodeConstructor({
|
|
8627
|
+
host: summary.host,
|
|
8628
|
+
...typeof profile.privateKey === "string" ? { privateKey: profile.privateKey } : {}
|
|
8629
|
+
});
|
|
8630
|
+
try {
|
|
8631
|
+
await node.restoreSession(activeSession);
|
|
8632
|
+
} catch (error) {
|
|
8633
|
+
if (isRecord7(error) && error.code === "AUTH_EXPIRED") {
|
|
8634
|
+
return failed(summary, operationError(
|
|
8635
|
+
"AUTH_REQUIRED",
|
|
8636
|
+
"The stored session has expired or is no longer valid. Sign in again.",
|
|
8637
|
+
{ retryable: false, details: { recovery: signInRecovery(profileName, summary.posture) } }
|
|
8638
|
+
));
|
|
8639
|
+
}
|
|
8640
|
+
throw error;
|
|
8641
|
+
}
|
|
8642
|
+
const activeSessionDid = normalizeDid(node.sessionDid);
|
|
8643
|
+
const livePrincipalDid = normalizeDid(node.did);
|
|
8644
|
+
const livePermissions = [...node.getVerifiedSessionCapabilities()];
|
|
8645
|
+
const replay = await replayStoredDelegationRecords(
|
|
8646
|
+
profileName,
|
|
8647
|
+
node,
|
|
8648
|
+
{ host: summary.host, resolveSpace: operationSpaceResolver(node, summary.space) }
|
|
8649
|
+
);
|
|
8650
|
+
for (const installed of replay.installed) {
|
|
8651
|
+
livePermissions.push(...installed.effectivePermissions);
|
|
8652
|
+
}
|
|
8653
|
+
const runtime = {
|
|
8654
|
+
node,
|
|
8655
|
+
granted: canonicalizeCapabilities(livePermissions),
|
|
8656
|
+
...replay.warnings.length === 0 ? {} : { warnings: replay.warnings },
|
|
8657
|
+
localOwner: isLocalOwnerProfile(profile),
|
|
8658
|
+
skippedGrantReasons: replay.warnings.map((warning) => warning.reason)
|
|
8659
|
+
};
|
|
8660
|
+
return {
|
|
8661
|
+
ok: true,
|
|
8662
|
+
context: {
|
|
8663
|
+
summary: {
|
|
8664
|
+
...summary,
|
|
8665
|
+
...livePrincipalDid === void 0 ? {} : { principalDid: livePrincipalDid },
|
|
8666
|
+
...activeSessionDid === void 0 ? {} : { sessionDid: activeSessionDid }
|
|
8667
|
+
},
|
|
8668
|
+
runtime
|
|
8669
|
+
}
|
|
8670
|
+
};
|
|
8671
|
+
} catch {
|
|
8672
|
+
return failed(summary, operationError(
|
|
8673
|
+
"NODE_ERROR",
|
|
8674
|
+
"The selected profile runtime could not be initialized.",
|
|
8675
|
+
{ retryable: true }
|
|
8676
|
+
));
|
|
8677
|
+
}
|
|
8678
|
+
}
|
|
8118
8679
|
function spaceForAuthenticatedPrincipal(principal2) {
|
|
8119
8680
|
if (principal2 === void 0) return void 0;
|
|
8120
8681
|
try {
|
|
8121
|
-
const pkh =
|
|
8122
|
-
return pkh === null ? void 0 :
|
|
8682
|
+
const pkh = nodeSdk6.parsePkhDid(principal2);
|
|
8683
|
+
return pkh === null ? void 0 : nodeSdk6.makePkhSpaceId(pkh.address, pkh.chainId, "secrets");
|
|
8123
8684
|
} catch {
|
|
8124
8685
|
return void 0;
|
|
8125
8686
|
}
|
|
@@ -8169,6 +8730,7 @@ var init_runtime = __esm({
|
|
|
8169
8730
|
init_authority();
|
|
8170
8731
|
init_errors2();
|
|
8171
8732
|
init_profile();
|
|
8733
|
+
init_recovery();
|
|
8172
8734
|
init_secrets();
|
|
8173
8735
|
init_state();
|
|
8174
8736
|
init_delegation_binding();
|
|
@@ -8183,11 +8745,14 @@ init_artifacts();
|
|
|
8183
8745
|
import { createHash } from "crypto";
|
|
8184
8746
|
import { isAbsolute as isAbsolute2 } from "path";
|
|
8185
8747
|
import {
|
|
8186
|
-
makePkhSpaceId as
|
|
8187
|
-
parsePkhDid as
|
|
8748
|
+
makePkhSpaceId as makePkhSpaceId4,
|
|
8749
|
+
parsePkhDid as parsePkhDid4,
|
|
8188
8750
|
parseSpaceUri as parseSpaceUri2
|
|
8189
8751
|
} from "@tinycloud/node-sdk";
|
|
8190
8752
|
|
|
8753
|
+
// src/redaction.ts
|
|
8754
|
+
init_recovery();
|
|
8755
|
+
|
|
8191
8756
|
// src/safe-values.ts
|
|
8192
8757
|
function safeOriginHost(value) {
|
|
8193
8758
|
if (typeof value !== "string" || value.length === 0) return void 0;
|
|
@@ -8264,7 +8829,25 @@ function redactOperationError(_definition, error) {
|
|
|
8264
8829
|
}
|
|
8265
8830
|
var SAFE_ERROR_DETAIL_POLICIES = {
|
|
8266
8831
|
INPUT_INVALID: {
|
|
8267
|
-
issues: (value) => Array.isArray(value) ? safeIssueCodes(value) : void 0
|
|
8832
|
+
issues: (value) => Array.isArray(value) ? safeIssueCodes(value) : void 0,
|
|
8833
|
+
reason: (value) => value === "OWNER_MISMATCH" || value === "OWNER_DID_UNKNOWN" ? value : void 0
|
|
8834
|
+
},
|
|
8835
|
+
AUTH_REQUIRED: {
|
|
8836
|
+
recovery: (value) => isSafeRecovery(value, "sign_in") ? { ...value } : void 0,
|
|
8837
|
+
reason: (value) => value === "explicit_key" ? value : void 0
|
|
8838
|
+
},
|
|
8839
|
+
SESSION_NOT_FOUND: {
|
|
8840
|
+
recovery: (value) => isSafeRecovery(value, "sign_in") ? { ...value } : void 0
|
|
8841
|
+
},
|
|
8842
|
+
PROFILE_MIGRATION_REQUIRED: {
|
|
8843
|
+
recovery: (value) => isSafeRecovery(value, "complete_migration") ? { ...value } : void 0
|
|
8844
|
+
},
|
|
8845
|
+
// `secrets.get` not found for an identity no request link serves.
|
|
8846
|
+
KV_NOT_FOUND: {
|
|
8847
|
+
recoveryKind: (value) => value === "put_locally" || value === "not_requestable" ? value : void 0,
|
|
8848
|
+
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,
|
|
8849
|
+
scope: (value) => typeof value === "string" && value.length <= 256 && /^[a-z0-9]+(-[a-z0-9]+)*$/.test(value) ? value : void 0,
|
|
8850
|
+
owner: (value) => typeof value === "string" && /^did:pkh:eip155:[1-9][0-9]*:0x[0-9a-fA-F]{40}$/.test(value) ? value : void 0
|
|
8268
8851
|
},
|
|
8269
8852
|
OPERATION_VERSION_UNSUPPORTED: {
|
|
8270
8853
|
supportedVersions: (value) => Array.isArray(value) && value.every((item) => Number.isInteger(item)) ? value : void 0
|
|
@@ -8548,7 +9131,7 @@ async function prepareInvocation(operationId, operationVersion, invocationTarget
|
|
|
8548
9131
|
)
|
|
8549
9132
|
) };
|
|
8550
9133
|
}
|
|
8551
|
-
if (target.privateKey === void 0 && definition.runtime
|
|
9134
|
+
if (target.privateKey === void 0 && requiresRuntime(definition.runtime) && isOwnerPosture(inspectionResolution.context.summary.posture) && target.allowOwnerProfile !== true) {
|
|
8552
9135
|
return { status: "error", result: errorResult(
|
|
8553
9136
|
operation,
|
|
8554
9137
|
inspectionResolution.context.summary,
|
|
@@ -8558,15 +9141,15 @@ async function prepareInvocation(operationId, operationVersion, invocationTarget
|
|
|
8558
9141
|
)
|
|
8559
9142
|
) };
|
|
8560
9143
|
}
|
|
8561
|
-
const runtimeResolution = definition.runtime === "inspection" ? inspectionResolution : await resolveRuntime(target,
|
|
9144
|
+
const runtimeResolution = definition.runtime === "inspection" ? inspectionResolution : await resolveRuntime(target, definition.runtime);
|
|
8562
9145
|
if (!runtimeResolution.ok) {
|
|
8563
9146
|
return { status: "error", result: errorResult(
|
|
8564
9147
|
operation,
|
|
8565
9148
|
runtimeResolution.context,
|
|
8566
|
-
runtimeResolution.error
|
|
9149
|
+
redactOperationError(definition, runtimeResolution.error)
|
|
8567
9150
|
) };
|
|
8568
9151
|
}
|
|
8569
|
-
if (definition.runtime
|
|
9152
|
+
if (requiresRuntime(definition.runtime)) {
|
|
8570
9153
|
const actualPosture = runtimeResolution.context.summary.posture;
|
|
8571
9154
|
if (!definition.postures.includes(actualPosture)) {
|
|
8572
9155
|
return { status: "error", result: errorResult(
|
|
@@ -8966,8 +9549,8 @@ function canonicalPkhOwner(space) {
|
|
|
8966
9549
|
const parsedSpace = parseSpaceUri2(space);
|
|
8967
9550
|
if (parsedSpace === null) return void 0;
|
|
8968
9551
|
try {
|
|
8969
|
-
const pkh =
|
|
8970
|
-
return pkh === null ? void 0 : parseSpaceUri2(
|
|
9552
|
+
const pkh = parsePkhDid4(parsedSpace.owner);
|
|
9553
|
+
return pkh === null ? void 0 : parseSpaceUri2(makePkhSpaceId4(pkh.address, pkh.chainId, parsedSpace.name))?.owner;
|
|
8971
9554
|
} catch {
|
|
8972
9555
|
return void 0;
|
|
8973
9556
|
}
|
|
@@ -9052,6 +9635,15 @@ function internalOperationErrorResult(prepared) {
|
|
|
9052
9635
|
function isOwnerPosture(posture) {
|
|
9053
9636
|
return posture === "owner-openkey" || posture === "local-owner-key";
|
|
9054
9637
|
}
|
|
9638
|
+
function requiresRuntime(requirement) {
|
|
9639
|
+
switch (requirement) {
|
|
9640
|
+
case "authenticated":
|
|
9641
|
+
case "restored":
|
|
9642
|
+
return true;
|
|
9643
|
+
case "inspection":
|
|
9644
|
+
return false;
|
|
9645
|
+
}
|
|
9646
|
+
}
|
|
9055
9647
|
function zodIssueDetails(error) {
|
|
9056
9648
|
return {
|
|
9057
9649
|
// The canonical error channel carries only schema-owned issue codes.
|