PRODUCT ENGINEERING / BANK FLEET MANAGEMENT
UIC CONNECT TMS · CURRENT ARCHITECTURE

One bank.
Its entire terminal network.

A new, independent terminal-management module for institutions that own and operate POS fleets. Familiar UIC Connect experience. Explicit customer boundaries. Reliable device operations.

ASP.NET Core MVCClaims + SessionHTTP/2 gRPCDapperSQL Server / PostgreSQLMQTTnet broker
01 / OWNERSHIP

Bank as the customer

Super administrators allocate devices. Bank administrators manage their own fleet, users and operating structure.

02 / CONTROL

Intent to confirmed result

Durable commands, application releases and parameter downloads show what was requested and what the device applied.

03 / CONFIGURATION

Design once, render consistently

Visual schemas drive device forms, validation and current-save parameter delivery across supported terminals.

A clear separation of responsibilities

IMPLEMENTED RUNTIME TOPOLOGY

Three services, one SQL authority

Browser / Android HTTPS → TMS.Portal (including remote relay)
Android MQTTS → TMS.Connectivity.Mqtt
Portal + MQTT → loopback HTTP/2 gRPC → TMS.DataService → Dapper → SQL Server or PostgreSQL

Production defaults: HTTPS 5102 · MQTTS 5883 · internal gRPC 15101. No AWS services or standalone relay are deployed.

Baseline and decisions.The running single-server stack uses .NET 8, SQL Server 2022, Dapper, local MQTT mutual TLS and a portal-hosted remote relay. Parameters are saved and compiled on request. Chapter 30 distinguishes implemented behavior from future architecture.

A familiar portal, built around the fleet

SETUP AND USER MANUALS

Operator and integration documentation

English user manual · Manual de usuario en español

Android integration · Linux integration · Android en español · Linux en español

English setup PDF · PDF de instalación en español

Current implementation takes precedence: see chapters 30, 33 and 34. Earlier chapters preserve target designs and historical checkpoints.

The complete design baseline

35 CHAPTERS · MARKDOWN SOURCES INCLUDED

DESIGN BASELINE / CHAPTER 01Markdown source ↗

Product scope and operating model

Purpose

UIC Connect TMS enables a bank to administer the POS terminals it owns and places with merchants. The customer is the bank or other institution operating a terminal fleet. A merchant is an operating location or business relationship inside that customer's estate; it is not the tenant boundary.

The existing merchant-oriented UIC Connect business model remains separate. Payment routing and acquiring continue on their existing transaction path. A TMS outage must not itself interrupt payment authorization; a deliberate device block is a separate, capability-dependent administrative action.

Required capabilities

ID Requirement Design coverage
R01 Separate Kestrel ASP.NET Core MVC .NET 8 portal, Claims + Session Architecture, security
R02 TMS.DataService using gRPC over HTTP/2 and Dapper Architecture, data contracts
R03 Multiple customers; one or more administrators per customer Tenancy, customer lifecycle
R04 Only super administrators create customers and assign devices to them Authorization matrix, assignment workflow
R05 MQTT service or AWS IoT Core connectivity Connectivity decision and adapter
R06 Telemetry, properties, location, software and installed applications Device detail and ingest
R07 Reboot, message, block/unblock, remote control, app push, parameter push Operation lifecycle
R08 Visual schema designer and schema-driven device parameter editing Schema specification
R09 Device groups, nested subgroups and tags Tenant model, portal navigation
R10 Application upload: Android APK and legacy Linux ZIP Application lifecycle
R11 Reuse existing MQTT and remote-control proxy where appropriate Reuse assessment
R12 Independent solution with UIC Connect visual continuity Project boundaries, portal design

Vocabulary and ownership

Concept Meaning
Platform UIC-operated TMS installation and global device inventory
Customer Bank/institution; primary isolation and authorization boundary
Customer administrator User managing one customer's fleet and delegated access
Device Physical terminal with immutable internal identity and enrollment credentials
Merchant / site Optional customer-owned placement records; not mandatory for enrollment
Placement Dated association of a device to a merchant/site; distinct from customer assignment
Group / subgroup Customer-owned organizational hierarchy used to browse and target devices
Tag Customer-owned, many-to-many classification without ownership or permission semantics
Application Logical software product, with immutable APK/ZIP versions
Schema version Immutable published definition of parameter structure and form layout
Configuration revision Immutable resolved parameter document for one device and application

Customer and device lifecycle

  1. Super administrator creates a customer in Pending state and invites its first administrator.
  2. Customer becomes Active after at least one administrator accepts. An active customer cannot lose its last active administrator; recovery requires a super administrator and an audit reason.
  3. Super administrator registers/imports devices into global Unassigned inventory. Serial numbers are identifying attributes, not credentials.
  4. Super administrator assigns devices to the customer. This action is distinct from a customer administrator organizing those devices into groups or assigning merchant placement.
  5. Customer administrator configures groups, tags, applications, schemas, device parameters and operational users.
  6. Devices enroll, report state, receive approved operations and return application-level results.
  7. Retirement revokes credentials and disables new work while preserving historical records. A cross-customer transfer follows the quarantine procedure in the tenancy chapter.

Proposed states: customer Pending → Active → Suspended → Closed; device Unassigned → Assigned → Enrolled → Retired. Connection status and operational block status are separate dimensions, not lifecycle states.

Scope boundaries

Included: fleet administration, application distribution, configuration, remote support, operational audit, customer administration and optional merchant/site placement. Bank ownership and rental placement are recorded; rental billing, subscriptions, settlement, transaction processing, acquirer certification and full inventory procurement are outside this initial module.

The portal must distinguish Unsupported, Unknown, Stale, Pending and Failed. A Linux terminal may support parameters and ZIP installation without screen control. Support is negotiated from device capabilities; it is never inferred solely from a model name.

Initial assumptions for review

DESIGN BASELINE / CHAPTER 02Markdown source ↗

Solution architecture

Authoritative implementation summary: 26 September 2026. The original target design is retained in design-baseline/02-architecture-original.md; chapter 30 gives the detailed current checkpoint and chapter 33 defines Android/Linux integration.

Service boundary

Operators -- HTTPS --> Portal + remote relay
                         |
                         | authenticated loopback gRPC
                         v
                    DataService --> SQL Server
                         ^
                         | authenticated loopback gRPC
Android/Linux -- MQTTS --> MQTT gateway
Android/Linux -- HTTPS --> enrollment, IoT, package and parameter endpoints

Portal (5102), MQTT (5883) and DataService are three independently hosted Windows services in the single-server package. DataService owns business authorization and SQL persistence. Portal owns operator HTTP/session behavior and the in-memory Android remote relay. MQTT owns mutual-TLS device admission, presence, telemetry ingest, command dispatch and result delivery. Internal gRPC (15101) is loopback-only.

Application bytes and parameters use authenticated HTTPS. MQTT carries durable bounded JSON envelopes. Android remote screen/input uses WSS and is separate from commands and package transfer. SQL and private artifact storage must be backed up together.

Trust boundaries

Boundary Identity and enforcement
Operator to Portal BCrypt password, optional TOTP MFA, cookie + server session, antiforgery
Portal/MQTT to DataService Configured service key plus operator/device context; customer authorization repeated in DataService
Device to HTTPS Bootstrap proof before enrollment or provisioned device identity for protected downloads
Device to MQTT Device UUID/Secret, assignment epoch, per-device certificate fingerprint and exact topic scope
Browser to remote relay Authenticated operator, scoped device ticket, origin/WSS checks and bounded session

A terminal cannot create its portal inventory record. SuperAdmin first onboards the manufacturer serial, customer and portal model. Android test/debug provisioning imports its unique enrollment into app-private storage. Linux xTMSAgent claims the existing serial from a protected customer bootstrap. The first authenticated MQTT session closes the enrollment window.

Data and durable work

SQL stores customers, users/roles, audit, device/model/assignment, latest telemetry, application inventory, presence, commands/deployments, application catalog, parameters, IoT certificate lifecycle and location history. Device commands are at-least-once and tied to the assignment epoch. Agents journal command IDs before effects and retain results until an application-level storage receipt arrives.

One logical application/version can have distinct NEWPOS, NEXGO and A10 artifacts. The portal resolves compatible artifacts per target. Android verifies APK metadata, signer, hash and installed state. A10 uses the native signed tarball; the portal verifies structure/hash and the device vendor API verifies its signature/install.

Device platforms

Android UIC Home is a managed launcher and agent with a foreground MQTT service, hardware-flavor SDK adapters, application/parameter operations and consent-based remote assistance. Screen-off reliability depends on Android/vendor power policy. Preserve package identity, signer and app data during updates.

Linux xTMSAgent starts communications before TMS enrollment, provides F2 network configuration, supervises the payment application, reports complete model/resources/network/inventory and uses a file bridge for parameters/payment state. It installs/removes the A10 payment application and reboots after verified change. Remote desktop and official field-install instructions remain pending.

Cross-cutting portal behavior

Customer scope and feature Read/Write roles are enforced in the service, including audit and location. The device view separates portal model from reported model, shows free/total storage and available/total memory, preserves location history after meaningful 100-metre movement and permits manual positioning only while reported coordinates are unavailable.

The bilingual manuals are linked from the public sign-in page and authenticated header. See English portal manual, Español, Android integration and Linux integration.

Current constraints

The single-server runtime is not a multi-node architecture. Automatic IoT certificate renewal/CA rollover, production Android bootstrap distribution, official A10 installation, malware scanning, Linux remote desktop, scheduled parameter push and fleet-scale/load/restore qualification remain outstanding.

DESIGN BASELINE / CHAPTER 03Markdown source ↗

Customer isolation and access

Historical design requirements: consult chapter 30 for the current implementation and outstanding work.

Non-negotiable ownership boundary

Only a SuperAdmin can create a customer or assign, unassign or transfer a device between customers. Customer administrators may manage devices already assigned to their customer, including groups and merchant placement; they cannot acquire devices from global inventory by entering a serial number.

Every tenant-owned record carries CustomerId. Relationship constraints include the customer key so a group, device, schema, application or job cannot point across customers. Global device inventory is a separately authorized aggregate. CustomerId supplied by a browser is an untrusted selector, never proof of membership.

Proposed permission matrix

Action SuperAdmin CustomerAdmin FleetOperator SchemaDesigner Auditor
Create/suspend customer Yes No No No No
Assign/transfer devices to customer Yes No No No No
Manage customer users Yes, scoped Own customer No No No
View fleet/telemetry Explicit customer scope Own customer Own customer As granted Own customer
Groups/tags/placement Scoped permission Yes As granted No No
Reboot/message Scoped permission Yes Yes No No
Block/unblock Scoped permission Yes Separate grant No No
Start remote control Separate grant Separate grant Separate grant No No
Upload/release software Scoped permission Yes Separate grant No No
Edit/publish schemas Scoped permission Yes No Yes No
Edit/push parameters Scoped permission Yes Separate grants As granted No
Read/export audit Scoped permission Yes As granted As granted Yes

SuperAdmin is a platform role; customer roles are membership-scoped. Membership management cannot grant SuperAdmin or rights the actor is not allowed to delegate. High-impact operations can use a proposed bank-configurable approval policy; at minimum preview target count and require a reason for block, transfer and remote support. An approval is invalidated if targets or payload change.

Claims, cookies and session

The current release uses the local managed identity store. Passwords are BCrypt hashes. Optional MFA uses RFC-compatible six-digit TOTP codes, five-minute pre-session challenges and ten one-time recovery codes. MFA secrets are encrypted with an installation-specific account security key held in the machine-protected DPAPI secrets file. Enabling or disabling MFA requires the current password and a valid TOTP/recovery factor. Federation with a bank identity provider remains a future option.

Forgotten-password recovery is optional and SMTP-backed. The public request returns the same result for every address, limits repeated issuance, and delivers a random single-use token only for an enabled matching account. Tokens expire after 30 minutes, are stored only as SHA-256 hashes, and are invalidated after use. Resetting a password revokes active sessions but preserves MFA. SMTP credentials are DPAPI-protected. When email recovery is not configured, customer or platform administrators perform an authorized password reset from user administration.

Claims carry user ID and customer-scoped feature permissions. A CustomerId claim is only context and is revalidated. The portal uses secure HttpOnly cookies, strict SameSite policy and antiforgery validation on state-changing MVC actions. No authenticated session is created until an enabled MFA account completes its second factor.

Session stores convenience state, not permissions, commands or unsaved durable business drafts. Use distributed cache and a protected shared key ring. Session loss prompts customer reselection; it must never select another customer silently. ASP.NET Core session is ephemeral and non-locking, so concurrent tabs cannot rely on a shared selected-customer value for authorization. Explicit customer routes plus request context avoid cross-tab customer-switch errors. Microsoft session guidance.

DataService verifies service identity and signed actor delegation, and resolves current permissions server-side. Plain metadata such as x-customer-id or x-user-id is insufficient. Worker identities have narrowly scoped ingest/dispatch privileges and cannot impersonate a portal administrator. Revocation and customer suspension are checked before sensitive writes, dispatch and remote-session admission; permission caches must be versioned and invalidated.

Repository and resource enforcement

Safe customer transfer

  1. SuperAdmin requests transfer with source/target customer, expected assignment version and reason. Lock device assignment against concurrent changes.
  2. Quarantine the device; cancel undispatched work, prevent new work, terminate remote sessions and invalidate old delivery grants.
  3. Revoke credentials and old broker/shadow access; clear pending transport state. Require reset or verified removal of customer data and credentials on the terminal.
  4. Keep transfer Pending until cleanup is verified. An offline device cannot be activated under the new customer merely by updating SQL.
  5. Atomically close assignment history, increment AssignmentEpoch and create new assignment. Clear old groups, tags and placement; retain old audit and historical telemetry under the source customer.
  6. Issue fresh enrollment authorization and credentials. Activate for the target customer only after identity and cleanup verification.
  7. Reject old acknowledgements, tickets and messages by assignment epoch. Historical records are not re-labeled as belonging to the new customer.

Retirement uses the same credential/work/session shutdown rules without a new assignment.

Remote support and sensitive data

Issue short-lived, one-time connection tickets bound to customer, device, assignment epoch, actor, session and permitted mode (view/control). Validate origin and membership, audit start/stop, expire idle sessions and revoke immediately on permission loss or transfer. Ticket material must not appear in logs or long-lived URLs; prefer authenticated same-origin admission and an initial ticket message before any frames flow.

Payment credentials, PIN data, PAN/track data and cryptographic key material must never enter ordinary telemetry, screen recordings, logs or schema exports. Screen masking and payment-screen suppression require terminal-agent support; unsupported models cannot be offered unrestricted remote control over sensitive screens. No arbitrary terminal shell is included. Generic secret parameter fields use secret references and write-only replacement; payment key injection remains a separate controlled subsystem.

Isolation acceptance tests

For every sensitive endpoint and RPC: customer A cannot read, edit, export, command or connect to customer B's resources using guessed IDs, mixed parent/child IDs, forged metadata, stale membership or bulk selections. Test the same cases through the broker, downloads, remote tickets and delayed worker jobs. Verify last-admin protection, concurrent transfers, credential revocation and cross-tab customer changes.

DESIGN BASELINE / CHAPTER 04Markdown source ↗

Data model and service contracts

Historical design requirements: consult chapter 30 for the current implementation and outstanding work.

Current additions: migrations 014/015 implement tenant-scoped DeviceLocationHistory with reported/manual source, label and actor. The service exposes bounded location history and a Device Write manual-location command. Current SQL also contains the model catalog, command/deployment/application tables, IoT certificate lifecycle, user/role/audit records and current-save parameter workspace described in later chapters. Proposed revision/publish aggregates below remain design material unless chapter 30 says they are implemented.

Logical relational model

This is a proposed logical schema, not production DDL. SQL Server is the working database choice. All timestamps are UTC; display timezone belongs to user/customer preferences. Immutable IDs are independent of serial numbers, bank TIDs and merchant IDs.

Aggregate / tables Important keys and fields Invariants
Customer CustomerId, Code, Name, Status, TimeZone, RowVersion Unique customer code; active customer has an active admin
User, CustomerMembership, RoleGrant UserId, CustomerId, Role, Status, AuthzVersion Unique user/customer membership; platform role separate
DeviceInventory DeviceId, Manufacturer, SerialNumber, Model, Platform, Lifecycle Platform-owned; proposed unique manufacturer + serial
DeviceAssignment, AssignmentHistory DeviceId, CustomerId, AssignmentEpoch, StartUtc, EndUtc, RowVersion At most one current assignment per device
DeviceCredential CredentialId, DeviceId, Epoch, Fingerprint, Status, ExpiresUtc No plaintext private key; revoked credentials cannot connect
Merchant, Site, DevicePlacement CustomerId, MerchantId, SiteId, DeviceId, dates Same customer; placement is not device ownership
DeviceGroup CustomerId, GroupId, ParentGroupId, Name, RowVersion No cycles; same-customer parent; proposed depth limit 8
DeviceGroupMember CustomerId, DeviceId, GroupId One primary group per assigned device
Tag, DeviceTag CustomerId, TagId, NormalizedName, DeviceId Unique normalized tag per customer; many tags per device
DeviceState CustomerId, DeviceId, Epoch, LastReceivedUtc, ReportedUtc, Sequence, Payload Current snapshot, one per assignment; capabilities and freshness
TelemetryEvent CustomerId, DeviceId, Epoch, EventId, ReceivedUtc, Type Time-partitionable; deduplicate by device/epoch/event
DeviceApplication CustomerId, DeviceId, PackageId, Version, LastSeenUtc Observed inventory, not desired software
Application, ApplicationVersion CustomerId, ApplicationId, VersionId, Platform, Manifest, Hash, ObjectKey, ReleaseState Immutable version; approved artifact only
ParameterSchema, SchemaVersion CustomerId, SchemaId, ApplicationId, VersionId, DefinitionJson, State, Hash Published version immutable
CatalogDefinition, CatalogRecord CustomerId, SchemaVersionId, CatalogId, RecordId, ValuesJson Version-scoped typed references
ParameterTemplate, TemplateVersion CustomerId, ApplicationId, SchemaVersionId, ValuesJson Copy/apply input; never implicit live inheritance
DeviceConfiguration, ConfigurationRevision CustomerId, DeviceId, ApplicationId, SchemaVersionId, RevisionId, Json, Hash One current draft and published pointer per device/app; immutable revisions
Deployment, DeploymentTarget CustomerId, DeploymentId, DeviceId, ArtifactOrRevisionId, Epoch, State Frozen target set and payload; one per target
DeviceCommand, CommandAttempt CustomerId, CommandId, DeviceId, Epoch, Type, ExpiresUtc, State Idempotency key and per-attempt outcome
RemoteSession CustomerId, SessionId, DeviceId, Epoch, ActorId, Mode, ExpiresUtc One controlling operator per device by default
Outbox, Inbox, IdempotencyRecord CustomerId, MessageId, DedupKey, Hash, LeaseUntil, Attempts Atomic write/outbox; transactional consume/dedup
AuditEvent CustomerId optional, ActorId, Action, ResourceId, Outcome, Reason, CorrelationId Append-only app access; sensitive values redacted

Use composite unique keys such as (CustomerId, DeviceId, AssignmentEpoch) as referenced ownership keys for operations and history. Global inventory remains platform-owned; the current assignment projection provides customer-scoped joins. A composite FK on (CustomerId, GroupId) prevents foreign groups. Parent traversal and cycle validation run in a transaction with locking/concurrency protection.

Indexes and concurrency

Start with customer-first indexes on device status/last-seen, group and tag lookups, command state/due date, application identity/version, and audit timestamp. Use keyset pagination for growing telemetry/audit lists, and bounded paging for device grids. Store latest device state separately from append-only event history. Review actual execution plans before adding speculative indexes.

Use SQL rowversion or equivalent expected-version tokens for device assignment, group editing, drafts and approvals. A conflict returns current version information without overwriting another operator's changes. Worker claims use transactional leases with an owner, expiry and fencing token; expired leases may be reclaimed. An old lease cannot mark a newer claim complete.

