Development principles
AGENTS.md is the complete authoritative repository policy. This page is the
short conceptual guide used when shaping a change.
Build for the user and the trust boundary
Section titled “Build for the user and the trust boundary”Start with the person and outcome a feature serves. Customer UI should explain tasks in the user’s language. The API must independently enforce every authentication, tenant, organization, and authorization decision. A hidden UI button is never a security control.
Tenant boundaries are hard isolation boundaries. Tenant and organization scope must be explicit in APIs, repository methods, events, jobs, caches, logs where safe, and exports. Cross-tenant or cross-organization disclosure is a security defect.
Prefer the smallest complete change
Section titled “Prefer the smallest complete change”Add a service, broker, cache, abstraction, or extension mechanism only when a concrete capability needs it. Keep clear modules inside the existing deployables unless independent scaling, deployment, security, runtime, or ownership creates a real service boundary.
A small change is complete only when its input validation, errors, operability, tests, documentation, and deployment impact are handled. Omitting those parts does not make the change simpler.
Treat boundaries as contracts
Section titled “Treat boundaries as contracts”HTTP APIs, OpenAPI, internal events, MQTT payloads, database migrations, flow and block inputs/outputs, environment variables, Helm values, CSV formats, and retention behavior are contracts. Give cross-module contracts an authoritative location and assess compatibility before changing them.
Business logic depends on repositories, adapters, and capability interfaces. PostgreSQL, TimescaleDB, Kubernetes, and Helm are deliberate platform choices, but their details should stay inside the modules that own them.
Preserve the ordered telemetry path
Section titled “Preserve the ordered telemetry path”Raw evidence is stored before flow execution:
Netmore MQTT -> durable raw stream -> raw database commit -> transactional outbox -> typed flow -> measurementsThe MQTT receiver never dual-publishes to raw and flow paths. Every stage must tolerate duplicates, delay, reordering, malformed input, unknown devices, and dependency outages. Retryable handlers are idempotent.
Configuration and deployment stay external
Section titled “Configuration and deployment stay external”The same image should move through test, staging, and production. Differences belong in validated environment values, Helm values, Kubernetes Secrets, topology, and release selection—not code forks.
Secrets are never committed, logged, placed in examples, or baked into images. OpenBao is authoritative for application secret values; Kubernetes Secrets are runtime copies. Core operation must remain self-hostable without a paid or proprietary runtime service.
Make failure understandable
Section titled “Make failure understandable”Every deployable provides health, readiness, structured logs, safe errors, correlation context, and bounded metrics. A useful failure signal says what failed, which boundary was involved, and how to investigate without exposing credentials or unrelated tenant data.
Documentation and tests are implementation
Section titled “Documentation and tests are implementation”Update customer workflows, API reference, technical behavior, operations, and Internal roadmap in the same change that alters them. Keep localized roadmap pages semantically synchronized with the English source.
Tests follow risk: business logic gets unit tests; repositories and migrations get integration tests; contracts get contract tests; tenancy gets isolation tests; deployment gets Helm rendering or smoke checks; ingestion covers duplicates, malformed data, unknown devices, and outages.
Significant AI-assisted changes end with a separate review of contracts, tests, documentation, security, tenant isolation, migrations, deployment risk, and remaining assumptions, followed by human review.