@tinycloud/operations 0.3.2-beta.0 → 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/coverage.json
CHANGED
|
@@ -44,10 +44,14 @@
|
|
|
44
44
|
{ "command": "delegation info <cid>", "status": "legacy" },
|
|
45
45
|
{ "command": "delegation revoke <cid>", "status": "legacy" },
|
|
46
46
|
{ "command": "share", "status": "legacy" },
|
|
47
|
-
{ "command": "share
|
|
48
|
-
{ "command": "share
|
|
47
|
+
{ "command": "share inspect [url]", "status": "legacy" },
|
|
48
|
+
{ "command": "share migrate [url]", "status": "legacy" },
|
|
49
|
+
{ "command": "share notify <id>", "status": "legacy" },
|
|
50
|
+
{ "command": "share publish <files>", "status": "legacy" },
|
|
51
|
+
{ "command": "share receive [url]", "status": "legacy" },
|
|
49
52
|
{ "command": "share list", "status": "legacy" },
|
|
50
|
-
{ "command": "share revoke <
|
|
53
|
+
{ "command": "share revoke <id>", "status": "legacy" },
|
|
54
|
+
{ "command": "share show <id>", "status": "legacy" },
|
|
51
55
|
{ "command": "node", "status": "legacy" },
|
|
52
56
|
{ "command": "node health", "status": "legacy" },
|
|
53
57
|
{ "command": "node version", "status": "legacy" },
|
package/dist/artifacts.cjs
CHANGED
|
@@ -170,10 +170,10 @@ var require_decrypt_transport_response_error = __commonJS({
|
|
|
170
170
|
var __toCommonJS2 = (mod) => __copyProps2(__defProp2({}, "__esModule", { value: true }), mod);
|
|
171
171
|
var DecryptTransportResponseError_exports = {};
|
|
172
172
|
__export2(DecryptTransportResponseError_exports, {
|
|
173
|
-
DecryptTransportResponseError: () =>
|
|
173
|
+
DecryptTransportResponseError: () => DecryptTransportResponseError2
|
|
174
174
|
});
|
|
175
175
|
module2.exports = __toCommonJS2(DecryptTransportResponseError_exports);
|
|
176
|
-
var
|
|
176
|
+
var DecryptTransportResponseError2 = class extends Error {
|
|
177
177
|
constructor(status, permissionHint) {
|
|
178
178
|
super("Node decrypt request failed");
|
|
179
179
|
this.status = status;
|
|
@@ -209,9 +209,6 @@ var import_zod2 = require("zod");
|
|
|
209
209
|
// ../sdk-core/src/manifest.ts
|
|
210
210
|
var import_ms = __toESM(require_ms(), 1);
|
|
211
211
|
|
|
212
|
-
// ../sdk-services/dist/index.js
|
|
213
|
-
var import_zod = require("zod");
|
|
214
|
-
|
|
215
212
|
// ../bootstrap/dist/index.js
|
|
216
213
|
var CAPABILITIES = [
|
|
217
214
|
{ urn: "tinycloud.kv/get", service: "tinycloud.kv", status: "active" },
|
|
@@ -620,28 +617,6 @@ function withCapabilitiesReadForSpaces(resources) {
|
|
|
620
617
|
}))
|
|
621
618
|
]);
|
|
622
619
|
}
|
|
623
|
-
function accountRegistryPermissions() {
|
|
624
|
-
return [
|
|
625
|
-
{
|
|
626
|
-
service: "tinycloud.kv",
|
|
627
|
-
space: ACCOUNT_REGISTRY_SPACE,
|
|
628
|
-
path: ACCOUNT_REGISTRY_PATH,
|
|
629
|
-
actions: [KV.GET, KV.PUT, KV.LIST]
|
|
630
|
-
},
|
|
631
|
-
{
|
|
632
|
-
service: "tinycloud.kv",
|
|
633
|
-
space: ACCOUNT_REGISTRY_SPACE,
|
|
634
|
-
path: "spaces/",
|
|
635
|
-
actions: [KV.GET, KV.PUT, KV.LIST]
|
|
636
|
-
},
|
|
637
|
-
{
|
|
638
|
-
service: "tinycloud.sql",
|
|
639
|
-
space: ACCOUNT_REGISTRY_SPACE,
|
|
640
|
-
path: "account",
|
|
641
|
-
actions: [SQL.READ, SQL.WRITE, SQL.SCHEMA]
|
|
642
|
-
}
|
|
643
|
-
];
|
|
644
|
-
}
|
|
645
620
|
function composeManifestRequest(inputs, options = {}) {
|
|
646
621
|
if (!Array.isArray(inputs) || inputs.length === 0) {
|
|
647
622
|
throw new Error("composeManifestRequest requires at least one manifest");
|
|
@@ -655,7 +630,12 @@ function composeManifestRequest(inputs, options = {}) {
|
|
|
655
630
|
return explicit.flatMap((entry) => expandPermissionEntry(entry, prefix, space));
|
|
656
631
|
});
|
|
657
632
|
if (includeAccountRegistryPermissions) {
|
|
658
|
-
resources.push(
|
|
633
|
+
resources.push(
|
|
634
|
+
...ACCOUNT_MANIFEST_PERMISSIONS.map((resource) => ({
|
|
635
|
+
...resource,
|
|
636
|
+
actions: [...resource.actions]
|
|
637
|
+
}))
|
|
638
|
+
);
|
|
659
639
|
}
|
|
660
640
|
const manifestsByAppId = /* @__PURE__ */ new Map();
|
|
661
641
|
for (const manifest of manifests) {
|
|
@@ -683,11 +663,60 @@ function composeBootstrapSpaceManifest(space) {
|
|
|
683
663
|
includeAccountRegistryPermissions: false
|
|
684
664
|
});
|
|
685
665
|
}
|
|
666
|
+
var ACCOUNT_MANIFEST_PERMISSIONS = Object.freeze([
|
|
667
|
+
{
|
|
668
|
+
service: "tinycloud.kv",
|
|
669
|
+
space: ACCOUNT_REGISTRY_SPACE,
|
|
670
|
+
path: ACCOUNT_REGISTRY_PATH,
|
|
671
|
+
actions: [KV.GET, KV.PUT, KV.LIST]
|
|
672
|
+
},
|
|
673
|
+
{
|
|
674
|
+
service: "tinycloud.kv",
|
|
675
|
+
space: ACCOUNT_REGISTRY_SPACE,
|
|
676
|
+
path: "spaces/",
|
|
677
|
+
actions: [KV.GET, KV.PUT, KV.LIST]
|
|
678
|
+
},
|
|
679
|
+
{
|
|
680
|
+
service: "tinycloud.kv",
|
|
681
|
+
space: ACCOUNT_REGISTRY_SPACE,
|
|
682
|
+
path: "system/bootstrap/complete",
|
|
683
|
+
actions: [KV.GET, KV.PUT]
|
|
684
|
+
},
|
|
685
|
+
{
|
|
686
|
+
service: "tinycloud.delegation",
|
|
687
|
+
space: ACCOUNT_REGISTRY_SPACE,
|
|
688
|
+
path: "",
|
|
689
|
+
actions: ["tinycloud.delegation/list"]
|
|
690
|
+
},
|
|
691
|
+
{
|
|
692
|
+
service: "tinycloud.sql",
|
|
693
|
+
space: ACCOUNT_REGISTRY_SPACE,
|
|
694
|
+
path: "account",
|
|
695
|
+
actions: [SQL.READ, SQL.WRITE, SQL.SCHEMA]
|
|
696
|
+
},
|
|
697
|
+
{
|
|
698
|
+
service: "tinycloud.capabilities",
|
|
699
|
+
space: ACCOUNT_REGISTRY_SPACE,
|
|
700
|
+
path: "",
|
|
701
|
+
actions: [CAPABILITIES2.READ]
|
|
702
|
+
}
|
|
703
|
+
]);
|
|
704
|
+
var BOOTSTRAP_DEFAULT_ONLY_SESSION_REQUEST = composeBootstrapSpaceManifest(BOOTSTRAP_DEFAULT_SPACE);
|
|
705
|
+
var BOOTSTRAP_WIDENED_DEFAULT_SESSION_REQUEST = {
|
|
706
|
+
...BOOTSTRAP_DEFAULT_ONLY_SESSION_REQUEST,
|
|
707
|
+
resources: [
|
|
708
|
+
...BOOTSTRAP_DEFAULT_ONLY_SESSION_REQUEST.resources,
|
|
709
|
+
...ACCOUNT_MANIFEST_PERMISSIONS.map((resource) => ({
|
|
710
|
+
...resource,
|
|
711
|
+
actions: [...resource.actions]
|
|
712
|
+
}))
|
|
713
|
+
]
|
|
714
|
+
};
|
|
686
715
|
var BOOTSTRAP_SESSION_REQUESTS = Object.freeze(
|
|
687
716
|
Object.fromEntries(
|
|
688
717
|
BOOTSTRAP_SPACE_NAMES.map((space) => [
|
|
689
718
|
space,
|
|
690
|
-
composeBootstrapSpaceManifest(space)
|
|
719
|
+
space === BOOTSTRAP_DEFAULT_SPACE ? BOOTSTRAP_WIDENED_DEFAULT_SESSION_REQUEST : composeBootstrapSpaceManifest(space)
|
|
691
720
|
])
|
|
692
721
|
)
|
|
693
722
|
);
|
|
@@ -718,9 +747,8 @@ var BOOTSTRAP_ALLOWLIST = Object.freeze(
|
|
|
718
747
|
);
|
|
719
748
|
|
|
720
749
|
// ../sdk-services/dist/index.js
|
|
750
|
+
var import_zod = require("zod");
|
|
721
751
|
var import_decrypt_transport_response_error = __toESM(require_decrypt_transport_response_error(), 1);
|
|
722
|
-
var import_decrypt_transport_response_error2 = __toESM(require_decrypt_transport_response_error(), 1);
|
|
723
|
-
var import_decrypt_transport_response_error3 = __toESM(require_decrypt_transport_response_error(), 1);
|
|
724
752
|
var ErrorCodes = {
|
|
725
753
|
// Common errors
|
|
726
754
|
NOT_FOUND: "NOT_FOUND",
|
|
@@ -2261,6 +2289,7 @@ var KVService = class extends BaseService {
|
|
|
2261
2289
|
}
|
|
2262
2290
|
seen.add(path);
|
|
2263
2291
|
}
|
|
2292
|
+
let requestMayHaveDispatched = false;
|
|
2264
2293
|
try {
|
|
2265
2294
|
const body = new FormData();
|
|
2266
2295
|
for (let index = 0; index < items.length; index++) {
|
|
@@ -2278,14 +2307,31 @@ var KVService = class extends BaseService {
|
|
|
2278
2307
|
action: KVAction.PUT
|
|
2279
2308
|
}))
|
|
2280
2309
|
);
|
|
2281
|
-
const
|
|
2310
|
+
const url = `${this.host}/invoke`;
|
|
2311
|
+
const init = {
|
|
2282
2312
|
method: "POST",
|
|
2283
2313
|
headers,
|
|
2284
2314
|
body,
|
|
2285
2315
|
signal: this.combineSignals(options?.signal)
|
|
2286
|
-
}
|
|
2316
|
+
};
|
|
2317
|
+
const fetchFn = this.context.fetch;
|
|
2318
|
+
requestMayHaveDispatched = true;
|
|
2319
|
+
const response = await fetchFn(url, init);
|
|
2287
2320
|
if (!response.ok) {
|
|
2288
|
-
|
|
2321
|
+
let errorText;
|
|
2322
|
+
try {
|
|
2323
|
+
errorText = await response.text();
|
|
2324
|
+
} catch (textError) {
|
|
2325
|
+
const cause = textError instanceof Error ? textError : new Error(String(textError));
|
|
2326
|
+
return err(
|
|
2327
|
+
serviceError(
|
|
2328
|
+
ErrorCodes.KV_WRITE_FAILED,
|
|
2329
|
+
`Failed to batch put ${items.length} key(s): ${response.status} - <response body could not be read: ${cause.message}>`,
|
|
2330
|
+
"kv",
|
|
2331
|
+
{ cause, meta: { status: response.status, statusText: response.statusText } }
|
|
2332
|
+
)
|
|
2333
|
+
);
|
|
2334
|
+
}
|
|
2289
2335
|
if (response.status === 401 || response.status === 403) {
|
|
2290
2336
|
const { resource, action } = parseAuthError(errorText);
|
|
2291
2337
|
return err(authUnauthorizedError("kv", errorText, {
|
|
@@ -2311,19 +2357,73 @@ var KVService = class extends BaseService {
|
|
|
2311
2357
|
)
|
|
2312
2358
|
);
|
|
2313
2359
|
}
|
|
2314
|
-
|
|
2315
|
-
|
|
2360
|
+
let rawBody;
|
|
2361
|
+
try {
|
|
2362
|
+
rawBody = await response.json();
|
|
2363
|
+
} catch (jsonError) {
|
|
2364
|
+
const cause = jsonError instanceof Error ? jsonError : new Error(String(jsonError));
|
|
2365
|
+
return err(
|
|
2366
|
+
serviceError(
|
|
2367
|
+
ErrorCodes.NETWORK_ERROR,
|
|
2368
|
+
`KV batchPut response was not valid JSON: ${cause.message}`,
|
|
2369
|
+
"kv",
|
|
2370
|
+
{
|
|
2371
|
+
cause,
|
|
2372
|
+
meta: {
|
|
2373
|
+
requestMayHaveDispatched: true,
|
|
2374
|
+
responseReceived: true,
|
|
2375
|
+
status: response.status,
|
|
2376
|
+
outcome: "batch-unconfirmed"
|
|
2377
|
+
}
|
|
2378
|
+
}
|
|
2379
|
+
)
|
|
2380
|
+
);
|
|
2381
|
+
}
|
|
2382
|
+
const batchResponse = this.normalizeBatchPutResponse(rawBody);
|
|
2383
|
+
if (!batchResponse) {
|
|
2316
2384
|
return err(
|
|
2317
2385
|
serviceError(
|
|
2318
2386
|
ErrorCodes.NETWORK_ERROR,
|
|
2319
2387
|
"KV batchPut response did not include matching written keys and count",
|
|
2320
|
-
"kv"
|
|
2388
|
+
"kv",
|
|
2389
|
+
{
|
|
2390
|
+
meta: {
|
|
2391
|
+
requestMayHaveDispatched: true,
|
|
2392
|
+
responseReceived: true,
|
|
2393
|
+
status: response.status,
|
|
2394
|
+
outcome: "batch-unconfirmed"
|
|
2395
|
+
}
|
|
2396
|
+
}
|
|
2397
|
+
)
|
|
2398
|
+
);
|
|
2399
|
+
}
|
|
2400
|
+
const requestedPaths = new Set(paths);
|
|
2401
|
+
const writtenPaths = new Set(batchResponse.written);
|
|
2402
|
+
const matchesRequest = batchResponse.count === paths.length && batchResponse.written.length === paths.length && writtenPaths.size === paths.length && batchResponse.written.every((key) => requestedPaths.has(key));
|
|
2403
|
+
if (!matchesRequest) {
|
|
2404
|
+
return err(
|
|
2405
|
+
serviceError(
|
|
2406
|
+
ErrorCodes.NETWORK_ERROR,
|
|
2407
|
+
`KV batchPut response did not confirm all ${paths.length} requested key(s) were written`,
|
|
2408
|
+
"kv",
|
|
2409
|
+
{
|
|
2410
|
+
meta: {
|
|
2411
|
+
requestMayHaveDispatched: true,
|
|
2412
|
+
responseReceived: true,
|
|
2413
|
+
status: response.status,
|
|
2414
|
+
outcome: "batch-unconfirmed"
|
|
2415
|
+
}
|
|
2416
|
+
}
|
|
2321
2417
|
)
|
|
2322
2418
|
);
|
|
2323
2419
|
}
|
|
2324
2420
|
return ok(batchResponse);
|
|
2325
2421
|
} catch (error) {
|
|
2326
|
-
|
|
2422
|
+
const wrapped = wrapError("kv", error);
|
|
2423
|
+
return err({
|
|
2424
|
+
...wrapped,
|
|
2425
|
+
meta: { ...wrapped.meta, requestMayHaveDispatched }
|
|
2426
|
+
});
|
|
2327
2427
|
}
|
|
2328
2428
|
});
|
|
2329
2429
|
}
|
|
@@ -6661,15 +6761,28 @@ function normalizeSpace(space) {
|
|
|
6661
6761
|
function isCapabilitySubset(requested, granted) {
|
|
6662
6762
|
const missing = [];
|
|
6663
6763
|
for (const req of requested) {
|
|
6664
|
-
const
|
|
6665
|
-
|
|
6764
|
+
const matchingScope = granted.filter(
|
|
6765
|
+
(entry) => canonicalizeEntryScopeMatches(req, entry)
|
|
6766
|
+
);
|
|
6767
|
+
const requestedActions = expandActionShortNames(
|
|
6768
|
+
req.service,
|
|
6769
|
+
req.actions
|
|
6770
|
+
);
|
|
6771
|
+
const grantedActions = matchingScope.flatMap(
|
|
6772
|
+
(entry) => expandActionShortNames(entry.service, entry.actions)
|
|
6773
|
+
);
|
|
6774
|
+
const covered = requestedActions.every(
|
|
6775
|
+
(requestedAction) => grantedActions.some(
|
|
6776
|
+
(grantedAction) => actionContains(grantedAction, requestedAction)
|
|
6777
|
+
)
|
|
6778
|
+
);
|
|
6779
|
+
if (!covered) {
|
|
6666
6780
|
missing.push(cloneEntry(req));
|
|
6667
|
-
continue;
|
|
6668
6781
|
}
|
|
6669
6782
|
}
|
|
6670
6783
|
return { subset: missing.length === 0, missing };
|
|
6671
6784
|
}
|
|
6672
|
-
function
|
|
6785
|
+
function canonicalizeEntryScopeMatches(requested, granted) {
|
|
6673
6786
|
if (requested.service !== granted.service) {
|
|
6674
6787
|
return false;
|
|
6675
6788
|
}
|
|
@@ -6679,15 +6792,6 @@ function canonicalizeEntryMatches(requested, granted) {
|
|
|
6679
6792
|
if (!pathContains(granted.path, requested.path)) {
|
|
6680
6793
|
return false;
|
|
6681
6794
|
}
|
|
6682
|
-
const reqActions = new Set(
|
|
6683
|
-
expandActionShortNames(requested.service, requested.actions)
|
|
6684
|
-
);
|
|
6685
|
-
const grantedActions = expandActionShortNames(granted.service, granted.actions);
|
|
6686
|
-
for (const a of reqActions) {
|
|
6687
|
-
if (!grantedActions.some((grantedAction) => actionContains(grantedAction, a))) {
|
|
6688
|
-
return false;
|
|
6689
|
-
}
|
|
6690
|
-
}
|
|
6691
6795
|
if (!recapCaveatsEqual(requested.caveats, granted.caveats)) {
|
|
6692
6796
|
return false;
|
|
6693
6797
|
}
|