Service catalogue

Version protobuf packages as uic.tms.v1. Keep transport DTOs separate from SQL entities. The following methods are contract proposals, not generated API code.

gRPC service Representative methods Authorization
CustomerService CreateCustomer, SuspendCustomer, ListCustomers SuperAdmin for lifecycle
MembershipService InviteAdmin, GrantRole, RevokeMembership Scoped admin; constrained delegation
DeviceInventoryService RegisterDevice, AssignDevice, StartTransfer SuperAdmin
DeviceService ListDevices, GetDevice, UpdateProperties, SetPlacement Customer-scoped permissions
OrganizationService CreateGroup, MoveGroup, SetDeviceGroup, SetTags Customer fleet administration
SchemaService SaveDraft, ValidateDraft, PreviewMigration, PublishVersion Schema edit/publish permissions
ConfigurationService GetDraft, SaveDraft, ResolveTemplate, PublishRevision Parameter permissions
ApplicationService InitiateUpload, CompleteUpload, ValidateArtifact, ReleaseVersion Upload/release permissions; validator service role
OperationService PreviewTargets, CreateDeployment, QueueCommand, CancelPending, GetProgress Operation-specific permission
DeviceIngestService RecordTelemetryBatch, RecordInventory, AcknowledgeCommand Device gateway identity + verified enrollment
DispatchService LeaseWork, RenewLease, RecordDispatchAttempt Dispatcher role only
RemoteSessionService AuthorizeSession, RedeemTicket, EndSession Remote permission + relay identity
AuditService SearchAudit, RequestExport Scoped audit access

Contract conventions

Each customer RPC has a CustomerId selector and authenticated context; each mutation has RequestId/IdempotencyKey, optional ExpectedVersion and CorrelationId. Device-bound work includes AssignmentEpoch. DataService verifies all selectors against identity and current ownership. Use explicit enums with Unspecified = 0; prohibit unspecified values for required actions. Preserve protobuf field numbers and reserve removed fields.

Idempotency uniqueness is (CustomerId, ActorOrServiceId, RpcMethod, IdempotencyKey). Store a canonical request hash and durable result; the same key with a different payload returns a conflict. Retain keys at least as long as the supported retry window, proposed seven days for operator mutations and the command lifetime plus seven days for delivery results.

Return stable error codes and safe field-level validation details. Proposed mappings: malformed input → InvalidArgument; missing/expired identity → Unauthenticated; insufficient capability → PermissionDenied; inaccessible customer resource → NotFound; optimistic conflict → Aborted; unmet lifecycle condition → FailedPrecondition; throttling → ResourceExhausted; dependency failure → Unavailable. No SQL exception text reaches the browser.

Set proposed deadlines of 5 seconds for reads and 15 seconds for ordinary mutations; expensive scans, exports and deployments are asynchronous jobs. Propagate cancellation. Retry reads and idempotent mutations only, with bounded exponential backoff and jitter. A timeout is an unknown outcome until the original idempotency key or operation ID is queried.

Example command request

{
  "customerId": "bank-example",
  "deviceId": "device-example",
  "assignmentEpoch": 4,
  "commandType": "REBOOT",
  "idempotencyKey": "example-request-001",
  "reason": "Scheduled maintenance",
  "expiresAtUtc": "2026-09-24T02:15:00Z"
}

All identifiers are illustrative. Actor identity comes from a verified delegation token, not this JSON. The response returns CommandId and Queued/PendingApproval state, never a fabricated device success.

Dapper transaction example

-- Illustrative SQL shape; final table names and DDL are pending.
UPDATE DeviceConfiguration
SET DraftJson = @Json
WHERE CustomerId = @CustomerId
  AND DeviceId = @DeviceId
  AND ApplicationId = @ApplicationId
  AND RowVersion = @ExpectedVersion;
-- Require one affected row. In the same transaction, append audit.
-- Publishing additionally inserts an immutable revision and outbox event.

Use a service-owned SQL connection and explicit transaction passed to every related Dapper call. No dynamic schema/table names or SQL fragments may come from user input. Backup restore, migration rollback strategy and compatibility tests are deployment responsibilities.

Implemented model catalog

The local implementation now includes a global DeviceModel catalog with ModelId, Brand, Model and OS (Linux or Android). Brand + Model + OS is unique, with case-insensitive brand/model matching. SuperAdmins maintain the catalog; authenticated bank admins may read it. Every registered device references a required ModelId. Fleet displays derive brand, model and OS from that catalog, so corrections apply consistently to linked devices.

OperatorApi exposes ListModels and SaveModel. CreateDevice now requires model_id; its original free-text model/platform request fields are deprecated. Migration 002 backfills legacy model/OS pairs under brand “Unspecified”, preserving existing device identities and assignments. See the development guide for operational details.

DESIGN BASELINE / CHAPTER 05Markdown source ↗

Device connectivity and operations

Historical design requirements: consult chapter 30 for the current implementation and outstanding work.

Current decision: the deployed transport is the local MQTTnet mutual-TLS gateway using the uic/tms/v1/devices/{deviceId} contract. AWS IoT is not deployed. Android UIC Home and Linux xTMSAgent implement this contract; see chapters 10 and 33. The comparison below is retained as decision history.

Transport recommendation

Start the compatibility pilot with an adapter around the existing MQTT broker, then choose the production broker using measured fleet, availability, certificate and hosting requirements. Design one canonical application protocol so AWS IoT Core can be added without changing portal business rules. Do not run two active transports issuing independent commands to the same device.

Dimension Adapt existing MQTT AWS IoT Core
Legacy terminal fit Existing protocol and field experience Requires credential/topic and agent compatibility validation
Operations Team owns patching, persistence, failover and capacity Managed broker with AWS-specific policy/operations
Identity Add per-device identity, revocation and tenant mapping Per-device certificates and tightly scoped IoT policies
Device state TMS maintains desired/reported state Shadows optional; SQL business state remains authoritative
Hosting Bank-hosted, private cloud or cloud AWS region and connectivity constraints
Cost Infrastructure plus operational support Model connections, messages, shadows, rules and data transfer
Decision gate Isolation, recovery and load tests Agent proof, policy tests, region and cost review

AWS IoT Core supports MQTT QoS 0 and 1; QoS 1 can produce duplicate delivery and does not prove command execution. Device Shadows can represent desired/reported state, but should not be used as a queue of one-time reboot commands. AWS MQTT documentation, Device Shadows.

Canonical topic and message design

Proposed new-agent namespace: uic/tms/v1/devices/{deviceId}/telemetry, /inventory, /commands, /results, /config/request, /config/response. Device identity is globally unique; broker policy binds credentials to that exact device. Customer and AssignmentEpoch are resolved from trusted enrollment and compared with signed message context. Tenant identifiers in payloads cannot override that mapping.

Device may publish only its report/result/request topics and subscribe only to its own command/response topics. Deny wildcard subscriptions, arbitrary topic publishing and anonymous access. Backend transport identities have separate permissions. Use TLS; prefer unique device certificates where supported. Credential provisioning, rotation, expiry and revocation must be operational workflows.

Envelope fields: protocolVersion, messageId, deviceId, assignmentEpoch, sentAtUtc, sequence, bootId, correlationId and typed payload. Server also records receivedAtUtc. Use bootId + sequence to distinguish device restart from stale data; device clock is not authoritative for receipt or command expiry. Bound payload size, schema depth, collection lengths and per-device rate.

Never retain one-time commands. Keep pending work in the durable operation store and deliver only if unexpired, authorized and still assigned at the current epoch. QoS 0 is acceptable for replaceable heartbeats; important results/config acknowledgements require QoS 1 plus application-level retry/deduplication. Ingress acknowledges application-level durability after durable queue or DataService acceptance, not merely receipt into an in-memory handler.

Existing service reuse

Observed source Reuse candidate Required adaptation
MQTT/TMSMQTT.csproj .NET worker, MQTTnet, Dapper, service hosting Runtime alignment; isolate broker and business persistence
MQTT/Services/MqttAuthorizationService.cs Own-topic checks Remove global customer broadcast; fail closed without authenticated identity; customer/epoch mapping
MQTT/Models/MqttTopics.cs Existing notify/cmd/status and config handshake topics Versioned translation adapter for existing agents
MQTT/Data/TmsRepository.cs Existing state/task semantics Replace legacy table access with typed DataService calls
MQTT/Program.cs Broker, notification listener and task workers Outbox leasing and idempotent result handling
TMSRemoteControlServer WebSocket relay, H.264 frame forwarding, keyframe cache Scoped tickets, origin checks, WSS, session routing and revocation

Both inspected projects target net9.0. This is source-level reuse assessment only; no compatibility build or device test has been performed. Preserve legacy wire formats through a translation boundary until representative Android and Linux terminals pass contract tests. Terminal firmware capabilities are not yet verified.

The existing relay viewer uses a static query-string API key, and its documented terminal token is derived from a shared secret and terminal ID. Those authentication patterns are not the new authorization model. Keep the video forwarding mechanism; replace admission and session ownership. Audit and health endpoints must not expose other customers' sessions.

Durable operation state machine

Draft → [PendingApproval] → Queued → Dispatched → Accepted → Running → Succeeded
                            │           │          │          └→ Failed
                            │           └──────────┴───────────→ TimedOut
                            ├→ Cancelled
                            └→ Expired

Dispatched means the gateway handed the command to transport. Accepted means the agent acknowledged it. Succeeded requires device-reported completion evidence appropriate to the operation. Reboot may require a new bootId/uptime report; install requires observed package/version; parameter apply requires matching revision/hash. An elapsed timeout records uncertainty; late results are attached as reconciliation events without silently rewriting the audit trail. Terminal results are monotonic and sequence-checked.

Create operation + target snapshot + audit + outbox in one transaction. Dispatcher leases work, rechecks ownership/permission/expiry, publishes the same CommandId on retries and records attempts. Agent persists deduplication state and returns the previous result for repeated CommandId. If a legacy agent cannot guarantee deduplication, disable automatic retry for unsafe actions and expose an UnknownOutcome result for manual reconciliation.

Cancellation prevents queued work from starting; it cannot recall an already executed reboot. A dispatched command is cancellation-requested only if the agent supports cancellation. Serialize conflicting app/config/block operations per device and application. A new desired state supersedes stale work explicitly, with audit.

Operation policies

Operation Required behavior
Reboot Capability check, reason, expiry, maintenance window; verify subsequent boot
Send message Bounded text; escape display; define delivery versus user-read acknowledgement
Block/unblock Separate desired and reported state; authorized reason; unblock cannot be inferred from timeout
Remote control Online and capable device; short-lived scoped session; view/control permission; visible session indicator
Application push Approved artifact, compatible platform/model/agent, disk/battery constraints, install result
Parameter push Published compatible schema/config revision, integrity check, validate before atomic apply

Block semantics must be defined per terminal agent: restrict payment application or device workflow while preserving the management channel so an authorized unblock remains deliverable. Blocking is not an acquirer-side payment-account suspension. Offline devices show PendingBlock until acknowledged.

Applications: APK and Linux ZIP

Lifecycle: Uploading → Quarantined → Validating → Approved → Released → Withdrawn. Upload uses an expiring customer/application-scoped grant, size limits and server-generated storage key. Completion verifies checksum and scans content. Do not trust extension, client MIME type or uploaded metadata.

APK validation extracts package identifier, version code/name, signing identity, platform requirements and compatible device constraints. Enforce signing continuity and downgrade rules. ZIP validation requires a defined manifest, target model/architecture, installation type, payload hashes and signed package policy. Reject path traversal, absolute paths, dangerous symlinks and decompression bombs. Uploaded archives are never executed on the server.

Release produces an immutable artifact and approval record. Deployment freezes target devices, software version, schedule and assignment epochs. Use canary batches, bounded concurrency, pause thresholds and per-device outcomes. A signed HTTPS grant enables download; terminal verifies manifest/hash/signature before staging, installation and reporting. Renew an expired download grant only after reauthorization. Rollback is a new deployment and is offered only when the package/agent supports it.

Telemetry and location

Collect typed device properties, OS/firmware versions, battery/storage/network health, app inventory and optional location with source, accuracy and timestamp. Separate reported time from received time and display freshness. Proposed offline threshold is three missed heartbeat intervals plus grace; tune by network and terminal capabilities.

Location collection is customer policy controlled with role-limited map access and retention. A last-known coordinate must not be presented as live tracking. Keep raw location out of broad audit exports. Retention proposals: current state continuously replaced, raw telemetry 30 days, operational results 180 days, audit 365 days; each requires bank/residency review before production.

Failure and recovery cases

Test broker restart, duplicate/out-of-order reports, replay after transfer, queue outage, SQL outage, expired certificates, terminal clock skew, storage download failure and partial bulk deployment. Queue outage must not accept an important report and silently lose it. Portal uses last-known state with a stale indicator when live ingest is unavailable. Payment traffic stays independent from this management path.

DESIGN BASELINE / CHAPTER 06Markdown source ↗

Parameter schemas and configuration

Implementation status: see Parameter workspace and application delivery. This chapter is the broader design baseline; not every acceptance criterion is implemented.

Design objective

A visual schema designer lets authorized bank staff define parameter forms without writing application code. The same published schema drives device parameter editing, server validation, template application and terminal payload generation. The implementation belongs entirely to this solution: Razor views plus a focused JavaScript/TypeScript editor module, MVC endpoints and gRPC use cases.

The reference editor was inspected for interaction concepts: catalog/tree navigation, field properties, preview contexts, row/column/span layout, typed fields and import comparison. Its framework, service model and destructive overwrite behavior are not adopted. No external project references or branded components are required.

Designer workspace

Region Contents Behavior
Header Customer, application, schema version, Draft/Published badge Persistent ownership context; published version read-only
Left: structure Catalog tables, root node, child/repeatable nodes, fields Add, rename, reorder; stable IDs survive label changes
Center: canvas Form layout with sections, rows, columns and fields Move/resize fields; keyboard alternatives; design/preview toggle
Right: properties Type, key, label, help, required/default, constraints, reference Immediate local feedback; authoritative server validation
Bottom: validation Errors, warnings, compatibility and version diff Click error to select field/node; no publish while invalid
Action bar Save draft, preview, compare, import/export, publish Publish requires impact summary and permission

Preview uses the same renderer as the device parameter form. Responsive preview includes wide and narrow layouts. A schema is a declarative document; it cannot contain executable JavaScript, arbitrary HTML, SQL or remote code references.

Definition format

Use a versioned UIC TMS schema DSL, with formatVersion distinct from published schema version. It is not implicitly a standards-compliant JSON Schema document. Support text, textarea, integer/decimal, boolean, enum, date, hex, port, catalog reference, secret reference and controlled file reference. Field IDs and node IDs are immutable; labels and translated help text may change.

Validation includes required, requiredOnApply, length/range, enum membership, hex format, reference cardinality and safe regular expressions with timeout/complexity limits. Bound tree depth, repeat counts, total fields and document size. Stable record keys distinguish repeated acquirers/issuers; disallow duplicate keys. Published schemas identify compatible application versions, terminal platforms and serializer version.

{
  "formatVersion": 1,
  "applicationKey": "bank-payment",
  "schemaVersion": 1,
  "catalogs": [{
    "id": "hosts",
    "label": {"en": "Connection profiles", "es": "Perfiles de conexión"},
    "fields": [
      {"id": "host", "type": "text", "required": true},
      {"id": "port", "type": "port", "default": 443}
    ]
  }],
  "root": {
    "id": "terminal",
    "fields": [
      {"id": "terminalId", "type": "text", "requiredOnApply": true,
       "layout": {"row": 1, "column": 1, "span": 6}},
      {"id": "hostProfile", "type": "reference", "catalogId": "hosts",
       "required": true, "layout": {"row": 1, "column": 7, "span": 6}}
    ],
    "children": [{"id": "acquirers", "repeatable": true,
      "recordKey": "acquirerCode", "fields": [
        {"id": "acquirerCode", "type": "text", "required": true}
      ], "children": []}]
  }
}

The example is illustrative; validation rules and serializers must be specified and tested before implementation. Catalog references resolve only inside the same customer and pinned schema/catalog revision. Secret fields return a masked/set indicator; leaving them unchanged preserves the secret reference. Clear and replace are explicit actions with separate authorization.

Version lifecycle

Draft → Validated → Published → Deprecated → Retired. Save drafts with optimistic concurrency and durable autosave. Published versions are immutable; edit by cloning to a new version. Deprecation prevents new use by default but does not invalidate working devices. Retirement is blocked while required references remain unless an approved migration handles them.

Publishing validates the definition server-side, computes a canonical hash, records author and timestamp, identifies affected applications/devices/templates, and stores an immutable version. It never automatically deploys parameters to devices.

Import is staged: parse bounded content → validate format → show diff and compatibility impact → create draft/new version. Export excludes secret values and customer-specific records unless explicitly requested and authorized. Imports cannot overwrite published versions or delete existing values silently.

Editing and applying device parameters

  1. Select customer, device and application; load current published schema plus draft/config revision and concurrency token.
  2. Render catalog references and nested/repeatable records from the schema. Show defaults, current values, secret status and validation feedback.
  3. A template copies values into a draft. requiredOnApply fields prompt for device-specific values; unresolved fields block publication.
  4. Server validates types, unknown keys, reference ownership, compatibility and secrets. Save a draft without changing the terminal.
  5. Publish a resolved immutable revision, pinning schema, catalogs, serializer and artifact hashes. Show a value diff with secrets redacted.
  6. Push via a deployment; device downloads the authorized artifact, validates it, applies atomically and acknowledges revision/hash.
  7. Portal distinguishes draft, desired published revision, delivered revision and device-reported applied revision. Drift is visible; successful transport is not successful application.

Proposed release-one precedence is schema defaults → explicitly applied template → explicit device values. The result is materialized into a device revision. Groups/subgroups and tags are targeting tools, not automatic parameter inheritance. Moving a terminal between groups never mutates its effective configuration. Optional future group inheritance would require a separate decision defining precedence, exceptions and conflict behavior.

Schema evolution and rollback

Classify added optional fields/defaults as potentially compatible; removed fields, required fields without values, type changes, changed reference cardinality and renamed stable IDs require an explicit migration plan. Preview impact against saved configurations and templates; report per-device errors. Never purge old values just because a field disappears from the new schema.

Migrate into new draft revisions transactionally or through resumable batches, keeping the old published revisions intact. A rollback deploys a known revision after confirming application/agent compatibility. If the terminal cannot apply atomically, document the safe update procedure and expose partial/failed state rather than claiming rollback support.

Acceptance criteria

DESIGN BASELINE / CHAPTER 07Markdown source ↗

Portal experience

Historical design requirements: consult chapter 30 for the current implementation and outstanding work.

Observed UIC Connect reference

The existing demo portal was inspected in the signed-in browser on 23 September 2026: Home, Device Setup & Control, Device Status Monitor and Device Tag. Observed patterns include a dark navy left sidebar, UIC Connect branding, cyan/turquoise/blue accents, white top bar, pale workspace, breadcrumbs, search panels, paginated tables, and a top-right account menu.

Home presents transaction and device-management tiles. Setup & Control filters by Cloud MID, device serial/type and payment processor; its table leads with merchant identity. Status Monitor separates heartbeat time and device timestamp and includes payment-app version and IP information. Tags exposes an intersection-selection control. These are UI observations, not evidence of backend implementation or successful device operations. No live data was changed.

Adaptation for banks

Retain UIC visual continuity and familiar Device Management and Upgrade Manager language. Replace the merchant-first working context with a clearly visible bank/customer selector and fleet overview. Customer creation and device assignment appear only in the platform workspace. A customer administrator's Add Device action must not imply access to unassigned platform inventory.

Proposed design tokens: navy navigation #192235, blue primary #315DAD, teal highlight #21B9C5, pale workspace #F3F6FB, white surfaces and dark text #17243B. These are design approximations from visual inspection, not extracted official brand values. Use accessible contrast; reserve light turquoise for accents rather than small white text. Typography uses the installed system sans-serif stack.

