@tinycloud/sdk-core 2.2.0-beta.4 → 2.2.0-beta.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +180 -23
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +47 -17
- package/dist/index.d.ts +47 -17
- package/dist/index.js +181 -24
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -154,6 +154,7 @@ var Space = class {
|
|
|
154
154
|
this._id = config.id;
|
|
155
155
|
this._name = config.name;
|
|
156
156
|
this._kv = config.createKV(config.id);
|
|
157
|
+
this._vault = config.createVault(config.id);
|
|
157
158
|
this._delegations = config.createDelegations(config.id);
|
|
158
159
|
this._sharing = config.createSharing(config.id);
|
|
159
160
|
this._getInfo = config.getInfo;
|
|
@@ -176,6 +177,12 @@ var Space = class {
|
|
|
176
177
|
get kv() {
|
|
177
178
|
return this._kv;
|
|
178
179
|
}
|
|
180
|
+
/**
|
|
181
|
+
* Data Vault operations scoped to this space.
|
|
182
|
+
*/
|
|
183
|
+
get vault() {
|
|
184
|
+
return this._vault;
|
|
185
|
+
}
|
|
179
186
|
/**
|
|
180
187
|
* Delegation operations scoped to this space.
|
|
181
188
|
*/
|
|
@@ -559,6 +566,8 @@ var SpaceConfigSchema = z4.object({
|
|
|
559
566
|
name: z4.string(),
|
|
560
567
|
/** Factory function to create a space-scoped KV service */
|
|
561
568
|
createKV: z4.function(),
|
|
569
|
+
/** Factory function to create a space-scoped Data Vault service */
|
|
570
|
+
createVault: z4.function(),
|
|
562
571
|
/** Factory function to create space-scoped delegations */
|
|
563
572
|
createDelegations: z4.function(),
|
|
564
573
|
/** Factory function to create space-scoped sharing */
|
|
@@ -579,6 +588,8 @@ var SpaceServiceConfigSchema = z4.object({
|
|
|
579
588
|
capabilityRegistry: z4.unknown().optional(),
|
|
580
589
|
/** Factory function to create a space-scoped KV service */
|
|
581
590
|
createKVService: z4.function().optional(),
|
|
591
|
+
/** Factory function to create a space-scoped Data Vault service */
|
|
592
|
+
createVaultService: z4.function().optional(),
|
|
582
593
|
/** User's PKH DID (derived from address or provided explicitly) */
|
|
583
594
|
userDid: z4.string().optional(),
|
|
584
595
|
/** Optional SharingService for v2 sharing links (client-side) */
|
|
@@ -820,6 +831,7 @@ var SpaceService = class {
|
|
|
820
831
|
this.fetchFn = config.fetch ?? globalThis.fetch.bind(globalThis);
|
|
821
832
|
this.capabilityRegistry = config.capabilityRegistry;
|
|
822
833
|
this.createKVServiceFn = config.createKVService;
|
|
834
|
+
this.createVaultServiceFn = config.createVaultService;
|
|
823
835
|
this._userDid = config.userDid;
|
|
824
836
|
this.sharingService = config.sharingService;
|
|
825
837
|
this.createDelegationFn = config.createDelegation;
|
|
@@ -834,6 +846,7 @@ var SpaceService = class {
|
|
|
834
846
|
if (config.fetch) this.fetchFn = config.fetch;
|
|
835
847
|
if (config.capabilityRegistry) this.capabilityRegistry = config.capabilityRegistry;
|
|
836
848
|
if (config.createKVService) this.createKVServiceFn = config.createKVService;
|
|
849
|
+
if (config.createVaultService) this.createVaultServiceFn = config.createVaultService;
|
|
837
850
|
if (config.userDid !== void 0) this._userDid = config.userDid;
|
|
838
851
|
if (config.sharingService) this.sharingService = config.sharingService;
|
|
839
852
|
if (config.createDelegation) this.createDelegationFn = config.createDelegation;
|
|
@@ -1116,6 +1129,7 @@ var SpaceService = class {
|
|
|
1116
1129
|
id: spaceId,
|
|
1117
1130
|
name,
|
|
1118
1131
|
createKV: this.createSpaceScopedKV.bind(this),
|
|
1132
|
+
createVault: this.createSpaceScopedVault.bind(this),
|
|
1119
1133
|
createDelegations: this.createSpaceScopedDelegations.bind(this),
|
|
1120
1134
|
createSharing: this.createSpaceScopedSharing.bind(this),
|
|
1121
1135
|
getInfo: this.getSpaceInfo.bind(this)
|
|
@@ -1245,6 +1259,21 @@ var SpaceService = class {
|
|
|
1245
1259
|
}
|
|
1246
1260
|
});
|
|
1247
1261
|
}
|
|
1262
|
+
/**
|
|
1263
|
+
* Create a space-scoped Data Vault service.
|
|
1264
|
+
*/
|
|
1265
|
+
createSpaceScopedVault(spaceId) {
|
|
1266
|
+
if (this.createVaultServiceFn) {
|
|
1267
|
+
return this.createVaultServiceFn(spaceId);
|
|
1268
|
+
}
|
|
1269
|
+
return new Proxy({}, {
|
|
1270
|
+
get: () => {
|
|
1271
|
+
throw new Error(
|
|
1272
|
+
"Vault service factory not configured. Provide createVaultService in SpaceServiceConfig."
|
|
1273
|
+
);
|
|
1274
|
+
}
|
|
1275
|
+
});
|
|
1276
|
+
}
|
|
1248
1277
|
/**
|
|
1249
1278
|
* Create space-scoped delegation operations.
|
|
1250
1279
|
*/
|
|
@@ -1989,7 +2018,8 @@ import {
|
|
|
1989
2018
|
DataVaultService,
|
|
1990
2019
|
VaultHeaders,
|
|
1991
2020
|
VaultPublicSpaceKVActions,
|
|
1992
|
-
createVaultCrypto
|
|
2021
|
+
createVaultCrypto,
|
|
2022
|
+
SecretsService
|
|
1993
2023
|
} from "@tinycloud/sdk-services";
|
|
1994
2024
|
|
|
1995
2025
|
// src/space.ts
|
|
@@ -2670,6 +2700,8 @@ var DEFAULT_MANIFEST_VERSION = 1;
|
|
|
2670
2700
|
var DEFAULT_MANIFEST_SPACE = "applications";
|
|
2671
2701
|
var ACCOUNT_REGISTRY_SPACE = "account";
|
|
2672
2702
|
var ACCOUNT_REGISTRY_PATH = "applications/";
|
|
2703
|
+
var SECRETS_SPACE = "secrets";
|
|
2704
|
+
var SECRET_NAME_RE = /^[A-Z][A-Z0-9_]*$/;
|
|
2673
2705
|
var SERVICE_SHORT_TO_LONG = Object.freeze({
|
|
2674
2706
|
kv: "tinycloud.kv",
|
|
2675
2707
|
sql: "tinycloud.sql",
|
|
@@ -2694,12 +2726,6 @@ var DEFAULT_STANDARD_ENTRIES = [
|
|
|
2694
2726
|
space: DEFAULT_MANIFEST_SPACE,
|
|
2695
2727
|
path: "/",
|
|
2696
2728
|
actions: ["read", "write"]
|
|
2697
|
-
},
|
|
2698
|
-
{
|
|
2699
|
-
service: "tinycloud.capabilities",
|
|
2700
|
-
space: DEFAULT_MANIFEST_SPACE,
|
|
2701
|
-
path: "/",
|
|
2702
|
-
actions: ["read"]
|
|
2703
2729
|
}
|
|
2704
2730
|
];
|
|
2705
2731
|
var DEFAULT_ADMIN_ENTRIES = [
|
|
@@ -2714,12 +2740,6 @@ var DEFAULT_ADMIN_ENTRIES = [
|
|
|
2714
2740
|
space: DEFAULT_MANIFEST_SPACE,
|
|
2715
2741
|
path: "/",
|
|
2716
2742
|
actions: ["read", "write", "ddl"]
|
|
2717
|
-
},
|
|
2718
|
-
{
|
|
2719
|
-
service: "tinycloud.capabilities",
|
|
2720
|
-
space: DEFAULT_MANIFEST_SPACE,
|
|
2721
|
-
path: "/",
|
|
2722
|
-
actions: ["read", "admin"]
|
|
2723
2743
|
}
|
|
2724
2744
|
];
|
|
2725
2745
|
var DEFAULT_ALL_ENTRIES = [
|
|
@@ -2740,12 +2760,6 @@ var DEFAULT_ALL_ENTRIES = [
|
|
|
2740
2760
|
space: DEFAULT_MANIFEST_SPACE,
|
|
2741
2761
|
path: "/",
|
|
2742
2762
|
actions: ["read", "write"]
|
|
2743
|
-
},
|
|
2744
|
-
{
|
|
2745
|
-
service: "tinycloud.capabilities",
|
|
2746
|
-
space: DEFAULT_MANIFEST_SPACE,
|
|
2747
|
-
path: "/",
|
|
2748
|
-
actions: ["read", "admin"]
|
|
2749
2763
|
}
|
|
2750
2764
|
];
|
|
2751
2765
|
function parseExpiry(duration) {
|
|
@@ -2841,8 +2855,39 @@ function validateManifest(input) {
|
|
|
2841
2855
|
(p, i) => validatePermissionEntry(p, `permissions[${i}]`)
|
|
2842
2856
|
);
|
|
2843
2857
|
}
|
|
2858
|
+
if (m.secrets !== void 0) {
|
|
2859
|
+
validateManifestSecrets(m.secrets);
|
|
2860
|
+
}
|
|
2844
2861
|
return m;
|
|
2845
2862
|
}
|
|
2863
|
+
function validateManifestSecrets(secrets) {
|
|
2864
|
+
if (secrets === null || typeof secrets !== "object" || Array.isArray(secrets)) {
|
|
2865
|
+
throw new ManifestValidationError("manifest.secrets must be an object");
|
|
2866
|
+
}
|
|
2867
|
+
for (const [name, spec] of Object.entries(secrets)) {
|
|
2868
|
+
if (!SECRET_NAME_RE.test(name)) {
|
|
2869
|
+
throw new ManifestValidationError(
|
|
2870
|
+
`manifest.secrets.${name} must match ${SECRET_NAME_RE.source}`
|
|
2871
|
+
);
|
|
2872
|
+
}
|
|
2873
|
+
const actions = secretActionsFromSpec(name, spec);
|
|
2874
|
+
if (actions.length === 0) {
|
|
2875
|
+
throw new ManifestValidationError(
|
|
2876
|
+
`manifest.secrets.${name} actions must be non-empty`
|
|
2877
|
+
);
|
|
2878
|
+
}
|
|
2879
|
+
for (const action of actions) {
|
|
2880
|
+
if (typeof action !== "string" || action.length === 0) {
|
|
2881
|
+
throw new ManifestValidationError(
|
|
2882
|
+
`manifest.secrets.${name} actions must be non-empty strings`
|
|
2883
|
+
);
|
|
2884
|
+
}
|
|
2885
|
+
}
|
|
2886
|
+
if (spec !== null && typeof spec === "object" && !Array.isArray(spec) && spec.expiry !== void 0) {
|
|
2887
|
+
parseExpiry(spec.expiry);
|
|
2888
|
+
}
|
|
2889
|
+
}
|
|
2890
|
+
}
|
|
2846
2891
|
function validatePermissionEntry(p, path) {
|
|
2847
2892
|
if (p === null || typeof p !== "object") {
|
|
2848
2893
|
throw new ManifestValidationError(`${path} must be an object`);
|
|
@@ -2895,7 +2940,8 @@ function defaultEntriesForTier(tier) {
|
|
|
2895
2940
|
service: e.service,
|
|
2896
2941
|
space: e.space,
|
|
2897
2942
|
path: e.path,
|
|
2898
|
-
actions: [...e.actions]
|
|
2943
|
+
actions: [...e.actions],
|
|
2944
|
+
...e.skipPrefix !== void 0 ? { skipPrefix: e.skipPrefix } : {}
|
|
2899
2945
|
}));
|
|
2900
2946
|
}
|
|
2901
2947
|
function resolveManifest(input) {
|
|
@@ -2907,9 +2953,14 @@ function resolveManifest(input) {
|
|
|
2907
2953
|
const tier = normalizeDefaults(manifest.defaults);
|
|
2908
2954
|
const defaultEntries = defaultEntriesForTier(tier);
|
|
2909
2955
|
const explicitEntries = manifest.permissions ?? [];
|
|
2910
|
-
const
|
|
2911
|
-
const
|
|
2912
|
-
|
|
2956
|
+
const secretEntries = secretEntriesForManifest(manifest.secrets);
|
|
2957
|
+
const allEntries = [
|
|
2958
|
+
...defaultEntries,
|
|
2959
|
+
...explicitEntries,
|
|
2960
|
+
...secretEntries
|
|
2961
|
+
];
|
|
2962
|
+
const resources = withCapabilitiesReadForSpaces(
|
|
2963
|
+
allEntries.map((entry) => resolveEntry(entry, prefix, expiryMs, space))
|
|
2913
2964
|
);
|
|
2914
2965
|
const additionalDelegates = manifest.did === void 0 ? [] : [
|
|
2915
2966
|
{
|
|
@@ -2929,6 +2980,92 @@ function resolveManifest(input) {
|
|
|
2929
2980
|
additionalDelegates
|
|
2930
2981
|
};
|
|
2931
2982
|
}
|
|
2983
|
+
function normalizeSecretActions(actions) {
|
|
2984
|
+
const out = [];
|
|
2985
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2986
|
+
const add = (action) => {
|
|
2987
|
+
if (!seen.has(action)) {
|
|
2988
|
+
out.push(action);
|
|
2989
|
+
seen.add(action);
|
|
2990
|
+
}
|
|
2991
|
+
};
|
|
2992
|
+
for (const action of actions) {
|
|
2993
|
+
if (action === "read") {
|
|
2994
|
+
add("get");
|
|
2995
|
+
continue;
|
|
2996
|
+
}
|
|
2997
|
+
if (action === "write") {
|
|
2998
|
+
add("put");
|
|
2999
|
+
continue;
|
|
3000
|
+
}
|
|
3001
|
+
if (action === "delete") {
|
|
3002
|
+
add("del");
|
|
3003
|
+
continue;
|
|
3004
|
+
}
|
|
3005
|
+
if (action === "get" || action === "put" || action === "del" || action === "list" || action === "metadata") {
|
|
3006
|
+
add(action);
|
|
3007
|
+
continue;
|
|
3008
|
+
}
|
|
3009
|
+
if (action === "tinycloud.kv/get" || action === "tinycloud.kv/put" || action === "tinycloud.kv/del" || action === "tinycloud.kv/list" || action === "tinycloud.kv/metadata") {
|
|
3010
|
+
add(action);
|
|
3011
|
+
continue;
|
|
3012
|
+
}
|
|
3013
|
+
throw new ManifestValidationError(
|
|
3014
|
+
`unknown secret action ${JSON.stringify(action)}; expected read, write, delete, list, or metadata`
|
|
3015
|
+
);
|
|
3016
|
+
}
|
|
3017
|
+
return out;
|
|
3018
|
+
}
|
|
3019
|
+
function secretActionsFromSpec(name, spec) {
|
|
3020
|
+
if (spec === true) {
|
|
3021
|
+
return ["read"];
|
|
3022
|
+
}
|
|
3023
|
+
if (typeof spec === "string") {
|
|
3024
|
+
return [spec];
|
|
3025
|
+
}
|
|
3026
|
+
if (Array.isArray(spec)) {
|
|
3027
|
+
return spec;
|
|
3028
|
+
}
|
|
3029
|
+
if (spec === null || typeof spec !== "object") {
|
|
3030
|
+
throw new ManifestValidationError(
|
|
3031
|
+
`manifest.secrets.${name} must be true, a string action, an actions array, or an object`
|
|
3032
|
+
);
|
|
3033
|
+
}
|
|
3034
|
+
if (spec.actions === void 0) {
|
|
3035
|
+
return ["read"];
|
|
3036
|
+
}
|
|
3037
|
+
if (typeof spec.actions === "string") {
|
|
3038
|
+
return [spec.actions];
|
|
3039
|
+
}
|
|
3040
|
+
if (Array.isArray(spec.actions)) {
|
|
3041
|
+
return spec.actions;
|
|
3042
|
+
}
|
|
3043
|
+
throw new ManifestValidationError(
|
|
3044
|
+
`manifest.secrets.${name}.actions must be a string or array`
|
|
3045
|
+
);
|
|
3046
|
+
}
|
|
3047
|
+
function secretEntriesForManifest(secrets) {
|
|
3048
|
+
if (secrets === void 0) {
|
|
3049
|
+
return [];
|
|
3050
|
+
}
|
|
3051
|
+
const entries = [];
|
|
3052
|
+
for (const [name, spec] of Object.entries(secrets)) {
|
|
3053
|
+
const actions = secretActionsFromSpec(name, spec);
|
|
3054
|
+
const extra = spec !== true && typeof spec === "object" && !Array.isArray(spec) ? spec : {};
|
|
3055
|
+
for (const base of ["keys", "vault"]) {
|
|
3056
|
+
entries.push({
|
|
3057
|
+
service: "tinycloud.kv",
|
|
3058
|
+
space: SECRETS_SPACE,
|
|
3059
|
+
path: `${base}/secrets/${name}`,
|
|
3060
|
+
actions: normalizeSecretActions(actions),
|
|
3061
|
+
skipPrefix: true,
|
|
3062
|
+
...extra.expiry !== void 0 ? { expiry: extra.expiry } : {},
|
|
3063
|
+
...extra.description !== void 0 ? { description: extra.description } : {}
|
|
3064
|
+
});
|
|
3065
|
+
}
|
|
3066
|
+
}
|
|
3067
|
+
return entries;
|
|
3068
|
+
}
|
|
2932
3069
|
function resolveEntry(entry, prefix, _inheritedExpiryMs, inheritedSpace) {
|
|
2933
3070
|
const resolvedPath = applyPrefix(
|
|
2934
3071
|
prefix,
|
|
@@ -2992,6 +3129,24 @@ function dedupeResources(resources) {
|
|
|
2992
3129
|
}
|
|
2993
3130
|
return [...byKey.values()];
|
|
2994
3131
|
}
|
|
3132
|
+
function capabilitiesReadPermission(space) {
|
|
3133
|
+
return {
|
|
3134
|
+
service: "tinycloud.capabilities",
|
|
3135
|
+
space,
|
|
3136
|
+
path: "",
|
|
3137
|
+
actions: ["tinycloud.capabilities/read"]
|
|
3138
|
+
};
|
|
3139
|
+
}
|
|
3140
|
+
function withCapabilitiesReadForSpaces(resources) {
|
|
3141
|
+
if (resources.length === 0) {
|
|
3142
|
+
return [];
|
|
3143
|
+
}
|
|
3144
|
+
const spaces = new Set(resources.map((resource) => resource.space));
|
|
3145
|
+
return dedupeResources([
|
|
3146
|
+
...resources,
|
|
3147
|
+
...[...spaces].map(capabilitiesReadPermission)
|
|
3148
|
+
]);
|
|
3149
|
+
}
|
|
2995
3150
|
function accountRegistryPermission() {
|
|
2996
3151
|
return {
|
|
2997
3152
|
service: "tinycloud.kv",
|
|
@@ -3019,6 +3174,7 @@ function composeManifestRequest(inputs, options = {}) {
|
|
|
3019
3174
|
if (includeAccountRegistryPermissions) {
|
|
3020
3175
|
resources.push(accountRegistryPermission());
|
|
3021
3176
|
}
|
|
3177
|
+
const resourcesWithImplicitCapabilities = withCapabilitiesReadForSpaces(resources);
|
|
3022
3178
|
const manifestsByAppId = /* @__PURE__ */ new Map();
|
|
3023
3179
|
for (const manifest of manifests) {
|
|
3024
3180
|
const current = manifestsByAppId.get(manifest.app_id);
|
|
@@ -3038,7 +3194,7 @@ function composeManifestRequest(inputs, options = {}) {
|
|
|
3038
3194
|
})) : [];
|
|
3039
3195
|
return {
|
|
3040
3196
|
manifests,
|
|
3041
|
-
resources:
|
|
3197
|
+
resources: resourcesWithImplicitCapabilities,
|
|
3042
3198
|
delegationTargets,
|
|
3043
3199
|
registryRecords,
|
|
3044
3200
|
expiryMs: Math.max(...resolved.map((entry) => entry.expiryMs)),
|
|
@@ -4785,6 +4941,7 @@ export {
|
|
|
4785
4941
|
SERVICE_SHORT_TO_LONG,
|
|
4786
4942
|
SQLAction,
|
|
4787
4943
|
SQLService2 as SQLService,
|
|
4944
|
+
SecretsService,
|
|
4788
4945
|
ServiceContext2 as ServiceContext,
|
|
4789
4946
|
SessionExpiredError,
|
|
4790
4947
|
SharingService,
|