@oxy.so/core 7.23.1 → 7.24.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/api/accounts.js +102 -1
- package/dist/cjs/api/storeInstaller.js +1 -1
- package/dist/cjs/i18n/locales/compact/es-ES.generated.js +1 -1
- package/dist/cjs/i18n/locales/en-US.js +10 -0
- package/dist/cjs/i18n/locales/es-ES.js +10 -0
- package/dist/cjs/index.js +1 -1
- package/dist/esm/api/accounts.js +68 -1
- package/dist/esm/api/storeInstaller.js +1 -1
- package/dist/esm/i18n/locales/compact/es-ES.generated.js +1 -1
- package/dist/esm/i18n/locales/en-US.js +10 -0
- package/dist/esm/i18n/locales/es-ES.js +10 -0
- package/dist/esm/index.js +1 -1
- package/dist/types/api/accounts.d.ts +41 -1
- package/dist/types/api/storeInstaller.d.ts +1 -1
- package/dist/types/i18n/locales/en-US.d.ts +10 -0
- package/dist/types/i18n/locales/es-ES.d.ts +10 -0
- package/dist/types/server/appAssertion.d.ts +1 -1
- package/package.json +2 -2
- package/src/api/accounts.ts +135 -1
- package/src/api/storeInstaller.ts +1 -1
- package/src/i18n/locales/compact/es-ES.generated.ts +1 -1
- package/src/i18n/locales/en-US.ts +10 -0
- package/src/i18n/locales/es-ES.ts +10 -0
- package/src/index.ts +1 -1
|
@@ -681,6 +681,16 @@ const dict = {
|
|
|
681
681
|
add: 'Add your links',
|
|
682
682
|
placeholder: 'Enter URL',
|
|
683
683
|
yourLinks: 'Your Links',
|
|
684
|
+
linkTitle: 'Title',
|
|
685
|
+
moveUp: 'Move up',
|
|
686
|
+
moveDown: 'Move down',
|
|
687
|
+
errors: {
|
|
688
|
+
empty: 'Enter a link.',
|
|
689
|
+
invalid: 'Enter a valid link.',
|
|
690
|
+
insecure: 'Links must start with https://.',
|
|
691
|
+
duplicate: 'That link is already on your profile.',
|
|
692
|
+
limit: 'You can add up to {{count}} links.',
|
|
693
|
+
},
|
|
684
694
|
count: '{{count}} link added',
|
|
685
695
|
count_plural: '{{count}} links added',
|
|
686
696
|
},
|
|
@@ -383,6 +383,16 @@ const dict = {
|
|
|
383
383
|
add: 'Añade tus enlaces',
|
|
384
384
|
placeholder: 'Introduce la URL',
|
|
385
385
|
yourLinks: 'Tus enlaces',
|
|
386
|
+
linkTitle: 'Título',
|
|
387
|
+
moveUp: 'Subir',
|
|
388
|
+
moveDown: 'Bajar',
|
|
389
|
+
errors: {
|
|
390
|
+
empty: 'Introduce un enlace.',
|
|
391
|
+
invalid: 'Introduce un enlace válido.',
|
|
392
|
+
insecure: 'Los enlaces deben empezar por https://.',
|
|
393
|
+
duplicate: 'Ese enlace ya está en tu perfil.',
|
|
394
|
+
limit: 'Puedes añadir hasta {{count}} enlaces.',
|
|
395
|
+
},
|
|
386
396
|
count: '{{count}} enlace añadido',
|
|
387
397
|
count_plural: '{{count}} enlaces añadidos',
|
|
388
398
|
},
|
package/dist/cjs/index.js
CHANGED
|
@@ -61,7 +61,7 @@ Object.defineProperty(exports, "MAX_ACCOUNT_CATEGORIES", { enumerable: true, get
|
|
|
61
61
|
Object.defineProperty(exports, "SELECTABLE_ACCOUNT_CATEGORY_IDS", { enumerable: true, get: function () { return accounts_1.SELECTABLE_ACCOUNT_CATEGORY_IDS; } });
|
|
62
62
|
Object.defineProperty(exports, "isSelectableAccountCategoryId", { enumerable: true, get: function () { return accounts_1.isSelectableAccountCategoryId; } });
|
|
63
63
|
Object.defineProperty(exports, "kindAcceptsAccountCategories", { enumerable: true, get: function () { return accounts_1.kindAcceptsAccountCategories; } });
|
|
64
|
-
// The store's installer (ADR
|
|
64
|
+
// The store's installer (ADR 0059): what a runtime that installs applications registers beside
|
|
65
65
|
// `oxy.store`, and what a store asks it.
|
|
66
66
|
var storeInstaller_1 = require("./api/storeInstaller");
|
|
67
67
|
Object.defineProperty(exports, "getStoreInstaller", { enumerable: true, get: function () { return storeInstaller_1.getStoreInstaller; } });
|
package/dist/esm/api/accounts.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { agentKeyListResponseCheck, agentKeyOperationChallengeCheck, agentKeyOperationCheck, agentKeyOperationResultCheck, executeAgentKeyOperationCheck, parseContract, } from '@oxy.so/contracts/client';
|
|
1
|
+
import { agentKeyListResponseCheck, agentKeyOperationChallengeCheck, agentKeyOperationCheck, agentKeyOperationResultCheck, executeAgentKeyOperationCheck, organizationIdentityKeyStateCheck, organizationKeyApplyRequestCheck, organizationKeyChallengeCheck, organizationKeyChallengeRequestCheck, organizationKeyProofClaims, parseContract, } from '@oxy.so/contracts/client';
|
|
2
2
|
import { normalizeUserIdentity } from '../utils/userIdentity.js';
|
|
3
3
|
import { evictOxyIdentityCache } from '../utils/identityCacheSweep.js';
|
|
4
4
|
import { evictOxyAccountForestCache, oxyAccountDetailCacheKey, OXY_ACCOUNT_PER_ACCOUNT_CACHE_PREFIX, } from '../utils/accountCacheSweep.js';
|
|
@@ -75,6 +75,72 @@ export class AccountAgentKeysApi {
|
|
|
75
75
|
return parseContract(agentKeyOperationResultCheck, response);
|
|
76
76
|
}
|
|
77
77
|
}
|
|
78
|
+
/**
|
|
79
|
+
* `oxy.accounts.identityKey` — an organization's identity key (ADR 0061): its
|
|
80
|
+
* DID `#key-1`, the key Peable derives its FairCoin receive addresses from.
|
|
81
|
+
* Only the organization's owners and admins may read or change it; the key is
|
|
82
|
+
* created and held in Commons and never signs anybody in.
|
|
83
|
+
*
|
|
84
|
+
* `get` answers `publicKey: null` for an organization that has no key yet (its
|
|
85
|
+
* DID lists no `#key-1`): that is when a client shows its owners "Set up the
|
|
86
|
+
* organization's Peable wallet". A 403 (`ORGANIZATION_KEY_FORBIDDEN`) means the
|
|
87
|
+
* signed-in person is not an owner or admin of a claimed, active organization.
|
|
88
|
+
*/
|
|
89
|
+
export class AccountIdentityKeyApi {
|
|
90
|
+
constructor(ctx) {
|
|
91
|
+
this.ctx = ctx;
|
|
92
|
+
}
|
|
93
|
+
/** The organization's key (`null` without one) and every key it has had, oldest first. */
|
|
94
|
+
async get(accountId) {
|
|
95
|
+
return parseContract(organizationIdentityKeyStateCheck, await this.ctx.request('GET', `/accounts/${enc(accountId)}/identity-key`, undefined, { cache: false }));
|
|
96
|
+
}
|
|
97
|
+
/** A one-use challenge for one change, with the claims every signer signs. */
|
|
98
|
+
async requestChallenge(accountId, request) {
|
|
99
|
+
return parseContract(organizationKeyChallengeCheck, await this.ctx.request('POST', `/accounts/${enc(accountId)}/identity-key/challenge`, parseContract(organizationKeyChallengeRequestCheck, request), { cache: false }));
|
|
100
|
+
}
|
|
101
|
+
/** Apply a change with its signatures (see {@link link} for the whole ceremony). */
|
|
102
|
+
async apply(accountId, request) {
|
|
103
|
+
return parseContract(organizationIdentityKeyStateCheck, await this.ctx.request('POST', `/accounts/${enc(accountId)}/identity-key`, parseContract(organizationKeyApplyRequestCheck, request), { cache: false }));
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Commons' whole ceremony. NATIVE-ONLY: the actor is THIS device's personal
|
|
107
|
+
* root (`KeyManager`), which must be the signed-in person's. `key` is the
|
|
108
|
+
* organization key the device generated (`create`, or `replace` with a new
|
|
109
|
+
* one); `previousKey` is the current organization key when the device holds
|
|
110
|
+
* it, so the replacement is recorded as proven by it.
|
|
111
|
+
*/
|
|
112
|
+
async link(accountId, input) {
|
|
113
|
+
const { KeyManager, signIdentityProof } = await import('../crypto/index.js');
|
|
114
|
+
const [rootPrivateKey, rootPublicKey] = await Promise.all([
|
|
115
|
+
KeyManager.getPrivateKey(),
|
|
116
|
+
KeyManager.getPublicKey(),
|
|
117
|
+
]);
|
|
118
|
+
if (!rootPrivateKey || !rootPublicKey) {
|
|
119
|
+
throw new Error('No identity on this device to sign with');
|
|
120
|
+
}
|
|
121
|
+
const challenge = await this.requestChallenge(accountId, {
|
|
122
|
+
operation: input.operation,
|
|
123
|
+
publicKey: input.key.publicKey,
|
|
124
|
+
});
|
|
125
|
+
const root = rootPublicKey.trim().toLowerCase();
|
|
126
|
+
if (challenge.actorPublicKey !== root) {
|
|
127
|
+
throw new Error("This device's identity is not the signed-in account's");
|
|
128
|
+
}
|
|
129
|
+
const sign = async (signer, publicKey) => (await signIdentityProof({ privateKey: signer.privateKey, publicKey }, organizationKeyProofClaims(challenge, publicKey))).signature;
|
|
130
|
+
const previousPublicKey = challenge.previousPublicKey;
|
|
131
|
+
return this.apply(accountId, {
|
|
132
|
+
operation: input.operation,
|
|
133
|
+
publicKey: challenge.publicKey,
|
|
134
|
+
challenge: challenge.challenge,
|
|
135
|
+
expiresAt: challenge.expiresAt,
|
|
136
|
+
actorSignature: await sign({ privateKey: rootPrivateKey, publicKey: root }, root),
|
|
137
|
+
keySignature: await sign(input.key, challenge.publicKey),
|
|
138
|
+
...(input.previousKey && previousPublicKey
|
|
139
|
+
? { previousKeySignature: await sign(input.previousKey, previousPublicKey) }
|
|
140
|
+
: {}),
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
}
|
|
78
144
|
/** Consent-based invitations; never cached or queued as offline mutations. */
|
|
79
145
|
export class AccountInvitationsApi {
|
|
80
146
|
constructor(ctx) {
|
|
@@ -109,6 +175,7 @@ export class AccountsApi {
|
|
|
109
175
|
this.members = new AccountMembersApi(ctx);
|
|
110
176
|
this.invitations = new AccountInvitationsApi(ctx);
|
|
111
177
|
this.agentKeys = new AccountAgentKeysApi(ctx);
|
|
178
|
+
this.identityKey = new AccountIdentityKeyApi(ctx);
|
|
112
179
|
}
|
|
113
180
|
/**
|
|
114
181
|
* List the accounts the caller can access: their own personal (root)
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* `oxy.store` says what the store lists; an installer says what the machine can do with a
|
|
6
6
|
* listing. A runtime that installs applications registers one (OxyOS's Bloom host registers one
|
|
7
7
|
* backed by the system's install service before the application's code runs, OxyOS ADR 0030
|
|
8
|
-
* decision 9; ADR
|
|
8
|
+
* decision 9; ADR 0059 here). Where none is registered — the web, iOS, Android — there is
|
|
9
9
|
* nothing to install, and a store shows what it shows without one. An application never asks
|
|
10
10
|
* which platform it runs on: it asks whether there is an installer.
|
|
11
11
|
*
|