# ExtremeX ONE — Advanced Integration & API Specification

> **Product:** ExtremeX ONE Identity, Consent & Application Data Platform  
> **Publisher:** ExtremeX Technology  
> **Document classification:** Developer reference / implementation proposal  
> **Revision:** 1.0 — 23 October 2026  
> **Existing SDK baseline:** 3.2.0 (as shown on the reviewed integration guide)  
> **Status:** Existing API inventory plus **proposed additions**; proposed methods are **not confirmed shipped**.  
> **Primary documentation:** https://client.extremextechnology.com/docs  
> **Account portal:** https://one.extremextechnology.com/account

---

## 1. Executive summary

ExtremeX ONE provides federated authentication, granular consent, privacy-preserving identity attributes, per-application encrypted storage and unified account-management flows. This specification standardises the `one` facade, documents existing behaviour, and proposes new application metadata, legal-document consent, organisation-membership and account-lifecycle interfaces.

**Design objectives:**

1. **Privacy by default:** Applications receive only fields explicitly granted through ONE; raw date of birth and exact age must never be exposed.
2. **Least privilege:** Account, application, organisation and moderation operations are authorised independently and enforced on the ONE server.
3. **Predictable outcomes:** `null` means an unavailable/withheld profile value, **never** an assumed negative result or transport failure.
4. **Cross-platform parity:** Shared logical contracts map to Kotlin, Android, Swift, JavaScript, React Native, Flutter, Java and other supported clients.
5. **Strong consistency of consent:** Consent changes and disconnects take effect at the protected resource boundary; stale local caches cannot override server policy.
6. **Developer experience:** Stable method names, typed results, explicit errors, completion prompts, diagnostics and migration guidance.

### 1.1 Implementation status legend

| Label | Meaning |
|---|---|
| **Existing — documented** | Found in the reviewed live SDK 3.2 integration guide. |
| **Proposed** | Requested API or expanded contract; requires backend/SDK development and release verification. |
| **Recommended** | Design guidance or optional future enhancement, not a guarantee of current implementation. |

**Compatibility note:** The current native guide uses `one.auth.signOut()` for local sign-out. `one.auth.data.signOut()` below is a **proposed forwarding alias**, not a replacement for the existing call. The identifiers `Varified` and `Enroled` are preserved where explicitly requested for source compatibility; correctly spelled aliases may be introduced later.

---

## 2. Existing integration architecture

```text
Host application (Android / iOS / Web / Desktop / Server)
    |
    +--> ONE SDK facade (`one`)
             |
             +--> Auth: browser login, OAuth 2.0 / PKCE, callback, tokens
             +--> Profile: consent-filtered identity & derived age checks
             +--> App data: app/user-scoped typed key-value operations
             +--> [PROPOSED] App metadata and legal-doc consent
             +--> [PROPOSED] Organisation access and moderation gateways
    |
    +--> ExtremeX ONE OAuth / API infrastructure
             |
             +--> Identity & verified attributes
             +--> Live consent and revocation enforcement
             +--> Encrypted application data
             +--> [PROPOSED] Versioned legal document records
             +--> [PROPOSED] Organisation/project role bindings
             +--> [PROPOSED] Privileged moderation service
```

### 2.1 Authentication sequence

1. Register an application in ExtremeX Client and obtain `APP_ID`, `CLIENT_ID`, and the documented redirect configuration.
2. Configure requested data fields in **Client → Data access**, with a specific purpose and required/optional classification.
3. Start sign-in using the supported ONE browser-based flow. Public clients use OAuth 2.0 authorization code + **PKCE (S256)**; never embed client secrets in shipped clients.
4. ONE authenticates the user and displays its hosted consent and missing-profile completion screens.
5. Validate callback parameters and exchange the authorization code using the documented platform flow.
6. Bind an authenticated session to the `one` SDK instance. Refresh and persist rotating refresh tokens using platform-secure storage when available and authorised.
7. Invoke protected profile, application-data or proposed APIs. Each server call evaluates current access rights.
8. On local sign-out, clear local session state. Revocation of granted access is a separate ONE account action unless a future endpoint explicitly implements it.

**Current service endpoints (documented):**

```text
Authorization: https://one.extremextechnology.com/oauth/authorize
API base:     https://api.extremextechnology.com/one

GET    /oauth/authorize
POST   /oauth/token
GET    /oauth/userinfo
GET    /data?key=KEY
PUT    /data
DELETE /data?key=KEY
```

**Important:** The proposed app-document, organisation, and moderation endpoints later in this specification are design proposals. Their paths and payloads must be implemented and published before SDK methods can call them.

---

## 3. Shared API conventions

### 3.1 Namespaces

| Facade | Responsibility |
|---|---|
| `one.auth.data.*` | Consent-filtered user profile and derived identity attributes. |
| `one.auth.*` | Authentication lifecycle and session controls. |
| `one.app.data.*` | Registered app's public metadata and legal-document consent (**proposed**). |
| `one.data.*` | Per-user, per-app encrypted key-value storage. |
| `one.org.*` | **Recommended** future separation for organisation administration; existing requested aliases may remain under `one.auth.data`. |
| `one.admin.*` | **Recommended** privileged moderation namespace; `setBan` can remain as a compatibility delegate after authorisation. |

### 3.2 Result and null semantics

A getter may return `T | null` only when the requested profile attribute is missing, incomplete, or not granted. A missing but **granted** field should be eligible for ONE's existing completion experience; a **denied** field must not trigger a coercive completion prompt.

| Outcome | Return/behaviour | Required UI handling |
|---|---|---|
| Present and permitted | `T` | Use the value for the approved purpose. |
| Known condition is false | `false` | Treat as verified evaluation of the boolean predicate, not lack of data. |
| Missing profile field, consent granted | `null` | Offer ONE's existing completion prompt where supported, then retry after user returns. |
| Field not granted / permission withdrawn | `null` for profile getter | Explain feature limitation; offer voluntary permissions review, not automatic escalation. |
| Invalid/expired login | Explicit auth error | Refresh once where valid, otherwise request sign-in. |
| Revoked/disconnected app | Explicit access-revoked error | Discard session and stop protected operations. |
| Network failure | Explicit network error | Show retry action; do not convert to `null` or `false`. |
| Malformed request / server policy denial | Explicit validation/access error | Correct request or route to authorised administrator. |

`Boolean?`/`boolean | null` has three meaningful states: `true`, `false`, and `null`. Never treat `null` as `false` for age gating, verification, employment, membership, or eligibility.

### 3.3 Recommended type contracts

The following TypeScript-style contracts describe desired cross-platform semantics; they do **not** imply a production TypeScript SDK export.

