User Stories — FlexGalaxy.AI Frontend Applications

This document describes user stories for all frontend applications across the FlexGalaxy.AI platform, organized by persona.

Personas

Persona

Role

Apps Used

Bob

Root user / Org admin

StartPoint, DartBoard, AdminCenter, Org Console, QuotaCenter, TraceBook, ThingIO, ThingLab

Alice

IDC user (member account)

StartPoint, DartBoard, AdminCenter, ThingHub, ThingIO, ThingLab, TraceBook

Charlie

Developer (tenant)

StartPoint, DartBoard, Dev2M, OTAForge, ThingHub, ThingIO, ThingLab, TraceBook

Diana

Platform operator

StarGate, SuperCrew, BoardingPass, DeckLoader

Eve

Content editor (platform)

StarGate, OrbitCast

Frank

Marketplace admin (platform)

StarGate, AlienBazaar


Part 1 — Tenant-Facing Applications


StartPoint (console.flexgalaxy.com/start/)

US-SP-1: Root User Login

As Bob (root user), I want to log in with my email and password on StartPoint, so that I can access my accounts.

Steps:

  1. Bob navigates to console.flexgalaxy.com/start/.

  2. StartPoint shows the account picker. Bob has no active session.

  3. Bob clicks "Sign in" and is redirected to Keycloak (flexgalaxy realm).

  4. Bob enters email bob@example.com and password, completes MFA.

  5. After successful auth, Bob is redirected back to StartPoint.

  6. StartPoint shows Bob's account(s). Bob clicks his account to enter.

  7. Bob is redirected to DartBoard (console.flexgalaxy.com/).

US-SP-2: IDC User Login via Realm Discovery

As Alice (IDC user), I want to log in using my corporate email, so that StartPoint discovers my IDC realm and authenticates me.

Steps:

  1. Alice navigates to console.flexgalaxy.com/start/.

  2. Alice enters her email alice@acme-corp.com.

  3. StartPoint performs realm discovery — finds that acme-corp.com maps to an IDC realm.

  4. Alice enters her IDC password inline (no redirect to Keycloak login page).

  5. After authentication, StartPoint shows Alice's member account.

  6. Alice clicks the account to enter and is redirected to DartBoard.

US-SP-3: Multi-Account Switching

As Bob, I want to switch between accounts without re-authenticating, so that I can manage multiple accounts efficiently.

Steps:

  1. Bob is logged into account A and working in AdminCenter.

  2. Bob clicks the avatar dropdown → "Switch Account".

  3. Bob is taken back to StartPoint's account list.

  4. Bob clicks account B.

  5. DartBoard loads with account B's context and permission-filtered app grid.

US-SP-4: Account Registration

As a new user, I want to register for a FlexGalaxy.AI account, so that I can start using the platform.

Steps:

  1. User navigates to StartPoint and clicks "Create Account".

  2. User enters email, receives OTP, and verifies.

  3. User fills in account name and description on the setup form.

  4. After submission, user is redirected to StartPoint.

  5. StartPoint shows a provisioning progress indicator while the account is being created asynchronously.

  6. Once provisioning completes, the account appears in the list and the user can enter.

US-SP-5: Provisioning Status Display

As a newly registered user, I want to see real-time provisioning progress, so that I know my account is being created and when it's ready.

Steps:

  1. After registration, StartPoint shows a progress card: "Setting up your account..."

  2. Progress steps update in real-time: Creating account → Configuring IAM → Ready.

  3. When complete, the card transitions to a clickable account entry.

  4. If provisioning fails, an error message and retry option are shown.


DartBoard (console.flexgalaxy.com/)

US-DB-1: Permission-Filtered App Grid

As Bob (org admin), I want to see only the apps I have permission to use, so that I'm not confused by irrelevant tools.

Steps:

  1. Bob enters his account from StartPoint.

  2. DartBoard loads and displays a grid of app tiles.

  3. Bob sees: AdminCenter, ThingHub, ThingIO, ThingLab, QuotaCenter, TraceBook (based on his OrgAdmin permission set).

  4. Dev2M and OTAForge tiles are not shown (Bob lacks Developer permission).

US-DB-2: Developer App Grid

As Charlie (developer), I want to see developer tools in my launcher, so that I can quickly access Dev2M and OTAForge.

Steps:

  1. Charlie logs in and enters his account.

  2. DartBoard shows: ThingHub, ThingIO, ThingLab, Dev2M, OTAForge, TraceBook (Developer permission set grants Dev2M and OTAForge; ThingHub, ThingIO, ThingLab, TraceBook are visible to all).

  3. Charlie clicks the Dev2M tile and is navigated to console.flexgalaxy.com/dev2m/.

US-DB-3: Language and Theme Toggle

As any user, I want to switch language and theme from DartBoard, so that the platform matches my preferences.

Steps:

  1. User clicks the avatar dropdown on DartBoard.

  2. User selects language (English / Chinese / Japanese) from the menu.

  3. All apps reload with the selected locale.

  4. User toggles dark/light theme; preference is persisted.


AdminCenter (console.flexgalaxy.com/admincenter/)

US-AC-1: View and Manage Users

As Bob (root user), I want to view and manage IAM users in my account, so that I can control who has access.

Steps:

  1. Bob navigates to AdminCenter → Users.

  2. The users list shows all IAM users with status (active/disabled).

  3. Bob clicks a user to view details: username, email, groups, attached policies.

  4. Bob edits the user's group membership and saves.

US-AC-2: Create IAM User

As Bob, I want to create a new IAM user for a team member, so that they can access the platform under my account.

Steps:

  1. Bob clicks "Create User" in AdminCenter → Users.

  2. Bob fills in username, email, and selects initial group membership.

  3. Bob reviews the new user's effective permissions (inherited from groups).

  4. Bob confirms and the user is created. An invitation email is sent.

US-AC-3: Create and Manage Groups

As Bob, I want to create groups and assign policies to them, so that I can manage permissions at scale.

Steps:

  1. Bob navigates to AdminCenter → Groups.

  2. Bob creates a group named "Developers".

  3. Bob attaches the "DeveloperAccess" managed policy to the group.

  4. Bob adds Alice and Charlie as members of the "Developers" group.

  5. Alice and Charlie now see Dev2M and OTAForge on their DartBoard.

US-AC-4: Create Custom Policy

As Bob, I want to create a custom IAM policy, so that I can define fine-grained access control.