Information architecture

Workspace Navigation Primary purpose
Platform Overview, Customers, Global Inventory, Assignments, Platform Audit, Settings SuperAdmin lifecycle and governance
Customer Overview Health, offline devices, drift, recent failed operations
Customer Device Management: Devices, Groups, Tags, Map Fleet browse and organization
Customer Operations: Jobs, Remote Sessions Durable commands and support sessions
Customer Upgrade Manager: Applications, Versions, Deployments APK/ZIP catalogue and rollouts
Customer Parameters: Schemas, Catalogs, Templates Schema design and reusable configuration
Customer Merchants & Sites Optional device placement records
Customer Administration: Users & Roles, Audit, Settings Bank-scoped administration

Explicit customer context is shown in the page header and included in routes such as /customers/{customerId}/devices/{deviceId}. Authorized users can switch customers, but a page already open retains its original context; changing another tab cannot redirect its mutations.

Screen specifications

Fleet overview

Cards show assigned devices, online/stale/offline, blocked/pending-block, configuration drift and deployment failures. Every count is filtered by the current customer and shows freshness. Click a card to open the corresponding fleet filter. Show scheduled work and recent exceptions, with no transaction-revenue emphasis.

Device list

Primary columns: serial/device ID, model/platform, group path, merchant/site (optional), connection and last seen, reported app version, configuration status, desired/reported block state and tags. Server-side filter/search/sort/paging. Filters support descendants of a group and tags matching Any or All, continuing the current tag intersection concept.

Selection must distinguish Selected on this page from All matching results. Before a bulk operation, server resolves and freezes the target set and exclusions, shows count, customer, compatibility, schedule and expiry, and returns a preview token/hash. Execution verifies that preview and current assignment epochs. New devices matching a filter later do not join an existing deployment silently.

Device detail

Header shows customer, serial/model, connection freshness, group path and supported operations. Tabs: Overview, Telemetry, Properties, Location, Software & Apps, Parameters, Operations, Audit. The location tab shows source, accuracy and age. Software distinguishes reported installed inventory from desired releases. Unsupported controls are disabled with a reason, not hidden without explanation.

Groups and tags

Two-pane group tree and device list. Move a subgroup with explicit descendant impact preview and cycle validation. A non-empty group must be emptied/reparented before deletion; no silent cascade of devices. Tags have unique customer-local names, edit/merge workflows and Any/All filtering. Renaming a tag does not change frozen historical deployment selections.

Application catalogue and deployments

Application detail separates logical app, uploaded versions, validation results, approvals and deployments. Clearly display Android APK versus Linux ZIP and compatibility. Deployment wizard: Select release → Select targets → Review exclusions → Schedule/canary → Confirm. Progress table shows each device's download/install/result and retry eligibility.

Schema and parameter editor

Three-pane workspace: structure tree, form canvas/live preview, field properties. Header shows application, customer and version. Validation tray lists errors and impact. Device parameter forms use the same renderer, including nested records, reference pickers and masked secret fields. Save Draft, Publish Revision and Push are distinct actions.

Remote-control session

Admission screen shows customer/device, reason, permitted mode, operator and session duration. Viewer shows connection quality, capability, elapsed/remaining time and Stop. Display a conspicuous active-control indicator; require permission for input control separately from viewing. Screen traffic is not recorded by default. Connection loss shows disconnected state and does not automatically transfer control to a different operator.

Interaction and accessibility rules

Use semantic forms, persistent labels, keyboard focus, visible validation summaries and text alongside status colors. Provide keyboard alternatives for drag/reorder actions. Target WCAG 2.2 AA during implementation validation. Desktop is the primary authoring surface; at narrow widths the sidebar collapses and the schema editor becomes sequential panels. Tables may scroll within their container without forcing the whole page to scroll sideways.

Localize dates/numbers and display timezone. Preserve serials, identifiers and parameter keys verbatim. Proposed languages are English and Spanish. Empty states explain the next permitted action; failures preserve entered work. Saving a draft is not advertised as device success. Long jobs survive browser closure and can be resumed from Operations.

Visual concept in the HTML guide

The HTML guide includes an illustrative bank fleet view and a schema designer sketch using fictitious devices and counts. These are design artifacts, not screenshots of a working TMS. The guide's navigation/search/print controls are functional documentation features; mock portal buttons are intentionally non-operational.

DESIGN BASELINE / CHAPTER 08Markdown source ↗

Delivery plan and architecture decisions

Historical design requirements: consult chapter 30 for the current implementation and outstanding work.

Phased implementation

Phase Deliverables Exit criteria
0 — Validate Runtime/database/hosting decisions; agent capability inventory; broker and relay spikes Representative Android and Linux device handshake; agreed ownership model; approved stack baseline
1 — Foundation Separate solution, MVC shell, identity, distributed session, gRPC, Dapper migrations, CI Two customers isolated end to end; no portal SQL access; HTTP/2 through real proxy; revoked access denied
2 — Fleet Customer onboarding, global inventory, assignment, groups/tags, telemetry, app inventory, location Only super admin assigns; last-admin protection; correct freshness; replay-after-transfer rejected
3 — Operations Outbox/inbox, dispatcher, reboot/message/block, durable jobs, audit Duplicate/reordered messages safe; offline expiry works; failures do not report success
4 — Applications Quarantine/validation, APK/ZIP catalogue, canary deployments, downloads Invalid/hostile packages rejected; compatible device install verified; partial failure visible
5 — Parameters Schema WYSIWYG editor, catalogs, templates, versioning, device forms and push Nested schema authored visually; server validation; migration preview; revision/hash acknowledgement
6 — Remote support Adapted relay, scoped tickets, WSS, view/control admission, revocation Cross-customer sessions denied; payment-screen controls validated; reconnect and relay routing tested
7 — Production readiness Load/soak tests, backup restore, observability, security review, operator runbooks Agreed capacity/SLOs achieved; restore drill; supported runtime; pilot-bank acceptance

These are dependency stages rather than calendar estimates. Start one complete vertical slice early: authenticated customer administrator lists one assigned device through MVC → gRPC → Dapper, queues one safe command, and observes an audited result. MQTT/AWS feasibility and relay compatibility can be investigated before their feature phases.

Decision register

ADR Decision Status / consequence
001 Independent TMS solution with UIC Connect identity and visual conventions Required; no dependency on separate reference solution
002 Kestrel MVC, Claims + Session, .NET 8 Required baseline; runtime upgrade gate before production
003 TMS.DataService gRPC HTTP/2; Dapper persistence Required; portal and adapters cannot bypass service policies
004 Customer is bank/institution tenant; only SuperAdmin creates/assigns Required; enforced at service boundary
005 SQL Server in separate TMS database Proposed; verify UIC operational conventions and hosting
006 Existing MQTT adapter for first compatibility pilot Proposed; production broker decided after reliability/cost review
007 Durable commands, outbox/inbox, application acknowledgements Proposed baseline; avoids broker-delivery-as-success
008 One primary group, nested subgroups; many tags Proposed; groups/tags do not grant permissions
009 Per-device/app materialized parameters; no implicit group inheritance Proposed; predictable behavior during group moves
010 Immutable schemas/releases; explicit migration and deployment Proposed; rollback preserves evidence
011 Reuse relay transport, replace shared viewer authentication Proposed; short-lived scoped access
012 Object storage for packages and configuration artifacts Proposed; private access and quarantined upload

Decisions needed before implementation

  1. Runtime: approve a supported production version and upgrade timing while preserving the requested MVC/gRPC design.
  2. Hosting: bank-hosted, UIC-managed cloud, or both; database availability, region/residency and environment ownership.
  3. Device transport: supported OS/firmware/agent versions, certificate capability, current protocol guarantees and legacy constraints.
  4. Identity: the current local store includes optional TOTP MFA, recovery codes and SMTP password recovery. Decide whether a shared UIC or bank identity provider will replace or federate with it, and define customer invitation and emergency last-administrator recovery policy.
  5. Fleet semantics: one primary group versus multiple memberships, optional merchant placement fields, parameter templates versus future inheritance.
  6. Operational policy: fleet size, heartbeat interval, retention, remote consent/masking, block meaning and approval thresholds.
  7. UI toolkit: existing licensed controls and UIC design assets available for MVC; validate before choosing a new component vendor.

Verification strategy

Use unit tests for invariants and schema validation, SQL integration tests for tenant filtering/concurrency/transactions, and contract tests for protobuf evolution and agent messages. End-to-end tests cover identity → MVC → gRPC → SQL → dispatch → acknowledgement. Verify real Android and Linux terminals; a simulator alone cannot prove reboot, installation, screen capture or payment-screen masking.

Critical scenarios: foreign customer IDs; stale membership; forged service metadata; group cycles; duplicate commands; worker crash after publish; broker reconnect storm; device offline beyond expiry; partial app installation; schema migration incompatibility; expired download grants; transfer during deployment; late results from the old assignment; remote session revocation; session-cache failure; database restore and outbox replay.

Do not promise exactly-once transport delivery. Demonstrate idempotent effects within defined protocol support, and explicitly expose uncertainty for legacy devices that cannot supply that guarantee.

Observability and runbooks

Correlate portal request, RPC, operation, outbox message and device result using stable IDs. Metrics: ingest lag, last-seen freshness, queue age, dispatch latency, retries, duplicate suppression, failed deployments, SQL p95, gRPC errors and active remote sessions. Avoid serial/location/secrets in broad metric labels.

Runbooks must cover broker outage, certificate rotation/revocation, stuck operation reconciliation, quarantined transfer, artifact withdrawal, schema rollback, last-admin recovery and restore/replay. Audit exports are permission checked, scoped and access logged. Health endpoints expose readiness/liveness without revealing customer devices or sessions.

Review checklist for this baseline

Confirm the customer operating model, runtime upgrade decision, database choice, broker pilot, group/template semantics and production policies. After that, implementation can start with the foundation vertical slice. This documentation does not claim security certification, validated bank compliance or production readiness.

DESIGN BASELINE / CHAPTER 09Markdown source ↗

Evidence and technical references

Review scope

Originally prepared 23 September 2026 from read-only references. Implementation and physical verification continued through 26 September 2026; chapters 30, 33 and 34 now record the authoritative runtime and device evidence. The original evidence list remains provenance for initial architectural choices.

Local evidence

Source Observation Design implication
Existing workspace: Merchant_Terminal_Identity_Chain.html Documents UIC MVC .NET 8, Claims/Session, gRPC, Dapper and SQL Server architecture Preserve the layer pattern; independent TMS database proposed
Existing workspace: UIC_Connect_Device_Parameters_and_Telemetry_Proposal.html Earlier merchant-module proposal for direct device configuration and telemetry Background only; current requested bank module adds groups, remote control and app management
D:/Source/repos/TMS_Source/MQTT/TMSMQTT.csproj net9.0; MQTTnet 4.3.7.1207; Dapper 2.1.35; SQL client Source reuse requires runtime/dependency assessment
D:/Source/repos/TMS_Source/MQTT/Program.cs Broker host plus polling/notification/housekeeping workers Adapt responsibilities behind service/transport boundaries
D:/Source/repos/TMS_Source/MQTT/Services/MqttAuthorizationService.cs Own-terminal topic checks plus global broadcast and internal service access Add scoped identity/epoch checks; remove customer cross-fleet broadcast
D:/Source/repos/TMS_Source/MQTT/Models/MqttTopics.cs Legacy terminal notify/status/cmd and parameter acknowledgement topics Preserve through compatibility adapter where needed
D:/Source/repos/TMS_Source/MQTT/Data/TmsRepository.cs Direct legacy SQL access for status, blocking, tasks and version information Rewrite persistence integration through TMS.DataService
D:/Source/repos/TMS_Source/TMSRemoteControlServer/TMSRemoteControlServer.csproj net9.0 Kestrel relay with Dapper dependency Separate runtime process or source adaptation needed
D:/Source/repos/TMS_Source/TMSRemoteControlServer/README.md and Endpoints/ViewerWsHandler.cs H.264 relay and static viewer API-key admission Reuse streaming mechanics, replace admission model
Separate schema reference: schemaTypes.ts, SchemaEditorPage.tsx, SchemaPreviewPane.tsx Catalog/tree schema, typed fields, layout, properties/preview and import comparison Reimplement interaction concepts within MVC; independent contracts

The separate reference solution's name and absolute path are intentionally excluded from the product documentation. It is a design reference only. Existing UIC compatibility is supported by the supplied architecture documents, not a completed audit of the entire merchant portal source repository.

Browser evidence

Inspected the existing Edge tab at UIC Connect demo, then the authenticated Home, Setup & Control, Status Monitor and Tags pages. Review covered visible branding, navigation, filters and table structures. Device operations and data correctness were not tested. Documentation mockups use fictional data and do not reproduce account credentials or merchant records.

Primary technical references

Confidence and unresolved validation

Required product capabilities come from the current request. Local implementation observations come from the specific files above. All new project structure, schema tables, RPC methods, SLOs, retention periods, permission roles beyond the two required administrator roles, and UI sketches are proposals. Broker high availability, source-code retargeting, terminal-agent behavior and production sizing remain unvalidated until implementation spikes and device tests.

DESIGN BASELINE / CHAPTER 10Markdown source ↗

Implemented device-agent integration contract

Implementation checkpoint: 26 September 2026. This contract applies to Android UIC Home and Linux A10-T xTMSAgent. See chapter 33 and the bilingual platform manuals for installation and acceptance.

Identity and onboarding

  1. A SuperAdmin onboards the exact manufacturer serial under one customer and one portal model.
  2. The agent receives or claims a unique device ID, assignment epoch, Device Secret and topic prefix. A device cannot create its own portal record.
  3. The agent creates a private key locally, requests an IoT certificate, confirms possession and connects with mutual TLS.
  4. The first MQTT admission that validates certificate, Device Secret, assignment and topic scope marks the device IoT Provisioned and closes further enrollment downloads.

Android test/debug enrollment is transferred to private app storage and encrypted with AndroidKeyStore. Linux xTMSAgent claims the already-onboarded serial from a protected customer bootstrap, stores enrollment as mode 0600 and removes the bootstrap file. Neither flow embeds a reusable terminal Device Secret in source or a fleet-wide APK/package.

Transport

Production defaults are HTTPS/WSS 5102 and MQTTS 5883. Development defaults are HTTPS 15102 and MQTTS 18883. Validate the server hostname and certificate; do not disable TLS checks.

MQTT identity is the canonical device UUID, not the human serial. Client ID and username are the device ID; password is the unique Device Secret; the client certificate fingerprint must be bound to that same device and assignment.

Direction Topic
Device publishes uic/tms/v1/devices/{deviceId}/telemetry
Device publishes uic/tms/v1/devices/{deviceId}/results
Device publishes uic/tms/v1/devices/{deviceId}/config/request
Device subscribes uic/tms/v1/devices/{deviceId}/commands
Device subscribes uic/tms/v1/devices/{deviceId}/receipts
Device subscribes uic/tms/v1/devices/{deviceId}/config/response

Wildcard and foreign-device access is denied. Use QoS 1, non-retained messages and bounded payloads. HTTPS carries application/parameter artifacts; WSS carries Android remote frames/input. MQTT does not carry APKs, native packages or screen frames.

Envelope and storage receipt

{
  "protocolVersion": 1,
  "messageId": "33333333-3333-4333-8333-333333333333",
  "deviceId": "11111111-1111-4111-8111-111111111111",
  "assignmentEpoch": 1,
  "sentAtUtc": "2026-09-26T18:00:00Z",
  "payload": {}
}

Persist the exact serialized envelope before publish. Remove it only after a matching receipt such as:

{"protocolVersion":1,"messageId":"33333333-3333-4333-8333-333333333333","stored":true,"duplicate":false}

MQTT PUBACK is not database confirmation. After reconnect or a missing receipt, resend the same bytes and message ID. A duplicate with the same hash receives duplicate:true; reuse with different content is rejected.

Telemetry payload

Agents report the latest snapshot, including:

Android inventory excludes system applications/updates. Linux A10 inventory uses userappl/cfg/appname.txt, version.txt and the configured application ID. Do not replay old snapshots after a newer one; the portal presents received freshness, not the device clock as authority.

Location history records a new point after at least 100 metres. A device-reported valid point overrides manual portal location. See chapter 34.

Commands and results

{
  "protocolVersion": 1,
  "commandId": "22222222-2222-4222-8222-222222222222",
  "deviceId": "11111111-1111-4111-8111-111111111111",
  "assignmentEpoch": 1,
  "type": "report_status",
  "payload": {},
  "expiresAtUtc": "2026-09-26T18:05:00Z"
}

Validate protocol, device, assignment, type and expiry. Persist the command ID before an external effect. Redelivery returns the stored result and must not repeat message display, reboot or installation. Unknown or expired commands fail safely.

{
  "commandId":"22222222-2222-4222-8222-222222222222",
  "state":"Succeeded",
  "detail":"Status stored"
}

Results use a new envelope message ID and remain in the durable outbox until a storage receipt arrives. The server validates operation-specific evidence: a fresh status receipt, a new boot/uptime state, matching package/version/hash after install, or package absence after uninstall. Dispatch never counts as success.

Implemented common command types include report_status, send_message, reboot, install_application/install_zip, uninstall_application and parameter/configuration request paths. Android additionally supports remote assistance; Linux uses a payment-app file bridge and has no remote desktop.

Application delivery

The command supplies an authenticated HTTPS download URL, package identity, version, expected size/hash and model compatibility. The agent downloads to temporary storage, enforces bounds, validates SHA-256 and uses its platform installer.

Android verifies package ID, version, signer and installed APK hash, then invokes the NEWPOS or NEXGO SDK. UIC Home cannot remotely uninstall itself, the active Home application or system packages.

Linux A10 accepts the native signed prodapp.tarball.tar.gz. The portal validates archive structure/hash; xTMSAgent checks the command hash and invokes os_update_application, whose vendor path verifies the A10 signature. Successful A10 install/uninstall reports evidence before reboot and publishes new inventory afterward.

Parameters

The agent sends an application-scoped request with the last applied configuration hash. TMS compiles current saved schema/catalog/device values on demand and returns either upToDate:true or the current JSON payload/hash.

Android exposes the result through UIC Home's read-only payment-app provider. Linux writes it to the configured parameter payload and bridge response files. Neither agent should reapply an unchanged hash. The server currently has no independent app-applied receipt or scheduled parameter push.

Security and restrictions

DESIGN BASELINE / CHAPTER 11Markdown source ↗

Multi-brand Android hardware services

Scope update: the service-APK design below is reserved for the future payment application. uicu_home uses brand flavors for device management and excludes EMV, PIN-pad and printing. See chapter 12.

Decision

Use one brand-independent uicu_home APK plus one installed UIC hardware-provider APK for the terminal brand. Share a versioned Android AIDL contract and Kotlin client library. Each provider wraps its own vendor SDK and owns hardware coordination. Use Android Binder IPC, not HTTP, MQTT or a local gRPC server for device hardware calls.

This is an architecture decision and implementation plan. No provider APK has been built, installed or benchmarked during this investigation. The connected device was inspected read-only.

Verified evidence — 23 September 2026

Runtime and project layout

Logical call path:

uicu_home / authorized payment application
    → UIC hardware client library
    → versioned AIDL / Android Binder
    → UIC NEWPOS provider OR UIC NEXGO provider
    → vendor SDK / terminal system services / secure hardware

Proposed projects under agents/hardware-services:

Module Output and ownership
hardware-contract Android library: AIDL, typed request/event/result parcelables, documented semantics
hardware-client Android library: verified binding, negotiation, reconnect and Kotlin async wrappers
provider-core Android library: caller checks, sessions, bounded queues, deadlines and normalized errors
provider-newpos APK containing NEWPOS adapter and any required vendor-specific activities
provider-nexgo APK containing NEXGO adapter and required SDK dependencies
hardware-test-client Lab APK: the same client contract, diagnostics and repeatable performance tests

Separate package IDs, for example com.uic.hardware.newpos and com.uic.hardware.nexgo. Both implement the same AIDL package. No vendor classes, Android View objects or vendor enums appear in the public interface.

