@tinycloud/operations 0.1.0 → 0.2.0-beta.0

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.
@@ -88,6 +88,14 @@ var init_errors = __esm({
88
88
  "ENCRYPTION_NETWORK_UNRESOLVED",
89
89
  "NODE_UNREACHABLE",
90
90
  "NODE_ERROR",
91
+ "KV_NOT_FOUND",
92
+ "KV_PRECONDITION_FAILED",
93
+ "KV_CONFLICT",
94
+ "KV_RESPONSE_TOO_LARGE",
95
+ "SQL_QUERY_INVALID",
96
+ "SQL_EXECUTION_FAILED",
97
+ "SQL_RESULT_LIMIT_EXCEEDED",
98
+ "SQL_VALUE_UNSAFE",
91
99
  "SECRET_READ_FAILED",
92
100
  "SECRET_DECRYPT_FAILED",
93
101
  "OUTPUT_INVALID",
@@ -1135,6 +1143,11 @@ function validateMigrationOptions(options) {
1135
1143
  }
1136
1144
  return null;
1137
1145
  }
1146
+ function serializeSqlValues(values) {
1147
+ return values.map(
1148
+ (value) => value instanceof Uint8Array ? Array.from(value) : value
1149
+ );
1150
+ }
1138
1151
  function migrationKey(namespace, id) {
1139
1152
  return `${encodeURIComponent(namespace)}:${encodeURIComponent(id)}`;
1140
1153
  }
@@ -2408,6 +2421,9 @@ var init_dist2 = __esm({
2408
2421
  // KV-specific errors
2409
2422
  KV_NOT_FOUND: "KV_NOT_FOUND",
2410
2423
  KV_WRITE_FAILED: "KV_WRITE_FAILED",
2424
+ KV_PRECONDITION_FAILED: "KV_PRECONDITION_FAILED",
2425
+ KV_CONFLICT: "KV_CONFLICT",
2426
+ KV_RESPONSE_TOO_LARGE: "KV_RESPONSE_TOO_LARGE",
2411
2427
  // SQL-specific errors
2412
2428
  SQL_ERROR: "SQL_ERROR",
2413
2429
  SQL_PERMISSION_DENIED: "SQL_PERMISSION_DENIED",
@@ -3085,7 +3101,7 @@ var init_dist2 = __esm({
3085
3101
  * @param signal - Optional abort signal
3086
3102
  * @returns Fetch response
3087
3103
  */
3088
- async invokeOperation(path, action, body, signal) {
3104
+ async invokeOperation(path, action, body, signal, extraHeaders) {
3089
3105
  const session = this.context.session;
3090
3106
  const headers = this.context.invoke(
3091
3107
  session,
@@ -3093,9 +3109,10 @@ var init_dist2 = __esm({
3093
3109
  path,
3094
3110
  action
3095
3111
  );
3112
+ const requestHeaders = Array.isArray(headers) ? [...headers, ...Object.entries(extraHeaders ?? {})] : { ...headers, ...extraHeaders };
3096
3113
  return this.context.fetch(`${this.host}/invoke`, {
3097
3114
  method: "POST",
3098
- headers,
3115
+ headers: requestHeaders,
3099
3116
  body,
3100
3117
  signal: this.combineSignals(signal)
3101
3118
  });
@@ -3277,13 +3294,21 @@ var init_dist2 = __esm({
3277
3294
  if (!this.requireAuth()) {
3278
3295
  return err(authRequiredError("kv"));
3279
3296
  }
3297
+ if (options?.maxResponseBytes !== void 0 && (!Number.isSafeInteger(options.maxResponseBytes) || options.maxResponseBytes <= 0)) {
3298
+ return err(serviceError(
3299
+ ErrorCodes.INVALID_INPUT,
3300
+ "KV maxResponseBytes must be a positive safe integer",
3301
+ "kv"
3302
+ ));
3303
+ }
3280
3304
  const path = this.getFullPath(key, options?.prefix);
3281
3305
  try {
3282
3306
  const response = await this.invokeOperation(
3283
3307
  path,
3284
3308
  KVAction.GET,
3285
3309
  void 0,
3286
- options?.signal
3310
+ options?.signal,
3311
+ options?.maxResponseBytes === void 0 ? void 0 : { "x-tinycloud-max-response-bytes": String(options.maxResponseBytes) }
3287
3312
  );
3288
3313
  if (!response.ok) {
3289
3314
  if (response.status === 401 || response.status === 403) {
@@ -3301,6 +3326,14 @@ var init_dist2 = __esm({
3301
3326
  return this.classifyNotFound(response, key);
3302
3327
  }
3303
3328
  const errorText = await response.text();
3329
+ if (response.status === 413) {
3330
+ return err(serviceError(
3331
+ ErrorCodes.KV_RESPONSE_TOO_LARGE,
3332
+ `KV value at key "${key}" exceeds the requested response limit`,
3333
+ "kv",
3334
+ { meta: { status: response.status, statusText: response.statusText } }
3335
+ ));
3336
+ }
3304
3337
  return err(
3305
3338
  serviceError(
3306
3339
  ErrorCodes.NETWORK_ERROR,
@@ -3332,6 +3365,13 @@ var init_dist2 = __esm({
3332
3365
  if (!this.requireAuth()) {
3333
3366
  return err(authRequiredError("kv"));
3334
3367
  }
3368
+ if (options?.ifMatch !== void 0 && options.ifNoneMatch !== void 0) {
3369
+ return err(serviceError(
3370
+ ErrorCodes.INVALID_INPUT,
3371
+ "KV put cannot combine ifMatch and ifNoneMatch",
3372
+ "kv"
3373
+ ));
3374
+ }
3335
3375
  const path = this.getFullPath(key, options?.prefix);
3336
3376
  const body = this.serializePutValue(value, options?.contentType);
3337
3377
  try {
@@ -3339,7 +3379,11 @@ var init_dist2 = __esm({
3339
3379
  path,
3340
3380
  KVAction.PUT,
3341
3381
  body,
3342
- options?.signal
3382
+ options?.signal,
3383
+ {
3384
+ ...options?.ifMatch === void 0 ? {} : { "if-match": options.ifMatch },
3385
+ ...options?.ifNoneMatch === void 0 ? {} : { "if-none-match": options.ifNoneMatch }
3386
+ }
3343
3387
  );
3344
3388
  if (!response.ok) {
3345
3389
  if (response.status === 401) {
@@ -3352,6 +3396,22 @@ var init_dist2 = __esm({
3352
3396
  }));
3353
3397
  }
3354
3398
  const errorText = await response.text();
3399
+ if (response.status === 412) {
3400
+ return err(serviceError(
3401
+ ErrorCodes.KV_PRECONDITION_FAILED,
3402
+ `KV precondition failed for key "${key}"`,
3403
+ "kv",
3404
+ { meta: { status: response.status, statusText: response.statusText } }
3405
+ ));
3406
+ }
3407
+ if (response.status === 503 && (options?.ifMatch !== void 0 || options?.ifNoneMatch !== void 0)) {
3408
+ return err(serviceError(
3409
+ ErrorCodes.KV_CONFLICT,
3410
+ `Concurrent KV update conflicted for key "${key}"`,
3411
+ "kv",
3412
+ { meta: { status: response.status, statusText: response.statusText } }
3413
+ ));
3414
+ }
3355
3415
  const quotaError = this.handleQuotaErrorResponse(
3356
3416
  response,
3357
3417
  errorText,
@@ -3487,6 +3547,13 @@ var init_dist2 = __esm({
3487
3547
  if (!this.requireAuth()) {
3488
3548
  return err(authRequiredError("kv"));
3489
3549
  }
3550
+ if (options?.limit !== void 0 && (!Number.isInteger(options.limit) || options.limit < 1 || options.limit > 1e3)) {
3551
+ return err(serviceError(
3552
+ ErrorCodes.INVALID_INPUT,
3553
+ "KV list limit must be an integer from 1 through 1000",
3554
+ "kv"
3555
+ ));
3556
+ }
3490
3557
  let listPath = options?.prefix ?? this._config.prefix ?? "";
3491
3558
  if (options?.path) {
3492
3559
  listPath = listPath ? `${listPath}/${options.path}` : options.path;
@@ -3496,7 +3563,8 @@ var init_dist2 = __esm({
3496
3563
  listPath,
3497
3564
  KVAction.LIST,
3498
3565
  void 0,
3499
- options?.signal
3566
+ options?.signal,
3567
+ options?.limit === void 0 ? void 0 : { "x-tinycloud-limit": String(options.limit) }
3500
3568
  );
3501
3569
  if (!response.ok) {
3502
3570
  if (response.status === 401) {
@@ -3526,7 +3594,10 @@ var init_dist2 = __esm({
3526
3594
  (key) => key.startsWith(prefixWithSlash) ? key.slice(prefixWithSlash.length) : key
3527
3595
  );
3528
3596
  }
3529
- return ok({ keys });
3597
+ return ok({
3598
+ keys,
3599
+ ...response.headers.get("x-tinycloud-truncated") === null ? {} : { truncated: response.headers.get("x-tinycloud-truncated") === "true" }
3600
+ });
3530
3601
  } catch (error) {
3531
3602
  return err(wrapError("kv", error));
3532
3603
  }
@@ -3546,7 +3617,8 @@ var init_dist2 = __esm({
3546
3617
  path,
3547
3618
  KVAction.DELETE,
3548
3619
  void 0,
3549
- options?.signal
3620
+ options?.signal,
3621
+ options?.ifMatch === void 0 ? void 0 : { "if-match": options.ifMatch }
3550
3622
  );
3551
3623
  if (!response.ok) {
3552
3624
  if (response.status === 401) {
@@ -3562,6 +3634,22 @@ var init_dist2 = __esm({
3562
3634
  return this.classifyNotFound(response, key);
3563
3635
  }
3564
3636
  const errorText = await response.text();
3637
+ if (response.status === 412) {
3638
+ return err(serviceError(
3639
+ ErrorCodes.KV_PRECONDITION_FAILED,
3640
+ `KV precondition failed for key "${key}"`,
3641
+ "kv",
3642
+ { meta: { status: response.status, statusText: response.statusText } }
3643
+ ));
3644
+ }
3645
+ if (response.status === 503 && options?.ifMatch !== void 0) {
3646
+ return err(serviceError(
3647
+ ErrorCodes.KV_CONFLICT,
3648
+ `Concurrent KV delete conflicted for key "${key}"`,
3649
+ "kv",
3650
+ { meta: { status: response.status, statusText: response.statusText } }
3651
+ ));
3652
+ }
3565
3653
  return err(
3566
3654
  serviceError(
3567
3655
  ErrorCodes.NETWORK_ERROR,
@@ -3571,7 +3659,10 @@ var init_dist2 = __esm({
3571
3659
  )
3572
3660
  );
3573
3661
  }
3574
- return ok(void 0);
3662
+ return ok({
3663
+ data: void 0,
3664
+ headers: this.createResponseHeaders(response.headers)
3665
+ });
3575
3666
  } catch (error) {
3576
3667
  return err(wrapError("kv", error));
3577
3668
  }
@@ -3843,10 +3934,17 @@ var init_dist2 = __esm({
3843
3934
  return err(authRequiredError("sql"));
3844
3935
  }
3845
3936
  try {
3937
+ const body = {
3938
+ action: "query",
3939
+ sql,
3940
+ params: serializeSqlValues(params ?? [])
3941
+ };
3942
+ if (options?.maxRows !== void 0) body.maxRows = options.maxRows;
3943
+ if (options?.maxBytes !== void 0) body.maxBytes = options.maxBytes;
3846
3944
  const response = await this.invokeSQL(
3847
3945
  dbName,
3848
3946
  this.actionForSql(sql, SQLAction.READ),
3849
- { action: "query", sql, params: params ?? [] },
3947
+ body,
3850
3948
  options?.signal
3851
3949
  );
3852
3950
  if (!response.ok) {
@@ -3868,7 +3966,7 @@ var init_dist2 = __esm({
3868
3966
  const body = {
3869
3967
  action: "execute",
3870
3968
  sql,
3871
- params: params ?? []
3969
+ params: serializeSqlValues(params ?? [])
3872
3970
  };
3873
3971
  if (options?.schema) {
3874
3972
  body.schema = options.schema;
@@ -7820,7 +7918,7 @@ async function planAccountRegistryRead(context, path) {
7820
7918
  }];
7821
7919
  }
7822
7920
  async function planKvList(context, input) {
7823
- const space = resolveNonSecretSpace(context, input.space);
7921
+ const space = resolveGenericKvSpace(context, input.space);
7824
7922
  return [{
7825
7923
  service: "tinycloud.kv",
7826
7924
  space,
@@ -7829,7 +7927,7 @@ async function planKvList(context, input) {
7829
7927
  }];
7830
7928
  }
7831
7929
  async function planKvGet(context, input) {
7832
- const space = resolveNonSecretSpace(context, input.space);
7930
+ const space = resolveGenericKvSpace(context, input.space);
7833
7931
  return [{
7834
7932
  service: "tinycloud.kv",
7835
7933
  space,
@@ -7837,12 +7935,21 @@ async function planKvGet(context, input) {
7837
7935
  actions: ["tinycloud.kv/get"]
7838
7936
  }];
7839
7937
  }
7938
+ async function planExactKv(context, requestedSpace, key, action) {
7939
+ return [{
7940
+ service: "tinycloud.kv",
7941
+ space: resolveGenericKvSpace(context, requestedSpace),
7942
+ path: key,
7943
+ actions: [action]
7944
+ }];
7945
+ }
7840
7946
  async function executeAccountSpacesList(context, _input) {
7841
7947
  try {
7842
7948
  const entries = await readAccountRegistry(context, "spaces/");
7843
- if (!entries.ok) return nodeFailure("list account spaces");
7949
+ if (!entries.ok) return entries.outcome;
7844
7950
  const spaces = entries.records.map(({ key, value }) => projectAccountSpace(key, value)).sort((left, right) => left.name.localeCompare(right.name) || left.spaceId.localeCompare(right.spaceId));
7845
- return { status: "ok", output: { spaces, count: spaces.length } };
7951
+ const output = { spaces, count: spaces.length };
7952
+ return accountRegistryOutput(output);
7846
7953
  } catch {
7847
7954
  return nodeFailure("list account spaces");
7848
7955
  }
@@ -7850,9 +7957,10 @@ async function executeAccountSpacesList(context, _input) {
7850
7957
  async function executeAccountApplicationsList(context, _input) {
7851
7958
  try {
7852
7959
  const entries = await readAccountRegistry(context, "applications/");
7853
- if (!entries.ok) return nodeFailure("list account applications");
7960
+ if (!entries.ok) return entries.outcome;
7854
7961
  const applications = entries.records.map(({ key, value }) => projectAccountApplication(key, value)).sort((left, right) => left.appId.localeCompare(right.appId));
7855
- return { status: "ok", output: { applications, count: applications.length } };
7962
+ const output = { applications, count: applications.length };
7963
+ return accountRegistryOutput(output);
7856
7964
  } catch {
7857
7965
  return nodeFailure("list account applications");
7858
7966
  }
@@ -7860,15 +7968,22 @@ async function executeAccountApplicationsList(context, _input) {
7860
7968
  async function executeKvList(context, input) {
7861
7969
  try {
7862
7970
  const runtime = runtimeContext(context);
7863
- const space = resolveNonSecretSpace(runtime, input.space);
7864
- const result = await runtimeNode(runtime).kvForSpace(space).list(
7865
- input.prefix === void 0 ? void 0 : { prefix: input.prefix }
7866
- );
7971
+ const space = resolveGenericKvSpace(runtime, input.space);
7972
+ const result = await genericKv(runtime, space).list({
7973
+ ...input.prefix === void 0 ? {} : { prefix: input.prefix },
7974
+ limit: input.limit ?? DEFAULT_KV_LIST_LIMIT
7975
+ });
7867
7976
  if (!result.ok) return nodeFailure("list KV keys");
7868
7977
  const keys = [...result.data.keys];
7869
7978
  return {
7870
7979
  status: "ok",
7871
- output: { space, prefix: input.prefix ?? "", keys, count: keys.length }
7980
+ output: {
7981
+ space,
7982
+ prefix: input.prefix ?? "",
7983
+ keys,
7984
+ count: keys.length,
7985
+ truncated: result.data.truncated ?? false
7986
+ }
7872
7987
  };
7873
7988
  } catch (error) {
7874
7989
  if (error instanceof OperationInvocationError) {
@@ -7880,10 +7995,18 @@ async function executeKvList(context, input) {
7880
7995
  async function executeKvGet(context, input) {
7881
7996
  try {
7882
7997
  const runtime = runtimeContext(context);
7883
- const space = resolveNonSecretSpace(runtime, input.space);
7884
- const result = await runtimeNode(runtime).kvForSpace(space).get(input.key);
7885
- if (!result.ok) return nodeFailure("read the KV value");
7886
- const encoded = encodeKvValue(result.data.data);
7998
+ const space = resolveGenericKvSpace(runtime, input.space);
7999
+ const result = await genericKv(runtime, space).get(input.key, {
8000
+ binary: true,
8001
+ maxResponseBytes: MAX_KV_VALUE_BYTES
8002
+ });
8003
+ if (!result.ok) return kvFailure(result.error, "read the KV value");
8004
+ const bytes = result.data.data;
8005
+ if (bytes.byteLength > MAX_KV_VALUE_BYTES) {
8006
+ return kvFailure({ code: "KV_RESPONSE_TOO_LARGE" }, "read the KV value");
8007
+ }
8008
+ const encoded = encodeKvValue(bytes, input.representation ?? "base64");
8009
+ if (!encoded.ok) return encoded.outcome;
7887
8010
  return {
7888
8011
  status: "ok",
7889
8012
  output: {
@@ -7891,12 +8014,8 @@ async function executeKvGet(context, input) {
7891
8014
  key: input.key,
7892
8015
  value: encoded.value,
7893
8016
  encoding: encoded.encoding,
7894
- metadata: {
7895
- ...result.data.headers.etag === void 0 ? {} : { etag: result.data.headers.etag },
7896
- ...result.data.headers.contentType === void 0 ? {} : { contentType: result.data.headers.contentType },
7897
- ...result.data.headers.lastModified === void 0 ? {} : { lastModified: result.data.headers.lastModified },
7898
- ...result.data.headers.contentLength === void 0 ? {} : { contentLength: result.data.headers.contentLength }
7899
- }
8017
+ metadata: projectKvMetadata(result.data.headers),
8018
+ byteLength: bytes.byteLength
7900
8019
  }
7901
8020
  };
7902
8021
  } catch (error) {
@@ -7906,6 +8025,66 @@ async function executeKvGet(context, input) {
7906
8025
  return nodeFailure("read the KV value");
7907
8026
  }
7908
8027
  }
8028
+ async function executeKvHead(context, input) {
8029
+ try {
8030
+ const runtime = runtimeContext(context);
8031
+ const space = resolveGenericKvSpace(runtime, input.space);
8032
+ const result = await genericKv(runtime, space).head(input.key);
8033
+ if (!result.ok) return kvFailure(result.error, "read KV metadata");
8034
+ return { status: "ok", output: { space, key: input.key, metadata: projectKvMetadata(result.data.headers) } };
8035
+ } catch (error) {
8036
+ return caughtKvFailure(error, "read KV metadata");
8037
+ }
8038
+ }
8039
+ async function executeKvPut(context, input) {
8040
+ try {
8041
+ const runtime = runtimeContext(context);
8042
+ const space = resolveGenericKvSpace(runtime, input.space);
8043
+ const decoded = decodeKvPutContent(input.content);
8044
+ if (decoded === void 0 || decoded.byteLength > MAX_KV_VALUE_BYTES) {
8045
+ return { status: "error", error: operationError("INPUT_INVALID", "The KV content is invalid or too large.") };
8046
+ }
8047
+ const result = await genericKv(runtime, space).put(input.key, decoded.bytes, {
8048
+ contentType: input.contentType ?? decoded.contentType,
8049
+ ...input.mode === "create" ? { ifNoneMatch: "*" } : {},
8050
+ ...input.mode === "replace" ? { ifMatch: input.etag } : {}
8051
+ });
8052
+ if (!result.ok) return kvFailure(result.error, "write the KV value");
8053
+ return {
8054
+ status: "ok",
8055
+ output: {
8056
+ space,
8057
+ key: input.key,
8058
+ mode: input.mode,
8059
+ byteLength: decoded.byteLength,
8060
+ metadata: projectKvMetadata(result.data.headers)
8061
+ }
8062
+ };
8063
+ } catch (error) {
8064
+ return caughtKvFailure(error, "write the KV value");
8065
+ }
8066
+ }
8067
+ async function executeKvDelete(context, input) {
8068
+ try {
8069
+ const runtime = runtimeContext(context);
8070
+ const space = resolveGenericKvSpace(runtime, input.space);
8071
+ const result = await genericKv(runtime, space).delete(input.key, {
8072
+ ...input.etag === void 0 ? {} : { ifMatch: input.etag }
8073
+ });
8074
+ if (!result.ok) return kvFailure(result.error, "delete the KV value");
8075
+ return {
8076
+ status: "ok",
8077
+ output: {
8078
+ space,
8079
+ key: input.key,
8080
+ deleted: true,
8081
+ ...result.data.headers.etag === void 0 ? {} : { etag: result.data.headers.etag }
8082
+ }
8083
+ };
8084
+ } catch (error) {
8085
+ return caughtKvFailure(error, "delete the KV value");
8086
+ }
8087
+ }
7909
8088
  function runtimeContext(context) {
7910
8089
  if (context.runtime === void 0) {
7911
8090
  throw new TypeError("Authenticated operation runtime is unavailable.");
@@ -7915,15 +8094,19 @@ function runtimeContext(context) {
7915
8094
  function runtimeNode(context) {
7916
8095
  return runtimeContext(context).runtime.node;
7917
8096
  }
8097
+ function genericKv(context, space) {
8098
+ return runtimeNode(context).kvForSpace(space);
8099
+ }
7918
8100
  function resolveSpace(context, space) {
7919
8101
  return operationSpaceResolver(context.runtime.node, context.summary.space)(space);
7920
8102
  }
7921
- function resolveNonSecretSpace(context, space) {
8103
+ function resolveGenericKvSpace(context, space) {
7922
8104
  const resolved = resolveSpace(context, space);
7923
- if (resolved.split(":").at(-1)?.toLowerCase() === "secrets") {
8105
+ const protectedName = resolved.split(":").at(-1)?.toLowerCase();
8106
+ if (protectedName === "secrets" || protectedName === "account") {
7924
8107
  throw new OperationInvocationError(operationError(
7925
8108
  "INPUT_INVALID",
7926
- "Generic KV operations cannot access the TinyCloud secrets space; use tinycloud.secrets.get."
8109
+ "Generic KV operations cannot access TinyCloud account or secrets spaces."
7927
8110
  ));
7928
8111
  }
7929
8112
  return resolved;
@@ -7932,13 +8115,57 @@ async function readAccountRegistry(context, prefix) {
7932
8115
  const runtime = runtimeContext(context);
7933
8116
  const accountSpace = resolveSpace(runtime, "account");
7934
8117
  const kv = runtimeNode(runtime).kvForSpace(accountSpace);
7935
- const listed = await kv.list({ prefix });
7936
- if (!listed.ok) return { ok: false };
8118
+ const listed = await kv.list({ prefix, limit: MAX_ACCOUNT_REGISTRY_RECORDS });
8119
+ if (!listed.ok) return { ok: false, outcome: nodeFailure("list the account registry") };
8120
+ if (listed.data.truncated === true) {
8121
+ return {
8122
+ ok: false,
8123
+ outcome: {
8124
+ status: "error",
8125
+ error: operationError(
8126
+ "OUTPUT_INVALID",
8127
+ `The TinyCloud account registry exceeds the ${MAX_ACCOUNT_REGISTRY_RECORDS}-record exploration limit.`
8128
+ )
8129
+ }
8130
+ };
8131
+ }
7937
8132
  const records = [];
8133
+ let totalBytes = 0;
7938
8134
  for (const key of listed.data.keys) {
7939
- const loaded = await kv.get(key);
7940
- if (!loaded.ok || !isRecord2(loaded.data.data)) return { ok: false };
7941
- records.push({ key, value: loaded.data.data });
8135
+ const loaded = await kv.get(key, {
8136
+ binary: true,
8137
+ maxResponseBytes: MAX_KV_VALUE_BYTES
8138
+ });
8139
+ if (!loaded.ok) {
8140
+ return { ok: false, outcome: kvFailure(loaded.error, "read the account registry") };
8141
+ }
8142
+ const bytes = loaded.data.data;
8143
+ totalBytes += bytes.byteLength;
8144
+ if (bytes.byteLength > MAX_KV_VALUE_BYTES || totalBytes > MAX_ACCOUNT_REGISTRY_BYTES) {
8145
+ return {
8146
+ ok: false,
8147
+ outcome: {
8148
+ status: "error",
8149
+ error: operationError(
8150
+ "KV_RESPONSE_TOO_LARGE",
8151
+ `The TinyCloud account registry exceeds the ${MAX_ACCOUNT_REGISTRY_BYTES}-byte exploration limit.`
8152
+ )
8153
+ }
8154
+ };
8155
+ }
8156
+ try {
8157
+ const value = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes));
8158
+ if (!isRecord2(value)) throw new TypeError("Account registry values must be JSON objects.");
8159
+ records.push({ key, value });
8160
+ } catch {
8161
+ return {
8162
+ ok: false,
8163
+ outcome: {
8164
+ status: "error",
8165
+ error: operationError("OUTPUT_INVALID", "The TinyCloud account registry contains an invalid record.")
8166
+ }
8167
+ };
8168
+ }
7942
8169
  }
7943
8170
  return { ok: true, records };
7944
8171
  }
@@ -7984,15 +8211,110 @@ function stringField2(record, ...keys) {
7984
8211
  function isRecord2(value) {
7985
8212
  return typeof value === "object" && value !== null && !Array.isArray(value);
7986
8213
  }
7987
- function encodeKvValue(value) {
7988
- if (value instanceof Uint8Array) {
7989
- return { value: Buffer.from(value).toString("base64"), encoding: "base64" };
8214
+ function encodeKvValue(value, representation) {
8215
+ if (representation === "base64") {
8216
+ return { ok: true, value: Buffer.from(value).toString("base64"), encoding: "base64" };
8217
+ }
8218
+ let text;
8219
+ try {
8220
+ text = new TextDecoder("utf-8", { fatal: true }).decode(value);
8221
+ } catch {
8222
+ return {
8223
+ ok: false,
8224
+ outcome: { status: "error", error: operationError("OUTPUT_INVALID", "The KV value is not valid UTF-8.") }
8225
+ };
8226
+ }
8227
+ if (representation === "text") return { ok: true, value: text, encoding: "text" };
8228
+ try {
8229
+ const parsed = JsonValueSchema.safeParse(JSON.parse(text));
8230
+ if (!parsed.success) {
8231
+ return {
8232
+ ok: false,
8233
+ outcome: {
8234
+ status: "error",
8235
+ error: operationError(
8236
+ "OUTPUT_INVALID",
8237
+ "The KV JSON contains a number that cannot be represented safely."
8238
+ )
8239
+ }
8240
+ };
8241
+ }
8242
+ return { ok: true, value: parsed.data, encoding: "json" };
8243
+ } catch {
8244
+ return {
8245
+ ok: false,
8246
+ outcome: { status: "error", error: operationError("OUTPUT_INVALID", "The KV value is not valid JSON.") }
8247
+ };
8248
+ }
8249
+ }
8250
+ function decodeKvPutContent(content) {
8251
+ let bytes;
8252
+ let contentType;
8253
+ if (content.encoding === "utf8") {
8254
+ bytes = new TextEncoder().encode(content.value);
8255
+ contentType = "text/plain;charset=UTF-8";
8256
+ } else if (content.encoding === "json") {
8257
+ bytes = new TextEncoder().encode(JSON.stringify(content.value));
8258
+ contentType = "application/json";
8259
+ } else {
8260
+ if (!isCanonicalBase64(content.value)) return void 0;
8261
+ bytes = new Uint8Array(Buffer.from(content.value, "base64"));
8262
+ contentType = "application/octet-stream";
8263
+ }
8264
+ return { bytes, byteLength: bytes.byteLength, contentType };
8265
+ }
8266
+ function isCanonicalBase64(value) {
8267
+ if (value.length % 4 !== 0 || !/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(value)) {
8268
+ return false;
7990
8269
  }
8270
+ return Buffer.from(value, "base64").toString("base64") === value;
8271
+ }
8272
+ function projectKvMetadata(headers) {
7991
8273
  return {
7992
- value,
7993
- encoding: typeof value === "string" ? "text" : "json"
8274
+ ...headers.etag === void 0 ? {} : { etag: headers.etag },
8275
+ ...headers.contentType === void 0 ? {} : { contentType: headers.contentType },
8276
+ ...headers.lastModified === void 0 ? {} : { lastModified: headers.lastModified },
8277
+ ...headers.contentLength === void 0 ? {} : { contentLength: headers.contentLength }
7994
8278
  };
7995
8279
  }
8280
+ function caughtKvFailure(error, action) {
8281
+ if (error instanceof OperationInvocationError) return { status: "error", error: error.operationError };
8282
+ return nodeFailure(action);
8283
+ }
8284
+ function accountRegistryOutput(output) {
8285
+ if (Buffer.byteLength(JSON.stringify(output), "utf8") > MAX_ACCOUNT_REGISTRY_BYTES) {
8286
+ return {
8287
+ status: "error",
8288
+ error: operationError(
8289
+ "KV_RESPONSE_TOO_LARGE",
8290
+ `The TinyCloud account registry exceeds the ${MAX_ACCOUNT_REGISTRY_BYTES}-byte exploration limit.`
8291
+ )
8292
+ };
8293
+ }
8294
+ return { status: "ok", output };
8295
+ }
8296
+ function kvFailure(error, action) {
8297
+ if (error.code === "KV_NOT_FOUND") {
8298
+ return { status: "error", error: operationError("KV_NOT_FOUND", "The TinyCloud KV key was not found.") };
8299
+ }
8300
+ if (error.code === "KV_PRECONDITION_FAILED") {
8301
+ return { status: "error", error: operationError("KV_PRECONDITION_FAILED", "The TinyCloud KV object changed or already exists.") };
8302
+ }
8303
+ if (error.code === "KV_CONFLICT") {
8304
+ return {
8305
+ status: "error",
8306
+ error: operationError(
8307
+ "KV_CONFLICT",
8308
+ "A database serialization conflict prevented the conditional KV mutation; re-read the key state, which may still be absent, before deciding whether to retry.",
8309
+ { retryable: true }
8310
+ )
8311
+ };
8312
+ }
8313
+ if (error.code === "KV_RESPONSE_TOO_LARGE") {
8314
+ return { status: "error", error: operationError("KV_RESPONSE_TOO_LARGE", `The TinyCloud KV value exceeds ${MAX_KV_VALUE_BYTES} bytes.`) };
8315
+ }
8316
+ return nodeFailure(action);
8317
+ }
7996
8318
  function nodeFailure(action) {
7997
8319
  return {
7998
8320
  status: "error",
@@ -8003,13 +8325,17 @@ function nodeFailure(action) {
8003
8325
  )
8004
8326
  };
8005
8327
  }
8006
- var import_zod4, EmptyInputSchema2, SpaceSchema, PrefixSchema, KeySchema, AccountSpaceSchema, AccountSpacesOutputSchema, AccountApplicationSchema, AccountApplicationsOutputSchema, KvListInputSchema, KvListOutputSchema, KvGetInputSchema, KvGetOutputSchema, AUTHENTICATED_POSTURES, EXPLORATION_EXPOSURE, ACCOUNT_SPACES_SENSITIVITY, ACCOUNT_APPLICATIONS_SENSITIVITY, KV_LIST_SENSITIVITY, KV_GET_SENSITIVITY, explorationOperationDefinitions;
8328
+ var import_zod4, MAX_KV_VALUE_BYTES, DEFAULT_KV_LIST_LIMIT, MAX_ACCOUNT_REGISTRY_RECORDS, MAX_ACCOUNT_REGISTRY_BYTES, EmptyInputSchema2, SpaceSchema, PrefixSchema, KeySchema, LimitSchema, StrongEtagSchema, ContentTypeSchema, JsonNumberSchema, JsonValueSchema, KvMetadataSchema, AccountSpaceSchema, AccountSpacesOutputSchema, AccountApplicationSchema, AccountApplicationsOutputSchema, KvListInputSchema, KvListOutputSchema, KvGetInputSchema, KvGetOutputSchema, KvPutContentSchema, KvPutCommonSchema, KvPutInputSchema, KvPutOutputSchema, KvHeadInputSchema, KvHeadOutputSchema, KvDeleteInputSchema, KvDeleteOutputSchema, AUTHENTICATED_POSTURES, EXPLORATION_EXPOSURE, ACCOUNT_SPACES_SENSITIVITY, ACCOUNT_APPLICATIONS_SENSITIVITY, KV_LIST_SENSITIVITY, KV_GET_SENSITIVITY, KV_PUT_SENSITIVITY, KV_KEY_SENSITIVITY, explorationOperationDefinitions;
8007
8329
  var init_exploration = __esm({
8008
8330
  "src/operations/exploration.ts"() {
8009
8331
  "use strict";
8010
8332
  import_zod4 = require("zod");
8011
8333
  init_errors();
8012
8334
  init_secrets();
8335
+ MAX_KV_VALUE_BYTES = 1024 * 1024;
8336
+ DEFAULT_KV_LIST_LIMIT = 100;
8337
+ MAX_ACCOUNT_REGISTRY_RECORDS = 1e3;
8338
+ MAX_ACCOUNT_REGISTRY_BYTES = 4 * 1024 * 1024;
8013
8339
  EmptyInputSchema2 = import_zod4.z.object({}).strict();
8014
8340
  SpaceSchema = import_zod4.z.string().min(1).refine(
8015
8341
  (space) => (/^[A-Za-z0-9_-]+$/.test(space) || space.startsWith("tinycloud:")) && !space.includes("*"),
@@ -8023,6 +8349,33 @@ var init_exploration = __esm({
8023
8349
  (key) => key !== "/" && !key.endsWith("/") && !key.includes("*"),
8024
8350
  "Invalid KV key."
8025
8351
  );
8352
+ LimitSchema = import_zod4.z.number().int().min(1).max(1e3);
8353
+ StrongEtagSchema = import_zod4.z.string().regex(
8354
+ /^"blake3-[0-9a-f]{64}"$/,
8355
+ "A strong TinyCloud BLAKE3 ETag is required."
8356
+ );
8357
+ ContentTypeSchema = import_zod4.z.string().min(1).max(128).refine(
8358
+ (value) => !/[\x00-\x1f\x7f]/.test(value),
8359
+ "Invalid content type."
8360
+ );
8361
+ JsonNumberSchema = import_zod4.z.number().finite().refine(
8362
+ (value) => !Number.isInteger(value) || Number.isSafeInteger(value),
8363
+ "JSON integer values must be JavaScript safe integers."
8364
+ );
8365
+ JsonValueSchema = import_zod4.z.lazy(() => import_zod4.z.union([
8366
+ import_zod4.z.null(),
8367
+ import_zod4.z.boolean(),
8368
+ JsonNumberSchema,
8369
+ import_zod4.z.string(),
8370
+ import_zod4.z.array(JsonValueSchema),
8371
+ import_zod4.z.record(JsonValueSchema)
8372
+ ]));
8373
+ KvMetadataSchema = import_zod4.z.object({
8374
+ etag: import_zod4.z.string().optional(),
8375
+ contentType: import_zod4.z.string().optional(),
8376
+ lastModified: import_zod4.z.string().optional(),
8377
+ contentLength: import_zod4.z.number().int().nonnegative().optional()
8378
+ }).strict();
8026
8379
  AccountSpaceSchema = import_zod4.z.object({
8027
8380
  spaceId: import_zod4.z.string().min(1),
8028
8381
  name: import_zod4.z.string().min(1),
@@ -8052,17 +8405,20 @@ var init_exploration = __esm({
8052
8405
  }).strict();
8053
8406
  KvListInputSchema = import_zod4.z.object({
8054
8407
  space: SpaceSchema,
8055
- prefix: PrefixSchema.optional()
8408
+ prefix: PrefixSchema.optional(),
8409
+ limit: LimitSchema.optional()
8056
8410
  }).strict();
8057
8411
  KvListOutputSchema = import_zod4.z.object({
8058
8412
  space: import_zod4.z.string().min(1),
8059
8413
  prefix: import_zod4.z.string(),
8060
8414
  keys: import_zod4.z.array(import_zod4.z.string()),
8061
- count: import_zod4.z.number().int().nonnegative()
8415
+ count: import_zod4.z.number().int().nonnegative(),
8416
+ truncated: import_zod4.z.boolean()
8062
8417
  }).strict();
8063
8418
  KvGetInputSchema = import_zod4.z.object({
8064
8419
  space: SpaceSchema,
8065
- key: KeySchema
8420
+ key: KeySchema,
8421
+ representation: import_zod4.z.enum(["base64", "text", "json"]).optional()
8066
8422
  }).strict();
8067
8423
  KvGetOutputSchema = import_zod4.z.object({
8068
8424
  space: import_zod4.z.string().min(1),
@@ -8076,12 +8432,61 @@ var init_exploration = __esm({
8076
8432
  import_zod4.z.record(import_zod4.z.unknown())
8077
8433
  ]),
8078
8434
  encoding: import_zod4.z.enum(["json", "text", "base64"]),
8079
- metadata: import_zod4.z.object({
8080
- etag: import_zod4.z.string().optional(),
8081
- contentType: import_zod4.z.string().optional(),
8082
- lastModified: import_zod4.z.string().optional(),
8083
- contentLength: import_zod4.z.number().int().nonnegative().optional()
8084
- }).strict()
8435
+ metadata: KvMetadataSchema,
8436
+ byteLength: import_zod4.z.number().int().nonnegative()
8437
+ }).strict();
8438
+ KvPutContentSchema = import_zod4.z.discriminatedUnion("encoding", [
8439
+ import_zod4.z.object({ encoding: import_zod4.z.literal("utf8"), value: import_zod4.z.string() }).strict(),
8440
+ import_zod4.z.object({ encoding: import_zod4.z.literal("json"), value: JsonValueSchema }).strict(),
8441
+ import_zod4.z.object({ encoding: import_zod4.z.literal("base64"), value: import_zod4.z.string() }).strict()
8442
+ ]).superRefine((content, context) => {
8443
+ const decoded = decodeKvPutContent(content);
8444
+ if (decoded === void 0) {
8445
+ context.addIssue({ code: import_zod4.z.ZodIssueCode.custom, message: "Invalid canonical base64 content." });
8446
+ } else if (decoded.byteLength > MAX_KV_VALUE_BYTES) {
8447
+ context.addIssue({
8448
+ code: import_zod4.z.ZodIssueCode.too_big,
8449
+ type: "array",
8450
+ maximum: MAX_KV_VALUE_BYTES,
8451
+ inclusive: true,
8452
+ message: `KV content must not exceed ${MAX_KV_VALUE_BYTES} bytes.`
8453
+ });
8454
+ }
8455
+ });
8456
+ KvPutCommonSchema = {
8457
+ space: SpaceSchema,
8458
+ key: KeySchema,
8459
+ content: KvPutContentSchema,
8460
+ contentType: ContentTypeSchema.optional()
8461
+ };
8462
+ KvPutInputSchema = import_zod4.z.discriminatedUnion("mode", [
8463
+ import_zod4.z.object({ ...KvPutCommonSchema, mode: import_zod4.z.literal("create") }).strict(),
8464
+ import_zod4.z.object({ ...KvPutCommonSchema, mode: import_zod4.z.literal("upsert") }).strict(),
8465
+ import_zod4.z.object({ ...KvPutCommonSchema, mode: import_zod4.z.literal("replace"), etag: StrongEtagSchema }).strict()
8466
+ ]);
8467
+ KvPutOutputSchema = import_zod4.z.object({
8468
+ space: import_zod4.z.string().min(1),
8469
+ key: import_zod4.z.string().min(1),
8470
+ mode: import_zod4.z.enum(["create", "replace", "upsert"]),
8471
+ byteLength: import_zod4.z.number().int().nonnegative(),
8472
+ metadata: KvMetadataSchema
8473
+ }).strict();
8474
+ KvHeadInputSchema = import_zod4.z.object({ space: SpaceSchema, key: KeySchema }).strict();
8475
+ KvHeadOutputSchema = import_zod4.z.object({
8476
+ space: import_zod4.z.string().min(1),
8477
+ key: import_zod4.z.string().min(1),
8478
+ metadata: KvMetadataSchema
8479
+ }).strict();
8480
+ KvDeleteInputSchema = import_zod4.z.object({
8481
+ space: SpaceSchema,
8482
+ key: KeySchema,
8483
+ etag: StrongEtagSchema.optional()
8484
+ }).strict();
8485
+ KvDeleteOutputSchema = import_zod4.z.object({
8486
+ space: import_zod4.z.string().min(1),
8487
+ key: import_zod4.z.string().min(1),
8488
+ deleted: import_zod4.z.literal(true),
8489
+ etag: import_zod4.z.string().optional()
8085
8490
  }).strict();
8086
8491
  AUTHENTICATED_POSTURES = [
8087
8492
  "owner-openkey",
@@ -8113,6 +8518,8 @@ var init_exploration = __esm({
8113
8518
  input: ["/key"],
8114
8519
  output: ["/value"]
8115
8520
  };
8521
+ KV_PUT_SENSITIVITY = { input: ["/key", "/content"], output: [] };
8522
+ KV_KEY_SENSITIVITY = { input: ["/key"], output: [] };
8116
8523
  explorationOperationDefinitions = [
8117
8524
  {
8118
8525
  id: "tinycloud.account.spaces.list",
@@ -8163,7 +8570,7 @@ var init_exploration = __esm({
8163
8570
  id: "tinycloud.kv.get",
8164
8571
  version: 1,
8165
8572
  title: "Get a TinyCloud KV value",
8166
- description: "Read one exact key from a delegated non-secrets TinyCloud space.",
8573
+ description: "Read one exact key with a node-enforced one MiB response limit.",
8167
8574
  input: KvGetInputSchema,
8168
8575
  output: KvGetOutputSchema,
8169
8576
  effects: ["read"],
@@ -8173,6 +8580,51 @@ var init_exploration = __esm({
8173
8580
  sensitivity: KV_GET_SENSITIVITY,
8174
8581
  authority: planKvGet,
8175
8582
  execute: executeKvGet
8583
+ },
8584
+ {
8585
+ id: "tinycloud.kv.head",
8586
+ version: 1,
8587
+ title: "Inspect TinyCloud KV metadata",
8588
+ description: "Read metadata for one exact key without downloading its value.",
8589
+ input: KvHeadInputSchema,
8590
+ output: KvHeadOutputSchema,
8591
+ effects: ["read"],
8592
+ runtime: "authenticated",
8593
+ postures: AUTHENTICATED_POSTURES,
8594
+ exposure: EXPLORATION_EXPOSURE,
8595
+ sensitivity: KV_KEY_SENSITIVITY,
8596
+ authority: (context, input) => planExactKv(context, input.space, input.key, "tinycloud.kv/metadata"),
8597
+ execute: executeKvHead
8598
+ },
8599
+ {
8600
+ id: "tinycloud.kv.put",
8601
+ version: 1,
8602
+ title: "Write a TinyCloud KV value",
8603
+ description: "Create, conditionally replace, or explicitly upsert one exact KV key.",
8604
+ input: KvPutInputSchema,
8605
+ output: KvPutOutputSchema,
8606
+ effects: ["write"],
8607
+ runtime: "authenticated",
8608
+ postures: AUTHENTICATED_POSTURES,
8609
+ exposure: EXPLORATION_EXPOSURE,
8610
+ sensitivity: KV_PUT_SENSITIVITY,
8611
+ authority: (context, input) => planExactKv(context, input.space, input.key, "tinycloud.kv/put"),
8612
+ execute: executeKvPut
8613
+ },
8614
+ {
8615
+ id: "tinycloud.kv.delete",
8616
+ version: 1,
8617
+ title: "Delete a TinyCloud KV value",
8618
+ description: "Delete one exact KV key, optionally only when its ETag still matches.",
8619
+ input: KvDeleteInputSchema,
8620
+ output: KvDeleteOutputSchema,
8621
+ effects: ["destructive"],
8622
+ runtime: "authenticated",
8623
+ postures: AUTHENTICATED_POSTURES,
8624
+ exposure: EXPLORATION_EXPOSURE,
8625
+ sensitivity: KV_KEY_SENSITIVITY,
8626
+ authority: (context, input) => planExactKv(context, input.space, input.key, "tinycloud.kv/del"),
8627
+ execute: executeKvDelete
8176
8628
  }
8177
8629
  ];
8178
8630
  }
@@ -8387,6 +8839,541 @@ var init_secrets_get = __esm({
8387
8839
  }
8388
8840
  });
8389
8841
 
8842
+ // src/operations/sql.ts
8843
+ async function planSqlRead(context, input) {
8844
+ const space = resolveSqlSpace(context, input.space);
8845
+ return [{
8846
+ service: "tinycloud.sql",
8847
+ space,
8848
+ path: input.database,
8849
+ actions: ["tinycloud.sql/read"]
8850
+ }];
8851
+ }
8852
+ async function planSqlWrite(context, input) {
8853
+ const space = resolveSqlSpace(context, input.space);
8854
+ return [{
8855
+ service: "tinycloud.sql",
8856
+ space,
8857
+ path: input.database,
8858
+ actions: ["tinycloud.sql/write"],
8859
+ description: SQL_WRITE_AUTHORITY_NOTICE
8860
+ }];
8861
+ }
8862
+ async function executeSqlSchemaInspect(context, input) {
8863
+ try {
8864
+ const runtime = runtimeContext2(context);
8865
+ const space = resolveSqlSpace(runtime, input.space);
8866
+ const result = await runtimeNode2(runtime).sqlForSpace(space).db(input.database).query(SCHEMA_QUERY, [], { maxRows: SCHEMA_MAX_ROWS, maxBytes: SCHEMA_MAX_BYTES });
8867
+ if (!result.ok) return sqlServiceFailure(result.error, "inspect the SQLite schema");
8868
+ const normalized = normalizeQueryResult(result.data, SCHEMA_MAX_ROWS, SCHEMA_MAX_BYTES);
8869
+ const objects = normalized.rows.map((row) => schemaObject(row));
8870
+ return {
8871
+ status: "ok",
8872
+ output: {
8873
+ space,
8874
+ database: input.database,
8875
+ objects,
8876
+ count: objects.length,
8877
+ limits: limitsOutput(SCHEMA_MAX_ROWS, SCHEMA_MAX_BYTES)
8878
+ }
8879
+ };
8880
+ } catch (error) {
8881
+ return sqlFailure(error, "inspect the SQLite schema");
8882
+ }
8883
+ }
8884
+ async function executeSqlQuery(context, input) {
8885
+ try {
8886
+ if (!isSingleReadQuery(input.sql)) {
8887
+ return {
8888
+ status: "error",
8889
+ error: operationError(
8890
+ "SQL_QUERY_INVALID",
8891
+ "SQL must parse as exactly one SQLite SELECT statement."
8892
+ )
8893
+ };
8894
+ }
8895
+ const runtime = runtimeContext2(context);
8896
+ const space = resolveSqlSpace(runtime, input.space);
8897
+ const maxRows = input.maxRows ?? DEFAULT_MAX_ROWS;
8898
+ const maxBytes = input.maxBytes ?? DEFAULT_MAX_BYTES;
8899
+ const params = (input.params ?? []).map(decodeSqlInputValue);
8900
+ const result = await runtimeNode2(runtime).sqlForSpace(space).db(input.database).query(input.sql, params, { maxRows, maxBytes });
8901
+ if (!result.ok) return sqlServiceFailure(result.error, "run the SQLite query");
8902
+ const normalized = normalizeQueryResult(result.data, maxRows, maxBytes);
8903
+ return {
8904
+ status: "ok",
8905
+ output: {
8906
+ space,
8907
+ database: input.database,
8908
+ columns: normalized.columns,
8909
+ rows: normalized.rows,
8910
+ rowCount: normalized.rows.length,
8911
+ limits: limitsOutput(maxRows, maxBytes)
8912
+ }
8913
+ };
8914
+ } catch (error) {
8915
+ return sqlFailure(error, "run the SQLite query");
8916
+ }
8917
+ }
8918
+ async function executeSqlDml(context, input) {
8919
+ try {
8920
+ const statementType = parseSingleDmlStatement(input.sql, input.params.length);
8921
+ if (statementType === void 0) {
8922
+ return {
8923
+ status: "error",
8924
+ error: operationError(
8925
+ "SQL_QUERY_INVALID",
8926
+ "SQL must parse as exactly one parameterized INSERT, UPDATE, or DELETE with one value per positional placeholder."
8927
+ )
8928
+ };
8929
+ }
8930
+ const runtime = runtimeContext2(context);
8931
+ const space = resolveSqlSpace(runtime, input.space);
8932
+ const result = await runtimeNode2(runtime).sqlForSpace(space).db(input.database).execute(input.sql, input.params.map(decodeSqlInputValue));
8933
+ if (!result.ok) return sqlMutationFailure();
8934
+ const normalized = normalizeExecuteResult(result.data);
8935
+ return {
8936
+ status: "ok",
8937
+ output: {
8938
+ space,
8939
+ database: input.database,
8940
+ statementType,
8941
+ ...normalized,
8942
+ authorityNotice: SQL_WRITE_AUTHORITY_NOTICE
8943
+ }
8944
+ };
8945
+ } catch (error) {
8946
+ return sqlFailure(error, "execute the SQLite statement");
8947
+ }
8948
+ }
8949
+ function isSingleReadQuery(sql) {
8950
+ const ast = parseSingleStatement(sql);
8951
+ return ast !== void 0 && ast.type === "select";
8952
+ }
8953
+ function parseSingleDmlStatement(sql, parameterCount) {
8954
+ const ast = parseSingleStatement(sql);
8955
+ if (ast === void 0 || ast.type !== "insert" && ast.type !== "update" && ast.type !== "delete" || ast.with !== void 0 && ast.with !== null) {
8956
+ return void 0;
8957
+ }
8958
+ const placeholders = countPositionalParameters(ast);
8959
+ return placeholders > 0 && placeholders === parameterCount ? ast.type : void 0;
8960
+ }
8961
+ function parseSingleStatement(sql) {
8962
+ try {
8963
+ const ast = sqlParser.astify(sql, { database: "sqlite" });
8964
+ return !Array.isArray(ast) && isRecord3(ast) ? ast : void 0;
8965
+ } catch {
8966
+ return void 0;
8967
+ }
8968
+ }
8969
+ function countPositionalParameters(value) {
8970
+ if (Array.isArray(value)) {
8971
+ return value.reduce((count, entry) => count + countPositionalParameters(entry), 0);
8972
+ }
8973
+ if (!isRecord3(value)) return 0;
8974
+ const current = value.type === "origin" && value.value === "?" ? 1 : 0;
8975
+ return Object.values(value).reduce(
8976
+ (count, entry) => count + countPositionalParameters(entry),
8977
+ current
8978
+ );
8979
+ }
8980
+ function decodeSqlInputValue(value) {
8981
+ if (isRecord3(value) && value.type === "blob") {
8982
+ return new Uint8Array(Buffer.from(value.base64, "base64"));
8983
+ }
8984
+ return value;
8985
+ }
8986
+ function normalizeQueryResult(value, maxRows, maxBytes) {
8987
+ if (!isRecord3(value) || !Array.isArray(value.columns) || !Array.isArray(value.rows)) {
8988
+ throw unsafeSqlValue("The node returned an invalid SQLite query result.");
8989
+ }
8990
+ const columns = value.columns.map((column) => {
8991
+ if (typeof column !== "string") {
8992
+ throw unsafeSqlValue("The node returned an invalid SQLite column name.");
8993
+ }
8994
+ return column;
8995
+ });
8996
+ const rows = value.rows.map((row) => {
8997
+ if (!Array.isArray(row) || row.length !== columns.length) {
8998
+ throw unsafeSqlValue("The node returned an invalid SQLite row.");
8999
+ }
9000
+ return row.map(normalizeSqlOutputValue);
9001
+ });
9002
+ const serializedBytes = Buffer.byteLength(JSON.stringify({ columns, rows }), "utf8");
9003
+ if (rows.length > maxRows || serializedBytes > maxBytes) {
9004
+ throw new OperationInvocationError(operationError(
9005
+ "SQL_RESULT_LIMIT_EXCEEDED",
9006
+ "The SQLite query result exceeded the requested result limits.",
9007
+ {
9008
+ details: {
9009
+ maxRows,
9010
+ maxBytes,
9011
+ returnedRows: rows.length,
9012
+ returnedBytes: serializedBytes
9013
+ }
9014
+ }
9015
+ ));
9016
+ }
9017
+ return { columns, rows };
9018
+ }
9019
+ function normalizeSqlOutputValue(value) {
9020
+ if (value === null || typeof value === "string") return value;
9021
+ if (typeof value === "number") {
9022
+ if (!Number.isFinite(value) || Number.isInteger(value) && !Number.isSafeInteger(value)) {
9023
+ throw unsafeSqlValue("The node returned an integer that cannot be represented safely in JavaScript.");
9024
+ }
9025
+ return value;
9026
+ }
9027
+ if (value instanceof Uint8Array) return encodeBlob(value);
9028
+ if (Array.isArray(value) && value.every(isByte)) {
9029
+ return encodeBlob(Uint8Array.from(value));
9030
+ }
9031
+ if (isRecord3(value) && value.type === "Buffer" && Array.isArray(value.data) && value.data.every(isByte)) {
9032
+ return encodeBlob(Uint8Array.from(value.data));
9033
+ }
9034
+ throw unsafeSqlValue("The node returned an unsupported SQLite value.");
9035
+ }
9036
+ function normalizeExecuteResult(value) {
9037
+ if (!isRecord3(value) || !Number.isSafeInteger(value.changes) || value.changes < 0 || value.lastInsertRowId !== null && !Number.isSafeInteger(value.lastInsertRowId)) {
9038
+ throw unsafeSqlValue("The node returned SQLite mutation metadata that cannot be represented safely in JavaScript.");
9039
+ }
9040
+ return {
9041
+ changes: value.changes,
9042
+ lastInsertRowId: value.lastInsertRowId
9043
+ };
9044
+ }
9045
+ function schemaObject(row) {
9046
+ const [type, name, tableName, sql] = row;
9047
+ if (type !== "table" && type !== "view" && type !== "index" && type !== "trigger" || typeof name !== "string" || typeof tableName !== "string" || sql !== null && typeof sql !== "string") {
9048
+ throw unsafeSqlValue("The node returned an invalid SQLite schema record.");
9049
+ }
9050
+ return {
9051
+ type,
9052
+ name,
9053
+ tableName,
9054
+ ...sql === null ? {} : { sql }
9055
+ };
9056
+ }
9057
+ function limitsOutput(maxRows, maxBytes) {
9058
+ return { maxRows, maxBytes, enforcement: "node-requested-client-verified" };
9059
+ }
9060
+ function runtimeContext2(context) {
9061
+ if (context.runtime === void 0) {
9062
+ throw new TypeError("Authenticated operation runtime is unavailable.");
9063
+ }
9064
+ return context;
9065
+ }
9066
+ function runtimeNode2(context) {
9067
+ return context.runtime.node;
9068
+ }
9069
+ function resolveSqlSpace(context, space) {
9070
+ const resolved = operationSpaceResolver(
9071
+ context.runtime.node,
9072
+ context.summary.space
9073
+ )(space);
9074
+ const name = resolved.split(":").at(-1)?.toLowerCase();
9075
+ if (name === "secrets" || name === "account") {
9076
+ throw new OperationInvocationError(operationError(
9077
+ "INPUT_INVALID",
9078
+ "Generic SQL operations cannot access protected TinyCloud account or secrets spaces."
9079
+ ));
9080
+ }
9081
+ return resolved;
9082
+ }
9083
+ function encodeBlob(value) {
9084
+ return {
9085
+ type: "blob",
9086
+ base64: Buffer.from(value).toString("base64"),
9087
+ byteLength: value.byteLength
9088
+ };
9089
+ }
9090
+ function unsafeSqlValue(message) {
9091
+ return new OperationInvocationError(operationError("SQL_VALUE_UNSAFE", message));
9092
+ }
9093
+ function sqlFailure(error, action) {
9094
+ if (error instanceof OperationInvocationError) {
9095
+ return { status: "error", error: error.operationError };
9096
+ }
9097
+ return nodeFailure2(action);
9098
+ }
9099
+ function nodeFailure2(action) {
9100
+ return {
9101
+ status: "error",
9102
+ error: operationError(
9103
+ "NODE_ERROR",
9104
+ `The TinyCloud node could not ${action}.`,
9105
+ { retryable: true }
9106
+ )
9107
+ };
9108
+ }
9109
+ function sqlServiceFailure(error, action) {
9110
+ if (isRecord3(error) && error.code === "SQL_RESPONSE_TOO_LARGE") {
9111
+ return {
9112
+ status: "error",
9113
+ error: operationError(
9114
+ "SQL_RESULT_LIMIT_EXCEEDED",
9115
+ "The SQLite query result exceeded the requested result limits."
9116
+ )
9117
+ };
9118
+ }
9119
+ return nodeFailure2(action);
9120
+ }
9121
+ function sqlMutationFailure() {
9122
+ return {
9123
+ status: "error",
9124
+ error: operationError(
9125
+ "SQL_EXECUTION_FAILED",
9126
+ "The SQLite statement outcome is unknown; inspect database state before considering another write.",
9127
+ { retryable: false }
9128
+ )
9129
+ };
9130
+ }
9131
+ function isCanonicalBase642(value) {
9132
+ if (value === "") return true;
9133
+ if (value.length % 4 !== 0 || !/^[A-Za-z0-9+/]*={0,2}$/.test(value)) return false;
9134
+ return Buffer.from(value, "base64").toString("base64") === value;
9135
+ }
9136
+ function sqlInputValueBytes(value) {
9137
+ if (typeof value === "string") return Buffer.byteLength(value, "utf8");
9138
+ if (isRecord3(value) && value.type === "blob") {
9139
+ return Buffer.from(value.base64, "base64").byteLength;
9140
+ }
9141
+ return 8;
9142
+ }
9143
+ function isByte(value) {
9144
+ return Number.isInteger(value) && value >= 0 && value <= 255;
9145
+ }
9146
+ function isRecord3(value) {
9147
+ return typeof value === "object" && value !== null && !Array.isArray(value);
9148
+ }
9149
+ var import_node_sql_parser, import_zod6, DEFAULT_MAX_ROWS, MAX_MAX_ROWS, DEFAULT_MAX_BYTES, MAX_MAX_BYTES, SCHEMA_MAX_ROWS, SCHEMA_MAX_BYTES, MAX_PARAMETERS, MAX_SQL_LENGTH, SQL_WRITE_AUTHORITY_NOTICE, SCHEMA_QUERY, sqlParser, SpaceSchema2, DatabaseSchema, SafeNumberSchema, Base64Schema, SqlInputValueSchema, SqlParamsSchema, RequiredSqlParamsSchema, SqlOutputValueSchema, SqlTargetInputSchema, SqlQueryInputSchema, SqlExecuteInputSchema, SqlLimitsOutputSchema, SqlSchemaInspectOutputSchema, SqlQueryOutputSchema, SqlExecuteOutputSchema, AUTHENTICATED_POSTURES2, SQL_EXPOSURE, SQL_SCHEMA_SENSITIVITY, SQL_QUERY_SENSITIVITY, SQL_EXECUTE_SENSITIVITY, sqlOperationDefinitions;
9150
+ var init_sql = __esm({
9151
+ "src/operations/sql.ts"() {
9152
+ "use strict";
9153
+ import_node_sql_parser = __toESM(require("node-sql-parser"), 1);
9154
+ import_zod6 = require("zod");
9155
+ init_errors();
9156
+ init_secrets();
9157
+ DEFAULT_MAX_ROWS = 100;
9158
+ MAX_MAX_ROWS = 1e3;
9159
+ DEFAULT_MAX_BYTES = 1024 * 1024;
9160
+ MAX_MAX_BYTES = 4 * 1024 * 1024;
9161
+ SCHEMA_MAX_ROWS = 500;
9162
+ SCHEMA_MAX_BYTES = 1024 * 1024;
9163
+ MAX_PARAMETERS = 100;
9164
+ MAX_SQL_LENGTH = 64 * 1024;
9165
+ SQL_WRITE_AUTHORITY_NOTICE = "Approving tinycloud.sql/write grants full read/write/schema mutation authority over this exact database; the MCP tool itself accepts only one parameterized INSERT, UPDATE, or DELETE.";
9166
+ SCHEMA_QUERY = `SELECT type, name, tbl_name, sql
9167
+ FROM sqlite_schema
9168
+ WHERE type IN ('table', 'view', 'index', 'trigger')
9169
+ AND name NOT LIKE 'sqlite_%'
9170
+ ORDER BY type, name`;
9171
+ sqlParser = new import_node_sql_parser.default.Parser();
9172
+ SpaceSchema2 = import_zod6.z.string().min(1).refine(
9173
+ (space) => (/^[A-Za-z0-9_-]+$/.test(space) || space.startsWith("tinycloud:")) && !space.includes("*"),
9174
+ "Invalid TinyCloud space."
9175
+ );
9176
+ DatabaseSchema = import_zod6.z.string().min(1).max(256).refine(
9177
+ (database) => database !== "/" && !database.endsWith("/") && !database.includes("*") && !/[\u0000-\u001f\u007f]/.test(database),
9178
+ "Invalid SQLite database name."
9179
+ );
9180
+ SafeNumberSchema = import_zod6.z.number().finite().refine(
9181
+ (value) => !Number.isInteger(value) || Number.isSafeInteger(value),
9182
+ "SQLite integer parameters must be JavaScript safe integers."
9183
+ );
9184
+ Base64Schema = import_zod6.z.string().max(Math.ceil(MAX_MAX_BYTES / 3) * 4).refine(
9185
+ isCanonicalBase642,
9186
+ "Invalid base64 BLOB value."
9187
+ );
9188
+ SqlInputValueSchema = import_zod6.z.union([
9189
+ import_zod6.z.null(),
9190
+ SafeNumberSchema,
9191
+ import_zod6.z.string().max(MAX_MAX_BYTES),
9192
+ import_zod6.z.object({ type: import_zod6.z.literal("blob"), base64: Base64Schema }).strict()
9193
+ ]);
9194
+ SqlParamsSchema = import_zod6.z.array(SqlInputValueSchema).max(MAX_PARAMETERS).superRefine(
9195
+ (params, context) => {
9196
+ const totalBytes = params.reduce(
9197
+ (total, value) => total + sqlInputValueBytes(value),
9198
+ 0
9199
+ );
9200
+ if (totalBytes > MAX_MAX_BYTES) {
9201
+ context.addIssue({
9202
+ code: import_zod6.z.ZodIssueCode.custom,
9203
+ message: "SQLite query parameters exceed the 4 MiB input limit."
9204
+ });
9205
+ }
9206
+ }
9207
+ );
9208
+ RequiredSqlParamsSchema = import_zod6.z.array(SqlInputValueSchema).min(1).max(MAX_PARAMETERS).superRefine(
9209
+ (params, context) => {
9210
+ const totalBytes = params.reduce(
9211
+ (total, value) => total + sqlInputValueBytes(value),
9212
+ 0
9213
+ );
9214
+ if (totalBytes > MAX_MAX_BYTES) {
9215
+ context.addIssue({
9216
+ code: import_zod6.z.ZodIssueCode.custom,
9217
+ message: "SQLite query parameters exceed the 4 MiB input limit."
9218
+ });
9219
+ }
9220
+ }
9221
+ );
9222
+ SqlOutputValueSchema = import_zod6.z.union([
9223
+ import_zod6.z.null(),
9224
+ SafeNumberSchema,
9225
+ import_zod6.z.string(),
9226
+ import_zod6.z.object({
9227
+ type: import_zod6.z.literal("blob"),
9228
+ base64: import_zod6.z.string(),
9229
+ byteLength: import_zod6.z.number().int().nonnegative()
9230
+ }).strict()
9231
+ ]);
9232
+ SqlTargetInputSchema = import_zod6.z.object({
9233
+ space: SpaceSchema2,
9234
+ database: DatabaseSchema
9235
+ }).strict();
9236
+ SqlQueryInputSchema = import_zod6.z.object({
9237
+ space: SpaceSchema2,
9238
+ database: DatabaseSchema,
9239
+ sql: import_zod6.z.string().min(1).max(MAX_SQL_LENGTH).superRefine((sql, context) => {
9240
+ if (!isSingleReadQuery(sql)) {
9241
+ context.addIssue({
9242
+ code: import_zod6.z.ZodIssueCode.custom,
9243
+ message: "SQL must parse as exactly one SQLite SELECT statement."
9244
+ });
9245
+ }
9246
+ }),
9247
+ params: SqlParamsSchema.optional(),
9248
+ maxRows: import_zod6.z.number().int().positive().max(MAX_MAX_ROWS).optional(),
9249
+ maxBytes: import_zod6.z.number().int().positive().max(MAX_MAX_BYTES).optional()
9250
+ }).strict();
9251
+ SqlExecuteInputSchema = import_zod6.z.object({
9252
+ space: SpaceSchema2,
9253
+ database: DatabaseSchema,
9254
+ sql: import_zod6.z.string().min(1).max(MAX_SQL_LENGTH),
9255
+ params: RequiredSqlParamsSchema,
9256
+ acknowledgeDatabaseWideAuthority: import_zod6.z.literal(true).describe(SQL_WRITE_AUTHORITY_NOTICE)
9257
+ }).strict().superRefine((input, context) => {
9258
+ if (parseSingleDmlStatement(input.sql, input.params.length) === void 0) {
9259
+ context.addIssue({
9260
+ code: import_zod6.z.ZodIssueCode.custom,
9261
+ path: ["sql"],
9262
+ message: "SQL must parse as exactly one parameterized INSERT, UPDATE, or DELETE with one value per positional placeholder."
9263
+ });
9264
+ }
9265
+ });
9266
+ SqlLimitsOutputSchema = import_zod6.z.object({
9267
+ maxRows: import_zod6.z.number().int().positive(),
9268
+ maxBytes: import_zod6.z.number().int().positive(),
9269
+ enforcement: import_zod6.z.literal("node-requested-client-verified")
9270
+ }).strict();
9271
+ SqlSchemaInspectOutputSchema = import_zod6.z.object({
9272
+ space: import_zod6.z.string().min(1),
9273
+ database: import_zod6.z.string().min(1),
9274
+ objects: import_zod6.z.array(import_zod6.z.object({
9275
+ type: import_zod6.z.enum(["table", "view", "index", "trigger"]),
9276
+ name: import_zod6.z.string().min(1),
9277
+ tableName: import_zod6.z.string().min(1),
9278
+ sql: import_zod6.z.string().optional()
9279
+ }).strict()),
9280
+ count: import_zod6.z.number().int().nonnegative(),
9281
+ limits: SqlLimitsOutputSchema
9282
+ }).strict();
9283
+ SqlQueryOutputSchema = import_zod6.z.object({
9284
+ space: import_zod6.z.string().min(1),
9285
+ database: import_zod6.z.string().min(1),
9286
+ columns: import_zod6.z.array(import_zod6.z.string()),
9287
+ rows: import_zod6.z.array(import_zod6.z.array(SqlOutputValueSchema)),
9288
+ rowCount: import_zod6.z.number().int().nonnegative(),
9289
+ limits: SqlLimitsOutputSchema
9290
+ }).strict();
9291
+ SqlExecuteOutputSchema = import_zod6.z.object({
9292
+ space: import_zod6.z.string().min(1),
9293
+ database: import_zod6.z.string().min(1),
9294
+ statementType: import_zod6.z.enum(["insert", "update", "delete"]),
9295
+ changes: import_zod6.z.number().int().nonnegative(),
9296
+ lastInsertRowId: import_zod6.z.number().int().nullable(),
9297
+ authorityNotice: import_zod6.z.literal(SQL_WRITE_AUTHORITY_NOTICE)
9298
+ }).strict();
9299
+ AUTHENTICATED_POSTURES2 = [
9300
+ "owner-openkey",
9301
+ "delegate-session",
9302
+ "local-owner-key"
9303
+ ];
9304
+ SQL_EXPOSURE = {
9305
+ cli: {
9306
+ status: "excluded",
9307
+ reason: "Existing SQL Commander commands remain the CLI surface."
9308
+ },
9309
+ mcp: { status: "required" },
9310
+ skill: { status: "required" },
9311
+ docs: { status: "required" }
9312
+ };
9313
+ SQL_SCHEMA_SENSITIVITY = {
9314
+ input: ["/database"],
9315
+ output: ["/objects"]
9316
+ };
9317
+ SQL_QUERY_SENSITIVITY = {
9318
+ input: ["/database", "/sql", "/params"],
9319
+ output: ["/columns", "/rows"]
9320
+ };
9321
+ SQL_EXECUTE_SENSITIVITY = {
9322
+ input: ["/database", "/sql", "/params"],
9323
+ output: ["/lastInsertRowId"]
9324
+ };
9325
+ sqlOperationDefinitions = [
9326
+ {
9327
+ id: "tinycloud.sql.schema.inspect",
9328
+ version: 1,
9329
+ title: "Inspect a TinyCloud SQLite schema",
9330
+ description: "List user tables, views, indexes, and triggers in one exact TinyCloud SQLite database using a fixed read-only query.",
9331
+ input: SqlTargetInputSchema,
9332
+ output: SqlSchemaInspectOutputSchema,
9333
+ effects: ["read"],
9334
+ runtime: "authenticated",
9335
+ postures: AUTHENTICATED_POSTURES2,
9336
+ exposure: SQL_EXPOSURE,
9337
+ sensitivity: SQL_SCHEMA_SENSITIVITY,
9338
+ authority: planSqlRead,
9339
+ execute: executeSqlSchemaInspect
9340
+ },
9341
+ {
9342
+ id: "tinycloud.sql.query",
9343
+ version: 1,
9344
+ title: "Query a TinyCloud SQLite database",
9345
+ description: "Run exactly one parser-approved SELECT against one exact TinyCloud SQLite database. Result limits are requested from the node and verified locally without silent truncation.",
9346
+ input: SqlQueryInputSchema,
9347
+ output: SqlQueryOutputSchema,
9348
+ effects: ["read"],
9349
+ runtime: "authenticated",
9350
+ postures: AUTHENTICATED_POSTURES2,
9351
+ exposure: SQL_EXPOSURE,
9352
+ sensitivity: SQL_QUERY_SENSITIVITY,
9353
+ invalidInputErrorCode: "SQL_QUERY_INVALID",
9354
+ authority: planSqlRead,
9355
+ execute: executeSqlQuery
9356
+ },
9357
+ {
9358
+ id: "tinycloud.sql.execute",
9359
+ version: 1,
9360
+ title: "Execute a TinyCloud SQLite DML statement",
9361
+ description: `Run exactly one parameterized INSERT, UPDATE, or DELETE against one exact TinyCloud SQLite database. ${SQL_WRITE_AUTHORITY_NOTICE}`,
9362
+ input: SqlExecuteInputSchema,
9363
+ output: SqlExecuteOutputSchema,
9364
+ effects: ["write", "destructive"],
9365
+ runtime: "authenticated",
9366
+ postures: AUTHENTICATED_POSTURES2,
9367
+ exposure: SQL_EXPOSURE,
9368
+ sensitivity: SQL_EXECUTE_SENSITIVITY,
9369
+ invalidInputErrorCode: "SQL_QUERY_INVALID",
9370
+ authority: planSqlWrite,
9371
+ execute: executeSqlDml
9372
+ }
9373
+ ];
9374
+ }
9375
+ });
9376
+
8390
9377
  // src/operations/status.ts
8391
9378
  function createStatusDefinition(params) {
8392
9379
  return {
@@ -8442,7 +9429,7 @@ async function inspectPinnedProfileStatus(context, _input) {
8442
9429
  async function pinnedProfileExists(profile) {
8443
9430
  try {
8444
9431
  const storedProfile = await readProfile(profile);
8445
- return isRecord3(storedProfile);
9432
+ return isRecord4(storedProfile);
8446
9433
  } catch {
8447
9434
  return false;
8448
9435
  }
@@ -8462,7 +9449,7 @@ async function countLiveAdditionalDelegations(profile) {
8462
9449
  }
8463
9450
  function summarizeSession(session) {
8464
9451
  if (session === null) return { present: false, expired: null, expiresAt: null };
8465
- if (!isRecord3(session)) throw new TypeError("Invalid session store.");
9452
+ if (!isRecord4(session)) throw new TypeError("Invalid session store.");
8466
9453
  const expiry = extractSessionExpiry(session);
8467
9454
  if (expiry === null) return { present: true, expired: null, expiresAt: null };
8468
9455
  return {
@@ -8472,7 +9459,7 @@ function summarizeSession(session) {
8472
9459
  };
8473
9460
  }
8474
9461
  function storedDelegationExpiry(entry) {
8475
- if (!isRecord3(entry) || !isRecord3(entry.delegation) || !("expiry" in entry.delegation)) {
9462
+ if (!isRecord4(entry) || !isRecord4(entry.delegation) || !("expiry" in entry.delegation)) {
8476
9463
  throw new TypeError("Invalid stored delegation.");
8477
9464
  }
8478
9465
  return parseExpiry(entry.delegation.expiry);
@@ -8501,37 +9488,37 @@ function profileNotFound(profile) {
8501
9488
  )
8502
9489
  };
8503
9490
  }
8504
- function isRecord3(value) {
9491
+ function isRecord4(value) {
8505
9492
  return typeof value === "object" && value !== null && !Array.isArray(value);
8506
9493
  }
8507
- var import_zod6, StatusInputSchema, StatusOutputSchema, STATUS_POSTURES, STATUS_EXPOSURE, STATUS_SENSITIVITY, statusOperationDefinitions;
9494
+ var import_zod7, StatusInputSchema, StatusOutputSchema, STATUS_POSTURES, STATUS_EXPOSURE, STATUS_SENSITIVITY, statusOperationDefinitions;
8508
9495
  var init_status = __esm({
8509
9496
  "src/operations/status.ts"() {
8510
9497
  "use strict";
8511
- import_zod6 = require("zod");
9498
+ import_zod7 = require("zod");
8512
9499
  init_errors();
8513
9500
  init_state();
8514
- StatusInputSchema = import_zod6.z.object({}).strict();
8515
- StatusOutputSchema = import_zod6.z.object({
8516
- profile: import_zod6.z.string().min(1),
8517
- host: import_zod6.z.string().min(1),
8518
- posture: import_zod6.z.enum([
9501
+ StatusInputSchema = import_zod7.z.object({}).strict();
9502
+ StatusOutputSchema = import_zod7.z.object({
9503
+ profile: import_zod7.z.string().min(1),
9504
+ host: import_zod7.z.string().min(1),
9505
+ posture: import_zod7.z.enum([
8519
9506
  "owner-openkey",
8520
9507
  "delegate-session",
8521
9508
  "local-owner-key",
8522
9509
  "unauthenticated"
8523
9510
  ]),
8524
- operatorType: import_zod6.z.enum(["human", "agent"]).optional(),
8525
- principalDid: import_zod6.z.string().min(1).optional(),
8526
- sessionDid: import_zod6.z.string().min(1).optional(),
8527
- ownerDid: import_zod6.z.string().min(1).optional(),
8528
- space: import_zod6.z.string().min(1).optional(),
8529
- session: import_zod6.z.object({
8530
- present: import_zod6.z.boolean(),
8531
- expired: import_zod6.z.boolean().nullable(),
8532
- expiresAt: import_zod6.z.string().datetime({ offset: true }).nullable()
9511
+ operatorType: import_zod7.z.enum(["human", "agent"]).optional(),
9512
+ principalDid: import_zod7.z.string().min(1).optional(),
9513
+ sessionDid: import_zod7.z.string().min(1).optional(),
9514
+ ownerDid: import_zod7.z.string().min(1).optional(),
9515
+ space: import_zod7.z.string().min(1).optional(),
9516
+ session: import_zod7.z.object({
9517
+ present: import_zod7.z.boolean(),
9518
+ expired: import_zod7.z.boolean().nullable(),
9519
+ expiresAt: import_zod7.z.string().datetime({ offset: true }).nullable()
8533
9520
  }).strict(),
8534
- liveAdditionalDelegationCount: import_zod6.z.number().int().nonnegative()
9521
+ liveAdditionalDelegationCount: import_zod7.z.number().int().nonnegative()
8535
9522
  }).strict();
8536
9523
  STATUS_POSTURES = [
8537
9524
  "owner-openkey",
@@ -8572,6 +9559,7 @@ function registeredOperationDefinitions() {
8572
9559
  ...statusOperationDefinitions,
8573
9560
  ...authOperationDefinitions,
8574
9561
  ...explorationOperationDefinitions,
9562
+ ...sqlOperationDefinitions,
8575
9563
  ...secretsGetOperationDefinitions
8576
9564
  ]);
8577
9565
  return operationDefinitions;
@@ -8604,6 +9592,7 @@ var init_registry = __esm({
8604
9592
  init_auth();
8605
9593
  init_exploration();
8606
9594
  init_secrets_get();
9595
+ init_sql();
8607
9596
  init_status();
8608
9597
  }
8609
9598
  });
@@ -8683,9 +9672,9 @@ function isOperatorType(value) {
8683
9672
  return value === "human" || value === "agent";
8684
9673
  }
8685
9674
  function isStoredProfile(value) {
8686
- return isRecord4(value) && isNonEmptyString(value.name) && isNonEmptyString(value.host) && typeof value.chainId === "number" && Number.isFinite(value.chainId) && isNonEmptyString(value.spaceName) && isNonEmptyString(value.did) && isNonEmptyString(value.createdAt) && isOptionalNonEmptyString(value.sessionDid) && isOptionalNonEmptyString(value.ownerDid) && isOptionalNonEmptyString(value.spaceId) && isOptionalPosture(value.posture) && isOptionalOperatorType(value.operatorType) && isOptionalAuthMethod(value.authMethod) && isOptionalNonEmptyString(value.defaultSpace) && isOptionalNonEmptyString(value.privateKey) && isOptionalNonEmptyString(value.address) && isOptionalNonEmptyString(value.openkeyHost);
9675
+ return isRecord5(value) && isNonEmptyString(value.name) && isNonEmptyString(value.host) && typeof value.chainId === "number" && Number.isFinite(value.chainId) && isNonEmptyString(value.spaceName) && isNonEmptyString(value.did) && isNonEmptyString(value.createdAt) && isOptionalNonEmptyString(value.sessionDid) && isOptionalNonEmptyString(value.ownerDid) && isOptionalNonEmptyString(value.spaceId) && isOptionalPosture(value.posture) && isOptionalOperatorType(value.operatorType) && isOptionalAuthMethod(value.authMethod) && isOptionalNonEmptyString(value.defaultSpace) && isOptionalNonEmptyString(value.privateKey) && isOptionalNonEmptyString(value.address) && isOptionalNonEmptyString(value.openkeyHost);
8687
9676
  }
8688
- function isRecord4(value) {
9677
+ function isRecord5(value) {
8689
9678
  return typeof value === "object" && value !== null && !Array.isArray(value);
8690
9679
  }
8691
9680
  function isNonEmptyString(value) {
@@ -8849,7 +9838,7 @@ function spaceForAuthenticatedPrincipal(principal2) {
8849
9838
  function normalizeSession(session, key) {
8850
9839
  const header = session.delegationHeader;
8851
9840
  const jwk = hasPrivateParameter(session.jwk) ? session.jwk : key;
8852
- if (!isRecord5(header) || typeof header.Authorization !== "string" || typeof session.delegationCid !== "string" || typeof session.spaceId !== "string" || !hasPrivateParameter(jwk) || typeof session.verificationMethod !== "string") {
9841
+ if (!isRecord6(header) || typeof header.Authorization !== "string" || typeof session.delegationCid !== "string" || typeof session.spaceId !== "string" || !hasPrivateParameter(jwk) || typeof session.verificationMethod !== "string") {
8853
9842
  return void 0;
8854
9843
  }
8855
9844
  return {
@@ -8867,7 +9856,7 @@ function normalizeSession(session, key) {
8867
9856
  }
8868
9857
  function normalizeStoredDelegation(entry) {
8869
9858
  const raw = entry.delegation;
8870
- if (!isRecord5(raw) || !isRecord5(raw.delegationHeader)) return void 0;
9859
+ if (!isRecord6(raw) || !isRecord6(raw.delegationHeader)) return void 0;
8871
9860
  const expiry = parseExpiry2(raw.expiry);
8872
9861
  if (expiry === void 0 || typeof raw.cid !== "string" || typeof raw.spaceId !== "string" || typeof raw.path !== "string" || !Array.isArray(raw.actions) || !raw.actions.every((action) => typeof action === "string") || typeof raw.delegateDID !== "string" || typeof raw.ownerAddress !== "string" || typeof raw.chainId !== "number" || typeof raw.delegationHeader.Authorization !== "string") {
8873
9862
  return void 0;
@@ -8879,13 +9868,13 @@ function parseExpiry2(value) {
8879
9868
  return expiry !== void 0 && !Number.isNaN(expiry.getTime()) ? expiry : void 0;
8880
9869
  }
8881
9870
  function hasPrivateParameter(value) {
8882
- return isRecord5(value) && typeof value.d === "string" && value.d.length > 0;
9871
+ return isRecord6(value) && typeof value.d === "string" && value.d.length > 0;
8883
9872
  }
8884
9873
  function normalizeDid(value) {
8885
9874
  if (typeof value !== "string" || value.length === 0) return void 0;
8886
9875
  return value.split("#", 1)[0];
8887
9876
  }
8888
- function isRecord5(value) {
9877
+ function isRecord6(value) {
8889
9878
  return typeof value === "object" && value !== null && !Array.isArray(value);
8890
9879
  }
8891
9880
  function failed(context, error) {
@@ -9295,9 +10284,9 @@ async function invokeOperationWithLocalAuthorityRetry(operationId, operationVers
9295
10284
  )
9296
10285
  );
9297
10286
  }
9298
- const runtimeContext2 = prepared.runtimeResolution.context;
9299
- if (runtimeContext2.runtime === void 0) return internalOperationErrorResult(prepared);
9300
- const operationContext = runtimeContext2;
10287
+ const runtimeContext3 = prepared.runtimeResolution.context;
10288
+ if (runtimeContext3.runtime === void 0) return internalOperationErrorResult(prepared);
10289
+ const operationContext = runtimeContext3;
9301
10290
  let planned;
9302
10291
  try {
9303
10292
  planned = exactCapabilities2(await prepared.definition.authority(
@@ -9502,14 +10491,14 @@ async function prepareInvocation(operationId, operationVersion, invocationTarget
9502
10491
  }
9503
10492
  async function executePreparedInvocation(prepared, options = {}) {
9504
10493
  const { operation, definition, parsedInput, runtimeResolution } = prepared;
9505
- const runtimeContext2 = runtimeResolution.context.runtime === void 0 ? void 0 : runtimeResolution.context;
9506
- const resolveSpace2 = runtimeContext2 === void 0 ? void 0 : operationSpaceResolver(
9507
- runtimeContext2.runtime.node,
9508
- runtimeContext2.summary.space
10494
+ const runtimeContext3 = runtimeResolution.context.runtime === void 0 ? void 0 : runtimeResolution.context;
10495
+ const resolveSpace2 = runtimeContext3 === void 0 ? void 0 : operationSpaceResolver(
10496
+ runtimeContext3.runtime.node,
10497
+ runtimeContext3.summary.space
9509
10498
  );
9510
10499
  try {
9511
10500
  const planned = await definition.authority(
9512
- runtimeContext2 ?? runtimeResolution.context,
10501
+ runtimeContext3 ?? runtimeResolution.context,
9513
10502
  parsedInput.data
9514
10503
  );
9515
10504
  const required = exactCapabilities2(planned);
@@ -9524,12 +10513,12 @@ async function executePreparedInvocation(prepared, options = {}) {
9524
10513
  );
9525
10514
  }
9526
10515
  const evaluation = evaluateOperationAuthority(
9527
- runtimeContext2?.runtime.granted ?? [],
10516
+ runtimeContext3?.runtime.granted ?? [],
9528
10517
  required,
9529
10518
  resolveSpace2
9530
10519
  );
9531
10520
  if (!evaluation.satisfied) {
9532
- if (runtimeContext2 === void 0) {
10521
+ if (runtimeContext3 === void 0) {
9533
10522
  return errorResult(
9534
10523
  operation,
9535
10524
  runtimeResolution.context.summary,
@@ -9539,13 +10528,13 @@ async function executePreparedInvocation(prepared, options = {}) {
9539
10528
  if (options.deferAuthorityRequest) {
9540
10529
  try {
9541
10530
  const request = buildPermissionRequestArtifact({
9542
- profile: runtimeContext2.summary.profile,
9543
- host: runtimeContext2.summary.host,
9544
- sessionDid: runtimeContext2.summary.sessionDid,
9545
- posture: runtimeContext2.summary.posture,
9546
- operatorType: runtimeContext2.summary.operatorType ?? "human",
9547
- ...runtimeContext2.summary.ownerDid === void 0 ? {} : { ownerDid: runtimeContext2.summary.ownerDid },
9548
- ...runtimeContext2.summary.space === void 0 ? {} : { spaceId: runtimeContext2.summary.space },
10531
+ profile: runtimeContext3.summary.profile,
10532
+ host: runtimeContext3.summary.host,
10533
+ sessionDid: runtimeContext3.summary.sessionDid,
10534
+ posture: runtimeContext3.summary.posture,
10535
+ operatorType: runtimeContext3.summary.operatorType ?? "human",
10536
+ ...runtimeContext3.summary.ownerDid === void 0 ? {} : { ownerDid: runtimeContext3.summary.ownerDid },
10537
+ ...runtimeContext3.summary.space === void 0 ? {} : { spaceId: runtimeContext3.summary.space },
9549
10538
  missing: evaluation.missing
9550
10539
  });
9551
10540
  return authorityRequiredResult(
@@ -9554,7 +10543,7 @@ async function executePreparedInvocation(prepared, options = {}) {
9554
10543
  parsedInput.data,
9555
10544
  request,
9556
10545
  evaluation.missing,
9557
- runtimeContext2.runtime.node
10546
+ runtimeContext3.runtime.node
9558
10547
  );
9559
10548
  } catch {
9560
10549
  return errorResult(
@@ -9565,7 +10554,7 @@ async function executePreparedInvocation(prepared, options = {}) {
9565
10554
  }
9566
10555
  }
9567
10556
  const authority = await persistAuthorityRequest(
9568
- runtimeContext2,
10557
+ runtimeContext3,
9569
10558
  evaluation.missing
9570
10559
  );
9571
10560
  if (authority.status === "error") {
@@ -9581,7 +10570,7 @@ async function executePreparedInvocation(prepared, options = {}) {
9581
10570
  parsedInput.data,
9582
10571
  authority.request,
9583
10572
  authority.missing,
9584
- runtimeContext2.runtime.node
10573
+ runtimeContext3.runtime.node
9585
10574
  );
9586
10575
  }
9587
10576
  const outcome = await definition.execute(
@@ -9624,7 +10613,7 @@ async function executePreparedInvocation(prepared, options = {}) {
9624
10613
  )
9625
10614
  );
9626
10615
  }
9627
- if (runtimeContext2 === void 0) {
10616
+ if (runtimeContext3 === void 0) {
9628
10617
  return errorResult(
9629
10618
  operation,
9630
10619
  runtimeResolution.context.summary,
@@ -9634,13 +10623,13 @@ async function executePreparedInvocation(prepared, options = {}) {
9634
10623
  if (options.deferAuthorityRequest) {
9635
10624
  try {
9636
10625
  const request = buildPermissionRequestArtifact({
9637
- profile: runtimeContext2.summary.profile,
9638
- host: runtimeContext2.summary.host,
9639
- sessionDid: runtimeContext2.summary.sessionDid,
9640
- posture: runtimeContext2.summary.posture,
9641
- operatorType: runtimeContext2.summary.operatorType ?? "human",
9642
- ...runtimeContext2.summary.ownerDid === void 0 ? {} : { ownerDid: runtimeContext2.summary.ownerDid },
9643
- ...runtimeContext2.summary.space === void 0 ? {} : { spaceId: runtimeContext2.summary.space },
10626
+ profile: runtimeContext3.summary.profile,
10627
+ host: runtimeContext3.summary.host,
10628
+ sessionDid: runtimeContext3.summary.sessionDid,
10629
+ posture: runtimeContext3.summary.posture,
10630
+ operatorType: runtimeContext3.summary.operatorType ?? "human",
10631
+ ...runtimeContext3.summary.ownerDid === void 0 ? {} : { ownerDid: runtimeContext3.summary.ownerDid },
10632
+ ...runtimeContext3.summary.space === void 0 ? {} : { spaceId: runtimeContext3.summary.space },
9644
10633
  missing: hinted
9645
10634
  });
9646
10635
  return authorityRequiredResult(
@@ -9649,7 +10638,7 @@ async function executePreparedInvocation(prepared, options = {}) {
9649
10638
  parsedInput.data,
9650
10639
  request,
9651
10640
  hinted,
9652
- runtimeContext2.runtime.node,
10641
+ runtimeContext3.runtime.node,
9653
10642
  outcome.requiresCallerInput ?? false
9654
10643
  );
9655
10644
  } catch {
@@ -9661,7 +10650,7 @@ async function executePreparedInvocation(prepared, options = {}) {
9661
10650
  }
9662
10651
  }
9663
10652
  const authority = await persistAuthorityRequest(
9664
- runtimeContext2,
10653
+ runtimeContext3,
9665
10654
  hinted,
9666
10655
  true
9667
10656
  );
@@ -9678,7 +10667,7 @@ async function executePreparedInvocation(prepared, options = {}) {
9678
10667
  parsedInput.data,
9679
10668
  authority.request,
9680
10669
  authority.missing,
9681
- runtimeContext2.runtime.node,
10670
+ runtimeContext3.runtime.node,
9682
10671
  outcome.requiresCallerInput ?? false
9683
10672
  );
9684
10673
  }