```ts
type Nullable<T> = T | null;
type CountryCode = string;       // Prefer ISO 3166-1 alpha-2, or configured legacy OTHER
type LanguageCode = string;      // Define ISO language-code policy in backend schema
type UserName = [firstName: string | null, lastName: string | null];
type PhoneParts = [countryCode: string, nationalNumber: string];
type AddressParts = [
  premises: string | null,
  street: string | null,
  locality: string | null,
  region: string | null,
  country: string | null,
  postalCode: string | null
];
type Bitmap = PlatformNativeBitmap | DecodedRgbaBitmap;
interface DecodedRgbaBitmap { width: number; height: number; pixels: Uint8Array; }
```

**Why phone numbers use strings:** Country calling codes and subscriber numbers are identifiers, not quantities. Integers remove leading zeroes, cannot preserve `+`, extensions or significant formatting, and can overflow numeric representations. The live documentation already returns `[country_code, phone_number]` as **string arrays**. Preserve the exact storage and normalisation rules documented by ONE.

**Why arrays preserve null slots:** A six-part address must retain positional meaning even when apartment or county is absent. Do not shift components to fill gaps. For new API versions, a named object is preferable to positional arrays, while the requested existing array API remains supported.

### 3.4 Input validation principles

- `APP_ID`: registered application identifier, not an arbitrary client-supplied namespace.
- `CLIENT_ID`: public OAuth client identifier; always resolve it server-side to the authenticated registration.
- `CUSTOM_URI_SCHEME`: registered callback scheme; cannot authorise revocation or disconnection by itself.
- `ORG_ID` and `PROJECT_ACCESS_ID`: opaque identifiers, validated server-side against authorised relationships.
- `UUIDC`: opaque identity handle scoped to a defined audience; never use an unverified client-supplied value as proof of identity.
- Keys: predefined variable names where declarations are required; validate type, size, nesting and ownership.
- Duration: strongly typed units; no ambiguous numbers without a duration unit.

---

## 4. Existing functions — user profile

All functions in this section are **existing — documented** in the reviewed native integration guide, subject to SDK/platform availability and live consent. The odd historical spelling of `Varified` is retained to match the exposed API.

### 4.1 Identity, avatar and name

| Function | Permission | Return | Behaviour |
|---|---|---|---|
| `one.auth.data.getAvatar()` | `avatar` | Platform bitmap or `null` | Returns a decoded ONE profile image; documented max 256 × 256 pixels. |
| `one.auth.data.getName()` | `first_name`, `last_name` | `[firstName, lastName]` or `null` | Returns fixed-position name components; missing individual components remain `null`. |
| `one.auth.data.getEmail()` | `email` | `string | null` | Returns permitted personal email. |
| `one.auth.data.getPhoneNumber()` | `phone` | `[countryCode, nationalNumber] | null` | String parts without coercion to integers. |
| `one.auth.data.getAddress()` | `address` | `AddressParts | null` | Six positions: premises, street, city, region, country, postal code. |
| `one.auth.data.getCountry()` | `address` | `string | null` | Country derived from saved home address; currently uses country code or `OTHER`. |
| `one.auth.data.getNationality()` | `nationality` | `string | null` | Nationality as permitted by scope and saved profile. |
| `one.auth.data.getCountryOfBirth()` | `country_of_birth` | `string | null` | Country of birth only; **not** exact birth date. |
| `one.auth.data.getLanguages()` | `languages` | `string[] | null` | User's saved language entries. |

**Bitmap platform mapping (documented):** Android `Bitmap`; iOS `UIImage`; macOS `NSImage`; browser `ImageBitmap`; Java `AvatarBitmap`; source-based runtimes may expose RGBA pixels and dimensions. Always adapt images using the platform UI layer; do not treat bitmaps as arbitrary file uploads.

### 4.2 Privacy-safe age and birthday checks

| Function | Permission | Return | Precise meaning |
|---|---|---|---|
| `one.auth.data.isUserTeen()` | `date_of_birth` | `boolean | null` | User is **13+**. This does **not** mean aged 13–17 only. |
| `one.auth.data.isUserLegal()` | `date_of_birth` | `boolean | null` | User is **18+**. This is an age-threshold result, not a legal capacity guarantee in every jurisdiction. |
| `one.auth.data.isUserAdult()` | `date_of_birth` | `boolean | null` | User is **25+**. The name is legacy; do not assume 18–24-year-olds are minors. |
| `one.auth.data.isUserAgeVarified()` | `date_of_birth` | `boolean | null` | ONE's identity-backed age-verification procedure passed. A self-entered DOB alone never marks this `true`. |
| `one.auth.data.isUserBirthday()` | `date_of_birth` | `boolean | null` | Calendar day matches user's birthday; current implementation uses **UTC**. |

**Hard privacy invariant:** No client profile helper, REST `userinfo` response, log, debug payload, analytics property, SDK cache, or exception detail may expose exact date of birth or exact age. The currently reviewed integration guide expressly describes threshold-only results; historical SDK versions must not be relied on to access raw DOB.

**Example — verified 18+ gate (illustrative Kotlin):**

```kotlin
// Execute on a worker/coroutine after successful sign-in.
val is18Plus: Boolean? = one.auth.data.isUserLegal()
val hasVerifiedAge: Boolean? = one.auth.data.isUserAgeVarified()

when {
    is18Plus == null || hasVerifiedAge == null -> showUnavailableAgeState()
    is18Plus && hasVerifiedAge -> openRestrictedFeature()
    else -> showEligibilityOrVerificationScreen()
}
```

The UI functions above are application-defined placeholders. `isUserAgeVarified()` may offer ONE's existing age-verification action on a known `false` result, depending on the platform/UI integration.

### 4.3 Contact verification

| Function | Permission | Return | Behaviour |
|---|---|---|---|
| `one.auth.data.isUserEmailVarified()` | `email` | `boolean | null` | `true` when saved personal email is verified. |
| `one.auth.data.isPhoneNumberVerified()` | `phone` | `boolean | null` | `true` when saved personal phone number is verified. |
| `one.auth.data.isWorkEmailVarified()` | `work_email` | `boolean | null` | `true` when saved work email is verified. |
| `one.auth.data.isWorkPhoneNumberVerified()` | `work_phone` | `boolean | null` | `true` when saved work phone is verified. |

An explicitly present **unverified** contact attribute returns `false`; an absent or withheld attribute returns `null`. A `true` verification state confirms ONE's verification mechanism, not perpetual ownership or suitability for any regulated communication.

### 4.4 Work profile

| Function | Permission | Return | Behaviour |
|---|---|---|---|
| `one.auth.data.getWorkEmail()` | `work_email` | `string | null` | Permitted work email. |
| `one.auth.data.getWorkPhoneNumber()` | `work_phone` | `[countryCode, nationalNumber] | null` | Work number as string components. |
| `one.auth.data.getWorkAddress()` | `work_address` | `AddressParts | null` | Six-position work location. |
| `one.auth.data.getWorkCountry()` | `work_address` | `string | null` | Country from work address. |

### 4.5 Missing-data and verification prompts