Use one provider process per installed brand, with separate interfaces and permissions for management and payments. Do not grant uicu_home payment access just because it needs serial, printing or reboot. An authorized payment app can use the same contract library later.

Bind explicitly to an approved package/component after verifying its signing certificate. Negotiate major/minor API version, provider version, SDK version, device identity and capabilities. Never select a provider solely because it advertises an intent action. Reject incompatible major versions; add new methods/fields compatibly without reordering existing AIDL methods.

Only a verified compatible provider is active. Missing provider or SDK failure gives a clear unavailable state; the launcher must still start without loading vendor classes.

Common calls and callbacks

Names below are proposed contract semantics, not existing compiled interfaces.

Area Common calls Callback/result examples
Discovery getDescriptor, openSession, closeSession READY, UNAVAILABLE, capabilities
Beeper beep(requestId, pattern, deadline) completed, failed
Printer getPrinterStatus, submitPrintJob, cancelPrintJob accepted, paperOut, overheated, completed, outcomeUnknown
Device management getDeviceInfo, reboot, installPackage, uninstallPackage, setKioskPolicy progress, completed, denied, unsupported
EMV configuration validateProfile, applyProfile, getProfileRevision validationErrors, appliedRevision, failed
EMV transaction startTransaction, selectApplication, submitOnlineResponse, cancelTransaction cardPrompt, applicationSelectionRequired, onlineRequired, completed
Secure PIN beginPinEntry, cancelPinEntry, getKeyStatus pinEntryStarted, cancelled, encryptedResult, failed

Every asynchronous operation carries sessionId, requestId, monotonic deadline and ownership by authenticated caller UID. Events carry requestId, event sequence, standardized status and optional vendor diagnostic code. Payment prompts additionally carry a single-use prompt token. A response must match the active session, transaction, prompt and state; reject late or repeated replies.

Use typed parcelables and bounded byte arrays, not a generic execute(command, JSON) escape hatch. Requests use money in integer minor units with currency, never floating-point amounts. Publish explicit field size limits and a stable error vocabulary: UNSUPPORTED, NOT_READY, BUSY, INVALID_ARGUMENT, PERMISSION_DENIED, TIMEOUT, CANCELLED, HARDWARE_ERROR and OUTCOME_UNKNOWN.

Capabilities must describe what is available on this firmware/device and for this caller: printer width/formats, contact/contactless support, PIN modes and supported management operations. Return unsupported explicitly; never silently emulate a payment operation.

Efficiency and concurrency

Binder adds IPC overhead compared with an in-process SDK. This layout deliberately reduces the number of calls; no latency guarantee is claimed before measurement.

Measure on NEWPOS first: cold bind+SDK readiness, warm no-op IPC p50/p95/p99, beep request-to-SDK dispatch, callback delivery delay, print completion time, provider memory/idle CPU, concurrent print/payment admission, and restart recovery. Compare with the same vendor operation invoked directly in a lab baseline. Separate hardware duration from IPC overhead, and report device/firmware/build/sample count. Initial acceptance: zero dropped required events and zero main-thread hardware calls; numerical latency budgets follow the baseline.

EMV and PIN ownership

The provider owns the transaction state machine. Do not expose each vendor EMV function as a remote method. A typical public lifecycle is idle → waiting for card → application selection → kernel processing → awaiting online response → completion/cancellation. Actual legal transitions and fallback rules depend on the kernel and transaction flow.

PIN entry may require vendor UI. NEWPOS exposes Ped.setPinPadView and showPinKeyBoard with View/Context parameters, which cannot simply cross an APK boundary. Host that UI in a provider-owned activity or use a vendor-supported secure entry surface. A foreground caller launches the approved explicit activity/session flow; do not assume a background service can show it.

Do not transmit clear PIN digits or secret key material through the common interface. Keep keys in secure hardware and refer to authorized key slots/handles. Only the authorized payment client receives the required encrypted result and associated metadata. Offline PIN verification results are distinct from online encrypted PIN blocks. Logs and TMS telemetry must exclude PIN data, full track data and unfiltered payment payloads.

EMV configuration is a validated, versioned profile containing required AIDs/CAPKs/terminal settings. Apply only while no transaction owns the kernel. Do not promise atomic replacement if the vendor exposes destructive stepwise APIs: validate/stage first, record application state and block transactions until a complete known profile is active. Key injection is a separate controlled workflow, not a generic TMS parameter push.

Reliability and access control

Use signature-level permissions for UIC applications sharing an approved signing identity, and check Binder calling UID on each entry point before switching threads. If vendor signing requirements force different certificates, define an explicit certificate allowlist policy and verify packages belonging to the actual UID. Package-name strings supplied by the caller are not proof of identity. Verify the provider on the client side too.

Capture caller identity before dispatch and bind session/operation ownership to it. Split management and payment privileges. Export only necessary service/activity components, and expose no arbitrary shell execution interface.

Handle binder death and onServiceDisconnected: mark unavailable, cancel or safely close vendor sessions where possible, release ownership and reconnect with backoff. Client death must not leave PIN entry or the card reader locked.

Deduplicate operation IDs with a bounded journal. Never automatically repeat an uncertain print or payment after service death. Record OUTCOME_UNKNOWN and provide reconciliation/status lookup. Transport failure does not prove an operation was not executed. Reconnecting does not resume a payment unless the provider can establish its actual state.

NEWPOS mapping from supplied SDK

Common area Inspected SDK APIs Remaining validation
Initialize SDKManager.init(Context, SDKManagerCallback), release, getSdkVersion shared library loading, initialization result, permissions
Beep Beeper.getInstance, beep, beepNonBlock duration/frequency units, observed behavior
Printing Printer.getStatus/getWidth, startPrint(PrintTask, PrinterCallback), cancelPrint receipt conversion, callback meanings, actual print and paper-out behavior
EMV profiles EMVHandler AID/CAPK and terminal configuration methods supported kernels, profile completeness and safe replacement
EMV flow EMVHandler application selection, readAppData, cardholderVerify, onlineTransaction required callbacks, contactless orchestration and host-response flow
PIN Ped.getPinBlock/getOfflinePin/cancelInputPin and secure UI APIs keys, approved entry UI, formats, cancellation and permissions

The NEWPOS shared library declaration is evidence-backed; successful use from an ordinary signed app is still a hardware test. Do not package the throwing stub JAR as the implementation.

Migration and delivery order

  1. Implement contract/client/provider-core plus NEWPOS descriptor, readiness, beep and printer status. Use a separate test client on the connected device.
  2. Validate actual printing and callbacks, caller rejection, process death, queue bounds and latency. This proves the service architecture before EMV work.
  3. Implement NEXGO against the same non-payment contract. Remove vendor imports from uicu_home startup, serial lookup and device management paths. Centralize binding in one application-scoped client.
  4. Inventory all current privileged operations, including installation/uninstallation, system bars and kiosk controls. Map available capabilities; unsupported functions remain unavailable on NEWPOS.
  5. Add payment session coordination and provider-owned PIN UI. Implement/validate EMV profiles and transaction flows with test cards and approved lab key provisioning.
  6. Add provider identity/version/capabilities to TMS telemetry and provider compatibility metadata to the device model catalog. Brand/model/OS selects eligible packages; runtime capability negotiation still decides availability.

The current model catalog remains unchanged by this design. No payment, key injection, reboot, installation or device policy changes were performed during inspection.

Sources

DESIGN BASELINE / CHAPTER 12Markdown source ↗

Traditional launcher — development implementation

Current update: chapter 16 supersedes the earlier Wi-Fi/cellular protection and location-collection status.

Scope and source layout

The active :app module now points to launcher/ in the existing agents/uicu_home Gradle project. The copied app/ folder is retained unchanged as migration reference for legacy AWS/TMS and NEXGO functionality. Its old entry points, credentials and receivers are not packaged in the new launcher.

One active launcher module has independent client (uic, banpais, banrural) and brand (newpos, nexgo) flavor dimensions. Shared screens contain no vendor imports. Each brand supplies BrandDevice behind DeviceManagement. NEWPOS uses a compile-only SDK stub and the terminal's com.pos.device shared library. NEXGO includes only its own AAR. Payment, EMV, PIN-pad and printing are excluded.

The current flavor interface initializes the SDK and identifies the device. Installation, reboot, kiosk policies and remote control remain separate integration work. A subsequent change added live MQTT telemetry to the new TMS; see chapter 13. The existing server checkpoint continues to run independently.

Launcher behavior

Passcode boundary

This is a launcher entry-point gate, not a system-wide Android settings lock. Notification shade, other apps, vendor tools and adb can still offer separate settings paths. Device-owner/vendor policy enforcement is needed for managed lockdown and must be tested per brand.

PIN verification uses PBKDF2-HMAC-SHA256 with a random salt and a Keystore HMAC key. Plaintext PINs are not persisted. The requested default remains a known bootstrap value, so change it before deployment. Backup is disabled. Verification runs off the UI thread. Five failed attempts trigger a persisted 60-second delay; further failures increase it up to 15 minutes. Wall-clock changes can affect this local throttle; it is not tamper-resistant device-owner enforcement.

The passcode screen disables screenshots, autofill and saved field state. Returning home abandons the visible attempt. Authentication grants one settings launch; there is no cached unlocked session in the launcher. Once Android Settings is open, navigating inside it is governed by Android, not this launcher.

Build and test

From agents/uicu_home, using the installed Android SDK and JDK 21:

gradlew.bat :app:assembleUicNewposDebug :app:assembleUicNexgoDebug
gradlew.bat :app:testUicNewposDebugUnitTest
gradlew.bat :app:connectedUicNewposDebugAndroidTest

Debug app IDs are com.uic.tms.home.uic.newpos.debug and com.uic.tms.home.uic.nexgo.debug. Release signing is not configured. This avoids replacing unrelated installed launchers during testing.

Tests cover ASCII six-digit validation (including leading zeros), bounded escalating delays, initial PIN verification, PIN changes, rejection of the former PIN, persistence, throttling and absence of stored plaintext. Hardware verification results are recorded below after testing.

Architecture supersession

Chapter 11's service APK proposal now applies to the future payment application only. uicu_home uses in-process brand flavors for management, as subsequently selected by the product owner. EMV/printing/PIN services are not part of this launcher.

Verified on 23 September 2026

Both UIC NEWPOS and UIC NEXGO debug APKs built successfully. Two JVM rules tests passed; one instrumentation test on the connected NEWPOS Android 13 terminal passed, covering initial code, changing code, persistence, rejection of old/wrong code, lockout and no plaintext credential storage. The final NEWPOS debug APK was installed and opened.

Physical UI checks passed: incorrect passcode rejection, successful Android Settings/Wi-Fi launches, cellular fallback to Network & Internet without a ready SIM, and gates on NEWPOS PosSettings and Device Config. Screenshot reviewed at the terminal's actual 480×854 resolution. NEXGO physical validation remains pending. The system default home application was not changed automatically.

Traditional launcher on NEWPOS

DESIGN BASELINE / CHAPTER 13Markdown source ↗

Live NEWPOS telemetry checkpoint

Verified on 23 September 2026 against the physical NEWPOS terminal assigned to BANPAIS.

Historical checkpoint: UIC Home has since advanced to 3.9.14-dev with commands, applications, parameters, remote assistance, resource totals and location support. NEWPOS NEW9810 and NEXGO N82 are physically connected to the current portal; use chapters 30 and 33 for current capability claims.

Item Value
Hardware model NEW9810 (Android product reports NEW9830)
Manufacturer label serial H3R000700069081
Android system serial (ro.serialno) 9810260815431507
Customer BANPAIS / BNPHND
TMS device ID 96a5ce4f-65b2-4ca6-bc97-d5fbde526c17
Agent package com.uic.tms.home.uic.newpos.debug
Android 13 / API 33
Test transport USB adb reverse → localhost:18883 → TLS MQTT

Implemented

The active multi-brand launcher now includes a Paho MQTT 3.1.1 telemetry client. It authenticates with the device's enrollment UUID/password, verifies the server certificate and hostname, subscribes to its receipt topic, and publishes QoS 1, non-retained reports to its own telemetry topic. No broker certificate-validation bypass is used.

A snapshot is sampled every 30 seconds when no report is pending. It includes actual Android manufacturer/model/product, OS/API and agent versions, battery/charging, network transport, internet validation, free/total storage, available/total memory, uptime and up to 40 launcher-visible applications with versions. Inventory is explicitly marked as partial. Manufacturer serial comes from enrollment and is labelled accordingly. The initial enrollment mistakenly used ro.serialno; the operator supplied the physical label, proving H3R000700069081 is the manufacturer serial (also the adb transport identifier). The device record was corrected in an audited SQL transaction, preserving UUID, customer, epoch and credentials. The launcher now sends the corrected serial and the separate androidSystemSerial captured during lab provisioning. The system serial is not treated as the manufacturer serial. Location, SSID, payment data and privileged phone identifiers are not collected.

One pending envelope is persisted before publishing and retried byte-for-byte until the TMS returns a matching stored:true receipt after SQL commit. MQTT PUBACK alone does not clear it. Reconnect uses bounded backoff. The launcher footer distinguishes connecting, offline/retrying and last confirmed report time.

Enrollment is imported only in debug builds from private app storage, encrypted with an Android Keystore AES-GCM key, and the plaintext input is deleted. Credentials are not embedded in the APK or printed in logs. The ignored workstation enrollment file remains under .local for this lab device. Release provisioning UI is not yet implemented.

Physical verification

Continue the local test

Keep the TMS development services running and the terminal connected by USB. Restore forwarding after USB reconnect or workstation/device restart:

adb -s H3R000700069081 reverse tcp:18883 tcp:18883
adb -s H3R000700069081 shell am start -n com.uic.tms.home.uic.newpos.debug/com.uic.home.LauncherActivity

Open BANPAIS in http://localhost:15100, open the device's Overview tab. Technical identifiers and original JSON are available in Diagnostics. Last received uses server UTC. The launcher reports local acknowledgment time.

This first client is process-scoped: it continues while the app process is alive, but Android may suspend/kill it in the background. It is not yet an always-on managed agent. USB is the MQTT path even though the telemetry correctly reports Wi-Fi as the terminal's active Android network. Standalone LAN/cloud operation needs host configuration and an appropriate trusted certificate.

At this checkpoint the client advertised telemetry.v1 only. This statement is retained as historical evidence; the current client capabilities are documented in chapters 21-26 and 33.

DESIGN BASELINE / CHAPTER 14Markdown source ↗

Responsive, bilingual device workspace

Implemented 23 September 2026 and maintained through 26 September 2026 in the .NET 8 MVC portal. NEXGO N82 and NEWPOS NEW9810 are now physically connected; responsive bilingual device, deployment, location and user-management views have been exercised in the current portal.

Presentation

Theme and accessibility

CSS design tokens define the navy navigation, blue actions, pale workspace, white cards, borders, spacing and typography. Desktop sidebar becomes compact horizontal navigation on phones. Metrics and property rows reflow; phone tabs use two columns. Long identifiers wrap; tables confine scrolling to their own region. Visible labels, keyboard focus outlines, a skip link, semantic headings, active-page navigation and minimum-height touch controls are included.

Localization standard

All existing portal screens use shared English/Spanish resources: dashboard, device tabs, model catalog, enrollment, sign-in, errors and notices. ASP.NET request localization selects en/es with English fallback. The language control persists a cookie and safely returns to a local page. Numbers and UTC timestamps use the chosen culture; dates explicitly say UTC.

New components must add both resource entries, localize visible labels, validation, empty states and accessibility text, and be reviewed in both languages at phone and desktop widths. Brand names, package IDs, serials, protocol identifiers, OS names and raw diagnostic JSON remain original data. Browser form constraints use messages in the selected portal language; gRPC failures map to localized operator messages rather than exposing service text.

The active Android launcher's own UI localization is outside this portal change.

Serial correction

BANPAIS device 96a5ce4f-65b2-4ca6-bc97-d5fbde526c17 now displays manufacturer label serial H3R000700069081. The prior value 9810260815431507 came from Android ro.serialno. Both are now distinct in telemetry; the Android system value was captured during lab provisioning, not read dynamically on every report. The corrected record retains assignment and credentials. Audit action: LabelSerialCorrected. The ignored enrollment file was renamed to use the corrected serial.

Map recommendation and next integration

Recommended renderer: MapLibre GL JS. Initial vector map provider: OpenFreeMap, whose public service currently advertises no registration, API key or request/view limit. These are separate from coordinate acquisition. Keep the tile/style provider configurable and preserve required attribution; production availability requirements may justify self-hosting or a contracted provider. Self-hosting has infrastructure and maintenance costs.

The launcher must first collect authorized device location with latitude, longitude, accuracy, source and captured-at timestamp. The portal should show the last known point, its age and accuracy, never silently substitute the operator browser's position or an IP-derived estimate. No location collection, map requests, external assets or CSP relaxation were added in this change. This recommendation is not yet an implemented map feature.

Verification

DESIGN BASELINE / CHAPTER 15Markdown source ↗

OpenFreeMap and user application inventory

Current update: chapter 16 supersedes the earlier Wi-Fi/cellular protection and location-collection status. Implemented and checked through 26 September 2026. Chapter 34 is the authoritative location-history and manual-positioning description.

Map integration

The Overview tab uses MapLibre GL JS 5.24.0 and the OpenFreeMap Liberty style at https://tiles.openfreemap.org/styles/liberty. The renderer, CSS and separate CSP worker are vendored locally from the official npm archive; its SHA-512 npm integrity was verified and BSD-3-Clause license retained under wwwroot/vendor/maplibre. No API key or external script CDN is required at runtime.

The portal permits map connections only to tiles.openfreemap.org in addition to its own origin. Workers remain same-origin; scripts do not need unsafe-eval. Referrer-Policy is no-referrer so customer/device page URLs are not included in map resource requests. The provider necessarily receives the viewer's IP and requested map areas. Map markers and identity labels remain local browser overlays. Attribution is retained for OpenFreeMap, OpenMapTiles and OpenStreetMap.

Map controls and status messages are localized in English and Spanish. Geographic labels prefer the chosen language where the source offers it, with local-name fallbacks. Provider attribution retains its original wording. Mobile controls are touch-sized; wheel zoom is disabled to preserve page scrolling. Provider/WebGL failures show a localized message without hiding available coordinate details.

No valid location means a general map and explicit no-location text, with no marker. A valid telemetry payload may contain:

{
  "location": {
    "latitude": 0.0,
    "longitude": 0.0,
    "accuracyMeters": 25.0,
    "capturedAtUtc": "2026-09-23T12:00:00Z"
  }
}

These are schema examples, not this terminal's coordinates. Latitude/longitude must be finite and in range; accuracy must be nonnegative and the capture timestamp present and not more than five minutes in the future. Zero coordinates are valid. The card shows accuracy, capture time and a stale warning after 24 hours. Refresh follows the existing manual page refresh. The current Android agent advertises GPS support and reports a valid fix when Android permissions, location services and the physical environment provide one. Until then the portal shows Waiting for a location fix and no marker. The portal does not use browser geolocation or infer a terminal location from public IP.

The data service now keeps a location history for valid terminal reports. The first position is stored, and a later position is added only after the terminal has moved at least 100 meters from the last stored point. Smaller changes still update the current telemetry snapshot, but are omitted from history to suppress normal GPS precision drift. The device Overview shows the latest 200 stored points, newest first, and draws them as a route on the map. History is tenant-scoped and requires device read access.

Devices that do not report a valid location expose Set location on the Overview map to users with Devices write access. An operator can search for an address, click or drag a map pin, or type latitude and longitude. The saved position is identified as Manual in the history and produces an audit event. A correction within 100 meters updates the most recent manual point; a larger move creates another history entry. Once valid device telemetry includes a location, the manual editor is hidden and the service rejects manual changes so the terminal remains authoritative.

