@tinycloud/operations 0.3.2-beta.1 → 0.3.2-beta.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/coverage.json +7 -3
- package/dist/artifacts.cjs +155 -51
- package/dist/artifacts.cjs.map +1 -1
- package/dist/artifacts.js +155 -51
- package/dist/artifacts.js.map +1 -1
- package/dist/cli-runtime.cjs +156 -50
- package/dist/cli-runtime.cjs.map +1 -1
- package/dist/cli-runtime.js +156 -50
- package/dist/cli-runtime.js.map +1 -1
- package/dist/index.cjs +156 -50
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +156 -50
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/artifacts.js
CHANGED
|
@@ -164,10 +164,10 @@ var require_decrypt_transport_response_error = __commonJS({
|
|
|
164
164
|
var __toCommonJS = (mod) => __copyProps2(__defProp2({}, "__esModule", { value: true }), mod);
|
|
165
165
|
var DecryptTransportResponseError_exports = {};
|
|
166
166
|
__export(DecryptTransportResponseError_exports, {
|
|
167
|
-
DecryptTransportResponseError: () =>
|
|
167
|
+
DecryptTransportResponseError: () => DecryptTransportResponseError2
|
|
168
168
|
});
|
|
169
169
|
module.exports = __toCommonJS(DecryptTransportResponseError_exports);
|
|
170
|
-
var
|
|
170
|
+
var DecryptTransportResponseError2 = class extends Error {
|
|
171
171
|
constructor(status, permissionHint) {
|
|
172
172
|
super("Node decrypt request failed");
|
|
173
173
|
this.status = status;
|
|
@@ -185,9 +185,6 @@ import { z as z2 } from "zod";
|
|
|
185
185
|
// ../sdk-core/src/manifest.ts
|
|
186
186
|
var import_ms = __toESM(require_ms(), 1);
|
|
187
187
|
|
|
188
|
-
// ../sdk-services/dist/index.js
|
|
189
|
-
import { z } from "zod";
|
|
190
|
-
|
|
191
188
|
// ../bootstrap/dist/index.js
|
|
192
189
|
var CAPABILITIES = [
|
|
193
190
|
{ urn: "tinycloud.kv/get", service: "tinycloud.kv", status: "active" },
|
|
@@ -596,28 +593,6 @@ function withCapabilitiesReadForSpaces(resources) {
|
|
|
596
593
|
}))
|
|
597
594
|
]);
|
|
598
595
|
}
|
|
599
|
-
function accountRegistryPermissions() {
|
|
600
|
-
return [
|
|
601
|
-
{
|
|
602
|
-
service: "tinycloud.kv",
|
|
603
|
-
space: ACCOUNT_REGISTRY_SPACE,
|
|
604
|
-
path: ACCOUNT_REGISTRY_PATH,
|
|
605
|
-
actions: [KV.GET, KV.PUT, KV.LIST]
|
|
606
|
-
},
|
|
607
|
-
{
|
|
608
|
-
service: "tinycloud.kv",
|
|
609
|
-
space: ACCOUNT_REGISTRY_SPACE,
|
|
610
|
-
path: "spaces/",
|
|
611
|
-
actions: [KV.GET, KV.PUT, KV.LIST]
|
|
612
|
-
},
|
|
613
|
-
{
|
|
614
|
-
service: "tinycloud.sql",
|
|
615
|
-
space: ACCOUNT_REGISTRY_SPACE,
|
|
616
|
-
path: "account",
|
|
617
|
-
actions: [SQL.READ, SQL.WRITE, SQL.SCHEMA]
|
|
618
|
-
}
|
|
619
|
-
];
|
|
620
|
-
}
|
|
621
596
|
function composeManifestRequest(inputs, options = {}) {
|
|
622
597
|
if (!Array.isArray(inputs) || inputs.length === 0) {
|
|
623
598
|
throw new Error("composeManifestRequest requires at least one manifest");
|
|
@@ -631,7 +606,12 @@ function composeManifestRequest(inputs, options = {}) {
|
|
|
631
606
|
return explicit.flatMap((entry) => expandPermissionEntry(entry, prefix, space));
|
|
632
607
|
});
|
|
633
608
|
if (includeAccountRegistryPermissions) {
|
|
634
|
-
resources.push(
|
|
609
|
+
resources.push(
|
|
610
|
+
...ACCOUNT_MANIFEST_PERMISSIONS.map((resource) => ({
|
|
611
|
+
...resource,
|
|
612
|
+
actions: [...resource.actions]
|
|
613
|
+
}))
|
|
614
|
+
);
|
|
635
615
|
}
|
|
636
616
|
const manifestsByAppId = /* @__PURE__ */ new Map();
|
|
637
617
|
for (const manifest of manifests) {
|
|
@@ -659,11 +639,60 @@ function composeBootstrapSpaceManifest(space) {
|
|
|
659
639
|
includeAccountRegistryPermissions: false
|
|
660
640
|
});
|
|
661
641
|
}
|
|
642
|
+
var ACCOUNT_MANIFEST_PERMISSIONS = Object.freeze([
|
|
643
|
+
{
|
|
644
|
+
service: "tinycloud.kv",
|
|
645
|
+
space: ACCOUNT_REGISTRY_SPACE,
|
|
646
|
+
path: ACCOUNT_REGISTRY_PATH,
|
|
647
|
+
actions: [KV.GET, KV.PUT, KV.LIST]
|
|
648
|
+
},
|
|
649
|
+
{
|
|
650
|
+
service: "tinycloud.kv",
|
|
651
|
+
space: ACCOUNT_REGISTRY_SPACE,
|
|
652
|
+
path: "spaces/",
|
|
653
|
+
actions: [KV.GET, KV.PUT, KV.LIST]
|
|
654
|
+
},
|
|
655
|
+
{
|
|
656
|
+
service: "tinycloud.kv",
|
|
657
|
+
space: ACCOUNT_REGISTRY_SPACE,
|
|
658
|
+
path: "system/bootstrap/complete",
|
|
659
|
+
actions: [KV.GET, KV.PUT]
|
|
660
|
+
},
|
|
661
|
+
{
|
|
662
|
+
service: "tinycloud.delegation",
|
|
663
|
+
space: ACCOUNT_REGISTRY_SPACE,
|
|
664
|
+
path: "",
|
|
665
|
+
actions: ["tinycloud.delegation/list"]
|
|
666
|
+
},
|
|
667
|
+
{
|
|
668
|
+
service: "tinycloud.sql",
|
|
669
|
+
space: ACCOUNT_REGISTRY_SPACE,
|
|
670
|
+
path: "account",
|
|
671
|
+
actions: [SQL.READ, SQL.WRITE, SQL.SCHEMA]
|
|
672
|
+
},
|
|
673
|
+
{
|
|
674
|
+
service: "tinycloud.capabilities",
|
|
675
|
+
space: ACCOUNT_REGISTRY_SPACE,
|
|
676
|
+
path: "",
|
|
677
|
+
actions: [CAPABILITIES2.READ]
|
|
678
|
+
}
|
|
679
|
+
]);
|
|
680
|
+
var BOOTSTRAP_DEFAULT_ONLY_SESSION_REQUEST = composeBootstrapSpaceManifest(BOOTSTRAP_DEFAULT_SPACE);
|
|
681
|
+
var BOOTSTRAP_WIDENED_DEFAULT_SESSION_REQUEST = {
|
|
682
|
+
...BOOTSTRAP_DEFAULT_ONLY_SESSION_REQUEST,
|
|
683
|
+
resources: [
|
|
684
|
+
...BOOTSTRAP_DEFAULT_ONLY_SESSION_REQUEST.resources,
|
|
685
|
+
...ACCOUNT_MANIFEST_PERMISSIONS.map((resource) => ({
|
|
686
|
+
...resource,
|
|
687
|
+
actions: [...resource.actions]
|
|
688
|
+
}))
|
|
689
|
+
]
|
|
690
|
+
};
|
|
662
691
|
var BOOTSTRAP_SESSION_REQUESTS = Object.freeze(
|
|
663
692
|
Object.fromEntries(
|
|
664
693
|
BOOTSTRAP_SPACE_NAMES.map((space) => [
|
|
665
694
|
space,
|
|
666
|
-
composeBootstrapSpaceManifest(space)
|
|
695
|
+
space === BOOTSTRAP_DEFAULT_SPACE ? BOOTSTRAP_WIDENED_DEFAULT_SESSION_REQUEST : composeBootstrapSpaceManifest(space)
|
|
667
696
|
])
|
|
668
697
|
)
|
|
669
698
|
);
|
|
@@ -694,9 +723,8 @@ var BOOTSTRAP_ALLOWLIST = Object.freeze(
|
|
|
694
723
|
);
|
|
695
724
|
|
|
696
725
|
// ../sdk-services/dist/index.js
|
|
726
|
+
import { z } from "zod";
|
|
697
727
|
var import_decrypt_transport_response_error = __toESM(require_decrypt_transport_response_error(), 1);
|
|
698
|
-
var import_decrypt_transport_response_error2 = __toESM(require_decrypt_transport_response_error(), 1);
|
|
699
|
-
var import_decrypt_transport_response_error3 = __toESM(require_decrypt_transport_response_error(), 1);
|
|
700
728
|
var ErrorCodes = {
|
|
701
729
|
// Common errors
|
|
702
730
|
NOT_FOUND: "NOT_FOUND",
|
|
@@ -2237,6 +2265,7 @@ var KVService = class extends BaseService {
|
|
|
2237
2265
|
}
|
|
2238
2266
|
seen.add(path);
|
|
2239
2267
|
}
|
|
2268
|
+
let requestMayHaveDispatched = false;
|
|
2240
2269
|
try {
|
|
2241
2270
|
const body = new FormData();
|
|
2242
2271
|
for (let index = 0; index < items.length; index++) {
|
|
@@ -2254,14 +2283,31 @@ var KVService = class extends BaseService {
|
|
|
2254
2283
|
action: KVAction.PUT
|
|
2255
2284
|
}))
|
|
2256
2285
|
);
|
|
2257
|
-
const
|
|
2286
|
+
const url = `${this.host}/invoke`;
|
|
2287
|
+
const init = {
|
|
2258
2288
|
method: "POST",
|
|
2259
2289
|
headers,
|
|
2260
2290
|
body,
|
|
2261
2291
|
signal: this.combineSignals(options?.signal)
|
|
2262
|
-
}
|
|
2292
|
+
};
|
|
2293
|
+
const fetchFn = this.context.fetch;
|
|
2294
|
+
requestMayHaveDispatched = true;
|
|
2295
|
+
const response = await fetchFn(url, init);
|
|
2263
2296
|
if (!response.ok) {
|
|
2264
|
-
|
|
2297
|
+
let errorText;
|
|
2298
|
+
try {
|
|
2299
|
+
errorText = await response.text();
|
|
2300
|
+
} catch (textError) {
|
|
2301
|
+
const cause = textError instanceof Error ? textError : new Error(String(textError));
|
|
2302
|
+
return err(
|
|
2303
|
+
serviceError(
|
|
2304
|
+
ErrorCodes.KV_WRITE_FAILED,
|
|
2305
|
+
`Failed to batch put ${items.length} key(s): ${response.status} - <response body could not be read: ${cause.message}>`,
|
|
2306
|
+
"kv",
|
|
2307
|
+
{ cause, meta: { status: response.status, statusText: response.statusText } }
|
|
2308
|
+
)
|
|
2309
|
+
);
|
|
2310
|
+
}
|
|
2265
2311
|
if (response.status === 401 || response.status === 403) {
|
|
2266
2312
|
const { resource, action } = parseAuthError(errorText);
|
|
2267
2313
|
return err(authUnauthorizedError("kv", errorText, {
|
|
@@ -2287,19 +2333,73 @@ var KVService = class extends BaseService {
|
|
|
2287
2333
|
)
|
|
2288
2334
|
);
|
|
2289
2335
|
}
|
|
2290
|
-
|
|
2291
|
-
|
|
2336
|
+
let rawBody;
|
|
2337
|
+
try {
|
|
2338
|
+
rawBody = await response.json();
|
|
2339
|
+
} catch (jsonError) {
|
|
2340
|
+
const cause = jsonError instanceof Error ? jsonError : new Error(String(jsonError));
|
|
2341
|
+
return err(
|
|
2342
|
+
serviceError(
|
|
2343
|
+
ErrorCodes.NETWORK_ERROR,
|
|
2344
|
+
`KV batchPut response was not valid JSON: ${cause.message}`,
|
|
2345
|
+
"kv",
|
|
2346
|
+
{
|
|
2347
|
+
cause,
|
|
2348
|
+
meta: {
|
|
2349
|
+
requestMayHaveDispatched: true,
|
|
2350
|
+
responseReceived: true,
|
|
2351
|
+
status: response.status,
|
|
2352
|
+
outcome: "batch-unconfirmed"
|
|
2353
|
+
}
|
|
2354
|
+
}
|
|
2355
|
+
)
|
|
2356
|
+
);
|
|
2357
|
+
}
|
|
2358
|
+
const batchResponse = this.normalizeBatchPutResponse(rawBody);
|
|
2359
|
+
if (!batchResponse) {
|
|
2292
2360
|
return err(
|
|
2293
2361
|
serviceError(
|
|
2294
2362
|
ErrorCodes.NETWORK_ERROR,
|
|
2295
2363
|
"KV batchPut response did not include matching written keys and count",
|
|
2296
|
-
"kv"
|
|
2364
|
+
"kv",
|
|
2365
|
+
{
|
|
2366
|
+
meta: {
|
|
2367
|
+
requestMayHaveDispatched: true,
|
|
2368
|
+
responseReceived: true,
|
|
2369
|
+
status: response.status,
|
|
2370
|
+
outcome: "batch-unconfirmed"
|
|
2371
|
+
}
|
|
2372
|
+
}
|
|
2373
|
+
)
|
|
2374
|
+
);
|
|
2375
|
+
}
|
|
2376
|
+
const requestedPaths = new Set(paths);
|
|
2377
|
+
const writtenPaths = new Set(batchResponse.written);
|
|
2378
|
+
const matchesRequest = batchResponse.count === paths.length && batchResponse.written.length === paths.length && writtenPaths.size === paths.length && batchResponse.written.every((key) => requestedPaths.has(key));
|
|
2379
|
+
if (!matchesRequest) {
|
|
2380
|
+
return err(
|
|
2381
|
+
serviceError(
|
|
2382
|
+
ErrorCodes.NETWORK_ERROR,
|
|
2383
|
+
`KV batchPut response did not confirm all ${paths.length} requested key(s) were written`,
|
|
2384
|
+
"kv",
|
|
2385
|
+
{
|
|
2386
|
+
meta: {
|
|
2387
|
+
requestMayHaveDispatched: true,
|
|
2388
|
+
responseReceived: true,
|
|
2389
|
+
status: response.status,
|
|
2390
|
+
outcome: "batch-unconfirmed"
|
|
2391
|
+
}
|
|
2392
|
+
}
|
|
2297
2393
|
)
|
|
2298
2394
|
);
|
|
2299
2395
|
}
|
|
2300
2396
|
return ok(batchResponse);
|
|
2301
2397
|
} catch (error) {
|
|
2302
|
-
|
|
2398
|
+
const wrapped = wrapError("kv", error);
|
|
2399
|
+
return err({
|
|
2400
|
+
...wrapped,
|
|
2401
|
+
meta: { ...wrapped.meta, requestMayHaveDispatched }
|
|
2402
|
+
});
|
|
2303
2403
|
}
|
|
2304
2404
|
});
|
|
2305
2405
|
}
|
|
@@ -6637,15 +6737,28 @@ function normalizeSpace(space) {
|
|
|
6637
6737
|
function isCapabilitySubset(requested, granted) {
|
|
6638
6738
|
const missing = [];
|
|
6639
6739
|
for (const req of requested) {
|
|
6640
|
-
const
|
|
6641
|
-
|
|
6740
|
+
const matchingScope = granted.filter(
|
|
6741
|
+
(entry) => canonicalizeEntryScopeMatches(req, entry)
|
|
6742
|
+
);
|
|
6743
|
+
const requestedActions = expandActionShortNames(
|
|
6744
|
+
req.service,
|
|
6745
|
+
req.actions
|
|
6746
|
+
);
|
|
6747
|
+
const grantedActions = matchingScope.flatMap(
|
|
6748
|
+
(entry) => expandActionShortNames(entry.service, entry.actions)
|
|
6749
|
+
);
|
|
6750
|
+
const covered = requestedActions.every(
|
|
6751
|
+
(requestedAction) => grantedActions.some(
|
|
6752
|
+
(grantedAction) => actionContains(grantedAction, requestedAction)
|
|
6753
|
+
)
|
|
6754
|
+
);
|
|
6755
|
+
if (!covered) {
|
|
6642
6756
|
missing.push(cloneEntry(req));
|
|
6643
|
-
continue;
|
|
6644
6757
|
}
|
|
6645
6758
|
}
|
|
6646
6759
|
return { subset: missing.length === 0, missing };
|
|
6647
6760
|
}
|
|
6648
|
-
function
|
|
6761
|
+
function canonicalizeEntryScopeMatches(requested, granted) {
|
|
6649
6762
|
if (requested.service !== granted.service) {
|
|
6650
6763
|
return false;
|
|
6651
6764
|
}
|
|
@@ -6655,15 +6768,6 @@ function canonicalizeEntryMatches(requested, granted) {
|
|
|
6655
6768
|
if (!pathContains(granted.path, requested.path)) {
|
|
6656
6769
|
return false;
|
|
6657
6770
|
}
|
|
6658
|
-
const reqActions = new Set(
|
|
6659
|
-
expandActionShortNames(requested.service, requested.actions)
|
|
6660
|
-
);
|
|
6661
|
-
const grantedActions = expandActionShortNames(granted.service, granted.actions);
|
|
6662
|
-
for (const a of reqActions) {
|
|
6663
|
-
if (!grantedActions.some((grantedAction) => actionContains(grantedAction, a))) {
|
|
6664
|
-
return false;
|
|
6665
|
-
}
|
|
6666
|
-
}
|
|
6667
6771
|
if (!recapCaveatsEqual(requested.caveats, granted.caveats)) {
|
|
6668
6772
|
return false;
|
|
6669
6773
|
}
|