@oxy.so/core 7.11.0 → 7.12.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 +8 -0
- package/dist/cjs/HttpService.js +70 -1
- package/dist/cjs/OxyServices.js +1 -1
- package/dist/cjs/api/holderEvidence.js +12 -0
- package/dist/cjs/api/session.js +118 -0
- package/dist/cjs/aws/index.js +47 -1
- package/dist/cjs/index.js +6 -4
- package/dist/esm/HttpService.js +70 -1
- package/dist/esm/OxyServices.js +1 -1
- package/dist/esm/api/holderEvidence.js +9 -0
- package/dist/esm/api/session.js +118 -0
- package/dist/esm/aws/index.js +14 -1
- package/dist/esm/index.js +1 -0
- package/dist/types/HttpService.d.ts +25 -1
- package/dist/types/api/holderEvidence.d.ts +45 -0
- package/dist/types/api/session.d.ts +21 -0
- package/dist/types/index.d.ts +3 -1
- package/dist/types/server/safety.d.ts +9 -9
- package/package.json +9 -4
- package/src/HttpService.ts +108 -1
- package/src/OxyServices.ts +4 -1
- package/src/api/holderEvidence.ts +66 -0
- package/src/api/session.ts +145 -0
- package/src/aws/index.ts +15 -1
- package/src/index.ts +8 -0
package/dist/esm/api/session.js
CHANGED
|
@@ -8,12 +8,21 @@
|
|
|
8
8
|
import { jwtDecode } from 'jwt-decode';
|
|
9
9
|
import { normalizeUserIdentity } from '../utils/userIdentity.js';
|
|
10
10
|
import { OxyApiError } from '../OxyServices.errors.js';
|
|
11
|
+
import { checkContract, holderContextEvidenceV1ResponseCheck } from '@oxy.so/contracts/client';
|
|
12
|
+
/** How long a refusal (disabled, rate limited, unreachable) is remembered per installation. */
|
|
13
|
+
const EVIDENCE_REFUSAL_MS = 5000;
|
|
14
|
+
const unavailable = (reason) => ({
|
|
15
|
+
status: 'unavailable',
|
|
16
|
+
reason,
|
|
17
|
+
});
|
|
11
18
|
export class SessionApi {
|
|
12
19
|
constructor(ctx) {
|
|
13
20
|
this.ctx = ctx;
|
|
14
21
|
this.deviceCredentialProvider = null;
|
|
15
22
|
this.decodedFor = null;
|
|
16
23
|
this.decoded = null;
|
|
24
|
+
/** One server round trip per installed bearer; the key is the opaque generation. */
|
|
25
|
+
this.evidence = new WeakMap();
|
|
17
26
|
}
|
|
18
27
|
// ── Local state ──────────────────────────────────────────────────────────
|
|
19
28
|
/** The current access token, or `null` when signed out. */
|
|
@@ -118,6 +127,115 @@ export class SessionApi {
|
|
|
118
127
|
return null;
|
|
119
128
|
}
|
|
120
129
|
}
|
|
130
|
+
// ── Holder-context evidence (ADR 0053) ───────────────────────────────────
|
|
131
|
+
/**
|
|
132
|
+
* Ask the server which shared-device context the INSTALLED bearer belongs to,
|
|
133
|
+
* and bind the answer to that exact installation.
|
|
134
|
+
*
|
|
135
|
+
* The result is honored only if the credential generation captured before
|
|
136
|
+
* the request is still current when the answer is committed, so a refresh,
|
|
137
|
+
* setter, account or actor switch, cross-tab change, restore or A to B to A
|
|
138
|
+
* during the request yields `changed`. The answer must also agree with the
|
|
139
|
+
* claims of the bearer that was captured; a disagreement is
|
|
140
|
+
* `binding_unavailable`. Nothing here refreshes, clears or mints a credential,
|
|
141
|
+
* and no outcome is a revocation verdict: callers keep their existing checks.
|
|
142
|
+
* Concurrent callers share one request per installation.
|
|
143
|
+
*/
|
|
144
|
+
observeHolderEvidence() {
|
|
145
|
+
const generation = this.ctx.http.captureCredentialGeneration();
|
|
146
|
+
const token = this.ctx.http.getAccessToken();
|
|
147
|
+
if (!generation || !token)
|
|
148
|
+
return Promise.resolve(unavailable('no_credential'));
|
|
149
|
+
const known = this.evidence.get(generation);
|
|
150
|
+
if (known) {
|
|
151
|
+
const refused = known.settledAt !== undefined;
|
|
152
|
+
if (!refused || Date.now() - known.settledAt < EVIDENCE_REFUSAL_MS) {
|
|
153
|
+
return known.result.then((result) => result.status === 'ok' && result.evidence.expiresAtMs <= Date.now()
|
|
154
|
+
? this.refreshEvidence(generation, token)
|
|
155
|
+
: result);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return this.refreshEvidence(generation, token);
|
|
159
|
+
}
|
|
160
|
+
/** Whether evidence still names the installed bearer and has not expired. */
|
|
161
|
+
isHolderEvidenceCurrent(evidence) {
|
|
162
|
+
return (Date.now() < evidence.expiresAtMs &&
|
|
163
|
+
this.ctx.http.isCredentialGenerationCurrent(evidence.generation));
|
|
164
|
+
}
|
|
165
|
+
refreshEvidence(generation, token) {
|
|
166
|
+
const entry = {
|
|
167
|
+
result: this.acquireEvidence(generation, token).then((result) => {
|
|
168
|
+
if (result.status !== 'ok')
|
|
169
|
+
entry.settledAt = Date.now();
|
|
170
|
+
return result;
|
|
171
|
+
}),
|
|
172
|
+
};
|
|
173
|
+
this.evidence.set(generation, entry);
|
|
174
|
+
return entry.result;
|
|
175
|
+
}
|
|
176
|
+
async acquireEvidence(generation, token) {
|
|
177
|
+
let claims;
|
|
178
|
+
try {
|
|
179
|
+
claims = jwtDecode(token);
|
|
180
|
+
}
|
|
181
|
+
catch {
|
|
182
|
+
return unavailable('unsupported');
|
|
183
|
+
}
|
|
184
|
+
const proof = await this.readDeviceProof();
|
|
185
|
+
if (!proof)
|
|
186
|
+
return unavailable('no_holder');
|
|
187
|
+
let response;
|
|
188
|
+
try {
|
|
189
|
+
response = await this.ctx.request('POST', '/session/device/context-evidence-v1', proof, {
|
|
190
|
+
cache: false,
|
|
191
|
+
retry: false,
|
|
192
|
+
expectedCredentialGeneration: generation,
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
catch (error) {
|
|
196
|
+
if (error?.code === 'AUTH_SESSION_CHANGED') {
|
|
197
|
+
return unavailable('changed');
|
|
198
|
+
}
|
|
199
|
+
const status = error instanceof OxyApiError ? error.status : 0;
|
|
200
|
+
if (status === 403)
|
|
201
|
+
return unavailable('unsupported');
|
|
202
|
+
if (status === 409)
|
|
203
|
+
return unavailable('binding_unavailable');
|
|
204
|
+
return unavailable('unavailable');
|
|
205
|
+
}
|
|
206
|
+
const parsed = checkContract(holderContextEvidenceV1ResponseCheck, response);
|
|
207
|
+
if (!parsed)
|
|
208
|
+
return unavailable('unavailable');
|
|
209
|
+
// Commit synchronously: nothing may replace the bearer between this check
|
|
210
|
+
// and the evidence becoming visible to its caller.
|
|
211
|
+
if (!this.ctx.http.isCredentialGenerationCurrent(generation))
|
|
212
|
+
return unavailable('changed');
|
|
213
|
+
const expiresAtMs = Date.parse(parsed.expiresAt);
|
|
214
|
+
if (parsed.deviceId !== proof.deviceId ||
|
|
215
|
+
parsed.accountId !== claims.userId ||
|
|
216
|
+
parsed.sessionId !== claims.sessionId ||
|
|
217
|
+
(claims.act?.sub !== undefined && parsed.actorId !== claims.act.sub) ||
|
|
218
|
+
(claims.device_context_id !== undefined && parsed.contextId !== claims.device_context_id)) {
|
|
219
|
+
return unavailable('binding_unavailable');
|
|
220
|
+
}
|
|
221
|
+
if (!Number.isFinite(expiresAtMs) || expiresAtMs <= Date.now()) {
|
|
222
|
+
return unavailable('unavailable');
|
|
223
|
+
}
|
|
224
|
+
const evidence = Object.freeze({
|
|
225
|
+
generation,
|
|
226
|
+
identity: Object.freeze({
|
|
227
|
+
deviceId: parsed.deviceId,
|
|
228
|
+
deviceSessionId: parsed.deviceSessionId,
|
|
229
|
+
contextId: parsed.contextId,
|
|
230
|
+
actorId: parsed.actorId,
|
|
231
|
+
accountId: parsed.accountId,
|
|
232
|
+
sessionId: parsed.sessionId,
|
|
233
|
+
}),
|
|
234
|
+
deviceRevision: parsed.revision,
|
|
235
|
+
expiresAtMs,
|
|
236
|
+
});
|
|
237
|
+
return { status: 'ok', evidence };
|
|
238
|
+
}
|
|
121
239
|
// ── The server session ───────────────────────────────────────────────────
|
|
122
240
|
/** Ask the server whether the current access token is valid. */
|
|
123
241
|
async validateToken() {
|
package/dist/esm/aws/index.js
CHANGED
|
@@ -6,8 +6,21 @@ import { defaultProvider } from '@aws-sdk/credential-provider-node';
|
|
|
6
6
|
* Long-lived IAM user access keys are deliberately not a local service identity.
|
|
7
7
|
*/
|
|
8
8
|
export function createAwsWorkloadCredentialProvider(options = {}) {
|
|
9
|
-
|
|
9
|
+
// An explicitly selected profile is an authority boundary. defaultProvider
|
|
10
|
+
// falls through a missing profile to ambient ECS/IMDS credentials, which may
|
|
11
|
+
// name another application. fromIni resolves only the selected profile and
|
|
12
|
+
// its declared source chain, or rejects; there is no ambient fallback.
|
|
13
|
+
if (options.profile !== undefined && !options.profile.trim())
|
|
14
|
+
throw new Error('An explicit AWS workload profile must not be empty');
|
|
15
|
+
const ambient = options.profile === undefined ? defaultProvider(options) : undefined;
|
|
16
|
+
const resolveProfile = async () => (await import('@aws-sdk/credential-provider-ini')).fromIni(options);
|
|
17
|
+
let selectedProfile;
|
|
10
18
|
return async () => {
|
|
19
|
+
let provider = ambient;
|
|
20
|
+
if (!provider) {
|
|
21
|
+
selectedProfile ?? (selectedProfile = resolveProfile());
|
|
22
|
+
provider = await selectedProfile;
|
|
23
|
+
}
|
|
11
24
|
const credentials = await provider();
|
|
12
25
|
if (!credentials.sessionToken ||
|
|
13
26
|
!credentials.expiration ||
|
package/dist/esm/index.js
CHANGED
|
@@ -30,6 +30,7 @@ import './crypto/polyfill.js';
|
|
|
30
30
|
// ---------------------------------------------------------------------------
|
|
31
31
|
export { OxyServices, OXY_API_URL, OXY_CLOUD_URL } from './OxyServices.js';
|
|
32
32
|
export { OxyApiError, OxyAuthenticationError, OxyAuthenticationTimeoutError, AssetUrlResolutionError, ServiceAssetMetadataError, } from './OxyServices.errors.js';
|
|
33
|
+
export { sameHolderIdentity } from './api/holderEvidence.js';
|
|
33
34
|
export { ASSET_MULTIPART_UPLOAD_MAX_BYTES, assetUrlCacheTTL, MAX_UPLOAD_BYTES } from './api/assets.js';
|
|
34
35
|
export { DirectUploadInterruptedError } from './api/directUpload.js';
|
|
35
36
|
export { buildUserDid } from './api/identity.js';
|
|
@@ -22,6 +22,18 @@ export type AccessTokenProvider = () => string | null;
|
|
|
22
22
|
* — `null` to send it anonymous. See {@link HttpService.setAnonymousAuthProvider}.
|
|
23
23
|
*/
|
|
24
24
|
export type AnonymousAuthProvider = () => Promise<string | null>;
|
|
25
|
+
declare const credentialGenerationBrand: unique symbol;
|
|
26
|
+
/**
|
|
27
|
+
* An opaque, immutable token for ONE installation of a bearer in a client.
|
|
28
|
+
*
|
|
29
|
+
* `TokenStore` swaps it on every write path (setter, refresh, account or actor
|
|
30
|
+
* switch, cross-tab or restored token, clear), so two installations of the same
|
|
31
|
+
* bytes (A, B, A) are different generations. It names a local sequence only: it
|
|
32
|
+
* is not evidence of an account, a scope or authorization.
|
|
33
|
+
*/
|
|
34
|
+
export type CredentialGeneration = {
|
|
35
|
+
readonly [credentialGenerationBrand]: true;
|
|
36
|
+
};
|
|
25
37
|
/** A trusted platform transport, for example Expo's streaming fetch. */
|
|
26
38
|
export type ResponseTransport = (input: string, init: RequestInit) => Promise<Response>;
|
|
27
39
|
/**
|
|
@@ -44,6 +56,13 @@ export interface ResponseRequest {
|
|
|
44
56
|
/** Same response contract, but rejects locally when the SDK has no bearer. */
|
|
45
57
|
export type AuthenticatedResponseRequest = ResponseRequest;
|
|
46
58
|
export interface RequestOptions {
|
|
59
|
+
/**
|
|
60
|
+
* Bind a write to ONE installation of the source's bearer. The transport
|
|
61
|
+
* rejects (`AUTH_SESSION_CHANGED`) when the generation was replaced before
|
|
62
|
+
* dispatch, after queueing, or before the result is returned. Implies no cache,
|
|
63
|
+
* deduplication or retry, and a 401 neither refreshes nor clears the session.
|
|
64
|
+
*/
|
|
65
|
+
expectedCredentialGeneration?: CredentialGeneration;
|
|
47
66
|
cache?: boolean;
|
|
48
67
|
cacheTTL?: number;
|
|
49
68
|
deduplicate?: boolean;
|
|
@@ -228,6 +247,7 @@ export declare class HttpService {
|
|
|
228
247
|
* bearer — and through the token listeners, the account — back.
|
|
229
248
|
*/
|
|
230
249
|
private sessionEpoch;
|
|
250
|
+
private readonly credentialSource;
|
|
231
251
|
/** Preserve a known device across legacy rotations which omit the claim. */
|
|
232
252
|
private sessionDeviceId;
|
|
233
253
|
/** Preserve known actor and context hints across rotations without those claims. */
|
|
@@ -258,7 +278,7 @@ export declare class HttpService {
|
|
|
258
278
|
*/
|
|
259
279
|
private _tokenChangeListeners;
|
|
260
280
|
private requestMetrics;
|
|
261
|
-
constructor(config: OxyConfig);
|
|
281
|
+
constructor(config: OxyConfig, credentialSource?: HttpService | null);
|
|
262
282
|
private syncAccessTokenFromProvider;
|
|
263
283
|
/**
|
|
264
284
|
* Robust FormData detection that works in browser, React Native, and
|
|
@@ -521,6 +541,10 @@ export declare class HttpService {
|
|
|
521
541
|
* plants tokens itself (the device-secret arm) compares it across its awaits.
|
|
522
542
|
*/
|
|
523
543
|
getSessionEpoch(): number;
|
|
544
|
+
/** Capture only the local generation; the caller must separately bind authority. */
|
|
545
|
+
captureCredentialGeneration(): CredentialGeneration | null;
|
|
546
|
+
isCredentialGenerationCurrent(generation: CredentialGeneration): boolean;
|
|
547
|
+
private assertCredentialGeneration;
|
|
524
548
|
/** Whether {@link endSession} ran and no token has been planted since. */
|
|
525
549
|
hasSessionEnded(): boolean;
|
|
526
550
|
setAuthRefreshHandler(handler: AuthRefreshHandler | null): void;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Holder-context evidence: the server's point-in-time observation of which
|
|
3
|
+
* shared-device context a bearer is installed in, bound to ONE installation of
|
|
4
|
+
* that bearer in this client (ADR 0053).
|
|
5
|
+
*
|
|
6
|
+
* Evidence is never authorization. It lets a caller that already captured a
|
|
7
|
+
* viewer intent prove, before a write is dispatched, that the bearer the write
|
|
8
|
+
* will carry belongs to that viewer's account and actor, and then pin the write
|
|
9
|
+
* to the exact installation with `expectedCredentialGeneration`. Anything that
|
|
10
|
+
* cannot be proven is `unavailable`, and the caller keeps its existing checks.
|
|
11
|
+
*/
|
|
12
|
+
import type { HolderContextEvidenceV1Response } from '@oxy.so/contracts';
|
|
13
|
+
import type { CredentialGeneration } from '../HttpService';
|
|
14
|
+
/** The identifiers the server observed; none of them is a credential. */
|
|
15
|
+
export type HolderEvidenceIdentity = Readonly<Pick<HolderContextEvidenceV1Response, 'deviceId' | 'deviceSessionId' | 'contextId' | 'actorId' | 'accountId' | 'sessionId'>>;
|
|
16
|
+
export interface HolderEvidence {
|
|
17
|
+
/** The installation of the bearer this evidence was observed for. */
|
|
18
|
+
readonly generation: CredentialGeneration;
|
|
19
|
+
readonly identity: HolderEvidenceIdentity;
|
|
20
|
+
/** The device-session revision the server observed. */
|
|
21
|
+
readonly deviceRevision: number;
|
|
22
|
+
/** Epoch milliseconds: the earlier of the bearer and session expiry. */
|
|
23
|
+
readonly expiresAtMs: number;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Why no evidence exists. Every reason means "keep the existing checks": none of
|
|
27
|
+
* them says the session is revoked, and none may clear or refresh credentials.
|
|
28
|
+
*
|
|
29
|
+
* - `no_credential`: no bearer is installed, or it comes from a pull-only provider.
|
|
30
|
+
* - `no_holder`: this client holds no device credential to prove the holder with.
|
|
31
|
+
* - `changed`: the bearer was replaced while the evidence was being acquired.
|
|
32
|
+
* - `unsupported`: a delegated, OAuth or legacy bearer, or the endpoint is not offered.
|
|
33
|
+
* - `binding_unavailable`: the server could not match holder, context and bearer.
|
|
34
|
+
* - `unavailable`: the endpoint is off, rate limited, unreachable or answered wrongly.
|
|
35
|
+
*/
|
|
36
|
+
export type HolderEvidenceUnavailableReason = 'no_credential' | 'no_holder' | 'changed' | 'unsupported' | 'binding_unavailable' | 'unavailable';
|
|
37
|
+
export type HolderEvidenceResult = {
|
|
38
|
+
readonly status: 'ok';
|
|
39
|
+
readonly evidence: HolderEvidence;
|
|
40
|
+
} | {
|
|
41
|
+
readonly status: 'unavailable';
|
|
42
|
+
readonly reason: HolderEvidenceUnavailableReason;
|
|
43
|
+
};
|
|
44
|
+
/** The one comparison that decides whether two observations name the same viewer context. */
|
|
45
|
+
export declare function sameHolderIdentity(a: HolderEvidenceIdentity, b: HolderEvidenceIdentity): boolean;
|
|
@@ -2,6 +2,7 @@ import type { AccountActorChain, DeviceProof } from '@oxy.so/contracts';
|
|
|
2
2
|
import type { OxyContext } from '../client/context';
|
|
3
3
|
import type { ClientSession } from '../models/session';
|
|
4
4
|
import type { User } from '../models/interfaces';
|
|
5
|
+
import type { HolderEvidence, HolderEvidenceResult } from './holderEvidence';
|
|
5
6
|
/**
|
|
6
7
|
* Reads the device credential this client holds, if any — `{ deviceId,
|
|
7
8
|
* deviceSecret }` from the provider's auth store. See
|
|
@@ -29,6 +30,8 @@ export declare class SessionApi {
|
|
|
29
30
|
private deviceCredentialProvider;
|
|
30
31
|
private decodedFor;
|
|
31
32
|
private decoded;
|
|
33
|
+
/** One server round trip per installed bearer; the key is the opaque generation. */
|
|
34
|
+
private readonly evidence;
|
|
32
35
|
constructor(ctx: OxyContext);
|
|
33
36
|
/** The current access token, or `null` when signed out. */
|
|
34
37
|
get accessToken(): string | null;
|
|
@@ -75,6 +78,24 @@ export declare class SessionApi {
|
|
|
75
78
|
* that cannot be read only means the sign-in gets its own device.
|
|
76
79
|
*/
|
|
77
80
|
readDeviceProof(): Promise<DeviceProof | null>;
|
|
81
|
+
/**
|
|
82
|
+
* Ask the server which shared-device context the INSTALLED bearer belongs to,
|
|
83
|
+
* and bind the answer to that exact installation.
|
|
84
|
+
*
|
|
85
|
+
* The result is honored only if the credential generation captured before
|
|
86
|
+
* the request is still current when the answer is committed, so a refresh,
|
|
87
|
+
* setter, account or actor switch, cross-tab change, restore or A to B to A
|
|
88
|
+
* during the request yields `changed`. The answer must also agree with the
|
|
89
|
+
* claims of the bearer that was captured; a disagreement is
|
|
90
|
+
* `binding_unavailable`. Nothing here refreshes, clears or mints a credential,
|
|
91
|
+
* and no outcome is a revocation verdict: callers keep their existing checks.
|
|
92
|
+
* Concurrent callers share one request per installation.
|
|
93
|
+
*/
|
|
94
|
+
observeHolderEvidence(): Promise<HolderEvidenceResult>;
|
|
95
|
+
/** Whether evidence still names the installed bearer and has not expired. */
|
|
96
|
+
isHolderEvidenceCurrent(evidence: HolderEvidence): boolean;
|
|
97
|
+
private refreshEvidence;
|
|
98
|
+
private acquireEvidence;
|
|
78
99
|
/** Ask the server whether the current access token is valid. */
|
|
79
100
|
validateToken(): Promise<boolean>;
|
|
80
101
|
/**
|
package/dist/types/index.d.ts
CHANGED
|
@@ -24,7 +24,9 @@ export { OxyServices, OXY_API_URL, OXY_CLOUD_URL } from './OxyServices';
|
|
|
24
24
|
export type { OxyConfig, LinkedHttpClient } from './OxyServices';
|
|
25
25
|
export { OxyApiError, OxyAuthenticationError, OxyAuthenticationTimeoutError, AssetUrlResolutionError, ServiceAssetMetadataError, } from './OxyServices.errors';
|
|
26
26
|
export type { HttpMethod } from './client/context';
|
|
27
|
-
export type { RequestOptions, ResponsePayload, ResponseRequest, ResponseTransport, AuthenticatedResponseRequest, AuthRefreshReason, AuthRefreshHandler, } from './HttpService';
|
|
27
|
+
export type { RequestOptions, ResponsePayload, ResponseRequest, ResponseTransport, AuthenticatedResponseRequest, AuthRefreshReason, AuthRefreshHandler, CredentialGeneration, } from './HttpService';
|
|
28
|
+
export { sameHolderIdentity } from './api/holderEvidence';
|
|
29
|
+
export type { HolderEvidence, HolderEvidenceIdentity, HolderEvidenceResult, HolderEvidenceUnavailableReason, } from './api/holderEvidence';
|
|
28
30
|
export type { SessionApi, DeviceCredentialProvider, SessionValidation } from './api/session';
|
|
29
31
|
export type { AuthApi, ChallengeResponse, RegistrationRequest, ChallengeVerifyRequest, PublicKeyCheckResponse, OAuthUserInfoResponse, OAuthTokenExchangeResult, CommonsSignInHandle, CommonsSignInStatus, CommonsSignInPurpose, CommonsOAuthContext, CommonsApprovalInfo, CommonsApprovalSubjectAccount, CommonsSignInActionResult, CommonsOAuthFinalizeResult, CommonsDeliveryResult, SignInDeviceOptions, ClaimedSession, } from './api/auth';
|
|
30
32
|
export type { UsersApi, ResolveExternalUserInput, DeleteAccountProof } from './api/users';
|
|
@@ -17,7 +17,7 @@ export declare class ServerSafetyApi extends SafetyApi {
|
|
|
17
17
|
/** The original personal bearer, a verified MCP connection proof, or explicit anonymous access. */
|
|
18
18
|
profileAccess(input: ProfileAccessInput, options?: SafetyRequester): Promise<{
|
|
19
19
|
allowed: boolean;
|
|
20
|
-
reason: "blocked" | "private" | "public" | "
|
|
20
|
+
reason: "blocked" | "private" | "public" | "unavailable" | "owner";
|
|
21
21
|
policyVersion: "1";
|
|
22
22
|
}>;
|
|
23
23
|
profileAccessBatch(input: ProfileAccessBatchInput, options: SafetyRequester): Promise<{
|
|
@@ -25,14 +25,14 @@ export declare class ServerSafetyApi extends SafetyApi {
|
|
|
25
25
|
subjectAccountId: string;
|
|
26
26
|
decision: {
|
|
27
27
|
allowed: boolean;
|
|
28
|
-
reason: "blocked" | "private" | "public" | "
|
|
28
|
+
reason: "blocked" | "private" | "public" | "unavailable" | "owner" | "allowed" | "unsupported_consumer" | "contact_not_approved" | "mature_content" | "unrated_content" | "approval_required";
|
|
29
29
|
policyVersion: "2";
|
|
30
30
|
};
|
|
31
31
|
}[];
|
|
32
32
|
}>;
|
|
33
33
|
messageAccess(input: MessageAccessInput, options: SafetyRequester): Promise<{
|
|
34
34
|
allowed: boolean;
|
|
35
|
-
reason: "blocked" | "private" | "public" | "
|
|
35
|
+
reason: "blocked" | "private" | "public" | "unavailable" | "owner" | "allowed" | "unsupported_consumer" | "contact_not_approved" | "mature_content" | "unrated_content" | "approval_required";
|
|
36
36
|
policyVersion: "2";
|
|
37
37
|
}>;
|
|
38
38
|
messageAccessBatch(input: MessageAccessBatchInput, options: SafetyRequester): Promise<{
|
|
@@ -40,7 +40,7 @@ export declare class ServerSafetyApi extends SafetyApi {
|
|
|
40
40
|
resourceId: string;
|
|
41
41
|
decision: {
|
|
42
42
|
allowed: boolean;
|
|
43
|
-
reason: "blocked" | "private" | "public" | "
|
|
43
|
+
reason: "blocked" | "private" | "public" | "unavailable" | "owner" | "allowed" | "unsupported_consumer" | "contact_not_approved" | "mature_content" | "unrated_content" | "approval_required";
|
|
44
44
|
policyVersion: "2";
|
|
45
45
|
};
|
|
46
46
|
}[];
|
|
@@ -60,7 +60,7 @@ export declare class ServerSafetyApi extends SafetyApi {
|
|
|
60
60
|
resourceId: string;
|
|
61
61
|
decision: {
|
|
62
62
|
allowed: boolean;
|
|
63
|
-
reason: "blocked" | "private" | "public" | "
|
|
63
|
+
reason: "blocked" | "private" | "public" | "unavailable" | "owner" | "allowed" | "unsupported_consumer" | "contact_not_approved" | "mature_content" | "unrated_content" | "approval_required";
|
|
64
64
|
policyVersion: "2";
|
|
65
65
|
};
|
|
66
66
|
}[];
|
|
@@ -70,7 +70,7 @@ export declare class ServerSafetyApi extends SafetyApi {
|
|
|
70
70
|
targetAccountId: string;
|
|
71
71
|
decision: {
|
|
72
72
|
allowed: boolean;
|
|
73
|
-
reason: "blocked" | "private" | "public" | "
|
|
73
|
+
reason: "blocked" | "private" | "public" | "unavailable" | "owner" | "allowed" | "unsupported_consumer" | "contact_not_approved" | "mature_content" | "unrated_content" | "approval_required";
|
|
74
74
|
policyVersion: "2";
|
|
75
75
|
};
|
|
76
76
|
}[];
|
|
@@ -96,7 +96,7 @@ export declare class ServerSafetyApi extends SafetyApi {
|
|
|
96
96
|
}>;
|
|
97
97
|
contentAccess(input: ContentAccessInput, options: SafetyRequester): Promise<{
|
|
98
98
|
allowed: boolean;
|
|
99
|
-
reason: "blocked" | "private" | "public" | "
|
|
99
|
+
reason: "blocked" | "private" | "public" | "unavailable" | "owner" | "allowed" | "unsupported_consumer" | "contact_not_approved" | "mature_content" | "unrated_content" | "approval_required";
|
|
100
100
|
policyVersion: "2";
|
|
101
101
|
}>;
|
|
102
102
|
contentAccessBatch(input: ContentAccessBatchInput, options: SafetyRequester): Promise<{
|
|
@@ -104,14 +104,14 @@ export declare class ServerSafetyApi extends SafetyApi {
|
|
|
104
104
|
resourceId: string;
|
|
105
105
|
decision: {
|
|
106
106
|
allowed: boolean;
|
|
107
|
-
reason: "blocked" | "private" | "public" | "
|
|
107
|
+
reason: "blocked" | "private" | "public" | "unavailable" | "owner" | "allowed" | "unsupported_consumer" | "contact_not_approved" | "mature_content" | "unrated_content" | "approval_required";
|
|
108
108
|
policyVersion: "2";
|
|
109
109
|
};
|
|
110
110
|
}[];
|
|
111
111
|
}>;
|
|
112
112
|
deliveryAccess(input: DeliveryAccessInput): Promise<{
|
|
113
113
|
allowed: boolean;
|
|
114
|
-
reason: "blocked" | "private" | "public" | "
|
|
114
|
+
reason: "blocked" | "private" | "public" | "unavailable" | "owner" | "allowed" | "unsupported_consumer" | "contact_not_approved" | "mature_content" | "unrated_content" | "approval_required";
|
|
115
115
|
policyVersion: "2";
|
|
116
116
|
}>;
|
|
117
117
|
requestPurchaseApproval(input: PurchaseEffects, options: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oxy.so/core",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.12.0",
|
|
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",
|
|
@@ -181,7 +181,7 @@
|
|
|
181
181
|
"dependencies": {
|
|
182
182
|
"@noble/ciphers": "^1.3.0",
|
|
183
183
|
"@noble/hashes": "^1.8.0",
|
|
184
|
-
"@oxy.so/contracts": "6.
|
|
184
|
+
"@oxy.so/contracts": "6.4.0",
|
|
185
185
|
"@oxy.so/protocol": "^1.5.1",
|
|
186
186
|
"@oxy.so/telemetry": "^2.1.0",
|
|
187
187
|
"@scure/bip39": "^1.6.0",
|
|
@@ -199,7 +199,8 @@
|
|
|
199
199
|
"expo-crypto": "<59.0.0",
|
|
200
200
|
"expo-secure-store": "<59.0.0",
|
|
201
201
|
"express": "^4.0.0",
|
|
202
|
-
"@aws-sdk/credential-provider-node": ">=3.972.83 <4"
|
|
202
|
+
"@aws-sdk/credential-provider-node": ">=3.972.83 <4",
|
|
203
|
+
"@aws-sdk/credential-provider-ini": ">=3.973.16 <4"
|
|
203
204
|
},
|
|
204
205
|
"peerDependenciesMeta": {
|
|
205
206
|
"@react-native-async-storage/async-storage": {
|
|
@@ -216,6 +217,9 @@
|
|
|
216
217
|
},
|
|
217
218
|
"@aws-sdk/credential-provider-node": {
|
|
218
219
|
"optional": true
|
|
220
|
+
},
|
|
221
|
+
"@aws-sdk/credential-provider-ini": {
|
|
222
|
+
"optional": true
|
|
219
223
|
}
|
|
220
224
|
},
|
|
221
225
|
"devDependencies": {
|
|
@@ -232,6 +236,7 @@
|
|
|
232
236
|
"typescript": "^5.9.2",
|
|
233
237
|
"helmet": "^8.3.0",
|
|
234
238
|
"socket.io": "^4.8.1",
|
|
235
|
-
"@aws-sdk/credential-provider-node": "3.972.83"
|
|
239
|
+
"@aws-sdk/credential-provider-node": "3.972.83",
|
|
240
|
+
"@aws-sdk/credential-provider-ini": "3.973.16"
|
|
236
241
|
}
|
|
237
242
|
}
|