@oxyhq/core 3.11.0 → 3.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/dist/cjs/.tsbuildinfo +1 -1
- package/dist/cjs/crypto/signatureService.js +88 -2
- package/dist/cjs/index.js +19 -4
- package/dist/cjs/mixins/OxyServices.civic.js +611 -0
- package/dist/cjs/mixins/index.js +3 -0
- package/dist/cjs/utils/profileLinks.js +52 -0
- package/dist/esm/.tsbuildinfo +1 -1
- package/dist/esm/crypto/signatureService.js +87 -2
- package/dist/esm/index.js +11 -1
- package/dist/esm/mixins/OxyServices.civic.js +605 -0
- package/dist/esm/mixins/index.js +3 -0
- package/dist/esm/utils/profileLinks.js +49 -0
- package/dist/types/.tsbuildinfo +1 -1
- package/dist/types/crypto/signatureService.d.ts +54 -3
- package/dist/types/index.d.ts +5 -1
- package/dist/types/mixins/OxyServices.civic.d.ts +512 -0
- package/dist/types/mixins/index.d.ts +2 -1
- package/dist/types/utils/profileLinks.d.ts +36 -0
- package/package.json +2 -2
- package/src/crypto/__tests__/signedRecord.test.ts +221 -1
- package/src/crypto/signatureService.ts +102 -3
- package/src/index.ts +29 -1
- package/src/mixins/OxyServices.civic.ts +956 -0
- package/src/mixins/__tests__/OxyServices.civic.test.ts +1097 -0
- package/src/mixins/index.ts +4 -0
- package/src/utils/__tests__/profileLinks.test.ts +126 -0
- package/src/utils/profileLinks.ts +74 -0
|
@@ -10,17 +10,42 @@ import type { SignedRecordEnvelope } from '@oxyhq/contracts';
|
|
|
10
10
|
* EXCEPT the `publicKey` and `signature`. Both the client (when signing) and
|
|
11
11
|
* the server (when verifying) canonicalize exactly these fields, so they agree
|
|
12
12
|
* on the bytes that the signature covers.
|
|
13
|
+
*
|
|
14
|
+
* The v2 chain fields (`seq`/`prev`/`collection`/`rkey`) are optional: a v1
|
|
15
|
+
* envelope omits them and is signed over only the base fields; a v2 envelope
|
|
16
|
+
* carries them and includes them in the signed bytes.
|
|
13
17
|
*/
|
|
14
|
-
export type SignedRecordSigningFields = Pick<SignedRecordEnvelope, 'version' | 'type' | 'subject' | 'issuer' | 'record' | 'issuedAt'
|
|
18
|
+
export type SignedRecordSigningFields = Pick<SignedRecordEnvelope, 'version' | 'type' | 'subject' | 'issuer' | 'record' | 'issuedAt'> & Partial<Pick<SignedRecordEnvelope, 'seq' | 'prev' | 'collection' | 'rkey'>>;
|
|
15
19
|
/**
|
|
16
20
|
* Compute the canonical signing input for a signed-record envelope.
|
|
17
21
|
*
|
|
18
|
-
* This is the single definition of "what the signature covers"
|
|
19
|
-
* JSON of `{version, type, subject, issuer, record, issuedAt}`. `@oxyhq/core`
|
|
22
|
+
* This is the single definition of "what the signature covers". `@oxyhq/core`
|
|
20
23
|
* (client signing) and `@oxyhq/api` (server verification) both call this, so a
|
|
21
24
|
* record signed by a client and verified by the server cannot drift.
|
|
25
|
+
*
|
|
26
|
+
* - **v1**: the canonical JSON of `{version, type, subject, issuer, record,
|
|
27
|
+
* issuedAt}` — BYTE-IDENTICAL to the original scheme, so every signature
|
|
28
|
+
* already in production keeps verifying.
|
|
29
|
+
* - **v2**: the canonical JSON additionally includes the hash-chain fields
|
|
30
|
+
* `{seq, prev, collection, rkey}`. Because {@link canonicalize} sorts keys,
|
|
31
|
+
* the on-the-wire field order is irrelevant; the resulting canonical key
|
|
32
|
+
* order is `collection, issuedAt, issuer, prev, record, rkey, seq, subject,
|
|
33
|
+
* type, version`. `prev` is `null` at genesis (serialized as `null`, not
|
|
34
|
+
* omitted), so it is always part of the signed bytes.
|
|
22
35
|
*/
|
|
23
36
|
export declare function signedRecordSigningInput(fields: SignedRecordSigningFields): string;
|
|
37
|
+
/**
|
|
38
|
+
* Compute the `recordId` (content address) of a signed record: the SHA-256 hex
|
|
39
|
+
* digest of its canonical {@link signedRecordSigningInput}.
|
|
40
|
+
*
|
|
41
|
+
* Deterministic and stable across runtimes (it reuses the same canonicalization
|
|
42
|
+
* + SHA-256 the signature itself is built on). The recordId is what `prev`
|
|
43
|
+
* references in the per-subject hash chain, so `@oxyhq/core` (client) and
|
|
44
|
+
* `@oxyhq/api` (server) MUST compute it identically — both call this function.
|
|
45
|
+
* It is taken over the SIGNING input (excluding `publicKey`/`signature`), so it
|
|
46
|
+
* is a pure content address of the record's meaning, independent of who signed.
|
|
47
|
+
*/
|
|
48
|
+
export declare function computeRecordId(fields: SignedRecordSigningFields): Promise<string>;
|
|
24
49
|
export interface SignedMessage {
|
|
25
50
|
message: string;
|
|
26
51
|
signature: string;
|
|
@@ -135,6 +160,32 @@ export declare class SignatureService {
|
|
|
135
160
|
* @param record - The arbitrary record payload to attest to.
|
|
136
161
|
*/
|
|
137
162
|
static signRecord(type: SignedRecordEnvelope['type'], subject: string, record: Record<string, unknown>): Promise<SignedRecordEnvelope>;
|
|
163
|
+
/**
|
|
164
|
+
* Build a signed-record envelope (v2) carrying the per-subject hash-chain
|
|
165
|
+
* fields.
|
|
166
|
+
*
|
|
167
|
+
* Identical to {@link signRecord} (self-issued: `issuer === subject`; same
|
|
168
|
+
* `ES256K-DER-SHA256` scheme over {@link signedRecordSigningInput}) but
|
|
169
|
+
* `version` is `2` and the signed bytes additionally cover the chain fields:
|
|
170
|
+
*
|
|
171
|
+
* @param type - The record category.
|
|
172
|
+
* @param subject - The subject DID the record is about (also the issuer).
|
|
173
|
+
* @param record - The arbitrary record payload to attest to.
|
|
174
|
+
* @param chain - The hash-chain coordinates:
|
|
175
|
+
* - `seq` — strictly-increasing sequence number for this subject's chain.
|
|
176
|
+
* - `prev` — the `recordId` of the previous record, or `null` at genesis.
|
|
177
|
+
* - `collection` + `rkey` — the AtProto-style record key.
|
|
178
|
+
*
|
|
179
|
+
* The caller is responsible for fetching the current chain head (so `seq` /
|
|
180
|
+
* `prev` are correct) before signing. Requires a stored identity; throws if
|
|
181
|
+
* none exists.
|
|
182
|
+
*/
|
|
183
|
+
static signRecordV2(type: SignedRecordEnvelope['type'], subject: string, record: Record<string, unknown>, chain: {
|
|
184
|
+
seq: number;
|
|
185
|
+
prev: string | null;
|
|
186
|
+
collection: string;
|
|
187
|
+
rkey: string;
|
|
188
|
+
}): Promise<SignedRecordEnvelope>;
|
|
138
189
|
/**
|
|
139
190
|
* Verify a signed-record envelope: recompute the canonical signing input from
|
|
140
191
|
* the envelope's own fields and check the signature against the envelope's
|
package/dist/types/index.d.ts
CHANGED
|
@@ -39,11 +39,15 @@ export { OxyAppDataIdentifierError } from './mixins/OxyServices.appData';
|
|
|
39
39
|
export { getNormalizedUserId, normalizeUserIdentity, normalizeUserIdentityOrNull, } from './utils/userIdentity';
|
|
40
40
|
export { getCanonicalUserHandle, getNormalizedUserHandle, } from './utils/userHandle';
|
|
41
41
|
export type { CanonicalUserHandleInput, UserHandleInput } from './utils/userHandle';
|
|
42
|
+
export { normalizeProfileLinks } from './utils/profileLinks';
|
|
43
|
+
export type { ProfileLink, ProfileLinkMetadata } from './utils/profileLinks';
|
|
42
44
|
export type { Application, PublicApplication, ApplicationMember, ApplicationCredential, ApplicationRole, ApplicationType, ApplicationStatus, ApplicationMemberStatus, ApplicationCredentialType, ApplicationCredentialStatus, ApplicationEnvironment, CreateApplicationInput, UpdateApplicationInput, InviteApplicationMemberInput, UpdateApplicationMemberInput, TransferApplicationOwnershipInput, CreateApplicationCredentialInput, ApplicationCredentialWithSecret, RotateApplicationCredentialResult, ApplicationUsagePeriod, ApplicationUsageSummary, ApplicationUsageByDay, ApplicationUsageByEndpoint, ApplicationUsageStats, ApplicationSuccessResult, } from './mixins/OxyServices.applications';
|
|
43
45
|
export type { Workspace, WorkspaceMember, WorkspaceRole, WorkspaceType, WorkspaceStatus, WorkspaceMemberStatus, CreateWorkspaceInput, UpdateWorkspaceInput, InviteWorkspaceMemberInput, UpdateWorkspaceMemberInput, TransferWorkspaceOwnershipInput, WorkspaceSuccessResult, } from './mixins/OxyServices.workspaces';
|
|
44
46
|
export type { ReputationCategory, TrustTier, ReputationTransactionStatus, ReputationTargetEntityType, ReputationDisputeStatus, ReputationInfluenceContext, ReputationTransaction, ReputationBalanceBreakdown, ReputationInfluence, ReputationReliability, ReputationBalance, ReputationDispute, ReputationRule, ReputationLeaderboardEntry, ReputationInfluenceResult, ReverseReputationTransactionResult, AwardReputationInput, CreateReputationDisputeInput, ResolveReputationDisputeInput, UpsertReputationRuleInput, ReverseReputationTransactionInput, } from './mixins/OxyServices.reputation';
|
|
45
47
|
export { buildUserDid } from './mixins/OxyServices.identity';
|
|
46
48
|
export type { IdentityRecordType, UnlinkableAuthMethodType, LinkAuthMethodResult, PublishRecordResult, VerifyRecordResult, VerifyDomainResult, RemoveDomainResult, } from './mixins/OxyServices.identity';
|
|
49
|
+
export { parseIdPayload, parseAttestPayload, verifyPublicCardAttestation, } from './mixins/OxyServices.civic';
|
|
50
|
+
export type { CivicCardResult, IdCardRef, AttestQrPayload, ParsedAttestPayload, SubmitRealLifeAttestationInput, DenyValidationResult, VouchForPersonInput, WithdrawVouchResult, IssueCredentialInput, RevokeCredentialResult, } from './mixins/OxyServices.civic';
|
|
47
51
|
export { SessionSyncRequiredError, AuthenticationFailedError, ensureValidToken, isAuthenticationError, withAuthErrorHandling, authenticatedApiCall, } from './utils/authHelpers';
|
|
48
52
|
export type { HandleApiErrorOptions } from './utils/authHelpers';
|
|
49
53
|
export { mergeSessions, normalizeAndSortSessions, sessionsArraysEqual, } from './utils/sessionUtils';
|
|
@@ -51,7 +55,7 @@ export type { ClientSession, StorageKeys, MinimalUserData, SessionLoginResponse,
|
|
|
51
55
|
export type { RefreshAllResponse, RefreshAllAccount, RefreshAllAccountUser, RefreshCookieResponse, } from './models/interfaces';
|
|
52
56
|
export { KeyManager, IdentityAlreadyExistsError, IdentityPersistError, } from './crypto/keyManager';
|
|
53
57
|
export type { KeyPair } from './crypto/keyManager';
|
|
54
|
-
export { SignatureService, signedRecordSigningInput } from './crypto/signatureService';
|
|
58
|
+
export { SignatureService, signedRecordSigningInput, computeRecordId } from './crypto/signatureService';
|
|
55
59
|
export type { SignedMessage, AuthChallenge, SignedRecordSigningFields } from './crypto/signatureService';
|
|
56
60
|
export { canonicalize } from './crypto/canonicalJson';
|
|
57
61
|
export { RecoveryPhraseService } from './crypto/recoveryPhrase';
|
|
@@ -0,0 +1,512 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Civic Methods Mixin (Commons "Oxy ID" — Fase 1; anti-gaming — Fase 2)
|
|
3
|
+
*
|
|
4
|
+
* Provides typed access to the public, verifiable citizen-identity ("Oxy ID")
|
|
5
|
+
* card a Commons user shows and others scan, plus the Fase 2 anti-gaming surfaces
|
|
6
|
+
* (real-life counterparty attestation + the validator/jury flow):
|
|
7
|
+
*
|
|
8
|
+
* - {@link OxyServicesCivicMixin.getPublicCard} fetches a user's signed card
|
|
9
|
+
* (`GET /civic/:userId/card`) and verifies the Oxy custodial attestation
|
|
10
|
+
* CLIENT-SIDE, so a scanner can trust the card OFFLINE (e.g. a cached card
|
|
11
|
+
* replayed without network) instead of re-trusting the transport.
|
|
12
|
+
* - {@link OxyServicesCivicMixin.getMyIdPayload} builds the QR payload the user
|
|
13
|
+
* displays. The QR encodes ONLY the DID (`oxycommons://card?did=…&v=1`) — never
|
|
14
|
+
* trust data — so the card cannot be spoofed by crafting a QR; the scanner
|
|
15
|
+
* resolves the signed card server-side and re-verifies it.
|
|
16
|
+
* - {@link OxyServicesCivicMixin.buildAttestQrPayload} builds the high-value
|
|
17
|
+
* real-life-attestation QR the person BEING attested (A) shows; the SCANNER
|
|
18
|
+
* (B) parses it with {@link parseAttestPayload} and signs a self-issued
|
|
19
|
+
* counterparty attestation via
|
|
20
|
+
* {@link OxyServicesCivicMixin.submitRealLifeAttestation}.
|
|
21
|
+
* - {@link OxyServicesCivicMixin.getValidatorInbox} /
|
|
22
|
+
* {@link OxyServicesCivicMixin.submitValidationVote} /
|
|
23
|
+
* {@link OxyServicesCivicMixin.denyValidation} drive a randomly-selected
|
|
24
|
+
* juror's medium-weight peer-validation duties.
|
|
25
|
+
*
|
|
26
|
+
* The wire shapes (`PublicCard`, `SignedPublicCard`, `ExportAttestation`,
|
|
27
|
+
* `RealLifeAttestationResult`, `ValidationRequestSummary`, `ValidationVoteResult`,
|
|
28
|
+
* `SignedRecordEnvelope`) come from `@oxyhq/contracts` — the single source of
|
|
29
|
+
* truth the API validates its output against — so producer and consumer cannot
|
|
30
|
+
* drift. The public Oxy ID card's attestation is an `ES256K-DER-SHA256` signature
|
|
31
|
+
* over `canonicalize(card)` (the exact bytes the server signed, with ONLY the
|
|
32
|
+
* present keys), so a consumer re-canonicalizes the `card` it received and checks
|
|
33
|
+
* the signature against `attestation.publicKey`.
|
|
34
|
+
*
|
|
35
|
+
* Card verification NEVER throws on a bad/absent signature — it returns
|
|
36
|
+
* `verified: false` so the UI can render a forged/unsigned card as visibly
|
|
37
|
+
* untrusted rather than silently trusting it. A transport/network failure (the
|
|
38
|
+
* fetch itself) still rejects, as everywhere else in the SDK.
|
|
39
|
+
*
|
|
40
|
+
* The Fase 2 writes (`submitRealLifeAttestation`, `submitValidationVote`) sign a
|
|
41
|
+
* v2 self-issued signed-record envelope with the on-device identity key (so they
|
|
42
|
+
* are NATIVE-ONLY — they throw on web, where `KeyManager` has no key) on the
|
|
43
|
+
* caller's own per-subject hash chain: each fetches the caller's chain head
|
|
44
|
+
* (`GET /identity/records/:userId/chain/head`) to set `seq`/`prev` before signing
|
|
45
|
+
* with {@link SignatureService.signRecordV2}.
|
|
46
|
+
*
|
|
47
|
+
* Reading a public card and building/parsing the QR payloads are
|
|
48
|
+
* platform-agnostic; deriving the current user's DID requires an authenticated
|
|
49
|
+
* session.
|
|
50
|
+
*/
|
|
51
|
+
import type { CredentialIssueResult, CredentialListResult, CredentialStatus, CredentialVerifyResult, ExportAttestation, PersonhoodStatusResult, PublicCard, RealLifeAttestationResult, SignedPublicCard, SignedRecordEnvelope, SignedRecordType, ValidationRequestSummary, ValidationVerdict, ValidationVoteResult, VerifiableCredentialResponse, VouchResult } from '@oxyhq/contracts';
|
|
52
|
+
import type { OxyServicesBase } from '../OxyServices.base';
|
|
53
|
+
/**
|
|
54
|
+
* A {@link SignedPublicCard} augmented with the client's verification verdict.
|
|
55
|
+
*
|
|
56
|
+
* - `card` / `attestation` are echoed straight from the API response.
|
|
57
|
+
* - `verified` is `true` ONLY when `attestation` is present and its signature
|
|
58
|
+
* over `canonicalize(card)` checks out against `attestation.publicKey`. It is
|
|
59
|
+
* `false` for an unsigned card (dev, `attestation === null`), a tampered card,
|
|
60
|
+
* or a signature made with a different key.
|
|
61
|
+
*
|
|
62
|
+
* `verified` confirms the attestation's signature is internally consistent with
|
|
63
|
+
* its embedded `publicKey` (and that the card bytes were not mutated). It does
|
|
64
|
+
* NOT, on its own, establish that `publicKey` is Oxy's custodial key — that trust
|
|
65
|
+
* anchor is the Oxy API the card was fetched from (over TLS) and, for the
|
|
66
|
+
* pinning-conscious, `attestation.issuer` (the Oxy DID). The UI shows a trust
|
|
67
|
+
* indicator from `verified`; a `false` verdict MUST be surfaced as untrusted.
|
|
68
|
+
*/
|
|
69
|
+
export interface CivicCardResult extends SignedPublicCard {
|
|
70
|
+
verified: boolean;
|
|
71
|
+
}
|
|
72
|
+
/** The DID extracted from a scanned `oxycommons://card?did=…` Oxy ID payload. */
|
|
73
|
+
export interface IdCardRef {
|
|
74
|
+
/** The subject's Oxy DID (`did:web:oxy.so:u:<userId>`). */
|
|
75
|
+
did: string;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Parse a scanned / deep-linked Oxy ID payload (`oxycommons://card?did=…`) into
|
|
79
|
+
* the referenced DID. Pure + dependency-free (Hermes-safe, no `URL` global) so
|
|
80
|
+
* Commons (and any scanner) can reuse it without an OxyServices instance.
|
|
81
|
+
*
|
|
82
|
+
* @param raw - The raw scanned string or deep-link URL.
|
|
83
|
+
* @returns `{ did }` when a usable DID is present; `null` for anything else (a
|
|
84
|
+
* non-card scheme, a missing/empty `did`, or non-string input).
|
|
85
|
+
*/
|
|
86
|
+
export declare function parseIdPayload(raw: string): IdCardRef | null;
|
|
87
|
+
/**
|
|
88
|
+
* The fields decoded from a scanned real-life-attestation QR
|
|
89
|
+
* (`oxycommons://attest?subject=…&ctx=…&nonce=…&exp=…`). The SCANNER feeds these
|
|
90
|
+
* to {@link OxyServicesCivicMixin.submitRealLifeAttestation}.
|
|
91
|
+
*/
|
|
92
|
+
export interface ParsedAttestPayload {
|
|
93
|
+
/** The DID of the person being attested (A) — becomes the record's `about`. */
|
|
94
|
+
subjectDid: string;
|
|
95
|
+
/** Opaque interaction id (`ctx`); `''` when the QR omitted it. */
|
|
96
|
+
context: string;
|
|
97
|
+
/** Single-use replay-guard nonce. */
|
|
98
|
+
nonce: string;
|
|
99
|
+
/** Nonce expiry (epoch ms); the server re-checks freshness authoritatively. */
|
|
100
|
+
exp: number;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* The QR a person shows to be attested in real life, plus the fresh nonce/exp it
|
|
104
|
+
* embeds so the displaying app can track which scan completed it.
|
|
105
|
+
*/
|
|
106
|
+
export interface AttestQrPayload {
|
|
107
|
+
/** The `oxycommons://attest?subject=…&ctx=…&nonce=…&exp=…` string to encode as a QR. */
|
|
108
|
+
payload: string;
|
|
109
|
+
/** The single-use nonce embedded in the payload. */
|
|
110
|
+
nonce: string;
|
|
111
|
+
/** The nonce expiry embedded in the payload (epoch ms). */
|
|
112
|
+
exp: number;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Parse a scanned / deep-linked real-life-attestation payload
|
|
116
|
+
* (`oxycommons://attest?subject=…&ctx=…&nonce=…&exp=…`). Pure + dependency-free
|
|
117
|
+
* (Hermes-safe, no `URL` global), mirroring {@link parseIdPayload}, so Commons
|
|
118
|
+
* (and any scanner) can reuse it without an OxyServices instance.
|
|
119
|
+
*
|
|
120
|
+
* @param raw - The raw scanned string or deep-link URL.
|
|
121
|
+
* @returns `{ subjectDid, context, nonce, exp }` when the required fields are
|
|
122
|
+
* present and `exp` is a positive finite number; `null` otherwise (a non-attest
|
|
123
|
+
* scheme, a missing `subject`/`nonce`/`exp`, an unparseable `exp`, or non-string
|
|
124
|
+
* input). `context` defaults to `''` when the QR omits `ctx`.
|
|
125
|
+
*/
|
|
126
|
+
export declare function parseAttestPayload(raw: string): ParsedAttestPayload | null;
|
|
127
|
+
/**
|
|
128
|
+
* Verify the Oxy custodial attestation on a public card.
|
|
129
|
+
*
|
|
130
|
+
* Re-canonicalizes the received `card` (so the order of the JSON keys on the
|
|
131
|
+
* wire is irrelevant; `canonicalize` also omits any `undefined`-valued optional
|
|
132
|
+
* key, matching the server which omits absent keys entirely) and checks the
|
|
133
|
+
* `ES256K-DER-SHA256` signature against `attestation.publicKey`.
|
|
134
|
+
*
|
|
135
|
+
* NEVER throws: `SignatureService.verify` already swallows malformed-input
|
|
136
|
+
* errors and returns `false`, and an absent attestation short-circuits to
|
|
137
|
+
* `false`. A pure, reusable helper (Commons can call it on a cached card).
|
|
138
|
+
*
|
|
139
|
+
* @param card - The card to verify (exactly as received).
|
|
140
|
+
* @param attestation - The card's attestation, or `null` (unsigned ⇒ `false`).
|
|
141
|
+
*/
|
|
142
|
+
export declare function verifyPublicCardAttestation(card: PublicCard, attestation: ExportAttestation | null): Promise<boolean>;
|
|
143
|
+
/**
|
|
144
|
+
* Input for {@link OxyServicesCivicMixin.submitRealLifeAttestation} — the fields
|
|
145
|
+
* the SCANNER (B) carries over from a parsed {@link ParsedAttestPayload}, plus
|
|
146
|
+
* the optional co-location / biometric support signals B contributes.
|
|
147
|
+
*/
|
|
148
|
+
export interface SubmitRealLifeAttestationInput {
|
|
149
|
+
/** The DID of the person being attested (A); becomes the record's `about`. */
|
|
150
|
+
subjectDid: string;
|
|
151
|
+
/** Opaque interaction id from the QR. */
|
|
152
|
+
context: string;
|
|
153
|
+
/** Single-use nonce from the QR (also the record's `rkey`). */
|
|
154
|
+
nonce: string;
|
|
155
|
+
/** Nonce expiry from the QR (epoch ms). */
|
|
156
|
+
exp: number;
|
|
157
|
+
/** Coarse co-location proof (optional). */
|
|
158
|
+
geohash?: string;
|
|
159
|
+
/** Whether B's device biometric gate fired before signing (optional). */
|
|
160
|
+
biometricOk?: boolean;
|
|
161
|
+
}
|
|
162
|
+
/** Result of {@link OxyServicesCivicMixin.denyValidation}. */
|
|
163
|
+
export interface DenyValidationResult {
|
|
164
|
+
denied: boolean;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Input for {@link OxyServicesCivicMixin.vouchForPerson} — the SUBJECT (A) the
|
|
168
|
+
* current user (B) is vouching for, plus B's optional stake and biometric
|
|
169
|
+
* support signal.
|
|
170
|
+
*/
|
|
171
|
+
export interface VouchForPersonInput {
|
|
172
|
+
/** A's DID (`did:web:oxy.so:u:<userId>`); becomes the vouch record's `about`. */
|
|
173
|
+
subjectDid: string;
|
|
174
|
+
/**
|
|
175
|
+
* B's chosen stake (the `stake` wire field). Omitted ⇒ the server applies its
|
|
176
|
+
* default; the server clamps any value into its `[min, max]` and echoes the
|
|
177
|
+
* recorded amount back as `VouchResult.stakeAmount`.
|
|
178
|
+
*/
|
|
179
|
+
stakeAmount?: number;
|
|
180
|
+
/** Whether B's device biometric gate fired before signing (optional signal). */
|
|
181
|
+
biometricOk?: boolean;
|
|
182
|
+
}
|
|
183
|
+
/** Result of {@link OxyServicesCivicMixin.withdrawVouch}. */
|
|
184
|
+
export interface WithdrawVouchResult {
|
|
185
|
+
withdrawn: boolean;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Input for {@link OxyServicesCivicMixin.issueCredential} — the HOLDER the
|
|
189
|
+
* caller (issuer) attests a claim about, the VC type tags, the issuer's claim
|
|
190
|
+
* set, and an optional ISO-8601 expiry.
|
|
191
|
+
*/
|
|
192
|
+
export interface IssueCredentialInput {
|
|
193
|
+
/** The holder's Oxy DID (`did:web:oxy.so:u:<userId>`); becomes the record's `about`. */
|
|
194
|
+
holderDid: string;
|
|
195
|
+
/**
|
|
196
|
+
* The VC type tags. `'VerifiableCredential'` is the required base type and is
|
|
197
|
+
* prepended automatically when the caller omits it; provide at least one
|
|
198
|
+
* specific type alongside (e.g. `'EmploymentCredential'`).
|
|
199
|
+
*/
|
|
200
|
+
types: string[];
|
|
201
|
+
/** The arbitrary, issuer-asserted claim set about the holder (signed verbatim). */
|
|
202
|
+
claims: Record<string, unknown>;
|
|
203
|
+
/**
|
|
204
|
+
* Optional expiry as an ISO-8601 date string; absent = non-expiring. Converted
|
|
205
|
+
* to epoch milliseconds in the signed record (the wire/storage unit), so a
|
|
206
|
+
* holder cannot extend validity after the fact. Must be a parseable date and,
|
|
207
|
+
* per the server, in the future.
|
|
208
|
+
*/
|
|
209
|
+
expiresAt?: string;
|
|
210
|
+
}
|
|
211
|
+
/** Result of {@link OxyServicesCivicMixin.revokeCredential} (`POST …/:id/revoke`). */
|
|
212
|
+
export interface RevokeCredentialResult {
|
|
213
|
+
revoked: boolean;
|
|
214
|
+
credential: VerifiableCredentialResponse;
|
|
215
|
+
}
|
|
216
|
+
export declare function OxyServicesCivicMixin<T extends typeof OxyServicesBase>(Base: T): {
|
|
217
|
+
new (...args: any[]): {
|
|
218
|
+
/**
|
|
219
|
+
* Fetch a user's signed public Oxy ID card and verify the Oxy attestation
|
|
220
|
+
* client-side. Public (no auth required); short-TTL cached.
|
|
221
|
+
*
|
|
222
|
+
* Resolves to `{ card, attestation, verified }`. A bad/absent signature does
|
|
223
|
+
* NOT reject — it yields `verified: false` so the UI can warn. Only a
|
|
224
|
+
* transport failure (the fetch itself) rejects.
|
|
225
|
+
*
|
|
226
|
+
* @param userId - The subject account's Mongo `_id`. URL-encoded into the path.
|
|
227
|
+
*/
|
|
228
|
+
getPublicCard(userId: string): Promise<CivicCardResult>;
|
|
229
|
+
/**
|
|
230
|
+
* Build the Oxy ID QR payload for the current user:
|
|
231
|
+
* `oxycommons://card?did=<did>&v=1`, where `<did>` is the user's Oxy DID
|
|
232
|
+
* (`did:web:oxy.so:u:<userId>`). The QR encodes ONLY the DID (anti-spoof — no
|
|
233
|
+
* trust data); a scanner resolves the signed card via {@link getPublicCard}.
|
|
234
|
+
* Round-trips through {@link parseIdPayload}.
|
|
235
|
+
*
|
|
236
|
+
* Throws if no user is authenticated (no DID to derive).
|
|
237
|
+
*/
|
|
238
|
+
getMyIdPayload(): string;
|
|
239
|
+
/**
|
|
240
|
+
* Build the real-life-attestation QR the current user (A) shows to be
|
|
241
|
+
* attested by a counterparty (B):
|
|
242
|
+
* `oxycommons://attest?subject=<A.did>&ctx=<context>&nonce=<fresh>&exp=<now+10m>`.
|
|
243
|
+
*
|
|
244
|
+
* A fresh crypto-random nonce is minted per call (single-use replay guard);
|
|
245
|
+
* `exp` is `now + 10min` (matching the server ceiling — scan promptly). The
|
|
246
|
+
* QR carries NO trust data; B re-signs and the server is authoritative. The
|
|
247
|
+
* returned `nonce`/`exp` let the displaying screen track which scan completed.
|
|
248
|
+
*
|
|
249
|
+
* Async because a crypto-secure nonce requires the platform RNG (async on
|
|
250
|
+
* native via expo-crypto). Throws if no user is authenticated.
|
|
251
|
+
*
|
|
252
|
+
* @param input.context - An opaque interaction id describing the encounter.
|
|
253
|
+
*/
|
|
254
|
+
buildAttestQrPayload(input: {
|
|
255
|
+
context: string;
|
|
256
|
+
}): Promise<AttestQrPayload>;
|
|
257
|
+
/**
|
|
258
|
+
* Submit a real-life counterparty attestation as the SCANNER (B): sign a
|
|
259
|
+
* self-issued `real_life_attestation` v2 record on B's own chain
|
|
260
|
+
* (`subject === issuer === B.did`), referencing A via `record.about`, then
|
|
261
|
+
* `POST /civic/attestations`. The server enforces nonce single-use,
|
|
262
|
+
* freshness, graph-exclusion (B is not A's puppet), and the per-pair
|
|
263
|
+
* cooldown, then awards A the HIGH-weight points.
|
|
264
|
+
*
|
|
265
|
+
* NATIVE-ONLY (signs with the on-device key; throws on web / when no
|
|
266
|
+
* identity or no authenticated user). The record is keyed
|
|
267
|
+
* `collection: 'app.oxy.attestation'`, `rkey: <nonce>`.
|
|
268
|
+
*
|
|
269
|
+
* @param input - The parsed QR fields ({@link ParsedAttestPayload}) plus B's
|
|
270
|
+
* optional `geohash` / `biometricOk` support signals.
|
|
271
|
+
*/
|
|
272
|
+
submitRealLifeAttestation(input: SubmitRealLifeAttestationInput): Promise<RealLifeAttestationResult>;
|
|
273
|
+
/**
|
|
274
|
+
* List the current user's pending jury duties (`GET /civic/validations/inbox`).
|
|
275
|
+
* Auth required; never cached (the inbox is a live queue). Returns `[]` when
|
|
276
|
+
* the caller is on no juries.
|
|
277
|
+
*/
|
|
278
|
+
getValidatorInbox(): Promise<ValidationRequestSummary[]>;
|
|
279
|
+
/**
|
|
280
|
+
* Cast a SIGNED verdict on a validation request as a selected juror: sign a
|
|
281
|
+
* self-issued `validation_verdict` v2 record on the juror's own chain bound
|
|
282
|
+
* to `requestId` + `payloadHash` (so a verdict cannot be replayed onto a
|
|
283
|
+
* different request or an altered payload), then
|
|
284
|
+
* `POST /civic/validations/:id/vote`.
|
|
285
|
+
*
|
|
286
|
+
* NATIVE-ONLY (signs with the on-device key; throws on web / when no
|
|
287
|
+
* identity or no authenticated user). The record is keyed
|
|
288
|
+
* `collection: 'app.oxy.validation'`, `rkey: <requestId>`.
|
|
289
|
+
*
|
|
290
|
+
* @param requestId - The validation request being voted on.
|
|
291
|
+
* @param payloadHash - The request's canonical payload hash (from the inbox);
|
|
292
|
+
* the server rejects a vote whose hash does not match the stored request.
|
|
293
|
+
* @param verdict - `'valid'` | `'invalid'` | `'abstain'`.
|
|
294
|
+
*/
|
|
295
|
+
submitValidationVote(requestId: string, payloadHash: string, verdict: ValidationVerdict): Promise<ValidationVoteResult>;
|
|
296
|
+
/**
|
|
297
|
+
* Recuse from a validation request (`POST /civic/validations/:id/deny`): the
|
|
298
|
+
* juror is removed from the jury and the request is re-tallied. Auth
|
|
299
|
+
* required; no signed record (recusal is not an attestation).
|
|
300
|
+
*
|
|
301
|
+
* @param requestId - The validation request to recuse from.
|
|
302
|
+
*/
|
|
303
|
+
denyValidation(requestId: string): Promise<DenyValidationResult>;
|
|
304
|
+
/**
|
|
305
|
+
* Vouch that another user is a real person as the VOUCHER (B): sign a
|
|
306
|
+
* self-issued `personhood_vouch` v2 record on B's own chain
|
|
307
|
+
* (`subject === issuer === B.did`), referencing the subject (A) via
|
|
308
|
+
* `record.about`, then `POST /civic/personhood/vouch`. The server verifies
|
|
309
|
+
* it, enforces the voucher-eligibility (personhood ≥ τ) + graph-exclusion
|
|
310
|
+
* gates, stakes B, awards A `personhood_vouched`, and recomputes A's
|
|
311
|
+
* personhood. The voucher id is resolved server-side from the session — never
|
|
312
|
+
* from the body.
|
|
313
|
+
*
|
|
314
|
+
* The signed record matches the API schema: `{ about, stake?, … }` — note the
|
|
315
|
+
* wire field is `stake` (the caller's `stakeAmount` request), distinct from
|
|
316
|
+
* the server-clamped `VouchResult.stakeAmount` it returns. The optional
|
|
317
|
+
* `biometricOk` is carried as a signed support signal.
|
|
318
|
+
*
|
|
319
|
+
* NATIVE-ONLY (signs with the on-device key; throws on web / when no identity
|
|
320
|
+
* or no authenticated user). The record is keyed
|
|
321
|
+
* `collection: 'app.oxy.vouch'`, `rkey: <subjectDid>` (one vouch per subject
|
|
322
|
+
* on the voucher's chain — last-writer-wins). After a successful vouch the
|
|
323
|
+
* personhood + `/users/me` GET caches are swept.
|
|
324
|
+
*
|
|
325
|
+
* @param input - The subject DID plus B's optional stake / biometric signal.
|
|
326
|
+
*/
|
|
327
|
+
vouchForPerson(input: VouchForPersonInput): Promise<VouchResult>;
|
|
328
|
+
/**
|
|
329
|
+
* Withdraw the current user's active vouch for a subject
|
|
330
|
+
* (`DELETE /civic/personhood/vouch/:subjectUserId`). The vouch flips to
|
|
331
|
+
* `withdrawn` server-side and the subject is recomputed (which may demote
|
|
332
|
+
* them below θ). Auth required; no signed record (withdrawal is not an
|
|
333
|
+
* attestation). After a successful withdraw the personhood + `/users/me` GET
|
|
334
|
+
* caches are swept.
|
|
335
|
+
*
|
|
336
|
+
* @param subjectUserId - The subject account's Mongo `_id` (NOT a DID) — the
|
|
337
|
+
* id the server keys the vouch on. URL-encoded into the path.
|
|
338
|
+
*/
|
|
339
|
+
withdrawVouch(subjectUserId: string): Promise<WithdrawVouchResult>;
|
|
340
|
+
/**
|
|
341
|
+
* Fetch a user's public personhood status snapshot
|
|
342
|
+
* (`GET /civic/personhood/:userId`). Read-only: the server returns the cached
|
|
343
|
+
* snapshot, or a zeroed `unverified` shape (`breakdown`/`updatedAt` null) when
|
|
344
|
+
* none exists yet. Public (no auth required); short-TTL cached.
|
|
345
|
+
*
|
|
346
|
+
* @param userId - The subject account's Mongo `_id`. URL-encoded into the path.
|
|
347
|
+
*/
|
|
348
|
+
getPersonhood(userId: string): Promise<PersonhoodStatusResult>;
|
|
349
|
+
/**
|
|
350
|
+
* Fetch the CURRENT user's personhood status ({@link getPersonhood} for the
|
|
351
|
+
* authenticated user's id). Throws if no user is authenticated.
|
|
352
|
+
*/
|
|
353
|
+
getMyPersonhood(): Promise<PersonhoodStatusResult>;
|
|
354
|
+
/**
|
|
355
|
+
* Issue a verifiable credential as the ISSUER: sign a self-issued
|
|
356
|
+
* `credential` v2 record on the caller's own chain
|
|
357
|
+
* (`subject === issuer === issuer.did`) whose `record.about` is the HOLDER's
|
|
358
|
+
* DID (the W3C `credentialSubject`), then `POST /civic/credentials`. The
|
|
359
|
+
* server verifies the signature + the issuer's CURRENT verification method +
|
|
360
|
+
* chain continuity, stores the signed record, and projects a queryable
|
|
361
|
+
* credential row. All claim data comes from the SIGNED envelope — the issuer
|
|
362
|
+
* id is resolved server-side from the session, never from the body.
|
|
363
|
+
*
|
|
364
|
+
* `'VerifiableCredential'` is ensured present as the base type (prepended
|
|
365
|
+
* when the caller omits it; the server rejects a record missing it). An
|
|
366
|
+
* `expiresAt` ISO string is converted to the epoch-ms the signed record
|
|
367
|
+
* carries (the server rejects a past expiry).
|
|
368
|
+
*
|
|
369
|
+
* NATIVE-ONLY (signs with the on-device key; throws on web / when no identity
|
|
370
|
+
* or no authenticated user). The record is keyed
|
|
371
|
+
* `collection: 'app.oxy.credential'`, `rkey: <fresh unique nonce>` (each
|
|
372
|
+
* credential is a distinct chain entry, so the rkey must be unique per
|
|
373
|
+
* credential). After a successful issue the credential GET caches are swept.
|
|
374
|
+
*
|
|
375
|
+
* @param input - The holder DID, VC types, claims, and optional ISO expiry.
|
|
376
|
+
*/
|
|
377
|
+
issueCredential(input: IssueCredentialInput): Promise<CredentialIssueResult>;
|
|
378
|
+
/**
|
|
379
|
+
* List a holder's verifiable credentials
|
|
380
|
+
* (`GET /civic/credentials/:holderUserId`), newest first, optionally filtered
|
|
381
|
+
* by stored `status`. Public (credentials are issuer-signed attestations a
|
|
382
|
+
* holder collects to SHOW); short-TTL cached and swept after the caller's own
|
|
383
|
+
* issue / revoke. An unknown holder yields an empty list.
|
|
384
|
+
*
|
|
385
|
+
* @param holderUserId - The holder account's Mongo `_id` (NOT a DID). URL-encoded.
|
|
386
|
+
* @param opts.status - Optional `'active' | 'revoked' | 'expired'` filter.
|
|
387
|
+
*/
|
|
388
|
+
listCredentials(holderUserId: string, opts?: {
|
|
389
|
+
status?: CredentialStatus;
|
|
390
|
+
}): Promise<CredentialListResult>;
|
|
391
|
+
/**
|
|
392
|
+
* List the CURRENT user's verifiable credentials ({@link listCredentials} for
|
|
393
|
+
* the authenticated user's id). Throws if no user is authenticated.
|
|
394
|
+
*
|
|
395
|
+
* @param opts.status - Optional status filter.
|
|
396
|
+
*/
|
|
397
|
+
listMyCredentials(opts?: {
|
|
398
|
+
status?: CredentialStatus;
|
|
399
|
+
}): Promise<CredentialListResult>;
|
|
400
|
+
/**
|
|
401
|
+
* Verify a credential by its signed-record id
|
|
402
|
+
* (`GET /civic/credentials/by-record/:recordId/verify`). The server recomputes
|
|
403
|
+
* the canonical signing input from the STORED envelope and verifies the
|
|
404
|
+
* signature against a CURRENT verification method of the ISSUER DID (so a
|
|
405
|
+
* key the issuer has since rotated away no longer verifies), then checks the
|
|
406
|
+
* credential is neither revoked nor expired. Public; short-TTL cached
|
|
407
|
+
* (matching the server's `max-age=60`) and swept after the caller's own issue
|
|
408
|
+
* / revoke.
|
|
409
|
+
*
|
|
410
|
+
* A revoked / expired / unverifiable credential yields `valid: false` (NOT a
|
|
411
|
+
* throw) so the UI can render it as untrusted; `credential` is `null` only
|
|
412
|
+
* when no credential exists for the record id. Only a transport failure (the
|
|
413
|
+
* fetch itself) rejects.
|
|
414
|
+
*
|
|
415
|
+
* @param recordId - The credential's signed-record id. URL-encoded into the path.
|
|
416
|
+
*/
|
|
417
|
+
verifyCredential(recordId: string): Promise<CredentialVerifyResult>;
|
|
418
|
+
/**
|
|
419
|
+
* Revoke a credential the current user originally issued
|
|
420
|
+
* (`POST /civic/credentials/:id/revoke`). Only the original USER issuer may
|
|
421
|
+
* revoke; the server flips the credential to `revoked`. After a successful
|
|
422
|
+
* revoke the credential GET caches are swept.
|
|
423
|
+
*
|
|
424
|
+
* @param id - The credential's id (the projection row `_id`, NOT the signed
|
|
425
|
+
* record id). URL-encoded into the path.
|
|
426
|
+
*/
|
|
427
|
+
revokeCredential(id: string): Promise<RevokeCredentialResult>;
|
|
428
|
+
/**
|
|
429
|
+
* Sweep the credential GET caches an issue / revoke invalidates: every
|
|
430
|
+
* credential read (the holder list + the by-record verify, which share the
|
|
431
|
+
* `GET:/civic/credentials/` prefix) so a re-read reflects the new credential
|
|
432
|
+
* set / status. Public rather than `private` for the same TS4094 reason as
|
|
433
|
+
* {@link _signMyCivicRecordV2}.
|
|
434
|
+
*/
|
|
435
|
+
_sweepCredentialCaches(): void;
|
|
436
|
+
/**
|
|
437
|
+
* Sweep the GET caches a vouch / withdraw can invalidate: every personhood
|
|
438
|
+
* status read (the subject's snapshot changed) and `/users/me` (a subject
|
|
439
|
+
* crossing the threshold flips their mirrored `User.verified`). Public rather
|
|
440
|
+
* than `private` for the same TS4094 reason as {@link _signMyCivicRecordV2}.
|
|
441
|
+
*/
|
|
442
|
+
_sweepPersonhoodCaches(): void;
|
|
443
|
+
/**
|
|
444
|
+
* Sign a self-issued v2 signed-record envelope on the CURRENT user's own
|
|
445
|
+
* per-subject hash chain. Fetches the caller's chain head fresh (uncached, so
|
|
446
|
+
* `seq`/`prev` are never stale → no `bad_seq`/`chain_fork`) and signs with
|
|
447
|
+
* {@link SignatureService.signRecordV2}.
|
|
448
|
+
*
|
|
449
|
+
* NATIVE-ONLY (the private key lives in native secure storage). Internal
|
|
450
|
+
* helper (leading underscore); public rather than `private` because mixins
|
|
451
|
+
* compose into an exported anonymous class where TypeScript cannot represent a
|
|
452
|
+
* private member in the emitted declaration file (TS4094).
|
|
453
|
+
*
|
|
454
|
+
* @param type - The signed-record category.
|
|
455
|
+
* @param record - The record payload (canonicalized into the signed bytes).
|
|
456
|
+
* @param collection - The AtProto-style collection namespace.
|
|
457
|
+
* @param rkey - The AtProto-style record key within the collection.
|
|
458
|
+
*/
|
|
459
|
+
_signMyCivicRecordV2(type: SignedRecordType, record: Record<string, unknown>, collection: string, rkey: string): Promise<SignedRecordEnvelope>;
|
|
460
|
+
httpService: import("../HttpService").HttpService;
|
|
461
|
+
cloudURL: string;
|
|
462
|
+
config: import("../OxyServices.base").OxyConfig;
|
|
463
|
+
__resetTokensForTests(): void;
|
|
464
|
+
makeRequest<T_1>(method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE", url: string, data?: any, options?: import("../HttpService").RequestOptions): Promise<T_1>;
|
|
465
|
+
getBaseURL(): string;
|
|
466
|
+
getSessionBaseUrl(): string;
|
|
467
|
+
getClient(): import("../HttpService").HttpService;
|
|
468
|
+
createLinkedClient(config: import("../OxyServices.base").OxyConfig): import("..").LinkedHttpClient;
|
|
469
|
+
getMetrics(): {
|
|
470
|
+
totalRequests: number;
|
|
471
|
+
successfulRequests: number;
|
|
472
|
+
failedRequests: number;
|
|
473
|
+
cacheHits: number;
|
|
474
|
+
cacheMisses: number;
|
|
475
|
+
averageResponseTime: number;
|
|
476
|
+
};
|
|
477
|
+
clearCache(): void;
|
|
478
|
+
clearCacheEntry(key: string): void;
|
|
479
|
+
clearCacheByPrefix(prefix: string): number;
|
|
480
|
+
getCacheStats(): {
|
|
481
|
+
size: number;
|
|
482
|
+
hits: number;
|
|
483
|
+
misses: number;
|
|
484
|
+
hitRate: number;
|
|
485
|
+
};
|
|
486
|
+
getCloudURL(): string;
|
|
487
|
+
setTokens(accessToken: string): void;
|
|
488
|
+
clearTokens(): void;
|
|
489
|
+
onTokensChanged(listener: (accessToken: string | null) => void): () => void;
|
|
490
|
+
_cachedUserId: string | null | undefined;
|
|
491
|
+
_cachedAccessToken: string | null;
|
|
492
|
+
getCurrentUserId(): string | null;
|
|
493
|
+
hasValidToken(): boolean;
|
|
494
|
+
getAccessToken(): string | null;
|
|
495
|
+
setActingAs(userId: string | null): void;
|
|
496
|
+
getActingAs(): string | null;
|
|
497
|
+
waitForAuth(timeoutMs?: number): Promise<boolean>;
|
|
498
|
+
withAuthRetry<T_1>(operation: () => Promise<T_1>, operationName: string, options?: {
|
|
499
|
+
maxRetries?: number;
|
|
500
|
+
retryDelay?: number;
|
|
501
|
+
authTimeoutMs?: number;
|
|
502
|
+
}): Promise<T_1>;
|
|
503
|
+
validate(): Promise<boolean>;
|
|
504
|
+
handleError(error: unknown): Error;
|
|
505
|
+
healthCheck(): Promise<{
|
|
506
|
+
status: string;
|
|
507
|
+
users?: number;
|
|
508
|
+
timestamp?: string;
|
|
509
|
+
[key: string]: any;
|
|
510
|
+
}>;
|
|
511
|
+
};
|
|
512
|
+
} & T;
|
|
@@ -29,6 +29,7 @@ import { OxyServicesTopicsMixin } from './OxyServices.topics';
|
|
|
29
29
|
import { OxyServicesManagedAccountsMixin } from './OxyServices.managedAccounts';
|
|
30
30
|
import { OxyServicesContactsMixin } from './OxyServices.contacts';
|
|
31
31
|
import { OxyServicesAppDataMixin } from './OxyServices.appData';
|
|
32
|
+
import { OxyServicesCivicMixin } from './OxyServices.civic';
|
|
32
33
|
/**
|
|
33
34
|
* Instance shape of every mixin in the pipeline, intersected. The runtime
|
|
34
35
|
* `composeOxyServices()` produces a class whose instances expose all of
|
|
@@ -38,7 +39,7 @@ import { OxyServicesAppDataMixin } from './OxyServices.appData';
|
|
|
38
39
|
* If you add a new mixin to `MIXIN_PIPELINE`, add it here too so its methods
|
|
39
40
|
* are visible without a cast.
|
|
40
41
|
*/
|
|
41
|
-
type AllMixinInstances = InstanceType<ReturnType<typeof OxyServicesAuthMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesFedCMMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesSilentAuthMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesRedirectAuthMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesSsoMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesUserMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesIdentityMixin<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 OxyServicesApplicationsMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesWorkspacesMixin<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 OxyServicesManagedAccountsMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesContactsMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesAppDataMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesUtilityMixin<typeof OxyServicesBase>>>;
|
|
42
|
+
type AllMixinInstances = InstanceType<ReturnType<typeof OxyServicesAuthMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesFedCMMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesSilentAuthMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesRedirectAuthMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesSsoMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesUserMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesIdentityMixin<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 OxyServicesApplicationsMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesWorkspacesMixin<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 OxyServicesManagedAccountsMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesContactsMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesAppDataMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesCivicMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesUtilityMixin<typeof OxyServicesBase>>>;
|
|
42
43
|
/**
|
|
43
44
|
* Constructor type for the fully composed mixin pipeline. Each mixin returns
|
|
44
45
|
* a new constructor that augments its input; reducing across the pipeline
|