The existing ONE UI already supports missing-profile completion for **granted** fields, and supported platforms expose missing-data handlers. The account completion page is provided by ONE: host applications must not collect ONE account passwords, impersonate the hosted consent flow, or bypass denial.

```text
App requests a field
   |
   +-- Not granted -----------------> null; no missing-data prompt
   |
   +-- Granted but missing ---------> null + optional ONE completion prompt
   |                                      |
   |                                      +--> User updates ONE profile
   |                                             |
   |                                             +--> Refresh profile / retry
   |
   +-- Granted and present ---------> value
   |
   +-- Session, server, network failure -> explicit error
```

For identity verification, ONE may offer a verification prompt linking to the account portal. The documented process includes trusted-ID and liveness/face-match checks; do not implement a fake local verification toggle.

---

## 5. Existing functions — encrypted application data

**Status:** **Existing — documented** (`one.data.set/get/rep/del`). Each entry belongs to the signed-in user and the registered application namespace and requires the applicable App data consent (`attributes`).

| Function | Return concept | Behaviour |
|---|---|---|
| `one.data.set("VARIABLE_NAME", VALUE)` | Success / error | Create or overwrite an application variable. |
| `one.data.get("VARIABLE_NAME")` | JSON-compatible value or `null` | Read an existing value; a missing key resolves to `null`. |
| `one.data.rep("VARIABLE_NAME", VALUE)` | Success / error | Replace/upsert a value; a non-null replacement is required by the native guide. |
| `one.data.del("VARIABLE_NAME")` | Success / error | Remove one variable from this user's application namespace. |

The currently reviewed integration guide also describes `list` and `remove` aliases in some supported SDK contexts. Do not assume that a JSON `null` stored value can always be distinguished from a missing key using `get` alone; prefer explicit existence metadata if that distinction is required.

### 5.1 Storage guarantees and limits (documented)

- Encryption at rest: **AES-256-GCM**, with application-derived keys.
- Compression: **DEFLATE** before encryption.
- Accepted content: JSON-compatible strings, numbers, booleans, `null`, arrays and objects.
- Maximum uncompressed value: **16 KiB** of UTF-8 JSON.
- Maximum write batch: **100 keys**.
- Maximum nesting: **20 levels**.
- Maximum request body: **1.7 MB**.
- App isolation: one application cannot read another application's namespace.
- File uploads, media blobs, data URLs, binary byte arrays and disguised files are not supported in app data.

App-variable definitions and type checking remain server-owned. `set()` or `rep()` cannot evade declaration constraints or grant boundaries.

### 5.2 Example (documented API shape; illustrative Kotlin)

```kotlin
// Execute after sign-in and outside the Android main thread.
one.data.set("theme", "dark")
val theme = one.data.get("theme")  // "dark" or null
one.data.rep("theme", "light")
one.data.del("theme")
```

**Implementation recommendation:** Treat `set` and `rep` as idempotent upserts for the same key/value, but document actual concurrency and conditional-write semantics before promising optimistic locking. Do not assume cross-request transactions or atomic increments.

---

## 6. Proposed functions — registered application metadata

**Status:** **Proposed.** Public branding already appears in the documented SDK login view; the following explicit accessor API is not verified as released.

| Function | Suggested type | Contract |
|---|---|---|
| `one.app.data.appDisplayName()` | `string | null` | Registered display name, normalised for safe presentation. |
| `one.app.data.appDescription()` | `string | null` | Current public description of the calling application. |
| `one.app.data.appWebsite()` | `string | null` | Verified/public HTTPS website URL, if configured. |
| `one.app.data.appIcon()` | `Bitmap | null` | Fetched/decoded public app icon, platform-native representation. |

### 6.1 Behaviour

1. The SDK resolves its **authenticated/registered** APP_ID rather than accepting a caller-provided identity override.
2. The server returns only public metadata explicitly configured by the application owner.
3. Metadata may be cached with a short TTL and invalidated on app-settings changes; do not claim instant cross-device cache coherency.
4. Missing metadata returns `null`; network errors still raise typed errors.
5. Applications must not use display name, description, icon or website as proof of a legal entity or security authority.
6. The SDK should sanitise URLs and text before rendering. Load remote artwork only from approved HTTPS locations with bounded bytes, dimensions and redirects.

**Suggested metadata response:**

```json
{
  "app_id": "com.example.product",
  "display_name": "Example Product",
  "description": "A privacy-aware example application.",
  "website": "https://example.com",
  "icon_url": "https://example.com/icon.png",
  "updated_at": "2026-10-23T00:00:00Z"
}
```

The above is a **proposed payload**, not an existing ONE endpoint response.

---

## 7. Proposed functions — versioned legal documents and user agreements

**Status:** **Proposed.** Design these APIs as a distinct document-consent service, not as regular application data. Consent to terms is separate from granting personal-data scopes.

### 7.1 Exact requested API

```text
one.app.data.docs.isAgreed(type, slug, version)
one.app.data.docs.get(type, slug, version)
one.app.data.docs.agreeTo(type, slug, version)
```

### 7.2 Document types and versioning

```ts
enum docType {
  TERMS   = "TERMS",
  POLICY  = "POLICY",
  LICENCE = "LICENCE",
  OTHER   = "OTHER"
}

type DocumentVersion = string; // "1.0", "1.01", "1.001" (exact identifiers)
```

**Do not represent versions as floating point.** `1.0`, `1.00`, `1.01`, and `1.001` may be different publication identifiers, while floating-point conversion can erase trailing zeroes or introduce rounding. Normalise and validate versions server-side using an agreed string format; avoid numeric comparison of document revisions.

### 7.3 Operations

| Function | Suggested return | Contract |
|---|---|---|
| `docs.get(type, slug, version)` | `LegalDocument | null` | Retrieve an **immutable published version**. A missing document may return `null`; unauthorised/private docs return explicit access errors. |
| `docs.isAgreed(type, slug, version)` | `boolean | null` | `true` if the authenticated user has an active, verifiable acceptance of this exact version; `false` if definitively not accepted; `null` if the identity/acceptance state is unavailable. |
| `docs.agreeTo(type, slug, version)` | `AgreementReceipt` | Explicitly record an authenticated user's informed acceptance of an exact published document. |

### 7.4 Recommended document and receipt models

```ts
interface LegalDocument {
  appId: string;
  type: docType;
  slug: string;
  version: DocumentVersion;
  title: string;
  locale: string;
  contentFormat: "markdown" | "text" | "html";
  content: string;
  sha256: string;          // Digest of canonical published bytes
  effectiveAt: string;    // ISO 8601
  publishedAt: string;    // ISO 8601
  status: "published" | "superseded" | "withdrawn";
}

interface AgreementReceipt {
  receiptId: string;
  appId: string;
  documentType: docType;
  documentSlug: string;
  documentVersion: DocumentVersion;
  documentSha256: string;
  acceptedAt: string;    // Server timestamp, ISO 8601
  subject: string;       // Opaque user subject, not raw personal identity
  consentMethod: "one_hosted" | "verified_app_flow";
  locale: string;
}
```

