@tinycloud/sdk-services 3.1.0-beta.2 → 3.1.0-beta.6
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/encryption/index.cjs +106 -97
- package/dist/encryption/index.cjs.map +1 -1
- package/dist/encryption/index.js +106 -97
- package/dist/encryption/index.js.map +1 -1
- package/dist/index.cjs +269 -147
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +19 -1
- package/dist/index.d.ts +19 -1
- package/dist/index.js +249 -129
- package/dist/index.js.map +1 -1
- package/dist/kv/index.cjs +210 -20
- package/dist/kv/index.cjs.map +1 -1
- package/dist/kv/index.d.cts +5 -1
- package/dist/kv/index.d.ts +5 -1
- package/dist/kv/index.js +210 -20
- package/dist/kv/index.js.map +1 -1
- package/dist/sql/index.cjs +33 -21
- package/dist/sql/index.cjs.map +1 -1
- package/dist/sql/index.js +24 -12
- package/dist/sql/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -1083,6 +1083,24 @@ declare function authUnauthorizedError(service: string, message: string, meta?:
|
|
|
1083
1083
|
* - `"other"`: a non-authorization HTTP error status (4xx/5xx).
|
|
1084
1084
|
*/
|
|
1085
1085
|
type AuthorizationVerdict = "unauthenticated" | "forbidden" | "other";
|
|
1086
|
+
/**
|
|
1087
|
+
* Parse a canonical TinyCloud resource, keeping nested space names intact.
|
|
1088
|
+
* The first registered service segment is authoritative: a later matching
|
|
1089
|
+
* segment in the path cannot turn a different service into grant advice.
|
|
1090
|
+
*/
|
|
1091
|
+
declare function parseCapabilityResource(resource: string, service: string): {
|
|
1092
|
+
space: string;
|
|
1093
|
+
path: string;
|
|
1094
|
+
} | undefined;
|
|
1095
|
+
/**
|
|
1096
|
+
* Return a grantable missing capability only when typed authorization evidence
|
|
1097
|
+
* and both safe, service-matched capability fields are present. Status alone,
|
|
1098
|
+
* message text, wildcard actions and unrecognized actions cannot grant scope.
|
|
1099
|
+
*/
|
|
1100
|
+
declare function validatedCapabilityOf(error: unknown): {
|
|
1101
|
+
resource: string;
|
|
1102
|
+
requiredAction: string;
|
|
1103
|
+
} | undefined;
|
|
1086
1104
|
/**
|
|
1087
1105
|
* Classify an error from its typed HTTP error status (`status`, `statusCode`,
|
|
1088
1106
|
* or `meta.status`, 4xx/5xx only) and `AUTH_UNAUTHORIZED` code, following the
|
|
@@ -2297,4 +2315,4 @@ declare class SecretsService implements ISecretsService {
|
|
|
2297
2315
|
listAll(): Promise<Result<SecretCatalogEntry[], SecretsError>>;
|
|
2298
2316
|
}
|
|
2299
2317
|
|
|
2300
|
-
export { type AuthorizationVerdict, BaseService, type BaseServiceOptions, type ColumnInfo, type DataVaultConfig, DataVaultService, DecryptCapabilityProof, DuckDbAction, type DuckDbActionType, type DuckDbBatchOptions, type BatchResponse as DuckDbBatchResponse, DuckDbDatabaseHandle, type DuckDbExecuteOptions, type ExecuteResponse as DuckDbExecuteResponse, type DuckDbOptions, type DuckDbQueryOptions, type QueryResponse as DuckDbQueryResponse, DuckDbService, type DuckDbServiceConfig, type DuckDbStatement, type DuckDbValue, EventHandler, FetchFunction, GenericKVResponseSchema, type GenericKVResponseType, GenericResultSchema, type HookEvent, type HookServiceName, type HookStreamEvent, type HookSubscription, type HookWebhookListOptions, type HookWebhookRecord, type HookWebhookRegistration, type HookWebhookScope, type HookWebhookUnregisterOptions, HooksService, type HooksServiceConfig, type IDataVaultService, type IDuckDbDatabaseHandle, type IDuckDbService, IEncryptionService, type IHooksService, IKVService, type ISecretsService, IService, IServiceContext, InvokeAnyFunction, InvokeFunction, KVListResponseSchema, type KVListResponseType, KVListResultSchema, type KVListResultType, KVResponseHeadersSchema, type KVResponseHeadersType, type ParsedSecretCatalogKey, PermissionHint, type QuotaConfig, type QuotaStatus, type ResolvedSecretPath, Result, RetryPolicy, RetryPolicySchema, type RetryPolicyType, SECRET_NAME_RE, STORAGE_FULL_MESSAGE, STORAGE_WRITE_TOO_LARGE_MESSAGE, type SchemaInfo, type SecretCatalogEntry, type SecretPayload, type SecretScopeOptions, type SecretsError, SecretsService, type ServiceConstructor, ServiceContext, type ServiceContextConfig, ServiceError, ServiceErrorEventSchema, type ServiceErrorEventType, ServiceErrorSchema, type ServiceErrorType, type ServiceRegistration, ServiceRequestEventSchema, type ServiceRequestEventType, ServiceResponseEventSchema, type ServiceResponseEventType, ServiceRetryEventSchema, type ServiceRetryEventType, ServiceSession, ServiceSessionSchema, type ServiceSessionType, StorageQuotaInfo, type SubscribeOptions, type TableInfo, TelemetryConfig, TelemetrySpanEventSchema, type TelemetrySpanEventType, type TinyCloudDebugEnableOptions, type TinyCloudDebugEvent, type TinyCloudDebugLevel, TinyCloudDebugLogger, type TinyCloudDebugTimer, TinyCloudQuota, type ValidationError, type VaultCrypto, type VaultEntry, type VaultError, type VaultGetOptions, type VaultGrantOptions, VaultHeaders, type VaultListOptions, type VaultListPage, type VaultNetworkReadResult, VaultPublicSpaceKVActions, type VaultPutOptions, type ViewInfo, type WasmVaultFunctions, abortedError, authExpiredError, authRequiredError, authUnauthorizedError, authorizationVerdictOf, canonicalizeSecretScope, clearTinyCloudDebugLogs, createKVResponseSchema, createResultSchema, createVaultCrypto, disableTinyCloudDebug, enableTinyCloudDebug, errorResult, getTinyCloudDebugLogs, installTinyCloudDebugGlobals, isStorageFullError, networkError, notFoundError, parseAuthError, parsePermissionHint, parsePermissionHintFromErrorText, parseSecretCatalogKey, parseStorageQuotaBytes, permissionDeniedError, resolveSecretListPrefix, resolveSecretPath, storageLimitReachedError, storageQuotaExceededError, storageRejectionError, timeoutError, tinyCloudDebugLogger, validateKVListResponse, validateKVResponseHeaders, validateRetryPolicy, validateServiceError, validateServiceRequestEvent, validateServiceResponseEvent, validateServiceSession, validateTelemetrySpanEvent, wrapError };
|
|
2318
|
+
export { type AuthorizationVerdict, BaseService, type BaseServiceOptions, type ColumnInfo, type DataVaultConfig, DataVaultService, DecryptCapabilityProof, DuckDbAction, type DuckDbActionType, type DuckDbBatchOptions, type BatchResponse as DuckDbBatchResponse, DuckDbDatabaseHandle, type DuckDbExecuteOptions, type ExecuteResponse as DuckDbExecuteResponse, type DuckDbOptions, type DuckDbQueryOptions, type QueryResponse as DuckDbQueryResponse, DuckDbService, type DuckDbServiceConfig, type DuckDbStatement, type DuckDbValue, EventHandler, FetchFunction, GenericKVResponseSchema, type GenericKVResponseType, GenericResultSchema, type HookEvent, type HookServiceName, type HookStreamEvent, type HookSubscription, type HookWebhookListOptions, type HookWebhookRecord, type HookWebhookRegistration, type HookWebhookScope, type HookWebhookUnregisterOptions, HooksService, type HooksServiceConfig, type IDataVaultService, type IDuckDbDatabaseHandle, type IDuckDbService, IEncryptionService, type IHooksService, IKVService, type ISecretsService, IService, IServiceContext, InvokeAnyFunction, InvokeFunction, KVListResponseSchema, type KVListResponseType, KVListResultSchema, type KVListResultType, KVResponseHeadersSchema, type KVResponseHeadersType, type ParsedSecretCatalogKey, PermissionHint, type QuotaConfig, type QuotaStatus, type ResolvedSecretPath, Result, RetryPolicy, RetryPolicySchema, type RetryPolicyType, SECRET_NAME_RE, STORAGE_FULL_MESSAGE, STORAGE_WRITE_TOO_LARGE_MESSAGE, type SchemaInfo, type SecretCatalogEntry, type SecretPayload, type SecretScopeOptions, type SecretsError, SecretsService, type ServiceConstructor, ServiceContext, type ServiceContextConfig, ServiceError, ServiceErrorEventSchema, type ServiceErrorEventType, ServiceErrorSchema, type ServiceErrorType, type ServiceRegistration, ServiceRequestEventSchema, type ServiceRequestEventType, ServiceResponseEventSchema, type ServiceResponseEventType, ServiceRetryEventSchema, type ServiceRetryEventType, ServiceSession, ServiceSessionSchema, type ServiceSessionType, StorageQuotaInfo, type SubscribeOptions, type TableInfo, TelemetryConfig, TelemetrySpanEventSchema, type TelemetrySpanEventType, type TinyCloudDebugEnableOptions, type TinyCloudDebugEvent, type TinyCloudDebugLevel, TinyCloudDebugLogger, type TinyCloudDebugTimer, TinyCloudQuota, type ValidationError, type VaultCrypto, type VaultEntry, type VaultError, type VaultGetOptions, type VaultGrantOptions, VaultHeaders, type VaultListOptions, type VaultListPage, type VaultNetworkReadResult, VaultPublicSpaceKVActions, type VaultPutOptions, type ViewInfo, type WasmVaultFunctions, abortedError, authExpiredError, authRequiredError, authUnauthorizedError, authorizationVerdictOf, canonicalizeSecretScope, clearTinyCloudDebugLogs, createKVResponseSchema, createResultSchema, createVaultCrypto, disableTinyCloudDebug, enableTinyCloudDebug, errorResult, getTinyCloudDebugLogs, installTinyCloudDebugGlobals, isStorageFullError, networkError, notFoundError, parseAuthError, parseCapabilityResource, parsePermissionHint, parsePermissionHintFromErrorText, parseSecretCatalogKey, parseStorageQuotaBytes, permissionDeniedError, resolveSecretListPrefix, resolveSecretPath, storageLimitReachedError, storageQuotaExceededError, storageRejectionError, timeoutError, tinyCloudDebugLogger, validateKVListResponse, validateKVResponseHeaders, validateRetryPolicy, validateServiceError, validateServiceRequestEvent, validateServiceResponseEvent, validateServiceSession, validateTelemetrySpanEvent, validatedCapabilityOf, wrapError };
|
package/dist/index.d.ts
CHANGED
|
@@ -1083,6 +1083,24 @@ declare function authUnauthorizedError(service: string, message: string, meta?:
|
|
|
1083
1083
|
* - `"other"`: a non-authorization HTTP error status (4xx/5xx).
|
|
1084
1084
|
*/
|
|
1085
1085
|
type AuthorizationVerdict = "unauthenticated" | "forbidden" | "other";
|
|
1086
|
+
/**
|
|
1087
|
+
* Parse a canonical TinyCloud resource, keeping nested space names intact.
|
|
1088
|
+
* The first registered service segment is authoritative: a later matching
|
|
1089
|
+
* segment in the path cannot turn a different service into grant advice.
|
|
1090
|
+
*/
|
|
1091
|
+
declare function parseCapabilityResource(resource: string, service: string): {
|
|
1092
|
+
space: string;
|
|
1093
|
+
path: string;
|
|
1094
|
+
} | undefined;
|
|
1095
|
+
/**
|
|
1096
|
+
* Return a grantable missing capability only when typed authorization evidence
|
|
1097
|
+
* and both safe, service-matched capability fields are present. Status alone,
|
|
1098
|
+
* message text, wildcard actions and unrecognized actions cannot grant scope.
|
|
1099
|
+
*/
|
|
1100
|
+
declare function validatedCapabilityOf(error: unknown): {
|
|
1101
|
+
resource: string;
|
|
1102
|
+
requiredAction: string;
|
|
1103
|
+
} | undefined;
|
|
1086
1104
|
/**
|
|
1087
1105
|
* Classify an error from its typed HTTP error status (`status`, `statusCode`,
|
|
1088
1106
|
* or `meta.status`, 4xx/5xx only) and `AUTH_UNAUTHORIZED` code, following the
|
|
@@ -2297,4 +2315,4 @@ declare class SecretsService implements ISecretsService {
|
|
|
2297
2315
|
listAll(): Promise<Result<SecretCatalogEntry[], SecretsError>>;
|
|
2298
2316
|
}
|
|
2299
2317
|
|
|
2300
|
-
export { type AuthorizationVerdict, BaseService, type BaseServiceOptions, type ColumnInfo, type DataVaultConfig, DataVaultService, DecryptCapabilityProof, DuckDbAction, type DuckDbActionType, type DuckDbBatchOptions, type BatchResponse as DuckDbBatchResponse, DuckDbDatabaseHandle, type DuckDbExecuteOptions, type ExecuteResponse as DuckDbExecuteResponse, type DuckDbOptions, type DuckDbQueryOptions, type QueryResponse as DuckDbQueryResponse, DuckDbService, type DuckDbServiceConfig, type DuckDbStatement, type DuckDbValue, EventHandler, FetchFunction, GenericKVResponseSchema, type GenericKVResponseType, GenericResultSchema, type HookEvent, type HookServiceName, type HookStreamEvent, type HookSubscription, type HookWebhookListOptions, type HookWebhookRecord, type HookWebhookRegistration, type HookWebhookScope, type HookWebhookUnregisterOptions, HooksService, type HooksServiceConfig, type IDataVaultService, type IDuckDbDatabaseHandle, type IDuckDbService, IEncryptionService, type IHooksService, IKVService, type ISecretsService, IService, IServiceContext, InvokeAnyFunction, InvokeFunction, KVListResponseSchema, type KVListResponseType, KVListResultSchema, type KVListResultType, KVResponseHeadersSchema, type KVResponseHeadersType, type ParsedSecretCatalogKey, PermissionHint, type QuotaConfig, type QuotaStatus, type ResolvedSecretPath, Result, RetryPolicy, RetryPolicySchema, type RetryPolicyType, SECRET_NAME_RE, STORAGE_FULL_MESSAGE, STORAGE_WRITE_TOO_LARGE_MESSAGE, type SchemaInfo, type SecretCatalogEntry, type SecretPayload, type SecretScopeOptions, type SecretsError, SecretsService, type ServiceConstructor, ServiceContext, type ServiceContextConfig, ServiceError, ServiceErrorEventSchema, type ServiceErrorEventType, ServiceErrorSchema, type ServiceErrorType, type ServiceRegistration, ServiceRequestEventSchema, type ServiceRequestEventType, ServiceResponseEventSchema, type ServiceResponseEventType, ServiceRetryEventSchema, type ServiceRetryEventType, ServiceSession, ServiceSessionSchema, type ServiceSessionType, StorageQuotaInfo, type SubscribeOptions, type TableInfo, TelemetryConfig, TelemetrySpanEventSchema, type TelemetrySpanEventType, type TinyCloudDebugEnableOptions, type TinyCloudDebugEvent, type TinyCloudDebugLevel, TinyCloudDebugLogger, type TinyCloudDebugTimer, TinyCloudQuota, type ValidationError, type VaultCrypto, type VaultEntry, type VaultError, type VaultGetOptions, type VaultGrantOptions, VaultHeaders, type VaultListOptions, type VaultListPage, type VaultNetworkReadResult, VaultPublicSpaceKVActions, type VaultPutOptions, type ViewInfo, type WasmVaultFunctions, abortedError, authExpiredError, authRequiredError, authUnauthorizedError, authorizationVerdictOf, canonicalizeSecretScope, clearTinyCloudDebugLogs, createKVResponseSchema, createResultSchema, createVaultCrypto, disableTinyCloudDebug, enableTinyCloudDebug, errorResult, getTinyCloudDebugLogs, installTinyCloudDebugGlobals, isStorageFullError, networkError, notFoundError, parseAuthError, parsePermissionHint, parsePermissionHintFromErrorText, parseSecretCatalogKey, parseStorageQuotaBytes, permissionDeniedError, resolveSecretListPrefix, resolveSecretPath, storageLimitReachedError, storageQuotaExceededError, storageRejectionError, timeoutError, tinyCloudDebugLogger, validateKVListResponse, validateKVResponseHeaders, validateRetryPolicy, validateServiceError, validateServiceRequestEvent, validateServiceResponseEvent, validateServiceSession, validateTelemetrySpanEvent, wrapError };
|
|
2318
|
+
export { type AuthorizationVerdict, BaseService, type BaseServiceOptions, type ColumnInfo, type DataVaultConfig, DataVaultService, DecryptCapabilityProof, DuckDbAction, type DuckDbActionType, type DuckDbBatchOptions, type BatchResponse as DuckDbBatchResponse, DuckDbDatabaseHandle, type DuckDbExecuteOptions, type ExecuteResponse as DuckDbExecuteResponse, type DuckDbOptions, type DuckDbQueryOptions, type QueryResponse as DuckDbQueryResponse, DuckDbService, type DuckDbServiceConfig, type DuckDbStatement, type DuckDbValue, EventHandler, FetchFunction, GenericKVResponseSchema, type GenericKVResponseType, GenericResultSchema, type HookEvent, type HookServiceName, type HookStreamEvent, type HookSubscription, type HookWebhookListOptions, type HookWebhookRecord, type HookWebhookRegistration, type HookWebhookScope, type HookWebhookUnregisterOptions, HooksService, type HooksServiceConfig, type IDataVaultService, type IDuckDbDatabaseHandle, type IDuckDbService, IEncryptionService, type IHooksService, IKVService, type ISecretsService, IService, IServiceContext, InvokeAnyFunction, InvokeFunction, KVListResponseSchema, type KVListResponseType, KVListResultSchema, type KVListResultType, KVResponseHeadersSchema, type KVResponseHeadersType, type ParsedSecretCatalogKey, PermissionHint, type QuotaConfig, type QuotaStatus, type ResolvedSecretPath, Result, RetryPolicy, RetryPolicySchema, type RetryPolicyType, SECRET_NAME_RE, STORAGE_FULL_MESSAGE, STORAGE_WRITE_TOO_LARGE_MESSAGE, type SchemaInfo, type SecretCatalogEntry, type SecretPayload, type SecretScopeOptions, type SecretsError, SecretsService, type ServiceConstructor, ServiceContext, type ServiceContextConfig, ServiceError, ServiceErrorEventSchema, type ServiceErrorEventType, ServiceErrorSchema, type ServiceErrorType, type ServiceRegistration, ServiceRequestEventSchema, type ServiceRequestEventType, ServiceResponseEventSchema, type ServiceResponseEventType, ServiceRetryEventSchema, type ServiceRetryEventType, ServiceSession, ServiceSessionSchema, type ServiceSessionType, StorageQuotaInfo, type SubscribeOptions, type TableInfo, TelemetryConfig, TelemetrySpanEventSchema, type TelemetrySpanEventType, type TinyCloudDebugEnableOptions, type TinyCloudDebugEvent, type TinyCloudDebugLevel, TinyCloudDebugLogger, type TinyCloudDebugTimer, TinyCloudQuota, type ValidationError, type VaultCrypto, type VaultEntry, type VaultError, type VaultGetOptions, type VaultGrantOptions, VaultHeaders, type VaultListOptions, type VaultListPage, type VaultNetworkReadResult, VaultPublicSpaceKVActions, type VaultPutOptions, type ViewInfo, type WasmVaultFunctions, abortedError, authExpiredError, authRequiredError, authUnauthorizedError, authorizationVerdictOf, canonicalizeSecretScope, clearTinyCloudDebugLogs, createKVResponseSchema, createResultSchema, createVaultCrypto, disableTinyCloudDebug, enableTinyCloudDebug, errorResult, getTinyCloudDebugLogs, installTinyCloudDebugGlobals, isStorageFullError, networkError, notFoundError, parseAuthError, parseCapabilityResource, parsePermissionHint, parsePermissionHintFromErrorText, parseSecretCatalogKey, parseStorageQuotaBytes, permissionDeniedError, resolveSecretListPrefix, resolveSecretPath, storageLimitReachedError, storageQuotaExceededError, storageRejectionError, timeoutError, tinyCloudDebugLogger, validateKVListResponse, validateKVResponseHeaders, validateRetryPolicy, validateServiceError, validateServiceRequestEvent, validateServiceResponseEvent, validateServiceSession, validateTelemetrySpanEvent, validatedCapabilityOf, wrapError };
|
package/dist/index.js
CHANGED
|
@@ -896,6 +896,106 @@ var ServiceContext = class {
|
|
|
896
896
|
}
|
|
897
897
|
};
|
|
898
898
|
|
|
899
|
+
// src/errors.ts
|
|
900
|
+
import { CAPABILITY_REGISTRY } from "@tinycloud/bootstrap";
|
|
901
|
+
|
|
902
|
+
// src/encryption/networkId.ts
|
|
903
|
+
var URN_PREFIX = "urn:tinycloud:encryption:";
|
|
904
|
+
var NETWORK_NAME_RE = /^[a-z0-9][a-z0-9-]*$/;
|
|
905
|
+
var PKH_EIP155_DID_RE = /^did:pkh:eip155:(\d+):(0x[a-fA-F0-9]{40})$/;
|
|
906
|
+
var NetworkIdError = class extends Error {
|
|
907
|
+
constructor(message) {
|
|
908
|
+
super(message);
|
|
909
|
+
this.name = "NetworkIdError";
|
|
910
|
+
}
|
|
911
|
+
};
|
|
912
|
+
function parseNetworkId(networkId) {
|
|
913
|
+
if (typeof networkId !== "string" || networkId.length === 0) {
|
|
914
|
+
throw new NetworkIdError("networkId must be a non-empty string");
|
|
915
|
+
}
|
|
916
|
+
if (!networkId.startsWith(URN_PREFIX)) {
|
|
917
|
+
throw new NetworkIdError(
|
|
918
|
+
`networkId must start with ${URN_PREFIX} (got ${JSON.stringify(networkId)})`
|
|
919
|
+
);
|
|
920
|
+
}
|
|
921
|
+
const body = networkId.slice(URN_PREFIX.length);
|
|
922
|
+
const lastColon = body.lastIndexOf(":");
|
|
923
|
+
if (lastColon <= 0 || lastColon === body.length - 1) {
|
|
924
|
+
throw new NetworkIdError(
|
|
925
|
+
`networkId missing ownerDid or name segment (got ${JSON.stringify(networkId)})`
|
|
926
|
+
);
|
|
927
|
+
}
|
|
928
|
+
const ownerDid = body.slice(0, lastColon);
|
|
929
|
+
const name = body.slice(lastColon + 1);
|
|
930
|
+
if (!ownerDid.startsWith("did:")) {
|
|
931
|
+
throw new NetworkIdError(
|
|
932
|
+
`networkId ownerDid must be a DID (got ${JSON.stringify(ownerDid)})`
|
|
933
|
+
);
|
|
934
|
+
}
|
|
935
|
+
const didParts = ownerDid.split(":");
|
|
936
|
+
if (didParts.length < 3 || didParts.some((p) => p.length === 0)) {
|
|
937
|
+
throw new NetworkIdError(
|
|
938
|
+
`networkId ownerDid is not a well-formed DID (got ${JSON.stringify(ownerDid)})`
|
|
939
|
+
);
|
|
940
|
+
}
|
|
941
|
+
if (!NETWORK_NAME_RE.test(name)) {
|
|
942
|
+
throw new NetworkIdError(
|
|
943
|
+
`networkId name ${JSON.stringify(name)} must match ${NETWORK_NAME_RE.source}`
|
|
944
|
+
);
|
|
945
|
+
}
|
|
946
|
+
return { networkId, ownerDid, name };
|
|
947
|
+
}
|
|
948
|
+
function buildNetworkId(ownerDid, name) {
|
|
949
|
+
if (typeof ownerDid !== "string" || !ownerDid.startsWith("did:")) {
|
|
950
|
+
throw new NetworkIdError("ownerDid must be a DID");
|
|
951
|
+
}
|
|
952
|
+
if (typeof name !== "string" || !NETWORK_NAME_RE.test(name)) {
|
|
953
|
+
throw new NetworkIdError(
|
|
954
|
+
`network name ${JSON.stringify(name)} must match ${NETWORK_NAME_RE.source}`
|
|
955
|
+
);
|
|
956
|
+
}
|
|
957
|
+
const networkId = `${URN_PREFIX}${ownerDid}:${name}`;
|
|
958
|
+
parseNetworkId(networkId);
|
|
959
|
+
return networkId;
|
|
960
|
+
}
|
|
961
|
+
function isNetworkId(networkId) {
|
|
962
|
+
if (typeof networkId !== "string") {
|
|
963
|
+
return false;
|
|
964
|
+
}
|
|
965
|
+
try {
|
|
966
|
+
parseNetworkId(networkId);
|
|
967
|
+
return true;
|
|
968
|
+
} catch {
|
|
969
|
+
return false;
|
|
970
|
+
}
|
|
971
|
+
}
|
|
972
|
+
function parsePkhOwnerDid(ownerDid) {
|
|
973
|
+
const match = ownerDid.match(PKH_EIP155_DID_RE);
|
|
974
|
+
if (!match) return null;
|
|
975
|
+
return {
|
|
976
|
+
chainId: match[1],
|
|
977
|
+
address: match[2].toLowerCase()
|
|
978
|
+
};
|
|
979
|
+
}
|
|
980
|
+
function ownerDidMatches(a, b) {
|
|
981
|
+
const aPkh = parsePkhOwnerDid(a);
|
|
982
|
+
const bPkh = parsePkhOwnerDid(b);
|
|
983
|
+
if (aPkh && bPkh) {
|
|
984
|
+
return aPkh.chainId === bPkh.chainId && aPkh.address === bPkh.address;
|
|
985
|
+
}
|
|
986
|
+
return a === b;
|
|
987
|
+
}
|
|
988
|
+
function networkDiscoveryKey(name) {
|
|
989
|
+
if (!NETWORK_NAME_RE.test(name)) {
|
|
990
|
+
throw new NetworkIdError(
|
|
991
|
+
`network name ${JSON.stringify(name)} must match ${NETWORK_NAME_RE.source}`
|
|
992
|
+
);
|
|
993
|
+
}
|
|
994
|
+
return `.well-known/encryption/network/${name}`;
|
|
995
|
+
}
|
|
996
|
+
var ENCRYPTION_NETWORK_URN_PREFIX = URN_PREFIX;
|
|
997
|
+
var NETWORK_NAME_PATTERN = NETWORK_NAME_RE;
|
|
998
|
+
|
|
899
999
|
// src/errors.ts
|
|
900
1000
|
function parsePermissionHint(value) {
|
|
901
1001
|
if (typeof value !== "object" || value === null || Array.isArray(value)) return void 0;
|
|
@@ -993,6 +1093,70 @@ function parseAuthError(responseText) {
|
|
|
993
1093
|
function authUnauthorizedError(service, message, meta) {
|
|
994
1094
|
return serviceError(ErrorCodes.AUTH_UNAUTHORIZED, message, service, { meta });
|
|
995
1095
|
}
|
|
1096
|
+
var grantableActions = new Set(
|
|
1097
|
+
CAPABILITY_REGISTRY.map(({ urn }) => urn).filter((urn) => !urn.endsWith("/*"))
|
|
1098
|
+
);
|
|
1099
|
+
var capabilityServices = new Set(
|
|
1100
|
+
CAPABILITY_REGISTRY.map(({ service }) => service.slice("tinycloud.".length))
|
|
1101
|
+
);
|
|
1102
|
+
function parseCapabilityResource(resource, service) {
|
|
1103
|
+
if (resource.length === 0 || resource.length > 1024 || !capabilityServices.has(service) || /[\s\p{C}*#]/u.test(resource) || resource.includes("://")) return void 0;
|
|
1104
|
+
const segments = resource.split("/");
|
|
1105
|
+
if (!/^tinycloud:[A-Za-z0-9][A-Za-z0-9:._-]*$/.test(segments[0])) return void 0;
|
|
1106
|
+
const serviceIndex = segments.findIndex(
|
|
1107
|
+
(segment, index) => index > 0 && capabilityServices.has(segment)
|
|
1108
|
+
);
|
|
1109
|
+
if (serviceIndex < 1 || segments[serviceIndex] !== service) return void 0;
|
|
1110
|
+
if (segments.slice(1, serviceIndex).some(
|
|
1111
|
+
(segment) => segment.length === 0 || segment === "." || segment === ".."
|
|
1112
|
+
)) return void 0;
|
|
1113
|
+
const pathSegments = segments.slice(serviceIndex + 1);
|
|
1114
|
+
if (pathSegments.some((segment) => segment === "." || segment === "..")) return void 0;
|
|
1115
|
+
if (service !== "kv" && (pathSegments.length === 0 || pathSegments[pathSegments.length - 1] === "")) return void 0;
|
|
1116
|
+
return {
|
|
1117
|
+
space: segments.slice(0, serviceIndex).join("/"),
|
|
1118
|
+
path: pathSegments.join("/")
|
|
1119
|
+
};
|
|
1120
|
+
}
|
|
1121
|
+
function safeCapabilityResource(value, service, action) {
|
|
1122
|
+
if (typeof value !== "string" || value.length === 0 || value.length > 1024) return false;
|
|
1123
|
+
if (service === "encryption" && value.startsWith("urn:tinycloud:encryption:")) {
|
|
1124
|
+
if (!/^[A-Za-z0-9_][A-Za-z0-9_.:/-]*$/.test(value) || value.includes("//") || value.split("/").some((segment) => segment === "." || segment === "..")) return false;
|
|
1125
|
+
try {
|
|
1126
|
+
parseNetworkId(value);
|
|
1127
|
+
return true;
|
|
1128
|
+
} catch {
|
|
1129
|
+
return false;
|
|
1130
|
+
}
|
|
1131
|
+
}
|
|
1132
|
+
const parsed = parseCapabilityResource(value, service);
|
|
1133
|
+
return parsed !== void 0 && (!parsed.path.endsWith("/") || service === "kv" && action === "tinycloud.kv/list") && (parsed.path !== "" || service === "kv" && action === "tinycloud.kv/list");
|
|
1134
|
+
}
|
|
1135
|
+
function validatedCapabilityOf(error) {
|
|
1136
|
+
const verdict = authorizationVerdictOf(error);
|
|
1137
|
+
if (verdict !== "unauthenticated" && verdict !== "forbidden") return void 0;
|
|
1138
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1139
|
+
let node = error;
|
|
1140
|
+
for (let depth = 0; depth < MAX_CAUSE_DEPTH && typeof node === "object" && node !== null && !seen.has(node); depth += 1) {
|
|
1141
|
+
seen.add(node);
|
|
1142
|
+
const record = node;
|
|
1143
|
+
const status = errorStatusOf(record);
|
|
1144
|
+
const meta = record.meta;
|
|
1145
|
+
if ((status === 401 || status === 403 || status === void 0 && record.code === ErrorCodes.AUTH_UNAUTHORIZED) && typeof meta === "object" && meta !== null && !Array.isArray(meta)) {
|
|
1146
|
+
const metadata = meta;
|
|
1147
|
+
const { resource, requiredAction } = metadata;
|
|
1148
|
+
if (typeof requiredAction === "string" && grantableActions.has(requiredAction)) {
|
|
1149
|
+
const actionService = requiredAction.slice("tinycloud.".length, requiredAction.indexOf("/"));
|
|
1150
|
+
const explicitService = record.service === void 0 ? metadata.service : record.service;
|
|
1151
|
+
if (safeCapabilityResource(resource, actionService, requiredAction) && (explicitService === void 0 || explicitService === actionService || explicitService === `tinycloud.${actionService}`)) {
|
|
1152
|
+
return { resource, requiredAction };
|
|
1153
|
+
}
|
|
1154
|
+
}
|
|
1155
|
+
}
|
|
1156
|
+
node = record.cause;
|
|
1157
|
+
}
|
|
1158
|
+
return void 0;
|
|
1159
|
+
}
|
|
996
1160
|
var MAX_CAUSE_DEPTH = 8;
|
|
997
1161
|
function errorStatusOf(node) {
|
|
998
1162
|
const meta = node.meta;
|
|
@@ -1740,12 +1904,14 @@ var KVService = class extends BaseService {
|
|
|
1740
1904
|
signal: this.combineSignals(options?.signal)
|
|
1741
1905
|
});
|
|
1742
1906
|
if (!response.ok) {
|
|
1743
|
-
const errorText = await response.text();
|
|
1907
|
+
const errorText = response.status === 401 || response.status === 403 ? await this.readAuthorizationText(response) : await response.text();
|
|
1744
1908
|
if (response.status === 401 || response.status === 403) {
|
|
1745
1909
|
return this.authorizationFailure(
|
|
1746
1910
|
`Failed to batch read ${keys.length} key(s)`,
|
|
1747
1911
|
response,
|
|
1748
|
-
errorText
|
|
1912
|
+
errorText,
|
|
1913
|
+
paths,
|
|
1914
|
+
action
|
|
1749
1915
|
);
|
|
1750
1916
|
}
|
|
1751
1917
|
if (response.status === 413) {
|
|
@@ -1835,7 +2001,7 @@ var KVService = class extends BaseService {
|
|
|
1835
2001
|
return text;
|
|
1836
2002
|
}
|
|
1837
2003
|
}
|
|
1838
|
-
async createSignedReadUrlError(response, key) {
|
|
2004
|
+
async createSignedReadUrlError(response, key, path) {
|
|
1839
2005
|
let errorText = response.statusText;
|
|
1840
2006
|
try {
|
|
1841
2007
|
const text = await response.text();
|
|
@@ -1848,7 +2014,9 @@ var KVService = class extends BaseService {
|
|
|
1848
2014
|
return this.authorizationFailure(
|
|
1849
2015
|
`Failed to create signed read URL for key ${JSON.stringify(key)}`,
|
|
1850
2016
|
response,
|
|
1851
|
-
errorText
|
|
2017
|
+
errorText,
|
|
2018
|
+
[path],
|
|
2019
|
+
KVAction.GET
|
|
1852
2020
|
);
|
|
1853
2021
|
}
|
|
1854
2022
|
const code = response.status === 400 ? ErrorCodes.INVALID_INPUT : ErrorCodes.NETWORK_ERROR;
|
|
@@ -1861,21 +2029,42 @@ var KVService = class extends BaseService {
|
|
|
1861
2029
|
)
|
|
1862
2030
|
);
|
|
1863
2031
|
}
|
|
2032
|
+
/** A known 401/403 keeps its typed status even if reading its body fails. */
|
|
2033
|
+
async readAuthorizationText(response) {
|
|
2034
|
+
try {
|
|
2035
|
+
return await response.text();
|
|
2036
|
+
} catch {
|
|
2037
|
+
return "";
|
|
2038
|
+
}
|
|
2039
|
+
}
|
|
1864
2040
|
/**
|
|
1865
2041
|
* AUTH_UNAUTHORIZED for a 401/403 response. The message keeps the HTTP
|
|
1866
2042
|
* status and the server text (`<context>: <status> - <text>`, the same
|
|
1867
2043
|
* shape as every other KV failure) so callers that rethrow only the message
|
|
1868
2044
|
* still see the status; `meta.status` carries it for typed callers.
|
|
1869
|
-
*
|
|
2045
|
+
* Server hints must match the requested path/action (whether the node sends
|
|
2046
|
+
* a relative path or full resource); metadata uses only the request-derived
|
|
2047
|
+
* canonical resource under the authenticated session's space.
|
|
1870
2048
|
*/
|
|
1871
|
-
authorizationFailure(context, response, errorText, extraMeta = {}) {
|
|
2049
|
+
authorizationFailure(context, response, errorText, paths, expectedAction, extraMeta = {}) {
|
|
1872
2050
|
const { resource, action } = parseAuthError(errorText);
|
|
2051
|
+
const requestedPath = paths.find(
|
|
2052
|
+
(path) => resource === path || resource === `${this.context.session.spaceId}/kv/${path}`
|
|
2053
|
+
);
|
|
2054
|
+
const capability = requestedPath !== void 0 && action === expectedAction ? validatedCapabilityOf({
|
|
2055
|
+
service: "kv",
|
|
2056
|
+
code: ErrorCodes.AUTH_UNAUTHORIZED,
|
|
2057
|
+
meta: {
|
|
2058
|
+
status: response.status,
|
|
2059
|
+
resource: `${this.context.session.spaceId}/kv/${requestedPath}`,
|
|
2060
|
+
requiredAction: action
|
|
2061
|
+
}
|
|
2062
|
+
}) : void 0;
|
|
1873
2063
|
const detail = errorText.trim().length > 0 ? errorText : response.statusText || "authorization failed";
|
|
1874
2064
|
return err(authUnauthorizedError("kv", `${context}: ${response.status} - ${detail}`, {
|
|
1875
2065
|
status: response.status,
|
|
1876
|
-
...
|
|
1877
|
-
...
|
|
1878
|
-
...extraMeta
|
|
2066
|
+
...extraMeta,
|
|
2067
|
+
...capability
|
|
1879
2068
|
}));
|
|
1880
2069
|
}
|
|
1881
2070
|
normalizeSignedReadUrlResponse(data) {
|
|
@@ -1919,13 +2108,24 @@ var KVService = class extends BaseService {
|
|
|
1919
2108
|
);
|
|
1920
2109
|
if (!response.ok) {
|
|
1921
2110
|
if (response.status === 401 || response.status === 403) {
|
|
1922
|
-
const errorText2 = await
|
|
2111
|
+
const errorText2 = await this.readAuthorizationText(response);
|
|
1923
2112
|
const permissionHint = parsePermissionHintFromErrorText(errorText2);
|
|
2113
|
+
const structuredCapability = permissionHint?.service === "tinycloud.kv" && permissionHint.space === this.context.session.spaceId && permissionHint.path === path ? validatedCapabilityOf({
|
|
2114
|
+
service: "kv",
|
|
2115
|
+
code: ErrorCodes.AUTH_UNAUTHORIZED,
|
|
2116
|
+
meta: {
|
|
2117
|
+
status: response.status,
|
|
2118
|
+
resource: `${this.context.session.spaceId}/kv/${path}`,
|
|
2119
|
+
requiredAction: KVAction.GET
|
|
2120
|
+
}
|
|
2121
|
+
}) : void 0;
|
|
1924
2122
|
return this.authorizationFailure(
|
|
1925
2123
|
`Failed to get key ${JSON.stringify(key)}`,
|
|
1926
2124
|
response,
|
|
1927
2125
|
errorText2,
|
|
1928
|
-
|
|
2126
|
+
[path],
|
|
2127
|
+
KVAction.GET,
|
|
2128
|
+
structuredCapability ? { permissionHint, ...structuredCapability } : {}
|
|
1929
2129
|
);
|
|
1930
2130
|
}
|
|
1931
2131
|
if (response.status === 404) {
|
|
@@ -2002,7 +2202,9 @@ var KVService = class extends BaseService {
|
|
|
2002
2202
|
return this.authorizationFailure(
|
|
2003
2203
|
`Failed to put key ${JSON.stringify(key)}`,
|
|
2004
2204
|
response,
|
|
2005
|
-
await
|
|
2205
|
+
await this.readAuthorizationText(response),
|
|
2206
|
+
[path],
|
|
2207
|
+
KVAction.PUT
|
|
2006
2208
|
);
|
|
2007
2209
|
}
|
|
2008
2210
|
if (!response.ok) {
|
|
@@ -2131,7 +2333,9 @@ var KVService = class extends BaseService {
|
|
|
2131
2333
|
return this.authorizationFailure(
|
|
2132
2334
|
`Failed to batch put ${items.length} key(s)`,
|
|
2133
2335
|
response,
|
|
2134
|
-
errorText
|
|
2336
|
+
errorText,
|
|
2337
|
+
paths,
|
|
2338
|
+
KVAction.PUT
|
|
2135
2339
|
);
|
|
2136
2340
|
}
|
|
2137
2341
|
const quotaError = this.handleQuotaErrorResponse(
|
|
@@ -2252,11 +2456,13 @@ var KVService = class extends BaseService {
|
|
|
2252
2456
|
}
|
|
2253
2457
|
);
|
|
2254
2458
|
if (!response.ok) {
|
|
2255
|
-
if (response.status === 401) {
|
|
2459
|
+
if (response.status === 401 || response.status === 403) {
|
|
2256
2460
|
return this.authorizationFailure(
|
|
2257
2461
|
"Failed to list keys",
|
|
2258
2462
|
response,
|
|
2259
|
-
await
|
|
2463
|
+
await this.readAuthorizationText(response),
|
|
2464
|
+
[listPath],
|
|
2465
|
+
KVAction.LIST
|
|
2260
2466
|
);
|
|
2261
2467
|
}
|
|
2262
2468
|
const errorText = await response.text();
|
|
@@ -2305,11 +2511,13 @@ var KVService = class extends BaseService {
|
|
|
2305
2511
|
options?.ifMatch === void 0 ? void 0 : { "if-match": options.ifMatch }
|
|
2306
2512
|
);
|
|
2307
2513
|
if (!response.ok) {
|
|
2308
|
-
if (response.status === 401) {
|
|
2514
|
+
if (response.status === 401 || response.status === 403) {
|
|
2309
2515
|
return this.authorizationFailure(
|
|
2310
2516
|
`Failed to delete key ${JSON.stringify(key)}`,
|
|
2311
2517
|
response,
|
|
2312
|
-
await
|
|
2518
|
+
await this.readAuthorizationText(response),
|
|
2519
|
+
[path],
|
|
2520
|
+
KVAction.DELETE
|
|
2313
2521
|
);
|
|
2314
2522
|
}
|
|
2315
2523
|
if (response.status === 404) {
|
|
@@ -2367,11 +2575,13 @@ var KVService = class extends BaseService {
|
|
|
2367
2575
|
options?.signal
|
|
2368
2576
|
);
|
|
2369
2577
|
if (!response.ok) {
|
|
2370
|
-
if (response.status === 401) {
|
|
2578
|
+
if (response.status === 401 || response.status === 403) {
|
|
2371
2579
|
return this.authorizationFailure(
|
|
2372
2580
|
`Failed to get metadata for key ${JSON.stringify(key)}`,
|
|
2373
2581
|
response,
|
|
2374
|
-
await
|
|
2582
|
+
await this.readAuthorizationText(response),
|
|
2583
|
+
[path],
|
|
2584
|
+
KVAction.HEAD
|
|
2375
2585
|
);
|
|
2376
2586
|
}
|
|
2377
2587
|
if (response.status === 404) {
|
|
@@ -2438,7 +2648,7 @@ var KVService = class extends BaseService {
|
|
|
2438
2648
|
signal: this.combineSignals(options?.signal)
|
|
2439
2649
|
});
|
|
2440
2650
|
if (!response.ok) {
|
|
2441
|
-
return this.createSignedReadUrlError(response, key);
|
|
2651
|
+
return this.createSignedReadUrlError(response, key, path);
|
|
2442
2652
|
}
|
|
2443
2653
|
const signedUrl = this.normalizeSignedReadUrlResponse(
|
|
2444
2654
|
await response.json()
|
|
@@ -2676,14 +2886,15 @@ var SQLService = class extends BaseService {
|
|
|
2676
2886
|
};
|
|
2677
2887
|
if (options?.maxRows !== void 0) body.maxRows = options.maxRows;
|
|
2678
2888
|
if (options?.maxBytes !== void 0) body.maxBytes = options.maxBytes;
|
|
2889
|
+
const action = this.actionForSql(sql, SQLAction.READ);
|
|
2679
2890
|
const response = await this.invokeSQL(
|
|
2680
2891
|
dbName,
|
|
2681
|
-
|
|
2892
|
+
action,
|
|
2682
2893
|
body,
|
|
2683
2894
|
options?.signal
|
|
2684
2895
|
);
|
|
2685
2896
|
if (!response.ok) {
|
|
2686
|
-
return this.handleErrorResponse(response, "query");
|
|
2897
|
+
return this.handleErrorResponse(response, "query", dbName, [action]);
|
|
2687
2898
|
}
|
|
2688
2899
|
const data = await response.json();
|
|
2689
2900
|
return ok(data);
|
|
@@ -2712,14 +2923,15 @@ var SQLService = class extends BaseService {
|
|
|
2712
2923
|
(statement) => this.actionForSql(statement, SQLAction.SCHEMA)
|
|
2713
2924
|
)
|
|
2714
2925
|
];
|
|
2926
|
+
const requestedActions = this.dedupeActions(actions);
|
|
2715
2927
|
const response = await this.invokeSQL(
|
|
2716
2928
|
dbName,
|
|
2717
|
-
|
|
2929
|
+
requestedActions,
|
|
2718
2930
|
body,
|
|
2719
2931
|
options?.signal
|
|
2720
2932
|
);
|
|
2721
2933
|
if (!response.ok) {
|
|
2722
|
-
return this.handleErrorResponse(response, "execute");
|
|
2934
|
+
return this.handleErrorResponse(response, "execute", dbName, requestedActions);
|
|
2723
2935
|
}
|
|
2724
2936
|
const data = await response.json();
|
|
2725
2937
|
return ok(data);
|
|
@@ -2734,14 +2946,15 @@ var SQLService = class extends BaseService {
|
|
|
2734
2946
|
return err(authRequiredError("sql"));
|
|
2735
2947
|
}
|
|
2736
2948
|
try {
|
|
2949
|
+
const requestedActions = this.actionsForSqlBatch(statements);
|
|
2737
2950
|
const response = await this.invokeSQL(
|
|
2738
2951
|
dbName,
|
|
2739
|
-
|
|
2952
|
+
requestedActions,
|
|
2740
2953
|
{ action: "batch", statements },
|
|
2741
2954
|
options?.signal
|
|
2742
2955
|
);
|
|
2743
2956
|
if (!response.ok) {
|
|
2744
|
-
return this.handleErrorResponse(response, "batch");
|
|
2957
|
+
return this.handleErrorResponse(response, "batch", dbName, requestedActions);
|
|
2745
2958
|
}
|
|
2746
2959
|
const data = await response.json();
|
|
2747
2960
|
return ok(data);
|
|
@@ -2763,7 +2976,7 @@ var SQLService = class extends BaseService {
|
|
|
2763
2976
|
options?.signal
|
|
2764
2977
|
);
|
|
2765
2978
|
if (!response.ok) {
|
|
2766
|
-
return this.handleErrorResponse(response, "executeStatement");
|
|
2979
|
+
return this.handleErrorResponse(response, "executeStatement", dbName, [SQLAction.WRITE]);
|
|
2767
2980
|
}
|
|
2768
2981
|
const data = await response.json();
|
|
2769
2982
|
return ok(data);
|
|
@@ -2785,7 +2998,7 @@ var SQLService = class extends BaseService {
|
|
|
2785
2998
|
options?.signal
|
|
2786
2999
|
);
|
|
2787
3000
|
if (!response.ok) {
|
|
2788
|
-
return this.handleErrorResponse(response, "export");
|
|
3001
|
+
return this.handleErrorResponse(response, "export", dbName, [SQLAction.READ]);
|
|
2789
3002
|
}
|
|
2790
3003
|
const resp = response;
|
|
2791
3004
|
if (typeof resp.blob === "function") {
|
|
@@ -2919,7 +3132,7 @@ var SQLService = class extends BaseService {
|
|
|
2919
3132
|
}))
|
|
2920
3133
|
);
|
|
2921
3134
|
}
|
|
2922
|
-
async handleErrorResponse(response, operation) {
|
|
3135
|
+
async handleErrorResponse(response, operation, dbName, requestedActions) {
|
|
2923
3136
|
const errorText = await response.text();
|
|
2924
3137
|
const meta = responseErrorMeta(response.status, response.statusText, errorText);
|
|
2925
3138
|
if (response.status === 402) {
|
|
@@ -2938,9 +3151,11 @@ var SQLService = class extends BaseService {
|
|
|
2938
3151
|
errorBody
|
|
2939
3152
|
);
|
|
2940
3153
|
if (response.status === 401) {
|
|
2941
|
-
const {
|
|
2942
|
-
if (action
|
|
2943
|
-
|
|
3154
|
+
const { action } = parseAuthError(errorText);
|
|
3155
|
+
if (action && requestedActions.includes(action)) {
|
|
3156
|
+
meta.requiredAction = action;
|
|
3157
|
+
meta.resource = `${this.context.session.spaceId}/sql/${dbName}`;
|
|
3158
|
+
}
|
|
2944
3159
|
}
|
|
2945
3160
|
return err(
|
|
2946
3161
|
serviceError(errorCode, message, "sql", { meta })
|
|
@@ -5919,103 +6134,6 @@ function canonicalHashHex(sha256, value) {
|
|
|
5919
6134
|
return hexEncode2(sha256(utf8Encode(canonical)));
|
|
5920
6135
|
}
|
|
5921
6136
|
|
|
5922
|
-
// src/encryption/networkId.ts
|
|
5923
|
-
var URN_PREFIX = "urn:tinycloud:encryption:";
|
|
5924
|
-
var NETWORK_NAME_RE = /^[a-z0-9][a-z0-9-]*$/;
|
|
5925
|
-
var PKH_EIP155_DID_RE = /^did:pkh:eip155:(\d+):(0x[a-fA-F0-9]{40})$/;
|
|
5926
|
-
var NetworkIdError = class extends Error {
|
|
5927
|
-
constructor(message) {
|
|
5928
|
-
super(message);
|
|
5929
|
-
this.name = "NetworkIdError";
|
|
5930
|
-
}
|
|
5931
|
-
};
|
|
5932
|
-
function parseNetworkId(networkId) {
|
|
5933
|
-
if (typeof networkId !== "string" || networkId.length === 0) {
|
|
5934
|
-
throw new NetworkIdError("networkId must be a non-empty string");
|
|
5935
|
-
}
|
|
5936
|
-
if (!networkId.startsWith(URN_PREFIX)) {
|
|
5937
|
-
throw new NetworkIdError(
|
|
5938
|
-
`networkId must start with ${URN_PREFIX} (got ${JSON.stringify(networkId)})`
|
|
5939
|
-
);
|
|
5940
|
-
}
|
|
5941
|
-
const body = networkId.slice(URN_PREFIX.length);
|
|
5942
|
-
const lastColon = body.lastIndexOf(":");
|
|
5943
|
-
if (lastColon <= 0 || lastColon === body.length - 1) {
|
|
5944
|
-
throw new NetworkIdError(
|
|
5945
|
-
`networkId missing ownerDid or name segment (got ${JSON.stringify(networkId)})`
|
|
5946
|
-
);
|
|
5947
|
-
}
|
|
5948
|
-
const ownerDid = body.slice(0, lastColon);
|
|
5949
|
-
const name = body.slice(lastColon + 1);
|
|
5950
|
-
if (!ownerDid.startsWith("did:")) {
|
|
5951
|
-
throw new NetworkIdError(
|
|
5952
|
-
`networkId ownerDid must be a DID (got ${JSON.stringify(ownerDid)})`
|
|
5953
|
-
);
|
|
5954
|
-
}
|
|
5955
|
-
const didParts = ownerDid.split(":");
|
|
5956
|
-
if (didParts.length < 3 || didParts.some((p) => p.length === 0)) {
|
|
5957
|
-
throw new NetworkIdError(
|
|
5958
|
-
`networkId ownerDid is not a well-formed DID (got ${JSON.stringify(ownerDid)})`
|
|
5959
|
-
);
|
|
5960
|
-
}
|
|
5961
|
-
if (!NETWORK_NAME_RE.test(name)) {
|
|
5962
|
-
throw new NetworkIdError(
|
|
5963
|
-
`networkId name ${JSON.stringify(name)} must match ${NETWORK_NAME_RE.source}`
|
|
5964
|
-
);
|
|
5965
|
-
}
|
|
5966
|
-
return { networkId, ownerDid, name };
|
|
5967
|
-
}
|
|
5968
|
-
function buildNetworkId(ownerDid, name) {
|
|
5969
|
-
if (typeof ownerDid !== "string" || !ownerDid.startsWith("did:")) {
|
|
5970
|
-
throw new NetworkIdError("ownerDid must be a DID");
|
|
5971
|
-
}
|
|
5972
|
-
if (typeof name !== "string" || !NETWORK_NAME_RE.test(name)) {
|
|
5973
|
-
throw new NetworkIdError(
|
|
5974
|
-
`network name ${JSON.stringify(name)} must match ${NETWORK_NAME_RE.source}`
|
|
5975
|
-
);
|
|
5976
|
-
}
|
|
5977
|
-
const networkId = `${URN_PREFIX}${ownerDid}:${name}`;
|
|
5978
|
-
parseNetworkId(networkId);
|
|
5979
|
-
return networkId;
|
|
5980
|
-
}
|
|
5981
|
-
function isNetworkId(networkId) {
|
|
5982
|
-
if (typeof networkId !== "string") {
|
|
5983
|
-
return false;
|
|
5984
|
-
}
|
|
5985
|
-
try {
|
|
5986
|
-
parseNetworkId(networkId);
|
|
5987
|
-
return true;
|
|
5988
|
-
} catch {
|
|
5989
|
-
return false;
|
|
5990
|
-
}
|
|
5991
|
-
}
|
|
5992
|
-
function parsePkhOwnerDid(ownerDid) {
|
|
5993
|
-
const match = ownerDid.match(PKH_EIP155_DID_RE);
|
|
5994
|
-
if (!match) return null;
|
|
5995
|
-
return {
|
|
5996
|
-
chainId: match[1],
|
|
5997
|
-
address: match[2].toLowerCase()
|
|
5998
|
-
};
|
|
5999
|
-
}
|
|
6000
|
-
function ownerDidMatches(a, b) {
|
|
6001
|
-
const aPkh = parsePkhOwnerDid(a);
|
|
6002
|
-
const bPkh = parsePkhOwnerDid(b);
|
|
6003
|
-
if (aPkh && bPkh) {
|
|
6004
|
-
return aPkh.chainId === bPkh.chainId && aPkh.address === bPkh.address;
|
|
6005
|
-
}
|
|
6006
|
-
return a === b;
|
|
6007
|
-
}
|
|
6008
|
-
function networkDiscoveryKey(name) {
|
|
6009
|
-
if (!NETWORK_NAME_RE.test(name)) {
|
|
6010
|
-
throw new NetworkIdError(
|
|
6011
|
-
`network name ${JSON.stringify(name)} must match ${NETWORK_NAME_RE.source}`
|
|
6012
|
-
);
|
|
6013
|
-
}
|
|
6014
|
-
return `.well-known/encryption/network/${name}`;
|
|
6015
|
-
}
|
|
6016
|
-
var ENCRYPTION_NETWORK_URN_PREFIX = URN_PREFIX;
|
|
6017
|
-
var NETWORK_NAME_PATTERN = NETWORK_NAME_RE;
|
|
6018
|
-
|
|
6019
6137
|
// src/encryption/types.ts
|
|
6020
6138
|
var DEFAULT_ENCRYPTION_ALG = "x25519-aes256gcm/v1";
|
|
6021
6139
|
var ENVELOPE_VERSION = 1;
|
|
@@ -6958,6 +7076,7 @@ export {
|
|
|
6958
7076
|
ok,
|
|
6959
7077
|
openWrappedKey,
|
|
6960
7078
|
parseAuthError,
|
|
7079
|
+
parseCapabilityResource,
|
|
6961
7080
|
parseNetworkId,
|
|
6962
7081
|
parsePermissionHint,
|
|
6963
7082
|
parsePermissionHintFromErrorText,
|
|
@@ -6983,6 +7102,7 @@ export {
|
|
|
6983
7102
|
validateServiceResponseEvent,
|
|
6984
7103
|
validateServiceSession,
|
|
6985
7104
|
validateTelemetrySpanEvent,
|
|
7105
|
+
validatedCapabilityOf,
|
|
6986
7106
|
verifyDecryptResponse,
|
|
6987
7107
|
wrapError
|
|
6988
7108
|
};
|