@oxy.so/core 4.5.0-oxy-one.0 → 4.5.0
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/README.md +1 -1
- package/dist/cjs/HttpService.js +63 -19
- package/dist/cjs/api/accounts.js +10 -3
- package/dist/cjs/api/agency.js +3 -1
- package/dist/cjs/api/apps.js +15 -4
- package/dist/cjs/api/assets.js +49 -12
- package/dist/cjs/api/auth.js +37 -11
- package/dist/cjs/api/billing.js +24 -7
- package/dist/cjs/api/civic.js +14 -4
- package/dist/cjs/api/follows.js +9 -2
- package/dist/cjs/api/identity.js +31 -9
- package/dist/cjs/api/nodes.js +3 -1
- package/dist/cjs/api/privacy.js +8 -2
- package/dist/cjs/api/session.js +15 -4
- package/dist/cjs/api/store.js +15 -5
- package/dist/cjs/api/topics.js +10 -3
- package/dist/cjs/api/users.js +16 -4
- package/dist/cjs/boot/sessionColdBoot.js +40 -13
- package/dist/cjs/constants/version.js +6 -6
- package/dist/cjs/crypto/identityMarker.js +3 -1
- package/dist/cjs/crypto/identityProof.js +6 -1
- package/dist/cjs/crypto/keyManager.js +87 -32
- package/dist/cjs/crypto/recoveryPhrase.js +2 -2
- package/dist/cjs/crypto/signatureService.js +3 -4
- package/dist/cjs/i18n/index.js +16 -3
- package/dist/cjs/i18n/locales/ar-SA.js +366 -366
- package/dist/cjs/i18n/locales/ca-ES.js +366 -366
- package/dist/cjs/i18n/locales/de-DE.js +366 -366
- package/dist/cjs/i18n/locales/en-US.js +1994 -1994
- package/dist/cjs/i18n/locales/es-ES.js +1994 -1994
- package/dist/cjs/i18n/locales/fr-FR.js +366 -366
- package/dist/cjs/i18n/locales/it-IT.js +366 -366
- package/dist/cjs/i18n/locales/ja-JP.js +366 -366
- package/dist/cjs/i18n/locales/ko-KR.js +366 -366
- package/dist/cjs/i18n/locales/pt-PT.js +366 -366
- package/dist/cjs/i18n/locales/zh-CN.js +366 -366
- package/dist/cjs/inference/OxyInferenceClient.js +12 -18
- package/dist/cjs/models/interfaces.js +11 -11
- package/dist/cjs/server/OxyServer.js +86 -28
- package/dist/cjs/server/agentAccount.js +6 -2
- package/dist/cjs/server/aliaMachineCredential.js +39 -14
- package/dist/cjs/server/auth.js +5 -4
- package/dist/cjs/server/capabilityTicket.js +5 -5
- package/dist/cjs/server/index.js +2 -1
- package/dist/cjs/server/liveCapabilityTicket.js +4 -1
- package/dist/cjs/server/middleware.js +61 -42
- package/dist/cjs/server/namespaces.js +28 -7
- package/dist/cjs/server/requesterAssertion.js +36 -30
- package/dist/cjs/server/serviceTokenLifetime.js +7 -4
- package/dist/cjs/server/traffic.js +53 -14
- package/dist/cjs/server/trafficNodeHttp.js +33 -8
- package/dist/cjs/server/workloadIdentity.client.js +4 -0
- package/dist/cjs/server/workloadIdentity.js +28 -1
- package/dist/cjs/session/SessionClient.js +54 -17
- package/dist/cjs/session/accountDelegationAccess.js +4 -6
- package/dist/cjs/session/accountDialogController.js +1 -1
- package/dist/cjs/session/authStateStore.js +18 -9
- package/dist/cjs/session/identityPin.js +6 -2
- package/dist/cjs/session/refresh.js +81 -23
- package/dist/cjs/session/sharedDeviceCredential.js +28 -15
- package/dist/cjs/shared/utils/errorUtils.js +1 -1
- package/dist/cjs/shared/utils/networkUtils.js +1 -1
- package/dist/cjs/shared/utils/themeUtils.js +1 -1
- package/dist/cjs/utils/accountCacheSweep.js +3 -1
- package/dist/cjs/utils/accountUtils.js +1 -3
- package/dist/cjs/utils/asyncUtils.js +1 -1
- package/dist/cjs/utils/authHelpers.js +2 -1
- package/dist/cjs/utils/avatarUtils.js +4 -2
- package/dist/cjs/utils/cache.js +1 -1
- package/dist/cjs/utils/cacheKey.js +3 -1
- package/dist/cjs/utils/deviceManager.js +4 -4
- package/dist/cjs/utils/errorUtils.js +6 -4
- package/dist/cjs/utils/languageUtils.js +404 -57
- package/dist/cjs/utils/profileLinks.js +1 -3
- package/dist/cjs/utils/requestUtils.js +7 -1
- package/dist/cjs/utils/userIdentity.js +1 -1
- package/dist/cjs/utils/validationUtils.js +5 -6
- package/dist/esm/HttpService.js +64 -20
- package/dist/esm/api/accounts.js +11 -4
- package/dist/esm/api/agency.js +3 -1
- package/dist/esm/api/apps.js +15 -4
- package/dist/esm/api/assets.js +49 -12
- package/dist/esm/api/auth.js +37 -11
- package/dist/esm/api/billing.js +25 -8
- package/dist/esm/api/civic.js +14 -4
- package/dist/esm/api/follows.js +9 -2
- package/dist/esm/api/identity.js +31 -9
- package/dist/esm/api/nodes.js +3 -1
- package/dist/esm/api/privacy.js +8 -2
- package/dist/esm/api/session.js +15 -4
- package/dist/esm/api/store.js +15 -5
- package/dist/esm/api/topics.js +10 -3
- package/dist/esm/api/users.js +16 -4
- package/dist/esm/boot/sessionColdBoot.js +41 -14
- package/dist/esm/constants/version.js +6 -6
- package/dist/esm/crypto/identityMarker.js +3 -1
- package/dist/esm/crypto/identityProof.js +6 -1
- package/dist/esm/crypto/internal.js +1 -1
- package/dist/esm/crypto/keyManager.js +87 -32
- package/dist/esm/crypto/recoveryPhrase.js +2 -2
- package/dist/esm/crypto/signatureService.js +3 -4
- package/dist/esm/i18n/index.js +16 -3
- package/dist/esm/i18n/locales/ar-SA.js +366 -366
- package/dist/esm/i18n/locales/ca-ES.js +366 -366
- package/dist/esm/i18n/locales/de-DE.js +366 -366
- package/dist/esm/i18n/locales/en-US.js +1994 -1994
- package/dist/esm/i18n/locales/es-ES.js +1994 -1994
- package/dist/esm/i18n/locales/fr-FR.js +366 -366
- package/dist/esm/i18n/locales/it-IT.js +366 -366
- package/dist/esm/i18n/locales/ja-JP.js +366 -366
- package/dist/esm/i18n/locales/ko-KR.js +366 -366
- package/dist/esm/i18n/locales/pt-PT.js +366 -366
- package/dist/esm/i18n/locales/zh-CN.js +366 -366
- package/dist/esm/index.js +1 -1
- package/dist/esm/inference/OxyInferenceClient.js +13 -19
- package/dist/esm/models/interfaces.js +11 -11
- package/dist/esm/server/OxyServer.js +87 -29
- package/dist/esm/server/agentAccount.js +6 -2
- package/dist/esm/server/aliaMachineCredential.js +39 -14
- package/dist/esm/server/auth.js +6 -5
- package/dist/esm/server/capabilityTicket.js +6 -6
- package/dist/esm/server/index.js +5 -5
- package/dist/esm/server/liveCapabilityTicket.js +6 -3
- package/dist/esm/server/middleware.js +62 -43
- package/dist/esm/server/namespaces.js +31 -10
- package/dist/esm/server/requesterAssertion.js +36 -30
- package/dist/esm/server/serviceTokenLifetime.js +7 -4
- package/dist/esm/server/traffic.js +55 -16
- package/dist/esm/server/trafficNodeHttp.js +34 -9
- package/dist/esm/server/userInvalidation.js +1 -1
- package/dist/esm/server/workloadIdentity.client.js +3 -0
- package/dist/esm/server/workloadIdentity.js +27 -1
- package/dist/esm/session/SessionClient.js +54 -17
- package/dist/esm/session/accountDelegationAccess.js +5 -7
- package/dist/esm/session/accountDialogController.js +1 -1
- package/dist/esm/session/authStateStore.js +18 -9
- package/dist/esm/session/identityPin.js +6 -2
- package/dist/esm/session/refresh.js +82 -24
- package/dist/esm/session/sharedDeviceCredential.js +28 -15
- package/dist/esm/shared/utils/errorUtils.js +1 -1
- package/dist/esm/shared/utils/networkUtils.js +1 -1
- package/dist/esm/shared/utils/themeUtils.js +1 -1
- package/dist/esm/utils/accountCacheSweep.js +3 -1
- package/dist/esm/utils/accountUtils.js +1 -3
- package/dist/esm/utils/asyncUtils.js +1 -1
- package/dist/esm/utils/authHelpers.js +2 -1
- package/dist/esm/utils/avatarUtils.js +4 -2
- package/dist/esm/utils/cache.js +1 -1
- package/dist/esm/utils/cacheKey.js +3 -1
- package/dist/esm/utils/deviceManager.js +4 -4
- package/dist/esm/utils/errorUtils.js +6 -4
- package/dist/esm/utils/languageUtils.js +404 -57
- package/dist/esm/utils/profileLinks.js +1 -3
- package/dist/esm/utils/requestUtils.js +7 -1
- package/dist/esm/utils/userIdentity.js +1 -1
- package/dist/esm/utils/validationUtils.js +5 -6
- package/dist/types/HttpService.d.ts +1 -1
- package/dist/types/api/accounts.d.ts +1 -1
- package/dist/types/api/apps.d.ts +4 -4
- package/dist/types/api/assets.d.ts +2 -0
- package/dist/types/api/auth.d.ts +8 -3
- package/dist/types/crypto/internal.d.ts +1 -1
- package/dist/types/index.d.ts +4 -4
- package/dist/types/server/index.d.ts +6 -6
- package/dist/types/server/requesterAssertion.d.ts +2 -2
- package/dist/types/server/workloadIdentity.client.d.ts +5 -1
- package/dist/types/server/workloadIdentity.d.ts +26 -0
- package/dist/types/session/accountDelegationAccess.d.ts +1 -1
- package/dist/types/session/index.d.ts +1 -1
- package/dist/types/utils/userIdentity.d.ts +1 -1
- package/dist/types/utils/validationUtils.d.ts +4 -5
- package/package.json +2 -3
- package/src/HttpService.ts +183 -53
- package/src/OxyServices.errors.ts +7 -3
- package/src/OxyServices.ts +6 -2
- package/src/api/accounts.ts +76 -26
- package/src/api/agency.ts +24 -9
- package/src/api/appData.ts +12 -2
- package/src/api/apps.ts +81 -31
- package/src/api/assets.ts +122 -40
- package/src/api/auth.ts +154 -79
- package/src/api/billing.ts +112 -65
- package/src/api/civic.ts +61 -19
- package/src/api/contacts.ts +4 -1
- package/src/api/devices.ts +54 -21
- package/src/api/follows.ts +88 -31
- package/src/api/identity.ts +101 -33
- package/src/api/linkedAccounts.ts +26 -8
- package/src/api/nodes.ts +18 -6
- package/src/api/notifications.ts +26 -6
- package/src/api/privacy.ts +42 -8
- package/src/api/reputation.ts +18 -7
- package/src/api/session.ts +23 -5
- package/src/api/store.ts +81 -31
- package/src/api/topics.ts +18 -6
- package/src/api/users.ts +98 -35
- package/src/boot/sessionColdBoot.ts +60 -19
- package/src/civic/payloads.ts +1 -4
- package/src/client/context.ts +6 -1
- package/src/constants/version.ts +7 -6
- package/src/crypto/aead.ts +1 -5
- package/src/crypto/ecdh.ts +1 -4
- package/src/crypto/identityDerivations.ts +5 -1
- package/src/crypto/identityMarker.ts +3 -1
- package/src/crypto/identityProof.ts +6 -1
- package/src/crypto/index.ts +11 -11
- package/src/crypto/internal.ts +6 -1
- package/src/crypto/keyManager.ts +348 -98
- package/src/crypto/recoveryPhrase.ts +14 -9
- package/src/crypto/registrationPow.ts +1 -1
- package/src/crypto/signatureService.ts +14 -6
- package/src/i18n/accountCategoryLabels.ts +1 -4
- package/src/i18n/accountRoleLabels.ts +1 -4
- package/src/i18n/index.ts +25 -7
- package/src/i18n/locales/ar-SA.ts +375 -366
- package/src/i18n/locales/ca-ES.ts +382 -366
- package/src/i18n/locales/de-DE.ts +387 -366
- package/src/i18n/locales/en-US.ts +2034 -1994
- package/src/i18n/locales/es-ES.ts +2043 -1994
- package/src/i18n/locales/fr-FR.ts +387 -366
- package/src/i18n/locales/it-IT.ts +380 -366
- package/src/i18n/locales/ja-JP.ts +380 -366
- package/src/i18n/locales/ko-KR.ts +377 -366
- package/src/i18n/locales/pt-PT.ts +383 -366
- package/src/i18n/locales/zh-CN.ts +373 -366
- package/src/i18n/trustTierLabels.ts +1 -4
- package/src/index.ts +371 -349
- package/src/inference/OxyInferenceClient.ts +784 -780
- package/src/models/interfaces.ts +30 -27
- package/src/server/OxyServer.ts +227 -68
- package/src/server/agentAccount.ts +8 -2
- package/src/server/aliaMachineCredential.ts +57 -16
- package/src/server/auth.ts +9 -5
- package/src/server/capabilityTicket.ts +30 -21
- package/src/server/index.ts +29 -6
- package/src/server/liveCapabilityTicket.ts +31 -9
- package/src/server/middleware.ts +212 -121
- package/src/server/namespaces.ts +247 -94
- package/src/server/rateLimit.ts +2 -4
- package/src/server/requesterAssertion.ts +93 -54
- package/src/server/serviceTokenLifetime.ts +9 -4
- package/src/server/traffic.ts +117 -23
- package/src/server/trafficNodeHttp.ts +61 -14
- package/src/server/userInvalidation.ts +1 -4
- package/src/server/workloadIdentity.client.ts +12 -1
- package/src/server/workloadIdentity.ts +52 -5
- package/src/session/SessionClient.ts +170 -49
- package/src/session/accountDelegationAccess.ts +24 -31
- package/src/session/accountDialogController.ts +59 -14
- package/src/session/accountSwitchTargets.ts +10 -15
- package/src/session/authStateStore.ts +121 -81
- package/src/session/deviceDirectory.ts +1 -3
- package/src/session/identityPin.ts +10 -11
- package/src/session/identitySession.ts +3 -1
- package/src/session/index.ts +87 -82
- package/src/session/refresh.ts +138 -44
- package/src/session/sessionClientHost.ts +1 -3
- package/src/session/sharedDeviceCredential.ts +35 -14
- package/src/session/socketLoader.ts +9 -2
- package/src/shared/utils/errorUtils.ts +5 -2
- package/src/shared/utils/networkUtils.ts +5 -8
- package/src/shared/utils/themeUtils.ts +2 -6
- package/src/types/buffer.d.ts +66 -21
- package/src/types/expo-secure-store.d.ts +5 -1
- package/src/utils/accountCacheSweep.ts +4 -5
- package/src/utils/accountUtils.ts +107 -108
- package/src/utils/apiUtils.ts +3 -3
- package/src/utils/asyncUtils.ts +2 -2
- package/src/utils/authHelpers.ts +10 -5
- package/src/utils/avatarUtils.ts +11 -6
- package/src/utils/cache.ts +9 -10
- package/src/utils/cacheKey.ts +5 -1
- package/src/utils/coldBoot.ts +1 -3
- package/src/utils/commonsDelivery.ts +1 -4
- package/src/utils/deviceManager.ts +15 -14
- package/src/utils/errorUtils.ts +68 -86
- package/src/utils/languageUtils.ts +407 -58
- package/src/utils/oauthPkce.ts +1 -4
- package/src/utils/platform.ts +0 -1
- package/src/utils/profileLinks.ts +2 -5
- package/src/utils/requestUtils.ts +18 -14
- package/src/utils/sessionUtils.ts +34 -33
- package/src/utils/userHandle.ts +3 -1
- package/src/utils/userIdentity.ts +1 -1
- package/src/utils/validationUtils.ts +11 -9
package/src/server/namespaces.ts
CHANGED
|
@@ -4,7 +4,23 @@
|
|
|
4
4
|
* `server.assets.metadataByIds(...)` sits beside every client method of
|
|
5
5
|
* `oxy.assets`.
|
|
6
6
|
*/
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
capabilityTicketRequestSchema,
|
|
9
|
+
foregroundExecutionAuthorizationInputSchema,
|
|
10
|
+
type ForegroundExecutionAuthorizationInput,
|
|
11
|
+
type ActorRef,
|
|
12
|
+
type AppCapabilityCatalog,
|
|
13
|
+
type AutonomyLevel,
|
|
14
|
+
type CapabilityTicketClaims,
|
|
15
|
+
type CapabilityTicketRequest,
|
|
16
|
+
type GrantLimit,
|
|
17
|
+
type PolicyDecision,
|
|
18
|
+
type ResourceRef,
|
|
19
|
+
type CreateOxyNotificationRequest,
|
|
20
|
+
type AwardReputationInput,
|
|
21
|
+
type ReputationTransaction,
|
|
22
|
+
type ServiceLinkedAccountListResponse,
|
|
23
|
+
} from '@oxy.so/contracts';
|
|
8
24
|
import type { RequestOptions } from '../HttpService';
|
|
9
25
|
import type { OxyContext, ServiceLane } from '../client/context';
|
|
10
26
|
import type {
|
|
@@ -16,10 +32,18 @@ import type {
|
|
|
16
32
|
import { AssetsApi } from '../api/assets';
|
|
17
33
|
import { NotificationsApi } from '../api/notifications';
|
|
18
34
|
import { LinkedAccountsApi } from '../api/linkedAccounts';
|
|
19
|
-
import {
|
|
35
|
+
import {
|
|
36
|
+
AgencyApi,
|
|
37
|
+
type CapabilityExecutionAuthorization,
|
|
38
|
+
type RequesterAssertionGrant,
|
|
39
|
+
type RequesterAssertionIntrospection,
|
|
40
|
+
} from '../api/agency';
|
|
20
41
|
import { ReputationApi } from '../api/reputation';
|
|
21
42
|
import { AppsApi } from '../api/apps';
|
|
22
|
-
import {
|
|
43
|
+
import {
|
|
44
|
+
isOxyAliaMachinePrincipal,
|
|
45
|
+
type AliaMachineCredentialIntrospection,
|
|
46
|
+
} from './aliaMachineCredential';
|
|
23
47
|
import { ServiceAssetMetadataError, ServiceLinkedDownloadUrlError } from '../OxyServices.errors';
|
|
24
48
|
import { extractErrorStatus } from '../utils/errorUtils';
|
|
25
49
|
import { logger } from '../logger';
|
|
@@ -42,18 +66,29 @@ function lane(ctx: OxyContext): ServiceLane {
|
|
|
42
66
|
}
|
|
43
67
|
|
|
44
68
|
export class ServerAppsApi extends AppsApi {
|
|
45
|
-
constructor(private readonly serverCtx: OxyContext) {
|
|
69
|
+
constructor(private readonly serverCtx: OxyContext) {
|
|
70
|
+
super(serverCtx);
|
|
71
|
+
}
|
|
46
72
|
/** Live receiver-bound lookup using THIS resource server's own service token. */
|
|
47
|
-
async introspectAliaMachineCredential(
|
|
73
|
+
async introspectAliaMachineCredential(
|
|
74
|
+
token: string,
|
|
75
|
+
): Promise<AliaMachineCredentialIntrospection> {
|
|
48
76
|
if (!token.startsWith('oxy_sk_') || token.length > 2048) return { active: false };
|
|
49
77
|
const answer = await lane(this.serverCtx).request<unknown>(
|
|
50
|
-
'POST',
|
|
78
|
+
'POST',
|
|
79
|
+
'/internal/alia/machine-credentials/introspect',
|
|
80
|
+
{ token },
|
|
51
81
|
{ cache: false, retry: false },
|
|
52
82
|
);
|
|
53
|
-
if (!answer || typeof answer !== 'object' || Array.isArray(answer))
|
|
83
|
+
if (!answer || typeof answer !== 'object' || Array.isArray(answer))
|
|
84
|
+
throw new Error('Invalid machine credential verdict');
|
|
54
85
|
const record = answer as Record<string, unknown>;
|
|
55
86
|
if (record.active === false && Object.keys(record).length === 1) return { active: false };
|
|
56
|
-
if (
|
|
87
|
+
if (
|
|
88
|
+
record.active !== true ||
|
|
89
|
+
Object.keys(record).length !== 2 ||
|
|
90
|
+
!isOxyAliaMachinePrincipal(record.principal)
|
|
91
|
+
) {
|
|
57
92
|
throw new Error('Invalid machine credential verdict');
|
|
58
93
|
}
|
|
59
94
|
return { active: true, principal: record.principal };
|
|
@@ -67,7 +102,9 @@ function chunk<T>(items: T[], size: number): T[][] {
|
|
|
67
102
|
}
|
|
68
103
|
|
|
69
104
|
function uniqueIds(ids: string[]): string[] {
|
|
70
|
-
return Array.from(
|
|
105
|
+
return Array.from(
|
|
106
|
+
new Set(ids.filter((id): id is string => typeof id === 'string' && id.trim().length > 0)),
|
|
107
|
+
);
|
|
71
108
|
}
|
|
72
109
|
|
|
73
110
|
export class ServerAssetsApi extends AssetsApi {
|
|
@@ -81,7 +118,10 @@ export class ServerAssetsApi extends AssetsApi {
|
|
|
81
118
|
* {@link ServiceAssetMetadataError} carrying the ids it could not resolve,
|
|
82
119
|
* unless `{ partial: true }` asks for best-effort. Never cached.
|
|
83
120
|
*/
|
|
84
|
-
async metadataByIds(
|
|
121
|
+
async metadataByIds(
|
|
122
|
+
ids: string[],
|
|
123
|
+
options: { partial?: boolean } = {},
|
|
124
|
+
): Promise<ServiceAssetMetadata[]> {
|
|
85
125
|
const unique = uniqueIds(ids);
|
|
86
126
|
if (unique.length === 0) return [];
|
|
87
127
|
|
|
@@ -90,25 +130,31 @@ export class ServerAssetsApi extends AssetsApi {
|
|
|
90
130
|
let firstError: unknown;
|
|
91
131
|
|
|
92
132
|
const settled = await Promise.all(
|
|
93
|
-
chunk(unique, SERVICE_ASSET_METADATA_CHUNK_SIZE).map(
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
133
|
+
chunk(unique, SERVICE_ASSET_METADATA_CHUNK_SIZE).map(
|
|
134
|
+
async (part): Promise<ServiceAssetMetadata[]> => {
|
|
135
|
+
try {
|
|
136
|
+
const entries = await lane(this.ctx).request<ServiceAssetMetadata[]>(
|
|
137
|
+
'POST',
|
|
138
|
+
'/assets/service/by-ids',
|
|
139
|
+
{ ids: part },
|
|
140
|
+
);
|
|
141
|
+
return Array.isArray(entries) ? entries : [];
|
|
142
|
+
} catch (error: unknown) {
|
|
143
|
+
const status = extractErrorStatus(error);
|
|
144
|
+
logger.warn('assets.metadataByIds: chunk failed', {
|
|
145
|
+
method: 'assets.metadataByIds',
|
|
146
|
+
chunkSize: part.length,
|
|
147
|
+
status,
|
|
148
|
+
partial: options.partial === true,
|
|
149
|
+
error: error instanceof Error ? error.message : String(error),
|
|
150
|
+
});
|
|
151
|
+
unresolvedIds.push(...part);
|
|
152
|
+
if (typeof status === 'number') statuses.push(status);
|
|
153
|
+
firstError ??= error;
|
|
154
|
+
return [];
|
|
155
|
+
}
|
|
156
|
+
},
|
|
157
|
+
),
|
|
112
158
|
);
|
|
113
159
|
|
|
114
160
|
if (unresolvedIds.length > 0 && options.partial !== true) {
|
|
@@ -138,26 +184,32 @@ export class ServerAssetsApi extends AssetsApi {
|
|
|
138
184
|
let firstError: unknown;
|
|
139
185
|
|
|
140
186
|
const settled = await Promise.all(
|
|
141
|
-
chunk(unique, SERVICE_LINKED_DOWNLOAD_URL_CHUNK_SIZE).map(
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
status
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
187
|
+
chunk(unique, SERVICE_LINKED_DOWNLOAD_URL_CHUNK_SIZE).map(
|
|
188
|
+
async (part): Promise<ServiceLinkedDownloadUrl[]> => {
|
|
189
|
+
try {
|
|
190
|
+
const entries = await lane(this.ctx).request<ServiceLinkedDownloadUrl[]>(
|
|
191
|
+
'POST',
|
|
192
|
+
'/assets/service/linked-url',
|
|
193
|
+
{ ids: part },
|
|
194
|
+
);
|
|
195
|
+
return Array.isArray(entries) ? entries : [];
|
|
196
|
+
} catch (error: unknown) {
|
|
197
|
+
const status = extractErrorStatus(error);
|
|
198
|
+
// `chunkSize` and `status`, never the ids and never a `url`: a minted
|
|
199
|
+
// URL in a log line is a credential in a log line.
|
|
200
|
+
logger.warn('assets.linkedDownloadUrls: chunk failed', {
|
|
201
|
+
method: 'assets.linkedDownloadUrls',
|
|
202
|
+
chunkSize: part.length,
|
|
203
|
+
status,
|
|
204
|
+
error: error instanceof Error ? error.message : String(error),
|
|
205
|
+
});
|
|
206
|
+
unresolvedIds.push(...part);
|
|
207
|
+
if (typeof status === 'number') statuses.push(status);
|
|
208
|
+
firstError ??= error;
|
|
209
|
+
return [];
|
|
210
|
+
}
|
|
211
|
+
},
|
|
212
|
+
),
|
|
161
213
|
);
|
|
162
214
|
|
|
163
215
|
if (unresolvedIds.length > 0) {
|
|
@@ -194,21 +246,29 @@ export class ServerAssetsApi extends AssetsApi {
|
|
|
194
246
|
if (unique.length === 0) return [];
|
|
195
247
|
|
|
196
248
|
const settled = await Promise.all(
|
|
197
|
-
chunk(unique, SERVICE_ASSET_METADATA_BY_SHA_CHUNK_SIZE).map(
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
249
|
+
chunk(unique, SERVICE_ASSET_METADATA_BY_SHA_CHUNK_SIZE).map(
|
|
250
|
+
async (part): Promise<ServiceAssetMetadataBySha[]> => {
|
|
251
|
+
try {
|
|
252
|
+
const body = options.ownerUserId
|
|
253
|
+
? { sha256s: part, ownerUserId: options.ownerUserId }
|
|
254
|
+
: { sha256s: part };
|
|
255
|
+
const entries = await lane(this.ctx).request<ServiceAssetMetadataBySha[]>(
|
|
256
|
+
'POST',
|
|
257
|
+
'/assets/service/by-sha256',
|
|
258
|
+
body,
|
|
259
|
+
);
|
|
260
|
+
return Array.isArray(entries) ? entries : [];
|
|
261
|
+
} catch (error: unknown) {
|
|
262
|
+
logger.warn('assets.metadataBySha256: chunk failed, continuing with remaining chunks', {
|
|
263
|
+
method: 'assets.metadataBySha256',
|
|
264
|
+
chunkSize: part.length,
|
|
265
|
+
status: extractErrorStatus(error),
|
|
266
|
+
error: error instanceof Error ? error.message : String(error),
|
|
267
|
+
});
|
|
268
|
+
return [];
|
|
269
|
+
}
|
|
270
|
+
},
|
|
271
|
+
),
|
|
212
272
|
);
|
|
213
273
|
return settled.flat();
|
|
214
274
|
}
|
|
@@ -222,7 +282,11 @@ export class ServerNotificationsApi extends NotificationsApi {
|
|
|
222
282
|
* recipient's own account.
|
|
223
283
|
*/
|
|
224
284
|
async create(data: CreateOxyNotificationRequest): Promise<Notification> {
|
|
225
|
-
const res = await lane(this.ctx).request<{ notification: Notification }>(
|
|
285
|
+
const res = await lane(this.ctx).request<{ notification: Notification }>(
|
|
286
|
+
'POST',
|
|
287
|
+
'/notifications',
|
|
288
|
+
data,
|
|
289
|
+
);
|
|
226
290
|
return res.notification;
|
|
227
291
|
}
|
|
228
292
|
}
|
|
@@ -274,33 +338,76 @@ interface ExecutionAuthorizationTerms {
|
|
|
274
338
|
expiresAt: string;
|
|
275
339
|
}
|
|
276
340
|
|
|
277
|
-
export type CreateExecutionAuthorizationInput = ExecutionAuthorizationTerms &
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
341
|
+
export type CreateExecutionAuthorizationInput = ExecutionAuthorizationTerms &
|
|
342
|
+
(
|
|
343
|
+
| {
|
|
344
|
+
kind: 'direct_request';
|
|
345
|
+
runId: string;
|
|
346
|
+
stepId?: string;
|
|
347
|
+
automationId?: never;
|
|
348
|
+
maximumAutonomy: Exclude<AutonomyLevel, 'autonomous'>;
|
|
349
|
+
}
|
|
350
|
+
| {
|
|
351
|
+
kind: 'automation';
|
|
352
|
+
automationId: string;
|
|
353
|
+
runId?: never;
|
|
354
|
+
stepId?: never;
|
|
355
|
+
maximumAutonomy: AutonomyLevel;
|
|
356
|
+
}
|
|
357
|
+
);
|
|
281
358
|
|
|
282
359
|
function agencyAuthorityOptions(signal?: AbortSignal): RequestOptions {
|
|
283
360
|
signal?.throwIfAborted();
|
|
284
|
-
return {
|
|
361
|
+
return {
|
|
362
|
+
cache: false,
|
|
363
|
+
deduplicate: false,
|
|
364
|
+
retry: false,
|
|
365
|
+
skipAuth: true,
|
|
366
|
+
timeout: 5000,
|
|
367
|
+
...(signal ? { signal } : {}),
|
|
368
|
+
};
|
|
285
369
|
}
|
|
286
370
|
|
|
287
371
|
export class ServerAgencyApi extends AgencyApi {
|
|
288
372
|
/** Live registry discovery with this service's existing capability scopes. */
|
|
289
|
-
async serviceCatalogs(
|
|
373
|
+
async serviceCatalogs(
|
|
374
|
+
input: { appId?: string; signal?: AbortSignal } = {},
|
|
375
|
+
): Promise<ServiceCapabilityCatalog[]> {
|
|
290
376
|
const path = `/capabilities/catalogs${input.appId === undefined ? '' : `?appId=${encodeURIComponent(input.appId)}`}`;
|
|
291
|
-
const result = await lane(this.ctx).request<{ registrations: ServiceCapabilityCatalog[] }>(
|
|
377
|
+
const result = await lane(this.ctx).request<{ registrations: ServiceCapabilityCatalog[] }>(
|
|
378
|
+
'GET',
|
|
379
|
+
path,
|
|
380
|
+
undefined,
|
|
381
|
+
agencyAuthorityOptions(input.signal),
|
|
382
|
+
);
|
|
292
383
|
return result.registrations;
|
|
293
384
|
}
|
|
294
385
|
|
|
295
386
|
/** Existing Oxy execution authority is required; this call creates none. */
|
|
296
|
-
async issueCapabilityTicket(
|
|
297
|
-
|
|
387
|
+
async issueCapabilityTicket(
|
|
388
|
+
input: CapabilityTicketRequest,
|
|
389
|
+
options: { signal?: AbortSignal } = {},
|
|
390
|
+
): Promise<CapabilityTicketGrant> {
|
|
391
|
+
return lane(this.ctx).request<CapabilityTicketGrant>(
|
|
392
|
+
'POST',
|
|
393
|
+
'/capabilities/tickets',
|
|
394
|
+
capabilityTicketRequestSchema.parse(input),
|
|
395
|
+
agencyAuthorityOptions(options.signal),
|
|
396
|
+
);
|
|
298
397
|
}
|
|
299
398
|
|
|
300
399
|
/** Receiving app authenticates live introspection using its own service credential. */
|
|
301
|
-
async introspectCapabilityTicket(
|
|
400
|
+
async introspectCapabilityTicket(
|
|
401
|
+
ticket: string,
|
|
402
|
+
options: { signal?: AbortSignal } = {},
|
|
403
|
+
): Promise<CapabilityTicketIntrospection> {
|
|
302
404
|
if (ticket.trim() === '') throw new Error('A capability ticket is required');
|
|
303
|
-
return lane(this.ctx).request<CapabilityTicketIntrospection>(
|
|
405
|
+
return lane(this.ctx).request<CapabilityTicketIntrospection>(
|
|
406
|
+
'POST',
|
|
407
|
+
'/capabilities/tickets/introspect',
|
|
408
|
+
{ ticket },
|
|
409
|
+
agencyAuthorityOptions(options.signal),
|
|
410
|
+
);
|
|
304
411
|
}
|
|
305
412
|
|
|
306
413
|
/**
|
|
@@ -308,30 +415,69 @@ export class ServerAgencyApi extends AgencyApi {
|
|
|
308
415
|
* The service bearer and attribution headers cannot substitute for that user.
|
|
309
416
|
* The token goes only to this client's configured Oxy authority; never retry.
|
|
310
417
|
*/
|
|
311
|
-
async createExecutionAuthorization(
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
418
|
+
async createExecutionAuthorization(
|
|
419
|
+
input: CreateExecutionAuthorizationInput,
|
|
420
|
+
options: { requesterToken: string; signal?: AbortSignal },
|
|
421
|
+
): Promise<CapabilityExecutionAuthorization> {
|
|
422
|
+
if (options.requesterToken === '' || /\s/.test(options.requesterToken))
|
|
423
|
+
throw new Error('A requester bearer is required');
|
|
424
|
+
const result = await this.ctx.request<{ authorization: CapabilityExecutionAuthorization }>(
|
|
425
|
+
'POST',
|
|
426
|
+
'/capabilities/execution-authorizations',
|
|
427
|
+
input,
|
|
428
|
+
{
|
|
429
|
+
...agencyAuthorityOptions(options.signal),
|
|
430
|
+
headers: { Authorization: `Bearer ${options.requesterToken}` },
|
|
431
|
+
},
|
|
432
|
+
);
|
|
317
433
|
return result.authorization;
|
|
318
434
|
}
|
|
319
435
|
|
|
320
436
|
/** Revoke a direct approval on its canonical requester-authenticated lane. */
|
|
321
|
-
async revokeExecutionAuthorization(
|
|
437
|
+
async revokeExecutionAuthorization(
|
|
438
|
+
authorizationId: string,
|
|
439
|
+
options: { requesterToken: string; signal?: AbortSignal },
|
|
440
|
+
): Promise<void> {
|
|
322
441
|
options.signal?.throwIfAborted();
|
|
323
|
-
if (!authorizationId || authorizationId.length > 255 || /\s/.test(authorizationId))
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
442
|
+
if (!authorizationId || authorizationId.length > 255 || /\s/.test(authorizationId))
|
|
443
|
+
throw new Error('An execution authorization id is required');
|
|
444
|
+
if (
|
|
445
|
+
!options.requesterToken ||
|
|
446
|
+
options.requesterToken.length > 16_384 ||
|
|
447
|
+
/\s/.test(options.requesterToken)
|
|
448
|
+
)
|
|
449
|
+
throw new Error('A requester bearer is required');
|
|
450
|
+
await this.ctx.request<void>(
|
|
451
|
+
'DELETE',
|
|
452
|
+
`/capabilities/execution-authorizations/${encodeURIComponent(authorizationId)}`,
|
|
453
|
+
undefined,
|
|
454
|
+
{
|
|
455
|
+
...agencyAuthorityOptions(options.signal),
|
|
456
|
+
headers: { Authorization: `Bearer ${options.requesterToken}` },
|
|
457
|
+
},
|
|
458
|
+
);
|
|
327
459
|
}
|
|
328
460
|
|
|
329
461
|
/** Independent service proof plus present requester bearer, sent only to Oxy. */
|
|
330
|
-
async createForegroundExecutionAuthorization(
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
462
|
+
async createForegroundExecutionAuthorization(
|
|
463
|
+
input: ForegroundExecutionAuthorizationInput,
|
|
464
|
+
options: { requesterToken: string; signal?: AbortSignal },
|
|
465
|
+
): Promise<CapabilityExecutionAuthorization> {
|
|
466
|
+
if (
|
|
467
|
+
options.requesterToken === '' ||
|
|
468
|
+
options.requesterToken.length > 16_384 ||
|
|
469
|
+
/\s/.test(options.requesterToken)
|
|
470
|
+
)
|
|
471
|
+
throw new Error('A requester bearer is required');
|
|
472
|
+
const result = await lane(this.ctx).request<{
|
|
473
|
+
authorization: CapabilityExecutionAuthorization;
|
|
474
|
+
}>(
|
|
475
|
+
'POST',
|
|
476
|
+
'/capabilities/foreground-execution-authorizations',
|
|
477
|
+
{
|
|
478
|
+
...foregroundExecutionAuthorizationInputSchema.parse(input),
|
|
479
|
+
subjectToken: options.requesterToken,
|
|
480
|
+
},
|
|
335
481
|
agencyAuthorityOptions(options.signal),
|
|
336
482
|
);
|
|
337
483
|
return result.authorization;
|
|
@@ -344,7 +490,10 @@ export class ServerAgencyApi extends AgencyApi {
|
|
|
344
490
|
* forward it anywhere else. Not retried: a refusal is an answer, and the
|
|
345
491
|
* caller mints per turn.
|
|
346
492
|
*/
|
|
347
|
-
async mintRequesterAssertion(input: {
|
|
493
|
+
async mintRequesterAssertion(input: {
|
|
494
|
+
agentId: string;
|
|
495
|
+
subjectToken: string;
|
|
496
|
+
}): Promise<RequesterAssertionGrant> {
|
|
348
497
|
return lane(this.ctx).request<RequesterAssertionGrant>(
|
|
349
498
|
'POST',
|
|
350
499
|
'/internal/native-agents/requester-assertions',
|
|
@@ -378,7 +527,11 @@ export class ServerReputationApi extends ReputationApi {
|
|
|
378
527
|
* moves it by hand. Invalidates cached reputation reads.
|
|
379
528
|
*/
|
|
380
529
|
async award(input: AwardReputationInput): Promise<ReputationTransaction> {
|
|
381
|
-
const res = await lane(this.ctx).request<{ transaction: ReputationTransaction }>(
|
|
530
|
+
const res = await lane(this.ctx).request<{ transaction: ReputationTransaction }>(
|
|
531
|
+
'POST',
|
|
532
|
+
'/reputation/award',
|
|
533
|
+
input,
|
|
534
|
+
);
|
|
382
535
|
this.ctx.oxy.cache.deletePrefix(REPUTATION_CACHE_PREFIX);
|
|
383
536
|
return res.transaction;
|
|
384
537
|
}
|
package/src/server/rateLimit.ts
CHANGED
|
@@ -197,8 +197,7 @@ function maskIPv6(ip: string, bits: number): string {
|
|
|
197
197
|
* salt. The result is a short hex digest with no colons, so it is Redis-safe.
|
|
198
198
|
*/
|
|
199
199
|
function hashAnonymousIp(ip: string): string {
|
|
200
|
-
const normalized =
|
|
201
|
-
isIPv6(ip) && !ip.startsWith('::ffff:') ? maskIPv6(ip, IPV6_SUBNET_BITS) : ip;
|
|
200
|
+
const normalized = isIPv6(ip) && !ip.startsWith('::ffff:') ? maskIPv6(ip, IPV6_SUBNET_BITS) : ip;
|
|
202
201
|
const salt = process.env.IP_HASH_SALT || process.env.DEVICE_ID_SALT || '';
|
|
203
202
|
return createHmac('sha256', salt).update(`rl|${normalized}`).digest('hex').slice(0, 24);
|
|
204
203
|
}
|
|
@@ -273,8 +272,7 @@ export function createOxyRateLimit(
|
|
|
273
272
|
// not just to the bucket calculation.
|
|
274
273
|
const resolveSession = createOptionalOxyAuth(oxy, { auth });
|
|
275
274
|
|
|
276
|
-
const skip = (req: Request): boolean =>
|
|
277
|
-
isBuiltInExempt(req) || (exempt ? exempt(req) : false);
|
|
275
|
+
const skip = (req: Request): boolean => isBuiltInExempt(req) || (exempt ? exempt(req) : false);
|
|
278
276
|
|
|
279
277
|
const limiter = rateLimit({
|
|
280
278
|
windowMs,
|