### 7.5 Agreement lifecycle

1. Application owner creates and publishes a document version using an authenticated administrative publishing workflow.
2. ONE stores the immutable publication and content digest; an edited draft must be published as a **new** version.
3. SDK retrieves the exact version and presents its complete contents or a trusted rendering.
4. The user performs an explicit affirmative action, e.g. selecting **Agree and continue**. Passive page views or prechecked boxes must not count as consent.
5. Server verifies identity, publisher, app ownership, document state and digest before issuing the receipt.
6. `isAgreed` checks the stored receipt for that **specific** `(app_id, type, slug, version, digest)` tuple.
7. Later document versions do not silently inherit older acceptance. Define a re-acceptance policy explicitly, with jurisdiction-specific legal review if needed.
8. For privacy policy acknowledgements, do not incorrectly equate contractual acknowledgement with GDPR consent for processing. Track the legal basis separately.

### 7.6 Example (pseudocode, not a currently shipped SDK call)

```ts
const type = docType.TERMS;
const slug = "app-terms";
const version = "1.001";
const doc = await one.app.data.docs.get(type, slug, version);
if (!doc) throw new Error("Requested terms document is unavailable");

renderLegalDocument(doc); // Must be fully accessible and readable.

// Invoke ONLY after the user intentionally accepts the displayed document:
async function onUserPressedAgree() {
  const receipt = await one.app.data.docs.agreeTo(type, slug, version);
  await persistReceiptReference(receipt.receiptId); // Optional app-owned reference
}
```

**Proposed backend endpoints (not currently documented):**

```http
GET  /apps/me/metadata
GET  /apps/me/documents/{type}/{slug}/versions/{version}
GET  /apps/me/documents/{type}/{slug}/versions/{version}/agreement
POST /apps/me/documents/{type}/{slug}/versions/{version}/agreement
```

Never send untrusted raw HTML directly to a WebView without sanitisation and strict script/content security controls.

---

## 8. Proposed functions — extended user profile

| Function | Suggested return | Contract and access policy |
|---|---|---|
| `one.auth.data.UUIDC()` | `string | null` | Unique opaque user identification code; prefer app- or organisation-scoped pseudonymous identity rather than a globally correlatable identifier. |
| `one.auth.data.userGender()` | `string | null` | Self-described optional gender attribute; return only when explicitly requested and granted. Do not infer it. |
| `one.auth.data.getLanguages.primary()` | `string | null` | User-selected primary language from their saved preferences, subject to languages scope. |
| `one.auth.data.isOrgEnroled(ORG_ID, PROJECT_ACCESS_ID, UUIDC)` | `boolean | null` | Check active organisation **and** specified project enrollment through the server; do not trust the supplied UUIDC alone. |
| `one.auth.data.getOrgInfo(ORG_ID)` | `PublicOrgInfo | null` | Read an explicitly public, published organisation profile. |
| `one.auth.data.signOut()` | Completion / error | Proposed alias for documented `one.auth.signOut()`; clears the current local session only. |
| `one.auth.data.disconnectProfile(CLIENT_ID, APP_ID, CUSTOM_URI_SCHEME)` | `DisconnectResult` | Proposed account-connection revocation, distinct from local sign-out; requires strong server-side verification and user confirmation. |

### 8.1 `UUIDC()` — user identity safety

**Problem:** A globally stable identifier shared across unrelated applications enables unwanted cross-app tracking. Current ONE identity tooling already documents an opaque stable `sub` for its authentication flow.

**Recommended:** Make UUIDC an opaque **pairwise** identifier derived from the authenticated subject and authorised audience (e.g. app or organisation), or explicitly document where it matches an existing `sub`. It must not contain an email, phone, DOB, national ID or reversible personal-data component.

**Rules:**

- A client cannot ask the server to impersonate an arbitrary UUIDC.
- The server determines the currently signed-in user from the token/session.
- Org access checks must compare the supplied handle with that authenticated identity, or require privileged delegated access.
- Reject enumeration, excessive queries and cross-tenant lookups.
- Never log UUIDC in third-party analytics as a cross-service tracking key.

### 8.2 `userGender()`

Gender can be sensitive personal data in context. Make collection optional, purpose-specific and expressly grantable. Recommended values include a user-specified string/controlled vocabulary with a privacy-preserving **prefer not to say** state. Do not infer gender from name, photos or identity-document markers. Avoid mixing `null` (not granted/missing) with a deliberately selected privacy preference.

### 8.3 `getLanguages.primary()`

The requested syntax uses `.primary()` as a submethod, which means `getLanguages` is a callable object as well as a function in some languages. Java/Kotlin cannot implement that ergonomically without an intermediate facade. Recommended cross-platform alias:

```text
Requested compatibility syntax: one.auth.data.getLanguages.primary()
Recommended standard syntax:    one.auth.data.getPrimaryLanguage()
```

If the requested syntax is essential, implement a language-specific `getLanguages` facade; otherwise prefer `getPrimaryLanguage()` to avoid a brittle or impossible cross-platform binding. The primary language must be selected explicitly or according to a declared fallback policy, never guessed silently from nationality.

---

## 9. Proposed functions — organisation membership and public organisations

### 9.1 Membership eligibility

**Exact requested signature:**

```text
one.auth.data.isOrgEnroled(ORG_ID, PROJECT_ACCESS_ID, UUIDC)
```

**Recommended policy:**

1. Verify that `ORG_ID` exists and the project belongs to it.
2. Resolve authenticated user identity server-side; ensure the UUIDC argument is the same user unless caller has a dedicated administrative permission.
3. Evaluate current organisation membership, membership status, project binding, expiry and suspension.
4. Return `true` only if **all** required checks pass at the time of evaluation.
5. Return `false` for a definitive non-membership or absent project entitlement that the caller is authorised to check.
6. Return `null` only for unavailable/withheld identity context; reject unauthorised third-party enumeration with explicit errors.
7. Enforce all protected project actions again on the backend. A UI-level `true` is not an access token.

**Potential improved interface:**

```ts
interface MembershipAssessment {
  enrolled: boolean;
  orgId: string;
  projectAccessId: string;
  effectivePermissions?: string[];
  expiresAt?: string | null;
  checkedAt: string;
}
```

A richer response should require appropriate scope and must not reveal private organisation membership to arbitrary applications.

### 9.2 Organisation public information

```text
one.auth.data.getOrgInfo(ORG_ID)
```

Recommended response:

```ts
interface PublicOrgInfo {
  id: string;
  name: string;
  displayName?: string;
  description?: string;
  website?: string;
  logoUrl?: string;
  verified?: boolean;
  publicProjects?: Array<{ id: string; title: string }>;
  updatedAt: string;
}
```

Only administrator-approved **public** fields may be returned. Never expose employee rosters, internal project IDs, ownership information, billing configuration or unlisted membership from a public organisation lookup.

---

