@tinycloud/operations 0.7.11-beta.2 → 0.8.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/dist/artifacts.d.cts +1 -1
- package/dist/artifacts.d.ts +1 -1
- package/dist/cli-runtime.cjs +395 -62
- 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 +391 -58
- package/dist/cli-runtime.js.map +1 -1
- package/dist/{contract-DrtFhVsg.d.cts → contract-BGJGxuGr.d.cts} +1 -1
- package/dist/{contract-DrtFhVsg.d.ts → contract-BGJGxuGr.d.ts} +1 -1
- package/dist/delegation-binding.cjs.map +1 -1
- package/dist/delegation-binding.d.cts +2 -2
- package/dist/delegation-binding.d.ts +2 -2
- package/dist/delegation-binding.js.map +1 -1
- package/dist/{index-CVP0YT2f.d.cts → index-BIdLBYGe.d.cts} +1 -1
- package/dist/{index-D-72hsQ_.d.ts → index-DuLdLxGh.d.ts} +1 -1
- package/dist/index.cjs +392 -59
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +389 -56
- package/dist/index.js.map +1 -1
- package/dist/mcp-authority.cjs.map +1 -1
- package/dist/mcp-authority.d.cts +2 -2
- package/dist/mcp-authority.d.ts +2 -2
- package/dist/mcp-authority.js.map +1 -1
- package/dist/profile.d.cts +1 -1
- package/dist/profile.d.ts +1 -1
- package/dist/recovery.d.cts +1 -1
- package/dist/recovery.d.ts +1 -1
- package/dist/secret-request.d.cts +1 -1
- package/dist/secret-request.d.ts +1 -1
- package/generated/operations.json +4180 -1232
- package/package.json +1 -1
package/dist/cli-runtime.d.cts
CHANGED
package/dist/cli-runtime.d.ts
CHANGED
package/dist/cli-runtime.js
CHANGED
|
@@ -342,6 +342,8 @@ var init_errors2 = __esm({
|
|
|
342
342
|
"SQL_EXECUTION_FAILED",
|
|
343
343
|
"SQL_RESULT_LIMIT_EXCEEDED",
|
|
344
344
|
"SQL_VALUE_UNSAFE",
|
|
345
|
+
"READ_SOURCE_CHANGED",
|
|
346
|
+
"READ_CONTEXT_MISMATCH",
|
|
345
347
|
"SECRET_READ_FAILED",
|
|
346
348
|
"SECRET_DECRYPT_FAILED",
|
|
347
349
|
"OUTPUT_INVALID",
|
|
@@ -7820,10 +7822,20 @@ async function executeKvList(context, input) {
|
|
|
7820
7822
|
const space = resolveGenericKvSpace(runtime, input.space);
|
|
7821
7823
|
const result = await genericKv(runtime, space).list({
|
|
7822
7824
|
...input.prefix === void 0 ? {} : { prefix: input.prefix },
|
|
7825
|
+
...input.cursor === void 0 ? {} : { cursor: input.cursor },
|
|
7823
7826
|
limit: input.limit ?? DEFAULT_KV_LIST_LIMIT
|
|
7824
7827
|
});
|
|
7825
|
-
if (!result.ok)
|
|
7828
|
+
if (!result.ok) {
|
|
7829
|
+
if (input.cursor !== void 0 && result.error.meta?.status === 400) {
|
|
7830
|
+
return {
|
|
7831
|
+
status: "error",
|
|
7832
|
+
error: operationError("INPUT_INVALID", "The node rejected the KV listing cursor. Restart the listing without a cursor and discard earlier pages rather than combining different listings.")
|
|
7833
|
+
};
|
|
7834
|
+
}
|
|
7835
|
+
return kvFailure(result.error, "list KV keys");
|
|
7836
|
+
}
|
|
7826
7837
|
const keys = [...result.data.keys];
|
|
7838
|
+
const nextCursor = result.data.nextCursor ?? null;
|
|
7827
7839
|
return {
|
|
7828
7840
|
status: "ok",
|
|
7829
7841
|
output: {
|
|
@@ -7831,7 +7843,8 @@ async function executeKvList(context, input) {
|
|
|
7831
7843
|
prefix: input.prefix ?? "",
|
|
7832
7844
|
keys,
|
|
7833
7845
|
count: keys.length,
|
|
7834
|
-
truncated: result.data.truncated
|
|
7846
|
+
truncated: result.data.truncated === true || nextCursor !== null,
|
|
7847
|
+
nextCursor
|
|
7835
7848
|
}
|
|
7836
7849
|
};
|
|
7837
7850
|
} catch (error) {
|
|
@@ -8245,14 +8258,16 @@ var init_exploration = __esm({
|
|
|
8245
8258
|
KvListInputSchema = z7.object({
|
|
8246
8259
|
space: SpaceSchema2,
|
|
8247
8260
|
prefix: PrefixSchema2.optional(),
|
|
8248
|
-
limit: LimitSchema.optional()
|
|
8261
|
+
limit: LimitSchema.optional(),
|
|
8262
|
+
cursor: z7.string().optional()
|
|
8249
8263
|
}).strict();
|
|
8250
8264
|
KvListOutputSchema = z7.object({
|
|
8251
8265
|
space: z7.string().min(1),
|
|
8252
8266
|
prefix: z7.string(),
|
|
8253
8267
|
keys: z7.array(z7.string()),
|
|
8254
8268
|
count: z7.number().int().nonnegative(),
|
|
8255
|
-
truncated: z7.boolean()
|
|
8269
|
+
truncated: z7.boolean(),
|
|
8270
|
+
nextCursor: z7.string().nullable()
|
|
8256
8271
|
}).strict();
|
|
8257
8272
|
KvGetInputSchema = z7.object({
|
|
8258
8273
|
space: SpaceSchema2,
|
|
@@ -8394,7 +8409,7 @@ var init_exploration = __esm({
|
|
|
8394
8409
|
id: "tinycloud.kv.list",
|
|
8395
8410
|
version: 1,
|
|
8396
8411
|
title: "List TinyCloud KV keys",
|
|
8397
|
-
description: "List keys at
|
|
8412
|
+
description: "List a bounded page of keys at the supplied prefix in one delegated TinyCloud space. Continue with nextCursor as cursor and the same space and prefix; cursors are opaque and scope-bound. nextCursor is null when unavailable. If truncated is true without a cursor, coverage is incomplete: narrow the prefix rather than guessing offsets.",
|
|
8398
8413
|
input: KvListInputSchema,
|
|
8399
8414
|
output: KvListOutputSchema,
|
|
8400
8415
|
effects: ["read"],
|
|
@@ -8409,7 +8424,7 @@ var init_exploration = __esm({
|
|
|
8409
8424
|
id: "tinycloud.kv.get",
|
|
8410
8425
|
version: 1,
|
|
8411
8426
|
title: "Get a TinyCloud KV value",
|
|
8412
|
-
description: "Read one exact key with a
|
|
8427
|
+
description: "Read one exact key with a one MiB acquired-body limit in bytes. Hosted MCP separately caps the serialized response envelope at 100,000 UTF-16 code units; a value below one MiB can still exceed that cap. Use tinycloud_read for bounded, byte-preserving delivery within the acquisition limit.",
|
|
8413
8428
|
input: KvGetInputSchema,
|
|
8414
8429
|
output: KvGetOutputSchema,
|
|
8415
8430
|
effects: ["read"],
|
|
@@ -8967,6 +8982,320 @@ var init_knowledge = __esm({
|
|
|
8967
8982
|
}
|
|
8968
8983
|
});
|
|
8969
8984
|
|
|
8985
|
+
// src/operations/read.ts
|
|
8986
|
+
import { isUtf8 } from "buffer";
|
|
8987
|
+
import { createHash } from "crypto";
|
|
8988
|
+
import { parseSpaceUri as parseSpaceUri2 } from "@tinycloud/node-sdk";
|
|
8989
|
+
import { z as z9 } from "zod";
|
|
8990
|
+
async function planRead(context, input) {
|
|
8991
|
+
return input.resource.kind === "kv" ? planKvGet(context, input.resource) : planSqlRead(context, input.resource);
|
|
8992
|
+
}
|
|
8993
|
+
async function executeRead2(context, input) {
|
|
8994
|
+
try {
|
|
8995
|
+
const runtime = runtimeContext2(context);
|
|
8996
|
+
const requirements = await planRead(runtime, input);
|
|
8997
|
+
const space = requirements[0]?.space;
|
|
8998
|
+
if (typeof space !== "string") throw new TypeError("Read target space is unavailable.");
|
|
8999
|
+
const ownerDid = parseSpaceUri2(space)?.owner;
|
|
9000
|
+
if (ownerDid === void 0) return invalidInput2("The read target must resolve to an owner-scoped space.");
|
|
9001
|
+
const resource = resourceIdentity(input.resource, space);
|
|
9002
|
+
const expected = input.expected;
|
|
9003
|
+
const offset = input.offset ?? 0;
|
|
9004
|
+
if (offset > 0 && expected === void 0) {
|
|
9005
|
+
return invalidInput2("A nonzero byte offset requires the previous page's expected binding.");
|
|
9006
|
+
}
|
|
9007
|
+
if (expected !== void 0 && (expected.host !== context.summary.host || expected.ownerDid !== ownerDid || jcsCanonicalize(expected.resource) !== jcsCanonicalize(resource))) {
|
|
9008
|
+
return {
|
|
9009
|
+
status: "error",
|
|
9010
|
+
error: operationError("READ_CONTEXT_MISMATCH", "The expected read binding identifies a different host, owner, space, or resource.")
|
|
9011
|
+
};
|
|
9012
|
+
}
|
|
9013
|
+
let bytes;
|
|
9014
|
+
let etag = null;
|
|
9015
|
+
if (input.resource.kind === "kv") {
|
|
9016
|
+
const result = await genericKv(runtime, space).get(input.resource.key, {
|
|
9017
|
+
binary: true,
|
|
9018
|
+
maxResponseBytes: MAX_KV_VALUE_BYTES
|
|
9019
|
+
});
|
|
9020
|
+
if (!result.ok) return kvFailure(result.error, "read the KV value");
|
|
9021
|
+
bytes = result.data.data;
|
|
9022
|
+
if (bytes.byteLength > MAX_KV_VALUE_BYTES) {
|
|
9023
|
+
return kvFailure({ code: "KV_RESPONSE_TOO_LARGE" }, "read the KV value");
|
|
9024
|
+
}
|
|
9025
|
+
etag = result.data.headers.etag ?? null;
|
|
9026
|
+
} else {
|
|
9027
|
+
const result = await executeSqlQuery(context, input.resource);
|
|
9028
|
+
if (result.status !== "ok") return result;
|
|
9029
|
+
bytes = Buffer.from(JSON.stringify(result.output), "utf8");
|
|
9030
|
+
}
|
|
9031
|
+
const acquiredAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
9032
|
+
const sha256 = createHash("sha256").update(bytes).digest("hex");
|
|
9033
|
+
if (expected !== void 0 && (expected.sha256 !== sha256 || expected.totalBytes !== bytes.byteLength)) {
|
|
9034
|
+
return {
|
|
9035
|
+
status: "error",
|
|
9036
|
+
error: operationError("READ_SOURCE_CHANGED", "The acquired bytes no longer match the expected digest and byte length. Start a new read explicitly to accept a new source revision.")
|
|
9037
|
+
};
|
|
9038
|
+
}
|
|
9039
|
+
if (offset > bytes.byteLength) return invalidInput2("The byte offset exceeds the acquired body length.");
|
|
9040
|
+
const validUtf8 = input.encoding === "base64" ? false : isUtf8(bytes);
|
|
9041
|
+
const encoding = input.encoding ?? (validUtf8 ? "utf8" : "base64");
|
|
9042
|
+
if (encoding === "utf8" && !validUtf8) {
|
|
9043
|
+
return invalidInput2("The acquired body is not valid UTF-8. Request base64 to preserve its original bytes.");
|
|
9044
|
+
}
|
|
9045
|
+
if (encoding === "utf8" && isContinuationByte(bytes[offset])) {
|
|
9046
|
+
return invalidInput2("The byte offset is inside a UTF-8 character.");
|
|
9047
|
+
}
|
|
9048
|
+
const pageBytes = input.pageBytes ?? MAX_PAGE_BYTES;
|
|
9049
|
+
const binding = {
|
|
9050
|
+
host: context.summary.host,
|
|
9051
|
+
ownerDid,
|
|
9052
|
+
resource,
|
|
9053
|
+
sha256,
|
|
9054
|
+
totalBytes: bytes.byteLength
|
|
9055
|
+
};
|
|
9056
|
+
const provenance = {
|
|
9057
|
+
digestAlgorithm: "sha256",
|
|
9058
|
+
representation: input.resource.kind === "kv" ? "original-bytes" : "normalized-sql-result-json",
|
|
9059
|
+
acquiredAt,
|
|
9060
|
+
etag
|
|
9061
|
+
};
|
|
9062
|
+
let end = Math.min(offset + pageBytes, bytes.byteLength);
|
|
9063
|
+
for (; ; ) {
|
|
9064
|
+
if (encoding === "utf8") {
|
|
9065
|
+
while (end > offset && isContinuationByte(bytes[end])) end--;
|
|
9066
|
+
}
|
|
9067
|
+
if (end === offset && offset < bytes.byteLength) {
|
|
9068
|
+
return invalidInput2("The requested UTF-8 character or resource provenance cannot fit the bounded page. Use a larger pageBytes (at least 4 for UTF-8), base64, or a shorter locator.");
|
|
9069
|
+
}
|
|
9070
|
+
const value = Buffer.from(bytes.buffer, bytes.byteOffset + offset, end - offset).toString(
|
|
9071
|
+
encoding === "utf8" ? "utf8" : "base64"
|
|
9072
|
+
);
|
|
9073
|
+
const complete = end === bytes.byteLength;
|
|
9074
|
+
const output = {
|
|
9075
|
+
value,
|
|
9076
|
+
encoding,
|
|
9077
|
+
range: { unit: "bytes", start: offset, end },
|
|
9078
|
+
binding,
|
|
9079
|
+
provenance,
|
|
9080
|
+
complete,
|
|
9081
|
+
continuation: complete ? null : { offset: end, pageBytes, encoding, expected: binding }
|
|
9082
|
+
};
|
|
9083
|
+
if (Buffer.byteLength(JSON.stringify(output), "utf8") < MAX_PAGE_OUTPUT_BYTES) {
|
|
9084
|
+
return { status: "ok", output };
|
|
9085
|
+
}
|
|
9086
|
+
if (end === offset) {
|
|
9087
|
+
return invalidInput2("The resource provenance cannot fit the bounded page; use a shorter locator.");
|
|
9088
|
+
}
|
|
9089
|
+
end = offset + Math.floor((end - offset) / 2);
|
|
9090
|
+
}
|
|
9091
|
+
} catch (error) {
|
|
9092
|
+
if (error instanceof OperationInvocationError) return { status: "error", error: error.operationError };
|
|
9093
|
+
return caughtKvFailure(error, "read the resource");
|
|
9094
|
+
}
|
|
9095
|
+
}
|
|
9096
|
+
function resourceIdentity(resource, space) {
|
|
9097
|
+
if (resource.kind === "kv") return { kind: "kv", space, key: resource.key };
|
|
9098
|
+
const query = { database: resource.database, sql: resource.sql };
|
|
9099
|
+
if (resource.params !== void 0) query.params = resource.params;
|
|
9100
|
+
if (resource.maxRows !== void 0) query.maxRows = resource.maxRows;
|
|
9101
|
+
if (resource.maxBytes !== void 0) query.maxBytes = resource.maxBytes;
|
|
9102
|
+
return {
|
|
9103
|
+
kind: "sql",
|
|
9104
|
+
space,
|
|
9105
|
+
database: resource.database,
|
|
9106
|
+
querySha256: createHash("sha256").update(jcsCanonicalize(query), "utf8").digest("hex")
|
|
9107
|
+
};
|
|
9108
|
+
}
|
|
9109
|
+
function isContinuationByte(byte) {
|
|
9110
|
+
return byte !== void 0 && (byte & 192) === 128;
|
|
9111
|
+
}
|
|
9112
|
+
function invalidInput2(message) {
|
|
9113
|
+
return { status: "error", error: operationError("INPUT_INVALID", message) };
|
|
9114
|
+
}
|
|
9115
|
+
var MAX_PAGE_BYTES, MAX_PAGE_OUTPUT_BYTES, Sha256Schema, ByteOffsetSchema, EncodingSchema, PageBytesSchema, ResourceSchema, ResourceIdentitySchema, ReadBindingSchema, ContinuationSchema, ReadInputSchema2, ReadOutputSchema2, readOperationDefinitions;
|
|
9116
|
+
var init_read = __esm({
|
|
9117
|
+
"src/operations/read.ts"() {
|
|
9118
|
+
"use strict";
|
|
9119
|
+
init_jcs();
|
|
9120
|
+
init_errors2();
|
|
9121
|
+
init_exploration();
|
|
9122
|
+
init_sql();
|
|
9123
|
+
MAX_PAGE_BYTES = 12 * 1024;
|
|
9124
|
+
MAX_PAGE_OUTPUT_BYTES = 8e4;
|
|
9125
|
+
Sha256Schema = z9.string().regex(/^[0-9a-f]{64}$/);
|
|
9126
|
+
ByteOffsetSchema = z9.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER);
|
|
9127
|
+
EncodingSchema = z9.enum(["utf8", "base64"]);
|
|
9128
|
+
PageBytesSchema = z9.number().int().min(1).max(MAX_PAGE_BYTES);
|
|
9129
|
+
ResourceSchema = z9.discriminatedUnion("kind", [
|
|
9130
|
+
KvGetInputSchema.omit({ representation: true }).extend({ kind: z9.literal("kv") }),
|
|
9131
|
+
SqlQueryInputSchema.extend({ kind: z9.literal("sql") })
|
|
9132
|
+
]);
|
|
9133
|
+
ResourceIdentitySchema = z9.discriminatedUnion("kind", [
|
|
9134
|
+
z9.object({
|
|
9135
|
+
kind: z9.literal("kv"),
|
|
9136
|
+
space: z9.string().min(1),
|
|
9137
|
+
key: z9.string().min(1)
|
|
9138
|
+
}).strict(),
|
|
9139
|
+
z9.object({
|
|
9140
|
+
kind: z9.literal("sql"),
|
|
9141
|
+
space: z9.string().min(1),
|
|
9142
|
+
database: z9.string().min(1),
|
|
9143
|
+
querySha256: Sha256Schema
|
|
9144
|
+
}).strict()
|
|
9145
|
+
]);
|
|
9146
|
+
ReadBindingSchema = z9.object({
|
|
9147
|
+
host: z9.string().min(1),
|
|
9148
|
+
ownerDid: z9.string().min(1),
|
|
9149
|
+
resource: ResourceIdentitySchema,
|
|
9150
|
+
sha256: Sha256Schema,
|
|
9151
|
+
totalBytes: ByteOffsetSchema
|
|
9152
|
+
}).strict();
|
|
9153
|
+
ContinuationSchema = z9.object({
|
|
9154
|
+
offset: ByteOffsetSchema,
|
|
9155
|
+
pageBytes: PageBytesSchema,
|
|
9156
|
+
encoding: EncodingSchema,
|
|
9157
|
+
expected: ReadBindingSchema
|
|
9158
|
+
}).strict();
|
|
9159
|
+
ReadInputSchema2 = z9.object({
|
|
9160
|
+
resource: ResourceSchema,
|
|
9161
|
+
offset: ByteOffsetSchema.optional(),
|
|
9162
|
+
pageBytes: PageBytesSchema.optional(),
|
|
9163
|
+
encoding: EncodingSchema.optional(),
|
|
9164
|
+
expected: ReadBindingSchema.optional()
|
|
9165
|
+
}).strict().superRefine((input, context) => {
|
|
9166
|
+
if ((input.offset ?? 0) > 0 && input.expected === void 0) {
|
|
9167
|
+
context.addIssue({
|
|
9168
|
+
code: z9.ZodIssueCode.custom,
|
|
9169
|
+
path: ["expected"],
|
|
9170
|
+
message: "A nonzero byte offset requires the previous page's expected binding."
|
|
9171
|
+
});
|
|
9172
|
+
}
|
|
9173
|
+
});
|
|
9174
|
+
ReadOutputSchema2 = z9.object({
|
|
9175
|
+
value: z9.string(),
|
|
9176
|
+
encoding: EncodingSchema,
|
|
9177
|
+
range: z9.object({
|
|
9178
|
+
unit: z9.literal("bytes"),
|
|
9179
|
+
start: ByteOffsetSchema,
|
|
9180
|
+
end: ByteOffsetSchema
|
|
9181
|
+
}).strict(),
|
|
9182
|
+
binding: ReadBindingSchema,
|
|
9183
|
+
provenance: z9.object({
|
|
9184
|
+
digestAlgorithm: z9.literal("sha256"),
|
|
9185
|
+
representation: z9.enum(["original-bytes", "normalized-sql-result-json"]),
|
|
9186
|
+
acquiredAt: z9.string().datetime(),
|
|
9187
|
+
etag: z9.string().nullable()
|
|
9188
|
+
}).strict(),
|
|
9189
|
+
complete: z9.boolean(),
|
|
9190
|
+
continuation: ContinuationSchema.nullable()
|
|
9191
|
+
}).strict();
|
|
9192
|
+
readOperationDefinitions = [{
|
|
9193
|
+
id: "tinycloud.read",
|
|
9194
|
+
version: 1,
|
|
9195
|
+
title: "Read complete TinyCloud resource bytes in bounded pages",
|
|
9196
|
+
description: "Read original KV bytes or normalized read-only SQL result JSON in digest-bound byte pages. Every call reacquires the resource with current authority. Replay the original resource with continuation fields; a recipient can validate the first page with expected: binding. SQL locators require retaining the original query and parameters. Paging does not increase acquisition limits.",
|
|
9197
|
+
input: ReadInputSchema2,
|
|
9198
|
+
output: ReadOutputSchema2,
|
|
9199
|
+
effects: ["read"],
|
|
9200
|
+
runtime: "authenticated",
|
|
9201
|
+
postures: ["owner-openkey", "delegate-session", "local-owner-key"],
|
|
9202
|
+
exposure: {
|
|
9203
|
+
cli: { status: "excluded", reason: "Existing CLI KV and SQL reads remain the CLI surface." },
|
|
9204
|
+
mcp: { status: "required" },
|
|
9205
|
+
skill: { status: "required" },
|
|
9206
|
+
docs: { status: "required" }
|
|
9207
|
+
},
|
|
9208
|
+
sensitivity: { input: ["/resource", "/expected"], output: ["/value", "/binding", "/continuation"] },
|
|
9209
|
+
authority: planRead,
|
|
9210
|
+
execute: executeRead2
|
|
9211
|
+
}];
|
|
9212
|
+
}
|
|
9213
|
+
});
|
|
9214
|
+
|
|
9215
|
+
// src/operations/read-scope.ts
|
|
9216
|
+
import { z as z10 } from "zod";
|
|
9217
|
+
function scopeSpace(context, input) {
|
|
9218
|
+
const space = resolveGenericKvSpace(context, input.space);
|
|
9219
|
+
const ownSpace = resolveGenericKvSpace(context, space.split(":").at(-1));
|
|
9220
|
+
if (space !== ownSpace) {
|
|
9221
|
+
throw new OperationInvocationError(operationError(
|
|
9222
|
+
"INPUT_INVALID",
|
|
9223
|
+
"Read-scope approval must target the selected owner's space."
|
|
9224
|
+
));
|
|
9225
|
+
}
|
|
9226
|
+
return space;
|
|
9227
|
+
}
|
|
9228
|
+
async function planReadScope(context, input) {
|
|
9229
|
+
const space = scopeSpace(context, input);
|
|
9230
|
+
const permissions = [];
|
|
9231
|
+
for (const path of input.kvPrefixes ?? []) {
|
|
9232
|
+
permissions.push({
|
|
9233
|
+
service: "tinycloud.kv",
|
|
9234
|
+
space,
|
|
9235
|
+
path,
|
|
9236
|
+
actions: ["tinycloud.kv/get", "tinycloud.kv/metadata", "tinycloud.kv/list"]
|
|
9237
|
+
});
|
|
9238
|
+
}
|
|
9239
|
+
for (const path of input.databases ?? []) {
|
|
9240
|
+
permissions.push({ service: "tinycloud.sql", space, path, actions: ["tinycloud.sql/read"] });
|
|
9241
|
+
}
|
|
9242
|
+
return canonicalizeCapabilities(permissions);
|
|
9243
|
+
}
|
|
9244
|
+
var InputSchema, OutputSchema, readScopeOperationDefinitions;
|
|
9245
|
+
var init_read_scope = __esm({
|
|
9246
|
+
"src/operations/read-scope.ts"() {
|
|
9247
|
+
"use strict";
|
|
9248
|
+
init_artifacts();
|
|
9249
|
+
init_authority();
|
|
9250
|
+
init_errors2();
|
|
9251
|
+
init_exploration();
|
|
9252
|
+
init_sql();
|
|
9253
|
+
InputSchema = z10.object({
|
|
9254
|
+
space: KvGetInputSchema.shape.space,
|
|
9255
|
+
kvPrefixes: z10.array(z10.string().max(2048).refine(
|
|
9256
|
+
(prefix) => (prefix === "" || prefix.endsWith("/")) && prefix !== "/" && !prefix.includes("*") && !/[\u0000-\u001f\u007f]/.test(prefix),
|
|
9257
|
+
"Select a recursive slash-ended KV prefix, or explicitly select the empty prefix for the whole space."
|
|
9258
|
+
)).min(1).max(20).optional(),
|
|
9259
|
+
databases: z10.array(SqlQueryInputSchema.shape.database).min(1).max(20).optional()
|
|
9260
|
+
}).strict().superRefine((input, issue) => {
|
|
9261
|
+
if (input.kvPrefixes === void 0 && input.databases === void 0) {
|
|
9262
|
+
issue.addIssue({ code: z10.ZodIssueCode.custom, message: "Select at least one KV prefix or exact database." });
|
|
9263
|
+
}
|
|
9264
|
+
});
|
|
9265
|
+
OutputSchema = z10.object({
|
|
9266
|
+
space: z10.string().min(1),
|
|
9267
|
+
permissions: z10.array(PermissionEntrySchema).min(1),
|
|
9268
|
+
access: z10.literal("not-tested")
|
|
9269
|
+
}).strict();
|
|
9270
|
+
readScopeOperationDefinitions = [{
|
|
9271
|
+
id: "tinycloud.auth.read_scope",
|
|
9272
|
+
version: 1,
|
|
9273
|
+
title: "Approve a reusable TinyCloud read scope",
|
|
9274
|
+
description: "Explicitly select recursive KV prefixes and/or exact read-only databases in one existing owner space. Missing authority uses the normal request-bound approval flow. Empty KV prefix explicitly requests the whole space. No write authority is requested; ordinary GET/HEAD requests stay exact. Future children are covered only until grant expiry/revocation. Success reports capability coverage, not a storage read; then use KV/SQL discovery or tinycloud_read.",
|
|
9275
|
+
input: InputSchema,
|
|
9276
|
+
output: OutputSchema,
|
|
9277
|
+
effects: ["read"],
|
|
9278
|
+
runtime: "authenticated",
|
|
9279
|
+
postures: ["owner-openkey", "delegate-session", "local-owner-key"],
|
|
9280
|
+
exposure: {
|
|
9281
|
+
cli: { status: "excluded", reason: "The CLI retains its explicit permission-manifest/request flow; SDK callers use invokeOperation." },
|
|
9282
|
+
mcp: { status: "required" },
|
|
9283
|
+
skill: { status: "required" },
|
|
9284
|
+
docs: { status: "required" }
|
|
9285
|
+
},
|
|
9286
|
+
sensitivity: { input: ["/kvPrefixes", "/databases"], output: ["/permissions"] },
|
|
9287
|
+
authority: planReadScope,
|
|
9288
|
+
execute: async (context, input) => {
|
|
9289
|
+
const runtime = runtimeContext2(context);
|
|
9290
|
+
return {
|
|
9291
|
+
status: "ok",
|
|
9292
|
+
output: { space: scopeSpace(runtime, input), permissions: await planReadScope(runtime, input), access: "not-tested" }
|
|
9293
|
+
};
|
|
9294
|
+
}
|
|
9295
|
+
}];
|
|
9296
|
+
}
|
|
9297
|
+
});
|
|
9298
|
+
|
|
8970
9299
|
// src/secret-request.ts
|
|
8971
9300
|
import * as nodeSdk3 from "@tinycloud/node-sdk";
|
|
8972
9301
|
function canonicalSecretRequestOwner(did) {
|
|
@@ -9154,7 +9483,7 @@ var init_secret_request = __esm({
|
|
|
9154
9483
|
});
|
|
9155
9484
|
|
|
9156
9485
|
// src/operations/secrets-get.ts
|
|
9157
|
-
import { z as
|
|
9486
|
+
import { z as z11 } from "zod";
|
|
9158
9487
|
async function planSecretGet(context, input) {
|
|
9159
9488
|
const reference = resolveSecretReferenceForOperation(
|
|
9160
9489
|
input,
|
|
@@ -9342,19 +9671,19 @@ var init_secrets_get = __esm({
|
|
|
9342
9671
|
init_errors2();
|
|
9343
9672
|
init_secret_request();
|
|
9344
9673
|
init_secrets();
|
|
9345
|
-
SecretsGetInputSchema =
|
|
9346
|
-
name:
|
|
9347
|
-
scope:
|
|
9348
|
-
space:
|
|
9674
|
+
SecretsGetInputSchema = z11.object({
|
|
9675
|
+
name: z11.string(),
|
|
9676
|
+
scope: z11.string().optional(),
|
|
9677
|
+
space: z11.string().optional()
|
|
9349
9678
|
}).strict().superRefine((input, context) => {
|
|
9350
9679
|
try {
|
|
9351
9680
|
resolveSecretReference(input);
|
|
9352
9681
|
} catch {
|
|
9353
|
-
context.addIssue({ code:
|
|
9682
|
+
context.addIssue({ code: z11.ZodIssueCode.custom, message: "Invalid secret reference." });
|
|
9354
9683
|
}
|
|
9355
9684
|
}).transform(normalizeSecretsGetInput);
|
|
9356
|
-
SecretsGetOutputSchema =
|
|
9357
|
-
value:
|
|
9685
|
+
SecretsGetOutputSchema = z11.object({
|
|
9686
|
+
value: z11.string()
|
|
9358
9687
|
}).strict();
|
|
9359
9688
|
SECRETS_GET_POSTURES = [
|
|
9360
9689
|
"owner-openkey",
|
|
@@ -9393,7 +9722,7 @@ var init_secrets_get = __esm({
|
|
|
9393
9722
|
});
|
|
9394
9723
|
|
|
9395
9724
|
// src/operations/secrets-status.ts
|
|
9396
|
-
import { z as
|
|
9725
|
+
import { z as z12 } from "zod";
|
|
9397
9726
|
import * as nodeSdk4 from "@tinycloud/node-sdk";
|
|
9398
9727
|
async function executeSecretsStatus(context, input) {
|
|
9399
9728
|
const runtime = context.runtime;
|
|
@@ -9492,27 +9821,27 @@ var init_secrets_status = __esm({
|
|
|
9492
9821
|
init_secrets();
|
|
9493
9822
|
PROBE_TIMEOUT_MS = 15e3;
|
|
9494
9823
|
SECRETS_STATUS_DEADLINE_MS = 18e3;
|
|
9495
|
-
SecretsStatusInputSchema =
|
|
9496
|
-
names:
|
|
9497
|
-
scope:
|
|
9498
|
-
owner:
|
|
9824
|
+
SecretsStatusInputSchema = z12.object({
|
|
9825
|
+
names: z12.array(z12.string()),
|
|
9826
|
+
scope: z12.string().optional(),
|
|
9827
|
+
owner: z12.string().optional()
|
|
9499
9828
|
}).strict().superRefine((input, context) => {
|
|
9500
9829
|
try {
|
|
9501
9830
|
validSecretNames(input.names);
|
|
9502
9831
|
} catch {
|
|
9503
|
-
context.addIssue({ code:
|
|
9832
|
+
context.addIssue({ code: z12.ZodIssueCode.custom, path: ["names"], message: "Invalid secret names." });
|
|
9504
9833
|
}
|
|
9505
9834
|
try {
|
|
9506
9835
|
const scope = canonicalizeSecretScope(input.scope);
|
|
9507
9836
|
if (scope !== void 0 && !isValidSecretRequestScope(scope)) throw new Error("invalid scope");
|
|
9508
9837
|
} catch {
|
|
9509
|
-
context.addIssue({ code:
|
|
9838
|
+
context.addIssue({ code: z12.ZodIssueCode.custom, path: ["scope"], message: "Invalid secret scope." });
|
|
9510
9839
|
}
|
|
9511
9840
|
if (input.owner !== void 0) {
|
|
9512
9841
|
try {
|
|
9513
9842
|
canonicalSecretRequestOwner(input.owner);
|
|
9514
9843
|
} catch {
|
|
9515
|
-
context.addIssue({ code:
|
|
9844
|
+
context.addIssue({ code: z12.ZodIssueCode.custom, path: ["owner"], message: "Invalid owner." });
|
|
9516
9845
|
}
|
|
9517
9846
|
}
|
|
9518
9847
|
}).transform((input) => {
|
|
@@ -9523,23 +9852,23 @@ var init_secrets_status = __esm({
|
|
|
9523
9852
|
...input.owner === void 0 ? {} : { owner: canonicalSecretRequestOwner(input.owner) }
|
|
9524
9853
|
};
|
|
9525
9854
|
});
|
|
9526
|
-
SecretSetupSchema =
|
|
9527
|
-
url:
|
|
9528
|
-
names:
|
|
9529
|
-
scope:
|
|
9530
|
-
owner:
|
|
9531
|
-
action:
|
|
9855
|
+
SecretSetupSchema = z12.object({
|
|
9856
|
+
url: z12.string().url(),
|
|
9857
|
+
names: z12.array(z12.string()).min(1),
|
|
9858
|
+
scope: z12.string().optional(),
|
|
9859
|
+
owner: z12.string(),
|
|
9860
|
+
action: z12.literal("add_secret")
|
|
9532
9861
|
}).strict();
|
|
9533
|
-
SecretsStatusOutputSchema =
|
|
9534
|
-
status:
|
|
9535
|
-
owner:
|
|
9536
|
-
names:
|
|
9537
|
-
scope:
|
|
9538
|
-
present:
|
|
9539
|
-
pending:
|
|
9540
|
-
denied:
|
|
9862
|
+
SecretsStatusOutputSchema = z12.object({
|
|
9863
|
+
status: z12.enum(["ready", "pending", "consent_required"]),
|
|
9864
|
+
owner: z12.string(),
|
|
9865
|
+
names: z12.array(z12.string()).min(1),
|
|
9866
|
+
scope: z12.string().optional(),
|
|
9867
|
+
present: z12.array(z12.string()),
|
|
9868
|
+
pending: z12.array(z12.string()),
|
|
9869
|
+
denied: z12.array(z12.string()),
|
|
9541
9870
|
setup: SecretSetupSchema.optional(),
|
|
9542
|
-
hint:
|
|
9871
|
+
hint: z12.string().optional()
|
|
9543
9872
|
}).strict();
|
|
9544
9873
|
SECRETS_STATUS_POSTURES = [
|
|
9545
9874
|
"owner-openkey",
|
|
@@ -9867,7 +10196,7 @@ var init_delegation_binding = __esm({
|
|
|
9867
10196
|
});
|
|
9868
10197
|
|
|
9869
10198
|
// src/operations/status.ts
|
|
9870
|
-
import { z as
|
|
10199
|
+
import { z as z13 } from "zod";
|
|
9871
10200
|
function createStatusDefinition(params) {
|
|
9872
10201
|
return {
|
|
9873
10202
|
id: params.id,
|
|
@@ -9992,27 +10321,27 @@ var init_status = __esm({
|
|
|
9992
10321
|
init_delegation_binding();
|
|
9993
10322
|
init_errors2();
|
|
9994
10323
|
init_state();
|
|
9995
|
-
StatusInputSchema =
|
|
9996
|
-
StatusOutputSchema =
|
|
9997
|
-
profile:
|
|
9998
|
-
host:
|
|
9999
|
-
posture:
|
|
10324
|
+
StatusInputSchema = z13.object({}).strict();
|
|
10325
|
+
StatusOutputSchema = z13.object({
|
|
10326
|
+
profile: z13.string().min(1),
|
|
10327
|
+
host: z13.string().min(1),
|
|
10328
|
+
posture: z13.enum([
|
|
10000
10329
|
"owner-openkey",
|
|
10001
10330
|
"delegate-session",
|
|
10002
10331
|
"local-owner-key",
|
|
10003
10332
|
"unauthenticated"
|
|
10004
10333
|
]),
|
|
10005
|
-
operatorType:
|
|
10006
|
-
principalDid:
|
|
10007
|
-
sessionDid:
|
|
10008
|
-
ownerDid:
|
|
10009
|
-
space:
|
|
10010
|
-
session:
|
|
10011
|
-
present:
|
|
10012
|
-
expired:
|
|
10013
|
-
expiresAt:
|
|
10334
|
+
operatorType: z13.enum(["human", "agent"]).optional(),
|
|
10335
|
+
principalDid: z13.string().min(1).optional(),
|
|
10336
|
+
sessionDid: z13.string().min(1).optional(),
|
|
10337
|
+
ownerDid: z13.string().min(1).optional(),
|
|
10338
|
+
space: z13.string().min(1).optional(),
|
|
10339
|
+
session: z13.object({
|
|
10340
|
+
present: z13.boolean(),
|
|
10341
|
+
expired: z13.boolean().nullable(),
|
|
10342
|
+
expiresAt: z13.string().datetime({ offset: true }).nullable()
|
|
10014
10343
|
}).strict(),
|
|
10015
|
-
liveAdditionalDelegationCount:
|
|
10344
|
+
liveAdditionalDelegationCount: z13.number().int().nonnegative().describe(
|
|
10016
10345
|
"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."
|
|
10017
10346
|
)
|
|
10018
10347
|
}).strict();
|
|
@@ -10054,6 +10383,8 @@ function registeredOperationDefinitions() {
|
|
|
10054
10383
|
operationDefinitions ?? (operationDefinitions = [
|
|
10055
10384
|
...statusOperationDefinitions,
|
|
10056
10385
|
...authOperationDefinitions,
|
|
10386
|
+
...readScopeOperationDefinitions,
|
|
10387
|
+
...readOperationDefinitions,
|
|
10057
10388
|
...explorationOperationDefinitions,
|
|
10058
10389
|
...appsOperationDefinitions,
|
|
10059
10390
|
...sqlOperationDefinitions,
|
|
@@ -10092,6 +10423,8 @@ var init_registry = __esm({
|
|
|
10092
10423
|
init_auth();
|
|
10093
10424
|
init_exploration();
|
|
10094
10425
|
init_knowledge();
|
|
10426
|
+
init_read();
|
|
10427
|
+
init_read_scope();
|
|
10095
10428
|
init_secrets_get();
|
|
10096
10429
|
init_secrets_status();
|
|
10097
10430
|
init_sql();
|
|
@@ -10534,12 +10867,12 @@ init_jcs();
|
|
|
10534
10867
|
init_errors2();
|
|
10535
10868
|
init_authority();
|
|
10536
10869
|
init_artifacts();
|
|
10537
|
-
import { createHash } from "crypto";
|
|
10870
|
+
import { createHash as createHash2 } from "crypto";
|
|
10538
10871
|
import { isAbsolute as isAbsolute2 } from "path";
|
|
10539
10872
|
import {
|
|
10540
10873
|
makePkhSpaceId as makePkhSpaceId4,
|
|
10541
10874
|
parsePkhDid as parsePkhDid4,
|
|
10542
|
-
parseSpaceUri as
|
|
10875
|
+
parseSpaceUri as parseSpaceUri3
|
|
10543
10876
|
} from "@tinycloud/node-sdk";
|
|
10544
10877
|
|
|
10545
10878
|
// src/redaction.ts
|
|
@@ -11261,7 +11594,7 @@ function operationRetryDescriptor(operation, input, requiresCallerInput = false)
|
|
|
11261
11594
|
return {
|
|
11262
11595
|
operationId: operation.operationId,
|
|
11263
11596
|
operationVersion: operation.operationVersion,
|
|
11264
|
-
inputDigest:
|
|
11597
|
+
inputDigest: createHash2("sha256").update(jcsCanonicalize(input), "utf8").digest("hex"),
|
|
11265
11598
|
requiresCallerInput
|
|
11266
11599
|
};
|
|
11267
11600
|
}
|
|
@@ -11361,11 +11694,11 @@ function requirementsBelongToAuthenticatedOwner(requirements, authenticatedSpace
|
|
|
11361
11694
|
}
|
|
11362
11695
|
function canonicalPkhOwner(space) {
|
|
11363
11696
|
if (typeof space !== "string") return void 0;
|
|
11364
|
-
const parsedSpace =
|
|
11697
|
+
const parsedSpace = parseSpaceUri3(space);
|
|
11365
11698
|
if (parsedSpace === null) return void 0;
|
|
11366
11699
|
try {
|
|
11367
11700
|
const pkh = parsePkhDid4(parsedSpace.owner);
|
|
11368
|
-
return pkh === null ? void 0 :
|
|
11701
|
+
return pkh === null ? void 0 : parseSpaceUri3(makePkhSpaceId4(pkh.address, pkh.chainId, parsedSpace.name))?.owner;
|
|
11369
11702
|
} catch {
|
|
11370
11703
|
return void 0;
|
|
11371
11704
|
}
|