@oxy.so/core 1.0.1 → 1.1.2
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/cjs/.tsbuildinfo +1 -1
- package/dist/cjs/OxyServices.errors.js +28 -1
- package/dist/cjs/i18n/locales/en-US.json +14 -1
- package/dist/cjs/i18n/locales/es-ES.json +14 -1
- package/dist/cjs/i18n/locales/locales/en-US.json +14 -1
- package/dist/cjs/i18n/locales/locales/es-ES.json +14 -1
- package/dist/cjs/mixins/OxyServices.agency.js +113 -0
- package/dist/cjs/mixins/OxyServices.assets.js +90 -0
- package/dist/cjs/mixins/OxyServices.connectedApps.js +20 -3
- package/dist/cjs/mixins/OxyServices.utility.js +1 -21
- package/dist/cjs/mixins/index.js +3 -4
- package/dist/cjs/server/index.js +6 -1
- package/dist/cjs/server/traffic.js +107 -0
- package/dist/cjs/server/trafficNodeHttp.js +86 -0
- package/dist/cjs/utils/cache.js +28 -19
- package/dist/cjs/utils/textNormalization.js +1 -1
- package/dist/esm/.tsbuildinfo +1 -1
- package/dist/esm/OxyServices.errors.js +26 -0
- package/dist/esm/i18n/locales/en-US.json +14 -1
- package/dist/esm/i18n/locales/es-ES.json +14 -1
- package/dist/esm/i18n/locales/locales/en-US.json +14 -1
- package/dist/esm/i18n/locales/locales/es-ES.json +14 -1
- package/dist/esm/mixins/OxyServices.agency.js +110 -0
- package/dist/esm/mixins/OxyServices.assets.js +91 -1
- package/dist/esm/mixins/OxyServices.connectedApps.js +20 -3
- package/dist/esm/mixins/OxyServices.utility.js +1 -21
- package/dist/esm/mixins/index.js +3 -4
- package/dist/esm/server/index.js +2 -0
- package/dist/esm/server/traffic.js +104 -0
- package/dist/esm/server/trafficNodeHttp.js +79 -0
- package/dist/esm/utils/cache.js +28 -19
- package/dist/esm/utils/textNormalization.js +1 -1
- package/dist/types/.tsbuildinfo +1 -1
- package/dist/types/OxyServices.errors.d.ts +24 -0
- package/dist/types/index.d.ts +2 -1
- package/dist/types/mixins/OxyServices.agency.d.ts +135 -0
- package/dist/types/mixins/OxyServices.assets.d.ts +43 -1
- package/dist/types/mixins/OxyServices.connectedApps.d.ts +15 -0
- package/dist/types/mixins/OxyServices.utility.d.ts +0 -9
- package/dist/types/mixins/index.d.ts +2 -2
- package/dist/types/models/interfaces.d.ts +26 -0
- package/dist/types/server/index.d.ts +3 -0
- package/dist/types/server/traffic.d.ts +27 -0
- package/dist/types/server/trafficNodeHttp.d.ts +6 -0
- package/dist/types/utils/cache.d.ts +1 -4
- package/dist/types/utils/textNormalization.d.ts +1 -1
- package/package.json +4 -4
- package/src/OxyServices.errors.ts +36 -0
- package/src/i18n/locales/en-US.json +14 -1
- package/src/i18n/locales/es-ES.json +14 -1
- package/src/index.ts +15 -0
- package/src/mixins/OxyServices.agency.ts +277 -0
- package/src/mixins/OxyServices.assets.ts +105 -2
- package/src/mixins/OxyServices.connectedApps.ts +42 -4
- package/src/mixins/OxyServices.utility.ts +1 -26
- package/src/mixins/__tests__/OxyServices.serviceLinkedDownloadUrl.test.ts +139 -0
- package/src/mixins/__tests__/agency.test.ts +120 -0
- package/src/mixins/__tests__/connectedApps.test.ts +23 -0
- package/src/mixins/index.ts +4 -5
- package/src/models/interfaces.ts +27 -0
- package/src/server/__tests__/traffic.test.ts +49 -0
- package/src/server/__tests__/trafficNodeHttp.test.ts +38 -0
- package/src/server/index.ts +5 -0
- package/src/server/traffic.ts +116 -0
- package/src/server/trafficNodeHttp.ts +69 -0
- package/src/utils/__tests__/cacheLifecycle.test.ts +65 -0
- package/src/utils/cache.ts +22 -20
- package/src/utils/textNormalization.ts +1 -1
- package/dist/cjs/mixins/OxyServices.links.js +0 -72
- package/dist/esm/mixins/OxyServices.links.js +0 -69
- package/dist/types/mixins/OxyServices.links.d.ts +0 -104
- package/src/mixins/OxyServices.links.ts +0 -107
- package/src/mixins/__tests__/OxyServices.links.test.ts +0 -154
|
@@ -79,6 +79,30 @@ export declare class ServiceAssetMetadataError extends Error {
|
|
|
79
79
|
readonly cause?: unknown;
|
|
80
80
|
constructor(unresolvedIds: string[], statuses: number[], cause?: unknown);
|
|
81
81
|
}
|
|
82
|
+
/**
|
|
83
|
+
* A chunk of `POST /assets/service/linked-url` failed, so the SDK cannot say
|
|
84
|
+
* whether those ids have URLs.
|
|
85
|
+
*
|
|
86
|
+
* Its own class rather than a reuse of {@link ServiceAssetMetadataError}, and
|
|
87
|
+
* deliberately WITHOUT that one's `{ partial: true }` escape hatch, because the
|
|
88
|
+
* two mistakes cost different things. Reading a failed metadata lookup as
|
|
89
|
+
* "absent" embedded a media item with no hash. Reading a failed DOWNLOAD mint as
|
|
90
|
+
* "absent" tells a buyer who paid that the file they own is not there — and
|
|
91
|
+
* "not there" is already this route's answer for "not yours", so a best-effort
|
|
92
|
+
* mode would make a throttled request indistinguishable from a refusal. There is
|
|
93
|
+
* no download path that legitimately wants that, so there is no option to ask
|
|
94
|
+
* for it.
|
|
95
|
+
*/
|
|
96
|
+
export declare class ServiceLinkedDownloadUrlError extends Error {
|
|
97
|
+
readonly code = "SERVICE_LINKED_DOWNLOAD_URL_UNRESOLVED";
|
|
98
|
+
/** Every id belonging to a chunk whose request failed. */
|
|
99
|
+
readonly unresolvedIds: string[];
|
|
100
|
+
/** HTTP statuses observed across the failed chunks (deduped, ascending). */
|
|
101
|
+
readonly statuses: number[];
|
|
102
|
+
/** The first underlying transport/API failure — see the sibling class. */
|
|
103
|
+
readonly cause?: unknown;
|
|
104
|
+
constructor(unresolvedIds: string[], statuses: number[], cause?: unknown);
|
|
105
|
+
}
|
|
82
106
|
export declare class OxyAuthenticationTimeoutError extends OxyAuthenticationError {
|
|
83
107
|
constructor(operationName: string, timeoutMs: number);
|
|
84
108
|
}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -38,7 +38,8 @@ export { getCanonicalUserHandle, getNormalizedUserHandle, } from './utils/userHa
|
|
|
38
38
|
export type { CanonicalUserHandleInput, UserHandleInput } from './utils/userHandle';
|
|
39
39
|
export { normalizeProfileLinks } from './utils/profileLinks';
|
|
40
40
|
export type { ProfileLink, ProfileLinkMetadata } from './utils/profileLinks';
|
|
41
|
-
export type { PublicApplication, ConnectedApp, } from './mixins/OxyServices.connectedApps';
|
|
41
|
+
export type { PublicApplication, ConnectedApp, ConnectedMcpClient, } from './mixins/OxyServices.connectedApps';
|
|
42
|
+
export type { AccountCapabilityPolicy, AvailableCapabilityCatalog, CapabilityExecutionAuthorization, CreateDelegationGrantInput, DelegationCatalogBinding, DelegationGrantView, PutAccountCapabilityPolicyInput, UpdateDelegationGrantInput, } from './mixins/OxyServices.agency';
|
|
42
43
|
export type { StoreCategory, StoreRating, StoreListingSummary, StoreListingDetail, StoreScreenshot, StoreScreenshotPlatform, StoreReview, StoreOwnReview, WriteStoreReviewInput, StoreListingStatus, PublisherListing, WriteListingInput, AddScreenshotInput, UpdateScreenshotInput, StorePage, StorePageOptions, StoreReviewsOptions, } from './mixins/OxyServices.store';
|
|
43
44
|
export type { AccountKind, AccountCategoryId, AccountRelationship, AccountRole, AccountMemberStatus, AccountMemberSource, AccountMember, AccountNode, ListAccountsOptions, CreateAccountInput, UpdateAccountInput, ProvisionChannelInput, ProvisionChannelMemberInput, ProvisionChannelResult, InviteAccountMemberInput, UpdateAccountMemberInput, TransferAccountOwnershipInput, AccountSuccessResult, SwitchAccountResult, Application, ApplicationType, ApplicationStatus, ApplicationCredential, ApplicationCredentialType, ApplicationCredentialStatus, ApplicationEnvironment, CreateApplicationInput, UpdateApplicationInput, CreateApplicationCredentialInput, RotateApplicationCredentialInput, ApplicationCredentialWithSecret, RotateApplicationCredentialResult, ApplicationUsagePeriod, ApplicationUsageSummary, ApplicationUsageByDay, ApplicationUsageByEndpoint, ApplicationUsageStats, } from './mixins/OxyServices.accounts';
|
|
44
45
|
export { ACCOUNT_CATEGORY_IDS, MAX_ACCOUNT_CATEGORIES, SELECTABLE_ACCOUNT_CATEGORY_IDS, isSelectableAccountCategoryId, kindAcceptsAccountCategories, } from './mixins/OxyServices.accounts';
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Native Alia and digital-agent authority.
|
|
3
|
+
*
|
|
4
|
+
* These methods manage Oxy-owned delegation grants, account autonomy policy,
|
|
5
|
+
* execution authorizations and their audit trail. They deliberately use the
|
|
6
|
+
* signed-in account session: capability tickets and app service credentials
|
|
7
|
+
* stay on the server and are never exposed to Settings clients.
|
|
8
|
+
*/
|
|
9
|
+
import type { AppCapabilityCatalog, AuditEvent, AutonomyLevel, CapabilityCatalogBinding, CapabilityPackage, DelegationGrant, GrantLimit, ResourceRef, ToolGrantOverride } from '@oxy.so/contracts';
|
|
10
|
+
import type { OxyServicesBase } from '../OxyServices.base';
|
|
11
|
+
export type DelegationCatalogBinding = CapabilityCatalogBinding;
|
|
12
|
+
export type DelegationGrantView = DelegationGrant;
|
|
13
|
+
export interface CreateDelegationGrantInput {
|
|
14
|
+
ownerAccountId: string;
|
|
15
|
+
actorAccountId: string;
|
|
16
|
+
resource: ResourceRef;
|
|
17
|
+
capabilityPackages: CapabilityPackage[];
|
|
18
|
+
capabilities: string[];
|
|
19
|
+
toolOverrides?: ToolGrantOverride[];
|
|
20
|
+
limits?: GrantLimit[];
|
|
21
|
+
maximumAutonomy: AutonomyLevel;
|
|
22
|
+
canRedelegate?: boolean;
|
|
23
|
+
expiresAt?: string | null;
|
|
24
|
+
}
|
|
25
|
+
export type UpdateDelegationGrantInput = Pick<CreateDelegationGrantInput, 'capabilityPackages' | 'capabilities' | 'toolOverrides' | 'limits' | 'maximumAutonomy' | 'canRedelegate' | 'expiresAt'>;
|
|
26
|
+
export interface AvailableCapabilityCatalog {
|
|
27
|
+
id: string;
|
|
28
|
+
appId: string;
|
|
29
|
+
version: string;
|
|
30
|
+
digest: string;
|
|
31
|
+
audience: string;
|
|
32
|
+
catalog: AppCapabilityCatalog;
|
|
33
|
+
}
|
|
34
|
+
export interface AccountCapabilityPolicy {
|
|
35
|
+
id: string;
|
|
36
|
+
accountId: string;
|
|
37
|
+
appSlug: string;
|
|
38
|
+
maximumAutonomy: AutonomyLevel;
|
|
39
|
+
deniedCapabilities: string[];
|
|
40
|
+
createdAt: string;
|
|
41
|
+
updatedAt: string;
|
|
42
|
+
}
|
|
43
|
+
export interface PutAccountCapabilityPolicyInput {
|
|
44
|
+
accountId: string;
|
|
45
|
+
maximumAutonomy: AutonomyLevel;
|
|
46
|
+
deniedCapabilities: string[];
|
|
47
|
+
}
|
|
48
|
+
export interface CapabilityExecutionAuthorization {
|
|
49
|
+
id: string;
|
|
50
|
+
kind: 'direct_request' | 'automation';
|
|
51
|
+
requesterAccountId: string;
|
|
52
|
+
ownerAccountId: string;
|
|
53
|
+
coordinatorApplicationId: string;
|
|
54
|
+
coordinatorCredentialId: string;
|
|
55
|
+
actorType: 'alia' | 'agent';
|
|
56
|
+
actorAccountId: string | null;
|
|
57
|
+
resourceApp: string;
|
|
58
|
+
effectiveAccountId: string;
|
|
59
|
+
resourceType: string;
|
|
60
|
+
resourceKey: string;
|
|
61
|
+
tool: string;
|
|
62
|
+
runId: string | null;
|
|
63
|
+
stepId: string | null;
|
|
64
|
+
automationId: string | null;
|
|
65
|
+
maximumAutonomy: AutonomyLevel;
|
|
66
|
+
limits: GrantLimit[];
|
|
67
|
+
expiresAt: string;
|
|
68
|
+
revokedAt: string | null;
|
|
69
|
+
createdAt: string;
|
|
70
|
+
updatedAt: string;
|
|
71
|
+
}
|
|
72
|
+
export declare function OxyServicesAgencyMixin<T extends typeof OxyServicesBase>(Base: T): {
|
|
73
|
+
new (...args: any[]): {
|
|
74
|
+
listAvailableCapabilityCatalogs(accountId: string): Promise<AvailableCapabilityCatalog[]>;
|
|
75
|
+
listDelegationGrants(ownerAccountId: string): Promise<DelegationGrantView[]>;
|
|
76
|
+
createDelegationGrant(input: CreateDelegationGrantInput): Promise<DelegationGrantView>;
|
|
77
|
+
revokeDelegationGrant(grantId: string, ownerAccountId: string): Promise<void>;
|
|
78
|
+
updateDelegationGrant(grantId: string, ownerAccountId: string, input: UpdateDelegationGrantInput): Promise<DelegationGrantView>;
|
|
79
|
+
listAccountCapabilityPolicies(accountId: string): Promise<AccountCapabilityPolicy[]>;
|
|
80
|
+
putAccountCapabilityPolicy(appId: string, input: PutAccountCapabilityPolicyInput): Promise<AccountCapabilityPolicy>;
|
|
81
|
+
deleteAccountCapabilityPolicy(appId: string, accountId: string): Promise<void>;
|
|
82
|
+
listCapabilityExecutionAuthorizations(ownerAccountId: string): Promise<CapabilityExecutionAuthorization[]>;
|
|
83
|
+
revokeCapabilityExecutionAuthorization(authorizationId: string, ownerAccountId: string): Promise<void>;
|
|
84
|
+
listCapabilityAuditEvents(accountId: string): Promise<AuditEvent[]>;
|
|
85
|
+
httpService: import("../HttpService").HttpService;
|
|
86
|
+
cloudURL: string;
|
|
87
|
+
config: import("../OxyServices.base").OxyConfig;
|
|
88
|
+
__resetTokensForTests(): void;
|
|
89
|
+
makeRequest<T_1>(method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE", url: string, data?: any, options?: import("../HttpService").RequestOptions): Promise<T_1>;
|
|
90
|
+
getBaseURL(): string;
|
|
91
|
+
getClient(): import("../HttpService").HttpService;
|
|
92
|
+
createLinkedClient(config: import("../OxyServices.base").OxyConfig): import("..").LinkedHttpClient;
|
|
93
|
+
getMetrics(): {
|
|
94
|
+
totalRequests: number;
|
|
95
|
+
successfulRequests: number;
|
|
96
|
+
failedRequests: number;
|
|
97
|
+
cacheHits: number;
|
|
98
|
+
cacheMisses: number;
|
|
99
|
+
averageResponseTime: number;
|
|
100
|
+
};
|
|
101
|
+
clearCache(): void;
|
|
102
|
+
clearCacheEntry(key: string): void;
|
|
103
|
+
clearCacheByPrefix(prefix: string): number;
|
|
104
|
+
getCacheStats(): {
|
|
105
|
+
size: number;
|
|
106
|
+
hits: number;
|
|
107
|
+
misses: number;
|
|
108
|
+
hitRate: number;
|
|
109
|
+
};
|
|
110
|
+
getCloudURL(): string;
|
|
111
|
+
setTokens(accessToken: string): void;
|
|
112
|
+
clearTokens(): void;
|
|
113
|
+
onTokensChanged(listener: (accessToken: string | null) => void): () => void;
|
|
114
|
+
_cachedUserId: string | null | undefined;
|
|
115
|
+
_cachedAccessToken: string | null;
|
|
116
|
+
getCurrentUserId(): string | null;
|
|
117
|
+
hasValidToken(): boolean;
|
|
118
|
+
getAccessToken(): string | null;
|
|
119
|
+
getAccessTokenExpiry(): number | null;
|
|
120
|
+
waitForAuth(timeoutMs?: number): Promise<boolean>;
|
|
121
|
+
withAuthRetry<T_1>(operation: () => Promise<T_1>, operationName: string, options?: {
|
|
122
|
+
maxRetries?: number;
|
|
123
|
+
retryDelay?: number;
|
|
124
|
+
authTimeoutMs?: number;
|
|
125
|
+
}): Promise<T_1>;
|
|
126
|
+
validate(): Promise<boolean>;
|
|
127
|
+
handleError(error: unknown): Error;
|
|
128
|
+
healthCheck(): Promise<{
|
|
129
|
+
status: string;
|
|
130
|
+
users?: number;
|
|
131
|
+
timestamp?: string;
|
|
132
|
+
[key: string]: any;
|
|
133
|
+
}>;
|
|
134
|
+
};
|
|
135
|
+
} & T;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AccountStorageUsageResponse, AssetUploadInput, AssetUrlResponse, AssetVariant, BatchFileAccessResponse, ServiceAssetMetadata, ServiceAssetMetadataBySha } from '../models/interfaces';
|
|
1
|
+
import type { AccountStorageUsageResponse, AssetUploadInput, AssetUrlResponse, AssetVariant, BatchFileAccessResponse, ServiceAssetMetadata, ServiceAssetMetadataBySha, ServiceLinkedDownloadUrl } from '../models/interfaces';
|
|
2
2
|
import type { OxyServicesBase } from '../OxyServices.base';
|
|
3
3
|
export declare function OxyServicesAssetsMixin<T extends typeof OxyServicesBase>(Base: T): {
|
|
4
4
|
new (...args: any[]): {
|
|
@@ -181,6 +181,48 @@ export declare function OxyServicesAssetsMixin<T extends typeof OxyServicesBase>
|
|
|
181
181
|
getServiceAssetMetadataByIds(ids: string[], options?: {
|
|
182
182
|
partial?: boolean;
|
|
183
183
|
}): Promise<ServiceAssetMetadata[]>;
|
|
184
|
+
/**
|
|
185
|
+
* Mint short-lived direct download URLs for files the calling application's
|
|
186
|
+
* own users attached to it, via `POST /assets/service/linked-url`.
|
|
187
|
+
*
|
|
188
|
+
* This is the ONLY path in this SDK by which a service token reaches file
|
|
189
|
+
* BYTES. {@link getServiceAssetMetadataByIds} is metadata-only, and every
|
|
190
|
+
* other download helper here — {@link getFileDownloadUrl},
|
|
191
|
+
* {@link getFileDownloadUrlAsync}, {@link getBatchFileAccess} — resolves a URL
|
|
192
|
+
* for the CURRENT USER through `makeRequest`, which is a different question: a
|
|
193
|
+
* relying service holds no user session, and the buyer whose entitlement it is
|
|
194
|
+
* enforcing is not a viewer Oxy knows anything about.
|
|
195
|
+
*
|
|
196
|
+
* **Service-token auth (required), plus the `files:linked:read` scope**, which
|
|
197
|
+
* is NOT implied by `files:read`. The calling client must be service-configured
|
|
198
|
+
* (`configureServiceAuth(apiKey, apiSecret)`); a user-session request is
|
|
199
|
+
* rejected by the route's service-auth guard.
|
|
200
|
+
*
|
|
201
|
+
* **What the server will and will not give you.** A URL comes back only for a
|
|
202
|
+
* file whose OWN OWNER linked it to this application (`file_links.created_by =
|
|
203
|
+
* files.owner_user_id`). Every other id is omitted: unknown, deleted,
|
|
204
|
+
* system-owned, linked by somebody else, or not linked here at all. So the
|
|
205
|
+
* result is routinely shorter than the input and must be mapped by `id`.
|
|
206
|
+
*
|
|
207
|
+
* ABSENCE IS A REFUSAL, NOT A FACT ABOUT THE FILE, and the caller is the only
|
|
208
|
+
* party that can tell the difference. The route deliberately cannot — it
|
|
209
|
+
* answers identically for "no such file" and "not yours" so it leaks nothing —
|
|
210
|
+
* which means a service must decide what to tell its user from its OWN
|
|
211
|
+
* entitlement record, never from this response. Do not surface "file not
|
|
212
|
+
* found" on the strength of an omission.
|
|
213
|
+
*
|
|
214
|
+
* FAILURE IS NOT ABSENCE EITHER, and here it cannot be opted out of: a failed
|
|
215
|
+
* chunk throws {@link ServiceLinkedDownloadUrlError} carrying its ids, with no
|
|
216
|
+
* `{ partial: true }` mode. Swallowing a 429 would tell a user who paid for a
|
|
217
|
+
* file that it is not there. An empty input resolves to `[]` with no network
|
|
218
|
+
* call.
|
|
219
|
+
*
|
|
220
|
+
* Never cached at the SDK layer, and that is a stronger statement than the
|
|
221
|
+
* sibling methods' "low hit rate": each entry is a live credential for the
|
|
222
|
+
* bytes, so caching one keeps it usable after the service has decided the
|
|
223
|
+
* caller's entitlement ended.
|
|
224
|
+
*/
|
|
225
|
+
getServiceLinkedDownloadUrls(ids: string[]): Promise<ServiceLinkedDownloadUrl[]>;
|
|
184
226
|
/**
|
|
185
227
|
* Reverse content-address lookup: resolve many content `sha256` digests to
|
|
186
228
|
* the servable Oxy asset holding each, in one round-trip per chunk via
|
|
@@ -77,6 +77,17 @@ export interface ConnectedApp {
|
|
|
77
77
|
/** ISO timestamp of when the grant was last exercised. */
|
|
78
78
|
lastUsedAt: string;
|
|
79
79
|
}
|
|
80
|
+
/** An external MCP client authorized for one exact app resource and account. */
|
|
81
|
+
export interface ConnectedMcpClient {
|
|
82
|
+
id: string;
|
|
83
|
+
appSlug: string;
|
|
84
|
+
resource: string;
|
|
85
|
+
scopes: string[];
|
|
86
|
+
clientId: string;
|
|
87
|
+
clientName: string;
|
|
88
|
+
createdAt: string;
|
|
89
|
+
lastUsedAt: string;
|
|
90
|
+
}
|
|
80
91
|
export declare function OxyServicesConnectedAppsMixin<T extends typeof OxyServicesBase>(Base: T): {
|
|
81
92
|
new (...args: any[]): {
|
|
82
93
|
/**
|
|
@@ -116,6 +127,10 @@ export declare function OxyServicesConnectedAppsMixin<T extends typeof OxyServic
|
|
|
116
127
|
* @param applicationId - The connected application's Mongo `_id`.
|
|
117
128
|
*/
|
|
118
129
|
revokeAppGrant(applicationId: string): Promise<void>;
|
|
130
|
+
/** List resource-bound external MCP connections for the active Oxy account. */
|
|
131
|
+
listConnectedMcpClients(): Promise<ConnectedMcpClient[]>;
|
|
132
|
+
/** Revoke one external MCP connection and every token in its family. */
|
|
133
|
+
revokeConnectedMcpClient(grantId: string): Promise<void>;
|
|
119
134
|
httpService: import("../HttpService").HttpService;
|
|
120
135
|
cloudURL: string;
|
|
121
136
|
config: import("../OxyServices.base").OxyConfig;
|
|
@@ -121,15 +121,6 @@ export declare function OxyServicesUtilityMixin<T extends typeof OxyServicesBase
|
|
|
121
121
|
* @internal Used by the auth() middleware — not part of the public API
|
|
122
122
|
*/
|
|
123
123
|
verifyServiceActingAs(appId: string, userId: string): Promise<ServiceActingAsVerification | null>;
|
|
124
|
-
/**
|
|
125
|
-
* Fetch link metadata
|
|
126
|
-
*/
|
|
127
|
-
fetchLinkMetadata(url: string): Promise<{
|
|
128
|
-
url: string;
|
|
129
|
-
title: string;
|
|
130
|
-
description: string;
|
|
131
|
-
image?: string;
|
|
132
|
-
}>;
|
|
133
124
|
/**
|
|
134
125
|
* Express.js authentication middleware
|
|
135
126
|
*
|
|
@@ -16,6 +16,7 @@ import { OxyServicesReputationMixin } from './OxyServices.reputation';
|
|
|
16
16
|
import { OxyServicesAssetsMixin } from './OxyServices.assets';
|
|
17
17
|
import { OxyServicesAccountsMixin } from './OxyServices.accounts';
|
|
18
18
|
import { OxyServicesConnectedAppsMixin } from './OxyServices.connectedApps';
|
|
19
|
+
import { OxyServicesAgencyMixin } from './OxyServices.agency';
|
|
19
20
|
import { OxyServicesStoreMixin } from './OxyServices.store';
|
|
20
21
|
import { OxyServicesLocationMixin } from './OxyServices.location';
|
|
21
22
|
import { OxyServicesAnalyticsMixin } from './OxyServices.analytics';
|
|
@@ -30,7 +31,6 @@ import { OxyServicesAppDataMixin } from './OxyServices.appData';
|
|
|
30
31
|
import { OxyServicesCivicMixin } from './OxyServices.civic';
|
|
31
32
|
import { OxyServicesChainsMixin } from './OxyServices.chains';
|
|
32
33
|
import { OxyServicesNodesMixin } from './OxyServices.nodes';
|
|
33
|
-
import { OxyServicesLinksMixin } from './OxyServices.links';
|
|
34
34
|
import { OxyServicesFollowGraphMixin } from './OxyServices.followGraph';
|
|
35
35
|
import { OxyServicesInferenceMixin } from './OxyServices.inference';
|
|
36
36
|
import { OxyServicesDeviceBootMixin } from './OxyServices.deviceBoot';
|
|
@@ -44,7 +44,7 @@ import { OxyServicesDeviceTransferMixin } from './OxyServices.deviceTransfer';
|
|
|
44
44
|
* If you add a new mixin to `MIXIN_PIPELINE`, add it here too so its methods
|
|
45
45
|
* are visible without a cast.
|
|
46
46
|
*/
|
|
47
|
-
type AllMixinInstances = InstanceType<ReturnType<typeof OxyServicesAuthMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesUserMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesIdentityMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesIdentityBackupMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesPrivacyMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesLanguageMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesPaymentMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesReputationMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesAssetsMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesAccountsMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesConnectedAppsMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof
|
|
47
|
+
type AllMixinInstances = InstanceType<ReturnType<typeof OxyServicesAuthMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesUserMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesIdentityMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesIdentityBackupMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesPrivacyMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesLanguageMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesPaymentMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesReputationMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesAssetsMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesAccountsMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesConnectedAppsMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesAgencyMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesStoreMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesLocationMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesAnalyticsMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesDevicesMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesSecurityMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesFeaturesMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesTopicsMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesContactsMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesNotificationsMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesAppDataMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesCivicMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesChainsMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesNodesMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesFollowGraphMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesInferenceMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesDeviceBootMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesDeviceTransferMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesUtilityMixin<typeof OxyServicesBase>>>;
|
|
48
48
|
/**
|
|
49
49
|
* Constructor type for the fully composed mixin pipeline. Each mixin returns
|
|
50
50
|
* a new constructor that augments its input; reducing across the pipeline
|
|
@@ -525,6 +525,32 @@ export interface AssetUpdateVisibilityResponse {
|
|
|
525
525
|
* deleted ids are omitted from the response (never error the whole batch),
|
|
526
526
|
* so the result may be shorter than the requested id list.
|
|
527
527
|
*/
|
|
528
|
+
/**
|
|
529
|
+
* A short-lived direct download URL for a file the calling application's own
|
|
530
|
+
* user attached to it, from `POST /assets/service/linked-url`.
|
|
531
|
+
*
|
|
532
|
+
* `url` is BEARER AUTHORITY over the bytes for `expiresIn` seconds: whoever
|
|
533
|
+
* holds the string is the reader, and nothing about the calling service's
|
|
534
|
+
* entitlement is re-evaluated when it is used. Hand it only to a caller the
|
|
535
|
+
* service has itself authorized, and never log it.
|
|
536
|
+
*
|
|
537
|
+
* `expiresIn` bounds when a transfer may START, not how long one may take. A
|
|
538
|
+
* large file downloads fine on a slow link; a RESUMED range request after the
|
|
539
|
+
* deadline does not, and needs a fresh URL.
|
|
540
|
+
*
|
|
541
|
+
* Unlike {@link ServiceAssetMetadata}, the absence of an id from the response is
|
|
542
|
+
* an AUTHORIZATION answer as often as an existence one — see
|
|
543
|
+
* `getServiceLinkedDownloadUrls`.
|
|
544
|
+
*/
|
|
545
|
+
export interface ServiceLinkedDownloadUrl {
|
|
546
|
+
id: string;
|
|
547
|
+
url: string;
|
|
548
|
+
/** Seconds from issue until `url` stops being accepted. */
|
|
549
|
+
expiresIn: number;
|
|
550
|
+
mime: string;
|
|
551
|
+
size: number;
|
|
552
|
+
sha256: string;
|
|
553
|
+
}
|
|
528
554
|
export interface ServiceAssetMetadata {
|
|
529
555
|
id: string;
|
|
530
556
|
sha256: string;
|
|
@@ -33,3 +33,6 @@ export { evictOxyIdentityCache, oxyUserByIdCacheKey, OXY_IDENTITY_CACHE_PREFIXES
|
|
|
33
33
|
export type { OxyIdentityCacheEvictor } from '../utils/identityCacheSweep';
|
|
34
34
|
export { registrableApex } from '../utils/registrableApex';
|
|
35
35
|
export { isOfficialWebOrigin } from '../utils/officialOrigins';
|
|
36
|
+
export { createEcosystemTraffic } from './traffic';
|
|
37
|
+
export type { EcosystemTrafficOptions } from './traffic';
|
|
38
|
+
export { observeNodeHttp, withoutNodeHttpObservation } from './trafficNodeHttp';
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { observeTrafficSocket, observeTrafficWebSocket, type TrafficWebSocket, type TrafficSocket } from '@oxy.so/telemetry/socket';
|
|
2
|
+
import type { RequestHandler } from 'express';
|
|
3
|
+
import { trafficMiddleware, type TrafficFlow, type ServiceEndpoint } from '@oxy.so/telemetry/collector';
|
|
4
|
+
export interface EcosystemTrafficOptions {
|
|
5
|
+
service: string;
|
|
6
|
+
region?: string;
|
|
7
|
+
baseURL?: string;
|
|
8
|
+
credential?: () => Promise<string>;
|
|
9
|
+
resolveEndpoint?: (url: URL) => ServiceEndpoint | undefined;
|
|
10
|
+
onError?: () => void;
|
|
11
|
+
ready?: () => boolean;
|
|
12
|
+
location?: {
|
|
13
|
+
label: string;
|
|
14
|
+
coordinates: [number, number];
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
/** Install once per service process, before registering HTTP routes. */
|
|
18
|
+
export declare function createEcosystemTraffic(options: EcosystemTrafficOptions): {
|
|
19
|
+
middleware: RequestHandler;
|
|
20
|
+
record(flow: Omit<TrafficFlow, 'service' | 'region'>): void;
|
|
21
|
+
wrapFetch(fetcher: typeof fetch): typeof fetch;
|
|
22
|
+
installFetch(): void;
|
|
23
|
+
observeHttp: ReturnType<typeof trafficMiddleware>;
|
|
24
|
+
observeSocket(socket: TrafficSocket, options?: Parameters<typeof observeTrafficSocket>[4]): () => void;
|
|
25
|
+
observeWebSocket(socket: TrafficWebSocket, options?: Parameters<typeof observeTrafficWebSocket>[4]): () => void;
|
|
26
|
+
stop(): Promise<void>;
|
|
27
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type TrafficFlow, type ServiceEndpoint } from '@oxy.so/telemetry/collector';
|
|
2
|
+
export declare function withoutNodeHttpObservation<T>(callback: () => T): T;
|
|
3
|
+
/** Node and Bun share the HTTP facade; Bun does not emit Node's HTTP diagnostic channels. */
|
|
4
|
+
export declare function observeNodeHttp(collector: {
|
|
5
|
+
record(flow: TrafficFlow): void;
|
|
6
|
+
}, service: string, region: string, resolveEndpoint: (url: URL) => ServiceEndpoint | undefined): () => void;
|
|
@@ -118,10 +118,7 @@ export declare function createCache<T>(ttl?: number): TTLCache<T>;
|
|
|
118
118
|
* @param cache Cache instance to register
|
|
119
119
|
*/
|
|
120
120
|
export declare function registerCacheForCleanup(cache: TTLCache<any>): void;
|
|
121
|
-
/**
|
|
122
|
-
* Unregister a cache from automatic cleanup
|
|
123
|
-
* @param cache Cache instance to unregister
|
|
124
|
-
*/
|
|
121
|
+
/** Unregister a cache without changing its entries or TTL behavior. */
|
|
125
122
|
export declare function unregisterCacheFromCleanup(cache: TTLCache<any>): void;
|
|
126
123
|
/**
|
|
127
124
|
* Stop all cleanup intervals (useful for testing)
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
* normalize whitespace and Unicode form.
|
|
44
44
|
*/
|
|
45
45
|
/**
|
|
46
|
-
* Normalize a SINGLE-LINE text value
|
|
46
|
+
* Normalize a SINGLE-LINE text value such as a page title or `siteName`,
|
|
47
47
|
* display names, image alt text, handles, profile field labels.
|
|
48
48
|
*
|
|
49
49
|
* A line break in such a value is never meaningful — it is an artifact of the
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oxy.so/core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.2",
|
|
4
4
|
"description": "OxyHQ SDK Foundation — API client, authentication, cryptographic identity, and shared utilities",
|
|
5
5
|
"main": "dist/cjs/index.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|
|
@@ -86,7 +86,7 @@
|
|
|
86
86
|
"node": ">=18.0.0"
|
|
87
87
|
},
|
|
88
88
|
"scripts": {
|
|
89
|
-
"build": "bun run build:cjs && bun run build:esm && bun run build:types && bun run copy-assets && node scripts/mark-module-formats.mjs",
|
|
89
|
+
"build": "bun run --filter @oxy.so/telemetry build && bun run build:cjs && bun run build:esm && bun run build:types && bun run copy-assets && node scripts/mark-module-formats.mjs",
|
|
90
90
|
"copy-assets": "cp -r src/i18n/locales dist/cjs/i18n/locales && cp -r src/i18n/locales dist/esm/i18n/locales",
|
|
91
91
|
"build:cjs": "tsc -p tsconfig.cjs.json",
|
|
92
92
|
"build:esm": "tsc -p tsconfig.esm.json && node scripts/fix-esm-imports.mjs",
|
|
@@ -115,10 +115,10 @@
|
|
|
115
115
|
}
|
|
116
116
|
},
|
|
117
117
|
"dependencies": {
|
|
118
|
-
"@oxy.so/telemetry": "^1.
|
|
118
|
+
"@oxy.so/telemetry": "^1.1.1",
|
|
119
119
|
"@noble/ciphers": "^1.3.0",
|
|
120
120
|
"@noble/hashes": "^1.8.0",
|
|
121
|
-
"@oxy.so/contracts": "^1.
|
|
121
|
+
"@oxy.so/contracts": "^1.1.1",
|
|
122
122
|
"@oxy.so/protocol": "^1.0.1",
|
|
123
123
|
"@scure/bip39": "^1.6.0",
|
|
124
124
|
"buffer": "^6.0.3",
|
|
@@ -109,6 +109,42 @@ export class ServiceAssetMetadataError extends Error {
|
|
|
109
109
|
}
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
+
/**
|
|
113
|
+
* A chunk of `POST /assets/service/linked-url` failed, so the SDK cannot say
|
|
114
|
+
* whether those ids have URLs.
|
|
115
|
+
*
|
|
116
|
+
* Its own class rather than a reuse of {@link ServiceAssetMetadataError}, and
|
|
117
|
+
* deliberately WITHOUT that one's `{ partial: true }` escape hatch, because the
|
|
118
|
+
* two mistakes cost different things. Reading a failed metadata lookup as
|
|
119
|
+
* "absent" embedded a media item with no hash. Reading a failed DOWNLOAD mint as
|
|
120
|
+
* "absent" tells a buyer who paid that the file they own is not there — and
|
|
121
|
+
* "not there" is already this route's answer for "not yours", so a best-effort
|
|
122
|
+
* mode would make a throttled request indistinguishable from a refusal. There is
|
|
123
|
+
* no download path that legitimately wants that, so there is no option to ask
|
|
124
|
+
* for it.
|
|
125
|
+
*/
|
|
126
|
+
export class ServiceLinkedDownloadUrlError extends Error {
|
|
127
|
+
public readonly code = 'SERVICE_LINKED_DOWNLOAD_URL_UNRESOLVED';
|
|
128
|
+
/** Every id belonging to a chunk whose request failed. */
|
|
129
|
+
public readonly unresolvedIds: string[];
|
|
130
|
+
/** HTTP statuses observed across the failed chunks (deduped, ascending). */
|
|
131
|
+
public readonly statuses: number[];
|
|
132
|
+
/** The first underlying transport/API failure — see the sibling class. */
|
|
133
|
+
public readonly cause?: unknown;
|
|
134
|
+
|
|
135
|
+
constructor(unresolvedIds: string[], statuses: number[], cause?: unknown) {
|
|
136
|
+
const uniqueStatuses = Array.from(new Set(statuses)).sort((a, b) => a - b);
|
|
137
|
+
const statusSuffix = uniqueStatuses.length > 0 ? ` — status ${uniqueStatuses.join(', ')}` : '';
|
|
138
|
+
super(
|
|
139
|
+
`Could not mint download URLs for ${unresolvedIds.length} id(s)${statusSuffix}. Treat this as unknown, never as "the caller holds no right".`,
|
|
140
|
+
);
|
|
141
|
+
this.name = 'ServiceLinkedDownloadUrlError';
|
|
142
|
+
this.unresolvedIds = unresolvedIds;
|
|
143
|
+
this.statuses = uniqueStatuses;
|
|
144
|
+
this.cause = cause;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
112
148
|
export class OxyAuthenticationTimeoutError extends OxyAuthenticationError {
|
|
113
149
|
constructor(operationName: string, timeoutMs: number) {
|
|
114
150
|
super(
|
|
@@ -2127,6 +2127,18 @@
|
|
|
2127
2127
|
"title": "Permissions requested",
|
|
2128
2128
|
"basic": "Sign you in and read your basic profile"
|
|
2129
2129
|
},
|
|
2130
|
+
"resource": {
|
|
2131
|
+
"title": "Oxy app and protected resource"
|
|
2132
|
+
},
|
|
2133
|
+
"writeActions": {
|
|
2134
|
+
"title": "Actions this connection can perform"
|
|
2135
|
+
},
|
|
2136
|
+
"effects": {
|
|
2137
|
+
"write": "Write",
|
|
2138
|
+
"external": "External",
|
|
2139
|
+
"financial": "Financial",
|
|
2140
|
+
"security": "Security"
|
|
2141
|
+
},
|
|
2130
2142
|
"scopes": {
|
|
2131
2143
|
"openid": "Confirm your identity",
|
|
2132
2144
|
"profile": "Read your basic profile",
|
|
@@ -2147,7 +2159,8 @@
|
|
|
2147
2159
|
"federationWrite": "Act across federated services"
|
|
2148
2160
|
},
|
|
2149
2161
|
"account": {
|
|
2150
|
-
"title": "Signing in as"
|
|
2162
|
+
"title": "Signing in as",
|
|
2163
|
+
"id": "Account ID: {{id}}"
|
|
2151
2164
|
},
|
|
2152
2165
|
"links": {
|
|
2153
2166
|
"website": "Website",
|
|
@@ -2127,6 +2127,18 @@
|
|
|
2127
2127
|
"title": "Permisos solicitados",
|
|
2128
2128
|
"basic": "Iniciar sesión y leer tu perfil básico"
|
|
2129
2129
|
},
|
|
2130
|
+
"resource": {
|
|
2131
|
+
"title": "App de Oxy y recurso protegido"
|
|
2132
|
+
},
|
|
2133
|
+
"writeActions": {
|
|
2134
|
+
"title": "Acciones que puede realizar esta conexión"
|
|
2135
|
+
},
|
|
2136
|
+
"effects": {
|
|
2137
|
+
"write": "Escritura",
|
|
2138
|
+
"external": "Externa",
|
|
2139
|
+
"financial": "Financiera",
|
|
2140
|
+
"security": "Seguridad"
|
|
2141
|
+
},
|
|
2130
2142
|
"scopes": {
|
|
2131
2143
|
"openid": "Confirmar tu identidad",
|
|
2132
2144
|
"profile": "Leer tu perfil básico",
|
|
@@ -2147,7 +2159,8 @@
|
|
|
2147
2159
|
"federationWrite": "Actuar en servicios federados"
|
|
2148
2160
|
},
|
|
2149
2161
|
"account": {
|
|
2150
|
-
"title": "Iniciando sesión como"
|
|
2162
|
+
"title": "Iniciando sesión como",
|
|
2163
|
+
"id": "ID de cuenta: {{id}}"
|
|
2151
2164
|
},
|
|
2152
2165
|
"links": {
|
|
2153
2166
|
"website": "Sitio web",
|
package/src/index.ts
CHANGED
|
@@ -122,8 +122,23 @@ export type { ProfileLink, ProfileLinkMetadata } from './utils/profileLinks';
|
|
|
122
122
|
export type {
|
|
123
123
|
PublicApplication,
|
|
124
124
|
ConnectedApp,
|
|
125
|
+
ConnectedMcpClient,
|
|
125
126
|
} from './mixins/OxyServices.connectedApps';
|
|
126
127
|
|
|
128
|
+
// ---------------------------------------------------------------------------
|
|
129
|
+
// Native Alia and digital-agent authority
|
|
130
|
+
// ---------------------------------------------------------------------------
|
|
131
|
+
export type {
|
|
132
|
+
AccountCapabilityPolicy,
|
|
133
|
+
AvailableCapabilityCatalog,
|
|
134
|
+
CapabilityExecutionAuthorization,
|
|
135
|
+
CreateDelegationGrantInput,
|
|
136
|
+
DelegationCatalogBinding,
|
|
137
|
+
DelegationGrantView,
|
|
138
|
+
PutAccountCapabilityPolicyInput,
|
|
139
|
+
UpdateDelegationGrantInput,
|
|
140
|
+
} from './mixins/OxyServices.agency';
|
|
141
|
+
|
|
127
142
|
// ---------------------------------------------------------------------------
|
|
128
143
|
// App store (public storefront + reviews + the listing a publisher edits)
|
|
129
144
|
// ---------------------------------------------------------------------------
|