## 10. Proposed functions — moderation and bans

### 10.1 Requested function

```text
one.auth.data.setBan(duration, date, reason)
```

**Security classification:** **Privileged administrative mutation.** This method must **not** be callable by every signed-in app/user. Its existence under `auth.data` should be a compatibility shim; the preferred long-term interface is a server-side `one.admin.users.setBan(...)` API with delegated moderation scope, tenant separation and audit logging.

### 10.2 Duration and permanence

You requested a permanent ban when the duration in minutes exceeds 100 days.

```text
100 days = 100 × 24 × 60 = 144,000 minutes

if durationMinutes > 144000:
    banKind = PERMANENT
else:
    banKind = TEMPORARY
```

**Boundary:** Exactly `144000` minutes remains temporary under your stated **greater-than** condition. If you intend 100 days or longer, use `>=` and update the contract.

### 10.3 Recommended validated ban command

```ts
type BanKind = "TEMPORARY" | "PERMANENT";
interface BanRequest {
  targetSubject: string;           // Required: authenticated/admin-resolved user identifier
  appId: string;                   // App-scoped by default
  durationMinutes: number;         // Integer >= 1
  effectiveAt?: string;            // ISO 8601; omission means server now
  reasonCode: string;              // Stable policy category
  reason: string;                  // Moderation explanation
  evidenceReference?: string;      // Internal controlled reference, not raw evidence
  idempotencyKey: string;
}
interface BanRecord {
  id: string;
  kind: BanKind;
  effectiveAt: string;
  expiresAt: string | null;
  reason: string;
  createdBy: string;
  createdAt: string;
}
```

**Signature problem to resolve:** `setBan(duration, date, reason)` omits the target user. Under the proposed alias, it can only target the **currently authenticated user**, which is generally unsuitable for moderation. Do not allow the calling application to mutate arbitrary accounts without an explicit, server-verified subject and scope. A more useful privileged method is `setBan(targetSubject, durationMinutes, effectiveAt, reason)`.

### 10.4 Enforcement requirements

- Require administrator service authentication, a moderation role and app/tenant-scoped authorisation.
- **Default to app-scoped bans**, not global ONE account bans. Platform-wide enforcement is a separate high-trust workflow.
- Verify policy, reason, target, duration and effective date server-side.
- Store server-computed expiry; clients cannot decide they are unbanned by changing device clocks.
- Apply denial to protected ONE-facing resources for the relevant app according to its moderation policy.
- Record immutable audit evidence: actor, action, reason code, timestamp, target scope and previous/new state.
- Provide appeal/review and unban administrative processes, with retention according to applicable policy.
- Rate-limit requests, protect against abusive moderators, and avoid disclosing sensitive moderation evidence in public API errors.

**Existing baseline:** The reviewed guide describes app-scoped bans administered from the Client **Users** tab and exposed moderation error details. It does **not** establish that `one.auth.data.setBan()` already exists.

---

## 11. Proposed account lifecycle — sign-out and disconnect

### 11.1 Sign-out

```text
Proposed alias: one.auth.data.signOut()
Current API:   one.auth.signOut()
```

Current documented behaviour: clear the local app's ONE session. It does **not** guarantee sign-out from the system browser, revoke refresh tokens remotely or remove the application's user-data grant.

**Required client handling:** Clear local tokens, personally identifying view models, cached sensitive display state and active protected requests. If asynchronous sign-out is supported, complete those steps before reporting success.

### 11.2 Disconnect the connected profile

```text
one.auth.data.disconnectProfile(CLIENT_ID, APP_ID, CUSTOM_URI_SCHEME)
```

**Status:** **Proposed.** This is a materially stronger operation than sign-out and needs a backend revocation contract.

**Proposed sequence:**

1. Require a live, authenticated user session and a deliberate action to disconnect this app.
2. Resolve `CLIENT_ID` and `APP_ID` from server-side registration; reject any mismatch with current caller identity.
3. Validate the callback scheme **only for navigation**, never as proof of consent or ownership.
4. Present ONE-hosted confirmation specifying which app will lose access and what happens to app-specific stored data.
5. Revoke the appropriate application's grants and refresh-token chain on the server; invalidate access at protected endpoints.
6. Clear SDK local session/tokens, unsubscribe push or websocket streams where applicable and purge sensitive caches.
7. Return a non-sensitive receipt/status. Data deletion or retention must follow a **separate explicitly documented retention policy**; disconnection must not be silently treated as irreversible deletion without notice.

**Recommended return:**

```ts
interface DisconnectResult {
  appId: string;
  disconnected: boolean;
  effectiveAt: string;
  receiptId: string;
  dataDisposition: "retained_per_policy" | "deletion_requested" | "deleted";
}
```

**Important:** A disconnected token must not be able to call the same method to obtain new access. This is an account-connection lifecycle workflow, not an OAuth callback trick.

---

## 12. Permissions and data-minimisation matrix

This matrix identifies baseline documented profile scopes and **proposed** extensions. Registration, consent-screen field names and backend enforcement must be updated together.

| Data or operation | Scope / gate | Null on missing/denied? | Completion prompt? | Notes |
|---|---|---|---|---|
| Name | `first_name`, `last_name` | Yes | If granted but missing | Fixed positions. |
| Avatar | `avatar` | Yes | If granted but missing | Decoded bitmap. |
| Email / email verified | `email` | Yes | If granted but missing | Verification predicate returns `false` for known unverified. |
| Personal phone / verified | `phone` | Yes | If granted but missing | String components. |
| Home address / country | `address` | Yes | If granted but missing | Same scope, country derived. |
| DOB-derived age and birthday flags | `date_of_birth` | Yes | If granted but missing | **Never expose raw DOB.** |
| Work email / verified | `work_email` | Yes | If granted but missing | Distinct from personal scope. |
| Work phone / verified | `work_phone` | Yes | If granted but missing | Distinct from personal scope. |
| Work address / country | `work_address` | Yes | If granted but missing | Country derived. |
| Nationality | `nationality` | Yes | If granted but missing | Distinct from country of birth. |
| Country of birth | `country_of_birth` | Yes | If granted but missing | Never exact DOB. |
| Languages | `languages` | Yes | If granted but missing | Primary language requires a defined profile field (**proposed**). |
| Gender | `gender` (**proposed**) | Yes | If granted but missing | Optional and purpose-specific. |
| App data | `attributes` / App data | Key missing returns null | No profile prompt for missing key | Requires app variable declarations, where configured. |
| Long-lived session | `offline` | N/A | OAuth user decision | Refresh tokens rotate when used. |
| Public app metadata | Registration/visibility policy (**proposed**) | Yes | No | No account profile permission needed for public branding. |
| Legal-document retrieval | Published/visibility policy (**proposed**) | Not found → null | No | Receipt lookup requires authenticated subject. |
| Agreement receipt write | Authenticated user action (**proposed**) | No | User intentionally accepts | Not interchangeable with data-processing consent. |
| Organisation membership | `org.membership.read` (**proposed**) | Only for unavailable own identity | No | No third-party enrollment enumeration. |
| Organisation info | Public record (**proposed**) | Not found → null | No | Public-only attributes. |
| Ban assignment | `moderation.ban.write` (**proposed**) | No | No | Privileged backend-only gate. |
| Disconnect profile | User-authenticated revocation (**proposed**) | No | ONE-hosted confirmation | Server-side revocation. |

