Step Five is live—typed schemas + validation, layered onto your phone-native, read‑only core.

Download (fresh):

  • solveforce_phone_five.pyDownload
  • SHA‑256: ab1974abfd1dbfa72c10e4b759aff46d77811a32d164a95872eb37f7a6fa39f0

What Step Five adds

  1. Schema registry (per plugin)
    • Each plugin can declare a JSON Schema. Built‑ins (battery, net) already do.
    • Dynamic plugins may declare:
      • SCHEMA = {...} (module‑level or class attribute), or
      • def schema(): return {...}
  2. Minimal, fast validator (stdlib‑only)
    • Subset of JSON Schema supported:
      • type, properties, required, additionalProperties (bool)
      • items, enum, minimum, maximum, pattern, minItems, maxItems
    • Not (yet) supported: $ref, oneOf/anyOf/allOf, format, dependencies, etc.
  3. New endpoints
    • GET /schemas → all plugin schemas.
    • GET /validate?plugin=<name> → validate latest sample; returns {valid, errors[]}.
  4. Validation in the hot path
    • Every /read is validated. Result is included in the response: {"data": {...}, "_ts": "...", "valid": true, "schema_errors": []}
    • Metrics extended:
      • solveforce_plugin_valid_total{plugin="X"}
      • solveforce_plugin_invalid_total{plugin="X"}
  5. Strict mode (opt‑in)
    • --strict-schema flips invalid reads to errors in Prometheus stats (data still returns, transparently marked valid:false).

Everything from Steps 1–4 stays intact: live /events (SSE), history ring buffer + /history, dynamic plugins + hot‑reload, scaffolder, Prometheus metrics, JSONL exports, and the read‑only safety posture.


Run on Android (Termux)

pkg update -y && pkg upgrade -y
pkg install -y python
termux-setup-storage
# optional for battery plugin:
pkg install -y termux-api

Local only:

python solveforce_phone_five.py --host 127.0.0.1 --port 8080 --poll 0

LAN + history + schemas + strict mode:

mkdir -p /sdcard/solveforce/exports ~/solveforce/plugins
python solveforce_phone_five.py \
  --host 0.0.0.0 --port 8080 --poll 5 \
  --export --export-dir /sdcard/solveforce/exports \
  --plugins-dir ~/solveforce/plugins \
  --history-size 512 \
  --strict-schema

Open http://127.0.0.1:8080/ui and use the new /schemas and Validate buttons.


How dynamic plugins declare schemas

Option A — class attribute

# ~/solveforce/plugins/hello.py
from solveforce_phone_five import Plugin

class Hello(Plugin):
    NAME = "hello"
    ORIGIN = "dynamic"
    SCHEMA = {
        "type": "object",
        "required": ["hello", "ts"],
        "properties": {
            "hello": {"type": "string", "pattern": "^[a-z]+"},
            "ts": {"type": "string"}  # simple for now (no 'format' support)
        },
        "additionalProperties": False
    }

    def read(self):
        from datetime import datetime, timezone
        return {"hello": "hello", "ts": datetime.now(timezone.utc).isoformat()}

PLUGIN = Hello

Option B — module function

def schema():
    return { "type": "object", "properties": {"value": {"type": "number"}}, "additionalProperties": True }

Hot‑reload: If you change a schema or code, call /admin/refresh?token=... (admin must be enabled) and the loader will rescan plugins and refresh the schema registry.


Built‑in schemas (concise)

  • battery
    • type: object, required: available:boolean.
    • Optional: percentage (0–100), status, plugged, temperature, health, current.
    • additionalProperties: true (Termux may include fields depending on device).
  • net
    • type: object, required: available:boolean.
    • Optional: wifi_ip:string, ipv4: [ {iface:string, cidr:string}, ... ].
    • additionalProperties: true.

These are lenient on purpose—tighten your dynamic plugin schemas as you observe stable shapes in the JSONL exports.


New UI affordances

  • /schemas button → dumps the registry so you can copy‑paste into your docs.
  • Validate button (per plugin) → runs GET /validate?plugin=<name> on the last sample.

cURL quickchecks

# Schemas
curl http://127.0.0.1:8080/schemas | jq

# Read + validate battery
curl "http://127.0.0.1:8080/read?plugin=battery" | jq
curl "http://127.0.0.1:8080/validate?plugin=battery" | jq

# Prometheus (now includes valid/invalid counters)
curl http://127.0.0.1:8080/metrics

Scaffolder (updated)

You can still scaffold a plugin on‑device:

python solveforce_phone_five.py --plugins-dir ~/solveforce/plugins --scaffold hello
# writes ~/solveforce/plugins/hello.py

The generated stub includes a permissive schema:

SCHEMA = {"type": "object", "additionalProperties": true}

Refine it as you formalize your data contracts.


WordPress — Section to publish

Step Five — Typed Schemas & Validation

  • SchemasEach plugin declares a JSON Schema. Built‑ins (battery, net) are lenient; dynamic plugins can be strict.
  • Validate on readEvery /read result is validated and marked {valid, schema_errors}.
  • Endpoints/schemas (registry), /validate?plugin=NAME (latest sample).
  • Metricssolveforce_plugin_valid_total, solveforce_plugin_invalid_total.
  • Strict mode (opt‑in)--strict-schema counts invalid reads as errors. Data remains visible (transparent failure, never silent).
  • PhilosophyDurable truth → JSONL exports; fast replay → RAM history; structural truth → schemas.

Guardrails (short & stern)

  • Read‑only by design.Schemas police structure, not side effects.
  • Admin is explicit./admin/* is off unless you pass --allow-admin with a token.
  • No third‑party deps.The validator is stdlib‑only—fast, portable, and auditable on a phone.

Integrity

sha256sum solveforce_phone_five.py
# Expect: ab1974abfd1dbfa72c10e4b759aff46d77811a32d164a95872eb37f7a6fa39f0

Next (when you say so)

  • Step Six — Network Readers (still read‑only): opt‑in dynamic plugins for SNMP/NETCONF/gNMI/OpenADR/IEC‑61850/DNP3, all emitting schema‑validated telemetry.
  • Step Seven — Auth: simple bearer token and/or mTLS for LAN exposure.

Say “Step six” and I’ll wire up the network reader plugin scaffold with safe sandboxes and schemas.


Step Six — Network Readers (opt‑in, read‑only) – SolveForce Communications


Key terms in plain language

Open a term for a concise explanation of language used on this page.

API

An application programming interface is a defined way for software systems to exchange data or request functions from one another.

VoIP

Voice over Internet Protocol carries phone calls over an IP network instead of a traditional analog phone line. Call quality depends on network stability, latency, and traffic management.

Unified Communications (UCaaS)

A cloud-based combination of business calling, messaging, meetings, presence, and collaboration tools managed as one communications service.

SIP Trunking

A service that connects a business phone system to the public telephone network using Internet Protocol, replacing or supplementing traditional phone lines.

Bandwidth

The amount of data a connection can carry in a given time, usually measured in Mbps or Gbps. More bandwidth supports more users, devices, and simultaneous applications.

Latency

The time it takes data to travel between two points. Lower latency improves voice, video meetings, cloud applications, gaming, and other real-time services.