Steps:

  1. Bob navigates to AdminCenter → Policies → Create Policy.

  2. The policy editor opens with a JSON/visual editor.

  3. Bob defines statements: Allow devices:Read* on resource frn:fgai:devices:*:*:device/*.

  4. Bob names the policy "ReadOnlyDevices" and saves.

  5. Bob attaches the policy to a group or user.

US-AC-5: View Account Audit Log

As Bob, I want to review IAM changes in my account, so that I can track who changed what.

Steps:

  1. Bob navigates to AdminCenter → Audit.

  2. The audit log shows recent events: user creation, policy changes, group modifications.

  3. Bob filters by date range and event type.

  4. Bob clicks an event to see full details (who, what, when, IP address).

US-AC-6: Account Settings

As Bob, I want to manage my account settings, so that I can update account name, description, and preferences.

Steps:

  1. Bob navigates to AdminCenter → Settings.

  2. Bob updates the account display name.

  3. Bob reviews account-level configuration options.

  4. Changes are saved and reflected across all apps.

US-AC-7: Set Permission Boundary on a User

As Bob (root user), I want to attach a permission boundary to an IAM user, so that the user's effective permissions can never exceed a defined ceiling — even if overly broad policies are attached later.

Steps:

  1. Bob navigates to AdminCenter → Users and clicks Alice's user record.

  2. Bob opens the "Permission boundary" section. It shows "No boundary set".

  3. Bob clicks "Set permission boundary".

  4. A policy picker dialog opens showing managed and custom policies. Bob selects the "DeveloperBoundary" managed policy (allows devices:*, licenses:Read*, ota:Read*).

  5. AdminCenter calls POST /api/v1/accounts/{accountId}/permission-boundaries with Alice's user ID and the selected policy ID.

  6. The section now displays:

    • Boundary policy name: "DeveloperBoundary"

    • Attached at: timestamp

    • A summary of allowed actions (expanded from the policy statements).

  7. Alice's effective permissions are immediately capped — even though her group grants AdministratorAccess, she can only perform actions that intersect with "DeveloperBoundary".

Acceptance criteria:

  • Only one boundary can be set per user. The "Set" button is hidden when a boundary already exists (replaced by "Change" and "Remove").

  • The caller must hold the iam:PermissionBoundary:Set permission.

  • Setting a boundary triggers a policy version increment so connected clients re-evaluate permissions.

  • An audit event iam:PermissionBoundary:Set is recorded in TraceBook.

US-AC-8: Remove Permission Boundary from a User

As Bob, I want to remove a permission boundary from a user, so that the user's permissions are no longer capped.

Steps:

  1. Bob navigates to AdminCenter → Users → Alice → Permission boundary.

  2. The section shows the current boundary: "SeniorDeveloperBoundary".

  3. Bob clicks "Remove boundary".

  4. A confirmation dialog warns: "Removing the boundary means Alice's effective permissions will be determined solely by attached policies and SCPs. Are you sure?"

  5. Bob confirms. AdminCenter calls DELETE /api/v1/accounts/{accountId}/permission-boundaries/{userId}.

  6. The section reverts to "No boundary set" with the "Set" button visible.

Acceptance criteria:

  • The caller must hold the iam:PermissionBoundary:Delete permission.

  • An audit event iam:PermissionBoundary:Delete is recorded.

  • Effective permissions are recalculated immediately.

US-AC-9: View Permission Boundary Effect (Dry-Run)

As Bob, I want to preview how a permission boundary would affect a user's effective permissions before attaching it, so that I don't accidentally lock the user out of critical actions.

Steps:

  1. Bob is in the "Set permission boundary" dialog for Alice.

  2. Bob selects "DeveloperBoundary" from the policy picker.

  3. Bob clicks "Preview effect".

  4. AdminCenter shows a side-by-side comparison:

    • Current effective permissions (identity policies ∩ SCPs).

    • Effective after boundary (identity policies ∩ SCPs ∩ boundary).

    • Permissions that would be removed (highlighted in red).

  5. Bob sees that iam:User:Create would be removed — this is expected.

  6. Bob proceeds to attach the boundary.

Acceptance criteria:

  • Preview is read-only and does not modify any state.

  • The preview accounts for all layers: identity-based policies, group membership, SCPs, and the proposed boundary.

  • Actions currently in use (active sessions) that would be revoked are flagged with a warning icon.

US-AC-10: Enforce Boundary When Creating Users (Delegation Guard)

As Bob, I want to require that a permission boundary is always attached when Alice creates new IAM users, so that Alice cannot create users with more permissions than intended — even if she has iam:User:Create and iam:Policy:Attach.

Steps:

  1. Bob navigates to AdminCenter → Policies → Create Policy.

  2. Bob creates a policy "DelegatedUserAdmin":

    {
      "statements": [
        {
          "effect": "Allow",
          "actions": ["iam:User:Create", "iam:User:Read*", "iam:Policy:Attach"],
          "resources": ["frn:fgai:iam:*:*:user/*"],
          "conditions": {
            "StringEquals": {
              "iam:PermissionsBoundary": "DeveloperBoundary"
            }
          }
        }
      ]
    }
    
  3. Bob attaches "DelegatedUserAdmin" to Alice and sets "DeveloperBoundary" as Alice's own boundary.

  4. Alice logs in and creates a new user Charlie in AdminCenter.

  5. AdminCenter enforces the condition — Alice must select "DeveloperBoundary" as Charlie's boundary during creation. The "Create User" button is disabled until a boundary is selected.

  6. Alice cannot select a boundary more permissive than her own.

  7. Charlie is created with "DeveloperBoundary" attached. Even if Alice later attaches AdministratorAccess to Charlie, his effective permissions remain capped.

Acceptance criteria:

  • The iam:PermissionsBoundary condition key is enforced in the PDP during iam:User:Create evaluation.

  • If the condition is present and no matching boundary is attached, the PDP returns DENY.

  • AdminCenter reads the caller's policy conditions and auto-populates the boundary requirement in the "Create User" form.

  • This pattern prevents privilege escalation: Alice cannot grant permissions she herself does not have.

US-AC-11: Create Service User and Access Key

As Bob (root user), I want to create a service user with static access key credentials, so that my applications can call FlexGalaxy APIs programmatically without a human login session.

Steps:

  1. Bob navigates to AdminCenter → Service Users → Users.

  2. Bob clicks "Create user" and fills in username (white-svc-api), email (svc-api@white-corp.test), first name, and last name.

  3. Bob clicks "Create". The user appears in the users table.

  4. Bob clicks the new user row to open the user detail page.

  5. Bob clicks the "Security Credentials" tab.

  6. Bob clicks "Create access key", enters a description ("CI/CD pipeline key"), and confirms.

  7. A dialog displays the access key ID (AKIA…) and secret key. Bob copies or downloads the CSV. The secret key is shown only once.

  8. The credentials table now shows the key with status "Active", description, creation date, and "Last used: Never".

Acceptance criteria:

  • A maximum of 2 access keys per user is enforced.

  • The secret key is displayed only in the creation response — subsequent GET requests return the access key ID but never the secret.

  • The secret key is stored as a SHA-256 hash; it cannot be recovered.

  • An audit event iam:CreateCredential is recorded in TraceBook.

US-AC-12: Download and Save Access Key Credentials

As Bob (root user), I want to download the access key credentials as a CSV file immediately after creation, so that I can securely store them for later use — because the secret key is shown only once and cannot be retrieved afterward.

Steps:

  1. Bob creates an access key for the white-svc-api user (see US-AC-11). The "Access key created successfully" dialog appears, showing the access key ID and secret key.

  2. Bob clicks "Download .csv file". The browser downloads a file named white-svc-api_accessKeys.csv containing:

    Access key ID,Secret key
    AKIA1456A9224E6545CB,HuTKOL3X9iaFVSCXT32s...
    
  3. Bob stores the CSV in a secure location (password manager, secrets vault, or encrypted storage).

  4. Bob repeats the process for the ruby-svc-api user in the Ruby Labs account. The downloaded CSV is ruby-svc-api_accessKeys.csv.

  5. Bob closes the dialog. The secret key is no longer accessible — only the access key ID appears in the credentials table.

Acceptance criteria:

  • The "Download .csv file" button is available only in the creation confirmation dialog — it is not shown elsewhere.

  • The CSV file name includes the username for easy identification.

  • The CSV contains exactly two columns: Access key ID and Secret key.

  • After the dialog is dismissed, the secret key cannot be retrieved from any API endpoint, UI page, or database query (stored as SHA-256 hash).

  • If the user closes the dialog without downloading, a confirmation warning reminds them that the secret key will be permanently inaccessible.

  • Both tenants (White Corp and Ruby Labs) can independently create and download credentials for their own service users.

US-AC-13: Programmatic API Access with Access Key Credentials

As a service application running under the white-svc-api user, I want to authenticate to FlexGalaxy APIs using my access key, so that I can call APIs without a browser or interactive session.

Steps:

  1. The application constructs the authorization header: Authorization: FGAI Base64(<access_key_id>:<secret_key>).

  2. The application sends GET https://api.flexgalaxy.com/iam/v1/accounts with the header.

  3. The API gateway validates the credential against the authorization service, resolves the caller's account and identity, and forwards the request to the backend.

  4. The response contains the list of accounts visible to the caller.

  5. The application sends GET https://api.flexgalaxy.com/iam/v1/accounts/{accountId}/users to list IAM users in its own account.

  6. Both requests succeed with HTTP 200.

Acceptance criteria:

  • The FGAI auth scheme is accepted by the KrakenD API gateway and the console gateway's /iam/ proxy.

  • Invalid or deactivated credentials return HTTP 401.

  • The resolved identity carries the correct accountId and userId so that IAM policy evaluation scopes access to the caller's account.

  • API calls are recorded as audit events with the access key ID as the credential identifier.

US-AC-14: Set Permission Boundary for a Service User

As Bob (root user), I want to attach a permission boundary to a service user, so that the service user's API access is capped to a defined set of actions — regardless of how many policies are attached to it later.

Steps:

  1. Bob navigates to AdminCenter → Service Users → Users and clicks the white-svc-api user.

  2. Bob opens the "Permission Boundary" tab. It shows "No permission boundary" with a description.

  3. Bob clicks "Set permission boundary".

  4. A policy picker dialog lists available managed and custom policies. Bob selects "ReadOnlyAccess".

  5. AdminCenter calls POST /iam/v1/accounts/{accountId}/permission-boundaries with { "user_id": "<userId>", "policy_id": "<policyId>" }.

  6. The tab now shows the boundary policy ID and the timestamp.

  7. The service user's API calls are immediately constrained: even if its group grants FullAccess, effective permissions are FullAccess ReadOnlyAccess = ReadOnlyAccess.

Acceptance criteria:

  • The Permission Boundary tab renders correctly without console errors when no boundary is set (404 from backend is handled gracefully).

  • Setting a boundary triggers a policy version increment.

  • Only one boundary per user — attempting to set a second returns HTTP 409 Conflict.

  • Boundary evaluation occurs at step 6 of the 8-step authorization pipeline (after identity-based policy, before final decision).

US-AC-15: Multi-Tenant API Isolation with Separate Credentials

As a platform with two tenants (White Corp and Ruby Labs), I want to verify that each tenant's service user credentials are isolated, so that one tenant cannot access another tenant's resources.

Steps:

  1. White Corp creates account white with root user admin@white-corp.test, service user white-svc-api, and access key AKIA-WHITE….

  2. Ruby Labs creates account ruby with root user admin@ruby-labs.test, service user ruby-svc-api, and access key AKIA-RUBY….

  3. White's service user calls GET /iam/v1/accounts/{whiteAccountId}/users with AKIA-WHITE… → succeeds (HTTP 200), returns White's users only.

  4. Ruby's service user calls GET /iam/v1/accounts/{rubyAccountId}/users with AKIA-RUBY… → succeeds (HTTP 200), returns Ruby's users only.

  5. White's service user calls GET /iam/v1/accounts/{rubyAccountId}/users with AKIA-WHITE… → denied (HTTP 403), because the IAM policy only grants access to White's own account resources.

Acceptance criteria:

  • Each account has its own Keycloak realm (acc-*), IAM users, and policy namespace. No cross-account data leakage.

  • The authorization pipeline resolves the access key to the correct account and evaluates policies scoped to that account only.

  • Cross-account API calls are denied by default unless an explicit resource-based policy grants access (not set in this scenario).

  • Account creation provisions a full Keycloak realm, root user, and default managed policies via the /registration/submit endpoint.


Organization Console (console.flexgalaxy.com/orgs/)

US-ORG-1: Create Organization

As Bob (root user), I want to create an organization, so that I can manage multiple accounts under a unified structure.

Steps:

  1. Bob navigates to Organization Console.

  2. Since Bob has no org, the UI shows "Create Organization".

  3. Bob clicks create, names the org "Acme Corp", and confirms.

  4. Bob's account becomes the management account of the new org.

  5. The org dashboard shows the root OU with Bob's account.

US-ORG-2: Create Organizational Units and Accounts

As Bob (org admin), I want to create OUs and member accounts, so that I can structure my organization.

Steps:

  1. Bob creates two OUs: "Development" and "Production" under the root.

  2. Bob creates member accounts: iot-dev, wes-dev (under Development) and iot-prod, wes-prod (under Production).

  3. The org tree view shows the hierarchy.

  4. Bob can drag accounts between OUs to reorganize.

US-ORG-3: Close and Delete Account

As Bob, I want to close a member account, so that I can decommission unused accounts.

Steps:

  1. Bob selects account wes-dev in the org tree.

  2. Bob clicks "Close Account" and confirms.

  3. The account enters a 30-day grace period (shown as "Pending Closure").

  4. After 30 days, Bob can permanently delete the account.

US-ORG-4: Manage Service Control Policies

As Bob, I want to create and attach SCPs, so that I can enforce guardrails across member accounts.

Steps:

  1. Bob navigates to Organization Console → Policies.

  2. Bob creates an SCP that denies devices:Delete* actions.

  3. Bob attaches the SCP to the "Production" OU.

  4. All accounts under Production are now prevented from deleting devices.

US-ORG-5: Identity Center (IDC) User Management

As Bob, I want to manage IDC users and permission sets, so that corporate users can access member accounts with SSO.

Steps:

  1. Bob navigates to Organization Console → Identity Center.

  2. Bob creates IDC users (alice@acme-corp.com, charlie@acme-corp.com).

  3. Bob creates permission sets: "AdminAccess", "DeveloperAccess", "ReadOnly".

  4. Bob assigns Alice the "AdminAccess" permission set on the iot-dev account.

  5. Alice can now log in via StartPoint realm discovery and access iot-dev.

US-ORG-6: Delegated Admin Management

As Bob (management account), I want to delegate admin access, so that trusted accounts can manage parts of the org.

Steps:

  1. Bob navigates to Organization Console → Delegated Admins.

  2. Bob designates iot-dev as a delegated admin for the "Development" OU.

  3. The iot-dev root user can now manage accounts within "Development" (read-only for other OUs).


QuotaCenter (console.flexgalaxy.com/quotas/)

US-QC-1: View Current Quotas

As Bob (org admin), I want to view my organization's resource quotas, so that I can plan capacity.

Steps:

  1. Bob navigates to QuotaCenter from DartBoard.

  2. The dashboard shows current quotas: max accounts (10/10), max users per account (100/50 used), max policies (200/45 used).

  3. Usage bars indicate how close each quota is to its limit.

US-QC-2: Request Quota Increase

As Bob, I want to request a quota increase, so that I can grow my organization beyond default limits.

Steps:

  1. Bob clicks "Request Increase" next to the accounts quota.

  2. Bob enters desired new limit (35) and provides a business justification.

  3. Bob submits the request.

  4. The request appears in the requests list as "Pending".

  5. After platform admin approval (via SuperCrew), the quota is updated.

  6. Bob receives a notification (via NovaBell) that the request was approved.


ThingHub (console.flexgalaxy.com/thinghub/)

US-DC-1: View Enrolled Devices

As Alice (account user), I want to view all enrolled devices, so that I can monitor my device fleet.

Steps:

  1. Alice navigates to ThingHub → Enrolled Devices.

  2. The list shows devices with: name, status (online/offline), last seen, firmware version, assigned license.

  3. Alice searches for a specific device by serial number.

  4. Alice clicks a device to see detailed info: metadata, license status, update history.

US-DC-2: View Licenses

As Alice, I want to view my account's licenses, so that I can track allocation and expiration.

Steps:

  1. Alice navigates to ThingHub → Licenses.

  2. The list shows licenses: product name, type (perpetual/subscription), status (active/expired), assigned device count.

  3. Alice clicks a license to see details: activation date, expiration, assigned devices.

US-DC-3: View OTA Updates

As Alice, I want to see available OTA updates for my devices, so that I know what updates are pending.

Steps:

  1. Alice navigates to ThingHub → Updates.

  2. The list shows rollouts targeting her devices (read-only for non-developers).

  3. Alice sees rollout status: percentage deployed, success/failure counts.

US-DC-4: Register as Device Manufacturer

As Bob (root user of Ruby's account), I want to register my account as a device manufacturer, so that my account gains access to device enrollment, certificate management, and related manufacturer capabilities.

Steps:

  1. Bob navigates to ThingHub → Settings.

  2. The settings page shows an "Account Role" section. Bob's account has no role registered yet.

  3. Bob clicks "Register as Device Manufacturer".

  4. A form collects: company name, manufacturer ID (e.g. "RUBY"), business justification, and contact details.

  5. Bob submits the registration request.

  6. The request appears as "Pending Approval" in Settings.

  7. Diana (platform operator) reviews and approves the request in DeckLoader (see US-DL-4).

  8. Upon approval, the platform attaches a ManufacturerScope SCP to Bob's account. The SCP allows: devices:*, certificates:*, events:Read*, licenses:Read*.

  9. Bob's account now has manufacturer capabilities. ThingHub shows the enrollment section and device provisioning tools.

  10. All users in Bob's account are governed by the SCP — no user can exceed the manufacturer permission ceiling regardless of their individual policies.

Acceptance criteria:

  • Only root users can submit the registration request.

  • One account can have at most one active role SCP (manufacturer or license manager — not both).

  • The SCP is a platform-managed policy — the tenant cannot modify or detach it.

  • An audit event is recorded when the SCP is attached.

  • If the request is rejected, Bob receives a notification with the reason.


ThingIO (console.flexgalaxy.com/thingio/)

US-TIO-1: View Device Fleet Overview

As Alice (account user), I want to see an overview of my IoT device fleet, so that I can quickly assess the health and connectivity of all devices.

Steps:

  1. Alice navigates to ThingIO from DartBoard.

  2. The dashboard shows feature cards: Devices, Telemetry, Analytics, Alerts.

  3. Alice clicks the "Devices" card to drill into the device list.

US-TIO-2: Browse Enrolled Devices

As Alice, I want to browse all enrolled IoT devices in a table, so that I can find specific devices and check their provisioning status.

Steps:

  1. Alice navigates to ThingIO → Devices.

  2. The table shows: Thing ID, Model, Serial Number, License Type, Provisioned Date.

  3. License types are shown as colored tags (green for OFFICIAL, blue for other).

  4. Alice scans the table for a specific device by serial number.

  5. Alice clicks a device row to view its telemetry data.

US-TIO-3: View Device Telemetry

As Alice, I want to view real-time telemetry data for a specific device, so that I can monitor sensor readings and diagnose issues.

Steps:

  1. Alice clicks a device from the Devices list (or navigates directly to /thingio/devices/:thingId/telemetry).

  2. ThingIO fetches the last 24 hours of telemetry from ThingsBoard.

  3. The telemetry page shows metric tiles: temperature, humidity, battery level.

  4. Each tile displays the latest value and total data point count.

  5. Alice uses this data to verify that a device in the field is reporting correctly.

US-TIO-4: Developer Monitors Test Devices

As Charlie (developer), I want to monitor telemetry from devices running my firmware, so that I can validate that my OTA update is working correctly before expanding the rollout.

Steps:

  1. Charlie pushes a firmware update via OTAForge to a 10% canary group.

  2. Charlie opens ThingIO → Devices and finds a device in the canary group.

  3. Charlie views the telemetry page and checks that temperature and humidity readings are within expected ranges.

  4. Seeing normal telemetry, Charlie returns to OTAForge and advances the rollout to 50%.


ThingLab (console.flexgalaxy.com/thinglab/)

US-TL-1: View Emulation Dashboard

As Charlie (developer), I want to see an overview of my device emulation environment, so that I can track templates, fleet configs, and active runs at a glance.

Steps:

  1. Charlie navigates to ThingLab from DartBoard.

  2. The dashboard shows summary cards: Template Count, Fleet Config Count, Active Run Count.

  3. A recent runs table shows the last 5 runs with status tags (Pending, Running, Completed, Failed).

  4. Charlie clicks a card to navigate to the corresponding section.

US-TL-2: Create Device Template

As Charlie, I want to create reusable device templates, so that I can define the characteristics of devices I want to emulate.

Steps:

  1. Charlie navigates to ThingLab → Templates.

  2. Charlie clicks "Create Template".

  3. A modal opens with fields: name, Thing ID prefix, manufacturer, model, device type (Device or Gateway), description.

  4. Charlie fills in the form for a temperature sensor: name "TempSensor-v2", prefix "TS2", manufacturer "Acme", model "TS-200", type "Device".

  5. Charlie saves. The template appears in the templates table.

  6. Charlie repeats to create a gateway template: "GW-Core", prefix "GW", type "Gateway".

US-TL-3: Configure Fleet Emulation

As Charlie, I want to create a fleet configuration that combines a gateway with sensor and software profiles, so that I can define a realistic device topology for testing.

Steps:

  1. Charlie navigates to ThingLab → Fleet Configs → New.

  2. A 4-step wizard appears:

    • Step 1 — Select Gateway: Charlie picks the "GW-Core" gateway template.

    • Step 2 — Select Sensors: Charlie checks "TempSensor-v2" and "HumiditySensor-v1" from the available sensor templates/profiles.

    • Step 3 — Select Software: Charlie checks "FW-2.1.0" software profile.

    • Step 4 — Set Parameters: Charlie enters: name "Canary Fleet", device count 50, telemetry interval 10s, duration 3600s (1 hour).

  3. Charlie clicks "Create". The fleet config is saved and appears in the list.

US-TL-4: Start and Monitor Emulation Run

As Charlie, I want to start an emulation run and monitor its progress, so that I can generate realistic device telemetry for integration testing.

Steps:

  1. Charlie navigates to ThingLab → Runs.

  2. Charlie clicks "Start Run".

  3. A modal opens: Charlie selects "Canary Fleet" config, sets interval (10s) and duration (1800s).

  4. Charlie starts the run. It appears in the runs table as "Pending", then transitions to "Running".

  5. Charlie switches to ThingIO → Devices and sees the emulated devices appearing with live telemetry data.

  6. After testing, Charlie returns to ThingLab → Runs and clicks "Stop" to end the run early.

US-TL-5: Manage Device Templates and Fleet Configs

As Charlie, I want to edit and delete templates and fleet configs, so that I can iterate on my emulation setup.

Steps:

  1. Charlie navigates to ThingLab → Templates.

  2. Charlie clicks the edit icon on "TempSensor-v2" and updates the model to "TS-210".

  3. Charlie deletes an obsolete template "TempSensor-v1" via the delete icon and confirms.

  4. Charlie navigates to Fleet Configs and deletes an old config that is no longer needed.


Dev2M (console.flexgalaxy.com/dev2m/)

US-D2M-1: Register a Product

As Charlie (developer), I want to register a product on the marketplace, so that customers can discover and license it.

Steps:

  1. Charlie navigates to Dev2M → Products → Create.

  2. Charlie fills in: product name, description, category, icon.

  3. Charlie submits the product for review.

  4. The product appears in Charlie's list as "Pending Review".

  5. After platform approval (via AlienBazaar), the product is published.

US-D2M-2: Configure License Types

As Charlie, I want to define license types for my product, so that customers can purchase the right license tier.

Steps:

  1. Charlie opens a product and navigates to License Types.

  2. Charlie creates license types: "Standard" (perpetual, 1 device), "Enterprise" (subscription, unlimited devices).

  3. Charlie sets pricing, duration, and device limits for each type.

  4. The license types are published with the product.

US-D2M-3: View Billing

As Charlie, I want to view my developer billing summary, so that I can track revenue and payouts.

Steps:

  1. Charlie navigates to Dev2M → Billing.

  2. The dashboard shows: total revenue, pending payouts, transaction history.

  3. Charlie downloads a billing report for the current month.


OTAForge (console.flexgalaxy.com/otaforge/)

US-OF-1: Upload OTA Package

As Charlie (developer), I want to upload a firmware update package, so that I can distribute updates to customer devices.

Steps:

  1. Charlie navigates to OTAForge → Packages → Create.

  2. Charlie uploads the firmware binary, enters version number, release notes, and target device model.

  3. Charlie submits. The package is validated (checksum, format) and stored.

  4. The package appears in Charlie's list as "Ready".

US-OF-2: Create Rollout Campaign

As Charlie, I want to create a rollout campaign for an update, so that I can deploy firmware to devices in a controlled manner.

Steps:

  1. Charlie navigates to OTAForge → Rollouts → Create.

  2. Charlie selects the package (v2.1.0) and target criteria (device model, region, percentage).

  3. Charlie sets rollout strategy: staged (10% → 50% → 100%) with automatic progression.

  4. Charlie starts the rollout.

US-OF-3: Monitor Rollout

As Charlie, I want to monitor a rollout in progress, so that I can detect issues and pause if needed.

Steps:

  1. Charlie opens a rollout from the Rollouts list.

  2. The detail view shows: progress (45/100 devices), success rate (98%), failures (1 device).

  3. Charlie sees a timeline of rollout stages.

  4. Charlie notices a failure spike and clicks "Pause Rollout".

  5. Charlie investigates the failed device, fixes the package, and resumes.


TraceBook (console.flexgalaxy.com/tracebook/)

US-TB-1: Search Audit Events

As Alice, I want to search audit events for my account, so that I can investigate security incidents.

Steps:

  1. Alice navigates to TraceBook from DartBoard.

  2. The event history shows all auditable actions in her account.

  3. Alice filters by: date range (last 7 days), event type (IAM changes), actor (user ID).

  4. Results show: timestamp, event name, actor, resource, source IP.

  5. Alice clicks an event to see the full detail (request parameters, response).

US-TB-2: Organization-Scoped Audit

As Bob (org admin), I want to view audit events across all member accounts, so that I can monitor org-wide compliance.

Steps:

  1. Bob opens TraceBook and selects "Organization" scope.

  2. Events from all member accounts are aggregated.

  3. Bob filters by account to isolate activity in iot-prod.

  4. Bob exports the filtered events as CSV for compliance reporting.


Part 2 — Platform Admin Applications


StarGate (stargate.flexgalaxy.com/)

US-SG-1: Platform Admin Launcher

As Diana (platform operator), I want to access admin tools from StarGate, so that I can manage the platform.

Steps:

  1. Diana navigates to stargate.flexgalaxy.com.

  2. Diana authenticates via Keycloak (master realm, platform-admin role).

  3. StarGate shows the admin tools grid: SuperCrew, OrbitCast, BoardingPass, DeckLoader, AlienBazaar.

  4. Diana clicks SuperCrew to manage platform IAM.


SuperCrew (stargate.flexgalaxy.com/supercrew/)

US-SC-1: View All Accounts

As Diana, I want to view all accounts on the platform, so that I can monitor and manage tenant accounts.

Steps:

  1. Diana navigates to SuperCrew → Accounts.

  2. The list shows all accounts: name, type (standalone/management/member), status (active/suspended/pending-closure), creation date.

  3. Diana searches for "Acme Corp" and finds Bob's management account.

  4. Diana clicks to view account details.

US-SC-2: Manage Organizations

As Diana, I want to view and manage organizations, so that I can oversee multi-account structures.

Steps:

  1. Diana navigates to SuperCrew → Organizations.

  2. The list shows all organizations with: name, management account, member count.

  3. Diana clicks "Acme Corp" to see its org tree and member accounts.

  4. Diana can suspend an organization or force-close a member account if needed.

US-SC-3: Manage Namespaces (IDC Realms)

As Diana, I want to manage IDC namespaces, so that I can oversee realm configuration and policies.

Steps:

  1. Diana navigates to SuperCrew → Namespaces.

  2. The list shows all IDC realms/namespaces with status.

  3. Diana clicks a namespace to view: realm config, connected domains, users, permission sets.

  4. Diana can disable a namespace or update its configuration.

US-SC-4: Approve Quota Increase Requests

As Diana, I want to review and approve quota increase requests, so that tenants can grow their usage.

Steps:

  1. Diana sees a pending quota request from Bob (accounts: 10 → 35).

  2. Diana reviews Bob's current usage and business justification.

  3. Diana approves the request. The quota is updated automatically.

  4. Bob receives a notification via NovaBell.


BoardingPass (stargate.flexgalaxy.com/boardingpass/)

US-BP-1: License Analytics Dashboard

As Diana, I want to view platform-wide license analytics, so that I can monitor licensing health.

Steps:

  1. Diana navigates to BoardingPass → Overview.

  2. The dashboard shows: total active licenses, revenue trends, top products by license count, expiring licenses (next 30 days).

  3. Diana drills into a specific product to see per-tenant license breakdown.

US-BP-2: Approve License Requests

As Diana, I want to approve or deny license requests, so that I can manage license allocation.

Steps:

  1. Diana navigates to BoardingPass → Approvals.

  2. The queue shows pending requests: tenant, product, license type, quantity.

  3. Diana reviews a request, checks the tenant's quota and payment status.

  4. Diana clicks "Approve". The licenses are provisioned and the tenant is notified.

US-BP-3: Platform License Inventory

As Diana, I want to browse all licenses on the platform, so that I can audit and troubleshoot licensing issues.

Steps:

  1. Diana navigates to BoardingPass → Licenses.

  2. The inventory shows all licenses with: product, tenant, type, status, expiration.

  3. Diana filters by status "Expired" to find licenses needing attention.

  4. Diana can revoke or extend a license from the detail view.

US-BP-4: Approve License Approval Partner Registration

As Diana (platform operator), I want to review and approve requests from accounts that want to become license approval partners, so that only vetted partners can intercept license approval workflows.

Steps:

  1. Diana navigates to BoardingPass → Partner Requests.

  2. The queue shows pending registration requests from accounts that want to act as license approval partners (e.g. White).

  3. Diana opens White's request and reviews: company name, webhook URLs, integration details, business justification.

  4. Diana approves the request.

  5. The platform attaches a LicenseManagerScope SCP to White's account. The SCP allows: approvals:*, devices:Read*, licenses:Read*.

  6. White's account can now receive license approval webhooks and submit approval decisions via the TrustMint callback API.

  7. All users in White's account are governed by the SCP.

Acceptance criteria:

  • Diana can approve or reject with a reason.

  • Rejection sends a notification to the requesting account via NovaBell.

  • The LicenseManagerScope SCP is platform-managed — the tenant cannot modify or detach it.

  • An audit event is recorded.

  • Diana can revoke partner status later (detaches the SCP).

US-BP-5: Register as License Approval Partner (Tenant Side)

As Bob (root user of White's account), I want to register my account as a license approval partner, so that my account can intercept and approve license upgrade requests on behalf of device manufacturers.

Steps:

  1. Bob navigates to BoardingPass → Settings (accessible to tenants via the API gateway at /entitlements/v1/partner-registration).

  2. The settings page shows an "Account Role" section. Bob's account has no role registered yet.

  3. Bob clicks "Register as License Approval Partner".

  4. A form collects: company name, webhook endpoint URLs (device-provisioned, license-upgrade-requested), webhook secret, and business justification.

  5. Bob submits the registration request.

  6. The request appears as "Pending Approval" in Settings.

  7. Diana reviews and approves in BoardingPass (see US-BP-4).

  8. Upon approval, the LicenseManagerScope SCP is attached to Bob's account. TrustMint is configured to send webhooks to the registered endpoints.

  9. All users in Bob's account are governed by the SCP — no user can exceed the license manager permission ceiling.

Acceptance criteria:

  • Only root users can submit the registration request.

  • One account can have at most one active role SCP.

  • Webhook URLs are validated (must be HTTPS, must respond to a verification ping).

  • The SCP is platform-managed and cannot be modified by the tenant.

  • An audit event is recorded.


DeckLoader (stargate.flexgalaxy.com/deckloader/)

US-DL-1: Platform Device Inventory

As Diana, I want to view all enrolled devices across all tenants, so that I can monitor the device fleet.

Steps:

  1. Diana navigates to DeckLoader → Devices.

  2. The list shows all devices platform-wide: serial, tenant, model, status, firmware version.

  3. Diana searches by serial number to find a specific device.

  4. Diana clicks a device to see: enrollment date, assigned license, update history, health metrics.

US-DL-2: Device Enrollment Setup

As Diana, I want to generate enrollment credentials, so that new devices can register with the platform.

Steps:

  1. Diana navigates to DeckLoader → Enrollment.

  2. Diana creates an enrollment profile: target tenant, device model, QR code or token-based.

  3. The system generates enrollment credentials (QR code or token).

  4. Diana shares the credentials with the tenant for device onboarding.

US-DL-3: Device Monitoring

As Diana, I want to monitor device health across the platform, so that I can proactively address issues.

Steps:

  1. Diana navigates to DeckLoader → Monitoring.

  2. The dashboard shows: online/offline counts, firmware distribution chart, devices with errors.

  3. Diana filters to devices with "Error" status.

  4. Diana clicks a device to see diagnostic info and recent events.

US-DL-4: Approve Device Manufacturer Registration

As Diana (platform operator), I want to review and approve requests from accounts that want to become device manufacturers, so that only vetted manufacturers can enroll devices on the platform.

Steps:

  1. Diana navigates to DeckLoader → Manufacturer Requests.

  2. The queue shows pending registration requests (e.g. Ruby's account).

  3. Diana opens Ruby's request and reviews: company name, manufacturer ID, business justification, contact details.

  4. Diana approves the request.

  5. The platform attaches a ManufacturerScope SCP to Ruby's account. The SCP allows: devices:*, certificates:*, events:Read*, licenses:Read*.

  6. Ruby's account now has manufacturer capabilities — ThingHub shows enrollment tools for Ruby's users.

  7. All users in Ruby's account are governed by the SCP.

Acceptance criteria:

  • Diana can approve or reject with a reason.

  • Rejection sends a notification to the requesting account via NovaBell.

  • The ManufacturerScope SCP is platform-managed — the tenant cannot modify or detach it.

  • An audit event is recorded.

  • Diana can revoke manufacturer status later (detaches the SCP).


AlienBazaar (stargate.flexgalaxy.com/alienbazaar/)

US-AB-1: Review and Approve Products

As Frank (marketplace admin), I want to review submitted products, so that only quality products are published on the marketplace.

Steps:

  1. Frank navigates to AlienBazaar → Products.

  2. Frank filters by status "Pending Review".

  3. Frank opens a product submitted by Charlie: reviews description, icon, license types, pricing.

  4. Frank approves the product. It becomes visible on the marketplace.

  5. Charlie is notified via NovaBell.

US-AB-2: Manage Developer Accounts

As Frank, I want to manage developer accounts, so that I can onboard and monitor marketplace developers.

Steps:

  1. Frank navigates to AlienBazaar → Developers.

  2. The list shows developer accounts: name, product count, revenue, status.

  3. Frank clicks a developer to see: profile, products, billing history.

  4. Frank can suspend a developer account if terms are violated.

US-AB-3: Marketplace Billing Administration

As Frank, I want to manage marketplace billing, so that developers are paid correctly.

Steps:

  1. Frank navigates to AlienBazaar → Billing.

  2. The dashboard shows: total marketplace revenue, pending payouts, platform commission.

  3. Frank reviews pending payouts and triggers monthly payout processing.

US-AB-4: Monitor OTA Rollouts (Platform-Wide)

As Frank, I want to monitor all OTA rollouts, so that I can ensure update quality across the marketplace.

Steps:

  1. Frank navigates to AlienBazaar → Updates.

  2. The list shows all active rollouts: product, developer, stage, success rate.

  3. Frank notices a rollout with high failure rate and clicks to investigate.

  4. Frank can pause the rollout and notify the developer.


OrbitCast (stargate.flexgalaxy.com/orbitcast/)

US-OC-1: Create and Publish Article

As Eve (content editor), I want to create and publish website content, so that the FlexGalaxy.AI website stays current.

Steps:

  1. Eve navigates to OrbitCast → Articles → New.

  2. Eve writes the article using the rich text editor: title, body, featured image, category, tags.

  3. Eve previews the article.

  4. Eve clicks "Publish". The article goes live on the website.

US-OC-2: Manage Media Library

As Eve, I want to upload and organize media assets, so that I can use them in articles and pages.

Steps:

  1. Eve navigates to OrbitCast → Media.

  2. Eve uploads images and documents.

  3. Eve organizes media into collections (e.g., "Product Screenshots", "Blog Headers").

  4. When creating an article, Eve selects images from the media library.

US-OC-3: Manage Categories and Tags

As Eve, I want to organize content with categories and tags, so that website visitors can find content easily.

Steps:

  1. Eve navigates to OrbitCast → Categories.

  2. Eve creates categories: "Product Updates", "Tutorials", "Company News".

  3. Eve navigates to Tags and creates tags: "IoT", "Security", "Release".

  4. When publishing articles, Eve assigns relevant categories and tags.

US-OC-4: Edit Static Pages

As Eve, I want to edit static website pages, so that landing pages and informational content stay up to date.

Steps:

  1. Eve navigates to OrbitCast → Pages.

  2. Eve opens the "Pricing" page for editing.

  3. Eve updates the pricing tiers and feature comparison table.

  4. Eve saves and publishes the changes.


Part 3 — Cross-Cutting Stories


Notification (NovaBell Integration)

US-NB-1: Receive In-App Notifications

As any user, I want to receive notifications in the notification center, so that I'm aware of important events.

Steps:

  1. User is working in any app.

  2. A notification badge appears on the bell icon in the topbar.

  3. User clicks the bell to open the notification panel.

  4. Notifications include: quota request approved, product review complete, license expiring, rollout failed.

  5. User clicks a notification to navigate to the relevant resource.


Cross-App Navigation

US-NAV-1: Topbar Avatar Menu

As any user, I want to access common actions from the avatar menu, so that I can switch accounts, change settings, and sign out from anywhere.

Steps:

  1. User clicks the avatar icon in the topbar (present in all apps).

  2. The dropdown shows: current account name, Switch Account, Organization, Profile, Language, Theme, Sign Out.

  3. "Switch Account" returns to StartPoint.

  4. "Organization" navigates to Organization Console.

  5. "Sign Out" terminates the session and returns to StartPoint.

US-NAV-2: Inter-App Navigation via Relative Paths

As any user, I want to navigate between apps seamlessly, so that the platform feels unified.

Steps:

  1. User is in AdminCenter at console.flexgalaxy.com/admincenter/.

  2. User clicks "Devices" in the topbar or sidebar.

  3. Browser navigates to console.flexgalaxy.com/thinghub/ — same origin, no re-authentication needed.

  4. All apps share the same SSO session via the Console Gateway.

US-NAV-3: Browser Back Button Resilience

As any user, I want to use the browser back button reliably, so that navigation feels natural.

Steps:

  1. User navigates: DartBoard → AdminCenter → Users → User Detail.

  2. User presses Back: returns to Users list.

  3. User presses Back: returns to AdminCenter dashboard.

  4. User presses Back: returns to DartBoard.

  5. No blank pages or broken states at any step.


Multi-Session Identity

US-MS-1: Multiple Identities in One Browser

As a user with both root and IDC identities, I want to maintain multiple sessions, so that I can work across accounts without re-authenticating.

Steps:

  1. Bob logs in as root user → enters management account.

  2. Bob opens a new tab → StartPoint → "Add another identity".

  3. Bob logs in with his IDC credentials (different realm).

  4. Both sessions coexist. StartPoint shows both identities.

  5. Bob can switch between them from the avatar dropdown.

US-MS-2: Sign Out All Identities

As a user, I want to sign out all identities at once, so that my session is fully terminated when I leave.

Steps:

  1. User clicks avatar → "Sign out all".

  2. All active sessions (root + IDC) are terminated.

  3. User is returned to StartPoint with no active sessions.


Cross-Subdomain Preferences

US-PREF-1: Dark Theme Persists Across Homepage, Keycloak, and Apps

As any user, I want to switch to dark theme on the homepage and have it persist through account creation/login on Keycloak and into the app dashboard, so that the entire platform feels consistent and respects my preference.

Steps:

  1. User visits www.flexgalaxy.com (homepage).

  2. User clicks the theme toggle in the header → switches to dark mode.

  3. Homepage sets fg-theme=g100 cookie on .flexgalaxy.com domain.

  4. User clicks "Sign up" → redirected to auth.flexgalaxy.com (Keycloak).

  5. Keycloak login page reads fg-theme cookie → renders in dark theme.

  6. User completes registration, is redirected to console.flexgalaxy.com/start/.

  7. StartPoint reads fg-theme cookie → renders in dark theme.

  8. User enters DartBoard → dark theme is applied.

  9. User toggles theme in any app → cookie is updated → all subdomains reflect the change on next navigation.

Technical notes:

  • Cookie: fg-theme=white|g100; Domain=.{baseDomain}; Path=/; SameSite=Lax; Secure; Max-Age=31536000

  • All three projects (www, DotID/Keycloak, app-shell) read the cookie on load and dual-write to both cookie (cross-subdomain) and localStorage (cross-tab).

  • System preference (prefers-color-scheme) is used as final fallback when no cookie or localStorage value is set.

US-PREF-2: Language Preference Persists Across Homepage, Keycloak, and Apps

As any user, I want to switch language on the homepage and have Keycloak and all apps display in that language, so that I don't have to switch language again on every page.

Steps:

  1. User visits www.flexgalaxy.com/en/ (homepage in English).

  2. User clicks the language switcher → selects "日本語" (Japanese).

  3. Homepage sets fg-lang=ja cookie on .flexgalaxy.com domain and navigates to www.flexgalaxy.com/ja/.

  4. User clicks "ログイン" (Login) → redirected to auth.flexgalaxy.com.

  5. Keycloak reads fg-lang cookie → resolves locale to Japanese → renders login form in Japanese.

  6. User logs in and is redirected to console.flexgalaxy.com/start/.

  7. StartPoint reads fg-lang cookie → initializes i18n with Japanese.

  8. All subsequent apps (DartBoard, AdminCenter, etc.) read the same cookie and display in Japanese.

Technical notes:

  • Cookie: fg-lang=en|zh-CN|ja; Domain=.{baseDomain}; Path=/; SameSite=Lax; Secure; Max-Age=31536000

  • Keycloak locale resolution priority: kc_locale URL param → fg-lang cookie → fg-kc-locale localStorage → navigator.language → realm default.

  • Language changes in any app update the cookie, so the preference follows the user across subdomains.

US-PREF-3: Preferences Survive Session Loss

As any user, I want to keep my theme and language preferences even after my session expires or I clear cookies selectively, so that I don't have to reconfigure my preferences.

Steps:

  1. User has set dark theme and Japanese language.

  2. User's Keycloak session expires (e.g. inactivity timeout).

  3. User returns to any FlexGalaxy page.

  4. The page renders in dark theme and Japanese — preferences survived because the fg-theme and fg-lang cookies have a 1-year lifetime, independent of the Keycloak session cookie.

  5. User completes re-authentication → still in dark theme and Japanese.