**Registration rule:** Request only the scope needed for a working user feature, clearly disclose the use, and allow optional fields to be withheld without blocking unrelated functionality.

---

## 13. Error model and recovery

Use the existing `ExOneException` style or platform-equivalent exceptions for transport/auth/validation failures. Extend it with stable machine-readable codes rather than parsing error-message text.

| Code (existing or proposed) | Meaning | Suggested handling |
|---|---|---|
| `invalid_grant` | Invalid/used authorization code or refresh grant | Restart login; never replay consumed code. |
| `session_expired` | No refreshable session | Return to ONE sign-in. |
| `access_revoked` | User disconnected or scope revoked | Clear sensitive local state. |
| `insufficient_scope` | Application lacks required grant | Explain limitation; route to standard permission process. |
| `network_error` | Transport unavailable | Retry with bounded backoff and cancellation. |
| `invalid_argument` (**proposed**) | Invalid identifier, duration, version or input | Correct developer call; do not retry blindly. |
| `document_not_published` (**proposed**) | Requested legal version unavailable for acceptance | Display unavailability; do not record agreement. |
| `agreement_conflict` (**proposed**) | Version/digest mismatched or superseded | Fetch and display current published version. |
| `org_access_denied` (**proposed**) | Caller cannot inspect membership | Show access denied; do not leak membership. |
| `moderation_forbidden` (**proposed**) | Caller lacks administrative privileges | Disable admin control; audit attempt. |
| `ban_active` (**proposed code**) | Access blocked by policy | Show permitted reason/expiry and appeal path. |
| `disconnect_requires_confirmation` (**proposed**) | No validated user confirmation | Open ONE-hosted confirmation. |

**HTTP baseline:** The reviewed API reference associates 400 with invalid input, 401 with invalid session, 403 with missing/revoked access, 413 with oversized requests and 415 with non-JSON content.

**Operational requirements:** Never convert 401, 403, timeout, rate limiting, backend policy errors or corruption to `null`. Avoid infinite sign-in loops; apply bounded retries and idempotency keys for sensitive mutations.

---

## 14. Cross-platform implementation patterns

### 14.1 Android / Kotlin

The reviewed native guide shows SDK `3.2.0` and use of `ExOneAndroid`. The current working Kotlin/Android install pattern is:

```kotlin
// settings.gradle.kts
maven { url = uri("https://client.extremextechnology.com/repo") }

// app/build.gradle.kts — inside dependencies { ... }
implementation("com.extremex.one:exone-android:3.2.0")
```

```kotlin
import com.extremex.one.android.ExOneAndroid

val one = ExOneAndroid(applicationContext, "APP_ID", "CLIENT_ID")

// Show ONE's native sign-in component and handle the callback through
// the documented Activity lifecycle. Never call protected APIs before auth.
```

Native callbacks and sign-in wiring depend on the host Activity. Register `APP_ID://callback` appropriately in the Android manifest and handle both initial and subsequent callback Intents. The official guide documents attaching the client to recreated activities where necessary. Blocking profile/data reads belong on worker threads; async callbacks touching UI must switch to the main thread.

### 14.2 Kotlin Multiplatform

Keep domain policy and nullable result interpretation in `commonMain`, but delegate identity/image representations and browser/callback handling to platform-specific adapters. Do not assume Java `Bitmap` is available in common Kotlin code. Use an immutable shared decoded-image structure or `expect/actual` platform return types.

```kotlin
// Conceptual shared interface — not a shipped SDK declaration.
interface OneProfileReader {
    suspend fun is18Plus(): Boolean?
    suspend fun isAgeVerified(): Boolean?
    suspend fun getNameParts(): List<String?>?
}
```

### 14.3 Web / Next.js

Use the official browser sign-in mechanism and an authenticated server/session model. Keep token exchange, any confidential credentials, privileged moderation credentials and organisation administration on the backend. Avoid putting broad bearer tokens or personal profile payloads in publicly rendered HTML or client logs.

```ts
// Conceptual call flow; docs/agreement methods require implementation.
async function loadFeatureEligibility(one: OneClient) {
  const legal = await one.auth.data.isUserLegal();
  const verified = await one.auth.data.isUserAgeVarified();
  if (legal === null || verified === null) return "unknown";
  return legal && verified ? "eligible" : "ineligible";
}
```

`OneClient` above is an illustrative application type; adapt to the actual JS SDK export and callback/promise form in your installed version.

### 14.4 iOS / Swift

Use `ASWebAuthenticationSession` for sign-in and register the callback URI scheme/universal link described by ONE. Convert optional NSNumber/bool results carefully so `nil` remains unknown. Present age-completion and legal-agreement UIs in accessible sheets; do not infer identity from device settings.

### 14.5 React Native / Flutter / desktop

Use the ONE-supported source module or native bridge for the target platform, an external system browser for OAuth and a callback handler that validates state and PKCE. Images must use the platform-appropriate decoded representation. For headless applications, forward missing-data completion links to an authenticated UI rather than opening a server-side browser.

**Feature-parity rule:** A method should not be presented as universally supported merely because the TypeScript/Kotlin signature appears in this specification. Track builds and actual runtime tests platform by platform.

---

## 15. Worked integration scenarios

### 15.1 Profile display with progressive completion

1. Authenticate with ONE.
2. Request `first_name`, `last_name`, `avatar` and any optional contact scopes with stated reasons.
3. Call `getName()` and `getAvatar()` after sign-in.
4. If a granted profile field is missing, offer the existing ONE completion route; do not demand access to an ungranted optional field.
5. Retry on return, after current consent is confirmed.
6. Render partial information safely (e.g. first name only) rather than failing the whole screen.

### 15.2 Age-restricted experience

```text
isUserLegal() == true AND isUserAgeVarified() == true
     -> eligible for a verified-18+ feature (subject to other requirements)

One false, other known
     -> not yet eligible under this rule; offer ONE verification where appropriate

Either null
     -> eligibility unknown; keep restricted functionality inaccessible
```

Age threshold alone must never substitute for any independently required regional age-assurance, licensing or regulatory requirement.

### 15.3 Persisting user settings

```kotlin
one.data.set("appearance", "system")
val appearance = one.data.get("appearance")
one.data.rep("appearance", "dark")
```

Use platform-local storage for device-only or offline-only settings where server synchronisation is unnecessary. Do not store passwords, OAuth client secrets or oversized files in app data.

### 15.4 App terms re-acceptance (**proposed**)

