Audience: Hub team building the cloud service / web app for AkiraConsole.
Status: Draft v1.0 — implements the OS Shell install flow.
Overview
AkiraHub is the optional cloud companion service for AkiraConsole devices.
It provides:
- A catalogue of signed WASM apps that users can browse and push to their console.
- Remote app management (install, update, uninstall) via WebSocket push.
- Firmware OTA orchestration.
- A device registry so one account can manage multiple consoles.
The device-side client is implemented in src/connectivity/cloud/ and enabled by CONFIG_AKIRA_CLOUD_CLIENT.
Package Format — .akpkg
Every app distributed through AkiraHub is packaged as a gzip-compressed tar archive with the .akpkg extension.
app.akpkg
├── app.wasm # WASM binary (interpreter or AOT for target arch)
├── manifest.json # App metadata (see below)
└── icon_32.bmp # Optional — 32×32 BMP, shown in the launcher
manifest.json schema
{
"name": "my_app",
"version": "1.2.0",
"description": "A short description shown in the launcher.",
"author": "Your Name",
"capabilities": ["display.write", "gpio.read"],
"memory_quota": 65536,
"entry": "main",
"target_arch": "xtensa"
}
| Field | Type | Required | Description |
|---|---|---|---|
name | string | ✅ | Unique app identifier (ASCII, no spaces) |
version | string | ✅ | Semantic version MAJOR.MINOR.PATCH |
description | string | ✗ | Max 128 chars, displayed in launcher |
author | string | ✗ | Publisher name |
capabilities | string[] | ✅ | Required capability list (see below) |
memory_quota | integer | ✅ | Max WASM heap in bytes |
entry | string | ✅ | WASM export to call as main() |
target_arch | string | ✗ | xtensa, arm, native or generic |
Capability strings
| Capability string | Maps to Kconfig / security.h |
|---|---|
display.write | AKIRA_CAP_DISPLAY_WRITE |
gpio.read | AKIRA_CAP_GPIO_READ |
gpio.write | AKIRA_CAP_GPIO_WRITE |
storage.read | AKIRA_CAP_STORAGE_READ |
storage.write | AKIRA_CAP_STORAGE_WRITE |
network.use | AKIRA_CAP_NETWORK |
ble.use | AKIRA_CAP_BLE |
app.control | AKIRA_CAP_APP_CONTROL |
REST API
Base URL: https://hub.akiraos.io/api/v1 (or self-hosted).
All endpoints require Authorization: Bearer <device_token> unless noted.
App Catalogue
| Method | Path | Description |
|---|---|---|
GET | /catalog | List all published apps (paginated) |
GET | /catalog/{id} | Get metadata for one app |
GET | /catalog/{id}/download | Download the .akpkg file |
POST | /catalog/publish | Publish a new app (developer only) |
PUT | /catalog/{id} | Update app metadata or binary |
DELETE | /catalog/{id} | Retract an app (developer only) |
GET /catalog response
{
"total": 12,
"page": 1,
"per_page": 20,
"apps": [
{
"id": "hello_world",
"name": "Hello World",
"version": "1.0.0",
"description": "Minimal demo app.",
"author": "AkiraOS Team",
"size_bytes": 4096,
"icon_url": "https://hub.akiraos.io/icons/hello_world.png",
"published_at": "2025-01-15T12:00:00Z"
}
]
}
POST /catalog/publish request
Content-Type: multipart/form-data
| Field | Type | Description |
|---|---|---|
package | file | .akpkg archive |
signature | string | Ed25519 signature of the package (hex) |
Device Registry
| Method | Path | Description |
|---|---|---|
POST | /devices/register | Register a new device, returns device_token |
GET | /devices/me | Get current device info |
GET | /devices/me/apps | List apps installed on this device |
POST | /devices/me/apps/{id}/install | Push install command |
DELETE | /devices/me/apps/{id} | Push uninstall command |
Firmware OTA
| Method | Path | Description |
|---|---|---|
GET | /firmware/latest | Get latest firmware metadata |
GET | /firmware/{version}/download | Download signed firmware bundle |
WebSocket Push Channel
The device keeps a persistent connection to:
wss://hub.akiraos.io/ws/device/{device_token}
Server → Device messages
All messages are JSON with a type field.
app.install
{
"type": "app.install",
"app_id": "hello_world",
"version": "1.0.0",
"download_url": "https://hub.akiraos.io/api/v1/catalog/hello_world/download"
}
The device downloads the .akpkg, verifies the Ed25519 signature, extracts to /lfs/apps/, and calls app_manager_install_from_path().
app.uninstall
{
"type": "app.uninstall",
"app_id": "hello_world"
}
firmware.update
{
"type": "firmware.update",
"version": "1.2.0",
"download_url": "https://hub.akiraos.io/api/v1/firmware/1.2.0/download",
"signature": "<ed25519-hex>"
}
Device → Server messages
device.status
Sent on connect and every 60 seconds:
{
"type": "device.status",
"firmware_version": "1.0.0",
"free_heap_bytes": 131072,
"running_apps": ["hello_world"],
"wifi_rssi": -55
}
app.install.result
{
"type": "app.install.result",
"app_id": "hello_world",
"success": true,
"error": null
}
Authentication
Device token
Each device generates a unique UUID v4 at first boot stored in NVS under akira/hub/device_token. The token is bound to the device’s MAC address via HMAC-SHA256 at registration time to prevent token theft.
HMAC-SHA256(key=wifi_mac_bytes, data=uuid_string)
Package signature verification (Ed25519)
Each .akpkg is signed by the publisher’s Ed25519 private key. The device verifies using the publisher public key embedded in the certificate chain stored at /lfs/hub/trusted_keys.pem (updated via OTA bundles only).
Verification steps on device:
- Compute SHA-256 of the raw
.akpkgarchive bytes. - Verify the Ed25519 signature provided in the HTTP response header
X-Akira-Signature: <hex>or in thePOST /catalog/publishform field. - Reject the package if verification fails — log at
LOG_ERRlevel.
Device Discovery
AkiraConsole advertises itself via mDNS when on a local network:
Service: _akira._tcp.local
Instance: AkiraConsole-<last4ofMAC>._akira._tcp.local
Port: 8080
TXT records:
fw = 1.0.0
api = v1
The Hub web app can use mDNS to discover consoles on the same LAN for direct (cloud-bypass) installs. The same REST API is exposed locally at http://<device-ip>:8080/api/v1.
Firmware Bundle Format
A signed firmware bundle (.akfw) is a binary file with the following layout:
Offset Size Field
------ ---- -----
0 4 Magic: 0x414B4657 ("AKFW")
4 2 Format version: 0x0001
6 64 Ed25519 signature (signs bytes 70..end)
70 4 Firmware image length (LE uint32)
74 4 CRC32 of firmware image
78 n Raw firmware image (MCUboot slot0 binary)
The device checks magic, format version, Ed25519 signature, and CRC32 before handing the image to ota_manager.
Self-Hosted Hub
Hub is a stateless REST/WebSocket service. Minimum stack:
- HTTP server: Any (nginx, Caddy, Node.js express, Go net/http).
- WebSocket broker: Any (socket.io, ws, gorilla/websocket).
- Storage: File system or S3-compatible object store for
.akpkgfiles. - DB: SQLite or PostgreSQL for device registry and catalogue metadata.
Environment variables:
| Variable | Description |
|---|---|
AKIRA_HUB_SECRET | HMAC secret for token validation |
AKIRA_HUB_ED25519_PRIVATE_KEY | Publisher signing key (PEM) |
AKIRA_HUB_STORAGE_PATH | Path to .akpkg file store |
AKIRA_HUB_PORT | HTTP/WS listen port (default 8080) |
Minimum Viable Integration Checklist
For the initial AkiraConsole launch the Hub team must implement:
POST /devices/register— device token issuanceGET /catalog+GET /catalog/{id}/download— app browsingPOST /catalog/publish— developer upload with Ed25519 signing- WebSocket
/ws/device/{token}—app.install+app.uninstallpush - mDNS
_akira._tcp.localfor local network discovery - Ed25519 key distribution via
/lfs/hub/trusted_keys.pemin OTA bundles