Address lookup is an explicit search action, not autocomplete. By default it uses the public Nominatim endpoint through the portal server, caches results for 24 hours, permits at most ten searches per signed-in user per minute, and serializes uncached requests to at most one per second. The dialog displays OpenStreetMap attribution. GeocodingBaseUrl can switch to an organization-managed or commercial Nominatim-compatible provider without updating the portal. Search text is sent to that configured provider; do not enter personal or confidential data when the public service is configured.

The selected style URL is currently fixed in device-map.js. Changing map provider also requires reviewing the CSP allowlist. Sources: OpenFreeMap quick start and MapLibre documentation.

User application inventory

The Android agent filters launcher activities before collecting app metadata. Packages marked FLAG_SYSTEM or FLAG_UPDATED_SYSTEM_APP are excluded. For each remaining package it sends packageName, displayName (Android's application label), versionName and versionCode. Names are supplied by the device's installed application and language; the portal does not invent or translate them.

The inventory remains launcher-visible user applications, with up to 40 entries and a 20 KB application-array budget to leave space in the 32 KiB telemetry envelope. Labels/version strings are bounded, and truncated/incomplete inventory is indicated. Non-launchable services are outside this inventory. The portal shows display names prominently and package identifiers below, with a package fallback for older reports. Existing historical reports are not rewritten or purged; new reports exclude system packages.

Physical NEWPOS verification: the latest SQL telemetry contains one application, UIC Home / com.uic.tms.home.uic.newpos.debug, matching adb's third-party package inventory. System Settings, Gallery, vendor settings and other preinstalled applications are no longer sent. Updating the APK preserved enrollment and the settings passcode.

Verification

DESIGN BASELINE / CHAPTER 16Markdown source ↗

Unprotected network shortcuts and device geolocation

Implemented and physically verified beginning 23 September 2026. Current location history/manual positioning is in chapter 34; current Android builds are 3.9.14-dev.

Network access

UIC Home's Wi-Fi shortcut now opens Android Wi-Fi settings directly. Cellular opens the Android Internet connectivity panel directly, with data-usage/wireless-settings fallbacks for vendor builds that cannot handle the panel. No launcher passcode is required for these two shortcuts. The panel exposes cellular controls according to Android/SIM availability; the app does not secretly change network state.

General Android settings, vendor settings entries and changing the settings passcode remain protected by the existing six-digit gate. The configured passcode and enrollment were preserved. This is a launcher entry gate, not an OS-wide device-owner restriction on every possible settings navigation path.

Physical tests used the launcher shortcuts: Wi-Fi reached com.android.settings without a passcode screen; Cellular reached the System UI Internet panel without a passcode screen; Settings reached Protected settings / Passcode. No network connection or mobile-data toggle was changed during these tests.

GPS capability and current result

The connected NEWPOS NEW9810 advertises android.hardware.location.gps. Android lists an enabled GPS provider backed by GnssService with satellite positioning capabilities. System location was already enabled. After installation and location permission grant, diagnostics confirmed the agent's active GPS requests and mStarted=true.

At verification, the device had not delivered its first position: last location remained null and the TMS received gpsSupported=true, locationStatus=waiting_for_fix. The portal displays that status in English/Spanish. Hardware/software support is confirmed; a real satellite fix remains unverified. Keep the launcher visible near a window or outdoors for the initial acquisition. No location was fabricated or inferred from the workstation or IP address.

Agent behavior

The shared multi-brand launcher uses Android LocationManager, with no Google Play Services dependency. It requests coarse and fine foreground location permission once; denial does not block the launcher. Location collection starts while the launcher is resumed and stops when paused. Permission can later be managed in Android app settings. This implementation does not request background location or provide always-on background tracking.

Available enabled GPS, network and fused providers are used, with a 60-second minimum requested interval and 10-meter displacement threshold. Actual scheduling and accuracy depend on Android and the provider. Recent callbacks replace older fixes; last-known provider locations retain their original capture time. Mock, out-of-range, invalid-accuracy and implausibly future fixes are rejected. The API 29 mock-location compatibility path is retained.

Telemetry adds gpsSupported and locationStatus (permission_required, disabled, waiting_for_fix, available). When a valid fix exists and permission/system location remain enabled, location contains latitude, longitude, accuracyMeters, capturedAtUtc and source. Latest fixes are kept in process memory; they are sent through the existing durable MQTT outbox and server receipt flow. Existing OpenFreeMap rendering handles the marker, accuracy, timestamp and stale-location warning.

Verification

DESIGN BASELINE / CHAPTER 17Markdown source ↗

Current feature coverage

Reviewed 26 September 2026. Chapters 02, 30, 33 and 34 describe the current implementation. Earlier checkpoints remain historical evidence rather than delivery claims.

Area Implemented Outstanding
Platform .NET 8 MVC/Kestrel, sessions, gRPC, Dapper, SQL Server, three Windows services Multi-node deployment, independent service identities, load/restore qualification
Accounts SuperAdmin/customer users, roles with feature Read/Write, profile/password, MFA, recovery by SMTP or AWS SES External identity federation and additional enterprise lifecycle policies
Audit Date/time, actor, operation, entity and change; global SuperAdmin/customer-scoped visibility Export/retention policy and extended remote-session event detail
Fleet Models, portal/reported model, groups/subgroups, tags, serial/model/status search, device delete Fleet-scale performance qualification and bulk lifecycle tooling
Telemetry Resources with totals, network/SIM identifiers, observed public IP, app inventory, Android/A10 status Per-firmware identifier access and alerting/long-term raw telemetry policy
Location Current map, 100-metre history, source/time, manual address/map/coordinates when no reported fix Customer-approved retention, private geocoder option and broad physical testing
Connection Per-device mTLS + Device Secret, provisioning lock on first MQTT, reconnect/outbox Automatic certificate renewal/CA rollover and production Android bootstrap distribution
Operations Message, request status and reboot on Android/A10 Block/unblock policies and more model qualification
Remote desktop Android portal WSS relay, local consent, accessibility input, full-screen Linux support, multi-node routing and broader audit/scale qualification
Applications APK/native A10 upload, version/model artifacts, release, scalable deployments, task grid/details, install/uninstall, automatic inventory refresh Malware scanning, signer migration and rollback/canary policy
Parameters Grouped schemas, catalogs, templates/copy, device forms, Android provider and A10 file bridge Scheduled push, app-applied receipt, encrypted secret values
Windows setup Installer, SQL/TLS settings, DPAPI secrets, SMTP/SES, migrations and services Automated TLS renewal and completed production restore drill
Documentation Searchable architecture guide, bilingual portal manual/PDF, Android and Linux integration manuals linked from Help Official A10-T field installation chapter when installer is finalized

APK inspection is included; no external Java/Android SDK is required on the server. Server packaging does not compile device agents. NEWPOS NEW9810, NEXGO N82 and UIC A10-T have been exercised against the portal, but each production firmware/network still requires acceptance testing.

DESIGN BASELINE / CHAPTER 18Markdown source ↗

Application builds and scheduled delivery

Data model

Application belongs to one customer and identifies a package and platform. Android signing identity is fixed when the first artifact is accepted. AppArtifact is an immutable binary plus parsed version name/code, minimum Android SDK, file size, SHA-256, build label, validation/release state and creator. ArtifactModel is the many-to-many compatibility map to the shared brand/model/OS catalog.

An application may have several artifacts for one version. For example, build A can support models A1 and A2 while build B supports A3. A deployment always selects one artifact explicitly. Overlapping model maps are therefore allowed without an ambiguous automatic selection rule. Different Android package IDs are separate application records even when their display names match.

Deployment records the selected artifact, customer, actor, idempotency key, UTC start and expiry. Its device set is frozen into DeviceCommand rows with NotBeforeUtc, assignment epoch and the artifact's package/version/hash metadata. Migration 003_Applications.sql creates these tables and extends the existing command queue.

Upload and release

  1. Customer-authorized operator uploads an APK, manifest ZIP, or native signed A10 tar.gz, maximum 128 MiB, and selects one or more catalog models.
  2. MVC streams 32 KiB chunks over authenticated gRPC. DataService writes to private artifact storage outside the web root and calculates SHA-256.
  3. Archive checks reject traversal, absolute paths, unexpected links, excessive entry count and expanded size/ratio. Native A10 packages may contain only the expected relative appl.out link.
  4. APK metadata is read in-process by bundled apk-parser; bundled Android apksig verifies signatures/integrity through IKVM .NET assemblies. One signer is required and must match the application's previous signing identity. All selected models must match the package platform.
  5. Accepted artifacts enter Validated. Explicit operator review moves them to Released; only released artifacts can deploy. Failed uploads remove their temporary binary.

This is a trusted-package development release flow. Signature validity proves integrity/signing identity, not malware safety. A production scanner/quarantine/approval policy remains required by the architecture; the release screen states that scanning is not configured.

The Versions page permits operators with Applications write access to delete one unused package build or an entire application and all of its versions. Both actions require confirmation, remove the private stored package/icon after the catalog transaction commits, and retain an audit record of what was removed. A build referenced by any deployment is protected from deletion so deployment history and command evidence remain complete.

Linux package catalog and A10 delivery contracts

The ZIP must contain a root tms-package.json with platform: "Linux", packageId, versionName and positive numeric versionCode. Generic Linux ZIP remains a catalog contract unless a compatible Linux agent advertises install_zip.v1. UIC Home never advertises Linux installation.

The native A10 package is accepted without repackaging as prodapp.tarball.tar.gz. Its outer archive must contain only app.tar.gz and app.tar.gz.sign; the inner archive must contain a non-empty application executable through appl.out and cfg/version.txt. When present, cfg/appname.txt supplies the portal display name; older packages without it use the UIC Payment fallback. Versions such as A10TBP.02.01.01.04P are cataloged as the Linux PAYMENT_APP application with a numeric version code derived from the four version components. The portal requires the production signature payload and preserves the exact uploaded bytes. xTMSAgent checks the command hash and invokes the A10 vendor update API, which verifies the platform signature and installs into userappl.

Target review and schedule

The review checks customer ownership, enabled device, exact model mapping, platform capability (install_application.v1 / install_zip.v1) and Android API level. Excluded targets show a localized reason. Confirmation revalidates the submitted targets and creates durable SQL commands; no browser timer is involved.

Delivery and completion

The existing broker polls due commands and publishes them to the device's authenticated MQTT topic. The APK remains out of MQTT messages. The agent downloads through https://<portal>/device-packages/<commandId> using its provisioned credentials. The endpoint rechecks device, customer, assignment epoch, artifact/model, command state, start and expiry. HTTP requests are rejected; redirects are not followed by the agent.

UIC Home serializes commands in private storage, bounds downloads, validates size/hash/package/version/signer, rejects a lower installed version and calls the selected brand SDK. It reports success only after the installed package version and installed APK SHA-256 match the artifact. Results survive process restarts and are retried until SQL receipt confirmation. The server additionally checks that success evidence matches the command's package/version/hash. A dispatch acknowledgement is never displayed as installation success.

xTMSAgent applies the same durable command/result rules. It rejects unsafe updates while the payment application reports open transactions, downloads the exact A10 artifact over authenticated HTTPS, checks SHA-256 and calls os_update_application. It queues verified result evidence before requesting reboot; after restart it reports cfg/appname.txt/cfg/version.txt inventory. Uninstall coordinates payment-app shutdown, removes/recreates userappl, reports absent=true and also reboots. The development updateTMS.sh is not used for portal deployments.

Statuses: Scheduled → Queued → Dispatched → Succeeded / Failed, with Cancelled and Expired terminal alternatives. “Dispatched” includes download/install time; detailed percentage progress is not implemented. Repeated MQTT delivery uses the persisted command record to avoid reinstalling the same command.

Local development

DataService requires no external APK tools. The package includes the .NET-compatible inspection libraries and runtime support. Configure ArtifactStorage for the host; obsolete AndroidBuildTools and JavaPath settings are ignored. The private artifact directory must be retained together with the database; database-only backup does not preserve binaries.

The portal's local HTTPS package listener is PortalPort + 2 (15102 by default) and uses the configured local development certificate. The lab enrollment adds packageBaseUrl: "https://localhost:15102"; USB testing forwards 15102 and 18883 through ADB. Device credentials remain in private encrypted enrollment storage and must never appear in documentation or logs.

Build the Android test APK before running scripts/Test-Integration.ps1; application integration checks validate the actual signed file at agents/uicu_home/launcher/build/outputs/apk/uicNewpos/debug/app-uic-newpos-debug.apk.

Physical test evidence

The current clean integration suite passes 239 checks, including multi-model logical versions, model-specific artifacts, scalable target selection, command evidence and Android/A10 package rules. The .NET solution builds without warnings. English/Spanish resources have matching keys.

BANPAIS / NEWPOS NEW9810 / label serial H3R000700069081:

Test Observed result
Immediate push of 3.1.0-dev (code 2) Downloaded through authenticated HTTPS; exact installed APK already matched; succeeded with already_installed_verified
Scheduled push of 3.1.1-dev (code 3) Withheld as Scheduled, dispatched when due, NEWPOS SDK installed code 3
Completion after self-update Reopening UIC Home resumed the durable command; installed SHA-256 matched and installed_verified receipt committed

NEWPOS NEW9810 and NEXGO N82 both completed portal uninstall followed by one logical UIC Payment deployment that resolved each model's APK. UIC A10-T completed native payment-app upload, install, reboot/inventory refresh, uninstall and reboot through xTMSAgent. Production signing/trust, canary/rollback policy and fleet reliability remain to be qualified.

DESIGN BASELINE / CHAPTER 19Markdown source ↗

Dashboard, device search and fleet organization

Portal navigation

The home route / is now a dashboard. It shows customer fleet totals, Online/Offline/Never-connected counts, shortcuts and recent commands. Cards link to the corresponding filtered terminal grid. Counts cover the full customer fleet rather than only the first page.

Page Purpose
Dashboard — / Fleet summary and recent commands
Devices — /Fleet/Devices Terminal grid, combined search/filtering and pagination
Groups and tags — /Fleet/Groups Create, rename, move and remove groups/subgroups and tags
Device organization — /Fleet/Organize/{id} Assign one group and up to 50 distinct tags to a terminal
Application library — /Apps Package builds and immediate/scheduled delivery
Administration — /Home/Administration Super-admin customer creation, terminal enrollment and model catalog access

Device detail links back to Devices and shows its group path, tags and connection status. Its organization link opens the assignment form. The Administration page and mutations retain SuperAdmin authorization; customer administrators manage their own fleet organization without gaining device registration or customer creation permissions.

Search behavior

Search runs in SQL through gRPC/Dapper. Filters combine with AND: literal serial substring, group/subgroup, tag, catalog model and status. Selecting a parent group includes every descendant. Ungrouped is an explicit filter. The model includes brand/model/OS. Results sort by serial and device identity, in pages of 24; links retain filters. Changing customer through the workspace selector resets filters.

Group and tag identifiers never grant access. Every query and mutation validates customer membership. Cross-customer group parents, devices and tags are rejected. The database also enforces customer-scoped foreign keys for assignments.

Organization rules

Migration 004_FleetOrganization.sql adds FleetGroup, FleetTag, DeviceGroup, DeviceTag and the connection lease column.

Connection status

The MQTT broker renews a server-side connection lease every 15 seconds for authenticated connected devices. A lease lasts 45 seconds; normal disconnects expire it promptly. Broker failure or loss of the data-service connection therefore ages out rather than leaving a device permanently Online. This is a bounded freshness indication, not an instantaneous network guarantee.

Online requires an unexpired lease. Offline means a previous connection/report exists without a valid lease. Never connected means neither has been recorded. Disabled takes precedence. Last telemetry receipt remains a separate timestamp and does not determine Online status. Existing devices with older telemetry start as Offline until a broker renewal arrives.

Verification

The .NET 8 solution builds with zero warnings/errors, and all 98 integration checks pass. Desktop and 390-pixel phone checks confirmed localized controls and no page-level horizontal overflow on Dashboard, Devices, Groups/Tags and Administration. The connected NEW9810 matched a combined serial/model/Online search in BANPAIS.

Automated checks cover hierarchy cycles, duplicate names, cross-customer boundaries, assignments, protected deletion, subgroup moves, combined filters, literal serial searches, status transitions, full-fleet counts and pagination. MVC checks verify that dashboard, Devices and Administration are separate, and that group creation submits through protected MVC forms to gRPC. Desktop and phone layouts retain English/Spanish localization.

Group/tag-based application deployment targeting remains a later extension; this implementation provides organization and device filtering. Existing application deployments continue to freeze explicitly selected device IDs.

DESIGN BASELINE / CHAPTER 20Markdown source ↗

Remote Control operations

The device Operations tab now presents a responsive Remote Control button panel in English and Spanish.

Operation Interaction Availability
Send message Dialog with required text, maximum 500 characters Online and send_message.v1 capability
Reboot Dialog with explicit confirmation and interruption warning Online and reboot.v1 capability
Request status Direct operation button Online and report_status.v1 capability
Remote assistance Disabled placeholder Pending secure relay/session integration

Availability refreshes every 15 seconds while the page is visible and before opening a dialog. The refresh preserves the selected language. If availability cannot be confirmed, controls are disabled. Both desktop and phone layouts were visually checked, including Spanish dialogs.

The data service independently checks the live MQTT connection lease, customer/device scope and advertised operation capability when accepting a new request. Reboot requires explicit confirmation. Message/status requests expire after 60 seconds; reboot requests have a 5-minute completion window; accepted delivery is not proof of successful execution. Existing request identifiers retain idempotent behavior. Application deployments use their separate immediate/scheduled workflow.

UIC Home 3.2.0-dev implements message, status and reboot operations. See chapter 21 for durable execution, verified completion, physical tests and remaining background-execution limits. Remote assistance remains disabled.

Verification: 104 integration checks pass, including offline operation rejection, unsupported online operation rejection, reboot confirmation, customer isolation and the button/dialog rendering. Dialog interactions were checked with an isolated integration-test fixture.

DESIGN BASELINE / CHAPTER 21Markdown source ↗

Device message, status and reboot execution

This chapter records the operation implementation introduced in UIC Home 3.2.0-dev. The same durable behavior remains in UIC Home 3.9.14-dev, and xTMSAgent now supplies the equivalent message/status/reboot capabilities for A10-T where described in chapter 33. NEWPOS and NEXGO builds share the handler; reboot calls remain brand-specific.

Behavior and completion

Operation Device behavior Success evidence
Send message Shows a plain-text dialog when UIC Home is visible, up to 500 characters; English/Spanish title and close button message_displayed after the dialog is shown; this does not prove the user read it
Request status Captures a fresh report and retries its identical envelope until a SQL receipt arrives status_stored plus telemetry message ID; server checks this device/assignment and a report committed after command creation
Reboot Persists the current Android boot counter before invoking NEWPOS SystemManager.reboot() or NEXGO platform.rebootDevice() reboot_verified plus increasing before/after boot counters, after reconnection

Message/status requests have a 60-second window. Reboot uses five minutes to allow startup and reconnection. The server still requires an online MQTT connection lease and the advertised capability when accepting a new operation. Reboot also requires explicit portal confirmation; its capability is advertised only after SDK initialization.

Durable execution

Private atomic JSON records retain the command ID, assignment epoch, deadline and stage. Duplicate delivery cannot replace or re-execute a recorded command. Invalid identifiers, other devices/assignments, unsupported types and expired envelopes do not execute. Reboot is never retried after its pre-execution record is written: an ambiguous crash can result in failure/expiry, not a reboot loop.

Results persist and retry with the same message ID until TMS confirms SQL storage. A status operation waits for the telemetry storage receipt before emitting its successful result. A reboot result is never generated merely because the SDK returned. Records expire with the command and are cleaned up after seven days while the agent runs.

Boot recovery and limits

An Android BOOT_COMPLETED receiver schedules a bounded recovery job. It initializes the selected SDK, starts the agent and provides a three-minute background execution window for reconnecting and sending durable results. It does not change the user's selected launcher. Android/vendor scheduling, unlock requirements and connectivity can delay recovery; a five-minute expiry is not a guarantee of completion on every device.

The normal agent remains process-scoped. Continuous background execution and background message notifications are separate work. A message waits for UIC Home to be visible; if this does not happen within the deadline, it expires. No screen overlay permission, payment SDK, printing operation or remote-assistance session is introduced.

Verification

NEXGO is compile-checked; physical reboot qualification remains necessary on a NEXGO test terminal. Remote assistance remains pending.

Running Android tests without removing enrollment

Use scripts/Test-AndroidOperations.ps1 -DeviceSerial <adb-serial>. It installs with replacement, runs instrumentation, and reopens UIC Home without uninstalling it. The test cases use isolated storage. Avoid the Gradle connected-test cleanup workflow on an enrolled lab device because it can uninstall the application and remove its private enrollment.

Default Home registration (3.2.1-dev)

The previous launcher declared the Android HOME intent but did not select itself as the default. Version code 5 registers its exact flavor package and LauncherActivity after successful SDK initialization, including boot recovery. Registration is idempotent: it first resolves the current Android HOME activity and skips the SDK call when it already matches.

NEWPOS uses the documented SystemManager.setDefaultLauncher(packageName, className, false) call; false avoids launching a second Activity. NEXGO waits for SystemServiceHelper initialization before calling systemManager.setLauncher(packageName, true). No device-owner enrollment, root access or ADB default-home override is used.

The foreground launcher verifies Android's actual HOME resolution after registration. If the firmware declines or the SDK is unavailable, an English/Spanish “Set UIC Home as the home app” button opens Android's standard Home selection flow. A newly installed app must first be launched/provisioned; ordinary Android installation alone does not execute application code.

Verified on NEW9810 H3R000700069081: installing 3.2.1-dev with replacement preserved enrollment; after app startup, Android HOME resolved to com.uic.tms.home.uic.newpos.debug/com.uic.home.LauncherActivity, and pressing Home resumed that Activity without a chooser. Both brand variants built successfully; NEXGO default-home behavior remains physically unqualified.

DESIGN BASELINE / CHAPTER 22Markdown source ↗

Device network and SIM identifiers

UIC Home 3.3.0-dev introduced interface-level telemetry; it remains in 3.9.14-dev. The current portal also shows public IP observed by TMS, free/total storage and available/total memory. xTMSAgent reports the equivalent A10-T resource and interface fields. Loopback/link-local addresses and Android placeholder MACs are excluded. The active interface is marked; local addresses can include public IPv6.

The NEWPOS flavor reads IMEI and ICCID through SystemManager for SIM slots 1 and 2. Values remain strings to preserve all digits. Missing SIMs, denied access and unsupported firmware report missing values. These identifiers are not yet implemented through the NEXGO SDK; that variant compiles and shares network interface collection.

The broker includes its authenticated connection peer in the gRPC ingestion request. DataService stores connectionAddress and derives publicIp only for a public address; device-provided publicIp values cannot override this observation. Direct internet connections expose the NAT/egress address. Local USB forwarding, private networks or an intervening proxy may hide it. No proxy header or third-party lookup is used. Raw MQTT receipt hashing and deduplication remain based on the original envelope.

Device information now spans both right-hand cards (location, then groups/tags) on desktop. The map fills the available height. On phones the cards stack; network addresses wrap within their value cells. All added portal labels have English and Spanish resources.

Verified on BANPAIS NEW9810 H3R000700069081: Wi-Fi interface wlan0, private IPv4, Wi-Fi MAC and two IMEIs reported. Android reports both SIM slots ABSENT, so neither ICCID is available. The USB lab connection is loopback at the broker, so public IP is explicitly unavailable. 121 integration checks pass, including rejection of local/shared addresses as public and untrusted device public-IP values. Both Android brand builds pass.

DESIGN BASELINE / CHAPTER 23Markdown source ↗

File-first package upload

Selecting a file immediately uploads it to the data service through the MVC portal. The progress bar measures browser upload bytes, then switches to an indeterminate parsing and signature-verification stage. Saving the build does not upload the file a second time.

APK metadata includes the embedded application label, package ID, version name and code, minimum SDK and signing identity. Native A10 metadata comes from the signed nested application archive: cfg/appname.txt provides the display name and cfg/version.txt provides the version; the exact tar.gz remains unchanged. Packages created before cfg/appname.txt was introduced retain the UIC Payment fallback. The portal fills the display name and build name; package identity and version remain read-only. Only Android model choices are displayed for APKs; Linux ZIPs and A10 packages expose Linux models. The data service independently validates model platforms when saving.

Icons are read from embedded PNG resources (up to 256 KiB), or converted from simple Android vector paths into generated SVG with restricted path and color attributes. Adaptive icons, resource-dependent vectors and other unsupported drawables show an explicit fallback notice. New catalog entries retain supported extracted icons in artifact storage; existing entries require a new upload to acquire an icon.

Uploads are scoped to the authenticated operator and customer, expire after one hour, and are consumed once on save. Pending state currently lives in the data service process: after a restart, select the package again. A background cleanup removes expired unsaved packages and icon sidecars; committed artifacts are checked before deletion. Release remains an explicit subsequent review step. Existing 128 MiB package and archive-expansion limits remain enforced.

Validation: 128 integration checks passed, including staged metadata/vector icon extraction, no catalog publication during inspection, server rejection of Linux targets for APKs, customer isolation, and duplicate-save prevention. Browser verification used UIC Device Lab 1.0.0, confirming automatic metadata/icon preview, progress state and responsive phone layout. No deployment was created by this verification.

DESIGN BASELINE / CHAPTER 24Markdown source ↗

Push an application from a device

The Applications tab provides a paper-plane Push application button. Its dialog selects an application and one released build compatible with the device model/platform. The exact device is fixed as the target. Optional UTC scheduling and the delivery window use the existing deployment review and confirmation flow.

After confirmation, the Portal returns to the device Applications tab with the install task visible. It polls the command through queued, dispatched and terminal states. A successful install automatically queues a status-report command; after that report is committed, the page reloads the application inventory. The device dialog submits the logical application/version so the server can select the correct model-specific APK.

Start after installation is off by default and requires the reported start_after_install.v1 capability. The server checks that capability, includes the option in the request identity and command payload, and requires launchStatus=requested alongside verified installation evidence before accepting success for an install-and-start task.

UIC Home 3.4.0-dev (7) implements this on both brand flavors. It verifies the installed APK before asking Android to open its launcher activity. A durable pre-launch record prevents repeated launch attempts after redelivery or interruption. A crash during that step is reported as interrupted rather than retried. Android may restrict background activity starts: requested means the launch intent was submitted, not proof that the app became visible. Launch errors retain an explicit installed-but-launch-failed result.

Validation: 133 integration checks passed, including capability gating, command propagation, idempotency and result evidence. Both Android flavors built. NEWPOS agent updated in place on H3R000700069081; telemetry reports 3.4.0-dev and enables the checkbox. Desktop and phone dialog layouts checked. No application deployment was submitted during UI verification; physical install-and-launch remains to be exercised with a chosen released build.

DESIGN BASELINE / CHAPTER 25Markdown source ↗

Device application removal

The device inventory provides a trash button for non-home apps. A localized dialog names the app and package and asks for confirmation, including the possible loss of local app data. UIC Home has no removal control. Offline devices and agents without uninstall_application.v1 have disabled controls.

The Portal redirects back to the same Applications tab with the removal task visible and refreshes its state automatically. After verified removal succeeds, the Portal requests a fresh terminal status report and reloads the inventory so the removed application disappears without a manual refresh.

The service requires explicit confirmation, membership/customer scope, an online device, the reported capability and inventory membership. It rejects the reported agent package and UIC Home package family. The agent independently rejects its own package, UIC Home packages, the active Android home app and system/system-update apps.

UIC Home 3.5.0-dev (8) calls the NEWPOS/NEXGO uninstall SDK through the brand interface. The durable command records the attempt before invoking the SDK, then polls package absence for up to two minutes; redelivery does not invoke uninstall again. Success requires the matching package ID and absent=true. Commands expire after five minutes. Results appear in Recent commands; periodic telemetry refreshes inventory.

Validation: both Android flavors built and 139 integration checks passed, including missing confirmation, protected home, missing inventory, idempotency and absence evidence. NEWPOS test agent updated in place; portal confirms UIC Home has no uninstall button. No real device application was uninstalled. Physical uninstall remains to be tested with a disposable app.

DESIGN BASELINE / CHAPTER 26Markdown source ↗

Remote desktop — initial implementation

Operator flow

Open a device → Operations → Remote assistance. The device must be online and advertise remote_desktop.v1. Current agents wake the screen to present the request; a secure keyguard still requires local unlocking. The terminal user approves the UIC screen-sharing prompt and Android MediaProjection prompt. Enable UIC remote input in Android Accessibility to use taps, swipes and Back/Home/Recents. A foreground notification allows the terminal user to stop sharing. The portal provides End session.

Transport and admission

The secure DesktopSession primitive lives under TMS.RemoteControlRelay and is linked into the MVC portal host for this initial deployment. The copied legacy relay runtime remains disabled; its shared API-key admission and legacy database are not activated. The Android client connects over pinned TLS WebSockets on the existing package HTTPS endpoint (15102 locally), while the browser uses a same-origin authenticated WebSocket. No AWS components are required.

The operator starts through an authenticated CSRF-protected POST. A 256-bit random terminal ticket is delivered through the device-scoped MQTT command, used in an HTTPS header, and never embedded in the viewer page or URL. Admission lasts two minutes. Sessions last at most ten minutes, support one terminal/viewer, and end when either connection disconnects. The browser origin, operator session, customer membership, device assignment epoch and enabled status are checked; authorization is revalidated every five seconds. The session table is bounded at 100 entries. Frames and input are size/rate limited; slow peers are disconnected instead of accumulating frames. No screen recording is stored.

Screen and input

The Android MediaProjection foreground service produces JPEG frames at up to approximately three frames per second, scaled to 480 pixels wide, with backpressure. This is an initial support-oriented desktop stream, not the legacy H.264/WebRTC path. Android protected surfaces remain protected. An accessibility service handles only normalized gestures and Back/Home/Recents during an active session. It does not retrieve accessibility window contents or auto-approve permission prompts.

Limits and qualification

Current screen dimensions are fixed when capture starts; rotate the device before starting a session. Current agents use a wake-capable approval activity. The remote command result means the consent request was delivered to the agent; only incoming frames prove screen sharing is live. Sessions live in memory and do not survive a portal restart. Session-end audit events and standalone relay hosting are follow-up work; the start command uses the existing command audit. NEWPOS/NEXGO builds compile, but each vendor must be physically qualified.

145 integration checks passed, including authenticated session creation, duplicate-session rejection, no ticket in viewer HTML, terminal admission rejection without TLS/ticket, explicit end, and rejecting ended sessions. Agent 3.6.0-dev (9) was installed on the NEWPOS test terminal. Live screen/input verification awaits the operator approving Android permissions.

Remote input readiness

The terminal reports accessibility-service readiness once per second during sharing. The portal shows a localized View only notice with activation instructions and disables touch/navigation controls while unavailable. Enabling the service updates the viewer without restarting the session. The NEWPOS test user enabled the service after confirming screen sharing worked.

Wake for remote approval

UIC Home 3.6.1-dev (10) validates the request and wakes a sleeping display with a bounded wake lock, then presents the approval activity using the enabled accessibility service when available. It does not dismiss a secure keyguard or approve MediaProjection consent. The visible request keeps the display on only until the command expires or the activity closes. Verified physically on NEW9810: before request, power state Dozing; after the portal request, Awake with RemotePermissionActivity resumed. Both NEWPOS and NEXGO builds passed; NEXGO wake behavior has not been physically tested.

DESIGN BASELINE / CHAPTER 27Markdown source ↗

Parameter workspace and application delivery

Implemented checkpoint updated 26 September 2026. Portal → authenticated gRPC → Dapper → SQL Server 2022; Android UIC Home 3.9.14-dev uses the read-only provider and Linux xTMSAgent uses the parameter file bridge. Schema group values render related fields together. No legacy UIC Connect project dependency.

Operator workflow

  1. Open Parameters in the sidebar, select a customer and create a schema name (for example PAYAPP), or import a UIC Connect schema export.
  2. The editor shows device tables as an indented tree with connector lines, parent names and one/many-per-parent badges. Shared catalogs appear separately. Expand any table to edit its fields, or use Add child table to preselect that parent. Add shared catalog tables and child device tables. Edit fields, required/key flags, types, defaults, options, catalog references, validation and row/column/span. Preview uses the device form renderer. Tables and fields have a single Label, authored in the language chosen by the bank. The same label is shown in every portal language.
  3. Optionally configure the consuming Android package and/or signing certificate SHA-256. Blank values independently skip those restrictions; device authentication and customer/device scoping remain mandatory. Save the schema. It stays editable under the same name.
  4. Open Shared catalogs, create/edit/delete records and Save. Reference selectors use the current saved catalog.
  5. Choose Device parameters, select a terminal and start empty or from a template. Add Terminal, Acquirer and Issuer records, then Save. There is no Publish action or visible revision lifecycle.
  6. Every save validates required values, types, keys, parents and references. A schema or catalog change also validates existing dependent configurations in the same transaction. Breaking changes are rejected with the affected configuration name and validation reason.
  7. Save as template and Copy to device use the current saved values. Copying saves the replacement immediately, with confirmation before overwriting an existing target. Review merchant/terminal identifiers before copying. Templates are independent after creation.

Current data and download compilation

The current Json in each customer-scoped schema, catalog, template and device document is authoritative. Existing records use their last saved content without a republishing migration. Internal counters support optimistic concurrency and audit history, but are not displayed as user-facing versions. Legacy Published fields remain in the database/protobuf for compatibility; they do not govern availability. The obsolete Publish request flag is ignored.

On every authenticated download the service reads the current device configuration, schema and shared catalogs in one serializable transaction, rechecks device ownership and assignment epoch, enforces the current schema's application restrictions, validates the records and compiles the response. No stored published snapshot is used. Invalid legacy configurations cannot be downloaded until corrected and saved.

The payload retains format: uic-tms-parameters, formatVersion: 1, schemaName, deviceId, assignmentEpoch, schema, catalogs, and rows with row IDs and parent IDs. Internal revision, schemaRevision, and catalogRevision fields identify the inputs for diagnostics. Consumers should compare the SHA-256 of the complete response, not just the device counter, because shared data can change independently.

Saved schema/catalog changes appear on the next request without resaving each device. The existing SHA-256 response header covers the freshly compiled bytes. Save makes data available; it does not mean the payment application has downloaded or applied it. The Android provider protocol is unchanged.

Android payment app contract

UIC Home exposes a read-only ContentProvider, authority <installed-home-package>.parameters. Make the call from a background worker, not the application UI thread:

val uri = Uri.parse("content://com.uic.tms.home.uic.newpos.debug.parameters/PAYAPP")
val parameters = context.contentResolver.openInputStream(uri)!!.use {
    it.readBytes().toString(Charsets.UTF_8)
}
// Parse and validate schemaName and response hash; transactionally apply to the payment database.

Use the production Home package authority for release builds. Android package visibility declarations may be required for provider discovery on the consuming application.

Home obtains the caller UID from Binder, resolves its installed package and signing certificate, and sends those with enrolled device credentials to the HTTPS parameter endpoint. Caller-provided identities are not accepted. The service independently checks each nonblank package/certificate restriction in the current saved schema. Blank restrictions do not disable device authentication. Shared UIDs and multi-signer APKs are rejected in this checkpoint.

Downloads reuse the enrolled server certificate trust and normal hostname verification. Redirects are disabled; requests and responses are bounded. Home checks the snapshot hash, device, assignment epoch and schema name, writes the complete response atomically to a private temporary file and shares only the validated response through a reliable pipe. Enrollment secrets never leave Home. Failures close the pipe with an error; the application must retain its prior configuration and retry. There is no offline-cache fallback or application-applied acknowledgement yet.

Supplied PAYMENT_APP example

The schema imports successfully: nine tables and 223 fields. It has four shared catalogs and five device tree tables. PAYMENT_APP is saved for BANPAIS.

The supplied data export has 26 catalog records and no device records. Its EMV data contains 27 fields absent from the attached schema (25 contactless and two contact), and one populated encrypted field. Import validation reports unknown fields and unsupported secrets instead of silently discarding data. Reconcile those fields in the saved schema; remove secret values from a working import copy, preserving the original file.

Legacy default_from, value_from and inheritable metadata are retained as reference metadata, but no external bank/lane lookup or legacy UIC Connect inheritance is executed. Explicit values are required in TMS. Nonempty legacy tree-record imports are rejected because their parent-identity conversion needs a defined mapping; native UIC exports preserve row IDs and parent relationships.

Current boundaries

Validation and local environment

160 integration checks passed, including tenant/device isolation, immutable schemas, draft visibility, snapshot hashing, signer authorization, catalog pinning, stale edits, templates, invalid parents and unknown fields. NEWPOS and NEXGO APK builds compile. The physical device was not connected to ADB during this checkpoint, so IPC on the actual payment application remains unverified.

SQL Server reported OS error 21 / SQL error 823 for the existing UICConnectTMS_IntegrationTest files. The main UICConnectTMS database passed DBCC CHECKDB ... PHYSICAL_ONLY; migration 005 was applied. The original test database was retained. Tests were run against a fresh UICConnectTMS_ParametersTest database:

./scripts/Test-Integration.ps1 -TestDatabase UICConnectTMS_ParametersTest

The original test database's storage issue still needs investigation; no repair/data-loss operation was performed.

Portal dialog convention

Use the shared window.uicConfirm(message, options) styled modal for confirmations. Publish, deletion, import cleanup, draft replacement and unsaved-change navigation all use it. Cancel and Escape leave the action untouched; focus returns to the triggering control. Do not introduce native alert, confirm, prompt or beforeunload dialogs. Browser close/reload cannot show custom asynchronous confirmation; save drafts before closing or reloading. Portal link/form navigation is guarded with the styled discard dialog. Form constraint errors render inline, with accessible descriptions, instead of native validation bubbles.

DESIGN BASELINE / CHAPTER 28Markdown source ↗

Windows Server installation

Package and requirements

Extract the complete UICConnectTMS-win-x64 ZIP to a local staging directory. Run Configure.cmd, or run setup/TMS.ServerSetup.exe as Administrator. This is an interactive console EXE with masked password entry; it does not require the Windows Desktop runtime.

Requires Windows x64, .NET 8 runtime and ASP.NET Core 8 runtime. No SDK or IIS is required. The reported target server with both runtimes at 8.0.10 meets the major-version requirement. Keep server runtimes patched through your normal maintenance process.

The SQL database must already exist. Setup tests the connection and applies embedded, versioned SQL migrations without dropping the database. The SQL login needs migration DDL permissions for setup and normal application DML permissions at runtime. Existing administrator accounts are preserved.

APK metadata and signature inspection runs inside .NET using bundled libraries. No Android SDK, aapt, external apksigner, Java installation or tool-path configuration is required on the server. Keep all payload files together; see Third-party-notices.md for the bundled components.

Install or update step by step

  1. Copy the new ZIP and its .sha256 file to the server. Compare Get-FileHash .\UICConnectTMS-win-x64-<timestamp>.zip -Algorithm SHA256 with the checksum file, then extract into a new staging folder. Keep all package folders together.
  2. For an update, back up SQL, application artifacts, configuration and the TLS certificate. Schedule a maintenance window: setup applies database migrations before restarting services. Stop the three TMS services before running setup for an update.
  3. Run Configure.cmd as Administrator. On an existing installation, select the same configuration directory (default C:\ProgramData\UICConnectTMS). Enter retains stored settings and passwords; do not switch directories unless creating a separate installation.
  4. Enter SQL connection settings, portal and MQTT ports, public hostname, certificate and storage paths. SQL database creation is a separate prerequisite. Use the existing PFX on updates to retain terminal trust.
  5. No APK inspection tool paths are required. The package includes the inspection libraries and does not compile, configure or install any Android application.
  6. Setup checks the database before asking about the initial administrator. The default is no when users already exist and yes only when the database has no users. For a new database, create the initial administrator with a password of at least 12 characters.
  7. Answer yes to install/update and start Windows services. Keep the existing installation directory on updates. Permit the configured HTTPS and MQTT TLS ports through the server firewall according to your network policy.
  8. Open https://<server>:5102 (or your configured HTTPS port), sign in, and complete the checks below. No source repository, .NET SDK, Gradle, Android Studio or Windows Desktop runtime is needed on the server.

Verify the installation

In PowerShell, run:

dotnet --list-runtimes
Get-Service UICConnectTMS.DataService,UICConnectTMS.Mqtt,UICConnectTMS.Portal

Confirm all three services are Running, the portal opens, existing customers/devices and parameters are present, and a terminal can reconnect and report telemetry. Test remote assistance with operator consent. Service startup alone does not confirm terminal connectivity.

For APK upload verification, upload the separately supplied UIC-Device-Lab-NEWPOS-1.0.2.apk, select NEWPOS NEW9810, and save the build. Under View versions > Integrity, compare Signature against the previous build. Version 1.0.2 (build 3) uses the same development signing certificate as 1.0.0:

70DCD59AE328312F2154EF64210D95C437351E847975FB215243217CD6739D50

Its APK file SHA-256 is:

62E814E6EDC57F5964666C1C2F12ED0C80B93B04C735BE37CA3147449EA89AA3

The file hash changes between builds; the signing-certificate fingerprint should match for this update. Uploading validates a build; release and device deployment are separate actions. The demo APK is intentionally separate from this server package.

Configuration

Enter accepts the shown default or stored non-secret setting. Password prompts show asterisks and never display a stored value; Enter keeps an existing password. On first setup there is no default SQL or administrator password. PFX passwords and internal service keys are generated when creating a certificate.

Setting Default
SQL server / database localhost / UICConnectTMS
SQL login app_uic_tms, password required
SQL SSL / trust server certificate true / false
Portal HTTP 15100, loopback only
Portal HTTPS 5102, all IPv4 interfaces
Internal gRPC 15101, loopback HTTP/2 only
MQTT TLS only, 5883, all IPv4 interfaces
Remote desktop Portal HTTPS endpoint, same certificate
Remote session / admission / concurrency 10 minutes / 120 seconds / 100
Configuration C:\ProgramData\UICConnectTMS
Installed programs C:\Program Files\UICConnectTMS

Provide a public DNS name/IP matching the TLS certificate. Supply an existing PFX, or allow setup to create a self-signed server certificate at a new path. The generated public .crt is available for device enrollment trust. Self-signed certificates are not automatically browser-trusted. No trust-store or firewall rules are changed automatically. Allow inbound configured HTTPS and MQTT TLS ports as needed. HTTP and gRPC remain loopback-only.

MQTT requires an individual provisioned client certificate from the separate IoT CA, plus each enrolled device's unique credentials; there is no shared/default broker password or anonymous listener. Topic authorization remains device scoped. Remote desktop uses the active authenticated MVC relay implementation; the disabled legacy standalone proxy is deliberately not installed. Session limits are configurable, but remote consent and authorization checks remain enforced.

Certificate selection

Choose pfx, machine, or user in setup. Both HTTPS (including remote desktop) and MQTT use the chosen certificate.

Matches display subject, friendly name, expiry and thumbprint; choose the numbered certificate. Setup checks validity dates, private-key access and server-authentication usage. Check that the certificate SAN covers the public server hostname and that clients trust its issuer.

Store selection creates an encrypted PFX service copy in the protected configuration folder, with a generated password stored in DPAPI. This allows LocalService to use a certificate selected from a user's store without depending on that user's profile or changing the original private-key permissions. Store private keys must be exportable; non-exportable keys are rejected with instructions to supply a suitable PFX. Original store certificates remain unchanged. Store renewal is not automatic: rerun setup, select the renewed certificate and restart services.

New installations default to SQL user app_uic_tms, HTTPS 5102, and MQTT TLS 5883. Existing installations retain stored values as prompt defaults; explicitly enter the new values when migrating and update firewall rules and terminal endpoints accordingly. Setup does not create the SQL login.

Account recovery and MFA protection

Setup asks for the public HTTPS portal URL used in password-recovery links. Email recovery is optional. Choose standard smtp delivery or the native aws-ses API. SMTP requires the host, port, TLS, sender address and optional username/password. AWS SES requires a verified sender identity, region and either the AWS default credential chain (recommended for an EC2 instance role) or a dedicated access key with ses:SendEmail permission. Accounts still in the SES sandbox can send only to verified recipients. Verify outbound delivery and sender authorization after installation. The public recovery form deliberately returns the same response for known and unknown addresses.

Setup creates an installation-specific account security key. DataService uses it to encrypt authenticator MFA secrets with AES-GCM. The account key, SMTP password and any explicitly configured AWS SES access credentials are stored only in runtime.secrets.dpapi. Preserve that protected file on in-place upgrades and include it in the coordinated server backup. If the account key is lost, enrolled MFA secrets cannot be decrypted and affected accounts require administrative recovery.

MQTT IoT certificates

The installer creates a separate IoT certificate authority on first installation and preserves it on upgrades. Enter the 64-hex common bootstrap key using the masked prompt and securely provision that key into terminal enrollment. The CA password and bootstrap key are DPAPI-protected; the private CA PFX is access-restricted. Keep the CA and database together in protected backups.

MQTT now requires client certificates. Older agents using only passwords cannot connect. Install UIC Home 3.9.0-dev/build 13 or later with its secure enrollment settings. Device > Operations > Credential management > IoT certificates provides status, rotation and revocation. See the included IoT-certificates.md for the protocol and rollout limitations. The installer still does not build or configure the Android app.

Password protection

runtime.json stores only non-secret settings. runtime.secrets.dpapi contains the complete database connection string, PFX password, optional SMTP password or AWS SES credentials, MFA encryption key and internal service keys encrypted with Windows DPAPI LocalMachine. Secrets are decrypted only in service memory. Neither development runtime configuration nor development certificates are included in the package.

The configuration directory ACL grants Administrators and SYSTEM full access and LocalService read access. Artifact storage grants LocalService modify access. Installed programs grant LocalService read/execute only. DPAPI protects secrets at rest, not against a compromised administrator or a process already running with an authorized identity. The encrypted file is machine-bound: rerun setup and enter secrets when moving to another server. Back up the database and configuration together using your protected server backup process; do not expect copying the DPAPI file alone to a new machine to work.

Windows authentication is optional, but setup runs as your administrator while services run as LocalService. A successful integrated-auth setup connection does not prove the service identity has SQL access. SQL authentication is the default deployment choice; for Windows authentication arrange the correct SQL grants/service account before starting.

Services and updates

Setup optionally installs/updates and starts UICConnectTMS.DataService, UICConnectTMS.Mqtt and UICConnectTMS.Portal. They run as LocalService, start automatically and restart after failures. Portal and MQTT depend on DataService. Keep the extracted package to rerun configuration. Settings take effect after restarting services (the install/update choice does this).

The installer stops existing TMS services before copying program files. It never deletes the database, artifacts, or configuration. It does not provide automated binary rollback: retain the previous package and back up SQL/configuration before upgrading. Setup requires administrator elevation and service installation must be validated on the target server. Use Windows Event Viewer for service startup failures. The installer does not write SQL passwords or administrator passwords to log files.

The portal uses Kestrel directly. Access https://<server>:5102; the setup summary shows configured ports. Enroll terminals with the new server address, MQTTS port and certificate; local-development enrollment settings do not automatically transfer.

Build and checks

Run scripts/Build-ServerPackage.ps1 on the development machine. It produces framework-dependent win-x64 executables, a ZIP, and SHA-256 checksum. setup/TMS.ServerSetup.exe --self-test checks DPAPI round-trip without changing server settings or installing services. Live Windows-service registration requires an elevated target-server run and is not performed by the build.

Installation diagnostics

Setup keeps its window open on both success and failure. Service installation writes a timestamped service-install-*.log in the configuration directory and prints each service status. A success report means all three services were still Running after the startup check; it is not a substitute for testing portal login and device connectivity.

If setup fails, preserve the log, correct the reported error, and rerun Configure.cmd from the latest extracted package. Existing configuration and secrets are retained. Windows services run without desktop windows; inspect them in Services or with Get-Service UICConnectTMS.* in PowerShell.

For manual diagnostics, stop the corresponding service first to avoid port conflicts. Installed programs use their adjacent TmsConfig.path file to find the saved configuration. An explicit path also works:

& 'C:\Program Files\UICConnectTMS\TMS.DataService\TMS.DataService.exe' --TmsConfig 'C:\ProgramData\UICConnectTMS\runtime.json' --contentRoot 'C:\Program Files\UICConnectTMS\TMS.DataService'

Run diagnostics as Administrator because the configuration is access-restricted. Do not copy development .local files to the server. The default production configuration is under ProgramData, not Program Files.

Rotating diagnostic logs

Setup and all three services use Serilog file logging. Files are stored in the logs subdirectory next to runtime.json (normally C:\ProgramData\UICConnectTMS\logs). Each component has its own files: Setup-YYYYMMDD.log, TMS.DataService-YYYYMMDD.log, TMS.Connectivity.Mqtt-YYYYMMDD.log, and TMS.Portal-YYYYMMDD.log. Portal logs also cover its remote desktop hosting.

Service logs roll daily and at 10 MB. Keep 30 files per component by default, including size-roll segments: this means 30 files, not necessarily 30 days. The oldest files are removed when rolling. Installer prompts LogFileSizeMB (1–100) and LogRetainedFiles (2–365) configure services; restart them after changes. Setup itself uses fixed 10 MB / 30-file defaults.

Startup/shutdown, host errors and application diagnostics are recorded; startup failures include exception type, error code and stack. Request bodies, credentials, configuration dumps and verbose HTTP request logging are not enabled. Treat diagnostic files as private operational data. The installer gives Administrators/SYSTEM full access and LocalService modify access only to the logs folder, without granting write access to protected configuration.

The separate service-install-*.log transcript remains in the configuration directory and records Windows service registration and startup results. These per-run transcripts are not automatically rotated; archive or remove them under your server retention policy. Failures before setup can open the protected log directory remain visible in the console. Windows Event Viewer remains useful for Windows Service Control Manager and early process failures.

Remote desktop over HTTPS

Remote desktop shares portal TCP 5102 using secure WebSockets; MQTT remains TCP 5883. Browser HTTPS sessions may negotiate HTTP/2 WebSockets (CONNECT), while Android uses HTTP/1.1 upgrade (GET). Both remote socket endpoints support both methods. Form antiforgery applies to Start/End operations; socket admission uses the operator session and exact Origin for the viewer, and HTTPS plus the short-lived admission ticket for the terminal.

Portal logs include remote role, request method/protocol, WebSocket detection, handshake response status and connection termination. They do not record admission tickets or frame/input contents. HTTP/1.1 success is 101; HTTP/2 success is 200. A 400/405 response before connection can indicate an old portal build with GET-only routes or form-token filtering on CONNECT. Update the portal and create a new session. A reverse proxy, if present, must forward WebSockets correctly.

Included in the September 24 workspace update

Upgrade the complete service payload together: Portal, DataService, MQTT and their bundled dependencies. The group changes include updated gRPC contracts; do not apply only the Portal DLL. This feature update adds no database migration and does not require recreating the database. Retain existing configuration, secrets, TLS and IoT CA files. The installer retains them when using the same configuration directory.

The remote keyboard requires UIC Home 3.9.5 or later and enabled UIC remote input Accessibility. The connected test terminal has already received this agent version. The server package does not contain or install Android APKs. After upgrading, refresh the browser and create a new remote session.

Validation for these changes: 190 integration checks passed on the development environment, including direct group filtering, tenant authorization, tag-preserving moves, and bounded remote text forwarding. Final Windows service startup and device keyboard operation must also be checked on the target server.

DESIGN BASELINE / CHAPTER 29Markdown source ↗

MQTT IoT device certificates

Trust and authentication

MQTT requires mutual TLS. The existing HTTPS/MQTT server certificate still authenticates the server and its hostname. A separate self-signed UIC Connect TMS IoT CA signs individual device client certificates (RSA, SHA-256, client-authentication EKU, one-year lifetime bounded by the CA expiry). This CA is not the APK signing certificate or the portal HTTPS certificate.

The Android agent generates its private RSA key inside AndroidKeyStore. It submits only the public key, and downloads only the issued public certificate. The private key never traverses the network. TLS proves possession of that key. The broker additionally binds the exact SHA-256 certificate fingerprint to the enrolled device, assignment epoch and existing unique device credential. Anonymous and password-only MQTT connections are rejected.

Bootstrap proof and provisioning

Android enrollment must securely supply the known device ID, serial, assignment epoch, unique device password, server trust certificate, HTTPS URL and iotBootstrapKey (32 random bytes encoded as 64 hexadecimal characters). The common bootstrap key is never embedded in source/APKs or shown by the installer. The current Android development transfer writes private app enrollment storage through USB debugging; production Android enrollment distribution is a separate administrative process.

The A10 Linux xTMSAgent performs first-run credential enrollment itself after a SuperAdmin onboards the hardware serial under the customer and UIC A10-T model. Its customer-specific installation package contains a protected bootstrap file with customer identity, server endpoints and the common bootstrap key, but no terminal Device Secret. The agent reads the hardware serial and full reported model, signs a short-lived claim for that existing record, receives its unique Device Secret, and atomically saves it with mode 0600. It deletes the bootstrap file, provisions its client certificate and then connects to MQTT. A serial that is not onboarded is rejected; the terminal displays Enrollment pending and retries every 60 seconds or when Enter is pressed. The development terminal's updateTMS.sh only installs the package. Protect the customer package because extraction of the common bootstrap key remains a risk; MQTT and subsequent HTTPS access still require the independently issued device identity, secret and certificate.

POST /device-iot/issue is HTTPS-only and rate limited. The proof is AES-256-GCM with a random 12-byte IV, 16-byte tag, and AAD UIC-TMS-IOT-v1. The wire proof is IV + ciphertext + tag. Authenticated JSON includes deviceId, SHA-256 of trimmed uppercase serial, assignmentEpoch, SHA-256 of SubjectPublicKeyInfo, UTC Unix timestamp, and a random 32-hex nonce. Clock tolerance is two minutes. SQL stores used nonces; fresh time-bound proofs are required for retries. Nonce retention is ten minutes, longer than the replay-validity window. Certificate issuance is serialized per device.

Only registered, enabled devices with enabled customers may enroll. Before confirmation a retry with the same key returns the same certificate; changing the key requires operator rotation. After storing the certificate, the agent signs UIC-TMS-IOT-CONFIRM-v1 + newline + the uppercase certificate SHA-256 using SHA256withRSA and calls /device-iot/confirm. Confirmation is idempotent and marks the certificate Confirmed, proving that the terminal possesses the private key while leaving recovery open if MQTT cannot yet connect. The first MQTT admission that successfully validates both the confirmed client certificate and the device's unique password atomically marks the certificate Provisioned, records the audit event and disables subsequent credential/certificate downloads. Issued certificates cannot establish MQTT sessions.

Lifecycle and operator controls

Open Device > Operations > Credential management > IoT certificates. Customer scope controls read access; SuperAdmin controls rotation and revocation, with the portal confirmation dialog. The adjacent Device Secret action rotates the separate per-device credential, not the IoT certificate. See the bilingual manuals for recovery steps.

Revoked rows retain DER certificate, fingerprint, device binding, expiry, revoked time and reason. They are never reused or deleted during rotation. The database is the authoritative revocation registry; this implementation does not publish an X.509 CRL or OCSP service. The broker checks the custom CA chain and SQL state during TLS authentication, checks the device/fingerprint binding during MQTT authentication, and rechecks authorization for device traffic and during its dispatch loop. Existing sessions are disconnected when revocation is observed (normally within the next one-second loop; service failures/latency may delay physical disconnect). Data-service failure denies new TLS admissions and prevents authorized operations; no cached allow fallback is used.

Server installation and migration

ServerSetup generates a distinct 10-year IoT CA on first installation, preserves it on updates, and requires the administrator to enter the common bootstrap key through a masked prompt. CA PFX/password and bootstrap key must be backed up securely. Production passwords/key are protected by DPAPI and restricted ACLs. Development .local configuration contains test secrets and must not be distributed. The server package contains no CA private keys or bootstrap secrets.

Upgrading the broker is a mandatory mutual-TLS change: older agents without device certificates will no longer connect. Provision the common key and unique device enrollment, install UIC Home 3.9.14-dev or the current xTMSAgent, and verify each device reaches Provisioned before completing rollout. There is no password-only compatibility listener. Losing a terminal key requires operator rotation. Back up database and CA together; stale revocation data can restore obsolete authorization. CA rotation/multiple concurrent issuers and automatic renewal are not implemented.

Validation

dotnet run --project tests/TMS.IotTests uses the isolated UICConnectTMS_IotTest database to exercise stale/future proofs, serial/key validation, replay rejection, retry delivery, possession acknowledgement, recovery before connection, connection-gated download lock, foreign/revoked certificates, authorization and retained history. The main integration suite provisions a test certificate and checks password-only MQTT rejection before testing the authenticated MQTT flow.

Android TLS requires the Keystore key to allow the digest/padding operations used internally by Conscrypt; see Android KeyGenParameterSpec documentation. This does not export the key or disable TLS validation.

Verified on NEWPOS NEW9810, NEXGO N82 and UIC A10-T: first-connection provisioning lock, MQTT reconnection and fresh telemetry. NEWPOS rotation retains revoked history. Current clean integration validation passes 239 checks in addition to dedicated IoT lifecycle checks, including connection-gated provisioning, revocation and reconnect denial.

DESIGN BASELINE / CHAPTER 30Markdown source ↗

Current implementation architecture

Authoritative implementation checkpoint: 26 September 2026. This chapter supersedes conflicting target-state descriptions in earlier chapters. User documentation: English portal manual, Español, Android integration and Linux integration.

Runtime topology

Browser -- HTTPS/WSS 5102 --> TMS.Portal / Kestrel MVC + remote relay
                                  | operator cookie/session + antiforgery
                                  | authenticated gRPC / HTTP/2 loopback 15101
                                  v
                              TMS.DataService -- Dapper --> SQL Server 2022 or PostgreSQL 17
                                  ^
                                  | authenticated gRPC
Android/Linux -- MQTTS 5883 --> TMS.Connectivity.Mqtt
Android/Linux -- HTTPS 5102 --> enrollment, IoT, package and parameter endpoints

Local development uses HTTP 15100, HTTPS 15102 and MQTTS 18883. Windows deployments use three LocalService services and SQL Server. Linux deployments use three hardened systemd services and PostgreSQL. The provider is selected by DatabaseProvider; the same DataService binary supports both. Internal gRPC is cleartext HTTP/2 restricted to loopback and must never be exposed publicly. AWS IoT, Redis, separate dispatcher processes and multiple portal nodes are not deployed.

Project responsibilities

Component Responsibility
TMS.Portal MVC/Razor, bilingual UI/manuals, account recovery/MFA, HTTPS device endpoints and Android remote viewer/relay
TMS.Contracts Protobuf RPC contracts and generated types
TMS.DataService Authorization, customer/device use cases, audit, application/parameter/location and IoT lifecycle
TMS.DBAccess Parameterized Dapper persistence, SQL Server/PostgreSQL provider adaptation and transactional policy
TMS.Connectivity.Mqtt Mutual-TLS broker, per-device topic authorization, telemetry, presence, command dispatch/results
TMS.Hosting Service hosting, logging and protected configuration
TMS.ServerSetup / TMS.Setup Windows installer, DPAPI secrets, service configuration and migrations
Android UIC Home Launcher, MQTT agent, telemetry, operations, applications, parameters and remote assistance
Linux xTMSAgent A10 communications/bootstrap, MQTT agent, payment-app supervisor/bridge and native package operations

Operator identity and customer boundary

The SQL-backed identity store uses BCrypt passwords, server sessions and optional TOTP MFA with single-use recovery codes. Password recovery supports SMTP or AWS SES; reset links are hashed, single-use and expire after 30 minutes. Security changes are audited without secret material.

SuperAdmins can manage all customers, SuperAdmins, model catalog and onboarding. Customer administrators/users are restricted to memberships and feature-level Read/Write roles for their own customer. Portal controllers and DataService both enforce customer/device scope; hiding navigation is not authorization.

Device trust and enrollment

HTTPS and MQTT validate the server certificate. A separate IoT CA issues per-device client certificates. MQTT requires the current Device Secret, assignment epoch, exact non-revoked certificate fingerprint and own-topic policy.

A terminal cannot register itself in the fleet. SuperAdmin first onboards its exact manufacturer serial and portal model. Android currently uses an authorized private enrollment import for test/debug. Linux xTMSAgent uses a protected customer bootstrap to claim the existing serial, stores the unique returned secret with mode 0600, deletes the bootstrap and provisions its IoT key/certificate. The first successful MQTT admission marks the certificate Provisioned and closes further downloads. See chapters 29 and 33.

Persistence, commands and applications

SQL is authoritative for customers, users/roles, audit, devices, presence, commands, deployments, application metadata, parameters, IoT history and location history. SQL Server and PostgreSQL expose the same application behavior; a deployment chooses one provider and cannot point one database at both engines. Application binaries remain in private filesystem storage and must be backed up with the selected database.

Commands are durable, scoped to customer/device/assignment and delivered at least once. Agents persist command IDs and outgoing results; SQL commit receipts complete the device outbox. Queued/Dispatched is not execution success.

One logical application version can contain multiple immutable model-specific artifacts. The deployment resolves the correct artifact per target. Android APKs are parsed and signature-verified in process. Native A10 prodapp.tarball.tar.gz packages are structure/hash checked by the portal and vendor-signature checked by the terminal. Android and A10 install/uninstall are implemented; successful A10 changes reboot and report refreshed inventory. Malware scanning remains outstanding.

Parameters

The current saved schema, catalogs, templates and device JSON are compiled on request. Group metadata controls portal layout. Templates/copies use saved values. Android exposes parameters through a read-only provider; A10 uses a local file bridge. Scheduled parameter push, secret-value storage and a separate payment-app applied receipt are not implemented.

Telemetry and location

Current telemetry includes portal and reported model, OS/version, agent version, uptime, capabilities, free/total storage, available/total memory, network interfaces, observed public IP and user application inventory. Android additionally reports battery/SIM information when firmware permits. A10 inventory reads userappl/cfg/appname.txt and version.txt.

Valid reported location is stored as current state and history. A new history point is created after at least 100 metres. Operators with Device Write can set address/map/coordinate location only when no valid reported coordinate exists; telemetry always takes precedence. Address search is server-proxied, cached and rate-limited. See chapter 34.

Android and Linux runtime

UIC Home 3.9.14-dev uses a sticky foreground service, reconnect logic and bounded wake locks. Battery exemption/vendor power qualification remains necessary. Messages can wake an unlocked display; remote capture requires local approval and accessibility input. Sessions are bounded, memory-only and not recorded.

xTMSAgent starts CommServer before enrollment, allowing F2 network configuration on a new A10-T. It reports generic portal model and complete device model separately, supervises the payment app, uses durable MQTT spools and coordinates unsafe operations through payment-app status. Remote desktop is not implemented for Linux. Official A10-T field-install instructions remain pending.

Portal operations and records

The portal includes customer/SuperAdmin administration, customer users/roles, profile/password/MFA, audit log, MQTT diagnostics, device search/groups/tags, app library with per-version/application deletion rules, scalable deployment targeting, task grids/details, parameter schema/catalog/template/device workspaces, session-expiry dialogs and bilingual help.

Device details show telemetry, applications, operations, diagnostics, parameters, map/current/history location and manual positioning when eligible. Audit visibility is global for SuperAdmins and customer-scoped for customer administrators.

Remaining work and evidence limits

Outstanding: production Android enrollment distribution, official A10-T installation procedure, automatic IoT renewal/CA rollover, malware scanning, multi-node relay/session routing, fleet-scale/load/restore qualification, scheduled parameter push, app-applied parameter receipts and Linux remote desktop.

The SQL Server suite has passed 239 clean integration checks plus IoT/package/Android-specific checks. PostgreSQL installation, migration, super-admin login, customer creation, customer-admin login, scoped page access and MQTT status persistence have also been exercised on Ubuntu. NEWPOS NEW9810, NEXGO N82 and UIC A10-T have been exercised with the portal. This evidence does not certify every firmware, carrier network or unattended production fleet.

DESIGN BASELINE / CHAPTER 31Markdown source ↗

UICDemo test agent

The uicDemo client flavor is separate from uic and combines with both NEWPOS and NEXGO brand adapters. Current test deployment covers NEWPOS NEW9810 and NEXGO N82 using model-specific APKs under one logical UIC Home version.

Build from agents/uicu_home:

./gradlew.bat :app:assembleUicDemoNewposDebug :app:testUicDemoNewposDebugUnitTest

Public endpoints are flavor defaults. Device Secret, bootstrap key, device identity and server trust certificate are delivered separately through private debug enrollment. No credential is compiled into the APK. Existing per-device enrollment can override defaults. The remote server certificate was checked against operating-system trust and the administrator-provided thumbprint before enrollment.

This is a debug test build: enrollment uses authorized USB debugging and run-as into the app's private files directory. The app imports tms-enrollment.json, encrypts it with AndroidKeyStore, and deletes the plaintext input. Keep local enrollment files private and out of distributed artifacts. Release fleet enrollment remains a separate managed-provisioning workflow.

Because this flavor has a different package ID, Android treats it as a separate app. Home selection, background battery exemption, location and remote-input Accessibility approval must be verified for UICDemo Home. Do not uninstall the old flavor merely to switch servers; it retains its independent enrollment for returning to local development.

Verified deployment

Built and installed the NEWPOS debug APK. Both unit tests passed. The remote portal confirmed Online telemetry and IoT certificate status Provisioned. The terminal uses encrypted enrollment storage and the incoming plaintext enrollment file was removed by the app. The old UIC agent was stopped; its app data was preserved. UICDemo Home was selected as the home activity.

Per-app Android setup remains necessary: allow background battery exemption, location permission for GPS reporting, and UIC remote input Accessibility for remote taps. Those permissions do not transfer from the old package. No silent Accessibility or battery-permission grant was applied.

3.9.2 launcher update

The screen-off connection permission button now refreshes on activity resume and window focus. It disappears when Android reports the current package exempt from battery optimization, and reappears if that exemption is removed. This change does not grant or revoke permissions or alter enrollment.

3.9.3 remote input setup

The launcher displays Enable remote control / Habilitar control remoto only when this flavor's UIC remote input Accessibility service is not enabled. It opens that specific service's Android settings, with a general Accessibility fallback for firmware without the detail screen. The button rechecks actual enabled-service state on resume and focus, so granting or revoking permission updates its visibility. Android confirmation remains user-controlled.

3.9.4 remote passcode entry

The protected-settings and change-passcode forms now permit screen capture so an authorized remote operator can enter the code using the terminal keyboard. Digits remain masked; six-digit validation, attempt throttling, and clearing fields when leaving the screen remain unchanged. Screenshots and remote capture can now show these forms.

At the user's request, the old local-server UIC Home package was removed from the test terminal. Only UICDemo Home remains installed.

3.9.5 masked passcodes and remote keyboard

Passcode display now applies an always-masked transformation after single-line setup. Remote input supports replacing the focused editable field with up to 128 characters during an active remote session, using Android Accessibility window-content access. Portal keyboard and numeric keypad use masked entry, clear it after sending/disconnect, and support English/Spanish labels. Deploy the matching RemoteKeyboard portal patch; selecting Send to field replaces the selected Android field and does not submit its form. Android confirmation is still required when Accessibility is disabled.

DESIGN BASELINE / CHAPTER 32Markdown source ↗

Groups and subgroups workspace

The Groups and tags page uses an expandable hierarchy on the left and a paginated, searchable compact device grid on the right. Selecting a group shows direct membership; the separate Devices page retains descendant-inclusive group filters. Ungrouped shows devices without a group.

Root and subgroup buttons open the same named-group dialog. Edit permits renaming or choosing another parent; the group and its descendants cannot be selected as parents. The data service independently validates customer scope, cycles and maximum depth. Empty groups can be deleted with a styled confirmation. Groups with children or assigned devices cannot be deleted.

Add devices opens a paginated serial search. Assigning a device moves it from its prior group, preserving its tags atomically. Remove from group leaves the device registered and preserves tags. Group changes save immediately. Tags remain available in a collapsible section below.

Desktop uses two columns; phones stack the tree above the grid. English and Spanish labels are provided.

Deployment requires the updated Portal, DataService and their TMS.Contracts / TMS.DBAccess dependencies together. No database migration or Android update is required. The gRPC additions are direct_group_only on DeviceSearch and preserve_tags on OrganizationAssignment; existing callers retain their original behavior.

DESIGN BASELINE / CHAPTER 33Markdown source ↗

Android and Linux device integration architecture

Implementation checkpoint: 26 September 2026. This chapter is the common integration contract for UIC Home on Android and xTMSAgent on UIC A10-T Linux terminals. Operator procedures are in the Android integration manual and Linux integration manual, with Spanish Android and Spanish Linux editions.

Common lifecycle

SuperAdmin onboards serial + customer + portal model
        |
        v
Device receives or claims its unique Device Secret
        |
        v
Device creates a private key and obtains an IoT certificate
        |
        v
Certificate possession is confirmed
        |
        v
First authenticated MQTT connection marks IoT Provisioned
        |
        v
Telemetry, commands, parameters and application tasks

A terminal never creates its own fleet record. The SuperAdmin must first register the exact manufacturer serial under the correct customer and model. Enrollment fails closed when the serial, customer, assignment epoch, model family, device state or bootstrap proof does not match.

The Device Secret and IoT certificate are independent factors. MQTT admission requires the current device ID, assignment epoch, Device Secret and the exact non-revoked client-certificate fingerprint. Topic authorization limits a terminal to its own namespace. The first successful MQTT session closes enrollment downloads and marks the terminal IoT Provisioned; this avoids permanently disabling a terminal when certificate issuance succeeds but network admission temporarily fails.

Runtime paths

Path Purpose Required security
MQTTS 5883 Telemetry, commands, results, parameter request/response TLS server validation, per-device client certificate, Device Secret and exact topic scope
HTTPS 5102 Enrollment, certificate issuance/confirmation, application and parameter downloads TLS server validation plus bootstrap or provisioned device identity appropriate to the endpoint
WSS 5102 Android remote screen and input Short-lived portal-authorized session, local capture approval and Android accessibility for control
gRPC 15101 Portal/broker to DataService Loopback-only service authentication; never expose publicly

MQTT carries bounded JSON envelopes, not APKs, Linux packages, screen frames or payment data. Large artifacts use authenticated HTTPS. Every important terminal result is retained locally until the matching SQL commit receipt is received. MQTT PUBACK means broker receipt only.

Enrollment differences

Android UIC Home

The current Android production-bootstrap workflow is not yet packaged as a general field installer. An authorized provisioning station installs the correct brand/customer APK and transfers an enrollment record into app-private storage for the debug/test workflow. UIC Home encrypts the record with AndroidKeyStore, deletes plaintext input, generates its IoT private key inside AndroidKeyStore and provisions the certificate. An ordinary APK install alone does not enroll the terminal.

Updates must use the same package ID and compatible signing certificate with replace/install-in-place semantics so private enrollment, command history and keys remain. Uninstalling UIC Home or clearing its data removes those items and requires authorized enrollment recovery plus IoT certificate rotation.

Linux A10-T xTMSAgent

The xTMSAgent customer package contains server/customer bootstrap data, never a terminal Device Secret. It starts the A10 communication service before enrollment so Ethernet, Wi-Fi or cellular can be configured on a new device. It reads the hardware serial and full reported model from the SDK, then calls /device-iot/enroll to claim the already-onboarded record. The returned unique enrollment is written atomically to /home/user1/.xtms/enrollment.json with mode 0600; the bootstrap file is removed.

If the serial is not onboarded, the device shows Enrollment pending and retries every 60 seconds or when the operator requests Retry. It must remain usable for communications configuration while pending. The development updateTMS.sh only installs a package on the lab terminal; it is not part of identity enrollment and is not a production dependency.

Reported state

Both agents report a current snapshot containing identity, portal-model-compatible family, full reported model, OS/version, agent version, uptime, capabilities, network interfaces, local IP/MAC addresses, public IP observed by TMS, free/total storage, available/total memory and user-application inventory.

Android inventory excludes system apps and system-app updates. Linux A10 inventory reads the installed userappl application. cfg/appname.txt supplies the display name and cfg/version.txt supplies the version; the configured application ID defaults to PAYMENT_APP.

Location is optional. Valid reported telemetry always takes precedence over a manual portal position. History adds a point only after a change of at least 100 metres; smaller changes update the current point without creating precision-noise history. Devices without a valid reported coordinate can be assigned a manual location by an authorized operator. See chapter 34.

Commands and evidence

The broker delivers commands at least once. Agents validate protocol version, device ID, assignment epoch and expiry, persist command identity before an external effect, and return the previous result on redelivery.

Capability Android UIC Home Linux xTMSAgent
Current telemetry / request status Yes Yes
Display message Yes, wake-capable activity Yes, agent display or payment-app bridge
Reboot Brand SDK with boot evidence Payment-app coordination then device reboot
Application install Model-specific APK through brand SDK Signed native A10 prodapp.tarball.tar.gz through os_update_application
Application uninstall Brand SDK; UIC Home protected Removes configured userappl payload
Parameters Read-only provider to payment app File bridge and parameter response file
Remote desktop WSS screen + accessibility input Not implemented

Android installation verifies package ID, version, signer and exact artifact hash. A10 installation verifies portal hash before the vendor update API performs platform signature/install checks. Successful A10 install or uninstall queues the terminal result before reboot; the restarted agent then reports fresh inventory. A task is rejected while the payment application reports an unsafe state such as an open batch.

Restrictions and operating rules

Failure recovery

Symptom Recovery path
Serial not found / enrollment pending Verify exact manufacturer serial, customer, enabled state and model onboarding; then retry
Certificate issued but MQTT unavailable Correct network/TLS/clock and retry; enrollment stays open until the first valid MQTT connection
Revoked or lost IoT key SuperAdmin rotates the IoT certificate, then the agent provisions a new key/certificate
Device Secret lost or rotated Use the approved enrollment recovery path; the old secret cannot be recovered from SQL
Android app data cleared Re-enroll and rotate IoT credentials; reinstalling alone is insufficient
Linux package task fails Check portal model mapping, package hash, A10 signature, disk space, payment-app state and command detail
Operation remains dispatched Confirm terminal online state, task expiry, local agent log and durable result/outbox; do not assume success
DESIGN BASELINE / CHAPTER 34Markdown source ↗

Device location history and manual positioning

Implementation checkpoint: 26 September 2026.

Current and historical location

Device overview shows the last valid coordinate separately from its history. Each history record stores customer, device, assignment epoch, latitude, longitude, accuracy when reported, source, optional label, actor for manual entries and UTC time. Location access follows the same customer boundary as the device.

Reported device telemetry is authoritative. When a valid telemetry coordinate arrives:

The map never treats a general default view as a terminal coordinate. A missing fix is labelled clearly. A last-known position includes its source and timestamp and is not described as live tracking.

Manual location

Operators with Device Write access can set a location only while the terminal has no valid reported coordinate. The editor supports:

  1. searching for an address;
  2. choosing or dragging a point on the map;
  3. entering latitude and longitude directly.

The server rechecks the device and permission when Save is selected. If valid reported coordinates appeared while the dialog was open, the save is rejected so a manual value cannot overwrite telemetry. Manual changes under 100 metres update the last manual point; changes of 100 metres or more create another history row. The audit log records the actor, device, source and changed coordinates without exposing credentials.

Address search is proxied by the portal through a configurable Nominatim-compatible endpoint. It is intentionally submit-based rather than autocomplete. Results are cached for 24 hours; uncached requests are limited globally to one per second and per user to ten per minute. The UI displays OpenStreetMap attribution. Banks that cannot send address text to a public geocoder must configure an approved internal endpoint or use coordinates/map placement.

Retention and privacy

Location can identify a terminal placement and must be treated as customer data. Customer administrators see only their own devices and history; SuperAdmins can work across authorized customer context. Do not include precise location in broad exports or support logs unless the task requires it. A production retention period must be agreed with each customer and implemented before long-term fleet rollout.

Operational checks

DESIGN BASELINE / CHAPTER 35Markdown source ↗

Linux and PostgreSQL server deployment

This procedure installs the same UIC Connect TMS application on an Ubuntu server with PostgreSQL. Windows installations remain supported with SQL Server. Database selection is configuration-driven; application code and service contracts are shared.

Provider selection

TMS.DataService and TMS.Setup read DatabaseProvider from the runtime configuration.

Deployment DatabaseProvider Connection string
Windows / SQL Server SqlServer Standard Microsoft SQL Server connection string
Linux / PostgreSQL PostgreSql Standard Npgsql connection string

If DatabaseProvider is omitted, the application uses SqlServer for backward compatibility. Accepted PostgreSQL aliases are Postgres and Npgsql, although new configurations should use PostgreSql. A deployment must retain its chosen engine; switching the value does not migrate data between databases.

Package and prerequisites

The Linux package contains self-contained linux-x64 builds of DataService, Portal, MQTT and Setup plus packaging/linux/install.sh. The target requires Ubuntu, PostgreSQL, openssl, python3, sudo, systemd and UFW. The installer does not require a machine-wide .NET runtime.

Copy the archive and installer to the server, then run as root:

chmod 0755 /tmp/install-uic-connect-tms.sh
PUBLIC_HOST=tms.example.com sudo -E /tmp/install-uic-connect-tms.sh /tmp/uic-connect-tms-linux-x64.tar.gz

PUBLIC_HOST may be a DNS name or IPv4 address. The first installation creates a self-signed HTTPS/MQTT certificate. Replace it with an approved certificate before production use.

Installed resources

Resource Location or port
Versioned releases /opt/uic-connect-tms/releases
Active release /opt/uic-connect-tms/current
Runtime configuration and certificates /etc/uic-connect-tms
Application artifacts /var/lib/uic-connect-tms/artifacts
PostgreSQL database / role uic_connect_tms / uic_tms
Portal HTTPS TCP 5102
MQTT mutual TLS TCP 5883
Portal HTTP and DataService gRPC loopback TCP 15100 / 15101

The installer creates the unprivileged uictms service account, applies database migrations, enables the services and opens only the two public application ports in UFW. PostgreSQL should remain bound to loopback or a private administration network.

systemctl status uic-tms-data uic-tms-portal uic-tms-mqtt
journalctl -u uic-tms-data -u uic-tms-portal -u uic-tms-mqtt

The initial administrator is created only when the database has no users. Its one-time generated credentials are stored in /etc/uic-connect-tms/initial-admin.json, readable by root and the service group. Change the password after first sign-in. Re-running the installer preserves the database, generated secrets, certificates and existing administrator.

Backups and recovery

Back up PostgreSQL and the artifact directory as one recovery set. A database-only restore can leave released application records without their package files.

sudo -u postgres pg_dump --format=custom --file=/secure-backup/uic_connect_tms.dump uic_connect_tms
sudo tar -C /var/lib/uic-connect-tms -czf /secure-backup/uic-connect-tms-artifacts.tar.gz artifacts

Test restore procedures on an isolated host. Preserve /etc/uic-connect-tms separately because it contains certificates and deployment secrets; never place that directory in source control or a public delivery archive.

SQL Server compatibility

The Windows setup continues to write a SQL Server connection string and relies on the default SqlServer provider. SQL Server migrations remain embedded alongside the PostgreSQL baseline. Every persistence change must update and test both provider paths. Provider-specific exception handling must map equivalent constraint errors to the same gRPC result.