1. Product team publishes `TERMS/app-terms/1.001` immutably.
2. App fetches document and verifies success.
3. It checks the user's receipt for **exactly** `1.001`.
4. If `false`, display the full new text and explain differences where relevant.
5. Only the user's active confirmation invokes `agreeTo`.
6. Backend records a verifiable receipt; app proceeds.
7. If `null` or network failure, do not assert acceptance. Apply an explicit, legally reviewed offline policy.

### 15.5 Organisation-gated project access (**proposed**)

1. Authenticated user enters an org-bound feature.
2. Client requests an eligibility check for the **current** user and the exact project.
3. ONE verifies org enrollment and project membership server-side.
4. Client may show eligible UI on `true`.
5. Every subsequent protected operation rechecks authorisation server-side; a cached boolean does not confer access.

### 15.6 Administrative ban (**proposed**)

1. Authenticated and authorised moderator selects a user and an app scope.
2. Server validates the request, including target identity, duration, reason and moderation privileges.
3. More than **144000 minutes** selects `PERMANENT`; otherwise compute server-side expiry.
4. Server records a policy-bound ban and audit trail; middleware blocks affected operations.
5. User sees the permitted reason/expiry and appeal route. Client is never trusted to implement the restriction alone.

---

## 16. Suggested SDK facade evolution

To preserve existing calls while keeping authority boundaries clear:

```text
one
├── auth
│   ├── signOut()                             [EXISTING]
│   └── data
│       ├── getAvatar()                      [EXISTING]
│       ├── getName()                        [EXISTING]
│       ├── isUserTeen() / isUserLegal()     [EXISTING]
│       ├── isUserAdult()                    [EXISTING]
│       ├── isUserAgeVarified()              [EXISTING]
│       ├── isUserBirthday()                 [EXISTING]
│       ├── contact, address, language...    [EXISTING]
│       ├── UUIDC()                          [PROPOSED]
│       ├── userGender()                     [PROPOSED]
│       ├── getPrimaryLanguage()             [RECOMMENDED]
│       ├── getLanguages.primary()           [REQUESTED; platform adapter]
│       ├── isOrgEnroled(...)               [PROPOSED]
│       ├── getOrgInfo(...)                  [PROPOSED]
│       ├── signOut()                        [PROPOSED alias]
│       ├── disconnectProfile(...)          [PROPOSED]
│       └── setBan(...)                      [PROPOSED privileged alias]
├── app
│   └── data
│       ├── appDisplayName()                 [PROPOSED]
│       ├── appDescription()                 [PROPOSED]
│       ├── appWebsite()                     [PROPOSED]
│       ├── appIcon()                        [PROPOSED]
│       └── docs
│           ├── get(type,slug,version)       [PROPOSED]
│           ├── isAgreed(type,slug,version)  [PROPOSED]
│           └── agreeTo(type,slug,version)   [PROPOSED]
└── data
    ├── set(key,value)                     [EXISTING]
    ├── get(key)                           [EXISTING]
    ├── rep(key,value)                     [EXISTING]
    └── del(key)                           [EXISTING]
```

**Recommended follow-on:** Formalise a separate `one.admin` and `one.org` namespace in a future major release without abruptly removing legacy aliases.

---

## 17. Security, privacy and compliance engineering

### 17.1 Mandatory security properties

- Require **TLS** and verify remote hosts and certificate trust.
- Use OAuth PKCE on public clients; never bundle `client_secret` in APK, IPA, desktop binaries or JavaScript.
- Validate OAuth `state`, code lifetime, redirect URI and PKCE verifier; do not replay authorization codes.
- Store and rotate refresh tokens securely; replace the persisted token after each successful refresh.
- Revalidate scope, user identity, organisation membership and revocation server-side for protected operations.
- Treat callback URI schemes as routing identifiers, not authorisation credentials.
- Avoid logging profile data, DOB-derived internal values, tokens, full addresses, contact information and legal-agreement evidence in telemetry.
- Apply rate limits and audit logging to privileged actions and agreement receipts.
- Isolate per-user/per-app storage namespaces.
- Prevent unsafe HTML/script execution in document rendering.
- Provide accessible consent and missing-data completion experiences.

### 17.2 Privacy controls

- **Date-of-birth minimisation:** never return exact DOB or age from this API.
- **Purpose limitation:** request and retain only fields necessary for features.
- **User choice:** distinguish missing data from denied consent, and avoid repeated prompts after denial.
- **Revocation:** ensure withdrawn permission blocks future protected reads even if cached data exists locally.
- **Sensitive demographics:** gender and nationality require appropriately justified access; no derived demographic inference.
- **Identity correlation:** pairwise/tenant-scoped UUIDC over global tracking IDs whenever possible.
- **Document auditability:** associate acceptance with immutable document digest, version and server time.
- **Legal caveat:** GDPR and other applicable laws can impose additional obligations; legal-document consent, data-processing consent and age verification are separate concepts.

### 17.3 Threat model checkpoints

| Threat | Control |
|---|---|
| Malicious app probes denied profile field | Server-enforced live consent; field omitted/null. |
| Compromised client submits someone else's UUIDC | Bind identity to session; reject forged targets. |
| Ordinary app submits `setBan` | Backend moderator-only permission gate. |
| App falsely marks a user age verified | ONE-owned identity verification state only. |
| Tampered terms content during acceptance | Immutable publication + digest and receipt validation. |
| Redirect scheme spoofing | PKCE, state, exact registered callback and external browser. |
| Refresh-token reuse | Rotation and revocation checks. |
| Stale offline membership entitlement | Recheck all protected actions on backend. |
| Untrusted document markup | Sanitised rendering, script disabled, content policy. |
| Network failures hidden as null | Typed errors and transparent UI recovery. |

---

## 18. Verification and quality-assurance matrix

