@oxy.so/core 4.6.0 → 4.8.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.
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.OxyServices = exports.OXY_API_URL = exports.OXY_CLOUD_URL = void 0;
4
+ const safety_1 = require("./api/safety");
4
5
  /**
5
6
  * `OxyServices` — the Oxy API client.
6
7
  *
@@ -33,6 +34,7 @@ const privacy_1 = require("./api/privacy");
33
34
  const notifications_1 = require("./api/notifications");
34
35
  const assets_1 = require("./api/assets");
35
36
  const identity_1 = require("./api/identity");
37
+ const organizations_1 = require("./api/organizations");
36
38
  const accounts_1 = require("./api/accounts");
37
39
  const apps_1 = require("./api/apps");
38
40
  const linkedAccounts_1 = require("./api/linkedAccounts");
@@ -196,6 +198,16 @@ class OxyServices {
196
198
  return this._identity;
197
199
  }
198
200
  /** The account graph: accounts and their members. */
201
+ get safety() {
202
+ if (!this._safety)
203
+ this._safety = new safety_1.SafetyApi(this.context);
204
+ return this._safety;
205
+ }
206
+ get organizations() {
207
+ if (!this._organizations)
208
+ this._organizations = new organizations_1.OrganizationsApi(this.context);
209
+ return this._organizations;
210
+ }
199
211
  get accounts() {
200
212
  if (!this._accounts)
201
213
  this._accounts = new accounts_1.AccountsApi(this.context);
@@ -0,0 +1,94 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.OrganizationsApi = void 0;
4
+ const contracts_1 = require("@oxy.so/contracts");
5
+ const identityCacheSweep_1 = require("../utils/identityCacheSweep");
6
+ /** The public canonical organization directory. Claiming changes authority, never identity. */
7
+ class OrganizationsApi {
8
+ constructor(ctx) {
9
+ this.ctx = ctx;
10
+ }
11
+ async search(input) {
12
+ return contracts_1.organizationListSchema.parse(await this.ctx.request('GET', '/organizations', input, { cache: false, skipAuth: true }));
13
+ }
14
+ async get(accountId) {
15
+ return contracts_1.organizationSchema.parse(await this.ctx.request('GET', `/organizations/${encodeURIComponent(accountId)}`, undefined, {
16
+ cache: false,
17
+ skipAuth: true,
18
+ }));
19
+ }
20
+ async batch(input) {
21
+ return contracts_1.organizationBatchSchema.parse(await this.ctx.request('POST', '/organizations/batch', input, {
22
+ cache: false,
23
+ skipAuth: true,
24
+ }));
25
+ }
26
+ async create(input) {
27
+ return contracts_1.organizationSchema.parse(await this.ctx.request('POST', '/organizations', input, { cache: false }));
28
+ }
29
+ async update(accountId, input) {
30
+ const result = contracts_1.organizationSchema.parse(await this.ctx.request('PATCH', `/organizations/${encodeURIComponent(accountId)}`, input, {
31
+ cache: false,
32
+ }));
33
+ (0, identityCacheSweep_1.evictOxyIdentityCache)(this.ctx.http, accountId);
34
+ return result;
35
+ }
36
+ async claim(accountId, input) {
37
+ return contracts_1.organizationClaimSchema.parse(await this.ctx.request('POST', `/organizations/${encodeURIComponent(accountId)}/claims`, input, { cache: false }));
38
+ }
39
+ async myClaims(input = {}) {
40
+ return contracts_1.organizationClaimListSchema.parse(await this.ctx.request('GET', '/organizations/claims/mine', input, { cache: false }));
41
+ }
42
+ async myClaim(claimId) {
43
+ return contracts_1.organizationClaimDetailSchema.parse(await this.ctx.request('GET', `/organizations/claims/mine/${encodeURIComponent(claimId)}`, undefined, { cache: false }));
44
+ }
45
+ async reviewClaims(input = {}) {
46
+ return contracts_1.organizationClaimListSchema.parse(await this.ctx.request('GET', '/organizations/claims/review', input, { cache: false }));
47
+ }
48
+ async reviewClaimDetail(claimId) {
49
+ return contracts_1.organizationClaimDetailSchema.parse(await this.ctx.request('GET', `/organizations/claims/review/${encodeURIComponent(claimId)}`, undefined, { cache: false }));
50
+ }
51
+ async reviewClaim(claimId, input) {
52
+ const result = contracts_1.organizationClaimSchema.parse(await this.ctx.request('POST', `/organizations/claims/${encodeURIComponent(claimId)}/review`, input, { cache: false }));
53
+ (0, identityCacheSweep_1.evictOxyIdentityCache)(this.ctx.http, result.accountId);
54
+ return result;
55
+ }
56
+ async importBatch(input) {
57
+ if (!this.ctx.service?.available)
58
+ throw new Error('Organization batch import requires an OxyServer service identity');
59
+ return contracts_1.organizationImportBatchResultSchema.parse(await this.ctx.service.request('POST', '/organizations/external/batch', input, {
60
+ cache: false,
61
+ }));
62
+ }
63
+ async importExternal(input) {
64
+ return contracts_1.organizationExternalSchema.parse(await this.ctx.request('POST', '/organizations/external', input, { cache: false }));
65
+ }
66
+ async resolveExternal(input) {
67
+ return contracts_1.organizationExternalResolutionSchema.parse(await this.ctx.request('GET', `/organizations/external/${encodeURIComponent(input.namespace)}/${encodeURIComponent(input.externalId)}`, undefined, { cache: false }));
68
+ }
69
+ async curate(accountId, input) {
70
+ const result = contracts_1.organizationCurationResultSchema.parse(await this.ctx.request('POST', `/organizations/${encodeURIComponent(accountId)}/curation`, input, { cache: false }));
71
+ (0, identityCacheSweep_1.evictOxyIdentityCache)(this.ctx.http, accountId);
72
+ return result;
73
+ }
74
+ async merge(accountId, input) {
75
+ const result = contracts_1.organizationSchema.parse(await this.ctx.request('POST', `/organizations/${encodeURIComponent(accountId)}/merge`, input, { cache: false }));
76
+ (0, identityCacheSweep_1.evictOxyIdentityCache)(this.ctx.http, accountId);
77
+ (0, identityCacheSweep_1.evictOxyIdentityCache)(this.ctx.http, result.accountId);
78
+ return result;
79
+ }
80
+ async *iterate(input) {
81
+ let cursor = input.cursor;
82
+ const seen = new Set();
83
+ do {
84
+ const page = await this.search({ ...input, cursor });
85
+ yield* page.items;
86
+ cursor = page.nextCursor ?? undefined;
87
+ if (cursor && seen.has(cursor))
88
+ throw new Error('Organization directory repeated a cursor');
89
+ if (cursor)
90
+ seen.add(cursor);
91
+ } while (cursor);
92
+ }
93
+ }
94
+ exports.OrganizationsApi = OrganizationsApi;
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SafetyApi = void 0;
4
+ const contracts_1 = require("@oxy.so/contracts");
5
+ class SafetyApi {
6
+ constructor(ctx) {
7
+ this.ctx = ctx;
8
+ }
9
+ /** Server callers must explicitly supply the incoming user bearer or null for anonymous access. */
10
+ async profileAccess(input, options) {
11
+ if (this.ctx.service && options === undefined)
12
+ throw new Error('Server profile access requires an explicit requester bearer or null');
13
+ return contracts_1.profileAccessDecisionSchema.parse(await this.ctx.request('GET', '/safety/profile-access', contracts_1.profileAccessInputSchema.parse(input), {
14
+ cache: false,
15
+ ...(options
16
+ ? {
17
+ skipAuth: true,
18
+ headers: options.accessToken
19
+ ? { Authorization: `Bearer ${options.accessToken}` }
20
+ : {},
21
+ }
22
+ : {}),
23
+ }));
24
+ }
25
+ }
26
+ exports.SafetyApi = SafetyApi;
@@ -1,6 +1,67 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const dict = {
4
+ organizationDirectory: {
5
+ invalidName: 'Use a plain-text organization name (up to 300 characters).',
6
+ review: {
7
+ title: 'Review organization access requests',
8
+ forbidden: 'This action requires current staff authorization.',
9
+ empty: 'No requests are waiting for review.',
10
+ hint: 'Review the supporting evidence independently. Approval grants management access to the existing organization account.',
11
+ independent: 'Another reviewer must decide your own request.',
12
+ evidence: 'Review evidence reference',
13
+ approved: 'Approve access',
14
+ rejected: 'Reject request',
15
+ conflict: 'This request or organization changed. Refresh the queue before making another decision.',
16
+ failed: 'The review could not be saved. Your decision has not been confirmed.',
17
+ },
18
+ title: 'Organization directory',
19
+ search: 'Find your organization',
20
+ searchHint: 'Find an existing organization before creating an account. Its identity is shared across Oxy apps.',
21
+ empty: 'No organizations found.',
22
+ retry: 'Try again',
23
+ loadMore: 'Show more',
24
+ failed: 'Could not load the organization directory.',
25
+ unclaimed: 'Unclaimed',
26
+ claimed: 'Managed organization',
27
+ inactive: 'Inactive',
28
+ newAccount: 'Create a new organization account',
29
+ newAccountHint: 'Create and manage a new organization. Choose an existing entry if your organization is already listed.',
30
+ addDirectory: 'Add to directory',
31
+ directoryHint: 'This creates a shared, unclaimed entry. It does not give you access to manage the organization.',
32
+ added: 'Organization added to the directory',
33
+ back: 'Back to search',
34
+ type: 'Organization type',
35
+ types: {
36
+ business: 'Business',
37
+ nonprofit: 'Nonprofit',
38
+ public_body: 'Public body',
39
+ community: 'Community',
40
+ other: 'Other',
41
+ },
42
+ name: 'Organization name',
43
+ legalName: 'Legal name',
44
+ website: 'Website',
45
+ country: 'Country code',
46
+ save: 'Save organization',
47
+ saved: 'Organization updated',
48
+ invalid: 'Check the organization details. Use a complete website URL and a two-letter country code.',
49
+ saveFailed: 'Could not save the organization. Try again.',
50
+ claim: 'Request management access',
51
+ claimHint: 'Oxy reviews evidence of your authority. A request does not grant access or verify your role.',
52
+ evidence: 'Supporting evidence reference',
53
+ evidenceHint: 'Provide a reference to your private verification case or supporting records. Only you and reviewers can read it.',
54
+ claimSent: 'Request submitted for review',
55
+ claimFailed: 'Could not submit your request. Try again.',
56
+ claimedHint: 'This organization already has managers. Contact a manager to request access.',
57
+ requests: 'Organization access requests',
58
+ pending: 'Pending review',
59
+ approved: 'Approved',
60
+ rejected: 'Rejected',
61
+ requestError: 'Could not load your access requests.',
62
+ view: 'Organization details',
63
+ readonly: 'You do not have permission to edit this organization.',
64
+ },
4
65
  signin: {
5
66
  title: 'Sign in',
6
67
  subtitle: 'Use your Oxy account',
@@ -1,6 +1,67 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const dict = {
4
+ organizationDirectory: {
5
+ invalidName: 'Usa un nombre de organización en texto plano (hasta 300 caracteres).',
6
+ review: {
7
+ title: 'Revisar solicitudes de acceso a organizaciones',
8
+ forbidden: 'Esta acción requiere autorización vigente del personal de Oxy.',
9
+ empty: 'No hay solicitudes pendientes de revisión.',
10
+ hint: 'Revisa la documentación de forma independiente. La aprobación concede acceso de administración a la cuenta existente.',
11
+ independent: 'Otro revisor debe decidir sobre tu propia solicitud.',
12
+ evidence: 'Referencia de la documentación de revisión',
13
+ approved: 'Aprobar acceso',
14
+ rejected: 'Rechazar solicitud',
15
+ conflict: 'La solicitud o la organización ha cambiado. Actualiza la lista antes de tomar otra decisión.',
16
+ failed: 'No se pudo guardar la revisión. Tu decisión no se ha confirmado.',
17
+ },
18
+ title: 'Directorio de organizaciones',
19
+ search: 'Busca tu organización',
20
+ searchHint: 'Busca una organización existente antes de crear una cuenta. Su identidad se comparte entre las aplicaciones de Oxy.',
21
+ empty: 'No se encontraron organizaciones.',
22
+ retry: 'Reintentar',
23
+ loadMore: 'Mostrar más',
24
+ failed: 'No se pudo cargar el directorio de organizaciones.',
25
+ unclaimed: 'Sin reclamar',
26
+ claimed: 'Organización administrada',
27
+ inactive: 'Inactiva',
28
+ newAccount: 'Crear una nueva cuenta de organización',
29
+ newAccountHint: 'Crea y administra una organización nueva. Si ya aparece en el directorio, elige la entrada existente.',
30
+ addDirectory: 'Añadir al directorio',
31
+ directoryHint: 'Esto crea una entrada compartida sin reclamar. No te da acceso para administrar la organización.',
32
+ added: 'Organización añadida al directorio',
33
+ back: 'Volver a la búsqueda',
34
+ type: 'Tipo de organización',
35
+ types: {
36
+ business: 'Empresa',
37
+ nonprofit: 'Sin ánimo de lucro',
38
+ public_body: 'Organismo público',
39
+ community: 'Comunidad',
40
+ other: 'Otro',
41
+ },
42
+ name: 'Nombre de la organización',
43
+ legalName: 'Nombre legal',
44
+ website: 'Sitio web',
45
+ country: 'Código de país',
46
+ save: 'Guardar organización',
47
+ saved: 'Organización actualizada',
48
+ invalid: 'Revisa los datos. Usa una URL completa y un código de país de dos letras.',
49
+ saveFailed: 'No se pudo guardar la organización. Inténtalo de nuevo.',
50
+ claim: 'Solicitar acceso de administración',
51
+ claimHint: 'Oxy revisará las pruebas de tu autorización. Una solicitud no concede acceso ni verifica tu cargo.',
52
+ evidence: 'Referencia de la documentación',
53
+ evidenceHint: 'Indica una referencia a tu expediente privado de verificación o documentación acreditativa. Solo tú y los revisores podéis verla.',
54
+ claimSent: 'Solicitud enviada para revisión',
55
+ claimFailed: 'No se pudo enviar la solicitud. Inténtalo de nuevo.',
56
+ claimedHint: 'Esta organización ya tiene administradores. Contacta con uno para solicitar acceso.',
57
+ requests: 'Solicitudes de acceso a organizaciones',
58
+ pending: 'Pendiente de revisión',
59
+ approved: 'Aprobada',
60
+ rejected: 'Rechazada',
61
+ requestError: 'No se pudieron cargar tus solicitudes.',
62
+ view: 'Datos de la organización',
63
+ readonly: 'No tienes permiso para editar esta organización.',
64
+ },
4
65
  signin: {
5
66
  title: 'Iniciar sesión',
6
67
  subtitle: 'Usa tu cuenta de Oxy',
@@ -1,3 +1,4 @@
1
+ import { SafetyApi } from './api/safety.js';
1
2
  /**
2
3
  * `OxyServices` — the Oxy API client.
3
4
  *
@@ -30,6 +31,7 @@ import { PrivacyApi } from './api/privacy.js';
30
31
  import { NotificationsApi } from './api/notifications.js';
31
32
  import { AssetsApi } from './api/assets.js';
32
33
  import { IdentityApi } from './api/identity.js';
34
+ import { OrganizationsApi } from './api/organizations.js';
33
35
  import { AccountsApi } from './api/accounts.js';
34
36
  import { AppsApi } from './api/apps.js';
35
37
  import { LinkedAccountsApi } from './api/linkedAccounts.js';
@@ -193,6 +195,16 @@ export class OxyServices {
193
195
  return this._identity;
194
196
  }
195
197
  /** The account graph: accounts and their members. */
198
+ get safety() {
199
+ if (!this._safety)
200
+ this._safety = new SafetyApi(this.context);
201
+ return this._safety;
202
+ }
203
+ get organizations() {
204
+ if (!this._organizations)
205
+ this._organizations = new OrganizationsApi(this.context);
206
+ return this._organizations;
207
+ }
196
208
  get accounts() {
197
209
  if (!this._accounts)
198
210
  this._accounts = new AccountsApi(this.context);
@@ -0,0 +1,90 @@
1
+ import { organizationSchema, organizationListSchema, organizationBatchSchema, organizationClaimSchema, organizationExternalSchema, organizationExternalResolutionSchema, organizationImportBatchResultSchema, organizationCurationResultSchema, organizationClaimListSchema, organizationClaimDetailSchema, } from '@oxy.so/contracts';
2
+ import { evictOxyIdentityCache } from '../utils/identityCacheSweep.js';
3
+ /** The public canonical organization directory. Claiming changes authority, never identity. */
4
+ export class OrganizationsApi {
5
+ constructor(ctx) {
6
+ this.ctx = ctx;
7
+ }
8
+ async search(input) {
9
+ return organizationListSchema.parse(await this.ctx.request('GET', '/organizations', input, { cache: false, skipAuth: true }));
10
+ }
11
+ async get(accountId) {
12
+ return organizationSchema.parse(await this.ctx.request('GET', `/organizations/${encodeURIComponent(accountId)}`, undefined, {
13
+ cache: false,
14
+ skipAuth: true,
15
+ }));
16
+ }
17
+ async batch(input) {
18
+ return organizationBatchSchema.parse(await this.ctx.request('POST', '/organizations/batch', input, {
19
+ cache: false,
20
+ skipAuth: true,
21
+ }));
22
+ }
23
+ async create(input) {
24
+ return organizationSchema.parse(await this.ctx.request('POST', '/organizations', input, { cache: false }));
25
+ }
26
+ async update(accountId, input) {
27
+ const result = organizationSchema.parse(await this.ctx.request('PATCH', `/organizations/${encodeURIComponent(accountId)}`, input, {
28
+ cache: false,
29
+ }));
30
+ evictOxyIdentityCache(this.ctx.http, accountId);
31
+ return result;
32
+ }
33
+ async claim(accountId, input) {
34
+ return organizationClaimSchema.parse(await this.ctx.request('POST', `/organizations/${encodeURIComponent(accountId)}/claims`, input, { cache: false }));
35
+ }
36
+ async myClaims(input = {}) {
37
+ return organizationClaimListSchema.parse(await this.ctx.request('GET', '/organizations/claims/mine', input, { cache: false }));
38
+ }
39
+ async myClaim(claimId) {
40
+ return organizationClaimDetailSchema.parse(await this.ctx.request('GET', `/organizations/claims/mine/${encodeURIComponent(claimId)}`, undefined, { cache: false }));
41
+ }
42
+ async reviewClaims(input = {}) {
43
+ return organizationClaimListSchema.parse(await this.ctx.request('GET', '/organizations/claims/review', input, { cache: false }));
44
+ }
45
+ async reviewClaimDetail(claimId) {
46
+ return organizationClaimDetailSchema.parse(await this.ctx.request('GET', `/organizations/claims/review/${encodeURIComponent(claimId)}`, undefined, { cache: false }));
47
+ }
48
+ async reviewClaim(claimId, input) {
49
+ const result = organizationClaimSchema.parse(await this.ctx.request('POST', `/organizations/claims/${encodeURIComponent(claimId)}/review`, input, { cache: false }));
50
+ evictOxyIdentityCache(this.ctx.http, result.accountId);
51
+ return result;
52
+ }
53
+ async importBatch(input) {
54
+ if (!this.ctx.service?.available)
55
+ throw new Error('Organization batch import requires an OxyServer service identity');
56
+ return organizationImportBatchResultSchema.parse(await this.ctx.service.request('POST', '/organizations/external/batch', input, {
57
+ cache: false,
58
+ }));
59
+ }
60
+ async importExternal(input) {
61
+ return organizationExternalSchema.parse(await this.ctx.request('POST', '/organizations/external', input, { cache: false }));
62
+ }
63
+ async resolveExternal(input) {
64
+ return organizationExternalResolutionSchema.parse(await this.ctx.request('GET', `/organizations/external/${encodeURIComponent(input.namespace)}/${encodeURIComponent(input.externalId)}`, undefined, { cache: false }));
65
+ }
66
+ async curate(accountId, input) {
67
+ const result = organizationCurationResultSchema.parse(await this.ctx.request('POST', `/organizations/${encodeURIComponent(accountId)}/curation`, input, { cache: false }));
68
+ evictOxyIdentityCache(this.ctx.http, accountId);
69
+ return result;
70
+ }
71
+ async merge(accountId, input) {
72
+ const result = organizationSchema.parse(await this.ctx.request('POST', `/organizations/${encodeURIComponent(accountId)}/merge`, input, { cache: false }));
73
+ evictOxyIdentityCache(this.ctx.http, accountId);
74
+ evictOxyIdentityCache(this.ctx.http, result.accountId);
75
+ return result;
76
+ }
77
+ async *iterate(input) {
78
+ let cursor = input.cursor;
79
+ const seen = new Set();
80
+ do {
81
+ const page = await this.search({ ...input, cursor });
82
+ yield* page.items;
83
+ cursor = page.nextCursor ?? undefined;
84
+ if (cursor && seen.has(cursor))
85
+ throw new Error('Organization directory repeated a cursor');
86
+ if (cursor)
87
+ seen.add(cursor);
88
+ } while (cursor);
89
+ }
90
+ }
@@ -0,0 +1,22 @@
1
+ import { profileAccessInputSchema, profileAccessDecisionSchema, } from '@oxy.so/contracts';
2
+ export class SafetyApi {
3
+ constructor(ctx) {
4
+ this.ctx = ctx;
5
+ }
6
+ /** Server callers must explicitly supply the incoming user bearer or null for anonymous access. */
7
+ async profileAccess(input, options) {
8
+ if (this.ctx.service && options === undefined)
9
+ throw new Error('Server profile access requires an explicit requester bearer or null');
10
+ return profileAccessDecisionSchema.parse(await this.ctx.request('GET', '/safety/profile-access', profileAccessInputSchema.parse(input), {
11
+ cache: false,
12
+ ...(options
13
+ ? {
14
+ skipAuth: true,
15
+ headers: options.accessToken
16
+ ? { Authorization: `Bearer ${options.accessToken}` }
17
+ : {},
18
+ }
19
+ : {}),
20
+ }));
21
+ }
22
+ }
@@ -1,4 +1,65 @@
1
1
  const dict = {
2
+ organizationDirectory: {
3
+ invalidName: 'Use a plain-text organization name (up to 300 characters).',
4
+ review: {
5
+ title: 'Review organization access requests',
6
+ forbidden: 'This action requires current staff authorization.',
7
+ empty: 'No requests are waiting for review.',
8
+ hint: 'Review the supporting evidence independently. Approval grants management access to the existing organization account.',
9
+ independent: 'Another reviewer must decide your own request.',
10
+ evidence: 'Review evidence reference',
11
+ approved: 'Approve access',
12
+ rejected: 'Reject request',
13
+ conflict: 'This request or organization changed. Refresh the queue before making another decision.',
14
+ failed: 'The review could not be saved. Your decision has not been confirmed.',
15
+ },
16
+ title: 'Organization directory',
17
+ search: 'Find your organization',
18
+ searchHint: 'Find an existing organization before creating an account. Its identity is shared across Oxy apps.',
19
+ empty: 'No organizations found.',
20
+ retry: 'Try again',
21
+ loadMore: 'Show more',
22
+ failed: 'Could not load the organization directory.',
23
+ unclaimed: 'Unclaimed',
24
+ claimed: 'Managed organization',
25
+ inactive: 'Inactive',
26
+ newAccount: 'Create a new organization account',
27
+ newAccountHint: 'Create and manage a new organization. Choose an existing entry if your organization is already listed.',
28
+ addDirectory: 'Add to directory',
29
+ directoryHint: 'This creates a shared, unclaimed entry. It does not give you access to manage the organization.',
30
+ added: 'Organization added to the directory',
31
+ back: 'Back to search',
32
+ type: 'Organization type',
33
+ types: {
34
+ business: 'Business',
35
+ nonprofit: 'Nonprofit',
36
+ public_body: 'Public body',
37
+ community: 'Community',
38
+ other: 'Other',
39
+ },
40
+ name: 'Organization name',
41
+ legalName: 'Legal name',
42
+ website: 'Website',
43
+ country: 'Country code',
44
+ save: 'Save organization',
45
+ saved: 'Organization updated',
46
+ invalid: 'Check the organization details. Use a complete website URL and a two-letter country code.',
47
+ saveFailed: 'Could not save the organization. Try again.',
48
+ claim: 'Request management access',
49
+ claimHint: 'Oxy reviews evidence of your authority. A request does not grant access or verify your role.',
50
+ evidence: 'Supporting evidence reference',
51
+ evidenceHint: 'Provide a reference to your private verification case or supporting records. Only you and reviewers can read it.',
52
+ claimSent: 'Request submitted for review',
53
+ claimFailed: 'Could not submit your request. Try again.',
54
+ claimedHint: 'This organization already has managers. Contact a manager to request access.',
55
+ requests: 'Organization access requests',
56
+ pending: 'Pending review',
57
+ approved: 'Approved',
58
+ rejected: 'Rejected',
59
+ requestError: 'Could not load your access requests.',
60
+ view: 'Organization details',
61
+ readonly: 'You do not have permission to edit this organization.',
62
+ },
2
63
  signin: {
3
64
  title: 'Sign in',
4
65
  subtitle: 'Use your Oxy account',
@@ -1,4 +1,65 @@
1
1
  const dict = {
2
+ organizationDirectory: {
3
+ invalidName: 'Usa un nombre de organización en texto plano (hasta 300 caracteres).',
4
+ review: {
5
+ title: 'Revisar solicitudes de acceso a organizaciones',
6
+ forbidden: 'Esta acción requiere autorización vigente del personal de Oxy.',
7
+ empty: 'No hay solicitudes pendientes de revisión.',
8
+ hint: 'Revisa la documentación de forma independiente. La aprobación concede acceso de administración a la cuenta existente.',
9
+ independent: 'Otro revisor debe decidir sobre tu propia solicitud.',
10
+ evidence: 'Referencia de la documentación de revisión',
11
+ approved: 'Aprobar acceso',
12
+ rejected: 'Rechazar solicitud',
13
+ conflict: 'La solicitud o la organización ha cambiado. Actualiza la lista antes de tomar otra decisión.',
14
+ failed: 'No se pudo guardar la revisión. Tu decisión no se ha confirmado.',
15
+ },
16
+ title: 'Directorio de organizaciones',
17
+ search: 'Busca tu organización',
18
+ searchHint: 'Busca una organización existente antes de crear una cuenta. Su identidad se comparte entre las aplicaciones de Oxy.',
19
+ empty: 'No se encontraron organizaciones.',
20
+ retry: 'Reintentar',
21
+ loadMore: 'Mostrar más',
22
+ failed: 'No se pudo cargar el directorio de organizaciones.',
23
+ unclaimed: 'Sin reclamar',
24
+ claimed: 'Organización administrada',
25
+ inactive: 'Inactiva',
26
+ newAccount: 'Crear una nueva cuenta de organización',
27
+ newAccountHint: 'Crea y administra una organización nueva. Si ya aparece en el directorio, elige la entrada existente.',
28
+ addDirectory: 'Añadir al directorio',
29
+ directoryHint: 'Esto crea una entrada compartida sin reclamar. No te da acceso para administrar la organización.',
30
+ added: 'Organización añadida al directorio',
31
+ back: 'Volver a la búsqueda',
32
+ type: 'Tipo de organización',
33
+ types: {
34
+ business: 'Empresa',
35
+ nonprofit: 'Sin ánimo de lucro',
36
+ public_body: 'Organismo público',
37
+ community: 'Comunidad',
38
+ other: 'Otro',
39
+ },
40
+ name: 'Nombre de la organización',
41
+ legalName: 'Nombre legal',
42
+ website: 'Sitio web',
43
+ country: 'Código de país',
44
+ save: 'Guardar organización',
45
+ saved: 'Organización actualizada',
46
+ invalid: 'Revisa los datos. Usa una URL completa y un código de país de dos letras.',
47
+ saveFailed: 'No se pudo guardar la organización. Inténtalo de nuevo.',
48
+ claim: 'Solicitar acceso de administración',
49
+ claimHint: 'Oxy revisará las pruebas de tu autorización. Una solicitud no concede acceso ni verifica tu cargo.',
50
+ evidence: 'Referencia de la documentación',
51
+ evidenceHint: 'Indica una referencia a tu expediente privado de verificación o documentación acreditativa. Solo tú y los revisores podéis verla.',
52
+ claimSent: 'Solicitud enviada para revisión',
53
+ claimFailed: 'No se pudo enviar la solicitud. Inténtalo de nuevo.',
54
+ claimedHint: 'Esta organización ya tiene administradores. Contacta con uno para solicitar acceso.',
55
+ requests: 'Solicitudes de acceso a organizaciones',
56
+ pending: 'Pendiente de revisión',
57
+ approved: 'Aprobada',
58
+ rejected: 'Rechazada',
59
+ requestError: 'No se pudieron cargar tus solicitudes.',
60
+ view: 'Datos de la organización',
61
+ readonly: 'No tienes permiso para editar esta organización.',
62
+ },
2
63
  signin: {
3
64
  title: 'Iniciar sesión',
4
65
  subtitle: 'Usa tu cuenta de Oxy',
@@ -1,3 +1,4 @@
1
+ import { SafetyApi } from './api/safety';
1
2
  /**
2
3
  * `OxyServices` — the Oxy API client.
3
4
  *
@@ -31,6 +32,7 @@ import { PrivacyApi } from './api/privacy';
31
32
  import { NotificationsApi } from './api/notifications';
32
33
  import { AssetsApi } from './api/assets';
33
34
  import { IdentityApi } from './api/identity';
35
+ import { OrganizationsApi } from './api/organizations';
34
36
  import { AccountsApi } from './api/accounts';
35
37
  import { AppsApi } from './api/apps';
36
38
  import { LinkedAccountsApi } from './api/linkedAccounts';
@@ -116,6 +118,8 @@ export declare class OxyServices {
116
118
  private _assets?;
117
119
  private _identity?;
118
120
  private _accounts?;
121
+ private _organizations?;
122
+ private _safety?;
119
123
  private _apps?;
120
124
  private _linkedAccounts?;
121
125
  private _agency?;
@@ -145,6 +149,8 @@ export declare class OxyServices {
145
149
  /** DID, keys, identity links, domains, backup and the signed export. */
146
150
  get identity(): IdentityApi;
147
151
  /** The account graph: accounts and their members. */
152
+ get safety(): SafetyApi;
153
+ get organizations(): OrganizationsApi;
148
154
  get accounts(): AccountsApi;
149
155
  /** Applications an account owns, and the ones this user granted access. */
150
156
  get apps(): AppsApi;
@@ -1,3 +1,4 @@
1
+ import type { OrganizationType } from '@oxy.so/contracts';
1
2
  /**
2
3
  * `oxy.accounts` — the unified account graph (`/accounts`).
3
4
  *
@@ -193,6 +194,7 @@ export interface CreateAccountInput {
193
194
  * keep working. At most `MAX_ACCOUNT_CATEGORIES`, no duplicates.
194
195
  */
195
196
  accountCategories?: AccountCategoryId[];
197
+ organizationType?: OrganizationType;
196
198
  /**
197
199
  * Create the account already opted OUT of discovery — kept out of people
198
200
  * search, the follow-graph lists, `/similar` and the recommendation pools,
@@ -261,6 +263,7 @@ export interface UpdateAccountInput {
261
263
  * every other field here (`account:update`).
262
264
  */
263
265
  character?: AvatarCharacter;
266
+ organizationType?: OrganizationType;
264
267
  }
265
268
  /** Input accepted by `accounts.members.invite`. The owner role cannot be invited. */
266
269
  export interface InviteAccountMemberInput {