| Test ID | Test case | Expected outcome |
|---|---|---|
| AUTH-01 | Normal browser sign-in | Validated callback creates session. |
| AUTH-02 | Modified `state` / PKCE mismatch | Authentication denied; no session. |
| AUTH-03 | Reuse consumed code | Rejected. |
| AUTH-04 | Rotated refresh token reused | Rejected, secure session recovery. |
| PROFILE-01 | Optional field denied | Relevant getter returns `null`, no coercive completion prompt. |
| PROFILE-02 | Granted field missing | `null` and ONE completion flow where supported. |
| PROFILE-03 | Value present but unverified | Relevant verification returns `false`. |
| PROFILE-04 | Exact DOB requested via SDK/REST | Never exposed. |
| PROFILE-05 | Age 12 / 13 / 17 / 18 / 24 / 25 | Correct 13+/18+/25+ threshold matrix. |
| PROFILE-06 | Birthday near UTC midnight | Behaviour matches documented UTC calendar. |
| PROFILE-07 | Phone with leading zeroes | Strings preserve all digits. |
| PROFILE-08 | Sparse address | Six slots preserved with `null` positions. |
| PROFILE-09 | Missing avatar / huge source image | `null` or safely bounded bitmap, no resource exhaustion. |
| DATA-01 | Set/get/replace/delete | Round-trip and deletion correct. |
| DATA-02 | Cross-user/app read | Denied or isolated. |
| DATA-03 | Invalid declared variable type | Explicit validation error. |
| DATA-04 | Oversized value/file-like payload | Correct rejection and no partial corrupt write. |
| DOC-01 | Exact `1.0` vs `1.001` | Different receipt keys. |
| DOC-02 | Accept without user action | Rejected. |
| DOC-03 | Tamper document after publish | Immutable digest check rejects mutation. |
| DOC-04 | Re-accept current version | Idempotent outcome with consistent receipt. |
| ORG-01 | Authenticated user is enrolled in org but not project | `false`. |
| ORG-02 | Client spoofs a different UUIDC | Denied without leaking membership. |
| ORG-03 | Revoked organisation membership | Protected operation denied. |
| BAN-01 | Duration = 144000 minutes | TEMPORARY under `>` rule. |
| BAN-02 | Duration = 144001 minutes | PERMANENT. |
| BAN-03 | Ordinary user invokes ban API | Forbidden; audited. |
| DISC-01 | Local `signOut` | Clears local session; consent not silently revoked. |
| DISC-02 | Confirmed disconnect | Grants revoked; protected calls fail; data retention policy respected. |
| NET-01 | Offline or timeout | Explicit network error, never eligibility `false`. |

**Release verification:** Run unit tests, integration tests, consent-revocation tests, security reviews and real-device testing on each supported SDK platform. Do not mark platform parity complete based only on shared source code compiling.

---

## 19. Delivery plan and acceptance criteria

### Phase 1 — Baseline consistency

- Freeze a canonical inventory of `3.2.0` exported SDK symbols per platform.
- Document null/error handling and keep DOB exposure prohibited at every layer.
- Align existing helpers and return types; retain spelling aliases where already shipped.
- Add shared contract tests for age thresholds, personal/work scope enforcement and app-data operations.

### Phase 2 — Public app metadata

- Implement secure public metadata read, safe icon rendering and cache invalidation.
- Add platform-specific decoded image adapters and accessibility fallbacks.
- Document precise availability and installation versions.

### Phase 3 — Immutable legal documents

- Implement document publication, exact string versions, content digests and per-user acceptance receipts.
- Provide audit export, supersession rules and failure recovery.
- Validate intentional user acceptance in each UI platform.

### Phase 4 — Extended profile and organisation APIs

- Define `gender` and selected-primary-language storage/permissions.
- Define UUIDC identity scope and org/project access checks.
- Implement anti-enumeration checks, organisation public profiles, membership cache policies and server-side enforcement.

### Phase 5 — Moderation and disconnection

- Design explicit privileged moderation principals, scopes, reason codes, review and audit workflows.
- Implement disconnect confirmation and grant/token revocation.
- Keep local sign-out and remote disconnect semantically distinct.

### Phase 6 — Publication and observability

- Publish versioned API reference, migration guides, SDK generated examples and release notes.
- Measure success/error/latency by operation without collecting personal content in logs.
- Complete security/privacy reviews and real-device/platform certification checks.

### Definition of done

A proposed method is considered **shipped** only when all are true: backend contract exists; access policy is enforced; SDK implementation is available in a published version; platform-specific types are validated; test cases pass; errors are documented; the main developer documentation is updated; and a migration/release note identifies its availability.

---

## 20. Developer quick reference

```text
// Existing user profile
one.auth.data.getAvatar()
one.auth.data.getName()
one.auth.data.isUserTeen()                  // 13+
one.auth.data.isUserLegal()                 // 18+
one.auth.data.isUserAdult()                 // 25+
one.auth.data.isUserAgeVarified()           // ONE identity-verified age
one.auth.data.isUserBirthday()              // current UTC birthday match
one.auth.data.isUserEmailVarified()
one.auth.data.isPhoneNumberVerified()
one.auth.data.getEmail()
one.auth.data.getPhoneNumber()              // [callingCode, number] strings
one.auth.data.getAddress()                  // 6-part address
one.auth.data.getCountry()
one.auth.data.getWorkEmail()
one.auth.data.getWorkPhoneNumber()
one.auth.data.isWorkEmailVarified()
one.auth.data.isWorkPhoneNumberVerified()
one.auth.data.getNationality()
one.auth.data.getWorkAddress()
one.auth.data.getWorkCountry()
one.auth.data.getCountryOfBirth()
one.auth.data.getLanguages()

// Existing app data
one.data.set("KEY", VALUE)
one.data.get("KEY")
one.data.rep("KEY", NON_NULL_VALUE)
one.data.del("KEY")

// Existing session method
one.auth.signOut()

// Proposed public app info
one.app.data.appDisplayName()
one.app.data.appDescription()
one.app.data.appWebsite()
one.app.data.appIcon()

// Proposed legal-doc consent
one.app.data.docs.get(docType.TERMS, "app-terms", "1.001")
one.app.data.docs.isAgreed(docType.TERMS, "app-terms", "1.001")
one.app.data.docs.agreeTo(docType.TERMS, "app-terms", "1.001")

// Proposed profile and org methods
one.auth.data.UUIDC()
one.auth.data.userGender()
one.auth.data.getLanguages.primary()       // requested; binding design needed
one.auth.data.getPrimaryLanguage()          // recommended cross-platform alias
one.auth.data.isOrgEnroled(ORG_ID, PROJECT_ACCESS_ID, UUIDC)
one.auth.data.getOrgInfo(ORG_ID)

// Proposed account lifecycle and privileged moderation
one.auth.data.signOut()                     // forwarding alias
one.auth.data.disconnectProfile(CLIENT_ID, APP_ID, CUSTOM_URI_SCHEME)
one.auth.data.setBan(durationMinutes, date, reason) // privileged only; signature needs target resolution
```

---

## 21. Canonical references

- **ExtremeX ONE Client Integration Guide:** https://client.extremextechnology.com/docs — reviewed 23 October 2026; baseline SDK 3.2.0 and current behaviour for native profile helpers, age checks, app data, login/callback and missing-data prompts.
- **ExtremeX ONE account:** https://one.extremextechnology.com/account — profile completion and age-verification destination referenced in the live guide.
- **OAuth 2.0 for Native Apps:** RFC 8252 — https://www.rfc-editor.org/rfc/rfc8252
- **Proof Key for Code Exchange (PKCE):** RFC 7636 — https://www.rfc-editor.org/rfc/rfc7636

### Final contract notice

This document is an **advanced integration specification and implementation handoff**, not a claim that all proposed APIs already exist. Sections explicitly tagged **Existing — documented** reflect behaviour reviewed from the public documentation. Sections tagged **Proposed** or **Recommended** are design requirements for future ExtremeX ONE SDK and backend releases. Production consumers must use only methods confirmed by their installed SDK/API version.